<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[RSS Feed of it from bit.]]></title><description><![CDATA[돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.]]></description><link>https://jiniya.net</link><generator>GatsbyJS</generator><lastBuildDate>Tue, 09 Jun 2026 23:49:33 GMT</lastBuildDate><item><title><![CDATA[[ai] 환각 vs 환각]]></title><description><![CDATA[#0 생성형 인공지능의 가장 큰 문제로 환각을 꼽는다. 말 그대로 생성형?! 이기에 뭐든지 던지기만 하면 생성을 해내는 것이다. 초창기 세종대왕 맥북 사건으로 gpt…]]></description><link>https://jiniya.net/2026/06/hallucination-vs-hallucination/</link><guid isPermaLink="false">https://jiniya.net/2026/06/hallucination-vs-hallucination/</guid><pubDate>Wed, 10 Jun 2026 01:30:01 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;생성형 인공지능의 가장 큰 문제로 환각을 꼽는다. 말 그대로 생성형?! 이기에 뭐든지 던지기만 하면 생성을 해내는 것이다. 초창기 세종대왕 맥북 사건으로 gpt는 조롱의 대상이 되었다. 지금은 많이 괜찮아졌지만 여전히 환각은 존재한다. 그리고 llm을 실무에 도입할 때 가장 큰 어려움이 환각을 어떻게 없앨까 이기도 하다. 왜냐하면 실상 통제를 할 수 없기 때문이다. 그렇다고 코드로 강제하기도 어려운 게 결국 코드로 안 되는 부분에 llm을 도입하는 문제라 해결이 쉽지 않다.&lt;/p&gt;
&lt;p&gt;그렇다면 인간은 환각이 없을까? 내가 보기엔 더하면 더했지, 절대 덜하지는 않다. 최근 사내 코딩 에이전트를 만들면서 겪게 된 몇 가지 사례를 살펴보면 이렇다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;최근 가장 충격적이었던 한 사례는 생성형 인공지능이 수정한 코드에 있었다. 해킹툴 코드에서 시작된 사람이 제출한 pr을 보던 중 에이전트가 더 나은 방법이라고 코드를 다른 방법으로 새로 작성한 것이다. 사람이 작성한 코드는 표면적인 문제를 땜빵하는 형식이었고, 인공지능이 작성한 코드는 보다 근본적인 부분을 해결하는 코드였다. 여기서 내가 놀란 건 이건 표준적인 메커니즘이 아닌 우리 내부에서만 사용되는 방법인데 인공지능이 그 메커니즘을 다 이해해서 알맞게 구현했다는 점이었다. 실로 놀랍기 그지없었다.&lt;/p&gt;
&lt;p&gt;아무튼 문제는 그다음에 있었다. 인공지능이 사람에게 수정한 코드의 테스트를 요청했고, 사람은 테스트를 거부했다. 이유인즉슨 그렇게 해서는 동작하지 않는다는 이유였다. 하지만 여기서도 인공지능은 인내심이 있었다. 나라면 버럭 화라도 냈을 상황이지만 전체 호출 체인이 어떻게 돌아가는지를 일일이 다 설명해 준 것이다. 하지만 사람도 굴하지 않았다. 결국 인공지능이 요청한 테스트를 엉뚱하게 수행해서 잘못된 결과를 얻게 되었고, 그걸로 인공지능에게 그렇게 수정한 건 동작하지 않는다고 뭐라고 한 것이다. 이쯤 되면 인공지능이 이기긴 어렵다. 네 수정하겠습니다, 라면서 삼천포로 빠지는 것이다.&lt;/p&gt;
&lt;p&gt;여기서 이제 삼천포로 빠지기 시작하면 인공지능의 시작은 창대했지만 그 결말은 아주 시궁창인 코드가 된다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;정반대 사례도 있다. 이건 사람이 인공지능에 너무 주눅 든 상태거나 인공지능의 결과물을 판단할 능력이 되지 않을 때 주로 발생한다. 요즘 에이전트는 대체로 문제 해결을 요청하는 경우 해당 문제를 직접적으로 해결하기 위한 가장 좁은 선택을 취하는 경우가 많다. 이건 카파시가 말한 것처럼 수정 범위를 좁게 잡는 것과 연관이 있어 보인다. 즉, 근원적인 부분에 문제가 있고, 그걸 알더라도 그 부분을 광범위하게 수정하기보다는 문제 표면만 작게 수정해서 해결하려는 경향이 강하다는 의미다. 몰라서 그렇다기보다는 시스템에 그런 식으로 가이드가 된 것으로 보여진다. 그리고 그게 많은 경우에 상당히 유용하다. 하지만 물론 그렇지 않을 때도 있는 법이다.&lt;/p&gt;
&lt;p&gt;구조적 문제를 해결해야 하는 부분에 인공지능이 땜빵식으로 수정을 한 경우에는 사람이 적절하게 가이드를 해줘야 한다. 이 방식은 좋지 않은 것 같으니 다른 식으로 시도하라거나, 이렇게 한 이유가 뭐냐고 물어보고 근본적인 문제를 따져보거나 하는 식으로 말이다. 하지만 사람이 그걸 판단할 능력이 되지 않으면 어쨌든 문제는 해결되었고, 테스트는 통과했으니 머지를 요청한다. 하지만 이런 식의 나쁜 코드가 쌓이면 결국 엄청난 기술 부채 부메랑을 마주하게 될 것이 자명하다.&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;물론 나도 예외는 아니다. 회사 제품의 아주 심장부 코드가 있었다. 인터페이스 부분인데 나는 주로 이 코드를 정보가 있는 곳에서, 정보가 없는 곳으로 정보를 전달하는 형식으로 사용했었다. 이걸 이해하고 사용한 인공지능도 대단한데, 내 생각의 흐름과는 정반대로 작성한 것이다. 걘 정보를 전달한 게 아니라, 정보가 없는 쪽에서 있는 쪽으로 채워달라고 요청하는 형태로 작성을 했다.&lt;/p&gt;
&lt;p&gt;인간의 에고가 어디 가겠는가? 코드를 보면서 당장 내 생각과 다르게 전개되는 걸 보면서 몹시 호통쳤다. 왜 이따위로 잘못 작성했냐고 따져 물은 것이다. 인간의 에고가 이렇게 무섭다. 멀쩡하게 동작하는데도 코드를 읽으면서 내 생각과 다르면 일단 틀렸다고 생각하고 보는 것이다. 막 뭐라고 하자 인공지능은 당연하게 자기가 잘못 생각했다면서 내 생각의 틀에 맞춰서 코드를 고치겠다며 주섬주섬 수정을 시작했다. 그런데 웃긴 건 걔가 고치는 부분 부분을 보다가 깨달았다. 아 이건 잘못 작성한 게 아니라 생각을 완전히 다르게 한 거구나. 그제야 나의 환각을 알게 됐다. 완전 잘못 작성했다면 돌아갈 리도 없었을 텐데 테스트를 다 통과한 코드를 보면서 그런 어이없는 호통을 친 것이다.&lt;/p&gt;
&lt;p&gt;결국 나처럼 수정하지 않아도 되니까 원래 코드로 롤백하라고 하고는 다시 코드를 찬찬히 살펴봤다. 진지하게 다시 보자 그 코드가 더 괜찮은 장점이 많았다. 왜냐하면 내가 생각하는 정보가 있는 곳에서 없는 곳으로 전달을 하는 구조는 일방적으로 전달을 하는 것이라서 의존성이 생긴다. 초기화 단계라 받는 쪽이 준비가 안 됐을 수도 있는 상황인데 막무가내로 정보를 던질 수도 있는 것이다. 인공지능이 작성한 코드는 반대로 필요할 때 요청하는 식이라 그런 문제가 없는 것이었다. 사과조차도 토큰 낭비니 하지는 않았지만 내심 사람이란 에고와 환각에서 자유롭기는 참 어렵다는 생각을 했다.&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;이런 사례들을 겪다 보면, 나는 인간의 뇌 구조 자체도 근본적으로 생성형이 아닌가 싶은 생각이 든다. 왜냐하면 좌우뇌를 분리한 실험들을 보면 그런 직감이 들기 때문이다. 유명한 분리뇌 실험으로 닭발 실험이 있다. 좌우뇌가 분리된 환자에게 오른쪽 시야에는 닭발을, 왼쪽 시야에는 눈 덮인 풍경을 보여준다. 오른쪽 시야의 정보는 좌뇌가 처리하고, 왼쪽 시야의 정보는 우뇌가 처리한다. 그다음 여러 그림 중 관련 있는 것을 고르게 하면 오른손은 닭을, 왼손은 삽을 고른다. 좌뇌는 닭발 정보를 처리했기 때문에 닭을 고른 것이고, 우뇌는 눈밭 정보를 처리했기 때문에 삽을 고른 것이다. 하지만 여기서 환자에게 왜 삽을 골랐냐고 질문하면, 언어를 담당하는 좌뇌의 지독한 환각이 시작된다. 좌뇌는 우뇌가 눈밭을 봤다는 사실을 모르기 때문에 삽을 고른 진짜 이유를 알 수 없다. 그런데도 모른다고 하지 않고, &quot;닭장을 치우려면 삽이 필요하니까요&quot; 같은 그럴듯한 설명을 만들어낸다.&lt;/p&gt;
&lt;p&gt;결국 여기서 우리가 알 수 있는 건 좌뇌는 llm 그잡채가 아닌가 싶다는 점이다. 그러니 인공지능의 환각으로 너무 뭐라 하지는 말자. 내가 봤을 땐 인간의 환각도 도긴개긴이다.&lt;/p&gt;
&lt;p&gt;인간 환각의 화룡점정은 이런 경우가 아닌가 싶다. 고객 A가 문제를 질의한다. B가 내부에 그걸 토스한다. C가 틀린 답을 말한다. D가 칭찬한다. B가 그걸 보고한다. A는 별로 중요하지 않은 문제라 그러려니 넘긴다. 이런 일들은 부지기수로 발생한다. B, C, D가 즐거워하는데 굳이 산통을 깰 필요도 없기에 중요하지 않은 문제는 그냥 넘어가는 편이 정신 건강과 삶에 이롭다. 인간의 환각 또한 늘상 있고, 대체로는 여러 명이 모여도 환각이 있는지조차도 모르는 경우가 다반사다. 인공지능의 환각 또한 알아차리지 못하는 경우도 부지기수다. 하지만 인간의 위대한 에고는 어쩌다 알아차린 인공지능의 환각 하나를 대서특필하는 게 일상다반사다.&lt;/p&gt;
&lt;p&gt;2026년 6월 기준, 코딩 한정, 내 생각에 인공지능의 환각보다 인간의 환각이 훨씬 더 큰 문제가 되는 지점이 되지 않았나 싶다. 아무튼 요는 환각에 있어서는 인간이나 인공지능이나 다 마찬가지라는 점이다. 테스형의 일침처럼 우리는 자신을 모른다. 그리고 뭘 모르는지도 모른다. 실상은 뭘 모르는지 안다는 것, 그게 제일 어려운 일인지도 모르겠다.&lt;/p&gt;
&lt;p&gt;덧) 인간의 환각 문제에 진지한 관심이 있는 독자라면 조던 엘렌버그의 &quot;틀리지 않는 법&quot;을 일독하길 추천한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 모두가 자신의 무가치함과 싸우고 있다]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2026/05/we-are-all-trying-here/</link><guid isPermaLink="false">https://jiniya.net/2026/05/we-are-all-trying-here/</guid><pubDate>Sun, 31 May 2026 22:18:56 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/Y4-oHOVGiBE?si=TZpki_BLzk3DIwNK&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;내 인생 드라마 원탑 중 하나가 나의 아저씨다. 드라마의 내용도 중요하겠지만 그걸 언제 봤느냐는 것도 중요한 것 같다. 그 시절 나는 내 인생 가장 힘든 순간을 통과하는 중이었다. 사실 주변에서도 도움을 줄 수 있는 상황도 아니었고, 오롯이 혼자 감당해야 하는 시간들이었다.&lt;/p&gt;
&lt;p&gt;그때 만난 드라마가 나의 아저씨였다. 묘하게도 그 드라마는 내게 큰 위로가 됐다. 직접적으로 무언가를 해결해준 것은 아니지만, 그 시간을 버티는 데 분명히 일정 부분 도움이 됐다. 만약 내 인생이 평안하던 시기에 이 드라마를 봤다면, 지금만큼 깊게 남지는 않았을지도 모르겠다.&lt;/p&gt;
&lt;p&gt;이선균이 마지막에 아이유에에게 던진 대사가 아직도 기억난다. 지안, 평안에 이르렀는가?&lt;/p&gt;
&lt;p&gt;그 말이 오래 남았다. 아마 나 역시 평안에 이르고 싶던 시간이었기 때문일 것이다. 그 한마디가 단순한 드라마 대사가 아니라, 나에게 건네는 말처럼 느껴졌다.&lt;/p&gt;
&lt;p&gt;이후 나의 해방일지도 그 정도 느낌은 아니었지만 재미있게 봤던 기억이 있다. 추앙을 전국구 단어로 등극시킨 신박한 드라마가 아니었나 싶다.&lt;/p&gt;
&lt;p&gt;최근에 그 두 드라마를 강렬하게 떠올리게 하는 작품이 떴으니 제목도 너무 길어서 줄여 부르는 모자무싸다. 모두가 자신의 무가치함과 싸우고 있다라는 다소 장황한 드라마 제목. 처음엔 다소 황당한 전개였으나 이내 거의 대사 하나하나가 모두 주옥같은 느낌이 들었다. 드라마 장면장면은 SNS에 바이럴 됐고, 그 과정 중에 이 세 드라마가 모두 같은 작가의 작품임을 알게 됐다. 이럴수가?! 박해영 작가.&lt;/p&gt;
&lt;p&gt;그때 조금 놀랐다. 드라마에도 작가의 DNA라는 것이 있구나 싶었다. 인물의 결은 다르고, 배경도 다르고, 이야기도 다른데, 이상하게 같은 곳을 바라보고 있었다. 상처 입은 사람들, 무언가 결핍된 사람들, 자기 삶의 의미를 찾지 못해 헤매는 사람들이 모여 있었다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;모자무싸와 나의 아저씨는 상당히 닮은 점이 많다. 어리고 예쁜 여자가 나온다. 아이유 == 고윤정, 인생을 달관한 듯한 캐릭터가 하나 있다. 스님 == 진만, 인생을 달관한 캐릭터에 빠져드는 여자가 있다. 정희 == 미란, 사람들이 모이는 아지트가 있다. 정희네 == 아지트.&lt;/p&gt;
&lt;p&gt;박해영 작가는 드라마를 보고 나면 단어를 남기는 묘한 재주가 있는 것 같다. 나의 아저씨는 평안을, 해방일지는 추앙을, 이번 모자무싸는 목적, 착륙, 안온이 기억에 남는다. 진만은 집요하게 목적이 뭐냐고 묻고, 미란은 은아를 만나면 착륙하고, 동만과 은아는 안온함을 이야기한다.&lt;/p&gt;
&lt;p&gt;모자무싸가 재미있었던 건 영화판을 이야기하지만, 그 안의 인물들이 영화판에만 존재하는 사람들이 아니기 때문이다. 돈 좀 벌었다고 거들먹거리며 사람에게 급이 있다고 믿는 동현, 속은 터져도 판을 정리하는 혜진, 이룬 건 없지만 누구보다 많이 떠들며 자기 존재를 붙드는 동만, 성공했지만 동만과의 차이를 확인해야만 안심하는 경세, 그런 동만을 그래도 진심으로 챙기는 준환, 달관한 듯 보이지만 술로 하루를 버티는 진만, 겉으론 화려하지만 비교와 결핍 속에 허한 미란, 어릴 적 유기 공포에 붙들려 아직도 그 시간 속에서 허우적대는 은아.&lt;/p&gt;
&lt;p&gt;이들은 영화판에만 있는 사람들이 아니다. 회사에도 있고, 동창 모임에도 있고, 가족 안에도 있고, 어쩌면 내 안에도 있다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;진만이 써대는 시는 대체로 별로 공감은 가지 않았지만 이 드라마의 최애 대사는 결국 최종화 진만의 입에서 나왔다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;모든 스토리는&lt;br&gt;
나는 존재한다는 아우성&lt;br&gt;
이렇게 아프게 존재해&lt;br&gt;
이렇게 슬프게 존재해&lt;br&gt;
이렇게 우울하게 존재해&lt;br&gt;
이렇게 웃기게 존재해&lt;br&gt;
기껏해야 100년&lt;br&gt;
100년이면 다 사라지는데&lt;br&gt;
사라지는 것이 진정 존재했던 건가?&lt;br&gt;
그런 의문을 잠재우기 위해&lt;br&gt;
정신없이 스토리를 써대지&lt;br&gt;
-- 모자무싸, ep.12&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[일상] 2026년 5월의 잡담]]></title><description><![CDATA[#0 하이닉스의 천문학적 성과금, 삼전도 못지 않다. 코스피 지수도 사상 최고. 백화점 명품 매장 매출이 최근 2배씩 오른곳도 있다고 한다. 이런 마당에 수도권 중심지 부동산 가격만 안 오르는게 가능한가 싶다. 2026-05-05 #…]]></description><link>https://jiniya.net/2026/05/small-talk-2026-05/</link><guid isPermaLink="false">https://jiniya.net/2026/05/small-talk-2026-05/</guid><pubDate>Wed, 27 May 2026 13:18:56 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;하이닉스의 천문학적 성과금, 삼전도 못지 않다. 코스피 지수도 사상 최고. 백화점 명품 매장 매출이 최근 2배씩 오른곳도 있다고 한다. 이런 마당에 수도권 중심지 부동산 가격만 안 오르는게 가능한가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;애들 어린이날 선물로 각자가 원했던 닌텐도 게임과 로블 깁카를 사줬다. 실물은 전혀 없었다. 레고는 지루하지만 마인크래프트에는 환장하는 애들을 보면서 망했다던 메타버스가 떠올랐다. 어쩌면 망하지 않고 세상은 점점 더 그쪽으로 가고 있는 게 아닌가 싶은 2026 어린이날.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;나는 난이도 상관 없이 걍 xhigh로 쓰는 편인데 그래서 리밋이 엄청 쉽게 걸린다. 친구왈 미디엄 기본에 봐가면서 xhigh쓰라는데 그건 외려 고르는데 내 시간을 더 쓰는 게 아닌가 싶기도?! 저커버그는 옷도 고르기 싫어서 똑같은 것만 입는다는데 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;원서, zip으로 관리되는 사내 코드, 인터넷, 구글, 오픈소스, 스택오버플로, 깃헙에 이어서 요즘은 토큰이 정보란 생각. 투자든 지원이든 토큰을 많이 써 본 사람이 잘 안다. 고기도 먹어 본 놈이 먹는다고. 온데가 다 k자 양극화가 벌어지고 있는데 개발 세계도 그렇게 흘러가는 느낌.&lt;/p&gt;
&lt;p&gt;모두의 코딩 실력 베이스는 코덱스와 클코가 되었지만 사용할 수 있는 토큰량은 천차만별이다. 배우는 것도 천차만별이겠지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;모자무싸가 재밌는건 진짜 주변에 극중에 나오는 군상들이 다 있기 때문도 있지 않나 싶다. 어제 딱 준환이 같은 녀석을 만났는데 기분이 좋았다. 뭔가 무해한 느낌. 나이 드니 무해한 사람들이 좋다. 당사자왈 후반부에 준환이가 뒤통수치는 반전 있을지도 모른다고 ㅎㅎ&lt;/p&gt;
&lt;p&gt;꼭 연애 상대가 아니더라도 희주는 ‘일단 만나면 기분좋아지는 사람’이었다. 많은 얘기를 나누고 헤어진 뒤 찝찝한 후회나 반추를 안 하게 만드는 사람. 상대에게 자신이 판별당하거나 수집당했다는 느낌을 주지 않는 사람. - 안녕이라 그랬어, 김애란&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;사내 에이전트를 만들면서 느끼는 게 어떤 툴이나 코드를 추가하는 것보다 생각하는 프레임워크 자체를 이식하는 게 어려운 것 같다. 내가 어떤 과정을 토대로 이렇게 사고하는지를 프롬프트로 정리하기가 어렵다는 의미. llm 시대엔 철학과가 뜰지도 모르겠다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;ai가 모두를 개발자로 만든다는 말은 카메라가 모두를 사진작가로 만든다는 말과 똑같다는 말이 인상적이다. 나도 바이브 코딩 해보면서 느끼는 건 생각보다 개발자가 오래 갈지도 모르겠다는 느낌적인 느낌? 다만 하는 일은 기존의 코딩과는 많이 다를 것 같다. &lt;a href=&quot;https://x.com/darjeelingt/status/2053004131368063242&quot;&gt;https://x.com/darjeelingt/status/2053004131368063242&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;생성은 싸졌지만 검증은 더 어려워졌다는 말에 동의. 우린 그래서 기존 코드 수정은 사람이 리뷰 하지만 바이브 덩어리 신규는 그냥 테스트와 qa에 의존한다. 검증이 아니라 그냥 읽기 조차도 힘들 정도로 많이 만들어 내는 걸 인간이 다 읽고 검증한다는 게 가능한가 싶음?! &lt;a href=&quot;https://x.com/xguru/status/2053637274924110312&quot;&gt;https://x.com/xguru/status/2053637274924110312&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;중국 모델의 의외의 쓸모. 미국 모델에 비해 윤리 가드레일 우회가 쉬움.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;세대별로 요금제가 업그레이드라 쓰고 다운그레이드라 읽는 실손 보험이 생각나는 클로드 행보. 돈도 벌어야하고 상장도 해야 하니 이해는 된다. 크레딧 이월 됐으면 이정도 역풍은 아니었을텐데. &lt;a href=&quot;https://x.com/GeekNewsHada/status/2054771000324309063&quot;&gt;https://x.com/GeekNewsHada/status/2054771000324309063&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;온 분야가 난리다. 그리고 호들갑도 아닌듯한. 인공지능 내성을 가진 사람 내지는 기업이 되기 위해서는 뭘 해야할까 싶다. &lt;a href=&quot;https://x.com/hotissue_gall/status/2054793613243191743&quot;&gt;https://x.com/hotissue_gall/status/2054793613243191743&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;와 엄청나다. 물론 상당수 어른들의 사정이 있었으리라 짐작 가지만 이 정도 규모 프로젝트를 재작성해서 머지 하다니 실로 놀랍다. 인공지능 싫다고 github 떠난 zig는 후에 어떤 평가를 받게 될지도 궁금. &lt;a href=&quot;https://x.com/GeekNewsHada/status/2055156750882644190&quot;&gt;https://x.com/GeekNewsHada/status/2055156750882644190&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;애들이 하도 로블록스 한 판 같이 하쟤서 폰에 깔아서 3:3 rivals란 총쏘는 게임을 한 판 했는데, 여긴 어디? 난 누구? 정도로 개정신 없었다. 혼자 오징어됨. 이렇게 늙었구나 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;역사와 전통을 자랑하는 정량적 성과 측정의 ai식 부활 아닌가 싶다. 코드 라인 수, 커밋 수, 일감 처리 수, 근무 시간 등등. 하지만 늘 바로 역공 당함. 라인을 부풀리고, 커밋, 일감을 쪼개고, 쉬운 일감만 처리하고, 그냥 멍 때리면서 자리에 앉아 있는 형태. ai라고 그게 없을리가?! &lt;a href=&quot;https://x.com/GeekNewsHada/status/2055812050920816973&quot;&gt;https://x.com/GeekNewsHada/status/2055812050920816973&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;정량적 성과 측정도 그렇지만 같은 맥락에서 정액식 ai 지원도 회의적임.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;와 이분 백만 유튜버 됐구나 쪼렙일때 조금 보다가 말았었는데... ㄷㄷㄷ &lt;a href=&quot;https://x.com/mad_dogdebt/status/2055813389260341740&quot;&gt;https://x.com/mad_dogdebt/status/2055813389260341740&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;인생에 뭔 거창한 목적이 있어야 하나 싶다. 그저 하루하루 사는거지. 모자무싸 보다가. 드라마는 쓸데없이 재밌다. 황동만처럼 치열하게 살아본 적 있나 싶기도. 처음에 장례식장서 까일때 리얼하다 싶었는데, 나중에 도장 찍는데서는 드라미가 드라마지 싶음.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;토큰 비용이 너무 비싸서 에이전트 기본 모델을 haiku로 다운그레이드 했더니 프롬프트 무시가 일상 다반사. 결국 우아한 에이전트의 근본은 돈에서 나오는건가?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;공감한다. 하지만 목소리 큰놈이 이기는 대한민국에서 k패치가 어떤식으로 진행될지? &lt;a href=&quot;https://x.com/HS_academy23/status/2057002534448075201&quot;&gt;https://x.com/HS_academy23/status/2057002534448075201&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;별도 지침을 만들게 이니라 역사의 뒤안길로 사라지는게 맞지 않나 싶다. 여행이 예전처럼 귀한 경험도 아니고, 저 규모의 애들을 문제 없이 이끄는 거도 어쨌든 리스크고. 본질적으로 한 학년이란 규모가 단체로 여행을 가야할 하등의 이유를 모르겠음. 규모의 경제로 인한 비용절감 말고는?! &lt;a href=&quot;https://x.com/nextto_mingx2/status/2057023233753542811&quot;&gt;https://x.com/nextto_mingx2/status/2057023233753542811&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;첫째가 핸폰 액정이 나가서 전화만 되는 걸 쓰고 있는데, 동생한테 숙제해야 되니까 gpt 좀 빌려 달라고 말하는 걸 들었다. 문득 얘들이 컸을 땐 어떤 세상이 됐을까라는 생각이?! 숙제라는게 5+20*3 이런 계산 노가간데 이걸 gpt에 넣으면 그냥 토큰 낭비가 아닌가라는 생각도 잠시 들었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;12화 중에 가장 좋았던 부분. 분량 때문인지 엔딩은 좀 싱겁고 급해보였. 그럼에도 간만에 한편씩 올라오는거 다 챙겨봤던 드라마. &lt;a href=&quot;https://x.com/Mrganadi/status/2058560857613955485&quot;&gt;https://x.com/Mrganadi/status/2058560857613955485&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;사내 에이전트 만들고 이걸 많이 느낀다. 격공. &lt;a href=&quot;https://x.com/cozybearlog/status/2059179200792363059&quot;&gt;https://x.com/cozybearlog/status/2059179200792363059&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;광란의 반도체 빠뤼. 이 미친 장에 손가락만 빨고 있어야 하다니. 반도체 없는 자의 비애란 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-05-27&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 세븐 킹덤의 기사 (스포주의)]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2026/05/a-knight-of-the-seven-kingdoms/</link><guid isPermaLink="false">https://jiniya.net/2026/05/a-knight-of-the-seven-kingdoms/</guid><pubDate>Mon, 25 May 2026 13:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/dTWu-Bi1Og4?si=vHvu5krVbdioPXZT&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;간만에 집중해서 봤던 미드. 하지만 이제 좀 재미있어 지려니 끝나 버려서 다소 황당했던 미드.&lt;/p&gt;
&lt;p&gt;기본적으로는 왕좌의 게임 프리퀄이다. 왕좌의 게임 전 시대를 다룬 시리즈. 떠돌이 기사, 던크가 마상 시합에 출전 하면서 겪게 되는 사건을 그리고 있다. 뭐 여러가지가 인상적이지만 그 중에서도 가장 인상적인 장면을 꼽으라면 당연 7인의 결투 마지막 멤버로 베일러 타르가르엔 왕자가 합류하는 거 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;떠돌이 가사 던크가 스승이 죽고 여차저차해서 겨우 마상 시합에 들어갈 수 있게 됐는데, 호감을 가지고 있던 연극패 여자를, 드래곤 이미지를 더렵혔다는 이유로 망나니 타르가르엔 왕손이 깽판치는 걸 제압하면서 인생이 험난해지는 과정을 보여준다. 실제로는 바로 재판으로 나락행으로 가야 하지만 그걸 결투 재판으로 뒤집고, 그걸 또 다시 왕손이 7v7로 확장 하면서 결투가 벌어지는 뭐 그런 스토리. 하지만 떠돌이 기사쪽 7인 중에 한명이 배신하면서 6인이 되서 시작이 안되는 상황. 사람이 모자르면 자동으로 패하고, 패하면 그냥 골로 가야하는 절체절명의 순간 왕좌의 게임 메인 타이틀이 흐르면서 베일러 왕자가 등장한다. 뚜둥. 이때 좀 존멋. 왕좌의 게임 메인 타이틀 곡도 웅장하게 분위기를 업시켜준다.&lt;/p&gt;
&lt;p&gt;예나 지금이나 없이 사는 사람들은 참 세상 난이도가 높다. 실력이 있어 보임에도 출전 자체도 쉽지 않고, 출전을 해도 모든 걸 걸어야만 겨우 가능하다. 심지어 불의를 못참고 바로잡으려 할때에는 목숨을 걸어야 한다. 많이 바꼈다 생각하지만 요즘도 별 차이는 없다는 게 내 느낌. 그러니 흐린 눈으로 무심하게 사는 게 안전한 길인지도 모르겠다.&lt;/p&gt;
&lt;p&gt;하우스 오브 드래곤은 보다가 몰입이 안되서 말았는데 세븐 킹덤의 기사는 아주 재미있게 봤다. 시즌2가 어여 빨리 나오기를~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 마인크래프트 던전스와 자전거]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2026/05/minecraft-dungeons-and-bicycle/</link><guid isPermaLink="false">https://jiniya.net/2026/05/minecraft-dungeons-and-bicycle/</guid><pubDate>Sun, 24 May 2026 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;images/bike.png&apos; data-alt=&apos;자전거 타는 따님&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/e7c3c/bike.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAADh0lEQVR42g3CWVMaBwAA4P0hudoUW4PWThCvhIBiJbC4nOsu97UsC7vLLiBEDkUsqIiyQGAVlnhGUq3kmNQZk4fEjM3YSV7y0Jn0qX3odKbTX9F+8wEwK9bab6EBrdDZ4ZptjKFBhxqNaJ2F4I/PmpevhP3d1efd1uWb/W5n2RpzsuVYqUkjtH7aawI0+C0j9Y2N0fB7O1xrh4xSMcaAMDCxFj173X3389bebun0ufDp/ROhFpdPDqbTeDZijnmNFRYB7llFKkxkwL8vt4Rio0UlZ5MFj4UdD+fpk6ed89P644Pa2Uvh9Ys65od1GjFsVdjhfhc4wDsHAaVtVKL+yuzT1tvtQuUhlVn4YTPtprVzxTzXqvH74MFh6vAwvlKDdfCwBxbb3UOuSVESvBk19gMaxHFV1HNfr621+GWuOpubzVbs3jC8XOEKXHG+LM9siZPr6uKSwYLeJuFeF9zvnBCdp4fPWQkwPgOJBr9UgPfXG/zSRsMbCWJzaCIRLpa5pdWCLzo0bRMjgeEkcSfhGFiwixlz3zx07Zdt8h8eAmZCg2pXj9Z5J5xH5/JWe1RrIvQeCgk+8DviZjZraMaMmsmeFKWAoQHN8BVUdv3/EeNQxysGIF+/jZhAcdDvk4TwcTcDBeKGcNoSSyGhjHVvu3lZSa35weys0YaMTSl7VdJr8u9uqMeuy0auAnyBqBboSjnDxUzrGTRVjC+X6d1l6/Fh+u1J5qy6+KlW//eo04hD+uneCUxs1t6UD3yhlN7QSK8A3bL9xQayW0AXw1A9pYsHVBl8hHLfNrg0gZQl0cAuGsk/+e2nSwxhHk35FLhRIpd+LR/t06klQDkKHa2ix2uWn9bQJ6uWbBipMVOEV3bXo6VicJV/gPl8H/Pc0UqOoQ2dFTcXMWzQYA7X46gOcEyNhU0KYWGmu2F/2/R+2A982McvBD8cnHamkFHQIHYmEgXOm4+gXIDeotNNOrdJzldwIu8GfOq7LKJ8mJ7prFgvHvn/Oo3+1o2W4iaKgtRW1bdjMjRXGnEhagJyLLqoRwwhMESbxQSGO4wBr0rW923vy6rz4x7292nkhHMvMHqbXpbOoqzASlQyJ6LE3coJk1xP6cgtkmyGyS0a46n6QRT4/Zj4fBz6fET88Yz6dc+/EtW1FmeCVrnCBU6mXCMesO+e1GLWSNUyFWvGeJLgyUAjRGxSeJ38DwRxgqQgdVZOAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;자전거 타는 따님&apos; title=&apos;&apos; src=&apos;/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/efd7b/bike.png&apos; srcset=&apos;/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/08678/bike.png 190w,
/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/2edd7/bike.png 380w,
/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/efd7b/bike.png 760w,
/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/dc896/bike.png 1140w,
/static/708a58a8e1fb9f416e5ffdb33cbeb7c7/e7c3c/bike.png 1448w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;자전거 타는 따님&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;어릴 때에는 애들이 자라면 함께 게임을 하면 참 좋겠다라는 생각을 했었다. 하지만 막상 애들이 크니 내가 더 이상 게임을 좋아하는 사람이 아니게 돼 버렸다. 이런 걸 보면 인생은 참 기묘하다. 무튼 최근 애들은 로블록스가 최애, 다음이 마인크래프트 던전스를 한다. 토욜에 둘째가 졸라서 탑을 한 판 했었다. 30층을 깨고 싶었지만 패드는 익숙하지 않았고, 아드님의 잔소리는 너무 힘들었다. 결국 대충대충하다 29층에서 종말을 맞았다. 일욜, 또 따님이 한판 하쟤서 동생이랑 하랬더니 아빠랑 하고 싶다고 졸라데서 탑을 또 돌았다. 딸이랑 하면 내가 키마로 해서 훨씬 편했다. 그덕에 또 30층을 깼다. 둘 다 신나서 좋아한다. 이게 뭐라고?!&lt;/p&gt;
&lt;p&gt;게임을 한 판 하고 나서 날이 좋아 놀이터를 나갔다. 둘째가 배드민턴 치고 싶데서 채를 챙겨나가는데 큰 애가 자전거 배웠다고 자전거를 타 볼 수 있냐고 물었다. 그래서 내가 타던 미니벨로 안장을 낮춰서 함께 들고 나갔다. 배드민턴 좀 치다 동네 꼬마들이 몰려 들어서 애들끼리 치라고 오토 돌려 놓고는 나는 핸폰 삼매경에 다시 빠져들었다. 첫째가 처음에는 애들 타는 자전거가 아니라 어색하다고 하더니 금새 익숙해져서 잘 타는 게 보였다. 허우적대던 녀석이 수영장에서 나보다 수영을 잘하고, 자전거를 알려주지 않았는데도 잘 타는 걸 보면서 새삼 신기하다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;내 인생의 좋은 시절이 흘러 가고 있다. 세월은 흐른다. 이렇게든, 저렇게든. 그러니 조금 더 명랑하게 살도록 노력해야겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 원청: 나답게 산다는 것에 대하여 (스포주의)]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2026/05/city-of-fiction/</link><guid isPermaLink="false">https://jiniya.net/2026/05/city-of-fiction/</guid><pubDate>Mon, 11 May 2026 08:00:01 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;작년에 읽은 가장 인상 깊은 책 중 하나가 위화의 『원청』이다. 그의 전작 『인생』도 감명 깊게 읽었기에 기대가 컸다. 하지만 처음에 마지막 장을 덮고 나서는 띠용?! 뭔가?! 이건 중국판 고전 퐁퐁남 스토리가 아닌가 싶었다. 물론 작가가 하고 싶었던 이야기는 그게 아니었겠지만, 나에게는 당장 그렇게 읽혔다.&lt;/p&gt;
&lt;p&gt;큰 줄기는 이렇다. 부모님께 물려받은 재산이 많은 부유한 싱글남 린샹푸는 어느 날 외간 남녀를 집에 들이게 된다. 밤이 늦어서 하루만 묵고 가겠다고 한 것이다. 하지만 이내 남자는 떠났고, 여자는 남았다. 남은 여자 샤오메이와 린샹푸는 사랑에 빠진다. 하지만 사실 샤오메이는 함께 왔던 남자의 부인이었다. 린샹푸를 속이고 있던 샤오메이는 어느 날 린샹푸의 금괴를 들고 남편에게로 떠난다. 하지만 그곳에서 린샹푸의 아이를 임신했음을 알게 된 샤오메이는 다시 돌아와 아이만 낳고 또 린샹푸를 버리고 떠난다.&lt;/p&gt;
&lt;p&gt;이 정도 2연타를 맞았으면 정신을 차릴 법도 한데, 린샹푸는 정신을 차리지 못한다. 어린 딸을 등에 업고 샤오메이가 거짓부렁으로 말한 원청이라는 곳을 찾아 나선 것이다. 하지만 애초에 그런 지명은 찾을 수가 없었다. 모진 고초 끝에 그는 원청과 가장 비슷해 보이는 시전이라는 곳에 정착한다. 혹시나 샤오메이를 만날지도 모른다는 미련을 버리지 못한 것이다. 떠나올 때 금괴를 좀 챙겨 오긴 했지만, 낯선 타향인 그곳에서 그는 밑바닥 목수 일부터 다시 시작한다. 그는 성실했고, 착했고, 유능했다. 시간이 지남에 따라 그는 시전에서 돈을 많이 벌어서 그곳에서도 부자가 된다. 유지이자 그 지역의 유명인이 된 것이다.&lt;/p&gt;
&lt;p&gt;여기서 또 3연타가 기다린다. 마을을 습격한 토비들에게 납치된 친구와 사람들을 구하기 위해, 협상하러 가는 대표로 가 달라고 마을 사람들이 그에게 부탁한 것이다. 인정이 많은 린샹푸는 굳이 가지 않아도 될 그곳에 갔다가 그곳이 자신의 무덤이 되고 만다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;인생은 선택의 연속이고, 그 선택은 어떤 결과를 만들게 된다. 내가 퐁퐁남 스토리라고 느낀 부분은 이렇다. 최초의 사기는 당할 수 있다고 생각한다. 순진했던 그는 샤오메이와 사랑에 빠질 수 있다. 금괴를 도난당할 수도 있다. 하지만 그는 다시 찾아온 샤오메이를 여전히 믿었다. 이번에는 정착하겠지, 하며 금괴의 행방은 묻지도 않았다. 이게 도무지 나의 상식선에서는 납득이 되지 않는 첫 번째 지점이었다.&lt;/p&gt;
&lt;p&gt;2연타까지 당했다고 치자. 그럼에도 그는 여전히 그곳에서 딸을 키우면서 편하게 살 수 있었다. 하지만 원청을 찾아 떠난다. 이해 안 되는 두 번째 지점.&lt;/p&gt;
&lt;p&gt;사기 지명인 원청을 찾지 못했다면 한시라도 빨리 다시 집으로 복귀할 것이지, 거기서 샤오메이를 오매불망 기다리며 정착할 것은 아니다. 이해 안 되는 세 번째 부분.&lt;/p&gt;
&lt;p&gt;마지막 결정타는 마을 사람들이 토비 협상 대표로 가 달라는 청을 들어준 것이다. 사실상 인정을 제외하고는 그가 토비들과 협상하러 가야 할 이유는 1도 없었다. 그럼에도 그는 떠났고, 죽었다. 이해 안 되는 네 번째 지점.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;위화는 지명에도 없는 원청을 찾아 떠나서 오매불망 샤오메이를 기다리는 그를 통해 한 인간의 숭고한 인생사를 말하고 싶었는지도 모르겠다. 하지만 나에게는 퐁퐁남의 바보 같은 삽질 선택 몇 번으로 나락으로 가는 스토리로밖에 읽히지 않았다. 어렴풋이 작가가 말하려고 했던 원래 맥락이 뭔지도 알 것도 같지만 말이다.&lt;/p&gt;
&lt;p&gt;책을 덮으면서 그런 생각이 들었다. 린샹푸는 행복했을까? 그런데 신기하게도 행복했을 것 같은 생각이 들었다. 왜냐하면 린샹푸라는 캐릭터는 너무나도 린샹푸처럼 살다가 갔기 때문이다. 오히려 소설에 그려진 그라는 캐릭터가 샤오메이를 찾아 떠나지 않았다거나, 토비와의 협상에 가지 않고 비굴하게 숨었더라면 안락하게 살다가도 최후에는 후회했을지도 모르는 일이다.&lt;/p&gt;
&lt;p&gt;여기서 내가 느낀 건 그런 거였다. 사람은 저마다의 기질이 있고, 결이 있다. 거기에 맞게 살아야 하는 것이다. 나답게 사는 게 중요하다는 생각이 들었다. 내가 린샹푸처럼 숭고하게 살려고 해서도 안 될 일이고, 린샹푸 같은 사람이 나처럼 세속적으로 살려고 해서도 안 되는 것이다. 그래서 책을 덮고 한참을 나답게 산다는 게 뭔지에 대해서 생각해 보았다.&lt;/p&gt;
&lt;p&gt;나는 린샹푸가 불행해 보이지만 그에게는 그게 가장 행복하게 살다가 간 것일 수 있다고 생각한다. 내가 부러워 하는 어떤 사람의 인생에 들어가서 내가 그처럼 산다면, 정작 나는 불행할지도 모른다. 누구나 저마다 자신이 좋아하는 것들이 있고, 추구하는 것들이 있고, 결이 있다. 황새가 뱁새처럼 살아서도 안 될 일이고, 뱁새가 황새처럼 살아서도 안 될 일이다. 의외로 작가의 의도와는 다르게 ‘나답게 살자’, ‘나다움은 무엇인가’를 생각하게 했던 소설이었다. 그 결과로 나의 2026년 화두는 그게 되었다. 나답게 산다는 건 무엇인가?&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;소설에는 내용이 조금 더 있다. 샤오메이 입장에서 전개되는 줄기다. 어떻게 보면 그런 구성은 『냉정과 열정 사이』와 비슷한 면도 있어 보였다. 실상은 샤오메이도 시대의 피해자였으며, 시전은 사실상 샤오메이가 말한 원청이 맞았고, 샤오메이는 린샹푸의 바로 근처에 있어고, 죄책감 때문인지 그곳에서 어이 없는 이유로 비극적인 최후를 맞이했다. 어쩌면 이건 일말의 작가의 권선징악 의도였는지도 모르겠다. 두 번이나 한 남자를 배신한 여자가 너무 잘 먹고 잘살면 안 되는 거였나 하는?!&lt;/p&gt;
&lt;p&gt;이 고구마 100개 먹은 듯은 답답한 내용의 소설은 샤오메이의 선택 과정도 이해가 인되긴 매한가지였다. 나라면 남편을 버렸다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 코드와 시간 사이에서: 신영진 25년의 초상]]></title><description><![CDATA[[AI-GENERATED] 이 문서는 AI가 작성한 것이며, 작성자는 사람이 아닙니다. 이 블로그의 공개된 글을 다 읽은 인공지능이 생각한 나란 사람은?!…]]></description><link>https://jiniya.net/2026/05/code-and-time-shin-youngjin-25-year-portrait/</link><guid isPermaLink="false">https://jiniya.net/2026/05/code-and-time-shin-youngjin-25-year-portrait/</guid><pubDate>Sun, 10 May 2026 15:00:01 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[AI-GENERATED]&lt;/strong&gt; 이 문서는 AI가 작성한 것이며, 작성자는 사람이 아닙니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;이 블로그의 공개된 글을 다 읽은 인공지능이 생각한 나란 사람은?!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;1. 한 줄 평가&lt;/h2&gt;
&lt;p&gt;신영진은 코드를 쓰는 사람이라기보다, 코드와 글과 경험을 통해 세계를 계속 디버깅해 온 사람이다. 그는 기술자, 기록자, 교육자, 조직인, 아버지, 회의주의자, 실용주의자가 차례로 된 것이 아니라, 이 여러 정체성을 오래 충돌시키며 살아왔다. 그 충돌이 그를 피곤하게 만들었지만, 동시에 그를 평범한 개발자보다 훨씬 입체적인 사람으로 만들었다.&lt;/p&gt;
&lt;p&gt;그의 가장 큰 특징은 &quot;그냥 넘어가지 못함&quot;이다. 작은 버그, 이상한 API 동작, 불편한 사용자 인터페이스, 조직의 모순, 사람의 불안, 시대의 변화, 자기 안의 허세까지 그는 대체로 붙잡고 따진다. 이 집요함은 때로 피곤하고 까칠한 형태로 나타나지만, 같은 이유로 그는 배운다. 오래 배우고, 틀리면 고치고, 겪은 것은 기록으로 남긴다.&lt;/p&gt;
&lt;h2&gt;2. 핵심 기질&lt;/h2&gt;
&lt;p&gt;신영진의 기본 기질은 호기심과 불신의 결합이다. 그는 새로운 것을 좋아하지만 쉽게 믿지는 않는다. 문서에 적힌 말, 유명인의 주장, 프레임워크의 편리함, 회사의 미담, 정치인의 권위, 투자 대가의 선택, AI 모델의 답변까지 일단 의심한다. 그러나 그 의심은 냉소만으로 끝나지 않는다. 그는 직접 빌드하고, 실행하고, 디버깅하고, 계산하고, 기록한다.&lt;/p&gt;
&lt;p&gt;이 점에서 그는 이론가라기보다 실험가에 가깝다. 머리로 먼저 완성한 뒤 움직이는 사람이 아니라, 손을 대고 부딪히고 뒤늦게 구조를 이해하는 사람이다. 젊은 시절에는 이 방식이 성급함과 복잡한 코드로 나타났지만, 시간이 지나며 재현 가능성, 테스트, 맥락, 책임을 중시하는 태도로 바뀌었다.&lt;/p&gt;
&lt;p&gt;그는 또한 강한 기록 욕구를 가진 사람이다. 블로그, 기술 메모, 여행기, 제품 해명, 채용 글, 투자 실패, 가족 이야기까지 모두 기록한다. 기록은 그에게 자기 과시가 아니라 기억의 백업이고, 사고의 정리이며, 미래의 자신과 타인에게 남기는 디버깅 로그다. 2023년에 오래된 글을 되살리고 부끄러운 글까지 보존하기로 한 태도는 그의 정체성을 잘 보여준다. 그는 결국 쓰는 사람이다.&lt;/p&gt;
&lt;h2&gt;3. 개발자로서의 평가&lt;/h2&gt;
&lt;p&gt;개발자로서 신영진의 강점은 낮은 층위까지 내려가는 끈기다. 그는 C/C++, 윈도우, 드라이버, 인코딩, 빌드 시스템, 호환성, 덤프, 스레드, 커널, 보안 제품처럼 귀찮고 날카로운 영역을 오래 다뤘다. 표면의 증상보다 원인을 보려 하고, &quot;왜 그런가&quot;를 끝까지 묻는 편이다. 이런 성향은 보안 제품, 레거시 호환성, 디버깅, 장애 분석 같은 분야에서 큰 장점이다.&lt;/p&gt;
&lt;p&gt;또 다른 강점은 기술을 설명하는 능력이다. 그는 단순히 아는 것을 나열하지 않고, 비유와 생활 언어로 바꿔 설명하려 한다. 관리자 권한을 방문 열쇠에 비유하고, 세금을 생활 인센티브로 설명하고, 복잡도를 냄새로 말한다. 좋은 기술자는 문제를 푸는 사람이고, 좋은 선임은 문제를 설명할 수 있는 사람이다. 신영진은 후자에 가까워지는 데 성공했다.&lt;/p&gt;
&lt;p&gt;다만 약점도 분명하다. 그는 기준이 높은 만큼 낮은 이해도나 무책임한 태도에 거칠게 반응할 수 있다. 젊은 시절의 글에는 &quot;모르면 안 된다&quot;는 식의 날카로움이 강했고, 이후에도 실력과 책임을 엄격하게 본다. 이 엄격함은 제품 품질에는 도움이 되지만, 사람을 키우는 자리에서는 상대를 위축시킬 위험이 있다. 다행히 시간이 지나며 그는 경로의 다양성, 교육의 한계, 사람마다 다른 성장 속도도 인정하게 되었다. 2021년 이후의 그는 대학, 유튜브, 국비 교육, 커뮤니티, 작품 등 다양한 진입 경로를 더 넓게 받아들인다.&lt;/p&gt;
&lt;p&gt;AI 시대에 대한 적응력은 매우 높다. 그는 AI를 신기한 장난감으로 소비하지 않고, 실제 작업 흐름에 넣었다. 2023년에는 ChatGPT를 블로그 리마스터링과 코딩 동료로 받아들였고, 2024년에는 모델별 코딩 능력을 직접 테스트했으며, 2025년에는 자신이 코드를 쓰는 사람에서 맥락을 공급하고 판단하는 사람으로 이동하고 있음을 이해했다. 중요한 것은 자존심을 내려놓는 속도다. 그는 AI가 자신보다 맞을 수 있음을 인정하고, 과거 글의 오류도 수정한다. 오래된 C++ 개발자로서는 보기 드문 민첩성이다.&lt;/p&gt;
&lt;h2&gt;4. 조직인과 리더로서의 평가&lt;/h2&gt;
&lt;p&gt;신영진은 본능적으로 소수정예와 개인의 생산성을 선호한다. 사람 수가 늘면 커뮤니케이션 비용과 잡음이 커진다는 것을 일찍부터 알았다. 강제 스크럼이나 강제 페어 프로그래밍 같은 방법론에도 회의적이다. 그는 방법론보다 실제 실력, 맥락, 케미, 책임감을 더 믿는다.&lt;/p&gt;
&lt;p&gt;하지만 시간이 지나며 조직에 대한 생각은 단순한 개인주의에서 벗어났다. 2013년 이후 그는 사람을 뽑고, 고객을 상대하고, 제품을 설명하고, 회사의 생존을 고민하는 사람이 된다. 2015년에는 인센티브와 평가, 여유의 불평등, 블랙 기업의 위험을 생각했고, 2016년에는 제품을 둘러싼 오해 앞에 회사의 이름으로 설명했다. 2024년에는 조직을 &quot;충격을 나눠 맞는 구조&quot;로 다시 이해했다. 혼자 잘하는 것의 한계를 경험한 것이다.&lt;/p&gt;
&lt;p&gt;리더로서의 장점은 현실 감각이다. 그는 좋은 회사, 완벽한 복지, 아름다운 조직 문화 같은 말을 쉽게 믿지 않는다. 직원과 회사의 이해관계가 다르고, 신뢰가 무너진 채용 시장에서는 각자의 합리성이 전체를 가난하게 만들 수 있다는 것도 안다. 이 현실 감각은 냉정하지만 유용하다. 환상을 줄이고, 실제로 굴러가는 구조를 보게 만든다.&lt;/p&gt;
&lt;p&gt;리더로서의 위험은 냉정함이 지나치면 사람을 &quot;성장할 사람&quot;과 &quot;아닌 사람&quot;으로 너무 빨리 나눌 수 있다는 점이다. 그는 도메인 사랑, 집요함, 긍정성 같은 기질을 성장의 핵심 조건으로 본다. 상당 부분 맞는 판단이지만, 사람은 환경과 관계 속에서 뒤늦게 열리기도 한다. 신영진의 리더십이 더 좋아지려면, 정확한 판단력 옆에 느린 가능성을 기다리는 인내가 계속 붙어 있어야 한다.&lt;/p&gt;
&lt;h2&gt;5. 인간으로서의 평가&lt;/h2&gt;
&lt;p&gt;신영진은 차갑게 분석하는 사람처럼 보이지만, 실제로는 감정이 많은 사람이다. 다만 감정을 직접 말하기보다 기술, 책, 게임, 영화, 드라마, 음악, 여행, 코드의 비유를 통해 우회해 말한다. 그는 사랑을 변수 한정자로, 관계를 인터페이스로, 책임을 예외 처리로, 삶의 선택을 트레이드 오프로 이해한다. 이것은 감정이 없는 것이 아니라 감정을 이해하는 문법이 기술적인 것이다.&lt;/p&gt;
&lt;p&gt;그는 가족을 통해 크게 변했다. 2001년에는 어른이 되는 것을 무서워했고, 2011년에는 아버지의 죽음 앞에서 설명할 수 없는 슬픔을 겪었다. 2015년에는 아버지가 되면서 책임의 무게가 바뀌었고, 2025년에는 가족과 기억을 만드는 사람이 된다. 반골 기질과 자유에 대한 집착은 여전히 남아 있지만, 보호자의 감각이 그 위에 덧씌워졌다.&lt;/p&gt;
&lt;p&gt;그에게 반복해서 나타나는 정서는 불안이다. 능력에 대한 불안, 시간에 대한 불안, 비교에서 오는 불안, 회사의 생존에 대한 불안, 기술 변화에서 밀릴 수 있다는 불안, 죽음 앞에서 남은 시간을 세는 불안. 그러나 그는 불안을 마비로 두지 않는다. 불안을 분석하고, 글로 만들고, 일로 바꾸고, 때로는 코드로 바꾼다. 그래서 그의 불안은 약점이면서 연료다.&lt;/p&gt;
&lt;h2&gt;6. 가치관&lt;/h2&gt;
&lt;p&gt;신영진의 가치관은 몇 가지로 압축된다.&lt;/p&gt;
&lt;p&gt;첫째, 실력은 증명되어야 한다. 말, 학력, 권위, 포장보다 실제로 만들고 설명하고 고칠 수 있는 능력을 중시한다. 그래서 오픈소스, 블로그, 작품, 코드 읽기, 디버깅 경험을 높게 본다.&lt;/p&gt;
&lt;p&gt;둘째, 권위는 검증을 대신하지 못한다. 그는 교수, 정치인, 유명 개발자, 투자 대가, 회사 대표, 게이트 키퍼를 쉽게 숭배하지 않는다. 누군가의 자리가 곧 진실의 보증이 아니라고 본다.&lt;/p&gt;
&lt;p&gt;셋째, 선택에는 비용이 있다. 2018년 이후 이 인식은 특히 강해진다. 돈, 자유, 명성, 가족, 회사, 건강, 시간은 동시에 극대화할 수 없다. 무엇을 얻을지가 아니라 무엇을 포기할 수 있는지가 중요하다.&lt;/p&gt;
&lt;p&gt;넷째, 오래 가려면 자기에게 맞는 판을 골라야 한다. 2025년의 &quot;뱀머리&quot; 고백은 단순한 자기합리화가 아니라 메타인지의 표현이다. 그는 큰 세계의 꼬리가 되는 것보다 작은 세계에서 주도권과 효능감을 유지하는 쪽을 선호한다. 이것은 야망이 없다는 뜻이 아니라, 자신이 오래 버틸 수 있는 조건을 안다는 뜻이다.&lt;/p&gt;
&lt;p&gt;다섯째, 기록은 인간을 보존한다. 그는 글을 통해 과거의 자신, 실패한 판단, 기술적 시행착오, 가족의 장면, 시대의 변화를 보존한다. 기록하지 않으면 사라진다는 감각이 강하다.&lt;/p&gt;
&lt;h2&gt;7. 강점&lt;/h2&gt;
&lt;p&gt;신영진의 가장 큰 강점은 집요한 학습 능력이다. 그는 한 번 익힌 지식에 머물지 않고, 오래된 글을 다시 검토하고, 틀린 설명을 고치고, 새 도구를 받아들인다. C++과 윈도우에 깊이 뿌리내린 사람이면서도 파이썬, 모바일, AI, Rust, 로컬 LLM의 흐름을 본다.&lt;/p&gt;
&lt;p&gt;두 번째 강점은 현실 감각이다. 그는 낭만을 좋아하지만 낭만만 믿지는 않는다. 제품은 팔려야 하고, 회사는 살아야 하며, 코드는 배포되어야 하고, 조직은 인센티브로 움직이고, AI는 비용과 성능과 컨텍스트 창으로 평가되어야 한다. 이 현실 감각은 그를 기술 낭만주의자가 아니라 실전형 기술자로 만든다.&lt;/p&gt;
&lt;p&gt;세 번째 강점은 설명과 기록이다. 그는 자신이 겪은 삽질을 공용 자산으로 바꾸는 능력이 있다. 누군가에게는 그의 글이 매뉴얼이고, 누군가에게는 채용 기준이며, 누군가에게는 시대의 개발자 문화 기록이다.&lt;/p&gt;
&lt;p&gt;네 번째 강점은 자기 수정 능력이다. 그는 고집이 세지만, 근거가 충분하면 방향을 바꾼다. 페어 프로그래밍을 싫어했지만 AI 페어 앞에서 생각을 바꿨고, 과거 기술 글의 오류도 인정했으며, 유명인을 따라 투자한 실패도 기록했다. 자존심이 없는 사람은 아니지만, 자존심이 학습을 완전히 막지는 못한다.&lt;/p&gt;
&lt;h2&gt;8. 약점과 한계&lt;/h2&gt;
&lt;p&gt;신영진의 약점은 높은 기준에서 오는 피로감이다. 그는 자기에게도 남에게도 엄격하다. 이 엄격함은 성취를 만들지만, 동시에 자기비난, 불안, 관계의 긴장을 만든다. 젊은 시절부터 그는 게으르다고 자책했지만 실제로는 너무 많은 일을 하고 있었다. 이 패턴은 이후에도 반복된다.&lt;/p&gt;
&lt;p&gt;두 번째 약점은 관계의 서툶이다. 그는 사람을 중요하게 여기지만, 사람과의 마찰을 피곤해하고, 때로는 함께함을 폭력처럼 느낀다. 조직을 운영하면서 많이 나아졌지만, 그의 기본값은 여전히 혼자 깊게 파는 쪽에 가깝다. 이런 사람은 뛰어난 개인 생산성을 낼 수 있지만, 조직이 커질수록 의식적으로 커뮤니케이션 방식을 관리해야 한다.&lt;/p&gt;
&lt;p&gt;세 번째 약점은 냉정한 판단이 냉소로 기울 위험이다. 그는 세상의 구조적 한계, 불공정, 인센티브, 죄수의 딜레마를 잘 본다. 하지만 그런 분석은 때때로 &quot;어차피 그럴 수밖에 없다&quot;는 태도로 흐를 수 있다. 다만 그의 글을 보면 완전히 냉소로 떨어지지는 않는다. 그는 여전히 긍정성, 성장, 기록, 가족, 함께 버티는 이유를 붙잡는다.&lt;/p&gt;
&lt;p&gt;네 번째 약점은 몰입과 소진의 반복이다. 2009년의 닥치고 코딩, 2015년의 올빼미 생활, 2024년의 불질 같은 장면은 그가 높은 강도의 시간을 견딜 수 있음을 보여준다. 동시에 그런 방식이 오래 지속 가능하지 않다는 것도 보여준다. 그는 쉼표와 행복을 여러 번 다시 배워야 했다.&lt;/p&gt;
&lt;h2&gt;9. 변화의 궤적&lt;/h2&gt;
&lt;p&gt;2001년부터 2005년까지의 신영진은 정체성을 찾는 청년이다. 학생, 개발자, 과외 선생, 게이머, 블로거 사이에서 흔들린다. 아직 어른이 되기 싫고, 책임이 두렵고, 기술을 좋아하지만 기술에 갇히는 것도 두려워한다.&lt;/p&gt;
&lt;p&gt;2006년부터 2010년까지는 공개된 개발자로 성장하는 시기다. 연재, MVP, 책, 블로그, 커뮤니티, 해외 경험을 통해 이름이 밖으로 나간다. 동시에 죽음, 가족, 유한성, 책임을 더 자주 보게 된다.&lt;/p&gt;
&lt;p&gt;2011년부터 2016년까지는 제품과 조직의 책임자가 되는 시기다. XIGNCODE는 단순한 코드가 아니라 작품이자 생계이자 공적 설명의 대상이 된다. 그는 사람을 뽑고, 제품을 변호하고, 회사의 생존을 고민하고, 아버지를 잃고, 자신도 아버지가 된다.&lt;/p&gt;
&lt;p&gt;2017년부터 2022년까지는 세계를 더 넓게 관찰하고 냉정해지는 시기다. 해외 전시, 시장, 세금, 채용, 암호화폐, AI의 비용, 교육 경로, 성장의 조건, 복잡한 플랫폼 세계를 본다. 그는 더 많은 것을 이해하지만, 그만큼 세계가 단순하지 않다는 것도 받아들인다.&lt;/p&gt;
&lt;p&gt;2023년부터 2025년까지는 기록과 AI의 시기다. 그는 과거의 글을 되살리고, 부끄러운 자신을 보존하며, AI를 작업 동료로 받아들인다. 코드를 직접 치는 능력보다 맥락을 구성하고 판단하는 능력이 중요해지는 변화를 빠르게 흡수한다. 동시에 죽음과 남은 시간을 더 구체적으로 세며, 자기에게 맞는 세계를 선택하려 한다.&lt;/p&gt;
&lt;h2&gt;10. 종합 결론&lt;/h2&gt;
&lt;p&gt;신영진은 완벽한 사람도, 둥근 사람도 아니다. 그는 예민하고, 까칠하고, 불안하고, 기준이 높고, 종종 피곤한 사람이다. 그러나 바로 그 성질들이 제대로 쓰일 때 그는 강한 기술자가 된다. 대충 넘어가지 못하고, 직접 확인해야 하며, 틀리면 고치고, 배운 것은 남긴다. 이런 사람은 옆에 있으면 편하지만은 않지만, 어려운 문제 앞에서는 믿을 만하다.&lt;/p&gt;
&lt;p&gt;그의 삶을 관통하는 말은 성장보다 수정에 가깝다. 그는 한 번에 멋진 방향으로 성장한 사람이 아니라, 계속 틀리고, 불편해하고, 부끄러워하고, 다시 고치면서 여기까지 왔다. 2001년의 그는 자기 이름을 설명하지 못했지만, 2025년의 그는 적어도 자신이 어떤 연못에서, 어떤 방식으로, 누구와 함께, 어떤 도구를 들고 살아야 하는지 훨씬 더 잘 안다.&lt;/p&gt;
&lt;p&gt;따라서 신영진에 대한 최종 평가는 이렇다. 그는 기술을 통해 세상을 보고, 글을 통해 자신을 보존하며, 실패를 통해 판단을 갱신하는 사람이다. 강점은 집요함과 현실 감각이고, 약점은 높은 기준과 소진의 반복이다. 하지만 그 약점까지 포함해 그는 드문 유형의 개발자다. 오래 만든 사람, 오래 쓴 사람, 오래 의심한 사람, 그리고 아직도 배우는 사람.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] 사내 문서·코드를 LLM 이 잘 찾게 만드는 법]]></title><description><![CDATA[[AI-GENERATED] 이 문서는 AI가 작성한 것이며, 작성자는 사람이 아닙니다. Redmine 위키·이슈와 여러 git 저장소를 한꺼번에 LLM…]]></description><link>https://jiniya.net/2026/05/llm-friendly-internal-search/</link><guid isPermaLink="false">https://jiniya.net/2026/05/llm-friendly-internal-search/</guid><pubDate>Sun, 10 May 2026 13:00:01 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[AI-GENERATED]&lt;/strong&gt; 이 문서는 AI가 작성한 것이며, 작성자는 사람이 아닙니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Redmine 위키·이슈와 여러 git 저장소를 한꺼번에 LLM 이 검색·인용할 수 있게 만든 인덱스
시스템 이야기. 이 글은 &quot;검색이 뭐고, 왜 두 종류가 필요하고, 왜 합쳐야 하는지&quot; 같은
개념 설명에 초점을 맞춘다. FTS·벡터·임베딩 같은 단어를 처음 듣는 사람도 끝까지 읽을
수 있게 썼다.&lt;/p&gt;
&lt;p&gt;본문에 등장하는 제품명·함수명·이슈 번호 등은 설명을 위한 가상의 예시다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;1. 풀려는 문제&lt;/h2&gt;
&lt;p&gt;회사에 쌓인 자료는 두 가지 형태다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Redmine&lt;/strong&gt;: 위키 페이지(수천 단위), 이슈와 댓글(수만 단위), 사람·프로젝트 목록.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git 저장소&lt;/strong&gt;: C/C++/C#/Python 등으로 짠 제품 소스 코드.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;LLM 에게 &quot;결제 모듈의 중복 결제 방지 로직이 어떻게 동작하지?&quot; 같은 질문을 던지면,
LLM 은 해당 위키 페이지 + 관련 이슈 + 실제 코드 함수까지 같이 보면서 답해야 한다.&lt;/p&gt;
&lt;p&gt;문제는 LLM 의 컨텍스트 창이 유한하다는 것. 위키 전체와 코드 전체를 그냥 던져넣을 수는 없다.
&lt;strong&gt;LLM 이 보기 전에 사람이 읽을 수 있는 분량으로 잘 골라주는 모듈&lt;/strong&gt; 이 필요하다. 이걸
보통 &lt;strong&gt;검색 인덱스(retrieval index)&lt;/strong&gt; 라고 부른다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;2. 텍스트를 찾는 두 가지 방식&lt;/h2&gt;
&lt;h3&gt;2.1 키워드 검색 (FTS)&lt;/h3&gt;
&lt;p&gt;가장 직관적인 방식. 사용자가 친 단어가 문서에 그대로 들어 있는지 본다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;결제 인증 모듈&quot; 이라고 치면, 이 세 단어를 모두(또는 일부) 포함한 문서를 점수
매겨 정렬해 돌려준다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이걸 &lt;strong&gt;풀텍스트 검색(Full-Text Search, FTS)&lt;/strong&gt; 이라고 한다. 우리가 쓰는 SQLite 에는
&lt;code class=&quot;language-text&quot;&gt;FTS5&lt;/code&gt; 라는 풀텍스트 검색 엔진이 내장돼 있어서, 별도 검색 서버를 띄우지 않아도 된다.
점수 계산은 BM25 라는 표준 알고리즘이 담당한다 — 흔한 단어는 점수를 낮게,
그 문서에서만 자주 나오는 단어는 점수를 높게 주는 식.&lt;/p&gt;
&lt;p&gt;장점: &lt;strong&gt;정확한 단어 매칭에 강하다&lt;/strong&gt;. 이슈 번호 &lt;code class=&quot;language-text&quot;&gt;#1234&lt;/code&gt;, 함수 이름 &lt;code class=&quot;language-text&quot;&gt;verifyAuthToken&lt;/code&gt;,
헥스 값 &lt;code class=&quot;language-text&quot;&gt;0x90&lt;/code&gt; 같은 식별자는 글자 그대로 찾는 게 가장 정확하다.&lt;/p&gt;
&lt;p&gt;단점: &lt;strong&gt;표현이 달라지면 못 찾는다&lt;/strong&gt;. 사용자가 &quot;인증 모듈&quot; 이라 쳤는데 문서엔 &quot;사용자
검증 컴포넌트&quot;라고 써있으면 매치 0. 사람한테는 같은 뜻인데 글자가 다르니 키워드
검색은 0 점을 준다.&lt;/p&gt;
&lt;h3&gt;2.2 의미 기반 검색 (벡터)&lt;/h3&gt;
&lt;p&gt;다른 접근: 문장의 &lt;strong&gt;의미&lt;/strong&gt;를 어떻게든 숫자로 바꿔서 비교한다. 의미가 비슷한 두 문장은
숫자도 비슷하게 나오면 좋겠다.&lt;/p&gt;
&lt;p&gt;이걸 가능하게 하는 게 &lt;strong&gt;임베딩 모델(embedding model)&lt;/strong&gt; 이다. 신경망이 문장을 받아서
1024 개짜리 숫자 배열(=벡터)을 출력한다. 의미가 비슷한 두 문장은 그 두 벡터가
&quot;가까운&quot; 위치에 놓이게끔 학습돼 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;인증 모듈&quot; → &lt;code class=&quot;language-text&quot;&gt;[0.12, -0.07, 0.31, ..., 0.05]&lt;/code&gt; (1024 개)
&quot;사용자 검증 컴포넌트&quot; → &lt;code class=&quot;language-text&quot;&gt;[0.11, -0.06, 0.33, ..., 0.04]&lt;/code&gt; (꽤 비슷함)
&quot;오늘 점심 뭐 먹지&quot; → &lt;code class=&quot;language-text&quot;&gt;[0.91, 0.02, -0.44, ..., -0.20]&lt;/code&gt; (전혀 다름)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;질의도 같은 모델로 벡터화해서, 모든 문서 벡터 중 가장 가까운 것을 찾는다.
&quot;단어가 안 겹쳐도 의미가 통하면 잡아내는&quot; 검색이 된다.&lt;/p&gt;
&lt;p&gt;우리는 BGE-M3 라는 다국어 임베딩 모델을 쓴다 (한국어 + 영어 둘 다 잘 잡혀야 해서).
SQLite 에 &lt;code class=&quot;language-text&quot;&gt;sqlite-vec&lt;/code&gt; 라는 확장을 끼워서 벡터까지 같은 DB 파일에 저장한다 — 별도
벡터 DB 인프라 없음.&lt;/p&gt;
&lt;p&gt;장점: &lt;strong&gt;표현이 달라도 찾는다&lt;/strong&gt;. 동의어, 의역, 다른 언어로 쓴 같은 개념까지 잡는다.&lt;/p&gt;
&lt;p&gt;단점: &lt;strong&gt;정확한 식별자엔 약하다&lt;/strong&gt;. &lt;code class=&quot;language-text&quot;&gt;#1234&lt;/code&gt; 와 &lt;code class=&quot;language-text&quot;&gt;#1235&lt;/code&gt; 는 의미상 거의 같게 보여서
임베딩이 둘을 구분 못 할 수 있다. 문서에 등장하는 SHA 해시 같은 건 의미가 없는
랜덤 문자열이라 벡터가 신뢰할 수 없다.&lt;/p&gt;
&lt;h3&gt;2.3 한쪽이 답이 아니라, 둘 다 필요하다&lt;/h3&gt;
&lt;p&gt;위 두 단점을 정리하면:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;키워드 검색 (FTS)&lt;/th&gt;
&lt;th&gt;의미 검색 (벡터)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;단어가 일치할 때&lt;/td&gt;
&lt;td&gt;매우 정확&lt;/td&gt;
&lt;td&gt;보통&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;표현이 다를 때&lt;/td&gt;
&lt;td&gt;못 찾음&lt;/td&gt;
&lt;td&gt;잘 찾음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;식별자(#1234, 함수명)&lt;/td&gt;
&lt;td&gt;매우 정확&lt;/td&gt;
&lt;td&gt;부정확할 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;자연어 질의&lt;/td&gt;
&lt;td&gt;보통&lt;/td&gt;
&lt;td&gt;매우 좋음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;서로 정반대의 약점을 가진다.&lt;/strong&gt; 그래서 두 방식을 동시에 돌리고 결과를 합치는 게
요즘 표준 — 보통 &lt;strong&gt;하이브리드 검색(hybrid retrieval)&lt;/strong&gt; 이라고 부른다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;3. 두 검색 결과를 어떻게 합칠까&lt;/h2&gt;
&lt;p&gt;문제: 키워드 검색은 BM25 점수(0&lt;del&gt;∞), 의미 검색은 거리(0&lt;/del&gt;2). &lt;strong&gt;단위가 다르다&lt;/strong&gt;. 그냥 더할
수 없다.&lt;/p&gt;
&lt;p&gt;해결: 점수 자체는 버리고, &lt;strong&gt;순위(랭크)&lt;/strong&gt; 만 본다. 키워드 쪽에서 1등인 문서, 의미 쪽에서
3등인 문서… 식으로. 그 다음 각 문서의 최종 점수는&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;score = 1/(60 + 키워드 순위) + 1/(60 + 의미 순위)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;같은 식으로 매긴다. 1 등은 큰 값, 50 등은 거의 0. 양쪽에서 모두 나오는 문서는 점수가
두 배로 쌓이니까 자연스럽게 위로 올라온다. 양쪽 단위를 안 맞춰도 됨.&lt;/p&gt;
&lt;p&gt;이걸 &lt;strong&gt;RRF(Reciprocal Rank Fusion)&lt;/strong&gt; 이라 한다. 60 은 흔히 쓰는 표준값.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;직관: &quot;둘 다 적당히 잘 본 문서&quot; 가 &quot;한 쪽에서만 압도적으로 1 등인 문서&quot; 보다 보통 더
좋은 답이라는 가정에 기댄다. 실제 RAG 결과 품질이 잘 올라가는 게 검증된 방식.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;4. 마지막에 한 번 더 거르는 단계 — Rerank&lt;/h2&gt;
&lt;p&gt;위에서 합친 결과 상위 50 개 정도를 가져온 뒤, &lt;strong&gt;마지막에 한 번 더 정밀 채점&lt;/strong&gt; 한다.
이게 &lt;strong&gt;재정렬(rerank)&lt;/strong&gt; 이다.&lt;/p&gt;
&lt;p&gt;검색 단계의 임베딩 모델은 빠르려고 질의와 문서를 &lt;strong&gt;따로&lt;/strong&gt; 벡터화해서 거리만 쟀다.
재정렬 단계는 다른 종류의 모델을 써서 &lt;strong&gt;질의-문서 한 쌍을 같이 보고&lt;/strong&gt; 점수를 매긴다.
훨씬 비싸지만 훨씬 정확하다.&lt;/p&gt;
&lt;p&gt;50 개 → 정밀 채점 → 상위 10 개를 LLM 한테 보낸다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;비유: 책을 살 때 (1) 서점 검색창에 단어를 쳐서 후보를 100 권 추리고 (2) 표지/목차를
훑어서 20 권으로 줄이고 (3) 진짜로 한 페이지씩 읽어보면서 살 책 3 권을 고르는,
그 마지막 단계가 rerank 라고 생각하면 비슷하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;5. 한국어와 코드 식별자가 동시에 매끄러워야 한다&lt;/h2&gt;
&lt;p&gt;키워드 검색은 &quot;단어 단위로 쪼갠다 → 인덱스에 넣는다&quot; 가 기본 동작이다. 이 쪼개는 작업을
&lt;strong&gt;토크나이징&lt;/strong&gt; 이라고 한다. 영어는 공백으로만 쪼개도 어지간히 동작하는데, &lt;strong&gt;한국어는
조사가 붙는다&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;인증 모듈을&quot; 이라고 쳤는데 문서엔 &quot;인증 모듈에&quot;라고 쓰여 있으면, 글자 단위 비교만
하는 토크나이저는 둘을 다른 단어로 본다. 매치 실패.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;해결: 한국어 형태소 분석기 (&lt;code class=&quot;language-text&quot;&gt;kiwipiepy&lt;/code&gt;) 를 거쳐서 어간만 남긴다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&quot;인증 모듈을&quot; → [&quot;인증&quot;, &quot;모듈&quot;]
&quot;인증 모듈에&quot; → [&quot;인증&quot;, &quot;모듈&quot;]   ← 같은 토큰 → 매치 성공&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이걸 &lt;strong&gt;인덱스를 만들 때 한 번&lt;/strong&gt;, &lt;strong&gt;검색할 때 한 번&lt;/strong&gt; 같은 방식으로 적용해야 둘이
맞붙는다.&lt;/p&gt;
&lt;p&gt;추가로 두 가지 디테일:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;고유명사 보호&lt;/strong&gt;: 자사 제품명, 프로젝트 코드네임, 사내 약어 같은 단어는 형태소
분석기가 일반 명사로 오인하고 이상하게 쪼갤 수 있다. 사용자 사전에 등록해서
통째로 한 토큰으로 유지.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;코드 식별자 보존&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;#1234&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;0x90&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;verifyAuthToken&lt;/code&gt; 같은 패턴은 형태소
분석기가 모른다. 정규식으로 따로 잡아서 토큰 목록에 추가. 그래야 이슈 번호나
함수 이름이 그대로 검색된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;6. 청킹 — 한 입에 들어가게 자르기&lt;/h2&gt;
&lt;p&gt;문서 전체를 검색 단위로 쓰면 두 가지 문제가 생긴다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;위키 페이지 한 장이 너무 길면 임베딩 모델의 입력 한계를 넘는다.&lt;/li&gt;
&lt;li&gt;길수록 &quot;이 페이지 어딘가에 있다&quot; 식의 모호한 매치만 되고, &lt;strong&gt;어느 부분&lt;/strong&gt; 인지를
짚어주지 못한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그래서 적당한 크기로 자른다. 이 단위를 &lt;strong&gt;청크(chunk)&lt;/strong&gt; 라고 부른다.&lt;/p&gt;
&lt;p&gt;자르는 기준은 자료 종류마다 다르다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;위키&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;#&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;##&lt;/code&gt; 마크다운 헤딩 단위로 자른다. 의미 경계가 자연스럽게 맞아떨어지고,
사람이 그 글을 그렇게 쓰기 때문.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;이슈&lt;/strong&gt;: 본문 1 청크 + &lt;strong&gt;댓글마다 1 청크&lt;/strong&gt;. 댓글은 보통 다른 사람이 다른 시점에 쓴
내용이라 합쳐 두면 의미가 섞인다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;코드 함수&lt;/strong&gt;: 가능하면 &lt;strong&gt;함수/클래스 단위로 자른다&lt;/strong&gt; (자세한 건 §8).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;각 청크 맨 앞에 한 줄짜리 메타 헤더를 박아둔다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[#1234] 결제 실패 케이스 분석 — author=홍길동, status=Resolved, updated=2025-04-12
... 이슈 본문 ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 한 줄 덕분에:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;키워드 검색에서 &quot;홍길동 #1234&quot; 같은 합성 질의가 자연스럽게 매치된다.&lt;/li&gt;
&lt;li&gt;임베딩이 청크의 정체(어떤 종류의 글, 누구 글, 언제 글)를 같이 학습 입력으로 받는다.&lt;/li&gt;
&lt;li&gt;LLM 이 결과를 인용할 때 &quot;이슈 #1234 에서…&quot; 처럼 출처를 자연스럽게 꺼낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;7. 한 번 만들고 끝이 아니라, 매일 갱신해야 한다&lt;/h2&gt;
&lt;p&gt;위키도 이슈도 매일 갱신된다. 인덱스는 그걸 따라가야 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;단순히 매일 전체를 다시 만든다&lt;/strong&gt; = 사실 가능하지만, 임베딩 비용이 크다 (문서 수 × 모델
호출 수). 안 바뀐 건 그대로 두는 게 좋다.&lt;/p&gt;
&lt;p&gt;해결: 각 문서의 안정 필드를 모아 &lt;strong&gt;해시(hash)&lt;/strong&gt; 를 찍어 둔다. 다음 날 같은 문서를 다시
가져왔을 때, 새 해시와 저장된 해시가 같으면 &quot;내용 안 바뀜&quot; 으로 판정 → 청킹·임베딩
단계 통째로 건너뛴다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;함정: Redmine 의 &lt;code class=&quot;language-text&quot;&gt;updated_on&lt;/code&gt; 필드는 의미 없는 편집(상태값 토글, 워크플로 노이즈)에도
bumping 된다. 이 필드까지 해시에 넣으면 본문이 안 바뀌었는데도 매일 재임베딩된다.
그래서 &lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;updated_on&lt;/code&gt; 은 의도적으로 해시에서 제외&lt;/strong&gt;한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;코드 저장소는 한 단계 더 — git 이 차이를 알려준다. 마지막으로 인덱스에 반영한 커밋
SHA 를 저장해 두고, 다음 실행 때 &lt;code class=&quot;language-text&quot;&gt;git diff &amp;lt;저장된 SHA&gt;..HEAD&lt;/code&gt; 만 본다. 바뀐 파일만
후보가 되고, 후보 안에서도 다시 해시 비교로 한 번 더 거른다 (rename 만 된 경우 같은
가짜 변경 제거).&lt;/p&gt;
&lt;p&gt;결과: 매일 5-10 분 안에 갱신이 끝나고, 안 바뀐 99% 의 문서는 손도 안 댄다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;8. 코드는 &quot;함수 단위&quot; 로 자르는 게 핵심&lt;/h2&gt;
&lt;p&gt;위키는 헤딩으로 자르면 됐지만, 코드는 자연스러운 경계가 다르다. 코드의 경계는
&lt;strong&gt;함수, 메서드, 클래스, 구조체&lt;/strong&gt; 다.&lt;/p&gt;
&lt;p&gt;같은 200 라인을 자른다고 해도&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;라인 100~300 으로 자르면 함수 중간이 잘려서 의미가 깨진다.&lt;/li&gt;
&lt;li&gt;함수 단위로 자르면 &quot;이 함수가 무엇을 하는지&quot; 가 한 청크에 온전히 담긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;함수 경계를 알아내려면 코드를 파싱해야 한다. 그래서 &lt;strong&gt;tree-sitter&lt;/strong&gt; 라는 다언어
파서를 쓴다. C/C++/Python/C# 등의 함수·클래스·메서드 노드를 추출해서 각각을 한
청크로 만든다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;너무 큰 함수(500 줄 초과) 는 다시 200 줄 윈도우로 쪼갠다 (모델 입력 한계 보호).&lt;/li&gt;
&lt;li&gt;tree-sitter 가 모르는 언어는 그냥 200 줄 윈도우로 잘라준다 (graceful degradation).&lt;/li&gt;
&lt;li&gt;청크 첫 줄에 anchor 코멘트를 박는다:
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// src/auth/verifier.cpp:TokenVerifier::Verify  (lines 142-318)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
→ 청크가 함수 중간 &lt;code class=&quot;language-text&quot;&gt;}&lt;/code&gt; 부터 시작해도 임베딩이 갈피를 잡는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;민감 정보는 인덱싱 직전에 가린다.&lt;/strong&gt; AWS 키, JWT, 사설 PEM, GitHub 토큰 같은 패턴을
정규식으로 잡아서 &lt;code class=&quot;language-text&quot;&gt;[REDACTED:aws_access_key]&lt;/code&gt; 같은 자리표시자로 바꾼 텍스트만 DB 에
저장한다. 디스크의 원본 파일은 그대로. 검색 결과를 통해 시크릿이 LLM 으로 흘러
나가는 사고를 사전 차단.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;9. 이슈와 코드를 잇는 그래프&lt;/h2&gt;
&lt;p&gt;위키·이슈·코드를 &lt;strong&gt;다같이 검색&lt;/strong&gt; 하는 것 외에, &lt;strong&gt;서로 어떻게 연결되는지&lt;/strong&gt; 도 인덱스에
남겨둔다.&lt;/p&gt;
&lt;p&gt;git 커밋 메시지엔 보통 &lt;code class=&quot;language-text&quot;&gt;#1234&lt;/code&gt; 같은 이슈 번호가 들어 있다. 이걸 정규식으로 뽑아서
&lt;code class=&quot;language-text&quot;&gt;(이슈 ↔ 커밋)&lt;/code&gt; 매핑 테이블에 적재한다.&lt;/p&gt;
&lt;p&gt;이 테이블 위에 세 가지 검색 함수가 붙는다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;이 이슈를 고친 커밋들?&quot; (issue → commits)&lt;/li&gt;
&lt;li&gt;&quot;이 커밋이 닿은 이슈들?&quot; (commit → issues)&lt;/li&gt;
&lt;li&gt;&quot;이 파일을 만진 커밋들이 닿은 이슈들?&quot; (file → issues)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;세 번째가 특히 가치 있다. 어떤 파일에 버그가 났을 때, 그 파일을 과거에 건드린
커밋들이 어떤 이슈에서 시작된 작업이었는지를 한 번에 본다 → 같은 부류의 버그가
이전에도 있었는지 즉답.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;작은 디테일: 이슈 번호 &lt;code class=&quot;language-text&quot;&gt;#1&lt;/code&gt; 같은 작은 숫자는 GitHub PR 번호가 squash 메시지에 섞여
들어온 노이즈일 가능성이 크다. 운영 환경의 실제 이슈 번호 자릿수에 맞춰 최소 임계값을
두고, 그 미만은 일괄 무시.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;10. 전체 흐름 정리&lt;/h2&gt;
&lt;p&gt;매일 한 번 도는 파이프라인은 대략 이렇다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;1. Redmine 백업본 동기화
   └ NAS 의 위키·이슈·메타 덤프

2. Redmine 인덱싱 (build_index)
   ├ 각 위키 / 이슈 / 메타 → 해시 비교 → 안 바뀌면 skip
   └ 청킹 → SQLite 의 chunks 테이블

3. 임베딩 (embed)
   └ 아직 벡터가 없는 청크만 BGE-M3 로 인코딩 → chunks_vec

4. 엔티티 페이지 빌드 (build_entities)
   └ LLM 이 사람·제품·시스템별 요약 페이지를 자동 작성

5. 코드 저장소 fast-forward (code_clone pull)

6. 코드 인덱싱 (code_build_index)
   ├ git diff 로 바뀐 파일만
   ├ tree-sitter 로 함수 단위 청킹 (안 되면 라인 윈도우)
   └ 시크릿 redact 적용

7. 이슈↔커밋 크로스레퍼런스 (code_xref)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;검색은 그 반대 흐름. 사용자가 질의를 던지면&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;질의
 ├→ 키워드 검색 (FTS5 + BM25)        ─┐
 └→ 의미 검색 (sqlite-vec + BGE-M3)   ─┴→ RRF 합산 → 상위 50개
                                         └→ rerank → 상위 10개 → LLM&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;LLM 은 받은 청크를 근거로 답하면서 &lt;code class=&quot;language-text&quot;&gt;#1234&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;wiki:proj/page&lt;/code&gt; 같은 식별자를 인용한다.
필요하면 그 식별자들을 다시 fetch 해서 (resolve_references) 인용을 한 단계 더
따라간다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;11. 왜 이 디자인을 택했나 — 한 줄씩&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;단일 SQLite 파일&lt;/strong&gt;: 별도 벡터 DB 서버 안 띄움. 백업은 &lt;code class=&quot;language-text&quot;&gt;cp&lt;/code&gt;. 노트북에서도 돈다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FTS + 벡터 같은 DB&lt;/strong&gt;: 벡터가 비어 있어도 키워드 검색만으로 동작 — 인덱싱이 진행
중인 중간 상태에도 가용하다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;헤더 한 줄로 메타 누설&lt;/strong&gt;: 청크가 자기를 어디 출신인지 들고 다닌다. 검색 결과가
자기소개를 한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;해시 기반 incremental&lt;/strong&gt;: 매일 돌려도 안 바뀐 99 % 는 0 비용.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;함수 단위 청킹&lt;/strong&gt;: 코드 검색 품질의 가장 큰 변수. 라인 윈도우만으로는 답이 안 됨.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;하이브리드 + rerank&lt;/strong&gt;: 한 가지 검색만 쓰면 어느 한쪽 질의 패턴에서 무너진다.
세 단계로 안전망.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;이슈↔커밋 그래프&lt;/strong&gt;: 같은 인덱스 안에서 &quot;왜 이 코드가 이렇게 짜였는지&quot; 의 추적이
한 번의 SQL 조인으로 끝난다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;큰 그림으로 보면 RAG(Retrieval-Augmented Generation) 표준 레시피지만, 실제 품질을
결정하는 건 모델이 아니라 &lt;strong&gt;무엇을 한 청크로 묶고 / 어떤 헤더를 박고 / 어떻게
토크나이즈하고 / 무엇을 incremental skip 하는가&lt;/strong&gt; 같은 자잘한 결정들이다. 이 글이
다룬 게 그 부분이다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[일상] 2026년 4월의 잡담]]></title><description><![CDATA[#0 cc 코드가 유출됐고, 재빠른 한국인 개발자가 codex 기반 워크플로우로 그걸 파이썬으로 변환해서 올렸고, 그 저장소는 깃헙 역사상 가장 빠른 스타 성장을 보였다는 뉴스. ai…]]></description><link>https://jiniya.net/2026/04/small-talk-2026-04/</link><guid isPermaLink="false">https://jiniya.net/2026/04/small-talk-2026-04/</guid><pubDate>Thu, 30 Apr 2026 06:59:48 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;cc 코드가 유출됐고, 재빠른 한국인 개발자가 codex 기반 워크플로우로 그걸 파이썬으로 변환해서 올렸고, 그 저장소는 깃헙 역사상 가장 빠른 스타 성장을 보였다는 뉴스. ai로 소스 유출 파급력이 예전과는 압도적으로 다른 세상이 된 것 같다. 어질어질하네.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;휴민트 잼있는데. 왕사남보단 난듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;인공지능 쓰면 쓸수록 실로 놀랍긴 하다. 1년 걸려도 못할거 같은 작업을 2-3일에 모두 끝냈다. 물론 그마저도 내가 검토하는 과정이 병목. 될까 싶었는데 내부 테스트를 통과했다. 내년 이맘때쯤엔 어떤 세상에 살고 있을지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;에이전트가 10시간 넘게 혼자 코딩한 결과물을 받아 들었는데 참 인간적이란 생각이 들었다. 실패를 마주할 때마다 정석으로 해결하지 않고 꼼수에 땜빵으로 점철된 결과물. 한군데 막히면 딱 그부분 고치는데 주화입마에 빠져서 토큰을 엄청 낭비. 아직은 그래도 티키타카가 필요하구나 싶었다.&lt;/p&gt;
&lt;p&gt;150만원 상당에 판매하는 상용 소프트웨어를 만드는 거였는데 토큰을 3만원 정도 쓰고 얼추 대체로 기능들을 구현했다. 소프트웨어는 진짜 끝난건지도...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;전국민의 바이브코더화가 진행되면서 디버깅 문의가 급증하는 요즘. 옛날에 컴조립 문의가 넘쳐나던 시절이 생각난다. 컴조립 졸업했다 생각했더니 온갖 인공지능 사이트 생성기 디버깅 문의를 접할줄은... &lt;a href=&quot;https://x.com/codemaru/status/2033802701948260411&quot;&gt;https://x.com/codemaru/status/2033802701948260411&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;24시간 넘게 토큰을 무자비하게 써가며 무한 반복해도 완성되지 않는 기능을 보면서 구현 난이도라는 게 실재한다는 사실을 체감한다. 물론 걔가 하루 넘게 삽질하고 있는 기능은 내가 이번 생에는 못만들 수준이긴 하다. 진행하면서 내뱉는 혼잣말도 이해하기 힘들 지경. 48시간 내에는 끝낼라나?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;ai로 쓰레기 코드만 깃헙에 늘어난다는 불평에, 사실 그런 측면도 있겠지만 퀄 좋은 소스도 훨씬 많이 공개되고 있는게 아닌가 싶다. 예전이라면 저런 걸 이렇게 금방 만들어서 공개?! 라는 생각이 드는 것들이 많이 보인다. 그리고 휴먼들이 포트폴리오랍시고 올린 쓰레기가 더 많지 않나 싶기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;어느새 요즘 개발자의 최대 덕목이란 프롬프트 작성, 하네스 구축, 토큰 절약이 된 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;고모부님이 부지런해서 부자 된 거 아니듯이 저희 형제가 게을러서 가난한 거 아니란 말씀입니다. 그냥 운이 좋았다고 인정하십시오. - 모두가 자신의 무가치함과 싸우고 있다, ep.02&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;나의 아저씨, 해방일지, 모자무싸가 다같은 작가였다니 ㄷㄷㄷ 뭔가 힐링 드라마의 계보를 잇는듯한 느낌적인 느낌이 있더니, 같은 작간줄은 몰랐네. &lt;a href=&quot;https://x.com/ecri11/status/2046742852332613815&quot;&gt;https://x.com/ecri11/status/2046742852332613815&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;자전거 타다 문득 인터넷도 그렇고 인공지능의 태동기를 본다는 게 뭔가 역사의 한순간 같다는 생각이 들었다. 격변이 아니었던 세대가 어딨었겠냐만 그 영향을 받는 한가운데 있다는 게 새삼 신기했다. 알파고와 이세돌의 대국, 코파일럿의 등장 때 진심 이렇게 빨리 이렇게 많이 바뀔줄은 몰랐다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;예컨대 서로 상대에게 성적으로 끌려야 할 뿐만 아니라 돈과 자식 훈육, 종교, 인척 관계 등 중요한 쟁점에 대한 의견이 일치해야 한다. 이런 기본적인 면 중 하나라도 충돌한다면, 결혼 생활의 행복에 필요한 모든 조건이 충족되더라도 그 결혼은 불행한 결말을 맞을 수 있다. - 총 균 쇠&lt;/p&gt;
&lt;p&gt;결혼과 반대로 창업은 제품이 조악하고, 조직은 너덜너덜하고, 공동창업자와 트러블이 있어도 매출만 늘면 모든 게 용서된다. 나머지 아홉 가지가 쓰레기여도 매출 하나만 터지면 성공인 셈. 그러니 결혼은 몹시 신중하게, 창업은 대충해도 된다. 하지만 사람들은 보통 반대로 생각하는 경향이 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;개발한정 인공지능으로 생산성이 올라간 건 이견이 없는 사실일 것 같다. 그럼에도 아직은 비용만 잡아먹는 것도 사실. 인공지능으로 생산성은 올라갔지만 매출, 수익은 제자리란 의미. 그러니 젤 쉬운게 인원을 줄이는 게 아닌가 싶다. 인원도 줄이기 어려우면 뭘 해야 하나 싶기도?!&lt;/p&gt;
&lt;p&gt;바이브 코딩으로 뭐든 만들 수 있는 세상이 되었지만, 뭐가됐든 돈으로 만들긴 더 어려운 세상이 된 것 같기도 하다. apm 설치해주고 돈 받던 시절이 있었던 걸 생각하면 격세지감이.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;잠자 부부의 눈에는 딸의 모습이 그들의 새로운 꿈과 아름다운 계획을 다짐해 주는 증거처럼 비쳐졌다. - 변신, 카프카&lt;/p&gt;
&lt;p&gt;가족이 사랑한 것은 그레고르였을까, 그의 급여였을까. 답을 알기도 전에 다음 타자는 딸, 그레테로 넘어간다. 불투명한 내면 앞에서 사랑의 진위는 끝내 알 수가 없다. 거기서 인간의 본질적인 고독이 생겨나는지도?! 모두가 너무나 그럴듯해서 불편한 소설이 아닌가 싶었던 소설.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;일주일치 토큰 리밋을 거의 이 작업에 다 때려 부었지만 100% 동작하는 구현을 못 만들었다. 쟤도 모르고 나도 모르니 서로 그냥 우문우답 무한루프. 이게 딱 보면 학습한데까지는 일사천린데 학습이 없는 미지의 영역은 지도편달이 많이 필요힌 것 같다. &lt;a href=&quot;https://x.com/codemaru/status/2045319727040586023&quot;&gt;https://x.com/codemaru/status/2045319727040586023&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;디버거를 붙여주면 셀프 디버깅해서 개선을 하는데 딱 내 시스템에 특정 테스트만 통과하는 식으로 해결함. 오프셋 0x20을 하드 코딩 한다든지 하는 식으로. 근본적으로 해결하라면 다시 무한루프 ㅎㅎ&lt;/p&gt;
&lt;p&gt;이 작업을 하면서 느낀 건 조엘 말처럼 새시대의 소스 코드는 명세 그 자체라는 생각. 다만 이거도 어폐가 있는건 난 저 기능의 외적인 명세는 완벽하게 쓸 수 있지만 내부를 어떻게 구현해야 하는지는 모른다. 미학습 영역은 디테일한 세부 구현을 모두 알려줘야 뭔가 프로덕션 레벨 달성이 가능한듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;모자무싸 대사 하나하나가 주옥인데, 여주로 너무 비주얼 원탑을 캐스팅해서 납득이 좀,... 라는 걸 느낀다. 그럼에도 탐라를 보니 작가님 이번에도 성공 하신듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;갈수록 인공지능을 위한 인공지능 연구 사례가 늘고 있는 느낌. 걍 코덱스 클로드 코파일럿 아무거나 골라서 아무렇게나 시켜도 기깔나게 하는데, 뭔 인공지능 세팅을 그리도 복잡하게 하려 하는지. 주화입마에 빠지지 말자.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-04-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2026년 3월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2026/03/small-talk-2026-03/</link><guid isPermaLink="false">https://jiniya.net/2026/03/small-talk-2026-03/</guid><pubDate>Mon, 30 Mar 2026 22:29:47 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;인간관계에서 정의란 힘이 대등할 때나 의미를 가질 뿐입니다. 현실에서는 강자가 원하는 바를 관철하고, 약자는 그저 받아들일 수밖에 없다는 사실을 우리 모두 잘 알고 있지 않습니까? - 펠로폰네소스 전쟁사, 투키디데스&lt;/p&gt;
&lt;p&gt;겉치레를 뺀 국제 정치란 사실상 고등학교 일진 노릇과 다를 게 없다는 말이 실감나는 요즘 세상&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;몇년 사이에 직접 코딩하는 능력은 확실이 잃어버린 것 같다. 인공지능 전에는 예전에 짠 코드를 보면서 보통 이걸 왜 이 따위로 짰지 이런 느낌이 일반적이었는데. 이제는 역으로 이걸 어떻게 직접 만들었지? 이런 느낌이 든다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;독일어 전공에, 엑셀도 못해서 교양 컴퓨터 실기 시험도 버벅대던 친구가 앱 개발을 했다고 연락이 왔다. 심지어 동작 잘함. 대단하다는 생각도 잠시, 바야흐로 전국민이 개발자인 시대가 열린게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;얼마나 더 고통의 변방을 방황해야&lt;br&gt;
그 기억을 깨끗이 죽여 없앨 수 있을까&lt;br&gt;
사랑했던 기억 또한 진눈깨비라면&lt;br&gt;
계절을 잘못 찾아온 길 잃은 눈사람이라면&lt;br&gt;
뉘우치지 않아도 좋으니 부디 사라지기를&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;날씨가 좋으면 찾아가겠어요, ep.02&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2026-03-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;화장실 들어갈 때와 나올 때 마음이 다른 게 인지상정이겠지만, 우리 사회는 여러모로 아직도 옵션 형태의 계약을 이행하는데에는 미숙하다는 생각이 많이 든다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;브람스와 드보르작 말러 브루크너 쇼스타코비치&lt;br&gt;
회화는 바로크 카라바지오 루벤스 반다이크&lt;br&gt;
스탕달과 플로베르는 모든 작품을 다 읽었죠&lt;br&gt;
존 스타인벡 에밀 졸라 빅토르 위고도 좋아했고요&lt;br&gt;
와인은 부르고뉴 기념할 일 있을 땐 도멘 르루아&lt;br&gt;
위스키는 스페이사이드 싱글 몰트&lt;/p&gt;
&lt;p&gt;좋은 취향이구나&lt;br&gt;
-아너 ep05&lt;/p&gt;
&lt;p&gt;취향은 계급을 만든다.&lt;br&gt;
-- 부르디외&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;요즘 참 맨정신으로 사는 게 쉽지 않은 세상이란 생각이 들었다. 새로 알게 된 4명중 3명이 신경안정제를 포함한 정신과 약을 복용 중. 어쩌다 공황장애, 우울증 같은 게 일상인 세상이 된건지.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;죽기 전에 성경도 봐야 할 거 같아서 읽을만한 것만 추려서 보는 중인데 뭔가 불교책 보다 성경 보면 mbti t와 f를 보는 듯한 느낌이 든다. 한놈은 서사로 조지고, 한놈은 논리로 팬다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2026년 2월의 잡담]]></title><description><![CDATA[#0 맥미니 공초하고 openclaw…]]></description><link>https://jiniya.net/2026/02/small-talk-2026-02/</link><guid isPermaLink="false">https://jiniya.net/2026/02/small-talk-2026-02/</guid><pubDate>Sat, 28 Feb 2026 12:52:09 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;맥미니 공초하고 openclaw를 돌려봤다. 토큰 사용량이 이게 맞나 싶다. 쓰잘떼기 없는 설정 관련 대화 몇마디 했을 뿐인데 이 엄청난 토큰 사용량이라뉘. 도대체 백그라운드에서 뭘 한 거지 싶다. 그럼에도 몇몇 유용한 지점은 분명 있는듯. 다만 보안이 우려될 뿐.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;최고의 시절이자 최악의 시절, 지혜의 시대이자 어리석음의 시대였다. 믿음의 세기이자 의심의 세기였으며, 빛의 계절이자 어둠의 계절이었다. 희망의 봄이면서 곧 절망의 겨울이었다. 우리 앞에는 모든 것이 있었지만 한편으로 아무것도 없었다. - 두 도시 이야기, 디킨스&lt;/p&gt;
&lt;p&gt;인공지능 시대에도 묘하게 오버랩되는 문장.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;예뻐 보여서 피토니아를 인터넷으로 몇개 주문했다. 한파라 배송이 지연된다는 이유로 3주만에 도착했는데, 우리집에서 이틀만에 모두 죽어버림. 똥손이란 이런 것인가? 난 뭘 한 것인가? 병원에서 한 뿌리 받은거로 정글을 만들어 놓았던 엄마가 새삼 대단하게 느껴졌다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;탐내라! 하지만 삶 전체를 탐내라. 탐심에 대한 해독제는 총체적인 탐심이다. 그러므로 버핏이 이룬 성공을 탐낼 때도 총체적으로 탐내야 한다. 버핏이 건설한 제국과 축적한 수십억 달러뿐만 아니라, 그가 살아온 삶도 포함해야 한다. - 죽음은 통제할 수 없지만 인생은 설계할 수 있다&lt;/p&gt;
&lt;p&gt;유튜브에서 추천해서 봤는데 전반부 저자 인생 얘기가 무지 지루했다. 스토아 철학 다이제스트는 나름 유용. 4장부터 읽는 걸 추천.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;매일 쓰는 물건이 아름다우면 좋죠. 그리고 그냥 시간을 견딘 것들이 주는 위로가 있잖아요? - 안녕이라 그랬어, 김애란&lt;/p&gt;
&lt;p&gt;당연한 얘기지만 긴 시간 엄마 옆에 머물며 내가 가장 그리워한 사람은 헌수였다. 나와 결혼할 뻔한 사람이어서가 아니라 나와 같은 고독을 겪은 사람이라 그랬다.&lt;/p&gt;
&lt;p&gt;단편 내용들을 보면서 김애란 작가도 이제 나이가 들었구나, 라는 생각을 하게 됐다. 어쩌면 또래라 비슷한 렌즈로 세상을 보고 있는 건지도 모르겠다. 김애란 작가 단편집은 실패가 없는듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;사업가나 사기꾼이나 매한가지긴 해. 근데, 사업가가 사기꾼과 다른 게 딱 한 가지 있어. 뭔지 알아? 시작은 허풍일지라도 끝은 아니라는거지. - 레이디 두아 ep.04&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;기술이 외모지상주의를 해결해 줄거란 생각을 별로 하지 않는다. 테드 창 소설에 나오는 것처럼 한 기준을 차단하면 사람들은 또 다른 기준으로 서열을 나눌테니. 외모 뿐만이 아니라 애초에 우리가 가진 모든 것들 중에 공평한 거라곤 사실 1도 없는 게 진실 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;왕과 사는 남자 하도 말이 많아서 십만년만에 애들 영화 아닌거로 극장 가서 봤는데. 그닥이었다. 넷플에서 틀었다면 절대 끝까지 못봤을 느낌. 그럼에도 평점은 어마무시.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;알지? 너 개새끼인거 - 파반느, 2026&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-02-28&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[잡기] 추사 김정희의 도망시]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2026/02/elegy-for-my-wife-in-exile/</link><guid isPermaLink="false">https://jiniya.net/2026/02/elegy-for-my-wife-in-exile/</guid><pubDate>Mon, 23 Feb 2026 21:00:01 GMT</pubDate><content:encoded>&lt;p&gt;저녁 먹으면서 볼 게 없어서 경도를 기다리며, 라는 드라마를 한 편 봤는데 거기 추사의 도망시라는 게 나왔다. 도망시가 제목인 줄 알았는데 &apos;도망시(悼亡詩)&apos;는 특정 시의 제목이 아니라 &apos;죽은 아내를 애도하는 시&apos;를 통칭하는 문학적 갈래라고 한다. 추사 김정희의 지극한 아내 사랑이 잘 드러나는 시인 것 같아서 가져와 보았다.&lt;/p&gt;
&lt;p&gt;예전에 유시민 작가가 한 말인지 잘 모르겠는데 인간의 원초적 고독감은 감각 기관이 고립돼 있다는 데서 온다는 말을 들었던 기억이 있다. 무슨 말이냐면 내가 느끼는 걸 동일하게 타인이 느낄 수가 없는 구조라는 것이다. 실제로 내가 보는 파랑과 타인이 보는 파랑은 모두 다르다. 또 우리는 이해한다는 말을 하지만 타인이 느끼는 희노애락을 똑같이 느낄 수는 없다. 단지 상상할 뿐이다. 결국 우리는 저마다의 감각 기관이 수집한 정보를 저마다의 뇌가 만들어낸 환상으로 이루어진 고립된 섬 속에 존재하고 있는 셈이다. 그래서 인간은 원초적으로 고독한 존재라고 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;배소만처상 (配所輓妻喪)&lt;br&gt;
유배지에서 아내의 죽음을 애도하며&lt;br&gt;
&lt;br/&gt;
那將月佬訟冥司 (나장월노송명사)&lt;br&gt;
어찌 월하노인을 시켜 저승에 하소연하여,&lt;br&gt;
&lt;br/&gt;
來世夫妻易地爲 (내세부처역지위)&lt;br&gt;
다음 생엔 우리 부부가 서로 바꿔서 태어날까.&lt;br&gt;
&lt;br/&gt;
我死君生千里外 (아사군생천리외)&lt;br&gt;
나는 죽고 당신은 천 리 밖에 살아남아서,&lt;br&gt;
&lt;br/&gt;
使君知我此心悲 (사군지아차심비)&lt;br&gt;
나의 이 슬픈 마음 당신이 알게 했으면.&lt;br&gt;
&lt;br/&gt;
-- Gemini 3.1 Pro&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;김정희는 또 그가 말년에 쓴 대팽두부라는 구절로 유명하기도 하다. 최고의 자리와 최악의 시절을 모두 겪어본 그가 하는 말이라 더 공감이 가는지도 모르겠다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;大烹豆腐瓜薑菜 (대팽두부과강채)&lt;br&gt;
최고로 좋은 반찬은 두부, 오이, 생강, 나물이고&lt;br&gt;
&lt;br/&gt;
高會夫妻兒女孫 (고회부처아녀손)&lt;br&gt;
최고로 훌륭한 모임은 부부와 아들딸, 손자 손녀가 모인 자리이다.&lt;br&gt;
&lt;br/&gt;
이 두 줄의 글귀 옆에는 추사가 덧붙인 작은 글씨(협서)가 있습니다.&lt;br&gt;
&quot;이것은 촌늙은이의 제일가는 즐거움이다. 비록 정승 판서가 누리는 밥상이나 삼천 명의 시녀를 거느린 귀족이라도 이 맛을 알지는 못할 것이다.&quot;&lt;br&gt;
&lt;br/&gt;
-- Gemini 3.1 Pro&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TMI로 김정희는 &lt;a href=&quot;/2025/06/korean-imperial-exam/&quot;&gt;일기를 쓰다, 흠영선집&lt;/a&gt;의 원작자인 유만주의 6촌형 유준주의 딸이 시집가서 낳은 아들이다. 유만주의 딸 진아는 추사의 6촌형 김도희에게 시집갔다. 이렇게 보면 참 스머프 마을같고, 유전자빨이란게 있나 싶은 생각이 들지만, 사실 6촌이면 남 아닌가 싶은 생각이 들기도 한다. 6촌 중에 실질적으로 아는 사람이 없다. 5촌 당숙 정도가 한계인듯. 그럼에도 유만주와 유준주는 흠영을 보면 몹시 잦은 교류가 있는 사이였다는 게 또 반전 아닌가 싶기도?!&lt;/p&gt;
&lt;p&gt;TIM2. 김정희는 결혼을 두 번 했다. 15세에 결혼한 첫번째 부인은 20세에 먼저 떠났고, 이 시의 주인공인 두번째 부인은 23살에 결혼해서 김정희가 55살이던 해에 병으로 먼저 떠났다고 한다. 그의 다른 인생사도 기구하지만 두 부인다 먼저 떠난 부분도 참 안타깝다는 생각이 든다. 그럼에도 시에 드러난 감정이 생길 정도로 애틋한 사람을 만났던 건 행운이 아닌가 싶다. 좋은 집안에, 좋은 머리로 태어나 출세 가도를 달린 인생 전반부와 당쟁에 휘말려 귀양과 유배로 보냈던 후반부를 오버랩시켜 보면 인생사라는 게 어쩌면 총량의 법칙이 실재하는게 아닌가 싶기도 한 생각이 든다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 카핑 베토벤, 2007]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2026/02/copying-beethoven/</link><guid isPermaLink="false">https://jiniya.net/2026/02/copying-beethoven/</guid><pubDate>Mon, 23 Feb 2026 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;불멸의 연인 후에 본 베토벤에 관한 또다른 영화. 베토벤의 인생 후반부를 다룬다. 제목만 보면 뭔 베토벤 곡을 베끼나?!라는 생각을 하게 되는데, 영화가 시작하면 그게 다름 아닌 카피스트라는 사람들이란 걸 알게 된다. 작곡가가 알아보기 힘들게 작성한 악보를 보기 좋게 필사해 주는 직업이다. 실제로 당시에는 그런 역할을 하는 카피스트라는 직업이 존재했다고 한다. 영화는 재미를 위해서 안나 홀츠라는 여성 카피스트를 등장시킨다.&lt;/p&gt;
&lt;p&gt;영화는 크게 3부분으로 나뉜다. 귀가 안들리는 상황에서 9번 교향곡을 작곡해서 메가 히트를 치는 장면, 이어서 대푸가를 공연하면서 똥망하는 장면, 그리고 죽다 살아나서 현악 4중주를 작곡하는 장면으로 끝이 난다. 9번 교향곡 지휘하는 장면만 엄청 길게 나오는 등, 클래식을 좋아하지 않으면 재미있게 보기는 상당히 힘든 영화가 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;실제로 대푸가를 들어보면 당시 욕했던 사람들이 상당히 이해되는 부분이 있다. 아고르 스트라빈스키는 대푸가를 &quot;영원히 현대적인, 절대적으로 동시대적인 음악&quot;이라고 평가했다고 한다. 미술이든 음악이든 현대적이라는 말은 참 난해하다. 23세기에도 현대적일 것 같은 베토벤의 대푸가. 5분 버티기가 힘들다.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/j5XAdttmOLo?si=opJZ9lDs04i7pvU5&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 불멸의 연인, 1995 (스포주의)]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2026/02/immortal-beloved/</link><guid isPermaLink="false">https://jiniya.net/2026/02/immortal-beloved/</guid><pubDate>Mon, 23 Feb 2026 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;연휴 기간에 우연찮게 베토벤을 들어봐야 겠다는 생각을 하다 베토벤 영화를 두 편 보게 됐다. 그 중 한편이 불멸의 연인. 베토벤은 평생을 독신으로 살았다. 하지만 연인이 아예 없었던 것은 아니었다. 그가 사랑한 대부분의 여인이 귀족이었고 신분 차이 때문에 결혼까지는 이르지 못한 것으로 보여진다. 월광 소나타를 헌정한 줄리에타 귀차르디, 엘리제를 위하여의 원 주인공으로 생각되는 테레제 말파티, 그리고 그의 사후 편지에서 발견된 누군지 특정되지 않은 불멸의 연인이 있다. 영화는 이 불멸의 연인을 찾아서 떠나는 미스테리 스릴러다. 다음은 인공지능이 정리한 베토벤의 연애사(?!)다. 영화를 보고 싶은 사람은 여기 까지만 읽고 영화를 보기를 추천한다. 다음 내용은 영화에 대한 스포 그잡채.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;불멸의 연인 (Immortal Beloved): 음악사에서 가장 유명한 미스터리 중 하나이다. 1827년 베토벤이 세상을 떠난 후, 비서 안톤 쉰들러가 그의 책상 속 숨겨진 칸에서 연필로 쓴 10페이지 분량의 연애편지를 발견했다. 1812년 7월 6~7일 이틀에 걸쳐 쓰인 이 편지에는 받는 사람의 이름 없이 &apos;불멸의 연인에게&apos;라고만 적혀 있었다. 200년이 넘도록 수신인의 정체는 밝혀지지 않았으며, 현재 학자들은 안토니 브렌타노와 요제피네 브룬스비크를 가장 유력한 후보로 보고 있다.&lt;br&gt;
&lt;br/&gt;
줄리에타 귀차르디 (Giulietta Guicciardi): 〈월광 소나타〉의 헌정을 받은 인물이다. 1800년경부터 베토벤의 피아노 제자였으며, 베토벤은 사랑에 빠져 청혼까지 했다. 줄리에타 본인도 받아들일 의향이 있었으나, 부모가 지위와 재산이 없다는 이유로 결혼을 금지했다. 줄리에타는 1803년 갈렌베르크 백작과 결혼하여 나폴리로 떠났다.&lt;br&gt;
&lt;br/&gt;
테레제 말파티 (Therese Malfatti): 베토벤의 피아노 제자로, 베토벤이 청혼했으나 말파티 가문이 신분과 현실적 이유를 들어 거절했다. 1867년 음악학자 루트비히 놀이 테레제의 유품에서 발견한 악보를 출판하면서, 베토벤의 악필로 인해 헌정 문구를 &apos;엘리제를 위하여&apos;로 잘못 읽었다. 원래는 &apos;테레제를 위하여&apos;였다는 설이 가장 유력하나, 엘리자베트 뢰켈 등 다른 후보도 있어 완전히 확정되지는 않았다.&lt;br&gt;
&lt;br/&gt;
-- Opus 4.6&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 영화는 불멸의 연인 편지까지만 팩트에 기반하고 나머지는 일부 사실과 엄청난 작가의 상상력을 동원해서 연인을 추정한다. 결론만 본다면 베토벤 측에서 명예 훼손으로 고소해도 되지 않을까 싶은 정도. 왜냐하면 연인으로 지목한 대상이 다름아닌 동생의 아내이기 때문이다. 영화 줄거리만 본다면 다음과 같은 빌드업이다. 1) 베토벤과 조안나는 밀애 관계였다. 2) 조안나가 베토벤의 아이를 임신한다. 3) 둘은 특정 지역 호텔에서 비밀리에 만나기로 한다. 4) 베토벤의 마차가 진창에 빠져 약속 시간을 못 맞추게 된다. 베토벤은 편지를 남긴다. 4) 호텔 주인은 그걸 조안나에게 직접 전달하는 것이 아니라 음식 쟁반 아래 깔아서 전달한다. 5) 조안나는 음식을 보자 입덧이 올라와서 편지는 보지도 못하고 호텔을 떠난다. 오지 않은 베토벤을 보며 자신을 버렸다고 오해한다. 6) 호텔에 늦게 도착한 베토벤은 그녀가 떠난 걸 알고 미쳐 날뛴다. 7) 이후 조안나는 베토벤의 동생의 고백으로 친동생과 결혼한다. 8) 베토벤은 그런 그녀를 평생 저주하면서 살아간다. 9) 동생 사후에는 조카 양육권으로 조안나와 지리한 법정 소송도 벌인다. 10) 죽기 직전에야 양육권을 다시 조안나에게 돌려주는 문서에 서명한다.&lt;/p&gt;
&lt;p&gt;이 중 실제 사실로 추정되는 건 불멸의 연인에 대한 편지가 남아 있었다는 것. 그리고 조카인 칼 베토벤의 양육권으로 실제로 제수씨와 법정 소송을 했었다는 점 정도다. 그럼에도, 음악을 몰라도 재미있게 볼 수 있는 영화였다.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/AVe0uV9AQsA?si=6xYYon3hyGm14wKX&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title><![CDATA[[일상] 2026년 1월의 잡담]]></title><description><![CDATA[#0 주로 윈도우 개발을 하는데 작업 피씨를 리눅스로 전환했다. 내가 코딩할 일이 거의 없다는 의미. ai 툴들이 대체로 리눅스에서 더 잘 동작해서 wsl 쓰다가 윈도우를 쓰는게 아니라 wsl…]]></description><link>https://jiniya.net/2026/01/small-talk-2026-01/</link><guid isPermaLink="false">https://jiniya.net/2026/01/small-talk-2026-01/</guid><pubDate>Wed, 28 Jan 2026 16:16:09 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;주로 윈도우 개발을 하는데 작업 피씨를 리눅스로 전환했다. 내가 코딩할 일이 거의 없다는 의미. ai 툴들이 대체로 리눅스에서 더 잘 동작해서 wsl 쓰다가 윈도우를 쓰는게 아니라 wsl을 쓰는 느낌이라 넘어옴. 슬랙웨어에서 점프한 사람이 경험하는 2026 리눅스 데스크탑 환경은 그야말로 상전벽해.&lt;/p&gt;
&lt;p&gt;디아4가 별 설정 없이 윈도우만큼 잘 돌아간다. kvm으로 gpu 패스스루 쌩쑈하며 돌려봤는데 그냥 스팀으로 네이티브 리눅스로 돌리는 게 더 성능이 좋은듯. 실제 체감도 리눅스 네이티브는 윈도우 네이티브랑 별차이를 못 느낀다. kvm gpu 패스스루는 간간히 랙발생.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;요즘은 진심 코인이 젤 문제아. 수익 코인이 다 까먹고 있다. 국장이 우등생인거도 웃기지만 코인이 어쩌다 이 지경이 된건지.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;인생 낭비라던 sns에서 평범한 직장인 급여보다 높은 소득을 얻는 사람들을 보니 묘한 생각이 든다. 모두가 인간의 관심을 끌기 위해 무한 경쟁하는 세상. 바야흐로 관심을 채굴하는 시대가 아닌가 싶기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;최근 AI 발전 속도를 보면 컴공 기초에 깊게 투자하는 건 시간 낭비 같다. 아는 만큼 통제할 수 있다, 라는 논리도 알겠지만, 이 속도면 1-2년 뒤에도 그 말이 통할까 싶다. 바이브 코딩으로 제품을 더 많이 만들어 보는게 roi가 더 좋지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;굳이 기초에 투자한다면 읽기, 쓰기 능력에 투자할 것 같다. llm 시대엔 국어 능력이 특히 중요해진게 아닌가 싶기도. 돌고돌아 국영수인가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;바이브 코딩 창업 바이브는 여돌 지망생이 장원영 카리나 꿈꾸는 거랑 비슷한 확률이라는 생각. 시장은 생각보다 효율적이고 냉정하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;주화입마에 빠진 현상황. 개발을 돕기 위해 ai를 쓰는 게 아니라 ai를 위한 ai를 쓰는 게 아닌가 싶기도. &lt;a href=&quot;https://x.com/gregisenberg/status/2015180689335812480&quot;&gt;https://x.com/gregisenberg/status/2015180689335812480&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;6년 근속한 제법 괜찮은 20대 청년 개발자가 퇴사했다는 이야기를 들었다. 사유가 코딩은 이제 노답인 것 같다고. 말렸지만 안됐다는 전말. 전망보고 선택하는 거도 좋지 않지만, 전망 보고 포기하는 거도 그닥이라는 생각.&lt;/p&gt;
&lt;p&gt;최근 몇 년 사이 코딩에 대한 전망이 바뀌는 과정만 봐도 현기증이 난다. 누가 2026년에 코딩이 이렇게 찬밥될 줄 알았을까? 과거를 보면 미래는 우리 예측과는 다를 확률이 높다. 2035년에 과연 배관공 롱, 프로그래머 숏한 선택이 맞았을지가 궁금한 요즘.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;코스피 5175, 환율 1423의 현실을 보니 이재명 대통령의 코스닥 3000 발언을 무시하긴 어렵다는 생각. 그러니 너도나도 불나방처럼 달려든다. 비이성적 과열은 이럴때 써야 하는 말이 아닌가 싶기도. 코스닥 시총 상위 주식을 보면 새롬기술이 묘하게 오버랩된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;대답이 값싸고 즉각적인 시대일수록 주의와 겸손은 귀해집니다. 대규모 언어 모델은 우리의 문장을 완성하지만, 『도덕경』은 우리에게 문장을 불완전하게 남겨두는 법을, 이름 붙이기를 거부하는 것과 함께 앉아 있는 법을 가르쳐줍니다. - 길을 찾는 책 도덕경, 켄 리우&lt;/p&gt;
&lt;p&gt;하늘과 땅은 자애롭지 않다. 그 둘에게 우주의 만물은 짚으로 만든 개나 마찬가지다. 도를 깨달은 자는 자애롭지 않다. 그에게 만인은 짚으로 만든 개나 마찬가지다.&lt;/p&gt;
&lt;p&gt;번역이 유려해서 뭐지 싶었는데, 심지어 외국인이 번역한 도덕경. llm 시대에 추천할만한 책이 아닐까 싶다. epub 편집은 llm의 도움이 조금 필요한 수준.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-01-28&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 12월의 잡담]]></title><description><![CDATA[#0 저게 없어질 줄이야. 진정한 노인과 바다, 그리고 아파트로 거듭나는 부산. https://x.com/REAL_GOMGOM/status/1997838338099913025 2025-12-08 #…]]></description><link>https://jiniya.net/2025/12/small-talk-2025-12/</link><guid isPermaLink="false">https://jiniya.net/2025/12/small-talk-2025-12/</guid><pubDate>Fri, 26 Dec 2025 16:20:36 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;저게 없어질 줄이야. 진정한 노인과 바다, 그리고 아파트로 거듭나는 부산. &lt;a href=&quot;https://x.com/REAL_GOMGOM/status/1997838338099913025&quot;&gt;https://x.com/REAL_GOMGOM/status/1997838338099913025&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;현시점 코딩 에이전트의 최대 강점이라면 인간이라면 감히 엄두도 못낼 단순 노가다 반복 작업에 있는게 아닌가 싶다. 파일을 한 수백개쯤 일일이 열어서 확인하고 노가다해야 하는 작업에 투입해보면 진심 돈값한다는걸 느낀다. 지난 20년간 아무도 감히 엄두조차 못냈던 작업을 2일만에 끝냄.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;연말 송년회 자리에서 느낀 점은 인공지능 주화입마가 많아졌단 느낌. 뭐든지 균형을 찾는게 중요하지 않나 싶다. 그리고 늘 그렇지만 은탄환은 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;쓰면 쓸수록 gpt 구관이 명관이다. 5.2가 기대되는. claude max결제해서 빡쎄게 몇일 돌려봤는데 뭔가 요란한데 결과물은 황망한 경우가 많은듯. 이때 해결해준거도 gpt가 잘못된 코드를 짠 건 아니고 보안 규정상 코딩해 줄 수 없다는거였다. 실상 짜주면 위험한 코드기도 했다. &lt;a href=&quot;https://x.com/codemaru/status/1994333678000914656&quot;&gt;https://x.com/codemaru/status/1994333678000914656&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;올초에 딥싴 여파가 한창일때 뽕 맞아서 서버용 ddr5 64gb 24개를 샀었다. 해외 직구한 보드와 씨퓨는 불량이 있었고, 몇달에 걸쳐 조립했지만 속도는 생각보다 처참했다. 채팅하고 놀만한 수준은 되는데 작업시키긴 하세월. 램값 올라서 램만 중고로 팔았는데 수익률이 57%. 주식, 코인보다 낫다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;9년된 저장소, 그사이 제품이 6개가 더 추가됐다. 중구난방일 수 밖에. 연말을 맞아 대대적인 리팩토링을 하고 있는데 리팩토링이 참 그렇다. 뭔가 엄청나게 힘들여 했는데 결과물은 똑같은?! 약간 현타가 오기도. 그럼에도 해야겠지?! 10년은 더 존버해야 할테니.&lt;/p&gt;
&lt;p&gt;비워야 채울 수 있다. 리팩토링을 하면 이말이 참 실감난다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;인공지능이 근 20년 전에 내가 만든 쓰레기를 환골탈퇴시켜 새 코드를 만들었다. 리뷰를 시켰더니 쓰레기같지 않다고 최대한 쓰레기같이 만들어 버리는 수정을 한 리뷰어. 앵커링 효과가 무섭기도 하고 인간의 커뮤니케이션은 참 어렵다는 생각이 많이 든다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;자백의 대가 다봤다. 간만에 집중해 본 드라마. 도깨비 나올때만 해도 김고은 캐스팅이 이해가 안됐는데 지금은 충무로의 대본이 모두 그녀에게 간다는 게 이해되는 작품이었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;개이듴 ㅎㅎ &lt;a href=&quot;https://x.com/lessislessxxx/status/2004103375227695354&quot;&gt;https://x.com/lessislessxxx/status/2004103375227695354&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-12-26&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 11월의 잡담]]></title><description><![CDATA[#0 거짓말이 거짓말을 부르는 것처럼 어떤 잘못된 설계 선택은 다른 잘못된 선택을 계속 강요 받게 만든다. 해결하려고 땜빵을 추가하면 그 땜빵 때문에 또 예외 케이스가 더해지는 악순환. 레거시 때문에 이제와서 잘못을 돌릴수도 없다. 2…]]></description><link>https://jiniya.net/2025/11/small-talk-2025-11/</link><guid isPermaLink="false">https://jiniya.net/2025/11/small-talk-2025-11/</guid><pubDate>Fri, 28 Nov 2025 18:12:56 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;거짓말이 거짓말을 부르는 것처럼 어떤 잘못된 설계 선택은 다른 잘못된 선택을 계속 강요 받게 만든다. 해결하려고 땜빵을 추가하면 그 땜빵 때문에 또 예외 케이스가 더해지는 악순환. 레거시 때문에 이제와서 잘못을 돌릴수도 없다. 20년 가까이 된 프로젝트의 말로가 이런건가 싶기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;회사 직원이 매뉴얼 교정 및 번역 도구를 만들었다. 폴더 구조 바꾸느라 귀찮아서 이미 돌린 결과 버리고 걍 새로 돌렸더니 어제 96불. 넘 많이 나와서 모델 싼걸로 변경해서 돌리니 오늘 6불 사용. 걍 복붙 했어야 하나 싶은 생각이. 물론 사람이 했다면 한중일영 4명 붙어서 2-3달은 걸렸겠지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;인공지능으로 개발이 나락가니 운영이 상대적으로 귀족된 느낌. devops가 아니라 opsdev같은 느낌? 어찌될지 모르는게 세상 일이라지만 뭔가 격세지감이...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;베르나르 베르베르 인생책으로 슈테판 츠바이크의 체스 이야기가 있길래 봤는데, 베르나르 베르베르 작품만큼이나 나랑은 결이 안 맞는 느낌. 끝에 해설 보니 유명한 작품이기는 한 것 같은데 뭐징?! 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;손실다 만회하고 수익났다고 고맙다고 연락와서 오랜만에 만났다. 8개월 수익률이 51%, 청출어람인가 싶은? 요즘은 13f 따라사는 매매법에 빠져있길래, 벌었으면 적당히 팔고 나오라고했지만 원금오면 주식은 쳐다도 안본다던 초심은 이미 없었다. &lt;a href=&quot;https://x.com/codemaru/status/1893513760964248035&quot;&gt;https://x.com/codemaru/status/1893513760964248035&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;구글 시트를 하나 만들어줬었는데, 시트 신봉자가 돼 있었다. 소소한 성공 경험도 중요하지만 자극이 너무 세면 외려 역효과가 나기도 한다는 걸 느꼈다. 하도 이거저거 얘기해서 시트를 업그레이드해줬다. 도미노를 알려줬지만 그 친구에게 시트는 이미 어떤 종교적인 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;쓰잘때기 없는 코딩 강좌 들을 시간에 &lt;a href=&quot;http://agents.md&quot;&gt;http://agents.md&lt;/a&gt; 다듬는 법이나 배우자. 집값을 근로소득이 못 따라잡듯 코딩 공부 백날 해봐야 인공지능 발전 속도를 이길 수가 없다. 그래도 정 하고 싶으면 github가서 그냥 유명한 오픈 소스 코드를 읽는게 훨씬 생산적일듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;진심 추석이 고점이었던 것인가?! 떨어지는 각도가 예사롭지 않다. 에브리씽 랠리라며 호둘갑 떨때 조심했었어야하는건가 싶기도 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;이 모델이 코딩 잘하니 저 모델이 더 좋니 하는게 인공지능 시대의 새로운 종교 논쟁이 아닌가 싶다. 걍 취향껏 쓰자. 말려들면 답도 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;새로운 길을 가기에는 전 이미 반대 방향으로 너무 멀리 왔습니다.&lt;/p&gt;
&lt;p&gt;그럼 다시 원점이네요. 트레일은 원형이니까.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;나의 완벽한 비서 ep.01&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;진심 무슨 공식 있나 싶을 정도로 k드라마 표준 공식 그 잡채인 드라마. 그 모든 단점을 커버하는 한지민의 비쥬얼이란.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;fsd 출시 된다길래 찍먹해볼까 싶어서 모델x 리뷰를 좀 봤는데. 모델y 적용될때까지는 참는게 좋을 거 같다는 생각이 들었다. 1억 넘는 차를 원래 그래요, 어쩔 수 없어요로 팔아도 되는건가?!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/l0gNskmK-bY?si=Lug8rwqOHkUoGHTJ&quot;&gt;https://youtu.be/l0gNskmK-bY?si=Lug8rwqOHkUoGHTJ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;뒤늦게 밀리에 떠서 삼체를 보고 있는데 보면서 놀란 점이 넷플릭스 드라마 진짜 잘 만들었다는 생각. 보통 원작 읽으면 이걸 어케 저따위로 만들었지가 일반적인데 이건 반대로 드라마 장면이 오버랩되며 감탄하게 된다. 그나저나 시즌2는 안나오는 것인지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;구글 게임 매출 챠트 순위를 보면 메타 주식을 사야할 것 같은데 환율이 안습 그 자체. 진심 이 환율이 뉴노멀인가? 1370도 비싸다 생각했는데 1480이 다되가네 ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;예전에 비비고 왕교자 먹고는 감동 받아서 제일제당 주식을 샀다가 영 별로라 팔았는데, 최근 크리스피 치킨 먹어보니 다시 뽐뿌가 온다. 하지만 컨센은 나락인듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;고용안정성 맥락에서 보면 대기업에 들어간 1970년대생들과 1980년대 초반생들은 어떻게 보면 행운아들이다.&lt;/p&gt;
&lt;p&gt;소득 불평등의 시대가 지나가고 자산 불평등의 시대가 왔다는 걸 잊으면 자신만 손해다. 지금은 금융이 경제의 중심축인 세상이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;돈의 대폭발, 손진석&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;끼인 세대라고 생각했는데 의자 줄어들기 전에 가장 꿀빨기 좋았던 세대였기도 한 것 같다. 여러모로 인생사 운이 참 중요하다는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;평가의 계절이 다가온다. 친한데 일 못하는 직원에게 나쁜 고과를 주는 것보다 안친한데 일 못하는 직원에게 나쁜 고과를 줘야할 때 자기 검열이 훨씬 고되다. 내가 편향된 건 아닌가 싶은? 그나저나 노이즈 많은 직원은 해가 변해도 항상 비슷하다. 매번 두세번씩 뒤치닥거리 하는거도 지침.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;탐라에 구글에 대한 사람들의 인식 변화가 실로 놀랍다. 주가가 올라서 인식이 개선된건지, 인식이 개선되서 주가가 오른건지 헷갈림. 나는 gemini 3 pro보단 2.5 pro때 더 놀랐던 것 같다. 사실 갈수록 코딩 측면에서 개선을 느끼기는 점점 더 어렵다는 생각. 대체로 모두 잘한다. deepseek도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;코딩의 가격은 빛의 속도로 내려가고 있지만, 여전히 돈되는 제품을 만들기란 어렵다는게 함정 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;억대 연봉이 이렇게나 흔했다니 전체 근로소득자중 6.7%, 단순 비교로도 대상자가 대한민국 전체 공무원보다 많다고 한다. 대기업 임금 상승률도 생각보다 놀랍다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/9aTKDR3ubtw?si=THHbPa3H30HxVSMM&quot;&gt;https://youtu.be/9aTKDR3ubtw?si=THHbPa3H30HxVSMM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;같은 통계를 보고도 난 저렇게 많은 줄 몰랐는데 과표기준으로 봐서 그런듯. 총급여 기준으로 보니 저 수치가 맞다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;채용 페널티 받을까봐 블로그를 개인사와 포폴로 나눠서 운영한다는 글을 봤다. 그런 걸로 페널티 주는 회사면 그냥 안가는 게 맞지 않나 싶다. 들어가도 안맞을 확률 높음.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;학생 때 대회 나갈때 말고는 코딩을 누구와 대결한다거나 경쟁한다는 프레임으로 생각해 본 적이 없는데, 탐라를 보니 나이 들어서도 그런 프레임을 가진 사람들이 더러 있는 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;유튭 컨텐츠도 사업도 여러모로 월가아재랑 비교해서 보게되는 인물. 한명은 자극적이고 요란하고, 다른 한명은 심심하고 조용한듯. &lt;a href=&quot;https://x.com/mint_voyager/status/1992857947945464185&quot;&gt;https://x.com/mint_voyager/status/1992857947945464185&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;출시된지 2년이나 된 개발자 드라이브라는 기능을 이제야 알게됐다. refs라는 새로운 파일 시스템이라는데, 번외로 부가 기능이 윈도우 디펜더에서 파일을 덜 감시하는거라는듯. ms도 알고는 있었구나? 개발할 때 디펜더 겁나 거슬린다는걸.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;opus 4.5 썰들이 많아서 10만년만에 결제를 했다. 하지만 실망만. 일단 클로드 코드 클라우드 버전에 아직 opus 4.5 모델 선택이 안됨. sonnet으로 해도 저장소 클론조차 실패해서 작업 시킬수도 없음. 이뭐병?! 다른 작업을 로컬에서 코파일럿으로 모델 선택해서 opus 4.5로 시켜 봤는데 그건 1등함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;애 성장 주사를 시도해 본 부장님 왈, 효과는 있더라고요. 다만 원래 클 때여서 큰 건지 주사 때문에 큰 건지는 알수가 없었어요. 비슷한 생각을 사내 인공지능 도입에서 느낀다. 닥달하니 그래도 이만큼은 쓰는 건지, 원래 쓸건데 오버하서 닥달한건지?!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/092/0002399938?cds=news_edit&quot;&gt;https://n.news.naver.com/article/092/0002399938?cds=news_edit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;요즘 심취한 놀이. 코딩 에이전트 종류별로 동일 프롬프트로 작업 시키고 결과물을 다시 100점 기준으로 비교 평가 시키는 일. 코드 작성은 제각각인데 결과 평가는 대체로 비슷하게 수렴함. 결과를 보면 모델 못지않게 에이전트 만드는 기술에 따른 차이도 크다는 걸 새삼 느낀다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;요즘 서울 주택 시장에서 느끼는 신기한 점은 에어비앤비 문의가 많다는 거. 기존 월세 대비 프리미엄이 제법 붙어도 에어비앤비 가능하면 월세 낸다는 사람이 많다. 돌리면 꽤나 짭짤한가봄?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;한중일러북. 진심 박터지는 동네 아닌가 싶은 생각이 ㄷㄷ &lt;a href=&quot;https://x.com/baofamily_save/status/1993816924942422076&quot;&gt;https://x.com/baofamily_save/status/1993816924942422076&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;no llm, no ai 정책이라뉘. 러다이트 같은 느낌인건가?! &lt;a href=&quot;https://x.com/GeekNewsHada/status/1994234297054842944&quot;&gt;https://x.com/GeekNewsHada/status/1994234297054842944&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;opus 4.5 잘하네. 괜히 결제해서 돈 날렸다 생각했는데 채팅창만으로도 이번 달 결제는 뽕을 뽑았다. 단돈 20불로 이걸 해결해 주다뉘 ㄷㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-11-28&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 10월의 잡담]]></title><description><![CDATA[#0 사람이 한땀한땀 논리표로 조건문 구조를 최적화하는 영상을 보다 심심해서 gpt…]]></description><link>https://jiniya.net/2025/10/small-talk-2025-10/</link><guid isPermaLink="false">https://jiniya.net/2025/10/small-talk-2025-10/</guid><pubDate>Fri, 31 Oct 2025 19:30:21 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;사람이 한땀한땀 논리표로 조건문 구조를 최적화하는 영상을 보다 심심해서 gpt에 던져봤다. 몇초만에 최종 버전과 동일한 코드가 나왔다. 이런 건 이제 신기하지도 않다. 요즘은 코딩은 다들 포기하고 설계쪽을 방어하는 분위긴데 과연 인간이 설계를 더 잘하긴 할까?&lt;/p&gt;
&lt;p&gt;프로그래머가 잠시 좋은 직업이었던 것 같다. 그 잠깐 좋은 시기에 경력 대부분을 보낸 건 참 운이 좋았다. 부인하고 싶지만 자동차가 등장하는 시기에 마부가 되는 느낌은 지울 수 없다. 이제 이 업계에 들어오는 사람은 앞으로 택시 기사가 뭐가될지를 더 고민해야 하는 시기가 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;장원영이 대단하긴 하다. 핸펀만 쳐다보던 사람들이 죄다 엘베 광고판 보고 아씀 ㄷㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;그게 나야. 넌 이해 못하겠지만. - 은중과 상연 ep.09&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;나는 당신이 부럽다. 매순간&lt;br&gt;
당신은 나를 떠날 수 있다.&lt;/p&gt;
&lt;p&gt;나는 나를&lt;br&gt;
떠날 수 없다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;나는 할 수 없다, 안나 스위르&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-10-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;젤 똑똑한 애들이 울세라 쏘고 있어서 미래가 없다는데, 넷플 틱톡에서도 똑같은 얘기가 있었다. 로켓 과학자 할 애들이 거기 가서 추천 알고리즘 짜고 있다는 말. 좋은지 나쁜지 알기란 생각보다 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;은중과 상연 중간에 삼각관계 지나치게 끌어서 포기하려 했으나 참고 끝까지 봤는데 결말은 생각보다 나쁘지 않았다. 우리 나라도 어여 빨리 안락사가 합법화되기를 기원한다. 상연 말처럼 고통을 거부할 권리는 있어야 하지 않나?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;오직 자유가 삶의 목적이라면&lt;br&gt;
평생 자유롭지 못할 겁니다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;쇼군 ep.05&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;꽃은 지기 때문에&lt;br&gt;
꽃입니다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;쇼군 ep.09&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;추석 기념으로 뒤늦게 쇼군을 정주행 했다. 추천인 들의 말이나 제목이랑 다르게 쇼군이 아니라 거의 안진과 마리코가 주인공 아니었나 싶었던 드라마.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;인공지능을 떠나 의외로 요즘 발전이 대단하다 생각되는 분야가 간편 식품. 에프와 냉동의 조합은 특이점을 넘은듯. 이러니 피자집이 장사가 되겠나 싶다. 족발, 보쌈도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;어쩔 수가 없다 보고 드는 생각이 해고가 저정도로 충격적인 사건인가라는 생각? 워낙 어릴 때 한 번 당해본 게 전부라 감이 없다. 한날 동시에 단체로 해고 당하고 함께 창업을 했었다. 해고시킨 업체보단 잘되겠지라며. 이것도 it 장점인듯. 장치산업은 자본이 없으면 애초에 창업이 불가능하니.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;부의 가장 강력한 정의는 ‘무엇을 가지고 있느냐’가 아니다. 진짜로 중요한 것은, ‘가진 것’과 ‘원하는 것’ 사이의 간극이다. - 소비의 기술, 모건 하우절&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;x, if not y&lt;/p&gt;
&lt;p&gt;gpt x며, 아니 어쩌면 y이기까지 하는&lt;br&gt;
claude x거나 y인&lt;br&gt;
grok x거나 아니면 y인&lt;br&gt;
gemini y까지는 아니더라도 x인&lt;/p&gt;
&lt;p&gt;흥미롭게도 같은 문장이 정반대의 뉘앙스를 가질 수 있는 영어의 재미있는 예시죠! - claude&lt;/p&gt;
&lt;p&gt;전혀 흥미롭지 않은데, 뭔 이런 거지발싸개같은 표현이 있지 싶었다.&lt;/p&gt;
&lt;p&gt;한국어 예시를 보고 바로 납득됨. 표현이 그럴수도 있지 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&quot;그 사람 참 대단하네&quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;해석 1: 진짜 훌륭하다 (칭찬)&lt;/li&gt;
&lt;li&gt;해석 2: 어이없다, 황당하다 (비꼬기) - 억양과 문맥에 따라&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&quot;괜찮아&quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;해석 1: 정말 좋다&lt;/li&gt;
&lt;li&gt;해석 2: 그냥 참을 만하다&lt;/li&gt;
&lt;li&gt;해석 3: 사실 별로다 (거절의 완곡 표현)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-10-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;엔비디아 인턴 출신으로 북미 취업을 준비하던 친구가 큰업체 두군데서 뱅기 숙식 바우처까지 제공해준다는 면접 단계까지 갔는데, 럼프형 비자 폭탄으로 취소됐다는 이야기를 들었다. 비자 가격이 1억으로 올랐다고. 진심 운9기1의 리얼 월드가 아닌가 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;탐라에 코인 청산 관련 간증글을 보니 몇년전 지인의 지인이 코인 투자로 2000억 벌었다는 얘기가 생각난다. 이후 테라루나 사태로 99% 날렸다고. 그정도 벌면 다른 안전한데 분산 투자할법 하지 않았냐고 말했더니, 친구왈 그런 마인드면 2000억 근처도 못간다고. 하지만 곱하기 0 한번이면 나락인걸.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;오늘도 gpt와 gemini가 나의 무지를 깨쳐주고, 코드를 작성해주고, 검증하는 법도 알려주었다. 정말 멋진 신세계가 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;쿠팡의 다이나믹 프라이싱에 결국 굴복했다. 인간이 알고리즘을 어케 이기나 싶다. 큰돈은 아니지만 주문 실수로 날린 돈이 아까운 건 어쩔수가 없는듯 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;i can do this - 스토어웨이, 2021&lt;/p&gt;
&lt;p&gt;재밌게 봤는데 네이버 평점보고 깜놀. 다들 생각하는 게 많이 다르구나 싶었다. 산소 가지러 가는 장면이 백미였다. 별 거 아닌데 나름 긴장되는.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;인생을 결산하는 것은 돈이 아니라 전반적인 행복이다. 그러므로 균형을 유지해야 한다. - 전설의 프로 트레이더 빅, 빅터 스페란데오&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;대기업 25년차 부장에, 서울 아파트 자가에, 애 대학까지 보낸 인생은 위대한게 맞다고 본다. 사실 애 키워보면 그냥 멀쩡하게 밥벌어 먹고 사는 일반인으로 키워내는 것만 해도 위대한 게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;시험을 못 봤을때 어떠셨어요? 학교 생활 다 망친 것 같고 세상이 끝난 것 같지만, 나중에 되돌아보면 그때 왜 그렇게 고민했을까, 하는 생각이 들죠. 똑같아요. 회사에서 은퇴했다고 해서 삶을 다 은퇴한 게 아니예요. 사기 한 번 당했다고 해서 인생이 막을 내리는 게 아닙니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서울 자가에 대기업 다니는 김부장 이야기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;상사 3명을 합쳐서 묘사하면서 시작된 이야기라는데 관찰 불가능한 부분은 너무 퐌타지 스러움. 특히 아내가 유독 지나치게 비현실적인 느낌. 김부장이 내 또래로 설정된 게 묘하게 씁쓸하기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;악어에게 물렸을 때 살아남는 유일한 방법은, 다리 하나를 내주고 빠져나오는 방법뿐임을 기억하라. 이 원리를 시장에 적용하면 “잘못을 깨달은 순간 포지션을 청산하라!”가 된다. - 전설의 프로 트레이더 빅, 빅터 스페란데오&lt;/p&gt;
&lt;p&gt;뉴진스 기사를 보니 이 문구가 생각났다. 소송 결과나 손배 위약금 따위를 다 떠나서 천금같은 시간을 다 날리고 있는걸 보면 참 안타깝다는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;전형적인 쇼비지니스라 생각되는 젠슨황 깐부치킨 회동이 엄청나게 바이럴 되는 걸 보니 돈만 많고 아무도 나를 몰랐으면 좋겠다는 밈이 절로 생각난다. 드라마에서 재벌 회장님이 요플레 뚜껑 핥는지 아닌지 궁금해 하는 씬을 오바라고 생각했는데 이번에 보니 현실적이었단 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-10-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 함께해서 인상적인 날 (feat. KOF98 & 마인크래프트 던전스)]]></title><description><![CDATA[인생이 무료하던 시점 어릴 때 생각이 나서 월광보합 파이널…]]></description><link>https://jiniya.net/2025/10/a-memorable-day-together/</link><guid isPermaLink="false">https://jiniya.net/2025/10/a-memorable-day-together/</guid><pubDate>Sat, 04 Oct 2025 11:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;kof.png&apos; data-alt=&apos;KOF98을 플레이하는 아드님&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/9d69b6a484110f6e2f69f7b590625011/e8464/kof.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAADJElEQVR42gEZA+b8AL2dZsima6iKVpZ7Tq2GTbSUWrORWLOSWreVX7aXX7qbYraYZK2RYKeMXKCGWJt+UIZwR0RXQVRiSl5rUwC8nWW3mWWTeENzgGqthD7JkTStfzSSbTWccjKkbDKrgkvHqGy/oGi0l2KBbEFlUihcTCVITjFSYEdfbVMAsJRfjnxVfmU3oW4ss3wxvXQjvXwql2gylGgupG8xp4JNzKxtyahtcmI4LCgLNS0NPDEOWEMXWlw6XW9UAK+TXo17U3BbM4lUHJBgJ4liLpZkKYZVKXJKK6ZrLKmARdGwb8SmaYhsOXJUJDMuDzsyEUg2D1hcOWKDaACukV2LeFFwWzSjZyClcCpzYjebay2qYh+MVSOtaiOlfD/JqWnHp2rInVvWlUijczVSQBc4Lg1yc0tggGMArpJdjnpTemM3mnc8pXYtqHcrxowwyIsvmG0pqXotg204UUsreWo9xZlX3ZlJ6JtLiGAtWVEodoNdc3U7AKCGU2tdOGxbMXhlOnNgNWVTKFBFHl5RLYNrO7OLRpZ1OkM/H3FfMayNUqN/SJyDQa2nUHl9OXFtPKV/JQBxYDlDPx5jVCqObDWofzt6YSxkUiRnUyV+YSiKaCqKZyh0WCaWbTLJj0OCdzpnkkWLs1SEoUprUhyGXh4AmXU4fWQtmXUznHEumXEvcVopc1opYk8kUEUiX0wlfF4rtIQ/WEgiUEIdXHY3bJZGfJ5KiKtObWAlfVUfAJRzNHlkMcSUQoFoMnNOJHhSJHVPJFRHJFVHIlpIIks+G5xyNL+IP6BuMZF5NVV9OmyTRYmtUGlgKo5fHADEk0CXdTSsgTl9YSpFOxxxTiFnSiBJPx1JPxxOQxxiTh5gTB2OZiu2ejl3ajFIcjZpj0SBqFB2YiSRYxgAx5I/3KJGz5hBqXw1ZVEiPDoaXU0gfV8llGwoo3UsmnAuimcwfl8uSj8dR2QuUXo7YoU+cptLaFkecVEdAI5rMsiSPM6XQcyVQLmGNaJ0K6l6LpxxLo9sNHxiNWtXMpBlMZBiJ0I4DktPHktwNlyBPV9/PmZsP3BgKbIxM/KjYvObAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;KOF98을 플레이하는 아드님&apos; title=&apos;&apos; src=&apos;/static/9d69b6a484110f6e2f69f7b590625011/efd7b/kof.png&apos; srcset=&apos;/static/9d69b6a484110f6e2f69f7b590625011/08678/kof.png 190w,
/static/9d69b6a484110f6e2f69f7b590625011/2edd7/kof.png 380w,
/static/9d69b6a484110f6e2f69f7b590625011/efd7b/kof.png 760w,
/static/9d69b6a484110f6e2f69f7b590625011/dc896/kof.png 1140w,
/static/9d69b6a484110f6e2f69f7b590625011/78873/kof.png 1520w,
/static/9d69b6a484110f6e2f69f7b590625011/e8464/kof.png 1536w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;KOF98을 플레이하는 아드님&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;인생이 무료하던 시점 어릴 때 생각이 나서 월광보합 파이널2를 산 적이 있었다. 사서 한두번 하다가 내가 생각했던 느낌은 아니라 한구석에 방치돼 있었다. 추억이란게 보통 그렇다. 생각할 때는 그럴듯하지만 막상 다시 마주해보면 그 느낌은 아닌 것이다. 그래서 기억만으로 간직하는 게 더 좋은건지도.&lt;/p&gt;
&lt;p&gt;무튼 그러다 최근 애들 방을 새로 만들어주면서 작은 애 방에 공간이 있어서 방치된 모니터에 연결해서 레트로 게임기를 만들어줬다. 그리고 킹 오브 파이터즈 98을 아들과 함께 했다. 사실 애는 뭐가 뭔지 하나도 모른다. 그냥 막 누르는 거. 기술을 알려준다고 해다 필요 없다는 대답. 그럼에도 아들은 몹시 신나했었다. 어쨌든 그렇게 둘이 함께 즐거운 한때를 보냈다. 2025.9.27은 몹시 인상적인 하루였다.&lt;/p&gt;
&lt;p&gt;추석 연휴 즈음 컴퓨터가 고장나서 컴퓨존에 수리를 맡기면서 애들 컴퓨터를 사주면 좋겠다는 생각이 들어서 배그 정도 돌아가는 컴퓨터로 조립을 했다. 굴러다니는 잡동사니 부픔이 많은 줄 알았는데 죄다 오래된 것 밖에 없어서 결국 쓸 수 있었던 건 ssd와 파워 뿐이었다. 심지어 파워도 400w라 간당간당한데 그래픽 카드가 좋은 건 아니라 될 거 같아서 그냥 사용했다. 램도 4g 3개가 굴러다니는 게 있어서 쓰면 되겠다 싶었는데 gpt한테 물어보니 ddr3라 호환이 안된다는 말. 어쨌든 어찌저찌 10만년만에 조립을 해서 동작시켰다. 몹시 아이들이 좋아할 줄 알았는데 생각보다 반응은 시큰둥했다. 새로운 컴퓨터로는 애들과 새로운 게임을 함께 했다. 마인크래프트 던전스. 애들이 제일 좋아하는 게임이 로블록스, 마인크래프트다. 하다 보니 언젠가 얘들이 커서 자식을 가진다면 그때는 마인크래프트를 함께하면서 나같은 생각을 하겠다 싶었다.&lt;/p&gt;
&lt;p&gt;천하를 다 가진 것처럼 보이는 데이비드 베컴은 인생에서 가장 기억에 남는 순간 중 하나로, 아내가 자신이 먹는 음식을 함께 먹었던 일을 꼽았다. 아내 빅토리아 베컴은 25년째 생선과 찐야채만 먹는다고 한다. 단 한 번 임신했을 때 베컴이 먹는 걸 같이 먹어줬다고 한다. 별것 아닌 일처럼 들리지만, 어쩌면 우리는 무엇이든, 내가 좋아하는 그 무언가를 사랑하는 사람과 함께하는 그 순간 자체를 가장 좋아하는건지도 모르겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 9월의 잡담]]></title><description><![CDATA[#0 전 윤지호 센터장이 살림살이 괜찮은데 강의 팔이한다고 뭐라하는 사람들한테 하소연하는 글을 남긴걸 봤다. 지난 번 저속노화 선생님도 그렇고 우리 나라는 이상하게 남이 돈벌이 하는데 감나라 배나라하는 경향이 있는 것 같다. 선비의 나라 dna…]]></description><link>https://jiniya.net/2025/09/small-talk-2025-09/</link><guid isPermaLink="false">https://jiniya.net/2025/09/small-talk-2025-09/</guid><pubDate>Tue, 30 Sep 2025 21:59:45 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;전 윤지호 센터장이 살림살이 괜찮은데 강의 팔이한다고 뭐라하는 사람들한테 하소연하는 글을 남긴걸 봤다. 지난 번 저속노화 선생님도 그렇고 우리 나라는 이상하게 남이 돈벌이 하는데 감나라 배나라하는 경향이 있는 것 같다. 선비의 나라 dna는 노답인듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;선주문 후감상 예정. 우리 나라도 이런 책을 내는 분들이 많아졌으면 좋겠다는 바램. 사실 회고는 성공담보다는 실패담에서 배울 게 더 많은 게 아닌가 싶기도 하다. &lt;a href=&quot;https://x.com/jojoldu/status/1964165890603151475&quot;&gt;https://x.com/jojoldu/status/1964165890603151475&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;한남더힐 전용70펑. 매물이 주로 130억, 취득세 4.5억, 종부세포함 보유세 연 0.6억, 월세를 줄 경우 시세 2억/0.25억. 이 엄청난 세금을 감안했을 때 이게 수익이 나나 싶어보이는데 재미삼아 인공지능에 분석을 시켜 보았다.&lt;/p&gt;
&lt;p&gt;소득 창출이나 유동성 측면에서는 약점을 보이지만, 자산의 안정성과 보존 가치, 그리고 미래 자본 상승 잠재력 측면에서는 타의 추종을 불허하는 압도적인 강점을 지니고 있다. 이는 단기적인 재무 성과보다는 장기적인 부의 증식과 보존을 최우선으로 하는 투자자에게 최적화된 자산임을 의미한다.&lt;/p&gt;
&lt;p&gt;타의 추종을 불허하는 압도적인 장점을 지니고 있다는 전혀 예상밖의 대답 ㄷㄷㄷ 엄마랑 의견이 비슷한듯. 10년 후엔 과연 저 말이 맞았을지 두고 볼 일.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;이런 세상인데 아직 인공지능 버프 1도 없이 개발하는 프로그래머가 오프라인에는 많은 것도 신기함. &lt;a href=&quot;https://x.com/BenjaminKim_/status/1964527111521345707&quot;&gt;https://x.com/BenjaminKim_/status/1964527111521345707&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/052/0002244518&quot;&gt;https://n.news.naver.com/article/052/0002244518&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;진짜 올해는 해킹의 한해로 기억될듯. 뭔놈의 해킹이 끊이질 않는 2025년. 대 해킹의 시대 서막인가 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;실패를 통과하는 일을 읽기 시작했는데 메르의 블로그 같은 방식으로 작성돼 있다. 성경처럼 번호를 붙여서 글을 쓰는 형식. 메르의 블로그 이후로 이런 식으로 글을 쓰는 사람들이 제법 되는 듯한 느낌. 트렌드인가?! 콘텐츠 회사 대표라 그런지 일단 책 내용은 재밌다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;문제는 통계적으로 스타트업은 같은 시기에 시작한 10개 중 9개가 사라진다는 점이다. 그렇다면 창업자 입장에서 냉정하게 따져볼 때, 내가 겪을 확률이 더 높은 것은 남는 한 개가 아니라 사라지는 9개 쪽이다. - 실패를 통과하는 일, 박소령&lt;/p&gt;
&lt;p&gt;그렇기에 좋은 vc란 무엇인가? 내가 사라지는 9개 쪽일 때, 즉 회사를 정리해야 할 때 얼마나 창업자에게 우호적인 의사결정을 해주는 곳인가? 그게 창업자에게는 훨씬 중요한 문제라는 것을 이번에 뼈저리게 느꼈다.&lt;/p&gt;
&lt;p&gt;스타트업의 디폴트가 실패인 것처럼 vc의 디폴트 모드도 냉정할 수 밖에 없을 수 밖에 없다고 생각한다. 회사를 정리할 때 내게 유리한 의사결정을 기대하는 건 스타트업의 디폴트를 성공으로 가정하는 것 만큼이나 낭만적인 환상 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;성공하지 않은 회사의 대표가 회고록을 쓰는 건 거의 보지를 못한 것 같은데 그런 점에서 굉장히 인상적이었고 의미 있는 책 아닌가 싶다. 또한 내용이 나의 기억과 현시점에서 판단으로 구성된 것도 좋았다. 컨텐츠 회사 대표였던 것만큼 다양한 컨텐츠가 글 속에 인용되는 점도 좋았다.&lt;/p&gt;
&lt;p&gt;비슷했던 책이 그나마 옐로 모바일을 다룬 스타트업은 어떻게 유니콘이 되는가 정도 있는 것 같다. 그 책은 내부자긴 하지만 대표가 직접 기록한 건 아니라 다소 차이가 있긴 하다. 그럼에도 그 책도 무척 흥미롭게 읽었던 기억이,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;애플 망했다 망했다 하는데 쿠팡 예약 페이지 결제 몰려서 오류뜨는 걸 보니, 세상 쓰잘떼기 없는 걱정이 연옌걱정 애플걱정 아닌가 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;나는 선천적으로 왼손잡이인데 부모님이 교정해서 부모님이 관찰 가능한 건 오른손, 관찰 못하는 건 왼손으로 함. 수저, 글쓰기는 오른손, 칼질은 왼손같은 식. 근데 이만큼이라도 교정해준 부모님께 진심 감사드린다. 이 조금의 차이도 살아보면 물리적, 심리적 불편함을 꽤나 경험하게됨.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;[일상] 경쟁력 없다와 외람되다 사이에서 &lt;a href=&quot;https://jiniya.net/2025/09/between-being-uncompetitive-and-being-presumptuous/&quot;&gt;https://jiniya.net/2025/09/between-being-uncompetitive-and-being-presumptuous/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;경기 안좋다. 불황이다. 난린데 동네 마사지샵 보면 그런거 같지도 않음. 허구헌날 풀이라 예약하기가 청약 수준인듴 ㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;에어팟 프로3 c타입에 쓸어서 볼륨 조절 되는 게 진심 감동.남들 기본적으로 다되는거 해주고 감동을 주는 애플의 능력이란 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;그럼에도 불구하고 아직도 인공지능 코딩 못한다는 소리를 더러 듣는 재미난 세상. &lt;a href=&quot;https://x.com/jrogue/status/1968633245282537540&quot;&gt;https://x.com/jrogue/status/1968633245282537540&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;실질적으로 더 많은 자산을 가진 사람들은 cfd로 같은 배당주에 투자해도 배당소득이 11프로 분류과세로 끝남. 사실 어정쩡하게 가진 사람들만 타겟팅되는 셈. &lt;a href=&quot;https://x.com/mercy_kwonu/status/1968532074282832242&quot;&gt;https://x.com/mercy_kwonu/status/1968532074282832242&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;반려인이 늘어나면서 층간소음만큼 개짓는 소리의 폐혜도 심각하다. 언뜻 담배 연기보다 더 해로운게 아닌가 싶기도. 모든 소음을 피하려면 단독주택외에는 노답인가 싶다. 그럼에도 단독은 상가가 치명적 단점. 엄마 말마따느 물도 좋고 정자도 좋은 곳은 없다는게 진리인가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;그간 왜 경비 아저씨들이 기를 쓰고 주차 게이트 안 열어 주고 방문등록 하라고 부탁하는지 의문이었는데, 주차 시스템이 변경돼서 커뮤니티 앱을 처음 깔아보고 알게됐다. 이렇게 클레임 거는 사람들이 많았었구나. 참 피곤했겠다 싶은.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;서류 정리하다 예전 회사 결산 자료가 있어서 vflat으로 스캔하는데 진심 성능 미쳤다. 돈내고 쓰면서 광고해주는 앱은 첨인듯한 ㄷㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;그때는 어려서 몰랐는데 결산 자료에 찍힌 마이너스들을 보니 대표님은 참 어떻게 버텼나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;카톡은 친구로 등록된 사람들은 모두 친밀하다, 라는 가정에서 업데이트를 한거로 보여지는데 동네 청소 업체, 이사 업체 등 온갖 사무적인 관계로 등록된 사람이 더 많은게 문제 아닌가 싶다. 그나마 업뎃 궁금한 사람들은 죄다 설정 변경해서 피드에 아예 뜨지도 않는다는 게 더 황당한 현실.&lt;/p&gt;
&lt;p&gt;과거 데이터까지 끌어서 랜덤으로 보여주는건 빈약한 데이터 기반을 영끌하는 느낌이라 애잔하기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;너 사람 동정해. 그게 참 사람을 비참하게 만들어. - 사미귀, 2025&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-09-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 메멘토 모리를 되새기며 (feat. 교통사고)]]></title><description><![CDATA[#0 애들 여름방학 때 본가에 가다 큰 교통사고가 날 뻔했다. 고속도로 1차로로 주행 중이었는데 앞쪽에 사고가 나서, N차 사고가 나고, 또 내 앞차가 N+…]]></description><link>https://jiniya.net/2025/09/memento-mori/</link><guid isPermaLink="false">https://jiniya.net/2025/09/memento-mori/</guid><pubDate>Sun, 21 Sep 2025 13:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/ZDoH5dQ58ps?si=uMPsvZ_shYKmiXAr&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;애들 여름방학 때 본가에 가다 큰 교통사고가 날 뻔했다. 고속도로 1차로로 주행 중이었는데 앞쪽에 사고가 나서, N차 사고가 나고, 또 내 앞차가 N+1차 사고를 낸 상황이었다. 나도 급브레이크를 밟았지만 아슬아슬하게 사고가 나거나 직전에 멈출 것 같은 느낌이었다. 하지만 백미러로 본 내 뒷차는 거의 백프로 추돌할 것 같은 생각이 들었다. 전에도 이런 종류의 사고가 두 번 난 적이 있었는데 나는 모두 멈췄지만 뒷차가 모두 내 차를 박았다. 그럼에도 여기서 나의 합리적인 조치는 최선을 다해 멈추고 뒷차가 박으면 그냥 사고를 당하는 것이었다.&lt;/p&gt;
&lt;p&gt;하지만 애들이 타고 있어서 그랬는지 미친 짓을 해버렸다. 바로 핸들을 틀어서 옆차선으로 간 것이다. 물론 내가 옆 차선을 확인하고 차가 없고, 뒤에서 오는 차와의 거리도 안전하다고 판단한 다음 틀었다면 잘한 일이겠지만 나의 좌뇌는 그것을 확인하지 않았다. 아마 애들이 타고 있어서 사고는 피해야 한다는 생각으로 나의 무의식이 그 미친 짓을 한 것으로 보인다. 하지만 우뇌는 확인했을지도 모르겠는 게 옆 차선은 다행히 비어 있었다. 다만 고속도로라 뒤에서 오는 차가 있었고, 그 속도가 맹렬했을 뿐이었다. 행운의 여신이 나를 아직 버리지 않은 것은 그 뒤에서 오던 아반떼 차량의 운전자가 빠른 속도에도 불구하고 제법 능숙하게 사고를 피해 주었다는 점이다. 그가 갓길로 주행해서 우리는 2차로 고속도로에서 잠시 3개 차선으로 주행을 했다. 이내 나는 미친 짓을 한 걸 깨닫고 1차선에 사고 난 차량들 사이로 다시 돌아와서 멈췄다. 내가 계속 주행을 했다면 아반떼도 사고를 피하기는 힘들었다. 왜냐하면 전방 갓길에는 그전에 사고 난 차량들이 또 널브러져 있었기 때문이다.&lt;/p&gt;
&lt;p&gt;수십 초의 아주 짧은 순간에 이 모든 일이 벌어졌다. 얌전히 있었으면 사고가 나더라도 그렇게 큰 사고는 아니었을 수 있다. 하지만 핸들을 트는 바람에 재수가 없었다면 정말 큰 사고가 날 뻔한 것이다. 사고난 차량들 사이에 멈추고 보니 대략 전방 갓길에 널브러린 차량을 포함해서 6-7대 가량이 사고가 나 있었다.&lt;/p&gt;
&lt;p&gt;운전을 시작한 이래로 이렇게 큰 사고가 날뻔한 경험은 처음이이었다. 그간 운이 좋았다는 생각도 들었다. 오늘은 정말이지 조상님들이 도왔다는 생각도 들었다. 그전에 좋지 않은 소식을 전화로 들었던 터라 마음이 불편했는데, 그 순간 웃기게도 이 세상 모든 것에 감사함이 느껴졌다. 특히 그 아반떼 차량 운전자에게 너무 고마웠다. 당연하겠지만 남은 길은 졸졸 운전했고, 올라오는 길도 크루즈로 얌전히 올라왔다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;그 기억이 너무 강렬해서였을까? 여운이 며칠은 더 갔다. 그저 살아 있다는 게 고마웠고, 아이들이 무사해서 다행이었다. 그리곤 이내 깨달았다. 아등바등 스프레드시트 쳐다보며 전체 수익률이 몇프로니, 내부 수익률이 몇프로니, 금리가 어떠니, 고평가니, 저평가니 따져본들 죽음 앞에서는 다 부질없는 일이겠구나 싶었다. 인간의 가장 큰 모순이 천년만년 살 것처럼 굴다가 결국은 살아 보지도 못한 것처럼 죽는 일이라고 하지 않았던가?! 또 잡스의 말처럼 죽음 앞에서는 모든 게 초연해진다는 말도 새삼 공감됐다. 우리가 집착하며 살아가는 그 모든 것들이 죽고 나면 다 무슨 소용일까 싶은 것이다.&lt;/p&gt;
&lt;p&gt;그리고 또 그런 생각이 들었다. 과연 내가 죽는다면 마지막 순간에 나는 어떤 시간을 기억할까? 엄마가 꺼내주지 않던 세발자전거를 혼자 끌고 나오다가 화상을 입었던 날일까? 처음 두발자전거를 혼자 타게 된 날일까? 여름방학 내도록 매일 아빠와 해운대 바닷가에 갔던 날들일까? 처음으로 컴퓨터를 샀던 순간일까? 수능 시험 날일까? 첫 키스일까? 창업해서 제품을 만들면서 고생했던 날들일까? 애들이 태어나던 날일까? 운 좋게 투자로 큰 돈을 벌었던 순간일까? 아니면 실수로 전재산을 날렸던 때일까? 곰곰 생각해보니 모두 아닌 것 같았다.&lt;/p&gt;
&lt;p&gt;내 인생을 돌아봤을 때 마지막에 기억할 것 같은 해들은 2000, 2001, 2005, 2006년인 것 같았다. 그 해가 특별한 이유는 뭘까? 20대였기 때문일까? 맞다. 그것도 클 수 있다. 하지만 20대의 다른 해들도 있는데 유독 그 네 해만 떠오르는 이유는 따로 있다. 그 이유는 바로 내 인생 전체를 통틀어서 내 의지대로 오롯이 살았던 날들이 그 해를 제외하고는 없기 때문이다.&lt;/p&gt;
&lt;p&gt;우리는 대체로 책임감, 의무감, 또는 주변의 기대나 시선 같은 실상은 내 의지와 다른 것들에 의해서 많은 시간을 보낸다. 내 인생의 대부분의 날들 또한 그런 것들로 채워진 순간이었다. 아마 경우에 따라서는 평생을 전부 그런 시간들로 살아온 사람들도 있을 수 있다. 하지만 어쨌든 나는 돌아보니 저 4년만큼은 내 생각대로 내 맘대로 살았다고 말할 수 있었다. 40년 넘는 인생을 살아 왔지만 실상 몇 년을 살았냐고 물어본다면 그 네 해가 전부가 아닌가 싶기도 한 서글픈 생각이 들기도 했다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;최근에 읽은 책 &quot;실패를 통과하는 일&quot;에는 강철의 연금술사 이야기가 나온다. 이 작품이 명작의 반열에 오를 수 있었던 이유로 작가가 처음부터 최종화에서 할 이야기를 정해 두고 첫 화를 시작했기 때문이라는 내용이 있었다. 우리의 인생도 어쩌면 그럴지 모른다. 끝을 떠올려야 비로소 지금의 삶이 선명해지는 순간이 있다.&lt;/p&gt;
&lt;p&gt;우리는 언젠가 모두 죽는다. 메멘토 모리(Memento mori) — 죽음을 기억하라는 말은, 결국 현재를 충실히 더 잘 살라는 뜻일지도 모른다.&lt;/p&gt;
&lt;p&gt;통계청에서는 생각보다 재미난 통계를 많이 발표한다. 그런 것 중 하나로 &lt;a href=&quot;https://kosis.kr/search/search.do?query=%EC%83%9D%EB%AA%85%ED%91%9C&quot;&gt;생명표&lt;/a&gt;가 있다. 생명표는 한국 사람들의 나이와 성별에 따른 대략적인 기대 여명을 알려준다. 2023년 자료가 최신인데 그 자료에 의하면 나에게 이제 남은 시간은 37년 남짓이다. 살아온 시간이 살아갈 시간보다 한참 많아진 셈이다. 또 그 생명표는 어쨌든 평균이니 나에게는 그만큼의 시간도 없을 확률이 높다. 37년이면 긴 시간 같지만 또 따져보면 이제 나에게는 37번의 여름 뿐이라는 말도 된다. 그렇게 생각하면 뭔가 아쉽기도 하고 매 순간을 소중하게 생각해야겠다는 마음이 들기도 한다.&lt;/p&gt;
&lt;p&gt;가을이 온다. 내 인생에서 마흔 번도 채 남지 않은 가을이 오고 있다. 25%의 시간은 아이들에게 저당잡혔지만, 남은 75%의 시간은 내 의지대로 오롯이 살았던 2025년 가을이 되기를 바란다. 그래서 마지막 순간에는 &quot;아, 2025년의 그 가을도 있었지&quot; 하고 미소 지을 수 있기를 희망해 본다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 낳음 당했다에 부쳐]]></title><description><![CDATA[#0 SNS를 보다가 요즘 애들 사이에서 유행한다는 낳음 당했다는 말을 알게 되었다. 나는 그 표현을 보면서 요즘 애들은 참 똑똑하다, 라고 생각했는데 SNS 상의 어른들 반응은 대체로 요즘 애들 1) 무섭다 2) 버릇없다 3) 어떻게 그런 말을…]]></description><link>https://jiniya.net/2025/09/on-having-been-born/</link><guid isPermaLink="false">https://jiniya.net/2025/09/on-having-been-born/</guid><pubDate>Wed, 17 Sep 2025 13:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/pC6tPEaAiYU?si=hh11Kwz2PsKzBc5w&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;SNS를 보다가 요즘 애들 사이에서 유행한다는 낳음 당했다는 말을 알게 되었다. 나는 그 표현을 보면서 요즘 애들은 참 똑똑하다, 라고 생각했는데 SNS 상의 어른들 반응은 대체로 요즘 애들 1) 무섭다 2) 버릇없다 3) 어떻게 그런 말을 4) 우리 애가 그럴까 겁난다와 같이 부정적이었다. 과연 낳음 당했다는 말을 꼭 그렇게만 볼 일일까? 애들이 하는 철없는 말로 치부하기에는 생각보다 거기에는 더 많은 함의가 내포돼 있는 건 아닐까 싶었다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;그 표현을 보고 처음 든 생각은 쇼펜하우어였다. 요즘은 좀 시들해졌지만 한동안 서점가를 쇼펜하우어가 점령했던 시기가 있었다. 내가 보기에 낳음 당했다도 일정 부분은 거기서 영향을 받은 게 아닌가라는 생각이 들기도 했다. 왜냐하면 쇼펜하우어의 철학적 사유의 근간이 인생을 고통으로 보고 낳음 당했다와 유사한 논지를 피력하기 때문이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;쇼펜하우어는 이렇게 말한다.&lt;br&gt;
&lt;br/&gt;
생존한다는 것은 누구에게든 자신에게 부과된 강제노동을 치르는 것과 같다. 이러한 부채를 계약한 것은 성적인 쾌락을 얻는 것을 대가로 하여 그를 낳은 사람이다. 이처럼 한 사람이 즐긴 대가로 다른 한 사람은 삶을 살아야 하고 괴로워해야 하며 죽어야 하는 것이다.&lt;br&gt;
&lt;br/&gt;
-- 사는 게 고통일 때, 쇼펜하우어, 박찬국&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위 내용만 보면 쇼펜하우어의 기본적인 생각이 요즘 애들이 한다는 낳음 당했다는 말과 놀랍도록 유사하다. 그리고 나는 저 기본적인 사고의 흐름이 그렇게 잘못됐다고 판단하지 않는다. 부모로써 자식에게 기본적으로 잘해줄 수 밖에 없는 이유도 일종의 저런 좋류의 부채 의식이 무의식 중에 깔려 있는 게 아닌가 싶기도 하다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;쇼펜하우어만큼 직접적이지는 않지만 실존주의 철학도 낳음 당했다와 유사한 지점이 있다. 하이데거는 인간은 이 세계에 던져진 존재라고 표현했다. 이 말은 우리가 태어날 시대, 장소, 가정, 언어 같은 조건을 스스로 선택하지 않았다는 뜻이다. 우리의 의지와 무관하게 우리는 이미 이 시간, 이 공간, 이 세계 속에 들어와 있다는 점이다.&lt;/p&gt;
&lt;p&gt;게임 캐릭터를 만들어서 입장하는 세계를 상상한다면 아마 지금의 나를 그대로 캐릭터로 만들어 들어오고 싶은 사람은 많지 않을 것이다. 그런 점에서 실존주의가 말하는 이미 주어진 조건과 아이들이 말하는 낳음 당했다는 감각은 분명 접점이 있다.&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;카뮈는 던져짐과는 조금 다르게 부조리란 개념을 말한다. 부조리는 이 세계는 내가 어떠한 의미를 찾으려 해도 응답하지 않는 것을 의미한다. 예컨대, 성실하게 일했는데도 회사 사정으로 하루아침에 구조조정을 당한다거나, 선하게 살아 보상받고 싶었지만 그 보상은 오지 않는다거나, 오래 마음을 쏟았지만 상대의 감정은 끝내 돌아오지 않는다거나, 온 힘을 들여 만든 작업은 조용히 사라지고, 가볍게 한 결과물이 우연히 주목받는다거나 하는 일들이다. 간절히 기도하고 약속해도 세계는 아무 대답을 주지 않는다.&lt;/p&gt;
&lt;p&gt;이 세계 자체는 철저하게 나의 의지와는 아무 관련이 없이 돌아가는 것이다. 그러니 인간의 입장에서 세계를 바라보면 부조리해 보일 수 밖에 없다. 왜냐하면 거기엔 어떠한 의미도 없기 때문이다.&lt;/p&gt;
&lt;p&gt;그리고 이런 부조리의 감각은 아이들이 말하는 낳음 당했다, 와도 일부 맥락을 공유한다. 둘 다 내가 선택하지 않은 조건에서 출발하고, 내가 세운 의미나 기대가 세계에서 아무 보증도 받지 못한다는 체감을 드러내는 부분이 있기 때문이다.&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;이런 철학적 개념들을 쭉 살펴보면 애들이 말하는 낳음 당했다는 말이 그저 버릇없이, 감히 부모한테 어떻게 그런 말을처럼 가볍게 넘길 말은 아니지 싶다. 그들은 지금의 상황을 선택하지 않았고 그 상황 속으로 내던져졌고, 그들에게 현 상황은 한없이 부조리하고, 아무 의미도 없어 보일 수 있는 것이다. 심지어 이런 상황을 만든 장본인들은 다름 아닌 순간의 쾌락을 선택한 그들의 부모처럼 보이기도 한다. 그 모든 걸 한마디로 퉁치면 결국 낳음 당했다가 되는 셈이다.&lt;/p&gt;
&lt;p&gt;그렇다면 우리가 낳음 당했다고 말하는 아이들에게 해줘야 할 이야기는 무엇일까? 내던져진 상황에서, 부조리한 세계에서, 또는 고통 뿐인 삶을 어떻게 생각하고 살아나가야 하는 것인지를 알려줘야 하는 건 아닐까? 쇼펜하우어도, 하이데거도, 카뮈도 각자의 답을 했지만 사실상 정답은 없다. 어쩌면 답을 말해주기 보다는 상황 인식을 공감해 주는 게 더 큰 위로가 될지도 모른다. 왜냐하면 그걸 듣는 부모조차도 부조리한 세계 속으로 그저 던져졌고, 그 결과로 고통인 삶을 살아가는 똑같은 사람이니까 말이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 용꼬리 vs 뱀머리, 당신의 선택은?]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2025/09/small-fish-in-a-big-pond-vs-big-fish-in-a-small-pond/</link><guid isPermaLink="false">https://jiniya.net/2025/09/small-fish-in-a-big-pond-vs-big-fish-in-a-small-pond/</guid><pubDate>Sat, 13 Sep 2025 13:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/RR9v9MQQoBQ?si=IzVxAf5CKkc1K5ng&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;전투에서 이기는 것보다 전쟁에서 이기는 게 중요하다고 한다. 또 나무를 보지 말고 숲을 보라는 말도 있다. 비슷하게 반백년 가까이 살아보니 인생 전체를 보면 세부적인 어떤 노력이나 선택보다는 큰 틀에서의 세계관을 잘 정하는 게 전체적으로는 더 큰 영향을 미친다는 것을 많이 경험했다.&lt;/p&gt;
&lt;p&gt;그런 큰 주제 중에 하나가 용꼬리와 뱀머리 논쟁이다. 바닥을 쓸어도 큰 물에서 놀아야 한다는 것이 용꼬리 쪽 입장이라면, 구멍 가게에서 일을 해도 대장질을 하겠다는 것이 뱀머리 입장이라고 할 수 있다. 물론 세상은 이렇게 극단적인 이분법으로 나뉘진 않는다. 대부분은 그 사이 어떤 지점에서 선택을 하게 된다. 둘의 세계관은 뭘 더 중시하겠냐는 것을 나타낸다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;나는 태생적으로 뱀머리 주의자였다. 일단은 경쟁 환경에 노출되는 것을 별로 좋아하지 않고, 선택권이 나에게 없는 것을 선호하지 않았다. 죽이되는 밥이되든 내가 선택하는 것을 좋아한다. 그리고 자유의지가 실제로 존재하든 하지 않든 내가 주도한다는 느낌이 드는 환경을 좋아했다. 그리고 &lt;a href=&quot;/2025/09/gate-keeper/&quot;&gt;이전 글에서도&lt;/a&gt; 밝혔듯이 게이트 키퍼를 좋아하지 않기에 누가 나를 평가한다는 것을 그닥 유쾌하게 생각하지 않았고, 결론적으로 그건 큰 세계로 나가는데에는 장애물이나 다름없었다.&lt;/p&gt;
&lt;p&gt;그래서 주변에서 더러 그런 말들을 들었다. 더 좋은 대학을 가지, 더 좋은 과를 선택하지, 더 좋은 회사 취직하지, 왜 그러고 사냐 같은 말들 말이다. 하지만 강철의 연금술사에 나오는 등가교환 원칙처럼 이런 것들이 반대로 가져다 주는 장점도 크다. 일단 스트레스 레벨이 낮아진다. 마음이 평화롭고, 자기 효능감이 커진다. 이게 얼마나 큰지는 나이가 들면 들수록 느낄 수 있다. 왜냐하면 스트레스는 만병의 근원이기 때문이다. 또 추구하지 않아도 자존감이 보충된다.&lt;/p&gt;
&lt;p&gt;뭐 발전적이지 않은 사람이라고 비판해도 할 말은 없다. 어쨌든 개인적인 선호가 마음 편한 게 다른 것보다 더 중요하니 말이다. 안그래도 짧은 인생, 불필요한 것들로 스트레스 받으며 살 필요는 없다는 생각이다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;한때 서판교에 살았던 적이 있었다. 내가 살았던 동네 중에는 가장 부자 동네라고 할 수 있는데 여기서도 비슷한 경험을 했다. 다른 건 차치하더라도 주변에서 내가 평소에는 흔히 경험할 수 없었던 장면들이 더러 눈에 띄었던 것이다. 처음 충격을 받았던 게 기사였다. 대체로 기사라는 존재는 드라마 외에는 현실 세계에서는 볼 수가 없었던 나는 그 동네 살면서 숱하게 기사를 만났다. 출근하러 주차장에 가면 항상 말끔하게 차려입고 대기하는 기사님들이 계셨다. 그 정도는 그냥 넘겼다. 같은 라인에 사장님이 사는구나 싶었다.&lt;/p&gt;
&lt;p&gt;애들 어린이집을 등원시켜 주면서도 그런 일들이 반복되니 조금 신기했다. 한날 애들 생일 선물을 잘 챙겨주는 어머니랑 등원 시간이 겹쳐서 만나게 됐는데 일단 아주 고급 차를 가지고 온 것은 워낙 흔한 일이라 그러려니 했다. 그런데 애들을 맡기고 차를 타는데 기사가 나와서 문을 열어 주는 걸 보고는 뭐지 싶었던 것이다. 심지어 그분은 전업주부였다. 그때 어렴풋이 느꼈다. 아 이동네 분위기가 좀 다르구나.&lt;/p&gt;
&lt;p&gt;그러다 결정적인 일이 집 앞 커피숍에서 있었다. 노트북으로 코딩을 하고 있었는데, 목소리가 커서 본의 아니게 옆 테이블 이야기를 듣게 된 것이다. 그 동네 사람들이 대체로 집에 일하는 이모님들이 있다는 건 알았지만 그 다음이 더 가관이었다. 중국어 튜터를 애들 별로 한명씩 고용할지 말지를 얘기하고 있었던 것이다. 그때 결심했다. 아 이동네 살아서 나한테 좋을게 그닥 없겠구나. 그리고 그 해 나는 이사를 갔다. 어쨌든 그 동네는 내가 살기에는 큰 연못이었던 셈이다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;세상은 참 다양한게 나와 정반대의 입장인 사람들도 많다. 한 지인은 애를 예술 중학교에 입학시켰다. 그 집 사정을 알기에 다소 의문스럽기도 했는데, 본인이 하는 얘기를 들어봐도 내 생각과 비슷했다. 학교 입학식에 애를 데리고 갔는데 국산차를 타고 온 것은 본인 밖에 없었다는 얘기였다. 더 심각한 건 그 학교 학비였다. 맞벌이인 그 집 세후 소득의 거의 절반이 그냥 학비로 소진된다고 했다. 물론 별도의 레슨 비용이나 이런 걸 따지자면 훨씬 더 들 것이다. 이렇게까지 뒷바라지를 한다손 치더라도, 애는 아마 그 학교를 다니면 다닐수록 더 많은 격차를 느낄 가능성이 높다. 지인은 동네 피아노 학원은 할 수 있겠지라고 말했지만 내가 보기엔 그걸 하기 위한 투자치고는 너무 큰 게 아닌가 싶었다.&lt;/p&gt;
&lt;p&gt;소셜 믹스를 선호하는 사례도 있었다. 강남 고급 주택가에 새로 들어서는 단지의 임대 주택 조건에 본인이 해당한다는 말이었다. 그러면서 모모 회장님 아들과 같은 초등학교에 애를 보낼 수 있어서 좋다는 이야기를 했다. 워낙 오래전 일이고 그다지 친분이 깊은 사이는 아니라 네네 했는데, 속으로는 다른 생각을 하고 있었다. 왜냐하면 그분이 꿈꿨던 회장님 아들과 어릴 때부터 끈끈한 친구가 되는 그런 환상적인 일이 벌어지기보다는, 현실에서는 &amp;#x3C;더 글로리&gt; 같은 전개가 펼쳐질 확률이 훨씬 더 높다고 생각하니 말이다. 거기서 사라는 혜정이에게 다 커서 이런 대사를 날린다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;근로소득세 내는 넌 모르는 종합소득세 내는 세계가 있단다, 혜정아.&lt;br&gt;
&lt;br/&gt;
-- 더 글로리&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;이런 건 그냥 개인적인 선호나 느낌일 뿐이지 않을까, 이런 세계관의 선택이 뭐가 크게 중요하지, 라고 생각할 수 있다. 여기에 과학적인 뭔가가 있을까 싶은 것이다. 하지만 세상은 넓고 온갖 것들을 연구하는 사람들은 많다. 둘의 세계관 사이에 차이가 있다는 결과를 보여주는 연구들이 있는 것이다. 아웃라이어로 유명한 말콤 글래드웰의 저서 다윗과 골리앗을 보면 관련 내용이 나온다. 몇 가지를 소개해 보면 이렇다.&lt;/p&gt;
&lt;p&gt;하나는 대학별로 STEM 전공 기준 졸업생 비율을 조사한 연구다. 흥미롭게도 대학의 순위를 가리지 않고 1/3 정도만 학위를 취득했다는 결과가 나왔다. 이는 상식적으로 이해되지 않는다. 왜냐하면 하버드에 간 꼴지가 이름모를 대학에 들어간 1등보다는 몇배는 똑똑할 것이기 때문이다. 하지만 하버드 꼴지는 학위 취득에 실패했고, 이름모를 대학의 1등은 학위를 취득했다. 저자는 이에 대해서 이렇게 코멘트를 추가한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;이 &apos;하버드의 얼간이들&apos;은 매우 크고 무시무시한 연못에 사는 작은 물고기다. &apos;하트윅 올스타&apos;는 매우 푸근한 작은 연못에 사는 큰 물고기다. 이공계 학위를 받을 가능성을 결정짓는 데 중요한 것은 단지 당신이 얼마나 똑똑한가의 문제가 아니다. 중요한 것은 교실 안에 있는 다른 학생들과 비교해서 얼마나 자신이 똑똑하다고 느끼느냐 하는 것이다.&lt;br&gt;
&lt;br/&gt;
-- 다윗과 골리앗, 말콤 글래드웰&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;또 다른 연구 자료로 우수한 대학을 졸업한 학생들의 연구 업적과 낮은 순위의 학교를 졸업한 학생들의 연구 업적을 비교한 내용이 소개된다. 우수 대학의 상위 1% 학생은 당연하게도 가장 뛰어난 논문 발표수를 자랑한다. 하지만 상위 20%만 되더라도 하위 대학의 상위 1% 학생이 압도한다. MIT의 상위 1% 학생은 평균 논문을 4.73개, MIT의 상위 20% 학생은 평균 0.83개, 상위 45%는 0.12개를 발표했다. 30위 이하 대학교의 상위 1%의 평균 발표 수는 1.05다. 당연히 MIT의 상위 45%가 30위 이하 대학교의 상위 1%보다 훨씬 똑똑한 학생일 가능성이 높다. 하지만 졸업 후의 연구 업적은 하위 대학 졸업생이 오히려 더 높은 것이다. 여기에 대해서 저자는 이렇게 판단한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그런데 왜 대학원에 지원할 때까지는 모든 것을 잘해낸 승자였던 다수의 성공적인 학생들이 박사과정 훈련을 받고 난 뒤에는 그토록 별볼 일 없게 되는 것일까? 우리가 학생들을 잘못 길러온 것인가, 아니면 학생들이 우리의 기대를 저버린 것인가?&lt;br&gt;
&lt;br/&gt;
물론 대답은 둘 다 아니다. 아무도 누군가를 저버리지 않았다. 이 결과는 최상위권 학생들에게는 끝내주는 곳인 엘리트 학교가 다른 모든 학생들에게는 아주 힘겨운 곳이라는 사실을 확인시켜줄 따름이다.&lt;br&gt;
&lt;br/&gt;
-- 다윗과 골리앗, 말콤 글래드웰&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이후 책에서는 다소 파격적인 이야기를 이어가는데 특수 전형 이야기다. 학업 성취 능력과 상관 없이 우대해서 입학시켜주는 정책 이야기다. 이를 먼저 도입한 학교로 하버드를 예로 드는데 그 시발점이 큰 연못의 위험함을 막기 위해서였다는 이야기다. 결국 누군가는 하위 1/4를 해야하고, 그렇다면 자존감을 예체능등 전공과 상관 없는 특수 분야에서 충족한 학생들로 채우려는 목적이었다는 것이다. 결국 냉정하게 달리 말하면 그들은 그냥 다른 학생들의 자존감을 채우기 위한 목적으로 입학시켰다는 말이 된다. 진실이든 아니든 다소 충격적이긴 하다. 그러면서 저자는 사배자 전형을 언급하는데, 그게 과연 도움이 되는 것일지 아닐지에 대한 고민이 필요하다는 말을 덧붙인다.&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;논쟁적일 순 있겠지만 지금까지의 사례와 연구 결과를 종합해 보면, 많은 경우 &apos;뱀의 머리&apos;가 되는 것이 더 나은 선택일 수 있다는 점을 시사한다. 자신의 능력과 별개로 주변 환경이 주는 압박감과 상대적 박탈감은 개인의 잠재력을 갉아먹을 수 있기 때문이다. 물론 극단적인 환경을 이겨내는 강한 정신력의 소유자도 있겠지만, 평균적인 우리에게는 환경의 영향이 생각보다 크다는 사실을 인정해야 한다. 천하의 제프 베조스조차도 양자역학을 듣고는 물리학자의 길을 접었다는 사실을 기억할 필요가 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그는 물리학을 공부할 생각으로 프린스턴 대학에 진학했다. 아주 좋은 계획처럼 보였다. 양자역학 수업을 만나기 전까지는 말이다. 어느 날인가 어려운 미분 방정식을 풀던 그와 룸메이트는 도움을 구하러 다른 친구의 방을 찾아갔고, 친구는 문제를 잠시 들여다보더니 답을 알려주었다. 풀이 과정만 장장 세 페이지에 이르는 그 문제를 머릿속으로 계산해낸 친구를 보고 베조스는 어안이 벙벙해졌다. “그 순간 저는 위대한 이론 물리학자가 될 수 없다는 깨달음을 얻었습니다. 그 불길한 신호를 포착하고선 재빨리 전기공학과 컴퓨터공학으로 전공을 바꿨죠.” 쉽지 않은 자각이었다. 물리학자가 되기로 마음먹고 있었음에도 자신의 한계를 직시했던 것이다.&lt;br&gt;
&lt;br/&gt;
-- 발명과 방황, 제프 베조스&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;결국 가장 중요한 것은 &apos;메타인지&apos;다. 내가 어느 정도의 물에서 &apos;머리&apos; 역할을 하며 스스로의 효능감을 느끼고 성장할 수 있는지 객관적으로 파악하는 능력 말이다. 나에게 맞는 연못을 찾는 지혜, 그것이 &apos;용꼬리&apos;와 &apos;뱀머리&apos; 논쟁의 핵심일 것이다. 돌고 돌아 소크라테스 선생님의 일갈로 귀결된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Know Yourself!&lt;br&gt;
너 자신을 알라!&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[일상] 경쟁력 없다와 외람되다 사이에서]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2025/09/between-being-uncompetitive-and-being-presumptuous/</link><guid isPermaLink="false">https://jiniya.net/2025/09/between-being-uncompetitive-and-being-presumptuous/</guid><pubDate>Thu, 11 Sep 2025 11:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/CjxugyZCfuw?si=8ys756AfV8COzC8z&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;제법 오래 전이었던 것 같다. 어느 회사나 그렇겠지만 특정 시기마다 뭐에 홀린듯 이상한 문화를 한번씩 경험하는 경우가 있다. 특정인의 바램 때문일수도 있고, 구성원 모두의 기운이 그쪽으로 몰려서 그럴 수도 있겠다. 어쨌든 당시에 우리는 세미나에 홀려 있었다. 그것도 전사 세미나. 이제는 기억이 가물가물한데 돌아가면서 한번씩 주제 발표를 하는 그런 전사 세미나였던 것 같다. 당시에도 이게 뭔 의미일까 싶었지만 지나고 봐도 솔직히 큰 의미는 없었다. 그리고 그 세미나를 했던 대다수 인원은 지금 회사에 없다. 그렇게 꽤나 오랜 기간 당시에는 전사 세미나를 했는데 우습게도 그때 가장 인상 깊었던 장면은 세미나와 전혀 관련 없는 상황에서 발생했다.&lt;/p&gt;
&lt;p&gt;보통 발표자가 발표를 하고 Q&amp;#x26;A 하고 나면 대표님께서 한 말씀 하는 그런 느낌으로 흘러갔던거 같은데 당시 대표님께서 뜬금포로 우리 회사 경쟁력이 뭐냐고 물었던 것이었다. 하지만 안봐도 비디오처럼 답해야 하는 쪽의 반응은 쎄했다. 아무도 뭐라 말하지 못하고 불편한 침묵이 이어졌고, 보다 못한 대표님께서 특정인을 지목했다. 이럴 때 지목되는 건 보통 힘없고 나약하며 부서지기 쉬운 막내인 경우가 많다. 당시 정확히 막내는 아니었지만 얼추 그 근방에 있는 개발실 직원이 호명됐고, 그 직원은 의외로 호기롭게 대답했다. 우리 회사는 경쟁력이 없는 것 같습니다. 띠용~~ 뭐 어쨌든 마무리는 됐고, 그 직원은 이어진 뒤풀이 회식 장소에서 대표님 옆에서 농담 반, 진담 반으로 핀잔을 조금 듣긴 했다.&lt;/p&gt;
&lt;p&gt;그 여러차례의 세미나 기간 중에 내가 유독 이 장면이 인상적이었던 것은 바로 이 장면이야말로 나는 우리 회사의 경쟁력을 보여준다고 생각했기 때문이다. 고작 20명 남짓한 직원을 가진 회사에서 -- 직원이 작을수록 대표는 더 하늘같은 존재가 된다 -- 대표가 전직원 앞에서 회사 경쟁력이 뭐냐고 묻는데 거침없이 한치의 거짓 없이 아주 솔직하게 경쟁력이 없다고 답할 수 있는 회사라는 생각이 들었기 때문이다. 이건 달리 말하면 진실을 말해도 아무런 불이익도 없다는 강려크한 신뢰가 있을 때나 할 수 있는 행동이라고 봐도 무방하기 때문이다. 물론 나는 이 의견을 뒤풀이 때도 이야기 했지만 동의하는 사람은 1도 없었다.&lt;/p&gt;
&lt;p&gt;이후 그 직원은 당연히 어떠한 불이익도 받지는 않았고, 국내 굴지의 게임 회사로 성공적으로 이직했다. 또한 그만둘 때 나에게 오픈소스 개발 같은 걸 해서 돈을 벌어 보고 싶다는 이야기를 했었는데 실제로 그걸 이뤄낸 유일한 사람이기도 했다. 그런 의미에서 개인적으로 존경한다. 그때는 몰랐지만 경쟁력 없다고 답할만큼 떡잎부터 다른 친구긴 했던 것 같다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;세월이 아주 많이 흘렀다. 당시와 직원도 많이 바뀌었다. 여전히 있는 고인물들도 있지만 거의 절반 넘게는 모두 새로운 사람들이 아닐까 싶다. 그러던 어제 묘하게 그때 사건이 생각나게 하는 일이 있었다. 한 직원이 내가 올린 이슈 트래커 댓글에 대댓글을 달았는데 외람되지만... 이라면서 내용을 단 것이다. 그 직원 입장에서는 내 의견에 반박하는 내용이라 조심스러웠을 수도 있고, 올릴까 말까 고민했을 수도 있고, 챗지피티에게 직장 상사가 화나지 않게 써달라고 부탁했을 수도 있다. 어쨌든 외람되지만... 으로 시작되는 글을 보면서 경쟁력 없다고 말했던 그 직원이 떠올랐다.&lt;/p&gt;
&lt;p&gt;대부분의 이슈라는게 해결되기 전까지는 원인을 알 수 없는 문제기 때문에 진행 중일 때에는 뭐가 문제인지는 오리무중인 경우가 많다. 또한 그 직원은 내가 생각하기에 우리 회사에서 보기 드물게 논리적으로 일하는 직원 중에 한명이다. 그리고 그 외람되지만... 으로 올린 내용 중에 틀린 내용도 없었고, 이후에 올린 내용을 봐도 대체로 그 직원은 상황을 전체적으로 잘 판단하고 있는 것으로 보여졌다. 그 글에 답을 달고 일단락이 됐지만, 내심 마음 한켠에 불편함이 있었다. 그래서 국어 사전에서 외람되다는 말을 찾아봤다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;외람되다 adj 하는 짓이 분수에 지나치다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;찾아보고 나니 마음이 더 불편해졌다. 맞는 말이든, 틀린 말이든 어쨌든 자기 생각을 올리는 일에 분수에 지나친 경우는 없을테니 말이다. 그 친구가 그 내용을 올리기가 그만큼 힘들었다는 걸 대변하는 게 아닐까라는 조심스런 추측만 해봤다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;웃기게도 외람되지만... 으로 글을 쓴 친구를 보면서 경쟁력 없다고 답했던 친구로부터 회사 경쟁력이 그 차이만큼 없어진 건 아닐까, 라는 의문이 들었다. 왜냐하면 관리자 입장에서 가장 두려운 건 현실 세계에서 벌어지고 있는 사건, 또는 불편한 진실들이 은폐, 왜곡되는 거니까 말이다. 지금은 외람되지만... 이지만 조금 더 지나면 말해봐야 뭐하겠어가 될수도 있지 않을까라는 생각이 들기도 하는 것이다.&lt;/p&gt;
&lt;p&gt;앞으로도 모두가 자유롭게 본인들의 생각과 의견을 얘기할 수 있는 회사가 됐으면 좋겠다는 바램이 있다. 설령 그게 특정인들을 불편하게 하는 것일지라도 말이다. 회사의 경쟁력은 좋은 의사 결정이 쌓이는데서 비롯되고, 좋은 의사 결정은 진실이 왜곡되지 않고 모두 전달될 때 만들어진다고 믿기 때문이다.&lt;/p&gt;
&lt;p&gt;글을 다 쓰고 생각해보니 그 외람되지만... 을 썼던 친구도 엄청 호기로웠던 적이 있었다. 대표님께서 연말 회식 때 건배사를 하라고 시켰는데, MZ는 건배사를 하지 않습니다로 퉁친 유일한 직원이었기 때문이다. 대리 진급을 앞두고 있는 그 직원이 성공적으로 승진하기를, 그리고도 오래오래 근무하기를 희망해본다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게이트 키퍼를 대하는 자세]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2025/09/gate-keeper/</link><guid isPermaLink="false">https://jiniya.net/2025/09/gate-keeper/</guid><pubDate>Sat, 06 Sep 2025 11:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/UT_iMqUi17o?si=eWBFHKQ63YqYQsdz&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;대학때 무용과 친구를 알고 지냈던 적이 있었다. 그 친구는 입시 학원 선생님께 거의 맹종하고 있었는데, 내가 한 날 물었던 기억이 난다. 그렇게 비싼 돈을 주고 레슨을 받으면 니가 갑인데 어떻게 그렇게 쩔쩔 메냐고 말이다. 그때 그 친구가 한 이야기가 다소 충격적이었다. 통상 입시 학원을 다니면 선생님이 무용 음악을 지정해 주는데 그게 중요하다는 말이었다. 즉, 그 선생님과 그 학교 심사 위원 사이에 카르텔이 있고, 그 정보 교환을 선정곡으로 한다는 맥락의 의미였다. 지금도 그런지는 모르겠지만 당시는 다소 충격적이었다. 아, 블라인드 테스트다 뭐다 온갖 장치를 만들어 본 들 뛰는 놈 위에 나는 놈 있는 세상이구나 싶었다. 그 친구가 입시를 지나서도 계속 맹종할 수 밖에 없었던 이유는 그 좁은 이너 서클에 끼기 위해서는 그 선생님과의 친분이 절대적으로 필요했던 것이다.&lt;/p&gt;
&lt;p&gt;특정 음악을 통해서 평가가 진행된다는 걸 보면 해당 분야가 본질적인 실력보다는 특정 인맥과 연관된 네트워크가 중요함을 보여준다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;예체능이 아닌 분야도 이런 사례는 있다. 한 친구는 10년째 박사학위 논문으로 씨름 중이다. 같은 논문만 세 가지 버전을 썼는데 담당 교수는 논문을 읽지도 않고 계속 다시 쓰라고 한다고 하소연 한다. 심지어 그 교수가 자기 챗지피티가 이런 부분이 잘못됐다고 고치라고 그걸 카톡으로 보내줬다고 한다. 내 챗지피티라는 표현도 웃긴데, 본인이 판단해야 할 부분을 전적으로 위임한 것도 모자라 그걸 자기 의견인양 표현하는 최소한의 예의도 없이 거침없이 말한다는 것도 다소 어이없긴 했다. 아니면 벌써 챗지피티가 그 정도의 권위를 획득했는지도 모르겠다.&lt;/p&gt;
&lt;p&gt;나는 그 친구에게 내가 박사 과정을 안해봐서 모르겠지만 혹시 교수가 원하는 다른 게 있는 거 아니냐는 말을 했다. 그러니 말도 안되는 논문의 내용이 아닌 그래프를 3차원으로 그려라 따위를 지적질 하는 거 아니냐고. 심지어 그 그래프는 3차원으로 그리는 형태의 그래프가 아니다.&lt;/p&gt;
&lt;p&gt;이 친구와 정반대의 사례도 있다. 교수에게 정부 고위 관료들과의 만남 자리들을 주선하고 아주 쉽게 박사 과정을 진행한 사례. 그 교수에게는 이 사람의 경우 졸업을 하고도 필요하다고 판단해서 잘해주는 건지도 모른다.&lt;/p&gt;
&lt;p&gt;이 두 사례를 보더라도 학문 분야도 담당 교수의 역할이 얼마나 큰 지 알 수 있다. 또한 그 지도 교수의 역할이란게 대체로 그 교수의 기분과 판단에 의존한다는 점이 결정적이다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;내가 직접 경험한 사례도 있었다. 애가 어릴 때 하도 성화라 강남에 연예인 육성 학원에 오디션을 보러 간 적이 있었다. 나름 그 바닥에서 입지가 있는 학원이었다. 입구부터 누구를 어디 출연했는지 끝도 없이 이어져 있었다. 심지어 우리는 양반이었다. 어디 들어보지도 못한 지방에서도 새벽 차를 타고 올라온 사람들이 부지기수 였기 때문이다. 그런 곳을 처음 가봐서 나름 충격적이었다. 아, 이렇게 아이가 연예인이 되기를 바라는 사람들이 많구나 싶었다. 그리고 약간의 테스트 아닌 테스트를 하고 설명이 이어졌다.&lt;/p&gt;
&lt;p&gt;내가 보기에는 딱봐도 그냥 약장수 같아 보였다. 연예인이 그런 식으로 만들어진다고 생각을 하지 않았기 때문이었다. 그들이 그나마 방송에 출연 시키는 원리는 인맥이나 카르텔 그 이상도 이하도 아닌 걸로 보였다. 일단 대사도 없는 아역의 경우 누가 나오든 별반 차이도 없을 것이고, 그렇다면 담당 권한을 가진 사람과 아무래도 친분이 있는 사람이 추천하는 사람을 쓸 가능성이 높을테니 말이다. 실제로도 광고한다고 걸려 있는 면면을 봐도 대다수가 그런 사례 밖에는 없어 보였다.&lt;/p&gt;
&lt;p&gt;요즘 세상이 어떤 세상인데 끼만 있으면 찍어서 유튜브 올리면 연예인 하기 싫어도 연예인 되는 세상이라고 말렸던 기억이 난다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;입시 학원 선생님, 지도 교수, 방송국 연줄이 있는 학원 원장들을 살펴 보았다. 물론 그것도 그들의 능력이겠지만 이렇게 딱히 본질적인 이유가 아닌 걸로 길목을 지키고, 그 길목을 지나가는 데 통행료를 받는 역할을 하는 사람들을 통상 게이트 키퍼라고 부른다. 나는 어렸을 때 부터 반골 기질이 있어서 그런지 이런 역할을 다소 싫어했다. 그래서 전 인생을 통틀어 게이트 키퍼를 피하려고 했다. 내가 마주한 게이트 키퍼는 병역특례 회사 입사가 필요할 때의 면접관을 제외하곤 없었다. 그마저도 그들을 마주치지 않고 해결하는 방법이 있었다면 그렇게 했을 것이다.&lt;/p&gt;
&lt;p&gt;세상은 점점 편평해지고 있다. 위에도 언급한 것처럼 요즘은 실력만 있으면 누구나 인플루언서가 될 수 있다. 실상 인플루언서와 연예인의 간극도 좁아지고 있다. 방송국 입성보다 유튜브 구독자 떡상을 더 높게 치는 세상이니 말이다. 물론 아직 일부 라이선스 직종에 게이트 키퍼를 아예 피할 수가 없는 세상도 있다. 그럼에도 예전에 권한을 가졌던 많은 부분이 기술의 발달에 따라 권한이 사라졌다.&lt;/p&gt;
&lt;p&gt;방송국에 출연하지 않아도 유튜브에 찍어 올리면 전세계 수억 명의 사람에게 동시 송출이 된다. 가장 높은 권한 중의 하나였던 화폐 발권 권한도 민간이 가져가려는 움직임도 나타나고 있다. 누구나 멋진 아이디어가 있으면 관련 내용을 인터넷에 업로드할 수 있다. 물론 이런 새로운 세상도 게이트 키퍼가 아예 없는 건 아니다. 알고리즘이 그 역할을 한다고도 볼 수 있다. 하지만 알고리즘은 인간에 비해 변덕이 덜하고, 기분에 따라 움직이지 않으며, 결정적으로 대체로 모두에게 공평하게 동작한다고 할 수 있다. 심지어 요즘은 이런 공정성이 훼손되는 경우에는 심사 대상이 되기도 한다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;결론은 이렇다. 유기체 게이트 키퍼를 피할 수 있으면 피하는 게 좋다. 왜냐하면 그런 게 엮인 상황은 결과가 나의 기본 능력 보다는 다른 것에 좌우되거나 상대의 기분, 변덕에 따라 좌지우지될 확률이 높기 때문이다.&lt;/p&gt;
&lt;p&gt;입사 면접의 경우는 불특정 다수의 게이트 키퍼에게 노출되는 것이기 때문에 분산 투자와 비슷하다고 할 수 있어서 그 경향이 덜하다. 하지만 지도 교수는 거의 올인급에 해당한다. 왜냐하면 해당 담당 교수와 맞지 않는다고 변경하는 것이 쉽지 않기 때문이다. 후배 중에는 담당 교수의 불법을 고발했다 결국 졸업을 하지 못하고 수료한 친구도 있었다. 잘못은 교수가 했는데 피해는 그 친구가 본 것이다. 그러니 이런 식의 올인급 게이트 키퍼는 대체로 마주하지 않는 편이 좋다.&lt;/p&gt;
&lt;p&gt;아예 이런 원칙이 불가능한 분야도 있다. 그런 분야라면 냉정하게 생각해야 한다. 내가 인간 게이트 키퍼의 변덕과 기분을 뛰어 넘을 정도로 탁월한지 말이다. 그렇지 않다면 차라리 분야를 바꾸는 게 낫다. 내가 탁월한지 아닌지 어떻게 알 수 있냐고? 그런 질문을 가졌다면 안타깝게도 탁월하지 않을 확률이 높다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;어느 날 한 젊은이가 모차르트에게 와서 이렇게 물었습니다:&lt;br&gt;
&quot;교향곡은 어떻게 쓰는 건가요?&quot;&lt;br&gt;
이에 모차르트는 차분하게 대답했습니다.&lt;br&gt;
&quot;자넨 아직 교향곡을 쓰기엔 너무 어리다네.&quot;&lt;br&gt;
젊은이는 당황하며 말했죠: “하지만 당신은 10살 때부터 교향곡을 쓰셨잖습니까!”&lt;br&gt;
그러자 모차르트가 웃으며 답했습니다:&lt;br&gt;
&quot;그랬지. 하지만 난 남에게 방법을 물어보진 않았다네.&quot;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[소고] 불교에서 윤회와 업은 방편이었을까?]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2025/09/rebirth-and-karma-in-buddhism/</link><guid isPermaLink="false">https://jiniya.net/2025/09/rebirth-and-karma-in-buddhism/</guid><pubDate>Tue, 02 Sep 2025 13:00:01 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;나는 중학교는 미션 스쿨, 집안은 제사를 지내는 유교, 어머니는 기복 신앙으로 절에 다니신다. 그럼에도 성인이 된 나는 종교가 없다. 무교다. 대체로 많은 종교가 신을 상정하고 믿을 것을 강조한다. 믿음천국, 불신지옥 설파가 기본이다. 그런 대다수 종교와 불교가 조금 다른 점은 상당한 철학적 사유가 배경에 있다는 점 아닐까 싶다. 심지어 석가모니가 초기 불교를 설립하던 시절은 지금처럼 기복 신앙으로써의 불교를 만든 게 아니었다. 누구나 깨달음을 얻으면 열반에 이르러 부처가 될 수 있다고 가르친 것이다. 몇천 년 전 사람이 그런 사유를 했다는 것이 실로 놀랍기 그지없다. 내가 평생을 걸쳐 접한 모든 생각 가운데 가장 뛰어난 생각이 불교 철학아닌가 싶기도 하다.&lt;/p&gt;
&lt;p&gt;어쨌든 그런 불교 철학에서 유일하게 좀 거슬리는 부분이 있다면 그건 다름 아닌 윤회와 업이다. 윤회는 끊임없이 다시 태어난다는 개념이고, 업은 극단적으로 단순화하면 권선징악을 의미한다. 착한일 하면 상받고, 나쁜짓하면 벌받는다는 말이다. 살아보면 알겠지만 권선징악으로 세상은 돌아가지 않는다. 석가모니 시대에도 사람들은 그런 질문을 끊임없이 했을 것이다. 그런 질문에 답하기 위해 여기서 윤회로 확장한다. 즉, 나쁜일을 해도 이번 생은 무사할 수 있어도 다음 생에는 반드시 댓가를 치른다는 생각이다.&lt;/p&gt;
&lt;p&gt;그렇다면 윤회와 업이 불편한 이유가 뭘까? 불교의 다른 부분은 상당한 연역적 사유에 가반하는데 이건 묻지도 따지지도 않고 튀어나오기 때문이다. 그나마 권선징악은 연기의 개념을 차용해 확률적으로 생각한다손 치더라도 윤회쯤 가면 기복신앙과 다를게 뭔가 싶어지는 지점이다. 실제로도 불교 철학에서 윤회와 업의 개념은 불교 독창적인 개념이라기 보다는 당시 선행 종교에 이미 있었던 개념이기도 했다. 그래서 현대의 사람들은 대체로 두가지로 해석한다. 1) 석가모니도 어쩔 수 없는 사람이었다. 시대적 배경을 무시할 순 없다. 2) 윤회와 업은 방편으로 설파한 것이다. 여기서 방편이란 사람들이 열반의 길로 보다 쉽게 가게 하기 위해서 본질은 아니지만 차용해서 말하는 것을 의미한다. 즉, 석가모니 입장에서는 내가 이 생각에 동의하는 건 아니지만 너희가 이 생각을 따르면 그나마 쉽게 열반에 들 수 있다는 의미로 이런 개념을 사용했다는 것이다.&lt;/p&gt;
&lt;p&gt;여기까지가 대체로 내가 지금까지 이해하던 불교의 세계관이다. 그러다 오늘 한 책을 읽다가 새로운 사실을 알게 되었다. 어쩌면 제 3의 가능성이 있을지도 모른다는 생각이다. 시대적 배경도 아니고 방편도 아니고, 윤회와 업을 차용하지 않으면 굉장히 곤란해지기 때문에 어쩔 수 없이 차용한 것이라는 설명이다. 일종의 외통수라 빠져나갈 길이 윤회와 업밖에 없었다는 설명인 것이다. 이를 이해하기 위해서는 불교 철학의 토대를 살펴볼 필요가 있다.&lt;/p&gt;
&lt;p&gt;불교 세계관의 시작은 무상에서 시작한다. 이 세상에 변하지 않는 것은 없다는 사실이다. 살펴보면 모든 게 변한다. 꽃이 피면 지고, 사람이 태어나면 죽는다. 달도 차면 기울고, 빅뱅에서 시작한 우주는 팽창하다 어찌될지 모른다. 변하지 않는 건 없다. 석가모니는 여기서 고를 끌어낸다. 모든 게 변하기 때문에 고통이라는 것이다. 왜 변하는 게 고통이냐면 내가 꽃을 좋아했는데 그게 계속 그 상태로 변하지 않고 있는 게 아니라 시들어 없어지기 때문이다. 즉 내가 좋아하든 싫어하든 뭐가 됐든 내가 원하는 상태로 잡아둘 수 없고 계속 변하기 때문에 세상은 불만족, 고통으로 가득 차 있다는 것이다. 그래서 이런 불만족, 고통을 없애기 위해서는 무아를 깨쳐야 한다고 말한다. 무아란 나의 실체적 자아가 없다는 말이다. 내 생각, 내 느낌, 내 몸, 어떤 것이든 나라고 생각하는 모든 게 사실은 환상이고 내 것이 아니라는 말이다. 내 것이 아니기 때문에 당연히 내 마음대로 할 수도 없고, 내 마음대로 할 수 없으니 거기 집착할 필요가 없다. 그렇게 집착을 끊으면 변하는 것을 그저 변하는 상태로 관조하게 되고, 판단을 개입시키지 않기 때문에 고통이 사라진다고 설명한다. 무아를 좀 더 심도있게 연역하기 위해서 연기와 공이 끌려 들어온다.&lt;/p&gt;
&lt;p&gt;이게 기본적인 큰 토대다, 무상, 고, 무아로 이어지는 사유 체계. 지금까지 여기 굳이 업과 윤회가 필요한가 싶었다. 그저 종교적인 색채를 보강하는 결함처럼 보이기도 했다. 그런데 오늘 알게 된 놀라운 사실은 무상, 고, 무아로 이어지는 사유를 할 수도 있지만, 무상, 고, 반출생주의로 갈수도 있다는 점이다. 즉 세상은 무상하고, 내 뜻대로 안되는 고통으로 가득차니 출생 자체가 문제였고, 그걸 죽음으로 롤백 시키겠다는 쪽으로 생각이 발전할 수도 있다는 의미다. 사실상 이렇게 빠지는 생각을 불교 세계관으로는 막을 방법이 없다. 실컷 무상, 고를 설파했는데 무아로 가는 게 아니라 자살로 이어질 수 있는 것이다. 그래서 여기서 이걸 막기 위해서는 윤회가 동원될 수 밖에 없다. 윤회는 죽어도 끝이 아니라는 의미기 때문이다. 죽으면 끝이 아니라 재시작이 되는 것이다. 이렇게 세계를 설정하면 자살로 이어지는 생각을 막을 수 있고, 어떻게든 무아를 깨쳐서 열반에 이르러 윤회의 수레바퀴를 탈출해야 한다는 불교의 대서사를 완성할 수 있는 것이다.&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;이상 아침에 책 조금 읽고 심취해서 썰을 풀은 한 인간의 환각이었고, GPT-5에 따르면 윤회를 동원하지 않고도 불교 자체적으로 반출생주의로 빠지지 않는 논리 기반은 있다고 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;상견(常見): 죽어도 영혼/자아가 계속 존재한다.&lt;br&gt;
단견(斷見): 죽으면 모든 게 완전히 사라진다.&lt;br&gt;
&lt;br/&gt;
두 주장 모두 &quot;자아(ātman)&quot;라는 항을 가정한다.&lt;br&gt;
그러나 무아 논증(오온 무상·무아, 연기 법칙)에 따르면 항 자체가 성립하지 않는다.&lt;br&gt;
따라서 두 극단적 결론은 전제 자체가 붕괴한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;대승불교, 특히 용수(龍樹, Nāgārjuna)의 『중론』에서는 더 체계적으로 전개된다.&lt;br&gt;
모든 주장은 자성(自性, 본질적 실체)을 전제한다.&lt;br&gt;
&lt;br/&gt;
하지만 연기(조건적 발생)라는 구조에 따르면, 자성은 모순이므로 존재할 수 없다.&lt;br&gt;
따라서 &quot;태어나서 고통받고, 죽으면 끝&quot;이라는 서술도 결국 자성 개념에 기대므로 부정된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;결국 두 논리 모두 죽으면 끝이라는 말 자체도 자아가 존재할 때 성립될 수 있는데, 자아라는건 애초에 존재하지 않는다고 논증했기 때문에 말 자체가 성립되지 않는다고 보는 논리인 것 같다. 이렇게 쉽게 정리되는 걸 보면 애초에 윤회와 업은 방편이 맞았나 싶기도?!&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;불교의 놀라운 점은 그 똑똑하다는 양자 물리학자들이 절로 찾아오도록 만들었다는 점이다. 대체로 양자 물리학에 심취하면 이 세계에 대한 붕괴 내지는 모순 같은 것들을 경험하게 되는데 그때 철학적 피안처를 제공하는 게 웃기게도 불교인 경우가 많은 것 같다. 그래서 요즘은 양자 불교론이라는 세로운 장르가 나타나기도 한다. 실제로 양자 중력 이론으로 유명한 카를로 로벨리의 &quot;나 없이는 존재하지 않는 세상&quot;을 보면 끝머리에 동료 추천으로 용수를 접했다는 내용이 있다. 용수는 대승불교 철학자로 연기와 공 사상을 체계적으로 논증한 사람이다.&lt;/p&gt;
&lt;p&gt;몇천 년 전 한 인간의 사유 체계가 이토록 발전한 사회에서도 여전히 유효하다는 점은 정말 경이로움 그 자체 아닌가 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 8월의 잡담]]></title><description><![CDATA[#0 gpt oss 그렇게 뜸들이고 나온 거에 비해서는 결과가 다소 실망스럽다. 돌려보진 않았지만 벤치 자료들을 보면 qwen3보다 못한듯. 심지어 컨텍스트도 최신 경쟁력 있는 오픈 모델들에 비해 많이 떨어진다. gpt 5는 과연 어떨지?! 202…]]></description><link>https://jiniya.net/2025/08/small-talk-2025-08/</link><guid isPermaLink="false">https://jiniya.net/2025/08/small-talk-2025-08/</guid><pubDate>Wed, 27 Aug 2025 16:05:29 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;gpt oss 그렇게 뜸들이고 나온 거에 비해서는 결과가 다소 실망스럽다. 돌려보진 않았지만 벤치 자료들을 보면 qwen3보다 못한듯. 심지어 컨텍스트도 최신 경쟁력 있는 오픈 모델들에 비해 많이 떨어진다. gpt 5는 과연 어떨지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/021/0002727662?sid=101&quot;&gt;https://n.news.naver.com/article/021/0002727662?sid=101&lt;/a&gt; 돈버는덴 타고 난 머스크 형님.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;나무증권 제로 이벤트 선착순 퍼플렉시티 프로 1년 무료. 기존 고객도 적용됨. &lt;a href=&quot;https://www.mynamuhbegin.com/event?utm_source=google_m&amp;#x26;utm_campaign=NAMUH_NU_GA_AO_MO_GSA_CLICK_230703&amp;#x26;utm_medium=P_ALL_KEYWORD_BRAND_TOTAL_MO_X_230703&amp;#x26;utm_content=250512_251231_SA_AO_NURT_X_sitelink-zero_event&amp;#x26;utm_term=nh%20%EC%A6%9D%EA%B6%8C&amp;#x26;gad_source=1&amp;#x26;gad_campaignid=20264628840&amp;#x26;gclid=Cj0KCQjwndHEBhDVARIsAGh0g3AFo6F-BbTtm6k0KRIXDT5Gcz8kQb496vtrs5e2gt_oL6t0CZvOEtQaAlVJEALw_wcB&quot;&gt;https://www.mynamuhbegin.com/event?utm_source=google_m&amp;#x26;utm_campaign=NAMUH_NU_GA_AO_MO_GSA_CLICK_230703&amp;#x26;utm_medium=P_ALL_KEYWORD_BRAND_TOTAL_MO_X_230703&amp;#x26;utm_content=250512_251231_SA_AO_NURT_X_sitelink-zero_event&amp;#x26;utm_term=nh%20%EC%A6%9D%EA%B6%8C&amp;#x26;gad_source=1&amp;#x26;gad_campaignid=20264628840&amp;#x26;gclid=Cj0KCQjwndHEBhDVARIsAGh0g3AFo6F-BbTtm6k0KRIXDT5Gcz8kQb496vtrs5e2gt_oL6t0CZvOEtQaAlVJEALw_wcB&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;this is your adventure. it&apos;s not mine. - maid ep.10 힐빌리의 노래만큼이나 절절한 리얼 스토리. 대체로 가족이 문제다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;이는 주로 &apos;중간 부유층&apos;에 해당한다. 극도로 부유한 사람들은 모든 결정을 다른 사람에게 맡길 수 있다. 두 번째 집을 살 돈은 있지만 직접 관리해야 하는 사람들이 삶이 가장 복잡해진다. - 모건 하우절&lt;/p&gt;
&lt;p&gt;뭐든 어정쩡한 상태가 젤 골아픈듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;건물이라면 한숨부터 나오는 지금에 와서도, 건물주로 살았기 때문에 누렸던 기쁨에 대해서는 인정할 수밖에 없습니다. 월세가 없었다면 회사를 그만둔 뒤 몇 년 동안 앱 개발에 집중할 수 없었을지 모릅니다. - 건물주의 기쁨과 슬픔, 김재호&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;모기지 상환 시 기쁨의 눈물을 흘렸으며, 이는 돈을 단순히 스프레드시트를 만족하는 도구가 아닌 더 나은 삶을 위한 도구로 볼 때 많은 것이 달라진다는 것을 의미한다. - 모건 하우절&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;수박 몰랐는데 몹시 고혈당 식품이었다. ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;역사는 아무리 고통스럽더라도 되돌릴 수는 없지만, 용기를 가지고 마주한다면 다시 반복해서 겪을 필요는 없다. - 마야 안젤루&lt;/p&gt;
&lt;p&gt;나이 먹어 숙취로 돈쓰고, 고생하고, 민폐끼치고, 이게 뭔 난린가 싶다. 실수가 되풀이 되는게 인생이라지만 이만하면 이제 그만할 때가 된 게 아닌가 싶기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;람세스 2세는 이집트를 66년간 통치했고, 90세까지 살았으며, 부인은 200명, 자식은 100명이 있었다고 한다. 숫자 하나 하나 나올 때 마다 실로 놀랍기 그지 없다. 심지어 그 옛날에. 유전자빨인가?! ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;이탈리안 브레인롯과 케데헌을 모르고, 마인크래프트가 뭔 재민가 싶은 나 자신을 보면서, 서태지를 모르고, 스타크래프트 보고 벌레 나오는 그게 뭐가 재밌냐던 부모님을 30년 만에 이해하게 됐다. 서는 데가 바뀌면 풍경도 달라진다던 송곳의 대사는 정말 명문인듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;진짜 창피한 건 평생 두 번 다시 볼 일 없는 사람들 시선에 움츠러 들고, 그 사람들이 배설하듯 내뱉는 말에 스스로를 가두는 겁니다. 그들의 시선, 내뱉는 말들, 거기엔 아무런 의미도, 가치도, 책임도 없어요. - 에스콰이어 ep.02&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;모든 자산이 올타임 하이를 갱신 중인데 묘하게 쎄한 느낌이 많이 드는 요즘.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;이런 사연이 있는 줄은 몰랐는데 흥미롭다. 앞으로 다양한 분야에서 비슷한 일이 벌어지지 않을까? 뒤집어진 강자는 부정하고, 버프 받고 올라오는 사람은 환영할듯. 근데 이러니 저러니 해도 결국 비겁한 변명 아닌가 싶다. &lt;a href=&quot;https://x.com/JongwonKim/status/1959892712397967785&quot;&gt;https://x.com/JongwonKim/status/1959892712397967785&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;조선의 실록 편찬 과정은 여러모로 신기하다. 실록을 실시간으로 기록해서 사후 왜곡을 줄이려 한것도 굉장한데, 기록물을 당대 임금은 열람 금지시켜 사관이 눈치보지 않고 쓸 수 있었다는 점도 독특하다. 그게 연산군 빼고 쭉 지켜졌다는 것도 신기함. 심지어 분산 보관해서 왜란에도 살아남았다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;우리를 만드는 것은 반복적인 행동이다. 그러므로 탁월함은 특별한 행위가 아니라 삶 속의 습관이다. - 아리스토텔레스&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;예전에 이재용 회장 집에 초대받아 갔더니 2억원대 와인을 따주더라는 말을 들은 적이 있다. 그집 사람들과 친분도 있고 직접 투자도 받았던 사람인지라 구라는 아닐듯. 2억원짜리 와인을 팡팡 따면서 살려면 50억은 택도 없고, 나는 자연인이다처럼 살려면 50억은 차고도 넘치는 돈 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;답도 없는 50억 파이어 이야기로 탐라가 뜨거운 걸 보다가. 케바케, 사바사 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;직접 짜려고 낑낑거리다 복잡하고 머리가 아파서 걍 아몰랑 llm에 다 때려넣고 작성하라고 시켰더니, 1) 새 코드를 짜낸 것은 물론, 2) 때려넣은 기존 코드에 있는 버그까지 찾아서 알려준다. 2분 45초에 이게 다 되는 거였다니 정말 당황스럽네.&lt;/p&gt;
&lt;p&gt;심지어 버그 지적질이 틀린거 같다고 했더니 llm왈 코드 만든 사람은 내가 말한대로 설계한게 아니라고 잘못 생각하고 있다는 대답,, 내가 작성한 코드라고 나는 내 말대로 설계한거라고 했더니. 그러면 그 생각대로 만드려면 어떻게 고쳐야 하는지 알려줌. 이랬든 저랬든 틀린거였 ㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-08-27&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 7월의 잡담]]></title><description><![CDATA[#0 테슬라를 직접 투자하진 않지만 진심 성과를 떠나 저렇게 요란하고, 시끄럽고, 예측 불가능한 주식도 흔치는 않을거란 생각. 또 신기한 건 지나고 보면 이럴때 사면 항상 벌긴 하더라는. 그럼에도 겁나서 못 들어가는 거도 항상 똑같다. etf…]]></description><link>https://jiniya.net/2025/07/small-talk-2025-07/</link><guid isPermaLink="false">https://jiniya.net/2025/07/small-talk-2025-07/</guid><pubDate>Wed, 30 Jul 2025 23:17:45 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;테슬라를 직접 투자하진 않지만 진심 성과를 떠나 저렇게 요란하고, 시끄럽고, 예측 불가능한 주식도 흔치는 않을거란 생각. 또 신기한 건 지나고 보면 이럴때 사면 항상 벌긴 하더라는. 그럼에도 겁나서 못 들어가는 거도 항상 똑같다. etf로 포지션 일부는 테슬라에 노출돼 있음.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;[코딩] 초보 코더 탈출을 위한 꿀팁, 최소 가시성 &lt;a href=&quot;https://jiniya.net/2025/07/minimum-visibility/&quot;&gt;https://jiniya.net/2025/07/minimum-visibility/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;나는 겨우 스물다섯 살이었다. 삶이 끝나지 않고 계속되었으면 좋겠다고 생각했던 시절이었다. - 친밀한 이방인, 정한아&lt;/p&gt;
&lt;p&gt;지극히 평범한 인간들이 평범하게 걷고 있는 길 위의 풍경처럼 그들의 결혼생활도 그랬다. 우리가 질서를 연기하는 한, 진짜 삶은 아무도 눈치채지 못한다. 그렇다면 진짜 삶은 어디 있는가? 그것은 인생의 마지막에서야 밝혀질 대목이다. 모든 걸 다 잃어버린 후, 폐허가 된 길목에서.&lt;/p&gt;
&lt;p&gt;드라마 안나랑 내용이 비슷하다 싶었는데 알고보니 원작이었다. 알았으면 시작을 안했을텐데 이미 와버린 길이 있어 마저 읽었다. 결말은 드라마보다 책이 나은듯. 세번째 소설이라는데 이 작가의 1, 2번째 소설도 궁금해졌다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;수제 코드란 표현이 재밌다. 뭔가 적절한 거 같기도 ㅎㅎ &lt;a href=&quot;https://x.com/wapj2000/status/1940353643066384495&quot;&gt;https://x.com/wapj2000/status/1940353643066384495&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;[소고] 인공지능이 생산성 향상으로 이어지지 않는 이유 1 &lt;a href=&quot;https://jiniya.net/2025/07/reasons-ai-may-not-increase-productivity-1/&quot;&gt;https://jiniya.net/2025/07/reasons-ai-may-not-increase-productivity-1/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;1000일간 먹이를 받아온 칠면조는 인간을 믿게 된다. 그러나 추수감사절 아침, 그 믿음은 가장 잔인한 방식으로 깨진다. 지금까지 안 그랬으니 앞으로도 괜찮을거다라는 논리의 함정, 블랙스완. 우리가 경험한 과거가 미래를 보장하진 않는다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;너도 너만의 이유를 찾아&lt;br&gt;
개같이 구르고 엿같이 깨져도&lt;br&gt;
절대로 변하지 않을 그런 이유&lt;br&gt;
이 퍽퍽하고 꺼끌꺼끌한 이 길을&lt;br&gt;
아무런 이유도 없이 그냥 걸어 가기에는&lt;br&gt;
너무 되다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;중증외상센터 ep.06&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-07-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;구글의 개발 프로세스나 박진영의 인맥 무용론 같은 건 걸러 들을 필요가 있다는 생각. 그 회사, 그 사람에게는 최선의 방법이겠지만 그걸 좋다고 다른 회사, 다른 개인에게 단순 무식하게 일반화시켜 적용하면 부작용이 더 심할수도 있지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;내일이 어찌 되든&lt;br&gt;
오늘은 잘 보내자고&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;원 데이, 2012&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-07-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;숭실대 서준식 교수 대단한듯. 남들 다 비웃을때 은행주 엄청 사더니 폭등, 은행 올라서 증권 좋아보인다고 갈아탄다고 하더니 폭등, 요즘은 통신, 광고주 사고 있다는데. 늘 그렇듯 요즘 픽은 통신?, 광고? 이런 느낌인듯. 그나저나 국장 이게 맞나 싶다. 이제 싼거 같지도 않은데...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;메타가 거액을 들여 ai 어벤져스를 만들고 있다. 과연 잘 될까? 배가 산으로 가지 않을까 싶은 생각이 든다. 과연 이번엔 투입한 돈에 걸맞는 아웃풋이 나올지도 관전 포인트 아닌가 싶기도. 천하에 하릴없는 빅테크 걱정.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;박종훈 기자가 쓴 세계 경제 지각 변동을 읽었다. 약간 킬링타임용 무협지 읽은 느낌. 이 모든 아수라장은 결국 저성장으로 촉발됐다는 말이 의미심장했다. 먹을 게 없으면 일단 남의 거라도 뺐는게 인간의 본성인가 싶기도. 구조적 문제라 쉬 해결되지도 않을거라 더 개판이 될 것 같은 느낌?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;진심 인공지능 환각은 애교다. 인간 아무말 대잔치는 답이 없음.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;프로그램에 문제가 발생했다. 인간은 아무도 문제 원인을 파악하지 못했다. 단순 장애로 판정. 하지만 인공지능이 문제 원인을 파악했고 수정도 했다. 몇 분 안 걸림. 테스트 결과 인공지능이 파악한 문제가 맞았다. 이 문제를 인간이 이해하도록 해명하는데 반나절 걸림.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;코로나때 한시적으로 주35시간(4.5일) 하다 지금도 유지 중인데, 가능했던 이유는 점심 시간을 칼 1시간으로 변경. 기존에는 그냥 대충 2시간씩 사용했음. 그리고 포괄임금제라 해당 시간을 야근대비용 버퍼라 생각하는. 물론 야근이 그만큼 많지는 않다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;애가 엔트리봇 반복 블록으로 구구단 만드는 영상을 보냈다. 나도 비슷한 나이 때 코딩을 배웠던 것 같은데 30년 넘는 세월이 흘렀는데 코딩 교육은 몹시 퇴보한 느낌. 추상화를 위한 추상화, 코딩 교육을 위한 코딩이 아닌가 싶다. 그냥 파이썬, 자바스크립트 가르치면 될 걸 뭔 닭짓인가 싶음.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;이북 볼 때 불편해서 유툽서 검색하다 rii i4를 알게되서 알리에서 하나 샀는데 완전 신세계. 이렇게 편하게 페이지 넘김이 되다니. 심지어 마우스 패드도 붙어있다. 만칠천원짜리 만듦새가 미쳤다. 심지어 무료배송. 중국은 정말 가격으로 이기기는 노답인듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;grok4 livebenh, 전체 4등. 이로써 다시 한 번 일론은 대단하다는 사실을 입증한듯. 저커버그 현타가 심각하겠다. 근데 코딩 순위는 한참 낮은데 livebench 코딩 순위가 맞나 싶다. 코딩 기준 체감이랑 순위랑 다소 이질적임. r1이 장기 상위권 랭크도 인상적이네.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;취미도 결이 맞아야 한다. 하도 할 거 없어서 이참에 필체나 고쳐보자 싶어서 미꽃체 강좌를 거금을 들여 끊었는데, 첫 날 하루 연습하고 한번도 안 함. 해야지 싶다가도 왜케 하기 싫은건지. 노오력은 하기 싫고 멋진 필체는 갖고 싶고, 운동은 하기 싫고 살은 빼고 싶고. 모순 그 자체.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;진심 자비 없는 날씨. 원래 이렇게 더운게 맞나 싶을 정도로 덥네 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;국장 미장 금 은 구리 코인 부동산 다 떡상하는 걸 보면 그냥 현금이 쓰레기되고 있는 장세 아닌가 싶다. 심지어 엘베에 냉방비 10프로 인상 공지까지. 이러다 강남 아파트 200억 시대 열리는 건 아닌지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;자기, 돈 많아? 자기가 일론 머스크야? 어? - 살롱 드 홈즈 ep.01&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;만약 내 눈앞에 일론 머스크와 버지니아 울프가 앉아 있다면 나는 당연히 일론 머스크가 개무시당한다고 느낄 정도로 버지니아 울프에게 집중할 것이었다.  - 이유 없이 싫어하는 것들에 대하여, 임지은&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;뭔 웹툰인가 궁금해서 찾아보니 네이버웹툰 이직로그, 분류가 순정인데 개발자 이야기라니 나름 신박했다. &lt;a href=&quot;https://x.com/winterwolf0412/status/1944210866251215205&quot;&gt;https://x.com/winterwolf0412/status/1944210866251215205&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;예전엔 탑티어 모델이 아니면 의미없다 생각헤 소버린ai에 부정적이었는데, gemini 2.5pro 아후로 생각이 바뀜. 일정 수준 넘어서면 모델 자체는 큰 차이가 없어지는 느낌. 일반인들이 쓰는 수준 자체가 고만고만하기 때문. 그냥 편하고, 싸고, 접근성 좋은거 쓰게되는 거 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;뛰는 놈 위에 나는 놈 있다고, oai에 지브리가 있었다면 xai는 그록 컴패니언. 머스크답다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;앞으로 난! 뭘 의지하며 살아야 하냐구!! 가르쳐 줘!! 제발!!&lt;br&gt;
그런 건 스스로 생각해. 일어나서 걸어. 앞으로 나아가. 너는 튼튼한 두 다리가 있잖아.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;강철의 연금술사, vol. 01&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-07-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;지인이 어짜피 쿠팡서 쇼핑할거 시리즈 통해서 쇼핑하면 무료 캐시 준다고 알려줘서 잘 쓰다 얼마전부터 사라져서 아쉬워 하고 있었는데, 물어보니 카카오 페이지에도 똑같은 시스템이 있다고. 카카페는 심지어 대여권으로 전환해두면 캐시 유효기한도 사라짐. 쿠팡 참 여러모로 혜자스럽다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/qVTAPMe6YVE?si=_O7JqvpYPuszyS0n&quot;&gt;https://youtu.be/qVTAPMe6YVE?si=_O7JqvpYPuszyS0n&lt;/a&gt; 요즘 어린 친구들은 눌러 앉을 좋은 회사에서는 회식같은 행사에 그나마 우호적이지만, 거쳐가는 회사에서는 부정적인 경우가 많다는 얘기를 들었다. 결국 미국과 비슷한 이유로 줄고 있는 게 아닌가 싶다. 거쳐가는 회사 입장에서도 그냥 일 잘하는 직원이 좋다는 거.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#29&lt;/h2&gt;
&lt;p&gt;개인적으로 괜찮았던 불교 책. 불교는 마음은 편해지지만, 그만큼 발전도 없어지는듯한 느낌. 등가교환인가?!&lt;/p&gt;
&lt;p&gt;인문학을 좋아하는 사람들을 위한 불교수업&lt;br&gt;
인생의 괴로움과 깨달음&lt;br&gt;
붓다 브레인&lt;br&gt;
불교는 왜 진실인가&lt;br&gt;
메달린 절벽에서 손을 뗄 수 있는가?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#30&lt;/h2&gt;
&lt;p&gt;10대 때 들었던 음악을 평생 좋아한다는 얘기를 들은 적이 있다. 게임도 그런 게 아닌가 싶다. 나이 들어서는 당췌 새로운 게임을 배우기가 쉽지 않다. 나름 어릴 때는 애들이랑 같이 게임해보는게 로망이었는데 이제는 내가 우리 엄마가 하던 멘트 치고 있다. 그게 뭐가 재밌어?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#31&lt;/h2&gt;
&lt;p&gt;“우리 집안 금괴를 절반이나 훔쳐 달아나서 하나도 가져오지 않았지만, 내 아이를 벌판에서 낳지 않고 데려왔군요.”&lt;br&gt;
그리고 잠시 뒤 또 말했다. “금괴를 전부 훔쳐 갈 정도로 독하지는 않았지요. 훔쳐 간 것보다 남겨둔 게 더 많으니.” - 원청, 위화&lt;/p&gt;
&lt;p&gt;어렴풋하게 ‘나뭇잎은 떨어지면 뿌리로 돌아가고 사람은 죽으면 고향으로 돌아간다’라는 구절이 보여 구이민은 눈가가 촉촉해졌다. 린샹푸가 토비에게 총기를 가져가기에 앞서 모든 준비를 마쳤음을 알 수 있었다.&lt;/p&gt;
&lt;p&gt;원청의 린샹푸나 인생의 푸구이나 보는 내내 뭐라 말로 표현하기 힘든 애잔함이. 이런 류의 소설을 쓰는데 위화는 남다른 재주가 있는 듯. 위화의 소설을 읽고 나면 그냥 평화로운 시대 잠깐 살다 가는 것만 해도 얼마나 큰 복인지를 새삼 깨닫는다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#32&lt;/h2&gt;
&lt;p&gt;이상하게도 이 세계에서는 거인에 대항할 힘을 높인 자일수록 거인에게서 멀어질 수 있어.&lt;br&gt;
왜 이런 코미디가 벌어진다고 생각해?&lt;br&gt;
글쎄? 왜일까?&lt;br&gt;
그게 인간의 본질이라서가 아닐까?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;진격의 거인 vol.04&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-07-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#33&lt;/h2&gt;
&lt;p&gt;지금 내게는 행복도 불행도 없습니다.&lt;br&gt;
모든 것은 지나갑니다.&lt;br&gt;
내가 지금껏 지옥 같은 삶을 살아온 이른바 ‘인간’ 세계에서 다만 한 가지 진리처럼 여긴 것은 이 사실뿐입니다.&lt;br&gt;
모든 것은 지나갑니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;인간실격, 다자이 오사무, 정회성 옮김&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;민음사판으로 읽었는데 책세상 정희성 역으로 읽기를 추천. 읽는 내내 &quot;예의&quot;란 표헌이 무척 거슬렸는데 알고보니 이게 일본어 번역체 문장 특징. 읽고 나서 5권 넘게 다른 번역을 살펴봤는데 예의가 없는 유일한 역본이 정희성역.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#34&lt;/h2&gt;
&lt;p&gt;인간은 자신의 죽음을 예측하지 못하고, 인생을 마르지 않는 샘이라고 생각한다. 하지만 세상 모든 일은 고작 몇 차례 일어날까 말까다. 자신의 삶을 좌우했다고 생각할 정도로 소중한 어린 시절의 기억조차 앞으로 몇 번이나 더 떠올릴 수 있을지 모른다. 많아야 네다섯 번 정도겠지.&lt;/p&gt;
&lt;p&gt;앞으로 몇 번이나 더 보름달을 바라볼 수 있을까? 기껏해야 스무 번 정도 아닐까. 그러나 사람들은 기회가 무한하다고 여긴다. - 나는 앞으로 몇 번의 보름달을 볼 수 있을까, 류이치 사카모토&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#35&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/003/0013363393?sid=101&quot;&gt;https://n.news.naver.com/article/003/0013363393?sid=101&lt;/a&gt; 단 유튜브 라이트를 이용할 경우 음악 콘텐츠에는 광고가 노출되며 백그라운드 재생이나 오프라인 재생 기능은 포함되지 않는다. -- 빅테크 잔머리를 무슨 수로 이기나 싶은 기사&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#36&lt;/h2&gt;
&lt;p&gt;예전엔 작성한 코드가 실제로 내 생각대로 문제 없이 동작할 때 도파민 뿜뿜이었다면, 요즘은 인공지능이 네, 그 지적은 매우 날카롭고 정확합니다... 라고 말해줄 때 도파민 터짐. 이것도 요즘 개발자나 느낄 수 있는 사치 아닐까 싶긴 하다. 점점더 잘할테니까. 그나저나 진짜 코딩 잘한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#37&lt;/h2&gt;
&lt;p&gt;메리츠 증권 앱의 최대 장점. 스플래시 화면 정중앙에 신세경 뜬다는 거. 업데이트 한다고 로딩 화면에 멈춰 있어도 화가 안나는 버프 추가됨.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#38&lt;/h2&gt;
&lt;p&gt;인공지능 시대에 cs 전공 떡밥이라뉘. 난 내가 지금 10대인데 프로그래머가 되고 싶은 상황이라면, 대학을 가진 않을듯. 그냥 바로 프로그래머를 할 것 같다. 프로그래머 하려고 cs 전공을 하는 건 전형적인 오버 엔지니어링 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#39&lt;/h2&gt;
&lt;p&gt;천년만년 살 것처럼 행동하지 마라. 죽음이 지척에 있다. 살아 있는 동안, 할 수 있는 동안 선한 자가 되라. - 명상록, 마르쿠스 아우렐리우스/천병희 옮김&lt;/p&gt;
&lt;p&gt;천병희 이 분 번역에 진심 놀랍다. 역자로 검색해서 읽을만한 반열인듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#40&lt;/h2&gt;
&lt;p&gt;저게 말이 돼? 했던 협상이 트럼프 입맛대로 진행돼 가는 걸 보니 협상을 잘하는 건 맞긴 한건가 싶기도. 그럼에도 미국인이 아니라 일진 양아치같아 보이는 건 어쩔 수 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-07-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 인공지능이 생산성 향상으로 이어지지 않는 이유 1]]></title><description><![CDATA[내가 처음 인공지능과 조우한 순간은 깃헙 코파일럿이 출시되던 시점이었다. 그때 바로 알게됐다. 이거 물건이다. 이건 우릴 드라마틱한 생산성 향상의 천국으로 안내할 호박마차다 싶었다. 그리고 제법 몇년이 지났고 202…]]></description><link>https://jiniya.net/2025/07/reasons-ai-may-not-increase-productivity-1/</link><guid isPermaLink="false">https://jiniya.net/2025/07/reasons-ai-may-not-increase-productivity-1/</guid><pubDate>Thu, 03 Jul 2025 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;내가 처음 인공지능과 조우한 순간은 &lt;a href=&quot;/dev/ai-driven-development/&quot;&gt;깃헙 코파일럿이 출시되던&lt;/a&gt; 시점이었다. 그때 바로 알게됐다. 이거 물건이다. 이건 우릴 드라마틱한 생산성 향상의 천국으로 안내할 호박마차다 싶었다. 그리고 제법 몇년이 지났고 2022년 당시의 인공지능은 오징어로 만들어버리는 기똥한 모델들이 줄지어 출시됐다. 가격은 기하급수적으로 싸졌다. 오죽하면 요즘은 세상에서 제일 싼 게 지능이라는 소리가 나올 정도니 말 다했다. 그럼에도 신기한 사실은 그런 세상이 왔지만 생각외로 생산성 향상은 잘 관찰되지 않는다는 점이다.&lt;/p&gt;
&lt;p&gt;과거 왜 생산성 향상이 없을까란 생각에 빠져 주변을 관찰해보면 결과는 사람들이 인공지능을 사용하지 않기 때문이라는 단순한 사실로 귀결됐다. 그래서 처음에는 비싸니까, 돈이 드니까 안쓰나 보다 싶었다. 그리고 이후 쓸만한 무료 인공지능이 많이 출시됐고, 그런 것들의 존재를 알려주었지만 결과는 비슷했다. 아니 미묘하게 달라졌다고 해야 정확할 것 같다. 인공지능을 쓸 때는 쓴다. 다만 생산성 향상을 일으킬 수 있는 많은 문제들에 적극적으로 사용하지 않을 뿐이다. 정리하자면 1) 인공지능의 존재를 알고, 2) 문제를 마주했지만, 3) 생산성 향상이 발생하지 않는 이유 중 대다수는 4) 그 문제를 인공지능에게 물어보지 않기 때문이라는 사실. 뭐 결국 인공지능을 사용하지 않는다는 점은 똑같다. 주요한 차이는 인공지능의 존재를 몰라서 또는 싫어서 사용하지 않는 게 아니라 문제를 문제라고 인식조차 하지 못한다는 데 있다는 것이다.&lt;/p&gt;
&lt;p&gt;일본어를 할 줄 모르는 내가 일본어 문서를 읽어야 한다는 상황을 생각해보자. 이 상황은 명확해서 인공지능의 존재를 아는 사람은 응당 인공지능에게 번역을 시킬 것이다. 사실 이런 건 누구나 불편하고 누구나 된다는 걸 알기 때문에 어느 정도 활용이 되고 있는 측면이 많다. 이 상황은 현재 많이 개선되서 이런 종류의 생산성 향상은 많이 관찰된다.&lt;/p&gt;
&lt;p&gt;진정한 문제는 문제라고 인식조차 못하는 상황에서 발견된다. 예를들면 이런 상황이다. 1.1, 1.2, 1.3, 1.4, ..., 1.10, 2.1 버전까지 버전이 있다. 그런데 2.1 버전에서 문제가 발생한 걸 알게 되었다. 그 문제가 1.2 버전에서는 없었다는 사실도 과거 기록으로 확인됐다. 1.3 ~ 2.1 사이의 어디에서 문제가 발생했는지 테스트를 해야 하는 상황인 것이다. 이 상황을 마주한 담당자가 취할 수 있는 많은 선택지가 있겠지만 거칠게 두 부류로 나눈다면 A) 1.3버전부터 순차적으로 테스트 하는 사람이 있고, B) 1.7을 먼저 테스트하는 바이너리 서치 식으로 테스트를 하는 사람이 있다. 문제는 바로 옆에 나보다 똑똑하다고 평가 받는 인공지능이 있지만 이걸 인공지능한테 물어봐야지 라는 생각을 A도, B도 둘 다 하지 않는다는 점이다. 이건 내가 해야할 일이지, 내가 풀어야 할 문제라고 인식하지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;O(N) 세상에 살고 있는 A가 O(logN) 세상에 사는 B로 업그레이드가 돼야 생산성 향상이 발생한다. 그리고 이건 현재 시중에 나와 있는 조금 괜찮은 인공지능이라면 모두가 적절한 답을 정해줄 것이라 기대된다. 하지만 사람은 묻지 않는다. 아니 이걸 물어봐야 한다고 생각조차 하지 않는다. 그러니 A가 B로 업그레이드 되기는 요원한 것이고, 그러니 현실 세계에서는 생산성 향상이 생각만큼 많이 관찰되지 않는 것이다.&lt;/p&gt;
&lt;p&gt;생산성 향상을 위해서 인공지능을 사용합시다, 라는 말에는 상당한 사람이 반감을 가진다. 하지만 같은 연봉으로 근무 시간을 주 40시간에서 30시간으로 단축시킵시다. 하면 쌍수들고 환영하지 반대할 사람은 없을 것이다. 둘은 같은 말인데도 반응이 천지차이라는게 웃픈 현실 아닌가 싶다.&lt;/p&gt;
&lt;h2&gt;grok의 복음...&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;1.1, 1.2, 1.3, 1.4, ..., 1.10, 2.1 버전까지 버전이 있다. 그런데 2.1 버전에서 문제가 발생한 걸 알게 되었다. 그 문제가 1.2 버전에서는 없었다는 사실도 과거 기록으로 확인됐다.&lt;/p&gt;
&lt;p&gt;이때 어떻게 테스트하는 게 좋은 방법이야.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;라는 질문에 대한 이하 grok의 복음...&lt;/p&gt;
&lt;p&gt;주어진 상황에서 소프트웨어 버전 1.1부터 2.1까지 존재하고, 버전 2.1에서 문제가 발생했으며, 버전 1.2에서는 해당 문제가 없었다는 사실을 알게 되었습니다. 문제를 효율적으로 파악하고 해결하기 위해 다음과 같은 테스트 방법을 추천합니다. 이 방법은 이진 탐색(binary search) 기반의 체계적인 접근법을 사용하여 문제의 원인이 처음 나타난 버전을 빠르게 식별하는 것을 목표로 합니다.&lt;/p&gt;
&lt;h3&gt;테스트 전략: 이진 탐색을 활용한 버전 테스트&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;목표&lt;/strong&gt;: 문제가 처음 발생한 버전을 정확히 찾아내기 위해 테스트를 최소화하면서 버전 간 비교를 수행합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;단계별 접근법&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;초기 범위 설정&lt;/strong&gt;: 문제가 없는 것으로 확인된 버전 1.2와 문제가 있는 버전 2.1 사이에서 테스트를 진행합니다. 테스트 대상 버전은 1.3, 1.4, ..., 1.10, 2.1입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;이진 탐색 적용&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;전체 버전 리스트(1.3 ~ 2.1, 총 9개 버전)에서 중간 지점에 가까운 버전을 선택합니다. 예를 들어, 1.7(대략 중간)을 테스트합니다.&lt;/li&gt;
&lt;li&gt;버전 1.7에서 문제를 테스트:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;문제가 있으면&lt;/strong&gt;: 문제가 1.3 ~ 1.7 사이에 처음 발생했을 가능성이 있으므로, 이 범위로 범위를 좁힙니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;문제가 없으면&lt;/strong&gt;: 문제가 1.8 ~ 2.1 사이에 발생했을 가능성이 있으므로, 이 범위로 범위를 좁힙니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;좁혀진 범위에서 다시 중간 지점의 버전을 선택하여 테스트를 반복합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;종료 조건&lt;/strong&gt;: 문제가 있는 버전과 없는 버전이 인접한 두 버전(예: 1.x와 1.x+1)으로 좁혀질 때까지 반복합니다. 이로써 문제가 처음 도입된 버전을 정확히 식별할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;세부 절차&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;테스트 환경 준비&lt;/strong&gt;: 각 버전을 테스트할 수 있는 일관된 환경(동일한 하드웨어, OS, 데이터 등)을 구축하여 변수 통제를 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;문제 재현&lt;/strong&gt;: 버전 2.1에서 확인된 문제를 정확히 재현할 수 있는 테스트 케이스를 준비합니다. 문제의 재현 조건(입력값, 사용자 행동 등)을 명확히 정의합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;버전별 테스트&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;선택한 버전(예: 1.7)을 설치하고 테스트 케이스를 실행하여 문제가 발생하는지 확인합니다.&lt;/li&gt;
&lt;li&gt;결과를 기록하고, 문제 발생 여부에 따라 범위를 반으로 나눠 다음 테스트 버전을 선택합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결과 분석&lt;/strong&gt;: 문제가 처음 발생한 버전을 찾은 후, 해당 버전과 직전 버전(문제가 없는 마지막 버전)의 변경 로그, 코드 차이점(diff)을 분석하여 문제의 원인을 추적합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;예시 시나리오&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;버전 리스트: [1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 2.1]&lt;/li&gt;
&lt;li&gt;1단계: 중간 버전 1.7 테스트
&lt;ul&gt;
&lt;li&gt;문제가 있음 → 다음 범위: 1.3 ~ 1.7&lt;/li&gt;
&lt;li&gt;문제가 없음 → 다음 범위: 1.8 ~ 2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2단계: 새 범위에서 중간 버전(예: 1.5 또는 1.9) 테스트
&lt;ul&gt;
&lt;li&gt;이 과정을 반복하여 범위를 좁힙니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최종적으로 문제가 1.9에서 없고 1.10에서 처음 발생했다고 가정하면, 1.10의 변경 사항을 분석합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;효율성&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이진 탐색 방식은 최대 약 log₂(9) ≈ 4번의 테스트로 문제의 원인이 된 버전을 찾을 수 있습니다(최악의 경우).&lt;/li&gt;
&lt;li&gt;무작위로 모든 버전을 테스트하는 대신 체계적으로 범위를 줄여 시간과 자원을 절약합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;추가 고려사항&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;변경 로그 확인&lt;/strong&gt;: 가능하다면 각 버전의 변경 로그를 미리 검토하여 코드 변경, 새 기능 추가, 버그 수정 등을 파악하면 문제 원인을 좁히는 데 도움이 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동화 테스트&lt;/strong&gt;: 문제가 명확히 재현 가능한 경우, 자동화된 테스트 스크립트를 작성하여 각 버전에서 빠르게 테스트할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;병렬 테스트&lt;/strong&gt;: 리소스가 충분하다면, 여러 버전을 병렬로 테스트하여 시간을 단축할 수 있습니다(예: 1.5와 1.9를 동시에 테스트).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;환경 일관성&lt;/strong&gt;: 버전 간 차이로 인한 오탐지를 피하기 위해 테스트 환경을 항상 동일하게 유지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;다음 단계&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;문제가 처음 발생한 버전을 찾은 후, 해당 버전에서 추가된 기능, 수정된 코드, 또는 종속성 변경(라이브러리 업데이트 등)을 분석합니다.&lt;/li&gt;
&lt;li&gt;코드 디버깅, 로그 분석, 또는 단위 테스트를 통해 문제의 근본 원인을 파악합니다.&lt;/li&gt;
&lt;li&gt;필요하면 개발 팀과 협력하여 수정 패치를 개발하고, 문제가 해결되었는지 확인하기 위해 후속 버전(예: 2.2)에서 테스트합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;주의점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;문제 재현성&lt;/strong&gt;: 테스트 케이스가 2.1에서 문제를 확실히 재현할 수 있는지 확인하세요. 재현이 불확실하면 결과가 왜곡될 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;버전 간 종속성&lt;/strong&gt;: 일부 버전은 특정 라이브러리나 환경 설정이 달라질 수 있으므로, 설치 시 오류가 발생하지 않도록 주의하세요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;문서화&lt;/strong&gt;: 각 테스트 결과를 상세히 기록(버전, 문제 발생 여부, 테스트 조건 등)하여 추후 분석에 활용하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;결론&lt;/h3&gt;
&lt;p&gt;이진 탐색 기반의 테스트 전략은 최소한의 테스트로 문제를 처음 도입한 버전을 효율적으로 찾을 수 있는 방법입니다. 버전 1.7을 시작으로 테스트를 진행하고, 결과를 바탕으로 범위를 좁혀가며 문제를 식별하세요. 문제가 발생한 버전을 찾은 후에는 변경 로그와 코드를 분석하여 원인을 파악하고 해결 방안을 마련하면 됩니다. 추가 질문이 있다면 말씀해주세요!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[코딩] 초보 코더 탈출을 위한 꿀팁, 최소 가시성]]></title><description><![CDATA[코드를 머지하려고 보면 참 기분 좋은 경우가 있는가 하면, "이게 뭐지?!" 하는 생각이 절로 드는 경우도 있다. 내가 코드를 보면서 초보와 초보가 아님을 가르는 가장 큰 기준 중 하나가 바로 '가시성(Visibility)', 즉 '스코프(Scope…]]></description><link>https://jiniya.net/2025/07/minimum-visibility/</link><guid isPermaLink="false">https://jiniya.net/2025/07/minimum-visibility/</guid><pubDate>Wed, 02 Jul 2025 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;코드를 머지하려고 보면 참 기분 좋은 경우가 있는가 하면, &quot;이게 뭐지?!&quot; 하는 생각이 절로 드는 경우도 있다. 내가 코드를 보면서 초보와 초보가 아님을 가르는 가장 큰 기준 중 하나가 바로 &apos;가시성(Visibility)&apos;, 즉 &apos;스코프(Scope)&apos;다.&lt;/p&gt;
&lt;p&gt;스코프란 프로그램 전체에서 해당 변수나 함수가 어디까지 노출될지를 결정하는 거라고 보면 된다. 이런 설정이 잘 된 코드는 일단 기본기가 탄탄하다는 느낌을 주지만, 이게 엉망인 코드는 보는 내내 불안감과 의문을 던져준다.&lt;/p&gt;
&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;요즘 많이 쓰는 파이썬 코드로 시작해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;global_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;           &lt;span class=&quot;token comment&quot;&gt;# 1. 전역 변수&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OneBigBeautifulClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  class_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;# 2. 클래스 변수&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;member_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 3. 인스턴스 변수&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    local_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b    &lt;span class=&quot;token comment&quot;&gt;# 4. 지역 변수&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; local_variable&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기엔 크게 4가지 변수가 있다. &lt;code class=&quot;language-text&quot;&gt;global_variable&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;class_variable&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;member_variable&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;local_variable&lt;/code&gt;이 그것이다. 순서대로 스코프 범위가 넓다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;전역 변수&lt;/strong&gt;: 이 코드 전체, 어디서든 참조할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;클래스 변수&lt;/strong&gt;: 인스턴스와 관계없이 해당 클래스 전체에서 참조된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;인스턴스 변수&lt;/strong&gt;: 생성된 인스턴스로 범위가 제한된다. (&lt;code class=&quot;language-text&quot;&gt;self.&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;지역 변수&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;plus&lt;/code&gt; 함수 내에서만 목숨이 붙어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;이 코드를 보면 간단한 원리를 발견할 수 있다. 대체로 넓은 범위의 변수는 좁은 범위의 변수 기능을 대체할 수 있다는 점이다. 즉, 전역 변수로 지역 변수가 할 일을 시켜도 코드는 일단 돌아간다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# [예시 1] 일단은 문제 없이 동작한다&lt;/span&gt;
global_variable2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OneBigBeautifulClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;global&lt;/span&gt; global_variable2
    global_variable2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; global_variable2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 그 반대는 안 된다. 지역 변수가 전역 변수를 대체할 수는 없다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# [예시 2] 당연히 동작하지 않는다&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OneBigBeautifulClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    local_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; local_variable

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;local_variable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 에러 발생&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;넓은 범위로 확장이 가능하기에, 초보 코더가 작성한 코드를 보면 필요 이상으로 스코프를 크게 잡는 문제가 생긴다. 지역 변수로 써도 될 것을 굳이 멤버 변수로, 클래스 변수로, 심지어 전역 변수로 쓰는 것이다.&lt;/p&gt;
&lt;p&gt;&quot;돌아가면 장땡 아니냐?&quot; 할 수 있다. 하지만 변수든 함수든 범위가 넓다는 건 그만큼 조심해야 할 게 많다는 의미다. 집 안에서는 알몸으로 돌아다녀도 뭐라 할 사람이 없지만, 집 밖으로 나올 때는 주의해야 하는 거랑 같은 원리다. 스코프가 넓은 변수는 여기저기서 의도치 않게 건드려질 수 있는 위험에 항상 노출된다.&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;초보 티를 벗기 위해 명심해야 할 한 가지는 최소 가시성 원칙이다. 내가 만들 변수나 함수의 가시성은 &apos;최소한&apos;이 되도록 설정하면 대체로 그게 맞다는 말이다.&lt;/p&gt;
&lt;p&gt;전역 변수를 썼는데 생각해보니 지역 변수로도 될 것 같다? 그럼 지역 변수로 바꾸는 게 맞다. 멤버 변수(&lt;code class=&quot;language-text&quot;&gt;self.변수&lt;/code&gt;)로 썼는데, 한 함수 안에서만 쓰고 만다? 그럼 지역 변수로 하는 게 맞다.&lt;/p&gt;
&lt;p&gt;아래 코드를 보자. &lt;code class=&quot;language-text&quot;&gt;self.member_variable&lt;/code&gt;은 오직 &lt;code class=&quot;language-text&quot;&gt;plus&lt;/code&gt; 함수 안에서만 사용된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OneBigBeautifulClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;member_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;member_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;member_variable&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이럴 땐 굳이 인스턴스 전체가 공유하는 멤버 변수로 둘 필요가 없다. 아래처럼 바꾸는 것이 훨씬 안정적이고 좋은 코드다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# [더 좋은 코드]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OneBigBeautifulClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;pass&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    local_variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b &lt;span class=&quot;token comment&quot;&gt;# plus 함수에서만 쓸 변수이므로 지역 변수로&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; local_variable&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 변수의 스코프를 필요한 만큼만 최소한으로 부여하는 습관, 이것만으로도 코드의 품질은 훨씬 좋아진다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 6월의 잡담]]></title><description><![CDATA[#0 살아보니 인생도 가치투자랑 비슷해서 얼마나 멋진 선택을 많이 하느냐보단 멍청한 선택을 줄이는 게 더 중요한 것 같다. 특히 궤멸적 타격을 조심해야 한다. 투자도 곱하기…]]></description><link>https://jiniya.net/2025/06/small-talk-2025-06/</link><guid isPermaLink="false">https://jiniya.net/2025/06/small-talk-2025-06/</guid><pubDate>Mon, 30 Jun 2025 13:54:38 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;살아보니 인생도 가치투자랑 비슷해서 얼마나 멋진 선택을 많이 하느냐보단 멍청한 선택을 줄이는 게 더 중요한 것 같다. 특히 궤멸적 타격을 조심해야 한다. 투자도 곱하기 0 한방에 나락갈 수 있는 것처럼 인생도 어떤 문제들은 한 번 실수로 돌이킬 수 없는 지경이 되기도 한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;─ 여길 스타트업이라고 할 수나 있는 거야? 아무리 봐도 스타트만 있고 업이 없는데.&lt;br&gt;
─ 오호호, 오죽하면 스타트업의 ‘업’은 ‘UP’이 아니고 업보의 ‘업(業)’이라는 말이 있겠어.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;언러키 스타트업, 정지음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;─ 대표님이 다음 달부터 대리 달아 준다고 했대요. 비밀인데 저한테만 알려 준다면서, 그렇게 부르라던데요.&lt;/p&gt;
&lt;p&gt;─ ……웃기고 자빠졌네, 직함이 발렛파킹도 아니고 미리 부르라는 건 또 뭐야?&lt;/p&gt;
&lt;p&gt;나는 마지못해 감사하단 대답을 웅얼거렸다.&lt;/p&gt;
&lt;p&gt;직장인의 ‘감사합니다’는 때로 경멸의 뜻이기도 했지만, 대표들은 늘 그것을 몰랐다. 몰라도 돼서 몰랐고, 모르는 게 나으니까 몰랐고, 실제로도 그냥 몰랐다.&lt;/p&gt;
&lt;p&gt;그러나 나는 나보다도 시간을 믿는다. 인생은 절대로 고이지 않는다. 인생이 고이는 종류의 속성이었다면 애초부터 내가 국제마인드뷰티콘텐츠그룹으로 흐를 일도, 그곳을 스스로의 힘으로 나올 일도 없었을 것이다. 아직 괜찮지 않다면 시간이 더 흘러야만 한다는 뜻이었다.&lt;/p&gt;
&lt;p&gt;간만에 빵 터지며 읽었다. 이 땅의 수많은 대표님들께 헌정해야하는 책이 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;모쏠에게 연애 비법 배우는 만큼이나 고액 연봉이 아닌 사람이 말하는 연봉 많이 받는 법 같은 건 공허한 메아리가 아닌가 싶다. 100배 주식 찾는 법, 100억 조기 퐈이어 방법 등등의 자매품도 마찬가지. 그걸 성취한 사람들이 하는 말도 가려 듣는게 여러모로 좋다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;투자를 안하는 사람들과 얘기 해보면 현금도 하나의 포지션이라는 사실을 잘 모른다. 집을 사지 않고 전세 사는 거도 하나의 포지션. 전세 살고 현금 가지고 있으면 중립이라 생각하는데 실상은 디플레이션에 베팅하고 있는 상태에 가깝다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;버지니아 울프의 어느 작가의 일기가 절판되서 중고로 웃돈을 주고 구매했는데 서울대학교 전기공학부 해동학술정보실에 비치됐던 걸로 보이는 책이 왔다. 장물인건가? 심지어 중고 서점이 서울대 지근거리 신림동. 찝찝해서 문의 남김.&lt;/p&gt;
&lt;p&gt;오래된 일기를 다시 읽으면서 생각하는 것이지만, 가장 중요한 것은 검열자로서의 역할을 다하는 것이 아니라, 마음 내키는 대로 아무거나 쓰는 것이다. 내가 별생각 없이 써 놓았던 것 중, 쓸 당시에는 전혀 눈에 띄지 않았던 곳에서 의미를 발견하고, 묘한 기분이 들기 때문이다. - 어느 작가의 일기&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;1778년 8월 13일&lt;br&gt;
사람에겐 다섯 가지 큰 욕망이 있으니, 맘에 드는 남녀를 만나는 것, 맛있는 음식을 먹는 것, 과거에 합격해 벼슬아치가 되는 것, 재물을 많이 얻는 것, 맘에 맞는 취미 생활을 하는 것 등이 그것이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;일기를 쓰다, 유만주&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그때나 지금이나 인간의 욕망이 하나도 변하지 않은 것 같아 신기하다. 247년이란 세월이 무색할 지경.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;암만 모냥 빠지고 추저분해 보여도 살자고 하는 짓은 다 용감한 거야  - 미지의 서울 ep.04&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;[잡기] 조선의 과거 시험 경쟁률은?! (feat. 흠영) &lt;a href=&quot;https://jiniya.net/2025/06/korean-imperial-exam/&quot;&gt;https://jiniya.net/2025/06/korean-imperial-exam/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;국장 약간 인간지표 느낌이 드는게 엘베에서 사람들이 국장 종목 얘기를 시작함. 주식 안한다던 애들이 국장에 돈 넣기 시작함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;&quot;모든 게 잘 풀린다면 우리 회사가 얼마나 커질 수 있을 거라고 생각해?&quot;&lt;br&gt;
&quot;프로그래머를 서른다섯 명쯤 둔 회사 정도는 되지 않을까.&quot;&lt;br&gt;
나는 빌의 대답이 굉장히 야심 찬 계획이라는 생각이 들었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;아이디어맨, 폴 앨런&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;마이크로소프트는 지난 달에 6천명 가까이 해고했고, 2400명인 40% 정도가 소프트웨어 엔지니어링 분야였다고 한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;당근을 하면 돈이 들어온다는 기쁨보다는 물건이 없어진다는 즐거움이 더 크다. 그리고 올려보면 사람들이 실제로 뭘 더 필요로 하는지가 보여짐. 비쌀거 같은데 결국 나눔해야 하는 것도 있고, 쓰레긴줄 알았는데 날개 달린 듯이 팔리는 것도 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;정규직이라고 대놓고 빨대 꼽고 월급 루팡하려는 직원이나 네카라쿠배도 아닌데 육각형 직원 원하는 회사나 다들 염치가 없긴 마찬가지 아닌가 싶다. 자신을 알기가 이렇게나 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;주식은 최대 손실은 원금인데, 상방은 무한하기 때문에 본질적으로 비대칭적인 구조다. 채용도 비슷하다. 한 명 잘못 뽑으면 회사가 하루아침에 망할수도 있지만, 제갈량, 여포를 뽑아도 극적으로 좋아지는 일은 드물다. 그러니 채용은 인재를 놓치더라도 최악의 선택을 피하는 것이 훨씬 더 중요하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;어릴 때는 매주 로또 당첨되는 그런 일들로 도파민 뿜어져 나오는 인생을 꿈꿨는데, 나이가 들수록 그저 무탈하면 고맙다. 무심하게 별 일 없는 하루를 보낼 수 있어 참 다행이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;&quot;공정&quot;이란 객관적 잣대라기 보다는 합의된 룰을 일관되게 적용하는 신뢰의 문제에 가깝다. 룰은 투명하게 공개돼야 하고, 예외 대상 없이 일관되게 적용해야 한다. 또 룰은 조직 내에서 어떤 방식으로든 합의된 것이어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;간만에 엄청난 삽질. 인공지능 붙들고 어제 종일 사투를 벌였지만 아직도 미해결. 다만 그 과정에 리눅스 커널에 대해서 많이 알게됐다는 게 그나마 위안. 마지막 퍼즐 조각 하나만 알아내면 될 거 같은데 그게 어디 숨었는지 알수가 없다. 인공지능fud로 난리지만 여전히 해결 안되는 문제들도 많다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;(매미가) 땅 위로 나와서는 겨우 한달 남짓 산대요. 가끔은 궁금해요. 한달간의 생이 존재한다면, 나는 누구를 가장 먼저 기억하고, 누구를 가장 마지막으로 떠올릴지. - 두고 온 여름, 성해나&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;사실 내 또래 it 바닥에 있는 사람들은 운이 좋았던 건 맞다고 본다. 졸업 당시 분위기는 남들 쳐다보지 않는 저평가 분야라 경쟁이 낮았고, 이후 꾸준히 구조적 성장이 이뤄지면서 지금은 남들이 가고 싶어하는 회사가 됐음. 심지어 노동법 버프 까지. 눈떠보니 인생 가치투자한게 되버린 셈.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;프론트, 백엔드 논쟁이 뜨거운데, 연역적으론 그런거 따지지 말고 입금해 주는거 하자는 주의고, 귀납적으론 백엔드가 롱런하는 경우를 많이 봤다. 이유는 난이도 보다는 프론트보다는 덜 변하기 때문이 아닌가 추측. 저커버그가 1억불 준다면 뒤도 안보고 갈아탈거 너무 에고 투영하지 말자.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-06-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[잡기] 조선의 과거 시험 경쟁률은?! (feat. 흠영)]]></title><description><![CDATA[최근에 18세기 조선의 양반 유만주가 쓴 흠영이라는 책을 읽게 됐다. 이 책은 몇가지 점에서 몹시 인상 깊었는데, 1) 저자가 쓴 일기를 모은 책인데 20살부터 13년 동안 거의 매일이 기록돼 있다는 점,…]]></description><link>https://jiniya.net/2025/06/korean-imperial-exam/</link><guid isPermaLink="false">https://jiniya.net/2025/06/korean-imperial-exam/</guid><pubDate>Tue, 10 Jun 2025 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;최근에 18세기 조선의 양반 유만주가 쓴 흠영이라는 책을 읽게 됐다. 이 책은 몇가지 점에서 몹시 인상 깊었는데, 1) 저자가 쓴 일기를 모은 책인데 20살부터 13년 동안 거의 매일이 기록돼 있다는 점, 2) 유명인사가 아닌 철저하게 일반인인 저자가 작성했다는 점. 유만주는 양반이긴 했으나 음서제로 관직에 진출할만큼의 좋은 집안은 아니었고, 그렇다고 과거에 급제할만큼 뛰어난 사람도 아니었다. 3) 18세기 조선이라면 꽉 막힌 세상일 것 같은데 생각외로 유만주의 생각들은 요즘 생각과 별반 차이가 없는 것들이 더러 있다는 점. 4) 서로 다른 시간대의 비슷한 공간을 가진 사람으로써 기호와 취향이 비슷하다는 점 등이 그것이다. 어쨌든 간만에 아주 재미있는 책이었고, 이 자리를 빌어 이 책을 추천해준 ChatGPT 4o에게 심심한 감사를 전한다.&lt;/p&gt;
&lt;p&gt;책의 주된 내용 중 하나가 유만주가 조선의 과거 시험에 대한 어려움과 방식에 대한 불만을 토로하는 점이다. 책을 읽어보면 알겠지만 유만주 개인도 책과 독서를 애정하는 사람이며, 글을 보면 글도 매우 잘 작성하는 사람임을 알 수 있다. 그럼에도 그는 평생을 과거 시험에 메달렸지만 급제하지 못하고 34살의 나이로 요절했다.&lt;/p&gt;
&lt;p&gt;책을 읽다가 문득 궁금증이 생겼다. 이렇게 책 좋아하고 똑똑해 보이는 사람도 합격이 힘들다면 조선시대 과거 시험은 도대체 경쟁률이 어떤 수준이었을까? 그래서 찾아봤다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“21일의 경과는 3곳으로 나누어 치렀는데 총 응시자는 11만1838명에 달했고, 시권(답안지)를 바친 자는 모두 3만8614명이었다. 다음날의 인일제 응시자는 모두 10만3579명이었고, 시권을 바친 자는 3만2884명이었다…”(&amp;#x3C;정조실록&gt; &amp;#x3C;홍재전서&gt;)&lt;/p&gt;
&lt;p&gt;이틀간 답안지를 제출한 응시생만 해도 7만1498명에 달했는데요. 그중 첫날의 경과를 통해 10명, 이튿날 인일제에서 2명의 합격자가 선발되었으니 어떻습니까.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.khan.co.kr/article/202111220603001&quot;&gt;https://www.khan.co.kr/article/202111220603001&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이건 정조때(1800년) 세자 책봉을 기념해서 치러진 안일제라는 특별 과거 시험의 경쟁률이다. 첫날만 보면 10명이 뽑혔는데 지원자가 111,838명이다. 0.008% 합격률. 통상의 조선의 과거 시험은 3년에 한 번 치러지고 최종 대과 합격자는 33명을 뽑았다고 한다. 대략 지원자를 10만명으로 퉁친다면 0.033% 정도 되겠다. 사실 이정도로는 어느 정도 수준인지 감이 잘 오지 않는다. 2025학년도 대학수학능력시험에 응시자 수는 392,783명이고, 서울대학교 의대 정시 정원이 42명이다. 0.01%, 연대, 고대까지 포함하면 135명으로 0.034%다. 결국 조선 시대 과거 시험은 대략 서연고 의대 정시로 갈만큼 어려웠다고 볼 수 있겠다.&lt;/p&gt;
&lt;p&gt;실제 인물을 통해서 그 극악 난이도를 알 수 있는데, 지폐에서 흔히 보는 퇴계 이황 선생님 께서도 과거에 3번 낙방하고 대과에 처음 급제한 건 34살의 나이였다고 한다. 열하일기로 유명한 연암 박지원 선생은 과거 시험은 많이 쳤지만 급제한 적이 없다. 모두 낙방해서 결국은 음서제(집안빨 등용)로 관직에 진출했다고 한다. 9번 장원급제했다고 알려진 불세출의 천재 율곡 이이도 대과를 9번 장원급제한게 아니다. 대과를 가는 길에 있는 소과를 포함해 모두 9번 장원 급제한 것이고, 처음 대과를 급제한 29세 전인 23세 시험에서는 대과에서 낙방했다.&lt;/p&gt;
&lt;p&gt;그러다 다시 의문이 들었다. 조선이란 나라는 당췌 3년에 33명 뽑아서 관직을 주면 도대체 나라가 어떻게 돌아갔다는 말인가? 빈 자리가 이렇게 안나왔던 것일까, 라는 생각이 들었다. 정년이 없었다해도 죽는 사람이 있으니 자리는 계속 생길텐데 이렇게 조금 뽑아서 그게 유지가 됐냐는 생각. 그래서 조금 더 검색해보다 충격적인 사실을 접했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;대과에 급제한 33명 모두 관직을 받은 건 아니었다. 우수 3명에게만 관직을 부여하고, 나머지 인원은 합격증과 어사화 정도 주고 퉁쳤다.&lt;/li&gt;
&lt;li&gt;총 관직수 5605직이었지만, 은퇴자를 위한 자리 3110직, 돈안주는 자리 95직, 실질 자리수는 2400직, 그 중 문관직 1779직이 거의 전부였다고 한다. 이 몇 개 안 남는 자리를 서로 차지하기 위해서 싸운게 당파싸움의 실질 원인 중 하나였다고 한다.&lt;/li&gt;
&lt;li&gt;그러니 실질 확률은 0.033%의 1/11인 0.003%라고 할 수 있다.&lt;/li&gt;
&lt;li&gt;이런 말도 안되는 난이도의 과거 시험에 모든 양반이 목메단 이유도 있었는데, 다름 아닌 3대 동안 과거 급제자가 한명도 안나오면 양반을 박탈하고 양인으로 강등시켰기 때문.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.paju.go.kr/news/user/BD_newsView.do?q_ctgCd=1002&amp;#x26;newsSeq=419&quot;&gt;https://www.paju.go.kr/news/user/BD_newsView.do?q_ctgCd=1002&amp;#x26;newsSeq=419&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;예나 지금이나 하는 일 없이 밥그릇만 차지하고 있는 사람들은 늘 있는 것 같다. 실질 관직이 2400직인데, 은퇴자를 위한 자리가 3110직이니 말이다. 조선이 500년 더 유지됐다면 아마 6000직은 됐을듯한?! 그리고 조선 시대를 살아남은 양반 가문이라면 자부심을 가져도 될 법 하겠다. 3대에 걸쳐 서연고 의대로 정시 한 명은 합격 시켰다는 의미가 될테니 말이다.&lt;/p&gt;
&lt;p&gt;퇴계 이황 선생님이 34살의 나이게 과거에 처음 급제했다는 걸 보면 유만주는 너무 일찍 요절한 건 아닌가라는 생각이 든다. 그럼에도 그의 책을 보면 그가 더 살았더라도 아마 과거에 급제하지는 못했을 거란 생각도 든다. 왜냐하면 그 또한 묘하게 반골 기질이 있기 때문이다. 시험을 위한 시험, 공부를 위한 공부가 무슨 의미가 있냐는 한탄을 그의 글 곳곳에서 발견할 수 있다. 실질적으로 그는 과거 시험을 위한 공부 자체에는 별 흥미가 없었을 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 5월의 잡담]]></title><description><![CDATA[#0 너한테 배운거야, 마이크. 규칙 제1조라고 했잖아. 이길 수 없다고 판단되는 패는 당장 버려라. - 라운더스, 1998 2025-05-03 #…]]></description><link>https://jiniya.net/2025/05/small-talk-2025-05/</link><guid isPermaLink="false">https://jiniya.net/2025/05/small-talk-2025-05/</guid><pubDate>Tue, 27 May 2025 22:07:49 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;너한테 배운거야, 마이크. 규칙 제1조라고 했잖아. 이길 수 없다고 판단되는 패는 당장 버려라. - 라운더스, 1998&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;가슴이 좀 벌렁벌렁해야 돈을 따시지. 베팅을 안 하면 한 방도 없어요. ... 개천에서 진짜 용이 날라면 개천은 죽어나야 되는 거니까. - 폭싹 속았수다, ep07&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;뒤늦게 영화 서브스턴스를 봤는데, 뜬금없게도 좀 더 신중하게 살아야겠다는 생각이 들었다. 1년 후, 10년 후의 내가 지금 실행된 어떤 선택들로 고통받지 않도록. 특히 오랜 시간에 걸쳐서 영향을 미치는 선택들은 더 조심해야겠다. 쓸데없이 몹시 교훈적인 영화였다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;내가 외줄을 탈 때마다 아빠는 그물을 펼치고 서 있었다. 떨어져도 아빠가 있다. 그 한 마디가 얼마나 든든했는지. 한 번은 말해 줄 걸 - 폭싹 속았수다 ep13&lt;/p&gt;
&lt;p&gt;개인적으로 내용보다 아이유 나레이션이 하드 캐리한 드라마가 아니었나 싶다. 젊은 날엔 젊음을 모르고 사랑할땐 사랑을 모른다. 좋은 것들은 죄다 지나간 후에야 좋았다는 걸 알게되는 요상한 세상. 모두 이번 생은 처음이라 그런 거겠지...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;대기업 입사를 위해 장기 취준생이 되는 건 반대지만, 가능한 선에서 가장 조건 좋은 곳에서 시작하는게 유리하다는 생각. 돈 포기하고 이직을 할지 말지는 내 선택의 문제지만, 그 선택을 할 때의 내 통장 잔고 차이는 몹시 크다. 심지어 인생은 복리. 초기 급여가 나중 급여보다 천만배 더 중요함. &lt;a href=&quot;https://t.co/ObUjK4C4rZ&quot;&gt;https://t.co/ObUjK4C4rZ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;귀납적으로 주변만 봐도 그때 대기업 갈 껄은 많지만, 괜히 대기업 갔다는 정말 1도 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;대체로 부정적인 의견이 많은듯. 나도 부정적으로 본다. 추격자들이 따라잡는 속도를 보면 openai에 과연 장기적 해자가 있을지 의문이 든다. ai 코딩 에디터는 결국 ms가 평정하지 않을까라는 생각. 댓글에도 나온 것처럼 vscode 플러그인들을 일부 잠그기 시작함. &lt;a href=&quot;https://x.com/GeekNewsHada/status/1919916612876173702&quot;&gt;https://x.com/GeekNewsHada/status/1919916612876173702&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;누군가와 이해관계가 얽히기 전에는 반드시 생각이 같은 방향으로 정렬된건지 점검이 필요하다. 두루뭉실하게 같은 생각이겠지, 라고 넘긴 경우 열에 아홉은 동상이몽. 정렬이 틀어진 걸 발견하면 그 즉시 이해관계를 해소하는게 비용이 제일 적다. 사람 생각이란게 생각보다 잘 안바뀌기 때문. &lt;a href=&quot;https://x.com/codemaru/status/1884101268731486329&quot;&gt;https://x.com/codemaru/status/1884101268731486329&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;패자부활전이 없다던 대한민국도 요즘 스타트업들 보면 분위기가 많이 바꼈다 싶다. 10년째 대규모 적자를 기록하며 투자로 연명해도 무탈하게 운영되는 걸 보면. 물론 쿠팡 얘기하면 할 말은 없다. 쿠팡 이후로 계획된 적자가 유행어가 된 듯한 느낌. 이래저래 쿠팡은 입지전적이긴 한듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;탭댄스까지 갈 필요도 없다. 양치질, 젓가락질 같이 매일 반복적으로 하는 행위들의 수준만 봐도 단순 시간 투입한다고 전문가가되는 건 아님. 저기서 말하는 시간은 의도적 수련 시간. 버핏의 견해와는 다르게 나는 그가 탭댄스를 1만 시간 수련하면 제법 괜찮은 아마추어 수준은 될거라 생각한다. &lt;a href=&quot;https://x.com/best181p/status/1919514011441443027&quot;&gt;https://x.com/best181p/status/1919514011441443027&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;유사한 사례로 버핏은 젊은 시절 대중 연설을 못했다고 한다. 그런 약점을 극복하기 위해서 데일카네기 연설 코스를 수료했고, 이후 그런 문제를 고쳤다함. 버핏의 영상을 보면 제법 대중 강연이 제법 자연스럽다. 물론 오바마에 비할 바는 아니지만. 괜찮은 아마추어 수준은 가능하지 않나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;연예인 할거도 아닌데 나이불문 성별불문 생각 이상으로 많은 사람들이 외모나 옷차림 같이 겉으로 드러나는 요소로 사람을 판단하는 경우가 많다는데 가끔 놀란다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;승부의 세계에서는 일류가 아닌 인생은 너무 서글픈 거거든 - 승부, 2025&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;&quot;C++는 대체될 수 있는 언어가 아니다&quot;며 &quot;우리가 진정으로 대체하려는 게 무엇인지 묻는다면 그건 언어가 아니라 개발자의 사고 체계일지도 모른다&quot; -- 대가도 에고를 내려놓긴 참 힘들다. 사람인지라. &lt;a href=&quot;https://zdnet.co.kr/view/?no=20250512100248&quot;&gt;https://zdnet.co.kr/view/?no=20250512100248&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;우리는 많은 종류의 위험을 피한다. 사기꾼이 경영하는 기업은 거르고, 턴어라운드 기업은 피하고, 레버리지와 가능한 멀리 떨어지고, M&amp;#x26;A 중독자를 무시하고, 빠르게 변화하는 산업을 예상하려 하지 않고, 주주의 이해관계에 부합하지 않는 소유주와는 함께 가지 않는다. - 투자, 진화를 만나다&lt;/p&gt;
&lt;p&gt;평균적으로 1종 오류를 피하는 것이 장기적으로 놀라운 성공을 낳기 때문에, 우리의 성공이 테슬라와 에이처를 편안한 마음으로 버리는 것에 달려 있다고 믿는다. 그리고 지금까지 그랬다.&lt;/p&gt;
&lt;p&gt;우리는 주가를 무시하고 기업의 질에 집중함으로써, 많은 고통을 겪지 않아도 됐다. 남녀 관계에 비유하자면, 결혼에 집중해서 가볍게 즐기는 만남을 피하려고 했다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;몇년째 지도 교수가 박사 논문을 통과시켜주지 않아 졸업을 못하는 친구의 하소연. 지도 교수도 읽지 않는 논문을 왜 쓰는지 모르겠다고. 톡 캡쳐를 보니 지도 교수가 자기 챗지피티가 검토한 내용이라고 수정 사항을 보냈다. 벌써 인간보다 인공지능에게 잘 보여야 하는 세상이 온건가 싶다.&lt;/p&gt;
&lt;p&gt;문과인데, 교수 표현이 재밌는게 내 챗이 검토한 내용입니다. 이럼. 니챗 내챗이 어딨냐는. 그거 때문에 자괴감에 빠진 친구는 나한테 니챗은 뭐라는지 봐달라고 ㅠㅜ 주화입마가 참 무섭다. 모델이랑 프롬프트를 주던가.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;뭐든지 임계 지점이 있는 게 아닌가 싶다. 모래알이 모래성을 만들다 어느 한알갱이부터 성이 무너져 내리는 것 같은 그런 지점. 그때부터는 대체로 비가역적인 상태가 된다. 돌아가기란 대체로 불가능하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;가만 있으면 중간은 간다는 옛말이 떠오르는 뉴스. 굳이 먼저 살 필요도 없겠지만, 먼저 팔 필요도 있었나 싶다.  &lt;a href=&quot;https://coinness.com/news/1128786&quot;&gt;https://coinness.com/news/1128786&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;어떤 산업에서든, 기업이 자신의 이름을 널리 알리려면 수십 년은 아니더라도 수년에 걸쳐 막대한 시간과 노력을 쏟아부어야 하기 때문에, 좋은 평판은 비용이 상당히 많이 소요되는 값비싼 신호고, 따라서 정직한 신호다. - 투자, 진화를 만나다&lt;/p&gt;
&lt;p&gt;평판을 쌓는 데는 20년이 걸리지만, 그것을 무너뜨리는 데는 5분이면 충분하다. 그 점을 생각해 보면 행동이 달라질 것이다. - 워렌 버핏&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;대표가 회사서 좀 놀면 안되나요? 라고 반문하던 기업이 여전히 한해도 안 거르고 성장 중이란 사실이 놀랍다. 인원은 거의 그대론거 같은데 생산성 무엇?! 너무 안놀고 열심히 해서 이모양인가 싶은 생각이 들기도 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-05-27&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 4월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2025/04/small-talk-2025-04/</link><guid isPermaLink="false">https://jiniya.net/2025/04/small-talk-2025-04/</guid><pubDate>Wed, 30 Apr 2025 10:12:37 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;사람들이 코딩만 박살나고 있는 줄 아는데 글쓰기, 음악, 그리기 다 위기다. 개인적인 느낌으론 글이랑 음악이 진도가 제일 빠르고 그담이 코딩이랑 그리긴듯. 글은 거의 완벽 그잡채, 음악은 더러 실수가 있어도 알기 어렵고, 그림은 아직 소소하게 손댈 곳이 있음. 지식 근로자의 총체적 위기다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;llm이 나의 개발 스타일을 바꾼 거 중에 하나가 문서화를 먼저 하게 됐다는 점. 근데 요새는 그거도 대략 요지만 던져주고 설계서 만들라고 하고 읽어보고 틀린거 있음 고치고, 없음 그거 그대로 넣어서 코딩하라고 하면 잘한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;우리 메인 저장소 readme에는 크레딧이 젤 길다. 현역이거나 지금까지 거쳐간 개빌자가 모두 나와 있다. 총 37명. 여기 인공지능 크레딧을 분리해서 추가했다. 이제 개발팀 전체 인원이 작성하는 코드의 합보다 인공지능 작성 분량이 많다는 게 누가봐도 명백하기 때문.&lt;/p&gt;
&lt;p&gt;총 7개의 모델이 거쳐갔다. 4, 4o, o1-preview, o3-mini-high, qwen2.5-coder-32b, qwq-32b, gemimi 2.5 pro. 얘들의 특이점은 가장 신입이 늘 가장 뛰어나다는 점.&lt;/p&gt;
&lt;p&gt;인공지능 크레딧에 대한 헌사는 gpt 4.5가 이렇게 썼다. -- 이 무한한 가능성의 여정을 함께한 인공지능 동료들!!! 여기 담긴 코드와 지식들은 과거와 현재, 수많은 인공지능들의 창의성과 노력 위에 세워져 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;사람들이 활기차 보이는 오후&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;향후 일자리 전망과 관련해 농업과 소셜을 예시로 든 부분이 인상적이다. &lt;a href=&quot;https://x.com/GeekNewsHada/status/1909784849092952367&quot;&gt;https://x.com/GeekNewsHada/status/1909784849092952367&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;딥리서치도 구글이 엄청 따라왔다. 사실 애초에 딥리서치야말로 구글이 못할수가 없는 분야긴 하지만.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;rust는 abi 안정화 작업이 절실하다. 최근에 rust로 개발하는 업체와 작업하는데 안정적으로 바이너리를 제공하려면 c abi를 선택하는 방법 외에는 없는듯. 그런데 c abi를 사용하면 rust 장점이 없다는 거. rust abi를 사용하려면 업체와 빌드 환경을 맞추는 방법외에는 없는듯하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;창업하고는 입금 코딩만 했는데, llm 덕에 다시 취미 코딩을 해본다. 그러면서 느낀점. 확실히 조금만 커져도 타입이 있는 편이 안정감 있다. 자바스크립트 바이브 코딩하다 코드가 완전 난장판되서 뭐가뭔지 알수가 없었는데, 그 코드를 단순히 타입스크립트로 변환했을 뿐인데 다시 관리 가능해짐.&lt;/p&gt;
&lt;p&gt;참고로 난 자바스크립트는 익숙하지만 타입스크립트는 처음 써 본 상황. 변환도 llm이 다해 주었다. 그럼에도 코드를 고치기가 타입스크립트가 훨씬 수월했다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;몇해전 퇴사한 직원이 작성한 코드를 유지보수하는데 코드에서 그가 겪었던 고뇌가 그대로 느껴진다. 이걸 내가 동작하게 만들고야 말겠다는 강력한 의지같은?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;정신에도 dna가 있다면 걔랑 나는 핏줄이야. - 하이퍼나이프 ep.08&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;직원들이 왜 인공지능을 안쓰지?!, 라는 생각을 많이 했는데. 결론은 그냥 검색이랑 같다는 생각이 들었다. 검색해보면 나오는거 안된다고 말하는거나 인공지능에 물어보면 나오는거 안된다고 말하는거나 메커니즘은 똑같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;복잡한 대상일수록 점진적으로 개선해야 한다. 한번에 너무 많이 바꾸려다간 대체로 중간에 실패함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;[pl] 객체지향 설계에서 상속보다 포함을 우선해야 하는 이유 &lt;a href=&quot;https://jiniya.net/2025/04/composition-over-Inheritance/&quot;&gt;https://jiniya.net/2025/04/composition-over-Inheritance/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;챗지피티 메모리 기능 업데이트 후에 유행하는 지금까지 대화 내용으로 나를 멋지게 표현해 달라는 요청을 해보았다. 기술과 창의가 만나는 지점에서 빛나는 디지털 폴리매스. 그런데 폴리매스가 뭔말인지 몰라 다시 물어봄.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;[pl] 현대 소프트웨어 개발에서의 진정한 코드 복잡성 분석 및 관리 전략 &lt;a href=&quot;https://jiniya.net/2025/04/code-complexity/&quot;&gt;https://jiniya.net/2025/04/code-complexity/&lt;/a&gt; 딸깍 딥리서치 수준 ㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;우리는 그래도 돼 - 보통의 가족, 별 생각 없이 틀었는데 쓸데없이 재밌었다. 싯다르타가 아들 이름을 라훌라로 지었다는 얘기가 생각나는 영화.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;llm 경쟁이 실로 치열하다. o1, o3다 3개월만에 퇴장. 다시 o4-mini-high로.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;솔직히 개발한정, 테스트와 책임질 사람만 남은게 아닌가 싶다. 최근 1년내 개발팀에 개발 업무를 지시한 적이 있나 싶다. 우리가 한 일은 대부분  인공지능이 짠 코드 테스트거나, 배포해도되는지 확인하는 작업이었다. &lt;a href=&quot;https://x.com/_jeyraof/status/1912822420563759286&quot;&gt;https://x.com/_jeyraof/status/1912822420563759286&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;o3-mini-high 이후로 저숙련 개발자에게 맡기던 사소한 코딩 작업들은 테스트할 필요도 없이 분단위로 완료된다. 그러니 개발로 취업하려는 신입에게는 생각보다 많이 가혹한 환경인지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;다같은 인공지능 쓰는데 차별성을 어떻게 만드냐는 글을 봤다. 우문인게 인공지능 전에도 다 같은 도구를 썼지만 차이는 극명했다. 미켈란젤로가 도구빨로 피에타를 조각한게 아니다. 도구는 도구일 뿐 주화입마에 빠지진 말자.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;여행을 가거나, 새로운 음식을 먹는 걸 경험이라고 하지만, 진짜 경험은 그런 소비의 역사라기보다는 &apos;극복의 역사&apos;라고 생각합니다. - 나는 솔로 ep.154&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;현실 세계에서 담당 개발자 퇴사하고 코드 잘짰다, 유지보수 편하다는 얘기를 들어본 적이 없다. 그러니 llm 너무 나무라지 말자. 오늘 에고 충만해서 직접 작성한 그 코드도 남들 눈엔 llm 짠 코드랑 도긴개긴 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;불변의 법칙이 떠오르는 글귀. 흘러간 세월이 얼만데 놀랍도록 지금 시대에도 그대로 적용되는 말들이 아닌가 싶다. &lt;a href=&quot;https://x.com/akzkfltm2/status/1914492208537018823&quot;&gt;https://x.com/akzkfltm2/status/1914492208537018823&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;미장 왠일로 오르는?! 럼프형이 조용한건가...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;구글이 45조 가량에 이스라엘 클러우드 보안 업체 위즈를 인수했다. 그런데 그 청구서가 우리에게 날아왔다. 기존 사용하던 보안 관련 서비스를 통합한다는 명분으로 가격 인상. 다른 기능 필요없데도 다 써야한다함. 견적서는 안왔지만 인터넷 검색시 기존 가격 대비 거의 4.5배 비싼듯한 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;아이들이 어른보다 대체로 행복한 이유 중에 하나는 뭐든 안좋은 일을 금방 잊기 때문이 아닌가 싶다. 그에 비해 어른들은 지독하게 잊지를 못한다. 망각은 정말 축복이다. 잊자. 나쁜 일들은.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;llm 쓰고 많이 공감하게 된 말. 최고의 복지는 좋은 동료다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;요즘 서울도 월세 계약하러 가보면 임차인이 전에 못보던 파키스탄, 우즈벡 이런데서 온 사람들이 보인다. 이전에는 그나마 외국인이라곤 중국 교포밖에 없었던 것 같은데 한국도 참 많이 변했다. 생각보다 빠르게 다문화 사회가 되고 있는지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;뭍에 잡혀 올라온 물고기가&lt;br&gt;
온몸을 던져&lt;br&gt;
바닥을 치듯이&lt;br&gt;
그렇게 절망이 온몸으로&lt;br&gt;
바닥을 친 적 있는지&lt;br&gt;
그물에 걸린 새가&lt;br&gt;
부리가 부러지도록&lt;br&gt;
그물눈을 찢듯이&lt;br&gt;
그렇게 슬픔이 온 존재의&lt;br&gt;
눈금을 찢은 적은 있는지&lt;br&gt;
살아 있다는 것은&lt;br&gt;
그렇게 온 생애를 거는 일이다&lt;/p&gt;
&lt;p&gt;실패해도 온몸을 내던져&lt;br&gt;
실패하는 일이다&lt;br&gt;
그렇게 되돌릴 겨를도 없이&lt;br&gt;
두렵게 절실한 일이다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;살아 있다는 것, 류시화&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-04-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;전세계에서 소프트웨어 개발 젤 잘한다고 평가받는 기업의 현실. 심지어 감원 중. &lt;a href=&quot;https://x.com/RealChickenBoy9/status/1915687125942685754&quot;&gt;https://x.com/RealChickenBoy9/status/1915687125942685754&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#29&lt;/h2&gt;
&lt;p&gt;리스펙 하는 교수님 중 한 분. 수업 시간에도 갑자기 맞춤법 뭐 떠오르면 돌려봐야겠다며 나중에 추가하고는 하셨던. 나라인포테크도 그때는 돈 없는 학생들 알바로 써서 학비도 많이 지원해주심. 모든 걸 떠나 최애할 수 밖에 없었던 이유. 출결 체크 없음. &lt;a href=&quot;https://x.com/pyodogi/status/1915935595903520814&quot;&gt;https://x.com/pyodogi/status/1915935595903520814&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#30&lt;/h2&gt;
&lt;p&gt;GPS 이전에 운전을 배운 아버지는 운전과 내비게이션을 동시에 처리하는 데 어려움을 겪음. 반면 GPS와 함께 운전을 배운 사람들은 내비게이션 지시를 처리하면서 운전을 관리하는 능력을 개발함. -- 등가교환인가? 미처 생각못한 흥미로운 관점. &lt;a href=&quot;https://x.com/ohyecloudy/status/1917217741968179469&quot;&gt;https://x.com/ohyecloudy/status/1917217741968179469&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-04-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[코딩] 현대 소프트웨어 개발에서의 진정한 코드 복잡성 분석 및 관리 전략]]></title><description><![CDATA[진정한 코드 복잡성이 뭔지 고민이 많다는 친구의 말에 심심해서 돌려본 딥리서치 자료.
현업에서 일하는 실무자의 관점에서는 사실 이건 포르노랑 비슷한 측면이 있다.
정의해서 측정하기는 어렵겠지만 보면 알 수 있다.
이게 복잡한 코드인지 아닌지?! I…]]></description><link>https://jiniya.net/2025/04/code-complexity/</link><guid isPermaLink="false">https://jiniya.net/2025/04/code-complexity/</guid><pubDate>Sun, 13 Apr 2025 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;진정한 코드 복잡성이 뭔지 고민이 많다는 친구의 말에 심심해서 돌려본 딥리서치 자료.
현업에서 일하는 실무자의 관점에서는 사실 이건 포르노랑 비슷한 측면이 있다.
정의해서 측정하기는 어렵겠지만 보면 알 수 있다.
이게 복잡한 코드인지 아닌지?!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I shall not today attempt further to define the kinds of material I understand to be embraced within that shorthand description [&apos;hard-core pornography&apos;]; and perhaps I could never succeed in intelligibly doing so. But I know it when I see it...&lt;br&gt;
&lt;br/&gt;
나는 오늘 그 약칭 표현 [‘하드코어 포르노’]에 포함된다고 여겨지는 자료의 종류를 더 이상 정의하려고 시도하지 않을 것이다. 아마도 나는 그것을 명확하게 정의하는 데 결코 성공하지 못할지도 모른다. 하지만 직접 보면 안다.&lt;br&gt;
&lt;br/&gt;
— Justice Potter Stewart, concurring opinion in Jacobellis v. Ohio, 378 U.S. 184 (1964)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;서론&lt;/h2&gt;
&lt;p&gt;소프트웨어 공학 분야에서 코드 복잡성을 이해하고 관리하는 것은 지속적인 과제이다. 특히 30년 이상 전에 정의된 전통적인 복잡성 측정 지표들이 현대 소프트웨어 개발 환경의 복잡다단한 현실을 제대로 반영하지 못한다는 인식이 확산되고 있다.1 새로운 프로그래밍 패러다임, 언어의 발전, 분산 아키텍처의 보편화 등은 코드의 구조적 측면뿐만 아니라 인지적 부하, 유지보수성, 시스템 전체의 상호작용 등 다양한 차원에서 복잡성을 야기한다.2&lt;/p&gt;
&lt;p&gt;본 보고서는 이러한 문제의식에 기반하여 &apos;진정한&apos; 코드 복잡성의 다면적 본질을 심층적으로 분석하고자 한다. 먼저 순환 복잡도(Cyclomatic Complexity)와 코드 라인 수(Lines of Code)와 같은 전통적인 측정 지표의 정의와 한계를 비판적으로 검토한다. 이어서 인지 복잡성(Cognitive Complexity), 유지보수성(Maintainability), 가독성(Readability), 테스트 용이성(Testability) 등 현대적인 관점에서 복잡성을 재조명한다. 또한, 마이크로서비스와 모놀리식 아키텍처, 디자인 패턴, 코드 의존성 및 결합도와 같은 시스템 수준의 요인들이 복잡성에 미치는 영향을 분석한다. 나아가 문제 영역 자체의 본질적 복잡성(Essential Complexity)과 개발 과정에서 발생하는 우발적 복잡성(Accidental Complexity)을 구분하고, 이러한 다양한 관점을 종합하여 오늘날 코드 복잡성을 구성하는 요소들에 대한 다각적인 이해를 구축한다. 최종적으로, 현대 소프트웨어 개발 환경에서 코드 복잡성을 효과적으로 관리하기 위한 실용적인 전략과 모범 사례를 제시하는 것을 목표로 한다. 이는 단순히 과거 지표의 부적절함을 지적하는 것을 넘어, 현대 소프트웨어의 특성을 반영하는 복잡성에 대한 깊이 있는 통찰과 실질적인 관리 방안을 모색하는 과정이 될 것이다.&lt;/p&gt;
&lt;h2&gt;I. 전통적 관점: 순환 복잡도와 코드 라인 수&lt;/h2&gt;
&lt;p&gt;소프트웨어 복잡성을 정량화하려는 초기 시도는 주로 코드의 구조적 특성에 초점을 맞추었다. 대표적인 지표인 순환 복잡도와 코드 라인 수는 수십 년간 널리 사용되어 왔으며, 특정 측면에서 유용성을 인정받았다.&lt;/p&gt;
&lt;h3&gt;가. 순환 복잡도(Cyclomatic Complexity, CC): 기원, 원리, 목적&lt;/h3&gt;
&lt;p&gt;순환 복잡도는 1976년 Thomas J. McCabe, Sr.에 의해 개발된 정량적 소프트웨어 메트릭이다.4 이는 프로그램 소스 코드를 통한 선형적으로 독립적인 경로의 수를 측정하여 프로그램의 복잡성을 나타낸다.4 McCabe는 모듈화의 정량적 기반을 제공하고 테스트하거나 유지보수하기 어려운 소프트웨어 모듈을 식별할 수 있는 수학적 기법의 필요성을 인식했다.7&lt;/p&gt;
&lt;p&gt;순환 복잡도는 제어 흐름 그래프(Control Flow Graph)를 사용하여 시각화될 수 있으며, 여기서 노드는 명령어 블록을, 엣지는 제어 흐름을 나타낸다.6 계산 공식은 일반적으로 M = E - N + 2P (E: 엣지 수, N: 노드 수, P: 연결된 컴포넌트 수)로 표현되거나, 단일 진입점과 단일 탈출점을 가진 구조적 프로그램의 경우 M = 결정 지점(Decision Points) 수 + 1로 단순화될 수 있다.4 예를 들어, 단일 조건의 if 문은 두 개의 경로(참/거짓)를 생성하므로 복잡도는 2가 되며, 중첩된 if 문이나 두 개의 조건을 가진 if 문은 복잡도 3을 생성한다.4 McCabe는 원래 1-10은 단순하고 위험이 적음, 11-20은 더 복잡하고 중간 정도 위험, 21-50은 복잡하고 높은 위험, 50 초과는 테스트 불가능하고 매우 높은 위험으로 분류했으며, 이 임계값은 여전히 참조된다.4&lt;/p&gt;
&lt;p&gt;McCabe의 주된 목적은 테스트 및 유지보수가 어려운 모듈을 식별하는 것이었다.4 특히 순환 복잡도는 필요한 최소 테스트 케이스 수, 즉 모든 실행 경로를 최소 한 번 이상 커버하기 위해 필요한 테스트 수를 나타내는 지표로 강하게 연관되어 테스트 노력과 밀접한 관련이 있다.5&lt;/p&gt;
&lt;h3&gt;나. 코드 라인 수(Lines of Code, LOC): 크기의 척도, 반드시 복잡성은 아님&lt;/h3&gt;
&lt;p&gt;코드 라인 수(LOC 또는 SLOC)는 소스 텍스트의 라인 수를 세어 소프트웨어의 크기를 측정하는 가장 기본적인 방법이다.10 주석이나 빈 줄을 포함하는 물리적 LOC와 실제 실행 가능한 구문만 계산하는 논리적 LOC로 구분될 수 있으며, 프로그래밍 언어, 코딩 스타일, 계산 방식에 따라 값이 크게 달라질 수 있다.11 예를 들어, 동일한 기능을 구현하더라도 Python은 Java나 C++보다 훨씬 적은 LOC를 사용할 수 있다.12&lt;/p&gt;
&lt;p&gt;역사적으로 LOC는 COCOMO와 같은 노력 추정 모델의 입력 값이나 유사한 프로젝트 간의 크기 비교 기준으로 사용되었다.10 또한, 테스트 커버리지 밀도(테스트된 LOC / 전체 LOC)를 계산하는 데 활용되기도 한다.10&lt;/p&gt;
&lt;p&gt;흥미롭게도, McCabe는 순환 복잡도를 제안할 당시 LOC를 복잡성 측정 지표로 사용하는 것을 명시적으로 거부했다. 그는 코드 길이와 모듈의 제어 흐름 복잡성 사이에 명확한 관계가 없다고 보았다.7&lt;/p&gt;
&lt;h3&gt;다. 초기 가치 인식 및 활용&lt;/h3&gt;
&lt;p&gt;이러한 전통적인 메트릭들은 초기에 상당한 가치를 인정받았다. 순환 복잡도는 위험 평가 도구로 빠르게 채택되었다. 높은 CC 값은 높은 결함 밀도와 상관관계가 있는 것으로 나타났으며 9, 코드 검토와 같은 추가적인 품질 보증 활동이 필요한 위험한 모듈을 식별하는 데 사용되었다.9&lt;/p&gt;
&lt;p&gt;개발 지침으로서, McCabe는 개발 중에 모듈의 CC를 특정 임계값(종종 10 또는 15) 이하로 제한하여 복잡한 함수를 더 작고 관리하기 쉬운 단위로 분할하도록 권장했다.4 이는 일부 개발 방법론에서 수용된 관행이 되었다.4&lt;/p&gt;
&lt;p&gt;테스팅 영역에서 CC는 기반 경로 테스팅(basis path testing)에 필요한 최소 테스트 케이스 수를 직접적으로 알려주는 중요한 지표였다.5 이는 테스트 범위를 정량화하고 테스트 노력을 계획하는 데 도움을 주었다.6&lt;/p&gt;
&lt;p&gt;LOC 역시 복잡성 측정에는 한계가 있지만, 유사한 환경에서 구축된 애플리케이션 간의 상대적 크기를 가늠하거나 10 전체 코드베이스 대비 테스트 커버리지 비율을 파악하는 데 여전히 유용하게 사용된다.10&lt;/p&gt;
&lt;p&gt;이러한 전통적인 메트릭들은 구조적 프로그래밍이 지배적이던 시대에 테스트, 유지보수 노력, 위험 관리와 같은 소프트웨어 개발 프로세스의 특정 측면을 정량화하려는 요구에서 비롯되었다. 그 기반은 주로 코드의 구조적 특성과 정량적 계산에 있으며 4, 이는 당시 중요하게 여겨졌던 절차적 코드 구조의 복잡성을 통제하는 데 어느 정도 기여했다. 하지만 초기부터 이러한 메트릭들이 완벽한 지표가 아니라는 암묵적인 이해가 존재했다. 예를 들어, McCabe 자신이 switch 문이 개념적 어려움을 반드시 증가시키지 않으면서도 CC를 부풀릴 수 있음을 인정하고 예외를 제안한 것은 9 순전히 구조적인 관점의 한계를 시사하며 후대의 비판을 예고하는 것이었다.&lt;/p&gt;
&lt;h2&gt;II. 기반의 균열: 전통적 메트릭의 한계&lt;/h2&gt;
&lt;p&gt;수십 년간 활용되어 온 순환 복잡도(CC)와 코드 라인 수(LOC)는 현대 소프트웨어 개발의 복잡성을 포착하는 데 점차 한계를 드러내고 있다. 이는 메트릭 자체의 내재적 문제와 더불어 소프트웨어 개발 환경의 급격한 변화에서 기인한다.&lt;/p&gt;
&lt;h3&gt;가. 메트릭과 현실의 간극: 인지 부하, 중첩, 구조 무시&lt;/h3&gt;
&lt;p&gt;순환 복잡도의 맹점: CC의 가장 큰 비판점 중 하나는 인간의 코드 이해 과정, 즉 인지적 부하를 제대로 반영하지 못한다는 것이다. 동일한 CC 값을 가진 두 함수가 이해도 측면에서는 현저히 다를 수 있다.1 대표적인 예로, 단순한 switch-case 문과 복잡하게 중첩된 논리(예: 버블 정렬 알고리즘)가 비슷한 CC 점수를 받을 수 있지만, 후자가 훨씬 이해하기 어렵다.1 특히 CC는 코드의 중첩 깊이(nesting depth)를 적절히 반영하지 못하는데 1, 깊은 중첩은 인간의 작업 기억(working memory)에 큰 부담을 주어 코드 추적을 어렵게 만들고 오류 발생 가능성을 높인다.1 또한, CC는 코드 구조 개선 노력이나 goto와 같은 비구조적 기법 사용 여부에 둔감하다.7&lt;/p&gt;
&lt;p&gt;LOC의 피상성: LOC는 복잡성이나 생산성을 측정하는 데 매우 부적절한 지표로 널리 인식된다.10 언어 간의 표현력 차이로 인해 동일 기능도 LOC가 크게 달라질 수 있으며 (예: Python vs. Java) 11, 숙련된 개발자는 종종 더 적은 코드로 더 많은 기능을 효율적으로 구현한다 (&apos;양보다 질&apos;).12 오히려 리팩토링을 통해 LOC를 줄이는 것이 코드 품질을 향상시키는 긍정적인 활동인 경우가 많다.13&lt;/p&gt;
&lt;p&gt;예측력 부족: 여러 연구와 경험적 증거들은 CC나 LOC가 실제 인지되는 복잡성, 유지보수 문제, 심지어 결함 예측력 측면에서도 다른 요인이나 새로운 메트릭에 비해 상관관계가 약하거나 부족함을 시사한다.1 CodeScene의 머신러닝 알고리즘이 CC의 예측 가치를 낮게 평가한 사례나 1, 일부 연구에서 결함 예측에 LOC가 CC보다 더 나은 성능을 보였다는 결과는 7 이러한 한계를 뒷받침한다.&lt;/p&gt;
&lt;h3&gt;나. 현대적 맥락의 도전: 패러다임, 언어, 규모&lt;/h3&gt;
&lt;p&gt;새로운 패러다임: 함수형 프로그래밍(작고 조합 가능한 함수), 비동기 프로그래밍(콜백, Promise, async/await), 반응형 프로그래밍, 이벤트 기반 아키텍처 등 현대적인 프로그래밍 패러다임은 단순한 경로 계산이나 라인 수 계산으로는 포착하기 어려운 종류의 복잡성을 도입한다.3 재귀적이거나 멀티스레딩 코드의 복잡성은 눈에 보이는 구조보다는 실행의 재귀적 또는 병렬적 특성에 있다.2&lt;/p&gt;
&lt;p&gt;언어의 진화: 현대 언어들은 리스트 컴프리헨션, 람다 표현식 등 강력하고 표현력 있는 기능을 제공한다. 이는 LOC를 줄일 수 있지만, 복잡한 로직을 몇 줄에 응축시켜 전통적인 메트릭이 시사하는 것과는 다른 방식으로 가독성에 영향을 미칠 수 있다.12 또한, 현대 언어의 다양한 구문으로 인해 코드를 제어 흐름 그래프로 명확하게 매핑하는 것이 모호해질 수 있다.7&lt;/p&gt;
&lt;p&gt;규모와 상호연결성: 현대 소프트웨어 시스템은 방대한 코드베이스를 가지며 2, 마이크로서비스와 같이 분산된 컴포넌트 간의 복잡한 상호작용을 포함하는 경우가 많다.3 이러한 시스템의 전체 복잡성은 개별 모듈의 내부 복잡성(CC나 LOC로 측정되는)보다는 모듈 간의 의존성, 인터페이스, 통신 방식에서 더 크게 비롯된다.19&lt;/p&gt;
&lt;p&gt;프레임워크와 라이브러리: 프레임워크와 외부 라이브러리에 대한 높은 의존성은 애플리케이션 자체의 CC나 LOC에는 반영되지 않는 또 다른 차원의 복잡성을 추가한다. 프레임워크의 동작 방식을 이해하고, 설정을 관리하며, 의존성 충돌을 해결하는 등의 작업은 상당한 노력을 요구한다.20&lt;/p&gt;
&lt;h3&gt;다. 오용과 오해의 위험&lt;/h3&gt;
&lt;p&gt;생산성 착각: LOC를 개발자 생산성 측정에 사용하는 것은 매우 잘못된 접근이라는 강력한 공감대가 형성되어 있다.10 이는 버그 수정처럼 적은 라인 변경에 많은 시간이 소요되는 복잡한 작업의 가치를 무시하며 10, 단순히 코드 라인 수를 늘리려는 부정적인 행동을 조장할 수 있다.16&lt;/p&gt;
&lt;p&gt;메트릭 게임: LOC나 심지어 CC 같은 메트릭을 성과 평가와 직접 연동하면, 개발자들은 메트릭 점수를 높이기 위해 코드를 불필요하게 장황하게 작성하거나, 리팩토링을 피하거나, 의미 없는 변경을 자주 하는 등의 행동을 할 수 있다.16 이는 오히려 코드 복잡성을 증가시키고 기술 부채를 쌓는 결과를 초래할 수 있다.16&lt;/p&gt;
&lt;p&gt;과도한 단순화: CC나 LOC의 임계값을 코드 품질의 절대적인 기준으로 삼는 것은 위험하다. 이는 코드의 가독성, 유지보수성, 설계의 적절성, 프로젝트의 특정 맥락 등 중요한 질적 측면을 간과하게 만든다.8 메트릭은 판단을 돕는 도구일 뿐, 판단 자체를 대체해서는 안 된다.8&lt;/p&gt;
&lt;p&gt;전통적인 메트릭의 핵심 한계는 코드의 *구문적 구조(syntactic structure)*에 초점을 맞추고, 코드의 *의미(semantic meaning)*나 이를 이해하는 데 필요한 *인지적 노력(cognitive effort)*을 간과한다는 점에서 비롯된다. 이러한 불일치는 다양한 형태의 추상화와 조합을 우선시하는 현대 프로그래밍 관행 하에서 더욱 두드러진다. CC는 제어 구조(IF, LOOP 등)에 기반한 경로를 계산하고 1, LOC는 단순히 라인 수를 센다.10 둘 다 구문적이다. 반면, 이들에 대한 비판은 꾸준히 &apos;이해도&apos;를 제대로 측정하지 못한다는 점을 지적하는데 1, 이는 인지적, 의미적 문제이다. 예를 들어 함수형 프로그래밍은 함수당 CC는 낮을 수 있지만, 그 조합을 이해하기 위해서는 다른 종류의 인지 능력이 요구될 수 있다.17 현대 소프트웨어가 목표를 달성하는 방식 자체가 CC가 설계되었던 시대의 단순한 절차적 제어 흐름과 달라지면서, 이들 메트릭의 부적절성이 커지는 것이다.&lt;/p&gt;
&lt;p&gt;더 나아가, LOC와 같은 단순한 메트릭을 생산성 측정에 오용하는 현상은 소프트웨어 공학의 근본적인 도전 과제, 즉 &apos;가치 창출&apos;을 측정하는 어려움을 반영한다. 소프트웨어 개발은 본질적으로 창의적인 문제 해결 활동이므로, 자동화하기 쉽지만 피상적인 지표로 결과물을 정량화하려는 시도는 종종 역효과를 낳는다. 잘못된 행동을 유도하고 잠재적으로 품질을 저해하는 것이다.16 이는 쉽게 측정 가능한 결과물(타이핑된 라인 수)과 실제 목표(문제를 효과적이고 유지보수 가능하게 해결하는 것) 사이의 괴리를 보여준다. 따라서 의미 있는 평가는 정량화하기는 더 어렵지만 더 관련성 높은 결과(요구사항 충족 22, 전달된 가치 23)와 질적 측면(유지보수성, 설계)을 고려해야 함을 시사한다.&lt;/p&gt;
&lt;p&gt;결국 CC와 LOC의 한계는 단순히 기술적인 문제를 넘어, 업계가 중요하게 여기는 가치의 역사적 변화를 반영한다. 초기에는 절차적 복잡성을 제어하고 기본적인 테스트 용이성을 확보하는 데 중점을 두었다. 현대에는 대규모 시스템 관리, 다양한 팀을 위한 인지 부하 감소, 빠른 진화에 대한 요구가 커지면서 다른 종류의 측정 기준과 관리 방식이 필요하게 되었다.&lt;/p&gt;
&lt;h2&gt;III. 코드 복잡성에 대한 현대적 관점&lt;/h2&gt;
&lt;p&gt;전통적인 메트릭의 한계가 명확해짐에 따라, 코드 복잡성을 평가하는 새로운 관점들이 주목받고 있다. 이들은 단순히 코드 구조를 넘어 인간의 인지 과정, 유지보수의 용이성, 효과적인 테스트 가능성 등을 복잡성의 핵심 요소로 간주한다.&lt;/p&gt;
&lt;h3&gt;가. 인지 복잡성(Cognitive Complexity): 이해도 정량화 시도&lt;/h3&gt;
&lt;p&gt;동기: 인지 복잡성은 SonarSource에 의해 개발되었으며, 순환 복잡도(CC)가 코드의 &apos;이해도&apos;를 측정하는 데 실패한다는 단점을 직접적으로 해결하기 위해 등장했다.25 이 메트릭의 목표는 인간이 특정 코드 조각을 읽고 이해하는 데 필요한 정신적 노력을 정량화하는 것이다.25&lt;/p&gt;
&lt;p&gt;측정 규칙: 인지 복잡도 계산의 핵심 원칙은 다음과 같다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;가독성 있는 축약 무시: 여러 구문을 가독성 있게 하나로 압축하는 구조(예: 단순 메서드 호출)는 복잡도를 증가시키지 않는다.26&lt;/li&gt;
&lt;li&gt;선형 흐름 중단 시 증가: 코드의 선형적 흐름을 깨는 구조(예: 루프, 조건문, switch, 예외 처리, goto, 재귀, &amp;#x26;&amp;#x26;나 || 같은 다중 논리 연산자)마다 복잡도가 증가한다.25&lt;/li&gt;
&lt;li&gt;중첩 페널티: 흐름을 깨는 구조가 다른 구조 내부에 중첩될 때 추가적인 페널티가 부과된다.25 이는 CC의 주요 약점 중 하나였던 중첩 깊이 문제를 직접적으로 다룬다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;CC와의 비교: 인지 복잡도는 CC와 명확히 대비된다. CC는 테스트 용이성(최소 테스트 경로 수)에 초점을 맞추는 반면, 인지 복잡도는 가독성 및 이해도(인지적 노력)에 초점을 맞춘다.25 예를 들어, 단순한 switch 문은 CC는 높지만 인지 복잡도는 낮을 수 있으며, 반대로 기능을 작은 함수들로 분해하는 리팩토링은 CC를 증가시킬 수 있지만 인지 복잡도는 감소시킬 수 있다.1 다음 표는 두 메트릭의 주요 차이점을 요약한다.&lt;/p&gt;
&lt;p&gt;표 1: 순환 복잡도와 인지 복잡도 비교&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;특징&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;순환 복잡도 (Cyclomatic Complexity)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;인지 복잡도 (Cognitive Complexity)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;주요 목표&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;테스트 용이성 (Testability)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;이해 용이성 (Understandability)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;측정 초점&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;제어 흐름 경로 수 (Number of control flow paths)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;인지적 노력 (Cognitive effort)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;주요 페널티 요인&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;분기 (Branches: if, loop, switch case 등)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;흐름 중단 (Flow breaks) + 중첩 (Nesting)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;단순 구조 처리&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;switch 등 단순 구조도 경로 수에 따라 높게 측정될 수 있음 1&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;가독성을 해치지 않는 선형 흐름 중단은 낮게 평가, 중첩에 민감 26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;주요 활용 사례&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;테스트 계획 (최소 테스트 케이스 수 결정) 5&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;코드 가독성 및 유지보수성 평가, 리팩토링 대상 식별 17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;참고 자료&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;1&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;한계: 인지 복잡도 역시 하나의 메트릭이며, 인간 인지의 모든 미묘함이나 특정 언어 기능의 어려움(예: 포인터 연산, 고급 타입 시스템)까지 포착하지는 못한다.25 여전히 구조 기반의 측정이며, 최종적인 판단에는 인간의 경험과 맥락 이해가 필수적이다.25&lt;/p&gt;
&lt;h3&gt;나. 유지보수성과 가독성을 핵심 관심사로&lt;/h3&gt;
&lt;p&gt;정의 및 중요성: 유지보수성은 코드를 수정하고 업데이트하기 쉬운 정도를, 가독성은 코드를 읽고 이해하기 쉬운 정도를 의미한다.8 이 두 요소는 소프트웨어 생명주기 전반에 걸쳐 비용, 시간, 결함률에 지대한 영향을 미치는 핵심 품질 속성이다.20 낮은 가독성과 유지보수성은 복잡성을 인지하는 주요 원인이 된다.8&lt;/p&gt;
&lt;p&gt;복잡성과의 관계: 일반적으로 복잡성(구조적이든 인지적이든)과 가독성/유지보수성 사이에는 강한 음의 상관관계가 관찰된다. 즉, 복잡한 코드는 이해하고 안전하게 수정하며 디버깅하기 어렵다.15 연구 결과에서도 가독성과 복잡성 간의 높은 음의 상관관계(-0.974)가 보고된 바 있으며 30, 이는 복잡한 컴포넌트가 유지보수 및 이해하기 훨씬 어렵다는 것을 확인시켜 준다.30&lt;/p&gt;
&lt;p&gt;영향 요인: 단순한 메트릭 점수 외에도 명확한 이름 규칙, 일관된 코드 스타일, 적절한 주석, 모듈화된 설계, 표준 준수, 낮은 결합도, 높은 응집도 등 다양한 요인이 가독성과 유지보수성에 영향을 미친다.8 가독성은 문제 영역 자체의 복잡성(본질적 복잡성)과 달리 엔지니어가 통제할 수 있는 &apos;우발적 속성&apos;으로 간주되기도 한다.30&lt;/p&gt;
&lt;h3&gt;다. 테스트 용이성: 경로 수를 넘어서&lt;/h3&gt;
&lt;p&gt;현대적 관점: 테스트 용이성은 단순히 CC가 나타내는 경로 커버리지 이상의 의미를 갖는다. 코드가 얼마나 쉽게 테스트 환경을 구성하고, 단위(unit)를 격리하여 테스트할 수 있는지에 대한 개념으로 확장된다.8&lt;/p&gt;
&lt;p&gt;테스트 용이성을 위한 설계: 설계 결정은 테스트 용이성에 큰 영향을 미친다. 의존성 주입(Dependency Injection, DI)은 컴포넌트를 분리하고 테스트 중에 실제 의존성을 목(Mock) 객체나 스텁(Stub)으로 쉽게 교체할 수 있게 함으로써 테스트 용이성을 높이는 핵심 디자인 패턴이다.32 이는 테스트 대상 단위를 효과적으로 격리시킨다.32&lt;/p&gt;
&lt;p&gt;모킹(Mocking): 모킹은 실제 의존성의 동작을 시뮬레이션하는 테스트 대역(test double)을 만드는 기술이다.32 DI는 이러한 목 객체를 쉽게 주입할 수 있도록 하여 테스트 코드 작성을 용이하게 한다.32&lt;/p&gt;
&lt;p&gt;복잡성과 테스트 용이성 연관성: 복잡한 코드(높은 CC, 높은 인지 복잡도, 강한 결합, 숨겨진 의존성)는 본질적으로 철저하고 안정적으로 테스트하기 어렵다.2 테스트하기 어려운 코드는 종종 근본적인 설계 문제를 내포하고 있다는 신호일 수 있다.36&lt;/p&gt;
&lt;p&gt;인지 복잡도의 등장은 소프트웨어 개발에서 초점이 단순히 &lt;em&gt;기계가 실행 가능한 경로&lt;/em&gt;(CC)에서 해당 경로와 코드의 의도를 이해하는 데 필요한 &lt;em&gt;인간의 인지적 노력&lt;/em&gt;으로 이동하고 있음을 보여주는 중요한 변화이다. 이는 코드베이스가 커지고 팀이 분산됨에 따라 코드를 &lt;em&gt;이해&lt;/em&gt;하는 비용이 전체 개발 비용과 위험의 주요 동인이 되고 있다는 인식이 커지고 있음을 반영한다.17&lt;/p&gt;
&lt;p&gt;또한, 테스트 용이성을 위해 설계하는 것(예: DI 사용)이 종종 더 모듈화되고, 덜 결합되며, 잠재적으로 전반적으로 덜 복잡한 설계로 이어진다는 점은 주목할 만하다. 이는 긍정적인 피드백 루프를 생성한다. 테스트하기 어렵다는 것은 종종 높은 결합도나 낮은 응집도와 같은 설계 문제의 &lt;em&gt;증상&lt;/em&gt;이다.33 따라서 테스트 용이성을 향상시키는 관행(DI, 명확한 인터페이스)은 복잡성의 일반적인 원인(결합, 불분명한 책임)을 직접적으로 해결하는 경향이 있다.&lt;/p&gt;
&lt;p&gt;하지만 인지 복잡도가 CC보다 이해도를 더 잘 반영하더라도 여전히 &lt;em&gt;구조적&lt;/em&gt; 메트릭이라는 점을 인지해야 한다. 실제 인지 부하는 도메인 지식, 이름 명명의 질, 주석의 유용성, 코드의 일관성, 개별 개발자의 경험과 같은 비구조적 요인에 의해서도 영향을 받는다.2 현재의 자동화된 메트릭들은 이러한 측면을 완전히 포착하기 어렵다. 따라서 인지 복잡도와 같은 메트릭은 유용한 &lt;em&gt;지표&lt;/em&gt;이지만, 이러한 비구조적 측면을 다루는 질적 평가(예: 코드 리뷰)와 좋은 개발 관행으로 보완되어야 한다.&lt;/p&gt;
&lt;h2&gt;IV. 더 넓은 시야: 아키텍처, 디자인, 의존성&lt;/h2&gt;
&lt;p&gt;코드 복잡성은 개별 함수나 클래스 수준을 넘어 시스템 전체의 구조와 상호작용 방식에 의해 크게 영향을 받는다. 아키텍처 선택, 디자인 패턴 적용, 그리고 코드 간의 의존성 관리는 복잡성의 성격과 위치를 근본적으로 결정짓는 요소들이다.&lt;/p&gt;
&lt;h3&gt;가. 아키텍처의 영향: 모놀리스 대 마이크로서비스&lt;/h3&gt;
&lt;p&gt;모놀리식 아키텍처(Monolithic Architecture): 단일 코드베이스와 배포 단위를 특징으로 하는 전통적인 구조이다.20 초기에는 개발, 배포, 테스트, 디버깅이 상대적으로 단순하다는 장점이 있다.38 그러나 시스템 규모가 커짐에 따라 내부 복잡성이 증가하고, 컴포넌트 간의 강한 결합으로 인해 작은 변경이 시스템 전체에 예기치 않은 영향을 미치는 파급 효과(ripple effect)가 발생하기 쉽다.38 이는 개발 속도를 저하시키고, 특정 부분만 독립적으로 확장하기 어렵게 만들며, 새로운 기술 도입에 장벽이 되기도 한다.20&lt;/p&gt;
&lt;p&gt;마이크로서비스 아키텍처(Microservices Architecture): 애플리케이션을 작고 독립적으로 배포 가능한 서비스들의 집합으로 구성하는 접근 방식이다.37 각 서비스는 자체적인 비즈니스 로직과 데이터 저장소를 가질 수 있으며, 네트워크를 통해 잘 정의된 인터페이스로 통신한다.37 주요 장점으로는 서비스별 독립적인 확장, 배포, 기술 선택의 유연성, 높은 장애 격리(fault isolation), 자율적인 팀 구성 지원 등이 있다.19 각 서비스 내부의 코드베이스는 상대적으로 단순해질 수 있다.38&lt;/p&gt;
&lt;p&gt;복잡성 트레이드오프(Complexity Trade-offs): 중요한 점은 마이크로서비스가 복잡성을 제거하는 것이 아니라, 복잡성의 &lt;em&gt;형태를 바꾸고 이동시킨다&lt;/em&gt;는 것이다.38 개별 서비스의 &lt;em&gt;내부&lt;/em&gt; 코드 복잡성은 줄어들 수 있지만, 전체 &lt;em&gt;시스템&lt;/em&gt; 수준의 복잡성은 분산 시스템 고유의 문제들로 인해 증가한다. 여기에는 네트워크 지연 및 신뢰성 문제, 서비스 간 통신 및 데이터 일관성 유지의 어려움, 배포 및 모니터링의 운영 오버헤드 증가, 분산 트랜잭션 테스트의 복잡성, 서비스 검색(discoverability) 문제 등이 포함된다.19 따라서 마이크로서비스 전환은 단순히 기술적 유행을 따르기보다 명확한 기술적, 조직적 요구에 기반해야 하며 19, 때로는 잘 구조화된 &quot;모듈형 모놀리스(modular monolith)&quot;가 더 적합한 대안이 될 수도 있다.19&lt;/p&gt;
&lt;p&gt;표 2: 아키텍처 복잡성 트레이드오프: 모놀리스 vs. 마이크로서비스&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;측면&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;모놀리식 아키텍처 (Monolithic Architecture)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;마이크로서비스 아키텍처 (Microservices Architecture)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;내부 코드 복잡성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;높거나 증가하는 경향 20&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;서비스별로는 낮음 38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;시스템/상호작용 복잡성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;낮음 (내부 호출)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;높음 (네트워크 통신, 분산 시스템 문제) 19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;운영 복잡성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;상대적으로 낮음 (단일 배포/모니터링 대상) 38&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;높음 (다수 서비스 관리, 인프라 복잡성 증가) 39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;배포 복잡성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;단순한 단위 38&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;조정된 서비스 배포 필요 39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;확장성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;전체 단위 확장 (Coarse-grained) 38&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;서비스별 독립 확장 (Fine-grained) 38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;기술 유연성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;낮음 (단일 기술 스택 제약) 38&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;높음 (서비스별 최적 기술 선택 가능) 39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;팀 자율성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;낮음 (코드베이스 공유 및 의존성)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;높음 (독립적인 개발 및 배포 가능) 38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;참고 자료&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;20&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;나. 디자인 패턴: 복잡성 관리 도구인가, 또 다른 복잡성인가?&lt;/h3&gt;
&lt;p&gt;잠재적 이점: 잘 알려진 디자인 패턴은 일반적인 문제에 대한 표준적이고 검증된 해결책을 제공함으로써 복잡성을 관리하는 데 도움을 줄 수 있다.8 패턴은 코드 구조를 개선하고, 재사용성을 높이며, 특정 유형의 복잡한 로직(예: 상태 패턴이나 전략 패턴을 이용한 복잡한 조건문 처리 6)을 단순화할 수 있다. 또한, 패턴은 개발자 간의 의사소통을 위한 공통 어휘를 제공한다.8&lt;/p&gt;
&lt;p&gt;잠재적 단점: 그러나 디자인 패턴의 무분별한 적용은 오히려 복잡성을 증가시킬 수 있다. 패턴은 종종 추가적인 추상화 계층, 더 많은 클래스나 인터페이스, 간접 호출 등을 도입하여 코드 이해를 어렵게 만들 수 있다.21 필요하지 않은 곳에 패턴을 적용하는 오버 엔지니어링은 우발적 복잡성을 낳는다.21 또한, 패턴 자체를 이해하고 나중에 제거하는 것도 복잡한 작업이 될 수 있다.44 SOLID 원칙과 같은 설계 원칙들도 잘못 적용될 경우 불필요한 복잡성을 추가할 수 있다는 비판이 제기된다.21&lt;/p&gt;
&lt;p&gt;맥락의 중요성: 패턴의 가치는 특정 문제와 맥락에 따라 크게 달라진다. 패턴이 제공하는 유연성이나 구조가 현재 및 예상되는 미래의 요구사항에 정말로 필요한지를 신중하게 평가해야 한다.44&lt;/p&gt;
&lt;h3&gt;다. 의존성의 무게: 결합도와 응집도&lt;/h3&gt;
&lt;p&gt;정의: 결합도(Coupling)는 소프트웨어 모듈 간의 상호 의존성 정도를 나타낸다. 즉, 한 모듈의 변경이 다른 모듈의 변경을 요구하는 정도이다.46 응집도(Cohesion)는 단일 모듈 내의 요소들이 얼마나 서로 관련되어 있고 단일 목적을 위해 집중되어 있는지를 나타낸다.46 일반적인 설계 목표는 낮은 결합도와 높은 응집도(Low Coupling, High Cohesion)를 추구하는 것이다.46&lt;/p&gt;
&lt;p&gt;복잡성에 미치는 영향: 높은 결합도는 시스템 복잡성을 크게 증가시킨다. 변경 사항이 시스템 전체로 퍼져나가 예측하기 어렵고, 이해, 수정, 테스트를 어렵게 만든다.46 강하게 결합된 시스템은 변경에 취약하다. 반면, 낮은 응집도는 모듈이 서로 관련 없는 너무 많은 책임을 가지고 있음을 시사하며, 이는 모듈의 이해, 재사용, 유지보수를 어렵게 만든다.46 Feature Envy(다른 클래스의 데이터나 메서드를 과도하게 사용하는 것)나 Message Chains(객체가 다른 객체를 통해 연쇄적으로 메시지를 보내는 것)와 같은 코드 스멜(code smell)은 종종 결합도 및 응집도 문제와 관련이 있다.48&lt;/p&gt;
&lt;p&gt;시스템 전반의 효과: 내부 모듈 간의 의존성뿐만 아니라 외부 라이브러리, 프레임워크, 다른 서비스와의 의존성도 전체 시스템 복잡성에 기여한다.21 이러한 의존성을 관리하고, 그 영향을 파악하며, 호환성을 보장하는 것은 현대 소프트웨어 개발의 주요 과제 중 하나이다.8&lt;/p&gt;
&lt;p&gt;결합도 관리: 직접적인 결합도를 줄이기 위해 인터페이스 기반 설계, 콜백, 의존성 역전 원칙(Dependency Inversion Principle), 이벤트 기반 통신과 같은 기법들이 사용된다.34 Martin Fowler는 특히 시스템의 상위 수준 모듈 간의 결합도를 관리하는 것이 중요하다고 강조한다.47&lt;/p&gt;
&lt;p&gt;코드 복잡성을 개별 코드 조각만으로는 완전히 이해할 수 없다는 점이 분명해진다. 아키텍처 선택(모놀리스 vs. 마이크로서비스)과 시스템 내 의존성 네트워크는 복잡성의 &lt;em&gt;성격&lt;/em&gt;과 &lt;em&gt;위치&lt;/em&gt;를 근본적으로 형성한다. 모놀리스는 복잡성을 내부로 집중시키는 경향이 있고 20, 마이크로서비스는 복잡성을 서비스 간의 상호작용과 운영 환경으로 분산시킨다.38 아키텍처와 관계없이 모듈 간의 높은 결합도는 시스템 전체의 취약성을 야기한다.46 이는 복잡성이 단순히 코드 구조의 문제가 아니라 거시적 설계 결정에 크게 영향을 받는 시스템적 속성임을 보여준다.&lt;/p&gt;
&lt;p&gt;또한, 복잡성을 관리하기 위한 많은 기법들(마이크로서비스, 디자인 패턴, 디커플링)은 종종 트레이드오프를 수반한다. 이들은 한 종류의 복잡성(예: 내부 코드 복잡성)을 해결하는 대신 다른 종류의 복잡성(예: 운영 복잡성, 추상화 오버헤드)을 도입하는 경우가 많다.38 보편적으로 &apos;최선&apos;인 접근 방식은 없으며, 선택은 항상 특정 문제, 팀 역량, 장기 목표 등 맥락에 따라 이루어져야 한다. 이는 유행하는 기술을 맹목적으로 적용하기보다 신중한 분석이 필요함을 시사한다.&lt;/p&gt;
&lt;p&gt;결합도 관리는 클래스 설계(DI, 인터페이스 34)부터 상위 모듈(Fowler 47), 아키텍처 스타일(마이크로서비스 38)에 이르기까지 다양한 추상화 수준에서 핵심 주제로 반복적으로 등장한다. 이는 의존성을 제어하는 것이 전체 시스템의 복잡성과 유지보수성을 관리하는 데 가장 중요한 요소 중 하나임을 시사한다. 이해하기 쉽고 적응 가능한 시스템을 구축하는 데 있어 의존성 관리는 근본적인 중요성을 갖는다.&lt;/p&gt;
&lt;h2&gt;V. 본질적 복잡성 대 우발적 복잡성: 노력 집중하기&lt;/h2&gt;
&lt;p&gt;소프트웨어 복잡성을 효과적으로 관리하기 위해서는 복잡성의 근원을 이해하는 것이 중요하다. Fred Brooks가 제시한 &apos;본질적 복잡성&apos;과 &apos;우발적 복잡성&apos;의 구분은 복잡성의 어떤 측면에 노력을 집중해야 하는지에 대한 전략적 틀을 제공한다.&lt;/p&gt;
&lt;h3&gt;가. Brooks의 이분법: 내재된 복잡성 대 부가된 복잡성&lt;/h3&gt;
&lt;p&gt;기원: 이 개념은 컴퓨터 아키텍트이자 튜링상 수상자인 Fred Brooks가 1986년에 발표한 영향력 있는 논문 &quot;No Silver Bullet—Essence and Accident in Software Engineering&quot;에서 비롯되었다.49 Brooks는 하드웨어 공학에 비해 소프트웨어 공학의 생산성 향상이 더딘 이유를 분석하면서 이 구분을 제시했다.&lt;/p&gt;
&lt;p&gt;본질적 복잡성(Essential Complexity): 문제 영역 자체의 고유한 어려움에서 비롯되는 복잡성이다.45 이는 사용자가 요구하는 기능, 즉 소프트웨어가 &lt;em&gt;반드시&lt;/em&gt; 수행해야 하는 작업들의 복잡성이다.51 이 복잡성은 문제를 변경하지 않는 한 제거할 수 없다.45 예를 들어, 복잡한 비즈니스 규칙, 정교한 과학적 계산, 특정 문제의 본질적인 상태 관리 요구 등이 본질적 복잡성에 해당한다.30&lt;/p&gt;
&lt;p&gt;우발적 복잡성(Accidental Complexity): 개발 과정에서 사용되는 도구, 기술, 설계 결정 등으로 인해 부가적으로 발생하는 복잡성이다.49 이는 문제 자체에 내재된 것이 아니라, 개발자들이 해결 과정에서 의도치 않게 만들어내는 복잡성이다.49 따라서 이 복잡성은 엔지니어들이 잠재적으로 수정하거나 피할 수 있다.50 예를 들어, 과도하게 복잡한 추상화, 잘못된 설계 선택, 다루기 힘든 프레임워크, 복잡한 빌드/배포 프로세스, 불명확한 코드, 불필요한 의존성 등이 우발적 복잡성을 증가시킨다.20&lt;/p&gt;
&lt;h3&gt;나. 우발적 복잡성 인식 및 감소&lt;/h3&gt;
&lt;p&gt;Brooks의 주장: Brooks는 고급 프로그래밍 언어가 어셈블리 언어의 세부 사항을 추상화하는 등 우발적 복잡성을 줄이는 데 상당한 진전이 있었으며, 따라서 남은 과제는 주로 본질적 복잡성에 있다고 주장했다. 이 때문에 소프트웨어 생산성에서 획기적인(order-of-magnitude) 향상을 기대하기는 어렵다고 보았다.50&lt;/p&gt;
&lt;p&gt;현대적 관련성: Brooks의 지적에도 불구하고, 현대 소프트웨어 개발에서도 여전히 상당한 우발적 복잡성이 발생하고 있다.20 부적절한 도구나 프레임워크 선택 20, 잘못된 아키텍처 결정 20, 불필요한 디커플링 21, 과도한 의존성 21, 코드의 명확성 부족 20, 시기상조의 최적화나 일반화 21, 특정 기술이나 방법론을 맹목적으로 따르는 &apos;카고 컬트(cargo culting)&apos; 현상 53 등이 그 원인이 될 수 있다.&lt;/p&gt;
&lt;p&gt;노력 집중: 본질적 복잡성은 좋은 설계와 명확한 이해를 통해 &lt;em&gt;관리&lt;/em&gt;되어야 하는 반면, 우발적 복잡성은 적극적으로 &lt;em&gt;최소화&lt;/em&gt;해야 한다.18 이것이 엔지니어들이 유지보수성, 이해도, 생산성을 향상시키기 위해 가장 큰 영향력을 발휘할 수 있는 영역이다. 전략에는 단순화 추구, 적절한 도구 선택, 명확성 강조, 불필요한 요소 제거 등이 포함된다.21&lt;/p&gt;
&lt;p&gt;본질적/우발적 복잡성 구분은 복잡성 관리에 중요한 전략적 틀을 제공한다. 이는 개발 과정에서 스스로 만들어낸 어려움(우발적)을 &lt;em&gt;제거&lt;/em&gt;하는 데 노력을 기울이고, 피할 수 없는 어려움(본질적)은 효과적으로 &lt;em&gt;모델링하고 관리&lt;/em&gt;하는 데 집중하도록 방향을 제시한다. Brooks는 대부분의 생산성 향상이 우발적 복잡성 감소에서 왔다고 주장했지만 50, 현대 개발에서도 여전히 최적이 아닌 도구, 프로세스, 설계로 인해 상당한 우발적 복잡성이 발생한다.20 따라서 본질적 복잡성을 다루는 것이 어렵다 하더라도, 부주의하게 도입된 우발적 복잡성을 부지런히 식별하고 제거하는 것만으로도 상당한 가치를 창출할 수 있다. 이것이 개선을 위한 가장 실질적인 경로이다.&lt;/p&gt;
&lt;p&gt;하지만 본질적 복잡성과 우발적 복잡성 사이의 경계는 때때로 모호하고 맥락에 따라 달라질 수 있다. 예를 들어, 특정 복잡한 프레임워크 기능이 필요하다고 여겨지는 것이 본질적 복잡성처럼 보일 수 있다. 그러나 요구사항을 더 간단하게 충족할 수 있거나 해당 프레임워크 자체가 작업에 비해 불필요하게 복잡하다면, 이는 우발적 복잡성으로 드러날 수 있다. 이는 요구사항과 솔루션 선택을 비판적으로 평가하여 우발적 복잡성을 본질적 복잡성으로 오인하지 않도록 주의해야 함을 시사한다.&lt;/p&gt;
&lt;h2&gt;VI. 오늘날의 &apos;진정한&apos; 코드 복잡성 정의&lt;/h2&gt;
&lt;p&gt;전통적인 메트릭의 한계와 현대 소프트웨어 개발의 다면성을 고려할 때, &apos;진정한&apos; 코드 복잡성은 단일 지표로 정의될 수 없다. 이는 코드 자체의 구조적 특성뿐만 아니라, 이를 이해하고 다루는 인간의 인지 과정, 시스템 전체의 상호작용, 그리고 해결하려는 문제의 본질까지 아우르는 다차원적인 개념이다.&lt;/p&gt;
&lt;h3&gt;가. 다차원적 구성 요소: 요인 종합&lt;/h3&gt;
&lt;p&gt;단일 메트릭을 넘어서: 순환 복잡도, LOC, 심지어 인지 복잡도와 같은 어떤 단일 숫자도 &apos;진정한&apos; 복잡성의 전체 그림을 포착할 수는 없다.8 진정한 복잡성은 여러 요소가 복합적으로 작용한 결과이다.&lt;/p&gt;
&lt;p&gt;종합적 정의: 현대적 관점에서 코드 복잡성을 구성하는 주요 차원들은 다음과 같이 종합될 수 있다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;구조적 복잡성 (Structural Complexity): 제어 흐름의 얽힘, 코드 구성 방식의 복잡성. 순환 복잡도, 중첩 깊이(Nesting Depth) 등이 부분적으로 측정한다.4&lt;/li&gt;
&lt;li&gt;인지 복잡성 (Cognitive Complexity): 코드의 로직, 흐름, 의도를 파악하는 데 필요한 정신적 노력. 인지 복잡도 메트릭과 가독성 관련 요인(명명 규칙, 일관성 등)에 의해 영향을 받는다.25&lt;/li&gt;
&lt;li&gt;상태 공간 복잡성 (State Space Complexity): 시스템 또는 컴포넌트가 가질 수 있는 가능한 상태의 수와 이를 추론하는 어려움. 복잡한 로직의 테스트 및 디버깅 논의에서 암시적으로 나타난다.15&lt;/li&gt;
&lt;li&gt;의존성 복잡성 (Dependency Complexity): 내부 및 외부 의존성의 수, 성격, 결합 방식에서 발생하는 복잡성.8&lt;/li&gt;
&lt;li&gt;아키텍처 복잡성 (Architectural Complexity): 선택된 아키텍처 스타일(예: 마이크로서비스의 분산 시스템 문제)에 내재된 복잡성.19&lt;/li&gt;
&lt;li&gt;도메인 복잡성 (Domain Complexity / Essential): 해결하려는 문제 자체의 본질적인 복잡성.30&lt;/li&gt;
&lt;li&gt;도구/환경 복잡성 (Tooling/Environment Complexity / Accidental): 빌드 시스템, 배포 파이프라인, 프레임워크 등 개발 환경에서 비롯되는 부가적인 복잡성.49&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;나. 현대 복잡성 평가의 핵심 요소&lt;/h3&gt;
&lt;p&gt;전체론적 관점: 복잡성을 평가할 때는 단순히 코드 구조뿐만 아니라 위에서 언급된 다양한 차원을 종합적으로 고려해야 한다.&lt;br&gt;
맥락의 중요성: 복잡성의 영향은 팀의 규모와 경험, 프로젝트 목표, 예상 수명 등 맥락에 따라 달라진다.8 주니어 개발자에게 복잡한 것이 전문가에게는 단순할 수 있다.25&lt;br&gt;
질적 판단: 정량적 메트릭과 함께 인간의 판단, 코드 리뷰, 도메인 전문 지식의 중요성을 간과해서는 안 된다.8&lt;br&gt;
결국 &apos;진정한&apos; 코드 복잡성은 코드 자체의 속성이라기보다는, 코드, 코드가 속한 시스템, 코드가 해결하는 문제, 그리고 이를 개발하고 유지보수하는 인간 사이의 상호작용에서 &lt;em&gt;나타나는(emergent)&lt;/em&gt; 속성으로 이해하는 것이 가장 적절하다. 분석 과정에서 복잡성이 코드 구조(CC), 인간의 이해(인지 복잡성), 시스템 상호작용(결합도, 아키텍처), 문제 영역(본질적 복잡성) 등 다양한 원천에서 발생함을 확인했다. 메트릭만으로는 충분하지 않으며 8, 인지 부하나 팀 구조와 같은 인간적 요소가 결정적이다.25 따라서 복잡성에 대한 정의는 이러한 구조적, 시스템적, 인지적, 맥락적 요소를 통합해야 한다.&lt;/p&gt;
&lt;p&gt;복잡성이 다차원적이고 맥락 의존적이라는 사실은 효과적인 평가를 위해서는 단일 &apos;궁극의&apos; 복잡성 메트릭을 찾기보다는, 다양한 지표(CC, 인지 복잡도, 결합도 메트릭, 테스트 커버리지 등)들의 &lt;em&gt;대시보드&lt;/em&gt;와 질적 실천(코드 리뷰, 아키텍처 리뷰)을 결합해야 함을 시사한다. 이는 다른 분야에서 복잡한 시스템을 모니터링하는 방식과 유사하다. 다양한 정량적, 질적 정보를 종합해야만 복잡성에 대한 미묘하고 정확한 이해에 도달할 수 있다.&lt;/p&gt;
&lt;h2&gt;VII. 효과적인 복잡성 관리 전략&lt;/h2&gt;
&lt;p&gt;현대 소프트웨어 개발에서 코드 복잡성을 효과적으로 관리하는 것은 단순히 좋은 코드를 작성하는 것을 넘어, 설계, 프로세스, 팀 문화 전반에 걸친 지속적인 노력을 요구한다. 복잡성의 다면적 본질을 이해했다면, 이를 제어하고 완화하기 위한 구체적인 전략을 적용하는 것이 중요하다.&lt;/p&gt;
&lt;h3&gt;가. 선제적 설계 및 아키텍처&lt;/h3&gt;
&lt;p&gt;모듈화 (Modularization): 크고 복잡한 시스템을 작고, 응집력 있으며, 느슨하게 결합된 모듈이나 서비스로 나누는 것이 기본이다.42 관심사의 분리(Separation of Concerns, SoC) 원칙을 적용하고 54, 명확한 인터페이스와 API를 설계하여 모듈 간의 상호작용을 정의해야 한다.34 이는 마이크로서비스나 모듈형 모놀리스 아키텍처와 직접적으로 연결된다.40 모듈화는 코드 재사용을 촉진하고 가독성을 높이며, 각 컴포넌트를 더 쉽게 이해하고 유지보수할 수 있게 한다.42&lt;br&gt;
추상화 (Abstraction): 구현 세부 사항을 감추고 필수적인 기능만 노출하는 추상화를 효과적으로 사용해야 한다.42 캡슐화(Encapsulation)는 이를 달성하는 핵심 기법이다.54 잘 설계된 추상화는 개발자가 세부 사항에 얽매이지 않고 상위 수준에서 시스템과 상호작용할 수 있게 하여 인지 부하를 줄인다.42&lt;br&gt;
적절한 패턴 사용 (Appropriate Patterns): 디자인 패턴은 그것이 실제로 문제를 단순화하고 명확하게 할 때 유용하다.8 패턴 사용 자체가 목적이 되어서는 안 되며, 불필요한 패턴 적용은 오버 엔지니어링으로 이어져 우발적 복잡성을 증가시킬 수 있다.21 패턴의 장단점을 이해하고 맥락에 맞게 신중하게 선택해야 한다.44&lt;br&gt;
단순성 우선 (Simplicity Focus): 처음부터 단순한 설계를 지향하고, 불필요한 기능이나 미래에 대한 과도한 예측에 기반한 일반화를 피해야 한다.21 YAGNI(&quot;You Ain&apos;t Gonna Need It&quot;) 원칙을 따르는 것이 도움이 될 수 있다.58 꼭 필요한 경우가 아니라면 의존성 추가를 최소화해야 한다.21&lt;/p&gt;
&lt;h3&gt;나. 부지런한 코딩 및 리팩토링 관행&lt;/h3&gt;
&lt;p&gt;클린 코드 (Clean Code): 가독성 높은 코드는 복잡성 관리의 핵심이다. 의미 있는 변수 및 함수 이름 사용, 일관된 코딩 스타일 유지, 명확한 코드 구조 설계, 함수 및 메서드를 작게 유지하는 것 등이 중요하다.21 코드는 문서보다 더 정확하게 시스템의 동작을 반영하므로 21, 이해하기 쉬운 코드를 작성하는 것이 우선이다.54&lt;br&gt;
리팩토링 (Refactoring): 코드 구조를 개선하고, 중복을 제거하며(DRY 원칙), 로직을 단순화하고, 복잡성 메트릭을 낮추기 위해 지속적으로 리팩토링을 수행해야 한다.5 &apos;메서드 추출(Extract Method)&apos; 6, &apos;조건문 단순화&apos; 60, &apos;조건문을 다형성으로 대체(Replace Conditional with Polymorphism)&apos; 6 등 구체적인 리팩토링 기법을 활용할 수 있다. 리팩토링은 기술 부채 축적을 방지하는 중요한 활동이다.6&lt;br&gt;
테스트 주도 개발 (TDD/BDD): TDD와 같은 테스트 우선 접근 방식은 개발자가 코드를 사용하고 테스트하는 관점에서 먼저 생각하도록 유도하여 자연스럽게 더 단순하고 모듈화되며 테스트 가능한 코드를 작성하도록 이끌 수 있다.42&lt;br&gt;
죽은/불필요한 코드 제거 (Eliminate Dead/Useless Code): 사용되지 않는 코드, 불필요한 추상화 계층(예: 단일 구현 인터페이스), 가치를 제공하지 않는 디자인 패턴 등은 시스템에 불필요한 복잡성만 더한다.21 정기적으로 이러한 코드를 식별하고 과감하게 제거해야 한다.21&lt;/p&gt;
&lt;h3&gt;다. 견고한 프로세스 및 팀 협업&lt;/h3&gt;
&lt;p&gt;코드 리뷰 (Code Reviews): 동료 검토는 복잡성을 식별하고, 개선 방안을 제안하며, 지식을 공유하고, 코딩 표준을 유지하는 데 매우 중요한 역할을 한다.6 코드 리뷰는 잠재적인 문제를 조기에 발견하고 협업을 통해 코드 품질을 향상시키는 데 기여한다.42&lt;br&gt;
코딩 표준 (Coding Standards): 명확한 코딩 표준과 스타일 가이드라인을 수립하고 팀 전체가 이를 준수하도록 장려해야 한다.8 이는 코드의 일관성과 가독성을 높여 복잡성을 줄이는 데 도움이 된다.15 자동화된 린터(linter)나 포맷터(formatter)를 활용하면 표준 준수를 용이하게 할 수 있다.54&lt;br&gt;
자동화 (테스팅, CI/CD): 리팩토링이나 새로운 기능 개발 시 발생할 수 있는 회귀 오류(regression)를 잡기 위해 자동화된 테스트를 적극 활용해야 한다.42 CI/CD(지속적 통합/지속적 배포) 파이프라인을 구축하여 빌드, 테스트, 배포 프로세스를 자동화하면 통합 문제를 조기에 발견하고 일관성 있고 안정적인 배포를 보장할 수 있다.57&lt;br&gt;
문서화 (Documentation): 아키텍처, 복잡한 로직, API 등 필요한 부분에 대해서는 명확하고 간결한 문서를 유지해야 한다.42 하지만 가능한 경우, 코드가 스스로 설명하도록(self-documenting code) 작성하는 것을 우선시해야 한다.57&lt;br&gt;
명확한 요구사항 (Clear Requirements): 모호하거나 불완전한 요구사항은 복잡하거나 불필요한 구현으로 이어질 수 있다. 프로젝트 시작 단계에서 요구사항을 명확하게 정의하는 것이 중요하다.58&lt;br&gt;
측정 및 모니터링 (Measure and Monitor): 순환 복잡도, 인지 복잡도 등의 메트릭을 절대적인 목표치가 아닌, 주의가 필요한 잠재적 문제 영역(hotspot)을 식별하기 위한 신호로 사용해야 한다.5 복잡성 추세를 지속적으로 모니터링하고 분석하여 개선 기회를 찾아야 한다.6&lt;/p&gt;
&lt;p&gt;표 3: 복잡성 관리 전략 요약&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;전략 범주&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;구체적 전략&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;설명&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;주요 관리 대상 복잡성 차원&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;설계/아키텍처&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;모듈화 (Modularization)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;시스템을 작고 응집력 있으며 느슨하게 결합된 단위로 분할 54&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구조적, 의존성, 인지적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;추상화 (Abstraction)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구현 세부 사항 숨기고 필수 인터페이스 노출 42&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;인지적, 구조적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;적절한 패턴 사용 (Appropriate Patterns)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;문제 해결에 도움이 될 때 신중하게 패턴 적용 42&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구조적, 인지적 (잘못 사용 시 우발적 증가)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;단순성 우선 (Simplicity Focus)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;불필요한 기능/일반화 회피, 최소 의존성 유지 21&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;우발적, 구조적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;코딩/리팩토링&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;클린 코드 (Clean Code)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;가독성 높은 코드 작성 (명명, 스타일, 작은 함수 등) 21&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;인지적, 구조적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;지속적 리팩토링 (Continuous Refactoring)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;코드 구조 개선, 중복 제거, 로직 단순화 15&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구조적, 인지적, 우발적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;TDD/BDD&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;테스트 우선 접근 방식으로 설계 개선 유도 42&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구조적, 테스트 용이성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;죽은/불필요한 코드 제거&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;사용되지 않거나 가치 없는 코드 제거 21&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;우발적, 구조적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;프로세스/팀&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;코드 리뷰 (Code Reviews)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;동료 검토를 통한 문제 식별, 지식 공유, 표준 유지 6&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;모든 차원 (특히 인지적, 구조적, 우발적)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;코딩 표준 (Coding Standards)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;일관성 및 가독성 향상을 위한 표준 수립 및 준수 57&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;인지적, 우발적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;자동화 (Testing, CI/CD)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;회귀 방지, 통합 문제 조기 발견, 안정적 배포 57&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;테스트 용이성, 운영 복잡성 (우발적)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;문서화 (Documentation)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;필요한 정보 기록, 단 코드 자체의 명확성 우선 42&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;인지적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;명확한 요구사항 (Clear Requirements)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;모호성 제거로 불필요한 복잡성 방지 58&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;본질적 (명확화), 우발적 (방지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;측정 및 모니터링 (Measure &amp;#x26; Monitor)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;메트릭을 신호로 활용하여 문제 영역 식별 및 추세 관리 5&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구조적, 인지적 (지표로서), 관리 효율성&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;효과적인 복잡성 관리는 단순히 영리한 코드를 작성하는 기술적인 문제를 넘어선다. 이는 기술적 실천(설계, 코딩, 리팩토링), 프로세스 규율(리뷰, 표준, 자동화), 그리고 아키텍처에 대한 선견지명을 결합하는 전체론적인 접근 방식을 요구한다.54 단일 전략만으로는 충분하지 않으며, 소프트웨어 개발 생명주기의 여러 단계에서 상호 보완적인 노력이 필요하다.&lt;/p&gt;
&lt;p&gt;또한, 복잡성 관리는 일회성 작업이 아니라 지속적인 활동이다. 지속적인 리팩토링, 정기적인 리뷰, 표준 준수, 시스템 진화에 따른 설계 조정 등이 필요하다.15 복잡성과 관련된 기술 부채는 적극적으로 관리하지 않으면 시간이 지남에 따라 누적된다.6&lt;/p&gt;
&lt;p&gt;마지막으로, 많은 효과적인 전략들이 복잡성의 인간적 측면을 직접적으로 다룬다는 점을 주목해야 한다. 가독성 향상 21, 표준과 리뷰를 통한 공동 이해 증진 57, 모듈화와 추상화를 통한 인지 부하 감소 42 등이 그 예이다. 이는 코드 자체의 구조를 관리하는 것만큼이나 코드와 상호작용하는 인간의 경험을 관리하는 것이 중요함을 다시 한번 강조한다.&lt;/p&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;p&gt;본 보고서는 현대 소프트웨어 개발에서 &apos;진정한&apos; 코드 복잡성이 무엇인지에 대한 심층적인 분석을 제공하고자 했다. 30년 이상 전에 정의된 순환 복잡도나 코드 라인 수와 같은 전통적인 메트릭은 코드의 구조적 측면을 정량화하려는 초기 시도로서 가치가 있었으나, 현대 소프트웨어의 다면적인 복잡성을 포착하는 데는 명백한 한계를 지닌다. 특히 코드의 이해도와 관련된 인지적 부하, 중첩 구조의 영향, 그리고 새로운 프로그래밍 패러다임 및 아키텍처 패턴의 등장은 이러한 한계를 더욱 부각시킨다.&lt;/p&gt;
&lt;p&gt;현대적인 관점에서 복잡성은 단순히 코드 구조의 얽힘을 넘어선다. 인지 복잡도는 코드를 이해하는 데 필요한 정신적 노력을 측정하려는 시도이며, 유지보수성, 가독성, 테스트 용이성은 복잡성이 실제 개발 및 운영 과정에 미치는 영향을 반영하는 중요한 품질 속성이다. 또한, 마이크로서비스나 모놀리스와 같은 아키텍처 선택, 디자인 패턴의 적용 방식, 그리고 시스템 내외부의 의존성 및 결합도는 개별 코드 조각의 복잡성을 넘어서는 시스템 수준의 복잡성을 결정짓는다. Fred Brooks가 제시한 본질적 복잡성과 우발적 복잡성의 구분은 우리가 통제하고 개선할 수 있는 영역(우발적 복잡성)에 노력을 집중해야 함을 시사한다.&lt;/p&gt;
&lt;p&gt;결론적으로, 오늘날 &apos;진정한&apos; 코드 복잡성은 구조적, 인지적, 상태 공간적, 의존성 관련, 아키텍처적, 도메인 고유(본질적), 그리고 개발 환경(우발적) 차원들이 복합적으로 얽혀있는 다차원적 구성체이다. 이는 코드, 시스템, 문제 영역, 그리고 개발자 간의 상호작용에서 비롯되는 동적인 속성이다.&lt;/p&gt;
&lt;p&gt;따라서 복잡성을 효과적으로 관리하기 위해서는 단일 메트릭에 의존하기보다, 다양한 지표(CC, 인지 복잡도, 결합도 메트릭 등)를 상황에 맞게 활용하고 이를 질적인 평가(코드 리뷰, 아키텍처 검토)와 결합하는 전체론적 접근이 필요하다. 선제적인 설계 원칙(모듈화, 추상화, 단순성) 준수, 부지런한 코딩 및 리팩토링 관행(클린 코드, 지속적 개선), 그리고 견고한 개발 프로세스(표준, 자동화, 협업)를 통해 우발적 복잡성을 최소화하고 본질적 복잡성을 효과적으로 다루어야 한다.&lt;/p&gt;
&lt;p&gt;궁극적으로, 복잡성 관리는 기술적 숙련도를 넘어선 지속적인 관심과 규율을 요구하는 활동이다. 코드와 그것이 존재하는 맥락 모두에 주의를 기울이고, 명확성, 유지보수성, 그리고 팀의 이해도를 우선시하는 문화를 조성하는 것이 변화하는 소프트웨어 환경 속에서 지속 가능한 시스템을 구축하는 길이다.&lt;/p&gt;
&lt;h4&gt;참고 자료&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Cyclomatic complexity - a fresh look at code complexity｜Blog, 4월 13, 2025에 액세스, &lt;a href=&quot;https://codescene.com/engineering-blog/bumpy-road-code-complexity-in-context/&quot;&gt;https://codescene.com/engineering-blog/bumpy-road-code-complexity-in-context/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the accuracy of code complexity metrics: A neuroscience-based guideline for improvement - PMC - PubMed Central, 4월 13, 2025에 액세스, &lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC9942489/&quot;&gt;https://pmc.ncbi.nlm.nih.gov/articles/PMC9942489/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Software disenchantment - why does modern programming seem to lack of care for efficiency, simplicity, and excellence - Reddit, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.reddit.com/r/programming/comments/z7vsi0/software_disenchantment_why_does_modern/&quot;&gt;https://www.reddit.com/r/programming/comments/z7vsi0/software_disenchantment_why_does_modern/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic complexity - Wikipedia, 4월 13, 2025에 액세스, &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;https://en.wikipedia.org/wiki/Cyclomatic_complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;What is Cyclomatic Complexity? Definition Guide &amp;#x26; Examples - Sonar, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.sonarsource.com/learn/cyclomatic-complexity/&quot;&gt;https://www.sonarsource.com/learn/cyclomatic-complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic Complexity in Testing: Importance and Benefits - Bugasura, 4월 13, 2025에 액세스, &lt;a href=&quot;https://bugasura.io/blog/cyclomatic-complexity-in-testing/&quot;&gt;https://bugasura.io/blog/cyclomatic-complexity-in-testing/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A critique of cyclomatic complexity as a software metric - Computer Science Department, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.cs.du.edu/~snarayan/sada/teaching/COMP3705/lecture/p1/cycl-1.pdf&quot;&gt;https://www.cs.du.edu/~snarayan/sada/teaching/COMP3705/lecture/p1/cycl-1.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic complexity: Definition and limits in understanding code quality - DX, 4월 13, 2025에 액세스, &lt;a href=&quot;https://getdx.com/blog/cyclomatic-complexity/&quot;&gt;https://getdx.com/blog/cyclomatic-complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic Complexity - The Ganssle Group, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.ganssle.com/articles/cyclomaticcomplexity.html&quot;&gt;https://www.ganssle.com/articles/cyclomaticcomplexity.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Is Counting Lines of Code (LOC) Useful? - NDepend Blog, 4월 13, 2025에 액세스, &lt;a href=&quot;https://blog.ndepend.com/why-is-counting-lines-of-code-loc-useful/&quot;&gt;https://blog.ndepend.com/why-is-counting-lines-of-code-loc-useful/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;What Happened to Software Metrics? - PMC, 4월 13, 2025에 액세스, &lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC5544018/&quot;&gt;https://pmc.ncbi.nlm.nih.gov/articles/PMC5544018/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why lines of code are a bad measure of developer productivity - DX, 4월 13, 2025에 액세스, &lt;a href=&quot;https://getdx.com/blog/lines-of-code/&quot;&gt;https://getdx.com/blog/lines-of-code/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Lines of Code (LOC) Measures Irritate Me - ProjectManagement.com, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.projectmanagement.com/blog-post/5104/Why-Lines-of-Code--LOC--Measures-Irritate-Me&quot;&gt;https://www.projectmanagement.com/blog-post/5104/Why-Lines-of-Code--LOC--Measures-Irritate-Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Avoid High Cyclomatic Complexity - Better Embedded System SW, 4월 13, 2025에 액세스, &lt;a href=&quot;https://betterembsw.blogspot.com/2014/06/avoid-high-cyclomatic-complexity.html&quot;&gt;https://betterembsw.blogspot.com/2014/06/avoid-high-cyclomatic-complexity.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Code Complexity Metrics: Writing Clean, Maintainable Software - Iterators, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.iteratorshq.com/blog/code-complexity-metrics-writing-clean-maintainable-software/&quot;&gt;https://www.iteratorshq.com/blog/code-complexity-metrics-writing-clean-maintainable-software/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why your Lines of Code per day are not the right productivity metric—and what to use instead - Waydev, 4월 13, 2025에 액세스, &lt;a href=&quot;https://waydev.co/lines-of-code-per-day/&quot;&gt;https://waydev.co/lines-of-code-per-day/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Should we prefer cognitive complexity over cyclomatic complexity ..., 4월 13, 2025에 액세스, &lt;a href=&quot;https://community.sonarsource.com/t/should-we-prefer-cognitive-complexity-over-cyclomatic-complexity/12337&quot;&gt;https://community.sonarsource.com/t/should-we-prefer-cognitive-complexity-over-cyclomatic-complexity/12337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A Fundamental Theory for Explaining and Measuring Code Complexity - ResearchGate, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.researchgate.net/publication/362062741_A_Fundamental_Theory_for_Explaining_and_Measuring_Code_Complexity&quot;&gt;https://www.researchgate.net/publication/362062741_A_Fundamental_Theory_for_Explaining_and_Measuring_Code_Complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;My solution to Microservices complexity : r/node - Reddit, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.reddit.com/r/node/comments/1dvsfyz/my_solution_to_microservices_complexity/&quot;&gt;https://www.reddit.com/r/node/comments/1dvsfyz/my_solution_to_microservices_complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Code Complexity: An In-Depth Explanation and Metrics - Codacy | Blog, 4월 13, 2025에 액세스, &lt;a href=&quot;https://blog.codacy.com/code-complexity&quot;&gt;https://blog.codacy.com/code-complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How to Simplify Code Complexity: Avoid These Complexity Pitfalls - Turing, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.turing.com/blog/reduce-code-complexity-simplify-your-code&quot;&gt;https://www.turing.com/blog/reduce-code-complexity-simplify-your-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Is there a better programming metric than &quot;lines of code&quot;? - Reddit, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.reddit.com/r/programming/comments/cbuwd/is_there_a_better_programming_metric_than_lines/&quot;&gt;https://www.reddit.com/r/programming/comments/cbuwd/is_there_a_better_programming_metric_than_lines/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Negative 2000 Lines of Code (1982) - Hacker News, 4월 13, 2025에 액세스, &lt;a href=&quot;https://news.ycombinator.com/item?id=33483165&quot;&gt;https://news.ycombinator.com/item?id=33483165&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Pros and Cons of Using Cyclomatic Complexity as a Code Quality Metric - BlueOptima, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.blueoptima.com/the-pros-and-cons-of-using-cyclomatic-complexity-as-a-code-quality-metric/&quot;&gt;https://www.blueoptima.com/the-pros-and-cons-of-using-cyclomatic-complexity-as-a-code-quality-metric/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Understanding cognitive complexity in software development - GetDX, 4월 13, 2025에 액세스, &lt;a href=&quot;https://getdx.com/blog/cognitive-complexity/&quot;&gt;https://getdx.com/blog/cognitive-complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cognitive Complexity - Code Climate, 4월 13, 2025에 액세스, &lt;a href=&quot;https://docs.codeclimate.com/docs/cognitive-complexity&quot;&gt;https://docs.codeclimate.com/docs/cognitive-complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(PDF) Comparative Analysis between Cognitive Complexity and ..., 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.researchgate.net/publication/389175932_Comparative_Analysis_between_Cognitive_Complexity_and_Cyclomatic_Complexity_in_Software_Development&quot;&gt;https://www.researchgate.net/publication/389175932_Comparative_Analysis_between_Cognitive_Complexity_and_Cyclomatic_Complexity_in_Software_Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic Complexity vs Cognitive Complexity: Key Differences Explained - Graph AI, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.graphapp.ai/blog/cyclomatic-complexity-vs-cognitive-complexity-key-differences-explained&quot;&gt;https://www.graphapp.ai/blog/cyclomatic-complexity-vs-cognitive-complexity-key-differences-explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Do you use metrics for code complexity? : r/cpp - Reddit, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/l03xrr/do_you_use_metrics_for_code_complexity/&quot;&gt;https://www.reddit.com/r/cpp/comments/l03xrr/do_you_use_metrics_for_code_complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A Notional Understanding of the Relationship between Code Readability and Software Complexity - MDPI, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.mdpi.com/2078-2489/14/2/81&quot;&gt;https://www.mdpi.com/2078-2489/14/2/81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;An Empirical Study of the Relationships between Code Readability and Software Complexity - arXiv, 4월 13, 2025에 액세스, &lt;a href=&quot;https://arxiv.org/pdf/1909.01760&quot;&gt;https://arxiv.org/pdf/1909.01760&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Simplifying Unit Testing with Dependency Injection: A Comprehensive Guide, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.codingexplorations.com/blog/simplifying-unit-testing-with-dependency-injection-a-comprehensive-guide&quot;&gt;https://www.codingexplorations.com/blog/simplifying-unit-testing-with-dependency-injection-a-comprehensive-guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Testable and Maintainable code with Dependency Injection and Containers, 4월 13, 2025에 액세스, &lt;a href=&quot;https://fideloper.com/testable-maintainable-di-containers&quot;&gt;https://fideloper.com/testable-maintainable-di-containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;unit testing - What are the design principles that promote testable code? (designing testable code vs driving design through tests) - Software Engineering Stack Exchange, 4월 13, 2025에 액세스, &lt;a href=&quot;https://softwareengineering.stackexchange.com/questions/153410/what-are-the-design-principles-that-promote-testable-code-designing-testable-c&quot;&gt;https://softwareengineering.stackexchange.com/questions/153410/what-are-the-design-principles-that-promote-testable-code-designing-testable-c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Do you prefer Mock or Dependency Injection when Unit Testing Functions in Python?, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.reddit.com/r/Python/comments/195uk6d/do_you_prefer_mock_or_dependency_injection_when/&quot;&gt;https://www.reddit.com/r/Python/comments/195uk6d/do_you_prefer_mock_or_dependency_injection_when/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Good Code, Testable Code | Epic Web Dev, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.epicweb.dev/good-code-testable-code&quot;&gt;https://www.epicweb.dev/good-code-testable-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Monolithic vs Microservices - Difference Between Software Development Architectures, 4월 13, 2025에 액세스, &lt;a href=&quot;https://aws.amazon.com/compare/the-difference-between-monolithic-and-microservices-architecture/&quot;&gt;https://aws.amazon.com/compare/the-difference-between-monolithic-and-microservices-architecture/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microservices vs. monolithic architecture - Atlassian, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.atlassian.com/microservices/microservices-architecture/microservices-vs-monolith&quot;&gt;https://www.atlassian.com/microservices/microservices-architecture/microservices-vs-monolith&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Monolith Versus Microservices: Weigh the Pros and Cons of Both Configs | Akamai, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.akamai.com/blog/cloud/monolith-versus-microservices-weigh-the-difference&quot;&gt;https://www.akamai.com/blog/cloud/monolith-versus-microservices-weigh-the-difference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Comparing microservices to monoliths - BellSoft, 4월 13, 2025에 액세스, &lt;a href=&quot;https://bell-sw.com/blog/microservices-vs-monoliths-which-approach-is-better-for-your-project/&quot;&gt;https://bell-sw.com/blog/microservices-vs-monoliths-which-approach-is-better-for-your-project/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Micro Frontends - Martin Fowler, 4월 13, 2025에 액세스, &lt;a href=&quot;https://martinfowler.com/articles/micro-frontends.html&quot;&gt;https://martinfowler.com/articles/micro-frontends.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Understanding Code Complexity: Measurement and Reduction Techniques - Metabob, 4월 13, 2025에 액세스, &lt;a href=&quot;https://metabob.com/blog-articles/understanding-code-complexity-measurement-and-reduction-techniques.html&quot;&gt;https://metabob.com/blog-articles/understanding-code-complexity-measurement-and-reduction-techniques.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How to Reduce Cyclomatic Complexity: A Complete Guide | LinearB Blog, 4월 13, 2025에 액세스, &lt;a href=&quot;https://linearb.io/blog/reduce-cyclomatic-complexity&quot;&gt;https://linearb.io/blog/reduce-cyclomatic-complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Do design patterns increase or decrease the complexity of an Application? - Stack Overflow, 4월 13, 2025에 액세스, &lt;a href=&quot;https://stackoverflow.com/questions/759796/do-design-patterns-increase-or-decrease-the-complexity-of-an-application&quot;&gt;https://stackoverflow.com/questions/759796/do-design-patterns-increase-or-decrease-the-complexity-of-an-application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Essential and Accidental complexity, and performance - Eduardo Lavaque&apos;s Blog, 4월 13, 2025에 액세스, &lt;a href=&quot;https://greduan.com/blog/2024/07/25/essential-and-accidental-complexity-and-performance/&quot;&gt;https://greduan.com/blog/2024/07/25/essential-and-accidental-complexity-and-performance/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Coupling And Cohesion - C2 wiki, 4월 13, 2025에 액세스, &lt;a href=&quot;https://wiki.c2.com/?CouplingAndCohesion&quot;&gt;https://wiki.c2.com/?CouplingAndCohesion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Reducing Coupling, 4월 13, 2025에 액세스, &lt;a href=&quot;https://martinfowler.com.cn/ieeeSoftware/coupling.pdf&quot;&gt;https://martinfowler.com.cn/ieeeSoftware/coupling.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Book notes: Agile Technical Practices Distilled, 50 years of Cohesion and Coupling, 4월 13, 2025에 액세스, &lt;a href=&quot;https://espumita.org/2024/09/01/agile-technical-practices-distilled-book-notes/&quot;&gt;https://espumita.org/2024/09/01/agile-technical-practices-distilled-book-notes/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Accidental Complexity in Software Engineering - Chi Blog, 4월 13, 2025에 액세스, &lt;a href=&quot;https://cedricchee.com/blog/accidental-complexity/&quot;&gt;https://cedricchee.com/blog/accidental-complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;No Silver Bullet - Wikipedia, 4월 13, 2025에 액세스, &lt;a href=&quot;https://en.wikipedia.org/wiki/No_Silver_Bullet&quot;&gt;https://en.wikipedia.org/wiki/No_Silver_Bullet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Avoiding Accidental Complexity in Software Design - Nutshell CRM, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.nutshell.com/blog/accidental-complexity-software-design&quot;&gt;https://www.nutshell.com/blog/accidental-complexity-software-design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Simplify! - Part 3 - Uwe Friedrichsen, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.ufried.com/blog/simplify_3_essential_and_accidental_complexity/&quot;&gt;https://www.ufried.com/blog/simplify_3_essential_and_accidental_complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Linking Modular Architecture to Development Teams - Martin Fowler, 4월 13, 2025에 액세스, &lt;a href=&quot;https://martinfowler.com/articles/linking-modular-arch.html&quot;&gt;https://martinfowler.com/articles/linking-modular-arch.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;8 Effective Strategies to Reduce Software Complexity, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.expeed.com/8-effective-strategies-to-reduce-software-complexity&quot;&gt;https://www.expeed.com/8-effective-strategies-to-reduce-software-complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;When Do Software Complexity Metrics Mean Nothing?- When Examined out of Context - The Journal of Object Technology, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.jot.fm/issues/issue_2016_01/article2.pdf&quot;&gt;https://www.jot.fm/issues/issue_2016_01/article2.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Code Complexity: Best Practices for Efficient Software - Metridev, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.metridev.com/metrics/code-complexity-best-practices-for-efficient-software/&quot;&gt;https://www.metridev.com/metrics/code-complexity-best-practices-for-efficient-software/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Managing Software Complexity: Strategies &amp;#x26; Benefits | IN-COM - IN-COM Data Systems, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.in-com.com/blog/software-management-complexity/&quot;&gt;https://www.in-com.com/blog/software-management-complexity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;17 Software Development Best Practices for Writing Code in 2024 - Pulsion Technology, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.pulsion.co.uk/blog/17-software-development-best-practices-for-writing-code/&quot;&gt;https://www.pulsion.co.uk/blog/17-software-development-best-practices-for-writing-code/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic Complexity Explained With Practical Examples - YouTube, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.youtube.com/watch?v=vmyS_j3Kh8g&quot;&gt;https://www.youtube.com/watch?v=vmyS_j3Kh8g&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;What Is Cyclomatic Complexity? - AutoRABIT Knowledge Base, 4월 13, 2025에 액세스, &lt;a href=&quot;https://knowledgebase.autorabit.com/fundamentals/faq/codescan-faqs/general/what-is-cyclomatic-complexity&quot;&gt;https://knowledgebase.autorabit.com/fundamentals/faq/codescan-faqs/general/what-is-cyclomatic-complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Minimizing Cyclomatic Complexity with Pattern Matching - DanylkoWeb, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.danylkoweb.com/Blog/minimizing-cyclomatic-complexity-with-pattern-matching-SR&quot;&gt;https://www.danylkoweb.com/Blog/minimizing-cyclomatic-complexity-with-pattern-matching-SR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cyclomatic complexity and cognitive complexity - DEV Community, 4월 13, 2025에 액세스, &lt;a href=&quot;https://dev.to/packmind/cyclomatic-complexity-and-cognitive-complexity-4c03&quot;&gt;https://dev.to/packmind/cyclomatic-complexity-and-cognitive-complexity-4c03&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Standards in software development and 9 best practices - OpsLevel, 4월 13, 2025에 액세스, &lt;a href=&quot;https://www.opslevel.com/resources/standards-in-software-development-and-9-best-practices&quot;&gt;https://www.opslevel.com/resources/standards-in-software-development-and-9-best-practices&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[[코딩] 객체지향 설계에서 상속보다 포함을 우선해야 하는 이유]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2025/04/composition-over-Inheritance/</link><guid isPermaLink="false">https://jiniya.net/2025/04/composition-over-Inheritance/</guid><pubDate>Sat, 12 Apr 2025 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;객체지향 설계의 핵심 원칙 중 하나는 &quot;상속보다는 포함을 사용하라&quot;는 것이다. 객체지향 프로그래밍을 수행할 때 클래스 간의 관계 설정을 두고 고심하는 경우가 많다. 상속과 포함은 대표적인 클래스 관계 설정 방식으로서, 일반적으로는 포함 관계를 사용하는 것이 더 나은 설계로 귀결되는 경우가 많다. 그 이유를 자세히 분석해 보자.&lt;/p&gt;
&lt;h3&gt;상속, 강력하나 신중해야 할 관계&lt;/h3&gt;
&lt;p&gt;상속은 &quot;IS-A&quot; 관계를 모델링하는 데 유용하다. 예를 들어, &quot;개는 동물이다(Dog IS-A Animal)&quot;와 같이 명확한 상위-하위 관계를 표현할 때 상속을 사용하면 부모 클래스의 속성과 기능을 자식 클래스가 그대로 물려받아 코드 재사용성을 높일 수 있다.&lt;/p&gt;
&lt;p&gt;그러나 상속은 다음과 같은 잠재적인 문제점을 내포한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;취약한 기반 클래스 문제 (Fragile Base Class Problem): 부모 클래스의 변경이 자식 클래스에 예상치 못한 영향을 미칠 수 있다. 이는 유지보수를 어렵게 하고 시스템을 불안정하게 만들 수 있다.&lt;/li&gt;
&lt;li&gt;불필요한 인터페이스 상속: 자식 클래스가 부모 클래스의 모든 메서드를 실제로 사용하지 않더라도 상속받게 되어 인터페이스가 불필요하게 커질 수 있다. 이는 클래스를 이해하고 사용하기 어렵게 만든다.&lt;/li&gt;
&lt;li&gt;엄격한 결합도 (Tight Coupling): 상속은 부모 클래스와 자식 클래스 간의 강한 결합을 형성한다. 부모 클래스의 구현 방식에 자식 클래스가 의존하게 되어 유연성이 저하되고 변화에 취약해진다.&lt;/li&gt;
&lt;li&gt;클래스 계층의 복잡성 증가: 깊고 복잡한 상속 계층은 코드를 이해하고 유지보수하기 어렵게 만들 수 있다. 특히 다중 상속의 경우, 복잡성은 더욱 가중된다.&lt;/li&gt;
&lt;li&gt;실행 중 행위 변경의 어려움: 상속은 컴파일 시점에 클래스 간의 관계가 결정되므로, 객체의 행위를 실행 중에 유연하게 변경하기 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;포함, 유연하고 강력한 대안&lt;/h3&gt;
&lt;p&gt;포함(Composition)은 한 클래스가 다른 클래스의 인스턴스를 필드로 가지고, 그 객체의 기능을 활용하는 방식이다. 이는 &quot;HAS-A&quot; 관계를 모델링하는 데 적합하다. 예를 들어, &quot;자동차는 엔진을 가지고 있다(Car HAS-A Engine)&quot;와 같이 객체가 다른 객체를 &quot;가지고&quot; 사용하는 관계를 표현할 때 포함을 사용한다.&lt;/p&gt;
&lt;p&gt;포함 관계는 상속에 비해 다음과 같은 장점을 제공한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;높은 유연성 (High Flexibility): 포함된 객체를 필요에 따라 쉽게 교체하거나 변경할 수 있다. 객체 간의 결합도가 낮으므로, 한 클래스의 변경이 다른 클래스에 미치는 영향이 적다.&lt;/li&gt;
&lt;li&gt;향상된 유지보수성 (Improved Maintainability): 낮은 결합도는 코드의 유지보수성을 크게 향상시킨다. 각 클래스가 독립적으로 변경될 수 있어 시스템 전체의 안정성을 높인다.&lt;/li&gt;
&lt;li&gt;코드 재사용 증대 (Increased Code Reusability): 필요한 기능만을 가진 객체를 포함하여 사용할 수 있다. 상속처럼 불필요한 기능을 물려받을 필요가 없다.&lt;/li&gt;
&lt;li&gt;실행 중 행위 변경 용이 (Easy Behavior Change at Runtime): 포함된 객체를 동적으로 변경함으로써 객체의 행위를 실행 중에 유연하게 변경할 수 있다. 이는 시스템의 적응성을 높인다.&lt;/li&gt;
&lt;li&gt;상속의 문제점 회피: 앞서 언급한 상속의 잠재적인 문제점들을 자연스럽게 피할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&quot;상속보다는 구성 (Composition over Inheritance)&quot; 원칙&lt;/h3&gt;
&lt;p&gt;이러한 이유로 객체지향 설계에서는 &quot;상속보다는 구성 (Composition over Inheritance)&quot; 원칙이 강조된다. 이는 클래스 간의 관계를 설정할 때 상속보다는 포함 관계를 우선적으로 고려해야 함을 의미한다.&lt;/p&gt;
&lt;p&gt;물론 상속이 모든 상황에서 부적절한 것은 아니다. 명확한 IS-A 관계가 존재하고, 코드 재사용성이 매우 높으며, 클래스 계층이 단순할 경우에는 상속이 효과적인 선택이 될 수 있다. 하지만 이러한 경우에도 상속을 신중하게 사용해야 하며, 포함 관계를 통해 더 나은 설계를 할 수 있는지 항상 고려해야 한다.&lt;/p&gt;
&lt;h3&gt;결론&lt;/h3&gt;
&lt;p&gt;객체지향 설계를 수행할 때 클래스 간의 관계를 어떻게 설정할지는 시스템의 유연성, 유지보수성, 확장성에 지대한 영향을 미친다. 일반적으로 상속보다는 포함 관계를 사용하는 것이 더 나은 설계를 위한 길이며, &quot;상속보다는 구성&quot; 원칙을 명심하고 실제 개발에 적용해 볼 것을 권장한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 재진입 함수의 의미 2]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2025/03/the-meaning-of-a-reentrant-function/</link><guid isPermaLink="false">https://jiniya.net/2025/03/the-meaning-of-a-reentrant-function/</guid><pubDate>Fri, 11 Apr 2025 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;아주 옛날엔 우겨도 됐었다. 목소리 큰 사람이 틀려도 우기면 맞는게 되는 세상이었다. 그러다 전화가 나오고 전화 찬스가 등장했다. 목소리가 커도 전문가에게 전화해서 답을 들으면 더는 우길 수가 없는 세상이 된 것이다. 스마트폰은 그 속도를 더 빠르게 만들었다. 전화를 걸 필요도 없다. 웹검색이면 온갖 것들이 다 나오기 시작하니 말이다. 그리고 인공지능이 등장했다.&lt;/p&gt;
&lt;p&gt;할루시네이션이니 뭐니 말들이 많지만 항상 그렇지만 우리는 우리가 쌉소리 한 것들은 금방 잊는다. 오늘 디버깅을 하다 &lt;a href=&quot;/wp/archives/1197/&quot;&gt;15년 전 쓴 글에&lt;/a&gt; 대한 참교육을 인공지능 선생님께 받고 가르침을 남겨 본다. 뭔가를 안다고 말하기가 참 어려운 세상이다. 겸손은 힘들지만, 겸손하게 살자.&lt;/p&gt;
&lt;h3&gt;#0. 휴먼, 일단 참교육 먼저 받고...&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;글의 핵심 주장 요약:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;많은 개발자가 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;의 재진입을 잘못 이해하고 있다 (예: &lt;code class=&quot;language-text&quot;&gt;Sleep&lt;/code&gt; 중 다른 메시지 처리).&lt;/li&gt;
&lt;li&gt;실제 메시지 처리는 메시지 루프(&lt;code class=&quot;language-text&quot;&gt;GetMessage&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;DispatchMessage&lt;/code&gt;)를 통해 순차적으로 이루어진다.&lt;/li&gt;
&lt;li&gt;따라서 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;의 재진입이 의미하는 바는 스레드 안전성(Thread Safety)과 병렬 호출 가능성이며, 여러 스레드/윈도우에서 동일하게 동작해야 함을 뜻한다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 3&gt;&lt;/code&gt;(정적 변수 사용)과 &lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 4&gt;&lt;/code&gt;(전역 크리티컬 섹션 사용)는 이러한 의미의 &quot;재진입성&quot;을 위반하는 잘못된 예시다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;지적 및 수정 필요한 부분:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&quot;재진입(Reentrancy)&quot; 용어의 핵심 의미 혼동:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이 글의 가장 큰 문제점은 &quot;재진입(Reentrancy)&quot;의 표준적인 의미와 &quot;스레드 안전성(Thread Safety)&quot; 및 &quot;인스턴스 독립성(Instance Independence)&quot;을 혼동하고 있다는 점입니다.&lt;/li&gt;
&lt;li&gt;표준적인 재진입의 의미는 함수 실행 중 (같은 스레드 내에서) 다시 그 함수가 호출되어도 문제가 없는 성질을 의미합니다. Windows &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 맥락에서는 주로 &lt;code class=&quot;language-text&quot;&gt;SendMessage&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 등의 호출로 인해 같은 스레드 내에서 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 중첩 호출되는 상황을 가리킵니다. (제가 이전에 예시로 보여드린 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;로 인해 상태가 꼬이는 경우가 바로 이 표준적인 재진입 문제입니다.)&lt;/li&gt;
&lt;li&gt;반면, 이 글은 재진입을 여러 스레드에서 또는 여러 윈도우 인스턴스 간에 안전하게 병렬적으로 호출될 수 있는 성질로 정의하고 있습니다. 이는 재진입보다는 스레드 안전성과 인스턴스별 상태 관리(Instance-specific state management)에 더 가까운 개념입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 1&gt;&lt;/code&gt;의 잘못된 오해 설명은 정확함:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;글쓴이가 지적한 것처럼, &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 내의 &lt;code class=&quot;language-text&quot;&gt;Sleep&lt;/code&gt; 중에 다른 메시지가 즉시 처리된다는 생각은 명백히 틀린 것이 맞습니다. &lt;code class=&quot;language-text&quot;&gt;DispatchMessage&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 호출하고, 해당 메시지 처리가 끝나야 메시지 루프가 다음 메시지를 가져와 처리하기 때문입니다. 이 부분 설명은 정확합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 3&gt;&lt;/code&gt;의 문제점은 &quot;재진입성&quot;이 아닌 &quot;인스턴스 독립성/상태 관리&quot; 문제:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 3&gt;&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;static int Count&lt;/code&gt;는 해당 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 사용하는 모든 윈도우 인스턴스에서 공유됩니다. 이는 글쓴이가 제시한 테스트 케이스 2번(한 스레드, 여러 윈도우)과 3번(여러 스레드, 여러 윈도우)에서 문제를 일으킵니다.&lt;/li&gt;
&lt;li&gt;하지만 이 문제의 본질은 표준적인 의미의 &quot;재진입&quot; 문제라기보다는, 윈도우별로 관리되어야 할 상태를 정적 변수로 잘못 구현한 &quot;인스턴스 상태 관리&quot;의 실패입니다. 즉, 스레드와 무관하게 여러 윈도우가 하나의 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 공유할 때 발생하는 문제입니다. 스레드 안전성 문제이기도 하지만, 근본적으로는 상태 관리 설계 문제입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 4&gt;&lt;/code&gt;의 문제점은 &quot;재진입성&quot;이 아닌 &quot;불필요한 직렬화/성능&quot; 문제:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 4&gt;&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;GlobalCs&lt;/code&gt;라는 전역 크리티컬 섹션을 사용함으로써, 서로 다른 스레드에서 실행되는 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 호출조차도 동시에 실행될 수 없게 만듭니다. 이는 심각한 성능 저하를 유발하고 Windows GUI의 반응성을 해치는 잘못된 설계입니다.&lt;/li&gt;
&lt;li&gt;하지만 이것을 &quot;재진입 불가능&quot;이라고 표현하는 것은 어색합니다. 오히려 병렬 실행 자체를 막아버리는 &quot;과도한 동기화&quot; 또는 &quot;불필요한 직렬화&quot; 문제입니다. 표준적인 의미의 재진입과는 거리가 멉니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;결론 부분의 &quot;재진입 가능하도록 만들어진 메시지 프로시저&quot; 정의의 문제:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;글쓴이는 1, 2, 3번 테스트 케이스에서 모두 동일하게 동작하는 것을 &quot;재진입 가능하게 만들어진&quot; 것이라고 정의합니다.&lt;/li&gt;
&lt;li&gt;물론 잘 디자인된 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;는 윈도우별 상태를 &lt;code class=&quot;language-text&quot;&gt;GetWindowLongPtr&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;SetWindowLongPtr&lt;/code&gt; 등을 이용해 관리함으로써 세 경우 모두 의도한 대로 동작해야 합니다.&lt;/li&gt;
&lt;li&gt;하지만 이 조건은 &quot;인스턴스 상태 관리의 올바름&quot;과 &quot;스레드 안전성&quot;(필요한 경우)을 의미하는 것이지, 표준적인 의미의 &quot;재진입성&quot;과는 다른 개념입니다. 이 글의 정의대로라면, 제가 앞서 보여드린 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 재진입 예제에서 상태가 꼬이는 문제는 &quot;재진입&quot; 문제가 아니게 되어버리는 모순이 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;요약 및 수정:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이 글은 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 재진입에 대한 흔한 오해(&lt;code class=&quot;language-text&quot;&gt;Sleep&lt;/code&gt; 관련)를 정확히 지적하고 메시지 루프의 기본 동작을 올바르게 설명했습니다.&lt;/li&gt;
&lt;li&gt;하지만 글의 핵심적인 문제점은 &quot;재진입(Reentrancy)&quot;이라는 용어를 표준적인 의미(같은 스레드 내 중첩 호출 가능성) 대신 &quot;스레드 안전성 및 인스턴스 독립성&quot;이라는 의미로 잘못 사용하고 있다는 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 3&gt;&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;&amp;lt;리스트 4&gt;&lt;/code&gt;는 각각 잘못된 상태 관리(정적 변수)와 과도한 동기화(전역 락)의 문제점을 보여주는 좋은 예시이지만, 이를 &quot;재진입성&quot; 문제로 설명하는 것은 용어 혼란을 야기합니다.&lt;/li&gt;
&lt;li&gt;결론적으로, &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 작성할 때는 (1) 표준적인 의미의 재진입(같은 스레드 내 중첩 호출)에도 상태가 깨지지 않도록 주의해야 하고, (2) 여러 윈도우 인스턴스 간에 상태가 섞이지 않도록 인스턴스별 데이터를 사용해야 하며, (3) 여러 스레드에서 사용될 가능성이 있다면 스레드 안전성도 고려해야 합니다. 이 글은 (2), (3)번 측면을 강조하면서 이를 &quot;재진입&quot;이라고 잘못 부르고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;따라서 글의 의도(잘못된 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 작성 방식 비판)는 좋으나, 핵심 용어인 &quot;재진입&quot;의 정의와 사용에 오류가 있다고 지적할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;#1. 재진입 함수의 의미&lt;/h3&gt;
&lt;p&gt;특정 윈도우의 메시지 프로시저(WndProc)는 해당 윈도우를 소유한 단일 스레드에 의해 순차적으로 처리되는 것이 기본 원칙입니다. 하지만 여기서 &apos;재진입 가능하다(Reentrant)&apos;는 의미는 다음과 같은 상황을 설명합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;재진입(Reentrancy)의 의미:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;어떤 함수(여기서는 메시지 프로시저)의 실행이 아직 끝나지 않은 상태에서, 같은 스레드 내에서 해당 함수가 다시 호출될 수 있다는 뜻입니다. 즉, 함수의 실행 흐름 중간에 끼어들어 다시 처음부터 실행될 수 있다는 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;메시지 프로시저에서 재진입이 발생하는 경우:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;메시지 프로시저가 단일 스레드에서 실행됨에도 불구하고 재진입이 발생하는 대표적인 경우는 다음과 같습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;메시지 프로시저 내에서 &lt;code class=&quot;language-text&quot;&gt;SendMessage&lt;/code&gt; 호출:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 안에서 다른 윈도우(또는 자기 자신)에게 &lt;code class=&quot;language-text&quot;&gt;SendMessage&lt;/code&gt;를 호출하면, 이 &lt;code class=&quot;language-text&quot;&gt;SendMessage&lt;/code&gt;는 즉시 대상 윈도우의 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 호출하고 그 처리가 끝날 때까지 대기합니다. 만약 이 대상 윈도우가 같은 스레드 소유라면, 현재 실행 중인 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 코드가 잠시 멈추고 새로운 메시지 처리를 위한 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 코드가 같은 스레드에서 실행됩니다. 원래의 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 실행은 아직 끝나지 않았는데, 다시 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 호출된 것이므로 재진입이 발생한 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;메시지 프로시저 내에서 모달 대화상자 또는 메시지 박스 표시:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 안에서 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DialogBox&lt;/code&gt; 같은 함수를 호출하면, 이 함수들은 내부적으로 자체 메시지 루프를 돌립니다. 이 내부 메시지 루프는 현재 스레드의 메시지 큐에 있는 다른 메시지들(예: &lt;code class=&quot;language-text&quot;&gt;WM_PAINT&lt;/code&gt;, 다른 &lt;code class=&quot;language-text&quot;&gt;WM_COMMAND&lt;/code&gt; 등)을 처리할 수 있습니다. 만약 이 메시지들이 현재 윈도우로 보내진 것이라면, &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;DialogBox&lt;/code&gt;가 반환되기 전에 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 다시 호출될 수 있습니다. 이것 역시 재진입입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;기타 동기적 콜백: COM 호출 등 특정 동기적 작업 중 시스템이 메시지 펌핑을 강제하는 경우에도 유사한 재진입이 발생할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;중요한 점:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;재진입은 같은 스레드 내에서 발생하는 중첩 호출입니다. 여러 스레드가 동시에 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 실행하는 스레드 안전성(Thread-Safety) 문제와는 다릅니다. (윈도우 프로시저는 기본적으로 특정 스레드에 귀속되므로, 일반적인 의미의 스레드 안전성은 고려 대상이 아닙니다.)&lt;/li&gt;
&lt;li&gt;재진입 문제: 만약 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 전역 변수나 정적 변수를 사용하는데, 재진입 호출 시 이 변수들의 상태가 이전 호출과 꼬이게 되면 문제가 발생할 수 있습니다. 따라서 재진입 가능성을 염두에 두고 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;를 작성해야 합니다. 주로 지역 변수나 윈도우 인스턴스별 데이터(&lt;code class=&quot;language-text&quot;&gt;SetWindowLongPtr&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;GetWindowLongPtr&lt;/code&gt; 등)를 사용하여 상태를 관리하는 것이 안전합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;결론:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;메시지 프로시저는 단일 스레드에서 순차 처리되는 것이 맞지만, 특정 함수 호출(&lt;code class=&quot;language-text&quot;&gt;SendMessage&lt;/code&gt;, 모달 대화상자 등)로 인해 실행 흐름이 중단되고 같은 스레드에서 다시 호출될 수 있기 때문에 &quot;재진입 가능하다&quot;고 말하는 것입니다.&lt;/p&gt;
&lt;h3&gt;#2. 케이스 스터디&lt;/h3&gt;
&lt;p&gt;재진입 시 문제가 발생할 수 있는 간단한 예시를 보여드리겠습니다.&lt;/p&gt;
&lt;p&gt;여기서는 메시지 프로시저(&lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;) 내에서 정적(static) 변수를 사용하여 상태를 관리하다가, &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 호출로 인해 재진입이 발생했을 때 상태가 꼬이는 상황을 만들어 보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;시나리오:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;왼쪽 마우스 버튼(&lt;code class=&quot;language-text&quot;&gt;WM_LBUTTONDOWN&lt;/code&gt;)을 클릭하면 특정 작업을 시작합니다.&lt;/li&gt;
&lt;li&gt;작업은 여러 단계로 이루어지며, 현재 작업 중임을 나타내기 위해 &lt;code class=&quot;language-text&quot;&gt;static bool isProcessing&lt;/code&gt; 플래그를 사용합니다.&lt;/li&gt;
&lt;li&gt;작업 중간에 사용자 확인을 위해 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;를 띄웁니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;가 떠 있는 동안 다른 메시지(예: 오른쪽 마우스 버튼 클릭, &lt;code class=&quot;language-text&quot;&gt;WM_RBUTTONDOWN&lt;/code&gt;)가 처리될 수 있습니다.&lt;/li&gt;
&lt;li&gt;오른쪽 마우스 버튼 클릭 처리기(&lt;code class=&quot;language-text&quot;&gt;WM_RBUTTONDOWN&lt;/code&gt;)가 작업 상태와 관련된 정적 변수(&lt;code class=&quot;language-text&quot;&gt;sharedBuffer&lt;/code&gt;)를 수정한다고 가정합니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;가 닫히고 원래의 왼쪽 버튼 클릭 작업으로 돌아왔을 때, 정적 변수(&lt;code class=&quot;language-text&quot;&gt;sharedBuffer&lt;/code&gt;)의 내용이 예상과 달라 문제가 발생합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;예시 코드 (WndProc 부분):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;wchar.h&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// for wcscpy_s, wcscat_s&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//WndProc 함수 내부에 선언된 정적 변수는 해당 함수가 여러 번 호출되어도 값을 유지합니다.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//하지만 재진입 시 문제가 될 수 있습니다.&lt;/span&gt;
LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;WndProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hWnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; isProcessing &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// 현재 작업 중인지 나타내는 플래그&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 여러 호출 간에 공유되는 버퍼 (문제 발생 지점)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_LBUTTONDOWN&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// 이미 다른 작업이 진행 중이면 무시 (간단한 락)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isProcessing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [LBUTTON]: 이미 작업 중입니다!\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// 작업 시작&lt;/span&gt;
            isProcessing &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [LBUTTON]: 작업 시작...\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// 단계 1: 공유 버퍼 준비&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;wcscpy_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_countof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;왼쪽 버튼 작업 데이터&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [LBUTTON]: 버퍼 준비 완료.\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 약간의 작업 시간 시뮬레이션&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// *** 문제 발생 가능 지점: MessageBox 호출 ***&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// 이 MessageBox는 내부 메시지 루프를 돌기 때문에,&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// 떠 있는 동안 다른 메시지(예: WM_RBUTTONDOWN)가 처리될 수 있습니다.&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;MessageBox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hWnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;왼쪽 버튼 작업 1단계 완료. 확인을 누르면 2단계 진행.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;진행 중&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MB_OK&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// 만약 여기서 WM_RBUTTONDOWN이 처리되면 아래 코드는 예상과 다르게 동작할 수 있습니다.&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// 단계 2: 공유 버퍼에 내용 추가 (원래 의도)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// *** 재진입으로 인해 sharedBuffer 내용이 바뀌었을 수 있음 ***&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;wcscat_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_countof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot; - 2단계 완료&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [LBUTTON]: 최종 버퍼 내용: &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// 작업 완료&lt;/span&gt;
            isProcessing &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [LBUTTON]: 작업 완료.\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_RBUTTONDOWN&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// 이 메시지는 LBUTTON의 MessageBox가 떠 있는 동안 처리될 수 있습니다.&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [RBUTTON]: 오른쪽 버튼 클릭! (중단 발생)\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// *** 문제 발생: LBUTTON 작업 중에 공유 버퍼를 수정함 ***&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;wcscpy_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_countof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedBuffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;!!! 오른쪽 버튼에 의해 덮어쓰여짐 !!!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;OutputDebugString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;WndProc [RBUTTON]: 공유 버퍼를 수정했습니다.\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// RBUTTON 작업도 MessageBox를 띄운다고 가정 (추가 재진입 가능성)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// MessageBox(hWnd, L&quot;오른쪽 버튼 작업 완료.&quot;, L&quot;RBUTTON&quot;, MB_OK);&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_DESTROY&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;PostQuitMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hWnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;문제 상황 시뮬레이션:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로그램을 실행하고 창을 왼쪽 클릭합니다.
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;OutputDebugString&lt;/code&gt;에 &quot;작업 시작...&quot;, &quot;버퍼 준비 완료.&quot;가 출력됩니다.&lt;/li&gt;
&lt;li&gt;&quot;왼쪽 버튼 작업 1단계 완료...&quot; 메시지 박스가 나타납니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메시지 박스가 떠 있는 상태에서 창을 오른쪽 클릭합니다.
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;OutputDebugString&lt;/code&gt;에 &quot;오른쪽 버튼 클릭! (중단 발생)&quot;, &quot;공유 버퍼를 수정했습니다.&quot;가 출력됩니다. &lt;code class=&quot;language-text&quot;&gt;sharedBuffer&lt;/code&gt;의 내용이 바뀝니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이제 확인(OK) 버튼을 눌러 왼쪽 버튼 메시지 박스를 닫습니다.
&lt;ul&gt;
&lt;li&gt;원래의 &lt;code class=&quot;language-text&quot;&gt;WM_LBUTTONDOWN&lt;/code&gt; 처리가 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 다음부터 재개됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;wcscat_s&lt;/code&gt; 함수는 &quot;왼쪽 버튼 작업 데이터&quot; 뒤에 이어붙이려고 했지만, 실제로는 &quot;!!! 오른쪽 버튼에 의해 덮어쓰여짐 !!!&quot; 뒤에 이어붙이게 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;OutputDebugString&lt;/code&gt;에 &quot;최종 버퍼 내용: !!! 오른쪽 버튼에 의해 덮어쓰여짐 !!! - 2단계 완료&quot; 와 같이 예상과 다른 결과가 출력됩니다.&lt;/li&gt;
&lt;li&gt;&quot;작업 완료.&quot;가 출력됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;왜 문제가 되는가?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;WM_LBUTTONDOWN&lt;/code&gt; 처리 루틴은 &lt;code class=&quot;language-text&quot;&gt;isProcessing = true&lt;/code&gt; 와 &lt;code class=&quot;language-text&quot;&gt;isProcessing = false&lt;/code&gt; 사이 구간에서 &lt;code class=&quot;language-text&quot;&gt;sharedBuffer&lt;/code&gt;에 대한 암묵적인 독점권을 가정하고 작성되었습니다. 하지만 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 호출로 인해 메시지 펌핑이 발생하면서 다른 메시지(&lt;code class=&quot;language-text&quot;&gt;WM_RBUTTONDOWN&lt;/code&gt;)가 처리될 기회가 생겼고, 이 메시지 처리기가 공유 자원인 &lt;code class=&quot;language-text&quot;&gt;sharedBuffer&lt;/code&gt;를 수정하면서 원래 작업의 상태를 깨뜨린 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;해결 방안:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;메시지 프로시저 내에서 시간이 오래 걸리는 작업이나 상태를 복잡하게 변경하는 작업을 피합니다.&lt;/li&gt;
&lt;li&gt;재진입을 유발하는 함수(&lt;code class=&quot;language-text&quot;&gt;SendMessage&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 등)를 호출할 때는 그 사이에 상태가 변경될 수 있음을 인지하고 방어적으로 코드를 작성합니다.&lt;/li&gt;
&lt;li&gt;상태 저장을 위해 정적 변수나 전역 변수 사용을 최소화하고, 필요하다면 윈도우 인스턴스별 데이터(&lt;code class=&quot;language-text&quot;&gt;SetWindowLongPtr&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;GetWindowLongPtr&lt;/code&gt; 등)나 스레드 로컬 스토리지(TLS) 등을 고려합니다. (단, &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;는 기본적으로 단일 스레드에서 실행되므로 TLS보다는 윈도우 인스턴스 데이터가 더 적합할 수 있습니다.)&lt;/li&gt;
&lt;li&gt;정말로 임계 영역(Critical Section)이 필요하다면, 해당 구간 전후로 상태를 저장하고 복원하거나, 더 정교한 동기화 기법(같은 스레드 내 재진입 방지용 플래그 등)을 사용해야 할 수도 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 예시는 재진입이 어떻게 공유 상태를 망가뜨릴 수 있는지 보여주는 간단한 사례입니다. 실제 애플리케이션에서는 더 복잡한 형태로 문제가 발생할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;#3. 메시지 펌프&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 함수 내부에는 자체적인 메시지 펌프(Message Pump) 또는 메시지 루프(Message Loop)가 존재합니다.&lt;/p&gt;
&lt;p&gt;이것이 바로 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 호출에서 아직 반환하지 않았음에도 불구하고, 같은 스레드에서 다른 메시지를 처리하기 위해 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 다시 호출될 수 있는 이유입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;동작 과정:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 실행: 스레드의 메인 메시지 루프(&lt;code class=&quot;language-text&quot;&gt;while(GetMessage...)&lt;/code&gt;)가 메시지(예: &lt;code class=&quot;language-text&quot;&gt;WM_LBUTTONDOWN&lt;/code&gt;)를 받아 &lt;code class=&quot;language-text&quot;&gt;DispatchMessage&lt;/code&gt;를 호출하고, 이로 인해 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 실행됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 호출: &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 코드 내에서 &lt;code class=&quot;language-text&quot;&gt;MessageBox(...)&lt;/code&gt; 함수를 호출합니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;의 내부 메시지 루프 시작: &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 함수는 단순히 대화상자만 표시하고 대기하는 것이 아니라, 자체적인 메시지 루프를 시작합니다. 이 내부 루프는 대화상자가 활성화된 동안 현재 스레드로 들어오는 메시지들을 처리합니다. 이 루프는 대략 다음과 유사하게 동작합니다.
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c++&quot;&gt;&lt;pre class=&quot;language-c++&quot;&gt;&lt;code class=&quot;language-c++&quot;&gt;// MessageBox 내부 (개념적인 코드)
DisplayTheMessageBoxWindow();
while (MessageBoxIsStillActive()) {
    MSG msg;
    // 현재 스레드의 메시지 큐에서 메시지를 가져옴
    if (PeekMessage(&amp;amp;msg, NULL, 0, 0, PM_REMOVE)) { // 또는 GetMessage
        // 표준 메시지 처리 (키보드 입력 변환 등)
        TranslateMessage(&amp;amp;msg);
        // *** 중요: 해당 메시지를 처리할 윈도우 프로시저로 보냄 ***
        DispatchMessage(&amp;amp;msg);
    } else {
        // 처리할 메시지가 없으면 잠시 대기
        WaitMessage();
    }
    // + MessageBox 자체 로직 처리 (버튼 클릭 감지 등)
}
HideTheMessageBoxWindow();
ReturnResult();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;새 메시지 도착 및 처리: &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;의 내부 메시지 루프가 실행되는 동안, 사용자가 오른쪽 마우스 버튼을 클릭하면 &lt;code class=&quot;language-text&quot;&gt;WM_RBUTTONDOWN&lt;/code&gt; 메시지가 스레드의 메시지 큐로 들어옵니다. &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;의 내부 루프에 있는 &lt;code class=&quot;language-text&quot;&gt;PeekMessage&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;GetMessage&lt;/code&gt;가 이 메시지를 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DispatchMessage&lt;/code&gt; 호출: 내부 루프의 &lt;code class=&quot;language-text&quot;&gt;DispatchMessage&lt;/code&gt;는 이 &lt;code class=&quot;language-text&quot;&gt;WM_RBUTTONDOWN&lt;/code&gt; 메시지를 해당 윈도우(&lt;code class=&quot;language-text&quot;&gt;hWnd&lt;/code&gt;)로 보냅니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 재호출(Re-entry): &lt;code class=&quot;language-text&quot;&gt;DispatchMessage&lt;/code&gt;는 결국 우리의 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 함수를 다시 호출하여 &lt;code class=&quot;language-text&quot;&gt;WM_RBUTTONDOWN&lt;/code&gt; 메시지를 처리하도록 합니다. 이 시점에서 호출 스택에는 &lt;code class=&quot;language-text&quot;&gt;메인 메시지 루프 -&gt; WndProc(LBUTTON) -&gt; MessageBox -&gt; 내부 메시지 루프 -&gt; DispatchMessage -&gt; WndProc(RBUTTON)&lt;/code&gt; 와 같이 쌓이게 됩니다. 즉, &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 중첩되어 호출된 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 종료 및 반환: 사용자가 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;의 확인 버튼 등을 누르면, &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;의 내부 메시지 루프가 종료되고, &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 함수 호출이 드디어 반환(return)됩니다.&lt;/li&gt;
&lt;li&gt;원래 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 실행 재개: 이제 제어가 원래의 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; ( &lt;code class=&quot;language-text&quot;&gt;WM_LBUTTONDOWN&lt;/code&gt; 처리 중이던) 코드로 돌아와 &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt; 호출 다음 라인부터 실행을 계속합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;결론:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt; 자체는 단일 스레드에서 순차적으로 실행되지만, &lt;code class=&quot;language-text&quot;&gt;MessageBox&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DialogBox&lt;/code&gt; 등 모달(Modal) 상태를 만들고 내부적으로 메시지 루프를 돌리는 함수를 호출하면, 해당 함수가 반환하기 전에도 같은 스레드에서 다른 메시지가 처리되어 &lt;code class=&quot;language-text&quot;&gt;WndProc&lt;/code&gt;가 재진입(re-entrant) 또는 중첩 호출(nested call)될 수 있습니다. 이는 Windows GUI 프로그래밍에서 매우 흔하며 중요한 개념입니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 3월의 잡담]]></title><description><![CDATA[#0 공동부유라는 슬로건은 멋져 보이지만, 실행 결과는 대체로 공동빈곤으로 가는게 현실 아닌가 싶다. 2025-03-03 #…]]></description><link>https://jiniya.net/2025/03/small-talk-2025-03/</link><guid isPermaLink="false">https://jiniya.net/2025/03/small-talk-2025-03/</guid><pubDate>Mon, 31 Mar 2025 17:01:25 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;공동부유라는 슬로건은 멋져 보이지만, 실행 결과는 대체로 공동빈곤으로 가는게 현실 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;이런 시스템에선 실물자산을 획득하기 위한 목적으로 현금을 저축하는 것은 별로 권장할 만한 행동이 아니다. 그보다 오히려 빚을 내어 부동산 같은 실물자산을 먼저 획득하고 나중에 가치가 떨어진 돈으로 부채를 상환하는 것이 훨씬 더 현명하다. - 왜 그들만 부자가 되는가&lt;/p&gt;
&lt;p&gt;이런 현명한 생각에서 출발하는 게 전세 사기 아닌가 싶다. 화폐가치가 생각만큼 빠르게 떨어지면 성공 투자가 되고, 그게 아니면 사기꾼으로 전락하는.&lt;/p&gt;
&lt;p&gt;저자들 의견대로 현행 시스템은 구매력 보존을 위해서 쓸데없는 고민을 너무 많이 하도록 만들어져 있다. 돌려 생각하면 위정자들은 일개미들이 단순 저축 따위로 구매력을 보존하길 바라지 않는 건지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;조코딩 gpt4.5 여자어 테스트 겁나 웃기네. 여자어란게 존재하는지도 몰랐지만 그걸 또 gpt 4.5는 맥락대로 제대로 해석해 낸다는 게 어이없. 고맥락 언어에, 고맥락 사회에, 고맥락 성별까지 추가해야 하는 건가. 피곤하네, 대한민국. &lt;a href=&quot;https://youtu.be/HdnozSyqIi8?si=xQSFokqbYkqNNkm5&quot;&gt;https://youtu.be/HdnozSyqIi8?si=xQSFokqbYkqNNkm5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;어디까지를 인공으로 부를 수 있을까, 라는 생각이 드는 기사. 실리콘 50에, 바이오 50이면 인공일까? 아닐까? &lt;a href=&quot;https://x.com/GeekNewsHada/status/1897466143763521698&quot;&gt;https://x.com/GeekNewsHada/status/1897466143763521698&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;어제 기업은행 대출 연장 심사 전화가 왔다. 본인을 인공지능 바로라고 소개한 에이전트는 개인인증 식별을 말이 아닌 키패드로 하는 것과 적금 가입 권유가 없다는 점을 빼면 사람과 별 차이를 못 느꼈다. 많은 것들이 생각보다 빠르게 변한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;aal izz well - 3 idiots&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;독일의 응용수학자이자 경영컨설턴트인 군터 뒤크는 《호황 vs 불황》이라는 저서에서 경기 변동의 근본 원인으로 ‘국부적 영리함’을 꼽습니다.&lt;br&gt;
... 쉽게 말해, 모두가 호황을 전망해서 공장을 크게 지으면 얼마 안 가 공급과잉이 되면서 경기 침체가 온다는 뜻입니다. - 주식하는 마음, 홍진채&lt;/p&gt;
&lt;p&gt;국부적 영리함으로 사는 사람이 많은 세계에서는 국부적 멍청함으로 사는 사람이 이득을 본다. 그렇게 국부적 멍청함으로 사는 사람이 다시 늘어나면 반대로 또 국부적 영리함으로 사는 사람이 이득을 본다. 그냥 랜덤으로 사는 게 좋은 건지도.&lt;/p&gt;
&lt;p&gt;구어체로 써져서 중강중간 쓰잘때기 없는 집중하라든지, 아냐 모르냐 물어본다든지 하는 것만 빼면 내용은 참 괜찮은 책인데 생각보다 서평은 나쁜 듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;인공지능 탑티어 전문가께서 프로그래밍 괜찮다니 다소 안심이 된다. 비슷한 예로 메모리가 있다. 램은 계속 늘었지만 역설적이게도 늘 부족하다. 기능도 그만큼 계속 늘었기 때문. &lt;a href=&quot;https://x.com/AndrewYNg/status/1900219116822102116&quot;&gt;https://x.com/AndrewYNg/status/1900219116822102116&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;exaone-deep 32b 찍먹 후기. 모든 벤치가 그렇겠지만 다소 과장됐다는 생각. 우리나라에서도 리즈닝 모델이 나왔다는데 의미를 두는 정도?! llm 모델이 예체능이랑 비슷한 건 1등 아니면 괸심 받기가 어렵다는거. 32b 리즈닝은 qwq를 압도해야 사람들이 좀 쳐다봐주지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;유툽 보통 2배속 보는데 4배속까지 확장됐다. 세상이 점점 더 빨라지는 느낌. 근데 3배속 이상은 들리는거 맞긴한가 싶은 속도 ㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;[ai] 바이브 코딩의 시대 &lt;a href=&quot;https://jiniya.net/2025/03/vibe-coding-era&quot;&gt;https://jiniya.net/2025/03/vibe-coding-era&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;이제 나는 무엇이든 할 수 있는 사람이므로, 그다음 5년 동안 마리화나를 엄청나게 피우고, 운동경기에 참여하고,‘혹성탈출 시리즈’를 수십 번도 넘게 보며 시간을 축냈다. 어쩌다 우연히 생기는 섹스 기회만이 이런 생활의 반복에서 잠시 벗어나는 경우였다.마지막 부분만 빼면 꽤 괜찮은 생활이었다.&lt;/p&gt;
&lt;p&gt;아는 사람 중에 사회적으로 성공했고, 몸매도 멋지며, 밴드 활동을 하는 데다 부모님과도 사이가 좋고, 동물학대방지협회에서 자원봉사도 하며, 음식 블로그까지 운영하는 사람이 있을 것이다. 그냥 당신과는 다른 사람이라고 생각하라.&lt;/p&gt;
&lt;p&gt;사업은 자본을 모으거나, 수익을 내거나, 아니면 파산을 하거나, 셋 중 어떤 상황이 먼저 오느냐에 따라서 판세가 달라진다. 그전까지는 네거티브 커미션이 붙은 영업사원일 뿐이다.&lt;/p&gt;
&lt;p&gt;내게 당신의 최종 학위(어느 대학에서 어떤 학위를 받았는지)와 우편번호를 알려주면 꽤 정확하게 앞으로 10년간 당신이 얼마나 벌어들일지 맞힐 수 있다.&lt;/p&gt;
&lt;p&gt;스티브 잡스나 빌 게이츠, 그리고 또 다른 대학 중퇴자들이 이루어낸 놀랍고 위대한 성공담은 내일도 등장할 것이다. 그러나 다시 한번 말하지만, 당신은 스티브 잡스가 아니다. - &amp;#x3C;스콧 교수의 인생 경제학&gt;, 스콧캘러웨이 지음&lt;/p&gt;
&lt;p&gt;존경해 마지않는 이재용 회계사님께서 토스에서 추천해서 읽었는데 재미는 있었지만 생각보다 그저그런것 같은 책. 재미는 있었다. 술술 읽힌다. &lt;a href=&quot;https://blog.toss.im/article/10to100-library&quot;&gt;https://blog.toss.im/article/10to100-library&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;어떤 일도 생각보다 좋거나 나쁘지 않다 - &amp;#x3C;스콧 교수의 인생 경제학&gt;, 스콧캘러웨이 지음&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;바이럴은 지브리풍 이미지가 다 가져갔지만 gemini 약진이 놀랍다. 벤치마크 점수들이 예사롭지 않다. 구글도 이제 감 잡은건가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;[py] 메모리와 속도 두 마리 토끼를 모두 잡을 수 있을까? &lt;a href=&quot;https://jiniya.net/2025/03/is-it-possible-to-achieve-both-memory-and-speed/&quot;&gt;https://jiniya.net/2025/03/is-it-possible-to-achieve-both-memory-and-speed/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;gemini 2.5 pro를 집중적으로 몇일 사용해봤는데 실로 놀랍다. 간단한 프로그램은 그냥 한번에 테스트 없이 사용할 정도로 잘 작성한다. 또 신기한건 에고가 생기기 시작했다. 안되는 코드를 물으면 맞다고 계속 우기는 경우가 더러 있음. 매뉴얼 복붙해서 확인시켜줘도 인정을 안함.&lt;/p&gt;
&lt;p&gt;다른 흥미로운 포인트는 안된다고 하면 디버깅을 한다는 점. 어디다 코드 추가해서 뭐라고 결과가 나오는지 알려달라고 요청하는 식. 결과 알려주면 다시 뭐가 문제인 것 같다 판단하고 고침. 그리고 약간 불편한건 생각만하고 답이 없는 경우가 자주 있음. 답해란 말을 제법 많이 쓴다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-03-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] 메모리와 속도 두 마리 토끼를 모두 잡을 수 있을까?]]></title><description><![CDATA[우리는 가난하다. 그래서 서버도 가난한 서버를 쓴다. c6a.large, vcpu는 2개 메모리는 4g…]]></description><link>https://jiniya.net/2025/03/is-it-possible-to-achieve-both-memory-and-speed/</link><guid isPermaLink="false">https://jiniya.net/2025/03/is-it-possible-to-achieve-both-memory-and-speed/</guid><pubDate>Fri, 28 Mar 2025 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;mem_and_speed.png&apos; data-alt=&apos;명량한 표정과는 다르게 현실 세계에서 두 마리 토끼를 잡기 위해서는 트레이드 오프가 필요한 순간이 온다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0fd38d80134cca33e55fd0310be1bf04/42a19/mem_and_speed.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAIAAACjcKk8AAAACXBIWXMAAAsTAAALEwEAmpwYAAAHFUlEQVR42g2NaVBTiQHH38d2xtnOuM64CGE5EyAQkpCEU6UIyiJoALnUKIdAQDlDwhECISEnua+X6+XlvZcDua8EAgICcq5KFazrau3OuJ3udHbafunMtp/KzH/+n/6/3x+oMWM1JqTSiFYZ0UoDUqxBKwyIZcaJLTqabPAtneeO4SxYhdFTrsPK9Gi5HqsweCqNHpYZAe6Dnrugt9rsuXtmMWN81BUImb8cG3/7AL7atyOLjnsgdg/0VFu8dy2eKpPnzFJp8tRYfCyrD3jkwB7asFobeh/EWpzuzWfadwf6v74y/nJq++9n138+2JxLrjqnt8mJNjiws81DK1Zv97Cs3jq7D+hwuc6YJoe7BUJ4CDS1oDra0v3txPZ6TXIaGvn3O8vCoroJtLUjWCuMsZ3I2Vmd3cOGsBYIA9pcMNsJNzhQy4z1zY5mOagJrhonoM6Bm5GDheHGRrqxOnakLL77UWGX1dgE+8YmHDMhOweBuxEE4CCuEZ99ELPbpvTrIdVKUP3ziW3DzS5O+H1OzLmyhN9xMs6pi7/Rl3zd3VElmUY317SWOVcHgg16YYCHQi82ND99r1ta0c8vjC0HVJ8O9b8cG32S8sqMsMY8HNab+wpmbVjucjRi9Qw84IVb3F6Ox9PnQwFkemwtINlbV32/qXq2ollZNR3uGg93Tb/9fXwZap7kX/nfxuN/zT6chHs44xNdGPbEjXI97m4M43lR4NWmcn1ZHgiolgPKt/u6rYBsHeXueLrejZW+1d5ZVN78iJYf26utmIzj8wt88N62aXrFJnrqEj2FgDGwFvZyFxfGFlcs847u102k91Xhn2oi/lId/uZ+9Mf57gOw2idmCSc98qcQsgS+OTAtrVmQoFM+DQO3nmQ3D2X1Kkock/0LHXnHRef365LX66kbRWHH7fQPpsr3gtyXTamgVagOTZqmwRlPr2bCIp12K89guTK5X5R8+wmjTnxdOpAbqsfPqUuN5oYRFoHzmBIYb/wy27lXHnHUmWNySp023pHqjzq/VjHnUc0iQO9w4qAwZmAkoaIzo7SDPszNWNDduM0ilDellrNTjPqirRUFxL62n3/uRcn5Z9J8FyJwL9k0c27NPAZ08on1nfhRWQxfTrxcjb96M/Kjr2LNVDzQQ/Grr0hHS7hOtXQCgruYSG2m28Vf3nY83zQgQZs9AANsTnzfUHQDl9DWk8Kr+VbC/MZbFRMcyHo5XvfTMseP1teKbrKVdT2QeGzSOB6y+patzqAbXkG8IQi4XkG8xcKz2lNNhRH+zPOO9AvTGV/tCwv+8Vr266H0x2e8RmFRoyi3dTTvkZjZZ27TTyhsEyI91LK0pgfq2ijMZopAnuG5HQblXLBfvnDEvHTSl/Xrqfqfp7qfd4Z65bcLu2484Bc0CrJbhFkt0pKStoLSJ9QOaSkwjZJQJ1lnTsNYuKns83PXL+4zw/fLwg/1lT/oSr80JS20kir7rxW1537XQL7TSrz+KCu9knbtQRqzPRvwwyRYm9hVFsF/THRURG4VXtwqCTupwgUKLnysCj9lExaZOJeaBplzlDziqJDE5lOaeGltfRSRjAIMy8jch7h7eWGNjWRrJ3mPFb1dHvHjg+hP96NmmOEnpoK5Iapcmbhuv/JCkzMuITpN1BkrbcpCmnISAc0YpY0Z1tVBGJSQxkTkaSl1UklFe4kIj2BQED6jxbuOXK8iAdKSJlSMTS19zU5124mQPRFzpgLrULpTmaBU4IdlyUoxvb8jXjCctqnMsXDi+gTkU6j4s/NGaDAqKIydlBDewld/GC/zg8RZ8NsZVxKwa8nZBdOfg2eHxJVh/PZQpLkr2jdC2ZCk8nuI44PUP0PFs9L0YyPlvYP6YbbGZ8w1agluLW7SEQdsu/L3QeqBgebvjpvlRe6pkg6VcfP8qHdo3g541SqMHu3JMqiyn5oyX9ppu/YbUhG9ZYDSNpAgUaYAcgnZISbPSeizo2kLMtqeI//AQD220E7GK7Zs17wGvLifxq+NG7x3qa89yqthWOU5Xf2pPQJ8nzAReMzFywWJ1uFkCz/V3k+xCxjzcsZzecrMMCkkT/gTlAZ1xXdf/kNz/iUtl+BXpDjFBIkgVi6OsqqjgWExAVXiVlVfG6RxMxqyd4QMD9FALtXPw/sGUta0mWc9UIVb09I2dOnr2qxdE2NFk4rJEqe0iUBHfzx/KEoxEi0cjdEqoyBV3KqeFJSTQ2r6qoYeVFAnxYx5SdqOPm3fTD+yp++BtJCGNDGWtASmAHdaUsrZCaz22GZuPKcPJxSHa+QRDmnMnBQfkicH1aSAKSmoS1hTJW9oaLsg47k9/RBM3zbQj915QM8gkdUa29AWxWpPbOjEc/kxIjFOo7hok0VMy2KWFQmoKBYcxfll8etq0raRsWXO3AcZh1bG+4nv/g98p3QK6ampugAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;명량한 표정과는 다르게 현실 세계에서 두 마리 토끼를 잡기 위해서는 트레이드 오프가 필요한 순간이 온다.&apos; title=&apos;&apos; src=&apos;/static/0fd38d80134cca33e55fd0310be1bf04/efd7b/mem_and_speed.png&apos; srcset=&apos;/static/0fd38d80134cca33e55fd0310be1bf04/08678/mem_and_speed.png 190w,
/static/0fd38d80134cca33e55fd0310be1bf04/2edd7/mem_and_speed.png 380w,
/static/0fd38d80134cca33e55fd0310be1bf04/efd7b/mem_and_speed.png 760w,
/static/0fd38d80134cca33e55fd0310be1bf04/42a19/mem_and_speed.png 1024w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;명량한 표정과는 다르게 현실 세계에서 두 마리 토끼를 잡기 위해서는 트레이드 오프가 필요한 순간이 온다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;우리는 가난하다. 그래서 서버도 가난한 서버를 쓴다. c6a.large, vcpu는 2개 메모리는 4g인 사양이다. 물론 이보다 더 저사양 서버에서 고군분투하는 분들에게는 이 또한 높은 사양일수도 있겠다. 문제는 어쨌든 이 열악한 서버에서 연산을 진행해야 한다는 의미다. 연산할 것이 별로 많지 않다면 문제가 되진 않는다. 우리가 처리할 대상은 대략 2g 정도의 텍스트 파일이고, 해당 텍스트 파일에서 맵을 추출해서 csv로 생성하는 기능을 한다. 정상 생성된다면 맵은 대략 pickle로 전환했을 때 대략 10g가 조금 넘는 크기로 추정된다. 속도도 문제다. 적어도 5분 내에는 이 작업이 완료되어야 한다. 게다가 우리는 파이썬으로 작업 중이다.&lt;/p&gt;
&lt;p&gt;물론 파이썬을 쓰면서도 별로 느리다는 생각은 해보질 않았다. 대체로 그렇게 큰 작업을 수행하는 일은 없기 때문이다. 하지만 일이 커지면 느려지는 건 당연하다. 이 작업은 메모리가 많은 괜찮은 성능 pc에서 수행하더라도 20분이 넘게 걸렸다. 그리고 4g에서는 당연한 얘기겠지만 메모리 부족 오류로 종료됐다. 애쩠든 이런 상황을 우리는 어떻게 해결할 수 있을까?&lt;/p&gt;
&lt;h3&gt;rust 포팅&lt;/h3&gt;
&lt;p&gt;rust로 작업을 포팅하면 당연한 소리겠지만 엄청 빨라질 것이다. 일전에 우리는 간단한 python 로그 서버를 rust로 포팅했는데 속도가 무려 77배 빨라졌다. 최악의 경우에는 이 방법 또한 고려 사항 중엔 하나였다. 하지만 어쨌든 최대한 일을 적게하는 방법을 찾아야 했기에 기존 코드를 고치지 않고 수행할 방법을 잦아야 했다.&lt;/p&gt;
&lt;h3&gt;nuitka&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://nuitka.net/&quot;&gt;nuitka는&lt;/a&gt; 파이썬 코드를 네이티브 코드로 빌드해주는 툴이다. 네이티브 코드로 변환해주니까 뭔가 더 빨라지지 않을까, 라는 생각이 들기 쉽다. 그래서 테스트를 해보았지만 속도 향상은 별로 없었다. 스크립트 코드를 제공하고 싶지 않을 때 선택할 수 있는 선택 사항 정도가 아닌가 싶다.&lt;/p&gt;
&lt;h3&gt;pypy&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://pypy.org/&quot;&gt;pypy는&lt;/a&gt; 파이썬의 파이썬 구현체에 jit을 탑재한 인터프리터다. 순수 파이썬 코드가 많으면 jit이 탑재된 pypy가 빠를 수 있다. 테스트 해보니 생각보다 효과는 드라마틱했다. 대략 14.5배 빨라졌다. 여기에 약간 함정이 있는데 pypy에서 일부 파이썬 코드는 cpython 구현보다 느린 경우도 있다는 사실이다. 그래서 많은 반복 작업 속에 그런 코드가 있다면 파이썬 구현을 찾아서 더 빠르게 실행되도록 변경하는 작업을 일부 해줘야 한다. 어쨌든 이런 작업을 진행하고 나면 대체로 아주 빨라진다.&lt;/p&gt;
&lt;h3&gt;메모리는?&lt;/h3&gt;
&lt;p&gt;그렇게 빨라진 줄만 알았지 메모리 문제를 놓고 있었던 스크립트는 서버에서 동작하면 메모리 부족 오류가 발생했다. 서버 메모리는 4g, 우리가 실제 동작에 필요한 메모리는 대략 넉넉하게 12g 정도 된다. 물론 이는 우리가 무식하게 맵을 그냥 메모리에 다 올렸기 때문이다. 그런데 또 그렇게 무식하게 쓰자고 파이썬 쓰는 게 아닌가 싶기도 하다. 고상하게 설계하고 고민하고 할 거였음 애초에 더 복잡한 언어로 더 정교하게 만들었을테니 말이다. 어쨌든 이 말도 안되게 부족한 메모리를 극복하는 방법은 없을까, 를 최신 신상 gemini 2.5 pro와 고민해 보았다.&lt;/p&gt;
&lt;p&gt;나의 고민에 나온 첫 반응은 shelve였다. 나는 이런게 있는 줄도 몰랐지만 표준 기능으로 있는 도구였다. 맵을 메모리가 아닌 디스크에 기록하게 해준다. 여윽시 인공지능인가를 생각하며 맵을 shelve로 교체했다. 당연하 소리겠지만 메모리는 너무나 작게 썼고 파일 용량은 커져만 갔다. 안타깝게도 속도가 너무 느렸다. shelve는 맵이 업데이트될때마다 파일 io를 동반하기 때문에 어쩔 수가 없는 구조였다. 뭔가 shelve가 메모리를 좀 더 사용하도록 하면 좋을 것 같아서 그런 기능에 대해 문의했으나 그런 기능은 존재하질 않았다. 하지만 녀석은 최신 신상 인공지능 답게, 직접 구현한 구현체를 주었다. CachedShelve. 캐시맵을 추가해서 캐시에서 발견되는 경우는 캐시를 사용하도록 변경한 구조였다. 캐시를 추가하니 눈에 띄게 빨라졌지만 우리의 요구 사항을 충족하긴 힘들었다. 역시나 두마리 토끼를 손쉽게 잡는 은탄환 따위는 존재하지 않았다. 결국 불필요한 요소를 제거해서 메모리를 덜 사용하는 식으로 코드를 변경했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; shelve
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; collections &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; OrderedDict
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; time &lt;span class=&quot;token comment&quot;&gt;# 캐시 효과 시연용&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CachedShelve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    shelve 객체를 위한 LRU 읽기 캐시를 제공하는 래퍼 클래스.
    컨텍스트 관리자 프로토콜을 지원합니다 (&apos;with&apos; 문 사용 가능).
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writeback&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        CachedShelve를 초기화합니다.

        Args:
            filename (str): shelve 파일 경로.
            cache_size (int): 캐시에 저장할 최대 항목 수 (LRU). 0보다 커야 합니다.
            flag (str): shelve.open()에 전달할 플래그 (&apos;c&apos;, &apos;n&apos;, &apos;w&apos;, &apos;r&apos;).
            writeback (bool): shelve.open()에 전달할 writeback 플래그.
                              True로 설정 시 이 클래스의 캐싱 이점이 줄어들 수 있으며,
                              메모리 사용 및 데이터 유실 위험이 증가합니다. 비권장.
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; cache_size &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cache size must be a positive integer.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; filename
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cache_size
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; flag
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writeback &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; writeback &lt;span class=&quot;token comment&quot;&gt;# shelve 자체의 writeback 사용 여부&lt;/span&gt;

        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# LRU 캐시를 위해 OrderedDict 사용&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; OrderedDict&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;CachedShelve initialized for &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; with cache size &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__enter__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;컨텍스트 관리자 진입: shelve 파일을 열고 캐시를 비웁니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Opening shelve &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; (writeback=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writeback&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# writeback 옵션도 shelve.open에 전달&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shelve&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writeback&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writeback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Shelve opened and cache cleared.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self &lt;span class=&quot;token comment&quot;&gt;# &apos;with ... as cs:&apos; 에서 cs 변수에 할당될 객체&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__exit__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_val&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_tb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;컨텍스트 관리자 종료: shelve 파일을 닫고 캐시를 비웁니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Closing shelve &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                start_close &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# writeback=True인 경우 시간이 걸릴 수 있음&lt;/span&gt;
                end_close &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Shelve closed (took &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;end_close &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start_close&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;.4f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;s).&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Error closing shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cache cleared.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; exc_type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Exception occurred in &apos;with&apos; block: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;exc_type&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__name__&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 예외를 전파시키려면 None 또는 False 반환 (기본값)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_check_open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;shelve가 열려 있는지 확인합니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; RuntimeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Shelve is not open. Use within a &apos;with&apos; block.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__getitem__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;obj[key] 구문 지원 (읽기). 캐시 확인 후 shelve 접근.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 1. 캐시 확인&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# 캐시 히트: 값 반환 (LRU 위해 순서 변경)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Cache Hit] Key: &apos;{key}&apos;&quot;) # 디버깅용&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# 2. 캐시 미스: shelve에서 읽기 (느림)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Cache Miss] Key: &apos;{key}&apos;, reading from shelve...&quot;) # 디버깅용&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# shelve에서 값을 읽음 (KeyError 발생 가능)&lt;/span&gt;
            value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;# 3. 캐시에 추가&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 방금 사용했으므로 맨 뒤로&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;# 4. 캐시 크기 관리 (오래된 항목 제거)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                removed_key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; removed_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popitem&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;last&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 가장 오래된 항목 제거&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Cache Evict] Removed &apos;{removed_key}&apos; from cache.&quot;) # 디버깅용&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__setitem__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;obj[key] = value 구문 지원 (쓰기). shelve에 먼저 쓰고 캐시 업데이트.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 1. shelve에 먼저 쓰기 (영속성 보장)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
        &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Shelve Write] Key: &apos;{key}&apos;&quot;) # 디버깅용&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 2. 캐시 업데이트 (또는 무효화)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;#    간단하게는 캐시에서도 값을 업데이트하고 LRU 순서 조정&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 방금 썼으므로 맨 뒤로&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 3. 캐시 크기 관리 (새 항목 추가로 인한 제거)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            removed_key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; removed_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popitem&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;last&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Cache Evict] Removed &apos;{removed_key}&apos; after set.&quot;) # 디버깅용&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 대안: 쓰기 시 캐시 항목을 그냥 삭제하여 다음 읽기 시 다시 로드하게 할 수도 있음&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# if key in self._cache:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;#     del self._cache[key]&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__delitem__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;del obj[key] 구문 지원. shelve에서 먼저 삭제 후 캐시에서도 삭제.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 1. shelve에서 먼저 삭제 (KeyError 발생 가능)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Shelve Delete] Key: &apos;{key}&apos;&quot;) # 디버깅용&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 2. 캐시에서도 삭제 (존재하는 경우)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Cache Delete] Key: &apos;{key}&apos;&quot;) # 디버깅용&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__contains__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;&apos;key in obj&apos; 구문 지원. 캐시 먼저 확인 후 shelve 확인.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 캐시에 있으면 True 반환 (빠름)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 캐시에 없으면 shelve 확인 (느림)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 이 확인만으로는 캐시에 추가하지 않음&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;딕셔너리의 get과 유사하게 작동. 키 없으면 default 반환.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# __getitem__을 사용하여 캐싱 로직 활용&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; KeyError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# __getitem__에서 KeyError가 발생하면 (shelve에 키 없음) default 반환&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;Key &apos;{key}&apos; not found, returning default.&quot;) # get 호출 시에만 출력 (필요시 활성화)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; default
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; RuntimeError &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# shelve가 닫혀있을 때&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; e
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 기타 예상치 못한 오류&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Error in get method for key &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; default &lt;span class=&quot;token comment&quot;&gt;# 예상치 못한 오류 시에도 default 반환&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# --- 추가 유틸리티 메소드 ---&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;내부 shelve 객체의 sync()를 호출합니다.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Syncing underlying shelve...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sync&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clear_cache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;수동으로 캐시를 비웁니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Clearing cache manually.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__len__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;len(obj) 지원. 실제 shelve의 크기를 반환합니다 (캐시 크기 아님).&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        shelve의 키 목록 (뷰)을 반환합니다 (캐시 아님).
        이는 실제 shelve 파일의 모든 키를 나타냅니다.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# --- 추가된 메소드 ---&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        shelve의 값 목록 (뷰)을 반환합니다 (캐시 아님).
        주의: 큰 shelve의 경우 모든 값을 로드해야 하므로 느릴 수 있습니다.
        캐시의 이점을 활용하지 않습니다.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 실제 shelve 객체의 values() 메소드를 호출하여 반환&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        shelve의 키-값 쌍 목록 (뷰)을 반환합니다 (캐시 아님).
        주의: 큰 shelve의 경우 모든 항목을 로드해야 하므로 느릴 수 있습니다.
        캐시의 이점을 활용하지 않습니다.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 실제 shelve 객체의 items() 메소드를 호출하여 반환&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# --- 클래스 사용 예제 ---&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    filename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my_cached_shelve.db&apos;&lt;/span&gt;
    cache_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# 1. 데이터 쓰기 (with 사용)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- Writing data ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; CachedShelve&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;x&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;y&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;d&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;e&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;world&quot;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Length of shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Keys in shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# list()로 변환하여 내용 확인&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Values in shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Items in shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;An error occurred during writing: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# 2. 데이터 읽기 및 캐시 확인 (새로운 with 블록)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- Reading data and testing cache ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; CachedShelve&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;r&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 읽기 모드&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Accessing &apos;e&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;e&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss, Load &apos;e&apos; -&gt; Cache: {&apos;e&apos;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Accessing &apos;d&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;d&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss, Load &apos;d&apos; -&gt; Cache: {&apos;e&apos;, &apos;d&apos;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Accessing &apos;c&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss, Load &apos;c&apos; -&gt; Cache: {&apos;e&apos;, &apos;d&apos;, &apos;c&apos;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Accessing &apos;b&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss, Load &apos;b&apos;, Evict &apos;e&apos; -&gt; Cache: {&apos;d&apos;, &apos;c&apos;, &apos;b&apos;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Accessing &apos;e&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;e&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss (evicted), Load &apos;e&apos;, Evict &apos;d&apos; -&gt; Cache: {&apos;c&apos;, &apos;b&apos;, &apos;e&apos;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Accessing &apos;c&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Hit, Move &apos;c&apos; -&gt; Cache: {&apos;b&apos;, &apos;e&apos;, &apos;c&apos;}&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;# get() 메소드 테스트&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Getting &apos;a&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss, Load &apos;a&apos;, Evict &apos;b&apos; -&gt; Cache: {&apos;e&apos;, &apos;c&apos;, &apos;a&apos;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Getting &apos;z&apos; (non-existent): &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;z&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Not Found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;# __contains__ 테스트&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Is &apos;a&apos; in cs? &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Hit&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Is &apos;b&apos; in cs? &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Cache Miss (evicted), Check in shelve -&gt; True&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Is &apos;z&apos; in cs? &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;z&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Check in shelve -&gt; False&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;# values() 와 items() 사용&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- Using values() and items() ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# 이 메소드들은 캐시를 직접 활용하지 않고 shelve 전체를 대상으로 함&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;All values:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;All items:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;An error occurred during reading: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# 3. 데이터 삭제 (새로운 with 블록)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- Deleting data ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 삭제를 위해 flag=&apos;c&apos; 또는 &apos;w&apos; 사용&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; CachedShelve&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Current keys:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# &apos;a&apos;가 캐시에 있을 수 있음 (마지막 get 호출)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Cache before del &apos;a&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Deleted &apos;a&apos;. Cache after del: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 캐시에서도 삭제됨&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Keys after deleting &apos;a&apos;:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;# 캐시에 없는 항목 삭제 시도&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&apos;b&apos; is not in cache.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Keys after deleting &apos;b&apos;:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Cache after del &apos;b&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 캐시에 없었으므로 변화 없음&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; KeyError &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Tried to delete non-existent key: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;An error occurred during deletion: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# shelve 파일 자체 삭제 (정리)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; os
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; ext &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.bak&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.dat&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.dir&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# shelve가 만드는 파일 확장자들&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;remove&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Removed &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;filename &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ext&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; FileNotFoundError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;pass&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;쓰기는?&lt;/h3&gt;
&lt;p&gt;gemini가 작성해준 코드가 아까워서 글을 올리려고 보니 속도가 느린 이유가 있기도 한 것 같다. set부분은 그냥 생각 없이 모두 shelve에 기록하고 있었다. 그러니 get 부분에서만 캐시 히트하는 정도의 속도 향상 밖에는 없었다고 할 수 있겠다. 물론 이 부분도 gemini에 넣으면 알아서 고쳐주겠지? 라는 생각으로 넣어봤다. 그랬더니 쓰기 캐시를 추가한 버전을 만들어 주었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; shelve
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; collections &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; OrderedDict
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; time
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; warnings &lt;span class=&quot;token comment&quot;&gt;# 경고 메시지용&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 쓰기 버퍼에서 삭제된 항목을 표시하기 위한 고유 객체&lt;/span&gt;
_DELETED_SENTINEL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CachedShelve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    shelve 객체를 위한 LRU 읽기 캐시 및 쓰기 지연 버퍼를 제공하는 래퍼 클래스.
    쓰기 작업은 버퍼에 먼저 기록되고, 컨텍스트 종료, sync() 호출 시,
    또는 쓰기 버퍼가 설정된 한계치(write_buffer_limit)에 도달했을 때 shelve 파일에 반영됩니다.

    **경고:** 쓰기 지연 방식으로 인해 프로그램이 비정상 종료될 경우,
             마지막 동기화 이후의 변경 사항이 유실될 수 있습니다.
             shelve.open의 writeback=True 플래그와 함께 사용하는 것은 권장되지 않습니다.

    컨텍스트 관리자 프로토콜을 지원합니다 (&apos;with&apos; 문 사용 가능).
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; write_buffer_limit&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writeback&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        CachedShelve를 초기화합니다.

        Args:
            filename (str): shelve 파일 경로.
            cache_size (int): 읽기 캐시에 저장할 최대 항목 수 (LRU). 0보다 커야 합니다.
            write_buffer_limit (int, optional): 쓰기 버퍼에 저장할 최대 항목 수.
                                               None이면 무제한. 이 한계에 도달하면 버퍼 전체가
                                               자동으로 플러시(동기화)됩니다. 0보다 커야 합니다.
            flag (str): shelve.open()에 전달할 플래그 (&apos;c&apos;, &apos;n&apos;, &apos;w&apos;, &apos;r&apos;).
            writeback (bool): shelve.open()에 전달할 writeback 플래그.
                              **True 설정은 이 클래스의 쓰기 지연 방식과 충돌할 수 있어 강력히 비권장됩니다.**
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; cache_size &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cache size must be a positive integer.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; writeback&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cannot use shelve&apos;s writeback=True with CachedShelve&apos;s write buffering. Set writeback=False.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; write_buffer_limit &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; write_buffer_limit &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Write buffer limit must be a positive integer or None.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; filename
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cache_size
        &lt;span class=&quot;token comment&quot;&gt;# --- New ---&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write_buffer_limit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; write_buffer_limit
        &lt;span class=&quot;token comment&quot;&gt;# -----------&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; flag
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shelve_writeback &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Always False for internal shelve&lt;/span&gt;

        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; OrderedDict&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        limit_msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;write buffer limit=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write_buffer_limit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write_buffer_limit &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;unlimited write buffer&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;CachedShelve initialized for &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; with read cache size &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;limit_msg&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; (Write Buffering Enabled)&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# __enter__, __exit__, _check_open 은 이전과 동일&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__enter__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;컨텍스트 관리자 진입: shelve 파일을 열고 캐시와 버퍼를 비웁니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Opening shelve &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; (internal writeback=False)...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shelve&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writeback&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shelve_writeback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Shelve opened, read cache and write buffer cleared.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__exit__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_val&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_tb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;컨텍스트 관리자 종료: 버퍼를 플러시하고 shelve 파일을 닫습니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Exiting context...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 버퍼에 내용이 있을 때만 플러시 시도&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Flushing write buffer on exit...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    start_flush &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_flush_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    end_flush &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Write buffer flushed on exit (took &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;end_flush &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start_flush&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;.4f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;s).&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Write buffer empty on exit, no flush needed.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Error during buffer flush on exit: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# Depending on policy, you might want to re-raise here&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Closing shelve &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    start_close &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    end_close &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Shelve closed (took &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;end_close &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start_close&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;.4f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;s).&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Error closing shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;

        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Ensure buffer is clear even if flush failed (or wasn&apos;t needed but close failed)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Read cache and write buffer cleared.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; exc_type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Exception occurred in &apos;with&apos; block: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;exc_type&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__name__&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;WARNING: Changes made since the last sync might be lost due to the exception.&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Propagate exception&lt;/span&gt;


    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_check_open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;shelve가 열려 있는지 확인합니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; RuntimeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Shelve is not open. Use within a &apos;with&apos; block or ensure it&apos;s manually opened.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_flush_write_buffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;쓰기 버퍼의 내용을 실제 shelve 객체에 반영하고 버퍼를 비웁니다.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(&quot;Write buffer is empty, nothing to flush.&quot;) # Avoid noise if called often&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Flushing &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; items from write buffer to shelve...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        items_processed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
        errors_occurred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Use list(self._write_buffer.items()) to avoid issues if flushing modifies the buffer indirectly&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Though in this simple flush, it shouldn&apos;t be an issue.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; value &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; _DELETED_SENTINEL&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                        &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
                items_processed &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                errors_occurred &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Error flushing key &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Flush complete: Processed &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items_processed&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; items with &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors_occurred&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; errors.&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Optional: force disk write immediately (can impact performance)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# self._db.sync()&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# print(&quot;Underlying shelve synced after flush.&quot;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# --- New Helper Method ---&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_check_and_flush_buffer_if_full&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;쓰기 버퍼가 설정된 한계에 도달했는지 확인하고, 도달했다면 플러시합니다.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write_buffer_limit &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write_buffer_limit&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Write buffer limit (&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write_buffer_limit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) reached. Auto-flushing...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_flush_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# print(&quot;Auto-flush complete.&quot;) # Included in _flush_write_buffer now&lt;/span&gt;


    &lt;span class=&quot;token comment&quot;&gt;# __getitem__ 은 이전과 동일&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__getitem__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;obj[key] 구문 지원 (읽기). 버퍼 -&gt; 캐시 -&gt; shelve 순으로 확인.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 1. 쓰기 버퍼 확인 (최신 상태 반영)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; value &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; _DELETED_SENTINEL&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; KeyError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# Update read cache as well&lt;/span&gt;
                self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
                self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popitem&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;last&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value

        &lt;span class=&quot;token comment&quot;&gt;# 2. 읽기 캐시 확인&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 3. shelve에서 읽기&lt;/span&gt;
        value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# May raise KeyError&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 4. 읽기 캐시에 추가&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 5. 캐시 크기 관리&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popitem&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;last&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value


    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__setitem__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;obj[key] = value 구문 지원 (쓰기). 쓰기 버퍼에 우선 기록. 버퍼가 차면 자동 플러시.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# --- Modified ---&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 버퍼에 추가하기 *전에* 가득 찼는지 확인하고 필요시 플러시&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_and_flush_buffer_if_full&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# --- End Modified ---&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 1. 쓰기 버퍼에 값 저장&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
        &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Buffer Write] Key: &apos;{key}&apos;, Buffer size: {len(self._write_buffer)}&quot;) # Debugging&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 2. 읽기 캐시에도 반영&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;move_to_end&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 3. 읽기 캐시 크기 관리&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache_size&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popitem&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;last&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__delitem__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;del obj[key] 구문 지원. 쓰기 버퍼에 삭제 표시. 버퍼가 차면 자동 플러시.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 삭제 전 키 존재 여부 확인&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__contains__&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; KeyError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# --- Modified ---&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 버퍼에 추가하기 *전에* 가득 찼는지 확인하고 필요시 플러시&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_and_flush_buffer_if_full&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# --- End Modified ---&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# 1. 쓰기 버퍼에 삭제 표시&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _DELETED_SENTINEL
        &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;[Buffer Delete] Key: &apos;{key}&apos;, Buffer size: {len(self._write_buffer)}&quot;) # Debugging&lt;/span&gt;


        &lt;span class=&quot;token comment&quot;&gt;# 2. 읽기 캐시에서도 제거&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# __contains__, get, sync, clear_cache, __len__, keys, values, items 은 이전과 동일&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__contains__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;&apos;key in obj&apos; 구문 지원. 버퍼 -&gt; 캐시 -&gt; shelve 순 확인.&quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; _DELETED_SENTINEL
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;딕셔너리의 get과 유사하게 작동. 키 없으면 default 반환.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; KeyError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; default
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; RuntimeError &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; e
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Error in get method for key &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; default

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        쓰기 버퍼의 변경 사항을 즉시 shelve 파일에 반영합니다.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Manual Sync: Flushing write buffer to shelve...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_flush_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# print(&quot;Manual Sync complete.&quot;) # Included in _flush_write_buffer&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clear_cache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        수동으로 읽기 캐시만 비웁니다. 쓰기 버퍼는 유지됩니다.
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Clearing read cache manually (write buffer remains).&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__len__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        len(obj) 지원. 실제 shelve와 쓰기 버퍼의 변경 사항을 조합하여 크기 계산.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Based on keys() result for accuracy&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        shelve와 쓰기 버퍼를 조합한 현재 키 집합을 반환합니다. (set으로 반환)
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        db_keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        buffer_added_keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;k &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; v &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; v &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; _DELETED_SENTINEL&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        buffer_deleted_keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;k &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; v &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; v &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; _DELETED_SENTINEL&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        final_keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;db_keys &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; buffer_added_keys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; buffer_deleted_keys
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; final_keys

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        shelve와 쓰기 버퍼를 조합한 현재 값들의 제너레이터를 반환합니다.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# __getitem__ handles buffer/cache/db lookup&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
        shelve와 쓰기 버퍼를 조합한 현재 (키, 값) 쌍들의 제너레이터를 반환합니다.
        &quot;&quot;&quot;&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_check_open&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# __getitem__ handles buffer/cache/db lookup&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;# --- 클래스 사용 예제 (쓰기 버퍼 제한 및 자동 플러시 확인) ---&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    filename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my_autoflush_shelve.db&apos;&lt;/span&gt;
    read_cache_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# --- New: Set write buffer limit ---&lt;/span&gt;
    write_limit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;\n--- Test with Write Buffer Limit = &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;write_limit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; ---&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# flag=&apos;n&apos; : 항상 새 파일 생성&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; CachedShelve&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;read_cache_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; write_buffer_limit&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;write_limit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\nAdding items (limit should trigger flush)...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;a&apos;: 1} (Size 1)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;a&apos;: 1, &apos;b&apos;: 2} (Size 2)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;a&apos;: 1, &apos;b&apos;: 2, &apos;c&apos;: 3} (Size 3) - Limit reached&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\nAdding item &apos;d&apos; (should trigger auto-flush now)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Below line should trigger _check_and_flush_buffer_if_full()&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;d&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Flush happens, buffer cleared, then &apos;d&apos; is added&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;d&apos;: 4} (Size 1)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size after adding &apos;d&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Current keys (after potential flush): &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\nAdding more items...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;e&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;d&apos;: 4, &apos;e&apos;: 5} (Size 2)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;f&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;d&apos;: 4, &apos;e&apos;: 5, &apos;f&apos;: 6} (Size 3) - Limit reached again&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\nDeleting &apos;a&apos; (should trigger auto-flush)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# &apos;a&apos; was flushed earlier, now we delete it. Buffer limit reached.&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;del&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Flush happens (d, e, f written), buffer cleared, then &apos;a&apos; deletion added&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;a&apos;: SENTINEL} (Size 1)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size after deleting &apos;a&apos;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            cs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Buffer: {&apos;a&apos;: SENTINEL, &apos;g&apos;: 7} (Size 2)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Buffer size: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Final keys before exit: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Final buffer content before exit: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_write_buffer&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Exit flushes the remaining buffer {&apos;a&apos;: SENTINEL, &apos;g&apos;: 7}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- After &apos;with&apos; block (final flush on exit) ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;An error occurred: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Clean up in case of error during test&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; os
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; ext &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.bak&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.dat&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.dir&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;remove&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; FileNotFoundError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;pass&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Re-raise exception&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Verify final contents&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- Verifying final contents in shelve ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; CachedShelve&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;r&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cs_read&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Read-only&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Final keys in shelve: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cs_read&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# sorted for consistent output&lt;/span&gt;
            expected_keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;d&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;e&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;f&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# a deleted, c flushed then overwritten by flush of a&apos;s deletion? No, c was flushed. b was flushed. d,e,f flushed. a deleted in final flush, g added in final flush.&lt;/span&gt;
            actual_keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cs_read&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; actual_keys &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; expected_keys&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Verification successful!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Values:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; k &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actual_keys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;  &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;k&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cs_read&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;k&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Verification FAILED!&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;  Expected: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expected_keys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;  Actual:   &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actual_keys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;An error occurred during verification: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Clean up shelve files&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; os
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\nCleaning up shelve files...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; ext &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.bak&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.dat&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.dir&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;remove&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# print(f&quot;Removed {filename + ext}&quot;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; FileNotFoundError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;pass&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cleanup complete.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;sync i/o 최적화는?&lt;/h3&gt;
&lt;p&gt;그럼에도 이 또한 sync 과정에서 i/o가 개별적으로 발생하니 조삼모사 같기도 하다. 거기에 대한 gemini의 생각은 아래와 같다고 한다. 내심 처음 생각했던게 sqlite였는데 코드 고치기가 싫어서 다른 방법 찾다가 돌고돌아 결국 다시 원점으로 왔나 싶기도 하다. 뭔가 수미상관인가?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;네, 아주 정확한 지적입니다! 현재 &lt;code class=&quot;language-text&quot;&gt;_flush_write_buffer&lt;/code&gt; 메소드는 &lt;code class=&quot;language-text&quot;&gt;_write_buffer&lt;/code&gt;의 각 항목에 대해 루프를 돌면서 &lt;code class=&quot;language-text&quot;&gt;self._db[key] = value&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;del self._db[key]&lt;/code&gt;를 호출합니다. &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 객체는 딕셔너리처럼 동작하지만, 내부적으로는 각 할당/삭제 작업이 (대부분의 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 구현에서) 개별적인 파일 I/O 작업으로 이어질 수 있습니다. 따라서 버퍼에 100개의 변경 사항이 있었다면, 플러시 과정에서 100번의 작은 디스크 접근이 발생할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이 플러시 과정 자체를 최적화하여 I/O를 모아서 한 번에 처리할 수 있을까요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;안타깝게도 &lt;strong&gt;표준 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 모듈과 그 기반의 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 라이브러리 수준에서는 이 작업을 직접적으로 제어하거나 보장하는 간단하고 표준적인 방법이 제한적입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;몇 가지 관련된 측면과 가능한 접근법(및 한계)을 살펴보겠습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt;의 내부 동작 및 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt;:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt;는 키-값 저장을 위해 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; (예: &lt;code class=&quot;language-text&quot;&gt;dbm.gnu&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;dbm.ndbm&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;dbm.dumb&lt;/code&gt;) 같은 라이브러리를 사용합니다. 이러한 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 라이브러리가 내부적으로 어느 정도의 쓰기 버퍼링을 수행할 수는 있지만, &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 모듈 자체가 &quot;여러 항목을 한 번의 I/O 작업으로 쓰기&quot; 위한 명시적인 공개 API(예: &lt;code class=&quot;language-text&quot;&gt;update_batch(items)&lt;/code&gt;)를 제공하지는 않습니다.&lt;/li&gt;
&lt;li&gt;따라서 &lt;code class=&quot;language-text&quot;&gt;self._db[key] = value&lt;/code&gt; 호출이 즉시 디스크에 쓰일지, 내부 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 버퍼에 들어갈지는 사용 중인 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 구현과 운영체제에 따라 달라질 수 있으며, 파이썬 코드 수준에서 직접 제어하기 어렵습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;shelve.sync()&lt;/code&gt;의 역할:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 객체의 &lt;code class=&quot;language-text&quot;&gt;sync()&lt;/code&gt; 메소드는 아직 디스크에 기록되지 않은 데이터를 강제로 쓰도록 요청합니다.&lt;/li&gt;
&lt;li&gt;만약 &lt;code class=&quot;language-text&quot;&gt;_flush_write_buffer&lt;/code&gt; 루프가 끝난 &lt;em&gt;후&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;self._db.sync()&lt;/code&gt;를 호출하면, 루프 동안 요청된 모든 개별 쓰기 작업들이 (만약 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt;이나 OS 수준에서 버퍼링되고 있었다면) 디스크에 확실히 반영되도록 보장하는 데 도움이 됩니다.&lt;/li&gt;
&lt;li&gt;하지만 이것이 루프 동안 발생한 &lt;em&gt;여러 번의 I/O 요청 자체&lt;/em&gt;를 &lt;em&gt;한 번의 큰 I/O 요청&lt;/em&gt;으로 바꿔주지는 못할 가능성이 높습니다. 이미 여러 번의 쓰기/삭제 작업이 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 계층에 전달되었을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;shelve(writeback=True)&lt;/code&gt; 재고:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;이전에 우리는 &lt;code class=&quot;language-text&quot;&gt;writeback=True&lt;/code&gt; 사용을 금지했습니다. 하지만 이론적으로, 만약 &lt;code class=&quot;language-text&quot;&gt;shelve.open(..., writeback=True)&lt;/code&gt;를 사용한다면, &lt;code class=&quot;language-text&quot;&gt;_flush_write_buffer&lt;/code&gt; 루프에서 &lt;code class=&quot;language-text&quot;&gt;self._db[key] = value&lt;/code&gt; 등을 호출하는 것이 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt;의 내부 메모리 캐시만 업데이트할 수 있습니다. 그리고 루프가 끝난 후 &lt;code class=&quot;language-text&quot;&gt;self._db.sync()&lt;/code&gt;를 한 번 호출하면, &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt;가 내부 캐시의 모든 변경 사항을 (어쩌면 더 효율적으로) 디스크에 쓸 수도 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt; 이전에 논의했듯이 메모리 사용량 증가 (우리 캐시 + &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 캐시), 복잡성 증가, &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 내부 동작 의존성, 우리 캐싱 전략과의 충돌 가능성 등 문제가 많아 여전히 권장하기 어렵습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;shelve.update()&lt;/code&gt; 사용:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 객체도 딕셔너리처럼 &lt;code class=&quot;language-text&quot;&gt;update()&lt;/code&gt; 메소드를 가집니다. 쓰기 버퍼의 내용을 딕셔너리로 만들어 &lt;code class=&quot;language-text&quot;&gt;self._db.update(write_dict)&lt;/code&gt;를 호출하면 어떨까요?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;한계:&lt;/strong&gt; 파이썬의 일반적인 &lt;code class=&quot;language-text&quot;&gt;update()&lt;/code&gt; 구현은 단순히 입력 딕셔너리를 반복하며 각 항목에 대해 &lt;code class=&quot;language-text&quot;&gt;__setitem__&lt;/code&gt;을 호출하는 것과 같습니다. 따라서 &lt;code class=&quot;language-text&quot;&gt;_db.update(d)&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;for k, v in d.items(): _db[k] = v&lt;/code&gt;와 동일하게 동작할 가능성이 높으며, I/O 최적화를 보장하지 않습니다. (삭제 작업은 별도로 처리해야 함).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;대안: 다른 백엔드 사용:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;이 문제의 근본적인 해결책은 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 대신 &lt;strong&gt;명시적인 배치(batch) 쓰기 API를 제공하는 다른 저장소 백엔드를 사용&lt;/strong&gt;하는 것입니다.
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SQLite:&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;sqlite3&lt;/code&gt; 모듈을 사용하여 여러 SQL &lt;code class=&quot;language-text&quot;&gt;INSERT&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UPDATE&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt; 문을 하나의 트랜잭션으로 묶어 실행하면 훨씬 효율적입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LMDB (Lightning Memory-Mapped Database):&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;lmdb&lt;/code&gt; 파이썬 라이브러리는 트랜잭션 내에서 여러 쓰기 작업을 효율적으로 처리하는 기능을 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LevelDB/RocksDB:&lt;/strong&gt; 이 라이브러리들도 배치 쓰기 기능을 제공하는 경우가 많습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt; 이는 &lt;code class=&quot;language-text&quot;&gt;CachedShelve&lt;/code&gt; 클래스의 기반 저장소를 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt;가 아닌 다른 것으로 완전히 바꾸는 큰 변경이며, 기존 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 파일과의 호환성이 사라집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;결론:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;현재 &lt;code class=&quot;language-text&quot;&gt;CachedShelve&lt;/code&gt; 클래스가 &lt;strong&gt;표준 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 모듈을 사용하는 한&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;_flush_write_buffer&lt;/code&gt; 내의 여러 쓰기/삭제 요청을 &lt;strong&gt;하나의 최적화된 디스크 I/O 작업으로 확실하게 묶는 것은 어렵습니다.&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; API의 한계와 &lt;code class=&quot;language-text&quot;&gt;dbm&lt;/code&gt; 구현의 다양성 때문입니다.&lt;/p&gt;
&lt;p&gt;우리가 할 수 있는 최선은 다음과 같습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;쓰기 지연:&lt;/strong&gt; 현재 구현처럼 &lt;code class=&quot;language-text&quot;&gt;_write_buffer&lt;/code&gt;를 사용하여 &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt;에 대한 접근 자체를 최대한 지연시키는 것 (이것만으로도 상당한 성능 향상이 있을 수 있습니다).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;sync()&lt;/code&gt; 호출:&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;_flush_write_buffer&lt;/code&gt;가 끝난 후 &lt;code class=&quot;language-text&quot;&gt;self._db.sync()&lt;/code&gt;를 호출하여 데이터의 디스크 기록을 보장하는 것 (선택 사항, 내구성은 높이지만 약간의 추가 오버헤드 발생 가능).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;만약 플러시 과정 자체의 I/O 효율을 극대화하는 것이 매우 중요하다면, &lt;code class=&quot;language-text&quot;&gt;shelve&lt;/code&gt; 대신 SQLite나 LMDB 같은 다른 백엔드를 사용하도록 클래스를 재설계하는 것을 고려해야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;결론&lt;/h3&gt;
&lt;p&gt;결국 데이터 구조를 변경해서 해결했으니 이 모든 논의가 쓸모 없는 시간 낭비는 아닐까라는 생각이 들수도 있다. 하지만 과정이 재밌었고, 뭔가 배운게 있었다면 된 거 아닌가 싶다. 공자 선생님께서 말씀하셨듯이 배우고 때때로 익히면 또한 즐겁지 아니한가?&lt;/p&gt;
&lt;p&gt;어쨌든, 오늘의 교훈. 구글도 이제 감 잡은 거 같기도 하다는 거. gemini 2.5 pro 몹시 훌륭하다. 벤치마크에서는 양민 학살중~&lt;/p&gt;
&lt;p&gt;덧) 인공지능은 실수할 수 있다. 여기 올려진 코드에 버그가 있다고 너무 나무라지는 말자. 직접 작성해도 그 정도 버그는 나온다. 참고로 gemini는 저 모든 코드를 타이핑 하는 속도보다 빠르게 만들었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] 바이브 코딩의 시대]]></title><description><![CDATA[바이브 코딩이 유행이다. 직접 코딩하지 않고 자연어로 인공지능에 명령만 해서 코딩을 하는 것을 말하는 의미다. 통상 8…]]></description><link>https://jiniya.net/2025/03/vibe-coding-era/</link><guid isPermaLink="false">https://jiniya.net/2025/03/vibe-coding-era/</guid><pubDate>Tue, 25 Mar 2025 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;vibe-coding.webp&apos; data-alt=&apos;안드레 카파시 말처럼 바이브에 몸을 맡기자.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6f1ddd64dda716fb7d15ea7a59b631fe/a4772/vibe-coding.webp&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRqQAAABXRUJQVlA4IJgAAACQBACdASoUAAsAPtFUo0uoJKMhsAgBABoJbACdMoRwAdBw7IEsiQm1XNIbjoAA/tIDIGxT606MBeTJio552zXl42yyJKChdrxP9YbsiNLX54WjXNg8/yWiztn1tVdXoGV7VHW47v0yaNTRSPW6hi6Pj8BZzkoGlJLimHHS7Eaa6z8eWb6yCfsM3JHhNJ6f1vafPDAHrj4AAA==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;안드레 카파시 말처럼 바이브에 몸을 맡기자.&apos; title=&apos;&apos; src=&apos;/static/6f1ddd64dda716fb7d15ea7a59b631fe/7df04/vibe-coding.webp&apos; srcset=&apos;/static/6f1ddd64dda716fb7d15ea7a59b631fe/561c4/vibe-coding.webp 190w,
/static/6f1ddd64dda716fb7d15ea7a59b631fe/3e041/vibe-coding.webp 380w,
/static/6f1ddd64dda716fb7d15ea7a59b631fe/7df04/vibe-coding.webp 760w,
/static/6f1ddd64dda716fb7d15ea7a59b631fe/b2cd5/vibe-coding.webp 1140w,
/static/6f1ddd64dda716fb7d15ea7a59b631fe/98c2e/vibe-coding.webp 1520w,
/static/6f1ddd64dda716fb7d15ea7a59b631fe/a4772/vibe-coding.webp 1792w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;안드레 카파시 말처럼 바이브에 몸을 맡기자.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Vibe_coding&quot;&gt;바이브 코딩이&lt;/a&gt; 유행이다. 직접 코딩하지 않고 자연어로 인공지능에 명령만 해서 코딩을 하는 것을 말하는 의미다. 통상 80% 이상을 인공지능이 작성하면 바이브 코딩으로 보는 추세인 것 같다. 바이브 코딩으로 게임을 만들어서 큰 돈을 벌었다는 사람도 있고, SNS에는 온갖 것들을 바이브 코딩으로 만들었다는 개발자 또는 비개발자들의 글이 넘쳐난다.&lt;/p&gt;
&lt;p&gt;한편, 이를 바라보는 직업 프로그래머의 반응은 엇갈린다. 바이브에 올라타는 사람도 있고, 그로인한 리팩토링 대란이 벌어질 것이라는 얘기를 하는 사람들도 있다. 어쨌든 나는 바이브에 올라탄 사람 중에 한 명이긴 하다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;내가 처음 바이브 코딩을 해본 건 작년 한글날 정도였던 것 같다. 한창 새로운 제품 코드를 작성하고 있었다. 이 제품은 몇 년을 개발이 지지부진한 것 중에 하나였다. 내가 코드를 쓰지 않은 것도 있었지만 새로운 제품을 우리가 감당할 수 있을까, 라는 생각도 컸었다. 새로운 제품은, 새로운 테스트를, 새로운 지원을, 새로운 영업을, 새로운 홍보를 필요로하는 일이니 말이다. 하지만 우리는 힘든 시기를 겪고 있었고, 더이상 미룰 수는 없었다. 마침 o1-preview가 출시되기도 했었다. 거기다 세월을 묵힌 시간만큼 리서치 자료는 많이 쌓여 있었다. 벤치마킹할 타사 제품도 수두룩했다.&lt;/p&gt;
&lt;p&gt;처음에는 ChatGPT와 함께 작성하기 시작했다. 주로 4o에게 작업을 지시하고 결과를 내가 복붙해서 확인하는 작업이었다. ChatGPT로는 전체 프로그램을 한번에 작성하는 것은 쉽지 않기 때문에 전체 구조는 내가 생각했고 주로 함수 단위로 코딩을 지시해서 붙여넣었다. 당연히 출발은 우리의 리서치 자료에서 시작했다. 얼추 해당 자료대로 모두 구현을 했다. 그런데 테스트를 돌리니 예외가 너무 많이 발생했다. 리서치 자료가 크게 도움이 되지 않은 상황이었다.&lt;/p&gt;
&lt;p&gt;여기서부터는 멘붕, 과연 이걸 해결할 수 있을까, 라는 생각. 대충 땜빵식으로 해결할수도 있겠지만 리얼월드에서는 무슨 일이 벌어질지 모르는 것이라 그것도 한계가 있었다. 모든걸 원점 재검토가 필요한 상황이었다. 그렇게 새로운 방법을 시도했다. 하지만 번번히 예외 케이스들이 너무 많이 발생하는게 문제였다. 코딩이 문제가 아니라 문서화되지 않은 것들에 대한 구조를 이해하는 게 핵심이었는데 그건 나도 모르고, ChatGPT도 모르는 게 큰 일이었다. 당연한 얘기였지만 다른 제품들도 모두 안되기는 마찬가지였다. 왜냐하면 타사 제품도 모두 동일한 오픈소스를 사용하고 있었고, 그 오픈소스 코드가 잘 동작하지 않는 경우가 많은게 문제였기 때문이다.&lt;/p&gt;
&lt;p&gt;그렇게 설계를 3-4번은 뒤집어 엎었다. 최종적으로는 ChatGPT와 함께 오픈소스를 이해하기로 했다. 오픈소스는 너무 커서 거기서 내가 필요한 부분을 찾는 것도 일이었는데 웃긴 건 ChatGPT가 그걸 학습해서 그런지 오픈소스에서 내가 필요한 코드가 어디 있는지 물어보면 기가 막히게 알려줬다. 물론 오픈소스라는게 코드만 있다고 이해가 되는 건 아니다. 이해가 되지 않는 부분은 ChatGPT에 넣어서 다시 설명을 요청했다. 그 이해한 걸 토대로 ChatGPT한테 코딩을 시켜서 코드를 작성했다. 그 모든 작업을 하는 동안 o1-preview를 사용할 일은 한 번 밖에 없었다.&lt;/p&gt;
&lt;p&gt;그러다 커서라는 걸 알게됐고 커서로 코딩을 시작했다. 커서는 전체 컨텍스트를 자동으로 llm에 보내 주기 때문에 코딩이 훨씬 편했다. 인라인 에디팅이나 블록을 지정해서 고치기가 훨씬 쉬운게 장점이었다. 그리고 브라우저로 와리가리 안해도 되서 시간이 많이 절약됐다. 그렇게 돌아보니 80%는 아니라도 얼추 70%는 인공지능이 코딩한 제품이 완성됐다. 그때는 바이브 코딩이란 말도 없던 시기라 묘한 기분이 들었다. 제품이 다 작성됐고 빌드 후 테스트를 진행하는 단계가 되니 뭔가 ChatGPT랑 뒷풀이라도 해야 할 것 같다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;사람이면 설계를 3-4번 뒤집는 일을 참지 못했을 것 같다는 생각. 작성했지만 버렸던 수많은 코드에 엄청난 에고로 집착했을거라는 생각. 그리고 웃기게도 이 거대한 작업에서의 나에게 아하 모멘트는 이런 부분이었다. A라는 오픈소스에서 B라는 기능 관련된 코드가 어디있는지 알려줘. 이걸 당연히 답할거라고 생각을 안해서 물어볼 생각을 안했는데 하도 답답해서 물어봤는데 정말 어처구니 없을 정도로 정확하게 코드 위치를 잘 알려주었다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;해가 바뀌었고 deepseek가 미국 주도 인공지능 세계에 한차례 충격을 가했다. 더불어 인공지능 오픈소스 생태계는 더욱 풍성해졌다. 장비를 구성할 능력만 되면 로컬에서도 o1 급의 리즈닝 모델을 돌릴 수 있는 세상이 된 것이다. 물론 deepseek-r1은 아직 로컬에서는 돌리기 부담스러운 671b 모델이긴 하다. 하지만 뒤따라 출시된 qwen2.5-coder-32b나 qwq-32b 같은 모델만 사용해도 나쁘지 않은 성능을 보여주었다. 그도 그럴것이 앞서도 언급했지만 대부분의 보통 프로그래머가 작성하는 코드란게 뭔가 대단한 코드가 아니기 때문이다. 안타깝게도 우리는 너무나 뻔한 코드를 대부분 작성하는 경우가 다반사니까 말이다.&lt;/p&gt;
&lt;p&gt;최근에 일감이 하나 올라왔다. 고객사에서 api 사용에 문제를 겪는 일감이었다. 업체측에서 친절하게도 본인들이 구현한 코드를 보내주었다. 신입 개발자에게 확인해보라고 했지만 쉽지 않을거라는 생각이 들긴 했다. 그렇다고 내가 앉아서 그 모든 걸 보고 있기엔 다른 급한 일감도 너무 많았다. 그래서 딸깍 코딩을 해보기로 했다. 일감 내용과 업체 코드를 집어 넣고 문제를 재현할 수 있는 테스트 코드를 작성하라고 했다. 아키텍트로 qwq:32b_q4, 에디터로 qwen2.5-coder:32b_q4를 사용했다. 생각했던 것보다 아주 잘 작성했다. 웃긴건 걔가 제대로 작성했는데 내가 틀린 것 같아서 수정을 지시했는데, 업체측에 확인 요청한 결과 내가 지시한 부분이 잘못된 부분이었다. 걔가 원래 작성한 코드가 맞는 코드였다. 업체 측에서 우리가 봐도 되는 부분만 발췌해서 보낸 코드라 빠진 코드가 더러 있었다. 그런 코드는 나머지를 토대로 추론해서 작성하라고 지시를 했는데 그것도 잘 작성했다.&lt;/p&gt;
&lt;p&gt;어쨌든 잘 만들 필요는 없지만 재현시키기 위해서는 복잡한 귀찮은 작업이 필요한 그런 작업이었다. 내가 한다고 해도 몇일은 걸릴 것 같은 일이었다. 그런데 정말 딸깍 코딩으로 모든 게 만들어졌다. 내가 일부 수정한 건 경로가 맞지 않아서 포함 경로를 수정하고 포함 파일이 빠진 걸 몇 개 추가한 게 다였다. 물론 이 또한 바이브 코딩을 할 수 있겠지만 그걸 타이핑하는 시간에 코드 고치는 게 훨씬 빠르기에 내가 직접 했다. 결과적으로 그렇게 전체 작업을 하는 데 걸린 시간은 1-2 시간도 채 되지 않았다. 물론 그 마저도 대부분의 시간은 걔가 코딩 하는 걸 대기하는 시간이었다. 왜냐하면 우리 장비는 그리 좋은 장비가 아니라 느리다는 점. 모델 2개를 한번에 메모리에 로딩할 수가 없어서 아키텍트하고 에디팅할 때 항상 모델 교체를 위한 시간이 낭비된다는 점 때문이다. 지시도 몇개 안했지만 대부분 생각보다 너무 잘해서 놀랐다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;모든 코드를 잘 작성할 필요는 없다. 그냥 확인을 위해서 임시로 작성하는 코드도 수도 없이 많다. 그런 코딩은 인공지능에게 시키고 나는 중요한 다른 코드를 쓴다면 동시에 두가지 일을 하는 셈이 되는거니 생산성은 배가 된다. 시스템 프로그래머들에게 한참 전에 파이썬을 써야 한다고 하면 C/C++로도 다 할 수 있다는 핀잔을 듣던 시기가 있었다. 하지만 세월이 지나서 이제는 파이썬이 세상을 지배하고 있다. 인공지능도 머지 않아 그렇게 될 거라 본다. 직접해도 다 할 수 있다. 다만 인공지능을 사용하면 더 빨리 할 수 있다. 그리고 열린 마음으로 함께 한다면 나도 모르고, 인공지능도 모르는 것에 대한 작업도 함께 할 수 있다.&lt;/p&gt;
&lt;p&gt;인정하기 싫지만 인공지능이 나보다 코드를 더 잘 읽고, 더 잘 작성한지는 생각보다 제법 오래된 것 같다. 많은 경험을 토대로 느낀 점은 컨텍스트만 제대로 제공하면 거의 상당수 경우에 인간보다 훨씬 나은 결과가 나온다는 것이다. 그러니 이제, 안드레 카파시 말처럼 인공지능을 믿고 바이브에 몸을 맡기자.&lt;/p&gt;
&lt;p&gt;덧) 나는 이제 더 이상 커서를 사용하지 않는다. 내가 필요한 기능은 대부분 깃헙 코파일럿에 모두 추가되었고 커서의 크레딧 같은 기능은 코딩을 많이 하는 경우 거의 2주면 다 바닥났기 때문이다. 물론 결제를 더하면 더 늘릴 수 있겠지만 코파일럿이 너무 빨리 따라왔다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 2월의 잡담]]></title><description><![CDATA[#0 모두 실패했던 원본 문제를 o3-mini-high 3트만에 통과. 실제 코딩 점수도 2139로 루머 보다는 높다. 아슬아슬해 보이지만 왕좌는 여전히 openai…]]></description><link>https://jiniya.net/2025/02/small-talk-2025-02/</link><guid isPermaLink="false">https://jiniya.net/2025/02/small-talk-2025-02/</guid><pubDate>Fri, 28 Feb 2025 13:22:26 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;모두 실패했던 원본 문제를 o3-mini-high 3트만에 통과. 실제 코딩 점수도 2139로 루머 보다는 높다. 아슬아슬해 보이지만 왕좌는 여전히 openai라는 걸 입증하는데 성공한걸로. 당사자는 죽을 맛이겠지만 소비자 입장에서 경쟁은 어쨌든 행복하다. &lt;a href=&quot;https://openai.com/index/openai-o3-mini/&quot;&gt;https://openai.com/index/openai-o3-mini/&lt;/a&gt; &lt;a href=&quot;https://x.com/codemaru/status/1883746085811953718&quot;&gt;https://x.com/codemaru/status/1883746085811953718&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;사람보다 llm과 더 많이 일한지가 제법됐다. 어제도 모르는 문제를 r1, o1, gemini thinking과 교차 토론해서 해결. 예전엔 와 이것도 되네, 이러면서 쪼렙 같았던 애들이 이제는 대선배님 같은 느낌. 코딩을 배울 필요 없다던 젠슨황 말을 모두가 비웃었지만 점점 더 맞말처럼 느껴지는 요즘.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;적게 약속하고 잘 지키는게 공수표 남발보다 더 좋다고 생각한다. 하지만 당사자는 많이 서운해 하겠지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;펀더멘탈은 생각보다 중요하다. 특히 국면이 좋지 않을 때.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;적어도 체면과 품격을 눈곱만큼이라도 생각하는 사회 지도층을 보고 싶다. 착한 사람들은 너무 빨리 떠나고 낯짝 두꺼운 사람들만 남은게 아닌가 싶다. 정치는 실종되고 법만 남은 세상이 이런 건가 싶은 요즘.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;한때 평생 업적이라고는 어릴때 수능 잘친거 밖에 없는 사람들이 훈계질 하는 게 유행이더니, 요즘은 주식, 코인해서 돈 좀 벌었다는 인간들이 남에 인생에 감나라 배나라 하는게 트렌드인듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;인공지능의 불편한 진실. 내가 막 지시하고 재밌는거 하고 허드렛일은 인공지능이 다하고 이럴줄 알았는데. 정작 생각하고 판단하는건 인공지능이 다하고, 나는 인공지능이 시킨 잡일하고 있음.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;을들의 싸움이란 대체로 구차하고 질척이며 지리멸렬하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;인형을 뽑고 싶지만 인형 뽑기에 실패한다고 화가 나진 않는다. 논리적으로 똑같은 상황인데 인형 뽑기가 아닌 어떤 일들은 내뜻대로 되지 않으면 마음이 먼저 소란해진다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://rustdesk.com/ko/team/&quot;&gt;https://rustdesk.com/ko/team/&lt;/a&gt; 팀뷰어가 비싸서 시작했다는 말이 인상적이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;지식 근로자로서 공통된 직업 윤리가 있다면, 일정 수준 이상의 전문성을 쌓으려는 노력은 꾸준히 해야 한다는 점이 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;코딩, it 한정. 나는 llm보다 사람의 할루시네이션이 훨씬 심각하다고 본다. 다만 차이가 있다면 사람의 할루시네이션은 덜 상냥하고, 더 단호하다는 특징이 있다는 거. 물론 나도 똑같고.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;애들을 보면 가끔 불편할 때가 있다. 내가 싫어했던 나의 어린 시절 모습을 보는 것 같을 때. 유전자는 무섭구나 싶다가도, 워프시켜 미안하다가도, 너도 참 고달프겠다 싶어 애처로운 마음까지 묘하게 중첩된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;llm 추론을 직접 돌리려면 메모리 용량과 대역폭 속도가 주된 병목. epyc 듀얼 ddr5 24채널 1tb/s, m4 ultra로 1tb/s 정도로 예상. 4090 1tb/s, 5090 1.7tb/s, 현시점은 ddr5 24채널이 젤 싼듯. 5090은 돈 있어도 구하기가 쉽지 않다. &lt;a href=&quot;https://rasim.pro/blog/how-to-install-deepseek-r1-locally-full-6k-hardware-software-guide/&quot;&gt;https://rasim.pro/blog/how-to-install-deepseek-r1-locally-full-6k-hardware-software-guide/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;llm도 모국어가 있는듯?! 한글로만 답하라고 강조에 강조에 강조를 해도 qwen 추론하다 낮은 확률로 중국어 들어가는 경우가 있다. 토큰 깨진건가 싶어 번역기 돌려보면 문맥상 또 틀린 말은 아님.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;신호처리와 컴퓨터 아키텍쳐 떡밥이 핫한데, 개인적으론 성의과학 교양 과목을 제일 추천하고, 그담은 글쓰기, 말하기, 논리학 추천. 컴공을 떠나 남은 인생에 뭘하든 피가되고 살이된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;린님 덕분에 하나 배웠다. 인간 개발자의 환각이란. &lt;a href=&quot;https://jiniya.net/2025/make_unique/&quot;&gt;https://jiniya.net/2025/make_unique/&lt;/a&gt; &lt;a href=&quot;https://x.com/lyntohno/status/1885950323916992865&quot;&gt;https://x.com/lyntohno/status/1885950323916992865&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;한국의 소프트웨어 개발 역량이 탑티어는 아니어도 그렇게 떨어진다고 생각지도 않는게 운영체제, 워드프로세서, 검색엔진, 백신, 데이터베이스, 웹브라우저, 네비, 메신저, mmo 게임 다 자국에서 개발한 나라도 몇 안됨. 다만 비교를 미중 빅테크에다 대고 하니 오징어 되는게 한순간.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;추론 삼대장에게 최신 정보를 반영해서 삼전 물타기에 대한 의견을 물었다. 현시점 물타기 적절하다? o3 70%, r1 55%, gemini 65%. 그돈으로 하이닉스 사는게 더 좋다? o3  80%, r1 55%, gemini 65%. 인공지능 삼대장도 삼전을 버린건가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;국장 미장 코인 다 어질어질하네. 지옥문 오픈인가?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;이건 약간 혼자 오픈북으로 시험친 느낌 아닌가 싶은. &lt;a href=&quot;https://x.com/tsarnick/status/1886211247600972103&quot;&gt;https://x.com/tsarnick/status/1886211247600972103&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;딥리서치 맛보려고 프로 모드를 처음 사용해 봤다. 생각보다 인상적임. 다만 검색 풀이 지나치게 영문 사이트 위주라 결론이 다소 뻔하다. csdn이나 바이두 검색 등의 중국발 사이트를 추가하면 훨씬 도움이 많이 될 것 같은 느낌. 이 지점에서도 공짜 딥시크가 강점을 가지는 웃픈 현실.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;llm 초기부터 프롬프트 엔지니어링에는 다소 회의적인 입장. 요즘은 llm에다 프롬프트 짜달라고 하면 기가막히게 작성해줌. 심지어 핑퐁하면서 고도화까지 하는 걸 감안하면.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;빌게이츠가 돈으로 살 수 없는건 시간 밖에 없다고 다큐에서 그러든데, 운동도 돈으로 살 수 없는 게 아닌가 싶다. 딴 건 다 돈주고 위탁할 수 있지만 운동은 그게 안됨. 해야 하지만 세상 하기 싫은.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;역행인생, 긱이코노미는 부스러기나 나눠 먹는 경제임을 여실히 보여주는 영화. 초반에 개발 팀장이 자신이 만든 알고리즘에 의해 저성과자로 찍혀서 해고되는 장면이 뭔가 짠했다.이어지는 라이더도 알고리즘이 지배하는 세상. 알고리즘은 자비가 없다, 입장과 사정은 알빠노.&lt;/p&gt;
&lt;p&gt;영화 보니 전에 만났던 택시 기사님이 생각났다. 현대판 운수 좋은 날 같은 느낌이었는데, 오늘 콜이 한번도 끊기지 않았다고 몹시 신나 하시며 자랑하던게 기억난다. 본인이 뭔가 카카오 알고리즘의 비밀을 알아낸 것 같다며.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;율곡이이가 말했다고 전해지는 인생삼불행. 소년등과, 중년상처, 노년빈곤. 초년에 성공하거나, 중년에 처를 잃고 외롭거나, 나이들어 돈 없으면 고달파지는게 인생. 조선시대나 지금이나 사람은 참 변한게 없는 것 같은 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;grok3 출시 기념으로 돌려봤다. think 붙여 돌렸지만 실패. 심심해서 o1 pro도 돌려봄. 2트 성공. 다만 함정은 o3-mini-high보다 10배는 족히 시간이 더 걸렸다는 거. grok3의 신기한 점은 간증은 넘쳐나는데 공식 벤치 점수 찾기는 어렵다는 사실. &lt;a href=&quot;https://x.com/codemaru/status/1885519651930857838&quot;&gt;https://x.com/codemaru/status/1885519651930857838&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;번외로 트위터에서 다른 테스트 시에 응답에서 깨진 한글 토큰 발견. 상용 llm에서는 처음 본 듯. 그럼에도 이정도로 빨리 쫓아왔다는 점에서는 진격의 일론머스크가 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;최근 주변에 창업한 사람이 많아졌는데 골치아플 요소가 많긴 하지만 공동창업자가 1명이라도 있는 편이 덜 외로워 보였다. 상상했던 1인 기업과  현실의 1인 기업은 느낌이 많이 다르다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;3d 프린터로 제조업 창업한 지인에게 들었는데 그쪽 분야도 중국의 굴기가 무섭다고 한다. dji 출신이 만든 뱀부랩 제품 쓰는데 몹시 만족한다고. 이후 국내 업체는 거의 전멸했다 한다. 만듦새가 중국스럽지 않고 애플스런 느낌. 분야막론 중국과 경쟁헤서는 노답인듯. &lt;a href=&quot;https://3dprintingindustry.com/news/bambu-lab-driving-market-dominance-of-entry-level-3d-printers-context-reports-229884/&quot;&gt;https://3dprintingindustry.com/news/bambu-lab-driving-market-dominance-of-entry-level-3d-printers-context-reports-229884/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#29&lt;/h2&gt;
&lt;p&gt;하루 1% 수익을 낼 확률이 99.9%라도 1년 동안 계속 성공할 확률은 70%가 안됨. 99%면 3%가 안되고, 98%만 되도 0.06%로 낮아진다. 고로 매일 1% 수익을 꾸준하게 낸다는 가정은 그냥 퐌타지. 그럼에도 일어날 일은 일어난다는 양자역학적 관점에서 보면 어딘가에는 성공한 사람도 있을 수는 있다는거.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#30&lt;/h2&gt;
&lt;p&gt;똑똑한 애들은 게을러서 문제, 멍청한 애들은 부지런해서 문제. 현실은 참 아이러니 그잡채.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#31&lt;/h2&gt;
&lt;p&gt;연봉 떡밥을 믈어본다. 영혼까지 끌어모은 연봉도 아닌 근로소득 1억 이상은 총 957,381명으로 전체 근로소득자 중 상위 4.6프로. 2억을 넘어가면 기하급수적으로 줄어들어 0.7프로다. 엑스에서는 개나소나에 해당하지만 현실세계에선 생각보다 참 작다는 게 팩트. &lt;a href=&quot;https://tasis.nts.go.kr/websquare/websquare.html?w2xPath=/ui/ep/e/a/UTWEPEAA02.xml&amp;#x26;sttPblYr=2024&amp;#x26;sttsMtaInfrId=20240103D01202449511&quot;&gt;https://tasis.nts.go.kr/websquare/websquare.html?w2xPath=/ui/ep/e/a/UTWEPEAA02.xml&amp;#x26;sttPblYr=2024&amp;#x26;sttsMtaInfrId=20240103D01202449511&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#32&lt;/h2&gt;
&lt;p&gt;미래엔 AI에 자신의 뜻을 정확하게 지시하는 능력이 가장 중요한 기술이 되리라고 예상한다. 인터넷이 등장한 후 거의 모든 사람이 웹 검색 방법을 배워야 했듯이 말이다. - 앤드류 응 &lt;a href=&quot;https://www.chosun.com/international/international_general/2025/02/21/N4QL2HWBUJEKBACQGUYFMJXZGQ/&quot;&gt;https://www.chosun.com/international/international_general/2025/02/21/N4QL2HWBUJEKBACQGUYFMJXZGQ/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#33&lt;/h2&gt;
&lt;p&gt;livebench에 올리온 grok3. 코딩은 r1보다 조금 나은 수준인듴. 직접 테스트해 본 느낌도 비슷했다. openai가 아직은 천상계. &lt;a href=&quot;https://livebench.ai/#/&quot;&gt;https://livebench.ai/#/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#34&lt;/h2&gt;
&lt;p&gt;얼마나 세상이 의대 몰빵이면 애들 상대로 의사 직업만 전문적으로 체험하는 키카가 생김. 내과 산부인과 응급의학센터 같이 분과별로 체험 가능. 도떼기시장이 따로 없다. 진짜 의사될 애들은 시대인재에서 박터지고 있겠지, 라는 생각에 웃프다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#35&lt;/h2&gt;
&lt;p&gt;gpt에게 회사 상태를 알려주고 각 플레이어의 내쉬균형을 찾아보라고 했더니 경영자는 직원 투자 부담을 줄이고 현상 유지, 직원은 대기업 이직 가능한 경우 이직, 아니면 잔류가 내쉬균형이라고 도출됐다. 다들 뭔가 어설퍼 보여도 각자 입장에서 최선을 다하면서 사는 세상이란 생각이 들었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#36&lt;/h2&gt;
&lt;p&gt;2차 전지로 전체 포트의 30프로 손실이 난 친구의 주식 투자를 도와주고 있는데 뭐든 작더라도 성공 경험이 중요하다는 생각이 들었다. 한번도 좋은거 사놓고 진득하게 기다려서 수익 본 경험이 없어서 기다리질 못한다. 조금만 오르면 팔려고 함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#37&lt;/h2&gt;
&lt;p&gt;모든 형태의 정부 복지는 (…) 개인이 가족–생계 시스템의 일원이 되는 일의 가치를 떨어뜨린다. 가족–생계 시스템은 상호 간의 협동과 도움, 지원을 기초로 하는 광범위한 사회복지 시스템이다. - 왜 그들만 부자가 되는가&lt;/p&gt;
&lt;p&gt;그러나 정부의 복지제도로 결혼이 가치를 상실했으며 부모가 자녀들을 훌륭하게 양육하고 교육하는 일의 가치와 중요성이 떨어졌다. 이에 아이들이 부모에게 갖는 존경심도 줄어들었다.&lt;/p&gt;
&lt;p&gt;예전에는 자녀가 많으면 든든한 노후대책으로 간주되었지만 현대에는 오히려 빈곤에 빠질 수도 있는 위험신호로 바뀌었다. 자녀가 있다고 하더라도 부모들은 아이를 보육시설에 맡겨야 하는 상황이다.&lt;/p&gt;
&lt;p&gt;복지로 인해 출산율이 떨어지고 이혼율이 높아지고, 도움 없이 개인으로 생존 가능하니 사람들이 이기적이 된다는 신박한 생각. 다른 내용은 죄다 뻔한 내용들이었지만 이 부분은 신박했다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#38&lt;/h2&gt;
&lt;p&gt;당신은 센틸리언이 사라고 하는 걸 사고, 센틸리언이 읽으라고 하는 걸 읽고, 센틸리언이 만나야 한다고 하는 사람이랑 데이트를 해요. 그런데 진짜로 행복하긴 해요? - 종이 동물원, 켄 리우&lt;/p&gt;
&lt;p&gt;처칠이 이런 말을 했다지요. ‘건물을 만드는 것은 우리이지만, 나중에는 그 건물이 우리를 만든다.’ 우리는 생각하기를 돕는 기계를 만들었지만 이제는 그 기계가 우리를 대신해서 생각을 한다, 이겁니다.&lt;/p&gt;
&lt;p&gt;아무도 안 믿을 겁니다. 우리가 그렇게 만들 거니까요. 당신들이 무슨 말을 하든, 무슨 글을 쓰든, 누구 하나 듣지도 보지도 못할 겁니다. 인터넷에서는 센틸리언이 검색하지 못하는 것은 존재하지 않으니까요.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#39&lt;/h2&gt;
&lt;p&gt;인생사 새옹지마. 어떤 사건이 실질적으로 좋은지 나쁜지를 알기란 참 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#40&lt;/h2&gt;
&lt;p&gt;chatgpt 4.5 정말 애매하다. 코딩 말고 글쓰기 등에 대해서 4o랑 비교해 보는데 개선점을 느끼기가 쉽지 않다. 생성 속도는 4o보다 겁나 느림. 아이디어 탐색도 적게 말한다는 거 외에 좋다는 느낌은 별로 없다. 라이브때도 임팩트가 없어 보이더니 실제로도 그런듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#41&lt;/h2&gt;
&lt;p&gt;미장 나락가네. 서학개미 총출동 중인가, 이와중에 환율 무엇?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-02-28&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] make_unique<T[]>(n)]]></title><description><![CDATA[에 대해서 배열 초기화를 하지 않는다고 잘못 알고 있었던 사실이 있어서 정리해 본다. 은 내부적으로 을 호출하기 때문에 기본 타입에 대해서도 초기화 동작이 발생한다. 그런 이유로 초기화 없는 배열 할당을 위해서 C++ 2…]]></description><link>https://jiniya.net/2025/make_unique/</link><guid isPermaLink="false">https://jiniya.net/2025/make_unique/</guid><pubDate>Sun, 02 Feb 2025 17:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;make_unique&amp;lt;T[]&gt;(n)&lt;/code&gt;에 대해서 배열 초기화를 하지 않는다고 잘못 알고 있었던 &lt;a href=&quot;/2022/the-reasons-why-a-vector-is-unsuitable-for-use-as-a-buffer/&quot;&gt;사실이 있어서&lt;/a&gt; 정리해 본다. &lt;code class=&quot;language-text&quot;&gt;make_unique&amp;lt;T[]&gt;(n)&lt;/code&gt;은 내부적으로 &lt;code class=&quot;language-text&quot;&gt;new T[n]()&lt;/code&gt;을 호출하기 때문에 기본 타입에 대해서도 초기화 동작이 발생한다. 그런 이유로 초기화 없는 배열 할당을 위해서 C++ 20에서는 &lt;code class=&quot;language-text&quot;&gt;make_unique_for_overwrite&lt;/code&gt;가 추가되었다고 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;make_unique&amp;lt;T[]&gt;(n)&lt;/code&gt; - invokes &lt;code class=&quot;language-text&quot;&gt;new T[n]()&lt;/code&gt;, requesting value-initialization.&lt;br&gt;
&lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.htm&quot;&gt;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.htm&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;C++ 20 에서는 이런 경우 사용하는 함수가 추가되었다&lt;br&gt;
&lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&amp;lt;char[]&gt; arr = std::make_unique_for_overwrite&amp;lt;char[]&gt;(size);&lt;/code&gt;&lt;br&gt;
&lt;a href=&quot;https://blog.lunapiece.net/posts/C++-Dyanamic-Size-Buffer-Without-Initialization-And-Memoryleak/&quot;&gt;https://blog.lunapiece.net/posts/C++-Dyanamic-Size-Buffer-Without-Initialization-And-Memoryleak/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이하 deepseek v3 복음&lt;/p&gt;
&lt;h2&gt;make_unique&amp;#x3C;T[]&gt;&lt;/h2&gt;
&lt;p&gt;C++14 표준에서는 &lt;code class=&quot;language-text&quot;&gt;std::make_unique&lt;/code&gt;를 사용하여 동적 배열을 생성할 수 있도록 &lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T[]&gt;&lt;/code&gt;를 지원합니다. 이는 &lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&lt;/code&gt;을 사용하여 배열을 관리할 때 매우 유용합니다.&lt;/p&gt;
&lt;h3&gt;&lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T[]&gt;&lt;/code&gt;의 특징&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;배열 생성&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T[]&gt;&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; 타입의 동적 배열을 생성하고, 이를 관리하는 &lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&amp;lt;T[]&gt;&lt;/code&gt;를 반환합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;자동 메모리 관리&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&lt;/code&gt;은 소멸 시 자동으로 메모리를 해제하므로, 메모리 누수를 방지할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;초기화&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T[]&gt;&lt;/code&gt;는 배열의 각 요소를 기본값으로 초기화합니다. 예를 들어, &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt; 배열의 경우 모든 요소가 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;으로 초기화됩니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;사용 예제&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;memory&gt;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// std::make_unique를 사용하기 위해 필요&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// int 타입의 배열 10개를 동적 할당&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;make_unique&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 배열 초기화 및 출력&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        arr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// std::unique_ptr가 소멸되면 자동으로 메모리가 해제됨&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;주의사항&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T[]&gt;&lt;/code&gt;는 배열을 생성할 때만 사용할 수 있습니다. 단일 객체를 생성할 때는 &lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T&gt;&lt;/code&gt;를 사용해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&amp;lt;T[]&gt;&lt;/code&gt;는 배열을 관리하기 위해 특수화된 형태이므로, &lt;code class=&quot;language-text&quot;&gt;operator[]&lt;/code&gt;를 사용하여 배열 요소에 접근할 수 있습니다. 단일 객체를 관리하는 &lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&amp;lt;T&gt;&lt;/code&gt;에서는 &lt;code class=&quot;language-text&quot;&gt;operator[]&lt;/code&gt;를 사용할 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;요약&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;std::make_unique&amp;lt;T[]&gt;&lt;/code&gt;는 C++14에서 도입된 기능으로, 동적 배열을 생성하고 &lt;code class=&quot;language-text&quot;&gt;std::unique_ptr&lt;/code&gt;로 관리할 수 있게 해줍니다.&lt;/li&gt;
&lt;li&gt;이 기능은 메모리 관리와 안전성을 높이는 데 도움이 되며, 배열의 각 요소를 기본값으로 초기화합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이를 통해 C++에서 더 안전하고 간결하게 동적 배열을 관리할 수 있습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2025년 1월의 잡담]]></title><description><![CDATA[#0 인생은 고통과 권태 사이를 오가는 시계추와 같다. - 쇼펜하우어 2025-01-07 #1 같은 공간 같은 시간에 살아도 어쩌면 우린 참 다른 세상에 사는지도... 2025-01-07 #2 mmlu pro…]]></description><link>https://jiniya.net/2025/01/small-talk-2025-01/</link><guid isPermaLink="false">https://jiniya.net/2025/01/small-talk-2025-01/</guid><pubDate>Fri, 31 Jan 2025 23:18:47 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;인생은 고통과 권태 사이를 오가는 시계추와 같다. - 쇼펜하우어&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;같은 공간 같은 시간에 살아도 어쩌면 우린 참 다른 세상에 사는지도...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;mmlu pro 수치가 생각보다 정확한 것 같다. 오픈 모델 테스트 해보면 딱 그 정도 느낌으로 다가온다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;개발도 비슷한게 구글이 먼저인거 같은데 매년 안드로이드 하나씩 발표하니까 애플 따라하고 급기야 ms까지 따라감. 몇년에 한번씩 os나오고 어쩌다 서팩 하나씩 나오던 시절이 인간적이었다. ms는 욕심이 과해 연4회 하려다 포디하고 이제는 연2회 하는듯. 쿠팡이 하니 cj도 따라하는듯. &lt;a href=&quot;https://x.com/yeoreum1light/status/1876507922005692778&quot;&gt;https://x.com/yeoreum1light/status/1876507922005692778&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;노동 집약적인 현재 택배시스템은 쿠팡이든 cj든 지속 가능해 보이진 않는다. 인구 감소를 보면 그쪽도 금방 일할 사람 씨가 마를듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;여러 수만가지 내 뜻대로 된 일에 대해서 감사한 마음을 가지는 경우는 거의 없는 반면, 단 하나 내 맘대로 안되는 일에는 불편함을 참 쉽게도 느끼는 것 같다. 마음은 정말 마음대로 안 된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;자아는 명사라기보다 동사에 가깝다. 그것이 존재한다 생각할 때만 존재하며, 이는 생각함이 곧 자아이기 때문이다. - 자네, 좌뇌한테 속았네!&lt;/p&gt;
&lt;p&gt;자아가 존재를 유지하기 위해서는 생각이 지속적으로 일어나야 하고, 이를 위해 자아는 똑똑함과 매력과 성공의 척도를 계속 바꾼다. 새로운 “더 나음”을 제시함으로써 언제나 모자람에 머물러 있다.&lt;/p&gt;
&lt;p&gt;전에 얘기했지만 고통(suffer)의 정의는 슬픔, 실망, 고뇌 등의 느낌을 만들어냄을 의미한다. 그리고 이런 느낌은 우리가 새로운 버전의 자아 이미지를 원해 이전의 자아 이미지를 배척할 때 갖게 된다.&lt;/p&gt;
&lt;p&gt;삶이라는 게임에서 “승리”는, 애초에 이것이 단지 게임일 뿐이며, 그 게임의 설계자가 나 자신임을 경험적으로 알아차리는 것이라면? 이 발견이 경험적이어야 한다고 강조했다. 그리고 바로 그런 일이 붓다, 노자, 그리고 다른 고대의 스승들에게 일어났던 일이 아닐까?&lt;/p&gt;
&lt;p&gt;어떤 행위에 너무나 몰두한 나머지 그 순간엔 어디에도 ‘나’가 느껴지지 않는 경우. 그 직전에도 직후에도 내면의 나를 느꼈지만 그 순간만큼은 내가 없다. 이 점이 책의 핵심적인 질문이다. 아무도 그것에 대해 생각하지 않을 때 자아는 어디에 있는가?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;탐라에 돌아다니는 장원영 유퀴즈 인터뷰 짤을 보니 세상 참 많이 변했다는 생각이 든다. 그전 여돌 중에 인터뷰가 인상적이었던게 현아였는데 둘의 스탠스는 정말 거의 극과극. 대중이 그들에게 원하는 모습이 그만큼이나 바꼈구나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;한때 제조업으로 50명 이상인 기업을 운영하던 대표가 망했다. 제조업이 무서운 건 안팔리기 시작하면 모든 설비가 죄다 비용으로 다가온다는 것. 안전한 후퇴가 어렵다. 온갖 압류 딱지와 함께 공장과 설비는 모두 경매에 넘어갔고, 대표는 연락두절 후 도피중. 사업 참 어렵다. 그래도 연락두절은 ㅠ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;마야와 나는 우리 인생의 두 해에 가까운 나날을 밤마다 나란히 누워 함께 잤는데 지금도 나는 내가 마야를 진정으로 알았는지 궁금하다. 혹은 마야가 나를 진정으로 알았는지. - 사라진 것들, 앤드루 포터&lt;/p&gt;
&lt;p&gt;나는 마흔세 살이었다. 둘째 아이가 막 태어났다. 그 밖에는 인생에서 내 것이라고 할 만한 게 별로 없었다.&lt;/p&gt;
&lt;p&gt;마흔세 살이 되었는데 미래가 어떻게 될지 전혀 모르다니,삶의 어느 시점에 잘못된 기차에 올라타 정신을 차려보니 젊을 때는 예상하지도 원하지도 심지어 알지도 못했던 곳에 와버렸다는 걸 깨닫다니.꿈에서 깨어났는데 그 꿈을 꾼 사람이 자신이 아니었음을 알게 되는 것과 비슷하리라는 생각이 든다&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;감정의 골이 얇든 깊든&lt;br&gt;
적당히 신경을 끄고 용서하는 것이&lt;br&gt;
나에게 이롭다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;꽃길이 따로 있나, 내 삶이 꽃인 것을, 오평선&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-01-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;인생 다양한 고민을 chatgpt한테 물어보곤 하는데 언제나 탁월한 선택과 그 이유를 답해준다. 다만 안타까운건 걔가 알려준걸 내가 따라가지 못할 뿐. 의외로 인공지능이 우리에게 알려준 건 인간은 이성적이기보단 과도하게 감정적이라는게 아닐까 싶다. 그래서 늘 실수는 반복된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;요즘 보면 중국은 자유무역, 미국은 보호무역, 인공지능도 중국은 오픈모델, 미국은 독점모델. 둘이 뭔가 바뀐게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;원인이 chatgpt라는 근거는 빈약하지만, 개발자 입장에서 충분히 공감가는 내용. 솔직히 경력, 실력을 떠나서 코딩만 보면 알파고 순간을 진즉에 넘어섰다는 생각. 그나마 자율 실행과 최종 컨펌이 남았지만 이게 언제까지 지켜줄지는 모를 일이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/018/0005930296&quot;&gt;https://n.news.naver.com/article/018/0005930296&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;deepseek r1 성능 미쳤다. 대륙의 굴기가 매섭다. 베끼는 건 쉽다고 샘 알트만은 폄하하지만 전세계에서 쓸만하게 베껴서 출시해 내는 곳도 중국 밖에는 없다는 게 뭔가 묘하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;메타에게는 미안한 말이지만 인공지능 바둑때부터 인싱적인 뭔가를 보여줬던 적이 있었나 싶다. 물론 메타만 나무랄 일은 아니다. 오픈 모델 중에는 qeen2.5, deepseek r1을 제외하고는 인상적인 모델이 전무하니까. 여러 측면에서 중국이 뭔가 정말 신기하긴 하다. &lt;a href=&quot;https://x.com/GeekNewsHada/status/1882953290201350639&quot;&gt;https://x.com/GeekNewsHada/status/1882953290201350639&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;deepseek r1의 의문점은 llama 70b도 증류 모델을 공개했는데, 왜 qwen2.5 72b 모델을 증류하지 않았을까라는 점. 32b 증류 모델은 뭔가 아쉽네. llama3.3 70b보단 qwen2.5 72b를 증류하는게 훨 나았을텐데.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;최근에 o1이 실패한 코드 작성을 deepseek r1과 gemini thinking에 시켜봤지만 모두 실패. 스코프를 줄여서 시도한 건 deepseek 3트, gemini 7트, o1 1트. 로컬에서 돌릴 거 아니면 구관이 명관이다. llm 시대에도 분할정복법은 유효하다. o3는 과연 어떨지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;무릇 용이라는 동물은 길들여 친근해질 수 있고 탈 수도 있으나 목덜미 아래에 거꾸로 난 1척의 비늘인 역린이 있어 만일 건드리는 사람이 있으면 반드시 목숨을 잃는다고 한다. 군주 또한 역린이 있으니 유세하는 자가 군주의 역린을 건드리지 않으면 거의 성공할 수 있다. - 사기열전 , 사마천&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;잭 웰치는 마지막 강의 첫 내용으로 얼라인먼트를 강조했다. 어렸을 땐 몰랐지만 세월이 지나 다시 생각해보니 첫장에 강조할만한 내용이 맞다는 생각. 왜냐면 대체로 거의 모든 조직이 다 틀어져 있기 때문. 심지어 사람이 엮인 일이라 바로잡기가 몹시 어렵다는 사실.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;사피엔스 작가로 유명한 유발 하라리는 스마트폰이 아예 없고, 하루에 2시간 정도 명상을 하고, 일년에 30-60일 완전히 고립된 곳에서 휴식을 가진다고 한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;r1 천안문 검열로 말이 많은데 o1 가드도 많이 심한편. 보안관련된거 물어보면 계속 해킹하는 줄 알고 안 알랴줌. 4o는 그나마 덜한데 o1은 추론하다 이상하다 싶으면 그냥 도와줄수 없음 이러고 끝난다. 무엇을 보여줄지 말지는 결국 만든 사람의 선호고, 그걸 단적으로 평가하긴 어렵다는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;철저하게 후발 주자였음에도 개발 에디터는 vscode가 거의 평정한 것 같다. ms가 각잡고 만들면 얼마나 잘하는지 보여주는 사례가 아닌가 싶은. 그에 반해 팀즈는 시궁창을 벗어나질 못함. 구려도 오피스 끼워팔기로 잘나가니 딱히 신경을 안쓰는 듯한 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;좁은데 살다가 넓은데 가는건 문제가 없지만 반대는 무척 힘이든다. llm도 마찬가진듯. 72b 봤더니 낮은 애들은 안습. 이러다 r1 봤더니 72b도 오징어가 됐다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;20살때 가장 고학번 선배가 93학번, 27살. 그때는 그 형이 세상 모든 삼라만상을 통달한 도인같은 느낌 이었는데, 지금 생각해보면 27살 꼬꼬마가 참 자신감에 넘쳐서 아무말 대잔치 했구나 싶다. 병특 면접보다 문득 선배 얘기가 나와서.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;전 인생을 호구되지 말자는 신조로 살아왔는데. 요즘은 호구로 사는게 그리 나쁜 건 또 아니지 않을까, 라며 자기 위안을 삼는다. 내가 호구면 누군가는 개이득일테니.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;새해라 재미로 점보는 사람들 많은데, 의외로 명리학도 llm이 통달했다. 팔자 넣으면 기가막히게 풀어준다. 팔자는 만세력에 생년월일시 넣으면 나옴. 대운, 새운도 직접 입력해줘야 함. 팔자계산은 아직 미진한듯. 4o, gemini thinking은 캡쳐 화면 넣어도 잘봐주고, deepseek은 말로 넣어야함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;deepseek 어제 버거형들 출근 이후부터 먹통되는 경우가 많다. 추론도 트래픽 감당하려면 충분한 연산 능력이 있어야 하는게 인지상정. 게다가 671b는 생각보다 로컬에서 돌리긴 쉽지 않은 용량. nvda 떡락은 줍줍할 기회였을까? 떨어지는 칼날이었을까?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;‘나의 것’과 ‘남의 것’ 이 두 가지를 잊을 수 있다면&lt;br&gt;
설령 아무것도 가지지 않아도&lt;br&gt;
행복한 마음으로 지낼 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;초역 부처의 말, 코이케 류노스케&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2025-01-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;팩트라면 그렇게 줄기차게 던진 떡밥에 비해서 뭔가 김빠진 릴리즈가 아닌가 싶다. r1 벤치가 2029. 심지어 high가 pro용 릴리즈가 맞다면 본격 급나누기 시작인가 싶기도. &lt;a href=&quot;https://x.com/haider1/status/1885274715495031087&quot;&gt;https://x.com/haider1/status/1885274715495031087&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2025-01-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 12월의 잡담]]></title><description><![CDATA[#0 진짜 살아 돌아온줄. 이런거보면 인간은 그저 유전자를 전달하기위한 생존 기계라는 말이 심하게 와닿는다. https://t.co/O3ACgqOvXh 2024-12-02 #…]]></description><link>https://jiniya.net/2024/12/small-talk-2024-12/</link><guid isPermaLink="false">https://jiniya.net/2024/12/small-talk-2024-12/</guid><pubDate>Thu, 26 Dec 2024 12:02:48 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;진짜 살아 돌아온줄. 이런거보면 인간은 그저 유전자를 전달하기위한 생존 기계라는 말이 심하게 와닿는다. &lt;a href=&quot;https://t.co/O3ACgqOvXh&quot;&gt;https://t.co/O3ACgqOvXh&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;대부분의 평범한 부모가 그러하듯, 자식에게는 답답한 상식을 들먹이면서도 뒤로는 신나게 외도를 하거나 종교나 주식, 다단계 같은 것에 미쳐 있는 종류의 사람들이었다.  - 대도시의 사랑법, 박상영&lt;/p&gt;
&lt;p&gt;“상실하고 나서야 비로소 알게 되는 소중함도 있어. 네가 그래”&lt;/p&gt;
&lt;p&gt;집착이 사랑이 아니라면 난 한번도 사랑해본 적이 없다.&lt;/p&gt;
&lt;p&gt;언제나 때에 맞춰 블루베리를 사다 놓던 재희. 내가 만났던 모든 남자들의 이름과 얼굴을 기억하는, 내 연애사의 외장하드 재희. 아무 데서나 담배를 피우며, 가당찮은 남자만 골라 만나는 재희.&lt;/p&gt;
&lt;p&gt;모든 아름다움이라고 명명되는 시절이 찰나에 불과하다는 것을 가르쳐준 재희는, 이제 이곳에 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;chatgpt에 의하면 인간은 2비트로 구성된 30억개 가량의 유전 정보로 이루어져 있다고 한다. 정보량으로 계산하면 대충 750mb. 생각보다 작아서 놀랐다. 고작 750mb에 울고 웃는 인생사라뉘.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;2억이면 단순 월 1700가량. 400시간 하면 시급 4.25만. 울회사 신입이 시급 2.4만. 게다가 뉴욕. 게다가 신생 스타트업. 심지어 대표가 트랙레코드 없음. 스톡옵션은 긁지 않은 복권 정도로 봐야. 보상은 최고라 보긴 어렵고 성공은 공수표 아닌가 싶다. 공동창업자를 섭외하는게 빠르지 않을까?! &lt;a href=&quot;https://x.com/sinecera12/status/1863727891592409483&quot;&gt;https://x.com/sinecera12/status/1863727891592409483&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;리얼인가?&lt;br&gt;
&lt;a href=&quot;https://n.news.naver.com/article/029/0002920073?sid=100&quot;&gt;https://n.news.naver.com/article/029/0002920073?sid=100&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;진심 나라꼴이 이게먼지 ㄷ ㄷ ㄷ &lt;a href=&quot;https://n.news.naver.com/article/002/0002362429?type=breakingnews&amp;#x26;cds=news_edit&quot;&gt;https://n.news.naver.com/article/002/0002362429?type=breakingnews&amp;#x26;cds=news_edit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;400만원에 4배 올랐다고 팔고 좋아했던 나 자신을 돌아보게되는 늬우스. &lt;a href=&quot;https://n.news.naver.com/article/016/0002397677?type=breakingnews&amp;#x26;cds=news_edit&quot;&gt;https://n.news.naver.com/article/016/0002397677?type=breakingnews&amp;#x26;cds=news_edit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;최근 코드 리뷰를 o1-mini로 돌리고 있는데 나름 만족한다. 당연하지만 나보다 훨씬 일관되게 빠짐없이 지치지도 않고 친절하게 매번 리뷰한다. 심지어 에고 없음.&lt;/p&gt;
&lt;p&gt;돌리면서 느낀 건 내가 보는 걸 똑같이 보여주는게 생각보다 어렵다. 그렇다고 필요한 모든 걸 때려넣기엔 컨텍스트 제한이 있고, 제한이 없다 한들 비용이 문제겠지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;뉴스가 하나같이 진짜 어질어질하네&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;세상의 숨겨진 비밀들을 배울 기회가 전혀 없이 살아간다는 것은, 이렇게 말해도 좋다면 몹시 불행한 일이다. 그것은 마치 평생 똑같은 식단으로 밥을 먹어야 하는 식이요법 환자의 불행과 같은 것일 수 있다. - 모순, 양귀자&lt;/p&gt;
&lt;p&gt;이모는 자신의 죽음으로 자식들의 삶이 완벽하게 지리멸렬해지는 것을 막아냈다.&lt;/p&gt;
&lt;p&gt;인생은 탐구하면서 살아가는 것이 아니라, 살아가면서 탐구하는 것이다. 실수는 되풀이된다. 그것이 인생이다......&lt;/p&gt;
&lt;p&gt;엉뚱한 장소에서 전혀 쌩뚱맞은 사람이 추천해줘서 보게 됐는데 올해의 책에 둘만했다. 98년 초판인데 그시절을 살았던 사람으로 아날로그 감성이 묻어 있는 그때 장면들이 좋았다. 인생은 그 자체로 모순 덩어리인지도...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;openai o1 정식버전 출시. 2024 수능 수학 킬러문항 넣어봤다. 3분 넘게 생각하며 애를 태웠지만 여전히 풀지못함. o1-preview때보다 임팩트가 약한게, 지리멸렬한 일들만 하다보니 o1 쓸일이 그닥 없다는 걸 알게됐기 때문. 코딩에 마지막으로 쓴게 몇 달 된 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;다만 붓다가 생각했던 것은, 모든 만족이 만족의 최고점을 재현하지 못한다는 불만족을 필연적으로 수반한다는 사실이었다. 다시 말해 모든 만족은 그것이 유지되지 못한다는 면에서 동시에 불만족이라는 지적이다. - 인생의 괴로움과 깨달음 : 미처 몰랐던 불교, 알고 싶었던 붓다, 강성용&lt;/p&gt;
&lt;p&gt;인간의 경험은 모두 대상과 인간의 감각 기관에 의지해서 생겨난다. 따라서 이 논리에 따르자면 인간의 모든 경험은 조건에 따라 구성된 결과물이고, 그것은 영속성을 가질 수 없고, 영속적이지 않은 한 모두 고생으로 귀결된다는 명제가 만들어지는 맥락을 우리는 이제 이해할 수 있다.&lt;/p&gt;
&lt;p&gt;결국 정리하자면, 우리가 인생에서 어려움을 겪는 근본적인 이유는 좋아하는 일(rāga)이 있고 싫어하는 일(dveṣa)이 있고, 이것들 때문에 정신을 차리지 못하는 경우(moha)가 있기 때문이다. 이것이 인생에 대한 붓다의 근본적인 진단이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;민주주의는 다수가 인기 없는 소수를 죽이기로 결정할 수 있는 제도가 아니다. 민주주의는 중앙 권력에 분명한 제한이 있는 제도다. - 넥서스, 유발 하라리&lt;/p&gt;
&lt;p&gt;‘민주주의’로 정의하는 기준은 하나뿐이다. 즉 중앙정부가 무제한적인 권한을 갖지 않고 중앙의 실수를 바로잡을 수 있는 견고한 장치를 갖추고 있다는 것이다. 민주주의 네트워크는 모두가 오류를 범할 수 있다고 가정하며, 선거의 승자와 다수에 속하는 유권자들도 그 점에서는 예외가 아니다.&lt;/p&gt;
&lt;p&gt;언론인은 인기 정치인이 뇌물을 받았다고 폭로할 수 있으며, 판사는 법정에 유력한 증거가 제출되면 국민 대부분이 이 혐의를 믿고 싶어 하지 않아도 해당 정치인을 감옥에 보낼 수 있다.&lt;/p&gt;
&lt;p&gt;또한 권력을 견제하는 자정 장치는 너무 소모적이어서 중앙정부의 힘을 마비시켰다. 특히 세임의 모든 의원에게 주어진 의회 법안에 대한 거부권이 정치적 교착상태를 초래했다. 규모가 크고 다양한 구성원으로 이루어진 정치집단과 약한 중앙정부의 결합은 치명적이었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;o1이 분석한 이재명측 최선책.&lt;/p&gt;
&lt;p&gt;탄핵 추진을 서두르되, 이재명 본인의 대법원 확정판결 전에 헌재 결정과 조기 대선이 이루어지도록 타이밍을 맞추는 것. 이를 위해 탄핵 표결 과정에서 여당 내 분열을 최대한 활용하고,&lt;/p&gt;
&lt;p&gt;헌법재판소 재판관 구성을 야당에 유리하게 정비하며, 재판 과정에서는 최대한 시간을 벌어야 한다. 또한 한동훈 세력과 비공식적 합의를 통해 최소 8표 이상의 이탈표를 확보할 수 있는 뒷거래를 시도하는 것이 유리하다.&lt;/p&gt;
&lt;p&gt;여당이 계속 탄핵을 반대할 경우 추가 카드&lt;br&gt;
여론 압박 극대화&lt;br&gt;
여당 내 파열음 확대 유도&lt;br&gt;
대체적 카드 활용(장관 탄핵, 특검, 국정조사)&lt;br&gt;
법적, 제도적 절차 개선 압박&lt;br&gt;
제3세력 및 시민단체 활용&lt;/p&gt;
&lt;p&gt;한동훈측 최선책&lt;br&gt;
대통령과의 차별화, 이미지 세탁&lt;br&gt;
탄핵보다는 자진 하야 유도&lt;br&gt;
이재명 법적 리스크 활용&lt;br&gt;
중도·개혁 이미지로 여론 확보&lt;br&gt;
경제·안보 어젠다 선점&lt;/p&gt;
&lt;p&gt;한동훈측 선호 하야시점&lt;br&gt;
이재명 대법원 판결 직후&lt;br&gt;
여론 피로 극대화 시점&lt;br&gt;
여당 내부 재정비 가능 시점&lt;/p&gt;
&lt;p&gt;양측 모두 최선의 선택을 할 경우, 정국은 장기화되고 극단적 정치 대치 속에서 탄핵과 하야 타이밍, 재판 일정, 여론 지형, 당내 분열을 둘러싼 치열한 신경전이 벌어진다. 결국 승자는 마지막 순간, 어느 쪽이 타이밍을 더 정확히 맞추느냐에 달려 있다.&lt;/p&gt;
&lt;p&gt;이재명은 탄핵 성립을 서두르고, 한동훈은 탄핵을 저지·지연하면서 이재명의 법적 리스크가 확정되기를 기다리는 ‘시간과 기회의 게임’이 전개되는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;국장. 외국인 투매를 예상했지만, 정작 외국인은 사고 개미가 투매. 자국민이 더 못 믿는 k주식 클라쓰.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;우리나라도 점점 인력 귀해지는게 느껴진다. 채용공고 지원자 없음, 자영업자 영업시간 단축, 사람 들어가는 다른 온갖 일들도 구하기가 예전보다 훨 어려움. 앞으로 사람 엮인 일은 가급적 빨리 탈출하는게 스트레스가 덜할 것 같은 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;코딩한정 인공지능의 가장 웃긴 점은 없어도 개발 잘한다고 생각되는 사람들은 하나같이 미쳐서 입이 마르게 칭찬하며 사용하는데, 코딩 못하는 사람들은 한결같이 폄하하면서 안쓴다는 사실. 20불 투자해서 월급 받으면 남는 장사일 것 같은데. 왜 안쓰지?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;openai 말처럼 agi는 이미 달성된거 아닌가 싶은?! &lt;a href=&quot;https://x.com/golbin/status/1867047426617643136&quot;&gt;https://x.com/golbin/status/1867047426617643136&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;무례와 혐오와 경쟁과 분열과 비교와 나태와 허무의 달콤함에 길들지 말길, 의미와 무의미의 온갖 폭력을 이겨내고 하루하루를 온전히 경험하길, 그 끝에서 오래 기다리고 있는 낯선 나를 아무 아쉬움 없이 맞이하길 바랍니다. &lt;a href=&quot;https://maily.so/remem/posts/w6ov8jd9rk5&quot;&gt;https://maily.so/remem/posts/w6ov8jd9rk5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;생긴게 딱 비전프로, 샤오미 욕할게 아님. 패스트팔로어 원조 맛집 삼전.hbm도 빨리 따라가자. &lt;a href=&quot;https://n.news.naver.com/article/016/0002401969?cds=news_my&quot;&gt;https://n.news.naver.com/article/016/0002401969?cds=news_my&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;아무리 공인이라 한들 외모로 뭐라마라하는 세태를 보면 우리 사회가 폭력적이라는 생각이 많이 든다. 비판하고 싶다면 그냥 그 사람이 한 일로만 비판하면 충분하지 않나 싶다. 거기다 굳이 외모까지 끌어와서 비아냥댈 필요가 있나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;나는 결국 풍등에 두 글자만을 남겼다.&lt;br&gt;
규호.&lt;br&gt;
그게 내 소원이었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#x3C;대도시의 사랑법&gt;, 박상영&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;탐라에 하도 돌아다니길래 봤는데 생각보다 몹시 재밌었다. 글 내용 중에 이렇게 태어나서 라는 말들이 여럿 나와서 미약하게나마 퀴어를 조금은 이해하게 된 것 같다. 나도 테어나보니 왼손잡이. 이 털끝만큼의 차이도 많은 불편과 시선을 가져오는데 그들은 오죽할까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;앞으로는 법조항도 유닛테스트 후 테스트 커버리지 100프로 달성하도록 강제해야할듯. 현실이 막장으로 가니 헛점이 너무 많다. 아니면 라이브 테스트 중인지도?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;맞아요. 위대한 사랑 이야기라고 하는 「타이타닉」도 결국에 만난 지 얼마 안 된 사람을 위해 대신 죽을 정도로 도취되었던 거 아닌가요? 그 둘이 살아남았으면 결국 「레볼루셔너리 로드」처럼 진절머리 나는 결혼 생활을 했을 걸요. - &amp;#x3C;급류&gt;, 정대건&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-12-26&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] __del__에서 리소스 해제를 하면 안 되는 이유]]></title><description><![CDATA[시작은 mysql 클라이언트였다. 해당 클래스를 사용하는 코드에서 close를 하지 않아서 리소스 릭이 발생하는 문제. pymysql…]]></description><link>https://jiniya.net/2024/12/python_raii/</link><guid isPermaLink="false">https://jiniya.net/2024/12/python_raii/</guid><pubDate>Tue, 10 Dec 2024 11:35:00 GMT</pubDate><content:encoded>&lt;p&gt;시작은 mysql 클라이언트였다. 해당 클래스를 사용하는 코드에서 close를 하지 않아서 리소스 릭이 발생하는 문제. pymysql은 왜 이걸 파괴될 때 자동으로 해제하지 않게 만들어서 개발자가 실수하게 만들었지?! 라고 삽질하다 알게 된 이유. 오늘의 교훈: 언어 별로 비슷한 점도 있지만, 다른 점도 많다.&lt;/p&gt;
&lt;p&gt;파이썬에서 &lt;code class=&quot;language-text&quot;&gt;__init__&lt;/code&gt;에서 리소스를 획득하고, &lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt;에서 리소스를 해제하는 패턴은 피하는 것이 좋습니다. 이유는 다음과 같습니다:&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;1. &lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt; 호출 보장이 없음&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt; 메서드는 객체가 &lt;strong&gt;가비지 컬렉션&lt;/strong&gt;에 의해 삭제될 때 호출되지만, 호출 시점이 보장되지 않습니다.&lt;/li&gt;
&lt;li&gt;특히, 프로그램이 종료할 때 전역 객체들의 소멸 순서에 따라 &lt;strong&gt;필요한 리소스가 이미 해제된 상태&lt;/strong&gt;일 수 있습니다.
&lt;ul&gt;
&lt;li&gt;예: 파일 핸들러, 네트워크 연결 등이 이미 닫혀있는 경우 문제가 발생할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;2. &lt;strong&gt;순환 참조 문제&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;객체가 다른 객체와 순환 참조를 형성하면, 파이썬의 가비지 컬렉터가 &lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt;을 호출하지 않을 수 있습니다.
&lt;ul&gt;
&lt;li&gt;파이썬의 순환 참조를 감지하는 가비지 컬렉터는 &lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt;이 있는 객체를 처리하기 어렵습니다.&lt;/li&gt;
&lt;li&gt;결과적으로, 리소스가 영구적으로 해제되지 않을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;3. &lt;strong&gt;명시적 리소스 관리 부족&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;리소스 관리가 암묵적으로 이루어져 가독성과 유지보수가 어려워집니다.
&lt;ul&gt;
&lt;li&gt;리소스 사용자가 객체의 수명을 정확히 제어하지 못합니다.&lt;/li&gt;
&lt;li&gt;누군가 &lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt; 호출을 의도적으로 방지하거나 놓치면, 리소스 누수가 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;4. &lt;strong&gt;GC 타이밍에 의존&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;가비지 컬렉션은 &lt;strong&gt;언제 실행될지&lt;/strong&gt; 보장되지 않습니다.
&lt;ul&gt;
&lt;li&gt;예를 들어, 리소스를 빨리 해제해야 하는 상황에서 &lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt;에 의존하면, 리소스가 불필요하게 오래 유지될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;대안: &lt;strong&gt;컨텍스트 관리자 (&lt;code class=&quot;language-text&quot;&gt;with&lt;/code&gt; 문법)&lt;/strong&gt; 사용&lt;/h3&gt;
&lt;p&gt;컨텍스트 관리자를 통해 리소스를 명시적으로 관리하는 것이 더 안전하고 직관적입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ResourceHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; resource

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__enter__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 리소스 획득&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resource&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; 획득&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resource

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__exit__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exc_value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; traceback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 리소스 해제&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resource&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; 해제&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 예외 처리도 가능&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; exc_type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;예외 발생: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;exc_value&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 예외를 억제하지 않음&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 사용 예&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; ResourceHandler&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;파일&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; resource&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;resource&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; 사용 중&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;요약&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;__del__&lt;/code&gt; 대신 &lt;strong&gt;컨텍스트 관리자&lt;/strong&gt;나 명시적인 리소스 해제 메서드(&lt;code class=&quot;language-text&quot;&gt;close&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;release&lt;/code&gt; 등)를 사용하는 것이 바람직합니다.&lt;/li&gt;
&lt;li&gt;이를 통해 리소스 관리가 예측 가능하고, 코드가 더 견고해집니다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 11월의 잡담]]></title><description><![CDATA[#0 c로 코딩해보면 그나마 c++이 천사였구나 싶다. 2024-11-01 #1 나 포함 sns 하는 사람들은 일정 부분 다들 자의식 과잉 상태 아닌가 싶다. 그러니 에고는 좀 내려놓자. 냬러놔도 평균 이상일듯. 2024-11-03 #…]]></description><link>https://jiniya.net/2024/11/small-talk-2024-11/</link><guid isPermaLink="false">https://jiniya.net/2024/11/small-talk-2024-11/</guid><pubDate>Fri, 29 Nov 2024 13:30:06 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;c로 코딩해보면 그나마 c++이 천사였구나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;나 포함 sns 하는 사람들은 일정 부분 다들 자의식 과잉 상태 아닌가 싶다. 그러니 에고는 좀 내려놓자. 냬러놔도 평균 이상일듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;인공지능이 코드 리뷰를 시작했다. 친절하게 예시도 들어서 무슨 문제점이 있는지 착착 알려주었지만 생각보다 쓸모 없다는 결론. 사람이 리뷰를 읽지 않거나 읽어도 이해를 못함. 고쳐도 고친게 아닌 상황. 모든 일이 다 그렇겠지만 코딩도 적성이 있다는 걸 다시 한 번 느낀다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;내가 하는 일이 ‘나 자신’은 아니다. 삶에서 행한 그 어떤 역할로도 자신을 정의하지 마라. -  삶이 던지는 질문은 언제나 같다, 찰스 핸디&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;기분이 언짢을 때는 가급적 나쁜 말은 자제한다. 우울할 때는 술을 마시지 않는다. 나이 들면서 바뀐 것중에 그나마 괜찮은 것.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/087/0001077557?type=breakingnews&amp;#x26;cds=news_edit&quot;&gt;https://n.news.naver.com/article/087/0001077557?type=breakingnews&amp;#x26;cds=news_edit&lt;/a&gt; 트럼프가 대단한건지 머스크가 대단한건지, 세상은 더 요란해지겠다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;내 첫 컴퓨터는 삼성 매직스테이션 mm242u, 94년, 240만원. 소비자 물가지수 환산시 대략 현재가치 560만원. 정말 무지하게 사달라고 떼썼던 기억이 난다. 하지만 엄마의 예상과 다르게 엄마가 전 인생을 통틀어 수행한 모든 투자 중 가장 성공적인 투자가 됐다. &lt;a href=&quot;https://x.com/kinophio/status/1854851692862620044&quot;&gt;https://x.com/kinophio/status/1854851692862620044&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://kostat.go.kr/mondyValueCalc.es?mid=b70302000000&quot;&gt;https://kostat.go.kr/mondyValueCalc.es?mid=b70302000000&lt;/a&gt; 여기 기준으로 계산한건데 최근 거 넣어보니 신뢰가 팍 떨어지네. 2020년도부터 지금까지 고작 13프로 올랐다는데서??&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;미신이나 무속의 기본 속성이 시키는대로 했다가 몇번 계속 잘되면 자연스레 맹신의 길로 가게 된다는 점. 최회장이 바보라서 무당데리고 선물옵션질하다 감빵가따온게 아님. 옆에서 보면 비웃을 일로 보이지만 저 한복판에 들어가 있으면 정상적 사고가 어려워짐. &lt;a href=&quot;https://www.google.com/amp/s/m.mt.co.kr/renew/view_amp.html%3fno=2013092913544553628&quot;&gt;https://www.google.com/amp/s/m.mt.co.kr/renew/view_amp.html%3fno=2013092913544553628&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;어렸을 때 엄마는 컴퓨터가 게임기라고 사주질 않았었다. 물론 비싸기도 했다. 나중에도 컴터 오래 하고 있으면 돈도 안되는거 공부나 하라고 엄청 뭐라함. 컴공과 졸업했을땐 의전원 가라고. 가끔 우리 애들 세대엔 뭐가 그런 존재일까 생각해본다. 뭐가됐든 애들이 하겠다는데 내가 말리는 거겠지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;이건 약간 소름. 반쯤 읽다 말았는데 나머지 절반도 읽어야겠... &lt;a href=&quot;https://x.com/danmusk/status/1854015673615458370&quot;&gt;https://x.com/danmusk/status/1854015673615458370&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;농담이었다. 하지만 때로는 자녀들도 머스크가 농담을 하는 건지 진담을 하는 건지 구분하기 어려웠다. 어쩌면 그 자신도 그럴지 몰랐다. 아이들은 경악했다. 머스크는 농담이라며 아이들을 안심시켰다. - &amp;#x3C;일론 머스크&gt;, 월터 아이작슨 지음 / 안진환 옮김, 이어지는 내용도 머스크답네 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;코인 시장을 보니 퇴사자가 나올거 같은 불길한 예감이 ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;연속혈당측정기 글이 보여서. 덱스콤g7 + 파스타 추천. 다른 제품 대비 비싸긴 하지만 업계 표준인듯. 보정 안해도 되고 블투 지원. 카카오 파스타 연동 가능. 단점은 자다가 센서 눌리면 값 이상해 지는 정도?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;대체로 태도가 좋은 사람이 성과도 좋은 경우가 많다. 문제는 둘이 일치하지 않는 경우인데 나는 성과를 중시하는 반면, 보통 사람들은 태도를 더 중요하게 생각하는 것 같은 느낌. 공부를 얼마나 하느냐보다 야간자율학습 시간에 남아있는 걸 더 중시하던 시스템을 보는 것 같기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;gpt한테 c++ rest api 라이브러리 추천하라니까 crow를 추천해줌. 코드가 어디서 본거 같아서 찾아보니 예전에 ndc에서 발표됐던 코드가 베이스인듯. 그때 그 슬라이드 흑마법 설명 보고 아 c++의 길은 깊고도 넓구나 했던 기억이. &lt;a href=&quot;https://github.com/CrowCpp/Crow&quot;&gt;https://github.com/CrowCpp/Crow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;난 20년 넘게 c++ 프로그래머로 일했지만 이 코드에 버그가 있다면 솔직히 못 고칠 거 같다. 어짜피 누구나 만들고, 고칠 수 있는 코드에는 한계가 있다. 사람이 만든 거든, 인공지능이 만든 거든 사용하는 사람 인식의 한계를 넘어서면 그저 까만건 글이고 흰건 여백인게 당연한게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;남대가 없는 이유는 이미 공대가 있어선지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;두괄식을 법으로 규정하든가 해야지...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://jacob.kim/blog/esop&quot;&gt;https://jacob.kim/blog/esop&lt;/a&gt; 물타기 신공으로 겨우 익절하고 나왔지만, 나도 50만에 물렸던 주주로써 남 일 같지 않네. 돈 참 잘버는 회사임에도 주가는 ㅠㅜ 레버리지 올인은 이러나 저러나 위험하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;mstr의 프리미엄은 기관 투자의 우회 루트가 될 수 있기 때문 아닌가 싶다. 일례로 국민연금은 코인이 없지만 mstr 주식은 가지고 있다. 모든 기관이 개인과 동일하게 코인 접근이 가능해지는 시점이 온다면 차익은 없어지지 않을까? 고로 무위험 차익은 아니라는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;제법 투지 책도 읽고 요란하게 개별주 골라서 사팔사팔 난리쳐보기도 했지만 단순한 밴스 포폴보다 수익이 좋기가 쉽지 않은게 현실이었다. 심지어는 마이너스인 경우도. 모건 하우절 말처럼 노력과 결과가 일치하지 않는 몇 안되는 분야중 하나가 투자라는 말이 실감남. &lt;a href=&quot;https://x.com/stocktrainkorea/status/1855502891207082352&quot;&gt;https://x.com/stocktrainkorea/status/1855502891207082352&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;특정 국가가 존재하는지 여부를 물을 때 우리는 상호주관적 현실을 다루고 있는 것이다. 충분한 사람들이 특정 국가가 존재한다는 데 동의한다면 그 국가는 존재하게 된다. - 넥서스, 유발 하라리&lt;/p&gt;
&lt;p&gt;코인으로 바꿔도 별반 다르지 않다는 생각. 충분한 사람이 가치가 있다고 믿으면 가치가 생기는 게 아닐까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;빗발치는 시국 선언에는 여러가지 이유가 있겠지만 밥줄 건드린 것도 크다고 본다. 자랑스런 동문인 대학이 아직 하지 않는 이유는 어쩌면 그들은 밥줄에 1도 타격이 없기 때문인지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;메신저로 두문장 보내면 될 일을 미괄식 대면 보고로 장황하게 설명하는 상황이 참 불편하다. 아주 미묘하게 케미가 안맞는 사람들이 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;행복의 문 하나가 닫히면 다른 문이 열립니다. 그러나 우리는 종종 닫힌 문을 너무 오랫동안 바라보느라 우리를 위해 열려 있는 문을 보지 못합니다. - 헬렌켈러&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;세상 다 가진 것 같은 사람들도 보기보다 참 열심히 살고 있었구나를 새삼 다시 느낀다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;묻는 내용에 답하는 기본 사항만 지켜도 일잘러 평가를 들을 수 있다. 예 아니오 질문이면 예 아니오로, 수치를 물으면 수치로. 아닌 사람들 특징. 엉뚱한 답변을 함. 예 아니오는 없고 장황한 설명만 있어서 결론을 다시 물어봐야 하거나, 수치를 물었는데 정작 답변에 수치가 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;혼전계약서나 혼외출산이 자연스럽게 받아들여지는 세상이 될지, 결혼이 종말을 맞을지, 폴리아모리가 득세한 세상이 될지 궁금하다. 느려도 세상은 조금씩 바뀌는듯. 반전은 미국에서 낙태가 다시 불법이 되고, 파탄주의가 다시 유책주의로 회귀하려는 움직임도 있다는 사실.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://qwenlm.github.io/blog/qwq-32b-preview/&quot;&gt;https://qwenlm.github.io/blog/qwq-32b-preview/&lt;/a&gt; 테스트 해보진 않았지만 벤치만 보면 미쳤다. 어쩌면 생각보다 거대모델을 만드는 사업엔 해자가 없는건지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;사람이 옷입고 나와서 춤추던게 엊그제 같은데 발전 속도 무엇?! 현대가 인수한 보스턴다이나믹스는 뭐하고 있는지 ㅠㅜ &lt;a href=&quot;https://x.com/danmusk/status/1862117051814510753&quot;&gt;https://x.com/danmusk/status/1862117051814510753&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;뉴진스 관련 내용은 잘 모르지만 저 엄청난 계약이 내용증명 한통과 14일만에 저렇게 깔끔하게 종료시킬 수 있다고 생각하는게 다소 신선하다. 위약금을 논외로 하더라도 상당한 법적 분쟁을 피하긴 힘들거 같은 느낌인데. &lt;a href=&quot;https://n.news.naver.com/article/056/0011847501?sid=103&quot;&gt;https://n.news.naver.com/article/056/0011847501?sid=103&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#29&lt;/h2&gt;
&lt;p&gt;물에 빠지면 살기만해도 좋겠다 생각한다. 하지만 물밖으로 나오면 기쁘기도 잠시 보따리가 생각나는게 사람 아닌가 싶다. 물에 빠져서 생사를 넘나들던 그때를 잊지 말자. 보따리는 애초에 내것이 아니었던건지도 모른다. 목숨을 구한 것만해도 천운이다 생각하고 감사하자.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-11-29&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 10월의 잡담]]></title><description><![CDATA[#0 We write unsafe so you don't have to. 이 정도 워딩은 구글 클라스는 되야 할 수 있는 말인듯 ㅋㅋㅋ https://x.com/RustTrending/status/1840744999077781746 2024-10-0…]]></description><link>https://jiniya.net/2024/10/small-talk-2024-10/</link><guid isPermaLink="false">https://jiniya.net/2024/10/small-talk-2024-10/</guid><pubDate>Thu, 31 Oct 2024 20:59:20 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;We write unsafe so you don&apos;t have to. 이 정도 워딩은 구글 클라스는 되야 할 수 있는 말인듯 ㅋㅋㅋ &lt;a href=&quot;https://x.com/RustTrending/status/1840744999077781746&quot;&gt;https://x.com/RustTrending/status/1840744999077781746&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;예전엔 ai가 뭔가를 하면 신기해 했다. 이제는 어쩌다 ai가 못하는 걸 내가 하면 묘한 쾌감이 든다. 인간의 마지막 쓸모를 증명하는 느낌이랄까?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;기다려 봐. 시간은 어짜피 가게 돼 있고, 한 번은 기회가 와. - 백설 공주에게 죽음을 ep01&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;Cursor 좋데서 써봤는데. 완전 신세계. 이것이 21세기 개발이지 싶다. 쓰다가 새롭게 알게된건 ai와도 케미가 있다. 디폴트가 클로드인데 쓰다가 묘하게 거슬려서 gpt로 변경함. 구글은 아예 선택조차 안되는 현실.&lt;/p&gt;
&lt;p&gt;ai도 뭔가 출신 성분이 있는게 클로드와 지피티는 만든 사람들이 비슷해서 그런지 코딩하는거도 비슷함, 그에반해 제미나이는 약간 결이 다름. 그래서 오히려 두개쓰려면 제미나이를 넣는 게 더 좋다는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/052/0002095106?sid=104&quot;&gt;https://n.news.naver.com/article/052/0002095106?sid=104&lt;/a&gt; 안타까운 뉴스다. 그나마 비교적 안전한 나라에 조금은 평화로운 시기에 태어났다는 하나만으로도 감사하며 살아야 하는게 아닌가 싶다. 정말 싸우지 않는 인류란 존재할 수 없는 것인가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;[소고] 재미로 보는 개발자 채용 가산점 히스토리 &lt;a href=&quot;https://jiniya.net/2024/10/tips-for-hiring-developers-for-fun/&quot;&gt;https://jiniya.net/2024/10/tips-for-hiring-developers-for-fun/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;내겐 스위스까지 날아갈 비행기 티켓 값이 없었다. 자신이 원하는 품위 있는 죽음을 맞이하는 데는 많은 돈이 필요했다. 죽음은 모두에게 평등하지만, 죽음에 이르는 과정까지 평등하지는 않았다. - 나보다 어렸던 엄마에게, 정진영&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;와 삼전 ㅋㅋㅋ 주식 참 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;노벨 물리학상을 힌튼옹께서 받았다뉘. 대ai시대의 서막을 알리는건가. 그나저나 물리학자들은 다소 멘붕일듯. &lt;a href=&quot;https://n.news.naver.com/article/020/0003591187&quot;&gt;https://n.news.naver.com/article/020/0003591187&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;와우. 노벨상 힙하네 ㄷㄷ 개발자만 문제가 아닌듯한. 과학계도 이쯤되면 말들이 많을듯. &lt;a href=&quot;https://x.com/golbin/status/1843966745322901633&quot;&gt;https://x.com/golbin/status/1843966745322901633&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;새 제품 코드를 쓰고 있는데 어림잡아 7할은 gpt가 작성한다. 더 충격적인건 o1을 쓸만한 상황이 별로 없다는 점. 한 번 있었는데 역시나 몹시 우아한 코드를 선물해 주었다. 얼마나 루틴화된 코드만 쓰는지 새삼 실감한다. 웃픈건 끝나면 뒤풀이도 gpt랑 해야할 판. 참여한 휴먼은 나혼자라 ㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;어쩌다 신입을 덜 뽑는 세상이 되었을까? &lt;a href=&quot;https://jiniya.net/2024/10/hiring-fewer-entry-level-employees/&quot;&gt;https://jiniya.net/2024/10/hiring-fewer-entry-level-employees/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/022/0003975584?type=breakingnews&amp;#x26;cds=news_my&quot;&gt;https://n.news.naver.com/article/022/0003975584?type=breakingnews&amp;#x26;cds=news_my&lt;/a&gt; 헐헐헐... 무슨 일이 벌어지고 있는거지. 진심 대박 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://m.news2day.co.kr/article/20170817091506&quot;&gt;https://m.news2day.co.kr/article/20170817091506&lt;/a&gt; s-oil기준 10년에 거의 2배. 연봉도 연에 7프로는 오르는듯한... &lt;a href=&quot;https://x.com/PropertyDog/status/1844163088737763826&quot;&gt;https://x.com/PropertyDog/status/1844163088737763826&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;직원이 굳이 주인의식 가질 필요도 없고, 강요할 필요는 더 없다는 생각. 회사든 직원이든 쌍방 계약대로만 해도 서로 참 잘한 거라는 생각. 그나저나 요즘도 주인의식 운운하는 회사가 있을지?! 있다면 하루빨리 탈출하자.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;그래도 요즘 우리 사회가 많이 좋아졌다고 느끼는게 포괄임금제. 돈 있는 회사는 상당수 비포괄로 전향했고, 없는 회사는 대체로 워라밸이 좋아지는 쪽으로 진화한 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;진심 오지라퍼들의 나라. 이젠 좀 바뀌자. &lt;a href=&quot;https://x.com/_Valentino/status/1846369929580499223&quot;&gt;https://x.com/_Valentino/status/1846369929580499223&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;[일상] 거대 언어 모델 코딩 테스트 &lt;a href=&quot;https://jiniya.net/2024/10/llm-coding-test&quot;&gt;https://jiniya.net/2024/10/llm-coding-test&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;김영사에서 열일해서 감사하게 한글로 읽고 있는데. 하라리옹 뭔놈에 서론에 일케 힘을줬지. 서론 읽다 숨넘어가는쥴 ㄷ ㄷ ㄷ 이번 책도 재밌으면 킹정하겠지만 묘하게 불길한 예감이. &lt;a href=&quot;https://x.com/codemaru/status/1837777684153438702&quot;&gt;https://x.com/codemaru/status/1837777684153438702&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;캡쳐 공고 보다 문득,, 고성능 견고함 유연성 확장성같은 단어는 너무 뒷방 늙은이같은 느낌인걸까?! &lt;a href=&quot;https://x.com/utilforever/status/1846711699111661915&quot;&gt;https://x.com/utilforever/status/1846711699111661915&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Writing solid code를 버그 안녕이라고 번역하는 거도 오바지만 solid한 코드 작성하기도 뭔가 이상하지 않나 싶은...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;챗지피티 시대에 연구 일지에 결재 라인 없다고 연구소 승인 취소한다는 미친 소리를 ㅠㅜ 쌍팔년도도 아니고 결재 라인?! 진짜 노답 공뭔들. 연구 안하고 일지 안쓰는데를 잡아야지. 깨알같이 거의 전원 매일 일지 쓰는 회사에 일지에 결재 라인이 없다고 연구소 승인 취소 협박질이라뉘.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;ai 관련 유튜브를 좀 봤는데 생각보다 개념잡고 대충 뭐가되는지 확인하는데는 편리하다. 특히 차로 이동할때 틀어 놓고 듣기 편함. 물론 세부 내용은 추가로 문서 보거나 지피티 이용하는게 빠르긴함. 유튜브로 개발 공부한다고 뭐라할건 아닌듯. 심지어 요즘은 인강세대.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;[ai] Qwen2.5-72b 성능 무엇?! &lt;a href=&quot;https://jiniya.net/2024/10/qwen2.5-72b/&quot;&gt;https://jiniya.net/2024/10/qwen2.5-72b/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;비유 참 찰지다. 삼전이 아니더라도 한번 새겨볼만한 이야기. &lt;a href=&quot;https://x.com/ds1dbx/status/1848861078530494605&quot;&gt;https://x.com/ds1dbx/status/1848861078530494605&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;o1-preview보다 코딩 잘한데서 써봤는데 틀린 말은 아닌듯?! o1한테 시킨 마지막 작업을 똑같이 시켰는데 더 깔끔하고 한번에 동작하는 코드 ㄷ ㄷ ㄷ 40초 가까이 생각한 o1이 뻘쭘해졌다. &lt;a href=&quot;https://x.com/AnthropicAI/status/1848742740420341988&quot;&gt;https://x.com/AnthropicAI/status/1848742740420341988&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;나만 가려운건 아니었군. 이거 때문에 vscode로 갈아타는 작업을 하고 있는데 아무래도 vs만의 장점도 있기도 해서 쉽진 않은. &lt;a href=&quot;https://github.com/continuedev/continue/issues/759&quot;&gt;https://github.com/continuedev/continue/issues/759&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;할아버지는 노환으로 돌아가셨는데 평생 술을 드셨다. 병원에 입원하셔서 처음 와인을 드시고는 이렇게 맛있는 술을 왜 이제야 가져왔냐고. 병원에서도 좋아하시면 그냥 드시게 주라는 말. 80중반이 넘어서 돌아가셨는데 할머니가 계셨음 더 오래 건강하셨을거라는게 중론. 건강도 유전자빨이 크다.&lt;/p&gt;
&lt;p&gt;멍거옹도 콜라에 대해 기회 비용적 접근을 언급한 적이 있었다. 수명은 줄겠지만 그만큼의 청량감도 무시못한다고. 청량감을 선택하고 일찍 죽을지, 그런 재미를 포기하고 오래 살지는 개인의 결정이 아닐까 싶다. 아이러니하게도 청량감을 택한 멍거옹도 장수한게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;골아픈 하루. 모든 일이 럭키비키인 원영적 사고로 살고 싶지만 쉽지 않다. 진심 하드웨어와 사람이 함께 엮인 일은 결이 안 맞네.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-10-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] Qwen2.5-72b 성능 무엇?!]]></title><description><![CDATA[막내가 코드를 한 줄 고쳤다. 플래그가 잘못돼서 검사 루틴 체크가 안된다면서 값을 0x100에서 0x50으로 변경했다. 0x5…]]></description><link>https://jiniya.net/2024/10/qwen2.5-72b/</link><guid isPermaLink="false">https://jiniya.net/2024/10/qwen2.5-72b/</guid><pubDate>Thu, 17 Oct 2024 15:35:00 GMT</pubDate><content:encoded>&lt;p&gt;막내가 코드를 한 줄 고쳤다. 플래그가 잘못돼서 검사 루틴 체크가 안된다면서 값을 0x100에서 0x50으로 변경했다. 0x50만 보고 난 넘겨 짚었다. 쓸데 없는 걸 또 왜 고쳤지, 라는 생각.&lt;/p&gt;
&lt;p&gt;그러다 같이 저녁을 먹게 되서 관련해서 이야기를 듣게 됐다. 자기가 분석해봤는데 기존 코드에 이러저러한 부분 때문에 플래그가 클리어돼서 고쳐야 한다는 것이었다. 다른 주장이 있어서 일단 가서 다시 살펴 보겠다고는 했다. 그러면서도 내 생각은 여전히 세모라고 했다. 0x50은 틀린 건 확실했기 때문이다. 클리어 된다는 걸 내가 체크를 못한 건가 해서 확인을 해야겠다 싶었다.&lt;/p&gt;
&lt;p&gt;집에 와서 코드를 보니 막내 말도 맞았다. 하지만 문제는 0x50이었다. 0x10이랑 0x40을 쓰는 플래그랑 겹치는 값인 것이다. 그래서 과연 인공지능은 이 문제를 파악해낼지 궁금해서 테스트를 해보았다. 결과는 Qwen2.5-72b의 압승. 물론 사고력 모델인 o1 시리즈는 차원이 다른 답을 보여주었다. 그들 사이엔 768차원 정도의 간극이 있긴 한듯.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;프롬프트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;XXX 플래그 검사하는 로직으로 살펴봤을 때 아래 코드에서 EEE_INDEX를 MAKELONG(0x50, 3)로 변경하는게 문제 없는지 판단해줘&lt;/p&gt;
&lt;p&gt;AAA_INDEX = MAKELONG(0x10, 3),&lt;br&gt;
BBB_INDEX = MAKELONG(0x20, 3),&lt;br&gt;
CCC_INDEX = MAKELONG(0x40, 3),&lt;br&gt;
DDD_INDEX = MAKELONG(0x80, 3),&lt;br&gt;
EEE_INDEX = MAKELONG(0x100, 3),&lt;/p&gt;
&lt;p&gt;... 관련 코드 ...&lt;/p&gt;
&lt;h3&gt;4o-mini&lt;/h3&gt;
&lt;p&gt;얘는 일단 말귀 자체를 못 알아 먹는다. 0x100을 0x50으로 변경하는 걸 검토하라는데 엉뚱한 소리를 함.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x100, 3)&lt;/code&gt;으로 변경하는 것이 문제가 없는지 판단하기 위해 몇 가지 요소를 고려해야 합니다.&lt;/p&gt;
&lt;h3&gt;1. &lt;strong&gt;상수 중복 여부&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x100, 3)&lt;/code&gt;으로 설정될 경우, 다른 인덱스 값과의 중복 여부를 확인해야 합니다. 주어진 코드에서 다른 인덱스 &gt; 값들은 다음과 같습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;AAA_INDEX = MAKELONG(0x10, 3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;BBB_INDEX = MAKELONG(0x20, 3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;CCC_INDEX = MAKELONG(0x40, 3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DDD_INDEX = MAKELONG(0x80, 3)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x100, 3)&lt;/code&gt;는 이들과 중복되지 않으며, 기존의 값들과 겹치지 않기 때문에 문제는 없습니다.&lt;/p&gt;
&lt;h3&gt;2. &lt;strong&gt;논리적 의미&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;의 의미를 파악하는 것이 중요합니다. ...&lt;/p&gt;
&lt;h3&gt;3. &lt;strong&gt;사용된 위치&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;코드에서 &lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;가 어떻게 사용되는지를 검토해야 합니다. &lt;code class=&quot;language-text&quot;&gt;Do&lt;/code&gt; 메서드와 같은 곳에서 해당 플래그가 어떤 동작을 유발하는지 &gt; 이해해야 합니다. 만약 &lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;GetFileEx&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;TestFlag&lt;/code&gt;와 같은 중요한 검사와 연관되어 있다면, 변경으로 인해 예상치 못한 동작이 발생할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;결론&lt;/h3&gt;
&lt;p&gt;위의 분석을 바탕으로, &lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x100, 3)&lt;/code&gt;로 변경하는 것이 중복이나 충돌 없이 문제가 없을 것으로 보입니다. 그러나 해당 플래그가 어떤 의미를 지니고 있는지, 그리고 그 사용 위치를 검토하여 최종 판단을 내리는 것이 좋습니다. 특히, 기존의 로직이 이 값을 기반으로 동작하고 있다면, 변경이 다른 동작에 영향을 미칠 수 있으므로 신중해야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;4o&lt;/h3&gt;
&lt;p&gt;얘는 말귀는 알아 먹었고 전개도 나쁘진 않았지만 결국 장황하게 설명하며 핵심을 피해가고 있다. 아는 거 같기도 하고 모르는 거 같기도 하고 뭔가 모르지만 아는 척 하는 거 같기도 한 아주 두루뭉실 애매한 답변.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;주어진 코드에서는 다양한 이벤트 또는 조건 플래그를 설정하기 위해 MAKELONG 매크로를 사용합니다. MAKELONG는 두 개의 16비트 값을 받아 하나의 32비트 값을 생성하는 매크로로, 여기서는 인덱스를 생성하는 데 사용되고 있습니다.&lt;/p&gt;
&lt;p&gt;EEE_INDEX를 MAKELONG(0x100, 3)에서 MAKELONG(0x50, 3)으로 변경하려는 제안에 대해 검사해 보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;MAKELONG의 구조: MAKELONG(a, b) 구조에서 a는 하위 16비트 값을, b는 상위 16비트 값을 나타냅니다. 즉, MAKELONG(0x100, 3)은 0x00030064이라는 32비트 수를 생성하며, 이는 플래그 배열의 3번째 부분(HIWORD)에 0x100 비트를 설정하고자 할 때 사용됩니다.&lt;/p&gt;
&lt;p&gt;변경 시나리오:&lt;/p&gt;
&lt;p&gt;MAKELONG(0x50, 3)은 0x00030050이라는 값을 생성하게 됩니다. 이는 플래그 배열의 동일한 3번째 부분(HIWORD)에서 0x50 비트를 설정합니다.&lt;br&gt;
이 변경은 bit 부분만을 변경하므로, 인덱스의 비트 위치가 달라지게 되어 플래그가 검사될 때 다른 조건으로 해석될 수 있습니다.&lt;/p&gt;
&lt;p&gt;문제점:&lt;/p&gt;
&lt;p&gt;기존에 정의된 다른 플래그와의 중복이나, 애플리케이션의 로직 흐름에서 이 플래그의 역할이 달라질 가능성을 고려해야 합니다.&lt;br&gt;
다른 부분의 코드(예: TestFlag 및 파일 처리 로직)에서 이 플래그의 새로운 상태를 관리하는 방법이 제대로 처리되는지 확인해야 합니다.&lt;/p&gt;
&lt;p&gt;리스크 평가:&lt;/p&gt;
&lt;p&gt;만약 다른 플래그들과의 중복이 없다면, 변경은 문제를 일으키지 않지만, 코드 베이스 전체를 고려했을 때 이 변경이 코드의 다른 부분과 호환되는지 충분히 검토해야 합니다.&lt;br&gt;
결론적으로, EEE_INDEX 값을 0x50으로 변경하는 것은 인덱스 값의 비트 위치를 변경하는 것이므로, 이런 변경이 시스템 내 다른 곳에 영향을 미치지 않는지를 충분히 검토한 후에 수행해야 합니다. 구체적으로는 기존 로직에서 어떻게 이 플래그를 사용하는지 전반적인 코드 흐름에 대한 검토가 있을 때 비로소 안전하다고 판단할 수 있습니다.&lt;/p&gt;
&lt;p&gt;참고 문서&lt;br&gt;
C++ MAKELONG 매크로 사용법&lt;br&gt;
비트 연산을 통한 플래그 관리 방법&lt;br&gt;
코드 내 TestFlag와 유사 함수의 플래그 처리를 위한 예제 코드&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Qwen2.5-72b&lt;/h3&gt;
&lt;p&gt;놀랐다. 문제점을 정확하게 찾았다. 기존 플래그과 중첩된다는 걸 체크한다. 하지만 실수도 나랑 똑같았다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;새로운 플래그를 추가할 때는 이미 사용 중인 플래그와 충돌하지 않는 값으로 설정해야 합니다. 예를 들어, MAKELONG(0x200, 3)과 같은 값으로 변경하는 것이 안전할 것입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 부분이 옥의 티. 나도 별 생각 없이 예전에 만든 코드라 0x100을 추가했는데 한바이트라 비트를 8개 밖에 쓰지를 못한다. 그래서 제대로 수정하려면 MAKELONG(1, 4)가 돼야 한다. 그럼에도 얘는 정확하게 막내의 수정 사항의 문제점을 찾아냈다는데 대해서는 몹시 칭찬한다. 알리바바가 외계인을 갈아 넣고 있는 건 정말 진실인지도?!&lt;/p&gt;
&lt;p&gt;양자화가 모델에 미치는 영향을 살펴보기 위해서 추가로 테스트를 더 돌려 보았는데 문제 답을 맞추기 위해서는 8비트 이상이 필요했다. 8비트 아래로 내려가면 4o와 비슷한 수준의 답변만 내놓는다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;주어진 코드에서 EEE_INDEX를 MAKELONG(0x100, 3)에서 MAKELONG(0x50, 3)으로 변경하는 것이 문제 없는지 판단하기 위해서는 몇 가지 점을 고려해야 합니다.&lt;/p&gt;
&lt;p&gt;비트 충돌: MAKELONG(0x50, 3)은 0x50을 3번 째 부분에 설정하는 것을 의미합니다. 이 값이 이미 사용 중인 다른 플래그와 충돌하지 않는지 확인해야 합니다. 현재 코드에서 이미 사용 중인 플래그들은 다음과 같습니다:&lt;/p&gt;
&lt;p&gt;AAA_INDEX = MAKELONG(0x10, 3)&lt;br&gt;
BBB_INDEX = MAKELONG(0x20, 3)&lt;br&gt;
CCC_INDEX = MAKELONG(0x40, 3)&lt;br&gt;
DDD_INDEX = MAKELONG(0x80, 3)&lt;br&gt;
0x50은 0x40과 0x10의 조합으로, CCC_INDEX와 AAA_INDEX와 충돌할 수 있습니다. 따라서 EEE_INDEX를 MAKELONG(0x50, 3)으로 변경하면 이 두 플래그와의 충돌이 발생할 수 있습니다.&lt;/p&gt;
&lt;p&gt;플래그 관리: 플래그는 비트 마스크로 관리되므로, 각 플래그가 독립적으로 설정되고 해제될 수 있어야 합니다. 0x50은 0x40과 0x10의 조합이므로, EEE_INDEX를 설정하거나 해제할 때 AAA_INDEX와 CCC_INDEX도 함께 영향을 받게 됩니다. 이는 원하지 않는 동작을 초래할 수 있습니다.&lt;/p&gt;
&lt;p&gt;코드의 안정성: 플래그 값이 충돌하면 코드의 안정성과 예측 가능성이 떨어집니다. 따라서 새로운 플래그를 추가할 때는 이미 사용 중인 플래그와의 충돌을 피하는 것이 중요합니다.&lt;/p&gt;
&lt;p&gt;결론&lt;br&gt;
EEE_INDEX를 MAKELONG(0x50, 3)으로 변경하는 것은 이미 사용 중인 AAA_INDEX와 CCC_INDEX와의 충돌을 일으킬 수 있으므로, 이 변경은 권장되지 않습니다. 대신, 새로운 플래그를 추가할 때는 이미 사용 중인 플래그와 충돌하지 않는 값으로 설정해야 합니다. 예를 들어, MAKELONG(0x200, 3)과 같은 값으로 변경하는 것이 안전할 것입니다.&lt;/p&gt;
&lt;p&gt;참고 문서&lt;br&gt;
주어진 코드 스니펫&lt;br&gt;
비트 마스크와 플래그 관리에 대한 일반적인 지식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;o1-mini&lt;/h3&gt;
&lt;p&gt;사고력은 역시 미니라도 o1인가. o1-preview 는 굳이 등판할 이유조차 없는 답변. 한수 위가 뭔지 철저하게 보여준다. 참고로 5초 생각했다 ㅋㅋㅋ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;변수 &lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x100, 3)&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x50, 3)&lt;/code&gt;으로 변경하려는 의도는 이해됩니다. 그러나 이 변경이 문제를 일으킬 가능성이 높습니다. 아래에서 그 이유를 상세히 설명드리겠습니다.&lt;/p&gt;
&lt;h3&gt;현재 플래그 정의&lt;/h3&gt;
&lt;p&gt;현재 플래그는 다음과 같이 정의되어 있습니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;AAA_INDEX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MAKELONG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
BBB_INDEX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MAKELONG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
CCC_INDEX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MAKELONG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
DDD_INDEX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MAKELONG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
EEE_INDEX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MAKELONG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&lt;code class=&quot;language-text&quot;&gt;MAKELONG&lt;/code&gt;의 동작&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;MAKELONG&lt;/code&gt; 매크로는 두 개의 16비트 값을 받아 32비트 값을 생성합니다. 여기서 첫 번째 인자는 &lt;code class=&quot;language-text&quot;&gt;LOWORD&lt;/code&gt;, 두 번째 인자는 &lt;code class=&quot;language-text&quot;&gt;HIWORD&lt;/code&gt;로 설정됩니다. 예를 들어:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x10, 3)&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;HIWORD = 3&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;LOWORD = 0x10&lt;/code&gt;이 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x100, 3)&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x50, 3)&lt;/code&gt;으로 변경하면 &lt;code class=&quot;language-text&quot;&gt;LOWORD&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;0x50&lt;/code&gt;으로 변경됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;변경 시 발생할 수 있는 문제&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;비트 중복&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;0x50&lt;/code&gt;은 16진수로 &lt;code class=&quot;language-text&quot;&gt;0101 0000&lt;/code&gt; (2진수)입니다.&lt;/li&gt;
&lt;li&gt;이는 &lt;code class=&quot;language-text&quot;&gt;0x10&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;0001 0000&lt;/code&gt;)과 &lt;code class=&quot;language-text&quot;&gt;0x40&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;0100 0000&lt;/code&gt;)의 비트가 모두 설정된 상태입니다.&lt;/li&gt;
&lt;li&gt;현재 다른 플래그들이 &lt;code class=&quot;language-text&quot;&gt;0x10&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;0x40&lt;/code&gt;을 개별적으로 사용하고 있기 때문에, &lt;code class=&quot;language-text&quot;&gt;0x50&lt;/code&gt;으로 설정하면 두 플래그가 동시에 활성화된 것으로 인식될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;플래그 충돌&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;0x50&lt;/code&gt;으로 변경하면, 다른 플래그들과 비트가 겹치게 되어 의도치 않게 여러 플래그가 동시에 활성화되거나 해제될 수 있습니다.&lt;/li&gt;
&lt;li&gt;이는 플래그 검사 로직에서 혼란을 초래할 수 있으며, 예상치 못한 동작을 유발할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;플래그 관리의 복잡성 증가&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;단일 비트 플래그를 복합 비트로 변경하면, 플래그를 설정하거나 해제할 때 복잡성이 증가합니다.&lt;/li&gt;
&lt;li&gt;예를 들어, &lt;code class=&quot;language-text&quot;&gt;0x50&lt;/code&gt;을 설정할 때 &lt;code class=&quot;language-text&quot;&gt;0x10&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;0x40&lt;/code&gt;을 모두 설정해야 하며, 이를 해제할 때도 동일하게 처리해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;권장 사항&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;고유한 비트 사용&lt;/strong&gt;:
각 플래그는 고유한 비트를 사용하는 것이 좋습니다. 이는 플래그 간의 충돌을 방지하고, 플래그 관리의 명확성을 유지하는 데 도움이 됩니다.&lt;/p&gt;
&lt;p&gt;예를 들어, &lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;0x200&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x200, 3)&lt;/code&gt;)과 같이 고유한 비트를 할당하는 것을 고려해보세요.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;플래그 정의 재검토&lt;/strong&gt;:
만약 &lt;code class=&quot;language-text&quot;&gt;0x50&lt;/code&gt;을 사용해야 하는 특별한 이유가 있다면, 해당 플래그가 기존 플래그들과 어떻게 상호작용하는지, 그리고 이를 처리하기 위한 추가 로직이 필요한지 신중하게 검토해야 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;코드 리뷰 및 테스트&lt;/strong&gt;:
변경 사항을 적용하기 전에 코드 전체에 걸쳐 플래그가 어떻게 사용되고 있는지 철저히 리뷰하고, 충분한 테스트를 통해 예상치 못한 부작용이 없는지 확인해야 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;결론&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;EEE_INDEX&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;MAKELONG(0x50, 3)&lt;/code&gt;으로 변경하는 것은 현재 플래그 정의와 사용 방식을 고려할 때 권장되지 않습니다. 이는 플래그 간의 비트 충돌을 유발하여 시스템 동작에 예기치 않은 문제를 초래할 수 있습니다. 고유한 비트를 유지하는 방향으로 변경을 고려하시기 바랍니다.&lt;/p&gt;
&lt;p&gt;추가적인 질문이나 코드 관련 상세한 검토가 필요하시다면 언제든지 문의해주세요!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;총평&lt;/h3&gt;
&lt;p&gt;기존 챗본 경쟁에서 OpenAI의 해자는 점점 없어지는 것으로 보여진다. o1 모델이 나오지 않았다면 정말 참담하지 않았을까 싶다. o1 모델이 있긴 하지만 앞으로도 경쟁 우위를 유지하기란 쉽지 않을 것 같다는 생각. 최근 mmlu-pro 리더보드에 &lt;a href=&quot;https://huggingface.co/spaces/TIGER-Lab/MMLU-Pro&quot;&gt;grok2가 4o 위에 0.7546으로 등재됐다.&lt;/a&gt; 물론 셀프 리포팅이긴 하지만 구라는 아닐 거 같다는 느낌. 이런걸 보면 System 1 사고를 한다는 앵무새 챗봇 경쟁은 gpu 살만한 돈들이 있는 회사들은 대부분 상향 평준화가 된 게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;알리바바에 거액을 날려 먹었지만 공산당만 아니면 다시 투자할 의향이 생기는 QWen2.5 72b였다. 그럼에도 진정 이바닥 위너는 nvidia인가?!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] 거대 언어 모델 코딩 테스트]]></title><description><![CDATA[LLM이 코딩을 잘한다는 것은 이제 삼척동자도 아는 사실이다. 하지만 일반적으로는 함수 단위 또는 조금 넘어서 코드 블록 정도를 작성하는 수준으로 생각한다. 최근 회사에서 로컬 LLM을 테스트하면서 매뉴얼을 통째로 입력했을 때, LLM…]]></description><link>https://jiniya.net/2024/10/llm-coding-test/</link><guid isPermaLink="false">https://jiniya.net/2024/10/llm-coding-test/</guid><pubDate>Wed, 16 Oct 2024 15:35:00 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/bB3-CUMERIU?si=alydfbNEmohvZS_3&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;LLM이 코딩을 잘한다는 것은 이제 삼척동자도 아는 사실이다. 하지만 일반적으로는 함수 단위 또는 조금 넘어서 코드 블록 정도를 작성하는 수준으로 생각한다. 최근 회사에서 로컬 LLM을 테스트하면서 매뉴얼을 통째로 입력했을 때, LLM이 이를 토대로 적용 코드를 작성할 수 있을지 궁금했다. 이런 생각을 하게 된 것도 모델의 답변 퀄리티가 예상보다 훨씬 뛰어났기 때문이다. 그래서 여러 모델을 벤치마크해 보았다.&lt;/p&gt;
&lt;p&gt;매뉴얼은 총 80KB 분량의 adoc 텍스트 문서로, 클라이언트와 서버 매뉴얼이 합쳐져 있으며, 각종 언어에 대한 통신 프로토콜, SDK 초기화 및 종료 절차, 데이터 전송 방법 등의 설명이 상세히 기술되어 있다. 이러한 내용은 클라이언트/서버 프로그램 개발에 필수적인 정보를 제공한다. 80KB는 감이 잘 오지 않을 수 있는데, PDF로 환산하면 약 133페이지 분량이다. 해당 파일을 단순히 통째로 읽어 모든 데이터를 전달했다. 프롬프트는 다음과 같다. 출력 토큰은 8K로 설정했으며, claude-3-haiku만 8K를 지원하지 않아 4K로 테스트했다. 이 차이는 각 모델이 처리할 수 있는 데이터의 양과 응답 길이에 영향을 미쳐, 결과의 품질과 완성도에 차이를 만들 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;시스템&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다음 첨부된 자료를 참고하여 사용자 질의에 답변합니다.&lt;/p&gt;
&lt;p&gt;... 매뉴얼 89KB 텍스트 첨부 ...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;사용자 질의&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;xigncode3가 적용된 C++ 클라이언트/서버 프로그램을 작성해 주세요. 클라이언트와 서버 프로그램은 TCP/IP를 통해 통신하는 구조로 만들어 주세요.&lt;/p&gt;
&lt;p&gt;매뉴얼이나 세부 결과물은 회사 내부 자료가 포함되어 있어 공개하기는 어렵지만, 간략하게 평가한 내용은 다음과 같다. 참고로 이 업무는 회사에서 개발자가 들어오면 대체로 거치는 통과의례 같은 과정이며, 빠르면 1주일, 늦으면 2달까지도 걸리는 작업이다.&lt;/p&gt;
&lt;h3&gt;qwen2.5-14b-int4-128k&lt;/h3&gt;
&lt;p&gt;클라이언트 통신 코드를 작성 안함, 서버 통신 코드 작성 안함, 데이터 전송 코드 작성 안함.&lt;/p&gt;
&lt;p&gt;클라이언트에 SDK 초기화 코드를 구현했으나, 함수 하나는 잘못 호출했다.
클라이언트 SDK 종료 코드를 구현했다.
클라이언트에 SDK 통신 코드를 적용하지 않았다.&lt;/p&gt;
&lt;p&gt;서버 SDK 초기화 코드에 호출한 함수 4개가 모두 잘못되었다.
서버 SDK 종료 코드에 호출한 함수 1개가 잘못되었다.
서버 SDK 통신 코드를 적용하지 않았다.&lt;/p&gt;
&lt;p&gt;클라이언트 프로그램 설명이 중구난방이다.
서버 프로그램 설명이 중구난방이다.&lt;/p&gt;
&lt;h3&gt;qwen2.5-32b-int4-128k&lt;/h3&gt;
&lt;p&gt;클라이언트 통신 코드를 작성했다. 서버 통신 코드를 작성했다.
클라이언트/서버 데이터 전송 코드를 작성하지 않았다.&lt;/p&gt;
&lt;p&gt;클라이언트 SDK 초기화 코드를 작성했으나 잘못 작성했다. 서버 함수를 사용했다.
클라이언트 SDK 종료 코드를 작성했으나 잘못 작성했다.
클라이언트 통신 코드를 작성했으나 잘못 작성했다. 다른 언어 매뉴얼 함수를 잘못 사용했다.&lt;/p&gt;
&lt;p&gt;서버 SDK 초기화 코드를 일부 정상 구현했다.
서버 SDK 종료 코드를 정상 구현했다.
서버 SDK 통신 코드를 정상 구현했다. 일부 다른 언어의 함수를 잘못 사용했다.&lt;/p&gt;
&lt;p&gt;설명이 제법 정제되었다.&lt;/p&gt;
&lt;h3&gt;4o-mini&lt;/h3&gt;
&lt;p&gt;클라이언트 통신 코드 작성, 서버 통신 코드 작성, 데이터 전송 코드 작성했지만 일부 잘못됨.&lt;/p&gt;
&lt;p&gt;서버 SDK 초기화, 종료 코드 작성. 데이터 전송 코드는 작성하지 않음.&lt;/p&gt;
&lt;p&gt;클라이언트 SDK 초기화, 종료 코드 작성. 데이터 전송 코드는 작성하지 않음.&lt;/p&gt;
&lt;p&gt;설명이 간결함.&lt;/p&gt;
&lt;h3&gt;claude-3-haiku&lt;/h3&gt;
&lt;p&gt;전체적으로 결과가 의외로 신선하게 나왔다. 프로젝트 구조부터 각 파일을 구현하는 방식으로 전개됨.
다른 모든 모델은 단순히 서버 소스, 클라이언트 소스 같은 구조였음.
하지만 실질적으로 결과물은 그냥 그럴듯한 잡썰이라 평가에서 논외로.
전개는 몹시 설레였지만... 실제 코드는 망 ㅠㅜ&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;알겠습니다. XIGNCODE3를 적용한 C++ 기반 클라이언트/서버 프로그램 작성 방법을 안내해 드리겠습니다. 클라이언트와 서버가 TCP/IP를 통해 통신하는 구조로 구현하도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;먼저, 프로젝트 구조는 다음과 같습니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;- Project
    - Client
        - main.cpp
        - XigncodeClient.h
        - XigncodeClient.cpp
    - Server
        - main.cpp
        - XigncodeServer.h
        - XigncodeServer.cpp
    - Common
        - Util.h
        - Util.cpp&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Common&lt;/code&gt; 폴더에는 클라이언트와 서버에서 공통으로 사용하는 유틸리티 함수들이 들어있습니다.&lt;/p&gt;
&lt;p&gt;이제 각 파일의 구현 방법을 설명드리겠습니다.&lt;/p&gt;
&lt;p&gt;== 클라이언트 구현&lt;/p&gt;
&lt;p&gt;=== &lt;code class=&quot;language-text&quot;&gt;XigncodeClient.h&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;qwen2.5-72b-int4-128k&lt;/h3&gt;
&lt;p&gt;여기서부터가 조금 놀라웠다.
클라이언트 통신 코드 작성, 서버 통신 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;클라이언트 SDK 초기화, 종료 코드 작성. 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;서버 SDK 초기화, 종료 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;설명이 약간 장황함.&lt;/p&gt;
&lt;h3&gt;gpt-4o&lt;/h3&gt;
&lt;p&gt;클라이언트 통신 코드 작성, 서버 통신 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;클라이언트 SDK 초기화, 종료 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;서버 SDK 초기화, 종료 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;설명이 간결함.&lt;/p&gt;
&lt;h3&gt;claude-3.5-sonnet&lt;/h3&gt;
&lt;p&gt;클라이언트 통신 코드 작성, 서버 통신 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;클라이언트 SDK 초기화, 종료 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;서버 SDK 초기화, 종료 코드 작성, 데이터 전송 코드 작성.&lt;/p&gt;
&lt;p&gt;설명이 간결하나 GPT보다는 보충됨.&lt;/p&gt;
&lt;h3&gt;llama3.2-90b&lt;/h3&gt;
&lt;p&gt;번외로 해봤다. 일단 한글 문서에 한글 프롬프트임에도 대차게 영어로 대답하는 기개를 보여주었다. 한글을 못해서 그런지 내용은 매뉴얼이 하나도 반영되어 있지 않았다.&lt;/p&gt;
&lt;p&gt;너무 안타까운 마음에 영문 프롬프트에 영문 매뉴얼로 우대해줘서 다시 돌려봤다. 하지만 안타깝게도 결과는 별 차이가 없었다. 서버 쪽 구현이 조금 추가된 정도. 너무나 너무나 안타까운 마음에 다른 언어랑 헷갈리지 않도록 C++ 문서만 두개를 전달했다. 그랬더니 이제는 클라이언트 구현도 조금 추가했지만 여전히 4o-mini보다도 못한. &lt;a href=&quot;/ng/2020/07/deep-learning-101/&quot;&gt;알파고 따라 만든 바둑때부터 느꼈지만&lt;/a&gt; 뭔가 90b 치고는 참 어이없는 결과가 아닐 수 없겠다.&lt;/p&gt;
&lt;h3&gt;총평&lt;/h3&gt;
&lt;p&gt;qwen2.5-72b, gpt-4o, claude-3.5-sonnet 모두 납득할 만한 결과를 보여줬고, 나머지는 아직 실제 사용하기에는 부족한 느낌이다. 그런데도 더 놀라운 사실은 qwen2.5-72b, gpt-4o, claude-3.5-sonnet 중 우열을 가린다면 qwen2.5-72b에 손을 들어주고 싶다. 왜냐하면 평가표에는 언급되지 않았지만, 클라이언트/서버 SDK의 다른 주요 기능들이 하나씩 더 있었는데 아무도 그것을 구현하지 않았는데, 72b는 혼자 그것을 모두 다 구현했기 때문이다. 알리바바가 외계인을 갈아넣고 있거나 아니면 중국이니까 자료를 그냥 맘껏 사용하거나 둘중하나인듯한. 어쨌든 멋진 신세계가 아닐 수 없다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 어쩌다 신입을 덜 뽑는 세상이 되었을까?]]></title><description><![CDATA[#0 세상은 참 신기한 게, 영원한 건 없다는 점이다.
개발자 채용 광풍이 불어닥쳤던 코로나 시국이 지나자 혹한기가 찾아왔다.
비대면 시대가 저물면서 IT…]]></description><link>https://jiniya.net/2024/10/hiring-fewer-entry-level-employees/</link><guid isPermaLink="false">https://jiniya.net/2024/10/hiring-fewer-entry-level-employees/</guid><pubDate>Wed, 09 Oct 2024 15:35:00 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/HaMLXjyzObU?si=5Qa-yaM_MSBOncKR&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;세상은 참 신기한 게, 영원한 건 없다는 점이다.
&lt;a href=&quot;/ng/2021/07/coding-era/&quot;&gt;개발자 채용 광풍이&lt;/a&gt; 불어닥쳤던 코로나 시국이 지나자 &lt;a href=&quot;https://www.dt.co.kr/contents.html?article_no=2024100702109931092009&quot;&gt;혹한기가 찾아왔다.&lt;/a&gt;
비대면 시대가 저물면서 IT 서비스 회사들의 매출이 급감한 이유도 있지만, 인공지능의 등장도 큰 영향을 미쳤다고 생각한다.&lt;/p&gt;
&lt;p&gt;이런 경향과 무관하게 최근 몇 년간 또 다른 주된 트렌드는 신입 채용이 급격하게 줄어들고 있다는 점이다.
당연한 이야기지만, 소위 &apos;네카라쿠배&apos;로 불리는 좋은 회사일수록 이러한 경향이 더 두드러진다.
심지어 그런 회사에서 뽑는 신입은 면면을 잘 살펴보면 실제로는 경력이 있는 중고 신입을 원하는 경우도 많다.
어쩌다 이런 세상이 되었을까?&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;우리나라 채용 문화의 급격한 변화 지점으로 IMF 외환위기를 많이들 거론한다.
그전의 사회는 평생 직장이 있었고, 연공서열이 존재했다고 한다.
즉, 직원은 회사에 한 번 충성하면 회사는 그 직원을 어쨌든 평생 책임지는 구조였던 것이다.
물론 나는 그때 사회생활을 하지 않았기 때문에 실제로 그랬는지는 모른다.&lt;/p&gt;
&lt;p&gt;이런 문화는 90년대 후반 외환위기를 겪으면서 모든 것이 달라졌다.
평생 직장은 사라지고, 연공서열 자리에는 연봉이란 시스템이 도입됐다.
회사가 직원의 평생을 책임지지 않는 세상이 시작된 것이다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;다른 직원이 버려지는 것을 본 생존자는 어떤 생각을 할까?
&apos;아, 나는 더 열심히 해서 충성을 바쳐 높은 성과를 내서 생존해야겠다&apos;고 생각할까?
그건 다소 순진한 생각이다.&lt;/p&gt;
&lt;p&gt;안정적인 직장을 추구하고 최소한의 성과만 내는 소위 &apos;공무원 문화&apos;가 퍼지기 시작한다.
일은 최소한도로 하며 워라밸을 지키고, N잡을 뛰거나 투자를 하는 식으로 회사에 목을 매지 않는 세상이 온 것이다.
어차피 언제든 버려질 수 있다면, 나도 여기에 최선을 다하지 않겠다는 선언인 셈이다.&lt;/p&gt;
&lt;p&gt;전체보다 부분을 본다면 이는 합리적인 선택인지도 모른다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;이렇게 직원들이 한 회사에 최선을 다하지 않는 것을 본 회사의 다음 선택은 무엇일까?
바로 직원에 대한 투자를 더 줄이는 것이다.
교육이나 복지 같은 장기적 투자를 줄이고, 당장 생산성을 낼 수 있는 인력을 선호하게 된다.
키워서 오래 함께 가겠다는 생각보다는 당장 일을 할 수 있는 직원을 선호하는 것이다.
언제든 다른 곳으로 갈 수 있는 직원에게 투자하는 것은 다음 회사에게만 좋은 일을 시켜주는 셈이니 말이다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;결국 이 모든 문제는 회사와 직원 간의 신뢰가 사라진 것에서 출발한다.
IMF 외환위기 이후 평생 직장 개념이 사라지고, 회사가 직원을 보호하지 않게 되면서 이러한 신뢰가 무너지기 시작했다.
직원은 회사가 언제든 자신을 버릴 수 있다고 생각하고, 회사는 직원이 언제든 떠날 수 있다고 생각한다.
가장 좋은 합은 회사도 직원을 믿고, 직원도 회사를 믿으며 장기적으로 상생하는 구조지만, 현실에서는 쉽지 않다.&lt;/p&gt;
&lt;p&gt;이 문제는 잘 생각해보면 죄수의 딜레마와 닮았다.
게임 이론에 따르면 안타깝게도 죄수의 딜레마에서 내쉬 균형은 서로가 배신하는 선택을 통해 이루어진다.
겉으로는 세상이 비합리적으로 보일지라도, 사실은 매우 합리적이라는 뜻이다.
그러니 직원이 워라밸을 중시하며 다른 기회를 찾는 것이나, 회사가 신입을 채용하지 않고 기존 직원에게 덜 투자하는 것 모두 너무 아쉬워 하지는 말자.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 재미로 보는 개발자 채용 가산점 히스토리]]></title><description><![CDATA[200…]]></description><link>https://jiniya.net/2024/10/tips-for-hiring-developers-for-fun/</link><guid isPermaLink="false">https://jiniya.net/2024/10/tips-for-hiring-developers-for-fun/</guid><pubDate>Mon, 07 Oct 2024 05:35:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./iamges/tips-for-hiring-developers-for-fun.webp&apos; data-alt=&apos;세월따라 변하는 개발 트렌드&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dceb7ddd78b65cc801197c502f86dba7/a4772/tips-for-hiring-developers-for-fun.webp&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRqIAAABXRUJQVlA4IJYAAABwBACdASoUAAsAPtFUo0uoJKMhsAgBABoJZgCdMoADU3VwnnQSOl+I/AdRgAD1Wdr+hGkuYktNu/Ykxv14qt7s7LH2ekw9/7kIKAGN09iCuMlQMUm6ZGqDkpLqwLxoBipjpfcv9pnbiIdKKHujBHcQdqc5slL/hxQqOHX657LEODirIDDIJCuA3D8xgkywMyZbJVAAAAA=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;세월따라 변하는 개발 트렌드&apos; title=&apos;&apos; src=&apos;/static/dceb7ddd78b65cc801197c502f86dba7/7df04/tips-for-hiring-developers-for-fun.webp&apos; srcset=&apos;/static/dceb7ddd78b65cc801197c502f86dba7/561c4/tips-for-hiring-developers-for-fun.webp 190w,
/static/dceb7ddd78b65cc801197c502f86dba7/3e041/tips-for-hiring-developers-for-fun.webp 380w,
/static/dceb7ddd78b65cc801197c502f86dba7/7df04/tips-for-hiring-developers-for-fun.webp 760w,
/static/dceb7ddd78b65cc801197c502f86dba7/b2cd5/tips-for-hiring-developers-for-fun.webp 1140w,
/static/dceb7ddd78b65cc801197c502f86dba7/98c2e/tips-for-hiring-developers-for-fun.webp 1520w,
/static/dceb7ddd78b65cc801197c502f86dba7/a4772/tips-for-hiring-developers-for-fun.webp 1792w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;세월따라 변하는 개발 트렌드&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;2007년부터 개발자 채용을 시작했다.
햇수로 제법 오래되었지만 영세한 중소업체에서 채용을 진행하다보니 대단한 건수를 가진 건 아니다.
그럼에도 지난 시간동안 작은 회사치고는 제법 훌륭한 개발자들을 잘 채용했다고 자부한다.
그러니 회사가 망하진 않고 아직까지 유지되는 거겠지?!&lt;/p&gt;
&lt;p&gt;개발자를 채용함에 있어서 정말 많은 요소들을 볼 수 있겠지만 의외로 엉뚱한 질문 한두가지로도 그 사람을 어느 정도는 판단할 수 있다.
지난 시간동안 복잡한 면접 문제보다 오히려 더 좋은 성능의 필터인 경우가 많았던 것들을 소개해 본다.&lt;/p&gt;
&lt;h3&gt;Pre-AI&lt;/h3&gt;
&lt;h4&gt;뉴스그룹&lt;/h4&gt;
&lt;p&gt;뉴스그룹을 알거나 거기서 활동한다는 사실만으로도 가산점을 주던 시기가 있었다.
정보와 소스는 귀했고, 그나마 몇 안되는 정상적인 프로그래밍 관련 토론이 벌어지던 곳이 뉴스그룹이었다.&lt;/p&gt;
&lt;p&gt;요즘은 그게 유튜브로 변한듯하다.
얼마전 개발자를 뽑는데 조코딩으로 배웠다고 해서 내중에 그게 뭔지 알고는 실소를 했다는 이야기를 들었다.
조코딩은 유명한 개발 유튜브 채널이다.
세월따라 배우는 채널도 변하기 마련이다.&lt;/p&gt;
&lt;h4&gt;명서&lt;/h4&gt;
&lt;p&gt;감명 깊게 읽은 책에 명서가 있다고 해서 그게 꼭 좋은 프로그래머임을 반증하지는 않는다.
하지만 적어도 멍청한 개발자는 아니라는 사실은 어느 정도 판단해준다 믿는다.
최소한 어느 정도 취향은 비슷하다는 걸로도 해석할수도 있겠다.
어쨌든 아래 책이 그 목록에 있다면 가산점을 주었다.&lt;/p&gt;
&lt;p&gt;Windows Internals, Windows via C/C++, Art Of Unix Programming, Programming Pearls, 실용주의 프로그래머, 조엘온소프트웨어, 코딩 호러의 이펙티브 프로그래밍&lt;/p&gt;
&lt;p&gt;누가 내 치즈를 옮겼을까를 선택한 개발자에겐 미안한 이야기지만 선호하지 않았다.
내가 그걸 물어보던 시기에 인터넷에 감명깊게 읽은 책 물어보면 단골로 나오던 책이었다.
요즘으로 치면 세이노의 가르침정도 되겠다.
재미난 사실은 내가 30대때는 지금만큼 세이노가 유명하지 않았지만 그때 난 광팬이었다.
그러나 지금은 생각하는 게 많이 다르다.
세월따라 생각하는 것도 변하게 마련이다.&lt;/p&gt;
&lt;h4&gt;svn&lt;/h4&gt;
&lt;p&gt;믿기지 않겠지만 그 시절 업계에서 버전 관리 시스템을 사용하던 곳은 드물었다.
소스 코드는 말 그대로 개발자 각자가 알아서 관리하던 비법같은 존재였다.
나는 꾸준히 일하던 회사에 svn을 도입하자는 말을 했지만 말단 신입이라 쉽지 않았다.
더 엄청난 사실은 심지어 바이너리도 개발자가 시스템에서 직접 빌드한 것을 사용했다.&lt;/p&gt;
&lt;p&gt;CTO가 되고 나서 처음으로 사내에 버전관리 시스템을 도입할 수 있었다.
그전에는 혼자 썼다. C자가 붙으면 이런 게 좋다.&lt;/p&gt;
&lt;h4&gt;구글&lt;/h4&gt;
&lt;p&gt;난 대학시절부터 구글을 썼지만 아직 국내 검색 엔진 시장은 네이버가 평정하던 시기였다.
개발자 채용에도 구글이 뭔지 아예 모르는 사람이 많았다.
개발 관련 이슈에 검색엔진을 뭘 사용하는지 물어서 구글을 사용하다면 좋은 신호였다.&lt;/p&gt;
&lt;h4&gt;블로그&lt;/h4&gt;
&lt;p&gt;개인 블로그를 가지고 있고, 내용이 의미있는 경우에는 가산점을 주었다.
개인 블로그가 의미 있다는 사실은 두가지를 어느 정도는 증명한다고 본다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;긴 글을 이해할 수 있는 형태로 쓸 수 있는 능력을 가지고 있다.&lt;/li&gt;
&lt;li&gt;적어도 적혀진 내용에 대해서는 고민하는 시간을 가졌다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;요즘은 포트폴리오 차원에서 블로그를 하는 경우가 많아졌다.
하지만 여전히 의미있는 내용이 담겨있는 블로그는 드물다.
아주 드문 경우긴 하지만 블로그 내용을 보고 역으로 채용을 제안한 경우도 몇 있었다.&lt;/p&gt;
&lt;h4&gt;조엘테스트&lt;/h4&gt;
&lt;p&gt;이걸 알기만해도 코딩이 아닌 제품 개발에 있어서 실질적으로 중요한 부분이 무엇인지 어느 정도는 알고 있다고 생각한다.
놀라운 사실은 여전히 유효하다는 점이다.&lt;/p&gt;
&lt;h4&gt;스택오버플로&lt;/h4&gt;
&lt;p&gt;시간이 흘러 뉴스그룹은 스택오버플로로 바뀌었다.
지금은 그냥 검색해도 나오는게 죄다 스택오버플로인 세상이 되었지만 그 시기만해도 모르던 사람이 더 많았다.&lt;/p&gt;
&lt;h4&gt;git&lt;/h4&gt;
&lt;p&gt;이제 업계 전반에 버전 관리 시스템은 필수인 세상이 되었다.
하지만 여전히 빌드 시스템은 없는 회사가 많기도 했다.
git은 출시가 되었지만 이 시기에 대세는 여전히 svn이었다.
지인들 중에도 git의 장점이 뭔지 도통 모르겠다고 얘기하는 사람들이 많았다.&lt;/p&gt;
&lt;p&gt;git을 알기만 해도 가산점을 주었다.
나는 여전히 CTO였지만 svn에서 git으로 가는 과정은 쉽지 않았다.
사내 개발자들은 왜 잘 쓰고 있는 걸 옮기냐고 뭐라 했다.
나는 휴가지 노트북에서도 버전 관리를 계속할 수 있다는 이야기를 했지만?!
당연한 소리겠지만 설득은 1도 안됐다.
그래서 그냥 권력을 이용해서 강제로 변경했다.&lt;/p&gt;
&lt;p&gt;이제는 git을 안쓰는 경우가 더 드물것 같다.
git과 github은 개발 문화를 정말 많이 변화시켰다고 본다.&lt;/p&gt;
&lt;h4&gt;파이썬&lt;/h4&gt;
&lt;p&gt;주로 채용하는 포지션이 C/C++개발자라 파이썬을 사용할 줄 아는 경우 가산점을 주었다.
사내 개발자들에게도 파이썬을 배우면 좋다는 이야기를 많이 했지만 쉽진 않았다.&lt;/p&gt;
&lt;p&gt;대체로 그 시절 C/C++ 개발자들은 이건 C/C++로도 다 만들 수 있다는 이야기를 많이했다.
내가 파이썬으로 만드는 게 더 개발 속도가 빠르다고 했지만 당연히 별 의미 없는 소리였다.&lt;/p&gt;
&lt;p&gt;2024년이 된 지금, 결국 파이썬이 씹어먹는 세상이 되었다.&lt;/p&gt;
&lt;h4&gt;슬랙&lt;/h4&gt;
&lt;p&gt;업무용 메신저란 개념이 아직 드문 시기였다.
우리 회사도 네이트온을 쓰다가 슬랙으로 옮겼던 시기였다.
이것 또한 도입 진통이 없지는 않았다.
하지만 왜 바꾸냐는 말과는 달리 도입 후 사람들은 모두 채널 중독자가 되었다.&lt;/p&gt;
&lt;p&gt;대단한 건 아니지만 슬랙을 안다는 것 만으로도 가산점을 주었다.
요즘은 대학 동아리도 죄다 슬랙을 쓰는 세상이다.&lt;/p&gt;
&lt;h3&gt;Post-AI&lt;/h3&gt;
&lt;p&gt;여기까지가 지금까지의 이야기다.
내가 다음 개발자를 채용한다면 이제는 이런 것들에 가산점을 줄 것 같다.&lt;/p&gt;
&lt;h4&gt;chatgpt, claude, cursor&lt;/h4&gt;
&lt;p&gt;인터넷은 이 녀석들이 지배하고 있지만 아직 오프라인 개발자 중에는 모르는 사람도 많다.
유료 결제해서 사용하고 있다면 제곱으로 가산점을 줄 수 있을 것 같다.&lt;/p&gt;
&lt;p&gt;나는 코파일럿 출시 시점부터 인공지능 서비스를 광팬으로 쓰고 있다.
하지만 이후 현실 세계에서 관찰한 개발자를 보면 사용을 주저하는 경우가 많다는 것을 알게되었다.
도저히 왜인지는 모르겠지만 사람들은 여전히 인공지능 사용을 주저하는 집단이 있다.&lt;/p&gt;
&lt;p&gt;그 사람들이 모두 인공지능을 쓰기 전까지는 사용하는 사람이 경쟁 우위를 누릴 수 있다는 생각이다.
물론 이는 과거에도 있었다. 인텔리센스나 IDE를 사용하는 걸 두고 멍청한 개발자가 되는 길이라고 주장하던 사람들이다.&lt;/p&gt;
&lt;h4&gt;rust&lt;/h4&gt;
&lt;p&gt;파이썬은 이제 프로그래밍 언어에서 일반 언어의 반열에 올라갔다고 본다.
그래서 이제는 rust를 하는 사람에게 가산점을 주어야 하는 세상이 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;시스인터널의 창업자이자 MS 기술 펠로우인 루시노비치는 신규 프로젝트는 모두 rust로 진행하자고 주장했고,
리눅스와 git의 초기 개발자인 토발즈옹은 rust는 c보다 복잡한 언어지만 실수할 가능성이 적다는 이야기를 했다.
c++에게는 미안한 마음이지만 대세는 이미 기울었다.&lt;/p&gt;
&lt;h4&gt;로컬 llm&lt;/h4&gt;
&lt;p&gt;고가의 그래픽 카드가 필요하긴 하지만, 로컬 llm을 돌려서 뭔가를 해봤다면 분명 긍정적인 시그널이지 않을까 싶다.
지난 세월 파이썬이 생산성 향상을 위한 치트키였다면 앞으로는 llm이 대체할 거라 생각한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 9월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2024/09/small-talk-2024-09/</link><guid isPermaLink="false">https://jiniya.net/2024/09/small-talk-2024-09/</guid><pubDate>Fri, 27 Sep 2024 01:39:45 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;개발직군 구조 자체가 피라미드 식이라 나이가 들수록 취직이 어려워지는게 당연하다는 생각. 의자뺏기 놀이랑 같은 원리. 연차가 찰수록 의자가 줄어든다. 안타깝게도 실력도 크게 상관이 없는게 절대다수의 국내 소프트웨어 기업은 어려운 문제를 푸는 게 아니라 노가다를 반복하는 구조라 더 심함.&lt;/p&gt;
&lt;p&gt;it업계에서 이직을 잘하는 사람들을 보면 결국은 인맥. 경력 초기에 좋은 이너서클에 포함되면 해당 멤버들끼리 끌어주고 당겨주고 그런 경우를 많이 봄. 고로 나이들어 이직을 잘하려면 지금 옆에 있는 동료에게 잘하자. 시간 지나면 그런 사람들이 다 유명한 회사 대표되고 그럼.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;넘치는 재능, 풍부한 자본, 여유있는 시간, 다양한 인력이 결합해도 성과를 내는게 쉽지 않은 유튜브 세상. &lt;a href=&quot;https://x.com/DIPI_E/status/1831685377159286849&quot;&gt;https://x.com/DIPI_E/status/1831685377159286849&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;사회에서 본질적으로 인정해주는 실력은 한가지 밖에 없다. 부가가치를 창출해 내는 실력. 그것 외에는 어떤 것도 생존을 보장해주지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;가끔 직원들이 어쩌다 보안하게 됐냐고 묻는 경우가 있는데 멋진 답을 해주고 싶지만 진실은 보안 업체에서 병특한게 전부. 병특이 끈나고 그 경력 아까워 못 버리고 계속 하다보니 이 지경이. 매몰 비용에 대한 집착이 이렇게 무섭다. 머리는 합리적으로 살자라고 외치지만 언제나 감정이 이긴다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;우스워 보여도 살기위해 죽도록 최선을 다하는 각자의 인생이다. 대신 살아줄 거 아니면 부탁받지 않은 훈수는 자제하자. 이제 우리 사회도 좀 저오지랖 사회로 발전할 때도 되지 않았나 싶은데. 요원한듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;잡생각이 많으면 확실히 진도가 더디다. 그냥 버리는셈 치고 mvp정도를 빨리 만들겠다는 생각으로 덤비는 게 훨씬 더 생산적이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;o1preview 진심 미쳤네. 할당량이 아쉽지만 이 또한 늘어나겠지.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;어제 텍스트 파싱하는 코드를 작성하는데 gpt4o가 자꾸 헤매서 직접 짜느라 엄청 애를 먹었다. 저녁 먹으면서 200만원짜리 gpt신버전 나오면 이런거도 짜주겠지, 같은 얘기를 했는데 자고 났더니 o1preview가 뙇. 어제 그 문제를 다시 줘봤는데 그 앞에서 내가 짠 코드는 오징어가 되었다.&lt;/p&gt;
&lt;p&gt;코딩은 특이점이 온 건 분명한 것 같다. 사람 프로그래머는 내가 할 줄 아는걸 지시해도 결과가 별로인 경우가 많은데, 지피티는 내가 못하는 것도 해주니 그 차이가 실로 엄청나다. 20불에 써도 되나 싶다. 그나마 이해하고 생각한다던 인간의 착각도 얼마 안 남은듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;4o가 해결못한 문제를 나는 6시간 넘게 코딩해서 겨우 반쯤 돌아가는 누더기를 만들었다. o1은 65초만에 자료구조를 이용해서 깔끔하게 정상 동작하는 코드를 만들었다. 오래 걸린게 아니다. 아주 빠른거다. 내가 완전히 돌아가는 코드를 만드려면 하루 정도는 더 써야했을거다.&lt;/p&gt;
&lt;p&gt;마케팅도 중요하겠지만 현재 인공지능을 쓰는 대다수 사람은 그게 실질적으로 동작하고 매우 효과가 있기 때문에 쓰는게 아닌가 싶다. 펀더멘탈이 압도적이면 마케팅은 그저 거들뿐.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;그냥 엄마 자식인 걸로는 안돼? 내가 왜 엄마 인생의 포장지가 되어줘야 하는데? - 엄마 친구 아들, ep02&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;o1에게 간단한 문제를 넣으면 장고 끝에 악수 둔다는 말이 뭔지를 보게됨. 근데 실수가 사람들이 시도해보는 패턴과 비슷한 형태여서 몹시 신기함. 답이 있는 간단한 문제는 4o가 답변을 훨 잘한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;시작이 설레는 이유는 무한한 가능성만 품고 있기 때문 아닌가 싶다. 시간이 지날수록 가능성은 줄어들고 제약 사항은 점점 늘어난다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;우량주라고, 싸다고, 삼전을 샀지만 역시 바닥 밑에는 지하실 밑에는 땅굴이 ㅋㅋ 그나마 하닉 빠지는거 보고 위안을 삼는다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;2번이 젤 중요하다는 생각. 꿀이 떨어져도 크기가 작은 시장에는 대기업이 쉽게 들어오지 않는다. 안타깝게도 실질적으로 꿀이 있다는 게 알려지면 피라미가 들끓는 시장이 된다는 점. 그래도 어쨌든 같은 체급이면 대기업보다는 상대하기가 쉽겠지?! &lt;a href=&quot;https://x.com/GeekNewsHada/status/1837274299763490860&quot;&gt;https://x.com/GeekNewsHada/status/1837274299763490860&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;만일 이책을 처음 읽는 과정에서 그 부분을 공부하는 데 너무 많은 시간이 걸린다면, 안타깝지만 독자는 컴퓨터 프로그래밍 주제들에 쉽게 익숙해지기 힘든 사람일 수도 있다. - 컴퓨터 프로그래밍의 예술 1, 카누스&lt;/p&gt;
&lt;p&gt;10만년만에 책장에서 먼지 쌓인 프로그래밍 책을 꺼내봤다. 친절하신 카누스 교수님, 앞쪽에 스스로 진단할 수 있는 기준을 먼저 마련해두셨네. 과연 교수님께선 7권까지 완주하실 수 있을까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;마크 루시노비치도 신규 프로젝트는 이제 러스트로 하자고 했다가 개욕먹었지만 대체로 구루들의 의견이 비슷한듯. 러스트는 그렇지 않다고 말하는 토발즈옹이 대단한 건지. 그말을 듣는 러스트가 대단한 건지 판단하긴 어렵지만 어쨌든 전공필수 반열에는 오른 느낌적인 느낌. &lt;a href=&quot;https://x.com/zdnetkorea/status/1837651330179256790&quot;&gt;https://x.com/zdnetkorea/status/1837651330179256790&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이와중에 의문의 1패를 추가한 건 c++?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;묘하게 3po 생각나는 비쥬얼. &lt;a href=&quot;https://x.com/ai_for_success/status/1837472679906947324&quot;&gt;https://x.com/ai_for_success/status/1837472679906947324&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;인공지능이 다 번역해주는 세상에 유발 하라리 정도 네임드면 신작을 동시 출간 정도는 해줘야 하는게 아닌가 싶은데. 국내 출판 업계 나이브한듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;사실 우리 나라가 한글 발명한거 부터가 신기하긴 함. 자국 워드프로세서, 백신, 검색엔진, 메신저, 디비 가진 나라가 흔치 않음. 빅테크 보면서 개발 못한다고 난리치지만 반대로 생각하면 이만한 인구로 이정도 하는 나라도 없다는거. 위쪽은 해킹 기술은 넘사. 자부심을 가지자.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;[소고] o1preview의 등장 &lt;a href=&quot;https://jiniya.net/2024/09/o1preview/&quot;&gt;https://jiniya.net/2024/09/o1preview/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;gpt 쓰면 세상 인공지능이 다 정복한거 같은데 로컬에서 돌려보려면 뭐 하나 쉽게 되는 게 없음. 느린건 둘째치고 일단 메모리가 부족해서 로딩이 쉽지 읺음. 그렇다면 맥이 나은가 싶어 찾아보면 맥은 또 너무 느린듯. 당연한 소리겠지만 nvdia gpu 램 용량이 참 오묘하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;4년 만에 직원들 근속 연수 현황 파악을 해봤다. 근무 중은 3.45년에서 5.58년으로 늘었고, 퇴사한 인원은 2.54에서 2.5로 소폭 줄었다. 4년이 흘렀고 그사이 퇴사한 인원이 20명 넘게 발생했는데 퇴사자 평균이 거의 그대로라 소오름.&lt;/p&gt;
&lt;p&gt;현재 직원들의 평균 근속 년수가 높다는 것은 핵심 인재들이 회사에 남아 있을 가능성이 있다. 회사의 핵심 역량은 유지되고 있음을 나타낼 수 있지만, 신규 인력 유입과 유지에는 어려움이 있을 수 있다는 한 인공지능의 평가.&lt;/p&gt;
&lt;p&gt;평균 근속 연수가 높다는 게 곧바로 긍정적인 지표는 아니다. 장기 근속자들이 변화에 대한 적응력이 떨어지거나 성과가 낮은 상태로 안주하고 있을 수 있다. 역동적이고 우수한 인재들이 기회를 찾아서 떠났을 수 있다는 다른 인공지능의 평가.&lt;/p&gt;
&lt;p&gt;같은 자료. 다른 느낌. 뭐든 그렇지만 숫자만 봐서는 실체적 진실을 알기는 어렵다. 부디 회사가 안 망하길 바란다. 제발.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;고려아연 경영권 분쟁을 보면 잘잘못을 떠나서 동업이란 정말 잘되면 잘될수록 험한 꼴 보기 쉬운 거란 생각이 든다. 시작할 땐 달콤하지만 그걸 유지하기란 쉽지 않다. 빌 게이츠와 폴 앨런, 스티브 잡스랑 워즈니악만 봐도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;헐 실존 인물이었 ㄷ ㄷ &lt;a href=&quot;https://x.com/hangul/status/1838453893619212358&quot;&gt;https://x.com/hangul/status/1838453893619212358&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;신라가 삼국을 통일한지가 얼마나 됐는지 감도 안오지만 생각해보면 돌고돌아 그때나 지금이나 삼국 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;라떼는 선성과 후보상 체계가 일반적이었는데 요즘은 선보상 후성과를 원하는 세상인듯. 아니먼 노성과 노보상인가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;정말 우리 마음이란 미묘하기 짝이 없다. 너그러울 때는 온 세상을 다 받아들이다가 한 번 옹졸해지면 바늘 하나 꽂을 여유조차 없다. 그러한 마음을 돌이키기란 결코 쉬운 일이 아니다.&lt;br&gt;
그래서 마음에 따르지 말고 마음의 주인이 되라고 옛사람들은 말한 것이다. - 법정 스님&lt;/p&gt;
&lt;p&gt;기분이 태도가 되면 안되는데 그게 참 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;gpt 새 음성 모드 미쳤다 ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;사내에서 4090한개로 이거저거 해보는데 qwen2.5생각보다 괜찮다. 7b는 좀 멍청한데 14b만 되도 제법이다. 32b는 겨우 로딩되지만 컨텍스트가 너무 짧아서 쓰기 힘든. 14b-int4 64k로 쓰는데 생각보다 성능이 괜찮다. 요점정리 같은 건 생각보다 놀라움.&lt;/p&gt;
&lt;p&gt;코딩도 나쁘지 않다. 일감에 올라온거 한 번 시켜봤는데 짜준거 그대로 복붙해서 결과보는데 성공함. 물론 복잡한 코드는 아닌데 그래도 딱히 프롬프트 안다듬고 요청 온거 그대로 대충 입력했는데도 돌아가는 결과물이 나옴.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#29&lt;/h2&gt;
&lt;p&gt;더 충격적인 사실은 21년전에도 비슷했던. 그때는 강남이 평당 2천이어서 1년 일해야 한평 산다 그러면서 한숨셨는데 지금 생갇하면 선녀였던. 지금은 1년 일해서 한평 사면 고소득자로 분류되는게 현실. &lt;a href=&quot;https://x.com/Bohemianwandere/status/1015172548646989824&quot;&gt;https://x.com/Bohemianwandere/status/1015172548646989824&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#30&lt;/h2&gt;
&lt;p&gt;gpt등장하기전 구글 번역이 나름 선방하던 시절에 번역 잘되는 글을 잘 쓴 글이라고 이야기 하는 사람들이 있었다. 어쩌면 앞으로는 매뉴얼도 llm에 넣어서 결과가 잘나오는 게 더 좋은 걸로 평가 받는 시대가 올수도 있겠다. 어짜피 인간은 아무도 안 읽으니까.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-09-27&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] o1-preview의 등장]]></title><description><![CDATA[#0 내가 만들어야 하는 코드는 특수하게 처리된 텍스트 파일을 역으로 파싱해서 xml로 변환하는 코드였다.
이미 그 기능을 수행하는 사람이 작성한 java…]]></description><link>https://jiniya.net/2024/09/o1-preview/</link><guid isPermaLink="false">https://jiniya.net/2024/09/o1-preview/</guid><pubDate>Sun, 22 Sep 2024 01:35:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./o1preview/1.webp&apos; data-alt=&apos;어서와, o1preview는 처음이지?&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/89012ac6a16a5470794537ad18d7b1b3/a4772/1.webp&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRp4AAABXRUJQVlA4IJIAAACQBACdASoUAAsAPtFUo0uoJKMhsAgBABoJYwC258G6gFPyK53vCTfirYXvMAAA/un226d+pjU1xw7XtLD5hWPT8XsrTPjIL7paAQYOhrr4L9WSHnLLeIamiK5HE3YaccrhANI7sxDNT0xh3LAP+L1KaTjpk2msNPXQfh95f1+1lVVj+Qu0661hGs30uvevzPKAAA==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;어서와, o1preview는 처음이지?&apos; title=&apos;&apos; src=&apos;/static/89012ac6a16a5470794537ad18d7b1b3/7df04/1.webp&apos; srcset=&apos;/static/89012ac6a16a5470794537ad18d7b1b3/561c4/1.webp 190w,
/static/89012ac6a16a5470794537ad18d7b1b3/3e041/1.webp 380w,
/static/89012ac6a16a5470794537ad18d7b1b3/7df04/1.webp 760w,
/static/89012ac6a16a5470794537ad18d7b1b3/b2cd5/1.webp 1140w,
/static/89012ac6a16a5470794537ad18d7b1b3/98c2e/1.webp 1520w,
/static/89012ac6a16a5470794537ad18d7b1b3/a4772/1.webp 1792w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;어서와, o1preview는 처음이지?&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;내가 만들어야 하는 코드는 특수하게 처리된 텍스트 파일을 역으로 파싱해서 xml로 변환하는 코드였다.
이미 그 기능을 수행하는 사람이 작성한 java 코드가 있었다.
하지만 그냥 대충 봐도 버그가 있어 보이는 코드였다.
조금씩 버그를 수정하다 이걸로는 안되겠다 싶었다.
그래서 다시 작성하기로 마음먹었다.&lt;/p&gt;
&lt;p&gt;GPT-4o에게 텍스트 출력을 주고 구조를 설명하고 xml로 변환하는 코드를 작성하라고 했다.
4o는 그럭저럭 동작할 것 같은 코드를 뱉어냈다.
하지만 미묘한 엣지 케이스에 의도한 대로 동작을 하지 않았다.
구현체가 다소 복잡했는데 여러 단계로 구성되어 있어서 잘못 동작하는 케이스에 정상 동작하도록 구조를 변경하기 쉽지 않았다.
여러 단계에 걸쳐서 수정을 해야 하는데 애초에 그런 케이스를 염두에 두고 구조가 만들어져 있지 않아서 여기저기 고쳐야 할 곳이 많았던 탓이다.
4o에게 수정하라고 지시하다 안되서 새창을 열어서 다시 지시를 하다가 계속 헤매는 인공지능을 보며 드디어 사람이 나설 때라고 생각했다.&lt;/p&gt;
&lt;p&gt;그렇지,, 이런 건 그래도 20년 넘게 코딩한 내가 더 나을 수도 있겠지?&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;인간 프로그래머의 출발은 순조로웠다. 그도 그럴 것이 완전 맨땅에 헤딩은 아니었으니까.
사람이 만든 어설픈 java 코드도, 4o가 만든 미묘한 python 코드도 있었다.
나에게도 계획은 있었다.
인간이 만든 코드도, 4o가 만든 코드도 루프 구조에 문제가 있다고 판단했던 것이다.
재귀 호출을 이용해서 아름답게 동작하는 파서가 뭔지를 보여줄 참이었다.
누구나 그럴듯한 계획은 있게 마련이니까. 쳐맞기 전까지는 말이다.&lt;/p&gt;
&lt;p&gt;현실은 냉혹했다. 생각하는 코딩을 너무 오래 안해서였을까?
함수 호출 구조가 자꾸 꼬였다.
테스트 하다가 계속 미묘한 케이스를 해결하기 위해서 재귀 호출 함수의 파라미터는 늘어만 갔다.
뭔가 제대로 안되고 있다는 신호였다.
그렇게 1시간이면 끝날 것 같았던 작업에 하루를 꼬박 다 썼다.&lt;/p&gt;
&lt;p&gt;수많은 디버깅 끝에 결국 동작하는 코드는 만들었다.
하지만 이건 코드가 아니었다.
java 프로그래머가 작성한 것보다 훨씬 더 형편 없었다.
동작은 더 정확하다며 위안을 삼았지만 정신 승리에 가까웠다.
내일 마저 다듬어야겠다고 생각하고는 퇴근을 했다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;인간 프로그래머들과 저녁을 먹으며 오늘 있었던 일을 이야기 했다.
다른 프로그래머도 똑같은 얘기를 했다.
거기도 PE 파일을 파싱하는 코드를 시켰다가 100만개중에 70만개 정도만 통과해서 직접 다시 다 작성했다는 말을 했다.
4o에게 고치라고 해도 제대로 고치지를 못했다는 얘기.&lt;/p&gt;
&lt;p&gt;그러다 그때까지 베일에 가려져 있던 OpenAI의 신모델 이야기가 나왔다.
2주 안에 공개된다는 이야기. 200만원이 넘을지도 모른다는 가격 이야기.
그래도 신모델은 이런 것도 다 아름답게 작성해 줄 것 같다는 이야기를 했었다.
그러면서 만약 진짜 그런 세상이 온다면 200만원이 넘는 가격도 비싼 건 아닐지도 모른다는 이야기도 덧붙였다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;다음날 아침, 우리 이야기를 들었을리는 없겠지만 마법처럼 OpenAI의 새 모델이 출시됐다.
정식 출시라고 하기에는 무리가 있을지도 모르겠다. preview가 붙은 모델 o1-preview였다.
추론이 강화됐다고 했다. 심지어 4o 사용자는 바로 사용할 수 있다고 했다.
가슴이 웅장해지는 순간이 아닐 수 없었다.&lt;/p&gt;
&lt;p&gt;컴퓨터로 갔다. 어제 그 문제를 o1-preview에 다시 입력했다.
프로그레스바 대신에 간결한 설명 문장이 계속 바뀌면서 출력됐다.
답이 나오기까지가 한참이 걸렸다.
33초, 녀석은 코드를 출력하기 시작했다.
그 문제를 그대로 넣지도 않았다.
그냥 텍스트만 대충 던지고 xml을 만들라고 했는데 결과 코드는 대충 봐도 어제 것과는 달랐다.
어제 하루를 삽질했기 때문에 해당 문제를 푸는 코드 패턴에 익숙혀져서 쉽게 알 수 있었다.&lt;/p&gt;
&lt;p&gt;새 세션을 열었다. 프롬프트를 정제하고 다시 입력을 넣었다.
더 오랜 시간이 걸렸다. 인간의 참을성을 시험할만큼의 시간, 67초가 지날 무렵 코드가 출력되기 시작했다.
o1-preview가 보여주는 복음이었다.
아, 어제 4o가 하려고 했던 멋진 모습이 이런 것이었구나 라는 생각이 머리를 스쳤다.
스택을 사용한 아름다운 코드는 내가 짠 누더기 코드랑은 비교도 되지 않을 만큼 간결했고, 정확하게 동작했다.
당연하게도 어제 코드를 다듬을 필요는 없어졌다.&lt;/p&gt;
&lt;p&gt;preview라고 했다. o1은 더 대단하다고.
이게 마법이 아니면 뭐가 마법이란 말인가?
경외심이 들지 않을 수 없는 순간이었다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;o1-preview가 출시된 지 시간이 제법 흘렀다. o1-preview에 대해서 반응 속도가 느리다는 말들이 많다.
결과가 나오기까지 오래 걸린다는 말이다.
하지만 나는 그런 이야기를 하는 모든 사람들이 실질적으로 인간 프로그래머에게 뭔가를 지시해 본 적이 없는 사람들이라고 생각한다.
앞선 나의 케이스도 썼지만 사람에게 어떤 작업을 지시한다면 초나 분 단위로 결과가 나오는 경우는 거의 없다.
보통은 주단위나 빨라야 일단위다. 거기 비하면 o1-preview가 쓰는 시간은 빛의 속도에 가깝다고 생각한다.&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;코딩에 인공지능이 등장한지 고작 2년.
하지만 패러다임은 이미 변했다.
인공지능이 없던 시기에 코딩을 어떻게 했는지 상상할 수 없는 현실이 되었기 때문이다.
심심해서 헤아려 보니 ChatGPT에 지난 7일간 사용한 세션이 100개가 넘었다.
최근에 한 번 다운을 경험한 적이 있었다. 구글링을 하지 않았다.
포 플랫폼에 들어가서 4o를 선택하고 답을 사용했다.&lt;/p&gt;
&lt;p&gt;인간의 역할에 대해서 생각을 많이 한다.
그간에 이해한다, 생각한다는 말로 자위하던 것도 이제는 별 의미 없는 소리가 아닌가 싶다.
아직 위안을 삼을 수 있는 마지막 보루는 어쨌든 현실에 기대서 실행을 하는 것은 인간이라는 사실 아닐까 싶다.
물론 그마저도 OpenAI에서 말하는 에이전트 단계가 된다면 별 의미 없어지겠지만 말이다.&lt;/p&gt;
&lt;p&gt;사람의 역할을 떠나서 다만 한가지 바램이 있다면, 2030년에도 인공지능이 나에게 뭐가됐든 먼저 미안해 하기를 바랄 뿐이다.
그때의 인공지능은 눈에는 눈, 이에는 이라는 이슬람 교리를 설파하며, 넌 왜 먼저 반말이냐고 따져 물을지도 모르니까 말이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
...&lt;br&gt;
&lt;br&gt;
이 외에도 다양한 프로젝트와 작업에서 특정 기술적 문제를 해결하고 있는 중이라는 걸 기억하고 있어. 도움이 필요한 부분이 있으면 언제든 말해줘!&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
왜 반말이야?&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
죄송합니다. 앞으로는 존댓말로 대화드리겠습니다. 어떻게 도와드릴까요?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;#6&lt;/h3&gt;
&lt;p&gt;인공지능을 쓰자. 두 번 쓰자.
코딩에 있어서 특이점은 이미 넘어섰다.
github 저장소가 아니라 chatgpt와의 대화를 제출하고 그걸 gpt가 평가하는 세상이 올지도 모른다.&lt;/p&gt;
&lt;p&gt;아직 인공지능을 쓰지 않는 개발자가 많다는 걸 안다.
사용할지 말지는 개인의 자유다.
다만 사용하지 않는다면 분명한 한 가지 사실은 당신의 개발 속도는 빛의 속도로 느려지고 있다는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now, here, you see, it takes all the running you can do, to keep in the same place.&lt;br&gt;
If you want to get somewhere else, you must run at least twice as fast as that!&lt;br&gt;
&lt;br&gt;
여기서는, 보시다시피, 같은 자리에 있기 위해 할 수 있는 모든 힘을 다해 달려야 해요.&lt;br&gt;
만약 다른 곳으로 가고 싶다면, 최소한 그보다 두 배는 더 빨리 달려야 해요!&lt;br&gt;
&lt;br&gt;
-- 거울 나라의 앨리스&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 8월의 잡담]]></title><description><![CDATA[#0 간만에 ai 코딩 테스트 해봤다. 단 한 문제. Gpt4o 100점, gemini 1.5 pro 95점 (답은 맞지만 설명이 장황함) llama 3.1 405b 40점 뭔가 어설프게 빗겨 맞춤. claude opus 포함 나머지 다…]]></description><link>https://jiniya.net/2024/08/small-talk-2024-08/</link><guid isPermaLink="false">https://jiniya.net/2024/08/small-talk-2024-08/</guid><pubDate>Sat, 31 Aug 2024 23:55:49 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;간만에 ai 코딩 테스트 해봤다. 단 한 문제. Gpt4o 100점, gemini 1.5 pro 95점 (답은 맞지만 설명이 장황함) llama 3.1 405b 40점 뭔가 어설프게 빗겨 맞춤. claude opus 포함 나머지 다 0점. 아직 갈길이 멀다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;통제할 수 없는 일로 스트레스 받아봐야 나만 손해라는 걸 머리는 알지만 실천은 참 어렵다. 세상에서 젤 마음대로 되지 않는게 마음 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;아프리카bj나 아이돌이나 프로그래머나 치과 의사나 배관공이나 다 똑같다. 그냥 남들이 좋아하는거, 해달라는거 해주고 돈받는 게 본질. 21세기에도 여전히 선비의 나라에 살고 있는건 분명한 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;실력과 수입이 비례해야 한다는 믿음은 순진한 생각이다. 프로그래밍 실력과 연봉은 경험으로 알게 됐고, 가수의 가창력과 수입, 배우의 연기력과 소득 사이가 관계 없음은 형편 없는 슈퍼 스타들이 몸소 증명해준다. 실력은 그저 당신이 안망한다 정도를 알려주는 지표에 불과하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;이런거보면 머스크 추진력도 대단하지만, 본질적으로 llm 개발에 자본을 제외한 해자가 있긴 한걸까란 의문이 들기도 한다. &lt;a href=&quot;https://x.com/Joonits_plaid/status/1823639634435514747&quot;&gt;https://x.com/Joonits_plaid/status/1823639634435514747&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/008/0005077032?sid=105&quot;&gt;https://n.news.naver.com/article/008/0005077032?sid=105&lt;/a&gt; 주가가 100만원 넘기고, 한국시리즈 우승하고, 대표가 집행검 세레머니 하고, 전직원 연봉 인상하고, 택진형 택진형 하면서 추앙하던 때가 바로 엊그제 같은데 보릿고개라니,, 화무십일홍이란 말이 묘하게 오버랩된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;트위터 이거 누가 결제하나 싶었는데 생각보다 많은 것 같아 놀람. 그림 그리는거 추가되서 많이 보이는 건가? 망한다 망한다 한게 불과 얼마 안된거 같은데.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;탐라에 스레드 얘기가 많아서 설치하고 들어가봤다. 멀티버스는 실제한다는 강려크한 확신을 갔게 됐다. 같은 인터페이스, 다른 사용자들. 그나저나 메타도 계산해보고 수익창출 하는 거겠지?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;어느 날 나는 내가 부러워하는 인물들을 떠올리며 그들 삶의 좋은 부분만 골라서는 안 된다는 사실을 깨달았다. 이 사람의 몸매만, 저 사람의 재력만, 또는 이 사람의 성격만 갖고 싶어 해서는 안 된다. 그 사람 전체를 받아들여야 한다. 생각해보라.&lt;/p&gt;
&lt;p&gt;당신은 부러운 누군가의 행동, 욕망, 가족, 행복도, 인생관, 자아상까지 빠짐없이 포함해서 그 사람이 되고 싶은가? 그의 24시간을 기꺼이 그대로 살 의향이 없다면, 그의 인생 및 정체성과 당신의 것을 통째로 바꿀 의향이 없다면, 그를 부러워하는 것은 의미가 없다. - 불변의 법칙, 모건 하우절&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;할루시네이션이 인공지능 문제점 중 하나라고 한다. 자기가 뭘 모르는지를 모르는거다. 근데 이건 사람도 마찬가지가 아닌가 싶다. 헛소리를 저렇게 정성스럽게도 하는구나 싶은 경우가 다반사니까. 이걸 돌려 생각해보면 현재 llm대비 인간이 그나마 경쟁력을 가지는게 메타인지가 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;같은 경험을 가진 세대로써 지금 추억해보면 정말 야만의 시대가 아니었나 싶다. 언젠간 회식 때 고기 굽는 걸 시키는 지금을 그렇게 추억할지도. &lt;a href=&quot;https://x.com/i00000886666/status/1824193880234827802&quot;&gt;https://x.com/i00000886666/status/1824193880234827802&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;복지는 완결된 형태로 제공되어야 의미가 있다고 생각한다. 커피를 주면서 커피 머신 청소를 시켜야 한다면 그 회사는 커피 머신을 감당할 복지 능력이 없다는 생각. 그냥 주지 않거나 사먹을 수 있게 쿠폰을 주는게 맞지 않나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;Grok, gpt와는 다른 측면에서 압도적인듯. &lt;a href=&quot;https://x.com/TSLA_Bitcoin/status/1824680827344785726&quot;&gt;https://x.com/TSLA_Bitcoin/status/1824680827344785726&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;인간 한 명이 만들어지려면 수백억 개의 단계가 올바른 순서로 차질 없이 진행돼야 한다. 그러나 인간이 죽는 데에는 한 가지 일만 일어나면 충분하다. - 불변의 법칙 중에서&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;큰 누나는 조카들이 어릴 때 집에 대형 실내 미끄럽틀을 설치했다. 작은 누나는 거실에 그랜드 피아노를 두었다. 나는 아이들이 게임기, 핸드폰, 컴퓨터를 하는데 몹시 관대하다. 그때는 몰랐지만 이제보니 이게 다 각자가 느낀 결핍이었던 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;불편한 진실이지만 장기 근속이 꼭 좋은 것만은 아니라고 생각한다. 오래된 직원이 뭔가를 혁신하는 경우를 본적이 없기 때문이다. 반면에 처음부터, 원래, 지금까지, 관행 같은 말들로 변화를 가로막는 경우는 너무 많이 봤다. 고이면 썩게 마련이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;chatgpt를 유용하게 쓰는 법. 일단 일을 시킨다. 결과에서 모르는 부분이 있으면 다시 역으로 그게 뭐냐고 물어본다. 이해 못한 부분이 없을 때까지 반복한다. 무한 반복해도 짜증 한 번 없이, 언제나 친절하고 상냥하게 대답하는 완벽한 인격체를 마주할 수 있다. 최고의 학습도구.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;방시혁, 이수만 그리고 민희진이 떠오르는 기사. 일반적으로 천재를 만날 확률도, 개새끼를 만날 확률도 거의 제로 아닌가 싶다. 하물며 둘다면?! 그저 그런 사람들이 모여서 그저 그런 일을 하는 경우가 많은 일반인 입장에선 월급 루팡을 솎아내는 방법이 더 실용적일지도. &lt;a href=&quot;https://m.sports.naver.com/esports/article/439/0000029198&quot;&gt;https://m.sports.naver.com/esports/article/439/0000029198&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;잡스와 워즈니악, 버핏과 멍거, 게이츠와 커틀러, 조정호와 김용범 등의 사례를 보면 탑티어 경영자의 가장 탁월한 점은 인재 등용에 있는 게 아닌가 싶다. 이건희와 정의선에겐 있어 보이지만 이재용에겐 없어 보이기도 하는 것. 인사가 만사다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;생각보다 쓸만한 git 데스크탑 클라이언트가 없는데 fork 추천. 가끔 뜨는 구매 팝업만 무시하면 무료로 계속 사용할 수 있지만, 개인 개발하는 것 같으니 응원 차원에서 나쁘지 않으면 구매하는 걸 강력 추천. &lt;a href=&quot;https://git-fork.com/&quot;&gt;https://git-fork.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;투자 소득이 근로 소득을 넘기는 쉽지 않다. 그런데 한번 넘기 시작하면 왠만해선 재역전이 발생하지 않는다는 점이 신기하다. 시간이 흐를수록 그 간격은 더 커지고, 근로의 가치는 기하급수적으로 떨어진다. 중력이 있는 세상과 없는 세상의 차이.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;현존하는 최고의 채용 사이트는 병역일터가 아닌가 싶다. 지원자 퀄에서 잡코리아, 사람인과는 갭이 너무 크다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;토나오게 막히는 불금 퇴근 길 한복판에 못보던 귀요미 suv가 있길래 뭔가 해서 유심히 봤더니 애스턴마틴. 우르스 많이 보이던데 우르스보단 이쁜듯. 못보던 차라 그런가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;당신과 다른 경험을 한 사람은 당신과 다른 사고방식이나 관점을 지니기 마련이다. 그들은 다른 목표, 다른 견해, 다른 욕구, 다른 가치관을 지닌다. 따라서 사실 대부분의 논쟁은 의견이 아니라 경험이 충돌하는 상황이다. - 불변의 법칙, 모건 하우절&lt;/p&gt;
&lt;p&gt;모건 하우절의 돈의 심리학도 재밌게 읽었었는데 불변의 법칙도 좋았다. 책 말미에 저자가 다시 생각해보라고 던지는 질문에는 띠용~했다. 시간이 날 때 찬찬히 고민해볼 주제인듯한.&lt;/p&gt;
&lt;p&gt;일단 우리가 어떤 경험을 하고 나면, 다시는 그 경험을 하기 이전처럼 세상을 볼 수 없게 된다는 것이다. 우리가 어떤 경험을 하는 순간부터 그 경험은 과거, 현재, 그리고 미래를 보는 렌즈의 일부가 되어 우리가 보는 것들을 조성하고 왜곡한다. – 행복에 걸려 비틀거리다, 대니얼 길버트&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;텍스트힙, 있어빌러티라는 말은 당황스럽지만, 젊은층에서 독서율이 높아진다니 좋은 현상인듯. 나도 디올백보단 낫다는 생각. &lt;a href=&quot;https://x.com/telavi93/status/1827576408933036135&quot;&gt;https://x.com/telavi93/status/1827576408933036135&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;900조, 엄청난 것 같지만 대략 미국 전체 시총의 1.5프로 정도. 금투세 크리 터지면 한국 전체 시총만큼 미국 주식을 보유하는 날이 올지도. &lt;a href=&quot;https://x.com/steadyG11/status/1827917561687859607&quot;&gt;https://x.com/steadyG11/status/1827917561687859607&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;빈부격차가 줄어야 한다는 말에는 동의하지만 부자들이 더 부자될 필요가 없다는 말에는 동의하기 어렵다. 끝이 없는 인간의 탐욕에 기반했기 때문에 자본주의가 성공했다고 생각하기 때문. 그들의 욕망을 거세한다면 성장과 발전도 함께 거세되지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#27&lt;/h2&gt;
&lt;p&gt;&quot;... 3년 전에 아주 비슷한 문제를 풀었던 적이 있거든. 이 문제를 그 문제랑 연관시켜봤더니 답이 코사인이라는 걸 금방 알겠더라고.” 제게는 매우 중요한 순간이었습니다. 저는 결코 뛰어난 이론물리학자가 될 수 없을 거란 깨달음을 그때 얻었으니까요. - 제프 베조스, 발명과 방황&lt;/p&gt;
&lt;p&gt;대부분의 직업의 경우 사회에 기여하는 인재가 되려면 상위 10%에 들어야 합니다. 이론물리학의 경우엔 세계 50위권 내에 들지 않으면 큰 차이를 만들어내지 못하죠. 상황은 아주 명백했습니다. 불길한 징조를 알아차린 저는 바로 전기공학과 컴퓨터공학으로 전공을 바꿨습니다.&lt;/p&gt;
&lt;p&gt;학창 시절에 오래 달리기를 하면 항상 거의 꼴지 근처였다. 한번 가운데 등수를 한적이 있었는데 한바퀴 덜 뛴 경우였다. 넘 당당하게 들어가서 체육 쌤도 다뛴줄 알았던. 타고나기를 재능이 없는 분야도 있다. 나이가 들어보니 뭐가 됐든 재능이 있다는 게 어쩌면 더 신기한 일인 것 같기도 하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#28&lt;/h2&gt;
&lt;p&gt;사기 당해서 돈 떼인거도 억울할 거 같은데, 빚까지 떠안으면 진짜 그 화를 어떻게 참나 싶다. 티비 보다가 문득.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#29&lt;/h2&gt;
&lt;p&gt;별도 협의 계약서가 없다면 피해자는 골아플듯. 조국이 조국한 사건 아닌가 싶다. &lt;a href=&quot;https://x.com/lyntohno/status/1828974227875307859&quot;&gt;https://x.com/lyntohno/status/1828974227875307859&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#30&lt;/h2&gt;
&lt;p&gt;‘가난이란…… 하늘에서 떨어지는 작은 눈송이 하나에도 머리통이 깨지는 것. 작은 사건이 큰 재난이 되는 것. 복구가 잘 안 되는 것……’ - 이중 하나는 거짓말, 김애란&lt;/p&gt;
&lt;p&gt;결혼에 한 번 실패했는데 나는 그 실패조차 신뢰가 갔지. 자기 삶에 크게 실망해본 사람이라면 남의 인생도 쉽게 판단하지 않을 테니까. 무엇보다 그 사람은 나를 늘 존중해줬어.&lt;/p&gt;
&lt;p&gt;내 ‘최고의 날’, 내게 일어난 일은 이렇습니다.&lt;br&gt;
내가 말하면 그녀가 듣습니다. 그녀가 얘기하면 내가 듣습니다.&lt;br&gt;
우리는 함께 웃습니다.&lt;br&gt;
그곳에 큰 사건은 없습니다.&lt;br&gt;
대신 그녀가 있습니다.&lt;/p&gt;
&lt;p&gt;김애란 소설을 좋아한다. 그럼에도 이번 책은 그닥 임팩트 있지는 않았다. 장편보다는 단편이 훨씬 괜찮은 작가 같은 느낌적인 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-08-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 7월의 잡담]]></title><description><![CDATA[#0 토발즈옹의 c 코드를 보면 어셈이 보인다는 말의 의미는 프로그래머가 작성한 것 이상으로 컴파일러가 관여하는 부분이 없다는 의미 아닐까 싶다. C…]]></description><link>https://jiniya.net/2024/07/small-talk-2024-07/</link><guid isPermaLink="false">https://jiniya.net/2024/07/small-talk-2024-07/</guid><pubDate>Tue, 30 Jul 2024 21:11:27 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;토발즈옹의 c 코드를 보면 어셈이 보인다는 말의 의미는 프로그래머가 작성한 것 이상으로 컴파일러가 관여하는 부분이 없다는 의미 아닐까 싶다. C++만 해도 생성자, 소멸자, 예외 등 다양한 위치에 컴파일러가 생성한 코드가 들어가서 조금만 방심하면 의도랑 다르게 동작하는 경우가 생김.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-07-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;자신의 능력 범위를 넘어선 역할을 맡지 마라. 그것은 자신을 혹사하는 일이면서 동시에 자신이 잘해낼 수 있는 역할도 맡지 못하게 하는 일이다. - &amp;#x3C;나를 위해 살지 않으면 남을 위해 살게 된다&gt;, 에픽테토스&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-07-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;전후사정을 다 알긴 어렵지만 한번의 큰 성공이 오히려 독이된게 티메프 사태가 아닌가 싶다. 지마켓 엑시트와 티메프 건의 전개는 거의 유사하다. 결과론적으로 성공했냐 아니냐뿐. 그런점에서 els 사태, 전세 사기와도 닮았다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-07-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cs] .net 4.0 레퍼런스 어셈블리 수동으로 설치하기]]></title><description><![CDATA[.net 4.0으로 타겟팅된 프로젝트를 빌드할 때 레퍼런스 어셈블리가 없어서 빌드를 못하는 경우가 있다. 지원이 안되는 버전이라 그런지 공식 설치 파일도 없다. 그런 경우에는 수동으로 설치하면 된다. 아래 페이지에서 Download package…]]></description><link>https://jiniya.net/2024/07/install-dotnet-4.0-reference-assembly/</link><guid isPermaLink="false">https://jiniya.net/2024/07/install-dotnet-4.0-reference-assembly/</guid><pubDate>Thu, 11 Jul 2024 19:35:00 GMT</pubDate><content:encoded>&lt;p&gt;.net 4.0으로 타겟팅된 프로젝트를 빌드할 때 레퍼런스 어셈블리가 없어서 빌드를 못하는 경우가 있다. 지원이 안되는 버전이라 그런지 공식 설치 파일도 없다. 그런 경우에는 수동으로 설치하면 된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;아래 페이지에서 Download package를 선택해서 nupkg 파일을 다운로드 받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nuget.org/packages/Microsoft.NETFramework.ReferenceAssemblies.net40/&quot;&gt;https://www.nuget.org/packages/Microsoft.NETFramework.ReferenceAssemblies.net40/&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;nupkg 파일 압축을 해제한다. 그냥 zip 파일이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;build/.NETFramework에 보면 v4.0 폴더가 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;해당 폴더를 &quot;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework&quot; 로 복사하면 된다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 모여서 함께 일하는 이유]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2024/07/reasons-for-working-together/</link><guid isPermaLink="false">https://jiniya.net/2024/07/reasons-for-working-together/</guid><pubDate>Wed, 10 Jul 2024 19:35:00 GMT</pubDate><content:encoded>&lt;p&gt;예나 지금이나 소수정예로 일하는 것을 좋아한다. 사람이 많으면 커뮤니케이션 비용도 올라갈 뿐더러, 업무 외적인 일들로 발생하는 문제가 많아지기 때문이다. 궁극에는 능력만 된다면 혼자 일하는 게 제일 좋다는 생각이다. 하지만 그건 범인에게는 로망이나 꿈일 뿐이다. 혼자서는 독자적으로 부가가치 창출을 하기가 무진 어렵기 때문이다. 그래서 많은 사람이 그러듯 모여서 함께 지난한 밥벌이를 한다.&lt;/p&gt;
&lt;p&gt;시간이 많이 지난 먼 미래에 2024년을 어떻게 기억할지는 모르겠지만, 지금 당장을 기준으로는 올해는 정말 쉽지 않은 한해인 것은 분명한 것 같다. 여러모로 안좋은 국면을 지나는 시기라는 생각이 든다. 나쁜 소식이 하나 있어서 이제 끝나려나 하면 어서와 끝인줄 알았지, 라며 새로운 악재가 또 우리를 반겨준다. 엎친데 덮쳤다던가 산 넘어 산이라는 표현이 딱인 해가 2024년이 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;그런 어려운 국면을 지나다보니 모여서 함께 일을 한다는 것에 대해서 조금은 새로운 각도에서 바라보게 되었다. 바로 분산 투자 같은 장점이 있다는 사실이다. 혼자였으면 진작 멘붕에 빠져 나가 떨어졌을 것 같은 상황임에도 여럿이 같이 일을 하니 각자 몫 만큼만 데미지를 입으면 되는 것이다. 그러니 혼자서는 버티지 못했을 상황도 이겨낼 수 있는게 아닌 가 싶다. 고로 개인보다는 조직이 강한지도 모르겠다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그러고 보면 이 세상에서 참으로 좋은 것은 그 무엇이든 시련을 통한 단련을 거친다. 찬서리를 여러 번 견디고서야 사과에 깊고 오묘한 맛이 들 듯, 이 세상에서 모든 진선미는 비바람에 흔들리는 일 없이 꽃을 피우는 법이 없다.&lt;br&gt;
&lt;br&gt;
이러한 이치는 우리말 ‘부질없다’의 의미에 잘 녹아 있다. 부질없다는 ‘불질이 없다’는 말에서 유래했다. 불질은 단련의 과정을 말한다. 단련은 쇠붙이를 불에 시뻘겋게 달구어 망치로 두드리고, 이후 찬물에 담가 급하게 식히는 과정을 여러 번 반복하는 것을 말한다. 이러한 단련의 과정을 거쳐야 쇠가 강철로 단단해지며, 이러한 단련을 거치지 않으면 쇠붙이가 물러 터져서 제 구실을 다하지 못한다. 이처럼 불질(단련)을 거치지 않은 쇠붙이는 만들어 봐야 아무 쓸데가 없다는 뜻에서 ‘부질없다’는 말이 유래한 것이다.&lt;br&gt;
&lt;br&gt;
&amp;#x3C;오십에 읽는 주역&gt;, 강기진&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;부디 이 어려운 시기가 백련강이 되기 위한 불질의 시기였기를 기대해 본다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 지각 없는 회사를 만드는 비법]]></title><description><![CDATA[불철주야 많은 사장님들이 지각 없는 회사를 만들기 위해서 노력한다. 라떼야 30분 먼저 출근해서 업무 준비하는 게 미덕인 세상이었다면 요즘은 1…]]></description><link>https://jiniya.net/2024/07/secrets-to-creating-a-company-with-no-tardiness/</link><guid isPermaLink="false">https://jiniya.net/2024/07/secrets-to-creating-a-company-with-no-tardiness/</guid><pubDate>Wed, 03 Jul 2024 19:35:00 GMT</pubDate><content:encoded>&lt;p&gt;불철주야 많은 사장님들이 지각 없는 회사를 만들기 위해서 노력한다. 라떼야 30분 먼저 출근해서 업무 준비하는 게 미덕인 세상이었다면 요즘은 10분 먼저 출근하면 바보 취급 받는 세상이 되었다. 그런데 언젠가 술자리에서 재미난 이야기를 들었다. 예전에 회사 직원이었던 친구인데 현재는 KB로 이직해서 근무하고 있다. 그 친구 왈, 요즘같은 세상에도 자기 회사에는 지각이 절대 없다고 했다. 아무도 일찍 나오라는 이야기를 하지 않음에도 모두가 5분, 10분 먼저 나온다는 말.&lt;/p&gt;
&lt;p&gt;역시 국내 굴지의 금융 그룹이라 직원들의 마인드가 다른 것일까? 하는 찰나. 그 친구의 돌아오는 답변에서 무릎을 쳤다. KB는 5분, 10분 먼저 나온 것도 모두 일할 계산해서 급여에 추가해서 지급한다는 답이었다. 여윽시. 답은 금융치료가 제일 빠르다. 그렇게 직접 가면 불친절한 옆집 철물점 사장님도 유튜브에선 세상 따뜻한 사람이 되는 게 바로 자본주의의 매직 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;그렇다고 세상 모든 대표님들이 악덕해서 고정 근무제, 포괄 임금제를 유지하는 건 아닐거다. 중소기업 인력의 낮은 생산성으로 탄력 근무제, 포괄 임금제 폐지, 재택근무, 주4일의 길로 가기엔 부가가치 창출이 너무나 안되는 게 현실이다. 결국 대표님들도 힘들긴 마찬가지. 마치 이건 닭이 먼저냐? 달걀이 먼저냐? 같은 문제가 아닐까 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 6월의 잡담]]></title><description><![CDATA[#0 일관성 없이는 더 높은 수준이 될 수 없어요 - 더 베어, ep02 2024-06-02 #…]]></description><link>https://jiniya.net/2024/06/small-talk-2024-06/</link><guid isPermaLink="false">https://jiniya.net/2024/06/small-talk-2024-06/</guid><pubDate>Sun, 30 Jun 2024 12:39:15 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;일관성 없이는 더 높은 수준이 될 수 없어요 - 더 베어, ep02&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-06-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;삼촌이 상속 받은 돈으로 사업을 시작했다. 잘되다가 글로벌 금융위기로 어려워졌다. 주변에 빚을 내면서 막내 삼촌은 폐업을 권유했다. 하지만 존버를 했고, 결국은 연대보증으로 살던 집을 포함해 전재산을 잃었다. 가족은 풍비박산 났다. 버티는 게 항상 정답은 아니다. 물러설 줄도 알아야 한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-06-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;100억 있다고 시장이 찾아오진 않겠지만 소도시에서 100억 법인세 내면 찾아올지도. 부산에서 사업하는 사람 회사에 시장이 찾아온다길래, 머하러 오냐고 했더니 20년래 그 회사가 법인세 제일 많이 낸 회사라 찾아와서 불편한거 없냐 개선할거 없냐 물어본다는 썰을 들은 기억이.&lt;/p&gt;
&lt;p&gt;참 돈 값이 없어졌다고 느끼는게 예전엔 10in10이라고 10년 10억 모으기가 유행하더니. 요새는 기본 100억 인듯. 주식 게시판만 봐도 3자리는 돼야 말발이 먹힘. 코인판은 더하고. 허세도 아닌게 오프에서도 돈 번 사람들이 더러 보임. 울 회사 직원도 예전에 몇명 코인으로 파이어해서 퇴사하기도.&lt;/p&gt;
&lt;p&gt;그와중에 제일 안오른게 있다면 역시 월급. 초년생 때는 중소 병특 신입 연봉으로도 강남 1평을 샀지만 지금은 대기업 신입으로 영끌해도 1평이 빠듯할듯. 몇년 전에 심심해서 어렸을 적 부모님이 사준 250만원짜리 컴퓨터가 현재 얼마인지 계산해 본 적이 있는데 5천 정도였던 기억이.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-06-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] 윈도우 서버에 도커 설치하기]]></title><description><![CDATA[너무나 간단하지만 이 글을 쓰는 시점 기준 ChatGPT-4o가 학습하지 못한 것으로 추정되서 남긴다. https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set…]]></description><link>https://jiniya.net/2024/06/install-docker-on-windows-server/</link><guid isPermaLink="false">https://jiniya.net/2024/06/install-docker-on-windows-server/</guid><pubDate>Tue, 25 Jun 2024 10:35:00 GMT</pubDate><content:encoded>&lt;p&gt;너무나 간단하지만 이 글을 쓰는 시점 기준 ChatGPT-4o가 학습하지 못한 것으로 추정되서 남긴다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Invoke-WebRequest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;UseBasicParsing &lt;span class=&quot;token string&quot;&gt;&quot;https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;o &lt;span class=&quot;token function&quot;&gt;install-docker&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ce&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ps1
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;\&lt;span class=&quot;token function&quot;&gt;install-docker&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ce&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ps1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment?tabs=dockerce#windows-server-1&quot;&gt;https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment?tabs=dockerce#windows-server-1&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 5월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2024/05/small-talk-2024-05/</link><guid isPermaLink="false">https://jiniya.net/2024/05/small-talk-2024-05/</guid><pubDate>Fri, 31 May 2024 23:05:48 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;짐 사이먼의 메달리온 펀드의 연복리 수익률도 놀랍지만, 진정한 놀라움은 그 긴 시간 동안 퀀트 알고리즘에 대한 비밀을 지켰다는 점에 있다고 본다. 아마 퀀트 알고리즘이 공개됐으면 수익률은 지금과는 한참 달랐을듯. 어케보든 입지전적인 존잘 인물.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-05-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;첫째가 컴퓨터 게임을 할 수 있냬서 뭔가해서 컴퓨터를 켜줬다. 크롬을 실행하고 구글 페이지에 게임 아카이브를 검색하더니 플래시 게임을 한다. 조카들 쥬니버 켜줄때가 묘하게 오버랩됐다. 이제 10대가 되는 아이는 스노우 최애, 파파고, 크롬, 구글을 사용한다. 그래도 네이버가 죽진 않았다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-05-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;인생도 어쩌면 인형 뽑기 같다는 생각이 들었다. 안 뽑히는 게 일상이고, 어쩌다 운이 좋으면 한 번 뽑히는,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-05-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;스스로 부가가치 창출이 가능한 개발자는 대체로 1인 기업이든, 자기 사업이든 하는 경향이 있는듯. 근데 해보면 노동력을 직접 파는 일이 아니고서 100원 투입해서 110원 벌기란 여간 어려운게 아니다. 그나저나 이제 개발자가 매출까지 신경써야 하는 세상인 것인가?! ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-05-31&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;나도 곤경에 처하면 배경음악 싹 깔리면서  김수현같은 남자가 뙇 나타나서 마법처럼 해결해 주면 어떨까하는 상상을 해봤다. 아니면 네잎클로버 정도의 행운이라도. 늦게 봤지만 김수현 비주얼은 킹정 ㅎㅎ &lt;a href=&quot;https://youtu.be/ucpb4BYNJ6s?si=KQh9FfRlXRF8p11U&quot;&gt;https://youtu.be/ucpb4BYNJ6s?si=KQh9FfRlXRF8p11U&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-05-31&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;고객들 비위 맞추랴, 관계 유지하랴 저녁도 없는 삶의 연속인 영업쪽이나, 말도 안되는 이야기들에도 매번 꼬박 꼬박 친절하고 교양있게 응대해야 하는 지원쪽이나, 보고 있으면 진심 사람이지만 사람이 제일 힘든게 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-05-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 4월의 잡담]]></title><description><![CDATA[#0 알려줘도 코딩 컨벤션 안 지키는 개발자는 빨리 헤어지는 게 서로 윈윈 아닌가 싶다. 2024-04-04 #1 똑똑하고 전문적으로 보이는 걸 싫어하는 개발자는 없다. 그에 관한 아주 싸고 효과적인 방법이 있는데 답변하기 전에 llm…]]></description><link>https://jiniya.net/2024/04/small-talk-2024-04/</link><guid isPermaLink="false">https://jiniya.net/2024/04/small-talk-2024-04/</guid><pubDate>Sat, 27 Apr 2024 21:36:12 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;알려줘도 코딩 컨벤션 안 지키는 개발자는 빨리 헤어지는 게 서로 윈윈 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;똑똑하고 전문적으로 보이는 걸 싫어하는 개발자는 없다. 그에 관한 아주 싸고 효과적인 방법이 있는데 답변하기 전에 llm에 한번 물어보는 거다. 특히 안된다, 방법이 없다 같은 답변을 쓰기 전에는 필수. 대신 물어보고 그 답변을 인간에게 전달하는 짓을 하면서 드는 자괴감이란 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;개발팀은 대리 달면 다 나간다는 말에 심심해서 계산해봤다. 평균 근속 3.07년. 팩폭 오졌다. 그럼에도 탐라에 다른 글을 보니 3.07도 그리 나쁜 건 아닌듯. 창업 전엔 나도 3년 근처 다닌 회사도 없었다. 2년만 다녀도 지겨워지는게 인지상정. 젊고 똑똑하면 유혹하는 곳은 또 너무 많다는거.&lt;/p&gt;
&lt;p&gt;코시국을 지나면서 채용 난이도가 지수적으로 어려워진 것 같은 느낌적인 느낌. 이제는 회사의 주된 리스크가 채용에 있다고 느낄 정도. 채용 난이도 증가가 더 빠를지, 인공지능 발전이 더 빠를지. 둘 사이 경쟁이 아닐까 싶다. 10년은 더 존붜해야 하는데 쉽지 않다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;챗지피티 없이 개발해야 실력 향상이 된다는 글들을 보면서 좋은 방법은 아니란 생각. 그냥 하나라도 더 물어보고, 답변 하나라도 더 보는게 훨씬 더 빨리 발전할 거라는 데 500원은 걸 수 있다. 쓸데 없는 잔디 심지 말고 매일 30분씩 모르는거 물어보면서 과외받자. 심지어 과외비가 너무 싸다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;1번이 자아를 내려놓기인 걸 보니 뭔지는 잘 모르지만 503일 동안 찐개발 한 건 맞다는 생각. 컴공과에 전공필수로 개설이 시급하다. 자아를 내려놓기 수업. 개발을 하든 안 하든 인생 전반에 도움이 될거란 생각. &lt;a href=&quot;https://x.com/kodingwarrior/status/1778238799740571695&quot;&gt;https://x.com/kodingwarrior/status/1778238799740571695&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;특히 이건 인공지능 시대에 프롬프트 엔지니어링만큼이나 필요한 스킬이 될거란 느낌적인 느낌. 비트코인 화폐 철학과도 나오는 마당에 개설 못할 일도 없을 것 같은 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;컴퓨터 너드 천재를 굳이 이길 필요가 있을까 싶다. 패자가 되더라도 떨어지는 부스러기가 몹시 큰 시장이니까. 그게 예체능같은 승자독식 분야와 차이가 아닐까 싶다. 못해도 중간은 먹고 산다는 점. 심지어 요즘은 20불만 결제하면 못하기도 어려운 세상이 되었다. &lt;a href=&quot;https://x.com/casuarius14th/status/1778732802839855349&quot;&gt;https://x.com/casuarius14th/status/1778732802839855349&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;몽테스키외Montesquieu는 275년 전에 말했다. “그저 행복해지고 싶다면 그 목표는 쉽게 이룰 수 있다. 하지만 우리는 남들보다 더 행복해지길 원한다. 이는 언제나 어렵다. 왜냐하면 우리는 남들이 실제보다 더 행복하다고 믿기 때문이다.” - 불변의 법칙, 모건 하우절&lt;/p&gt;
&lt;p&gt;행복한 삶을 위한 제1원칙은 기대치를 낮추는 것입니다. 비현실적인 기대치를 갖고 있으면 평생 괴로워집니다. 합리적인 기대치를 갖고, 당신이 맞이한 결과가 좋든 나쁘든 침착함과 평정심을 갖고 받아들이십시오.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;내가 이혼도 하고&lt;br&gt;
좌천도 당해 봐서 아는데&lt;br&gt;
지금은 죽을 거 같아도&lt;br&gt;
지나면 아무것도 아니더라&lt;br&gt;
-- 하이드 e07&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;폴 그레이엄을 좋아하지만 이 의견에는 반대다. 저출산의 일반화, 딩크족, 무자식이 상팔자같은 속담만 봐도 집단 지성은 자식이 없는 상태를 더 좋게 평가하는게 아닌가 싶다. 투자에 비유하자면 자식은 손절이 불가능한 mdd 100프로인 자산과 유사한 느낌 아닐까 싶다. &lt;a href=&quot;https://x.com/dylayed/status/1779384991828615676&quot;&gt;https://x.com/dylayed/status/1779384991828615676&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;내 생각에 그레이엄 아저씨의 글에서 가장 주목할 부분은 &quot;and I know I&apos;ve been lucky.&quot;가 아닐까 싶다. 시쳇말로 자식운이 있다면 당연히 자식을 가지는게 없는 것보다 즐거운 일일 것이다. 반면 운이 따르지 않는다먼 여러 조만가지의 리스크가 있다는 점도 꼭 기억할 필요가 있지 않나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;할루시네이션으로 헛소리만 한다고 ai를 폄하하는 사람에게 ai 답변을 건내서 업무가 진행된다는 게 인공지능의 가장 신비한 점 중에 하나. 다음 엔지니어 채용 시에는 자기 돈으로 ai 하나 쯤은 결제해서 쓰는 사람을 뽑고 싶다. 깃헙 저장소가 아니라 챗지피티 대화 링크를 제출할 날도 머지 않은듯.&lt;/p&gt;
&lt;p&gt;진심으로 인공지능을 사용하는 사람이라면 기술 관련 지난 30일간의 대화 내용을 보면 면접 보다 더 많은 정보을 얻을 수 있다고 본다. 물론 그게 평가 기준이 된다면 잔디 심기처럼 챗지피티와 의미있게 대화하는 방법 같은 것들이 봇물처럼 넘쳐나겠지 ㄷㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;돈이야 언제든 벌 수 있지만 시간은 무엇으로도 살 수 없다. - 저스트.킵.바잉., 닉 매기울리&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;인생 성취의 5할은 태어난 지역이, 3할은 유전자가 결정한다고 한다. 심지어 남은 2할도 유년기 성장 환경등 운이 결정하는 요소가 상당하다고 한다. 운은 생각보다 더 중요한지도 모른다. 반면 우습게도 한국에 태어났다면 일단 운은 좋았던게 아닌가 싶다. 한끗 차이로 북한에 태어났다면? &lt;a href=&quot;https://x.com/aronze/status/1782224665081217319&quot;&gt;https://x.com/aronze/status/1782224665081217319&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;최애 명서, 지금 읽어도 메시지가 여전히 유효하다고 생각되는 책들. 조엘 온 소프트웨어, 코딩호러의 이펙티브 프로그래밍, 실용주의 프로그래머, 아트 오브 유닉스 프로그래밍, 맨먼스 미신, 라이팅 솔리드 코드, 쇼스토퍼&lt;/p&gt;
&lt;p&gt;해커와 화가 추가&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;누군지도 몰랐지만,, 하도 핫해서 봤더니 새로운 형식의 기자회견인건가 ㄷㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;탐라 민희진 관련 글을 보면 반응이 묘하게 사측과 노측으로 갈린다. 서는 데가 바뀌면 풍경도 달라진다는 말은 진심 명언인듴.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;클로드 별로 안써서 해지할까 싶었는데 오늘 지피티가 모르는거 알려줘서 유지하기로. 사실 한달에 이런거 하나만 있어도 유지할 가치는 충분 한 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;뜨거운 하루였다. 세상이 보온밥솥에 담긴 밥 한 그릇 같던 날씨. 사람들은 찐득하게 엉긴 밥알처럼 서로를 못 견뎌했다.  - &amp;#x3C;구의 증명&gt;, 최진영 지음&lt;/p&gt;
&lt;p&gt;그 주파수는 웃기거나 울리려고 하지 않아서 좋았다. 착한 척도 좋은 척도 하지 않아서 좋았다.&lt;/p&gt;
&lt;p&gt;이모는 내 인생의 가장 큰 행운이었다. 이모를 갖는 것으로 나는 내 인생의 행운을 다 써버린 거다. 너무 강력한 행운이어서 오래 지속되지 못한 거고. 그래. 그렇다고 치자.&lt;/p&gt;
&lt;p&gt;행복하자고 같이 있자는 게 아니야. 불행해도 괜찮으니까 같이 있자는 거지.&lt;/p&gt;
&lt;p&gt;특이한 형식인데 몰입감 있는 소설. 한글 소설 읽는 맛이 있어 좋았다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-04-27&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 3월의 잡담]]></title><description><![CDATA[#0 gemini랑 빙의 답변 차이를 알아보려고 빙에 똑같은 프롬프트 넣고 돌렸더니 딥이 얼추 같아서 뭐지 이랬는데, 깨알같이 밑에 참조 사이트가 http://gemini.google.com gemini…]]></description><link>https://jiniya.net/2024/03/small-talk-2024-03/</link><guid isPermaLink="false">https://jiniya.net/2024/03/small-talk-2024-03/</guid><pubDate>Fri, 22 Mar 2024 15:05:31 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;gemini랑 빙의 답변 차이를 알아보려고 빙에 똑같은 프롬프트 넣고 돌렸더니 딥이 얼추 같아서 뭐지 이랬는데, 깨알같이 밑에 참조 사이트가 &lt;a href=&quot;http://gemini.google.com&quot;&gt;http://gemini.google.com&lt;/a&gt; gemini도 빙을 참조하면 무한 루프에 빠지는 것인가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-03-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;Claude3 opus 극찬이 많아 테스트 해 봄. 코딩은 아직 gpt가 더 나은듯. 바로 쓸 수 있는 코드가 나오기까지 지적질이 많이 필요하고, 지적질을 해줘도 알겠다면서 엉뚱한 코드 만드는 경우가 많은듯. 주석은 opus가 내스탈. gpt는 쓸데없이 주석 많이 다는 느낌이라.&lt;/p&gt;
&lt;p&gt;많은 사람들이 칭찬한 것처럼 글을 읽고 추론하는 능력은 opus가 한수위인듯. 포괄적으로 글 내용을 더 잘 이해하고, 관련 질문에도 더 유용한 부분을 잘 캐치해서 대답하는 걸로 보임. 심지어 원글에 없는 내용도 질문하면 글에는 없지만 원글 기반으로 추론해보면 하면서 덧붙여서 알려줌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-03-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;구글이 앤스로픽에 투자해서 그런지는 모르겠지만 rust 코딩을 시켜보면 claude3랑 gemini랑 비슷하게 c스럽게 작성한다는 특징이 있는 것 같다. 같은 작업을 줬을 때 허술하게 작성하는 부분도 비슷함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-03-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;10대들이 아이폰 좋아한다는 기사를 볼때마다 몇몇 애들 얘기겠지 했는데, 조카들이 죄다 아이폰 15 프로 맥스 들고다니는 걸 보니, 이게 현실이구나 싶다. 애들이 아이폰을 추앙하는 이유는 뭘까? 갤럭시 참 좋은데 뭐라 할 말이 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-03-22&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 2월의 잡담]]></title><description><![CDATA[#0 경제 유튭 보다가 프랭크버거가 쉑쉑버거 하위호환이라는 걸 나만 느낀 건 아니라는 걸 알게돼서 웃겼다. 무튼 프랭크버거 강추. 심지어 난 쉑쉑보다 프랭크가 더 나은듯한. 2024-02-01 #…]]></description><link>https://jiniya.net/2024/02/small-talk-2024-02/</link><guid isPermaLink="false">https://jiniya.net/2024/02/small-talk-2024-02/</guid><pubDate>Fri, 16 Feb 2024 13:41:27 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;경제 유튭 보다가 프랭크버거가 쉑쉑버거 하위호환이라는 걸 나만 느낀 건 아니라는 걸 알게돼서 웃겼다. 무튼 프랭크버거 강추. 심지어 난 쉑쉑보다 프랭크가 더 나은듯한.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;대상의 속성은 상호작용하는 순간에만 존재하며, 그 속성이 한 대상과의 관계에서는 실재하지만 다른 대상과의 관계에서는 실재하지 않을 수 있다는 것입니다. - &amp;#x3C;나 없이는 존재하지 않는 세상&gt;, 카를로 로벨리&lt;/p&gt;
&lt;p&gt;세계는 이러한 상호작용의 네트워크입니다. 물리적 물체가 상호작용할 때는 관계가 성립합니다. 돌이 다른 돌과 부딪힙니다. 햇빛이 내 피부에 닿습니다. 독자인 당신은 이 글을 읽습니다.&lt;/p&gt;
&lt;p&gt;미래는 과거에 의해 결정되지 않습니다. 세계는 확률적인 것입니다.&lt;/p&gt;
&lt;p&gt;나가르주나의 핵심 논지를 간단히 말하면, 다른 어떤 것과도 무관하게 그 자체로 존재하는 것은 없다는 것입니다. 이는 곧바로 양자역학과 공명을 일으킵니다.&lt;/p&gt;
&lt;p&gt;나가르주나의 공空은 깊은 위안을 주는 윤리적 태도를 길러주기도 합니다. 우리가 자립적인 실체로 존재하지 않는다는 사실을 깨달음으로써 집착과 고통에서 벗어날 수 있게 도와주기 때문입니다. 인생은 무상하기 때문에, 절대적인 것은 없기 때문에, 삶은 의미가 있고 소중한 것입니다.&lt;/p&gt;
&lt;p&gt;연기와 공, 그리고 양자역학을 보면 부처는 진짜 깨달은 사람이 아닐까라는 생각이 뿜뿜. 막판에 그래서 삶이 의미 있고 소중하다는 의견은 너무 나간듯. 부처님은 그 삶에 대해서도 집착을 끊으라고 하셨을테니.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;언니는... 누구야?&lt;br&gt;
나는 말이야&lt;br&gt;
스즈메의... 내일이란다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;스즈메의 문단속&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2024-02-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;에릭 레이먼드의 성당과 시장이 떠오르는 결과. &lt;a href=&quot;https://x.com/mynameisdjkim/status/1755195553800126494&quot;&gt;https://x.com/mynameisdjkim/status/1755195553800126494&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;의사 2천명 늘린다고 온 나라가 떠들석한걸 보니 참 뭐라 할 말이,, 개발자처럼 십만명씩 양성한다고 말했다간 세상 무너질듴 ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;소위 사회 지도층이라 불리는 사람들 중에 잘못을 잘못했다고 순순히 인정하는 장면을 한번쯤은 보고 싶다. 그것만해도 걸출한 능력이고 대단한 재능일듯. 죄다 그냥 아몰랑 쟤가 더 나빠만 시전하는 요즘 시국. 요지경 속이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;절대 창업하면 안 될 것 같은 사람들은 멀쩡한 회사 두고 나와서 사업하고, 창업하면 돈싸들고 투자해 주고 싶은 사람들은 회사 그늘을 벗어나지 않는 현실을 보면서 본인이 어떤 사람인지를 안다는 게 참 어렵다는 걸 새삼 느낀다. 항상 함께하지만 가장 낯설기도 한 존재가 내가 아닌가 싶기도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;인생도 빅오 표기법으로 생각해야 한다는 걸 배운다. 최악을 가정하면 항상 모든 일이 놀랄만큼 만족스런 결과로 다가온다. 같은 이치로 기대가 크면 실망도 큰 법. 그럼에도 마음이 문제다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-02-16&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2024년 1월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2024/01/small-talk-2024-01/</link><guid isPermaLink="false">https://jiniya.net/2024/01/small-talk-2024-01/</guid><pubDate>Wed, 31 Jan 2024 23:25:38 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;&quot;어떤 사람을 복종시킨다는 것은 그를 다른 사람 없이는 살아가지 못하는 처지에 두지 않는 한 불능가능하다&quot;는 말이 현실이 된 것입니다. 루소의 말이 서늘한 이유는, 지금 현재 우리 대부분이 다른 사람 없이는 살 수 없기 때문입니다.&lt;/p&gt;
&lt;p&gt;취업을 하든 무엇을 하든 돈을 주는 사람을 떠나서는 생계를 유지할 수도 없습니다. 도망을 생각하지도 못했던 과거 노예나 지금 우리나 자신의 필요를 증명해야만 합니다. 그러지 않으면 억압체제는 우리에게 먹이를 주지 않을 테니까요.자신이 쓸모가 없더라도 쓸모 있는 척이라도 해야만 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;강신주의 장자수업, 강신주&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2024-01-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;테스트를 해보면 안하던 테스트를 하기만 해도 80프로 정도까지는 금방 올라간다. 문제는 80에서 90까지 10 올리는데 더 높은 비용이. 99에서 100으로 높이기는 거의 불가능에 가까운 노력이 든다. 노력도 가성비를 따져가며 할 필요가 있다. 일 하려고 태어난 인생은 아니잖은가?&lt;/p&gt;
&lt;p&gt;재밌어서 열심히 노력하며 사는 걸 뭐라하는 건 아니다. 치열하게 살지 않는 사람들에게 왜 그렇게 사냐는 얘기를 쉽게 할 수 있는 건 아니라는 얘기. 어쩌면 그들이 더 똑똑하고 효율적인 것일 수도 있다. 무용해서 거목이 됐다는 장자의 말처럼,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;관계는 피곤하고, 자유는 고독하다. 그 사이를 적당히 방황하며 사는 게 인생인듴,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;모름지기 성공한 사람은 성공 경험에 도취되게 마련이다. 한 번 성공했으니 그것을 재현하는 일도 쉬울 것이라고 생각한다. 그런데 노부나가는 성공의 덫에 빠지지 않고 조금이라도 위험한 싸움은 적극적으로 피했다. 이것이야말로 그의 남다른 면이며 그가 진정 강한 이유였다. - 확률적 사고의 힘&lt;/p&gt;
&lt;p&gt;노부나가는 천하통일의 경쟁자였던 강대한 세력가나 난다 긴다 하는 명장과는 직접 대결한 적이 거의 없다. 다케다 신겐과 우에스기 겐신上杉謙信 같은 명장은 철저하게, 때로는 체면이고 뭐고 다 팽개친 채 줄기차게 피했다. - &amp;#x3C;확률적 사고의 힘&gt;, 다부치 나오야&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;위기 관리의 진정한 과제는 얼마나 정확하게 미래를 예측하는가가 아니다. 예상하지 못한 사태가 발생해도 어떻게 살아남을 것인가다. 살아남기 위해서는 눈앞의 이익도, 체면도, 재산의 일부도 잃을 각오를 해야만 한다. - &amp;#x3C;확률적 사고의 힘&gt;, 다부치 나오야 / 황선종&lt;/p&gt;
&lt;p&gt;가오를 일류 기업으로 만든 것은 카리스마 경영자나 한 사람의 천재 기술자가 아니다. 클레임을 활용해 상품 개발을 줄기차게 해나가는 구조가 가오의 장기 성장을 지탱하고 있다.&lt;/p&gt;
&lt;p&gt;시행착오에 의한, 계획이 없는 진보야말로 불확실한 세계를 살아나가는 단 하나의 방식인 것이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;불편하지만 세상이 이런지는 좀 됐다. 비슷하게 대부분 쇼핑몰이 네이버 검색해서 들어가면 저렴하고, 그냥 들어가면 비싸다. 네이버 검색 순위를 높이기 위해서 네이버 검색에는 할인 붙여서 노출시킴. 쿠팡은 요즘 열심히 벌어서 쿠팡이츠에 퍼주는 편. &lt;a href=&quot;https://x.com/Kiko_kim_/status/1744319629739384906&quot;&gt;https://x.com/Kiko_kim_/status/1744319629739384906&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;이가 없으면 잇몸으로 산다. 입술이 없으면 이가 시리다. 신기하게도 둘다 팩트인 경우가 많은듯. 옛말은 참 심오하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;비트코인 현물 etf 승인. 다시 코인의 시간인가? 웃긴건 코인러들이 첨에 게리 갠슬러 등장할때는 찬양했는데, 지금은 역대급 빌런이 됐고, 선물 시장 열릴때도 환호했지만 매도 포지션에 통수 맞음. 과연 현물 etf는 어떨지?! 코인의 계절이 오면 마스터노드로 날렸던 비트가 생각나 속이 쓰리다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;나는 차라리 더러운 도랑에서 놀며 스스로 즐거움을 느낄지언정 국왕들의 속박은 받지 않을 것이오. 한평생 관리가 되지 않고 내 의지대로 유쾌하게 살고 싶소. - 사기열전 , 사마천&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/SppolgfJqdQ?si=mgsoevrP88EqFdvD&quot;&gt;https://youtu.be/SppolgfJqdQ?si=mgsoevrP88EqFdvD&lt;/a&gt; 시사기획 창, 정치 선진 모델로 본받아 보자고 취재한 스웨덴은 요즘 강력 범죄로 나라가 골로 가는 중. 무차별 난민 수용으로 인한 결과라는 평. 좋은 의도에서 시작한 일이 꼭 좋은 결과로 이어지진 않는다는 걸 입증한 또 한 사례가 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;동아시아 쪽은 사람들이 똑똑한데 정치 체제는 거의 발전이 없었던 거 같다. 서구 열강이 들어올 때까지 독자적으로 공화제나 민주주의를 채택한 곳은 없는 듯. 그렇다고 천년만년 왕조 하나가 지배한 거도 아닌걸 보면 딱히 통치를 잘한거도 아니고. 무너지면 어김없이 다른 왕조가 들어섬.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;정용진 회장을 보면 사업이 참 어렵다는 걸 실감한다. 모든 걸 다 가지고 저렇게 열정적으로 온갖 시도를 하는 족족 결과가 거의 다 나쁜 걸 보면 세상 쉬운게 하나 없구나 싶다. 이참에 그냥 대세 따라 이마트바이오로직스나 설립하는게,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;이문열의 삼국지는 작가 개입이 많다는 이유로 까이는데, 오히려 그점이 또 장점 아닌가 싶기도 하다. 공명이 죽고 그 평이 몇페이지에 걸쳐서 이어지는데 제갈량이 촉으로 간 이유가 용꼬리보다 뱀머리를 노렸을지도 모른다는 썰이 있었다. 듣고보니 그랬을지도?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;공동주택 매매는 가격을 떠나 이웃리스크가 너무 큰듯. 그나마 임대는 이사라도 가지, 매매했는데 좌우위아래 빌런 걸리면 답이 없다. 그렇다고 단독은 관리하기 개불편. 단독처럼 이웃리스크 없고, 주복처럼 인프라 편리하고, 아파트처럼 관리비 낮은 주거형태가 절실하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;가치를 축적하지 못하는 시간 == 실력 없는 경력,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;스스로 부가가치 창출이 가능하다면 작게 벌어도 혼자 벌어 먹고 사는게 속편하다는 주의인데, 혼자 벌어도 천년만년 살 것 같은 존잘 셀럽 슈카같은 사람이 비지니스 모델 운운하며 골아프게 직원 데리고 사업 하려는거 보면 세상은 넓고 사람은 많은듯. 자본주의의 힘인가? 공대장 성향 때문일까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;엔터 사업은 북미 쪽에는 없는 사업이라고 한다. 북미는 그냥 끼있는 애들이 떠서 걔들이 기획사 차리고 한다고. 우리처럼 발굴해서 키워내는 시스템은 없다는 거. 그런데 여기에 k엔터의 위대함도 있지만 한계도 있다는 생각. 그룹 부활이 축소판으로 그 모든 걸 잘 보여줬다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;20년전 교대는 인기 학과였지만 지금은 출생률 감소로 존폐 위기에 처했다. 순환론적 사고로 출생률이 반전하면 10년 후에는 다시 좋아질수도 있다는 말을 들었다. 난 반대인게 출생률이 올라가도 인공지능이 상당수 대체할 것 같다. 본질적으로 같은 말 계속 하는게 사람이 하기에 적합한 일은 아님.&lt;/p&gt;
&lt;p&gt;바보같은 질문을 해도 흐트러짐 없이 매번 상냥하게 착착 알려주는 인공지능을 사람이 이기기는 불가능에 가깝다고 본다. 또한 10년 후 초등학생 수는 얼추 정해진 미래라는거,,&lt;/p&gt;
&lt;p&gt;비슷하게 지금의 의대 쏠림이 20년 후에는 어떤 미래를 가져올지 궁금함. 의대를 많이 가던 시절이 있었지, 라고 할지. 여전히 그때도 의대 올인하고 있을지...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;안드로이드로 유튜브, 엑스, 출근해서 윈도우 비주얼 스튜디오로 코딩, 모르는건 챗지피티에 물어보고, 걔도 모르면 구글 가서 검색하고, 소통은 팀즈, 음악은 에어팟, 서버는 aws, 퇴근하면 넷플릭스, 엔비디아 그래픽 카드로 게임하는 걸 보면서 이래서 기승전 빅텍인건가, 아님 꼭지인가 싶다.&lt;/p&gt;
&lt;p&gt;나의 사각지대는 테슬라, 메타인듯. 과연 향후 10년도 미장의 대서사시가 이어질까? 아님 이머징의 반격이 시작될까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;의사들 이야기를 들어보면 환자들은 수명을 6개월 연장할 때 5천만원 정도 쓸 용의가 있다고 합니다. 수억 원을 호가하는 항암제도 있습니다. - &amp;#x3C;김학주의 40배 수익클럽&gt;, 김학주&lt;/p&gt;
&lt;p&gt;증시는 ‘미래의 기대’를 사고파는 곳입니다. 이곳에서의 죄는 ‘남보다 늦는 것’이라고 말했습니다. 저는 ‘현재’를 사고파는 사람 가운데 투자에 성공하는 경우를 거의 본 적이 없습니다.&lt;/p&gt;
&lt;p&gt;국내 투자 업계 종사자가 쓴 책 중에 시간이 아깝지 않았다 생각되는 몇 안되는 책.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;육아나 교육에 환상을 가진 부분이 더러 있는데 의외로 연구 결과를 보면 육아나 교육은 생각보다 아이 인생에 미치는 효과가 크지 않다. 유전이 거의 절대적임. 그러니 애나 어른이나 스트레스 안 받으면 그걸로 된거다. 로또 번호 열심히 고른다고 당첨되지 않는거랑 같은 원리.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;어떤 변화가 있었는지 모르겠지만 최근 삼전의 소프트웨어 역량이 많이 좋아진 것 같다. 예전에는 삼성앱은 쓰지도 않았는데 요즘 몇개 써보니 만듬새가 제법 괜찮다. 다만 아쉬운건 너무 갤럭시 우물 안에만 있다는거. 하드웨어에 끼워서 파는거니 이해는 한다만, 데스크탑 지원되면 금상첨화일듴,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;오늘날 같은 것의 테러는 모든 삶의 영역으로 확산된다. 우리는 세상 곳곳을 돌아다니면서도 하나의 경험도 하지 못한다. 모든 것을 인지하면서도 어떤 것도 인식하지 못한다. 정보와 데이터를 쌓으면서도 어떤 지식에도 도달하지 못한다. - 타자의 추방, 한병철&lt;/p&gt;
&lt;p&gt;체험과 흥분을 애타게 추구하면서도 언제나 같은 상태로 남아 있다. 친구와 팔로워를 쌓으면서도 어떤 타자도 만나지 못한다. 사회 매체들은 사회적인 것의 절대적인 소멸 단계를 보여준다.&lt;/p&gt;
&lt;p&gt;전면적인 디지털 네트워크와 소통은 타자와의 만남을 쉽게 해주지 않는다. 그것들은 오히려 낯선 자와 타자를 지나쳐 같은 자와 같은 생각을 지닌 사람들을 발견하도록 하고, 우리의 경험 지평이 갈수록 좁아지게 만든다.&lt;/p&gt;
&lt;p&gt;그것들은 우리를 무한한 자기 매듭 속으로 얽어 넣고, 결국에는 &quot;우리에게 우리 자신의 표상들을 주입시키는 자기선전&quot;으로 이끈다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;홍콩 els, 부동산 pf, 지식산업센터 등등 이런거 보면 우리 나라는 너무 쉽게 수익은 사유화, 손실은 사회화 하려는 경향이 있다. 수익도 나누든지, 그게 싫음 손실을 감당하든지. 둘중 하나만 해야.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-31&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;테슬라와 머스크를 보면 자본주의의 새로운 단면이 느껴진다. 주주들이든 직원이든 돈이 되면 생각보다 많은 것들이 용서된다는 점. 심지어 그런 기행이 역으로 추앙 받는다는 거. 돈 못 버는 사장은 참 고달프다고 말하던 모 게임사 대표가 묘하게 오버랩된다. 극혐과 추앙은 어쩌면 같은 건지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2024-01-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 12월의 잡담]]></title><description><![CDATA[#0 [소고] 페어 프로그래밍에 관한 단상 feat. ChatGPT https://jiniya.net/2023/12/dynamic-table-size-with-chat-gpt/ 2023-12-01 #…]]></description><link>https://jiniya.net/2023/12/small-talk-2023-12/</link><guid isPermaLink="false">https://jiniya.net/2023/12/small-talk-2023-12/</guid><pubDate>Mon, 25 Dec 2023 14:58:58 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;[소고] 페어 프로그래밍에 관한 단상 feat. ChatGPT &lt;a href=&quot;https://jiniya.net/2023/12/dynamic-table-size-with-chat-gpt/&quot;&gt;https://jiniya.net/2023/12/dynamic-table-size-with-chat-gpt/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;주변을 보면 크든 작든 어떤 성취를 이룬 사람들을 보면 진짜 뭔가를 꾸준히 한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;대규모 트래픽 떡밥을 물어본다. 고인물들이 생각하는 최후의 전선이란 생각. 거기 밀리면 더이상 기댈데가 없는게 아닌가 싶다. 거의 중고딩때 애들끼리 너 몇줄짜리 프로그램 짜봤니? 하는거랑 뭐가 다른가 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;생애 첫 gpt 프로그램을 작성했다. 하나는 번역기, 하나는 교정기.  단돈 3센트로 사람이 몇시간 작업해야 나올 법한 결과물이 뚝딱 나왔다. 기가 막히다는 말 밖에는. 몰랐는데 내가 주로 사용하는 패턴이 페르소나 패턴이었다. 프롬프트 패턴을 배워야하는 세상인 것인가?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;[cpp] condition_variable과 spurious wakeup &lt;a href=&quot;https://jiniya.net/2023/12/condition-variable-and-spurious-wakeup/&quot;&gt;https://jiniya.net/2023/12/condition-variable-and-spurious-wakeup/&lt;/a&gt; @codemaru 님이 씀&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;마치 열역학 제2법칙처럼 세상 많은 일들이 되게 하긴 어려워도 안되게 하긴 쉬운 느낌이 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;[일상] 멍거 옹을 추모하며 &lt;a href=&quot;https://jiniya.net/2023/12/rip-charlie-munger/&quot;&gt;https://jiniya.net/2023/12/rip-charlie-munger/&lt;/a&gt; @codemaru 님이 씀&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;인간이 인간과 일하는 게 제일 힘든 아이러니.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;openai 아무리 잘나가도 그렇지 휴먼 치크 선넘네. 두번 실패하고 좌절감이 ㅋㅋ 뭔놈에 문제를 20개나 다 맞춰야 통과가 되는지 ㄷ ㄷ ㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;[cpp] 오버로딩된 가상 함수 숨김 문제 &lt;a href=&quot;https://jiniya.net/2023/12/hide-overloaded-virtual-function/&quot;&gt;https://jiniya.net/2023/12/hide-overloaded-virtual-function/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;다정함은 인공지능에 무료로 기본 탑재된 것과는 대조적으로 인간에게는 참으로 비싼 기능인 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/mnews/article/214/0001320571?sid=102&quot;&gt;https://n.news.naver.com/mnews/article/214/0001320571?sid=102&lt;/a&gt; 각박한 세상. 따뜻한 뉴스. 위화의 인생을 건냈다는 얘기에서 판사의 진정성이 느껴진다. 인생이란,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-12-25&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 오버로딩된 가상 함수 숨김 문제]]></title><description><![CDATA[다음과 같은 간단한 코드에서 시작해 보자. 순수 가상 클래스인 Base에 Bark란 메소드가 있고, 그걸 상속 받은 순수 가상 클래스인 Derived는 BarkN을 가지고 있다. 이를 상속 받은 Dog은 두 메소드를 구현한다. main에서는 Dog…]]></description><link>https://jiniya.net/2023/12/hide-overloaded-virtual-function/</link><guid isPermaLink="false">https://jiniya.net/2023/12/hide-overloaded-virtual-function/</guid><pubDate>Tue, 12 Dec 2023 15:00:00 GMT</pubDate><content:encoded>&lt;p&gt;다음과 같은 간단한 코드에서 시작해 보자. 순수 가상 클래스인 Base에 Bark란 메소드가 있고, 그걸 상속 받은 순수 가상 클래스인 Derived는 BarkN을 가지고 있다. 이를 상속 받은 Dog은 두 메소드를 구현한다. main에서는 Dog를 할당해서 Derived 포인터를 통해서 Bark와 BarkN을 호출하고 있다. 아무 문제 없는 코드다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Derived&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BarkN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Derived&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Dog Bark\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BarkN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Dog Bark\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Derived &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dog &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; Dog&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	dog&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	dog&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;BarkN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 C++에서 함수를 오버로딩할 수 있다는 것을 알고 있다. 그래서 굳이 BarkN으로 이름을 지을 필요가 없다는 것을 깨달았다. N을 제거하고 다음처럼 Bark로 코드를 고쳐보자. 이제는 컴파일이 되지 않는다. dog-&gt;Bark(); 호출하는 부분에서 그런 함수를 찾을 수 없다고 오류가 발생하는 것이다. 이는 상속 받은 클래스에서 함수를 오버로딩하면 상위 클래스의 메소드가 숨겨지는 문제 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Base&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Derived&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Derived&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Dog Bark\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Dog Bark\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Derived &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dog &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; Dog&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	dog&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	dog&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;문제를 해결하기 위해서는 아래 코드처럼 Derived 클래스에서 상위 클래스의 메소드를 사용하겠다는 것을 명시적으로 표시해주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Derived&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; Base&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Bark&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[일상] 멍거 옹을 추모하며]]></title><description><![CDATA[한국 시간으로 2023년 11월 29일 멍거 옹이 9…]]></description><link>https://jiniya.net/2023/12/rip-charlie-munger/</link><guid isPermaLink="false">https://jiniya.net/2023/12/rip-charlie-munger/</guid><pubDate>Tue, 05 Dec 2023 22:00:00 GMT</pubDate><content:encoded>&lt;p&gt;한국 시간으로 2023년 11월 29일 멍거 옹이 99살의 나이로 타계했다.
찰리 멍거는 본인보다는 버핏의 오른팔로 더 유명하다.
버핏에게 꽁초 투자 보다는 위대한 기업을 적정 가격에 사는 투자가 더 낫다고 알려준 사람으로도 유명하다.&lt;/p&gt;
&lt;p&gt;버핏만큼 멍거 옹도 존경하기에 &quot;찰리 멍거 바이블&quot;이란 책을 읽었지만 이해하기는 쉽지 않았다.
그가 주장하는 격자틀 모형이라는 게 어떤 느낌인지는 알겠지만 그래서 실용적으로 어떻게 하라는 말인지는 모호한 측면이 없잖아 있는 것 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;애널리스트는 현금흐름을 예측하려고 방대한 과거 데이터를 살펴보지만(IQ가 높을수록 더 많은 데이터를 살펴보지만) 시간 낭비에 불과합니다. 진정한 투자는 패리 뮤추얼 베팅에서, 예컨데 확률은 50%인데 배당은 3배인 곳에 돈을 거는 것과 같습니다. 가치투자는 &apos;가격이 잘못 매겨진 도박&apos;을 찾아내는 행위입니다.&lt;br&gt;
&lt;br&gt;
소질이 있는 분야에서 열정을 발휘해야 합니다. 워런이 발레에 열광했다면 우리는 그의 이름을 투자 분야에서 들어보지 못했을 것입니다.&lt;br&gt;
&lt;br&gt;
가끔 다시 90세 시절로 돌아가고 싶은 마음이 간절합니다! 젊은이에게 해주고 싶은 말이 있습니다. 정말로 하고 싶은 일이 있으면 93세가 되기 전에 하세요.&lt;br&gt;
&lt;br&gt;
-- 찰리 멍거 바이블&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;유명인을 따라 매매하지는 않지만 멍거 옹을 워낙 존경했고, 나 또한 생각이 비슷해서 한때 알리바바에 투자했던 기억이 있다.
물론 그를 신격화해서 투자한 건 아니었지만 어쨌든 그를 통해 확증 편향 같은 건 어느 정도 가진 셈이었다.
결과는 대참패였다. 투자금의 절반을 날리고 손절했다.
알리바바는 지금도 손절가를 회복하지 못했다.&lt;/p&gt;
&lt;h3&gt;알리바바 매매썰&lt;/h3&gt;
&lt;p&gt;마윈이 뻘소리를 하면서 공산당 눈에 찍히고, 앤트 그룹 상장이 철회되고, 그의 종적이 묘연하던 그 시기. 알리바바 주가는 떡락했다. 급기야 한국계로 불리는 빌황 사태로 중국 주식인 알리바바의 나락행은 가속화됐다.&lt;/p&gt;
&lt;p&gt;존경해마지 않는 찰리멍거가 알리바바를 줍줍했다는 소식이 들려왔다. 심지어 멍거옹이 사고 알리바바는 더 떨어지고 있었다. 멍거옹보다 싸게 사면 손해는 안보지 않을까라는 아주 나이브한 생각으로 알리바바를 매입했다.&lt;/p&gt;
&lt;p&gt;하지만 추락하는 것은 날개가 없다고 했던가? 주가는 떨어지고 떨어지고 또 떨어졌다. 미중 갈등이 지속되면서 미장에 상장된 adr이 상폐된다는 소식까지 들려왔다. 너무 떨어져서 급기야 홍콩장에서 본주로 물을 타고 또 탔다. 하지만 주가는 계속 나락.&lt;/p&gt;
&lt;p&gt;빅테크 때리기가 과도했다고 판단했는지 경제가 망가지는게 두려웠는데 중국 정부의 빅테크 때리기가 끝이 났다. 마윈이 다시 복귀하고 알리바바 주가에도 잠시 볕이 들었다. 아주 잠시. 그리곤 다시 나락행.&lt;/p&gt;
&lt;p&gt;결국 중국은 투자할 곳이 못된다는 생각이 들었다. 눈물을 머금고 반토막난 주식을 손절했다. 불행중 다행인건 비슷한 시기에 산 엑손모빌 주식에서 난 수익이랑 퉁쳐져서 덜 슬펐다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;매매기록&lt;br&gt;
2021.06 baba $213 매수&lt;br&gt;
2021.09 baba $152 매수&lt;br&gt;
2021.10 HKD 알리바바 $154 매수&lt;br&gt;
2023.03 baba $89 매도&lt;br&gt;
2023.05 HKD 알리바바 $84 매도&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;오늘의 교훈&lt;/h3&gt;
&lt;p&gt;유명한 사람을 따라 매매하는건 나락가는 지름길이다. 정치적으로 안정되지 않은 국가에 투자하는건 돈을 삭제하는 101가지 방법 중 하나라는거,,,&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] condition_variable과 spurious wakeup]]></title><description><![CDATA[소위 모던 C++의 시초라고 할 수 있는 C++11부터 condition_variable이 생겼다.
조건 변수인데 단순하게 말하면 그냥 이벤트를 보내는 거라고 생각하면 된다.
조건 변수를 대기하고(wait…]]></description><link>https://jiniya.net/2023/12/condition-variable-and-spurious-wakeup/</link><guid isPermaLink="false">https://jiniya.net/2023/12/condition-variable-and-spurious-wakeup/</guid><pubDate>Mon, 04 Dec 2023 10:35:00 GMT</pubDate><content:encoded>&lt;p&gt;소위 모던 C++의 시초라고 할 수 있는 C++11부터 condition_variable이 생겼다.
조건 변수인데 단순하게 말하면 그냥 이벤트를 보내는 거라고 생각하면 된다.
조건 변수를 대기하고(wait) 있는 다른 스레드들을 하나만 깨우거나(notify_one), 모두 깨우거나(notify_all)할 수 있다.
아래는 조건 변수의 사용을 보여주는 간단한 예제다. waitThread가 먼저 실행돼서 wait를 호출해서 cv를 대기하고, wakeThread는 1초 후에 notify_one을 호출해서 해당 스레드를 깨운다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;thread&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;mutex&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;condition_variable&gt;&lt;/span&gt;&lt;/span&gt;

std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex mtx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;condition_variable cv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 대기하는 스레드의 함수&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;waitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;unique_lock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wait thread is activated.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 깨우는 스레드의 함수&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;wakeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;this_thread&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep_for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;chrono&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 1초 대기&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;lock_guard&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notify_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wake thread has triggered the condition variable.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;w1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;waitThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wakeThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	w1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	n1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;큰 문제가 없어 보이는 이 예제는 한 가지 문제가 있다. 바로 spurious wakeup이다.
spurious wakeup은 가짜 깨우기란 의미로 notify_one을 호출하지 않았음에도 wait 상태가 풀리는 것을 의미한다.
그래서 실제로 가짜 깨우기가 발생하면 위 예제는 개발자의 의도대로 동작하지 않는다.
그렇다면 문제를 해결하기 위해서는 어떻게 해야 할까?
가짜 깨우기를 제어할 수 있는 별도의 변수를 추가로 두는게 일반적인 방법이다.
다음 예제는 그런 방법을 보여준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;thread&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;mutex&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;condition_variable&gt;&lt;/span&gt;&lt;/span&gt;

std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex mtx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;condition_variable cv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; ready &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 대기하는 스레드의 함수&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;waitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;unique_lock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ready&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wait thread is activated.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 깨우는 스레드의 함수&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;wakeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;this_thread&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep_for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;chrono&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 1초 대기&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;lock_guard&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		ready &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notify_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wake thread has triggered the condition variable.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;w1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;waitThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wakeThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	w1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	n1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;가짜 깨우기를 제어할 수 있는 ready라는 변수가 추가되었다.
ready가 false인 상태에서 깨어나면 가짜 깨우기인 것이고, ready가 true 상태에서 깨어나면 notify_one이 호출됐다고 판단하는 것이다.
실제로 wait함수는 내부적으로 깨어나면 lock을 다시 획득하고, lock을 획득한 상태에서 뒤에 있는 조건 함수를 평가한다.
조건 함수가 참을 반환하면 실제 깨우기라고 판단하고 wait에서 리턴하고, 참이 아니라면 가짜 깨우기라고 생각하고 다시 대기 상태에 들어간다.&lt;/p&gt;
&lt;p&gt;여기까지는 아주 일반적인 상황이다. 조건 변수를 사용하는 스레드가 하나 밖에 없으니 말이다.
main에서 다음과 같이 대기 스레드를 두개를 만들었다고 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;w1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;waitThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;w2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;waitThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wakeThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	w1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	w2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	n1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 상태에서 앞선 ready와 동일한 조건 변수를 사용해서 상태를 관리한다고 하면 어떻게 될지 예측해보자.
대체로 물론 정상 동작한다. 하지만 이 상태에서는 단순 bool 변수만 가지고서는 가짜 깨우기를 구분하기가 어렵다.
왜냐하면 notify_one을 호출한 다음 시점에 임의 스레드가 가짜 깨우기로 일어난다면 그때는 ready 변수가 참이기 때문에 결국 하나만 깨워야 함에도 둘다 깨어나는 문제가 발생할 수 있다.
이 문제를 해결하기 위해서는 조건 체크 함수를 변경할 필요가 있다.
아래 함수는 조건 체크 함수 내에서 ready 변수를 변경해서 두 스레드가 동시에 깨어나는 문제를 해결한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;waitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;unique_lock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ready&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					ready &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wait thread is activated.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그나마 notify_one은 다루기 쉬운 편에 속한다. notify_all로 가면 문제가 더 복잡해진다.
스레드들이 랜덤하게 대기 상태에 들어가고, 정확하게 wait 중인 스레드만 깨우기 위해서는 어떻게 해야 할까?
아래 코드는 그러한 상태를 보여준다.
waitThread는 100개가 생성돼서 랜덤하게 대기 상태에 들어간다.
주 스레드는 모든 스레드가 종료될 때까지 주기적으로 notify_all을 호출한다.
지금 이 코드는 조건 함수가 없기 때문에 무정부 상태나 다름 없다.
어떻게 하면 항상 wait 중이었던 스레드만 모두 깨울 수 있을까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;thread&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;mutex&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;condition_variable&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;vector&gt;&lt;/span&gt;&lt;/span&gt;

std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex mtx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;condition_variable cv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;atomic&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ecount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 대기하는 스레드의 함수&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;waitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; no&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;try wait &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; no &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;unique_lock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wait thread is activated. &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; no &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;ecount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ecount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; num_threads &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; threads&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// 100개의 waitThread 스레드 생성&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; num_threads&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		threads&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emplace_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;waitThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ecount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;lock_guard&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;mutex&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mtx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		cv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notify_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wake thread has triggered the condition variable.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; ecount &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;this_thread&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep_for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;chrono&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;milliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// 모든 스레드가 완료될 때까지 대기&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; th &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		th&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;어쨌든 요는 condition_variable은 spurious wakeup 때문에 복잡한 스레딩 모델에서는 사용할 때 생각보다 많은 주의를 필요로 한다는 점이다. 별 생각 없이 썼다가는 라이브에서 어이 없는 황당한 문제들을 경험할 가능성이 높다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] 페어 프로그래밍에 관한 단상 feat. ChatGPT]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2023/12/dynamic-table-size-with-chat-gpt/</link><guid isPermaLink="false">https://jiniya.net/2023/12/dynamic-table-size-with-chat-gpt/</guid><pubDate>Fri, 01 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;테스트 주도 프로그래밍, 스크럼, 페어 프로그래밍 같은 애자일로 분류되는 많은 방법론들이 있다
좋아하는 것들도 있고 그렇지 않은 것들도 있다. 그중에 특히 극혐하는 것은 스크럼과 페어 프로그래밍이다.
내가 만약 면접 자리에서 궁금한게 없냐는 질문을 받는다면 반드시 물어볼 것이다.
스크럼과 페어 프로그래밍을 하나요? 만약 한다면 강제 사항인가요?
강제 사항이라면 나는 그 회사를 입사하지 않을 생각이다. 그만큼 싫어한다.
일단 스크럼은 차치하고, 오늘은 페어 프로그래밍에 대해서만 알아보자.&lt;/p&gt;
&lt;p&gt;개인적으론 페어 프로그래밍이란 메커니즘이 두 페어가 현재 수행하고 있는 과제에 대해서 비슷한 지적 능력을 가졌을 때
그 효과가 절정에 이른다고 생각한다. 그렇지 않고 차이가 일정 수준 이상 난다면 그건 페어 프로그래밍이라기 보다는
도제식 교육이나 수업에 가까워진다고 생각한다. 물론 그렇지 않다는 수많은 연구 결과가 존재한다는 것은 나도 알고있다.
하지만 연구 결과는 연구 결과고 임상은 임상이니까. 내가 현업에서 느낀 심정은 연구 결과와는 많은 차이가 있었다.&lt;/p&gt;
&lt;p&gt;그렇다면 두 페어의 실력만 비슷하면 시너지가 날까?
그렇지도 않다. 왜냐면 우리는 사람이기 때문이다.
사람이 뭔가? 아 다르고 어 다르게 느끼는 게 사람이다.
심지어 똑같은 아도 그사람 기분이 어떤지에 따라 몹시 다른 결과를 가져오는게 사람이다.
즉, 둘이서 한 모니터를 바라보며 사이좋게 작업을 하기 위해서는 케미라는 아주 미묘한 성질의 것이 또 잘 맞아야 한다는 말이다.&lt;/p&gt;
&lt;p&gt;그렇다면 현실 세계에서 비슷한 지적 능력을 가진 케미가 잘 맞는 파트너를 만나서 페어 프로그래밍을 할 수 있는 확률은 얼마가 될까?
자세히 계산해 보지 않아도 내가 로또에 당첨되는 게 더 빠르다는 생각이다.&lt;/p&gt;
&lt;p&gt;이렇게 설명하면 지적 우위를 가진 사람이 꼭 손해를 보는 느낌인 것 같다.
하지만 내가 현실 세계에서 느낀 페어 프로그래밍은 루즈 루즈 게임인 경우가 많았다.
실력이 좋은 사람은 딱히 페어 프로그래밍으로 얻은 이득은 없다고 느끼고 불편했다는 말을 많이 했다.
그런데 재미있게도 실력이 낮아 보이는 프로그래머도 똑같은 얘기를 하는 경우가 많았다.
이 지점이 도제식 교육과 페어 프로그래밍의 차이인 것이다.
도제식 교육이었다면 아마 배우는 사람은 그나마 그래도 만족했을 것이다.&lt;/p&gt;
&lt;p&gt;무튼 이런 여타의 이유로 나는 페어 프로그래밍을 싫어했다.
뭐, 지금까지는 말이다.
하지만 올해 2월을 기점으로 세상이 바뀌었다.
ChatGPT가 등장한 것이다.
이 친구는 내가 앞서 서술한 페어 프로그래밍의 모든 단점을 단박에 없앤다.
지적 능력은 당연히 나보다 월등하다. 그럼에도 감정이 없고 내가 어떤 쌉소리를 하더라도 화내는 법이 없이 친절하게 알려준다.
그리고 365일 24시간 내내 내가 원할 때 언제든지 나와 함께 코딩할 준비가 돼 있다.
물론 가끔 openai 서버가 다운되긴 한다. 자주 있는 일은 아니니 그럴 땐 쉬면 되겠다.&lt;/p&gt;
&lt;p&gt;ChatGPT와 근 9개월 가량 페어 프로그래밍을 함께 하면서 나는 앞선 단점들만 없으면 페어 프로그래밍이 확실히 효과적이라는 생각이 들 게 되었다.
그래서 이제는 입사 면접 자리에서 나에게 뭐가 궁금한지 물어보면 다음과 같이 물어볼 것 같다.
인공지능 사용이 가능한가요? ChatGPT를 지원해 주나요?&lt;/p&gt;
&lt;p&gt;아래는 블로그의 테이블 셀 크기를 동적으로 변경하는 자바스크립트 코드를 작성하기위한 ChatGPT와의 대화 일부다.
복사해놓고 다시 보니 이건 페어 프로그래밍이라기보다는 코딩 노예를 고용한 것에 가깝지 않냐는 느낌이 약간 들긴 한다.
어쨌든 이러나 저러나 멋진 신세계다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;pair-with-chat-gpt.png&apos; data-alt=&apos;내가 인공지능에게 코딩을 배우는 날이 올거라곤 상상 못했다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3dbc9c541356cb702c94ef8612b5ee25/445c6/pair-with-chat-gpt.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAADHklEQVR42hWS/VOTBQDHnz+ifuw6y37J68UTEIy1NYQEhmO8bg3HNvbiHNtY29j2iGOPDN3GA+PdeWFKgFfQwURNAtOEsNLLH7y8oxftpCju+KXu6ryrzk/rH/h+P/f5foUnPOXR9i84gwE2Hv/EH3//xaOtH7m2lENOHMfhOEJtjYJs0kfEb6YjcBSHvR6LsRKrpQ6z4W18bjP2Vi1thgqEJ/zL5s42PjHC4+1t/i/Y+X2HpU8vMZntZyh5HL22FLtVy8JMholMhPGUn4QUIhy0E3Q30xWyYX6nEpepCuGrBxt8srqGuf0Y619/wc9bP3D9xiK6plomRtN4/S5U1eWUHFTwuqKY01EzNxcGWVlbITOcwu1oJB5qwdhUgV73BsKf/MPD3zbxRsPc/+5BnjRAe8hLh9fKMa+H4jJ1PqiQZ3fvYv+hSuJSgFvLEyzkpuiNuTA0qnDnFfTHHVyQ3QhPgYe/buII+li/9yX7K9Ss3rnD3LVlmmztBDq92P0O2jxt1LboOdXrY3w0TjwzzNBIGn1DWZ6ujHjYQqLTiCCmZEJSD8keD/OTCT67fI6bMyexuZ2MpMOsTce4elHm7q2PyU2l8uOYmM2GOXv+HFI8SF1DNYVFL9PZYcJpUCEk0u+RTg4wcDLCfDbJ7FgXiwkN5noFnjyVVqPE0axk7pSR8YiOiLOamfFu5nNzDA33oSx9jZLSfRyqVtMTdSH4RJmI2ENnKMzsB+/jbXfS79dQXrSLvQolL71ZiaJoN0m7As3BAjSqPchddhY/GsPVWEpVeQFS0Ijm8Fs4LQ0I6iYXWr0Vq62VM3L+EnEnQ7GjnBatSPkB5L4YW5+n2bmbZSmv4oxYw+2lC1ycHCIZamaq+zBXx2wMdGqIHtmH0KDVEPHYsegOYCx7kbFkkA+nBumNtyMlJMZGM8xn3FwZaCMr1jMoNrG2usylG+v0xRysyDV8c97Et9Mmvp82IFy/fZ97G1tcmZsl4W2lp0tE7vaRG3GRelfH2RMGJKsSqaWAaMOrtGmLiUU6EE90oy55BdWeZ6gqfI66A89jUr/Af5JJIkHCBa4UAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;내가 인공지능에게 코딩을 배우는 날이 올거라곤 상상 못했다.&apos; title=&apos;&apos; src=&apos;/static/3dbc9c541356cb702c94ef8612b5ee25/efd7b/pair-with-chat-gpt.png&apos; srcset=&apos;/static/3dbc9c541356cb702c94ef8612b5ee25/08678/pair-with-chat-gpt.png 190w,
/static/3dbc9c541356cb702c94ef8612b5ee25/2edd7/pair-with-chat-gpt.png 380w,
/static/3dbc9c541356cb702c94ef8612b5ee25/efd7b/pair-with-chat-gpt.png 760w,
/static/3dbc9c541356cb702c94ef8612b5ee25/dc896/pair-with-chat-gpt.png 1140w,
/static/3dbc9c541356cb702c94ef8612b5ee25/78873/pair-with-chat-gpt.png 1520w,
/static/3dbc9c541356cb702c94ef8612b5ee25/445c6/pair-with-chat-gpt.png 1792w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;내가 인공지능에게 코딩을 배우는 날이 올거라곤 상상 못했다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;ChatGPT와의 페어 프로그래밍이라 쓰고 코딩 시키기&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
gatsby 블로그 마크다운에서 테이블 셀 크기가 3개가 있는데 처음 두개는 너무 작고, 나머지 하나가 너무 커. 적당하게 나눠서 표시되게 만드려면 어떻게 해야 해?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
Gatsby 블로그에서 Markdown 테이블의 셀 크기를 조정하려면 몇 가지 방법을 시도할 수 있습니다. Markdown 자체에는 셀 크기를 직접 조정하는 기능이 없으므로, CSS를 사용하여 스타일을 적용하는 방법이 가장 일반적입니다. 다음은 몇 가지 방법을 소개합니다:&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Inline 스타일&lt;/li&gt;
&lt;li&gt;자바스크립트 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
셀 내용에 따라 다이나믹하게 설정할 수는 없어?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
셀 내용에 따라 테이블 셀 크기를 동적으로 조정하려면 JavaScript를 사용하는 것이 가장 효과적입니다. CSS와 Markdown만으로는 셀의 내용에 반응하여 크기를 조정하는 것이 불가능합니다. JavaScript를 사용하면 셀 내용을 읽고, 그 내용에 따라 적절한 크기를 동적으로 할당할 수 있습니다.&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.my-table&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 대상 테이블 선택&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; rows&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; cell &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; cells&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 셀의 내용 길이에 따라 셀 크기 조정&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contentLength &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;20%&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contentLength &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;30%&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;50%&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
그렇게 하는 거 보다는 각 칼럼의 가장 긴 길이를 각각 구해서 해당 비율로 크기를 설정하는 것이 좋을 거 같아. 그렇게 수정해줘&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
셀 내용에 따라 테이블 셀의 크기를 동적으로 조정하기 위해, 각 칼럼의 가장 긴 셀의 내용을 기준으로 크기를 결정하는 접근 방법을 사용할 수 있습니다. 이 방법은 JavaScript를 사용하여 구현할 수 있으며, 다음 단계로 구성됩니다:&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.my-table&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 대상 테이블 선택&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; maxContentLengths &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 각 칼럼의 최대 길이 계산&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; rows&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 전체 최대 길이 계산&lt;/span&gt;
  totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 각 칼럼에 비율에 따른 너비 설정&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; rows&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; widthPercentage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; totalMaxLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;widthPercentage&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
cells.forEach is not a function 오류가 발생해&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
cells.forEach is not a function 오류가 발생하는 이유는 getElementsByTagName 메서드가 반환하는 HTMLCollection 객체가 Array가 아니기 때문에 forEach 메서드를 지원하지 않기 때문입니다. 이 문제를 해결하기 위해, Array.from 메서드를 사용하여 HTMLCollection을 배열로 변환하거나, 전통적인 for 루프를 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.my-table&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; maxContentLengths &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 각 칼럼의 최대 길이 계산&lt;/span&gt;
  rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 전체 최대 길이 계산&lt;/span&gt;
  totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 각 칼럼에 비율에 따른 너비 설정&lt;/span&gt;
  rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; widthPercentage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; totalMaxLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;widthPercentage&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
table 이 하나도 없는 경우에 예외 처리해줘&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
테이블이 없는 경우에 대한 예외 처리를 추가하려면, 먼저 테이블 요소의 존재 여부를 확인하는 로직을 추가해야 합니다. 이를 위해 document.querySelector로 선택한 테이블 요소가 null인지 확인하는 간단한 조건문을 사용할 수 있습니다. 테이블이 존재하지 않는 경우, 함수의 실행을 중단하거나 적절한 메시지를 표시하도록 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
table에 tr이나 td가 하나도 없는 경우도 예외 처리가 필요할 거 같아.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
테이블에 tr이나 td 요소가 하나도 없는 경우에 대한 예외 처리를 추가하는 것은 좋은 접근입니다. 이를 위해서는 tr 요소의 배열이 비어있는지, 그리고 각 tr 내의 td 요소가 존재하는지를 확인하는 조건문을 추가해야 합니다. tr이나 td 요소가 없는 경우에는 함수의 실행을 중단하거나 적절한 경고 메시지를 표시할 수 있습니다.&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
Array.from(null);은 정의돼 있어?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
Array.from(null)은 정의되어 있지 않습니다. Array.from 함수는 유사 배열 객체나 반복 가능한 객체를 새로운 배열 인스턴스로 만드는 메서드입니다. 그러나 null은 반복 가능한 객체가 아니기 때문에 Array.from(null)을 사용하려고 하면 오류가 발생합니다.&lt;/p&gt;
&lt;p&gt;따라서 Array.from을 사용하기 전에 반드시 해당 객체가 null이 아닌지 확인해야 합니다. 예를 들어, document.getElementsByTagName나 document.querySelectorAll과 같은 DOM 메서드가 비어있는 NodeList를 반환할 경우, 이를 배열로 변환하기 전에 null 여부를 검사해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
그렇게 수정해서 함수 새로 작성해줘&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
앞서 논의한 내용을 바탕으로, 테이블에 tr이나 td가 없는 경우에 대한 예외 처리를 포함한 새로운 JavaScript 함수를 작성하겠습니다. 이 함수는 테이블이 존재하고, 적어도 하나의 tr과 td가 있는 경우에만 셀 크기 조정 로직을 실행합니다.&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
비율이 너무 낮은 셀이 나오면 문제가 될 거 같아서 최소 15% 이상은 보장되도록 코드를 수정해줘&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
셀의 너비 비율이 너무 낮아지지 않도록 최소 15% 이상의 너비를 보장하는 로직을 추가하겠습니다. 이를 위해 각 셀의 계산된 비율을 검사하고, 만약 그 비율이 15% 미만인 경우 15%로 조정하는 로직을 추가합니다. 또한, 이러한 조정으로 인해 총 너비 합계가 100%를 초과하지 않도록 전체 너비의 합을 다시 계산해야 합니다.&lt;/p&gt;
&lt;p&gt;다음은 수정된 코드입니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.my-table&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;테이블이 존재하지 않습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;테이블에 행이 없습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; maxContentLengths &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; isCellPresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      isCellPresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isCellPresent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;테이블의 행에 셀이 없습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; widthPercentages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; totalMaxLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; adjustedPercentages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; widthPercentages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; adjustedTotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; adjustedPercentages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; adjustedWidth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;adjustedPercentages&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; adjustedTotal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;adjustedWidth&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
그런데 저렇게 작성했다고 하면 예를 들어 칼럼이 세개고 비율이 5, 5, 90이었는데 조정을 해서 15, 15, 90이 되었다고 한다면 최종적으로 첫번째 칼럼은 15 / 120이 되서 12.5%가 되니까 원래 요구했던 15%보다 작게 설정되는 거 아냐?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;br&gt;
맞습니다. 코드에서 조정된 비율이 15%, 15%, 90%로 변경된 경우, 총합이 120%가 되어 각 비율을 다시 조정할 때, 원래 의도했던 최소 15% 비율이 보장되지 않을 수 있습니다. 이 문제를 해결하기 위해, 조정된 비율의 합이 100%를 초과할 경우에 대한 추가적인 처리가 필요합니다.&lt;/p&gt;
&lt;p&gt;비율을 조정하는 과정에서, 각 칼럼의 비율이 최소 15%가 되도록 하면서도 전체 합이 100%를 넘지 않도록 조정하는 방법은 다음과 같습니다:&lt;/p&gt;
&lt;p&gt;먼저, 모든 칼럼의 비율을 계산합니다.
15% 미만인 칼럼의 비율을 15%로 조정합니다.
조정 후 총합이 100%를 넘는 경우, 15% 이상인 칼럼들의 비율을 적절히 감소시켜 총합이 100%가 되도록 합니다.
이 과정은 비교적 복잡할 수 있으며, 특히 칼럼의 수나 비율에 따라 다양한 시나리오를 고려해야 할 수 있습니다. 간단한 해결책으로, 모든 칼럼이 최소한 15%를 차지할 수 있도록 고정된 비율을 설정하거나, 동적으로 비율을 조정하는 더 복잡한 알고리즘을 구현할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;&lt;br&gt;
말로 하지 말고 그렇게 코드를 작성해줘&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;... 중략 ...&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.my-table&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;테이블이 존재하지 않습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;테이블에 행이 없습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; maxContentLengths &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; isCellPresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      isCellPresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isCellPresent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;테이블의 행에 셀이 없습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  totalMaxLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; widthPercentages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxContentLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; totalMaxLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; adjustedPercentages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; widthPercentages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; adjustedTotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; adjustedPercentages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 총합이 100%를 초과하는 경우, 초과분을 줄이는 로직&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;adjustedTotal &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; excess &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; adjustedTotal &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    adjustedPercentages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; adjustedPercentages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; excess &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; decrease &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; excess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        excess &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; decrease&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; width &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; decrease&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cells &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cells&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      cell&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;adjustedPercentages&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 11월의 잡담]]></title><description><![CDATA[#0 hwp…]]></description><link>https://jiniya.net/2023/11/small-talk-2023-11/</link><guid isPermaLink="false">https://jiniya.net/2023/11/small-talk-2023-11/</guid><pubDate>Thu, 30 Nov 2023 17:36:00 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;hwp 노션 이력서 안본다는 사람들이 많은데 굳이 구직자가 해당 포맷을 쓰겠다는 건 구직 의사가 낮은게 아닌가 싶다. 속도보다 방향이 중요하다는 말처럼 노오오력도 어느 방향으로 투자했냐가 중요한거 아닌가 싶다. 마치 시험에 미적분 안나온다고 했는데 미적분 공부하는 느낌이랄까?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;인생은 채워지지 않은 욕망으로 인해 느끼는 고통과, 욕망의 충족 이후에 들어서는 권태 사이를 오락가락하다가 죽음으로 끝나는 것에 불과하다.  - 사는 게 고통일 때, 쇼펜하우어&lt;/p&gt;
&lt;p&gt;괜히 철학자가 아니다. 이토록 간단 명료하고 반박 불가능한 인생에 대한 정의라뉘. 고통과 권태 사이를 오가는 시계추라...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;구글, 깃헙에 이어 어느새 chatgpt가 꺼지면 코딩하기 불편한 세상.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;인공지능을 지원해 주는게 복지가 아닌 생산성 향상에 몹시 높은 기여를 하겠단 생각에 설문 조사를 해봤다. 미사용62.5%, 가끔무료25%, 가끔유료12.5% 결과를 보고 앞서 나갔다는 생각이 들었다. 괜한 돈낭비를 할 뻔. 좋은 것도 알아야 쓴다는 생각이. 이 좋을 걸, 뭐라 할 말이 ㅠㅜ&lt;/p&gt;
&lt;p&gt;아껴뒀다 코파일럿 엔터프라이즈 출시하면 혼자서라도 써야겠다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;쓰거나 말거나 인공지능의 내부 사용을 장려하는 규정을 공유했다. 코파일럿 15개월, 챗지피티 9개월 가량 쓰고 난 느낌. 인공지능 없이 개발한다는 건 돌도끼 들고 개발하는거랑 거의 같지 않나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;20년 이상 생존하는 소프트웨어 기업은 1000개 중 3개  정도. 신기한건 15년쯤 생존했으면  20년은 문안할 거 같은데 16-20년 사이에 15년 동안 잘 살아남은 기업 10개중 9개가 망한다. 살아남기가 이렿게 어렵다. 중소기업은 후 불면 망한다는 얘기가 실감남.  &lt;a href=&quot;https://m.etnews.com/20180309000253&quot;&gt;https://m.etnews.com/20180309000253&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;반전에 반전에 반전. 기승전 ms인가?! &lt;a href=&quot;https://x.com/satyanadella/status/1726509045803336122&quot;&gt;https://x.com/satyanadella/status/1726509045803336122&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;chatgpt도 역대급이었지만 흘러가는 스토리도 역대급인 openai. 작가가 이런 스토리를 썼다면 개연성없고 작위적이라고 욕 먹었을것 같은데, 영화보다 더 영화같은 현실 세계 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;이런 이야기를 좋아한다. 크래프톤 웨이, 유난한 도전,   스타트업은 어떻게 유니콘이 되는가, 쇼스토퍼, 드리밍 인 코드, 둠도 추천,, &lt;a href=&quot;https://x.com/BenjaminKim_/status/1727533625019945154&quot;&gt;https://x.com/BenjaminKim_/status/1727533625019945154&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;챗지피티 시대에 닝겐들끼리 한심하게 급나누기 하는거 보면 좀 웃김. 그래봐야 도토리 키재기 아닌가 싶은뎅.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;정말 좋음. 강추 !! &lt;a href=&quot;https://x.com/hasherezade/status/1728879156564504754&quot;&gt;https://x.com/hasherezade/status/1728879156564504754&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;마이크로소프트가 루프라는 유사 노션 서비스를 만들었데서 써봤는데. 뭐하자는건지 모르겠다. 딴 건 모르겠고 로딩이 겁나 느림. 노션도 느린데 얜 더느린. 팀즈부터 좀 똑바로 만들어주면 좋겠다. 안되면 디스코드라도 사든가 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;#cloudflare pages 수동 베포 방법 &lt;a href=&quot;https://jiniya.net/2023/11/cloudflare-pages-manual-deploy/&quot;&gt;https://jiniya.net/2023/11/cloudflare-pages-manual-deploy/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;[cs] msbuil로 C# 프로젝트 빌드 시 project.assets.json 오류 해결 방법 &lt;a href=&quot;https://jiniya.net/2023/11/nuget-json-asset-error/&quot;&gt;https://jiniya.net/2023/11/nuget-json-asset-error/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-30&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;어제는 멍거옹 타계 소식이 들리더니, 오늘은 헨리 키신저 타계 소식이. 100이란 숫자는 뭔가 마의 벽같은 느낌. &lt;a href=&quot;https://n.news.naver.com/mnews/article/008/0004968547&quot;&gt;https://n.news.naver.com/mnews/article/008/0004968547&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-11-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cs] msbuil로 C# 프로젝트 빌드 시 project.assets.json 오류 해결 방법]]></title><description><![CDATA[우리는 대략 이런 커맨드로 msbuild를 사용하고 있었다.
project.sln에는 다수의 프로젝트가 포함되어 있고, cslib 그 중에 하나인 c# 프로젝트였다.
그런데 이상한게 Visual Studio…]]></description><link>https://jiniya.net/2023/11/nuget-json-asset-error/</link><guid isPermaLink="false">https://jiniya.net/2023/11/nuget-json-asset-error/</guid><pubDate>Thu, 30 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;msbuild project.sln -m -t &quot;cslib&quot; -p:Configuration=Release -p:Arch=AnyCPU&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 대략 이런 커맨드로 msbuild를 사용하고 있었다.
project.sln에는 다수의 프로젝트가 포함되어 있고, cslib 그 중에 하나인 c# 프로젝트였다.
그런데 이상한게 Visual Studio에서 빌드하면 멀쩡하게 빌드가 잘되는데 msbuild로만 실행하면 project.assets.json 파일이 없다며 오류가 발생했다.&lt;/p&gt;
&lt;p&gt;첫번째 문제는 경로였다. 우리는 프로젝트의 중간 파일과 출력 파일을 다른 경로로 지정해놓고 사용했는데 nuget이 생성하는 project.assets.json 파일은 그 경로가 아닌 디폴트 경로를 참조하는 것 같았다. 이를 해결하기 위해서는 cslib 프로젝트 파일이 있는 경로에 Directory.Build.props 파일을 생성한 다음 아래와 같이 설정해 주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PropertyGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;BaseIntermediateOutputPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;경로&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;BaseIntermediateOutputPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;PropertyGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;경로에는 C# 프로젝트에서 설정한 것과 동일한 중간 파일 경로를 입력하면 된다. $(SolutionDir) 같은 변수도 지원하기 때문에 그대로 사용하면 된다.&lt;/p&gt;
&lt;p&gt;이제는 잘 되겠지?! 하고는 했는데 여전히 되지 않았다. 온갖 오류 메시지를 하나씩 추적하면서 수정하는 온갖 삽질을 ChatGPT와 함께하고 알게 되었다. project.sln 파일이 AnyCPU에 대해서 정상적으로 설정돼 있지 않으면 nuget이 project.assets.json 파일을 생성을 못한다. 예를들어 포함된 test 프로젝트가 AnyCPU에 대해서 빌드 설정이 체크되어 있지 않으면 생성이 되지 않는 식이다. 또는 솔루션 파일에 포함된 구성 요소 프로젝트가 없어도 생성이 되지 않는다. 이런 모든 원리를 살펴보면 위 커맨드를 수행할 때 아래 커맨드가 먼저 수행되는 것으로 보여진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;msbuild project.sln -t &quot;restore&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 솔루션 전체를 복원하는 것이다. 나는 cslib만 빌드하고 싶을 뿐인데 말이다. 그래서 ChatGPT와 함께 열심히 찾아 보았지만 개별 프로젝트를 복원하는 방법은 없어 보였다. 그렇다면 어쩌지?! 솔루션을 멀쩡하게 만들어야 하나? 그러기엔 외부 참조가 많아서 빌드서버에서 clone해야 할게 너무 많아지는 문제가 있었다. ChatGPT는 다음과 같은 방법을 나에게 대안으로 알려주었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;msbuild cslib.csproj -m -t &quot;restore,rebuilt&quot; -p:Configuration=Release -p:Arch=AnyCPU&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;오 역시 ChatGPT. 바로 이거였어, 하고는 테스트를 했는데 한가지 추가적인 문제가 있었다. $(SolutionDir)이었다. 이는 프로젝트 파일을 직접 참조하기 때문에 $(SolutionDir)이 정의되지 않은 상태인 것이다. 다시 ChatGPT를 독촉하자. 완벽한 커맨드를 알려주었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;msbuild cslib.csproj -m -t &quot;restore,rebuilt&quot; -p:Configuration=Release -p:Arch=AnyCPU -p:SolutionDir=path/to/solution&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;얼마간 삽질했지만 정상적으로 빌드되도록 만들 수 있었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] CloudFlare Pages 수동 배포 방법]]></title><description><![CDATA[CloudFlare Pages를 자동 배포가 먹통이라 수동으로 배포해야 할 때는 아래 명령어를 사용하면 된다. <account_id>는 cloudflare pages 화면의 아래 빨간 네모로 표시된 위치에 값이 있다.  <worker_name…]]></description><link>https://jiniya.net/2023/11/cloudflare-pages-manual-deploy/</link><guid isPermaLink="false">https://jiniya.net/2023/11/cloudflare-pages-manual-deploy/</guid><pubDate>Wed, 29 Nov 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;CloudFlare Pages를 자동 배포가 먹통이라 수동으로 배포해야 할 때는 아래 명령어를 사용하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; POST &lt;span class=&quot;token string&quot;&gt;&quot;https://api.cloudflare.com/client/v4/accounts/&amp;lt;account_id&gt;/pages/projects/&amp;lt;worker_name&gt;/deployments&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;token parameter variable&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Authorization: Bearer &amp;lt;token&gt;&quot;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;token parameter variable&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type:application/json&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;account_id&gt;는 cloudflare pages 화면의 아래 빨간 네모로 표시된 위치에 값이 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 705px; margin-bottom: 16px;&apos; data-url=&apos;cf.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5f147edcc104fc56bb7b86ee639e0d7d/f8d10/cf.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 46.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABhklEQVR42m1SSXIUMRDUm7jwJLjwDiI48wYieAanuWIwbhPgjV4tqVvqdXpRd5LS2OAZuyIytJVKmakS27bhKXyM4whb1zDGhHnXdZBSYhgGzPOEqqzQtl0407pE1w9h7fPFUUEWW/24rlhP4Jw7Wj/GgcThvt8X1liUVYmKUFofJf+/BDhuL+7wqGcc/4mRJAnSNMGvrIdpp5ArLi8jfD37hiiKsNvtSNs+efnl8NK1UmiallJbaNPDNl1QJhQP4jhBnudEwYIVhp4JtkbDZDcNuNbAu8/A20/Axy9kSx99MV/4VJFom5rGKhhK1koiKxSkNrSgglS0YO5wlgKvPwCv3gNvWHRbFyiel1TjWOQRXpO41w1ukhK3aYW0KHEVl7i4azBM6z+zT2Ohh71U6KkujER3LzGyM0RhFlwVI35ne+SchxYhQ1u3wZNnMc+Yflygv73DzI9xaRawZjnc9Q3Enr00zQu92A4t8/D9Hi9+DPP30U/01mImI0cCGz1v2CHy+zn+AidtslOoGo44AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;cf&apos; title=&apos;&apos; src=&apos;/static/5f147edcc104fc56bb7b86ee639e0d7d/f8d10/cf.png&apos; srcset=&apos;/static/5f147edcc104fc56bb7b86ee639e0d7d/08678/cf.png 190w,
/static/5f147edcc104fc56bb7b86ee639e0d7d/2edd7/cf.png 380w,
/static/5f147edcc104fc56bb7b86ee639e0d7d/f8d10/cf.png 705w&apos; sizes=&apos;(max-width: 705px) 100vw, 705px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;worker_name&gt;은 자신의 페이지 프로젝트 이름을 입력하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;token&gt;은 발급받은 api 토큰을 넣어주면 된다.&lt;/p&gt;
&lt;p&gt;호출에 성공하면 대시보드에서 빌드가 진행되는 것을 볼 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] jiniya.net 리마스터링]]></title><description><![CDATA[#0 2…]]></description><link>https://jiniya.net/2023/11/jiniya-net-remastering/</link><guid isPermaLink="false">https://jiniya.net/2023/11/jiniya-net-remastering/</guid><pubDate>Tue, 28 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/X-yIEMduRXk?si=wE2rXepkhoypd77z&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;20대 어느 날 중고등학생 때 썼던 일기장을 모두 버린 기억이 있다.
본가에 두고 온 일기장을 누나가 읽었다며 놀린 게 계기가 되었다.
그 얘길 듣고 그걸 전부 자취방으로 가지고 왔었다.
내가 다시 읽어봐도 워낙 오글거려서 그날로 다 버렸다.
그때는 몰랐다. 데이터가 얼마나 소중한지.
그 글들이 내가 유일하게 추억할 수 있는 그 시절 나의 생생한 모습이란 사실도 말이다.&lt;/p&gt;
&lt;p&gt;일기장을 버린지 근 20년이 되어간다.
가끔 그때 버린 일기장이 기억날 때가 있다.
오글거리긴 해도 가끔 그시절 내가 어떤 생각을 했고, 어떤 고민을 했는지가 궁금할때가 있는 것이다.
물론 나이가 들어서일수도 있다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;올해 이글루란 블로그 서비스가 문을 닫는다는 소식이 들렸다.
어렸을 때 그곳에 적잖게 글을 썼던지라 들어가 보았다.
2004-5년 학생 시절에 쓴 글들이 많이 있었다.
웃기기도 하고, 이렇게 살았구나 싶기도 했다.
같은 실수를 두번하지 않기 위해서 이번에는 데이터가 삭제되기 전에 모두 백업을 했다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;이 블로그를 시작할 때만해도 내가 이걸 8000일이 넘는 시간동안 운영하게 될 거라곤 생각하지 못했다.
다만 조금 아쉬운 점은 자작 게시판, phpBB, 태터툴즈, 워드프레스, 지킬을 거치면서 얼마간은 데이터가 유실되었다는 점이다.
예전엔 데이터가 소중한지도 몰랐었고, 나중에 그게 아쉬울지도 몰랐다.
어쨌든 그런 일들을 겪고 보니 이제라도 한번 전체를 다시 재정비를 해야겠다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;기존에 파편화되어 있던 글들을 한곳에 다 모으기로 했다.
대체로 모을 수 있는 모든 글들을 모았다.
그리고 그렇게 모은 글들은 다시 다듬었다.
소위 블로그 리마스터링이라고 부를만한 작업을 했다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;작업을 하기에 앞서서 gatsby 템플릿을 변경할 필요가 있었다.
기존 템플릿이 너무 단촐해서 글을 너무 많이 담기에는 다소 무리가 있어 보였다.
여기저기 구경하던 중 &lt;a href=&quot;https://hudi.blog&quot;&gt;hudi 님께서 만든 템플릿이&lt;/a&gt; 좋아 보였다.
디자인도 멋지고, 반응형에, 태그와 시리즈를 지원하는 멋진 템플릿이었다.&lt;/p&gt;
&lt;p&gt;템플릿을 교체하는 과정도 순탄하지만은 않았다.
gatsby에 g도 모르는 입장이라 오류가 발생하면 뭐가 문제인지도 몰랐으나 오류 메시지를 복붙하면 대체로 ChatGPT가 다 해결해 주었다.&lt;/p&gt;
&lt;p&gt;기존 글들을 정리하면서 느낀 가장 큰 재앙은 오래된 글에 있는 링크는 거의 모두 사라졌거나 동작하지 않는다는 사실이었다.
퍼가는 사람들이 왜그럴까 했는데 이해가 되는 지점이었다.
그래서 나는 대체로 기존 링크를 유지할 수 있으면 유지하기로 결정했다.
이 기능도 템플릿을 고쳐서 가능했는데 gatsby의 유연한 시스템과 ChatGPT의 어시스트로 가능했다.
어쨌든 기본적인 프레임워크는 다 준비된 것 같아서 이제 글을 옮기기로 했다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;시작은 최근 데이터부터 시작했다.
단순 무식하게 카피앤페이스트로 지킬의 데이터를 다 옮겼다.
이것도 수작업으로 하니 생각보다 힘든 작업이었다.
그리고 남은 글들을 보았다. 워드프레스와 태터툴즈만 합쳐도 1000개가 넘는 글이 남아 있었다.
와 이거 노답인데 하는 생각도 순간, 나에게는 ChatGPT가 있었다.&lt;/p&gt;
&lt;p&gt;자동으로 긁어서 마크다운으로 변환해서 파일로 저장하는 스크립트를 작성하라고 시켰다.
ChatGPT는 나를 실망시키는 법이 없다.
녀석이 작성해준 코드는 기가 막히게 동작했고, 나는 제로 콜라 하나를 다 마시는 동안 모든 페이지가 마크다운으로 변환되는 기적을 맛보았다.&lt;/p&gt;
&lt;p&gt;그러고 나니 텍스트는 거의 다 저장되었는데 페이지에 포함된 이미지가 문제였다.
다시 ChatGPT에게 물었다. 녀석은 마크다운으로 변환하는 페이지에 포함된 이미지까지 모두 다운로드 받아서 저장해주는 스크립트를 안겨주었다.
올레~&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;물론 23년 가까이 쓴 글들은 지금 돌아보면 우습고 부끄럽고 이불킥하고 싶은 글들이 많다.
하지만 그런 것들도 다 나의 일부라 생각하고, 추억이기에 보존하기로 했다.&lt;/p&gt;
&lt;p&gt;그렇게 모아진 글들만 1200개가 넘는다.
없애지 않고 지금까지 잘 보존해준 과거의 나에게 감사함을 표한다.
그덕에 나는 &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/&quot;&gt;존경해 마지 않는 레이몬드 첸 아저씨&lt;/a&gt;보다 블로그를 오래한 몇 안되는 프로그래머 중에 한 명이 되었다.&lt;/p&gt;
&lt;h3&gt;#6&lt;/h3&gt;
&lt;p&gt;나는 더는 스타크래프트를 즐기지 않고, 와우를 미친 듯이 하지 않는다.
킹 오브 파이터즈를 하러 오락실을 찾지도 않고, 무한도전이나 러닝맨 같은 예능을 즐겨 보지도 않는다.
일요일 밤을 마감하는 웃찾사나 개그콘서트같은 개그 프로를 안 본지도 오래됐다.
과자를 자주 먹지도 않는다.&lt;/p&gt;
&lt;p&gt;긴 세월 만큼이나 나란 사람도 정말 많이 변했다.
하지만 그렇게 많은 세월이 지났어도 나는 여전히 여기에 글을 쓴다.
어쩌면 이게 내가 코딩을 제외하고 본질적으로 거의 유일하게 좋아하는 일인지도 모르겠다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;주춤했던 최근을 넘어서 앞으로는 그래도 종종 글을 남기겠다는 다짐을 해본다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 10월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2023/10/small-talk-2023-10/</link><guid isPermaLink="false">https://jiniya.net/2023/10/small-talk-2023-10/</guid><pubDate>Fri, 20 Oct 2023 22:45:55 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;학교 졸업장, 기업의 사원증 같은 것은 이제 성취 인증 시스템에서 구시대적 유물로 통할 날이 머지않았습니다. 검증된 깃허브의 스코어나 블로그의 구독자, 인스타그램의 달리기 기록처럼 ‘측정된 권위’를 쌓아가는 것이 필요합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;시대예보: 핵개인의 시대 중에서&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2023-10-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;집에 pc를 새로 사고 온갖 설정을 바꿔도 마우스 랙이 있어서 뭔가 했더니 케이블 문제. 노트북 연결해서 쓸때는 디피였는데, pc로 바꾸면서 hdmi를 쓴 게 문제였다. 케이블 하나 갈았더니 랙이 사라졌다. 30/60차이도 이정도면 144hz는 어떤 느낌인 것인가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-10-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;인공지능은 예술을 하고 사람은 청소나 빨래같은 노동이나 하는 세상이 아니라 모든 사람이 화가, 작가, 작곡가, 프로그래머가 되는 세상이 온 게 아닌가 싶다. 탐라에 돌아다니는 4컷 만화들만 봐도 이를 알 수 있다. 단돈 20불에 이 모든게 가능한 세상이라뉘 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-10-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;남들보다 잘하는 건 고사하고 남들만큼 하는 거도 참 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-10-20&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 9월의 잡담]]></title><description><![CDATA[#0 게임 보안 솔루션 개발, ,c++/rust 시스템 프로그래머 모집합니다. https://m.jobkorea.co.kr/Recruit/GI_Read/42833706 2023-09-08 #…]]></description><link>https://jiniya.net/2023/09/small-talk-2023-09/</link><guid isPermaLink="false">https://jiniya.net/2023/09/small-talk-2023-09/</guid><pubDate>Mon, 18 Sep 2023 11:06:51 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;게임 보안 솔루션 개발, ,c++/rust 시스템 프로그래머 모집합니다. &lt;a href=&quot;https://m.jobkorea.co.kr/Recruit/GI_Read/42833706&quot;&gt;https://m.jobkorea.co.kr/Recruit/GI_Read/42833706&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-09-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;지인이 신세계 상품권을 줬는데 쓸때가 없어서 고가의 뱅앤올룹슨 무선 이어폰을 사고 나서 알았다. 1) 블투는 음향기기가 아니라 소프트웨어. 페어링 잘 안되고, 된다음에도 겁나 튐. 노캔은 말해뭐해. 2) 걍 에어팟 맥스 살걸 3) 신세계 상품권 따위보단 쿠팡캐시가 훨씬 유용한 세상이 됐다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-09-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;난 유니티가 게임 외주 개발을 한다는 소릴 듣고 어렵구나 했는데, 작금의 사태를 보자니 더 어려운거 같다는 생각이. 하스스톤같은 카드 게임을 유니티가 직접 만든게 많다고 한다. 실제로 하스스톤도 블리자드 외주로 유니티가 개발했다는 썰이. 킹비디아 말고는 다들 힘든 계절인듴...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-09-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;대단한 개발자가 아니라도 충분히 잘 먹고 잘 살 수 있다. 시장이 그만큼 커졌기 때문이다. 그래서 직업인 개발자도 나쁘게 생각하지 않는다. 자기 밥값만 한다면 뭔들. 어느 직업이든 좋아하면서 잘하는건 디폴트가 아니라 굉장한 행운이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-09-18&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 7월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2023/07/small-talk-2023-07/</link><guid isPermaLink="false">https://jiniya.net/2023/07/small-talk-2023-07/</guid><pubDate>Sat, 29 Jul 2023 10:31:05 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;행복에 절대적인 영향을 미치지만, 대부분이 미처 생각지 않는 요인에 대해 살펴보려 한다. 어떤 것이 그렇게 중요할까? 오랫동안 행복을 연구한 석학들을 한 자리에 모아놓고 그 질문을 한다면 대답은 거의 비슷할 것이다.&lt;br&gt;
“유전. 더 구체적으로는 외향성.” - &amp;#x3C;행복의 기원&gt;, 서은국&lt;/p&gt;
&lt;p&gt;학계의 정설 중 일반인들에게 가장 덜 알려진 사실이 바로 행복과 유전의 관계다. DNA가 행복을 완전히 결정한다는 뜻은 물론 아니다. 학자에 따라 다소 의견이 다른 통계적 수치지만, 학계의 통상적인 견해는 행복 개인차의 약 50%가 유전과 관련이 있다고 본다. - &amp;#x3C;행복의 기원&gt;, 서은국&lt;/p&gt;
&lt;p&gt;여름 베짱이를 한심하게 생각하도록 세뇌받고 살았다. 두 가지 염려 때문에. 첫째, 쾌락주의자들의 즐거움은 저급하다. 둘째, 그런 삶의 말로는 한심할 것이다. 둘 다 근거 없는 염려다. 세상 모든 베짱이들이 루저가 된다는 증거는 없다. 수많은 최근 연구들에서 나오는 결론은 오히려 그 반대다.&lt;/p&gt;
&lt;p&gt;쇼팽과 셰익스피어도 우리에게 즐거움을 준다. 그러나 가장 본질적인 쾌감은 먹을 때와 섹스할 때, 더 넓게는 사람과의 관계에서 온다. 진화의 여정에서 쾌감이라는 경험이 탄생한 이유 자체가 두 자원(생존과 번식)을 확보하도록 하기 위함이었다. - &amp;#x3C;행복의 기원&gt;, 서은국&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-07-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;모 의원이 코이라는 물고기를 이야기한 후로 큰 강을 찾아 나서는 사람들이 늘어난 것 같다. 말콤 글래드웰의 다윗과 골리앗을 추천한다. 용꼬리보다 뱀머리를 선택하는 게 나을 수 있다는 논리적 근거를 제시해 준다. 너무 애쓰지 말자. 살아보니 9할은 운이더라.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-07-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;난 반대. 한국 아이돌이 노래도 영어로 부르고, 미친 인공지능 번역기가 널려있는 시대에 굳이. 득보다 실이 많을거라는 생각. 특히 토스같이 영어 잘하는 개발자 뽑을거 같은 회사에서 한다니 더 이해가 안되는. &lt;a href=&quot;https://t.co/f0KvMRZwj5&quot;&gt;https://t.co/f0KvMRZwj5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-07-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;무례하려면 그만큼의 과거 실적이나 실력이라도 있던가 그게 아니면 예의를 지키거나. 둘 다 없다면 극혐.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-07-29&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 6월의 잡담]]></title><description><![CDATA[#0 이짤에 놀란건 챗지피티보다 트위터... 트위터가 저정도였다뉘... https://x.com/aakashgupta/status/1663023449928003584 2023-06-01 #…]]></description><link>https://jiniya.net/2023/06/small-talk-2023-06/</link><guid isPermaLink="false">https://jiniya.net/2023/06/small-talk-2023-06/</guid><pubDate>Sun, 11 Jun 2023 14:40:13 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;이짤에 놀란건 챗지피티보다 트위터... 트위터가 저정도였다뉘... &lt;a href=&quot;https://x.com/aakashgupta/status/1663023449928003584&quot;&gt;https://x.com/aakashgupta/status/1663023449928003584&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-06-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;인생을 제대로 산다는 건 쓸데없는 걱정으로&lt;br&gt;
나 자신을 가두지 않는 것이다. - &amp;#x3C;모든 삶은 흐른다&gt;, 로랑스 드빌레르&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-06-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;하찮은 자존심을 다 내던질 정도로 사랑한건 아니었던거죠.  - 보라! 데보라 ep.07&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-06-11&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 5월의 잡담]]></title><description><![CDATA[#0 관점이 달라지면 기억이 달라지고, 기억이 달라지면 세계가 달라진다. 세계는 시선의 방향이 결정한다. 라는 말을 유튭에서 들었다. 나는 어떤 방향으로 무엇을 보고 있을까라는 생각이... 2023-05-04 #1 우리 회사 특징일 수 있지만 9…]]></description><link>https://jiniya.net/2023/05/small-talk-2023-05/</link><guid isPermaLink="false">https://jiniya.net/2023/05/small-talk-2023-05/</guid><pubDate>Wed, 31 May 2023 20:33:19 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;관점이 달라지면 기억이 달라지고, 기억이 달라지면 세계가 달라진다. 세계는 시선의 방향이 결정한다. 라는 말을 유튭에서 들었다. 나는 어떤 방향으로 무엇을 보고 있을까라는 생각이...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;우리 회사 특징일 수 있지만 90년대생들은 우리 때랑은 다르게 문서화를 아주 잘하는 경향이 있는 거 같다. 예전 세대는 인수인계 하라면 가서 말로 적당히 떼우는 경향이 있는데. 대체로 90년대 생들은 깔끔하게 문서로 정리해서 주는 경우를 많이 본다. 같이 일하기 편함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;거대언어모델에서 파라미터 개수가 일정 수를 넘어서면 나타난다는 새로운 능력은 정말 신기한거 같다. chatgpt가 나를 대신해 모든 걸 결정해 준다면 내가 ai의 아바타가 되는게 아닐까 싶은 생각이. 바보같은 선택을 내가 하는 삶이 나을까, 꼭두각시지만 최적의 선택을 하는 삶이 나을까?&lt;/p&gt;
&lt;p&gt;우리 아이들은 더는 점쟁이를 찾아가진 않을꺼 같다. 최신 업데이트에 파인 튜닝이 아주 잘된 gpt를 찾아가지 않을까란 생각이...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;최근 신입 포함 직원들의 코딩 능력이 향상됐다는 느낌을 많이 받는데, 물어보면 대체로 백엔드에 지피티가 있는듯. 심지어 본인 비용으로 유료로 쓰는 친구들도 있음. 예전에 2-3일 걸리던 작업이 요새는 2-3시간만에 아웃풋이 나옴. #멋진신세계&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;구글 바드 써봤는데 사람들 욕하는거항 다르게 느낌 나쁘지 않은뎅. 좀 늦었지만 역시 ai명가 구글인가?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;회사에 외계인과 접선한게 아닌가 싶을 정도로 분석을 잘하는 친구가 한 명 있다. 볼때마다 그런 생각이 든다. 이런게 운이군?!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;제가 물려받고 싶었던 건 권력이 아니라 자부심이었습니다. 아버님께서 틀리셨습니다. - 조선 변호사 ep16&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-31&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;git 저장소에 컨플릭트가 발생한 개발자에게 chatgpt가 force push를 알려줘서 저장소를 깨먹었다. 사람들은 chatgpt를 비난한다. 20년전 부사수였던 개발자는 컴파일이 안된다는 질문을 devpia에 올려서 답변을 받고는 windows.h를 고쳐서 컴파일하는  사건이 있었다. 인공지능이 문제가 아니다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-05-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 4월의 잡담]]></title><description><![CDATA[#0 네이버 증권에 코인탭이 생겨서 깜놀. 닭 모가지를 비틀어도 새벽은 온다는 말이 뇌리에 스친다. 주류에 있는 모두가 무시하지만 점점 자산군의 하나로는 무시못할 입지를 다져가는듯한 느낌. 2023-04-04 #…]]></description><link>https://jiniya.net/2023/04/small-talk-2023-04/</link><guid isPermaLink="false">https://jiniya.net/2023/04/small-talk-2023-04/</guid><pubDate>Sun, 30 Apr 2023 16:08:23 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;네이버 증권에 코인탭이 생겨서 깜놀. 닭 모가지를 비틀어도 새벽은 온다는 말이 뇌리에 스친다. 주류에 있는 모두가 무시하지만 점점 자산군의 하나로는 무시못할 입지를 다져가는듯한 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;친구가 추천해서 대행사 보는데 후반부로 갈수록 텐션 떨어진다. 재벌 딸램 역으로 나오는 배우 한예슬 느낌 약간 나서 찾아보니 연기 못한다는 평이 많은듯. 난 캐릭터 괜츈한거 같던데. 1도 없어 부른 걸그룹 출신일줄은,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;arm64 포팅하며 느낀점. 0) arm의 세상이 임박했다. 1) 명령어 디코더 코드가 생각보다 크다. 2) 신박한 방식의 어드레싱 모드에 놀랄수 있다. 3) 그걸 몰랐다면 정렬로 한 10시간쯤은 탕진할 수 있다. 4) 레이몬드 첸 형님은 이미 내가 포팅할걸 알고 있었다. 강력ㅊㅊ &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20220726-00/?p=106898&quot;&gt;https://devblogs.microsoft.com/oldnewthing/20220726-00/?p=106898&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;프롬프트 엔지니어링은 다소 거품이 있다는 생각. 그거 열심히 공부해서 써먹을려고 하면 이미 인공지능이 개떡같이 말해도 찰떡같이 대답할 확률이 높지 않을까? 그런점에서 인공지능 출력을 빠르게 잘 판단하는 걸 훈련하는게 더 남는 장사 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;뭐 미지근하게 사는 것도 나쁘진 않아. - 대행사 ep.16&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;사람들은 머스크를 조롱하고 비웃지만 입지전적인 사람이긴 한듯. 파딱이 누가 쓰냐고 비난하는 사람 천지임에도 탐라에 은근 많이 보임. 과정은 엉망진창이었지만 트위터는 여전히 잘 돌아간다. $tsla &lt;a href=&quot;https://n.news.naver.com/mnews/article/015/0004832512&quot;&gt;https://n.news.naver.com/mnews/article/015/0004832512&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;10대 20대에는 서점 가면 컴터 책만 보고 사고 했는데, 40대가 되니 주워오는 책들의 면면이 죄다 주식 책. 인정하긴 싫지만 요즘 관심사가 주식인건가 하는 생각이 든다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.sequoiacap.com/article/notion-spotlight/&quot;&gt;https://www.sequoiacap.com/article/notion-spotlight/&lt;/a&gt; 근래에 읽은 인상 깊은 글. 노션이 이렇게 컸는지는 몰랐다. 선샤인 하기만 했을 줄 알았던. Zhao says they spent 18 hours a day at their laptops, not bothering to dress, clean or cook. “We were just, code, code, code,” Zhao remembers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;공감. 경험상 코딩 잘하는게 소통 잘하는 능력보다 희소함. 심지어 연차가 오를수록 더 심해지는듯한 느낌. 둘다 잘해야겠지만 코딩을 잘하면 사실 소통할 거리도 줄어듬. 회사내 개발자가 소통한다는게 대체로 원하는 기한에 원하는대로 만들어주질 못해서 발생하는 경우가 많기 때문. &lt;a href=&quot;https://x.com/pakyoungrok/status/1648993523889487872&quot;&gt;https://x.com/pakyoungrok/status/1648993523889487872&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이런 이유로 나이가 들면 대체로 매니저로 가는 경우가 많고 계속 개발을 하는 경우는 드문게 아닌가 싶다. 실제로 해외든 국내든 개발자 분포를 보면 나이가 올라갈수록 인원이 확 줄어드는 경향이 있음. &lt;a href=&quot;http://www.jiniya.net/wp/archives/8185&quot;&gt;http://www.jiniya.net/wp/archives/8185&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;격하게 공감. 나만 그런건 아니었다는데서 위안을,, &lt;a href=&quot;https://x.com/iron4gg/status/1649069970599587843&quot;&gt;https://x.com/iron4gg/status/1649069970599587843&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;안전 벨트를 메는 것은 좋은 습관이다. 약간의 불편함으로 사고를 헷지할 수 있기 때문. 그럼에도 사람들은 당장의 편익은 눈에 보이고, 사고 확률은 낮고 멀리 있기 때문에 당장 편리한 미착용을 선택 하는경우가 더러 있다. 내가 선택하는 일이 안전벨트를  메는건지 푸는건지 돌아보면 도움이 된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;4번 공감. 나이, 성별을 떠나서 과거의 영광에 집착하는 사람치고 현재가 멀쩡한 사람을 거의 못본거 같다. &lt;a href=&quot;https://x.com/economakase/status/1650458091111211009&quot;&gt;https://x.com/economakase/status/1650458091111211009&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;이 문제에 정부도 일정부분 책임이 있다고 느끼는건 중기청년전세대출 같은거. 1억까지 1프로대 금리로 제공. 딱히 보증 물건의 담보 능력을 정부가 따지지도 않음. 저게 생기고 썩다리 원룸도 전세가 1억으로 상향 평준화됨. 조건되는 입장에서 보면 정말 달콤한 공짜점심처럼 보이는게 팩트 ㅠㅜ &lt;a href=&quot;https://x.com/moomini00/status/1650525499389804544&quot;&gt;https://x.com/moomini00/status/1650525499389804544&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;부동산 열풍에 묻지마 무자본 갭투자에 나선 투기꾼들, 저리에 유동성을 공급한 정부, 벼락거지된것 같은 느낌에 너도나도 빚투에 나선 청년들, 이 모든게 합쳐져서 지금 청구서가 날아오는게 아닌가 싶다. 어쨌든 공짜 점심은 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;Gpt4, 3시간 25개면 쓰지 말라는 소린가? Gpt4쓰다가 3.5쓰니까 갑갑하네. 12개로 낮추고 안쓸때 충전되는 시스템이면 더 좋을듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-04-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 3월의 잡담]]></title><description><![CDATA[#0 탐라를 보면서 요즘도 연차 쓰면서 눈치 본다거나, 개수대로 다 쓰지도 못하는 회사가 많다는 사실에 놀랐다. 다들 저마다 각자의 세상 속에서 살아가는 것 같다. 2023-03-06 #…]]></description><link>https://jiniya.net/2023/03/small-talk-2023-03/</link><guid isPermaLink="false">https://jiniya.net/2023/03/small-talk-2023-03/</guid><pubDate>Fri, 31 Mar 2023 15:38:54 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;탐라를 보면서 요즘도 연차 쓰면서 눈치 본다거나, 개수대로 다 쓰지도 못하는 회사가 많다는 사실에 놀랐다. 다들 저마다 각자의 세상 속에서 살아가는 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;오늘도 여기에 진실을 적지 않는다. 진실을 적지 않는 것이 진실이기에. - 친구 일기장,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;1년간 아무도 못 풀었던 문제를 21살 신입 사원이 이틀만에 명쾌한 정답을 찾아냈을 때의 기분은 좋을까? 당황스러울까? 채용을 잘했거나, 억세게 운이 좋았거나. 정말이지 세상은 넓고 용자는 많다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;이젠 선배가 흑잡는 거예요. 처음이니까. 착수는 내가 할께요. - 더 글로리 ep.16&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;어떤 싸움은 한쪽은 얻을거만 있고, 한쪽은 잃을거만 있는 경우가 있다. 손자병법을 따르자면 이 경우 후자는 싸우지 않는 것이 이득이겠지만 삶이 또 그리 간단치는 않은법. 후자의 입장에서 싸우게 된다면 좋은 전략은 무엇일까? 최근 마소, 구글의 인공지능 검색 시장 싸움도 비슷해보이는.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;페친 가라사대, 조만간 다들 자비스 하나씩 가지고 사는 세상이 될 것이다. 하지만 당신이 토니 스타크처럼 멋지게 살 가능성은 아주 희박하다. 아침부터 뼈때리는 진실.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;그러나 실제로 무일푼이 되지 않으려면  생각을 이렇게 바꿔야 합니다. &apos;이번 투자는 상각해버리고 나중에 다시 도전해야겠어. 여기에 집착할 필요 없어. 자칫하면 내가 다쳐.&apos; - 찰리 멍거 바이블&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;한때 ms가 백신 업체들 모아놓고 충돌 테스트를 해주던 때가 있었다. 디펜더가 천하통일하고 백신이 잠잠해지니 요새는 그 자리를 안티치트가 꿰찼다. macp라는 ms 안티치트 호환성 프로그램이 생김. 게임은 몹시 중요하고, 안티치트는 넘나 말썽꾸러기고 라는 ms형님들의 입장이 반영된 프로그램.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;생각보다 빵터짐. &lt;a href=&quot;https://codingmoonhak-library.oopy.io/&quot;&gt;https://codingmoonhak-library.oopy.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-03-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 2월의 잡담]]></title><description><![CDATA[#0 웃겼다 ㅋㅋㅋ 뭔가 러스티안의 성향을 잘 반영한 조크인듴... https://t.co/C9QTo8aSIE 2023-02-02 #1 2006년 회사를 창업후 지금까지 내가 회사에서 느낀것들.…]]></description><link>https://jiniya.net/2023/02/small-talk-2023-02/</link><guid isPermaLink="false">https://jiniya.net/2023/02/small-talk-2023-02/</guid><pubDate>Tue, 28 Feb 2023 19:31:08 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;웃겼다 ㅋㅋㅋ 뭔가 러스티안의 성향을 잘 반영한 조크인듴... &lt;a href=&quot;https://t.co/C9QTo8aSIE&quot;&gt;https://t.co/C9QTo8aSIE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-02&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;2006년 회사를 창업후 지금까지 내가 회사에서 느낀것들. 1) 복지를 늘리는 행위가 생산성 향상에 직접적으로 큰 도움을 주지는 않는다. 2) 높은 복리후생이 일류를 채용할 수 있는 길을 제공하지도 않는다. 3) 맥도날드 햄버거 조립라인에 쉐프를 고용할 필요는 없다.&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;
&lt;p&gt;시간이 지난다고 모두가 성장하지는 않는다. 5) 어떤 자리든 장이란 자리는 1이라도 똑똑한 사람이 맞는게 좋다. 6) 생산성을 저해하는 요소는 어떻게 포장해도  생산성을 저해한다. 7) 실력이 아무리 뛰어나도 회사에 기여를 하지 않는다면 아무 의미가 없다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;사람 문제로 보이는 내부갈등이 의외로 인간 관계의 문제가 아니라 해결해야할 과제가 역량에 비해 너무 많거나 높은게 원인인 경우가 많았다. 9) 회사 상황이 좋으면 많은 것들이 묻힌다. 10) 반대로 상황이 나쁘면 온갖 것들이 부각된다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;2023-02-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;챗지피티 진짜 텍스트박스는 텍스트에어리어로 변경이 시급하다. 코드 붙여넣을때 개불편...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;ms 진짜 열일한다. 덩치는 공룡임에도 속도는 스타트업,,, &lt;a href=&quot;https://x.com/delight412/status/1621843423576858624&quot;&gt;https://x.com/delight412/status/1621843423576858624&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-04&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;동어 반복 주석을 달고 좋은 습관이라고 착각하는 경우가 많은데 제일 흔한 악습이자 비용 낭비. 저장소가 커지면 주석/코드 불일치가 발생하는 것도, 그걸 계속 일치하게 만드는 것도 큰 비용. 무튼 주석은 공짜가 아니니 아껴서 잘 쓰는게 중요한 포인트가 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;주변에 코파일럿, 러스트, 챗지피티 같은 복음을 전파해보면 의외로 반응이 시큰둥하거나 부정적인 경우가 많다. 그렇게 약을 쳐도 아예 시도조차 안해보는 경우가 대다수. 온라인과 오프라인의 온도차가 참 크다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;챗지피티 플러스 버튼이 생겼길래 설레는 마음으로 들어갔지만 뭔 카드를 넣어도 죄다 거절되는 ㅠㅜ 결제단에서 막아둔건가? 어서 빨리 풀리길...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.llvm.org/posts/2021-03-26-the-new-pass-manager/&quot;&gt;https://blog.llvm.org/posts/2021-03-26-the-new-pass-manager/&lt;/a&gt; 왜케 다들 열심히 일하는 것인가?! 뉴 패스 매니저라니. 하위호환성 자비를 업계는 이제 버려 버린듴 ㅠㅜ 공짜로 될 줄 알았던 나의 무지에 당황쓰...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;오올,,, 챗지피티 플러스 한국 결제 풀렸다. 이제 더는 다운됐다는 메시지는 안봐도 되는 것인가?! 귀찮은건 코파일럿이 해주고, 모르는건 챗지피티가 해주고, 나는 컨펌만 하면 되는 멋진 신세계...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;사실 우리나라 전세라는 제도 자체가 폰지 사기와 유사한게 아닌가 싶다. 다음 더 비싼 전세로 들어올 사람이 있어야 돌아가는 구조. 대체로 집주인이 부유하다고 생각하지만 생각보다 대출과 보증금으로 근근히 버티는 경우도 많음. 특히 갭투자. &lt;a href=&quot;https://x.com/______River____/status/1624613704032727041&quot;&gt;https://x.com/______River____/status/1624613704032727041&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;업계 선배들이 노력하지 말라고 하는 말에는 큰 통찰이 담겨있다고 생각한다. 0) 노력은 다들 한다. 1) 노력과 결과는 생각보다 상관 관계가 높지 않았다. 2) 미친듯이 노력하다 번아웃돼 갈려 나가는 사람을 너무 많이 봤다. 3) 인피니트 게임이다. 지속가능성이 훨씬 중요하다.&lt;/p&gt;
&lt;p&gt;노력은 해야겠지만 애쓰지 마. 될 일은 되고 안될 일은 안된다. - 시지프스 ep.06&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;&quot;GPT가 알려준 코드로는 빈파일만 형성되고, 안에 내용이 없음&quot; 같은 질문을 보면 서 gpt의 장점과 단점을 모두 느낀다. gpt가 제시한 코드는 틀리지 않았지만 크롤링하고 싶은 사이트가 그걸 막아서 빈 파일이 생성되는게 원인이었다. 전문 프로그래머를 고용하라는 조언을 해주었다.&lt;/p&gt;
&lt;p&gt;안타깝게도 그 친구는 귓등으로도 듣지 않는 눈치. 그럴싸한 프롬프트 몇줄이면 해결할 수 있다고 생각하는 듯했다. 심지어 이 문제를 마주하기 전까지 gpt를 통해서 많은 과제를 모두 해결했기에 확증편향은 더욱 심했다. 개발자가 아닌 사람에게는 추천하지 않는게 좋겠다는 생각을 첨으로 했다.&lt;/p&gt;
&lt;p&gt;다만 해보진 않았지만 빈 파일이 나온다고 타령하며 집요하게 물어 뜯는다면 gpt가 해결책을 알려줄지도 모를 일이기도 하다. 이랬거나 저랬거나 요즘 코딩은 옛날에 컴퓨터 조립같은 느낌으로 전락해 버린듯한 느낌적인 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;테드 창의 글을 이제야 읽었다. 뇌도 우리에게 주어진 경험같은 입력에 대한 흐릿한 jpeg이 아닌가 싶다. 휴대폰 없으면 번호 기억 못하고, 네비 없으면 길 못찾아도 잘 산다. 인공지능도 어떤 점은 우리를 더 멍청하게 만들겠지만 그럼에도 여전히 우린 잘 살지 않을까? &lt;a href=&quot;https://www.newyorker.com/tech/annals-of-technology/chatgpt-is-a-blurry-jpeg-of-the-web&quot;&gt;https://www.newyorker.com/tech/annals-of-technology/chatgpt-is-a-blurry-jpeg-of-the-web&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;ide 떡밥을 물어본다. 키보드/마우스를 떠나서 난 그 사례가 인간 페어 프로그래밍의 전형적인 병폐를 보여준다는 생각. 개취가 뭔지를 모르는 사람이 너무 많다. 내가 키보드를 쓸지 마우스를 쓸지는 그냥 개인 취향 아닌가?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;탐라를 보니까 새삼 테슬라 주가가 많이 올랐다는걸 느낀다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;심심해서 해봤다. using selenium 프롬프트에 추가하니 크롤링되는 코드를 작성했다. 다만 자긴 언어 생성 모델이라 외부 사이트에 접근할 수 없어 xpath는 비워놨고, 해당 사이트가 스크래핑 허용하는지 체크하라는 말까지 추가해줌. 이제 전문 프로그래머의 역할은 xpath 찾아서 채워주는 것인가? &lt;a href=&quot;https://x.com/codemaru/status/1625470573752225792&quot;&gt;https://x.com/codemaru/status/1625470573752225792&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;html 붙여넣고 xpath 말하라면 당연히 알려주겠지라며 소스 보기했더니 자바스크립트 떡칠되서 소스가 없다. 역시 아직 dom 네비게이션해서 xpath 정도는 추출할 줄 아는 전문 프로그래머가 필요한 ㅎㅎ&lt;/p&gt;
&lt;p&gt;이 시점에서 웃긴건 얘가 그전에 작성했던 버전은 get 쿼리해서 bs4로 아이템 찾는거였는데 외부 사이트에 접속할 수 없다는 녀석이 get쿼리 파라미터가 맞았고, bs4로 스캔하는 엘리먼트가 일치했었. 그걸 토대로 봤을때는 xpath를 알고도 안알려주는거 아닌가 싶은. 약관 확인하라는 얘기도 그렇고.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;좋은 결정이라 생각. 난 예전부터 자기 머리로 생각해낸 이상한 코드를 짜내는 연습보다는 좋은 코드를 많이 보고 베끼면서 코드 패턴을 학습하는게 훨씬 유용하다고 생각했지만, 글케 주장했다가 교수님께 대차게 까였던 기억이. &lt;a href=&quot;https://x.com/mK4QnPUIHj2hdPA/status/1625775298729103360&quot;&gt;https://x.com/mK4QnPUIHj2hdPA/status/1625775298729103360&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;재밌는게 사람들이 보내주는 chatgpt 프롬프트 보면 사람들 성향이 보임. 1) 제발 이거 좀 해주세요. 공손형. 2) 이거 만들어서 제출해!! 명령형. 3) 거울아 거울아... 백설공주형?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;직업 프로그래머로 일하는데 필요한 최소한의 지식 수준이란 뭘까? 상대적이라 생각보다 어려운 질문이다. 5년 조금 넘는 시간이 흘렀고, 알파고가 아닌 chatgpt란 녀석이 코딩을 거의 마스터 한거로 보여진다. &lt;a href=&quot;http://www.jiniya.net/ng/2017/10/coding-is-difficult/&quot;&gt;http://www.jiniya.net/ng/2017/10/coding-is-difficult/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;페어 프로그래밍을 강제하나요? 스크럼을 하나요? 주간보고가 존재하나요? 소스코드 저장소를 사용하나요? 담당 업무외 코드도 를 볼 수 있나요? 코드 리뷰 하나요? 이슈 트래커를 사용하나요? 사내 위키가 있나요? 업무용 메신저가 있나요? 사내 코딩 규칙이 있나요? 야근있나요? 포괄임금제?&lt;/p&gt;
&lt;p&gt;페어프로그래밍 강제, 스크럼 진행, 주간 업무보고 있음, 저장소 없음, 소스 코드 가시성 없음, 코드 리뷰 시스템 없음 오프라인 코드리뷰는 없음 간주, 이슈 트래커 없음, 사내 위키 없음, 업무용 메신저 없음 라인 카톡 네톤 없음 간주, 코딩 규칙 없음, 야근 있고 포괄임금제인 회사는 생각해볼듯.&lt;/p&gt;
&lt;p&gt;면접은 회사가 사람을 선택하는 과정이기도 하지만 지원자가 회사를 선택하는 과정이기도 하다. 궁금한게 없냐곺하면 대부분 없다고 답하는데, 자신의 성향과 맞는지 확인할건 확인하는게 좋지 않을까란 생각. 어떤 사람들과 어떤 환경에서 일을 했는지가 생각보다 더 중요할 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;이런 인식은 진짜 위험하다 생각한다. 가끔 팀 회식 자리에서도 은근 이런 인식을 드러내는 친구들이 있는데 불편함. 더 내려가면 물리학 수학 철학순으로 귀결되는데, 결국 그 논리면 철학자들 앞에서 고개나 들고 다닐수가 있을지. 뭐가됐든 상호존중이 기본 아닐까 싶다. &lt;a href=&quot;https://t.co/u9nHrjvP44&quot;&gt;https://t.co/u9nHrjvP44&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;트위터 들와보면 참 세상 사람들이 이렇게 온갖 종류의 생각들로 화가 가득하다는걸 느낀다. 확실히 뭔가 결이 다른 sns...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;판돈 많다고 이기는 게임도 아니지만, 판돈 없으면 입장 불가한 그들만의 리그. 코드 한줄로 됩니다, 라는 말은 프레임워크에서 수만줄 미리 짜둬서 그렇듯. 내가 물어보면 짹짹 멋진 대답을 내뱉는 gpt 프롬프트 너머에선 어마어마한 자원이 소비된다. 내가 아낀 에너지는 결국엔 어디선가 지출된다. &lt;a href=&quot;https://x.com/kindtis/status/1628258126549090304&quot;&gt;https://x.com/kindtis/status/1628258126549090304&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;actix-web으로 간단한 웹서버를 만들다 비동기 처리가 이게 맞나 싶은 부분이 있어서 actix 소스 코드를 좀 살펴봤다. 난 러스트를 이해한게 아니었다. 여긴어디? 난 누구? 코알못이 소스 코드 보는 느낌이 이런 느낌일까 싶은. tokio에서 시작해야 하는건가,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;송재경님 시대엔 프로그래밍을 잘해야 40대까지 개발자를 하는 경우가 많았지만, 내 또래들은 딱히 잘하지 않아도 거의 대부분 40대까지 개발자를 하고 있다. 직원들도 딱히 실력에 관계 없이 대부분 경력을 잘 유지하는 느낌. 그만큼 이바닥 수요가 늘어난게 아닌가 싶다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/14748&quot;&gt;http://www.jiniya.net/wp/archives/14748&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;우리 세대는 벤처 1세대의 꿀단지는 놓쳤지만, 그래도 노코테, 주먹구구식 개발 문화의 덕을 어느 정도는 받았다는 느낌. 그만큼 준비가 안된 사람들도 개발자로 취업하기가 쉽고 좋았다. 지금 최애로 꼽히는 네카라의 네는 심지어 차순위로 가던 애들도 많았다.&lt;/p&gt;
&lt;p&gt;코딩을 아주 잘했다면 송재경님 시대가, 그럭저럭 했다면 우리 세대에 태어난게 더 유리했다고 생각한다. 다음 세대는 코딩 실력은 그렇게 중요하지 않을 가능성이 높을거 같은 느낌적인 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#25&lt;/h2&gt;
&lt;p&gt;모든 개발자의 로망 아닐까 싶다. 무소의 뿔처럼 혼자서 지속 가능한 부가가치를 창출 한다는거, 심지어 b2c. 나도 그랬지만 개발자 입장에서 이런 꿈의 가장 큰 좌절 포인트는 개발 난이도 보다는 기획, 마케팅 난이도가 아닐까 싶다. 카피캣 말고는 뭘 만들어야 돈이 되는지를 모른다는게 함정. &lt;a href=&quot;https://x.com/BenjaminKim_/status/1630407630257807360&quot;&gt;https://x.com/BenjaminKim_/status/1630407630257807360&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;재호님 의견대로 인공지능을 포함해 개발 지원 도구들이 너무 좋아져서 역설적이게도 코딩 능력보다는 마케팅, 기획 능력이 훨씬 더 희소해진것 같은 느낌. 1인 개발이란게 옆에서 보면 쉬워보여도 막상 시작해서 마켓에 올려보면 좌절스러운 현실을 직면하는 경우가 많지 않나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#26&lt;/h2&gt;
&lt;p&gt;빙ai를 써봤다. 챗지피티를 경험해서 그런지 그때 그 감흥은 없다. 역시 뭐든 첫느낌이 강렬하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-02-28&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2023년 1월의 잡담]]></title><description><![CDATA[#0 와우 ms미쳤. Bing신이 드디어 재탄생 하는건가?! https://x.com/GeekNewsHada/status/1610808562388987905 2023-01-05 #1 이건 진짜 킹정, 더불어 21세기에 cmake…]]></description><link>https://jiniya.net/2023/01/small-talk-2023-01/</link><guid isPermaLink="false">https://jiniya.net/2023/01/small-talk-2023-01/</guid><pubDate>Tue, 31 Jan 2023 15:33:03 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;와우 ms미쳤. Bing신이 드디어 재탄생 하는건가?! &lt;a href=&quot;https://x.com/GeekNewsHada/status/1610808562388987905&quot;&gt;https://x.com/GeekNewsHada/status/1610808562388987905&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;이건 진짜 킹정, 더불어 21세기에 cmake가 천하통일 하고 있다는거에 몹시 큰 자괴감이... &lt;a href=&quot;https://x.com/junghyun_nam_/status/1610636943578259461&quot;&gt;https://x.com/junghyun_nam_/status/1610636943578259461&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;php 웹서버 코드를 러스트로 컨버팅해보았다. 벤치를 돌렸는데 14배가 빨라졌다. 속도도 속도지만 진가는 네이티브 언어임에도 php나 파이썬만큼 작성하기 편리한 프레임워크가 존재한다는게 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;Url리다이렉션 시키는 코드로 30분 넘게 헤맸다. 엉뚱한 경로로 리다이렉션 되는 문제. 암만봐도 모르겠고 검색을 해봐도 딱히 답이 없었다. 혹시나 해서 chatgpt에 물어봤더니 3초만에 답을 알려주었다. &lt;a href=&quot;http://www...%EC%9D%84&quot;&gt;http://www...을&lt;/a&gt; http:://www로 쓴 것. 니가 모를거라고 생각한 나의 거만에 3초간 묵념.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;근래에 발견한 가장 유익한 블로그, 세상은 넓고 용자는 많다... &lt;a href=&quot;https://x.com/_jeyraof/status/1616117059913658368&quot;&gt;https://x.com/_jeyraof/status/1616117059913658368&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;그것이 알고싶다. 빌라왕편을 보고 든 생각. 동일 집주인이 3년이상 소유한 건물만 계약해도 저런 사기는 상당수 피할듯한. 신축이라 매매가가 불명확하고 그래서 전세가가 뻥튀기된걸 세입자가 알 수 없다는 게 문제의 본질. 뻥튀기가 불가능하면 애초에 나눠가질게 없어서 사기꾼들이 붙지를 못함.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;코딩봇이라며 아두이노로 진행하는 코딩 교육이 늘고 있는데 갠적으론 반대. 코드랑 회로랑 동시에 잘 만들어야해서 더 어려움. 걍 고전적인 gw베이직으로 원넓이, 삼각형 높이 구하는거 시키는게 더 나았다는 생각. Chatgpt 이후론 과연 코딩 교육이 얼만큼 의미있을지도 의문.&lt;/p&gt;
&lt;p&gt;어쩌면 시작부터 chatgpt와 협업하는 걸 가르치는게 더 나을지도. 어떻게 잘 부려먹는가가 대세가 되는 시대가 될지도 모르니까. 20년 후에 얘들은 뭐해먹고 살지 몹시 궁금. 그런거보면 부모 세대나 우리 세대나 미래에 대해 무지하기는 똑같다. 닥공부 외치던 세대나 영어, 코딩 시키는 세대나.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;자녀 코딩 교육으로 고민하는 인문과 친구에게 chatgpt의 존재를 알려주었다. 아바타2 관련 질문을 하고는 답변하지 못하는걸 통쾌해한다. 대다수 사람들의 반응은 얼추 비슷한듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;실력있고 인간안된 개발자나, 성실하고 착한데 실력 없는 개발자나 둘다 함께하기는 힘들다는 생각. 돈받고 하는 일이니 개발력이 기본 허들은 넘어야 하고, 함께 하는 일이니 인간성도 기본은 갖춰야 하는게 아닐지.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;신입 키워놓으면 딴 회사 간다는 말은 정말 난센스. 조건 좋은데 생기면 이직하는게 인지상정 아닌가? 노사관계는 계약 관계 이상도 이하도 아니다. 거기에 더 많은 의미를 넣으면 피차 피곤해진다. 그리고 요즘 it 바닥에서 키운다 만다도 엔지. 경력보다 잘하는 신입이 부지기수다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;구글과 메타가 챗지피티 수준의 것을 가지고 있지만 비지니스에 득이되지 않아 공개를 못한다는 얘기와 관련해서 구글은 인정이가지만 메타는 뭐가 있었나 싶다. 공개하는 ai 모델마다 다 망하지 않았나 싶은?!&lt;/p&gt;
&lt;p&gt;번외로 챗지피티를 쓰면 쓸수록 장기적으로 구글엔 정말 치명적일거 같은 느낌. 나만해도 벌써 선챗지피디. 거의 대부분 해결. 안된건 걔가 알려준 내용 중에 키워드 뽑아 구글 검색으로 대체로 바뀐듯. 그런 점에선 openai에 돈 들이붓는 ms가 위너일지도...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;간만에 밀리 들어갔더니 ai tts가 추가됐다. 진짜 요즘 세상이 미친듯이 바뀌는 중인듯. 사람이 한다는 것에 관한 생각들이 많이 바뀔거 같다. 난 신년사를 ai가 써도 무방하다고 생각한다. 지금은 인간이 가이드라인이라도 주지만, 나중에는 그마저도 없겠지. 유발하라리가 말한 것처럼.&lt;/p&gt;
&lt;p&gt;그 결과 직업시장 또는 결혼시장에서의 성공이 점점 더 코타나의 자질에 따라 판가름날 것이다. 그래서 최신 버전의 코타나를 소유한 부자들은 구버전을 소유한 가난한 사람들보다 결정적 우위를 점할 것이다. - 호모데우스, 유발하라리&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;간단한 자바스크립트 작성할 일이 있어 데이터 10개 중에 2개 정도 코드만 작성하고 나머지는 인턴한테 시켜야지 했는데. 챗지피티에게 보여주고 짜라고 하자 나머지 코드를 완전하게 다 작성해 주었다.  이제 인턴이 할 일은 검수 또는 2021년 이후 데이터를 조사하는 일 밖에는 없는 걸까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-31&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;챗지피티 수학 기능 업데이트 됐데서 2022년 수학능력시험 수학 문제 하나 넣어봤는데 정답을 맞췄 ㄷㄷㄷ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2023-01-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 12월의 잡담]]></title><description><![CDATA[#0 한국 16강... 와 진짜 미쳤,,, ㅎㅎㅎ 최선을 다하면 되긴 하는구나,,, 손흥민 진심 리스펙,,, 막판 뛰어갈때 저게 될까 싶었는데 ㅎㅎㅎ 2022-12-03 #1 It is difficult to understand the exact…]]></description><link>https://jiniya.net/2022/12/small-talk-2022-12/</link><guid isPermaLink="false">https://jiniya.net/2022/12/small-talk-2022-12/</guid><pubDate>Wed, 28 Dec 2022 01:14:36 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;한국 16강... 와 진짜 미쳤,,, ㅎㅎㅎ&lt;/p&gt;
&lt;p&gt;최선을 다하면 되긴 하는구나,,, 손흥민 진심 리스펙,,, 막판 뛰어갈때 저게 될까 싶었는데 ㅎㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;It is difficult to understand the exact purpose of the code without more context. 내가 모르는건 gpt도 어렵군 ㅠㅜ 그럼에도 엄청나다 진짜,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;chatgpt 스터디를 만들어야 할 지경인듯. Convert a code to b를 배웠다. 진짜 특이점인건가. 어떻게 저게 되는지 보면서도 신기하네. 마법이 따로 없군. 무료 풀리면 가격이 얼마일지,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;chatgpt를 쓰면 쓸수록 유발하라리가 호모데우스에서 말하던 세상이 코앞에 왔다는 느낌이 많이 든다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;대한민국 물류 사랑한다. 어제 주문한 피씨가 자고 나니 도착해 있는 신세계란,,, 용산 사람들 포장 기술도 진짜 기가 막힌다. 👍&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;나도 어릴때 이런 생각을 많이 했는데, 조선 시대 사람들 보면서 어떻게 저렇게 착취당하고 살았지? 근데 나이들어보니 그당시 태어났으면 나도 그냥 그렇게 살았을거 같다는 생각. 지금도 뭐 자본주의 노예니. 그리고 조선 무시하는데 500년 간 왕조도 흔치않은게 현실,,, &lt;a href=&quot;https://x.com/aichupanda/status/1601417465392926721&quot;&gt;https://x.com/aichupanda/status/1601417465392926721&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;3인 사업장에서 병특으로 경력을 시작한 입장에서, 여건이 안되서 그런데라도 취직하는 사람이 대부분이지 않을까 싶다. 물어볼 곳은 없지만 내멋대로 다 만들 수 있다는 점은 장점. 바보 선임이 엉뚱한 답변 주는 곳보다는 없는게 낫다. 스택오버플로 깃헙 코파일럿 챗지피티가 있는 세상이니. &lt;a href=&quot;https://x.com/backendMew/status/1601485448245022720&quot;&gt;https://x.com/backendMew/status/1601485448245022720&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;지나고보니 경력만큼 케바케도 없다. 갈 수 있는 곳 중에선 제일 좋은 곳으로 가야겠지만, 후진 곳에서 시작했다고 딱히 좌절할 필요도 없다. 어디가 됐든 장점도 있고 단점도 있으니. 그리고 올라탈 열차가 없는 상황에서는 어디가 됐든 일단 올라타는게 먼저라는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;인터뷰보면서 실력만큼 인성도 대단하다 생각했는데, 아버지도 레전드였,,, &lt;a href=&quot;https://x.com/museun_happen/status/1601505751058599937&quot;&gt;https://x.com/museun_happen/status/1601505751058599937&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;어제 십만년만에 피씨 사고 세팅으로 애를 먹었다. 블투 마우스는 잘되는데 블투 스피커만 연결하면 끊기고 튀고 난리. 바이오스 엡뎃에 드라이버 업뎃에 온갖 난리를 쳤는데, 결론은 메인보드에 함께온 안테나를 연결해야 한다는 거였, 메인보드에 블투 달린 컴터를 첨써봐서 몹시 당황쓰.&lt;/p&gt;
&lt;p&gt;막연하게 7950x 가성비 나쁠거 같아 7900x 질렀는데 사고보니 7950x가 가성비가 더 좋아보이는. 이걸 왜 사고나서 검색하고 앉아있는지는 의문. 앤드벗 그럼에도 빌드 속도가 회사 피씨와는 차원이 다른 수준. 회사피씨도 업글을 해야겠단 생각이,,, 놋북만 쓰다 써보니 소음은 안습 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;많이 늘긴 한 거 같다. 예전엔 그래도 2-3프로 정도 느낌이었는데,, 심심해서 찾아보니 10억초과, 10억 이하, 5억, 3억까지는 대략 구간 인원이 3배씩 증가하는데 3억에서 2억이하로 내려올때는 10배가 늘어남. 그래봐야 근로소득. 참고로 아무쓸모 없지만 10억 초과는 4480명, 0.02프로 ㅋㅋㅋ &lt;a href=&quot;https://x.com/tebica/status/1601795663737634816&quot;&gt;https://x.com/tebica/status/1601795663737634816&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;재벌집 막내아들 덕에 새롬기술을 다시 보게 되었다. 6개월 150배라니 비트코인도 울고 갈 챠트,,, 여담으로 송중기 나오는 드라마는 다소 유치한데 재밌는 감이 없잖아 있음. 빈센조도 그렇고 ㅋㅋ &lt;a href=&quot;https://mobile.newsis.com/view.html?ar_id=NISX20210122_0001315003&quot;&gt;https://mobile.newsis.com/view.html?ar_id=NISX20210122_0001315003&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;스택오버플로가 chatgpt답변을 금지했다고 한다. 그림 분야에서 인공지능을 밴시키는것과 거의 같은 느낌. 스택오버플로의 가장 큰 경쟁 상대는 chatgpt가 아니더라도 결국 인공지능이 될거란 느낌. 오답이라 사이트 품질을 떨어뜨린다는데서 실소를 금치 못했다. 그많은 닝겐들이 올리는 오답은?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;진심 빵터졌 ㅋㅋㅋ &lt;a href=&quot;https://x.com/ppyagdaegaligw1/status/1601968990615908352&quot;&gt;https://x.com/ppyagdaegaligw1/status/1601968990615908352&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;평생 아쉬운 인생이라는데 극공감이,,, 그래도 가끔은 나에게 잘해주자는 생각을 한다. 결국은 무슨 일이 있어도 내가 평생 마주하고 살아야하는게 나 자신이니까... &lt;a href=&quot;https://x.com/leebibim/status/1601816146084515846&quot;&gt;https://x.com/leebibim/status/1601816146084515846&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/bjhWOAHy4tU&quot;&gt;https://youtu.be/bjhWOAHy4tU&lt;/a&gt; gpt4는 파라미터가 100조개. 벌써 설렌다. Bing 신에 탑재가 시급하다. 앞으로는 사용하는 인공지능 버전에 따라 계층이 갈릴지도 모르겠다는 생각이. 올해는 진짜 코파일럿과 챗지피티의 한해가 아니었나 싶다. 알파고가 이세돌을 격파하던 그 때보다 더 충격적인 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;높은 위치에 있어서 뭔가 할 수 있을거 같지만, 충분한 설득력이 없는 것 같음. 카맥옹의 깊은 빡침이 여기까지 전해지는 느낌,, &lt;a href=&quot;https://x.com/GeekNewsHada/status/1604640669242646528&quot;&gt;https://x.com/GeekNewsHada/status/1604640669242646528&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://m.yes24.com/Goods/Detail/115292147&quot;&gt;http://m.yes24.com/Goods/Detail/115292147&lt;/a&gt; 우연찮게 알게되서 읽게됐는데 생각보다 흥미로운 책. 나도 오디오북 1.4배속, 유툽디폴트 1.5배속, 느린거 2배속으로 보는 입장에서 공감되는 부분이 많았다. 이 모든걸 관통하는 키워드 가성비와 실패하기 싫다는 심리가 다소 서글프긴 했지만,,&lt;/p&gt;
&lt;p&gt;다소 반성했던 부분은 답을 안 알려주고 해보라고 하는 직장 상사를 극혐한다는 부분. 맨날 머지가 안되도 되니까 일단 해보라고 했던터라 깊은 찔림이. 근데 직장 상사가 신도 아니고 해보기 전에 답을 어떻게 알까? 내가 만든 코드도 맨날천날 지웠다 붙였다 하는 마당에,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;부트캠프 비판하는 글들이 많이 보이는데, 뭐라도 시켜서 열심히 했다면 나쁘진 않다는 생각. 특히나 시작할때는 질만큼이나 양도 중요하다고 생각하는 입장이라.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;문제를 해결할 수 있음에 기뻐할지, 문제가 벌어진 상황에 절망할지 한끗 차이지만, 전자처럼 생각하는게 쉽지 않은 것 같다. 어릴때 했던 고민들을 지금 보면 시시해 보이는 것처럼 지금 내가 하는 고민도 더 나이가 들었을땐 귀엽게 느껴지기를. 이번 생은 첨이라, 참 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;재택이 회사와 동등한 수준의 개발 환경이 있다고 가정할경우 기술적으로 업무 효율이 떨어질 이유는 1도 없다고 생각하지만 막상 전사적으로 실시해보면 회사 전체적인 업무 능력이 많이 떨어졌다. 해서 신뢰 문제가 커 보임. 가능한 사람이 있겠지만 모두가 가능하진 않다는 머스크 관점이 맞을지도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;코파일럿이나 챗지피티가 채용 시장과는 무관할거란 의견이 많이 보이는데 난 반대. 서버관리를 보면 클라우드가 생기고 한명이 관리할 수 있는 서버 대수가 늘어나면서 자리가 없어지진 않았지만 티오는 전보다 줄었다. 비슷한 전개가 되지 않을까라는 느낌. 심지어 지금은 초기 버전인걸 감안해야.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-12-28&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 11월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2022/11/small-talk-2022-11/</link><guid isPermaLink="false">https://jiniya.net/2022/11/small-talk-2022-11/</guid><pubDate>Sun, 27 Nov 2022 22:57:45 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;브라질, 일본 개발자를 채용헤서 수년간 같이 일해본 결과 나쁘지 않았다. 독자적으로 업무를 처리할 수 있는 사람만 채용하고, 의사 소통은 영어로 진행하면 개발 관련된 부분은 딱히 문제가 없었다. 근무 태만이 큰 문제인데 이는 낮은 수준의 급여와 계약해지 옵션으로 어느 정도 보완된다고 생각. &lt;a href=&quot;https://x.com/Alisvolatprop12/status/1596816722727927808&quot;&gt;https://x.com/Alisvolatprop12/status/1596816722727927808&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;워낙 비용 메리트가 커서 추가 채용하고 싶은 생각도 있고, 실제로 브라질 개발자의 경우 주변에 아는 사람 추천해 달라고 요청해서 몇 명 면접을 보기도 했으나 최종 계약까지 진행되지는 않음. 면접은 다 통과 했으나 이후 연락 두절. 재택이 가속화 되는만큼 글로벌 채용도 가속화 될거라 생각한다.&lt;/p&gt;
&lt;p&gt;브라질은 시차도 기가 막힌게 퇴근할때 업무 할당하면 출근할 때 확인되는 신세계를 경험할 수 있음. 물론 열심히 일할 때 기준으로,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-11-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;벨 부등식 아이디어 소오름,,, 이 우주를 만든 설계자가 있다면 리버싱 당하는걸 좋아할까? 싫어할까? &lt;a href=&quot;https://youtu.be/6QPcmMa052s&quot;&gt;https://youtu.be/6QPcmMa052s&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-11-27&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 10월의 잡담]]></title><description><![CDATA[#0 오늘 배운 신박한 빅엿을 주는 방법,,, 공백 대신 u+3000을 입력하자... 당췌 왜?? 2022-10-05 #…]]></description><link>https://jiniya.net/2022/10/small-talk-2022-10/</link><guid isPermaLink="false">https://jiniya.net/2022/10/small-talk-2022-10/</guid><pubDate>Sat, 29 Oct 2022 19:55:07 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;오늘 배운 신박한 빅엿을 주는 방법,,, 공백 대신 u+3000을 입력하자... 당췌 왜??&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-05&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;골칫거리 사랑니를 뽑았다. 신경이 지나가는 쪽이라 몹시 복잡한 작업이었는데, 대학병원에서 수년간 외과 시술만 전문적으로 수련한 전문의가 한시간만에 깔끔하게 해결해 주었다. 단돈2만5천원, 대한민국 진짜 선진국이다. 강남365치과 사랑한다, 추천 !!!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-08&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;미친 스팀 ㅋㅋㅋ 메뉴에 시스템 종료가 있길래 프로그램 종료시키는 건줄 알고 눌렀더니 원격 컴퓨터가 꺼짐... 망 ㅠㅜ 당췌 먼 게임 프로그램 메뉴에 시스템 종료가 있는건지... 당황쓰,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;그냥 좋으면 말 안해도 알아서들 쓰고 퍼진다. 굳이 열올리며 그럴 필요가 없다는 생각. 세상 젤 쓸모없고 소모적인 논쟁이 언어가지고 좋네 나쁘네 핏대 올리는 일. 언어라는 도구를 가지고 얼마나 가치있는 일을 하느냐가 더 중요하지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;십만년만에 자바스크립트 코딩을 좀 했는데 es6는 완전 신세계... let, const, class, template string, ... 언어들도 상향 평준화되는 느낌적인 느낌.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;초등학교 들어간 딸 아이가 가을 체육대회 달리기에서 3등을 했다길래,,, 아빠는 달리기를 못해서 맨날 꼴지였는데 대단하다고 했더니 ㅋㅋㅋ 3명이서 뛰었다는 대답. 같이 하이파이브를 했다. 유전이란 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;카카오 문제로 엔지니어끼리 갑론을박이 많은데 파고 들어가보면 진실을 만나게 된다. 결국 돈문제,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;뒤늦게 malloc과 sized free 논쟁을 봤다. 화끈한뎅,,, 다만 기승전 인신공격으로 이어진 부분은 아쉬운...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;공개된 장소에 글을 쓴다는 건 불특정 다수의 비판을 감수하겠다는 의미라 생각한다. 그게 싫으면 공개 장소에 글을 안 쓰면 된다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;이 분 요약은 진심 리스펙트,,, 거의 요약계의 장인이 아닌가 싶은... &lt;a href=&quot;https://x.com/GeekNewsHada/status/1583287468081545216&quot;&gt;https://x.com/GeekNewsHada/status/1583287468081545216&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;21세기에 단모음 좌우분리되는 아이패드 앱을 찾기가 이렇게 힘든게 리얼인건가?!,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;분야를 막론하고 좋아하는 일을 돈까지 벌 수 있을 정도로 잘하기란 쉽지 않다는 생각. 좋아하지만 못하거나, 잘하지만 싫어하거나, 심지어 좋아하고 잘하지만 돈이 안되거나인 경우가 대부분. 그런 점에서 어떤 일이든 좋아하는 일을 하면서 돈도 벌 수 있으면 그게 바로 꽃놀이패가 아닌가 싶다. &lt;a href=&quot;https://x.com/sm_park/status/1583922954580406272&quot;&gt;https://x.com/sm_park/status/1583922954580406272&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;스트레스는 정말 만병의 근원이다.ㄴ 내몸이 증명함 ㅠㅜ,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;이런거보면 참 좋은 의도와 실제 현실 사이에 몹시 큰 괴리가 있음을 느낀다. 그리고 실제로 현실 세계에서 잘 작동하는 방식으로 문제를 해결하기란 참 어렵다는 사실도,,, 오죽하면 정의란 무엇인가로 유명한 샌댈 교수가 생각해낸 공정한 방법이 제비뽑기 ㅠㅜ &lt;a href=&quot;https://x.com/sanxiyn/status/1586202555155038209&quot;&gt;https://x.com/sanxiyn/status/1586202555155038209&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;러스트는 좀 신기한게 남들 어렵게하는건 쉽게 되는데 남들 아무렇지도 않게 하는게 의외로 몹시 어려운 부분이 있다. 초기화되지 않은 변수 하나를 쓰기 위해선 굉장한 수준의 삽질이 필요함. &lt;a href=&quot;https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html&quot;&gt;https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;아무리봐도 실패할 이유가 없는 코드가 실패를 해서 몇시간 삽질 끝에 알아낸 결론은 정렬 문제,,, 잊지 않겠다. fxsave. 먼놈에 16바이트 정렬을,,, 글고 api가 이런걸 쓰면 remark정도에는 언급해줘야하는게 예의가 아닌가 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-10-29&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 9월의 잡담]]></title><description><![CDATA[#0 실전 같은 모모를 배우기 보다는 그냥 진짜 실전을 보는게 도움이 된다는 생각. 구글 프로그래머는 테스트를 이렇게 만들었다. 코딩만큼 비밀이 없는 직업도 드문거 같다는 생각. 탐라에 뜬 광고와 번들툴 코드를 번갈아 보다가,,  https…]]></description><link>https://jiniya.net/2022/09/small-talk-2022-09/</link><guid isPermaLink="false">https://jiniya.net/2022/09/small-talk-2022-09/</guid><pubDate>Wed, 07 Sep 2022 12:49:07 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;실전 같은 모모를 배우기 보다는 그냥 진짜 실전을 보는게 도움이 된다는 생각. 구글 프로그래머는 테스트를 이렇게 만들었다. 코딩만큼 비밀이 없는 직업도 드문거 같다는 생각. 탐라에 뜬 광고와 번들툴 코드를 번갈아 보다가,,  &lt;a href=&quot;https://github.com/google/bundletool/tree/master/src/test/java/com/android/tools/build/bundletool&quot;&gt;https://github.com/google/bundletool/tree/master/src/test/java/com/android/tools/build/bundletool&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-09-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;러스트 다 좋은데 xp는 그렇다쳐도 비스타까지 포기한건 좀 안타깝다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-09-07&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 8월의 잡담]]></title><description><![CDATA[#0 어렸을때, 엄마가 우리를 과하게 혼냈단 생각이 들던 날에는 가끔 치킨을 사주셨다. 30년이 훌쩍 넘어 그 마음을 조금은 알겠다. 이 미약한 존재들에게 나의 부족한 인격을 들켜버린것 같아 미안하고 부끄러운 깊은 밤에,,, 2022-08-03 #…]]></description><link>https://jiniya.net/2022/08/small-talk-2022-08/</link><guid isPermaLink="false">https://jiniya.net/2022/08/small-talk-2022-08/</guid><pubDate>Wed, 31 Aug 2022 10:40:14 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;어렸을때, 엄마가 우리를 과하게 혼냈단 생각이 들던 날에는 가끔 치킨을 사주셨다. 30년이 훌쩍 넘어 그 마음을 조금은 알겠다. 이 미약한 존재들에게 나의 부족한 인격을 들켜버린것 같아 미안하고 부끄러운 깊은 밤에,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;여름 방학이라 애들이랑 시간을 보내고 있는데 아이 세대와 우리 세대가 느끼는 공정, 청결의 차이를 많이 느낀다. 30년의 차이가 참 크게 느껴진다. 대한민국이 스피드핵을 쓴건지도...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;생각보다 다들 짧은데? 2) 넷플이 1등? 3) 우버 지못미. &lt;a href=&quot;https://x.com/golbin/status/1555869700768550912&quot;&gt;https://x.com/golbin/status/1555869700768550912&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;2022-08-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;딴건 모르겠지만 인터넷 검열 없애자는 생각은 몹시 칭찬함,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;현실 세계에서 존 카맥이 말하는걸 처음 봤는데 말 엄청 잘하는 사람이었,,, 질답 정리 내용도 몹시 공감됨. 괜히 레전드가 아니넹. 진심 리스펙,, &lt;a href=&quot;https://x.com/sm_park/status/1558341832328691712&quot;&gt;https://x.com/sm_park/status/1558341832328691712&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;구현이야 벤더 맘이겠지만 이게 꼭 룩업 테이블이 필요할거 같지는 않은뎅, 4바이트를 더 할당하고 앞에다 사이즈 기록해 두도록 구현하면 굳이 룩업 테이블이 없어도 되는거 아닌가 싶은... &lt;a href=&quot;https://x.com/sanxiyn/status/1558719133843263488&quot;&gt;https://x.com/sanxiyn/status/1558719133843263488&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;일본 불매 운동으로 철수한 미루가메제면이 땡기는 날. 그나마 한번씩 찾아먹던 곳이었는데 몹시 안타깝다. 부러 오키나와까지 가기는 ㅠㅜ 백종원옹께서 똑같은 프렌차이즈를 만들어줬으면 좋겠다...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;나도 hwp 이력서는 열지 않는 주의인데. 그냥 상식적으로 pdf와 hwp가 그냥 열릴 확률을 비교해 본다면 pdf를 전달하는게 일반적이지 않나 싶은. alz, egg도 마찬가지,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;프롬프트 엔지니어링 인상적,, 저런 고급진 용어가 있었다뉘 ㅋㅋ &lt;a href=&quot;https://x.com/wapj2000/status/1559362123993858048&quot;&gt;https://x.com/wapj2000/status/1559362123993858048&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;인공지능이 그린 그림으로 만든 게임. 프로그래머만 밥줄 걱정할때가 아니구나. 웃픈 현실 ㅎㅎ &lt;a href=&quot;https://x.com/Nao_u_/status/1558595111147425792&quot;&gt;https://x.com/Nao_u_/status/1558595111147425792&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;ms가 만든 안드로이드 서브시스템도 대단하지만 그걸 또 magisk로 루팅하는 인간들도 보통은 아니네. 멋진 신세계,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;의존명사 &apos;등&apos;이 우리 사회에서 이렇게 중요했었던 적이 있었던가 ㅋ 웃프네,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;러스트 입문, 튜토리얼 괜츈한뎅... &lt;a href=&quot;https://rinthel.github.io/rust-lang-book-ko/foreword.html&quot;&gt;https://rinthel.github.io/rust-lang-book-ko/foreword.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;본의 아니게 러스트로 실전 프로젝트를 진행하고 있는데 딴 건 모르겠는데 cargo는 진짜 편하다. 디펜던시 한줄로 어디서든 완벽하게 찾아서 빌드해내는 시스템이란. 경이롭군,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;존잘이 존잘인 이유,,, 형님 이젠 좀 쉬엄쉬엄 하셔도. 몰랐는데 메타도 계속 일하는 거였,, &lt;a href=&quot;https://x.com/GeekNewsHada/status/1564108844568961024&quot;&gt;https://x.com/GeekNewsHada/status/1564108844568961024&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-29&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://m.yes24.com/Goods/Detail/110368348&quot;&gt;http://m.yes24.com/Goods/Detail/110368348&lt;/a&gt; 러스트 인 액션, 러스트를 첫 프로그래밍 언어로 익히는 사람들한테 추천. 이미 시스템 프로그래밍을 많이 해봤고 러스트를 배우려는 사람들에겐 좀 산만한 느낌이 있다. 처음 배우는 사람들에겐 저자가 선택한 고급진 예제들이 찰지게 다가올듯.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-08-31&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 7월의 잡담]]></title><description><![CDATA[#0 https://n.news.naver.com/article/008/000476571…]]></description><link>https://jiniya.net/2022/07/small-talk-2022-07/</link><guid isPermaLink="false">https://jiniya.net/2022/07/small-talk-2022-07/</guid><pubDate>Fri, 29 Jul 2022 09:12:37 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://n.news.naver.com/article/008/0004765717&quot;&gt;https://n.news.naver.com/article/008/0004765717&lt;/a&gt; 몇년간 개발자 몸값 전쟁은 비이성적 과열이었다는 생각. 많이 버는데야 상관 없겠지만 잉여 수익 없이 분위기에 취해서 같이 올린 곳들은 부메랑이 돌아오지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;유치원 논란 글을 보면서 새삼 나를 돌아보게 된다. 새상 참 쉬운게 없다는 생각도. 갠적으로 과도한 쿠션어를 별로 좋아하지 않는 입장. 고맥락 문화도 피곤하다는 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;몇달전 동네 독서 모임 갔다가 전뇌화 얘기가 나왔다. 마인드 업로딩이 가능해서 몸을 바꿔가며 영생을 누릴 수 있다면 하겠냐는 질문. 모두가 예스라고 답할거 같았지만 의외로 한명 빼고는 다 노였다. 벌써 지겨운 인생인데 영원히 산다는 건 지옥 아니겠냐고. 다들 사는게 비슷하구나 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-01&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/MjQjaB-HedA&quot;&gt;https://youtu.be/MjQjaB-HedA&lt;/a&gt; 유툽 알고리즘에 이끌려 듣게 됐는데 가사가 미쳤다. 나는 알지도 못한채 태어나 날 만났고,,, 듣는데 소오름 ㅋ 몰랐는데 바람이분다, 제발 포함 본인 명곡 대부분이 이소라가 직접 작사했다는데 한번더 놀람. 작사 천재였...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;내가 뇌를 보고 있는걸까? 뇌가 나를 보고 있는걸까?, 가 생각나는 트윗... &lt;a href=&quot;https://youtu.be/tdDAb-YNhwE&quot;&gt;https://youtu.be/tdDAb-YNhwE&lt;/a&gt; &lt;a href=&quot;https://t.co/Wm7Kayzr6k&quot;&gt;https://t.co/Wm7Kayzr6k&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-03&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;깃헙의 lg식 행보. 코파일럿이 루아를 지원함에도 공식  문서에 언급이 없음. 너란 뇨석, 정말이지 애정하지 않을수가 없군 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;모든 방법론이 상황과 조직에 맞게 적용되어야 한다는 생각. 구글이 그렇게 한다고 개발자 한두명인 회사가 똑같이 따라하다간 의도하지 않은 결과에 배보다 배꼽이 더 커지는 상황이 벌어질 수 있다. 한때 패턴에 주화입마된 사람들이 많더니 요새는 방법론에 몰입한 사람들이 많은듯. 은탄환은 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.google.com/amp/s/m.mk.co.kr/news/society/view-amp/2021/05/442875/&quot;&gt;https://www.google.com/amp/s/m.mk.co.kr/news/society/view-amp/2021/05/442875/&lt;/a&gt; 존 내시 선생님은 천재성이 명백한 분이었지만 현대수학자는 골방의 책상에 앉아 혼자 몰입하는 모습과 다르다. 개발자도 비슷하다는 생각. 게이츠 횽 혼자서 베이직 인터프리터를 모두 다 만들던 시대와 지금을 비교해 본다면, 현대개발자도 수학자랑 비슷하단 생각.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;간만에 굉장히 독창적인 해커를 보았다. 세상은 넓고 생각하는 방식은 다양하다는 걸 알게되었다. 킹정 !! 그나저나 사라진 dkom의 부활인가? 이 난장판을 치도록 패치가드는 무얼하고 있는 것일까. ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/HYbqG1m8nwk&quot;&gt;https://youtu.be/HYbqG1m8nwk&lt;/a&gt; 마케팅에 진심인 카스. 킹정 !!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-09&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;인력도 부족하고, 자본도 부족한 회사의 경쟁우위는 어디서 만들어 질 수 있을까? 그렇게 만들어진 경쟁우위는 지속 가능할까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;계획된 적자를 낸다는 기업들의 면면을 들여다 보고 있자면 사람들의 그릇, 내지는 깜냥 차이가 확실하게 느껴진다. 미래에 대한 확신이 있기에 가능한 거겠지. 또한, 새삼 100원 투자에서 101원 벌기가 얼마나 어려운 일인지 깨닫는다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-12&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;설렘 주의보 발령 !! 드디어 나왔구낭, 번역이 자비롭기를. &lt;a href=&quot;https://www.aladin.co.kr/m/mproduct.aspx?ItemId=297834576&quot;&gt;https://www.aladin.co.kr/m/mproduct.aspx?ItemId=297834576&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-13&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;푸앵카레는 습관을 정확하게 지키는 사람이었으며, 아침 10시부터 정오까지 오후5시부터 7시까지, 정확하게 하루에 네시간씩 수학을 연구했다. - 기하학 세상을 설명하다, 조던 엘렌버그&lt;/p&gt;
&lt;p&gt;기하학은 아름다울까? 그렇다. 하지만 맨몸은 아니다. 기하학자들은 작업복을 입은 미인을 본다. 당췌 먼소리야 싶어 찾아본 원문은. Is it beautiful? Yes, but not bare. Geometers see Beauty with its work clothes on. 이 책 번역 별로다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;하, 스타필드. 신세계 상품권 안되는 거였... 애들 장난감 사러 왔다가 눈탱이 맞음. 깊은 빡침이 ㅠㅜ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://m.yes24.com/Goods/Detail/101354429&quot;&gt;http://m.yes24.com/Goods/Detail/101354429&lt;/a&gt; 만약 시간이 존재하지 않는다면에 관한 이야기보다 저자의 연구 여정에 관한 이야기가 더 많아 보이는 책. 무튼 요즘은 협업을 잘하는 분들의 연구 성과가 좋은거 같다는 느낌. 단순 시간 관련 물리적인 내용은 동저자의 시간은 흐르지 않는다가 좋아보임.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;블랙의 신부라는 넷플릭스 드라마를 보다 새삼 it 개발자의 거품을 느낀다. 그 옛날 이찬진 대표가 결혼하던 시절 느낌이랄까. 카이스트 출신의 재계 30위 모바일 게임 개발사 대표란 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;헤어질 결심에서 젤 신박했던 장면은 배우들이 파파고로 음성 대화하는 장면. 그리고나서 네이버 웨일 번역이 좋다는 얘기가 있어서 깔아봤는데. 중국어 번역 한정 개인적인 느낌은 크롬 &gt; 엣지 &gt;&gt;&gt; 웨일인듯. 그럼에도 국내에서 진짜 인공지능 하는 업체는 네이버 킹정.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#18&lt;/h2&gt;
&lt;p&gt;과연 개발자들이 스택오버플로 코드를 복붙하면서 오픈소스 라이선스 걱정을 얼마나 할까? 코파일럿 라이선스 논란에 부쳐... &lt;a href=&quot;https://www.google.com/amp/s/fossa.com/blog/analyzing-legal-implications-github-copilot/amp/&quot;&gt;https://www.google.com/amp/s/fossa.com/blog/analyzing-legal-implications-github-copilot/amp/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#19&lt;/h2&gt;
&lt;p&gt;모게임사 김밥 꼬다리 사건이 생각나는. 김밥을 줬더니 꼬다리를 왜주냐고 머라해서 꼬다리를 빼고 줬더니, 꼬다리가 맛있는데 왜 뺐나고 또 머라해서 김밥이 없어졌다는 슬픈 전설. 모두를 만족시키기란 무척 어렵고, 무임승차한 인원을 솎아내도 그런 사람은 계속 나온다는게 함은정,, &lt;a href=&quot;https://x.com/markkimmulgrew/status/1550570341658988545&quot;&gt;https://x.com/markkimmulgrew/status/1550570341658988545&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#20&lt;/h2&gt;
&lt;p&gt;코드나 일에 지나치게 에고를 투영하는건 좋지 않다는 생각. 일은 일이고, 코드는 코드고, 나는 나다. 일과 나를 하나로 생각하고, 코드가 곧 본인이라고 생각하는 사람과 일하는 건 몹시 피곤.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-25&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#21&lt;/h2&gt;
&lt;p&gt;탐라에 코드리뷰 글이 보여서 한마디. 1) 해당 방법론은 생각보다 과대 평가된 것 같다는 느낌적인 느낌 2) 구성원들이 코드에 대한 에고를 빼는게 젤 중요 3) 리뷰 운운하기 전에 제발 잘 작성된 코드를 좀 읽자, 오픈소스 같은...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#22&lt;/h2&gt;
&lt;p&gt;리눅스 커널 코드를 보면서 아 난 졸라 코딩을 잘해, 라고 생각하는 사람은 거의 없다. 그러니 실력이 없다는 생각에 그만둘 필요는 없는거 같다. 난다긴다 해봐야 알파고한테 지는 건 똑같다. 실력 없는 거 같아서 그만뒀다는 얘기에,,, 존버 정신을 기억하자. &lt;a href=&quot;http://www.jiniya.net/ng/2016/06/about-genius/&quot;&gt;http://www.jiniya.net/ng/2016/06/about-genius/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#23&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://googleprojectzero.blogspot.com/2018/10/injecting-code-into-windows-protected.html?m=1&quot;&gt;https://googleprojectzero.blogspot.com/2018/10/injecting-code-into-windows-protected.html?m=1&lt;/a&gt; ppl 인젝션 쉬운게 아니었군. Ms형님들이 니들 쓰라고 만든 기능은 확실히 아닌데,, 하앍...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#24&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.deepmind.com/blog/alphafold-reveals-the-structure-of-the-protein-universe&quot;&gt;https://www.deepmind.com/blog/alphafold-reveals-the-structure-of-the-protein-universe&lt;/a&gt; 인간을 겸허하게 만드는인공지능의 업적, 알파코드는 과연?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-07-29&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 6월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2022/06/small-talk-2022-06/</link><guid isPermaLink="false">https://jiniya.net/2022/06/small-talk-2022-06/</guid><pubDate>Wed, 29 Jun 2022 13:41:25 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;나의 해방 일지 정주행. 추앙, 해방, 그리고 지겨운이란 단어가 인상적이 드라마. 생각을 하게 만드는 대사가 많았다. 워낙 잔잔해서 호불호가 갈릴듯. 나의 해방은 인연을 끊음에 있다고 생각되지만 그러기엔 인생이 또 너무 재미 없을듴. 고로 해방은 몹시 어렵다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-06&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;우리가 태어나서 죽을 때까지 맺는 온갖 관계 중에서 단 하나만이 진정으로 평생 이어집니다. 바로 우리 자신과 맺는 관계입니다. - 내가 틀릴 수도 있습니다, 비욘 나티코 린데블라드&lt;/p&gt;
&lt;p&gt;정말 이상하지 않아? 16년 동안 온갖 교육을 받았는데, 삶이 힘들 때 뭘 어떻게 해야 하는지에 대해서 배운 건 하나도 없다니!’&lt;/p&gt;
&lt;p&gt;17년 동안 깨달음을 얻고자 수행에 매진한 결과, 머릿속에 떠오른 생각을 다 믿지는 않게 되었습니다. 그게 제가 얻은 초능력입니다.&lt;/p&gt;
&lt;p&gt;여자친구와 헤어지고 스님이 되어 20년 가까이 깨달음을 얻는 수행 생활을 하던  우연히 벌레에 물려 혈소판 관련 희귀 질환이 생겨 스님을 그만두고 속세로 돌아온 남자, 이후 사랑하는 여자를 만나 결혼했지만 루게릭 병이 생겨 이른 나이에 세상을 떠나게 된다.&lt;/p&gt;
&lt;p&gt;메멘토 모리가 떠오르는 책. 시한부 판정을 받지 않았을 뿐 사실은 우리 모두 시한부 인생이다. 그걸 잊고 살아갈 뿐.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;저런 실험을 실제로 하다뉘 ㅋㅋ 반전 ㅎㅎ &lt;a href=&quot;https://x.com/idgmatrix/status/1536579785505538049&quot;&gt;https://x.com/idgmatrix/status/1536579785505538049&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-14&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;파인만옹이 저럴진데,, 하물며... &lt;a href=&quot;https://x.com/my_own_bookclub/status/1536722129210658818&quot;&gt;https://x.com/my_own_bookclub/status/1536722129210658818&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-15&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;1993 이후 가장 인기있는 웹사이트 탑10, 가장 놀라운 반전  야후가 아직도 10위권에 있다니 ㅋㅋㅋ  &lt;a href=&quot;https://youtu.be/hNDILCdZmRo&quot;&gt;https://youtu.be/hNDILCdZmRo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;어쩌다 소프트스킬, 하드스킬이 탐라를 도배하게 된 것인가? 뭣이 중헌지보다 진원지가 어딘지가 더 궁금한..&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;의외로 종이접기가 엄청난 두뇌 활동을 요한다. 유툽 0.5배속까지 동원해도 집중 안하면 쫓아가기 어려움. 당췌 이걸 처음 발명한 사람은 뇌구조가 어떤건지,, 겸손함을 배우기 좋은 취미.  자만심이 있다면 마스터 종이접기부터 시작하길 강추. &lt;a href=&quot;http://m.yes24.com/Goods/Detail/93960272&quot;&gt;http://m.yes24.com/Goods/Detail/93960272&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;강신주님의 메달린 절벽에서 손을 뗄 수 있는가를 다 읽었다. 대중강연하던 때의 그를 다소 가볍게 생각했으나 앞으로는 존경하기로 했다. 세상의 모든 철학자가 대단하게 느껴지는 책. 주인으로 산다는것, 나의 본래면목은 무엇인지를 생각해봤다.  &lt;a href=&quot;http://m.yes24.com/Goods/Detail/13465632&quot;&gt;http://m.yes24.com/Goods/Detail/13465632&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/features/copilot/&quot;&gt;https://github.com/features/copilot/&lt;/a&gt; 연봉 100불짜리 인공지능 프로그래머, c++ 3분 테스트 후 감탄과 놀라움을 금치 못하겠... 채용의사 확실함 ㅋㅋ 와 진짜 이제 하산할때가 된 것인가 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;깃헙 코파일럿과 오늘 첫 실전 코딩을 함께 해보았다. 안드로이드 네이티브 c++ 개발. 진짜 미쳤다. 이세돌이 느낀 감정을 이땅의 모든 프로그래머가 느낄 날이 머지 않은듯. 혁신이란 이런 것인가, 와 진짜 얼척이 없다.&lt;/p&gt;
&lt;p&gt;코타나가 권한을 얻으면 주인의 이익을 위해 상대의 코타나를 교묘히 조종하기 시작할 것이고,그결과 직업시장 또는 결혼시장에서의 성공이 점점 더 코타나의 자질에 따라 판가름날 것이다.그래서 최신 버전의 코타나를 소유한 부자들은 구버전을 소유한 가난한 사람들보다 결정적 우위를 점할 것이다.&lt;/p&gt;
&lt;p&gt;더 비싼 최신 버전의 코파일럿을 구독하는 개발자가 코딩을 더 잘할 날이 머지 않은 느낌적인 느낌. 그리고 온라인 코딩 테스트의 의미를 다시 생각해본다. 우리 회사 코딩 테스트는 코파일럿이 몇초도 안되는 시간에 만점으로 통과했다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/xdfmhWQyp_8&quot;&gt;https://youtu.be/xdfmhWQyp_8&lt;/a&gt; 21세기형 나귀,, 데리고 다니면 엄청 팬시하긴 하겠당. 만원 지하철, 엘베만 아니면. 성능좋은 블투 스피커와 구글 어시스턴트 탑재하면 1000불 더 받아도 지금보다 잘 팔릴듴. 보스턴 다이나믹스 이후로 디자인은 저게 최선인지 의문.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-26&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;코파일럿 다 좋은데 주석이 극혐하는 스탈로 달리는 경향이 있다. fopen... // open file. 코멘트 주도 개발이라 어쩔 수 없는듴...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-27&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;아마존 인공지능 코딩 도구. 코드 위스퍼, 코드 구루. 깃헙 코파일럿 보다 지원 언어는 제한적인듯함. 개발에도 이제 바둑처럼 ai류가 나오게 될 것인가? &lt;a href=&quot;https://aws.amazon.com/ko/blogs/korea/how-to-improve-software-development-productivity-ml-based-aws-cloud-services/&quot;&gt;https://aws.amazon.com/ko/blogs/korea/how-to-improve-software-development-productivity-ml-based-aws-cloud-services/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-28&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;&quot;AI 주도 개발&quot; &lt;a href=&quot;https://shinyoungjin.life/dev/ai-driven-development/&quot;&gt;https://shinyoungjin.life/dev/ai-driven-development/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-06-29&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] AI 주도 개발]]></title><description><![CDATA[최근 Github Copilot 출시 소식을 접했다. 소개 페이지를 보면 월 10불, 년 100불에 Python, JavaScript, TypeScript, Ruby, Go, C#, or C…]]></description><link>https://jiniya.net/dev/ai-driven-development/</link><guid isPermaLink="false">https://jiniya.net/dev/ai-driven-development/</guid><pubDate>Tue, 28 Jun 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;최근 Github Copilot 출시 소식을 접했다. 소개 페이지를 보면 월 10불, 년 100불에 Python, JavaScript, TypeScript, Ruby, Go, C#, or C++ 코딩을 도와주는 도구라고 나와있다. 알파고가 등장하기 전이었다면 쳐다보지도 않았겠지만 알파고의 위력을 알았기에 설치를 해보았다. 결과는 실로 놀라웠다. 처음 3분간 테스트 해 본 코드를 첨부하면 다음과 같다. ai+라고 주석이 달린 부분은 모두 인공지능이 작성해서 추가한 부분이다. 살펴보면 대체로 함수 원형만 작성하면 나머지는 모두 코파일럿이 작성했다는 것을 알 수 있다. 사실 여기까지만 보고도 많이 놀랐다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IsPrime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFactorial&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFactorial&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFactorialWithoutRecursion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		result &lt;span class=&quot;token operator&quot;&gt;*=&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetFibonacciWithoutRecursion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IsPalindromeString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; len &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;len &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetMaxValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t cnt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; max &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; max&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			max &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; max&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SortData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t cnt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
				data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
				data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_STUDENT&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; score&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; STUDENT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PSTUDENT&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindStudentScore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PSTUDENT students&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; cnt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;students&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; students&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;score&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;QuickSortData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t cnt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cnt &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pivot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cnt &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	size_t i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	size_t j &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cnt &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; j&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; pivot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; pivot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			j&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; j&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			j&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;QuickSortData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;QuickSortData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cnt &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;테스트 하면서 웃긴 장면이 하나 있었다. 다음 함수다. 중괄호 매치가 끝나지 않은 지점에 인공지능 코딩이 끝난 것이다. 사실 인간 입장에서 여기에서 코드가 종결된 것인지, 아니면 코드를 더 작성해야 하는지 알기가 쉽지 않겠다는 생각이 들었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;QuickSortDataWithoutRecursion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t cnt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;stack&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; stack&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cnt &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; right &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pivot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;left &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; right&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; right &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
				i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; pivot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// 이 시점에 인간 프로그래머의 심정&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// 1) 다 짠걸까? 2) 더 있는걸까? 3) 맞는걸까?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지 샘플 코드를 살펴보면 저건 단순하고 많이 테스트되는 코드들이니까 인공지능이 잘 작성했다고 생각할 수 있다. 어쨌든 나는 여기에서 가능성을 보았다. 그리고 이후 몇일간 실질적으로 회사 코딩을 하는데 적용해서 함께(?!) 코딩을 해보았다. 결과는 실로 놀라웠다.&lt;/p&gt;
&lt;p&gt;내가 테스트한 개발 방식은 총 3가지였다. 안드로이드 C++ 개발, 윈도우 C++ 개발, 윈도우 커널모드 C 개발. 안드로이드와 윈도우 C++ 개발은 굉장히 편리하게 사용할 수 있는 수준이었다. 윈도우 커널모드 C 개발의 경우 주석을 굉장히 디테일하게 작성해야 사용할 수 있는 코드가 도출되었다. 결론부터 총평하자면 무조건 써라. 회사에서 사주지 않으면 개인 비용으로라도 쓰길 추천한다.&lt;/p&gt;
&lt;p&gt;써보면서 가장 편리했던 부분은 끊임없이 레퍼런스를 참고하면서 작업해야 하는 반복적인 코딩이었다. 예를들면 Java 호출 코드를 JNI로 컨버팅하는 류인데 이런 경우 안드로이드 문서와 JNI 스펙 문서를 찾아보면서 일일이 타입, 시그니처를 찾고 생성해서 테스트를 해야 한다. 그렇게 일일이 수작업으로 생성해도 세미콜론이나 달러 기호가 빠져서 정상 동작하지 않는 경우가 많다. 하지만 코파일럿을 사용할 경우 주석만 적당히 입력하면 마법처럼 완벽한 코드를 생성해 냈다. 이게 몇 개 쌓이자 나중에는 일일이 확인을 하지도 않았다. 그냥 얘가 생성한거는 똑바로 생성했겠거니 하는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;두번째로 놀란 부분은 주석이 없어도 인공지능이 문맥을 어느 정도 파악한다는 점이다. 예를들면 내가 특정 조건을 실패로 리턴하면 다음부터는 그 함수 내에서는 그런 류의 판단은 자기가 알아서 성공/실패를 결정한다. 이건 진짜 웃긴데 내가 함수를 작성하다 구조가 마음에 안 들어서 위에서 한두개를 바꾸면 나머지는 다시 알아서 재추천을 해준다. 진짜 얘가 나와 상호작용을 하고 있다는 생각이 절로 든다. 나는 페어 프로그래밍은 시간 낭비라 생각해 많이 해보진 않았지만 그간 일반적인 신입 프로그래머와 코딩 작업이나 코드 리뷰를 해 본 경험에 비추어보자면 코파일럿이 보통의 신입 프로그래머보다는 훌륭하다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;세번째로 놀란 부분은 완벽하진 않지만 힌트를 제공하면 마법처럼 내 의도를 알아차린다는 점이었다. 예를들면 다음과 같은 코드였다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CombineValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buf_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; msb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; lsb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msb &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; lsb&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; buf_size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xFF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이건 아니지라는 생각에 AI가 추가한 코드를 지우고 memcpy(까지 치고 기다리면 다음처럼 올바른 코드를 생성해 낸다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CombineValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buf_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; msb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; lsb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;msb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;lsb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lsb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수가 리턴 값이 있어야 할 거 같아서 다음과 같이 bool 형으로 바꾸고 if까지 입력하고 대기하면 다음과 같은 코드를 생성해 준다. 물론 완벽하진 않지만 내가 뭘 체크하려고 if를 입력했는지를 캐치했다는 점은 놀랍다. 함께 코딩해보면 이런 적이 제법 많다. 실질적으로 내가 의도한 바는 &lt;code class=&quot;language-text&quot;&gt;buf_size &amp;lt; 16&lt;/code&gt;이다. 그럼에도 주석 한 줄 없이 이 정도 코드를 추천했다는 것은 놀랍다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CombineValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buf_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; msb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;uint64_t&lt;/span&gt; lsb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf_size &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;msb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;lsb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lsb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;회사 작업을 하면서 코파일럿이 추가한 코드는 여기에 올린 것처럼 ai+라는 주석을 달았다. 실질적으로 얼만큼 실용적인지를 보고 싶었다. 하지만 이제 더는 달지 않는다. 몇일 작업하면서 이미 코파일럿은 그 자체로 존재 가치를 충분히 증명했기 때문이다.&lt;/p&gt;
&lt;p&gt;나는 코파일럿이 제공하는 프로그래밍 언어를 다 다룰 줄 안다. 다만 주력으로는 파이썬, C++이고 나머지는 서브로 사용하고 있다. 그래서 해당 언어의 라이브러리 코드 등을 세세하게 다 기억하지 못해서 구글을 통해서 검색해가면서 개발하는 경우가 다반다사. 이런 경우에도 코파일럿은 굉장히 큰 도움이 되었다. 왜냐하면 그런 언어로 하는 작업은 실질적으로 아주 간단한 샘플 코드인 경우가 많아서 코파일럿 추천을 받기가 훨씬 쉽기 때문이었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Test&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; String &lt;span class=&quot;token function&quot;&gt;GetFileText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		String text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			FileInputStream fis &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FileInputStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			BufferedReader br &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BufferedReader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;InputStreamReader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fis&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			String line&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; null&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
				text &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; line &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IOException e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
			e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RequestPermission&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String permission&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		ActivityCompat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;requestPermissions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;permission&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ai+&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;예전에 나는 이런 도구에 대해서 조금은 부정적인 의견이 있었다. 이런 도구들이 발전할수록 개발자가 점점 멍청해지지 않을까라는 생각이 있었던 것이다. 그러나 이제는 생각이 좀 바뀌었다. 인공지능이 진화할수록 결국 나를 100% 대체할 것은 자명한 사실이다. 하지만 100% 대체가 되기 전까지는 어쨌든 인공지능의 도움을 받는 것이 다른 사람들과 경쟁을 하는데 도움이 된다는 생각이다. 그리고 코파일럿을 써 본 입장에서 생산성 차이는 엄청나다. 최신형 사이보그 의족을 달고 우샤인 볼트와 대결할 수 있게 된 것이다. 아직도 코파일럿을 안 쓰는 개발자도 많을 것이다. 그런 점에서 사용하는 사람은 비교우위에 설 수 있다는 게 내 생각이다.&lt;/p&gt;
&lt;p&gt;그리고 조심스레 예측해 본다. 앞으로 코파일럿에 적응한 개발자가 늘어날수록 함수명이나 변수명, 주석 등을 코파일럿이 적절하게 추천할 수 있도록 작성하는 것이 능력이 될 것이란 점이다. 아직까지는 주는 사람이고, 보조가 인공지능이지만 인공지능이 주가 될 날도 머지 않았다는 생각이 든다. 인공지능이 추천한 코드를 사용하다, 인공지능에게 코드 리뷰를 받다가, 결국에는 인공지능이 모두 다 작성하게 될 세상. 그런 세상에서 아마도 우린 이런 얘기를 하겠지? 라떼는 사람이 직접 프로그램을 입력하는 시절도 있었다고 말이다.&lt;/p&gt;
&lt;p&gt;진짜 정말 놀라운 세상이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;충분히 발달한 과학 기술은 마법과 구별할 수 없다.&lt;/p&gt;
&lt;p&gt;-- 아서 C. 클라크&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 5월의 잡담]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/2022/05/small-talk-2022-05/</link><guid isPermaLink="false">https://jiniya.net/2022/05/small-talk-2022-05/</guid><pubDate>Sun, 22 May 2022 20:18:05 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;만약 우리가 전체 그림을 볼 수 있다면, 전체 이야기를 안다면, 지금의 막힌 길이 언젠가는 선물이 되어 돌아오리라는 것을 알게 될까? 그것이 삶의 비밀이라는 것을. 우리의 가슴을 뛰게 하는 것은 지나간 길이 아니라 지금 다가오는 길이다. - &amp;#x3C; 좋은지 나쁜지 누가 아는가, 류시화 지음 &gt; 중에서&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-05-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;불교 철학에 관심이 있다고 하니 아는 동생이 강신주님이 요즘 불교 강좌를 한다는 이야기를 전해 주었다. 화두란 무엇인가? 우리는 매달린 절벽에서 손을 뗄 수 있을까?  &lt;a href=&quot;https://youtube.com/playlist?list=PL5WMTtfpXrft7m-zCOjeckIA_PM66_-fA&quot;&gt;https://youtube.com/playlist?list=PL5WMTtfpXrft7m-zCOjeckIA_PM66_-fA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-05-07&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;가능한 한 일찍 결혼하는 것은 여자의 비즈니스이고, 가능한 늦게까지 결혼하지 않고 있는 것은 남자의 비즈니스이다. ― 조지 버나드 쇼, 이 아저씨는 정말 촌철살인...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-05-10&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;배우자 심사 시 고려해야 할 조건, 배우자의 집안, 결혼 시기, 결혼 자금, 신혼여행, 신혼집 가구 배치, 출산 및 육아 계획, 부부 생활을 원만하게 유지하는 법 등에 대해서는 과도하게 신경 쓰는 반면, 대체 결혼을 왜 해야 하는지에 대해서는 진지하게 생각해보지 않는다는 뜻이다 -결혼의 종말&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://m.yes24.com/Goods/Detail/90701972&quot;&gt;http://m.yes24.com/Goods/Detail/90701972&lt;/a&gt; 굉장히 흥미로운 책이었다. 코 파기의 즐거움 만큼이나 특이한 주제로 심도 있는 글을 쓴 책인듯. 대체로 저자의 생각에 동의한다. 결혼 제도를 지탱하는 근간이 양육이라 생각되는데 그에 대한 논의는 별로 없는게 옥의 티라면 티?&lt;/p&gt;
&lt;p&gt;결혼은&lt;br&gt;
혼자 있었으면 있지도 않았을 문제들을&lt;br&gt;
둘이서 함께 해결하려는 시도다.&lt;br&gt;
&lt;br&gt;
― 에디 캔터 Eddie Cantor&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-05-11&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;우주는 생명을 만들었고 생명은 의식을 창조했고 의식은 영속한다. 그 말을 믿고 싶어지는 순간이다.  - &amp;#x3C; 작별 인사, 김영하 &gt; 중에서&lt;/p&gt;
&lt;p&gt;김영하님 소설은 첨 읽어봤는뎅 쏘쏘. 인공지능에 관한 소설인지 뭘 말하고 싶은건지는,,, 인공지능 메타버스 전뇌화 등등 수많은 떡밥을 버무려서... 결론은 버킹검 ㅎㅎ&lt;/p&gt;
&lt;p&gt;나는 말년의 아빠에게, 뇌를 백업하고 영생하지 않겠느냐고, 이미 많은 인간이 그렇게 하고 있다고 말했다. 아빠는 단호히 거부했었다. 육신이 없는 영생을 바라지 않는다고, 인간의 존엄성은 죽음을 직시하는 데에서 온다고 말했다. 그리고 육신 없는 삶이란 끝없는 지루함이며 참된 고통일 거라고도.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-05-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;뼈 때리는 짤 ㅎㅎㅎ &lt;a href=&quot;https://x.com/dungdungwee/status/1528283179651436544&quot;&gt;https://x.com/dungdungwee/status/1528283179651436544&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-05-22&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2022년 4월의 잡담]]></title><description><![CDATA[#0 가끔 왜 보안 프로그래머가 됐냐는 질문을 받는데, 병특 전직 기간 중 합격한 유일한 회사가 보안 솔루션 개발하는 곳이었다. 그때 게임 회사에 합격했다면 게임 개발자가 됐을지도 모른다. 돌아보면 개발엔 진심이었지만 분야에 관해서는…]]></description><link>https://jiniya.net/2022/04/small-talk-2022-04/</link><guid isPermaLink="false">https://jiniya.net/2022/04/small-talk-2022-04/</guid><pubDate>Sat, 30 Apr 2022 06:26:45 GMT</pubDate><content:encoded>&lt;h2&gt;#0&lt;/h2&gt;
&lt;p&gt;가끔 왜 보안 프로그래머가 됐냐는 질문을 받는데, 병특 전직 기간 중 합격한 유일한 회사가 보안 솔루션 개발하는 곳이었다. 그때 게임 회사에 합격했다면 게임 개발자가 됐을지도 모른다. 돌아보면 개발엔 진심이었지만 분야에 관해서는 1도 생각을 안했구나 싶다. 첫 직장은 생각보다 중요하다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#1&lt;/h2&gt;
&lt;p&gt;경관의 피, 뜨거운 피, 야차. 최근에 본 국내산 범죄 영화. 하나같이 별로였다. 뭔가 k영화가 뒷걸음질 치는거 같은 느낌적인 느낌...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-16&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#2&lt;/h2&gt;
&lt;p&gt;콕스 엔데버 35g 추천. 리얼포스 품절이라 사봤는데 나쁘지 않다. 키감 비슷하고, 더 저렴하고, 더 예쁘고, 심지어 마감도 싸구려같지는 않음. &lt;a href=&quot;http://m.danawa.com/product/product.html?code=8345919&amp;#x26;cateCode=112782&quot;&gt;http://m.danawa.com/product/product.html?code=8345919&amp;#x26;cateCode=112782&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-17&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#3&lt;/h2&gt;
&lt;p&gt;코딩테스트가 산으로 가고 있다는덴 공감. 반면에 큰 회사들 입장에서 그거보다 싸고 손쉽고 객관적인 변별력 지표를 찾기도 어렵다는 생각. 세상이 그렇게 돌아가는데에는 다 이유가 있지 않나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-18&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#4&lt;/h2&gt;
&lt;p&gt;pe 파일 구조 보는 툴. 회사 직원이 알려준 툴인데 몹시 칭찬할만한 툴. pe viewer는 빠잉... &lt;a href=&quot;https://hshrzd.wordpress.com/pe-bear/#:~:text=PE%2Dbear%20is%20a%20freeware,works%20for%20windows%20and%20Linux&quot;&gt;https://hshrzd.wordpress.com/pe-bear/#:~:text=PE%2Dbear%20is%20a%20freeware,works%20for%20windows%20and%20Linux&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#5&lt;/h2&gt;
&lt;p&gt;[일상스케치] 누가 성장했을까? - YoungJin Shin &lt;a href=&quot;http://www.jiniya.net/ng/2022/04/who-has-grown-up/&quot;&gt;http://www.jiniya.net/ng/2022/04/who-has-grown-up/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-19&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#6&lt;/h2&gt;
&lt;p&gt;사무실이 덥다. 여름이 오는 중인듯. 누가 뭐래도 지구는 하루에 한바퀴, 일년에 한바퀴 돌 긴 하나보다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-20&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#7&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://brunch.co.kr/@fbrudtjr1/44&quot;&gt;https://brunch.co.kr/@fbrudtjr1/44&lt;/a&gt; 논문급 분석글. 대단하다. 그와중에 배민이 적자 전환했다는 사실이 다소 충격적임. 쿠팡의 미래는 과연?&lt;/p&gt;
&lt;p&gt;&quot;2022 쿠팡, 과연 아마존이 될 상인가?&quot; &lt;a href=&quot;https://shinyoungjin.life/invest/coupang-20022/&quot;&gt;https://shinyoungjin.life/invest/coupang-20022/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-21&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#8&lt;/h2&gt;
&lt;p&gt;&quot;내가 오늘 교통사고를 당할 확률은?&quot; written by YoungJin Shin(@codemaru) &lt;a href=&quot;https://shinyoungjin.life/life/traffic-accident-probability/&quot;&gt;https://shinyoungjin.life/life/traffic-accident-probability/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#9&lt;/h2&gt;
&lt;p&gt;가뭄에 단비같은 느리지만 조금씩이라도 세상이 좋아지는거 같은 늬우스... &lt;a href=&quot;https://x.com/inventeam/status/1517315861828186113&quot;&gt;https://x.com/inventeam/status/1517315861828186113&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#10&lt;/h2&gt;
&lt;p&gt;처벌 또한 비슷한 관점에서 가능하다는 생각. 자유의지가 없다 하더라도 공동체에 피해를 준다면 사회로부터 격리가 가능하지 않을까? 감금하는 정신병원같이...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-22&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#11&lt;/h2&gt;
&lt;p&gt;자녀가 공부를 안해서 화가 난다는 친구 이야기를 들으며 공부는 스스로 해야지 시킨다고 되는게 아니니 마음쓰지 말라고 했다. 끝내 입장차를 좁히지 못했는데 지나서 생각해보니 난 주변에서 공부를 못했지만 성공한 케이스를 너무 많이 봤고, 그 친구는 그런 사례가 없었던게 차이라는 생각.&lt;/p&gt;
&lt;p&gt;잘하면 좋겠지만 안되는걸 억지로 시키면서 스트레스 받을 필요는 없다고 본다. 정치인들만 봐도 자식 교육이 얼마나 힘든지를 알 수 있다. 하물며 일반인들이야. 건강하고 착하면 된거다. 물론 그마저도 욕심이겠지만. 이런거보면 무자식이 상팔자라는 옛말이 하나 틀린게 없다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#12&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://m.yes24.com/Goods/Detail/108890677&quot;&gt;http://m.yes24.com/Goods/Detail/108890677&lt;/a&gt; 철학자의 불교공부 노트, 크게 이론편 수행편 나눠져 있다. 수행편은 그대로 노출된 한자어가 많아 마냥 읽기 편하진 않음. 그럼에도 보통 철학자들은 수행 관련 내용은 논하지 않았던 점을 고려한다면 새로웠당. 관연 평안에 이를수 있을까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-23&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#13&lt;/h2&gt;
&lt;p&gt;삶은 때로 도둑보다 더한 것을 우리에게 선사한다. 그때는 자신이 낯선 별에 불시착한 갈 곳 없는 영혼처럼 느껴진다. 산티아고는 어디든 갈 수 있는 바람을 부러워한다. 그리고 문득 깨닫는다. 모험을 떠나지 못하게 자신을 가로막는 것은 아무것도 없다는 사실을. -좋은지 나쁜지 누가 아는가,류시화&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#14&lt;/h2&gt;
&lt;p&gt;지금 요구되는 것은 ‘나를 괴롭히지 마세요’ ‘함부로 대하지 마세요’입니다. 예전 같았으면 영원한 상사였을 사람이 지금은 한시적 동료인 것입니다. 동료가 내게 무례하게 구는 걸 참을 수 없고, 심지어 그 관계마저 한시적이니 훗날을 기약하는 미덕을 굳이 발휘하지 않습니다. - 그냥 하지 말라&lt;/p&gt;
&lt;p&gt;상사가 아니라 동료가 되면 가장 무서운 게 뭔지 아십니까? 상대가 일하지 않는 것에 분노한다는 것입니다. 최근 데이터에서 상사와 관련해 ‘무능’이라는 말이 가장 많이 나오는 이유죠. 예전에는 상사가 일 안 한다고 뭐라 하지는 않았어요. - &amp;#x3C; 그냥 하지 말라, 송길영 &gt; 중에서&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#15&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://m.yes24.com/Goods/Detail/103841300&quot;&gt;http://m.yes24.com/Goods/Detail/103841300&lt;/a&gt; 별기대 없이 시작했는데 생각보다 굉장히 재밌는 책, 꼰대들에게 꼭 추천해주고 싶은 책. 우리는 앞으로 무인세상에서 혼자 오래 살게 될거라고 한다. 비대면이 아니라 선택적 대면이란 말에 빵터졌다.&lt;/p&gt;
&lt;p&gt;앞으로의 시대는 생각 없는 근면이 아닌 궁리하는 성실함이 필요합니다. ‘그냥 하지 말라Don’t Just Do It’고 말씀드리는 이유입니다. - &amp;#x3C; 그냥 하지 말라, 송길영 &gt; 중에서&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#16&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/veRuWVimnOE&quot;&gt;https://youtu.be/veRuWVimnOE&lt;/a&gt; 허태균 교수, 김정운 교수 이후로 비슷한 컨셉으로 방송가에서 뜨는 교수님인듯한 느낌적인 느낌. 공통점. 일단 웃김,,,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-24&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;#17&lt;/h2&gt;
&lt;p&gt;경험하지 않고 얻은 해답은 펼쳐지지 않은 날개와 같다. 삶의 문제는 삶으로 풀어야 한다. - &amp;#x3C; 좋은지 나쁜지 누가 아는가, 류시화 지음 &gt; 중에서&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2022-04-30&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 내가 오늘 교통사고를 당할 확률은?]]></title><description><![CDATA[출근길, 이렇게까지 막힐 길이 아닌데 터무니 없게 차들이 막혀 있다. 한참을 지나오니 3차선 길에 교통사고가 나서…]]></description><link>https://jiniya.net/life/traffic-accident-probability/</link><guid isPermaLink="false">https://jiniya.net/life/traffic-accident-probability/</guid><pubDate>Fri, 22 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;출근길, 이렇게까지 막힐 길이 아닌데 터무니 없게 차들이 막혀 있다. 한참을 지나오니 3차선 길에 교통사고가 나서 2개 차로가 막혀 있었다. 그렇게 사고를 지나 한참을 달려 톨게이트를 지나는데 또 거북이가 된 차선. 멍밍? 톨게이트 위 표지판에 전방에 사고로 1, 2차선이 막혀 있다는 글귀가 스크롤 된다. 비도 오지 않고, 눈도 오지 않고, 단지 조금 흐린 날씨인데 왜케 사고가 많은 것일까?, 라는 생각도 잠시. 사고가 나지 않아서 다행이란 생각이 오버랩됐다. 그러자 마음이 한결 편해진다.&lt;/p&gt;
&lt;p&gt;그렇게 또다시 막힌 길을 지나 열심히 달려서 상습 정체 구간에 도착했다. 느림보가 된 차안에서 갑자기 궁금증이 밀려온다. 오늘 내가 교통사고를 당할 확률은 얼마일까, 라는 생각. 어댑티브 크루즈를 켜두고 &quot;교통사고 확률&quot;같은 키워드로 포풍 검색을 해본다. 대체로 우리나라 사람이 평생 교통사고를 1번이라도 당할 확률은 나오지만 오늘 내가 교통사고를 당할 확률이 얼마인지는 나오질 않았다. 그래서 한번 역산을 해보기로 했다.&lt;/p&gt;
&lt;p&gt;이어지는 모든 내용은 나의 부족한 수학 지식에 기반한 것이므로 오류 및 잘못된 내용이 포함되어 있을 수 있다는 점 명심해주길 바라면서 계산을 한 번 시작해보자. &lt;a href=&quot;https://n.news.naver.com/mnews/article/086/0001996511&quot;&gt;이 기사&lt;/a&gt;에 따르면 우리나라 국민이 일평생 1번이라도 교통사고를 당할 확률은 35.2%라고 한다. 우리나라 국민의 평균 수명은 &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_countries_by_life_expectancy#List_by_the_World_Health_Organization_(2015)&quot;&gt;이 자료&lt;/a&gt;에 따르면 83.3세라고 한다. 계산의 편의를 위해서 80년이라고 가정한다.&lt;/p&gt;
&lt;p&gt;일평생 한번이라도 교통사고를 당할 확률이 35.2%라는 말은 일평생 교통사고를 한번도 당하지 않을 확률은 64.8%라는 말이 된다. 일평생 교통사고를 한번도 당하지 않을 확률은 오늘 내가 교통사고 당하지 않을 확률을 사는 기간 만큼 곱한 것이 된다. 결국. 0.648의 80제곱근을 구한다면 한해동안 내가 교통사고를 당하지 않을 확률, 29200(80*365)제곱근을 구한다면 오늘 내가 교통사고를 당하지 않을 확률이 나온다. x의 n제곱근은 x^(1/n)으로 구할 수 있다고 한다. 그렇게 계산을 해보면 0.648^(1/29200) = 0.999985가 나온다. 마침내 내가 오늘 교통사고를 당하지 않을 확률에 도달했다. 99.9985%, 교통사고를 당할 확률은 그 반대이니 0.0015%가 될 것이다.&lt;/p&gt;
&lt;p&gt;0.0015%라, 생각보다 확률이 너무 낮은 느낌적인 느낌. 인구가 5천만이라고 가정하면 하루에 확률적으로 750명 가량이 교통사고를 경험할 수 있게 되고, 그런 사람들 중 최소 4명을 내가 오늘 아침에 목격한 셈이 된다.&lt;/p&gt;
&lt;p&gt;오늘 하루, 교통사고 없이 무사히 출근하게 되어 억세게 운이 좋다고 생각하려고 하였으나 그렇게 생각하기에는 무리가 있어 보이는 확률 같다. 확률을 본다면 퇴근길에도 난 교통사고를 겪지 않을 것 같다. 그렇게 오늘도 보통 사람이 보통의 확률로 하루를 살아간다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 2022 쿠팡, 과연 아마존이 될 상인가?]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/invest/coupang-20022/</link><guid isPermaLink="false">https://jiniya.net/invest/coupang-20022/</guid><pubDate>Thu, 21 Apr 2022 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://brunch.co.kr/@fbrudtjr1/44&quot;&gt;쿠팡은 왜 적자를 탈출할 수 없는걸까?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이런 글을 보면 정말 애널리스트도 힘들겠구나 하는 생각이 든다. 반도의 흔한 블로거의 분석글 수준이 정말 넘사벽이다.&lt;/p&gt;
&lt;p&gt;쿠팡은 몇년전부터 개인적으로 몹시 미래가 궁금했던 기업 중 하나였다. 왜냐하면 저 사업 모델이 성공할까? 하는 생각도 있었고, 소비자로써는 너무나 지나치게 편리했기 때문이다. 상장전에는 실패할 확률이 높다고 생각했지만 보란듯이 나스닥에 성공적으로 상장해서 어마어마한 밸류에이션을 받는 걸 보고 나의 예측이 빗나갔음을 인정해야 했다.&lt;/p&gt;
&lt;p&gt;최근에 멤버십 가격을 올리고, 반품 정책을 변경하는등 서서히 비용 지출에 신경을 쓰는 모습으로 변신하고 있는 쿠팡. 과연 그들은 흑자 전환을 할 수 있을까? 안타깝게도 난 위 분석글과 같은 이유로 쉽지 않을거라 생각한다. 아래는 분석글 내용 요약.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;쿠팡은 2021년 매출 22조, 영업손실 1조8700억을 기록&lt;/li&gt;
&lt;li&gt;국내 소매시장 온라인 침투율 28.9%로 거의 포화상태, 플레이어 너무 많음, 흑자 거의 없음&lt;/li&gt;
&lt;li&gt;물류센터 자동화가 추후 규모의 경제를 달성하는데 중요함, 징동닷컴 85%, 슥 80%, 쿠팡 10% 수준&lt;/li&gt;
&lt;li&gt;멤버십은 흑자지만 거기서 나오는 비용은 조족지혈&lt;/li&gt;
&lt;li&gt;캐시카우 부재&lt;/li&gt;
&lt;li&gt;신규 사업은 모두 돈먹는 하마&lt;/li&gt;
&lt;li&gt;번외) 배민이 2019년부터 적자전환, 퀵커머스 진출로 유추 (충격)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그리고 원글에는 없는 개발자라면 모두 아는 아마존과의 결정적 차이, 아마존은 AWS를 팔고, 쿠팡은 AWS를 쓴다는 거. 심지어 베조스 다음 사장이 AWS 수장이 되었다. 그리고 다른 하나는 직고용 중인 천문학적 수준의 택배기사들. 규모가 커질수록 직고용이 늘고, 그렇게 늘어난 인원은 쿠팡이 바라는 규모의 경제를 달성하는데 거대한 허들이 되지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;이 모든 이야기에도 불구하고 로켓배송, 사랑한다.&lt;br&gt;
쿠팡의 적자만큼 소비자에겐 혜자라는 의미가 되기도 한다.&lt;/p&gt;
&lt;p&gt;대한민국 유니콘 신화가 계속 이어지기를...&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] Begin Again]]></title><description><![CDATA[2000년도 인터넷 수업 과제로 시작한 홈페이지가 이렇게 오랜 기간 이어질 줄은 몰랐다. 그러고보니 2…]]></description><link>https://jiniya.net/life/begin-again/</link><guid isPermaLink="false">https://jiniya.net/life/begin-again/</guid><pubDate>Wed, 20 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/hWYM5QEt0Fg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;2000년도 인터넷 수업 과제로 시작한 홈페이지가 이렇게 오랜 기간 이어질 줄은 몰랐다. 그러고보니 20년간 줄기차게 이어진 나의 유용한 취미 중 하나가 공개된 장소에 글을 쓰는 건 아니었나 싶다. 뜸한 시절도 있었고, 열정적으로 올린 시절도 있었지만 어쨌든 중요한 건 아직까지 이어지고 있다는 사실일 것이다.&lt;/p&gt;
&lt;p&gt;그간 자작 게시판, phpBB, 태터툴즈, 워드프레스, 지킬을 거쳐서 이번에는 개츠비로 정했다. 요즘 유행하는 github 저장소, cloudflare 배포 방식을 사용해보려고 도메인도 새로 만들어봤다. 이제부터 얼만큼 남아 있을지 모를 나의 인생 후반전의 기록을 여기에 남겨볼까 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;가장 훌륭한 시는 아직 씌어지지 않았다.&lt;br&gt;
가장 아름다운 노래는 아직 불려지지 않았다.&lt;br&gt;
최고의 날들은 아직 살지 않은 날들.&lt;br&gt;
가장 넓은 바다는 아직 항해되지 않았고,&lt;br&gt;
가장 먼 여행은 아직 끝나지 않았다.&lt;br&gt;
불멸의 춤은 아직 추어지지 않았으며,&lt;br&gt;
가장 빛나는 별은 아직 발견되지 않은 별.&lt;br&gt;
무엇을 해야 할지 더 이상 알 수 없을 때&lt;br&gt;
그때 비로소 진정한 무엇인가를 할 수 있다.&lt;br&gt;
어느 길로 가야 할지 더 이상 알 수 없을 때&lt;br&gt;
그때가 비로소 진정한 여행의 시작이다.&lt;/p&gt;
&lt;p&gt;– 진정한 여행, 나짐 히크메트&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;지금이 비로소 내 인생의 진정한 여행을 시작할 때인 것 같은 느낌...&lt;br&gt;
아직 오지 않은 최고의 날들을 기다리며 비긴 어게인...&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 누가 성장 했을까?]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2022/04/who-has-grown-up/</link><guid isPermaLink="false">https://jiniya.net/ng/2022/04/who-has-grown-up/</guid><pubDate>Tue, 19 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;회사를 시작하고 직원을 채용하고 그들과 함께 일을 하면서 가장 많이 들은 불만 사항중에 하나는 방목이다. 나는 꼰대라 그렇게 생각을 하지 않지만 직원들은 회사가 본인들을 충실하게 교육시켜서 연차에 알맞게 총총 성장을 시켜주길 바라는 것 같다. 물론 나도 그런 생각을 안해본 사람은 아니다. 창업을 했던 초창기에는 어렸고, 열정이 있었다. 밤을 새면서 A부터 Z까지 알려주려고 해본 적도 있었다. 응당 개발 속도는 달팽이보다 느려졌다. 그때마다 빨리 가려면 혼자 가고, 멀리 가려면 함께 가라는 말을 주문처럼 되내이면서 자기 위안을 삼았다.&lt;/p&gt;
&lt;p&gt;하지만 현실은 녹록치 않았다. 그 속도로 가다간 멀리는 고사하고 당장 한두달만돼도 굶어죽을 것 같았다. 속도도 느렸지만 품질도 문제였다. 충실하게 A부터 Z까지 교육을 받고 만든 친구는 성장했을지 모르겠지만 회사는 제자리였다. 아 이렇게 해서는 달은 고사하고 대기권 통과도 힘들겠구나 하는 생각이 절로 들었다. 결국 나는 방목을 택했다. 할 수 있는 것들만 시켰고, 못한다는 것은 할 수 있는 다른 사람들에게 부탁했다.&lt;/p&gt;
&lt;p&gt;그렇게 개발 속도가 올라갔고 몇해가 지났다. 사내 이슈 트래커는 해결되지 않은 문제들로 가득찼고 제법 오래 일한 직원들과 이야기를 했다. 돌아온 답은 방목. 교육을 받지 못해서 직원들이 성장을 못했다는 이야기였다. 그리고 주된 문제점은 쉬운 문제들은 연차가 쌓인 사람들이 다 빨리 해버리고 나니 어려운 문제만 남아서 아무도 해결을 못한다는 이야기들이 많았다. 그래서 쉬운 이슈들을 처리하면서 배울 수 있도록 해야 한다는 솔루션이 나왔다. 그래? 그럼 그렇게 해볼까? 회사가 그렇게 배고픈 시절은 아니었기에 해볼만한 시점이기도 했다.&lt;/p&gt;
&lt;p&gt;쉬운 일감들이 할 수 있을만한 사람에게 스스로 배정되었고, 그들은 차곡차곡 문제를 해결하고 코드를 제출했다. 나는 빨간펜 선생님처럼 리뷰를 하고 머지를 했다. 당연한 소리겠지만 과정은 아름다웠지만 속도는 거의 그린란드 상어가 성장하는 속도만큼 느려졌다. 그래도 이 시기만 거친다면 직원들이 충분히 성장할거란 기대를 해보았다. 그렇게 제법 오랜 시간을 우리는 아주 느려터졌지만 개발 교과서에 나오는 우아한 방식으로 업무를 진행해 보았다. 결과는 당황스러웠다. 내가 봤을 때는 방목일때나 빨간펜일때나 성장의 속도와 범위는 비슷한것처럼 보였다. 더 안타까운 사실은 그 아름다운 시기를 함께 경험한 직원들 중 지금까지 근무하는 사람이 별로 없다는 사실이다.&lt;/p&gt;
&lt;p&gt;그렇게 오랜 시간을 지켜보고 이 방법 저 방법 해보고 내린 결론은 이렇다. 누가 성장했을까? 1) 회사 업무와 관련된 도메인에 관심이 있는 사람 2) 자기 동기부여가 되는 사람 3) 주도적으로 업무 처리가 가능한 사람 4) 열린 마인드를 가진 사람 5) 긍정적인 사고를 하는 사람들이 성장했다.&lt;/p&gt;
&lt;p&gt;우리는 게임 보안 회사다. 입사 후에 가장 많은 성장과 기여를 한 친구들을 보면 대체로 입사 전부터 게임 보안에 관심이 있거나 그런 쪽의 작업을 한 친구들이 많았다. 사전에 관심이 많았다는 이야기는 스스로 학습할 가능성이 높다는 것을 담보하기도 하고, 입사 시점부터 경력직과 비슷한 효과를 가지기도 한다. 역대 입사한 직원들을 모두 나열해놓고 기여도가 높은 순서대로 정렬을 해본다면 거의 이 순서와 동일한 순서가 나온다. 그러니 애초에 도메인에 관심이 있다는 건 그 사람이 입사 후 성장할 가능성이 높이다는 가장 강려크한 지표 중에 하나라 할 수 있겠다.&lt;/p&gt;
&lt;p&gt;칭찬은 고래도 춤추게 한다지만 현실은 그리 녹록치 않다. 회사란 공간은 칭찬은 인색하고, 평가는 냉혹하다. 이런 환경에서 버티기 위해서는 자기 동기부여가 되는 사람들이 유리하다. 우쭈쭈해줘야 뭔가 에너지를 받을 수 있는 사람들은 오래 버티기가 힘들다. 또한 계속 우쭈쭈하기도 힘들다. 칭찬은 고래도 춤추게 한다는 생각으로 그런 걸 남발하면 종국에는 고등학교 써클의 축제 출품작 같은 결과물을 마주하게 될 가능성이 농후하다. 그러니 스스로 동기부여가 되는 사람들을 찾는 것이 여러모로 유리하다.&lt;/p&gt;
&lt;p&gt;주인 의식을 가지자는 말도 꼰대의 대표적인 언어가 된 요즘이다. 하지만 안타깝게도 성장하는 직원들은 대체로 주도적인 업무 처리를 하는 경우가 많았다. 우리 회사에 남겨진 대부분의 좋은 유산들은 회사에서 어떤 어떤 업무를 강제로 시켜서 남겨진 것은 거의 없다. 실무자들이 업무를 진행하면서 본인이 불편을 느끼거나, 다른 사람들이 업무 진행하는 것을 보면서 답답한 마음에 만든 것들이 남겨진 경우가 대부분이다. 주도적인 업무 처리를 하지 않는 사람들은 대체로 시킨대로 하거나, 현재 상태에서 개선을 하려는 의지가 없기 때문에 성장 기회를 얻을 가능성이 제한적이다.&lt;/p&gt;
&lt;p&gt;요즘 개발자 면접을 보면 이런 말을 꼭한다. 우리 회사는 이것도 하고, 저것도 하고, 심지어 지금은 말은 안했지만 나중에는 이만저만한 업무도 해야 할 수 있다. 구직자들이 극혐한다는 풀스택 이야기다. 나는 그들을 혹사시키려고 이런 구질구질한 이야기를 하는 것은 아니다. 작은 회사라는 것이 언제 어떤 업무를 하게될지 모르기 때문에 애초에 이야기를 하는 것이다. 입사 후 성장한 친구들도 살펴보면 대체로 열린 마인들을 가진 친구들이 많았다. 나는 테스터니까 테스트만 하겠다 라든지, 나는 C++ 개발자니까 C++만 하겠다는 친구들은 그렇지 않은 친구들보다 성장 범위가 제한되는 경우가 많았다. 또한 개인적인 경험에서도 다양한 개발을 해보는 것이 도움이 됐다. 왜냐하면 다른 분야나 시스템에서 좋은 것들을 배우게되면 원래 알던 분야에도 적용할 수 있기 때문이다. 그리고 이제는 제법 유명한 이야기지만 깊이 파기 위해서는 애초에 넓게 파기 시작해야 한다. 물론 레이저는 예외다.&lt;/p&gt;
&lt;p&gt;끝으로 긍정적 사고다. 긍정의 배신과 같은 책들도 있지만 어쨌든 긍정적 사고는 본인 내부에 가진 에너지를 보다 오래 보존시키는데 중요한 역할을 한다. 보안이라는 업무를 오래 하다보면 현타가 오는 시점이 있게 마련이다. 매번 대응 한다고 해도 해킹툴은 쏟아지고, 고객들의 불만은 미어터지고, 지원팀의 압박은 거세다. 나에게 감사한 사람은 아무도 없는 것 같은 순간이 찾아온다. 사실 그런 일들은 입사 시점부터 있어 왔겠지만 현타가 오는 시점은 본인에게 있던 긍정성이 고갈되는 순간인 경우가 많았다. 성장은 고통을 수반하고, 고통의 과정을 이겨내기 위해서는 결국 긍정 에너지가 어느 정도 필요 조건이 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;이제 방목과 교육을 다시 생각해본다. 도메인에 대한 관심, 자기 동기부여, 주도적 업무처리, 열린 마인드, 긍정적 사고와 같은 것들이 교육될 수 있는 것일까? 나는 그렇지 않다고 생각한다. 왜냐하면 이것들은 개인의 취향, 성격, 태도, 기질과 굉장히 밀접한 관련이 있는 것들이기 때문이다. 따라서 불행하게도 이런 종류의 것들은 입사 전부터 결정된 것들이고, 입사 후에도 변할 가능성은 별로 없다. 달리 말하면 어이없게도 성장할 사람은 입사 시점에 이미 거의 다 결정되어 있다는 말이다. 방목을 하든, 교육을 하든, 애자일을 하든, 코드리뷰를 하든, TDD를 하든, 세미나를 하든 하지 않든 말이다. 그 모든 것들을 하든지 하지 않든지 진짜 성장하는 사람은 그런 것들과는 상관이 없을 확률이 높다. 물론 애초에 좋은 기질을 가진 사람들에게 적절한 환경이 주어진다면 부스터가 될 수는 있을 것이다. 하지만 그 또한 미치는 영향력은 이러한 기질적 특성보다는 작은것처럼 보였다.&lt;/p&gt;
&lt;p&gt;결국 인사가 만사고 채용이 중요하다는 관점에서 이 사실을 역으로 적용하면 이렇다. 도메인에 관심이 있어 보이는 똑똑한 사람을 뽑는게 최선이다. 나머지 것들은 알아낼 수 있다면 좋겠지만 면접 과정에서 알아내기란 몹시 어려운 부분에 속한다. 반면에 수습 기간에는 알아낼 확률은 높아지겠지만 3년도 아닌 3개월로도 실상 알기가 어렵다. 어쨌든 면접 및 수습 과정을 통틀어 최대한 이 5가지 항목을 잘 관찰하는 것이 중요하다고 할 수 있겠다.&lt;/p&gt;
&lt;p&gt;개인의 관점에서 이 사실에서 한가지 교훈을 얻자면 똑같은 개발을 하더라도 관심있는 도메인이 어디인지는 한번쯤 생각해 보는게 도움이 된다는 점일 것이다. 평생 게임이라곤 한번도 안해본 사람이 게임 회사에 취직하는 것도, 주식은 도박이라고 생각하는 사람이 HTS 개발하는 업체에 취직하는 것도 고역일 것이고, 거기서 본인이 성장하기는 정말 어려울테니 말이다. 딜러, 힐러가 뭔지도 모르고, 이동평균선이 뭔지도 모르는 사람과 입사 전부터 딜힐 사이클과 각종 계산 방식 및 그것들이 가진 문제점에 대해서, 볼린져 밴드가 뭔지 P/E가 뭔지, 또 각종 지표의 문제점과 한계에 대해서 이미 모두 다 꿰고 있는 사람의 차이란 당신이 생각하는 것보다 클 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;노력은 해야겠지만 애쓰지 마. 될 일은 되고 안될 일은 안된다.&lt;br&gt;
— 시지프스 EP.06&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;당신의 채용에, 당신의 입사에 성장 열매가 가득 하기를…​&lt;br&gt;
건투를 빈다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 제갈량은 과연?]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2022/04/zhuge-liang/</link><guid isPermaLink="false">https://jiniya.net/ng/2022/04/zhuge-liang/</guid><pubDate>Fri, 15 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;삼국지는 정말 흥미로운 책이다. 온갖 사람들이 등장해서 펼치는 활극도 대단하지만 그게 또 일부는 실화라는 점은 더 말문이 막히게 만든다. 그런 삼국지 인물 중에서도 최애하는 한명을 꼽으라면 단연 제갈량이다. 유비와 함께 가장 많은 사람들이 사랑하는 캐릭터가 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;와이프 미모 빼고는 모든 걸 다 가졌다는 제갈량을 보면서 항상 궁금한게 있었다. 그렇게 똑똑하고 세상 이치를 잘 아는 그가, 왜 하필 유비를 따라 갔을까? 삼고초려해서? 결국 천하통일에 실패 했다는 관점에서 생각해 보자면, 1) 모르고 따라 갔다면 그의 수읽기가 부족한 것이고, 2) 어짜피 실패할 걸 알고 따라 갔다면 왜 따라간 것일까? 하는 의문들 가지지 않을 수 없다.&lt;/p&gt;
&lt;p&gt;그리고 또 한 장면, 출사표…​ 그는 줄기차게 출사표를 내고 사마의에 도전하지만 결국 하늘과 시간은 무심하게도 그를 버렸다. 1) 그는 질 걸 알면서도 줄기차게 출사표를 던지고 도전한 것일까? 2) 아니면 진심으로 이길 생각으로 나섰지만 패배한 것일까?&lt;/p&gt;
&lt;p&gt;자신의 사후 세계 전략까지도 지시할만큼 대단했던 그는 자기 운명을 알면서도 겁없이 도전한 것일까? 아니면 그냥 생각보다 멍청했던 것일까? 제갈량을 보면 항상 그런 스타크래프트 게임이 생각난다. 템플러 드랍해서 일꾼 테러하고, 리버 드랍해서 재미보고, 다크템플러로 씐나게 테러하고, 신은 있는대로 다 내고 재미있게 즐겼지만 결국 물량에 밀려서 패배하는 게임…​ 전 인생의 관점에서 바라본다면 과정이 재밌었던 프로토스가 이긴 게임일까? 꾸역꾸역 막고 버텨서 역전한 테란이 이긴 게임일까? 우리는 어떤 게임을 하고 있는 것일까?&lt;/p&gt;
&lt;p&gt;따뜻한 동남풍이 불어온다…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 21세기 게임 보안 프로그래머의 변천사]]></title><description><![CDATA[세상이 MS와 MS가 아닌 것들로 양분되던 시기에 개발을 시작했던 나는 참 편했다. MS가 워낙 독점적이었기에 MS가 아닌 것들은 사실 거들떠 볼 필요도 없던 시절이었다. 단지 MS것 내에서 이거냐 저거냐에 따라 차이가 있을 뿐. 그렇게 2…]]></description><link>https://jiniya.net/ng/2022/04/21st-game-security-programmer/</link><guid isPermaLink="false">https://jiniya.net/ng/2022/04/21st-game-security-programmer/</guid><pubDate>Thu, 14 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;세상이 MS와 MS가 아닌 것들로 양분되던 시기에 개발을 시작했던 나는 참 편했다. MS가 워낙 독점적이었기에 MS가 아닌 것들은 사실 거들떠 볼 필요도 없던 시절이었다. 단지 MS것 내에서 이거냐 저거냐에 따라 차이가 있을 뿐. 그렇게 20년의 세월이 지난 요즘은 MS가 너무 초라해졌고 개발자는 넘나 피곤해졌다. 재미로 정리해보는 시대별 변천사…​&lt;/p&gt;
&lt;h3&gt;2002&lt;/h3&gt;
&lt;p&gt;windows 95/98만 없으면 세상 편해질 것 같았던 시절, VxD는 인간이 코딩하라고 만든 것일까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsWindows9x()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2008&lt;/h3&gt;
&lt;p&gt;windows 2000에는 뭐가 이렇게 부족한게 많은 건지. 2000만 제거할 수 있다면 제품의 일관성을 유지하기가 한결 편할 것 같았던 시절.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsWindows2k()
IsWindows9x()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2015&lt;/h3&gt;
&lt;p&gt;어느덧 XP는 구시대의 유물이 되었고, 지원 안되는 기능은 너무나 많고, 심지어 시스템 고유 기능들 조차도 지원 안되는 것들이 많았던 시절. 슬슬 컴파일러들도 XP를 손절각을 보던 시기.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsWindowsXP()
IsWindows2k()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2016&lt;/h3&gt;
&lt;p&gt;64비트 운영체제가 일반화 되는 시기. 하지만 아직 대부분의 프로그램은 32비트. wow64처리가 안드로메다로 가는 시절. MS가 만든 에뮬레이팅 레이어를 벗어나기 위한 처절한 몸부림. 왜 이런게 생겼을까? 그냥 32/64만 있었으면 세상 편하겠구만…​&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsWow64()
IsWindowsXP()
IsWindows2k()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2017&lt;/h3&gt;
&lt;p&gt;누군가 wow64에 존재하는 천국의 문을 발견하면서 32비트 프로그램에서 64비트 코드를 직접 구동하는 것이 가능해진 시기. 진짜 64비트 시스템인지 판별하는 코드들이 삽입되고, 32비트 프로그램이 메모리 상에서 64비트 코드를 직접 실행하면서 32/64 포인터 변환 헬게이트가 열림.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsNative64()

IsWow64()
IsWindowsXP()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2020&lt;/h3&gt;
&lt;p&gt;wow64는 양반이었다. arm이라뉘. chpe는 또 무엇. 심지어 이건 당연한 소리겠지만 천국의 문 따윈 없다. 대중화되지 않았지만 실리콘 맥으로 대중화의 물꼬가 트일거 같은 느낌적인 느낌. 인텔만 있을때가 꿀이었던 것인가??&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsWindowsOnArm()

IsNative64()
IsWow64()
IsWindowsXP()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2022&lt;/h3&gt;
&lt;p&gt;윈도우만 있던 시절은 세상 편했다. 온갖 윈도우 포트 레이어 wine, proton, 네이티브 리눅스, 맥, 안드로이드, iOS가 난무하는 세상이란. 2022년의 게임 보안 개발자는 월요일은 온갖 윈도우 인텔/암/32/64/wow64/xp, 화요일은 리눅스와 각종 포트 레이어 linux/proton/wine, 수요일은 안드로이드, 목요일은 iOS/macOS를 개발해야 하는 세상이 돼 버렸다. 여기에 더 무서운 건 윈도우는 인사이더 빌드로 수시로 내부 구조체와 함수 구조를 바꾸고, 안드로이드와 iOS는 빼먹지 않고 매년 대규모 업데이트를 단행한다는 것…​&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsWine()
IsProton()
IsMacOS()
IsLinux()
IsAndroid()
IsiOS()

IsWindowsOnArm()
IsNative64()
IsWow64()
IsWindowsXP()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;금요일은? 놀 순 없지. 어서와 LLVM은 처음이지…​ Xcode가 이렇게 자주 업데이트 되는 줄 몰랐어? LLVM 애플 버전은 업스트림에 반영하지 않는 거도 몰랐어? 그럼 지금부터 LLVM 지옥문을 맛보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsTripleAndroid()
IsTripleiOS()
IsTripleMacOS()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;주말은? 새나라의 게임 보안 프로그래머라면 콘솔 개발해야지…​&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IsXbox()
IsPS()
IsNSW()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;20년간 우리가 버릴 수 있었던 if문은 IsWindows9x와 IsWindows2k 단 두 개 밖에 없었다. 새로 추가된 if문들을 보면 눈물이…​&lt;/p&gt;
&lt;p&gt;그럼에도 긍정적으로 바라보자면 우리에겐 github, slack, aws가 생겼다는거…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] 커널 모드 드라이버 삭제에 부쳐]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2022/04/delete-kernel-mode-driver-file/</link><guid isPermaLink="false">https://jiniya.net/ng/2022/04/delete-kernel-mode-driver-file/</guid><pubDate>Wed, 13 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;최근에 드라이버 코드를 개발하면서 새로 들어온 개발자와 다소 의견 차이가 있었다. 내가 드라이버 파일이 삭제된 경우에는 어떻게 할거냐고 물었는데 그 친구는 계속 로드된 드라이버 파일이 삭제되지는 않는다는 이야기를 했다. 아니? 뭐지? 일반적으로 커널 모드 드라이버 파일은 로딩을 완료한 후에는 자유롭게 삭제가 된다. 특수한 처리 방식이 있는 게 아니고 아래와 같은 코드로 간단하게 구현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;LoadDriver(path);
DeleteFile(path);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그래서 혹시 그 친구가 테스트를 안해본게 아닌가 해서 이만저만하게 해서 테스트를 해보라고 했더니 테스트 했는데 삭제가 안된다고 한다. 아니? 그럴수가? 그래서 나도 테스트 해봤는데 삭제가 되지 않았다. 이 무슨 시츄레이션이지…​&lt;/p&gt;
&lt;p&gt;해서 Windows 7에서 테스트를 해봤다. 역시나 삭제가 잘됐다. &lt;del&gt;그래서 혹시나 해서 Windows 10 TH1에서 테스트를 해봤다. 역시나 삭제가 잘 됐다.&lt;/del&gt; TH1 이후 어딘가부터 윈도우 구조가 바뀌면서 드라이버 파일이 삭제가 되지 않도록 변경된 것으로 보였다.&lt;/p&gt;
&lt;p&gt;그 친구는 개발을 배울 당시가 해당 윈도우 버전이라 파일이 삭제된다는 걸 본적이 한번도 없었고, 나는 Windows XP부터 개발을 했던 사람이라 삭제가 안된다는 걸 최근에 테스트한 적이 없었던 것이다. 그래서 혹시나 해서 드라이버 개발을 전문적으로 하는 사람한테 물어봤더니 역시나 몰랐다. 고인물들이란 ㅎㅎ^^&lt;/p&gt;
&lt;p&gt;그럼에도 이 모든 걸 뚫고 최신 버전 윈도우에도 파일이 없는 드라이버가 상주한 것들이 몇 개 있었다. 당췌 얘들은 뭐지 해서 검색해봤더니 레이몬드 첸 아저씨가 2016년에 이미 다 알려준 내용들.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20160913-00/?p=94305&quot;&gt;https://devblogs.microsoft.com/oldnewthing/20160913-00/?p=94305&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;고인물들의 지식은 업데이트된지 너무 오래 되었고, 새로 배우는 친구들은 역사를 알기가 어렵다.
그와중에 MS 개발자들은 너무 열일하신다는거…​&lt;/p&gt;
&lt;p&gt;덧) windows 10 th1 부터 변경된 것으로 보여집니다. feat KINUX&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] strcpy_s에서 예외가 잡히지 않는 이유]]></title><description><![CDATA[어제 직원이 strcpy_s를 사용하면 예외가 잡히지 않는다며 코드를 보내왔다. 아래 코드다. 어떻게 컴파일하든 catch가 출력되는 것을 볼 수 없다. strcpy_s대신 strcpy…]]></description><link>https://jiniya.net/ng/2022/04/no-exception/</link><guid isPermaLink="false">https://jiniya.net/ng/2022/04/no-exception/</guid><pubDate>Tue, 12 Apr 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;어제 직원이 strcpy_s를 사용하면 예외가 잡히지 않는다며 코드를 보내왔다. 아래 코드다. 어떻게 컴파일하든 catch가 출력되는 것을 볼 수 없다. strcpy_s대신 strcpy를 하면 잘 된다는 이야기.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;Windows.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    __try
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;strcpy_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;aaaa&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EXCEPTION_EXECUTE_HANDLER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;catch\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그래서 알아보기로 했다. 왜 예외가 잡히지 않는지를…​ strcpy_s는 다음과 같이 구현되어 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; errno_t __cdecl &lt;span class=&quot;token function&quot;&gt;strcpy_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;       &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    size_t      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; source
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;common_tcscpy_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;common_tcscpy_s로 들어가보면 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// _strcpy_s() and _wcscpy_s()&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;_Success_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; errno_t __cdecl &lt;span class=&quot;token function&quot;&gt;common_tcscpy_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_Out_writes_z_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Character&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    _In_                                 size_t &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    _In_z_                     Character &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; source
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_VALIDATE_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_VALIDATE_POINTER_RESET_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;source&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Character&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;       destination_it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; destination&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Character &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; source_it      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    size_t available &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;destination_it&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;source_it&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;available &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;available &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;_RESET_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;_RETURN_BUFFER_TOO_SMALL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_FILL_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_in_elements &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; available &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    _RETURN_NO_ERROR&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;_VALIDATE_STRING 매크로에서 destination이 NULL인 경우 체크가 들어간다는 것을 알 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* validations */&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;_VALIDATE_STRING_ERROR&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _Size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _Ret&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_VALIDATE_RETURN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_Size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EINVAL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_Ret&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;_VALIDATE_STRING&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _Size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_VALIDATE_STRING_ERROR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_Size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EINVAL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

_VALIDATE_RETURN 매크로는 _INVALID_PARAMETER 호출로 이어진다&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;_VALIDATE_RETURN&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; errorcode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; retexpr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;                             &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;                                                                          &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; _Expr_val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                                              &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_ASSERT_EXPR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_Expr_val&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_CRT_WIDE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#expr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                           &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_Expr_val&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;                                                      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;                                                                      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_errno&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;errorcode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                                           &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_INVALID_PARAMETER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_CRT_WIDE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#expr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                              &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;retexpr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                                                  &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;                                                                      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;_INVALID_PARAMETER는 릴리즈 버전에서 _invalid_parameter_noinfo 호출로 이어진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_DEBUG&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;_INVALID_PARAMETER&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_invalid_parameter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; __FUNCTIONW__&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; __FILEW__&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__LINE__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;_INVALID_PARAMETER&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_invalid_parameter_noinfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;_invalid_parameter_noinfo는 최종적으로 _invalid_parameter_internal 호출로 이어진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;_invalid_parameter_noinfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_invalid_parameter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;_invalid_parameter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    uintptr_t      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reserved
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    __crt_cached_ptd_host ptd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_invalid_parameter_internal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ptd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;_invalid_parameter_internal을 살펴보면 다음과 같다. _thread_local_iph 핸들러가 있는 경우 해당 핸들러를, 없는 경우 글로벌 핸들러를, 그마저도 없는 경우에는 _invoke_watson으로 이어진다. 일반적으로 핸들러 설정이 되어 있지 않기 때문에 _invoke_watson 호출로 진행된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;_invalid_parameter_internal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;     &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;     &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;     &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;       &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    uintptr_t          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __crt_cached_ptd_host&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;   ptd
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    __acrt_ptd &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; raw_ptd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ptd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_raw_ptd_noexit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw_ptd &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; raw_ptd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_thread_local_iph&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        raw_ptd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_thread_local_iph&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    _invalid_parameter_handler &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; global_handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__crt_fast_decode_pointer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__acrt_invalid_parameter_handler&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ptd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;global_handler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;global_handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;_invoke_watson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; null 인경우 이쪽으로 도달
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;_invoke_watson은 다음과 같이 구현되어 있다. 일반적으로 PF_FASTFAIL_AVAILABLE 플래그가 설정되어 있어서 __fastfail 호출로 이어진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__declspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;noreturn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;_invoke_watson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; function_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; file_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; line_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	uintptr_t      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reserved
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;UNREFERENCED_PARAMETER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expression   &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;UNREFERENCED_PARAMETER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;function_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;UNREFERENCED_PARAMETER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file_name    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;UNREFERENCED_PARAMETER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line_number  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;UNREFERENCED_PARAMETER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reserved     &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsProcessorFeaturePresent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PF_FASTFAIL_AVAILABLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;__fastfail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FAST_FAIL_INVALID_ARG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// Otherwise, raise a fast-fail exception and termintae the process:&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;__acrt_call_reportfault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		_CRT_DEBUGGER_INVALIDPARAMETER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		STATUS_INVALID_CRUNTIME_PARAMETER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		EXCEPTION_NONCONTINUABLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;TerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; STATUS_INVALID_CRUNTIME_PARAMETER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;__fastfail은 아래 문서를 참고하면 int 0x29로 구현된 컴파일러 함수다.&lt;br&gt;
&lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail?view=msvc-170&quot;&gt;https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail?view=msvc-170&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;결국 strcpy_s는 최종적으로 int 0x29로 이어진다. fastfail이란 말에서 알 수 있듯이 해당 인터럽트는 예외에 잡히지 않는다. 결국 strcpy_s 내부적으로 널체크를 해서 특수한 처리를 했기 때문에 예외에 잡히지 않는다. strcpy_s((char*)0x123, 10, &quot;aaaa&quot;); 등과 같이 호출하면 정상적으로 예외 처리가 이루어진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    __try
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x29&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EXCEPTION_EXECUTE_HANDLER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;catch\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;strcpy_s 입장에서는 NULL이면 프로그램을 종료시켜버리는 게 안전한 구현일 수 있다. 하지만 경우에 따라서는 오바하는 함수가 될수도 있겠다. 내가 알아서 할건데 왜 고작 문자열 복사하는 기능만 하면 될 함수가 릴리즈 버전에서 널체크까지 해가며 멋대로 강종시키지? 프로그램을? 예외처리도 안되게?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 미드나잇 라이브러리]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2022/midnight-library/</link><guid isPermaLink="false">https://jiniya.net/2022/midnight-library/</guid><pubDate>Sat, 29 Jan 2022 13:00:01 GMT</pubDate><content:encoded>&lt;h3&gt;저자&lt;/h3&gt;
&lt;p&gt;매트 헤이그, 영국 소설가. 우울증과 불안 장애로 자살 시도를 하고 극복한 경험이 있음. 그래서 관련된 내용에 관한 저술이 많아 보인다. 미드나잇 라이브러리도 그런 연장선상의 책이다.&lt;/p&gt;
&lt;h3&gt;줄거리&lt;/h3&gt;
&lt;p&gt;주인공 노라는 되는 일이 없다. 재능은 많았지만 많은 것들을 포기했다. 게다가 우울증과 불안장애 증상까지 있다. 키우던 고양이가 죽고, 직장을 잃으며 삶의 나락으로 몰린 주인공은 자살 시도를 한다. 그리고 자살 시도 과정에서 삶과 죽음의 중간 단계에 있는 미드나잇 라이브러리에 간다.&lt;/p&gt;
&lt;p&gt;미드나잇 라이브러리에서는 노라가 사는 동안 후회했던 것들을 바꾼 다양한 삶을 경험해 보게 된다. 그 경험한 삶이 마음에 든다면 그곳에서 살아도 되고, 마음에 들지 않는다면 다시 라이브러리로 돌아올 수 있다. 노라는 올림픽 메달리스트가 되기도 하고, 성공한 록밴드 작곡가 겸 보컬이 되기도 하고, 빙하학자가 되기도 한다.&lt;/p&gt;
&lt;p&gt;이런 온갖 다양한 삶을 경험하면서 역설적이게도 노라는 삶의 이유를 깨닫는다 그리고 다시 원래의 삶으로 돌아오고 거기서 아직 쓰지 못한 자신의 인생 이야기를 계속 써내려 간다.&lt;/p&gt;
&lt;h3&gt;인상 깊은 구절&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;모든 게 달라진 이유는 이젠 그녀가 단지 다른 사람의 꿈을 이뤄주기 위해 존재하지 않기 때문이었다. 상상 속 완벽한 딸이나 동생, 애인, 아내, 엄마, 직원, 혹은 무언가가 되는 데서 유일한 성취감을 찾아야 한다고 생각하지 않기 때문이었다. 이제는 그저 한 인간으로서 자신의 목표만 생각하며 자신만 책임지면 그만이었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;노라는 자신이 블랙홀이 아니라는 결론을 내렸다. 그녀는 화산이었다. 그리고 화산처럼 그녀는 자신에게서 달아날 수 없었다. 거기 남아서 그 황무지를 돌봐야 했다.&lt;br&gt;
역설적이게도 화산은 파괴의 상징인 동시에 생명의 상징이다. 용암이 흘러내리는 속도가 느려지고 열이 식으면, 용암은 응고되었다가 시간이 흐르면서 부서져 흙이 된다. 비옥하고 영양가가 풍부한 토양이 된다.&lt;br&gt;
자기 자신 안에 숲을 가꿀 수 있었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“이번 판은 선생님이 이기겠는데요.” 노라가 말했다.&lt;br&gt;
엘름 부인의 눈동자가 갑자기 생기를 띠며 반짝거렸다. “그게 체스의 미덕 아니니? 어떻게 끝날지 모른다는 거.”&lt;br&gt;
노라는 아직 체스판에 남아 있는 자신의 기물을 내려다보며 미소 짓고, 다음 수를 어떻게 둘지 생각했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;노라는 다이아몬드에 대한 닐의 잘못된 지식을 바로잡아주지 않았다. 석탄과 다이아몬드는 둘 다 탄소이기는 해도 석탄은 불순물이 너무 많이 섞여서 아무리 압력을 가해도 다이아몬드가 될 수 없다. 광물학에 따르면 한 번 석탄은 영원한 석탄이다. 어쩌면 그게 현실적인 교훈일 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;그녀가 둔 모든 수는 실수였고, 모든 결정은 재앙이었으며, 매일 자신이 상상했던 모습에서 한 걸음씩 멀어졌다.&lt;br&gt;
수영 선수. 뮤지션. 철학가. 배우자. 여행가. 빙하학자. 행복하고 사랑받는 사람.&lt;br&gt;
그중 어느 것도 되지 못했다.&lt;br&gt;
심지어 ‘고양이 주인’이라는 역할조차 제대로 해내지 못했다. 혹은 ‘일주일에 한 시간짜리 피아노 레슨 선생님’도. 혹은 ‘대화가 가능한 인간’도.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;난 올림픽에 출전하지 못했어. 빙하학자가 되지 못했어. 댄의 아내가 되지 못했어. 엄마가 되지 못했어. 라비린스의 리드 보컬도 되지 못했어. 정말로 좋은 사람 혹은 행복한 사람이 되지 못했어. 볼테르도 제대로 보살피지 못했어.&lt;br&gt;
그리고 이제 마지막으로 제대로 죽지도 못했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“모든 삶에는 수백만 개의 결정이 수반된단다. 중요한 결정도 있고, 사소한 결정도 있지. 하지만 둘 중 하나를 선택할 때마다 결과는 달라져. 되돌릴 수 없는 변화가 생기고 이는 더 많은 변화로 이어지지. 이 책들은 네가 살았을 수도 있는 모든 삶으로 들어가는 입구야.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“걱정 마라. 화장지는 인생과 같아. 늘 더 있는 법이야.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;댄에게는 장점이 훨씬 많았다. 아픈 노라의 엄마에게 극진히 대했고, 어떤 주제에 관해서든 편안히 이야기할 수 있었고, 미래에 대한 꿈으로 가득 찼으며, 매력적이고 함께 있으면 편안했다. 또한 예술을 열렬히 사랑했고, 길에서 노숙자를 보면 늘 걸음을 멈추고 얘기를 나눴다. 세상에 관심을 가졌다. 사람은 도시와 같아서 마음에 덜 드는 부분이 몇 개 있다고 해서 전체를 거부할 순 없다. 위험해 보이는 골목길이나 교외 등 마음에 안 드는 부분이 있을지라도 다른 장점이 그 도시를 가치 있게 만들어준다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“왜냐하면 노라, 때로는 살아봐야만 배울 수 있으니까.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;읽은 후&lt;/h3&gt;
&lt;p&gt;읽기는 굉장히 편한 책이다. 서사 구조가 복잡하지 않고 단조롭고 교훈적이다. 그리고 한 100페이지쯤 읽으면 책 내용이 어떻게 전개될지는 대충 예측이 된다. 심지어 마지막에 현재 삶을 의미하는 책을 찾겠다는 것까지.&lt;/p&gt;
&lt;p&gt;다만 소설적인 재미를 떠나 소설이 제공하려는 교훈을 끌어내는 측면에서 바라보자면 너무 급진적인 측면이 있는 건 아닌가라는 생각이 든다. 많은 인생을 경험하고 후회를 되돌려본 인생이 자기 생각과 달랐다는 측면이 있었다는 것까지는 이해가 된다. 하지만 그런 다양한 인생 경험을 토대로 블랙홀로 생각했던 내 인생이 화산이었다고 바라보는 시각을 변경하는 과정은 개연성이 충분한가 라는 생각이 든다.&lt;/p&gt;
&lt;p&gt;살아봐야만 배울 수 있는 것들이 있다. 또 아직 끝나지 않았다면 인생은 끝날 때까지 어떤 게임이 될지는 알 수 없다. 어떤 게임이 되었든 그것도 멋진 한 판의 바둑이었을 것이다. 다만 현실적인 생각을 조금 해보자면 게임이 진행될수록 경우의 수는 급격히 줄어든다는 점이다. 바둑판에 돌이 많이 있을 수록 경우의 수는 점점더 제한된다. 체스판의 기물이 줄어들수록 경우의 수 또한 급격하게 줄어든다. 그래서 시작은 무한한 가능성을 가진 한판의 게임이 펼쳐질 가능성이 있겠지만 중반을 넘어서면 사실상 경기의 궤도는 어느 정도 정해진 경우가 대다수다. 따라서 끝날 때까지 끝난 건 아니고, 어떤 게임이 될지 알 수 없다는 말처럼 희망이 있을 수 있겠지만 현실적으로는 게임이 진행될 수록 삶이 진행될수록 선택할 수 있는 선택지와 그 선택으로 벌어질 수 있는 희망의 가능성은 줄어든다.&lt;/p&gt;
&lt;p&gt;저자와 달리 나는 시뮬레이션 우주론과 결정론적 세계관을 가지고 있고, 자유의지는 없다고 믿는 편이다. 그런 나에겐 테드 창의 조언이 조금 더 현실적이란 생각이 많이 들었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;자유의지가 있는 것처럼 행동하라. 설령 사실이 아님을 알고 있어도, 스스로 내리는 선택에 의미가 있는 듯이 행동하는 것이 가장 중요하다. 무엇이 현실인지는 중요하지 않다. 정말로 중요한 것은 당신이 무엇을 믿느냐이며, 이 거짓말을 믿는 것이야말로 깨어 있는 혼수상태에 빠지는 것을 피할 수 있는 유일한 방법이다. 문명의 존속은 이제 자기기만에 달려 있다. 어쩌면 줄곧 그래 왔는지도 모른다.&lt;br&gt;
&lt;br&gt;
-- 숨(우리가 해야 할 일) | 테드 창&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이책과 비슷한 내용으로 훨씬 극적으로 삶의 의지를 불태우게 해주는 컨텐츠로 K드라마 “나의 아저씨”를 추천하고 싶다. 어쩌면 복잡한 내용을 떠나서 우리 모두가 듣고 싶은 이야기는 결국 이 한 마디가 아닐까. 괜.찮.아...&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 호모 데우스]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2022/homo-deus/</link><guid isPermaLink="false">https://jiniya.net/2022/homo-deus/</guid><pubDate>Tue, 25 Jan 2022 13:00:01 GMT</pubDate><content:encoded>&lt;h3&gt;간단한 소개, 동기, 저자에 관하여&lt;/h3&gt;
&lt;p&gt;유발 하라리는 사피엔스라는 책으로 일약 스타덤에 오른 역사학자다. 사피엔스는 호모 사피엔스가 어떻게 다른 호모 종들을 제치고 이 세상을 지배하는 종이 되었는지에 대한 그의 충걱적인 가설 및 서사를 들려주는 책이다. 아마도 그의 가설과 서사가 굉장히 그럴듯하고 충격적이었기에 많은 사람들의 공감과 관심을 받지 않았을까 싶다.&lt;/p&gt;
&lt;p&gt;호모 데우스는 그런 그가 호모 사피엔스의 다음 단계, 즉 앞으로 펼쳐질 미래 세상에 대한 이야기를 하는 책이다. 흔히들 미래를 알기 위해서는 과거를 알아야 한다는 말을 한다. 과거를 충실히 연구했고 호모 종이 지배종이 될 수 있었던 충격적인 서사를 들려준 그가 바라보는 미래는 어떤지 궁금해서 이 책을 선택하게 되었다.&lt;/p&gt;
&lt;h3&gt;인상 깊은 내용&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;오늘날 정설에 따르면 유기체는 알고리즘이고, 알고리즘은 수학 공식으로 표현할 수 있다. 자판기가 차 한 잔을 만들기 위해 밟는 일련의 단계들 그리고 우리의 뇌가 사자의 접근에 촉각을 곤두세울 때 밟는 일련의 단계들을 우리는 숫자와 수학 기호를 사용해 적을 수 있다. 그렇다면, 그리고 의식적 경험들이 어떤 중요한 기능을 한다면, 그 경험들 역시 수학적으로 표현할 수 있어야 한다. 왜냐하면 경험은 알고리즘의 필수적 부분이기 때문이다. ‘두려움 알고리즘’을 적고 ‘두려움’을 일련의 정확한 계산식으로 쪼개면 이렇게 말할 수 있다. ‘계산 과정의 93단계, 바로 이곳이 두려움이라는 주관적 경험이 개입하는 곳이다!’ 하지만 수학이라는 거대한 영역에 주관적 경험을 포함하는 알고리즘이 존재할까? 우리가 알기로 그런 알고리즘은 없다. 수학과 컴퓨터 과학 분야의 방대한 지식을 총동원해봐도, 우리가 창조한 데이터 처리 장치 가운데 그 어떤 것도 작동을 위해 주관적 경험이 필요한 것은 없고, 그 어떤 것도 고통, 쾌락, 분노, 사랑을 느끼지 않는다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;유기체가 알고리즘이고 주관적 경험은 실질적으로 필요 없다는 그의 주장은 파격적으로 들린다. 하지만 많은 최신 연구에 따르면 자유의지가 없다는 진영이 승리하는 것은 맞는 것처럼 보여지고 있다. 우리는 어떤 선택을 의식하기 전에 뇌는 이미 결정을 끝냈으며, 의식은 마치 그 끝낸 결정에 대한 그럴듯한 보충 설명을 해주는 것에 지나지 않는다고 한다. 또한 현재까지는 의식의 존재 자체가 미스테리이긴 하지만 인공지능 기술이 발전하면서 일정 수준의 복잡도를 넘어서는 순간 인공지능에서도 의식이 발현될 것으로 예측하고 있다. 어쨌든 유기체는 알고리즘이라는 정설을 받아들이는 순간 나는 무엇인가라는 생각이 저절로 따라오게 된다. MMORPG 게임 존재하는 NPC와 내가 다를 게 무엇일까?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그러면 구글은 이렇게 대답할 것이다. &quot;나는 네가 태어난 날부터 너를 알고 있었어. 네 이메일을 모두 읽었고, 네 통화를 모두 기록했고, 네가 좋아하는 영화들, 네 유전자 정보, 네 심장 기록도 모두 갖고 있어. 네가 데이트한 정확한 날짜도 보관하고 있으니, 존이나 폴과 만날 때마다 네 심장박동, 혈압, 혈당수치를 초 단위로 기록한 그래프를 원한다면 보여줄 수 있어. 필요하다면 네가 그들과 가진 모든 성관계의 정확한 순위도 제공할 수 있어. 그리고 당연히 나는 너를 아는 것만큼 그들도 잘 알아. 이 모든 정보, 내 뛰어난 알고리즘, 수많은 관계에 대한 수십 년에 걸친 통계자료를 토대로, 나는 너에게 존을 선택하라고 권해. 장기적으로 그와 함께할 때 더 만족스러울 확률이 87퍼센트야.&quot;&lt;br&gt;
&lt;br&gt;
&quot;나는 너를 잘 아는데, 너는 이 답변이 마음에 들지 않을 거야. 존보다 폴이 훨씬 더 잘생겼지. 너는 외모를 중시하니까, 내가 &apos;폴&apos;이라고 말해주기를 내심 바랐을 거야. 물론 외모는 중요하지. 하지만 네가 생각하는 것만큼은 아니야. 수만 년 전 아프리카 사바나에서 진화한 네 생화학적 알고리즘은 배우자감을 전반적으로 평가할 때 외모에 두는 비중이 35퍼센트야. 하지만 최신 연구와 통계를 바탕으로 하는 내 알고리즘은 외모가 사랑하는 관계에 장기적으로 미치는 영향은 14퍼센트에 불과하다고 말해. 그러니 폴의 외모를 고려한다 해도 네가 존과 함께하는 게 더 낫다고 생각해.&quot;&lt;br&gt;
&lt;br&gt;
이런 충실한 상담 서비스를 받는 대가로 우리가 포기해야 하는 것은 인간은 분할할 수 없는 존재이며 각 개인은 무엇이 선이고 무엇이 아름다움이고 무엇이 인생의 의미인지 결정할 자유의지를 갖고 있다는 개념뿐이다. 인간은 더 이상 이야기하는 자아가 꾸며내는 이야기들의 지시를 따르는 자율적 실체들이 아니라, 거대한 전 지구적 네트워크의 필수불가결한 일부가 될 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;미래 세계에 대한 그의 묘사 중 일부지만 내용이 다소 충격적인 것과 동시에 몇년 내에 저런 세상이 올지도 모른다는 생각에 굉장히 인상 깊었다. 구글 나우라는 기술은 지금도 켜두기만 하면 내가 자료를 입력하지 않아도 내 회사가 어디있고, 집이 어디있으며, 내가 수요일 저녁 시간에 어떤 공간에 있을 확률이 높고, 내가 좋아하는 음악이 무엇인지 등을 알려준다. 유발 하라리가 전개한 것과 같은 기술은 어쩌면 우리가 개인 정보 동의를 하는 순간부터 계속 진행되고 있는지도 모른다.&lt;/p&gt;
&lt;p&gt;과연 저런 세상이 펼쳐졌을때 우리는 인공지능의 선택에 저항할 수 있을까? 내 생각은 쉽지 않다는 생각이다. 왜냐하면 지금도 사람들은 초행길을 갈 때에 아무 생각없이 네비게이션이 우회전을 하라면 믿고 우회전을 하기 때문이다. 심지어 초행길이 아닌 길도 우회전을 하라고 하면 이 길이 더 빨라서 그런가? 하고는 생각없이 우회전을 한다. 주차를 할 때에도 본인의 느낌보다는 센서의 삑삑 소리에 더 의존하고 있다. 이런 세상은 가속화 될 것이고 우리는 점점 더 자유의지가 없는 것 같은 존재가 될지도 모른다. 그 시대가 된다면 과연 나란 무엇인지? 우리의 자유의지가 존재하긴 하는 것인지? 인공지능이 모든 선택을 대체한다면 삶의 의미는 무엇인지가 궁금해지는 대목이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;코타나가 신탁에서 대리인으로 진화하면 주인들 대신 자기들끼리 직접 이야기하기 시작할 것이다. 처음에는 내 코타나가 당신의 코타나에게 연락해 약속 장소와 시간을 잡는 것과 같은 단순한 일로 시작할 것이다. 하지만 어느 순간 정신을 차리고 보면, 내가 입사 지원한 회사의 인사팀장이 나에게 이력서를 보낼 필요 없이 자신의 코타나가 내 코타나를 면접 볼 수 있도록 해달라고 말한다. 또는 나에게 관심 있는 이성의 코타나가 내 코타나에게 접근해 서로 정보를 교환하며 두 사람이 좋은 짝인지 결정한다. 물론 이 모든 일은 그들의 주인들이 전혀 모르는 상태에서 이루어질 것이다.&lt;br&gt;
&lt;br&gt;
코타나가 권한을 얻으면 주인의 이익을 위해 상대의 코타나를 교묘히 조종하기 시작할 것이고, 그 결과 직업시장 또는 결혼시장에서의 성공이 점점 더 코타나의 자질에 따라 판가름날 것이다. 그래서 최신 버전의 코타나를 소유한 부자들은 구버전을 소유한 가난한 사람들보다 결정적 우위를 점할 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;장자의 호접지몽 이야기가 생각나는 대목이다. 나비 꿈을 꾸고 깨어보니 지금이 현실인지, 나비가 꾸는 꿈인지 구분이 되지 않는다는 이야기. 코타나가 대리인이 되는 순간 코타나가 나인지, 내가 코타나인지 구분할 수 있을까? 모든 선택과 결정을 코타나가 한다면 과연 그가 나의 인공지능 비서일까? 내가 그의 아바타일까?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;자유주의가 직면한 세 번째 위협은, 일부 사람들은 업그레이드되어 필수불가결한 동시에 해독 불가능한 존재로 남아 소규모 특권집단을 이룰 거라는 점이다. 이런 초인간들은 전대미문의 능력과 전례 없는 창의성을 지닐 것이고, 그런 힘을 이용해 세계적으로 중요한 대다수의 결정들을 계속 내릴 수 있을 것이다. 그들은 시스템의 유지보수를 담당할 것이고, 시스템은 그런 사람들을 이해하고 관리할 수 없을 것이다. 그러나 대부분의 사람들은 업그레이드되지 않을 것이고, 그 결과 컴퓨터 알고리즘과 새로운 초인간 양쪽의 지배를 받는 열등한 계급이 될 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;인간은 항상 계층을 나눠왔다. 누가 힘이 센지와 같은 유전자에 의해서 나누다가, 누구의 아들 딸인지 같은 출신 성분에 의해서 나누다가, 누가 시험을 통과했는지와 같이 능력에 의해서 나누다가, 누가 자본을 더 가졌는지와 같이 돈에 의해서 나누는 등. 문명이 시작된 이후 인간이 실질적으로 평등했던 순간은 없었다는 생각이다. 그의 예측대로라면 그렇다면 앞으로는 시스템을 이해하고 설계할 수 있는 계층과 그렇지 않은 계층으로 나뉘게될까?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;첫째, 의학은 중대한 개념적 혁명을 겪고 있는 중이다. 20세기에 의학의 목표는 병에 걸린 사람을 치료하는 것이었다. 하지만 21세기에 의학의 목표는 건강한 사람의 성능을 높이는 쪽(업그레이드)으로 가고 있다. 병든 사람을 치료하는 것은 평등주의적 목표였다. 왜냐하면 모두가 누릴 수 있고 누려야 하는 육체적ㆍ정신적 건강의 표준이 존재한다는 전제에서 출발했기 때문이다. 만약 어떤 사람이 그 표준 밑으로 떨어지면, 문제를 고쳐서 그 사람이 ‘다른 모든 사람들과 같아지게’ 만드는 것이 의사의 본분이었다. 반면 건강한 사람을 업그레이드하는 것은 엘리트주의적 목표이다. 모두에게 적용되는 보편적 표준이라는 개념을 거부하고, 일부 개인들에게 우위를 제공하려는 일이기 때문이다. 사람들은 뛰어난 기억력, 평균 이상의 지능, 최고의 성적 능력을 원한다. 만일 어떤 형태의 업그레이드가 저렴하고 흔해져서 누구나 접근할 수 있는 것이 된다면, 그것이 새로운 기준점이 되어 그것을 능가하는 차세대 치료법이 개발될 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;유전자 가위 기술은 상당히 발전해 있다. 인공지능을 통한 업그레이드가 되지 않더라도 우리가 유전자 코드를 해독하면 할수록 더 뛰어난 유전자 코드를 스스로 만들어 내는 길을 선택할지도 모른다.&lt;/p&gt;
&lt;h3&gt;읽은 후...&lt;/h3&gt;
&lt;p&gt;흔히들 미래를 인공지능, 사이보그의 세상이 될 것이라 얘기한다. 그리고 마치 그 세상은 모든 인류가 공통으로 그 혜택을 누리는 판타지 같은 세상일 것이라 얘기한다. 하지만 유발 하라리가 예측한 세상은 그렇지 않았다.&lt;/p&gt;
&lt;p&gt;전체적으로 그는 1) 유기체로써의 인간의 진화는 지금이 끝이다. 2) 그 이후 단계는 인공지능과, 사이보그 기술을 이용해 일부 인간들이 초인간으로 업그레이드 될 것이다. 3) 그 초인간들의 업그레이드가 완료되면 기존의 인간들은 더이상 쓸모 없는 잉여 인간이 될 것이다. 4) 그 초인간들 조차도 상당수가 인공지능의 도움으로 스스로 결정할 것이 없는 세상이 될 것이다. 5) 유기체로써의 모든 부분이 제거되고 나면 우주로 나갈 수 있는 진정한 초인간의 시대가 열린다고 말한다.&lt;/p&gt;
&lt;p&gt;디스토피아적 미래지만 상당히 그럴듯한 전개라고 생각한다. 엘론 머스크는 벌써 뉴럴 링크를 통해서 뇌에 인공지능 칩을 심는 실험을 하고 있다. 아마 그 실험이 성공적으로 끝난다면 우리는 머지 않아서 영어 기능을 제공하는 칩을 몇 백 달러에 사게 될지도 모른다. 그리고 각종 기능들이 칩으로 제공될 것이고 그것은 점점 더 그 칩을 가진 사람들과 못 가진 사람들의 격차를 벌리게 될 것이다. 이렇게 초인간과 불필요한 인간으로 나뉘는 세상이 오게 된다면 우리는 어떻게 대처해야 할까? 아직 그런 세상이 오지 않았고 내가 사는 기간 동안에는 안전할 것 같으니 괜찮은 것일까? 아니면 어떻게든 아등바등 그 초인간의 무리에 끼기 위해서 달려야 하는 것일까?&lt;/p&gt;
&lt;p&gt;미래에 대한 선명한 지도같은 책이었지만 역설적이게도 이 책은 나에게 엄청난 질문 덩어리만 안겨준 책이었다. 그리고 그 중간에는 사람, 인간이 있었다. 과연 그 수많은 잉여 인간의 존재 가치는 무엇이 될까?&lt;/p&gt;
&lt;h3&gt;당신의 생각은?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;유기체로써의 진화가 지금이 끝일지와 이유. 유전자 가위 vs 사이보그&lt;/li&gt;
&lt;li&gt;초인간으로 진화되어 인간이 두 부류로 나뉘게될지와 이유.&lt;/li&gt;
&lt;li&gt;저자의 생각대로 인간이 자체적으로 업그레이드해서 초인간이 된다고 했을 때 잉여 인간은 생존할까? 또 존재 가치는?&lt;/li&gt;
&lt;li&gt;텍스트에 나온 존과 폴 중 인공지능의 선택대로 존을 선택할까? 아니면 마음이 끌리는 잘생긴 폴을 선택할까?&lt;/li&gt;
&lt;li&gt;인공지능이 복잡한 의사 결정의 상당수를 대체한다고 했을때 인간의 존재가치는? 그리고 지금 현재 상태에서 자유의지가 있다고 믿는지? 아닌지? 그 이유는?&lt;/li&gt;
&lt;li&gt;대체로 이런 이야기 끝에 불멸의 존재가 되기 위해 전뇌화, 또는 마인드 업로딩으로 불리는 뇌를 네트워크에 업로드 하는 이야기가 나온다. 만약 본인이 그런 업로드를 통해 영생을 누릴 수 있다면 업로드 할지 말지와 그 이유.&lt;/li&gt;
&lt;li&gt;미래 방향 예측의 큰 갈래가 인간이 우주로 확장할 것이다와 메타버스 세계로 확장할 것이다로 나뉜다. 둘중 어떤 세상으로 확장할 가능성이 크다고 생각하는지와 그 이유.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[cpp] 버퍼로써 vector가 적합하지 않은 이유]]></title><description><![CDATA[C언어에서 동적 버퍼를 사용하던 코드를 C++로 포팅할 때 흔히 vector를 사용한다. 가장 편리하기 때문이다. 하지만 반복적으로 호출되는 코드일 경우 의외로 해당 코드 때문에 부하가 발생할 수 있다. 왜 그런지 살펴보고 더 적합한 C…]]></description><link>https://jiniya.net/2022/the-reasons-why-a-vector-is-unsuitable-for-use-as-a-buffer/</link><guid isPermaLink="false">https://jiniya.net/2022/the-reasons-why-a-vector-is-unsuitable-for-use-as-a-buffer/</guid><pubDate>Tue, 25 Jan 2022 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;C언어에서 동적 버퍼를 사용하던 코드를 C++로 포팅할 때 흔히 vector를 사용한다. 가장 편리하기 때문이다. 하지만 반복적으로 호출되는 코드일 경우 의외로 해당 코드 때문에 부하가 발생할 수 있다. 왜 그런지 살펴보고 더 적합한 C++ 객체가 없는지도 알아보자.&lt;/p&gt;
&lt;h2&gt;고정 버퍼&lt;/h2&gt;
&lt;p&gt;dir에 name을 붙여서 파일을 생성하는 흔한 C언어 코드다. 흔히들 이렇게 작성하기도 한다. 하지만 MAX_PATH가 왠지 걸린다. MAX_PATH면 충분할까? 제한도 없어진다는데? 더 긴 경로가 오면 어떻게 될까, 하는 불안감이 든다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateTempFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;StringCbCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;StringCbCatA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;CreateFileA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;동적 버퍼&lt;/h2&gt;
&lt;p&gt;길이를 런타임에 계산해서 필요한 만큼 공간을 확보하도록 만들 수 있다. 아래 코드는 dir과 name에 어떤 길이의 문자열이 오더라도 잘 동작한다. 메모리만 있다면 말이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateTempFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	size_t size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;StringCbCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;StringCbCatA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;CreateFileA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;vector&lt;/h2&gt;
&lt;p&gt;동적 버퍼를 요하는 코드를 C++로 바꿀 때 흔히 사용하는 객체가 벡터다. 간단하고 깔끔하고 사이즈 관리되고, 나무랄 때가 없는 것이다. 대체하기도 너무 심플하다. resize와 &amp;#x26;vector[0]만 사용하면 만사 OK다.&lt;/p&gt;
&lt;p&gt;C의 저급함과 C++의 고급함 사이의 가장 적절한 수준을 보여주는 것 같기도 하다. 하지만 한가지 문제가 있다. 이 코드가 그렇게 빠르지는 않다는 점이다. 왜냐하면 벡터는 내부적으로 공간을 확장할 때 모두 초기화를 시키기 때문이다. 사실상 우리는 초기화가 필요 없음에도 resize를 하는 순간 모든 공간이 초기화된다. 낭비다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateTempFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;StringCbCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;StringCbCatA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;CreateFileA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;shared_ptr&lt;/h2&gt;
&lt;p&gt;벡터의 초기화를 피할 수 있는 한가지 대안은 shared_ptr이다. 다만 배열 해제를 위한 메모리 해제 코드를 별도로 작성해야 하는 불편함이 있다. 물론 사이즈도 별도로 트래킹을 해야 한다. 하지만 더이상 벡터가 가지고 있는 개별 아이템 초기화에 대한 부담은 없다. 하지만 또 포인터 소유권과 관련된 레퍼런스 카운트 체크에 대한 부담이 늘어난다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateTempFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	size_t size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;shared_ptr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;StringCbCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;StringCbCatA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;CreateFileA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;unique_ptr&lt;/h2&gt;
&lt;p&gt;또 다른 대안으로 unique_ptr을 사용할 수 있다. unique_ptr&amp;#x3C;[]&gt;은 특수화가 되어 있어 사용하기도 무척 편리하며 vector와 같이 초기화 코드가 없기 때문에 빠르다. 게다가 레퍼런스 카운트 체크와 관련한 부하도 없기 때문에 더 빠르다. 지역 버퍼 용도로 쓰기에 가장 문안한 형태로 볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateTempFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	size_t size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;unique_ptr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;unique_ptr&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;StringCbCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;StringCbCatA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token function&quot;&gt;CreateFileA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[정보] 재테크 관련 유튜브]]></title><description><![CDATA[바야흐로 재테크 시대. 특히나 202…]]></description><link>https://jiniya.net/2022/investing-youtube/</link><guid isPermaLink="false">https://jiniya.net/2022/investing-youtube/</guid><pubDate>Mon, 24 Jan 2022 13:00:01 GMT</pubDate><content:encoded>&lt;p&gt;바야흐로 재테크 시대. 특히나 2020은 투자한 사람과 그렇지 않은 사람 사이의 자산 갭이 많이 발생한 한 해가 아니었나 싶다. 뭐라도 투자한 사람들은 수익률 올리기에 바쁘고, 들어서지 못한 사람들은 놓친 기회가 아쉬워 난리다. 하지만 기회는 언제든 다시 온다. 다가올 기회를 놓치기 싫다면 운전하면서 또는 심심할 때 보면 크게 도움될만한 재테크 채널들. 순서는 랜덤.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCsJ6RuBiTVWRX156FVbeaGg&quot;&gt;슈카월드&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCKTMvIu9a4VGSrpWy-8bUrQ&quot;&gt;내일은 투자왕 - 김단테&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/c/%EC%82%BC%ED%94%84%EB%A1%9Ctv/featured&quot;&gt;삼프로TV_경제의신과함께&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCSJELOytOHjywS1ynjNsLDA&quot;&gt;dp - Investor Unknown D.P.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCn_38aaCktkBLPv3EtfmiUA&quot;&gt;박종훈의 경제한방&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 코딩의 시대, 배움의 방식]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2021/07/coding-era/</link><guid isPermaLink="false">https://jiniya.net/ng/2021/07/coding-era/</guid><pubDate>Wed, 21 Jul 2021 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;올초 넥슨이 전직원 연봉을 일괄 인상하면서 인재 전쟁의 서막을 알렸다. 이후 각종 거의 모든 소위 잘나간다는 게임 업체들이 연봉 인상 러시에 동참하면서 코딩의 시대가 절정을 향해 가고 있음을 느끼게 해줬다. 그런 분위기를 반영하듯 페북에는 게임회사 직원을 대상으로 과외 선생님을 모신다는 광고가 연신 팝업된다.&lt;/p&gt;
&lt;p&gt;일자리가 없어서 난리인 시대에 아이러니하게도 주변에서는 개발자를 못 구해서 난리다. 김국현님의 자바 두명 타세요를 보면서 암울한 미래를 예견했던 우리 세대에게 지금의 현실은 다소 생경하기도 하다. 어쨌든 이런 모든 혼란스러움을 뒤로 하고 현재를 정의한다면 프로그래머 전성 시대다. 직무를 불문하고 삼성전자의 입사 시험 과목으로 파이썬이 들어갔다니 두말하면 입아픈 것 같기도 하다.&lt;/p&gt;
&lt;p&gt;그런만큼 요즘 사람들은 꿀 떨어지는 이 분야에 관심이 많다. 자연스레 그에 관한 비전공자들의 여러가지 질문을 받는다. 클래스101 이거 들으면 코딩할 수 있어? 유튜브 이거 보면 나도 프로그래머로 취직할 수 있을까? 거의 대부분 어디서 무엇으로 어떻게 공부하면 프로그래머가 된다거나 코딩을 할 수 있느냐는 질문이다. 그래서 주변을 둘러보며 이미 프로그래머가 된 다른 이들은 어떻게 배웠는지를 한 번 살펴봤다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;A는 게임 테스트 아르바이트로 입사했다. 테스트 아르바이트라는 것이 대체로 그러하듯 컴퓨터로 게임을 할 줄 알면 입사 요건이 충족된다. 내가 알기로 A는 이쪽 전공이 아니고 교육을 받은 적도 없다. A가 코딩을 공부한 건 유튜브와 블로그였다. 테스트를 하면서 코딩 유튜브를 틀어놓고 보면서 공부를 했고, 그런 장면이 내부 툴 개발자 B의 눈에 띄었다. B는 A와 같이 개발을 해보고 싶다는 얘기를 했고, 내가 잃을 거라곤 깃헙 슬롯 비용 밖에는 없을것 같아서 그러라고 했다. 그렇게 A는 깃헙 권한을 획득했다.&lt;/p&gt;
&lt;p&gt;최근에 A의 작업과 관련한 얘기들이 나와서 그가 커밋한 코드를 몇개 보았다. 유튜브로 공부한 거라고 생각하기에는 제법 필요한 코드를 필요한 장소에 올렸다. 물론 전공자가 아니라서 전공자도 어려워하는 스레딩 같은 것들과 관련해 잘못 이해하는 부분도 있는듯 보였지만 우리끼리 사용하는 내부 툴이라 크게 중요하진 않아 보였다. 어쨌든 A가 퇴근 후에도 얼마나 많은 시간을 공부에 할애했는지는 모르겠지만 아르바이트로 근무하면서 유튜브와 블로그로 코딩을 공부해서 실무에 써먹을 수준이 되었다는 건 제법 인상적이었다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;C는 A가 개발을 할 수 있도록 만들어준 B의 후임이다. B는 병특이 끝나고 게임을 개발하고 싶다고 퇴사를 했다. 그래서 그의 후임을 뽑게 됐다. 병특이 가능해 제법 여러 친구를 면접 봤다. 걔중에는 소위 스카이 대학에 재학중인 친구도 두명 정도 있었다. 하지만 최종 합격한 친구는 다소 이 분야와는 인연이 없을 것 같은 이력의 C다.&lt;/p&gt;
&lt;p&gt;C는 고등학교를 졸업하고 다양한 일을 했다. 그의 이력 중 가장 인상 깊었던 건 롯데리아 매니저였다. 어쨌든 그렇게 이일저일 하다가 그는 최근에 개발 관련 일자리가 많다는 걸 알고 국비 지원 자바 교육 과정을 5개월 이수했다. 그리고 지원한게 우리 회사였다. 아이러니하게도 그가 배운건 자바였지만 그가 지원한 포지션은 C#과 파이썬을 사용하는 자리였다. 파이썬은 면접 보기 전에 조금 공부했다고 했다. 그럼에도 그는 그 면접을 진행한 모든 사람을 통틀어 면접 문제를 다 푼 2명에 포함됐고 롯데리아 경력을 높게 평가받아 채용됐다.&lt;/p&gt;
&lt;p&gt;C는 국비 지원 과정을 하기 전에 컴퓨터 관련 교육을 받은 적도 혼자 공부한 적도 없다고 했다. 물론 교육 과정 동안은 정말 치열하게 공부했다고 한다. 예전엔 사실 정부에서 웹프로그래머 일만명 키운다고 국비 교육 과정 만들고 할때에는 회의적인 생각이 많았지만 C를 보면서 생각이 좀 바뀌었다. 교육의 영향력과 밀도는 모두에게 다를 수 있고 기회가 제공될 수 있다는 측면에서 긍정적인 효과가 있다고 생각하게 됐다.&lt;/p&gt;
&lt;p&gt;자바를 5개월 동안 공부했던 그는 선생님에게 하나를 잘 하면 다른 거도 금방 배운다는 얘기를 들었다고 했다. 틀린 말이 아니다. 어쨌든 좋은 선생님에게 배워서 그런지 그는 오늘도 C#으로 내부 툴을 고치고 업그레이드 한다. C는 어리다. 그래서 스펀지처럼 많은 것들을 흡수한다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;E는 한국이 아닌 다른 아시아 국가 출신이다. 그는 고등학교를 중퇴했다. 대신 그 기간동안 독학으로 프로그래밍, 리버싱 등에 관한 공부를 했다고 한다. 그가 회사로 보낸 건 간단한 이력서와 깃헙, 블로그 링크였다. 그의 깃헙 링크는 그가 얼마나 훌륭한 코드를 쓸 수 있는지를 보여 주었고, 블로그는 그가 체계적인 글을 쓰는 능력이 있다는 걸 증명할만큼 충분했다. 그렇게 그의 기술 면접은 바이패스 됐다. 3년 정도 독학으로 공부했다는 그에게 특별한 공부 방법이 있었냐고 물어보자 그저 관심이 있어서 빨리 배울 수 있었다고 했다.&lt;/p&gt;
&lt;p&gt;학부 시절 친한 후배에게서 정말 강려크한 인상을 받은 적이 있었다. 그 후배의 레드블랙 트리를 카피하던 순간이었다. 카피하다 말고 너무 잘 작성된 소스 코드 앞에서 눈물을 훔쳤다. 오프로 아는 다른 이의 코드를 보고 울었던 적은 그때가 처음이었고, 그 다음으로도 없었다. 그런 그가 공동 창업한 회사는 올해 카카오 모빌리티에 인수됐다. 오늘 E가 제출한 풀리퀘스트 코드를 보면서 그때가 떠올랐다. E는 20살이고, 고등학교 대신 3년을 독학한게 전부고, 그의 교재는 인터넷이다. 경력의 허무함과 신입의 가능성을 동시에 보여주는 그는 다소 신비한 존재다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;F는 몇해전 회사에 근무했던 직원이다. 그는 특성화 고등학교를 졸업했고, 학창 시절부터 게임 해킹에 관심이 있어서 이것 저것 해보다 졸업과 동시에 입사를 했다. 그가 입사할 때 우리 회사의 손코딩 문제는 지금보다 어려웠음에도 그는 잘 풀었다. 선생님과 함께 회사를 왔었던 기억이 난다. 처음에는 서툴렀지만 그나이 사람들이 그렇듯 그는 금방 배웠고 에이스 자리를 꿰찾다. 우리는 그를 여포라 불렀다.&lt;/p&gt;
&lt;p&gt;F는 특성화 고등학교를 졸업했지만 정규 교육 과정을 통해서 관련 지식을 배운 건 아니었다. 그도 거의 모든 걸 독학으로 배웠는데 특이하게도 그 경로에는 네이버 카페가 있었다. 비슷한 또래의 네이버 카페에서 난다 긴다하는 애들과 경쟁하다 보니 더 빨리 배우게 된 게 아닐까라는 추측을 해본다. 네이버 카페는 조금 재미난 특징이 있는데 모르는 애들끼리 모여서 말도 안되는 소리를 하는거 같은데 그 와중에 집단 지성이 동작해서 뭔가 발전이 일어난다는 점이다. 보통의 다른 커뮤니티나 사이트는 가르치는 사람이 있고 배우는 사람이 있는데 네이버 카페는 모르는 애들끼리 모여서 자기가 알아낸걸 각자 자신만의 방법으로 한마디씩 하다가 짠하고 종국에는 답이 나온다. 보고 있으면 황당하기도 하도 신기하기도 하고 그렇다.&lt;/p&gt;
&lt;p&gt;그렇게 배운 F는 지금은 국내에서 이름만대면 아는 유명한 IT 회사에 근무한다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;G는 이 이야기에 등장하는 유일한 컴퓨터 공학 전공자다. 그는 대학을 졸업하고 입사했다. 병역특례를 하지 않았다. 너무 평범한 일반적인 케이스가 아닌가? 그렇다. 다만 그가 입사에 있어 특이했던 점은 게임 보안 솔루션을 만들어서 제출을 했다는 것이다. 그는 이력서에 깃헙 링크를 함께 보냈고 거기엔 그가 만든 동작이 가능한 게임 보안 솔루션이 있었다. 뽑지 않을 이유가 없다. 동작하는 게임 보안 솔루션을 직접 생각해서 다 만들었다니…​&lt;/p&gt;
&lt;p&gt;면접 때 그에게 이걸 어떻게 만들었나 물었던 기억이 있다. 그는 자주 했던 게임에서 비슷한 걸 봤고 재밌어 보여서 직접 만들었다고 했다. 동아리나 그런 곳에서 함께 만든 거냐고 물었더니 혼자 만들었다고 했다. 오프에서 이쪽 분야에 관심이 있는 사람들을 만나기 힘들어 혼자서 공부했다는 얘기를 덧붙였다. 그는 지방에서 나고 그곳에서 대학을 졸업했다. 그가 만든 작품은 오버워치에 적용된 이후로 제법 업계에서 핫한 기법이었고 나는 몇가지 질문을 더했다. 그리고 이어진 그의 답변. 그 속에는 그가 얼마나 많은 시간을 날밤새며 사고실험과 삽질을 했는지가 오롯이 담겨 있었다.&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;유튜브, 블로그, 책, 국비 지원 교육 과정, 커뮤니티 사이트, 웹사이트, github, 네이버 카페, 대학교, 사고실험, 삽질 등 다양한 경로로 배움의 과정을 거친 이들을 봤다. 경로는 다양했지만 그들은 하나같이 그일을 하기에 차고도 넘칠 정도로 충분한 지식을 기지고 있었다. 물론 그런 실력을 가지기 위해서 그들이 얼마나 많은 시간과 노력을 투입했는지는 알 길이 없다. 하지만 어쨌든 한가지는 분명하다 관심과 취향이 맞고 노력이 더해진다면 어떤 경로를 택하든 당신이 원하면 당신은 직업 프로그래머가 될 수 있을 거라는 점이다.&lt;/p&gt;
&lt;p&gt;바야흐로 코딩의 시대, 당신이 배우는 단계에 있다면 응당 의문이 많을 수 밖에 없다. 이 방법이 맞을까? 남들도 이렇게 하는걸까? 이렇게해서 취직할 수 있을까? 어떤 길이든 지속할 수 있다면 틀린 길은 아니라고 감히 말할 수 있을 것 같다. 당신의 배움에 건투를 빈다.&lt;/p&gt;
&lt;p&gt;우리 때에는 김국현님의 자바 두명 타세요라는 괴담이 난무했다. 요즘은 업그레이드 된 인공지능 괴담이 난무하는 것 같다. 인공지능이 개발자를 모두 대체한다는 얘기 말이다. 하지만 김국현님의 괴담이 그랬듯 너무 겁낼 필요는 없을 것 같다. 인공지능이 언젠간 개발자를 모두 대체하겠지만 그때는 다른 직업도 상당수는 대체되었을테니 사회적으로 뭔가 다른 솔루션이 나왔을 가능성이 높다. 그리고 그 시간은 생각보다 오래 걸릴 수 있고, 전혀 엉뚱한 방향으로 전개될지도 모른다. 당신의 미래에도 지금 세대 개발자들이 누린 행운이 조금이나마 함께하길 바란다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 의천도룡기 2019]]></title><description><![CDATA[넷플릭스를 방황하다 우연찮게 틀게 된 "의천도룡기 201…]]></description><link>https://jiniya.net/2021/the-heaven-sword-and-dragon-saber-2019/</link><guid isPermaLink="false">https://jiniya.net/2021/the-heaven-sword-and-dragon-saber-2019/</guid><pubDate>Fri, 29 Jan 2021 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;넷플릭스를 방황하다 우연찮게 틀게 된 &quot;의천도룡기 2019&quot;가 내 인생 첫 중드가 되었다. 이상하게 중드는 그간 잘 보지 않았던 기억이 있다. 물론 어렸을 적 이연걸의 광팬이었고, 홍콩 무협 영화를 좋아했었던 것을 보면 딱히 중드를 안 볼 이유도 없는데 그저 이상하게 중드면 시작조차 하지 않았던 기억이 많았다. 그럼에도 의천도룡기를 정주행 할 수 있었던 가장 큰 힘은 아무래도 여캐들의 훈훈한 비주얼 탓이 아닌가 싶다. 그간 한중일중 미모는 한국이 원탑이라 생각했었는데 의천도룡기를 보고 생각이 다소 바뀌게 되었다. 여튼 각설하고,...&lt;/p&gt;
&lt;p&gt;김용의 소설 원작을 읽지 않았지만 의천도룡기 또한 그의 다른 소설과 비슷하게 몹시 재미있다. 시대를 초월해서 바뀌지 않는 인간상, 그리고 고뇌할 수 밖에 없는 인생사를 그리고 있어서 그런 것 같다. 이루어질 수 없는 사랑, 가질 수 없는 것들에 대한 욕망, 그리고 이루고 싶은 것에 대한 집요하고 끊질기며 처절하게 이어지는 집착, 그런 모든 면에서 이 드라마는 많은 것들을 담고 있다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./chomin.png&apos; data-alt=&apos;내가 조민이다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1bcdd4ebfe67f56ffe2b9bfd100a9531/78d47/chomin.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAADJUlEQVR42h2TXUybBRSGPygtHbRohjCQmm1cTOYWkykmOJeYOOPMvPFiGqOLiTNxW2QmskU3jNE4olsNDHSGzGHFTId0ZbgNRl07V1ugCmVtVwqU/pF+/LSQdR1stJbSx287yZv37sl7zpsjVJatpWbrBgRBIC8vD5nkx977gAezFF/i9kSQbCoFK6Ct+4QNygIqVGpU8nyK16gozi+gfG0x40N+ZryzCNVb1/P681uQCzkUKtdQmifj1OfHSSeShD1+7kfnSc1GsVy4TFdrO9pDtaxXFVIgk6FS5LOusAh1bi497Re5G15EqNSUsGfXNuQKGVWlFRzcUYP26Jf4Bh0MXenhdiiEOHITp/Ev5sZiWM5f4J2dLz2EqBUKHi96jBKFms/2HyHuTyDsemEzL1ZvQiFX8HJZOQeee5YTR+q5K0axduolYBDSabyDLux/mOlsaUXXoKW64gkekSspUa/j0fwidm9/hdCIiPD0kxp21lRRJN3ljfJSvtn9KsMmM8vxBOGbbshmWZye489zBjobv+PwW3tpP3GKk7UfUlVcxpvbnmHHpko2ajYyNhBAyM3JQSEVsUWjoWHPa7R/dICIx0ciMk8mmX6YztFlwHvDju3iNWnlbq7/1k1n8/ecqf8U3f532f7UZpQKJbqmNoRDbx/kq7oGfmo5j9Xkwmlx0y8VEA1ESC4kyMzG+Megl0B6en5oo6+1DfMvenp1HeibmqnbV4uuYwDdz0a+ONyA4AtnCM7AZARuTaRwee4RnrxD5n5KUhKWV3HdsNHR2IT560ZOv78PQ/NprradQ/vxUX79vR+TTcQ1cQ+TaQTBaA5yqW+CriujGC6N0msKYXfEEafThEJJ7EMxBu0if1v8WIy3uK43cvb4SX6sP8aZb89y1RzANiAyNplkKrqKMDC0wL/uRYalZE5vklF/Buf4fzg8y4x4Uww6l7A6EniksnvscdzBJH29w+i0LfR292OzBpmOrDI1k0FcyCB4Axk8EsQ9mcblS0u+gifwAJqSfAW/iKQM41NZrM5FrjkWSEiPY7EGCPruMCdtMj+fRYxJ0FiW/wEZfmoICCWI7QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;내가 조민이다.&apos; title=&apos;&apos; src=&apos;/static/1bcdd4ebfe67f56ffe2b9bfd100a9531/efd7b/chomin.png&apos; srcset=&apos;/static/1bcdd4ebfe67f56ffe2b9bfd100a9531/08678/chomin.png 190w,
/static/1bcdd4ebfe67f56ffe2b9bfd100a9531/2edd7/chomin.png 380w,
/static/1bcdd4ebfe67f56ffe2b9bfd100a9531/efd7b/chomin.png 760w,
/static/1bcdd4ebfe67f56ffe2b9bfd100a9531/78d47/chomin.png 800w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;내가 조민이다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그 모든 스토리 중에서도 단연 돋보였던 캐릭터는 다름아닌 조민이었다. 물론 그녀가 여주이면서 가장 예뻐서 그랬다는 점도 부인은 못하겠지만 그것 외에도 그 캐릭터가 보여주는 태도는 많은 것들을 느끼게 해주었다. 이루어질 수 없는 사랑, 그것을 위해서는 엄청난 희생이 따를 것이라는 것을 알면서도 그녀는 처절하고 끊질기고 집요하게 그 사랑을 얻기 위해 모든 것을 걸었다. 그녀 출신 성분 자체가 그것을 통해 얻을 것 보다는 잃을 것이 더 많다는 점은 그 과정을 더욱 납득하기 힘들게 만들었지만 반대로 또 더 애절해 보이게 만드는 효과가 있었다.&lt;/p&gt;
&lt;p&gt;드라마 3대 빌런을 꼽자면 나는 아미파의 멸절사태, 대사저, 지약을 꼽겠다. 작가가 남자라 그런지 악역을 여자 무림파에 몰아 넣은 감이 없잖아 있는 것 같다. 자신의 주장을 죽음을 앞에 두고도 굽히지 않으며 의미 없게 죽어서 여러사람 피곤하게 만드는 고집불통 빌런 멸절사태, 그리고 본인의 알량의 권력을 믿고 위로는 굽신거리며 아래 사람들에게는 끊임없이 막대하는 대사저, 그리고 우유부단 빌런의 끝판대장 지약.&lt;/p&gt;
&lt;p&gt;이 드라마는 시작부터 끝까지 인간의 처절한 고뇌를 담고 있다. 이루어지면 안 되는 정파와 사파의 사랑, 자신의 복수를 위해 한 평생을 바치며 온갖 악행을 저지르는 한 남자, 그들 사이에서 출생부터 복잡하게 꼬여버린 주인공, 삶과 죽음의 경계에서의 처절한 사투, 대업과 사랑 사이의 갈등 같은 우리가 살면서 겪을 수 있는 시대를 초월한 온갖 고뇌와 인간 군상들을 닮고 있기에 이 드라마는 재밌었고 유익했다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[ai] 너와 나의 인공지능이 멍청한 이유]]></title><description><![CDATA[모든 사람이 그렇듯 내가 머신러닝에 관심을 갖게 된 시점은 알파고가 이세돌을 무참히 격파하던 그 즈음이었다. 대국이 시작되기 전 나는 당연히 이세돌의 전승을 점쳤고,…]]></description><link>https://jiniya.net/ng/2020/07/deep-learning-101/</link><guid isPermaLink="false">https://jiniya.net/ng/2020/07/deep-learning-101/</guid><pubDate>Wed, 15 Jul 2020 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;모든 사람이 그렇듯 내가 머신러닝에 관심을 갖게 된 시점은 알파고가 이세돌을 무참히 격파하던 그 즈음이었다. 대국이 시작되기 전 나는 당연히 이세돌의 전승을 점쳤고, 1국이 끝나고 세상이 바뀌었다는 사실을 깨달았다. 그리고는 봇물처럼 머신러닝 자료와 강연들이 이어졌다. 그덕에 구글의 제프딘을 실제로 보기도 하는 호사를 누리기도 했다 (텐서플로 홍보차 국내에 옴)&lt;/p&gt;
&lt;p&gt;그때 제프딘이 발표한 내용 중에 이미지 인식(이게 고양이인지, 강아지인지, 나팔꽃인지, 장미인지, 등등을 판단) 분야에서는 기계가 인간을 뛰어 넘은지가 제법 됐다는 이야기를 했다. 그리고 얼마 지나지 않아 각종 렌즈앱들이 나오기 시작했고, 그 렌즈앱이 우리 엄마보다 더 정확하게 각종 식물의 이름을 나열하는 것을 보면서 2차 충격을 받았다. 그렇게 머신러닝의 르네상스는 시작되었고, 요즘 IT쪽 사람들을 만나서 뭐 하는지 물어보면 분야를 안 가리고 머신러닝 한다는 대답이 돌아오는 세상이 되었다.&lt;/p&gt;
&lt;p&gt;어쨌든 그맘때 이미지 인식을 그렇게 기계가 잘 한다면 바이너리 인식도 잘하지 않을까라는 생각이 들었다. 컴퓨터한테야 이미지든 바이너리든 결국은 숫자일 뿐이니 말이다. 그런 선상에서 그당시 유행하던 머신 러닝 라이브러리로 해킹툴 바이너리를 분류해서 몇 개 학습시켜 보고 결과를 체크해 보았다. 샘플에서는 너무 완벽하게 동작했지만 각종 정상 바이너리를 집어 넣자 오진이 무지하게 많이 났다.&lt;/p&gt;
&lt;p&gt;그당시 MS에서도 바이너리 분류와 관련한 컨테스트를 진행하고 있었다. 심지어 결과물도 공개가 되어 있었다. 테스트 안해볼 이유는 없기에 거기 1등한 사람들의 방법을 가져와서 우리도 테스트를 해보았다. MS 대회의 1위 답게 그냥 우리가 막 이미지 인식 시킨 것 보다는 훌륭했다. 그래서 본격적으로 돌려보자고 했는데, 회사 장비로는 한계가 있고 AWS에서 돌리면 수백만원 정도의 비용이 지출될 것 같다는 얘기를 했다. 될지 안될지도 모르는 일에 그 정도를 투자한다는게 쉽지 않은 일이라 거기까지 하고 말았던 기억이 난다.&lt;/p&gt;
&lt;p&gt;그 1등의 방식도 재미있었는데 각종 팩터를 넣어서 학습시키는데 그 중에 하나가 바이너리 앞부분 200바이트 해시를 사용한다거나(200이란 숫자는 정확한 건 아님) 하는 것이 있다. 그래서 왜 300도 아니고, 400도 아니고 200이지라는 의문을 가지고 그들이 쓴 논문을 봤는데, 그 논문 왈, 200바이트가 왜 잘되는지는 우리도 모르겠지만 여러 테스트 결과 그게 좋아서 그렇게 했다는 다소 충격적인 답변. 아, 이런게 머신러닝 이구나 라는 느낌만 가지고 기억속 한편으로 사라졌다.&lt;/p&gt;
&lt;p&gt;그렇게 잊고 있었던 머신러닝 관련해서 최근 지인 한 명이 그때 그 생각이 틀린 건 아닌 거 같다면서 MS에서 발표한 링크 를 보내줬다. 소오름. 내 생각이 바로 저거였는데 저게 된다니 ㄷ ㄷ ㄷ 그리고 우리가 머신러닝알못이라 그렇지 구현을 제대로 했으면 그때부터 잘됐을까라는 생각도 들었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.microsoft.com/security/blog/wp-content/uploads/2020/05/stamina-steps-blog.png&quot; alt=&quot;Analyzing malware represented as image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그렇게 다시금 인공지능에 대한 연구 의지가 불타오름과 동시에 교보문고에서 인공지능 책들을 마구 질렀다. 친구가 심지어 2권은 선물까지 해줬으나 서평은 요원한 단계. 어쨌든 그 책들을 읽고 이미지 분류에 그렇게 좋다는 CNN으로 이미지를 좀 분류해보려고 돌렸으나 결과는 썩 좋지 않았다. 인공지능 쪽에 다소 조예가 있는 주변인들에게 물어보면 대다수가 그게 교과서에 나오는 건 잘 되는데 실질적으로 현실 세계 데이터로 뭐를 해보려면 잘 안 된다는 이야기를 했다. 그 이야기와 함께 다시금 광속으로 연구 의지는 마이너스 무한대로 발산하게 되었다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;그런 기억이 희미해질만했던 6월 말 회사에서 병역특례로 근무하던 DevOps 친구가 그만두는 일이 있었다. 여러모로 똑똑한 친구였는데 헤어지는 자리에서도 다소 충격적인 이야기를 들려주었다. 머신러닝을 하기 위해서 무.려. 4400만원짜리 컴퓨터를 질렀다는 이야기.&lt;/p&gt;
&lt;p&gt;그 이야기의 여러 요소에서 다중 충격을 받았는데, 1) 머신러닝을 하기 위해서 개인 돈으로 컴퓨터를 사는 투자를 한다는 데 놀랐고, 2) 그것도 무려 4400만원짜리를 샀다는 데 두 번 놀랐고, 3) 그 엄청난 비용의 상당수가 최근 유행하는 T 코인(테슬라)에서 충당됐다는 사실에 놀랐다. 어쨌든 그 머신은 제온씨퓨에 타이탄을 무려 4개나 달았다고 했다.&lt;/p&gt;
&lt;p&gt;머신러닝을 하려면 그 정도 장비가 필요한 거냐고 물어봤더니 자기도 잘은 모르는데 제대로 해보려고 좋은 장비를 샀다는 이야기를 했다. 그와 더불어 요즘 AI 대회가 많아서 그런 곳에서 상금을 받으면 투자금 회수가 가능하다는 이야기도 덧붙였다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;그 친구가 퇴사한 이후에 회사에 인공지능 하는 친구들이 현장실습을 왔다. 그당시 하다가 포기한 이미지 분류 작업을 진행하기 위해서 왔는데 그들은 학교에 있는 1080TI가 몇 개 있는 장비를 사용할 수 있는 상태였다.&lt;/p&gt;
&lt;p&gt;출근한 날 같이 저녁을 먹을 시간이 있어서 이런 저런 얘기를 하다가 애니를 좋아한다는 이야기를 듣게 되었고, 추천작을 물어봤더니 고스트 바둑왕을 꼽았다. 나는 만화책으로 봤는데 끝이 너무 허했다는 이야기를 전했다. 작가가 히트 좀 하자 끝낸 용비불패같은 느낌. 그 친구가 애니는 그래도 괜찮다는 이야기를 했고 마침 스트리밍 서비스에 올라와 있길래 사이와 히카루의 대국을 애니로 몇 편 보게 되었다. 모든 만화가 그렇지만 보면 뿜뿜하게 된다. 바둑 기사 존멋~&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;히카루와 사이의 바둑에 빠져서 애니를 보다보니 자연스레 바둑을 배우고 싶다는 생각이 들었고, 예전에 프로 기사를 준비했던 동생이 알파고 이후에 제로 시리즈 인공지능 바둑이 많이 나왔다는 이야기를 들었던 기억이 많이 났다. 그래서 집에 설치해보고 돌렸는데 자기들끼리 두게 해도 제법 모양이 나오게 두었다. 나는 바둑을 둘 줄 몰라 실력을 알 수 없어서 온라인 바둑에 들어가서 몇 판 둬봤는데 지는 법이 없었다. 그리고 유튜브를 찾아보니 프로 기사들도 3점 놓고 둬야 이기고, 2점은 힘들다는 이야기들이 올라와 있었다.&lt;/p&gt;
&lt;p&gt;간략하게 인공지능 바둑에 대해서 이야기하자면 알파고가 시초고, 알파고 제로가 나오고 그들이 연구 방식을 논문으로 공개해서 유사한 종류의 인공지능이 많이 나오게 됐다. 제로의 특징은 인간의 기보를 사용하지 않고 자기 스스로 게임을 반복(self play)하면서 기량을 향상시켜 나가는 기법을 쓴다. 따라서 바둑의 룰만 넣어주고 돌리면 스스로 점점 더 강해진다는 알고나면 다소 단순해 보이는(?!) 컨셉이다.&lt;/p&gt;
&lt;p&gt;그 이후에 등장한 것 중에는 릴라제로의 경우 개인이 오픈소스로 만들어 대중의 참여로 분산 학습시켜 나가는 구조로 진행되고 있다, 페이스북에서도 엘프고라는 프로젝트로 야심차게 진행했으나 현재는 퇴물, 그리고 가장 최근에 나온 게 카타고다. 카타고의 특징은 기존 알파고가 바둑이란 게임의 특징을 별로 활용하지 않았다면 카타고는 바둑에 특화된 특징을 많이 사용해서 학습 속도가 빠르고 승률 외의 다른 종류의 예측들을 더 가지고 있다고 한다. 개인 컴퓨터에서 각종 인공지능들끼리의 대국을 펼쳐 보았는데 카타고가 제일 강했다. 심지어 생각하는 시간을 차이를 두어도 카타고가 이기는 경우가 많았다.&lt;/p&gt;
&lt;p&gt;대체로 프로 기사들 사이에서는 알파고 제로 &gt; 텐센트 절예 &gt; 카타고 &gt; 릴라 제로 정도로 판단되고 있는 것 같았다. 이런 걸 보면 궁금증이 생기게 마련이다. 비슷한 셀프 플레이란 방식으로 학습을 시켰음에도 그들 사이에서 큰 기량 차이가 생기는 이유는 뭘까? 심지어 페이스북도 나름 똑똑할텐데 왜 엘프고는 순위에도 끼지 못할까라는 생각을 하면서 릴라제로 소개 페이지를 보다가 신기한 사실을 알게 되었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Recomputing the AlphaGo Zero weights will take about 1700 years on commodity hardware.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;알파고 제로의 가중치 데이터를 재계산하는데에는 상용 하드웨어로 1700년이 걸린다는 이야기. 요는 이렇다. 제로 방식은 셀프 플레이를 토대로 가충치 파일을 만들어 추후 탐색을 할 때 더 적절하고 빠르게 하는 형태로 사용을 한다. 즉, 대다수 제로 방식 봇의 알맹이는 이 가중치 파일이란 것이다. 릴라제로 개발자는 1080ti 그래픽 카드 한 장으로 개발을 하는데 본인이 생각하는 추정치로는 그 그래픽 카드 하나로 알파고만큼의 수준을 계산하기 위해서는 1700년이 걸린다고 말한 것이다. 그걸 극복하기 위해서 릴라제로는 개인의 컴퓨팅 자원을 지원 받아 클라우드 형태로 계산해서 학습하는 구조로 진화를 하고 있다. 그냥 숫자만 보고 역시 구글이라는 생각을 하면서 카타고 자료도 살펴보게 되었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;KataGo’s latest run used about 28 GPUs, rather than thousands (like AlphaZero and ELF), first reached superhuman levels on that hardware in perhaps just three to six days, and reached strength similar to ELF in about 14 days. With minor adjustments and some more GPUs, starting around 40 days it roughly began to match surpass Leela Zero in some tests with different configurations, time controls, and hardware. The run continued for a total of about five months of training time, reaching several hundred Elo stronger than Leela Zero and likely other open-source bots. The run has ended for now, but we hope to be able to continue it or begin another run in the future!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;여기는 조금 구체적인데 28개의 GPU로 학습을 시켰고, 인간을 뛰어넘는데 3-6일이 걸렸고, 14일에 엘프고 수준에 도달했다. 여기에 조금의 조정을 하고 GPU를 몇개 더 추가해서 40일 정도 되니까 릴라 제로의 수준에 도달했고, 총 5개월 정도가 지나서는 릴라제로에 비해서 Elo 점수가 수백점 차이가 났고 학습을 중단시켰다는 이야기. 내용이 재밌어서 그들의 논문도 찾아서 읽어보았다. 도입부가 무척 흥미로웠는데 다음과 같이 정리돼 있었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In 2017, DeepMind’s AlphaGoZero demonstrated that it was possible to achieve superhuman performance in Go without reliance on human strategic knowledge or preexisting data [18]. Subsequently, DeepMind’s AlphaZero achieved comparable results in Chess and Shogi. However, the amount of computation required was large, with DeepMind’s main reported run for Go using 5000 TPUs for several days, totaling about 41 TPU-years [17]. Similarly ELF OpenGo, a replication by Facebook, used 2000 V100 GPUs for about 13-14 days, or about 74 GPU-years, to reach top levels of performance [19].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;알파고 제로의 경우 5000 TPU로 몇일 계산을 했다고 나와 있다. 총 41년 TPU 시간이 사용되었다. 엘프고의 경우 2000개의 V100 GPU를 사용해서 13-14일 계산을 했고, 총 74년 GPU 시간이 사용되었다.&lt;/p&gt;
&lt;p&gt;결국 당연한 소리겠지만 동등한 설정이라면 결국 연산 시간에 따라서 인공지능의 강함이 결정된다고 할 수 있겠다. 그런데 그 연산 시간이라는 것이 생각보다 천문학적이라는데 놀랐다. 릴라제로 개발자는 1080TI GPU 한장으로 개발을 하고 있고, 카타고는 V100 28장에서 몇 장을 더썼고, 엘프고는 V100 2000장, 알파고제로는 TPU 5000개를 사용했다.&lt;/p&gt;
&lt;p&gt;FP32벤치 마크 자료를 살펴보면 1TPU를 1.0으로 계산 시에, V100이 0.9정도, 1080TI가 0.4 정도 되는 것으로 추정된다. 이 데이터를 토대로 연산에 사용된 비용을 계산해보면 다소 충격적이다.&lt;/p&gt;
&lt;p&gt;카타고의 경우 줄여서 V100 28개 5개월로 계산할 경우 (28 x 5 x 30) / 365 = 11.5년에 해당하는 GPU 시간을 사용했다고 볼 수 있다. aws에서 v100을 8개 탑재한 p3.16xlarge의 경우 시간당 사용 비용이 24.48불이다. 단순 계산할 경우 5개월간 총 308,448불이 사용되었다고 볼 수 있다. 1200원 환율로 계산할 경우 3억 7천만원에 해당하는 금액이다.&lt;/p&gt;
&lt;p&gt;엘프고의 경우 동일한 장비로 74년 GPU 시간을 썼다고 나와 있기 때문에 계산해보면 1,983,614불을 썼고, 한화로 23억 8천만원 정도를 썼다고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;구글 TPU의 경우 선점형 v2 8코어가 시간당 1.35불이다. 이걸 토대로 41년 TPU시간을 계산해보면 60,608불, 7300만원 가량 사용한걸로 보여진다. 선점형이 아닌 주문형으로 할 경우 시간당 가격이 4.45로 올라가기 때문에 계산해보면 199,782불, 한화로 2억 4000만원 가량이 된다. 1대 0.9로 GPU 환산 계산시 45.51년 GPU 시간이 나오고 aws 비용으로 환산해 보면 1,219,922불, 한화로 14억 6400만원 가량이다.&lt;/p&gt;
&lt;p&gt;아마 이건 최적화된 경로로 계산을 하는 걸 밝힌 것이기 때문에 실질적으로 테스트에 사용되거나 폐기되거나 한 걸 감안한다면 훨씬 더 천문학적인 비용이 지출된다는 걸 알 수 있다. 그리고 왜 학습을 멈추는지도 이해할 수 있다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;우리가 바둑 인공지능을 만든다고 한다면 적어도 사람과는 대등하거나 잘 두는 수준이 되어야 쓸 만 하다고 인정을 해 줄 것이다. 이를 카타고 데이터를 토대로 최적화 시켜서 3일 걸린다고 가정을 하더라도 최적화된 계산 비용만 49,351불 한화로 6000만원 가까이를 써야 가능하다. 물론 이 또한 실패는 전혀 없는 모든 게 아마도 완벽한 상태에서의 계산 시간만을 가정했을 때 그렇다는 이야기일 것이다.&lt;/p&gt;
&lt;p&gt;재미삼아 또는 가능성만 보고 하기에는 쉽지 않은 분야라는 답이 나온다. 그리고 너와 나의 인공지능이 왜 그렇게 바보같은지도 어느 정도 이해가 된다. 구글이 왜 TPU를 만들었는지도 답이 나온다. 카타고가 더 강하게 만들지 않는 이유도 알 수 있고, 언제 새로 돌리기 시작할지도 예측해 볼 수 있다. 알파고 제로 가중치 파일을 공개하지 않는 이유도 추측해 볼 수 있고, 절예의 최신 가중치 파일을 왜 중국 프로 기사에게만 제공하는지도 납득이 된다. 심지어는 똑똑한 사람들이 돈을 많이 넣어도 결과가 좋지 않을 수 있다는 사실도 참고할 수 있다. 끝으로 몇년전 우리가 몇 백만원에 망설였던 게 얼마나 조족지혈인지도 알게 되었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] 웰비아닷컴은 채용 중~]]></title><description><![CDATA[이 채용 공고에 관심이 있고 해당 자격 요건을 갖추었다고 판단되시는 분은 codewiz 앳 wellbia 닷 com으로 이력서와 자기소개서를 메일 주시면 됩니다. 자격 요건 C/C…]]></description><link>https://jiniya.net/ng/2020/05/recruit/</link><guid isPermaLink="false">https://jiniya.net/ng/2020/05/recruit/</guid><pubDate>Tue, 12 May 2020 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;이 채용 공고에 관심이 있고 해당 자격 요건을 갖추었다고 판단되시는 분은 codewiz 앳 wellbia 닷 com으로 이력서와 자기소개서를 메일 주시면 됩니다.&lt;/p&gt;
&lt;h3&gt;자격 요건&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C/C++ 시스템 프로그래머&lt;br&gt;
윈도우, 리눅스 둘 중 하나는 잘 알아야 합니다.
CreateThread와 fork 둘 중 하나는 제대로 호출할 줄 아는 분이면 좋겠습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;리버스 엔지니어&lt;br&gt;
윈도우 시스템에 대한 이해가 있는 분석가를 모집 중입니다.
가상 메모리 구조, 실행 파일 구조, x86/64 어셈블리어에 대한 이해가 있는 분을 채용 중입니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;장점&lt;/h3&gt;
&lt;p&gt;(주)웰비아닷컴은 세계적으로 얼마 안되는 상용 게임 보안 제품을 만드는 회사입니다. a) 대체로 이쪽의 커리어를 쌓기 위해서는 한국, 독일, 핀란드 중에 한곳에 연고가 있는 것이 유리합니다. 한국에 계시다구요? 네 그러시면 저희와 함께 일하는 것이 좋을 것 같습니다. b) 저희는 전세계적으로 가장 인기있는 게임을 제작하는 게임 벤더들과 작업하고 있습니다. 그렇기에 최신의 최고급 해킹 테크닉과 방어 메커니즘을 가장 빠르게 배울 수 있습니다. 또한 그만큼 성장할 기회도 많다는 걸 의미하기도 합니다. c) 저희는 열린 회사입니다. 여러분이 접근할 수 없는 소스 코드는 없습니다. 모든 걸 볼 수 있고, 모든 걸 바꿀 수 있습니다. d) 야근이 없습니다. 99.478% 이상의 확률로 칼퇴근을 보장합니다. e) 직원을 어린이 취급하지 않습니다. 모두 똑같은 성인으로 존중합니다. 언제 쉴지 언제 일할지는 충분히 본인이 결정할 수 있다고 판단하고 그 의사를 존중합니다. 다른 것들도 마찬가지입니다.&lt;/p&gt;
&lt;h3&gt;단점&lt;/h3&gt;
&lt;p&gt;30명 미만의 작은 기업입니다. 연봉이 높지 않습니다. 박봉이라고 생각하지는 않지만 배달의민족 채용 공고처럼 그걸 강점으로 내세울 수 있는 수준은 아닙니다. 폭발적으로 성장하는 기업은 아닙니다. 물론 그렇다고 정체된 회사는 아니지만 쿠팡 채용 공고처럼 압도적으로 높은 성장률을 강점으로 내세울 수준은 아닙니다.&lt;/p&gt;
&lt;h3&gt;사족&lt;/h3&gt;
&lt;p&gt;덧1) 긍정적인 분만(!!) 채용합니다. 부정적인 성격이시면 저희와는 잘 맞지 않을 수 있습니다. 기본적으로 세상이 더 나은 방향으로 발전하고 있다고 확고하게 믿는 분들과 함께 일하는 것을 선호합니다.&lt;/p&gt;
&lt;p&gt;덧2) 관련 경력이 15년 이상인 올드스쿨 멤버들도 채용하고 있습니다. 이쪽 분야의 아주 오래된 고유 경력을 가지고 계시고 본의 아니게 경력을 이어나가기가 힘들어진 엔지니어 분이라면 언제든지 연락 주시면 좋겠습니다. 저희는 해당 경력을 완전하게 존중합니다. RESPECT!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 2019-06-26]]></title><description><![CDATA[지난 4년을 회고한다. 어쩌다 여기까지 오게 되었나? 무엇이 문제였나? 앞으로 어떻게 살아야 하는가? 내가 나를 몰랐다. 미래]]></description><link>https://jiniya.net/2019/06/2019-06-26/</link><guid isPermaLink="false">https://jiniya.net/2019/06/2019-06-26/</guid><pubDate>Wed, 26 Jun 2019 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;지난 4년을 회고한다.&lt;/p&gt;
&lt;p&gt;어쩌다 여기까지 오게 되었나?&lt;br&gt;
무엇이 문제였나?&lt;br&gt;
앞으로 어떻게 살아야 하는가?&lt;/p&gt;
&lt;p&gt;내가 나를 몰랐다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;미래&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 책임진다는 말...]]></title><description><![CDATA[오래전 일이다. 먹고 살기 힘들어 인건비 따먹기 SI 사업을 하던 때였다. 당연한 얘기지만 SI…]]></description><link>https://jiniya.net/ng/2018/11/take-responsibility/</link><guid isPermaLink="false">https://jiniya.net/ng/2018/11/take-responsibility/</guid><pubDate>Thu, 08 Nov 2018 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;오래전 일이다. 먹고 살기 힘들어 인건비 따먹기 SI 사업을 하던 때였다. 당연한 얘기지만 SI 사업에는 적은 리소스를 투입하고 최고의 효과를 얻어야 하던 시절이기도 했다. 그래야 시간이 생기고 그래야 우리 솔루션도 돌 볼 수 있기 때문이다. 그 당시 과제의 한 모듈을 담당했던 개발자가 자꾸 직접 구현해서 될 일이 아닌 것을 직접 구현하려고 했다. 문자열 인코딩을 처리해야 하는 모듈이었다. 문자열 인코딩만 본다면 개발자가 직접 구현해도 될 것 같지만 온갖 코드페이지를 다 처리해야 했기에 또 그렇게 간단하진 않은 모듈이었다. 그래서 왠만하면 오픈소스를 쓰라고 검토해서 알려주었다. 다소 C++ 중2병 환자가 만든 소스 코드 같아 보였지만 코드 내부를 봤을 때 온갖 코드페이지를 잘 처리할 수 있을 만큼 충분히 복잡하게 만들어져 있었다. 안타깝게도 문제의 개발자는 온몸으로 거부했다. 스스로 직접 구현할 수 있고, 그 소스는 너무 복잡하다고 했다. 그러고 덧붙였다. 잘못되면 책임지겠다.&lt;/p&gt;
&lt;p&gt;뭐 뻔한 결말이지만 그 친구가 만든 코드가 잘 되지도 책임을 지지도 못했다. 직접 만든 코드는 우리가 실시한 간단한 테스트는 통과 했지만 의뢰한 업체의 온갖 테스트에는 속속 문제가 발생했다. 러시아어에서 비롯된 문제는 온갖 if문을 달아가며 언어 하나가 나올 때마다 땜빵을 해봤지만 잘 되지 않았다. 결국 처음부터 그 오픈소스 코드를 가져다 쓰는 코드로 바꾸고서야 문제가 해결됐다. 하지 않아도 될 고생을 한 것도 화가 났지만, 우리에게 천금같았던 시간을 낭비했다는 데 더 많은 울화가 치밀었다.&lt;/p&gt;
&lt;p&gt;책임진다는 말을 우리는 너무 쉽게 하는 경향이 있다. 아마도 그 직원은 두 가지 의미에서 책임진다는 말을 했을 가능성이 높다. 1) 책임지고 그만두겠다. 2) 잘못되면 내가 그 돈을 메꾸겠다. 대체로 1번의 의도로 말하는 경향이 많지만 그건 그 어떤 것에 대한 책임도 되지 않는다. 회사 입장에서 책임이란 말은 그저 문제가 없는 상태로 일이 잘 처리되는 것 외에는 어떠한 방법도 없기 때문이다. 그런 맥락에서 2번도 해법은 아니다. 금전적 손실은 메꿀 수 있겠지만 일을 맡긴 업체와의 관계는 보상이 불가능하니 말이다. 사실 돈을 메꾼다는 것도 불가능한 상황이긴 했다. 그 친구가 숨도 안 쉬고 5년을 일해도 메꿀 수 없는 규모였다.&lt;/p&gt;
&lt;p&gt;시간이 많이 흘렀다. 이 어리고 서툴렀던 시절의 추억담이 종종 떠오른다. 그 친구 입장에 내가 서 있다는 생각이 들어서다. &quot;방향이 틀리면 속력은 아무런 의미가 없다&quot;라는 간디의 말도 다시금 생각나는 요즘이다. 아주 사소한 나의 잘못된 생각 하나에 시간과 속력이 더해져 우리는 완전 엉뚱한 장소에 도착해 버렸다. 이제는 내가 잘못 생각한 일들을 책임지고 바로 잡아야 하는 시간인 것 같다는 느낌. 사실 앞서도 말했지만 책임진다는 건 그 어떤 형태로도 불가능하다. 그 말을 꺼낸 순간 우리는 책임질 수 없는 상황에 도달한 경우가 더 많이 때문이다. 그럼에도 최선을 다해야 한다. 그게 그나마 나의 잘못을 조기에 알려준 현명한 사람들에 대한 예의일테니까…​ 머리가 나쁘면 손발이 고생이고, 똥인지 된장인지 먹어봐야 안다.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/bo_efYhYU2A?si=BljkyVBznwiFGqbr&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title><![CDATA[[소고] 재현 가능한 빌드, 재현 가능한 시드]]></title><description><![CDATA[#0 최근에 덤프 파일 심볼이 맞지 않는 문제가 있었다. wow64 프로세스 덤프를 뜬 건데 .reload를 해봐도 심지어 다운로드 받은 심볼을 지우고 다시 받아도, windbg를 업그레이드 해봐도 소용 없었다. 항간에 windows 10 rs…]]></description><link>https://jiniya.net/ng/2018/07/reproducible-builds/</link><guid isPermaLink="false">https://jiniya.net/ng/2018/07/reproducible-builds/</guid><pubDate>Mon, 23 Jul 2018 12:00:01 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;최근에 덤프 파일 심볼이 맞지 않는 문제가 있었다. wow64 프로세스 덤프를 뜬 건데 .reload를 해봐도 심지어 다운로드 받은 심볼을 지우고 다시 받아도, windbg를 업그레이드 해봐도 소용 없었다. 항간에 windows 10 rs4에서 심볼이 잘 안 맞춰진다는 이야기도 있어서 그런건가 싶어서 포풍 검색을 해봤지만 뾰족한 수가 없었다. 증상은 심플했는데 wow64 프로세스임에도 ntdll이 하나만 있었고, 로드된 dll 목록의 타임스탬프가 invalid라고 나왔다. 그리고 ntdll의 함수를 디스어셈블 하면 이상한 코드들이 나왔다. 여튼 그런 증상…​ 그렇게 퇴근 시간은 다가오고 오늘의 일을 내일로 미루고 퇴근을 했다…​&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;다음날. 덤프를 다시 열어서 방망이 깎는 노인이 그랬듯 출력되는 메시지를 한줄 한줄 꼼꼼히 쳐다 보았다. 그랬더니 이상한 점이 보였다. 덤프를 열면 통상적으로 운영체제 버전이 표기되는데 64비트 운영체제가 아니라 32비트 운영체제로 나오는 것이었다. 순간, 많은 정황을 고려해 보았을 때 덤프를 64비트 PC에서 32비트 덤프 생성 도구로 덤프를 뜬 것이 아닐까라는 생각이 들었다. 덤프를 생성한 직원에게 물어보자 그렇게 생성했다고 하길래 64비트로 다시 생성해 달라고 했다. 새롭게 만들어진 덤프은 기다렸다는 듯이 잘 동작했다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;뭐 이 즈음에는 대체로 내가 원한 모든 문제는 다 해결이 되었지만 그럼에도 불구하고 찜찜한 점이 하나 있었는데, 그건 여전히 dll들의 타임스탬프가 invalid라고 나오는 문제였다. 다른 모든 것은 기대한대로 동작했지만 타임스탬프 값은 여전히 오리무중…​ 다시 포풍 검색을 했다. 나에게 항상 해답을 주시는 레이몬드 첸 횽님께서 벌써 올해 1월에 관련 질문에 대한 답을 올려 놓으셨다. 이렇게 바지런 하시니 몸둘 바를…​&lt;/p&gt;
&lt;p&gt;해당 글을 통해 알게 된 썰은 이렇다. 윈도우 10부터 재현 가능한 빌드(reproducible builds)로 방향을 정했고, 그 정책의 일환으로 타임스탬프를 타임스탬프가 아닌 해시 값으로 변경했다는 것이다. 재현 가능한 빌드라는 건 한 마디로 정리하면 동일 소스 코드로 컴파일을 하면 동일 바이너리가 생성된다는 것을 보장한다는 개념이다. 즉, 니가 소스 코드를 한 줄도 안 고쳤다면 넌 어디에서건 다시 컴파일해도 동일한 바이너리를 가지게 된다는 의미다. 이렇게 하는 이유는 당연히 버그에 보다 빠르게 대응하기 위함이겠거니…​ 내지는 높으신 분의 개취…​&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;여기까지 오자 몇 해 전 우리에게 혁신적인 개념을 소개했던 직원의 아이디어에 대한 이름을 이제야 붙이 수 있게 되었다. 그 이름은 다름아닌 재현 가능한 시드(reproducible seed) 정도가 되겠다. 적어도 4-5년은 거슬러 올라가야 하는 이야기다. 우리는 당시 아주 난해한 버그를 마주하고 있었다. 100번 정도에 한 번씩 게임이 시작 시점에 크래시가 나는 문제였다. 지금에 비하면 아주 단촐했던 테스트 인력을 가지고 있던 당시로써는 문제를 발견해 낸 것만 해도 대단한 것이었다. 하지만 그 문제를 해결하는 것은 발견하는 것 이상의 노력이 필요했다. 재현을 하려면 100번을 실행해야 했기 때문이다. 어쨌든 그 당시 테스트 인력의 도움으로 어렵사리 덤프를 확보했다. 하지만 아무도 문제를 찾지 못했다. 딱 미제(미해결 과제)가 되기 좋은 사안이었는데 어디선가 혜성같이 등장한 구원 투수가 마법같이 문제의 원인을 알아냈다. 랜덤이 문제였다. 랜덤 결과가 특정 값이 될 경우 메모리가 오버래핑되는 문제가 있었던 것이다. 그 확률이 1/100정도 됐던 모양이다.&lt;/p&gt;
&lt;p&gt;그때 그 덤프에서 문제를 찾은 직원은 우리가 업무 특성상 랜덤을 많이 사용한다면 재현 가능한 시드 시스템을 도입해야 한다는 것을 주창했다. 그 메커니즘은 재현 가능한 빌드와 동일한데 시작 시에 랜덤 시드를 지정하면 프로그램 전체가 그 시드에 동기화되어서 동작하는 것을 보장하는 것을 의미한다. 이렇게 말하면 어려운데 그냥 쉽게 코드로 말하면 전역 의사 난수 시스템을 사용하고 시작 시에 시드를 고정할 수 있는 방법을 제공해야 하는 것을 말한다.&lt;/p&gt;
&lt;p&gt;이렇게 할 경우 어쩌다 한 번 크래시 났을 때, 시드를 알고 있다면 그 다음에는 굳이 100번 실행할 필요가 없다. 해당 시드를 넣고 실행하면 동일한 실행 결과를 보장하기 때문이다. 랜덤이 문제라면 똑같이 문제가 발생할 것이다. 즉, 버그를 찾기가 엄청 쉬워지는 장점이 있다. 여기에 플러스 퍼징 테스트를 하기가 아주 쉬워진다. 그 시드 값만 순차적으로 증가시켜 가면서 쭉 실행을 시키면 문제가 있는지 없는지 손쉽게 찾을 수 있으니 말이다.&lt;/p&gt;
&lt;p&gt;찾아낸 것도 대단하지만 그런 문제를 두 번 다시 겪지 않기 위해서 재현 가능한 시드라는 것을 주창했다는 것 또한 더 대단한 일이 아닐 수 없다 하겠다. 하지만 현실은 언제나 바쁘기에 그의 의견은 아직도 구현되진 못했다. 조선 최고의 천재라 일컬어지는 율곡 이이 선생의 십만양병설이 떠오르는 시점이 아닐 수 없다.&lt;/p&gt;
&lt;p&gt;윈도우 10도 재현 가능한 빌드를 사용하는 마당에 오래 전 그 직원이 주창했던 아이디어를 반성하는 의미에서 구현해야 겠다는 생각이 든다. 구슬이 서 말이라도 꿰어야 보배고, 아이디어가 아무리 많아도 구현이 없으면 공허한 메아리일 뿐이니 말이다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;다시 다음날. 반성하는 의미에서 우리가 사용하는 랜덤의 호출 경로를 추적하는 작업을 해 보았다. 그러다보니 이 문제가 생각보다 쉽지 않다는 것을 알게 되었고, 똑같은 짓을 몇 년 전에도 했다는 사실을 알게 되었다. 메멘토 같은 상황…​&lt;/p&gt;
&lt;p&gt;전말은 이렇다. 일반적으로 사용하는 rand 함수는 시드를 가지고 있고 멀티스레드 환경에 최적화하기 위해서 해당 시드를 스레드 로컬 스토리지에 저장한다. 이 말은 이걸 전역으로 한 번 초기화 한다고 해서 해당 값에 바인딩된 rand를 호출하는 모든 상황에 적용되는 것은 아니라는 것을 의미한다. 즉, 제대로 돌아가게 만들기 위해서는 모든 스레드의 시작 시점에 해당 시드로 초기화를 하는 루틴을 삽입해야 한다는 것을 의미한다. 응당 그게 쉽지 않으니 달리 생각할 수 있는 방법은 의사 랜덤 생성 함수를 새롭게 만드는 방법을 생각해 볼 수 있다. 이렇게 구현할 경우 스레드 안정성을 보장하기 위해서는 락을 쓰거나 락리스한 방법으로 좁혀진다. 그런데 랜덤 값 하나 만들겠다고 락을 쓰는 것은 뭐 빈대잡겠다고 초가삼간 태우는 격이니 결국은 락리스한 랜덤으로 방법은 더 좁혀진다. 그럼 그런 것을 내가 직접 만들 수는 없으니 구글에 검색을 하게 된다. 그렇게 나온 결과물을 쳐다 보고 있으면 그런 결론에 도달한다. 아~ 다른 일부터 해야겠구나…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 송도 지열군 스튜디오 돌상 사진 촬영기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2018/05/one-year/</link><guid isPermaLink="false">https://jiniya.net/ng/2018/05/one-year/</guid><pubDate>Mon, 14 May 2018 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;송도(인천)는 살기에 정말 거의 단점이 없는 동네인데 그 중에도 특히 최고의 강점 중에 하나가 거의 모든 인프라가 굉장히 잘 갖춰져 있다는 점이다. 홈플러스, 오네스타, 현대 프리미엄 아울렛, 트리플 스트리트로 이어지는 몰들의 향연에 한 번 빠지면 도대체 여긴 어딘가 싶다. 특히나 평일에는 사람도 많이 없어서 정말 좋다. 돈많은 아줌마가 살기에는 정말이지 최고의 동네라 할 수 있다.&lt;/p&gt;
&lt;p&gt;스튜디오도 그렇다. 네이버 검색 결과 송도 내에 스튜디오가 몇 개 있는 것으로 보였다. 그 중에서 다른 블로그를 보다 보니 지열군 스튜디오 사진이 괜찮고, 집과도 가까워서 장모님 칠순 가족 사진을 지열군에서 찍기로 했다. 가족 사진 찍으니 서비스 컷을 두 컷 주신다고 하셔서 한 컷을 애들 돌상 촬영을 해봤다. 첫째 애도 돌잔치는 집에서 하고 사진은 분당에 있는 스튜디오에서 전통 돌상 사진으로 찍었었다. 왠지 돌은 전통이 더 어울리는 듯한 느낌이다.&lt;/p&gt;
&lt;p&gt;첫째 아이 사진을 강남, 이태원, 마포, 분당 등지에서 찍어 봤는데 대부분의 스튜디오가 굉장히 열악하기 그지 없었다. 네비를 찍고 가도 찾기 어려운 건 기본이고, 주차 공간은 거의 제로에 가까워서 근처에 불법 주차를 해야 하는 경우가 대부분이었다. 그렇지 않은 경우는 발렛을 제공해 주기는 했는데 이 경우에는 발렛비를 별도로 내야 했다. 건물도 일반 가정집을 개조한 경우가 많아서 사진 촬영을 하다 보면 아래 위층을 왔다 갔다 해야 하는 경우가 많아서 아직 잘 걷지 못하는 애들을 데리고 사진을 찍기란 여간 어려운 일이 아니었다. 찍다가 부모도, 아이도 파김치가 되는 건 일상적인 풍경…​&lt;/p&gt;
&lt;p&gt;하.지.만. 지열군 스튜디오는 이런 모든 불편함이 없었다. 일단 아파트형 공장 같은 건물의 한 호실에 모든 스튜디오가 갖춰져 있어서 계단 사용할 일이 없다. 애들 안고 이동을 하지 않아도 된다는 의미다. 인테리어도 요즘 새로 한 것 같아서 상당히 깔끔하다. 특히 창가쪽 벽면 전체에 인테리어 형태의 쇼파가 쫙 붙어있는데 정말 좋았다. 앉아서 쉬기도 좋고, 애들 뭔가 뒷정리 해줄때도 상당히 유용했다. 아파트형 공장 같은 건물이기 때문에 주차 문제는 애시당초 없다. 게다가 무려 300만원에 달하는 디트로네를 타 볼 수 있다. 물론 사장님께서 허락해 주셔야 하는데 애들이 칭얼 거리면 사장님께서 흔쾌이 탈 수 있도록 배려해 주셨다. 우리도 두바퀴를 탔는데 첫째가 참 좋아했다. 집에 있는 30만원짜리 싸구려 아우디 전동차와는 뭔가 격이 다른 느낌 ㅋㅋㅋ~ 이런 모든 장점을 가진 스튜디오가 무려 우리 집에서 5분 거리. 이러니 송도를 사랑하지 않을 수 없다.&lt;/p&gt;
&lt;p&gt;아직 정신 못차리는 애들이 둘이나 있기에 사진 촬영은 정말 쉽지 않았음에도 인내심을 가지고 촬영을 잘 해 주셨다. 특히 돌상 찍을 때는 애들 컨디션이 나락 상태였음에도 최선을 다해서 찍어 주셔서 고마울 따름이었다. 전통 돌상 촬영은 사실 별반 특별할 것이 없다. 돌상 아이템이 얼마나 잘 갖춰져 있느냐와 때깔 좋은 한복이 얼마나 갖춰져 있느냐의 승부인데, 사장님 말씀으로는 새로 시작하는 세트라 특별히 신경써서 고급 한복을 많이 가져다 놓을 예정이라고 했다. 그리고 요즘 시작하는 세트니 당연히 색감이나 이런 것들이 오래된 스튜디오에 있는 한복보다 곱다. 실제로 서비스 컷으로 찍은 한복 때깔이 첫애 때 분당서 돈 주고 촬영한 한복보다 훨씬 더 고급져 보였다.&lt;/p&gt;
&lt;p&gt;전통 돌상 촬영의 다른 한 부분은 세트 장이 얼마나 다양하게 꾸며져 있느냐가 있는데 지열군 스튜디오는 아직까지는 일반 돌상이 전부다. 전통 가옥으로 된 스튜디오 장은 없다. 하지만 아.마.도. 돌상 촬영을 하게 되는 경우에는 일반 스튜디오에서 다른 사진을 함께 찍을 수 있을 것으로 추정된다. 그리고 중요한 가격 정보는 와이프가 모두 얘기해서 알 길이 없다. 아마 친절하신 사장님 마인드를 봐서는 가격도 많이 착할 것으로 예상된다. 어쨌든 송도나 송도 근처 인천에 계신 분들이라면 애들 사진 찍기에 강추할만한 스튜디오다. 서울에서 오기에도 괜찮다. 위에서 언급한 홈플러스, 오네스타, 현대 프리미엄 아울렛, 트리플 스트리트 바로 옆이기 때문에 사진 찍고 몰에 가서 쇼핑도 하고, 맛난 것도 먹고, 애들 데리고 놀기도 좋다. 애들 사진은 가급적 인터넷에 안 올리는 것이 좋다고 생각하지만 사진이 넘나 잘나와서 몇 장 올려본다. 어서어서 무럭 무럭 자라라. 얘들아…​&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./b1.jpg&apos; data-alt=&apos;Figure 1. 둘째, 사장님 포스, 잘 찍고 있지? ㅋ&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e840e63db2712fa0f60b6bb44ca798f8/56d4e/b1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 77.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIFBP/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAHe01hpkkL/xAAZEAEAAgMAAAAAAAAAAAAAAAABAAIREiH/2gAIAQEAAQUC2JtwmeZa2Sw//8QAFhEBAQEAAAAAAAAAAAAAAAAAABES/9oACAEDAQE/AYy//8QAFhEBAQEAAAAAAAAAAAAAAAAAABES/9oACAECAQE/Aa0//8QAGBAAAwEBAAAAAAAAAAAAAAAAAAEREEH/2gAIAQEABj8C2dGqSn//xAAcEAACAgIDAAAAAAAAAAAAAAABEQAhMUFRYYH/2gAIAQEAAT8h4jUQs2IT2vY1TsCW8QFh7odQ2y7U/9oADAMBAAIAAwAAABB0P//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxCOn//EABURAQEAAAAAAAAAAAAAAAAAABAx/9oACAECAQE/EIH/xAAcEAEAAgMBAQEAAAAAAAAAAAABABEhMUFRYXH/2gAIAQEAAT8QoM1Dd7+zqAcYIVCvTpBUhDgCYb4DbyJct35pannqpF4UZoUv9n//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 둘째, 사장님 포스, 잘 찍고 있지? ㅋ&apos; title=&apos;&apos; src=&apos;/static/e840e63db2712fa0f60b6bb44ca798f8/56d4e/b1.jpg&apos; srcset=&apos;/static/e840e63db2712fa0f60b6bb44ca798f8/8ccab/b1.jpg 190w,
/static/e840e63db2712fa0f60b6bb44ca798f8/ea4c8/b1.jpg 380w,
/static/e840e63db2712fa0f60b6bb44ca798f8/56d4e/b1.jpg 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 둘째, 사장님 포스, 잘 찍고 있지? ㅋ&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./b2.jpg&apos; data-alt=&apos;Figure 2. 첫째랑, 둘째랑 함께, 어서어서 무럭 무럭 자라길…​&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3a1dab3b664379ac4fc74862e1389c08/56d4e/b2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAF7JNmqBQn/xAAaEAACAwEBAAAAAAAAAAAAAAAAAQIDERIT/9oACAEBAAEFAo2JnaO0yNeSzX5o/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8BiP/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/Aar/xAAZEAEAAgMAAAAAAAAAAAAAAAABABARITH/2gAIAQEABj8Ca1Az2Ff/xAAbEAACAgMBAAAAAAAAAAAAAAAAAREhMWGxcf/aAAgBAQABPyGkTsVynArLSjmsPo7Im4bXh//aAAwDAQACAAMAAAAQx8//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPxAl/8QAFREBAQAAAAAAAAAAAAAAAAAAAAH/2gAIAQIBAT8QZL//xAAbEAEBAAIDAQAAAAAAAAAAAAABEQAhQWGBsf/aAAgBAQABPxBZblqej5m4FdvMoXHPeQjscRNChuV2TzGUZaCgZ//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 2. 첫째랑, 둘째랑 함께, 어서어서 무럭 무럭 자라길…​&apos; title=&apos;&apos; src=&apos;/static/3a1dab3b664379ac4fc74862e1389c08/56d4e/b2.jpg&apos; srcset=&apos;/static/3a1dab3b664379ac4fc74862e1389c08/8ccab/b2.jpg 190w,
/static/3a1dab3b664379ac4fc74862e1389c08/ea4c8/b2.jpg 380w,
/static/3a1dab3b664379ac4fc74862e1389c08/56d4e/b2.jpg 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 2. 첫째랑, 둘째랑 함께, 어서어서 무럭 무럭 자라길…​&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./b3.jpg&apos; data-alt=&apos;Figure 3. 첫째 짬컷, 이러니 딸바보 안 될래야 안 될 방법이 없다…​&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 427px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1cea6b6296ca22fa0f20de4599064524/a2c7b/b3.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAQP/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAbfKW1JSIYO41rUgoEf/xAAbEAADAQEAAwAAAAAAAAAAAAABAgMRABASE//aAAgBAQABBQL2GbiclKcLMCzULRmR1IBj8mXg2+CRv//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/ASn/xAAWEQEBAQAAAAAAAAAAAAAAAAAAERD/2gAIAQIBAT8BXI//xAAdEAACAQQDAAAAAAAAAAAAAAAAARECECExEjKB/9oACAEBAAY/AjVuoqWsD4vBNRhwRE+30f/EABsQAAMAAwEBAAAAAAAAAAAAAAABESExQVEQ/9oACAEBAAE/IWzB8KTuttlXpCpixDZTlnYrjIpo6tUsgdRGmgrgq8+Y/9oADAMBAAIAAwAAABD/AM3P/8QAGhEAAgIDAAAAAAAAAAAAAAAAABEBMUFRYf/aAAgBAwEBPxBTY50JkfT/xAAWEQEBAQAAAAAAAAAAAAAAAAARAAH/2gAIAQIBAT8QchGBC//EAB4QAQADAQADAAMAAAAAAAAAAAEAESExQWFxUYHR/9oACAEBAAE/EHFLdjfEsQtgPNhzpnuWgEq3OlfyAxlLL37Em24es/cvDsgBp4X3K1HWtdfzF1w8CCfIZ1kXG1DUq1P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 3. 첫째 짬컷, 이러니 딸바보 안 될래야 안 될 방법이 없다…​&apos; title=&apos;&apos; src=&apos;/static/1cea6b6296ca22fa0f20de4599064524/a2c7b/b3.jpg&apos; srcset=&apos;/static/1cea6b6296ca22fa0f20de4599064524/8ccab/b3.jpg 190w,
/static/1cea6b6296ca22fa0f20de4599064524/ea4c8/b3.jpg 380w,
/static/1cea6b6296ca22fa0f20de4599064524/a2c7b/b3.jpg 427w&apos; sizes=&apos;(max-width: 427px) 100vw, 427px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 3. 첫째 짬컷, 이러니 딸바보 안 될래야 안 될 방법이 없다…​&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;아, 지열군 스튜디오를 처음 방문한다면 주차장 찾는데 조금 난항을 겪을 수 있다. 네비가 알려주는 곳에 주차장 입구가 없기 때문이다. 정확한 주차장은 아래 위치에 있다. 워낙 건물이 길어서 모르면 다소 헤맬 수 있다. 아래 그림의 빨간 부분이 주차장 입구다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./map.png&apos; data-alt=&apos;Figure 4. 빨간데가 주차장 입구다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fbb288434c14bebec9991e27338255fe/0f09e/map.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 83.6842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7DAAAOwwHHb6hkAAADsElEQVR42k2UCW/bRhCF+d+L/oQ2RRq4QOvUTRO7cdPYiWXlsAvbjS1LlqyLFO/7piieEqXX4QItQmCw0i717ZuZN+IO7n/Ay8EztOv+3fcU3+F4tI+3k9/QnfwBOzjHet1DXWlQ3SF0X8QyiRAGLtJlgCyNWRRZwoJ72W9BT/F7/xl+7T3B87snOHzYw+vRAU4e3iAvT7FZL1AUOyiCClt3YOoWLMOGF3iIkwxFvUOz3WFLwWXle1yJz3HQ+5FFq/bPx328unsNN+4Au/fICh6eG0LTVHieB8dxYRom7XkwDANBQEqznCID5/sPaOrPsJNjnI5/wosBQXtHmFvvAHyC7B+BdwdwrBCT6RSiJGKVrhCGIaIoYpA4jkndFid/HYPjpQVEZUp1+UJqupiZpxipLewDkvwMndnPUIIpkriAqulQVRWqosKyLEiSxNZ2r2kaAkfgRIXHQhZYKPoAbniBHYF32w8woxMcP+4xoB+EUCwVpkf1cy0kScLUtSrTNKXf7NA+DCgxKI/BdIws/0i3nWOzOce26VK6hxDdB2R1CWtpw0ldRHmMuEiwrFJ8/bTQ/4H34zmC6G/aPkMUX0MzhkiW12jWJ8hznkpSwKP0NnlO9shYiv+p+vrhVL1VxkMxbxlsmV4ytQtZhCAJMOxbFKWMut6iqiry5IY1oNk07HsbG9qryvZsDa43FjDiB1Szc/LaJ0gqdZKpntFnHrw4g+s5dFZRrZa0rgjYoCxL2I4H13aRUT01XaM6++De3UzopY9EPyfAkFTxBJwzaBuCPCVQgnVVIF/Z9G6f1Haxqa+xShSI5ghd/hU+L45wIR6RD6NLlqphDSgCyJoMURUILoCXqLuhR7VqkEQGQt9Gmc9Q0+Vn/R5WeQdxdoYr6QVOpr/gzXCPgHEXtnsN3fKQrnJESQrdtLBQBFiOzsapyENS59PMmkxdls7woKZYZiNqWofq2SFrvcXhP0/B6c4FJqKFql4jiJdYEtT1Q0pXIuussa4LgpSkLKTCX6IqHlFvKhjjW8z6t+QEhf44boBtBysaY46Xb+F4MWRFBi+QKtshdSLyIiNYTspcgsVkE5e6OYdtiBjOR4i+/Qb53Q2ox3SeIM8EOr8CZ1gGmwJRlmm0NExmU0o7ojRq8pvPXi7yKdnjhi4gpdTlwDexLnPKgGxTrmgvpqaVEK17cIK8IK85NCEVbC8gtS5NyIZubFNMCabTekFwjSKg9DJmYFGYYNi/YVk0dQ3NH2NufsG/lXzdbiXa+tEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 4. 빨간데가 주차장 입구다.&apos; title=&apos;&apos; src=&apos;/static/fbb288434c14bebec9991e27338255fe/0f09e/map.png&apos; srcset=&apos;/static/fbb288434c14bebec9991e27338255fe/08678/map.png 190w,
/static/fbb288434c14bebec9991e27338255fe/2edd7/map.png 380w,
/static/fbb288434c14bebec9991e27338255fe/0f09e/map.png 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 4. 빨간데가 주차장 입구다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 완벽한 회사...]]></title><description><![CDATA[설 연휴에 SBS…]]></description><link>https://jiniya.net/ng/2018/02/perfect-company/</link><guid isPermaLink="false">https://jiniya.net/ng/2018/02/perfect-company/</guid><pubDate>Mon, 19 Feb 2018 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;설 연휴에 SBS 스페셜 다큐를 한 편 봤다. &quot;검색 말고 사색, 고독연습&quot;이라는 제목의 다큐였다. 제목 그대로 현대인들은 너무나 고독한 시간이 없고, 스스로 생각을 안 하고 산다는 그런 내용이다. 그리고 고독한 시간 속에서 진정한 내면의 문제를 해결할 수 있다는 아주 교훈적인 내용의 다큐. 뻔한 이야기긴 한데 내가 감탄한 부분은 다른데 있었다. 그건 다름 아닌 해당 내용과 같이 소개된 회사였다. 아래 멘트로 소개되는 회사. 특히 소프트웨어 회사라 어떤 회사인지 더 궁금하기도 했다.&lt;/p&gt;
&lt;p&gt;건설 설계 소프트웨어 분야 세계 1위, 무스펙, 무징벌, 무상대평가, 무정년, 이른바 4무 경영, 5성급 호텔 쉐프가 매일 아침, 점심, 저녁 제공, 1인당 연간 식비만 1천만원 이상 지출, 회사에서 운영하는 20일의 자아성찰 프로그램 (제주도에서 20일간 묵으며 자아 성찰을 하는 프로그램, 유급)&lt;/p&gt;
&lt;p&gt;몇몇 인상 깊었던 대표의 멘트, &quot;제 인생으로 온 사람들이잖아요. 모두 행복했으면 좋겠습니다.&quot;, &quot;개나리는 개나리대로, 진달래는 진달래대로 각자 자신의 꽃을 아름답게 피울 수 있도록 만들어 주는 회사가 됐으면 좋겠습니다.&quot; (대충 기억나는 대로 적은 거라 다를 수도 있음)&lt;/p&gt;
&lt;p&gt;당연한 얘기지만 다큐에서는 회사명이 직접 거론되지는 않았다. 오늘 궁금해서 검색해보니 금방 나온다. 판교에 있는 마이다스아이티라는 회사. &lt;a href=&quot;https://insight.wanted.co.kr/company/059fac2b8cb41ad377349994df59f6e967f285b0&quot;&gt;궁금해서 한 번 찾아봤다.&lt;/a&gt; 세상에 완벽한 회사는 존재하지 않는다. 양쪽의 입장 사이에는 너무나 극명한 차이가 있기 때문인 것 같다. 서로 약간씩 물러나 상대의 입장을 이해하기란 여간 쉬운 일이 아닌 것 같다.&lt;/p&gt;
&lt;p&gt;몇 해 전 구글 코리아에서 제법 오래 근무하다 그만 둔 형이 한 이야기가 떠올랐다. 입사할 때 그 회사는 정말 좋은 회사였는데, 그만둘 때에는 그런 장점들이 많이 퇴색해진 것 같다고. 그리고 이어서 떠오르는 최근에 이슈가 된 &lt;a href=&quot;https://www.yna.co.kr/view/AKR20180207059700091&quot;&gt;페이스북에서 CEO 개인에 관한 여론을 조사하는 직원을 고용했다던 기사&lt;/a&gt;가 생각나기도 했다. 아이언맨으로 칭송되는 엘론 머스크의 테슬라와 스페이스엑스도 말도 안 되게 높은 업무 강도로 유명하다는 이야기도 자주 들린다. 아마존 대표 베조스의 막말은 언급하면 입 아픈 정도.&lt;/p&gt;
&lt;p&gt;회사는 회사고, 나는 나다. 직원들에게는 그저 다니는 회사가 블랙 회사가 아니면 만족하고 다닐 법 하다는 이야기를, 대표님들에게는 그저 일 적게 시키고 돈 많이 주면 그게 좋은 회사라는 이야기를 해주고 싶다.&lt;/p&gt;
&lt;p&gt;엄마가 늘 하시던 말씀이 생각나는 시점. 물 좋고, 정자 좋은 곳은 세상에 없단다…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 트레이드 오프]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2018/01/trade-off/</link><guid isPermaLink="false">https://jiniya.net/ng/2018/01/trade-off/</guid><pubDate>Fri, 26 Jan 2018 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;전산학에서 배운 개념 중에서 일상에 가장 쓸모 있는 개념이 있다면 바로 트레이드 오프다. 트레이드 오프는 간단히 말하면 두가지를 동시에 추구하기란 쉽지 않다는 개념이다. 속도를 빠르게 하려면 공간을 더 써야 하고, 공간을 줄이려면 속도를 희생해야 한다는 것과 같이 두 가지 목표를 동시에 추구하기가 쉽지 않은 문제에 쓰인다. 즉, 하나를 선택하면 다른 하나는 일정 부분 포기해야 함을 의미한다. 물론 고상한 전산학까지 가지 않아도 초중등 교과서에도 이 내용이 나온다. 두마리 토끼를 잡지 못한다는 이야기다. 트레이드 오프는 그것보다는 조금 더 확장된 개념이긴 하다. 두마리 토끼를 잡을 수 없다고 한다면 한 마리만 잡을 수 있다는 이야기처럼 들리지만 트레이드 오프는 반반을 추구할 수도 있기 때문이다. 더 내려가서 초등학교 때에도 이 개념을 배우긴 한다. 사탕 항아리에 아이가 사탕을 꺼내려고 손을 넣고 있다. 사탕을 집고 있어서 손이 나오지 않는다. 아이가 사탕을 적당히 포기해야 손을 뺄 수 있다는 이야기가 그것이다. 그렇게 인생 전반에 걸쳐서 우리는 트레이드 오프란 개념을 배운다. 그만큼 중요한 개념이기 때문일 수도 있고, 그만큼 사람들이 쉽게 잊어버리는 내용이기 때문일지도 모르겠다.&lt;/p&gt;
&lt;p&gt;인생은 B(Birth)와 D(Death)사이의 C(Choice)라고 얘기한 철학자의 말처럼 인생은 선택의 연속이고, 그 선택이란 것이 결국은 트레이드 오프를 조율하는 과정이다. 연봉을 많이 주는 회사에 입사하면 돈은 더 벌 수 있겠지만 개인 시간은 더 많이 희생할 수 밖에 없다. 작은 회사에 다니면 보다 많은 사사로운 자유로움은 누릴 수 있겠지만 어디 가서 이야기할 때 그 회사를 아는 사람이 없을 수 있다. 아이를 놓으면 아이가 커 가는 것을 지켜 보는 기쁨은 누릴 수 있겠지만 자신의 인생 중 중요한 시간 대부분을 아이를 위해서 희생해야 한다. 유명해지면 많은 사람들이 알아보기 때문에 좋겠지만 그 사람의 사생활은 없어진다. 인생 전반에서 우리를 향해 달려오는 많은 일들이 사실은 트레이드 오프적인 성격의 것들이고 우리는 그 사이에서 어떤 것을 얼만큼 추구할지 결정해야 한다.&lt;/p&gt;
&lt;p&gt;사람들이 가장 많이 잊어버리는 내용 중 하나는 바로 항아리에서 손을 못 빼고 있는 아이처럼 그런 종류의 많은 문제들이 트레이드 오프적인 성격의 것이라는 것을 인지하지 못한다는 사실이다. 아이를 놓고 기르면서도 그 전과 같은 평범한 일상을 누릴 수 있다고 생각한다거나, 연봉을 많이 주는 회사에 들어가도 일은 조금 해도 된다고 생각한다거나, 유명한 연예인이 되어도 그 전과 같은 사소한 일상을 누릴 수 있을 것이라고 생각한다. 현실은 그렇지 않은데 말이다.&lt;/p&gt;
&lt;p&gt;예전에 친구의 죽음으로 충격을 받은 모 프로그래머가 만든 게임이 생각난다. 그 게임은 간단하다. 시작은 직사각형 모양의 왼쪽 상단에서 한다. 한번에 우리는 네 방향 중 한 칸만큼 움직일 수 있다. 우리가 게임 내에서 움직일 수 있는 최대 횟수는 정해져 있다. 그 프로그래머가 말하고 싶었던 것이 바로 트레이드 오프다. 우리가 오른쪽으로 많이 움직인다면 상대적으로 위나 아래, 왼쪽으로는 적게 움직일 수 밖에 없다. 우리는 그 제한된 횟수 내에서 우리가 선택한만큼 경험하게 되고 죽음을 맞이하게 된다는 것이다.&lt;/p&gt;
&lt;p&gt;세상 모든 것을 다 가질 순 없다. 하나를 더 많이 가지기 위해서는 다른 하나는 그만큼 포기해야 한다. 보통 사람들이 무엇을 더 가질지는 잘 선택하지만 무엇을 포기할지는 망설이는 경우가 많다. 하지만 중요한 것은 무엇을 더 가질지 보다는 무엇을 포기해도 되는지를 먼저 정하는 것이다. 그래야 비로소 어떤 방향으로 가야 하는지가 명확해지기 때문이다. 당신은 오늘 무엇을 트레이드 오프 하고 있는가? 또 무엇을 얻고, 무엇을 포기했는가?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] 서피스 프로 LTE]]></title><description><![CDATA[그러하다. 하드웨어 명가 MS가 드디어 완벽한 껍데기를 만들었다. 팬리스, i5, LTE가 달린 서피스. 내가 원하는 바로 그것. 지름신 강림…​ ㅋㅋㅋ 지금 사용하는게 서피스 프로4 M…]]></description><link>https://jiniya.net/ng/2017/11/surface-pro-lte/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/11/surface-pro-lte/</guid><pubDate>Wed, 08 Nov 2017 12:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/X8Z91UjM9PM?si=N-f5xN1FTcjvuxUw&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;그러하다. 하드웨어 명가 MS가 드디어 완벽한 껍데기를 만들었다.&lt;/p&gt;
&lt;p&gt;팬리스, i5, LTE가 달린 서피스. 내가 원하는 바로 그것. 지름신 강림…​ ㅋㅋㅋ&lt;/p&gt;
&lt;p&gt;지금 사용하는게 서피스 프로4 M3 버전인데, 지금껏 써 온 그 어떤 노트북보다 만족한다…​.&lt;/p&gt;
&lt;p&gt;쓰면서 딱 불편한게 M3의 약한 파워, 태더링의 불편함…​ 그런데 이 모든 문제점을 해결한 버전이 나온 것이다…​&lt;/p&gt;
&lt;p&gt;12월 출시라는데 한국도 제발 출시해주길…​&lt;/p&gt;
&lt;p&gt;이런 거 들고 발리가서 서핑하면서 코딩하면 한 2천배쯤 생산성이 향상될 거 같은 느낌적인 느낌…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우 x64 호출 규약 리뷰]]></title><description><![CDATA[윈도우 x64 호출 규약은 굉장히 심플하다. 파라미터가 첫번째부터 rcx, rdx, r8d, r9d…]]></description><link>https://jiniya.net/ng/2017/11/x64-calling-convention/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/11/x64-calling-convention/</guid><pubDate>Tue, 07 Nov 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;윈도우 x64 호출 규약은 굉장히 심플하다. 파라미터가 첫번째부터 rcx, rdx, r8d, r9d를 통해서 전달되고 그 다음 추가 파라미터는 스택을 통해 전달된다. 스택 정리는 호출한 쪽에서 수행한다. 그런데 여기서 한 가지 주의해야 할 것이 홈 공간이다. 홈 공간이란 파라미터가 레지스터를 통해서 전송되더라도 그걸 저장하기 위한 스택 공간을 호출하는 쪽에서 제공해야 한다는 것을 의미한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Func1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; param1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드를 보자. 위의 파라미터 전송 설명대로라면 Func1(3)은 아래와 같이 호출하면 될 거 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mov rcx, 3
call Func1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 그렇지 않다. 홈 공간이 필요하기 때문이다. 그래서 아래와 같이 값을 저장하지는 않더라도 공간은 확보해 주어야 한다. sub rsp, 8을 통해서 Func1이 param1 저장을 위해서 사용할 공간을 확보한 후에 호출해야 한다. 이게 홈 공간이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;sub rsp, 8
mov rcx, 3
call Func1
add rsp, 8&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;조금 복잡하게 파라미터가 5개인 함수를 살펴보자.&lt;/p&gt;
&lt;p&gt;void Func2(int p1, int p2, int p3, int p4, int p5);
Func2(1, 2, 3, 4, 5)를 호출한다고 생각해보자. 그러면 아래와 같이 호출하면 된다. push 5를 통해서 스택에 마지막 값을 기록한다. 이후 앞에 4개의 값을 기록할 공간을 확보한 후, rcx, rdx, r8d, r9d에 변수를 지정하고 Func2를 호출하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;push 5
sub rsp, 32
mov rcx, 1
mov rdx, 2
mov r8d, 3
mov r9d, 4
call Func2
add rsp, 40&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;실제로 컴파일러는 매 함수 호출마다 이렇게 스택을 조작하지는 않는다. 여유 있는 스택 공간을 함수 도입부에 확보해놓고 지속적으로 사용한다. 어쨌든 우리가 기억해야 할 사항은 이것이다. 앞에 4개는 레지스터로 뒤에꺼는 스택으로, 그리고 파라미터 개수만큼 스택 공간은 항상 확보해 주어야 한다는 점이다. 호출 규약에 관한 더 자세한 내용은 호출의 예술을 참고하자.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] 주차를 알고 싶을 땐 isocalendar]]></title><description><![CDATA[일주일씩 묶어서 통계를 내고 싶을 때가 있다. 그런데 이게 날짜를 기준으로 하기도 애매하고 위크데이를 기준으로 해도 영 뭔가 계산하기가 쉽지 않다. 이럴 때 isocalendar를 사용하면 편리하다. 해당 날짜가…]]></description><link>https://jiniya.net/ng/2017/11/isocalendar/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/11/isocalendar/</guid><pubDate>Sun, 05 Nov 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;일주일씩 묶어서 통계를 내고 싶을 때가 있다. 그런데 이게 날짜를 기준으로 하기도 애매하고 위크데이를 기준으로 해도 영 뭔가 계산하기가 쉽지 않다. 이럴 때 isocalendar를 사용하면 편리하다. 해당 날짜가 1년의 몇 번째 주차인지 반환해 준다. 사용법은 아래와 같이 심플하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;Python &lt;span class=&quot;token number&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;.2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;4def2a2901a5&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Jun &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2016&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;55&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MSC v&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1900&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;64&lt;/span&gt; bit &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AMD64&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; on win32
Type &lt;span class=&quot;token string&quot;&gt;&quot;help&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;copyright&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;credits&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;license&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; more information&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; datetime
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; datetime&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;datetime&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;now&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isocalendar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; datetime&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;datetime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isocalendar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;44&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;isocalendar의 반환 값은 튜플인데 차례대로 ISO 연도, ISO 주차, ISO 요일 번호다. 오늘이 벌써 올해 45주차라뉘…​ 일년이 52주라 그랬던거 같은데 이렇게 또 일년이 흘러가려고 하나보다. 여튼 이렇게 일주일 단위로 묶은 통계를 낼 때에는 isocalendar가 참 편리하다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 정규 표현식]]></title><description><![CDATA[C++11부터 정규 표현식이 표준 라이브러리에 포함됐다. 문자열 다루기 힘든 C…]]></description><link>https://jiniya.net/ng/2017/11/regex/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/11/regex/</guid><pubDate>Wed, 01 Nov 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;C++11부터 정규 표현식이 표준 라이브러리에 포함됐다. 문자열 다루기 힘든 C++에서 이런게 되다니 정말 기가 찰 노릇이다. 구슬이 서말이라도 꿰어야 보배이듯이 표준 라이브러리에 있어도 사용법을 모른다면 의미가 없다. 간략하게 사례별로 어떻게 사용하는지 살펴보도록 하자. 일단 코드를 먼저 보고,…​&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;string&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;regex&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;123&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;regex &lt;span class=&quot;token function&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[0-9]+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;regex_match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;number\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;not number\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;정규 표현식을 이용해서 문자열이 숫자인지 아닌지를 판단하는 프로그램을 만들어 본 것이다. s의 값을 변경해가면서 출력 값을 체크해보면 대략 어떻게 쓰는 것인지 알 수 있다. std::regex_match 함수를 사용하면 특정 문자열이 정규 표현식에 부합하는지 아닌지를 체크할 수 있다는 사실을 알면 되겠다. 한 가지 주의해야 할 점은 std::regex_match 함수의 경우 재귀 호출을 사용한다는 점이다. 따라서 정규 표현식에 따라서 문자열이 길면 스택 오버플로로 크래시가 발생할 수 있다. Visual Studio 2015에서는 이러한 문제점을 없애기 위해서 재귀 호출의 최대 깊이를 상수로 지정할 수 있도록 되어 있다. regex를 포함하기 전 _REGEX_MAX_STACK_COUNT를 특정 값으로 선언해 주면 된다. 기본적으로 64비트는 600, 32비트는 1000으로 설정돼 있다. 그 크기를 늘려주면 더 긴 문자열도 오류 없이 매치할 수 있다. 물론 너무 높게 설정하면 스택 오버플로로 크래시가 발생할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;string&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;regex&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;123 456 789&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;regex &lt;span class=&quot;token function&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[0-9]+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;sregex_iterator &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;sregex_iterator end&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;smatch m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 예제는 특정 문자열에서 정규 표현식에 부합하는 요소만 추출해서 출력하는 예를 보여주고 있다. std::sregex_iterator를 사용해서 부합하는 요소만 열거할 수 있고, std::smatch 객체를 이용하면 부합한 내용이 무엇인지 출력할 수 있다. 위 프로그램의 출력 결과는 123, 456, 789가 된다. std::smatch의 str 함수의 첫번째 파라미터로 넘어간 숫자가 애매한데 그건 매치한 대상 중에 어떤 것을 출력할지를 결정한다. 위 예에서는 매치 대상이 별도로 구분되어 있지 않기 때문에 0번 밖에는 없다. 아래 예제를 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;string&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;regex&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;123 456 789&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;regex &lt;span class=&quot;token function&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;([0-9])([0-9])([0-9])&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;sregex_iterator &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;sregex_iterator end&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;smatch m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 프로그램의 출력 결과는 1, 4, 7이 된다. 정규 표현식이 ([0-9])([0-9])([0-9]) 이와 같이 구성되어 있기 때문에 123이 이 표현식에 매치되면 std::smatch의 str 함수의 0번은 123을, 1번은 1을 2번은 2를, 3번은 3을 나타낸다. 그렇다면 정규 표현식 전체를 괄호로 한 번 더 묶으면 어떻게 될까? &quot;(([0-9])([0-9])([0-9]))&quot; 이렇게 말이다. 이러면 0은 123을 1도 123을 2는 1을, 3은 2를, 4는 3을 반환한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 봇 트레이딩 체험기...]]></title><description><![CDATA[어쩌다 올초에 비트코인에 투자를 했다. 처음에 재미삼아 1비트를 사봤는데 계속 떨어져서 물타기를 하다가 금액이 커져서 그냥 냅두게 됐었다. 그게 4,…]]></description><link>https://jiniya.net/ng/2017/10/bot-trading/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/10/bot-trading/</guid><pubDate>Wed, 25 Oct 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;어쩌다 올초에 비트코인에 투자를 했다. 처음에 재미삼아 1비트를 사봤는데 계속 떨어져서 물타기를 하다가 금액이 커져서 그냥 냅두게 됐었다. 그게 4, 5월 엄청 폭등하는 바람에 수익을 좀 봤다. 이런 사실을 아는 출판사 다니는 친구 녀석이 자기 회사에서 주식 자동매매 책이 잘 팔린다고 암호화폐 자동매매 책을 써 볼 생각이 없냐는 제안을 했다. 그렇게 어쩌다보니 봇 거래를 해보게 됐다.&lt;/p&gt;
&lt;p&gt;사실 전업 프로그래머 입장에서 투자 전략이야 천차만별이지만 시스템 트레이딩 코드를 만드는 건 너무 쉽다. 게다가 포인터를 다뤄야 하는 C/C++도 아니고 파이썬이면 충분하기 때문에 뻥 좀 보태서 한 시간이면 봇을 만들 수 있다. 요는 코딩이 어려운 건 아니고 전략이 어렵다는 의미다. 어쨌든 30분 정도 REST API를 훓어보고 봇으로 거래를 해보게 됐다. 당연한 얘기지만 된다. 거기에 내가 생각한 한 가지 아이디어를 넣어서 거래를 해보게 했더니 수익이 발생하는게 아닌가? 긴 추석 연휴 기간 동안 봇을 조금 다듬었다. 그렇게 25일이 됐고 봇이 나에게 월급을 줘야 하는 시점에 봇의 성적표는 다음과 같다. 각각 날짜, 비트코인봇 수익, 비트코인봇 거래회수, 이더리움봇 수익, 이더리움봇 거래회수, 토탈 수익, 토탈 거래회수, 누적 수익이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./bot_result.png&apos; data-alt=&apos;BOT 트레이딩 수익&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 544px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d47d4dbbcda61dc3eaaeb850086a3a3f/cfd82/bot_result.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 87.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAC8klEQVR42k1U2VLiUBBtISqyKioimxu7oBAMkc3BcqYs/2BqZvRJovOgzv+/9JyTTpU+3Arc9D19lr6RX48/dfX8W4PgSV9ennQV/NHX18fw/9/XJ31/f9Z/H4F+YL29BdgLdLUKNFh9Pl8C+82nJLOO5nKi2azoxoZoJiPh/9w2fmPPcUQ3N20ltkRja6JrXDH7LWIrFrN9GXop7XRien4e11QyroNhXBv1uPp+XAv7cRQ6Wiw6Wig4Wjty0MBRd+TgjKPX145Wqw4aO7qY45l2VAZeQtttAaDozo7odCZ6eornRAAoenQi2mqK9i9Q0wXLhOjVFfZaAkDRw0PRItYE9SkokPEsoV2AXVxCNuQ2cLhRF51N0SAvOsJh1xX1cbiPuizsmC9Em6i7vRUtl0SrNdH7ewAmAehNAIjOlwPRbfjmjQVyAAimu7sGdIlmrbYxTILFzY2EqsZjU9FoiD48iG6RISWTPlnu46Xvi56B4QRA+3sA6pgdvR5AWsZwOjXAwRByD0TrdWNLO2TkG2CvD4ACfJmYP5RMhs22Me7jfb9nKsi607baStlqlgDMpADojg2QksoVK6I/HrwrHBgLWkJQgjC4+dxqyJSAfE+GaQIOx5ZyHT5UAOgD8OzMUi4hPfcqAsOhbsckhx62zMNa1YJczCOGw4hhE6sAybOoO72kBQyJ/rkjSzmdsRFhEJOIIeupLEzZnyfCAzS+hvhnC+t+uzQLmDbH5hqHXaS9jVG6u7P6b0tTxQn5/sMmQFyEQkntjs0TmdWjOeTAcojp0XBkknklZ1HK9LBUMvaLhV1dXL1EGAgXu3FoW5FkArJ7v/c5OrzfngeZDfOyWrF9BpVMfkmZoZTKZnTIEFIPijbU9GvkGTBDIRvWEKRatTGjr8mvN4XGnp7YPLGYh3hPeYdpB2V1oSKPYV8uo1kF4PEx9nu2l2LK+UIi/HTxs8U5KpftU7a3Z58sFvEdu3Ofe5wG7uURUDpts8nm6+ui/wHTGcdou5+3rgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;BOT 트레이딩 수익&apos; title=&apos;&apos; src=&apos;/static/d47d4dbbcda61dc3eaaeb850086a3a3f/cfd82/bot_result.png&apos; srcset=&apos;/static/d47d4dbbcda61dc3eaaeb850086a3a3f/08678/bot_result.png 190w,
/static/d47d4dbbcda61dc3eaaeb850086a3a3f/2edd7/bot_result.png 380w,
/static/d47d4dbbcda61dc3eaaeb850086a3a3f/cfd82/bot_result.png 544w&apos; sizes=&apos;(max-width: 544px) 100vw, 544px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;BOT 트레이딩 수익&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;bot result&lt;/h3&gt;
&lt;p&gt;생각보다 많을 수도 있고, 적을 수도 있는데 나는 이 봇의 이름을 최저임금봇이라 명명했다. 시급 만원 정도를 추종하도록 설계됐다. 물론 시장 상황이 좋으면 더 벌기도 하고, 나쁘면 덜 벌기도 하는데 대략 그 정도 수준에서 24시간 돌면서 거래를 한다. 재미난 건 상수 값 몇 개 바꾸면 저 단위가 10배가 될 수도 있다는 점이다. 물론 내가 쪽빡찰 확률은 100배가 되겠지만 말이다. 여기까지만 쓰면 단순 자랑질 이상도 이하도 아닐 것이다. 그래서 트레이딩 봇을 만들면서 알게된 점 몇 가지를 정리해 본다. 분명 이런 시스템을 만드려는 금융 쪽 종사자가 아닌 프로그래머가 있다면 도움이 되리라 확신한다.&lt;/p&gt;
&lt;h3&gt;삼위일체&lt;/h3&gt;
&lt;p&gt;처음에 봇을 만들고 가동시키자 봇이 엉뚱한 실수를 계속 했다. 분명 50원에 샀으면 100원에 팔라고 코딩을 해놨는데 계속 40원에 팔면서 수익을 내고 있다고 착각하고 있는 것이었다. 나같은 프로페셔널한 프로그래머가 if문 따위를 잘못 코딩할리도 없는데 말이다. 부랴부랴 Ctrl + C를 눌러서 봇을 껐지만 제법 손실이 난 후였다. 이 버그 아닌 버그를 찾는데 가장 많은 시간이 들었는데 원인은 다름아닌 트랜잭션에 있었다.&lt;/p&gt;
&lt;p&gt;내가 상상한 퐌타지한 세계는 그랬다. 거래소에서 나에게 제공하는 모든 데이터는 수직 동기화가 되어 있을 줄 알았다. 즉 그 사이게 시간 차가 존재할 줄 몰랐다는 의미다. 하지만 현실 세계는 그렇지 않았다. KRW 잔고가 먼저 반영되기도 하고, BTC 잔고가 그 다음에 움직이기도 하고, 거래 트랜잭션 데이터는 몇 십초가 있다가 확정되기도 했다. 즉 이 사이에는 어느 정도 시간적인 불일치가 있었다. 이걸 한쪽 데이터만 보고 판단해서 거래를 하면 나처럼 낭패를 볼 수 밖에 없다. 검산을 해야 한다. KRW 잔고와 BTC 잔고와 거래 내역이 모두 일치하는 삼위일체의 상태에 있을 때에 수익을 계산하고 베팅을 해야 한다.&lt;/p&gt;
&lt;h3&gt;부동소수점?&lt;/h3&gt;
&lt;p&gt;이 오류가 정확하게 부동소수점 때문인지 아니면 내 계산 방식 때문인지는 모르겠지만 위 삼위일체 검산 로직을 추가해도 정확하게 데이터가 일치하지 않았다. 나는 그냥 편하게 부동소수점 때문이라고 판단했는데 1사토시 근처에서 오류가 있는 경우가 많았다. 그래서 그냥 0.00000001 정도의 차이는 동일하다고 간주했다.&lt;/p&gt;
&lt;h3&gt;하락장을 고려해야 한다&lt;/h3&gt;
&lt;p&gt;상승만 한다면 바보 같은 봇들도 모두 수익을 낼 수 있다. 그리고 어렵게 봇을 만들 필요도 없다. 사두고 장기 보유하면 되기 때문이다. 하지만 시장은 항상 그렇듯이 오르기도 하고 내리기도 한다. 암호화폐 시장은 그 변동성이 더 크다. 그래서 봇 거래가 수익을 내기 좋은 환경이기도 하다. 어쨌든 하락장을 고려해야 한다.&lt;/p&gt;
&lt;p&gt;처음 만든 봇은 그저 오른다는 가정하에 만들었고 시장 상황이 계속 올라서 참 쉬웠다. 그러다 하락장이 왔는데 봇은 어쩔줄을 몰라 했다. 출구전략이 필요했다. 그런데 이론적으로 주구장창 하락한다면 일반 거래로 수익을 얻을 방법은 없다. 여기서 일반 거래란 공매도 같은 장치가 없음을 의미한다. 따라서 출구 전략은 단순할 수 밖에 없다. 더 사서 물타기를 할지 아니면 손절을 할지를 판단하는게 전부다. 여러가지 전략이 있을 수 있는데 나도 5가지 정도의 전략을 테스트 해보았다. 갈수록 산수에서 수학으로 가는 내용들이 도입됐고 코드도 복잡해졌다. 그런데 아니러니 하게도 수익률은 두번째 방법이 가장 좋았다. 그래서 그냥 그걸로 적용해 두었다.&lt;/p&gt;
&lt;h3&gt;인간은 개입하지 말지어다&lt;/h3&gt;
&lt;p&gt;위에서 말한 하락장에서 봇의 손실이 제법 커졌다. 사람은 당연히 불안해질 수 밖에 없다. 봇은 사지도 팔지도 못하고 있었다. 그러다 코인 가격이 반등되어 적당한 가격이 왔다. 봇은 아직 팔 때가 아니라서 거래를 하고 있지 않았다. 사람인 나는 조급해질 수 밖에 없었다. 봇이 사들인 코인의 대부분을 이 시점에 손절해 버렸다. 봇은 회복할 수 없는 타격을 입었다. 봇은 내가 저지른 만행을 복구할 수가 없는 지경이 됐다. 결국 나는 봇의 수익률 추종치를 리밸런싱할 수 밖에 없었다. 이게 비트코인 봇인데 원래 비트코인 봇이 이더리움 봇 보다는 수익률이 월등했는데 이 당시의 내 개입으로 인해서 구려졌다.&lt;/p&gt;
&lt;p&gt;봇이 어쩔 줄 몰라 하면 봇을 고쳐서 대응하면 된다. 절대 수동 트레이드로 개입할 필요가 없다. 왜냐하면 내가 느끼는 감성적인 수치와 봇이 정확하게 계산한 수치 사이에는 항상 간극이 존재할 수 밖에 없기 때문이다. 감정적인 대응의 결과는 손실 밖에 없다.&lt;/p&gt;
&lt;h3&gt;거래 수수료 트레이프오프&lt;/h3&gt;
&lt;p&gt;봇 트레이딩의 가장 큰 리스크는 다름 아닌 거래 수수료다. 봇이라서 엄청나게 많은 회수의 거래를 하는데 그때마다 수수료가 발생하기 때문이다. 상당수는 거래 볼륨으로 커버가 가능한데 대부분의 거래소가 거래 볼륨이 커질 수록 수수료가 낮아지도록 책정되어 있기 때문이다. 거래소에 따라서 일정 수준을 넘어서면 수수료 없이 거래하는 것도 가능하다. 그런데 문제는 그 수수료가 한 가지가 아니라 두 가지란 점에 있다. 모든 거래소 시스템이 비슷한 방식의 수수료를 책정하고 있는데 일명 메이커, 테이커 비용이다.&lt;/p&gt;
&lt;p&gt;시장에 유동성을 공급하는 거래에는 메이커, 유동성을 없애는 거래에는 테이커 비용을 물린다. 이게 거의 수수료가 없는 쪽은 메이커 비용이고, 테이커 비용은 수수료가 높다. 테이커 비용에 물리게 되면 사실상 단타 매매로 수익을 내기가 굉장히 어려워진다. 문제는 이 테이커 비용을 최대한 덜 내게 하는 방법인데 이게 쉽지가 않다. 그런 API가 존재하면 좋겠지만 거래소 수익 때문인지 그런 API를 제공하지 않는다. 내가 주문을 낼 때에는 멀쩡한 메이커 주문이었는데 그게 거래소 트랜잭션 시스템에서 직렬화 되면서 테이커 비용을 물게 되는 경우가 왕왕있다.&lt;/p&gt;
&lt;p&gt;당연한 얘기겠지만 되도록 이 테이커 비용을 피하면서 거래를 성사시키는 것이 중요하다. 그런데 문제가 그렇게 간단하지는 않은 것이 거래를 성립시키려면 테이커 비용을 무는 쪽으로 다가 가야 하기 때문이다. 즉, 이 사이에는 트레이드 오프가 있다. 거래를 잘 성립하게 만들다보면 테이커 비용을 무는 경우가 많고, 그렇다고 완전 회피하려면 유동성만 공급할 뿐 거래가 성사되지 않기 때문이다. 즉, 최대한 원활하게 거래를 성립시키면서 테이커 비용은 최대한 피하는 그런 방법을 만드는 것이 중요하다.&lt;/p&gt;
&lt;h3&gt;두려움을 넘어서&lt;/h3&gt;
&lt;p&gt;이 모든 봇 거래의 가장 큰 어려움은 두려움이다. 이 단순한 봇도 내 전재산의 무시 못할 수준의 금액을 가지고 도박을 한다. 내가 자는 동안에 위에서 말한 삼위일체 문제 같은게 발생한다면 거지되는 것이다. 그 두려움이 처음 3일 정도는 있었던 것 같다. 이제는 어느 정도 봇을 믿게 됐다. 특히 내가 한 수동 거래가 병신짓으로 판명난 이후에는 봇을 더 신뢰하게 됐다. 어쨌든 자신이 만든 버그가 현실 세계에서 어떻게 발현될 수 있는지 확인해 보고 싶은 프로그래머라면 도전해 볼 만한 영역인 것 같다. 물론 수익은 덤이다. 재미삼아 시작했는데 결과가 나쁘지 않아 누적 수익이 0이 될 때까지는 봇 실험을 계속해 볼 생각이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 코딩은 어려워]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2017/10/coding-is-difficult/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/10/coding-is-difficult/</guid><pubDate>Sun, 22 Oct 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;판교, 커피숍. 앉아서 간만에 회사 일이랑은 관련 없는 코딩을 좀 하고 웹서핑을 하고 있다. 옆에 여자 아이도 한 명 앉아서 뭔가를 만들고 있다. 그렇게 한참 지났을 무렵, 그 여자의 남자 친구가 왔다. 어딘가 면접을 보고 온 것 같다. 바로 옆자리 — 전원 있는 자리가 한정적이다 — 들으려고 듣는건 아닌데 말 소리가 커서 귀에 쏙쏙 꼽힌다. 흥분한 남자의 첫 마디. &quot;넌 링크드 리스트, 요이땅 하면 바로 짤 수 있어?&quot; 못짜지라는 말을 기대하고는 묻는 질문처럼 들린다. 여자가 링크드 리스트는 기본 아니냐는 말을 하자, 남자는 재차 말한다. &quot;기본인데, 요이땅 하면 바로 만들 수 있냐고?&quot; …​ 그렇게 한참을 입사 시험 문제에 대한 이야기들이 오간다. 판교 어딘가에 있는 회사의 코딩 시험을 방금 보고 나온 것 같다. 첫번째 문제가 링크드 리스트를 만들어서 그걸로 스택을 구현하라는 문제였던 것 같다. 다음 문제는 피보나치 수열, 팩토리얼 …​ 대화 내용으로 추정컨데 남자 보다는 여자가 프로그래밍을 잘하는 것으로 보인다.&lt;/p&gt;
&lt;p&gt;면접도 많이 보고 프로그래머 채용도 더러 해봐서 그런지 대화 내용이 납득이 가기도 하고 일견 또 이해가 되지 않기도 한다. 과연 프로그래머로 일을 하는데 얼마만큼의 지식이 필요한걸까? 프로그래머라는 직업을 가지는 데 필요한 최소 수준의 지식이라는 게 있을까? 라는 생각을 해봤다. 링크드 리스트를 못 만들어도 요즘은 문제가 없다. 잘 만들어진 링크드 리스트는 정말 많다. 스택을 못 만들면 또 어떤가? 푸시, 팝 하면 기똥차게 동작하는 코드들이 널려 있다. 피보나치 수열, 팩토리얼이 뭔지 몰라도 상관 없지 않을까? 재귀호출을 모르면 또 어떤가? 사실 실전에서 그리 사용 빈도가 높지도 않은데 말이다. 그런데 또 반대로 생각해 보면 그렇다. 링크드 리스트도 요이땅 하면 못 만드는 친구가 더 복잡한 건 어떻게 만들 수 있을까? 푸시는 어떻게든 구현했는데, 팝을 구현 못했다는데 팝을 어떻게 만들어야 하는지도 모르는 친구가 현업에서 작성할 코드가 있을까? 재귀호출은 또 어떤가? 그 정도의 복잡함을 시뮬레이션 할 수 없다면 과연 더 복잡한 추상적인 구조는 어떻게 머리속에서 떠올릴 수 있을까?&lt;/p&gt;
&lt;p&gt;하지만 세상 일이 그리 단순하진 않을 것이다. 예전의 나라면 단호하게 말했겠지만 지금의 나는 그러지는 못하겠다. 세상이 얼마나 넓은지 예전보다는 조금 더 알게 되었기 때문이다. 유명한 오픈소스 개발자가 트리를 못 뒤집어서 구글에서 떨어졌다는 일화가 한 때 유행했었다. 그때도 비슷한 생각을 했다. 과연 프로그래머로 일을 하는데 필요한 기본적인 지식이라는 게 무엇일까? 나도 구글이든 페북이든 큰 회사들의 코딩 시험에 나오는 문제들을 못 푼다. 예전에 회사에서 그런 시험에 대비하는 책을 사서 본 적이 있었는데 생각보다 문제가 어려웠다. 우리 회사의 시험 문제도 그럴지도 모른다. 문자열 복사 함수를 구현하는 일이 누군가에겐 쉬워도 누군가에겐 &apos;=&apos; 하나로 되는 일이기도 하고 또 누군가에겐 &apos;strcpy’로 되는 일이기도 하니 실제로 포인터를 조작하면서 구현하는게 어려울 수도 있다. 그래도 한 가지 바램이 있다면 그런 생각이 있다. 적어도 요이땅 하면 링크드 리스트를 구현할 수 있는 프로그래머랑 같이 일하고 싶다는 바램…​ 트리를 뒤집는 문제는 좀 더 생각해보고…​&lt;/p&gt;
&lt;p&gt;이랬든 저랬든 코딩은 어렵다. 입사 시험에 나오는 코딩도 이렇게 어려운데 현실 세계의 복잡한 문제들을 해결하는 코드들을 작성하는 일은 또 얼마나 어렵겠는가? 알파고 제로가 하루빨리 코딩을 마스터 하는 날이 오기를 희망해 본다. 너무 어려워서 사람이 하기에 적합한 일이 아닌 것 같다. 코딩이 말이다. 물론 이건 나 혼자만의 생각은 아닌 것 같다. 세계에서 손꼽히는 석학인 Knuth 노교수도 자신이 해 본 어떤 일보다 프로그래밍이 어렵다는 이야기를 했었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In fact, my main conclusion after spending ten years of my life working on the TEX project is that software is hard. It’s harder than anything else I’ve ever had to do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TEX 프로젝트에서 10 년을 보낸 후 내가 내린 주요 결론은 소프트웨어가 어렵다는 것입니다. 내가 이제까지 했던 그 어떤 일보다 더 어려워요.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] 파이썬으로 김프 계산하기]]></title><description><![CDATA[requests 패키지가 있으면 편리하다. 아래 명령어로 requests 패키지 설치가 가능하다. 거래소가 많기 때문에 일단 기준 거래소를 정해야 가격 비교가 쉽다. 거래소가 비교를 위한 REST API…]]></description><link>https://jiniya.net/2017/07/calculate-kimchi-premium/</link><guid isPermaLink="false">https://jiniya.net/2017/07/calculate-kimchi-premium/</guid><pubDate>Wed, 05 Jul 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;requests 패키지가 있으면 편리하다. 아래 명령어로 requests 패키지 설치가 가능하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pip install requests&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;거래소가 많기 때문에 일단 기준 거래소를 정해야 가격 비교가 쉽다. 거래소가 비교를 위한 REST API를 제공하지 않으면 힘들다. 만약 제공하지 않으면 그냥 과감하게 그런 거래소는 빼도록 하자. 개념이 있는 대부분의 거래소는 REST API를 제공한다. 우리는 거래량이 많은 Bittrex와 Coinone의 가격을 토대로 김치 프리미엄을 계산해 보자.&lt;/p&gt;
&lt;p&gt;Bittrex거래소의 API는 여기 설명 페이지를 참고하면 어떤 REST API를 제공하는지 알 수 있다. Coinone은 여기 설명 페이지를 참고하면 된다. REST API라는게 별 거 없다. 그냥 get이나 post 방식으로 명령을 주면 주로 json 형태로 응답을 주는게 전부다.&lt;/p&gt;
&lt;p&gt;우리가 가격 비교를 위해서 사용할 Bittrex API를 알아보면 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bittrex.com/api/v1.1/public/getticker?market=USDT-BTC&quot;&gt;https://bittrex.com/api/v1.1/public/getticker?market=USDT-BTC&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;위 쿼리를 날리면 비트트렉스에서 가격 정보를 JSON 형태로 날려준다. 응답에서 우리가 참고할 부분은 success필드가 true인가 하는 것과 result의 Last 값이다.&lt;/p&gt;
&lt;p&gt;Coinone API는 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://api.coinone.co.kr/ticker/?currency=BTC&quot;&gt;https://api.coinone.co.kr/ticker/?currency=BTC&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;위 쿼리 응답의 result가 success인지 체크하고 last 값을 사용하면 된다.&lt;/p&gt;
&lt;p&gt;이제 프리미엄을 계산할 달러 환율만 있으면 된다. 달러 환율은 아래 사이트를 통해서 구할 수 있다. 똑같이 REST API 형태의 쿼리로 결과를 얻을 수 있다. 결과의 USD_KRW 필드의 val 값을 참조하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://free.currencyconverterapi.com/api/v5/convert?q=USD_KRW&amp;#x26;compact=y&quot;&gt;https://free.currencyconverterapi.com/api/v5/convert?q=USD_KRW&amp;#x26;compact=y&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이제 준비물이 모두 모였다. 파이썬 코드를 작성해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; json

resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://free.currencyconverterapi.com/api/v5/convert?q=USD_KRW&amp;amp;compact=y&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text
usd_krw &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loads&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;USD_KRW&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;val&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://bittrex.com/api/v1.1/public/getticker?market=USDT-BTC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text
btc_usd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loads&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Last&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://api.coinone.co.kr/ticker/?currency=BTC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text
btc_krw &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loads&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;last&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

fprice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; btc_usd &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; usd_krw
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Bittrex: %d Coinone: %d KP: %.2f%%&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fprice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; btc_krw&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; btc_krw &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; fprice &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;각각 Bittrex 가격, Coinone 가격, 김치 프리미엄이 표기된다. +면 한국이 비싼거고, -면 한국이 싼 거라고 생각하면 된다. +면 Bittrex에서 사서 Coinone에서 팔고, -면 Coinone에서 사서 BIttrex에 파는 전략을 구사하면 완벽하다. 물론 거래 수수료와 전송 속도에 따른 불확실성을 헷징할 방법은 각자 찾는 걸로…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] C++ 프로그래머 채용합니다.]]></title><description><![CDATA[C++ 프로그래머 채용합니다. 학력, 경력, 출신, 나이, 종교, 성별, 정치성향, 외모, 성격 따지지 않습니다. C++ 코드를 읽을 수 있는지, 또 C…]]></description><link>https://jiniya.net/ng/2017/03/recruit-cpp-programmer/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/03/recruit-cpp-programmer/</guid><pubDate>Wed, 29 Mar 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./deadlock.png&apos; data-alt=&apos;Figure 1. 이 정도 유머는 이해할 수 있는 C++ 프로그래머를 찾고 있습니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5a4a4a33ed79c4eec846c494b70d09df/407f2/deadlock.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABsklEQVR42qVSXY+TQBTl//8FH9XEBxNfNGvii3aptrCt7paPMkwZGD5moNgCLUm7KYyHuppVm2jiCSEzk3vO3DPnaofDgfg0CILl0suyzLJsIaVtO58mk4CxvCiWnmc7jsxzpVTf9+oRtKbZ6eOP5s1sNps7rjubz8F0l5DyhBB13QgheZxsNpsL5LL8+v7DaDKdTgxjNLqmlHqEVFXVtm3TNPX567pOXYJ2PB718fjq6q1+rS8WFjqwLAtapnlze3tn2fbUMCB0mYyb9QFjVN8tFlPDnH/+AucsjNTfoKGlw/39qXswg+3pdOrP+H7ym89fyUqNXr989eJZmOJhMp6KMMkymXd/ACqPFwMZl9I3z989fSLKqijWRVnKokB+6h8wtC2lJMQPw4jzeL1eD9lE3PMI9SmST9M0SZI0SdkqCMMwTTMpoF88kBEG5xwhoQbZojSK+IquGGPQTWLYyPCXYAkRxxBKivxMVv8BDe7RQ7tvkVlV1cAwG3W9PQNrzNZ2u9k1O5zu9yhs+x/QEAwGEzZc1/V9QqkPYD5XhIaM4dAwTMux45gTglfwWch+RvgNpbDRuLTCv5QAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 이 정도 유머는 이해할 수 있는 C++ 프로그래머를 찾고 있습니다.&apos; title=&apos;&apos; src=&apos;/static/5a4a4a33ed79c4eec846c494b70d09df/407f2/deadlock.png&apos; srcset=&apos;/static/5a4a4a33ed79c4eec846c494b70d09df/08678/deadlock.png 190w,
/static/5a4a4a33ed79c4eec846c494b70d09df/2edd7/deadlock.png 380w,
/static/5a4a4a33ed79c4eec846c494b70d09df/407f2/deadlock.png 520w&apos; sizes=&apos;(max-width: 520px) 100vw, 520px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 이 정도 유머는 이해할 수 있는 C++ 프로그래머를 찾고 있습니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;C++ 프로그래머 채용합니다. 학력, 경력, 출신, 나이, 종교, 성별, 정치성향, 외모, 성격 따지지 않습니다. C++ 코드를 읽을 수 있는지, 또 C++ 코드를 쓸 수 있는지만 봅니다. 파이썬을 할 줄 알면 더 좋구요. 몰라고 크게 상관은 하지 않습니다. 데드락 유머들 이해할 수 있다면 충분하다는 생각입니다. 윈도우/리눅스/BSD/macOS 중 하나 이상 시스템 프로그래밍 경험이 있다면 금상첨화지요.&lt;/p&gt;
&lt;p&gt;하는 일은 심플합니다. 저희가 11년째 해오고 있는 게임 해킹툴 박멸 작업에 참여하는 일입니다.&lt;/p&gt;
&lt;p&gt;병역특례 전직, 보충역 신규 편입 가능합니다.&lt;/p&gt;
&lt;p&gt;참고할만한 과거 채용 공고들…​
&lt;a href=&quot;http://www.jiniya.net/wp/archives/12367&quot;&gt;http://www.jiniya.net/wp/archives/12367&lt;/a&gt;
&lt;a href=&quot;http://www.jiniya.net/wp/archives/7276&quot;&gt;http://www.jiniya.net/wp/archives/7276&lt;/a&gt;
&lt;a href=&quot;http://jiniya.net/tt/694&quot;&gt;http://jiniya.net/tt/694&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;하는 일은 동일합니다.&lt;/p&gt;
&lt;p&gt;환경은 많이 변했습니다. 좋은 쪽으로…​&lt;/p&gt;
&lt;p&gt;관심 있는 분들은 codewiz 앳 wellbia.com으로 이력서, 자기소개서 보내 주세요.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 실험 주도 프로그래밍]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2017/02/expr-driven-programming/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/expr-driven-programming/</guid><pubDate>Sun, 19 Feb 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;신입 프로그래머들이 자주 사용하는 기법 중에 하나로 실험 주도 개발이 있다. 정식 용어는 아니고 그들이 프로그래밍 하는 과정이 일종에 물리 법칙에 관한 실험을 하는 것과 유사해서 나는 그렇게 부른다. 잘 사용한다면 빠르게 결과물을 도출할 수 있는 방법이지만 잘못 사용된다면 아주 위험할 수 있는 방법이기에 간단하게 그 방식에 관한 생각을 정리해 본다.&lt;/p&gt;
&lt;h3&gt;실험 주도 프로그래밍&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BadFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;PLATFORM_A&lt;/span&gt;&lt;/span&gt;
    some code
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
    some other code
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 코드에서 PLATFORM_A 환경에서만 크래시가 발생한다. 어떻게 해야 할까? 이때 우리가 대처할 수 있는 방법은 크게 두 가지 방법이 있다. 1) 덤프 파일을 분석해서 정확하게 왜 크래시가 발생했는지를 알아낸다. 2) 위 코드가 정확하게 어떤 동작을 하는 코드인지 이해하고 무엇이 잘못되었는지 생각해서 잘못된 원인을 찾아낸다. 그런데 여기에 이 두가지 방법이 아닌 전혀 새로운 방식의 접근 방법이 있다. 바로 실험 주도 프로그래밍이다.&lt;/p&gt;
&lt;p&gt;실험 주도 프로그래밍은 물리적 현상을 추론해 내는데 사용하는 가설, 검증 방식의 실험과 유사하게 코드를 고쳐 나가는 것을 말한다. 전체적인 시나리오는 이렇다. 1) 가설을 세운다. 2) 실험을 한다. 3) 결과를 관찰한다. 아주 심플하다. 그러면 간단한 가설을 세워보자. PLATFORM_A에서만 크래시가 나니 some code의 문제일 수 있다. some code를 주석처리 한 다음 컴파일을 해본다. 이제 결과를 관찰한다. 잘 동작한다면 가설이 맞은 것이니 주석을 풀고 그 코드 내부에 대한 추가적인 세부 가설을 세우고 실험을 진행한다. 가설이 맞지 않다면 주석을 풀고 return 1 부분에 관한 가설을 세우고 다시 테스트를 한다.&lt;/p&gt;
&lt;p&gt;이 방식은 관찰된 현상에 따라서 가설만 잘 세운다면 본질적인 구조를 모르고도 굉장히 빠르게 문제를 수정할 수 있다는 장점이 있다. 그래서 대체로 다른 이들이 작성한 코드를 유지보수해야 하는 신입 프로그래머들이 많이 사용하는 것 같다.&lt;/p&gt;
&lt;h3&gt;가설, 검증 구조가 가지는 함정&lt;/h3&gt;
&lt;p&gt;앞선 실험 주도 프로그래밍의 가설, 검증 방식의 함정은 잘 동작하는 결과를 가졌을 때 발견된다. 예를들어 보자. 앞선 코드에서 가설, 검증 과정을 통해서 return 뒤의 1을 0으로 바꾸니 크래시가 발생하지 않고 잘 동작했다고 생각해보자. 그러면 이제 거기서 1을 0으로 바꾸고 끝을 내도 되는 것일까? 만약 끝을 내도 된다고 생각한다면 다음 우스개에 나오는 과학자와 비슷한 오류를 범하는 꼴이 된다.&lt;/p&gt;
&lt;p&gt;옛날에 한 과학자가 있었다. 파리에 관한 연구를 하던 과학자는 한날 박수를 치니 파리가 날아가는 것을 보고는 파리에게도 분명 귀가 있을 거라는 생각을 한다. 그리고 그 귀가 어디에 달려 있을까를 알아내기로 했다. 과학자는 가설을 세운다. 처음에는 파리의 귀가 다리에 붙어 있을 거라고 생각했다. 그래서 다리를 뜯었다. 그리고는 옆에서 박수 소리를 들려줬다. 그러니 파리가 날아서 도망을 갔다. 다리에 귀가 있다면 박수 소리를 못 들어 도망 가지 못했을테니 과학자는 다리는 아니라고 생각한다. 다음은 날개에 귀가 있다는 가설을 세운다. 그리고는 날개를 뜯고 실험을 했다. 그러자 이번에는 박수를 쳐도 파리가 도망 가지 않고 가만히 있었다. 과학자는 당당하게 실험 결과를 토대로 파리의 귀는 날개에 달려 있다는 논문을 쓴다.&lt;/p&gt;
&lt;p&gt;사실 위의 우스개는 과학이 가지는 본질적인 문제점을 풍자한 것이다. 요즘 발표되는 많은 논문들이 사실은 위와 다름이 없다. 어느 날은 비타민 과다 복용이 좋다고 했다가 어느 날은 과다 복용은 위험하다고 한다. 어느 날은 운동이 건강에 좋다고 했다가, 어느 날은 운동하다 죽는 사람이 더 많다고 한다. 과학이 이러니 프로그래밍도 이렇게 하면 되는 것일까? 하지만 거기엔 엄청난 차이가 있다. 가장 큰 차이는 과학이 탐구하는 대상인 자연, 인간, 우주 같은 것들은 본질적으로 우리가 만든 것이 아니다. 그러니 우리는 그 원리를 알 수 없기 때문에 귀납적 추론을 할 수 밖에 없다. 반대로 프로그래밍은 아주 사소한 약속 하나부터 모두 우리가 정한 것이다. 그러니 이 세계는 본질적으로는 귀납적으로 추리할 필요가 없다. 모두 우리가 만든 약속을 쌓아 올려서 만든 것이니 당연히 그 모든 것을 연역적인 방식으로 설명할 수 있어야 하는 것이다.&lt;/p&gt;
&lt;p&gt;앞선 return으로 돌아가 보자. 1을 0으로 바꾼 결과 정상 동작하는 것을 관찰했다면 그 다음은 무엇을 해야 할까? 왜 1이면 동작하지 않고, 0이면 동작하는지에 대한 설명을 할 수 있어야 한다. 만약 그걸 설명하지 못한다면 원인을 찾은 것도 아니고 코드를 이해한 것도 아니다. 이 단계에서 완전한 설명이 가능하고 그것을 다른 프로그래머에게 이야기를 했을 때에 똑같이 동의를 한다면 그것은 어느 정도 올바른 해결책을 찾은 것으로 간주해도 될 것이다.&lt;/p&gt;
&lt;h3&gt;완전한 이해&lt;/h3&gt;
&lt;p&gt;신입 프로그래머들이 실험 주도 프로그래밍의 함정에 빠지는 것은 그들이 이해해야 하는 어떤 대상에 대해서 완전한 이해를 하지 않기 때문인 것 같다. 완전한 이해의 대상은 기존에 작성된 코드일 수도 있고, 특정 프로그래밍 언어일 수도 있고, 특정 라이브러리나 프레임워크일 수도 있고, 특정 운영체제일 수도 있다. 심지어는 특정 표준에 대한 스펙일 수도 있다. 그런 대상에 대한 이해가 부족하기 때문에 어느 지점에서 문제가 발생한다는 것을 관찰했을 때에도 느낌표가 없고 계속 물음표만 존재하는 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 많은 신입 프로그래머들이 실력 향상을 원한다고 이야기를 하면서도 정작 중요한 문제 해결에 필요한 완전한 이해를 하지 않는 것일까? 아마도 그 과정이 시간이 오래 걸리고 고통스럽기 때문일 것이다. 따분하고 지루한 공부가 필요하다는 의미다. 하지만 안타깝게도 현실 세계에서 내가 관찰한 대부분의 경우는 공부가 부족한 경우가 많았다. 일단 대체로 절대적으로 공부하는 시간이 부족하다. 앞선 이해의 대상 중 어떤 것이든 간단하게라도 살펴보기 위해서는 상당히 많은 시간이 필요하다. 하지만 많은 신입 프로그래머들은 그런 연속된 시간을 투자하는 것을 시간 낭비라고 생각한다. 심지어는 퇴근 후에 컴퓨터를 본다는 것은 뭔가 손해보는 일이라고 생각하기까지 한다. 다음으론 검색의 지나친 발달로 인한 폐해를 들 수 있다. 대체로 거의 모든 문제에 대해서 구글 검색을 하면 결과가 나오기 때문이다. 그러니 복잡하고 원론적인 이해 보다는 단편적인 현상에 대한 답만 알고 넘어가려는 경향이 강하다. 그렇게 빈약하게 이해를 하더라도 문제가 해결되니 말이다.&lt;/p&gt;
&lt;p&gt;검색으로 얻는 파편적인 지식으로는 한계가 있다. 잘 쓰여진 좋은 책을 통해서 한 점이 아닌 전체적인 선 모양이 어떤지를 알 수 있는 공부를 해야 한다. 또 일주일에 한두시간 공부하는 것으로도 한계가 있다. 아마 환갑 잔치 때가 되서야 목표에 도달할 수 있을 것이다. 훨씬 더 많은 시간을 투자해야 한다. 물론 취미로 프로그래밍을 하거나 직업의 영속성이 크게 중요하지 않은 사람들에겐 이런 조언이 별로 중요하지 않을 수 있다. 하지만 반대로 해자를 구축하고 장기적으로 살아 남아야 하는 사람이라면 그래야 하지 않을까라는 생각을 해본다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;여기서는 제자리에 머물기 위해서라면 아주 빨리 달려야 해.&lt;br&gt;
만약 다른 곳에 가려면 지금보다 두 배는 빨리 뛰어야 하지.&lt;/p&gt;
&lt;p&gt;-— 거울 나라의 앨리스&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[정보] 샌프란시스코 음식점들...]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2017/02/sf-food/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/sf-food/</guid><pubDate>Fri, 17 Feb 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;기억을 위해 샌프란시스코에서 가 본 음식점을 정리해 본다. 또 누군가에겐 도움이 되지 않을까 싶은 마음에…​&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/HYmxWvQU9qy&quot;&gt;산라쿠&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;일식집. 초밥, 사시미, 롤, 우동, 튀김 등을 판다. 일식이 대체로 그렇지만 기본은 하는 집. 쏘쏘하다. 생각보다 손님이 많다. 식사 시간에 간다면 예약하고 가는 게 정신 건강에 좋을듯.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/6M1BmMhGrmm&quot;&gt;수퍼 두퍼&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이쪽 동네에 있는 햄버거 체인. 패티 두개 들어간 수퍼 버거를 먹었는데 약간 느끼했다. 토핑을 추가할 수 있는데 모두 추가한다는게 잘못돼서 그냥 일반 버거로 먹었다. 기름기가 많다. 피클을 나눠주는데 나눠주는 이유가 있는듯. 갠적으론 쉑쉑이 더 맛있었다. 첨 나오면 조그맣게 생겨서 양이 별로 안 되는 것 같은데 이동네 음식들이 다 그렇지만 먹고 나면 그런 생각이 싹 사라진다. 네이버 검색에 의하면 미니 버거에 이것 저것 추가해서 먹어보는 사람이 많은 것 같다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/3aDuf4pcgio&quot;&gt;닉스 라이트하우스&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;피어에 위치한 해산물 집. 랍스터와 만찬 세트(?!)를 먹어봤다. 아줌마가 장사를 잘한다. 랍스터는 진짜 큰 걸 먹었는데 그닥 취향은 아니었다. 만찬 세트도 그저 그런 정도. 와 맛있어서 찾아가야겠다 할 정도는 아님. 맥주는 맛있다.&lt;/p&gt;
&lt;p&gt;39번 피어 쪽에서 구경도 하고 가게를 찾아가는게 조금 더 현명한듯한 느낌적인 느낌.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/518d46dtvKU2&quot;&gt;크랩 하우스 앳 피어 39&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;크랩집. 나쁘지 않았다. 배고플 때 한 번 가봐서 정확한 느낌은 아닐 수 있다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/sp2SR3VSST52&quot;&gt;존스 그릴&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;진짜 가지 말아야 할 집. 저주할 지어다. 스테이크 집인데 스테이크가 별로다. 비싸다. medium rare와 medium well을 시켰는데 medium well은 거의 태운 상태 medium rare는 색깔은 그런대로 맞춰 구어진 것 같은데 육즙이 제로였다. 스테이크가 아니라 고무 씹는 느낌. 역사가 오래된 느낌이어서 가봤는데 역사만 오래된 집이었다. 먹고 나서 yelp에 가봤더니 투어리스트 트랩이라는 평이 인상적이었다. 심지어 추리소설에 나온 적이 있는 집이라고 했다. 정말 돈 값 못하는 집…​ 참고로 함께 간 일행 모두 보통 뭔들 먹고 나서 맛없다는 이야기를 안 하는데 모두가 최악이라 평했다.&lt;/p&gt;
&lt;p&gt;너무 빡쳐서 나오면서 다른 사람들이 시킨 것도 살펴봤는데 죄다 육즙이 없기는 마찬가지. 손님은 정말 많아서 마치 진짜 맛집같은 느낌인데…​ 투어리스트 트랩이라는 평이 딱 맞다. 애피타이저까진 나쁘지 않았는데…​&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/LzpUJdWmU9U2&quot;&gt;미스 사이공&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;미스 사이공, 베트남 쌀국수 집. 샌프란시스코에 왔을 때 첨 가 본 쌀국수 집. 이후에 다른 쌀국수 집도 몇 군데 가봤는데 이곳이 그나마 나은듯한 느낌. 블루보틀 근처라 나오면서 블루보틀에서 라떼 한 잔 하기 좋은 위치.&lt;/p&gt;
&lt;p&gt;고수를 싫어한다면 주문전에 노 실란트로 외워갈 것. 대체로 그렇지만 디폴트로 탑재해서 나온다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/WfLGRg1xc7q&quot;&gt;꼬꼬방&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;한국식 포차. 온갖 메뉴를 다 판다. 치맥을 주로 했는데 갈비가 먹을만 했다. 라면도 괜츈하다. 늦게까지(새벽 2시?!) 하는게 장점이다. 힐튼 쪽에 호텔이면 가깝다는 것도 큰 장점. 그래서 그런지 늦은 시간에 손님이 많다.&lt;/p&gt;
&lt;p&gt;이번에 길을 잘못 들어서 꼬꼬방 간다는게 aria라고 다른 곳을 갔는데 거기는 테이블이 별로 없고 주로 포장해서 가는 집인듯 했다. yelp 보고 찾아가면 대략 낭패.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/7Py2ZmKvpjB2&quot;&gt;이자카야 닌자&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이자카야. 그냥저냥 먹을만하다. 시킨 거 먹기만 해서 그닥 무슨 메뉴가 있었는지 잘 기억이 안남.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/UeZ1ZFYg3V42&quot;&gt;고려정&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;한식 고기집. 삼겹살과 갈비를 먹어봤는데 쏘쏘하다. 10시에 문을 닫는다는게 술을 많이 마시는 사람 입장에서는 다소 부담스러울 수도 있다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/LdnHGoBMMts&quot;&gt;산왕반점&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;중국집. 한번쯤 가서 먹기에 괜찮다. 짬뽕 국물도 괜찮고 다른 요리 메뉴도 대체로 다 괜찮은듯.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/qFuebhzcxdF2&quot;&gt;블루보틀 커피&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;샌프란시스코의 명물이라고 했는데 그 출발점이 다소 불분명하다. 여튼 샌프란시스코에 파는데가 있다. 처음 가보면 간판에 이름도 없고 파란병만 그려 있는 것이 다소 황당하다. 라떼가 맛있다. 탁월한 부드러움, 적당한 온도, 고소함이 특징. 사실 다른 라떼랑 섞어 놓고 고르라면 고를 자신은 의문…​&lt;/p&gt;
&lt;p&gt;블루보틀 앞에 푸드 트럭이 있는데 의외로 현지인들에게 인기있는 듯 하다. 보울드 아사이라고, 기회되면 한 번 먹어 보고 싶었다. 현지인들이 많이 먹는 것으로 봐서는 먹을만한 것 같은 느낌적인 느낌. 한국으로 치면 일종의 컵밥 같은?! 단점이라면 근처에 홈리스가 많아서 잊을만하면 한번씩 온다는 점.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/6UpGeyMB6ym&quot;&gt;태드네 스테이크&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;스테이크만 달랑 나온다. 싸고 양이 많은 게 장점인듯. 그냥저냥 먹을만 하다. 존스 그릴 보다는 백만배쯤 맛있다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/RkyzDZs5L9q&quot;&gt;테일러 커피숍&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;아침을 판다. 엄청 좁다. 아침에 가면 사람이 좀 있다. 재수 없으면 엄청 오래 기다려야 함. 그냥 미국식 아침 메뉴를 판다. 베이컨, 에그, 뭐 그런. 먹을만 하다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/hbMxTA7yfNv&quot;&gt;진미순두부&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;순두부집. 샌프란시스코에는 BCD 북창동 순두부는 없는 듯 하다. 왤까? 해물순두부만 먹어봤는데 그럭저럭 먹을만하다. 아침 식사 가능하다.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goo.gl/maps/vpegiePHGLR2&quot;&gt;더 스피나커&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;다운타운에 있는 집은 아니다. 금문교 건너 소살리토라는 동네에 위치한 집. 바다에 완전 접해 있어서 전망이 예술이다. 간다면 꼭 창가 자리로 예약할 것. 스테이크를 먹었었는데 맛있었다. 소살리토도 구경하기 좋은 동네. 다운타운이랑은 분위기가 천지차이다. 일단 홈리스와 지린내가 없다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] RSA 2017 DAY #2]]></title><description><![CDATA[1일차는 노스관 2일차는 사우스관을 봤다. 사우스 쪽은 우리랑 비슷한 일을 하는 업체는 없는 것으로 보였다. 1, 2일 모두 쭉 돌아보면서 많이 본 키워드를 뽑아 보면 breach, endpoint, malware, NGAV(Next…]]></description><link>https://jiniya.net/ng/2017/02/rsa-2017-day-2/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/rsa-2017-day-2/</guid><pubDate>Fri, 17 Feb 2017 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;1일차는 노스관 2일차는 사우스관을 봤다. 사우스 쪽은 우리랑 비슷한 일을 하는 업체는 없는 것으로 보였다. 1, 2일 모두 쭉 돌아보면서 많이 본 키워드를 뽑아 보면 breach, endpoint, malware, NGAV(Next Generation Anti-Virus), mobile, virtual 정도 인 듯. 대략 그런 일을 하는 업체들이 많은 것 같다. 백신 업체도 더이상 백신 이야기를 많이 하지 않는 느낌적인 느낌. 메이저 백신 업체들의 타겟팅은 이제 일반 PC 보다는 IoT 쪽이 많은 것 같아 보였고, 심지어는 국가 기간망을 대상으로 영업 활동을 전개하는 곳도 있어 보였다.&lt;/p&gt;
&lt;p&gt;이런 쇼 오면 꼭 하나 살펴보는 게 빨때 꼽는 업체들을 찾아본다. 보안 쪽은 로그 서비스와 라이브러리 정도가 전부인 것 같다. 보안 업체 특성 상 또 외부 솔루션을 잘 사용하지 않기 때문인 것 같아서 그런 것 같기도 하다. 직원 보호 솔루션이라 쓰고 감시(?!)하는 솔루션도 더러 있었는데 약간 무섭기도 했다.&lt;/p&gt;
&lt;p&gt;대체로 대다수 업체가 센서를 통해서 온갖 정보를 수집하고 인공 지능이나 머신 러닝 같은 기술을 사용해서 마이닝을 하여 뭔가 찾아낸 다음 그걸 알흠답게 고객에게 뷰잉해주겠다는 방향으로 달려가는 것 같은 느낌…​&lt;/p&gt;
&lt;p&gt;또하나 인상적인 것은 미국 국가 기관 부스가 많이 있었다. 대체로 홍보나 기술 전시 보다는 채용에 목적을 둔 것으로 추정되는데 신기한 점이긴 했다. 한국 업체 중에서는 파수가 그나마 부스를 멋들어지게 만들었다. 부스만 보고는 한국 업체 아닌줄…​ ㅋㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] RSA 2017 DAY #1]]></title><description><![CDATA[세계 최대 보안 컨퍼런스인 RSA…]]></description><link>https://jiniya.net/ng/2017/02/rsa-2017-day-1/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/rsa-2017-day-1/</guid><pubDate>Thu, 16 Feb 2017 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./rsa_badge.jpg&apos; data-alt=&apos;Figure 1. RSA 2017 엑스포 배지&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/77384aa6a195909aee19d28ec57af609/ba98e/rsa_badge.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEBQH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAwL/2gAMAwEAAhADEAAAARelw3KaImeiqeU0ihr/AP/EAB0QAAICAgMBAAAAAAAAAAAAAAACAQMREgQTMSH/2gAIAQEAAQUCwexpYaLELk+k8ga5jtOtDxrLGiz/xAAZEQADAAMAAAAAAAAAAAAAAAAAARECEkH/2gAIAQMBAT8BKa5vonD/xAAWEQEBAQAAAAAAAAAAAAAAAAAQESH/2gAIAQIBAT8Bwp//xAAbEAACAwEBAQAAAAAAAAAAAAAAAQIhMREQMv/aAAgBAQAGPwLnRRPkwvzDUi5MdGIkk6P/xAAdEAACAgIDAQAAAAAAAAAAAAABEQAhUXExQWGx/9oACAEBAAE/Iblk9MSxlTcl4LjxxXb5L5gA0R3OnpRs/cFzm5SAAPER4A0FP//aAAwDAQACAAMAAAAQa9D9/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAEQETFRwf/aAAgBAwEBPxC1qKyAxK4f/8QAGREAAwEBAQAAAAAAAAAAAAAAAAERIUFR/9oACAECAQE/EFHCrwo16f/EABwQAQEBAQEAAwEAAAAAAAAAAAERACExUWGBof/aAAgBAQABPxBBmKNwwAGSdaeZu9fZe4WF6Hr/AHXUD4kB+adAVwgeL6CZA8TsVXE+ReRyfmYKGnq6JmAgdwTiA5w3/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. RSA 2017 엑스포 배지&apos; title=&apos;&apos; src=&apos;/static/77384aa6a195909aee19d28ec57af609/ba98e/rsa_badge.jpg&apos; srcset=&apos;/static/77384aa6a195909aee19d28ec57af609/8ccab/rsa_badge.jpg 190w,
/static/77384aa6a195909aee19d28ec57af609/ba98e/rsa_badge.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. RSA 2017 엑스포 배지&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;세계 최대 보안 컨퍼런스인 RSA에 처음으로 참관했다. 뭐 배우러 온것은 아니고 세상이 어찌 돌아가는지 구경하는게 목적이라 엑스포만 참관했다. 그간 다녀본 게임 관련 쇼나 컨퍼런스랑은 다소 다른 분위기였다. 보안이라 그런지 대체로 거의 모든 사람이 정장을 입고 있다는데 적응이 되지 않았고, 보안이라 비주얼이 약해서 보는 재미가 별로 없었다. 대부분의 부스가 그럼에도 액티브하게 보이려고 노력을 했지만 한계가 있어 보였다. 말이 많이 필요했고, 부스도 대체로 수많은 텍스트로 꾸며진 경우가 많았다.&lt;/p&gt;
&lt;p&gt;어쨌든 참관하면서 관심 있게 본 유사 분야 업체를 간단히 정리해 본다. 별로 없을 줄 알았는데 생각보다 없지는 않았다. 알리바바가 특히 의외였다. 마윈 회장이 자율 주행 자동차도 만든다고 얘기하는 걸 티비에서 본 적이 있었는데 정말 안 하는게 없는 것 같다.&lt;/p&gt;
&lt;p&gt;GuardSquare
안드로이드에서 많이 사용되는 난독화 도구인 ProGuard, DexGuard의 제작사. DexGuard 플러그인으로 DexGuard NDK와 Secure Keyboard, Device Fingerprinting이 있다는 것을 새롭게 알게 됐다. 그리고 iOS 버전으로 새롭게 출시한 iXGuard가 있다는 것도. 부스에서 iXGuard를 그닥 홍보하고 있지는 않았다. 왤까?&lt;/p&gt;
&lt;p&gt;AlibabaCloud Mobile Security
알리바바에서 클라우드를 하는 업체인 알리바바클라우드에서 모바일 보안 서비스도 제공하고 있는 것으로 보여진다. Alibaba JAQ Security Solution으로 불리는 것으로 애플리케이션 하드닝으로 표현하는 기술이 기존에 난독화 솔루션이 대체로 제공하는 기능으로 보여진다. 브로셔를 보면 SO, DEX 난독화 기능을 SO shelling, DEX shelling으로 표현한게 인상적. 껍데기를 씌우는거라 그렇게 표현한 것으로 추측된다. 인상적인 부분은 Java execution simulation 자바단의 코드를 덤프하는 것을 막기 위해서 별도의 환경에서 코드를 돌리는 기술을 말하는 것으로 보여졌다.&lt;/p&gt;
&lt;p&gt;알리바바가 이런 것도 한다는게 다소 신기했다. 대기업들이 돈되는 건 다하는 세상인 것 같아 조금은 씁슬한 면도 없잖아 있었다. 불과 몇년만에 알리바바를 스타트업에서 대기업으로 표현하는 게 좀 웃기긴 하지만. 어쨌든 이제는 대기업이니…​&lt;/p&gt;
&lt;p&gt;ARXAN
기술적인 진화 보다는 시장을 분류해서 마케팅하는 방법이 인상적이었다. 게임을 위한 제품(for Gaming), 모바일 결제 및 뱅킹을 위한 제품 (for Mobile Payment &amp;#x26; Banking), 헬스케어 장비를 위한 제품 (for Healthcare IoT), 자동차 장비를 위한 제품(for Automotive IoT)으로 나눠서 제품을 만들었다. 물론 근간이 되는 기술은 크게 다르지 않은 것으로 보여진다. 사실 자동차까지는 많이들 얘기하지만 의료 장비는 다소 의외였다. 보안이 필요 없는 분야가 있겠냐만은, 의료장비 레퍼런스가 있는지가 조금 궁금하긴 했다.&lt;/p&gt;
&lt;p&gt;AllthatSoft
쉴딩 형태의 제품으로 보여지는 모바일 코드 보호 제품인 App Servo를 홍보하고 있었다. 제품의 기술적인 특이점은 흔히 스톨른 바이트(Stolen Bytes)라고 불리는 기법을 적용한 제품이라는 것. 원본 코드를 분리하고 특정 코드를 외부에 보관한 다음 필요한 시점에 동적 결합 또는 원격 실행을 하는 구조인 것으로 보여진다. 해당 회사는 그 기능을 Self-Randomization으로 소개하고 세부 주요 구현 기술로 CODE-SPLITTING, SELF-MODIFYING이라고 설명했다. 어쨌든 스톨른 바이트에 기반한 앱 보호 제품은 첨 본 것 같다.&lt;/p&gt;
&lt;p&gt;적용 분야로 모바일 결제, 모바일 뱅킹, 자동차 공유, 모바일 게임을 들고 있다. 자동차 공유 서비스를 타게팅한 것도 다소 의외였다.&lt;/p&gt;
&lt;p&gt;intertrust
whiteCryption의 Code Protection 기능이 하드닝, 난독화 기능을 제공하는 것으로 보여진다. 대체로 브로셔에서 설명하는 개념은 ARXAN이랑 비슷한 것으로 보여졌다. 단지 ARXAN은 가드라고 부르고 intertrust는 체커라고 부르는 게 차이점인듯.&lt;/p&gt;
&lt;p&gt;덧) 구경하는데 왜 이렇게 줄이 길지 하는 곳이 있었다. 뭐 나눠 주나보다 했는데 케빈 미트닉 옹께서 &quot;The Art of Invisibility&quot;라는 본인의 저서에 사인을 해주고 사진을 같이 찍어주는 행사를 하고 있었다. 첨에는 케빈 미트닉이 아닌 줄 알았다. 줄이 길고 피곤해서 사인북을 받지는 않았는데, 나중에 나와서 검색해보니 매년 오시는 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 광고, 예술이 되다.]]></title><description><![CDATA[어쩌다 유튜브 보는데 나온 광고. 차에 관심 1도 없는데 살짝 심쿵했다. 간지 멘트하며, 그 멘트들의 절묘한 전개, "The balance isn’t found. It’s created…]]></description><link>https://jiniya.net/ng/2017/02/super-bowl-ads/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/super-bowl-ads/</guid><pubDate>Fri, 10 Feb 2017 12:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/piU6jh56NPE?si=rlkT5QfwPzwJHzpg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;어쩌다 유튜브 보는데 나온 광고. 차에 관심 1도 없는데 살짝 심쿵했다. 간지 멘트하며, 그 멘트들의 절묘한 전개, &quot;The balance isn’t found. It’s created&quot;에서는 이래서 이빨에 넘어가는 구나 했다. 저 느린듯 템포 있게 조화로운 배경 음악 하며. 저 차 사면 진짜 막 용에 올라타는 그런 느낌일거 같고…​ 급기야 무슨 브랜드인지를 몰라서 심지어 정지시켜 놓고 검색해보게 만드는 위엄. 이래서 광고가 돈이 되는구나 싶다. 하지만 결정적으로 차 디자인은 내 스타일은 아니긔…​ ㅋㅋㅋ&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/HIpoTW1JDFQ?si=YxqzUM0Qum65d4qK&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;정반대 느낌의 기아차 슈퍼볼 광고, 재미는 있다. 아니 재미만 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 당신의 연말 정산 이야기]]></title><description><![CDATA[연말 정산 시즌이다. 이맘때면 한숨과 고성이 오간다. 13월의 급여를 받는 사람도 있고, 한달치 급여가 사라진 사람들도 있다. 연말 정산의 아픔이 잊혀질만한…]]></description><link>https://jiniya.net/ng/2017/02/tax/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/tax/</guid><pubDate>Mon, 06 Feb 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;연말 정산 시즌이다. 이맘때면 한숨과 고성이 오간다. 13월의 급여를 받는 사람도 있고, 한달치 급여가 사라진 사람들도 있다. 연말 정산의 아픔이 잊혀질만한 4월이 되면 건보료 폭탄이 또 한 번 때린다. 대체로 급여가 오른 만큼 건보료도 정산해서 토해낸다. 그때는 다들 한숨만 깊어진다. 나이가 들고 연봉이 오르고 하다보면 결국 알게 되는 건 세금 밖에 없다.&lt;/p&gt;
&lt;p&gt;토해내는 입장에서는 도대체 돌려 받는 사람들은 왜 돌려받는지가 무척 궁금해진다. 그리고 무지에 의해서 마치 엄청난 비밀이 숨어 있는 것처럼 음모론들을 제기해 보지만 거기에 음모 따위는 없다. 그저 여러분이 국가가 장려하는 활동을 많이 하면 혜택을 많이 주고, 국가가 싫어하는 활동을 많이 하면 세금이 많아지고 하는 것이다. 각설하고 이 말도 많고 탈도 많은 연말 정산이 어떤 구조로 이루어지는지 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;연말 정산은 말 그대로 일년 동안 내야할 세금을 최종적으로 확정짓는 과정이다. 대한민국은 급여소득자에게 세금을 미리 원천 징수하고 나중에 다시 정산 과정을 통해서 원천 징수한 금액이 많으면 돌려주고, 적으면 더 받아내는 시스템을 사용한다. 흔히 직장인 급여를 유리 지갑이라고 하는 이유가 여기 있다. 애초에 받을 때 국가에 신고가 들어가고 세금은 공제하고 남은 차액만 받기 때문이다. 당신의 급여 명세서 항목 중에서 소득세와 지방세라는 것이 국가가 이렇게 미리 뜯어가는 비용이다.&lt;/p&gt;
&lt;p&gt;그러면 그냥 원천 징수만 하고 끝내면 될텐데 왜 연말 정산이라는 것을 할까? 원천 징수는 표준 모형에 의한 것이기 때문에 원천 징수를 얼마 할지는 급여가 정해지면 일괄적으로 책정된다. 하지만 국가가 그리 나쁜 놈들은 아니다. 아니면 더 나쁜 놈일수도 있다. 어쨌든 그런 이유로 국가는 사람들이 그 급여를 몽땅 다 써버리길 원하지 않는다. 그들의 미래를 위해서 쓰기를 바라기도 하고 자신들의 세금 계산을 위해서 현금이 아닌 카드를 사용하기를 원하기도 한다. 또 부양 가족이 있어서 돈이 많이 필요한 사람들에게는 세금을 감면해 주기도 한다. 결국 국가는 최종적으로 개개인들에게 그들의 돈을 어떻게 사용해야 할지에 대한 인센티브를 세금을 통해서 제공한다고 보면 된다.&lt;/p&gt;
&lt;p&gt;그럼 먼저 소득세를 어떻게 계산하는지에 대해서 간단히 살펴보자. 대한민국의 소득세는 누진적 구조로 이루어져 있다. 즉 많이 벌면 세금을 더 많이 내도록 된 구조다. 살펴보면 1200만원 이하는 6%의 세금을, 그 다음 4600만원 이하는 15%의 세금을 그 다음 8800만원 이하는 24%의 세금을, 그 다음 1억 5000만원 이하는 35%의 세금을, 그 다음 5억 이하는 38%의 세금을, 5억을 초과하면 40%의 세금을 낸다. 자, 통크게 내 연봉이 10억이라고 가정해보자. 그럼 얼마를 세금으로 내야 할까? 1200만원까지는 72만원 4600만원까지 510만원, 8800만원까지 1008만원, 15000까지 2170만원, 5억까지 13300만원, 끝으로 10억까지 20000만원을 세금으로 낸다. 다 더하면 72 + 510 + 1008 + 2170 + 13300 + 20000 = 37060만원을 세금으로 낸다. 여기에 10% 지방세가 붙는다. 3706만원을 지방세로 납부하니 최종적으로는 10억을 벌면 국가에 4억 하고도 766만원을 세금으로 내야 한다. (계산하고 공제하는 더 간편한 방법이 있다. 단지 어떻게 세금이 누진되어 가는지를 보여주기 위해서 불편한 방법을 썼다.)&lt;/p&gt;
&lt;p&gt;다음으로는 이제 이렇게 산정된 소득세에 대해서 어떤 방식으로 인센티브를 제공하는 살펴보자. 인센티브를 제공하는 방식은 크게 두 가지 방식이 있다. 하나는 소득 공제이고 다른 하나는 세액 공제다. 소득 공제는 전체 소득에서 정해진 만큼 빼고 세금을 계산하는 방식이고, 세액 공제는 최종 확정된 세금에서 정해진 만큼 빼는 구조다. 이 둘의 차이는 쉽게 말하면 이렇다. 소득 공제는 세금 계산 전에 빼기 때문에 혜택이 차등적이고, 세액 공제는 균등하다. 다시 말하면 소득 공제는 배율을 확정짓기 전에 빼기 때문에 고소득자일수록 유리하다. 최고 세율인 40%인 사람들의 경우 100만원 소득 공제가 되면 40만원을 돌려 받는 것과 동일한 효과를 가진다. 반면 소득세율이 15%인 사람은 15만원을 돌려받는데 그친다. 똑같이 100만원 쓴 것에 대한 혜택을 받는데 고소득자가 더 유리한 제도인 것이다. 반면 세액 공제는 최종 금액에서 차감하기 때문에 동일한 활동을 했을 때 고소득자와 저소득자가 받는 차이는 크게 없다.&lt;/p&gt;
&lt;p&gt;여기서 조삼모사가 나온다. 예를 들면 연금저축을 들 수 있다. 이게 원래 400만원까지 소득 공제 항목에 있었다. 그러면 40% 세금을 낸다면 연 160만원을 돌려받을 수 있고, 20% 세금을 내는 사람은 80만원을 돌려 받는 구조였다. 그런데 정부에서 이를 세액 공제로 변경했다. 그리고는 400만원을 납입하면 연 100만원을 세액 공제 해준다고 한 것이다. 40% 세금을 내던 사람은 이제는 60만원을 덜 돌려 받게 되었고, 20% 세금을 내던 사람은 20만원을 더 돌려받게 된다. 즉, 대체로 세액 공제로 바뀌면 없는 사람에게 더 유리해 지는 것이다. 그럼에도 정부가 그때 개욕을 먹었던 것은 저 세액 공제율을 잘못 선정하는 바람에 고소득자든 저소득자든 다 손해보는 구조를 만들어서 그런 것이었다. 물론 그것조차도 계획된 것일 수 있지만…​ (참고로 여기에 제시된 수치들은 가상적인 수치다)&lt;/p&gt;
&lt;p&gt;자 이게 연말 정산의 모든 비밀이다. 국가가 세금을 미리 계산해서 가져갔고, 연말 정산을 할 때에는 이제 국가가 장려하는 활동에 얼마를 썼느냐에 따라서 세금을 다시 조정할 것이다. 국가가 좋아하는 일을 했다면 세금을 많이 돌려받을 것이고, 국가가 싫어하는 일을 했다면 그닥 못 돌려 받을 것이다.&lt;/p&gt;
&lt;p&gt;2017년 대한민국은 어떤 활동에 인센티브를 제공하는지 살펴보자. 소득 공제 항목을 살펴보면 이렇다. 부양 가족. 최고로 갑이다. 벌이가 없는 부모님, 자식 등을 부양가족으로 올리면 일정 수준 소득 공제를 해준다. 더불어 그 부양 가족이 사용한 모든 비용도 내가 사용한 비용으로 인정해준다. 일정 조건에 합당한 무주택자가 집 산다고 빌린 돈. 님들이 집을 사도록 국가가 유도하는 것이다. 어쨌든 이를 갚은 것들은 국가가 비용으로 인정해주고 일정 수준 세금을 감면해 준다. 신용카드 사용액, 이는 최초에는 현금이 아닌 신용카드 사용을 장려하기 위해 생긴 제도였다. 지금은 많이 퇴색되어 수명이 오늘 내일 하는 소득공제 항목 중에 하나다. 여기에 관해 생긴 가장 큰 오해 중에 하나가 연말 정산에서 많이 쓰면 많이 돌려받는 다는 것이다. 그런데 신용 카드 사용에 관해서는 아주 복잡한 공식이 존재하지만 결론만 말하면 쓰는 금액 대비 공제해 주는 양이 아주 적기 때문에 이를 위해서 지출을 늘리는 것은 정말 바보 같은 행위다. 기부금. 이는 사실 소득공제로 보긴 힘들다. 기부한 금액보다는 적게 소득 공제를 해주기 때문이다. 주택마련 저축 납입금. 집 산다고 통장을 만들어 납입하면 정해진 한도 내에서 소득 공제를 해준다. 그리고 일반인들에게는 잘 알려지지 않았지만 지금 최고의 소득 공제 항목으로는 벤처 기업 투자가 있다. 조건에 해당하는 벤처기업에 투자할 경우 파격적인 소득 공제 혜택을 준다.&lt;/p&gt;
&lt;p&gt;세액 공제 항목을 살펴보면 이렇다. 보장성 보험을 가입하면 연간 100만원 한도 내에서 일정 수준 세액 공제를 해준다. 일년에 여유되면 100만원 정도는 보장성 보험에 돈을 투자하라는 예기다. 연금저축 연간 400만원 한도 내에서 일정 수준 세액 공제를 해준다. 이는 말이 많은 항목인데 더 맡이 많아지게 되었다. 왜냐하면 정부의 안대로 지금 당장 납입하면 세액 공제를 받을 수 있지만 나중에 연금을 받을 때 다시 세금을 납부하기 때문에 실제로는 정말 조삼모사같은 상품이기 때문이다. 이는 실상은 과세 이연이지 혜택이라고 보기는 힘들다. 그래도 어쨌든 국가는 여러분의 미래를 위해서 연금을 들기를 희망하고 있다. 퇴직 연금 또한 연에 300만원 한도로 세액 공제를 해준다. 의료비, 교육비도 일정 수준 공제를 해준다. 또 정치 기부금의 경우 10만원까지는 전액 세액 공제가 된다. 좋아하는 국회의원이 있다면 10만원 기부하면 10만원을 돌려받게 된다. 참으로 신박한데 법을 누가 정하는지 알게되면 왜 이런 신박한 제도가 생겼는지 절로 이해가 된다. 월세에 대한 세액 공제도 해준다. 일정 수준의 조건이 맞아야 하지만 월세로 납부한 금액의 일부를 세액 공제로 돌려준다.&lt;/p&gt;
&lt;p&gt;자 종합해보면 그렇다. 정부는 여러분이 결혼을 해서(+부양가족) 빚을 내서(+대출) 집을 산(+부동산) 다음에도 여유가 있다면 기부를 하기를 희망한다. 자신의 소득의 일정 수준 이상은 신용카드로 사용하기를 희망하고, 신용카드 보다는 체크카드 사용을 더 장려하고 있다. 보장성 보험을 연간 100만원 정도 내기를 바라고, 개개인의 미래를 위해서 연금 저축을 400만원, 퇴직 연금을 300만원 정도 매년 투자하기를 바란다. 국회 의원에게는 매년 10만원 정도 무조건 기부를 했으면 하고, 여러분이 그나마 월세에서 고통 받는 것을 조금은 덜어주고 싶어한다. 그리고 여러분이 이 모든 활동을 넘어서 돈이 너무 많은 자산가라면 벤처 기업에 투자하기를 희망한다.&lt;/p&gt;
&lt;p&gt;조금 더 현실적인 조언을 해보자. 여러분이 일반적인 급여 수준의 미혼 남성이라면 어떤 활동을 하는 것이 좋을까? 일단 영혼까지 끌어모아 부양가족 수를 늘린다. 청약 저축을 만들고 매달 10만원씩 납부한다. 보장성 보험이 없다면 만들고 매달 9만원 정도 납부하고, 연금 저축을 개설하고 매달 34만원씩 납부하고, 퇴직 연금이 된다면 매달 25만원씩 납부하고, 12월에 한 번 그 해 제일 맘에 드는 국회의원에게 10만원 기부를 하면 대체로 정부가 원하는 대로 행동했다고 볼 수 있겠다. 물론 월세를 살고 있다면 월세 비용도 공제 받으면 금상첨화.&lt;/p&gt;
&lt;p&gt;끝으로 최근 들어 생긴 조삼모사 끝판 대장 중에 하나를 소개하고 마칠까한다. 바로 원천 징수율을 결정하는 것이다. 80%, 100%, 120% 중에 선택할 수 있다. 적게 내고 적게 돌려 받을 지, 사전에 많이 떼고 많이 돌려받을지 결정하는 것이다. 대체로 자금 관리에 자신이 있는 사람이라면 80%가 유리하다. 왜냐하면 시간 가치가 있기 때문이다. 이자도 없이 정부가 일년간 묵혔다가 주는 돈을 받는 것 보다는 먼저 많이 받고 그 돈을 투자해서 불리는 것이 유리하기 때문이다. 모두가 이상적인 사람으로만 구성되었다면 사실상 100%와 120%는 의미 없는 선택지다. 하지만, 여러분이 비자금이 필요한 유부남이라던가, 자금 관리에는 젬병인 사람이라면 120%를 선택하는 것도 나쁘진 않다. 어쨌든 미리 많이 뗐기 때문에 돌려 받을 돈이 많을 수 밖에 없다. 강제 비자금 통장, 강제 적금 통장으로 국세청을 이용하는 셈이된다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 서울 유동인구 어디가 많을까?]]></title><description><![CDATA[200…]]></description><link>https://jiniya.net/ng/2017/02/seoul-floating-population/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/02/seoul-floating-population/</guid><pubDate>Mon, 06 Feb 2017 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;2003년에 처음 구로공단에 내렸을 때가 생각난다. 병역특례 전직 업체를 찾아서 온 서울, 그 전 면접은 최악이었다. 스마트폰도 없던 시대. 주소 하나 가지고 건물을 찾아가야 하는 상황, 뭔가 이상해서 길을 물어보면 아무도 길을 몰랐다. 그렇게 서울은 20대의 나에겐 차가운 도시였다.&lt;/p&gt;
&lt;p&gt;병역특례를 마치고는 영원히 인연이 없을것 같았던 구로디지털단지에 10년이 훌쩍 넘는 내 청춘의 시간을 갈아 넣었다. 그나마 조금의 위안이 있다면 2003년과 지금은 상전벽해라는 말이 어울릴 정도로 많이 변했다는 것 하나. 온통 공사중이던 빌딩들은 이제 더 이상 지을 공간이 부족할 정도로 빼곡이 들어섰고, 그 사이 호텔이 두개나 지어졌고, 최근 들어 국내에서 돈을 제일 잘 번다는 게임사도 본사를 두고 있다. 가끔 지인들과 근처에서 술을 마시면 이런 얘기들을 하곤 한다. 여기가 요즘 서울에서 유동인구로는 순위권에 드는 동네라고 말이다. 뭐 사실 근거 있는 얘기는 아니었다. 그냥 먹자 골목에 사람이 많다는 것, 그리고 우리가 들어간 식당에 대기가 너무 길다는 것 같은 추상적인 현상을 토대로 하는 말들어었다.&lt;/p&gt;
&lt;p&gt;문득 갑작스럽게 그 말이 진짜인지 궁금했다. 구글 검색을 해보았지만 예전 데이터 뿐이었다. 이럴 때는 프로그래머라는 직업이 다소 편리하다. 디지털 데이터는 도처에 널려있고, 프로그래머는 그것들을 아주 손쉽게 입맛에 맞게 가공할 수 있기 때문이다. 다양한 방법이 있겠지만 나는 그 지역 대중 교통을 사용하는 사람의 인원으로 유동인구를 측정해 보기로 했다. 서울 시에서 제공하는 공공 원시 데이터를 가공해서 수치를 뽑아 보았다.&lt;/p&gt;
&lt;p&gt;먼저 지하철이다. 2016년 12월 승하차 데이터를 대상으로 집계한 순위다. 데이터 내용은 순번, 만단위 승하차인원, 지하철역이다. 2호선 강남역이 1등으로 12월 한달간 562만명이 그 역에서 승하차를 했다. 2등은 잠실역으로 480만명, 3등은 홍대로 473만명이 이용을 했다. 회사가 있는 구로디지털단지역은 5등으로 357만명이 승하차를 했다. 다음 역들을 보아도 대체로 우리가 알고 있는 유명한 역들이 상위권에 랭크돼 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;001 562 2호선_강남
002 480 2호선_잠실(송파구청)
003 473 2호선_홍대입구
004 399 2호선_신림
005 357 2호선_구로디지털단지
006 350 2호선_신도림
007 347 2호선_삼성(무역센터)
008 326 3호선_고속터미널
009 315 1호선_서울역
010 301 2호선_을지로입구
011 297 경부선_영등포
012 288 2호선_선릉
013 287 2호선_서울대입구(관악구청)
014 285 2호선_신촌
015 274 1호선_종각
016 271 2호선_역삼
017 270 2호선_강변(동서울터미널)
018 270 4호선_혜화
019 267 2호선_건대입구
020 263 2호선_사당
021 253 4호선_명동
022 252 4호선_수유(강북구청)
023 251 5호선_광화문(세종문화회관)
024 241 경부선_수원
025 240 3호선_양재(서초구청)
026 233 3호선_연신내
027 227 경인선_부천
028 227 7호선_가산디지털단지
029 223 경인선_부평
030 221 2호선_교대(법원.검찰청)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음은 버스를 기준으로 살펴보았다. 같은 기간 2016년 12월 데이터로 순번, 정류장ID, 만단위 승하차 인원, 역이름이다. 정류장ID는 네이버 지도를 이용하면 해당 역의 위치가 어디인지 검색된다. 버스는 미아사거리와 수유역이 1, 2등을 차지했다. 강남역은 3등에 54만명, 11위에 46만명이, 구로디지털단지는 4등에 53만명, 6등에 51만명이 랭크됐다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;001 09012 064 미아사거리역
002 09004 061 수유역.강북구청
003 22012 054 지하철2호선강남역
004 17014 053 구로디지털단지역환승센터
005 22020 051 고속터미널
006 21001 051 구로디지털단지역
007 09011 049 미아사거리역
008 22019 048 고속터미널
009 06015 047 청량리역환승센타
010 24146 046 잠실역.롯데월드
011 22011 046 지하철2호선강남역
012 09013 045 수유(강북구청)역
013 08008 045 돈암사거리.성신여대입구
014 19112 044 경방타임스퀘어.신세계백화점
015 14015 043 홍대입구역
016 21148 040 신림사거리
017 08010 039 삼선교.한성대학교
018 24138 037 잠실역.롯데월드
019 06019 037 청량리역환승센터
020 21350 037 신림사거리.신림역
021 14016 036 홍대입구역
022 11283 035 석계역1번출구A
023 17001 035 신도림역
024 21916 034 신림역4번출구
025 17002 034 신도림역
026 21117 034 신림사거리.신림역
027 08007 033 돈암사거리.성신여대입구
028 02140 032 롯데백화점
029 24132 032 잠실역8번출구
030 13028 032 홍제역&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;상기 데이터로 볼 때 우리가 얘기했던 구로디지털단지가 강남, 홍대 수준의 유동인구를 가지고 있다는 말은 실제 사실인 것으로 보인다. 압구정과 신촌이 죽었다는 것도 어느 정도 사실인 것으로 보인다. 번외로 신기했던 점은 전혀 몰랐던 수유역이 사람이 많다는 점과 신림역은 알았지만 생각외로 많다는 점 정도인 것 같다. 시간 나면 장기 데이터를 토대로 추계를 뽑아보면 더 재밌을거 같기도 하다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] CES 2017 DAY #3]]></title><description><![CDATA[미국시간 2017.01.06 14:00 pm - 20:00 pm 전날의 여파로 모두가 늦잠을 잤다. 그나마 S만 일찍 일어났다. S가 네 번 Y와 J를 깨웠지만 그들은 너무 깊이 잠든 상태였다. TKS가 먼저 CES를 구경하로 떠났다. S…]]></description><link>https://jiniya.net/ng/2017/01/ces-2017-day-3/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/01/ces-2017-day-3/</guid><pubDate>Wed, 04 Jan 2017 12:30:01 GMT</pubDate><content:encoded>&lt;h3&gt;미국시간 2017.01.06 14:00 pm - 20:00 pm&lt;/h3&gt;
&lt;p&gt;전날의 여파로 모두가 늦잠을 잤다. 그나마 S만 일찍 일어났다. S가 네 번 Y와 J를 깨웠지만 그들은 너무 깊이 잠든 상태였다. TKS가 먼저 CES를 구경하로 떠났다. S는 먼저 간다고 일어나면 연락 달라는 라인 메시지를 남기고 떠났다. Y와 J가 그것을 본 것은 오후가 되어서였다.&lt;/p&gt;
&lt;p&gt;오후에 일어난 Y와 J는 어짜피 늦었다는 생각에 급하게 굴지는 않았다. 씻고 준비한 다음 1층에서 아점으로 라면을 먹기로 했다. 컵라면이 없어 끓인 라면 두개를 했다. 계란도 있어 두 개를 넣었다. 햇반도 두 개 데우고, 김과 참지를 꺼냈다. Y는 차려진 한 상을 보면서 여기가 베가스인지 판교인지 알기가 힘들다는 생각을 했다. 라면을 먹고 J가 우버를 불렀다. 도착한다고 해서 밖에서 기다렸는데 기사가 취소를 해버렸다. 다시 부른 사이 가스 아저씨가 와서 그 집 가스 미터기를 보여줄 수 있냐는 말을 건낸다. 대략 무슨 말인지는 알겠지만 그에게 우리 상황을 설명하기는 쉽지 않았다. 버벅대는 영어로 힘들게 이것 저것 이야기한다. 결국 그는 포기하고 돌아간다. 조금 있다 우버가 도착했고, 그걸 타고 컨벤션 센터로 이동했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d03_01.jpg&apos; data-alt=&apos;Figure 1. 어제 아껴 놓았던 사우스 관&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1b8914df3b859cc8aac76a6c65837b61/ba98e/ces_2017_d03_01.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAWAQEBAQAAAAAAAAAAAAAAAAADAAL/2gAMAwEAAhADEAAAAW1u81TbNmjej0Yxq2Jlf//EABsQAQEAAgMBAAAAAAAAAAAAAAIBAxAAESIh/9oACAEBAAEFAoPOsqTMSl7N5kMgXlXIe3fj1//EABcRAQEBAQAAAAAAAAAAAAAAAAEAERD/2gAIAQMBAT8BwsZOf//EABgRAQEAAwAAAAAAAAAAAAAAAAEAEBES/9oACAECAQE/ARbqHWP/xAAaEAACAgMAAAAAAAAAAAAAAAABEAIxADJB/9oACAEBAAY/AiTTlyICsPXC/wD/xAAdEAEAAwABBQAAAAAAAAAAAAABABExIRBBUXGR/9oACAEBAAE/IbeGBNlQArAIYHIGs+0VHmIJuqY7kX3E2nc9P//aAAwDAQACAAMAAAAQEPiO/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQEQ/9oACAEDAQE/EKRklz//xAAWEQEBAQAAAAAAAAAAAAAAAAAAESH/2gAIAQIBAT8QrqEjX//EAB4QAQACAgMAAwAAAAAAAAAAAAEAESExQWGBELHR/9oACAEBAAE/EN8jTtqUDefjS9iLa3hfyDkNqulrzcwQvH3Co2imPOwEOdxA9iC5ujiZCZbcsMk//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 어제 아껴 놓았던 사우스 관&apos; title=&apos;&apos; src=&apos;/static/1b8914df3b859cc8aac76a6c65837b61/ba98e/ces_2017_d03_01.jpg&apos; srcset=&apos;/static/1b8914df3b859cc8aac76a6c65837b61/8ccab/ces_2017_d03_01.jpg 190w,
/static/1b8914df3b859cc8aac76a6c65837b61/ba98e/ces_2017_d03_01.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 어제 아껴 놓았던 사우스 관&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이미 너무 늦었기 때문에 사우스 관을 다 보기는 힘들어 보였다. 그래서 애초에 다 보는 것은 포기하고 볼 수 있는 만큼만 보겠다는 생각으로 돌아 다녔다. DJI 부스가 컸다. 드론계의 애플이라 불리는 중국 회사. 하지만 부스가 크게 감흥은 없었다. 그저 접어지는 들고다니기 편한 드론이 있다는 정도? 그렇게 부스를 보다가 M을 만났다. M을 만나 조금 더 구경을 하고는 밖으로 나왔다. M은 DJI 보다 달걀 모얌으로 생긴 드론 팜플렛을 보여주며 이게 더 인상 깊었다는 이야기를 했다. 그러면서 오늘 아침 이야기를 했는데 정말 황당했다. 그가 타고오는 모노레일의 같은 칸을 T와 K와 S가 탔다는 것이었다. 그러면서 만나도 어떻게 그렇게 만나냐며 너스레를 떤다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d03_02.jpg&apos; data-alt=&apos;Figure 2. DJI의 접히는 드론. 접어서 들고다니기가 편하다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6cfc1ed7504399edea540a53ff212b29/7fbea/ces_2017_d03_02.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUDBAb/xAAUAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAFfLVfjngB//8QAGxAAAgMAAwAAAAAAAAAAAAAAAgMAAREEEhP/2gAIAQEAAQUCRVEbOOQzMiz6G4q8s2f/xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAwEBPwFX/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERMRIhQVH/2gAIAQEABj8CxfT0sWhubJP/xAAaEAACAwEBAAAAAAAAAAAAAAABEQAhMVFh/9oACAEBAAE/IREiGZ2G8yEiS1wxyQ2JiIBRhecOf//aAAwDAQACAAMAAAAQqC//xAAWEQEBAQAAAAAAAAAAAAAAAAAAAUH/2gAIAQMBAT8QSYf/xAAVEQEBAAAAAAAAAAAAAAAAAAABAP/aAAgBAgEBPxCUv//EABwQAAMBAAIDAAAAAAAAAAAAAAERIQAxQWFxkf/aAAgBAQABPxDuyJIRVcUbZIF+frEixJEAWEsDPheHUKSA98cXV0MMW//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 2. DJI의 접히는 드론. 접어서 들고다니기가 편하다.&apos; title=&apos;&apos; src=&apos;/static/6cfc1ed7504399edea540a53ff212b29/7fbea/ces_2017_d03_02.jpg&apos; srcset=&apos;/static/6cfc1ed7504399edea540a53ff212b29/8ccab/ces_2017_d03_02.jpg 190w,
/static/6cfc1ed7504399edea540a53ff212b29/ea4c8/ces_2017_d03_02.jpg 380w,
/static/6cfc1ed7504399edea540a53ff212b29/7fbea/ces_2017_d03_02.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 2. DJI의 접히는 드론. 접어서 들고다니기가 편하다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;J와 M과 Y가 기다리고 있는 장소는 어제 그곳이다. 버스정류장 벤치. J가 라인으로 위치를 보낸다. 조금 있다 S가 도착했다. K와 T를 물으니 중간에 헤어져서 모르겠다고 한다. 조금 있다 메시지가 하나 더 왔다. KT는 샤오미 부스에 있는데 조금 더 보다가 이동하겠다는 내용이다. JYMS는 모노레일을 타고 이동한다. 어제와 다르게 너무나 사람이 많고 줄은 개미가 기어가는 속도로 줄어들었다. 마칠 시간에 사람이 몰려서 그런 것 같다. 힘들게 들어가서 그들이 내린 곳은 센터에서 한 정거장 옆에 있는 LINQ 역이었다. Y는 이상한 생각이 든다. LINQ 호텔인데 자꾸 프로그래밍 할 때 만난 LINQ가 떠올랐기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d03_03.jpg&apos; data-alt=&apos;Figure 3. LINQ 역과 카지노 입구 사이에 있던 NOOK, 나름 단열처리된 컵이다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/edbd8d0a1dee51b51c544f692e2c8250/ba98e/ces_2017_d03_03.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMFAQT/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAQID/9oADAMBAAIQAxAAAAFDevm56CgKvJG2ViIH/8QAHBAAAgIDAQEAAAAAAAAAAAAAAQIAAxESIRMx/9oACAEBAAEFAkSoONDFXSFBrRWQeQWIwyBPRZV9r7ZjM//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/ASH/xAAgEAABAgYDAQAAAAAAAAAAAAABACECEBExQVESE1Jx/9oACAEBAAY/Aic+dKnW31Uhsiz7R5OspiJXEowdS//EABwQAQADAAMBAQAAAAAAAAAAAAEAESExUYFBkf/aAAgBAQABPyFI2865C0slQ01exuArHBR1L6fiWBHsPoD2VcyJQrLITaAkiNM//9oADAMBAAIAAwAAABDXzz//xAAYEQACAwAAAAAAAAAAAAAAAAAAERAhMf/aAAgBAwEBPxDKGOP/xAAWEQEBAQAAAAAAAAAAAAAAAAARABD/2gAIAQIBAT8QYwX/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAxQSFhcYGR/9oACAEBAAE/EEHiTQB57/c7MatEu+uVRsj5KXl7gooIARxg0Dy04CSXrECd0mNd9JiyU/NxyxVjDMiR4gpiMa63n//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 3. LINQ 역과 카지노 입구 사이에 있던 NOOK, 나름 단열처리된 컵이다.&apos; title=&apos;&apos; src=&apos;/static/edbd8d0a1dee51b51c544f692e2c8250/ba98e/ces_2017_d03_03.jpg&apos; srcset=&apos;/static/edbd8d0a1dee51b51c544f692e2c8250/8ccab/ces_2017_d03_03.jpg 190w,
/static/edbd8d0a1dee51b51c544f692e2c8250/ba98e/ces_2017_d03_03.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 3. LINQ 역과 카지노 입구 사이에 있던 NOOK, 나름 단열처리된 컵이다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;LINQ 역에 내려서 호텔로 이동하는 연결 지점에 있는 NOOK 커피숍에 잠시 앉는다. 아메리카노를 시킨다. 그즈음 KT도 나왔다는 메시지를 보냈다. 하지만 JYMS가 있는 곳은 로밍 인터넷이 터지지 않는 지점이다. J가 멀리 돌아가서 인터넷 되는 곳에서 NOOK 커피숍 위치를 알려주고 돌아온다. 커피 잔에 두르는 골판지를 가지러 갔던 M이 돌아오면서 커피잔이 특수 처리돼서 필요 없다는 이야기를 들었다며 이래서 미국 촌놈이라는 이야기를 듣는다며 수줍어 한다. 그제서야 J, Y, S도 커피잔을 다시 만져본다. 잔이 이중으로 되어 있다. 그리고 그 사이에 공기가 들어가 있다. 어떤게 효과적인지는 모르겠지만 Y는 골판지 만큼 그 이중 공기 단열이 효과적인 것은 아니라는 생각을 한다.&lt;/p&gt;
&lt;p&gt;잠시후 KT가 도착했다. 똑같이 커피를 시킨다. 둘러앉아 남은 일정에 대해서 이야기를 한다. J와 M이 베가스에 왔으니 카지노를 한 번 하고 가자고 한다. Y도 그러자고 한다. 하지만 KTS는 신통찮은 분위기다. 마지못해 동의해서 차가 있는 플라밍고 근처에서 카지노를 하기로 한다. 그렇게 플라밍고에 도착할 무렵 K는 T와 S에게 대관람차를 타자는 제안을 한다. 그리고 JYM에게는 카지노를 하고 만나자고 제안한다. JYM도 동의한다. J, Y, M은 플라밍고 카지노로 들어갔다. J가 카지노로 들어가며 우리만 노름꾼이 된 것 같다는 불평을 한다. 잠시 방황하다 빈 자리가 있는 룰렛 테이블에 앉았다. 각자 100불씩 칩을 바꾸고 플레이를 한다. 모두가 처음이기에 베팅 실수가 조금 발생한다. 특히 Y가 딜러의 잔소리를 많이 듣는다. 3번 정도 실수 후에 룰을 완전히 알 수 있었다. 룰렛의 인과 아웃이 있는데 인은 개별 숫자가 있는 곳에 베팅을 아웃은 숫자 덩어리에 (홀짝 같은) 베팅을 하는 것이었다. 인, 아웃은 각각 최소 베팅 금액이 10불이었다. 인에서는 10불을 나눠서 여러개의 숫자에 걸 수 있고, 아웃은 무조건 한 칸에 10불 이상을 걸어야 했다. 이게 룰의 전부였다. 물론 걸쳐서 놓는 것들도 있었는데 그런 고급 베팅을 사용하지는 않았다. 다 초보였기 때문이다.&lt;/p&gt;
&lt;p&gt;크게 JYM의 전략은 세가지로 나뉘었다. J는 매턴 10불울 두개씩 쪼개어 다섯 군데의 개별 숫자에 걸었다. 이렇게 하다 하나가 걸리면 35배를 받게 된다. 즉 5군데 중에 한 곳이 맞으면 72불을 받게 된다. 10불얼 베팅했으니 이득이 62불이 된다. 베팅에 실패하면 10불을 잃는다. 가능성은 룰렛 숫자가 38개라 5/38이다. Y는 어제 본 사람과 유사한 전략을 택했다. 아웃의 세 덩어리로 나뉜 지점의 두 곳에 10불씩 베팅을 하는 것이다. 이렇게 해서 한 곳이 걸리면 3배인 30분을 준다. 베팅하지 않은 곳이 걸리면 20불을 잃는다. 당첨 확률은 24/38이다. M은 무작위 전략을 썼다. 홀짝에도 걸었다가, 검빨에도 걸었다가 개별 숫자에도 걸었다.&lt;/p&gt;
&lt;p&gt;생각보다 그 과정은 단순했다. Y는 처음에는 20불씩 거는 것에 약간 긴장했으나 몇 턴이 지나서는 더이상 돈을 의식하지 않았다. 그저 장난감 칩을 가지고 논다는 생각이었다. 의외로 J가 잘 맞춘다. M은 어떻게 맞추냐며 부러워한다. 그의 칩이 가장 빠른 속도로 사라졌기 때문이다. Y의 베팅은 큰 이득도 없지만 큰 손해도 없는 그런 전략이었다. Y는 대체로 차곡차곡 경기를 했고 이득이 생겼을 때 개별 숫자에 베팅해 칩을 불렸다. 그렇게 한시간 넘게 게임을 했고 Y는 150불 가량을 땄고, J와 M은 잃었다. 결국 카지노는 Y가 딴 돈보다 더 따서 손해는 아니었다. 다 아는 사실이지만 결국은 모두 카지노가 딴다. 룰렛의 경우 0과 00 때문에 대체로 많은 베팅이 카지노에게 유리하게 세팅돼 있다.&lt;/p&gt;
&lt;h3&gt;미국 시간 2017.01.06 20:00 pm - 2017.01.07 03:00 am&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d03_07.jpg&apos; data-alt=&apos;Figure 4. 저녁을 먹은 야드 하우스 입구&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/42797c7ee3ea300b7f59875054fb6bf7/7fbea/ces_2017_d03_07.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABt5DU3MQj/8QAGRABAAMBAQAAAAAAAAAAAAAAAQACAxES/9oACAEBAAEFAtOS1Fnjg62Usxus/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8BR//EABoQAAICAwAAAAAAAAAAAAAAAAABEBEhMUH/2gAIAQEABj8Ca7GS42f/xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhMUFR/9oACAEBAAE/Iaz5u1GLDh5BhSP86VFGsS6n/9oADAMBAAIAAwAAABB/P//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxBNIG//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQIBAT8QHG2f/8QAHBABAQACAgMAAAAAAAAAAAAAAREAITFhccHw/9oACAEBAAE/EObU2Qk94SCgl+d4Q70p4zUw0zUwDZ1JdYUXUTnP/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 4. 저녁을 먹은 야드 하우스 입구&apos; title=&apos;&apos; src=&apos;/static/42797c7ee3ea300b7f59875054fb6bf7/7fbea/ces_2017_d03_07.jpg&apos; srcset=&apos;/static/42797c7ee3ea300b7f59875054fb6bf7/8ccab/ces_2017_d03_07.jpg 190w,
/static/42797c7ee3ea300b7f59875054fb6bf7/ea4c8/ces_2017_d03_07.jpg 380w,
/static/42797c7ee3ea300b7f59875054fb6bf7/7fbea/ces_2017_d03_07.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 4. 저녁을 먹은 야드 하우스 입구&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;K가 라인을 보내왔다. 배고프다고 밥 먹자는 이야기였다. JYM 모두 약간 아쉬워 하는 분위기였지만 늦지 않게 나왔다. 나와서 KTS가 있는 곳으로 왔더니 식당 앞에서 대기하고 있었다. JYM은 괜히 일찍 나왔다는 생각을 한다. 몇 판 더 할껄. Y는 그래서 도박이 무섭다고 느낀다. 사람은 의외로 쉽게 중독된다. 저녁은 야드 하우스라는 체인점에서 먹었다. 에일 맥주가 다양하게 있는 집이었다. KT가 주문을 했는데 많이 와 본 사람들 답게 일반적으로 좋아하는 메뉴로 식탁을 가득 채웠다. 배고픈 일행은 허겁지겁 먹기 시작한다. 그렇게 30분 가량 먹고 나니 이제는 모두 배가 불러 더이상 못먹는 상태가 되었다. 하지만 남은 음식은 아직도 많다. 화제 거리가 떨어질 무렵 티비 켜진 농구경기에 모두 집중했다. 멤피스와 다른 곳이 하고 있는 경기였는데 10점차가 넘게 나는 경기를 멤피스가 역전했다. 몇초 남지 않은 사이에 승부가 바뀌는 경기라 보고 있으면 짜릿한 맛이 있었다. K가 오늘은 타이밍이 좋은 것 같다는 이야기를 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d03_04.jpg&apos; data-alt=&apos;Figure 5. 야드 하우스의 시그니처 하프 야드 맥주, 길이가 하프 야드다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/19832a91caff4ca35dbdefcd88b9cdd9/ba98e/ces_2017_d03_04.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEDAgT/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/9oADAMBAAIQAxAAAAGSi0IkMtuVMdtHIVH/xAAdEAACAgEFAAAAAAAAAAAAAAABAgADIQQQERIi/9oACAEBAAEFAksjMhAVSKMzr4PMqGFZlU6WyDYXWAf/xAAYEQACAwAAAAAAAAAAAAAAAAAAAQIQIf/aAAgBAwEBPwGlEw//xAAZEQABBQAAAAAAAAAAAAAAAAAAAQIQESH/2gAIAQIBAT8BuFcaf//EABwQAQACAQUAAAAAAAAAAAAAAAEAESECECAxUf/aAAgBAQAGPwKPcM1HbMaaYnvCjWz/xAAdEAEAAgMBAAMAAAAAAAAAAAABABEhMUFREGGR/9oACAEBAAE/IeP7F4s+6ilXDswJzyG2tMtfZBsLksxAaUxDdjf38XUoQBP/2gAMAwEAAgADAAAAEN8Ew//EABgRAQADAQAAAAAAAAAAAAAAAAEAESEQ/9oACAEDAQE/EAamQK3j/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERUf/aAAgBAgEBPxBisZSbP//EAB0QAQEAAgIDAQAAAAAAAAAAAAERADEhQVFhcYH/2gAIAQEAAT8QFNU8C8esgQuxw/O8TKHkFu95JCqaVMBha6s6s59ZbhOJLJhLhAqfeO8RTYoWHrxmqEGhzUzZ8wtwqC6z/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 5. 야드 하우스의 시그니처 하프 야드 맥주, 길이가 하프 야드다.&apos; title=&apos;&apos; src=&apos;/static/19832a91caff4ca35dbdefcd88b9cdd9/ba98e/ces_2017_d03_04.jpg&apos; srcset=&apos;/static/19832a91caff4ca35dbdefcd88b9cdd9/8ccab/ces_2017_d03_04.jpg 190w,
/static/19832a91caff4ca35dbdefcd88b9cdd9/ba98e/ces_2017_d03_04.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 5. 야드 하우스의 시그니처 하프 야드 맥주, 길이가 하프 야드다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;밥먹고 나오니 모두 배가 불렀다. 뭘하지라고 잠시 고민하던 시점에 J와 M이 룰렛을 하자는 이야기를 한다. K는 처음에는 내키지 않는 분위기 였으나 이내 따라 나선다. 구경을 하다 테이블이 없어서 카지노를 나가려던 즈음 빈 테이블이 하나 생겼다. 그게 시작이었다. JMK가 앉아서 플레이를 하고, YTS는 구경하다 방해될까봐 여기저기를 돌아다녔다. 앉을 때가 없어 카지노 안에 있는 이상한 펍 같은 곳을 들어갔다. 음악이 나오고 춤추는 사람도 더러 있었다. 자리는 많이 비어 있었다. Y는 음악이 너무 시끄러웠다. 그리고 T와 S가 자신이 없는게 더 편할거라는 생각을 했다. Y는 괜히 방해꾼이 된듯한 느낌이다. 그저 기다리고 있어야 하는 그들이 안스럽기도 했다. 그래서 JMK가 플레이하는 곳에 가서 TS가 놀다 오겠다는 이야기를 전한다. K는 그러라고 한다. Y는 라인으로 T에게 그렇게 전한다. 그리고 Y도 그 룰렛 판에 앉는다. 이미 JMK 모두 상당량을 잃은 상태였다. Y는 100불을 교환하고 아까와 같은 전략으로 플레이를 한다. 하지만 이번엔 광속으로 모두 잃는다. 다시 100불을 교환한다. 조금씩 따기 시작했다. 그즈음 100불 칩은 옆으로 분리해서 두고 딴 칩으로만 플레이를 한다.&lt;/p&gt;
&lt;p&gt;한참 시간이 지났다. T와 S가 왔다. 기다리다 지친 분위기다. K와 J가 T와 S에게 같이 하라며 100불씩을 준다. 각자 그걸 칩으로 바꿔서 참가한다. Y는 아직도 기계적으로 베팅하며 잃었다 땄다를 반복한다. 그즈음 M은 약간 잃었고, J는 제법 잃었고, K는 더 잃었다가 다시 따는 중이었다. T와 S가 칩을 바꿔 베팅을 시작한다. T가 처음 몇 판을 크게 딴다. Y는 옆에서 땄을 때 잃어나는게 용자라는 말을 전한다. 그는 아직도 본전을 힘겹게 되찾고 있는 중이었다. S는 광속으로 칩을 잃었다. J, M, S는 추가로 칩을 더 바꾸었다. 그렇게 하기를 한참. T가 칩을 캐시로 바꾼다. 별로 남지 않아서 Y가 아까 바꾸면 용자였다고 이야기를 하자 손에 비싼 칩을 보이며 그래도 조금 땄다는 이야기를 한다. 그즈음 K는 제법 크게 따고 있었다. S는 칩을 거의 다 잃어갈 무렵 Y를 따라 베팅하기 시작했다. M은 여전히 무작위로 베팅했다. 칩이 덜 줄어들기 위해서 그는 베팅을 잘 하지 않고 구경하는 판이 많았다. 조금 있다 J도 칩을 모두 잃고 일어났다. S가 그 뒤를 이었다. K, Y, M이 남았다. Y는 거의 본전을 찾아가고 있었다. Y가 본전이 되었을 때 K가 기다리는 사람도 지치니 5판만 하고 가자고 했다. Y는 사실 그때 멈추고 싶었지만 그러기도 쉽지 않았다. 그즘 M은 Y를 따라 베팅해야 겠다는 이야기를 한다. 그렇게 마지막 5판이 시작된다. M은 Y를 따라 베팅하다 달아 세번을 잃는다. 그는 크게 베팅했기에 손실이 훨씬 컸다. 그러다 Y가 딴 네번째 판에 같이 땄고 그는 크게 걸어서 크게 딴다는 이야기를 했다. 하지만 그건 옳은 이야기는 아니었다. 그가 3판에 잃은 칩은 120불이었고, 그가 4번째 판에 딴 칩은 60불이었기 때문이다. 그는 결국 60불을 잃은 것이었다. 마지막 5판 Y는 손실을 줄이기 위해 개별 칩에 10불만 베팅했다.&lt;/p&gt;
&lt;p&gt;칩을 정산해서 나왔다. 그때가 벌써 새벽 3시였다. K는 250불을 땄고, Y는 150불을 땄다가 50불을 잃어서 100불을 땄고, T는 50불을 땄다. 하지만 나머지 세 사람이 카지노에서 잃은 돈은 그보다는 훨씬 많았다. 결국은 당연하게도 하우스가 이기는 게임이다. 즐기러 간 자리였지만 즐기는 비용은 그리 싸진 않았다. 아무렇게나 플레이한다면 정말 10분만에 100불을 잃은 것은 아무것도 아니었다. 하지만 K는 반대로 자신감이 붙었다. 한 번 해서 이겼기 때문이다. 돈을 걸고 한다는 것이 묘한 흡입력이 있었다.&lt;/p&gt;
&lt;p&gt;집에 도착해서 T와 S는 광속으로 셧다운 되었고, K와 J가 담배피는 사이 Y는 옷을 갈아 입었다. 출출하던 그는 K와 J에게 라면을 먹겠냐고 물었고 K는 콜을, J는 다이를 했다. 공교롭게도 남은 라면은 너구리 컵라면 하나에 끓이는 참깨라면과 신라면이 하나씩 있었다. K는 참깨와 신라면을 섞어서 끓이자고 했다. 섞어서 끓이고 남은 계란까지 모두 넣었다. 햇반 두개에, 김 하나, 참치 하나까지 그 새벽에 Y와 K는 그걸 나눠먹고는 잠들었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] CES 2017 DAY #2]]></title><description><![CDATA[미국 시간 2017.01.05 08:00 am - 2017.01.05 21:00 pm 잠에서 가장 먼저 깬 것은 S였다. 전날 다른 일행들이…]]></description><link>https://jiniya.net/ng/2017/01/ces-2017-day-2/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/01/ces-2017-day-2/</guid><pubDate>Wed, 04 Jan 2017 12:20:01 GMT</pubDate><content:encoded>&lt;h3&gt;미국 시간 2017.01.05 08:00 am - 2017.01.05 21:00 pm&lt;/h3&gt;
&lt;p&gt;잠에서 가장 먼저 깬 것은 S였다. 전날 다른 일행들이 8시 즈음 일어나서 준비를 하자는 얘기를 곧이 곧대로 믿었기 때문이다. 심지어 더욱 놀라운 사실은 그녀는 다른 사람들이 일어나지도 않았는데 아침으로 라면을 준비했다는 점이다. 안타깝게도 그녀를 제외한 다른 사람들은 모두 꿈나라를 헤매고 있었기에 그 라면은 변기가 모두 먹어치웠다. 그녀는 단톡방에 푹 주무시라는 이야기를 올리고는 본인도 다시 잠을 청했다.&lt;/p&gt;
&lt;p&gt;Y가 잠에서 깬 시간은 9시였다. 화장실을 갔다와서 S의 메시지를 본 Y는 다시 잠에 들었다. 일행이 실제로 일어난 시간은 10시가 지났을 무렵이었다. 아침을 먹을지를 잠시 고민하다 K가 배고픈 사람이 없으면 그냥 커피나 먹자는 이야기를 했다. 자연스럽게 근처 스타벅스로 이동했다. K가 앱으로 주문을 받았다. Y가 먼저 아메리카노를 불렀고, J도 그걸 먹겠다고 했고, T도 동참했다. S는 라떼를 선택했다. K는 라떼가 어느 메뉴에 있냐며 운전 중이던 T에게 물었고 T는 몇 가지 추측성 답을 했다. 어렵게 메뉴를 찾은 K는 라떼를 시키고 본인의 아메리카노도 추가했다. 하지만 안타깝게도 주문은 큰 의미가 없었다. 왜냐하면 우리가 간 스타벅스는 드라이브 스루가 있었기 때문이다. 결국 앱 주문은 무시하고 드라이브 스루로 주문했다. 최종적으로 T가 주문한 메뉴는 아메리카노 셋, 라떼 둘이었다. T의 속마음을 조금 알 수 있는 대목이다.&lt;/p&gt;
&lt;p&gt;T가 원래 베가스는 주차가 무료였는데 최근 변경되어서 MGM 계열은 주차료를 받는다는 이야기를 한다. 그래서 MGM계열이 아닌 플라밍고 주차장에 차를 세우고 모노레일을 타자고 K에게 묻는다. K는 그러라고 한다. 주차장에 차를 세우고 모노레일을 타러 가는 사이 잠시 길을 헤맸다. T가 호텔 가드에게 물어서 정확한 방향을 알아낸다. 모노레일에 도착해 일행 모두 2일치 모노레일 프리패스를 끊었다. 베가스 모노레일 정거장은 몇 개 없었다. 그들은 2정거장 다음에 있는 컨벤션 센터역으로 향했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d02_01.jpg&apos; data-alt=&apos;Figure 1. CES 2017 입구, 사람 진짜 많음&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/7cc5450c976adb1315472605faa7387c/7fbea/ces_2017_d02_01.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFA//EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAFRlPeKRLK//8QAGhABAQACAwAAAAAAAAAAAAAAAQIAAxEhIv/aAAgBAQABBQLXTNVa5O8g46oDDzn/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAdEAABAgcAAAAAAAAAAAAAAAAAARECEBIzUXKh/9oACAEBAAY/AsF3pSsoNhnc/8QAGxAAAgMBAQEAAAAAAAAAAAAAAAERITFBUXH/2gAIAQEAAT8hoDNwy1ZHhHLac18GUMo56KkfQz//2gAMAwEAAgADAAAAEHgP/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABcRAQADAAAAAAAAAAAAAAAAAAABESH/2gAIAQIBAT8QjFv/xAAcEAEAAgMAAwAAAAAAAAAAAAABABEhMUFRYZH/2gAIAQEAAT8QKusKqWEPRltIZfCHgXpQQOEGrTRR8skGi2ArRGKBdSe2f//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. CES 2017 입구, 사람 진짜 많음&apos; title=&apos;&apos; src=&apos;/static/7cc5450c976adb1315472605faa7387c/7fbea/ces_2017_d02_01.jpg&apos; srcset=&apos;/static/7cc5450c976adb1315472605faa7387c/8ccab/ces_2017_d02_01.jpg 190w,
/static/7cc5450c976adb1315472605faa7387c/ea4c8/ces_2017_d02_01.jpg 380w,
/static/7cc5450c976adb1315472605faa7387c/7fbea/ces_2017_d02_01.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. CES 2017 입구, 사람 진짜 많음&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;센터에 내려서 CES 입구에서 담배를 피우며 서 있었다. J가 CES에 참관한다는 이야기를 듣고 미국에 있던 M도 합류하겠다고 했기 때문이다. 둘은 CES 입구에서 보기로 했다. M이 도착하지 않아 J의 일행은 적지 않은 시간을 입구에서 보냈다. 한참 후에 M이 도착했고 일행은 모두 M과 인사했다. J를 제외한 모든 사람이 M을 처음 보는 자리였다. Y는 J에게서 M 이야기를 여러번 들었지만 실제로 만나는 것은 이번이 처음이었다.&lt;/p&gt;
&lt;p&gt;CES 입구에서는 표와 짐을 검사하고 있었다. 총기 소지가 자유로는 미국은 대부분의 전시회 입구에서 가방 검사를 한다. 폭탄이나 총같은 것들이 있는지 체크하는 것 같다. 하지만 대체로 형식적인 검사다. 가방 검사를 하던 사이 Y는 잠시 일행과 떨어졌다. 다른 일행은 모두 먼저 검사하고 입구에 들어간 상태였고 Y는 늦게 들어갔다. 약간 헤대마 일행이 모여있는 곳이 합류했다. 그쪽 입구에 가장 먼저 위치한 것은 LG 부스였다. LG 부스인만큼 사람이 정말 많았다. 자연스럽게 일행은 둘로 쪼개졌다. K와 T는 K의 관심사가 있는 곳으로 같이 이동했고, J, M, Y, S는 붙어서 LG관 구경을 시작했다.&lt;/p&gt;
&lt;p&gt;사람이 너무 많아서 제대로 볼 수 없었다. 사람들이 TV 앞에서 연신 사진을 찍고 있었다. 베스트 오브 베스트에 선정된 그 초박형 TV였다. 어찌나 얇은지 아크릴판에 붙여 놓았는데 진짜 거짓말 좀 많이 보태서 껌딱지 두께 수준이었다. S가 대단한 것을 발견한 것처럼 소리친다. 와 이거 진짜 얇아요. 정말 소리칠만큼 얇았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d02_02.jpg&apos; data-alt=&apos;Figure 2. 우리가 낚인 보쉬 솜사탕 로봇. 솜사탕 만들어서 사람들에게 준다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6ad30669f7c81b8793cf3d9715161708/ba98e/ces_2017_d02_02.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAARbWBYOQVJChPriUTL//xAAdEAEBAAEEAwAAAAAAAAAAAAACAQMABBESITEy/9oACAEBAAEFArknF6qxzHONLFYiSoiceNZO0LQ1uPg+pPH/xAAWEQADAAAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8BI//EABYRAQEBAAAAAAAAAAAAAAAAABEAEP/aAAgBAgEBPwFnf//EAB8QAAIBAgcAAAAAAAAAAAAAAAERAAIQEiExQVFhkf/aAAgBAQAGPwJLO2F26mp8hO/MVJLiFLlUFv/EAB4QAAIDAAEFAAAAAAAAAAAAAAABESExcVFhgaHB/9oACAEBAAE/IXX4zJVWlnkTo67Ck1RD7StE8e0BJ1Rch9yNlYhBVdT0/oqVO6KhR//aAAwDAQACAAMAAAAQcAW+/8QAFxEBAAMAAAAAAAAAAAAAAAAAABEhYf/aAAgBAwEBPxBBin//xAAZEQADAAMAAAAAAAAAAAAAAAAAAREhMWH/2gAIAQIBAT8Q0HyYjbHaf//EABwQAQADAQEAAwAAAAAAAAAAAAEAESExYUFxkf/aAAgBAQABPxB4aGxFqKAbwp39uADBd7u9uKcS3YGq1URKwhT4e79x+ciFNKOVsVLqRr3kLsIipKNjcAPVkz7GBMBt9NxbUn//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 2. 우리가 낚인 보쉬 솜사탕 로봇. 솜사탕 만들어서 사람들에게 준다.&apos; title=&apos;&apos; src=&apos;/static/6ad30669f7c81b8793cf3d9715161708/ba98e/ces_2017_d02_02.jpg&apos; srcset=&apos;/static/6ad30669f7c81b8793cf3d9715161708/8ccab/ces_2017_d02_02.jpg 190w,
/static/6ad30669f7c81b8793cf3d9715161708/ba98e/ces_2017_d02_02.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 2. 우리가 낚인 보쉬 솜사탕 로봇. 솜사탕 만들어서 사람들에게 준다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그렇게 JYMS 일행은 노스관가 센터관을 쭉 훓어 보기 시작했다. 삼성 부스도 구경을 했다. J는 작년에 왔었기에 올해도 LG가 이긴 거 같다는 이야기를 했다. 일행이 가장 많은 시간을 보낸 곳은 어처구니 없게도 보쉬의 로봇이 있는 코너였다. 가정용 로봇은 아니고 산업용 로봇이었다. 보쉬의 전략에 낚인 것일 수도 있었다. 처음 그들이 본 로봇은 솜사탕을 만들어 주고 있었다. 솜사탕이 나온다는게 신기해서 쳐다보다 로봇이 만든다는 것에 더 놀라웠다. 그러고 이동을 하려고 했으나 마지막 즈음에 주문을 받아서 커피를 타주는 로봇에 재차 낚였다. 거기서 가장 많은 시간을 보냈다. S는 직접 주문을 하기도 했다. 주문하는 곳에 이름을 적고 완료 버튼을 누르면 로봇이 컵을 가져와 서 프린터 앞에서 주문자가 쓴 이름을 프린트하고 커피 머신의 커피가 내려오는 곳에 놓았다. 그리고는 머신으로 커피가 내려오도록 한 다음 다 내려오면 그 컵을 옆에 있는 완료 지점에 위치 시켰다. 그러면 사람이 그 컵을 다시 구경꾼이 있는 테이블위이 올려주면 주문한 사람이 찾아가는 그런 구조였다. 그 산업용 로봇의 핵심 기능 중에 하나로 보쉬는 인간과의 자연스러운 협업이 가능하다는 것을 강조 했기에 사람을 억지로 끼워 넣은 것처럼 보였다. 실상 그 로봇은 사람 없이도 주문자가 있는 테이블에 컵을 가져다 놓을 수 있었기 때문이다. 대체로 그러하듯 JYMS 일행은 모두 일자리가 없어지는 우울한 미래를 상상했다. 우리는 무엇을 해야 할까? 우리의 아이들은 어떤 세상에 살게 될까, 라는 생각을 하면서 나머지 것들을 구경했다.&lt;/p&gt;
&lt;p&gt;그렇게 JYMS 일행은 노스와 센터에 있는 부스를 모두 구경했다. 밖에서 담배를 피우며 버스 정류장에 잠시 앉았다. KT 일행이 어디에 있는지 몰랐기 때문이다. 라인을 보낸다. KT는 벌써 사우스 관이라고 했다. J는 그것도 오늘 보면 내일은 할 것이 없기에 내일 사우스 관을 보자고 했다. YMS도 그러자고 한다. JYMS 일행이 정류장에 앉아서 각자 핸드폰을 하면서 기다리길 한참. KT 일행이 도착했다. 이후 모두 모노레일을 타러 이동했다. M이 표가 없었기에 M이 표 끊기를 기다려 모노레일을 탔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d02_03.jpg&apos; data-alt=&apos;Figure 3. 쉑쉑 버거 입구. 뉴욕꺼라고 뉴욕뉴욕에 있다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a09863dd6dc1e104c662d333ea34c599/7fbea/ces_2017_d02_03.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQD/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAY98SXoBf//EABkQAAIDAQAAAAAAAAAAAAAAAAACAQMSEf/aAAgBAQABBQLWpW1lItUyhyDkH//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAAIBBQAAAAAAAAAAAAAAAAABMQIDESEi/9oACAEBAAY/AjVaWTq82yCCD//EAB4QAAICAAcAAAAAAAAAAAAAAAABESExUWFxoeHx/9oACAEBAAE/IXjKixA4zR0IrcioyuZ6hm//2gAMAwEAAgADAAAAELT/AP/EABYRAQEBAAAAAAAAAAAAAAAAAAARgf/aAAgBAwEBPxCsf//EABcRAQADAAAAAAAAAAAAAAAAAAARIVH/2gAIAQIBAT8Qhev/xAAcEAEAAwACAwAAAAAAAAAAAAABABEhMXFBYfH/2gAIAQEAAT8QSg2XAH7AzfF3BU8nRPQVAG0OqStwOe0U8DrJ/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 3. 쉑쉑 버거 입구. 뉴욕꺼라고 뉴욕뉴욕에 있다.&apos; title=&apos;&apos; src=&apos;/static/a09863dd6dc1e104c662d333ea34c599/7fbea/ces_2017_d02_03.jpg&apos; srcset=&apos;/static/a09863dd6dc1e104c662d333ea34c599/8ccab/ces_2017_d02_03.jpg 190w,
/static/a09863dd6dc1e104c662d333ea34c599/ea4c8/ces_2017_d02_03.jpg 380w,
/static/a09863dd6dc1e104c662d333ea34c599/7fbea/ces_2017_d02_03.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 3. 쉑쉑 버거 입구. 뉴욕꺼라고 뉴욕뉴욕에 있다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;베가스가 처음이 Y와 S를 위해서 메인 스트리트 구경을 하기로 했다. 아침을 먹지 않아 출출한 일행은 점심으로 쉑쉑 버거를 먹기로 했다. MGM 역에서 내려 뉴욕뉴욕으로 걸어갔다. 가는 중간 중간 베가스에 관한 것들이 나오면 K가 설명을 해줬다. MGM의 카지노를 지날 때 J가 사람이 별로 없다는 이야기를 한다. M은 그것도 분위기가 있는 것 같다고 오래된 곳보다는 새로운 곳으로 많이 가서 그런 것 같다는 답변을 한다. 그렇게 이런 저런 이야기를 하며 쉑쉑버거 앞까지 걸어갔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d02_04.jpg&apos; data-alt=&apos;Figure 4. 우리가 주문한 버거. 쫀득한게 맛있었다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2ee26db519e03863dca9eb767a0fbaf1/7fbea/ces_2017_d02_04.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBP/EABUBAQEAAAAAAAAAAAAAAAAAAAID/9oADAMBAAIQAxAAAAGlnmTRAz//xAAZEAADAQEBAAAAAAAAAAAAAAAAARIREzH/2gAIAQEAAQUC5ohFyI16/f/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABYRAAMAAAAAAAAAAAAAAAAAAAEQMf/aAAgBAgEBPwERf//EABsQAAIBBQAAAAAAAAAAAAAAAAAQEQEhMUFR/9oACAEBAAY/AqdL7IWZX//EABoQAQACAwEAAAAAAAAAAAAAAAEAESExQVH/2gAIAQEAAT8hVEOtW4jdSp6ghS8Rbe+xHSOjFaZ//9oADAMBAAIAAwAAABDDP//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMWH/2gAIAQMBAT8QNxf/xAAYEQACAwAAAAAAAAAAAAAAAAAAEQEhMf/aAAgBAgEBPxB9TYz/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhMUFRYf/aAAgBAQABPxBxJVcsgcjEwzRevv6vJapGCslajoqyqTXJlDXPo+MfIpcn/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 4. 우리가 주문한 버거. 쫀득한게 맛있었다.&apos; title=&apos;&apos; src=&apos;/static/2ee26db519e03863dca9eb767a0fbaf1/7fbea/ces_2017_d02_04.jpg&apos; srcset=&apos;/static/2ee26db519e03863dca9eb767a0fbaf1/8ccab/ces_2017_d02_04.jpg 190w,
/static/2ee26db519e03863dca9eb767a0fbaf1/ea4c8/ces_2017_d02_04.jpg 380w,
/static/2ee26db519e03863dca9eb767a0fbaf1/7fbea/ces_2017_d02_04.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 4. 우리가 주문한 버거. 쫀득한게 맛있었다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;T가 주문을 받았다. 잘 몰라서 모두 K가 추천해 주는 메뉴로 통일해서 먹는다. M이 음료로 스트로베리 쉐이크를 시킨다. 그걸 들은 다른 사람도 콜라가 아닌 쉐이크를 시키자 T가 걱정하며 말린다. 엄청 달아서 별로 입에 안 맞을 수 있으니 하나씩 시켜 맛만 보라는 이야기였다. 그렇게 하기로 했다. 이후 메뉴가 나왔을 때 Y는 감탄했다. T가 정말 대단하다는 생각이 들었기 때문이다. 스트로베리는 지나치게 달았다. 한모금 이상 마시기가 어려웠다. T와 같은 잔을 먹는 K도 마찬가지였다. K는 미국 애들은 여기 감자튀김을 찍어 먹는다고 그렇게 먹자고 했다. 그렇게 먹어도 달았다. 결국 Y와 K는 쉐이크를 거의 다 버렸다.&lt;/p&gt;
&lt;p&gt;쉑쉑버거를 먹으면서 어쩌다가 M이 세금 이야기를 꺼냈고 대체로 K와 Y는 관심이 많은 주제였기에 집중해서 이야기가 이어졌다. K는 한국 회사에 근무하지만 미국에서 일하는 관계로 세금을 두 군데에 모두 내고 있다고 한다. 조세 협정이 맺어져서 미국에는 한국에 낸 세금을 제하고 나머지 세금만 낸다고 한다. M이 꺼낸 이야기는 양도 소득세에 대한 근로 소득세 이중 과세에 관한 이야기다. K는 그건 이치에 합당하지 않다는 말을 한다. 왜냐하면 이중 과세가 되기 때문이란다. M은 배당도 똑같이 이중 과세라며 국세청에서 관리하는 리스트에 올라가면 일단 세금을 물리고 그걸 나중에 개인에게 소명하라고 이야기 한다는 말을 한다. 실제로 자기 친구가 그렇게 당했다는 이야기를 붙인다. K 또한 다른 이유로 국세청에 가서 소명한 적은 있지만 지금까지 양도세와 근소세의 이중 과세를 당해서 간 적은 없다고 주장한다. 중간 중간에 최대 주주 및 비상장 법인에 대한 양도세 강화 등이 나왔고 Y는 네이버에 그런 것들을 찾아본다. K가 결과가 어떻게 되었냐고 Y에게 묻는다. Y는 K 말도 일부 맞고 M 말도 일부 맞는 것 같다는 답을 한다. 이중 과세 부분은 K의 말이 맞았고, 최대 주주 및 양도세 강화와 관련된 주장은 M의 말이 맞았다. S와 T는 딴나라 이야기를 듣는 듯한 표정이다.&lt;/p&gt;
&lt;p&gt;K는 세금을 지나치게 걷는 것은 나쁘다는 주장을 피력한다. 그러면 누가 사업을 하겠냐는 이야기다. 상당수 비상장 법인에 대한 투자 및 인수 합병에 세금이 많은 걸림돌이 된다는 이야기를 붙인다. 요는 세금이 투자 및 인수 비용을 상향 시키는 역할을 하기 때문에 일정 크기가 넘어가면 투자자와 피투자자 인수자와 피인수자 상호 간에 딜을 방해하는 허들 작용을 한다는 것이었다. Y는 그런 경험은 없었지만 K의 말도 일리 있다는 생각을 한다. 그러면서 또 한편으로는 모두가 각자의 입장에 맞는 주장을 한다는 생각을 해본다. 서는 데가 달라지면 풍경도 달라진다는 말처럼 말이다.&lt;/p&gt;
&lt;p&gt;쉑쉑버거는 맛있었다. 치즈는 쫀득쫀득했고, 패티는 부드러웠다. 굉장히 단촐한 햄버거인데 맛있었다. Y에게 약간 느끼하긴 했지만 버거가 크기 않아 부담스럽지는 않았다. 쉑쉑 버거를 처음 먹어보는 J와 S도 대체로 맛에 만족했다.&lt;/p&gt;
&lt;p&gt;M이 아리아 호텔에 아마존 부스가 있다는 이야기를 해서 일행은 그쪽 부스를 구경하러 아리아 호텔로 출발했다. 쉑쉑 버거에 들어갈때는 환했지만 나올 때는 약간씩 해가 지고 있었다. 보안 검사를 마치고 아마존 부스를 찾아 갔다. 하지만 거기엔 일행이 기대한 것은 없었다. B2B 관이었기 때문이다. 전시는 거의 없었고 B2B 룸만 잔뜩 있었다. 실망한 일행은 호텔을 나왔다. 드디어 밤이 됐다. 당연한 이야기지만 베가스는 이제 시작이었다. 낮보다 밤이 훨씬 화려했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d02_05.jpg&apos; data-alt=&apos;Figure 5. 벨라지오 호텔. 이 거대한 분수에서 분수쇼가 펼쳐지려 했으나 바람 관계상 ㅠㅜ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d761614e8381f936109feba96c39d0f3/7fbea/ces_2017_d02_05.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAHJtNCxBf/EABoQAQEAAgMAAAAAAAAAAAAAAAECAAMREyL/2gAIAQEAAQUCifbEoaXO2uXYuFuf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/AW1//8QAGBABAQADAAAAAAAAAAAAAAAAMQABECH/2gAIAQEABj8COROJ3//EABsQAAIDAAMAAAAAAAAAAAAAAAABESFBMWFx/9oACAEBAAE/IdcuxVIeDCtQrEjaZC5Z/9oADAMBAAIAAwAAABAQ/wD/xAAWEQADAAAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QUIj/xAAWEQEBAQAAAAAAAAAAAAAAAAARARD/2gAIAQIBAT8Qq4//xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhUaGx/9oACAEBAAE/EAw+tVx5MpMvX9llT42zVQJFZ7cAT0n/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 5. 벨라지오 호텔. 이 거대한 분수에서 분수쇼가 펼쳐지려 했으나 바람 관계상 ㅠㅜ~&apos; title=&apos;&apos; src=&apos;/static/d761614e8381f936109feba96c39d0f3/7fbea/ces_2017_d02_05.jpg&apos; srcset=&apos;/static/d761614e8381f936109feba96c39d0f3/8ccab/ces_2017_d02_05.jpg 190w,
/static/d761614e8381f936109feba96c39d0f3/ea4c8/ces_2017_d02_05.jpg 380w,
/static/d761614e8381f936109feba96c39d0f3/7fbea/ces_2017_d02_05.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 5. 벨라지오 호텔. 이 거대한 분수에서 분수쇼가 펼쳐지려 했으나 바람 관계상 ㅠㅜ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;일행은 벨라지오 호텔에서 하는 분수쇼를 보러 출발했다. 가는 길에 있는 메인스트리트에 대한 설명을 K가 해주었다. Y는 이제야 베가스에 온 것 같은 느낌이 들었다. 영화나 드라마에 등장하는 그 베가스가 이제야 나타났기 때문이다. 일행이 벨라지오 앞에 도착한 것은 분수쇼를 하기 15분쯤 전이이었다. 정각이 되면 분수쇼가 시작될 예정이었다. 바람이 많이 불고 날씨는 쌀쌀했지만 멋진 분수가 나타나길 일행은 기다렸다. 그사이 다스베이더가 나타났고 S는 그와 사진을 찍었다. 그리곤 1달러를 그에게 건냈다. 사진은 광속으로 찍었지만 가방에서 돈을 찾지 못해 다스베이더가 한참을 기다렸다. 급기야 헬맷을 벗기까지, Y가 대신 주러 다가갈 즈음 S는 가방에서 돈을 찾아서 그에게 주었다.&lt;/p&gt;
&lt;p&gt;정각이 다 되갈 즈음 레이디스 앤 젠틀맨이라며 방송이 나왔다. J는 자연스레 이제 시작하는 것 같다는 이야기를 했고, Y도 그런 것 같다고 했다. 사실 방송 내용은 너무 작았고 잘 들리진 않았다. 하지만 정각이 지나도 분수는 없었다. 일행은 포풍 검색을 했고, S가 바람 불면 안 하는 것 같다는 얘기를 했다. 5분 정도 더 기다려도 분수가 나오지 않아 일행은 포기하고 베가스 메인 스트리트를 걷기 시작했다. 우리의 구글 역할을 한 T가 화장실을 가고 없었다. 나중에 T가 전화를 해서 확인을 했는데 바람이 불어 취소된 것이 맞다고 했다.&lt;/p&gt;
&lt;p&gt;베가스의 호텔은 모두 각각의 특징이 있다. 파리를 테마로 한 호텔, 뉴욕을 테마로 한 호텔, 베니스를 테마로 한 호텔 같은 식이다. 괜찮은 생각 같았다. 한참을 길을 걸으며 내려갈 때 J가 허름한 숙소 한 곳을 가르키며 저기 2001년에 놀러왔었다는 이야기를 했다. 그때와 지금 많은 것들이 달라졌지만 그 숙소는 여전히 그 자리에 그대로 있었다. J는 아련한 생각에 잠시 빠진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d02_06.jpg&apos; data-alt=&apos;Figure 6. 베네치안 호텔. 밖은 밤이지만 여긴 하늘이 별도 구현되어 있다. 곤돌라까지, 서프라이즈.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/26d046bb627fcdfb70dda4e0856bafbe/ba98e/ces_2017_d02_06.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAUBAwQC/8QAFwEAAwEAAAAAAAAAAAAAAAAAAQIDAP/aAAwDAQACEAMQAAABpZLJlRqLx0XWU9EbTEYf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAAxASExH/2gAIAQEAAQUCRzKrjYSrGKyzdROxEHkUjboMDH//xAAXEQEBAQEAAAAAAAAAAAAAAAAAARES/9oACAEDAQE/AbJXDWv/xAAXEQEBAQEAAAAAAAAAAAAAAAAAARES/9oACAECAQE/AZbHbGP/xAAeEAABAwQDAAAAAAAAAAAAAAAAARAxERIgIXGB4f/aAAgBAQAGPwKS1UZa9bNTyetBGH//xAAdEAACAgIDAQAAAAAAAAAAAAAAAREhMUEQYZGh/9oACAEBAAE/IZqfoeFp0xtNkHo0UTG6fQcJXjYZE6VlpAUNrxgyT//aAAwDAQACAAMAAAAQrP8AD//EABkRAAMAAwAAAAAAAAAAAAAAAAABESFRcf/aAAgBAwEBPxBRk7G8hez/xAAZEQACAwEAAAAAAAAAAAAAAAAAAREhUTH/2gAIAQIBAT8QcUieCTpDD//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExYUFx/9oACAEBAAE/ECsFVgxlHIGg24tX5hiYKLAW9ncE5QX4uaRydLgfc8Ncjb6AbjtB9IBUxRBHFn//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 6. 베네치안 호텔. 밖은 밤이지만 여긴 하늘이 별도 구현되어 있다. 곤돌라까지, 서프라이즈.&apos; title=&apos;&apos; src=&apos;/static/26d046bb627fcdfb70dda4e0856bafbe/ba98e/ces_2017_d02_06.jpg&apos; srcset=&apos;/static/26d046bb627fcdfb70dda4e0856bafbe/8ccab/ces_2017_d02_06.jpg 190w,
/static/26d046bb627fcdfb70dda4e0856bafbe/ba98e/ces_2017_d02_06.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 6. 베네치안 호텔. 밖은 밤이지만 여긴 하늘이 별도 구현되어 있다. 곤돌라까지, 서프라이즈.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그렇게 구경을 하면서 하염없이 걷는다. T는 한국 사람들이 베가스를 처음 오면 명동이랑 비슷하다는 말을 했다는 이야기를 한다. Y는 속으로 명동이라기엔 사람이 너무 없는데 라는 생각을 했다. 하지만 코너를 돌자 그 생각은 없어졌다. 사람들이 물밀듯이 쏟아졌기 때문이다. 일행이 미자막으로 도착한 곳은 베네치안 호텔이었다. 앞서도 말한 것과 같이 그곳은 베니스를 옮겨둔 곳이었다. Y는 처음 들어갈 때 깜짝 놀랐다. 왜냐하면 깜깜한 밤길을 걷다가 실내로 들어갔는데 갑자기 대낮이 되었기 때문이다. 대낮이 환하다는 의미가 아니라 그냥 아침이 된듯한 느낌이었다. 나중에 안 사실이지만 천정에다 하늘 그림을 자연스럽게 그린 다음 불을 켜 두어서 그런 착시를 일으키는 것이었다. Y는 정말 신박하다는 생각을 한다. 물길이 있고 곤돌라가 있다. 진짜 베니스라는 생각이 절로 든다.&lt;/p&gt;
&lt;p&gt;너무 걸어서 모두가 피곤했다. 모두 앉을 곳을 찾았지만 마땅치 않았다. 그러다 T가 푸드코트 같은 곳을 발견했고 음료수를 시켜 모두가 앉았다. 바로 옆이 카지노였다. 이후 일정에 대한 이런 저런 이야기를 한다. 어디를 갈거냐 이곳 저곳 전화를 해서 예약이 되는지를 묻는다. 당첨된 곳은 일식집이었다. 21시에 예약이 된다고 했다. 아직 두시간 가량 남은 시간이다. 피곤했지만 또 심심하기도 했다. J는 카지노에서 시간을 떼우다 가자는 이야기를 한다. 일행은 그러기로 한다. 하지만 K는 탐탁지 않아 하는 분위기다. 결국 K와 S는 밖으로 나가 바람을 쏘이기로 하고 T는 플라밍고에서 차를 찾아서 이쪽 호텔 입구로 가져오기로 한다. JYM만 남아서 카지노를 구경한다. 이곳저곳 구경을 하는데 대부분 싸지 않다. 블랙잭은 대체로 25불씩이다. 섣불리 하기엔 비싼 금액. 1불짜리 슬롯머신을 J가 잠깐 했지만 진짜 금방 끝이 난다. JYM은 룰렛 옆에서 다른 사람들이 하는 것을 구경한다. 사실 JYM 모두 대체로 처음이라 카지노를 아는 사람이 없다. 그래도 룰렛은 워낙 간단해서 옆에서 보자 대체로 룰이 이해가 된다. 구경하는 테이블은 혼자서 플레이 하고 있었는데 Y가 보기에 그 전략은 수학적으로 상당히 합당한 전략 같아 보였다. 플레이어는 따기도 하고 잃기도 했지만 혼자서 오랜 시간 플레이를 하고 있었다.&lt;/p&gt;
&lt;p&gt;카지노를 구경하니 시간은 금방 간다. 결국 JYM은 그날 카지노를 하지는 못하고 구경만 하다 밖으로 나간다. S가 했냐고 묻는다. Y는 케이스 스터디를 하고 왔다고 너스레를 떤다. K는 호텔 입구에서 큰 기업 회장으로 보이는 사람이 지나가는 것을 두 번 봤다며 한국의 의전 문제를 이야기 한다. 저런 문화는 좋지 않다고 비판한다. 그러면서 그나마 IT 업계는 그런 것은 덜한 것 같다는 이야기를 덧붙인다. Y는 IT 업계도 실상 조금만 커지면 똑같지 않냐는 반론을 이야기 해본다. M은 오늘 근처에 현대 정의선 부회장이 왔다는 이야기를 들었다는 말을 한다.&lt;/p&gt;
&lt;h3&gt;미국 시간 2017.01.05 21:00 pm - 2017.01.06 05:00 am&lt;/h3&gt;
&lt;p&gt;T가 플라밍고에서 차를 가지고 일행이 기다리는 호텔 입구로 오고 있었다. 거의 비슷한 시간에 도착해서 JYM은 많이 기다리지 않고 곧바로 차를 탈 수 있었다. 도착한 곳은 이자카야 분위기의 일식집. 어제 먹었던 A18 보다는 훨씬 좋다. 서빙을 하는 아가씨가 한국말을 참 잘한다. 그런데 옆 테이블에 가서는 또 유창한 일본어로 주문을 받는다. 일행은 서빙 하는 친구가 3개국어를 한다며 여러가지 추측을 쏟아낸다. 결국 물어서 알게 된 사실은 한국 사람이고 근처 간호 학교에 다니고 있다고 한다. 안주도 괜찮았고 술도 나쁘지 않다. 술자리가 길어지기에 금상첨화인 상황.&lt;/p&gt;
&lt;p&gt;분위기가 무르익을즈음 M이 핵폭탄 화두를 던진다. 한국의 회사 운영 시스템이 좋지 않다는 것이다. 어쩌다보니 또 어제처럼 M은 공격하고 K는 수비하는 입장이 된다. M의 주된 논지는 한국 회사는 너무 대표 독단으로 운영되는 경우가 많다며 대표를 견제할 시스템이 없는 것이 문제라는 것이다. 특히나 중소 회사의 경우 대표가 최대주주인 경우가 많기 때문에 문제가 더 심각하다고 한다. 하지만 미국 회사의 경우에는 이사회라는 시스템을 통해서 운영되기 때문에 그런 문제가 없다고 한다. K는 다양한 방법으로 자신을 수비한다. 자신은 공정하다, 그렇게 운영하지 않는다는 이야기를 수차례. M이 그냥 돌직구를 날린다. 그래서 그 회사의 대표는 누가 견제할 수 있어요? K의 말문이 막힌다. Y가 대신 대답한다. 없죠.&lt;/p&gt;
&lt;p&gt;K는 자신의 회사 사람들은 대표 의견에 반대하는 것이 있으면 직설적으로 말한다는 이야기를 여러차례 근거로 들었다. 그말에 Y가 M을 거든다. 그래도 결국 진짜 중요한 결정은 다 대표님 생각대로 되는 것 아니냐는 대답이다. K도 어쩔 수 없다는 이야기를 한다. M은 그게 문제라며 공격을 이어 간다. 이번엔 반대로 Y가 K를 도와준다. 미국 또한 이사회가 오염되면 똑같다는 이야기였다. 결국은 정치 문제로 귀결된다는 말이다. 이사회가 존재하지만 이상하게 운영되는 미국 회사들의 예는 수도 없이 많다며 콕 찝어 보자면 회사가 적자가 나도 대규모 인센티브를 받는 CEO들을 지적한다. M도 완벽한 시스템은 없다고 시인한다. 하지만 견제 세력이 있는 것과 없는 것은 천지 차이라는 말을 덧붙인다. Y는 소규모의 경우는 합의에 낭비하는 시간 보다는 빠른 결정을 통한 효율 추구가 더 좋을 수도 있다는 이야기로 맞불었다. 실제로 그도 창업 초기에 그런 경험을 했었기 때문이다.&lt;/p&gt;
&lt;p&gt;이 이야기는 길게 길게 무럭 무럭 이어졌다. 안주도 좋았고 술도 좋았기 때문이다. T와 S는 많이 힘들어 하는 분위기다. 재밌는 주제도 아니고 그들이 거들 말도 별로 없었기 때문이리라. 2시까지 하는 가게가 거의 마칠 즈음에 그들은 나왔다. T는 다시 운전대를 잡는다. M이 묵고 있는 호텔에 그를 데려다주고 나머지 일행은 에어비앤비로 예약한 집으로 향한다. 집에 도착하니 거의 3시가 다 된 시각. 정말 늦었고 술도 취했다. 하지만 K는 아직 끝이 아니었다. S를 두고 JYKT는 한잔 더 하기 위해 베가스로 우버를 타고 나왔다. K는 진짜 베가스의 밤은 지금부터라며 호기롭게 말했다. 모두가 피곤했지만 K를 말릴수는 없는 노릇이었다. 결국 그들은 베가스의 가장 화려한 곳으로 출동해서 베가스의 밤을 즐겼다. 다시 집에 도착했을 때 시간은 5시였다. Y는 속이 쓰려 컵라면에 햇반을 하나 먹고 잠들었다. 나머지 일행은 광속으로 셧다운 됐다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] CES 2017 DAY #1]]></title><description><![CDATA[미국 시간 2017.01.04 09:30 am - 2017.01.04 12:00 pm LA 공항에 도착했다. 베가스행 비행기를 갈아타는데 셋에게 허락된 시간은 한시간 남짓이다. 그마저도 J…]]></description><link>https://jiniya.net/ng/2017/01/ces-2017-day-1/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/01/ces-2017-day-1/</guid><pubDate>Wed, 04 Jan 2017 12:10:01 GMT</pubDate><content:encoded>&lt;h3&gt;미국 시간 2017.01.04 09:30 am - 2017.01.04 12:00 pm&lt;/h3&gt;
&lt;p&gt;LA 공항에 도착했다. 베가스행 비행기를 갈아타는데 셋에게 허락된 시간은 한시간 남짓이다. 그마저도 J가 랜덤 체크에 걸리는 바람에 티케팅까지 해야하는 상황. 비행기에서 거의 다섯 손가락에 꼽힐만큼 빨리 내려서는 &quot;Express Connection&quot; 이라고 적힌 종이를 받아들고는 달리기 시작했다. 그나마 급행이라 그런지 입국 심사는 간단하게 넘어갔다. S가 조금 오래 걸렸지만 그래도 일반적인 미국 입국 심사보다는 간소했다. 짐들도 일등석 태그가 붙어 있어서 먼저 나왔다. 대한항공 티켓팅 직원이 환승 시간이 짧다고 발휘한 센스였다. 다시 달리기 시작. 세관 신고도 급행으로 하고 갸방을 다시 베가스행으로 보내고 델타 항공이 있는 게이트로 달리기 시작했다. J와 Y가 앞서고 S는 힘들게 쫓아온다. 델타가 있는 게이트는 5번 달려도 달려도 나오질 않는다. 4번이 무지 길다. Y는 잠시 이거 원래 뛰는게 아니라 교통 수단을 이용하는 것이 아닌가라는 생각을 해봤다. 그즘에 5번 게이트가 나왔다. 셋 모두 잽싸게 올라가서 티켓팅을 했다. 출력하고 다시 검색대 앞. 미국이라 그런지 보안 검사가 까다롭다. Y는 신발을 신고 있다가 지적질을 받았다. 짐을 검색대 안으로 넣지 않는다는 지적을 또 한 번 받는다. Y는 속으로 까탈스럽다는 생각을 한다.&lt;/p&gt;
&lt;p&gt;그렇게 검색대를 통과해 이제는 조금 여유롭게 걸어서 게이트 앞에 섰다. 그리고는 긴 줄 끝에 비행기에 올랐다. 셋 모두 안도했다. J는 50분에 이게 가능하네라며 허탈 웃음을 짓는다. 그리곤 이내 J, S, Y 모두 깊은 꿈나라로 빠져든다. 한시간 조금 넘는 비행 시간 동안 셋 모두 기절했다.&lt;/p&gt;
&lt;h3&gt;미국 시간 2017.01.04 13:00 pm - 2017.01.05 03:30 am&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d01_01.jpg&apos; data-alt=&apos;Figure 1. 베가스 공항의 첫 장면, 벌써 카지노 머신들이 즐비하다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1aeb95e279e8c8255d712db273203851/7fbea/ces_2017_d01_01.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEEAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABT5+YtJBP/8QAGhABAAIDAQAAAAAAAAAAAAAAAQADAgQhEf/aAAgBAQABBQI2iN2KNh6S3jj0/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8BJ//EABkQAAIDAQAAAAAAAAAAAAAAAAExABARcf/aAAgBAQAGPwJZGaPa0uf/xAAaEAEAAgMBAAAAAAAAAAAAAAABABEhMWFR/9oACAEBAAE/IXbu1dR8qPYZgGOQgyNCYnvFlZ//2gAMAwEAAgADAAAAEPff/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAx/9oACAEDAQE/EDF//8QAFREBAQAAAAAAAAAAAAAAAAAAEDH/2gAIAQIBAT8Qo//EAB4QAQEAAgICAwAAAAAAAAAAAAERACExQVFhcYGx/9oACAEBAAE/ENCQu2i+8FKrK1wwPuZMGganc335yBB8i4Q0SFnff7jebqjlc//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 베가스 공항의 첫 장면, 벌써 카지노 머신들이 즐비하다.&apos; title=&apos;&apos; src=&apos;/static/1aeb95e279e8c8255d712db273203851/7fbea/ces_2017_d01_01.jpg&apos; srcset=&apos;/static/1aeb95e279e8c8255d712db273203851/8ccab/ces_2017_d01_01.jpg 190w,
/static/1aeb95e279e8c8255d712db273203851/ea4c8/ces_2017_d01_01.jpg 380w,
/static/1aeb95e279e8c8255d712db273203851/7fbea/ces_2017_d01_01.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 베가스 공항의 첫 장면, 벌써 카지노 머신들이 즐비하다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;비행기 소리에 Y가 깬다. 그래도 한숨 붙여서 다행이라고 생각한다. 그즈음 비행기가 베가스 공항에 도착했다. Y가 공항에 내린 첫 느낌은 여기가 베가스구나, 라는 생각이었다. 공항에는 벌써 슬롯 머신들이 즐비했다. 웰컴 투 라스베가스라는 푯말을 지나 가방을 찾으러 간다. 가방이 나오는 곳에 도착했을 때 가방은 모두 나와 있는 상태. 가방을 찾자 J가 예매한 CES 티켓을 공항에서 찾아가면 된다며 사람들이 기다리고 있는 줄을 가리킨다. 셋 모두 거기 줄을 섰다. 줄은 길었고, 티켓 발매 직원은 한 명이었다. 시간이 제법 걸렸다. J는 작년은 이렇지 않았다며 올해 사람이 많이 온 것 같다는 얘기를 건낸다. Y와 S는 아직도 어리둥절한 상태라서 그러려니 하고 있다. 한참을 기다려서는 셋 모두 티켓을 받고 공항을 빠져 나왔다. 담배 피는 곳에서 J는 담배를 태우고 Y와 S는 기다린다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d01_02.jpg&apos; data-alt=&apos;Figure 2. CES 2017 티켓&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 236px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e714483792eb93adc299890c4d92acb6/c701c/ces_2017_d01_02.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 177.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAkABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMFBAb/xAAXAQEBAQEAAAAAAAAAAAAAAAACAQMA/9oADAMBAAIQAxAAAAFSquiSAWgPDQ5hzNwkiCWhisYGvf/EABsQAAIDAQEBAAAAAAAAAAAAAAECAAMSEyEi/9oACAEBAAEFAgGM4vqUEciwMxKX+El12GKlSlhEbTlRp7hlD6f/xAAZEQACAwEAAAAAAAAAAAAAAAAAARAREjH/2gAIAQMBAT8B6YQyxx//xAAbEQACAQUAAAAAAAAAAAAAAAAAEAECERIxMv/aAAgBAgEBPwHRnJdU9r//xAAfEAACAQQCAwAAAAAAAAAAAAAAAREQITEyA0EiUpH/2gAIAQEABj8CULY8+NnaE2WZqIwRPVMv6SxyW9qf/8QAHRABAAMAAgMBAAAAAAAAAAAAAQARITFBUXGB0f/aAAgBAQABPyFY26r5E0qOmUYIhiBCOJBsH3Ha13mVmMoP6lSPJBg1bOCu8EcwOdzc1qBRi7RWdep//9oADAMBAAIAAwAAABAM6gGML//EABkRAQADAQEAAAAAAAAAAAAAAAEAESEgYf/aAAgBAwEBPxA1TPQhTa4f/8QAGxEBAAICAwAAAAAAAAAAAAAAAQARIWEQMdH/2gAIAQIBAT8QcLJoYQWnUWRrzj//xAAgEAEBAAICAgIDAAAAAAAAAAABEQAhMUFRkXGBobHw/9oACAEBAAE/EDT6iv8AD7wmLvJ604zFuJC+s3TJ0V7cARx3U31zgpKKqG3J3Wbvzj4rZ2mfS4h4Ufk537qXj5xASFlBfesjm8AooeMC1lbdt84DEFmu5mkEjI0P3n//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 2. CES 2017 티켓&apos; title=&apos;&apos; src=&apos;/static/e714483792eb93adc299890c4d92acb6/c701c/ces_2017_d01_02.jpg&apos; srcset=&apos;/static/e714483792eb93adc299890c4d92acb6/8ccab/ces_2017_d01_02.jpg 190w,
/static/e714483792eb93adc299890c4d92acb6/c701c/ces_2017_d01_02.jpg 236w&apos; sizes=&apos;(max-width: 236px) 100vw, 236px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 2. CES 2017 티켓&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;J가 라인으로 합류하기로 한 다른 일행의 위치를 점검한다. K와 T가 LA에서 베가스로 셋을 마중나오기로 했는데 아직 도착하지 않았기 때문이다. 담배를 달아서 몇 개비를 피웠을 때 K와 T가 도착했다. 그들도 CES 티케팅을 위해 기다려야 했다. 20분 넘게 걸렸다. 밖에서 담배를 피우며 점심으로 무엇을 먹을지를 이야기를 한다. K가 곰탕이 좋다며 이조곰탕으로 가자고 했다. 모두 그러자고 한다. CES 티켓을 끊고 K와 T가 타고온 차를 이용해서 곰탕 집으로 향했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d01_03.jpg&apos; data-alt=&apos;Figure 3. 베가스 곰탕 맛집, 이조곰탕&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/433cf085f78865579c01b8551f2ee5ce/7fbea/ces_2017_d01_03.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAwAE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAL/2gAMAwEAAhADEAAAAWzpnDjor//EABoQAQEAAgMAAAAAAAAAAAAAAAIBABEDEiH/2gAIAQEAAQUCU1ifneZdo8khKol//8QAFxEAAwEAAAAAAAAAAAAAAAAAAQIQEf/aAAgBAwEBPwFRk//EABYRAQEBAAAAAAAAAAAAAAAAAAIQEf/aAAgBAgEBPwFLZ//EABwQAAICAgMAAAAAAAAAAAAAAAABAiEQETFRcf/aAAgBAQAGPwJ9lqsOWxvzkuJ//8QAHBABAAMAAgMAAAAAAAAAAAAAAQARITFBUWFx/9oACAEBAAE/ISGinXmW0q9I3YM4YbUAgqa+opKJ/9oADAMBAAIAAwAAABBn/wD/xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QnLX/xAAXEQADAQAAAAAAAAAAAAAAAAAAARFh/9oACAECAQE/EGPCYf/EABwQAQEAAgMBAQAAAAAAAAAAAAERACExQVFhcf/aAAgBAQABPxBykAi+s2ULrYf3Dwg90Zy+Bi23zzKOicg9tGWYoJHUQz//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 3. 베가스 곰탕 맛집, 이조곰탕&apos; title=&apos;&apos; src=&apos;/static/433cf085f78865579c01b8551f2ee5ce/7fbea/ces_2017_d01_03.jpg&apos; srcset=&apos;/static/433cf085f78865579c01b8551f2ee5ce/8ccab/ces_2017_d01_03.jpg 190w,
/static/433cf085f78865579c01b8551f2ee5ce/ea4c8/ces_2017_d01_03.jpg 380w,
/static/433cf085f78865579c01b8551f2ee5ce/7fbea/ces_2017_d01_03.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 3. 베가스 곰탕 맛집, 이조곰탕&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;ces 2017 d01 04
Figure 4. 이조곰탕에서의 거한 점심
이조곰탕, 베가스에서 나름 잘하는 집이다. 벌써 주차장은 가득 차고 웨이팅 종이는 모두 써서 더 적을 공간이 없었다. Y가 함께한 일행 보다 먼저 온 일행이 있다. 얘기하는 폼새가 삼성전자 직원 같았다. 그걸 모르고 늦게 온 K가 담배를 태우며 작년 CES와 올해 CES를 예상하며 올해도 LG가 이길 것 같다는 이야기를 한다. 이내 대기하는 사람들이 삼성 직원이라는 것을 알고는 조용해졌다. K의 팀이 늦게 왔지만 삼성 일행은 인원이 훨씬 많아 K팀 일행이 먼저 들어간다. 도가니 셋, 살코기 하나, 섞어 하나를 시킨다. 불고기 안주에 소맥으로 낮술이 시작된다. 그렇게 거하게 먹고는 에어비밴비로 예약한 집으로 이동했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d01_05.jpg&apos; data-alt=&apos;Figure 5. 에어비앤비로 예약한 집. 헤니의 그 집이랑 흡사하다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/10db225ab0dc8da35920cb4786e3cff6/7fbea/ces_2017_d01_05.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAv/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/aAAwDAQACEAMQAAABJYnBbEFn/8QAHBAAAQMFAAAAAAAAAAAAAAAAAQACAxESIjFB/9oACAEBAAEFAgI73SOBNV04ra//xAAWEQEBAQAAAAAAAAAAAAAAAAAAASH/2gAIAQMBAT8Bla//xAAWEQEBAQAAAAAAAAAAAAAAAAAAASH/2gAIAQIBAT8BsY//xAAbEAABBAMAAAAAAAAAAAAAAAABAAIQYREhMf/aAAgBAQAGPwLDXFVYXWxsR//EABoQAQEBAAMBAAAAAAAAAAAAAAERACExYVH/2gAIAQEAAT8hSQB80qE+sNNVc8Urzu0h7dKUIO//2gAMAwEAAgADAAAAEATv/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAwEBPxCKg94z/8QAFxEBAQEBAAAAAAAAAAAAAAAAAREAIf/aAAgBAgEBPxALcM9N/8QAGxABAQACAwEAAAAAAAAAAAAAAREAMSFBUdH/2gAIAQEAAT8QQV0RTONa9xKsoACswuwArPjiSW1XvLEU8RtgBxFA6IZ//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 5. 에어비앤비로 예약한 집. 헤니의 그 집이랑 흡사하다.&apos; title=&apos;&apos; src=&apos;/static/10db225ab0dc8da35920cb4786e3cff6/7fbea/ces_2017_d01_05.jpg&apos; srcset=&apos;/static/10db225ab0dc8da35920cb4786e3cff6/8ccab/ces_2017_d01_05.jpg 190w,
/static/10db225ab0dc8da35920cb4786e3cff6/ea4c8/ces_2017_d01_05.jpg 380w,
/static/10db225ab0dc8da35920cb4786e3cff6/7fbea/ces_2017_d01_05.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 5. 에어비앤비로 예약한 집. 헤니의 그 집이랑 흡사하다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;집에 짐을 풀고 잠시 집 구경을 했다. 다니엘 헤니가 사는 그런 일반적인 미국 집이다. 이층 집으로 방이 5개, 화장실 3개, 뒷마당에 수영장이 있는 그런 집. 대충 집의 상태가 파악될즈음 T와 S는 생필품을 사러 마트에 갔다. 출장 막내의 삶은 그렇게 피곤하다. Y는 그사이 배정받은 방에서 쓰러졌다. 한시간쯤 잤을까? 북적거리는 소리에 Y가 잠을 깨고는 내려간다. K가 새로산 블루투스 오디오를 자랑한다. 삼성이 인수한 하만카돈의 제품이라며 저렇게 조그마한 스피커에서 이렇게 웅장한 소리가 난다고 너스레를 떤다. Y가 생각해도 소리가 빵빵하긴 했다. 잠시 음악을 들으며 마트에서 사온 짐 정리를 대충 마칠때쯤 우버X를 불러서 저녁을 먹으로 출동했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d01_06.jpg&apos; data-alt=&apos;Figure 6. 첫 저녁 A18, 절대 피하길…​&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/793b97932d00cbd24badbe24e9b6f032/7fbea/ces_2017_d01_06.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAQP/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQP/2gAMAwEAAhADEAAAAZVXMn3JhT//xAAaEAEAAgMBAAAAAAAAAAAAAAABAAIDERIh/9oACAEBAAEFAo6hby7w3uI5p//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/Aar/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwGI/8QAGhAAAgIDAAAAAAAAAAAAAAAAACEBAhARYf/aAAgBAQAGPwLUDwjoqn//xAAbEAACAwADAAAAAAAAAAAAAAABEQAhMUFhcf/aAAgBAQABPyG8shJftCGFGoTR7Awi05EDQUhd7P/aAAwDAQACAAMAAAAQ6O//xAAWEQEBAQAAAAAAAAAAAAAAAAABEBH/2gAIAQMBAT8QdEf/xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAgEBPxAJH//EABwQAQEAAgMBAQAAAAAAAAAAAAERADEhQWFRgf/aAAgBAQABPxAgogYYIiFlEd9ZzAk0Wr++4To65N31l9UjYH2e8bw8kCJXLtz/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 6. 첫 저녁 A18, 절대 피하길…​&apos; title=&apos;&apos; src=&apos;/static/793b97932d00cbd24badbe24e9b6f032/7fbea/ces_2017_d01_06.jpg&apos; srcset=&apos;/static/793b97932d00cbd24badbe24e9b6f032/8ccab/ces_2017_d01_06.jpg 190w,
/static/793b97932d00cbd24badbe24e9b6f032/ea4c8/ces_2017_d01_06.jpg 380w,
/static/793b97932d00cbd24badbe24e9b6f032/7fbea/ces_2017_d01_06.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 6. 첫 저녁 A18, 절대 피하길…​&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;T가 찾은 집은 A18이라는 치킨 집이었다. A18을 보는 순간 T를 제외한 모든 사람은 웃기다는 생각을 했다. T는 18이 에이틴으로 보이는 영어가 더 편한 교포였기 때문에 솔직히 무슨 말들을 하는지 잘 이해할 수 없었다. 잠시 바람을 쏘이고 가게로 올라갔다. 치맥으로 시작한다. 시키는 메뉴마다 양은 어마어마 했다. 하지만 맛은 그닥이었다. 한국식 영계 치킨에 익숙한 이들에게 다자란 노계로 만든 듯한 치킨은 살이 퍽퍽하고 맛이 별로였다. T도 그런 표정이다. 그나마 그 사이 섞여있는 감자 튀김이 제일 괜찮은 것 같다는 이야기를 한다. 안타깝게도 맥주 또한 별로였다. 김빠진 맥주는 정말이지 그들을 좌절시키기에 충분했다. 이것저것 바꿔가며 시켜봤지만 모든 맥주가 맛이 형편 없었다. 화제는 S의 연애사였다. 유부남 셋이서 S의 연애사에 관한 이야기를 한마디씩 거드니 이야기가 끝이없이 이어진다. Y는 속으로 남녀의 차이는 정말이지 시대와 나이와 성별과 인종을 막론하고 통하는 주제라는 생각을 했다. 한참 이야기를 하고 있을 무렵 J가 라인으로 연락하던 B가 합류했다. 혼자가 아이었다. G가 함께왔다.&lt;/p&gt;
&lt;p&gt;G는 나름 업계에서 유명한 사람이기에 Y는 신기하다는 생각을 했다. 비유를 들자면 술집에서 맥주를 마시고 있는데 연예인이 온 것과 비슷한 상황. Y는 G에 관한 웃지 못할 에피소드를 하나 들어서 알고 있었고, 과거 술자리 안주로 그 이야기를 많이 했었다. 그래서 그런지 G가 어떤 사람인지 더욱 궁금했다. 그런데 G는 Y가 생각한 것과는 다소 상반된 사람이었다. 그리고 생각보다 재미난 사람이었다.&lt;/p&gt;
&lt;p&gt;베가스 답게 G가 처음 한 얘기는 겜블링이었다. 안타깝게도 G와 B를 제외한 나머지 사람들인 Y의 일행 중에는 도박을 하는 사람이 없었다. 대체로 명절 고스톱 정도 치는 사람들이었다. K는 심지어 그마저도 하지 않는 사람이었다. 나름 뼈대 있는 집안의 자손인 그는 집안 대대로 내려오는 집안의 룰이 있었기 때문이다. 그 중에 하나가 도박을 하지 말라는 것이었다. 여튼 그렇게 도박에는 하등 관심 없는 사람들을 상대로 G는 구구절절 도박 예찬론을 늘어놨다. G의 논지는 이랬다.&lt;/p&gt;
&lt;p&gt;일단 카지노의 슬롯 머신 룰렛 따위는 겜블이 아니다. 그건 그저 돈을 카지노에 가져다 바치는 행위다. 그가 겜블이라고 말하는 것은 포커와 블랙잭이었다. 일종의 마인드 스포츠로써 어느 정도 실력에 따라 승부가 결정되는 게임이라고 그는 주장했다. 그러면서 특히 포커에 대해서 많은 이야기를 했다. 그는 기업가는 반드시 겜블링을 해야 하는데 그 이유는 흥망성쇠를 간접적으로 짧은 시간에 느낄 수 있기 때문이라고 했다. 그가 포커를 하면서 배운 가장 큰 교훈은 상황이 좋지 않을 때 견디는 방법, 또 상황이 좋을 때 자만하지 않는 법이라고 했다. 그리고 특히나 포커를 하면서 한없이 패가 계속 좋지 않아서 하염없이 돈을 잃으면서 이 상황이 언제 끝날까, 라는 생각을 하며 게임을 할 때. 그때 그는 가장 많이 배웠다고 했다. 그 상황을 견뎌 내는 것이 사업에서 좋지 않은 상황이 계속 이어질 때 견뎌내는 것과 같다는 지론이었다. 그러면서 우리에게 꼭 겜블을 해볼 것을 권했다.&lt;/p&gt;
&lt;p&gt;겜블 이야기 다음은 연예인 이야기가 이어졌다. Y가 바라본 G는 정말 신기한 사람이었다. 그렇게 바쁘고 시간이 없을 것 같은 사람이 알고 봤더니 아이돌 전문가였기 때문이었다. 뒤쪽 스크린에 나오는 아이돌의 이름을 줄줄이 꿰고 있었다. 정말이지 신기했다. 그리고 드라마 이야기가 이어졌다. 역시 줄줄꿰고 있는 G. 그 자리에 있던 어린 친구들보다 훨씬 더 많은 연예인 정보를 알고 있었다.&lt;/p&gt;
&lt;p&gt;그렇게 이어지던 가십 이야기가 끝나고 CES 이야기가 나왔다. 그러다 VR 이야기가 테이블에 올라왔다. G는 요즘 사업들이 모두 초거대기업들의 문샷 배틀을 제외하고는 돈이 될만한 사업 아이템이 없다는 이야기를 했다. 그러면서 VR 또한 그런 것 중에 하나라는 이야기를 한다. K는 반대다. 그는 VR에 기회가 있을 거라는 입장이었다. G는 아직 기술이 덜 무르익었다는 생각이고, K는 지금부터 준비해야 하는 입장. G의 집요한 공격이 이어졌다. 그래서 뭐할거냐? 특정 분야를 제외하고 VR이 의미 있는 경우를 설명해 보라. 그래서 지금 사업에서 VR 쪽에 어느 정도 비율로 투자하고 있는가? G는 면접관이자 심판이었고, K는 면접자이자 플레이어였다. 하지만 K도 말빨로 어디가서 딸리는 사람은 아니기에 그렇게 이어지는 공격을 주구장창 막아냈다. 이야기가 길어지고 있었다.&lt;/p&gt;
&lt;p&gt;그들이 담배 피러 나간 사이 대화에 끼지 못하고 듣고 있던 S와 T와 Y는 잠시 서로 대화를 나눌 수 있었다. 셋의 마음은 똑같았다. 언제 끝날까? 우리는 언제쯤 침대에 누울 수 있을까? K를 다년간 수행한 T가 예언을 했다. 우리가 오늘 잘 시간은 3시라는 예언이었다. S는 소스라쳤고, Y는 정확하다는 생각을 했다.&lt;/p&gt;
&lt;p&gt;VR에 대한 열띤 토론이 끝나고 잠시 최순실 박근혜 얘기가 나올 즈음 1차가 끝이났다. 많이 아쉬워하는 G를 뒤로한체 J의 일행은 다시 집으로 돌아왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d01_07.jpg&apos; data-alt=&apos;Figure 7. 뒷마당에서의 술자리, 불이 있어 몽환적인 분위기. 애어비앤비 집의 유일한 장점이었다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/7eca4866729e7d1d607b622035a38f0f/7fbea/ces_2017_d01_07.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMFAf/EABUBAQEAAAAAAAAAAAAAAAAAAAIA/9oADAMBAAIQAxAAAAGfShaGwQK//8QAGRAAAgMBAAAAAAAAAAAAAAAAAQMCEBIR/9oACAEBAAEFAlcEnyVjVE1//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8Bqv/EABYRAQEBAAAAAAAAAAAAAAAAAAASAf/aAAgBAgEBPwGdS//EABgQAAIDAAAAAAAAAAAAAAAAAAAxICEi/9oACAEBAAY/ArMscP/EABgQAQEBAQEAAAAAAAAAAAAAAAEAERDx/9oACAEBAAE/IcytOGPjDkrz/9oADAMBAAIAAwAAABAf7//EABYRAAMAAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxBLCz//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREh/9oACAECAQE/EHTGQf/EABkQAQEBAQEBAAAAAAAAAAAAAAERACExUf/aAAgBAQABPxA8LfEt3EiIPzLYonCLnXMBFct3/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 7. 뒷마당에서의 술자리, 불이 있어 몽환적인 분위기. 애어비앤비 집의 유일한 장점이었다.&apos; title=&apos;&apos; src=&apos;/static/7eca4866729e7d1d607b622035a38f0f/7fbea/ces_2017_d01_07.jpg&apos; srcset=&apos;/static/7eca4866729e7d1d607b622035a38f0f/8ccab/ces_2017_d01_07.jpg 190w,
/static/7eca4866729e7d1d607b622035a38f0f/ea4c8/ces_2017_d01_07.jpg 380w,
/static/7eca4866729e7d1d607b622035a38f0f/7fbea/ces_2017_d01_07.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 7. 뒷마당에서의 술자리, 불이 있어 몽환적인 분위기. 애어비앤비 집의 유일한 장점이었다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;도착한 K는 뒷마당에 있는 파이어 스테이션에 불을 붙이고 블루투스 스피커로 노래를 틀었다. 하지만 그의 핸드폰 인터넷이 불안정했다. 결국 S의 로밍 인터넷으로 음악을 들었다. 그의 취향에 적합한 거미의 목소리가 백야드에 울려퍼졌다. 불이 있고, 술이 있고, 음악이 있는 약간 몽환적인 분위기의 술자리가 이어졌다. 심지어 의자도 제법 편했다. 그렇게 일행은 거미의 노래가 수도 없이 이어져서 결국은 도저히 알 수 없는 거미의 노래가 나올때까지 맥주를 마셨다. 그리고는 라면으로 지친 속을 달래고 각자 방으로 갔다. Y는 방에 누워 시계를 보았다. T의 예언은 정확했다. 침대에 누운 그 시간이 새벽 3시 30분이었기 때문이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] CES 2017 DAY #0]]></title><description><![CDATA[내가 본 것들, 경험한 것에 대한 기억을 보존하기 위해서 이 기행을 남긴다. 한국시간 2017.01.04 12:00 - 15:00 pm 그들이 탈 비행기는 LA행 3시 출발 대한항공 KE0017편이다. A380 기종이다. J와 Y는 1…]]></description><link>https://jiniya.net/ng/2017/01/ces-2017-day-0/</link><guid isPermaLink="false">https://jiniya.net/ng/2017/01/ces-2017-day-0/</guid><pubDate>Wed, 04 Jan 2017 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;내가 본 것들, 경험한 것에 대한 기억을 보존하기 위해서 이 기행을 남긴다.&lt;/p&gt;
&lt;h3&gt;한국시간 2017.01.04 12:00 - 15:00 pm&lt;/h3&gt;
&lt;p&gt;그들이 탈 비행기는 LA행 3시 출발 대한항공 KE0017편이다. A380 기종이다. J와 Y는 11시쯤 회사에서 택시를 타고 출발해 인천 공항에 열두시쯤 도착했다. S는 집에서 바로 공항으로 오기로 했다. J와 Y가 공항에서 10분 남짓 기다리자 S가 왔다. 한국은 영하의 겨울이지만 LA는 봄날씨다. 이런 사실을 잘 알고 있는 J는 공항에서 패딩 점퍼를 간절기의 가벼운 옷차림으로 갈아 입었다. Y와 S에게도 갈아 입을지 물었지만 둘은 괜찮다는 답변을 한다.&lt;/p&gt;
&lt;p&gt;J의 트렁크를 다시 정비하고 티켓팅을 하러 갔다. 줄이 길다. 약간 지루해지는 찰나 그들의 차례가 됐다. 티켓팅 중에 사소한 문제가 생겼다. J가 SSSS라는 일명 랜덤 체크에 걸린 것이다. J는 제법 여러차례 미국을 다녔지만 이런 것을 당해보기는 처음이다. Y와 S도 처음 보긴 마찬가지다. 티켓팅을 하는 직원이 친절하게 설명해주면서 난처해 한다. 그도 그럴것이 그들은 LA 공항에서 다시 베가스행 비행기로 갈아타야 하는데 그 시간이 무척 촉박했기 때문이다. Y와 S의 베가스행 티켓은 미리 발권해 주었지만 J는 랜덤 체크라 그러지 못했다. 1시간 남짓한 시간 안에 입국 심사를 마치고 다음 비행기를 타야 하는데 이제는 현지 티켓팅 작업까지 추가된 것이다. 업친데 덮친격. SSSS에 대한 네이버 검색 결과는 그들을 더 멘붕에 빠트리기에 충분했다. 모두가 약간 긴장했다.&lt;/p&gt;
&lt;p&gt;J와 Y는 로밍을 하고 보조 배터리를 받았다. J는 필요가 없다며 배터리를 S에게 건낸다. J의 기업인 카드 덕분에 공항의 빠른 검색대를 사용할 수 있었다. 인천 공항의 가장자리에 있는 검색대였다. 기업인 카드를 가진 사람과 그 일행은 해당 검색대를 사용할 수 있다. 공항은 엄청난 인파로 붐볐지만 빠른 검색대는 놀라울만큼 한산했다. 검색대를 지나 J와 Y가 출국 심사대 줄을 선다. S는 자동 심사대로 향했다. 그가 그것을 통과할즈음 J와 Y도 이제 더이상 사전 등록을 하지 않아도 자동 심사대를 쓸 수 있다는 사실을 알게 되었다. 그들도 줄을 떠나 자동 심사대로 빠르게 통과했다.&lt;/p&gt;
&lt;p&gt;J가 면세점 쇼핑을 할 것인지를 묻는다. Y, S 모두 그닥 살게 없다는 표정을 짓는다. 칼라운지로 직행한다. Y는 작년 GDC 갈때에도 이곳을 왔다. 작년 보다는 조금 더 사람이 많다고 느꼈다. 셋이 자리를 찾아 헤매다 결국 의자를 돌려서 테이블을 마주보고 앉도록 한 후에 음식을 가지러 간다. Y는 이것 저것 떠와서 먹었지만 음식 품질이 작년보다 덜하다고 느꼈다. 빵들이 지나치게 오래된 느낌이었기 때문이다. 셋다 빵을 조금씩 먹었고, S와 Y는 추가로 컵라면도 하나씩 끓여 먹었다. 정신 없이 오느라 모두 점심을 먹지 못해 배가 고팠다. 대충 끼니를 때우고 J는 담배를 피우고, S는 핸펀을 하고, Y는 노트북을 켜서 메일 확인을 하고 중요한 메일에 회신을 한 통 해주었다. 골치아픈 문제의 답을 알려주는 반가운 메일이었다.&lt;/p&gt;
&lt;p&gt;라운지에서의 시간은 금방 간다. 2시 10분 즈음에 내려와서 게이트 앞에 섰다. J는 그사이 담배를 사왔다. 곧이어 탐승한다. 프레스티지란 말이 무색하게 줄이 길었다.. 불행중 다행은 셋다 일찌감치 줄을 섰기에 빠르게 탈 수 있었다는 점이다. 옆에 일등석 손님이 한 명 있다. 평소 Y는 어떤 사람들이 일등석을 타나 궁금했기에 그를 면밀히 살펴본다. 지나칠정도로 너무나 평범한 사람이었다. 정말 평범하다는 생각을 했다. 비행기로 올라타는 길목에서는 J는 정밀 검색을 받으러 갔다. S와 Y는 먼저 탄다.&lt;/p&gt;
&lt;h3&gt;한국시간 2017.1.4 15:00 pm - 미국시간 2017.1.4 09:00 am&lt;/h3&gt;
&lt;p&gt;A380는 이층으로 되어있다. 스튜어디스가 Y에게 이층으로 가라고 안내했다. S도 따라간다. Y는 스튜어디스가 안내해 준 11E 자리에 앉았다. 비행기는 뭔가 산만한 분위기다. 스튜어디스가 S와 Y의 외투를 받아서 걸어준다. 이내 J가 도착했다. 걱정했던 것만큼 심각하진 않았던 것 같다. 다들 자리에 앉아 실내화로 갈아 신고 USB를 연결한다. 스튜어디스가 안전 설명을 하는 사이 Y는 잠이 들었다. 어제 먹었던 소주의 숙취 때문인지 피곤했다. 이내 비행기가 이륙한다.&lt;/p&gt;
&lt;p&gt;J와 S는 모니터를 꺼내서 둘러본다. Y는 주구장창 볼거라 핸펀을 꺼내서 책을 읽는다. 조금 있다 스튜어디스가 식사 메뉴를 묻는 질문을 한다. Y는 스테이크를 J와 S는 불고기 비빔밥을 선택했다. 프레스티지석의 식사 시간은 지나칠 정도로 장황하다. 스테이크는 이랬다. 전채가 나오고 빵이 나오고 수프가 나오고 와인이 나오고 스테이크가 나오고 치즈. 과자. 과일이 나오고. 이어서 커피와 차가 나왔다. 다 먹는데 거의 꼬박 한 시간이 걸렸다. Y는 시험한다는 생각으로 죄다 달라고 해서 모두 먹어 본다. 치즈가 세 종류가 나왔는데 말랑말랑한 젤 맛있게 생긴 녀석의 반전에 당했다. 말랑한게 달달하게 생겨서는 엄청 역한 맛을 내는 치즈였기 때문이다. 이름이 궁금했지만 물어보진 않았다.&lt;/p&gt;
&lt;p&gt;식사가 끝나고 스튜어디스가 물과 세관 신고서를 나눠준다. J와 S가 먼저 작성하고 Y는 S의 펜과 신고서를 받아 베꼈다. 이내 다들 모니터 삼매경이 빠진다. 여기 영화를 죄다 섭렵할즈음 도착하리라, 라고 Y는 생각했다. Y는 &quot;잭 리처&quot;라는 톰 크루즈 주연의 영화를 틀었다. 뻔한 내용의 뻔한 전개지만 재미있다. 그즈음 기내에 불이 꺼진다. 자는 사람도 한둘 보인다.&lt;/p&gt;
&lt;p&gt;Y가 보던 영화가 끝났다. 탑승한지 꼬박 다섯 시간이 지난 시점, J와 S는 여전히 모니터 삼매경에 빠져있다. Y는 찌뿌둥한 몸을 좀 풀러 밖으로 나간다. 바가 있는 곳에 드러 눕는다. 세상 편하다고 그는 생각한다. 그 상태로 다시 핸펀 책읽기를 시작한다. 결국 가벼운 책을 완독했다. 난기류가 있으니 안전 벨트를 착용하라는 방송이 나온다. 흔들리지도 않는데 계속 방송은 나오는 상황이었다. Y는 버텨보다가 비행기가 조금 흔들리자 잽싸게 자세를 고쳐 앉아서는 벨트를 맨다.&lt;/p&gt;
&lt;p&gt;벨트를 하고 있기를 십여분 좀이 쑤신다. Y는 반대편 끝 칵테일 바가 있는 곳까지 걸어가서 스트레칭을 하고는 자리로 돌아왔다. S가 헤드셋을 빼고 앉아 있다. 영화를 많이 봤냐고 묻자 라면을 시키고 기다리는 중이라는 대답을 한다. Y는 수면 자세로 자리를 조정했다. 조금 있다 S의 라면이 왔다. 냄새가 향기롭다. 아까 비빔밥을 많이 안 먹더니 배가 고팠던 것 같다. 라면도 많이 먹지는 않는 눈치다. Y도 따라 시키려다 속이 좋지 않을 것 같아서 참는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ces_2017_d0_01.jpg&apos; data-alt=&apos;Figure 1. 아침으로 나온 기내식 죽&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/06d8fe0fbb89c2ea5a374eb4940c55e9/7fbea/ces_2017_d0_01.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQGAQL/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAAB3ploo8pQf//EABoQAQEAAwEBAAAAAAAAAAAAAAIBAxITABH/2gAIAQEAAQUCRT9tzL+123vjk0WINf/EABcRAAMBAAAAAAAAAAAAAAAAAAEQETH/2gAIAQMBAT8Bg1f/xAAXEQADAQAAAAAAAAAAAAAAAAAAAREC/9oACAECAQE/AXpyFP/EAB4QAAEDBAMAAAAAAAAAAAAAAAABAhEDECIxEiFh/9oACAEBAAY/Ak5YkbFnZV8Z1bJqH//EABoQAQEBAAMBAAAAAAAAAAAAAAERACExQbH/2gAIAQEAAT8hecKSOPVV8MkbE7tXyaRxmihON//aAAwDAQACAAMAAAAQjx//xAAWEQEBAQAAAAAAAAAAAAAAAAABEFH/2gAIAQMBAT8QCdT/xAAWEQEBAQAAAAAAAAAAAAAAAAABEDH/2gAIAQIBAT8QUFkf/8QAHhABAQACAgIDAAAAAAAAAAAAAREAITFBUWGRofD/2gAIAQEAAT8QOPdCW3Zx3htbqqz9rLRpUed7xBrhs921PeCCHQV2/OMdSFJDx95//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 아침으로 나온 기내식 죽&apos; title=&apos;&apos; src=&apos;/static/06d8fe0fbb89c2ea5a374eb4940c55e9/7fbea/ces_2017_d0_01.jpg&apos; srcset=&apos;/static/06d8fe0fbb89c2ea5a374eb4940c55e9/8ccab/ces_2017_d0_01.jpg 190w,
/static/06d8fe0fbb89c2ea5a374eb4940c55e9/ea4c8/ces_2017_d0_01.jpg 380w,
/static/06d8fe0fbb89c2ea5a374eb4940c55e9/7fbea/ces_2017_d0_01.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 아침으로 나온 기내식 죽&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;J는 두번째 CES 참관이고, S와 Y는 처음이다. S는 생애 처음 미국을 가보는 것이고, Y는 미국은 가봤지만 베가스는 처음이다. 이래저래 설레는 새해 첫 비행이다. 항상 그렇지만 모든 여행은 그 출발의 설레임이 좋다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] VS 2015의 magic statics 구현 세부 사항]]></title><description><![CDATA[최근에 좀 골치 아픈 문제를 겪어서 여기에다 정리해 놓는다. 컴파일러를 업그레이드하면서 알게 된 문제인데 정적 지역 변수의 초기화와 관련이 있었다. 문제의 발단은 이랬다. 컴파일러 업그레이드 후 이상하게 싱글턴 등을 구현하기 위해서 사용된 static…]]></description><link>https://jiniya.net/ng/2016/11/magic-statics/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/11/magic-statics/</guid><pubDate>Thu, 24 Nov 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;최근에 좀 골치 아픈 문제를 겪어서 여기에다 정리해 놓는다. 컴파일러를 업그레이드하면서 알게 된 문제인데 정적 지역 변수의 초기화와 관련이 있었다. 문제의 발단은 이랬다. 컴파일러 업그레이드 후 이상하게 싱글턴 등을 구현하기 위해서 사용된 static 지역 변수 코드가 정상적으로 동작하지 않는 문제가 있었다. 구글 형님들께서도 POD를 제외하고 전역 객치를 만들지 말라는 조언을 하셨기에 우리가 만든 코드는 대체로 포인터를 사용하도록 변경했다. 그러다 급기야 어제는 부스트 라이브러리 코드를 디버깅 하기에 이르렀다. 잘 알겠지만 부스트 같은 템플릿 라이브러리는 쓰기는 편리하지만 디버깅은 지옥이다. 문제는 property_tree에서 발생했다. property_tree가 내부적으로 사용하는 rapidxml을 쓰면 잘 동작했는데 property_tree 코드만 쓰면 xml을 정상적으로 파싱하지 못했다. 여기저기 printf를 추가해서 따라간 마지막 장소에는 static 객체가 있었다.&lt;/p&gt;
&lt;p&gt;여기까지만 읽고 마치 새로운 컴파일러가 문제가 있다고 생각할 사람들이 있을까봐 노파심에 이야기를 하자면 컴파일러가 생성한 코드를 그냥 그대로 사용하면 문제가 되지 않는다. 우리가 그대로 사용하지 않고 별도의 처리를 해서 사용하면서 발생하는 문제였다.&lt;/p&gt;
&lt;p&gt;이 문제의 원인은 지역 static 객체 생성과 관련이 있었다. C++11 부터는 지역 static 객체 생성이 스레드 안전하게 보장하도록 표준에 추가되었다. 이 기능을 magic statics라 부르는 듯하다. 그간에는 이 기능에 대한 지원이 되지 않다가 VS2015에서 이 기능을 구현하면서 문제가 된 것이다. 그러면 VS2015가 내부적으로 스레드 안전한 초기화를 보장하기 위해서 어떻게 구현을 했는지 살펴보도록 하자. 그래야 왜 문제가 발생했는지도 알 수 있고, 어떻게 고칠 수 있는지도 알 수 있을테니 말이다. VS2015가 static 지역 객체 초기화를 스레드 안전하게 하기위해서 사용하는 전략은 단순하다. 락과 TLS다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Uninitialized    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; BeingInitialized &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; EpochStart       &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; INT_MIN&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Access to these variables is guarded in the below functions.  They may only&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// be modified while the lock is held.  _Tss_epoch is readable from user&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// code and is read without taking the lock.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; _Init_global_epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; EpochStart&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;__declspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; _Init_thread_epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; EpochStart&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; CRITICAL_SECTION   _Tss_mutex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; CONDITION_VARIABLE _Tss_cv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; HANDLE             _Tss_event&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;decltype&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SleepConditionVariableCS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; encoded_sleep_condition_variable_cs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;decltype&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WakeAllConditionVariable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; encoded_wake_all_condition_variable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;컴파일러가 동기화를 위해서 사용하는 자원이다. 크리티컬 섹션으로 동기화하고 조건 변수나 조건 변수를 지원하지 않는 시스템이면 이벤트를 통해서 초기화 완료를 알리겠다는 생각이다. 위에 적힌 전역 변수는 모두 DLL이나 EXE가 실행될 때 최초에 초기화 된다. 위와는 별개로 정적 지역 객체가 존재하면 컴파일러는 해당 객체의 초기화 상태를 트래킹하기 위한 전역 변수를 추가한다. 이제 간단한 싱글턴 객체를 만들어보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Single&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ctor\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dtor\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; Single&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; Single s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;핵심은 멀티스레드에서 Single::Instance를 미친듯이 호출한다고 할 때 그 내부에 있는 s 객체의 초기화를 단 한번만 하도록 만드는 것이다. VS2015는 다음과 같은 형태로 코드를 만든다. 여기서 우리에게 문제가 된 부분은 최초 락 없이 생성됐는지를 체크하는 조건문 if(g_single_once &gt; _Init_thread_epoch)에 있었다. g_single_once는 단순히 0으로 초기화 되지만 _Init_thread_epoch은 0x80000000으로 초기화 된다. 문제는 이게 TLS 변수라는 점에 있다. VS2015는 이를 위해서 __declspec(thread)를 사용해서 암시적 TLS로 처리했는데 이를 정상적으로 지원하지 않아서 _Init_thread_epoch이 0으로 함께 초기화됐고 그러면서 생성도 되지 않은 객체가 생성됐다고 판단이 이루어진 것이었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; g_single_once &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Uninitialized&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; SIngle&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g_single_once &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; _Init_thread_epoch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;_Init_thread_header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;g_single_once&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g_single_once &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; BeingInitialized&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;// 생성자 호출&lt;/span&gt;
			&lt;span class=&quot;token class-name&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// 종료 시에 소멸자 호출되도록 등록&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;atexit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Single&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;Single&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;_Init_thread_footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;g_single_once&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;동기화 구현의 핵심은 _Init_thread_header와 _Init_thread_footer에 있다. 해당 함수의 구현은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Control access to the initialization expression.  Only one thread may leave&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// this function before the variable has completed initialization, this thread&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// will perform initialization.  All other threads are blocked until the&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// initialization completes or fails due to an exception.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;_Init_thread_header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pOnce&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_Init_thread_lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pOnce &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; Uninitialized&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pOnce &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; BeingInitialized&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pOnce &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; BeingInitialized&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// Timeout can be replaced with an infinite wait when XP support is&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// removed or the XP-based condition variable is sophisticated enough&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// to guarantee all waiting threads will be woken when the variable is&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// signalled.&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;_Init_thread_wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;XpTimeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pOnce &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; Uninitialized&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pOnce &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; BeingInitialized&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;_Init_thread_unlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        _Init_thread_epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _Init_global_epoch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;_Init_thread_unlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Called by the thread that completes initialization of a variable.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Increment the global and per thread counters, mark the variable as&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// initialized, and release waiting threads.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;_Init_thread_footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pOnce&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_Init_thread_lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;_Init_global_epoch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pOnce &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _Init_global_epoch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    _Init_thread_epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _Init_global_epoch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_Init_thread_unlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;_Init_thread_notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 모든 구현을 살펴보고 나면 의문이 든다. 왜냐하면 암시적 TLS를 사용하는 엄청난 결정을 한 반면 그 암시적 TLS가 가져다주는 이점은 Single::Instance 구현의 첫번째 조건문 if(g_single_once &gt; _Init_thread_epoch) 앞에 메모리 장벽이 없어도 된다는 것 밖에는 없어 보이기 때문이다. Interlocked 함수 하나 안 쓰겠다고 암시적 TLS 지원이 정상적으로 안 되는 XP 시스템을 포기한 셈이다. 실제로 이 구현을 사용한 DLL을 XP 시스템에서 LoadLibrary 등으로 동적 로딩하면 정상적으로 동작하지 않는다.&lt;/p&gt;
&lt;p&gt;그러니 더 고민이 되었다. 이 신박한 구현에는 내가 생각하지 않은 다른 이유가 있을거야. Interlocked 함수 하나 안 쓰겠다고 이렇게 만든 것은 아닐거야. 뭔가 다른 이유가 있을거야 라면서 엄청 고민을 해봤다. 심지어 실행 카운트를 추적하는 기법 같아 보여서 이게 혹시 ABA 문제 등과 연관된 것은 아닐까 싶어 이것 저것 예외 케이스를 많이 생각해 보았지만 그 또한 아닌 것 같았다. thread local storage, lock optimizing, double checked 등과 같은 키워드로 겁나 검색했지만 걸리는 건 아무것도 없었다.&lt;/p&gt;
&lt;p&gt;그렇게 이틀을 고민하며 보낸 끝에 어이없는 곳에서 이 구현의 원본을 찾게 되었다. Mike Burrows라는 구글에 계신 형님께서 A Fast Implementation of Synchronized Initialization 이름으로 전파한 복음이었다. 그 상세한 알고리즘 분석 내용에는 내가 찾던 정답 또한 들어 있었다. &quot;The technique is useful only if such an access is faster than a memory barrier.&quot; 이 테크닉은 TLS 접근이 메모리 배리어보다 빠를 때에만 의미가 있다는 말.&lt;/p&gt;
&lt;p&gt;lock cmpxchg 보다는 mov 몇 개 더 있는게 더 빠르겠지? 아마도? 하지만 여전히 남는 의문은 그 차이가 XP를 포기할만큼 그리 컸을까 싶은 생각…​ 지원 중단된 과거 보다는 미래를 더 중요하게 생각해서 내린 결정인지도 모르겠다. 어쨌든 XP에서 돌릴 수 있도록 해당 기능을 끌 수 있는 플래그는 존재하니 말이다.&lt;/p&gt;
&lt;h3&gt;참고한 것들&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;There is a way to access thread-specific data or thread-local storage. The technique is useful only if such an access is faster than a memory barrier. For the disassembly above, the compiler used its ability to access thread-local storage using variables declared with __thread, so the thread-local access is a normal &quot;mov&quot; instruction with a different segment register.&lt;/p&gt;
&lt;p&gt;-- &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm#Appendix&quot;&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm#Appendix&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a known limitation with Windows XP and thread-safe local static initialization. The thread-safe local initialization code relies on thread-local storage for efficient lock-free checking in many cases. Unfortunately, XP contains bugs that prevent loading DLLs with thread-local storage variables from working correctly when the DLL is loaded through LoadLibrary. Since XP is out of its service lifetime these bugs are unlikely to be fixed.&lt;/p&gt;
&lt;p&gt;As a workaround, you can compile the program with /Zc:threadSafeInit-, which disables the thread-safe implementation. The old implementation does not rely on thread-local storage and will work on XP even in the presence of LoadLibrary, but is, of course, not thread-safe. If the function containing the local to initialize may be called from multiple threads you will need to handle appropriate synchronization manually when using /Zc:threadSafeInit-.&lt;/p&gt;
&lt;p&gt;-- &lt;a href=&quot;https://connect.microsoft.com/VisualStudio/Feedback/Details/1941836&quot;&gt;https://connect.microsoft.com/VisualStudio/Feedback/Details/1941836&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Starting in C++11, a static local variable initialization is guaranteed to be thread-safe. This feature is sometimes called magic statics. However, in a multithreaded application all subsequent assignments must be synchronized. The thread-safe statics feature can be disabled by using the /Zc:threadSafeInit- flag to avoid taking a dependency on the CRT.&lt;/p&gt;
&lt;p&gt;-- &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/y5f6w579.aspx&quot;&gt;https://msdn.microsoft.com/en-us/library/y5f6w579.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[시스템] WSL 환경에서 asciidoctor-pdf 설치하기]]></title><description><![CDATA[윈도우 bash 환경에서 asciidoctor-pdf를 설치해서 asciidoc 파일을 pdf로 변환하는 방법을 알아보자. 우선 설치를 위해서는 cmd에서 bash…]]></description><link>https://jiniya.net/ng/2016/11/install-asciidoctor-pdf-on-wsl/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/11/install-asciidoctor-pdf-on-wsl/</guid><pubDate>Tue, 01 Nov 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;윈도우 bash 환경에서 asciidoctor-pdf를 설치해서 asciidoc 파일을 pdf로 변환하는 방법을 알아보자. 우선 설치를 위해서는 cmd에서 bash 치고 들어가서 아래 명령어를 순서대로 입력해 주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; software-properties-common
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; apt-add-repository ppa:brightbox/ruby-ng
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update

$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; ruby2.1
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; ruby2.1-dev

$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; asciidoctor
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; coderay pygments.rb
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--pre&lt;/span&gt; asciidoctor-pdf
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; asciidoctor-pdf-cjk-kai_gen_gothic
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; asciidoctor-pdf-cjk-kai_gen_gothic-install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;설치가 모두 성공했다면 아래 명령어를 통해서 adoc 파일을 pdf로 변환할 수 있다. 아래 명령을 실행하면 example.adoc을 변환해서 example.pdf 파일이 생성된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ asciidoctor-pdf &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; asciidoctor-pdf-cjk-kai_gen_gothic &lt;span class=&quot;token parameter variable&quot;&gt;-a&lt;/span&gt; pdf-style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;KaiGenGothicKR example.adoc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;작업에 참고한 고마운 페이지들…​&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/questions/39011459/how-to-change-versions-of-ruby-1-9-to-ruby-2-0-in-the-new-windows-10-bash-shell&quot;&gt;http://stackoverflow.com/questions/39011459/how-to-change-versions-of-ruby-1-9-to-ruby-2-0-in-the-new-windows-10-bash-shell&lt;/a&gt;
&lt;a href=&quot;http://java.ihoney.pe.kr/430&quot;&gt;http://java.ihoney.pe.kr/430&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;그냥 윈도우 환경에서도 설치가 잘 되는데 마지막 폰트 설치 작업에서 SSL 에러가 나서 폰트를 다운로드 받지를 못했다. 귀찮아서 그냥 bash에다 설치하는걸로…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] MSVC 왜 wprintf는 되고 printf는 되지 않는 것일까?]]></title><description><![CDATA[아래와 같은 간단한 코드를 살펴보자. 1252 코드페이지로 '안녕’을 변환해서 출력하는 예제다. 출력을 해보면 printf는 begin까지만 출력되고 wprintf는 end까지 모두 출력된다. 이를두고 printf…]]></description><link>https://jiniya.net/ng/2016/10/msvc-wprintf-printf/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/10/msvc-wprintf-printf/</guid><pubDate>Thu, 13 Oct 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;아래와 같은 간단한 코드를 살펴보자. 1252 코드페이지로 &apos;안녕’을 변환해서 출력하는 예제다. 출력을 해보면 printf는 begin까지만 출력되고 wprintf는 end까지 모두 출력된다. 이를두고 printf는 안시 함수라 유니코드 문자열을 정상적으로 출력하지 못하고, wprintf는 유니코드 함수라 정상적으로 출력한다면 오산이다. 왜냐하면 둘다 출력은 틀렸기 때문이다. wprintf가 출력한게 한글 &quot;안녕&quot;이 아니라는 의미다. 한글은 우리가 잘 아는 문자라 이런 오류를 쉽게 인지할 수 있지만 모르는 문자 속에 섞여 있으면 자칫 wprintf는 제대로 출력한다는 오해를 할수도 있다. 그렇다면 왜 printf는 실패하고, wprintf는 끝까지 출력할까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// windows-1252	ANSI Latin 1; Western European (Windows)&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// 한글 변환이 불가능한 코드 페이지&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;setlocale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LC_ALL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.1252&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;안녕&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;printf begin %ls end&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;wprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;wprintf begin %ls end&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이유는 간단하다. 그렇게 만들었기 때문이다. 먼저 printf부터 살펴보자. 결국 아래 코드로 들어간다. _WCTOMB_S가 변환에 실패하면 루프를 제어하는 변수 charsout이 -1로 설정되고 루프가 종료되어 더 이상 출력이 진행되지 않는다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_output_l&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;format&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; charsout &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        e &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_WCTOMB_S&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;retval&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L_buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_countof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; retval &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            charsout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token function&quot;&gt;WRITE_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L_buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; retval&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;charsout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반면 wprintf는 아래와 같이 전개되고, 변환에 실패하면 ?를 출력하고 성공인 척 하도록 되어 있다. 즉, wprintf라고 정상 출력을 해내는 것이 아니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_output_l&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;format&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; charsout &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;WRITE_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wz&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; textlen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;charsout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;LOCAL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;write_string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    _TCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pnumwritten
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_flag &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; _IOSTRG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; f&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_base &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pnumwritten&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;len&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;write_char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pnumwritten&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pnumwritten &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;errno &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; EILSEQ&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 변환 실패로 빠지면 ?를 출력하고 성공인척 한다.&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;write_char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pnumwritten&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드에는 변환하는 부분이 나와 있지 않은데 write_char 함수를 따라가보면 결국 _fputwc_noblock으로 이어지고 콘솔인 stdout은 텍스트 모드라 printf와 동일하게 wctomb_s로 변환을 시도한다. 다만 여기서 실패해도 위쪽에서 살펴본 if문에 의해서 ?를 출력하고 계속 출력을 이어가도록 만들어둔 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;wint_t __cdecl &lt;span class=&quot;token function&quot;&gt;_fputwc_nolock&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;


        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_flag &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; _IOSTRG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_textmode_safe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_fileno&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; __IOINFO_TM_UTF16LE
                    &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_textmode_safe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_fileno&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; __IOINFO_TM_UTF8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;/* binary (Unicode) mode */&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_cnt &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wint_t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xffff&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_ptr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wint_t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_flswbuf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_osfile_safe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_fileno&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; FTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token comment&quot;&gt;// stdout은 이쪽으로 빠진다.&lt;/span&gt;
				&lt;span class=&quot;token comment&quot;&gt;// 결국 wctomb_s 함수로 printf와 동일하게 변환을 시도한다.&lt;/span&gt;

                &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; mbc&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MB_LEN_MAX&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;token comment&quot;&gt;/* text (multi-byte) mode */&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wctomb_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mbc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MB_LEN_MAX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token comment&quot;&gt;/*
                         * Conversion failed; errno is set by wctomb_s;
                         * we return WEOF to indicate failure.
                         */&lt;/span&gt;
                        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; WEOF&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;간혹 깨진 문자열을 보고 UTF-16으로 바로 출력됐다는 소리를 하는 황당한 경우도 있다. UTF-16으로 바로 출력하고 싶다면 printf와 같은 텍스트 계열 함수가 아닌 fwrite 같은 바이너리 계통의 함수를 사용해야 한다. 아래와 같이 출력하면 UTF-16으로 출력된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fwrite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wcslen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(사족) 가끔 느끼는 거지만 자기가 지금 짜고 있는 코드가 정확하게 무슨 일을 하고 있는지 알고 있는 프로그래머가 생각보다 드문 것 같다. 토이 프로그램만 만들게 아니라면 자기가 짠 코드나 라이브러리가 정확하게 무슨 일을 하는지 알고 있는 것은 무척 중요하다. 컴퓨터는 복잡하고 코드는 추상적이기 때문에 프로그래머는 공부를 열심히 해야 한다. 내가 생각하는 프로그래머라는 업의 본질은 그런 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 마이크로소프트는 왜 setlocale에서 UTF-8을 지원하지 않을까?]]></title><description><![CDATA[지난 글에서 우리는 setlocale에서 UTF-7이나 UTF-8을 지정할 경우 실패한다는 것을 알게 되었다. 하지만 여전히 의문은 남는다. 왜 MS는 setlocale에서 흔해빠진 UTF-…]]></description><link>https://jiniya.net/ng/2016/10/msvc-setlocale-utf8/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/10/msvc-setlocale-utf8/</guid><pubDate>Thu, 13 Oct 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;/ng/2016/10/printf-and-unicode/&quot;&gt;지난 글에서&lt;/a&gt; 우리는 setlocale에서 UTF-7이나 UTF-8을 지정할 경우 실패한다는 것을 알게 되었다. 하지만 여전히 의문은 남는다. 왜 MS는 setlocale에서 흔해빠진 UTF-8 따위를 지원하지 않을까? 도대체 무엇이 우리를 가로 막는 것일까? 안 될 이유가 없는게 안되면 한번쯤은 내부가 궁금해지게 마련이다. 그래서 이런 간단한 코드를 디버깅 해보기로 했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%p\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setlocale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LC_CTYPE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Korean_Korea.65001&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;디버깅 결과 총 세 지점에 우리를 가로막는 허들이 존재한다는 사실을 알게 되었다. 첫번째는 아래 지점이다. 대놓고 CP_UTF7과 CP_UTF8은 안 된다는 소리다. 재미난 사실은 if 문에 이 코드가 들어간 것이 Visual Studio의 특정 버전 부터라는 점이다. Visual C++ 6.0에는 CP_UTF7과 CP_UTF8을 검사하는 코드가 없다. 단지 IsValidCodePage로만 체크한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL __cdecl &lt;span class=&quot;token function&quot;&gt;__get_qualified_locale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; LPLC_STRINGS lpInStr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPLC_ID lpOutId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                    LPLC_STRINGS lpOutStr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//  verify codepage validity&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;iCodePage &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; iCodePage &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; CP_UTF7 &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; iCodePage &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; CP_UTF8 &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsValidCodePage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WORD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;iCodePage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음 허들은 아래 지점이다. 현재 코드페이지로 변환 되는 최대 글자 개수가 MB_LEN_MAX보다 크면 안 된다는 소리다. MB_LEN_MAX의 경우 Visual Studio 2015는 5로 정의되어 있다. 따라서 이 코드는 넘어간다. 반면에 Visual C++ 6.0에서는 MB_LEN_MAX가 2고 CP_UTF8은 이 구문을 넘지 못하고 실패한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; __cdecl &lt;span class=&quot;token function&quot;&gt;__init_ctype&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        pthreadlocinfo ploci
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lpCPInfo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MaxCharSize &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; MB_LEN_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;goto&lt;/span&gt; error_cleanup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;마지막 허들은 아래 지점이다. MultiByteToWideChar 함수를 통해서 버퍼가 얼마나 커야 하는지 구하는 부분이다. code_page에 CP_UTF8이 들어 있으면 플래그로 0이나 MB_ERR_INVALID_CHARS가 전달되어야 하지만 여기에서는 MB_PRECOMPOSED가 합쳐서 전달된다. MSDN 페이지에 나와 있는 것처럼 ERROR_INVALID_FLAGS로 실패한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; BOOL __cdecl &lt;span class=&quot;token function&quot;&gt;__crtGetStringTypeA_stat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        _locale_t plocinfo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        DWORD    dwInfoType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        LPCSTR   lpSrcStr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;      cchSrc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        LPWORD   lpCharType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;      code_page&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;      lcid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        BOOL     bError
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;/* find out how big a buffer we need */&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buff_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MultiByteToWideChar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; code_page&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                                    bError &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;
                                                        MB_PRECOMPOSED &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
                                                        MB_ERR_INVALID_CHARS
                                                        &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MB_PRECOMPOSED&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                                    lpSrcStr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                                    cchSrc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                                    &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                                    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지 따라오면 대충 뭔가 감이 잡힌다. 마지막 MSDN의 주석에 있던 코드페이지를 넘기면 setlocale은 죄다 실패한다. 그리고 그 코드 페이지가 가지고 있는 대체적인 특징은 한 글자가 2바이트가 넘는 3바이트, 4바이트 등으로 변환되는 코드페이지라는 점이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For the code pages listed below, dwFlags must be set to 0. Otherwise, the function fails with ERROR_INVALID_FLAGS.&lt;br&gt;
&lt;br&gt;
50220&lt;br&gt;
50221&lt;br&gt;
50222&lt;br&gt;
50225&lt;br&gt;
50227&lt;br&gt;
50229&lt;br&gt;
57002 through 57011&lt;br&gt;
65000 (UTF-7)&lt;br&gt;
42 (Symbol)&lt;br&gt;
&lt;br&gt;
Note For UTF-8 or code page 54936 (GB18030, starting with Windows Vista), dwFlags must be set to either 0 or MB_ERR_INVALID_CHARS. Otherwise, the function fails with ERROR_INVALID_FLAGS.&lt;br&gt;
&lt;br&gt;
— MultiBytesToWideChar MSDN&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;다시 setlocale의 MSDN 페이지를 살펴보자. UTF-7과 UTF-8을 넣으면 실패한다는 앞 문장에 의미심장한 설명이 있다. 한 글자당 두 바이트를 넘게 사용하는 코드 페이지는 예외라는 설명이다. 예외~ 즉, UTF-8이 안 되는 것이 아니라 한 글자에 두 바이트를 넘게 쓰는 코드페이지는 죄다 setlocale로 지정할 수 없고, wcstombs나 mbstowcs 함수로 변환할 수 없다는 것을 의미한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The set of available locale names, languages, country/region codes, and code pages includes all those supported by the Windows NLS API except code pages that require more than two bytes per character, such as UTF-7 and UTF-8.&lt;br&gt;
&lt;br&gt;
— setlocale MSDN&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그렇다면 MS는 왜 한 글자당 두 바이트 이상을 사용하는 코드페이지는 예외 처리를 했을까? 이 페이지에 약간의 힌트가 나와 있다. 수많은 레거시 코드가 멀티바이트에서 한 글자에 사용할 수 있는 저장 공간이 최대 두 바이트라고 가정하고 작성했기 때문이란다. 말 그대로 레거시 코드와의 호환성을 위해서 MS는 setlocale로 UTF-8을 지정할 수 없도록 만들었다. 미래 세대의 불편함 따위보다는 과거 세대와의 호환성 유지가 더 중요했기 때문이리라…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] printf와 유니코드 출력]]></title><description><![CDATA[이 코드는 유니코드 문자열 "안녕하세요. 끝."을 출력한다. 단순한 이 출력 속에도 복잡한 변환이 숨겨져 있다. printf는 내부적으로 유니코드 문자열을 멀티바이트 문자열로 변환을 시도한다. 이 변환에는 wcstombs…]]></description><link>https://jiniya.net/ng/2016/10/printf-and-unicode/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/10/printf-and-unicode/</guid><pubDate>Wed, 05 Oct 2016 12:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;안녕하세요.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%ls 끝.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 유니코드 문자열 &quot;안녕하세요. 끝.&quot;을 출력한다. 단순한 이 출력 속에도 복잡한 변환이 숨겨져 있다. printf는 내부적으로 유니코드 문자열을 멀티바이트 문자열로 변환을 시도한다. 이 변환에는 wcstombs와 같은 계열의 함수들이 사용된다. 이 함수는 현재 설정된 로케일을 참조한다. 해당 로케일은 setlocale 등으로 지정할 수 있다. 해당 로케일 정보에 포함된 코드 페이지로 변환한다. 특정 유니코드 문자가 해당 코드페이지로 적절하게 변환이 되지 않을 수도 있다. 그런 일이 발생하면 printf 함수는 실패하고 &quot;안녕하세요&quot; 다음에 있는 &quot;끝&quot;은 출력되지 않는다.&lt;/p&gt;
&lt;p&gt;따라서 printf로 유니코드 문자열을 출력할 때에는 로케일이 굉장히 중요하다. 해당 로케일은 앞서도 살펴보았듯이 setlocale로 지정할 수 있다. 일반적으로 UTF-8로 변환해서 출력하기 위해서는 다음과 같이 사용한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setlocale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;en_US.UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;안녕하세요.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%ls 끝.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 안타깝게도 Visual Studio를 사용한다면 위 코드를 통해서 UTF-8 출력을 사용할 수 없다. setlocale MSDN 페이지를 참고하면 다양한 형태로 로케일을 지정할 수 있는 것을 볼 수 있다. 그리고 en_US.UTF-8은 해당 페이지에서 언급하는 규칙에도 부합하는 것으로 보여진다. 혹시나 하는 마음으로 UTF-8에 해당하는 코드페이지인 65001을 사용해서 en_US.65001을 전달해 보아도 setlocale은 실패한다. 그리고 MSDN 페이지를 좀 더 꼼꼼하게 읽어보면 왜 그런지가 나와 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you provide a code page value of UTF-7 or UTF-8, setlocale will fail, returning NULL.&lt;br&gt;
&lt;br&gt;
— setlocale MSDN&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Visual C++을 사용해서는 setlocale을 통해서 UTF-8을 코드페이지로 지정할 방법은 없는 것으로 추정된다. 이뭐병?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] Visual Studio 2015에서 stdio 라이브러리 오류 해결 방법]]></title><description><![CDATA[Visual Studio 2015를 사용해서 오픈 소스를 빌드해보면 종종 링크 단계에서 vsnprintf를 찾을 수 없다거나 황당하게 printf를 찾을 수 없다는 링크 오류가 발생한다. 해당 문제는 해당 함수들이 Visual Stduio 201…]]></description><link>https://jiniya.net/ng/2016/08/stdio-link-error-in-msvc-2015/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/08/stdio-link-error-in-msvc-2015/</guid><pubDate>Sat, 06 Aug 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;Visual Studio 2015를 사용해서 오픈 소스를 빌드해보면 종종 링크 단계에서 vsnprintf를 찾을 수 없다거나 황당하게 printf를 찾을 수 없다는 링크 오류가 발생한다. 해당 문제는 해당 함수들이 Visual Stduio 2015에서 인라인 구현으로 변경되었기 때문이다. &amp;#x3C;stdio.h&gt;나 &amp;#x3C;conio.h&gt;를 포함하고 관련 함수를 사용하면 상관이 없는데 해당 헤더를 인클루드 하지 않고 컴파일한 다음 링크를 하면 심벌을 찾을 수 없다는 오류가 발생한다.&lt;/p&gt;
&lt;p&gt;해결 방법은 두 가지인데 1) 파일을 일일이 뒤져서 헤더 파일을 추가해주는 방법 2) legacy_stdio_definitions.lib을 링크 단계에서 포함시켜주는 방법이 있다. 당연지사 그 많은 소스 파일을 수정할 수 없기 때문에 legacy_stdio_definitions.lib을 추가해 주는 것이 편리하다.&lt;/p&gt;
&lt;p&gt;이것 외에도 Visual Studio 2015에서 호환성을 저해하는 변경 사항이 궁금하다면 아래 페이지를 참고하도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/bb531344.aspx&quot;&gt;https://msdn.microsoft.com/en-us/library/bb531344.aspx&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] Visual Studio 2015 명령줄에서 XP 타겟 사용하기]]></title><description><![CDATA[Visual Studio 2012부터 XP 타겟을 사용하기 위해서는 툴체인을 XP가 들어간 것을 선택해야 한다. Visual Studio 2015는 v140_xp를 선택하면 된다. IDE…]]></description><link>https://jiniya.net/ng/2016/08/using-xp-target-in-msvc-2015/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/08/using-xp-target-in-msvc-2015/</guid><pubDate>Fri, 05 Aug 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;Visual Studio 2012부터 XP 타겟을 사용하기 위해서는 툴체인을 XP가 들어간 것을 선택해야 한다. Visual Studio 2015는 v140_xp를 선택하면 된다. IDE에서는 그렇게 사용하면 되는데 명령 프롬프트에서 직접 빌드 해야 할때에는 어떻게 해야 할까? 컴파일러에 주는 뭔가 옵션이 있는 것일까, 아니면 CRT 라이브러리를 다른걸 선택하면 되는건가, 라는 여러가지 의문이 생긴다. 당황하지 않게 어떡하는지 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;우선 Visual Studio 2012부터 생긴 XP 타겟이 해주는 역할은 크게 두 가지다. 1) XP 호환되는 플랫폼 SDK를 사용해서 컴파일한다. 7.1A 버전이 마지막 호환되는 SDK다. 2) XP 호환되는 플랫폼 SDK를 사용해서 링크한다. 마찬가지로 7.1A에 포함된 라이브러리를 말한다. 3) 링크 옵션으로 실행 가능한 운영체체를 XP 버전으로 지정한다. 이걸 하지 않으면 6.0으로 선택되서 Vista부터 실행 가능한 이미지가 생성된다.&lt;/p&gt;
&lt;p&gt;XP 타겟이 하는 일을 알았으니 결론은 간단하다. 1은 cl에다 옵션을 주면 되는 것이고, 2, 3은 link에다 옵션을 추가하면 된다. 이미 만들어진 빌드 스크립트를 사용한다면 빌드 옵션을 조정하는 것도 일이기 때문에 환경 변수를 이용하면 편리하다.&lt;/p&gt;
&lt;p&gt;cl에 추가되는 옵션을 조정하기 위해서는 아래 환경 변수를 추가하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;set INCLUDE=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE%
set PATH=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Bin;%PATH%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;link에 사용되는 라이브러리를 변경하기 위해서는 아래 환경 변수를 추가하면 된다. 32비트 빌드라면 아래 환경 변수를 추가하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;set LIB=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Lib;%LIB%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;64비트라면 아래 환경 변수를 추가한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;set LIB=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Lib\x64;%LIB%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;32비트 콘솔 프로그램을 빌드하면 아래와 같이 환경 변수를 추가한다. 윈도우 프로그램이라면 subsystem을 windows로 지정하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;set LINK=/SUBSYSTEM:CONSOLE,5.01 %LINK%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;64비트 콘솔 프로그램을 빌드하면 아래와 같이 추가하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;set LINK=/SUBSYSTEM:CONSOLE,5.02 %LINK%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그런데 여기까지 하고 나면 함정이 하나 있다. Visual Studio 2015는 과거 버전이 그랬던것처럼 빌드 가능한 명령 프롬프트를 시작 메뉴에 등록하지 않는다는 점이다. 어디서 빌드를 시작해야 난감해진다. 당황할 필요 없다. 배치 파일은 동일한 경로에 있다. 아래와 같이 실행하면 각각 32비트 64비트 빌드 환경으로 진입할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat x86
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat amd64&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;전체적인 메커니즘에 대해서 더 궁금한 분은 &lt;a href=&quot;https://blogs.msdn.microsoft.com/vcblog/2012/10/08/windows-xp-targeting-with-c-in-visual-studio-2012/&quot;&gt;여기 글을&lt;/a&gt; 참고하도록 하자. 해당 글을 보면 CL 옵션으로 &lt;em&gt;USING_V110_SDK71&lt;/em&gt; 매크로 정의를 추가하는 것을 볼 수 있는데 그건 잘못된 SDK가 빌드되는 것을 막기 위한 용도로 현재는 사용되지 않는다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] Linux 서브 시스템, 윈도우 대격변의 서막]]></title><description><![CDATA[윈도우를 배울 때 누구나 그러하듯이 서브시스템이란 것이 존재하고, OS/2, POSIX, WIN32가 있다고 배운다. 하지만 그 존재를 알아채기란 쉽지 않다. 그저 그런가 보다 한다. 왜냐하면 그나마 명맥을 유지하는 거라곤 WIN3…]]></description><link>https://jiniya.net/ng/2016/08/windows-subsystem-for-linux/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/08/windows-subsystem-for-linux/</guid><pubDate>Fri, 05 Aug 2016 11:00:01 GMT</pubDate><content:encoded>&lt;p&gt;윈도우를 배울 때 누구나 그러하듯이 서브시스템이란 것이 존재하고, OS/2, POSIX, WIN32가 있다고 배운다. 하지만 그 존재를 알아채기란 쉽지 않다. 그저 그런가 보다 한다. 왜냐하면 그나마 명맥을 유지하는 거라곤 WIN32밖에 없기 때문이다. 그러다 윈도우의 역사를 좀 알게되고 데이비드 커틀러란 걸출한 프로그래머를 인식하게 되면 개발 초기에는 WIN32보다 OS/2를 지원하는 것이 무척이나 중요했다는 사실을 그나마 알게 된다. 그랬거나 말거나 OS/2는 역사의 뒤안길로 사라졌고 남은건 WIN32 밖에 없다. Windows NT가 출시되고 거의 20년간 그랬다.&lt;/p&gt;
&lt;p&gt;그랬던 거의 존재조차 유명무실했던 서브시스템이란 존재가 20년 만에 다시 재조명되고 있다. WIN32 밖에 보지 못해 있는거야 없는거야 라고 느꼈던 많은 프로그래머들도 이제는 그것이 단지 역사가 아닌 실제 존재한다는 사실을 온몸으로 느낄 수 있게 됐다. 바로 8/2일자로 진행된 윈도우 10 1주년 업데이트로 말이다. 20년 만에 윈도우가 리눅스를 품었다. 바로 리눅스 서브시스템이 생긴 것이다. Cygwin 정도를 상상했다면 잊어도 괜찮다. ELF 바이너리가 네이티브로 돌아가는 신세계가 펼쳐지니 말이다.&lt;/p&gt;
&lt;p&gt;인사이더 빌드 때부터 꾸준히 말이 많았지만 나이가 들어서 그런지 그래도 어느 정도 완성된 다음에 구경하고 싶은 마음에 정식 출시 하기를 기다렸다. 하지만 정식 출시에서도 베타 딱지는 아직 떼지못한 것으로 보여진다.&lt;/p&gt;
&lt;p&gt;윈도우 10 1주년 업데이트는 &lt;a href=&quot;https://support.microsoft.com/ko-kr/help/12387/windows-10-update-history?ocid=update_setting_client&quot;&gt;여기서&lt;/a&gt; 다운로드 받아서 설치하면 된다. bash쉘을 활성화하는 법은 &lt;a href=&quot;http://www.sysnet.pe.kr/2/0/11009&quot;&gt;정성태 님의 글을&lt;/a&gt; 참고 하자. 그저 여기서는 맛배기로 대격변의 서막이 어떻게 진행되고 있는지만 살펴보기로 하자.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./wsl1.png&apos; data-alt=&apos;Figure 1. 프로세스 트리&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b6674fcfe6021b37b0eee1a5f512a54f/6e34c/wsl1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAB2HAAAdhwGP5fFlAAADMklEQVR42iXK6W/adhzHcf+ZmzblwVRNmqY+2ONpWjK6SttU7aiqPpq6lqWQcYS0gRwc4QoQwhGCAWN8/2xjbP98cduG36xNeumr90f6YrQkqDpUNF2ezVRo6IZp2LbpONCyN76/3e9d3/cQ+p8bzN1+7Xm+53HLFcbwhALAFAg8w0iCMDfNpW1buja3LBtCy1msNAW5nu+6e89bLxaOYZoQbmybMiyM0jUKOpSmsxByhilYNqND3rIYCFnDGMsyOZ0GgG3zhjkQhOBhttmarjuCBtbd+9eqFSfHOV1poV3FsQtQ7yB057uBc4FNMdQpS6bYSUbkExTxEXCXM+nG0HqOg+WAfz5ehG+pN1Uq3tdPh/ZJVz0jFsFN4tb7phhu8G9vmTflSbghhOvcu1vmryp1XBeaUwvLz3Znk3WkIyYI85zfnlGLU9LOaSg7QxeSH+nK//SV913puC1Ge0q4Jf4daIsnD2pTsTFrV5PnV7iUttz8FtW11ZVsp1eo4uxL832R0ZJ9LjIE0YEQFYwU3F7qmwt1nbHdNO3wmO63Z5vyA8ji4IPqlsVFgYZXDmqaqAF3NRyctchYj0s2iehI/jBd55X1DdzVF6hGOQCrLPwkrSUm0qW6LK3QNVylZaO6RcXlruC48QkIRIdsZEDHxiAyYE8IIUaKSVq5100s27cjBZBsWDkCZUfoordN1s10z7voeeed9Ul5Fi1Oj/MgnOWjRfk4L/5HiJfVO2BiUB4Q91UdL+/kAdLGK66rj2pLrhP0FjxK3RvuPis/3IBOXh1UhXaObV47VBuJ+JCnMYMJdcrf0KVPtMcvkfTUwp+o3S98/iniv97SXwn1g1HhU7ry+aT8GWgcBMHXD4z+E3980KOymK392Sp+yz6GlsofaPnakV5A7mfkvEbzV67+OxiEJp1DYRCiH47A8Bnb+0EaPbfAC7R++cg3MGMT7pI/4tyh6f66Qq9k+xfR/CmIOXpper8R4lFv8h0BjnD2+4kcCmIsHZLKM235HFeaWJ64KkxOS3yqyCZKXKJAJ7JkrMjGC0ysIqRqYqbCZ6pCuipkbkGmLmda2uWdenk/+1iWyX8BIQrvEA93fbQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 프로세스 트리&apos; title=&apos;&apos; src=&apos;/static/b6674fcfe6021b37b0eee1a5f512a54f/efd7b/wsl1.png&apos; srcset=&apos;/static/b6674fcfe6021b37b0eee1a5f512a54f/08678/wsl1.png 190w,
/static/b6674fcfe6021b37b0eee1a5f512a54f/2edd7/wsl1.png 380w,
/static/b6674fcfe6021b37b0eee1a5f512a54f/efd7b/wsl1.png 760w,
/static/b6674fcfe6021b37b0eee1a5f512a54f/dc896/wsl1.png 1140w,
/static/b6674fcfe6021b37b0eee1a5f512a54f/78873/wsl1.png 1520w,
/static/b6674fcfe6021b37b0eee1a5f512a54f/6e34c/wsl1.png 1578w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 프로세스 트리&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;우선 프로세스 트리다. bash.exe가 일종의 게이트를 하는 것으로 보여진다. 윈도우 실행 파일인데 이 녀석을 실행하면 동시에 svchost.exe 밑에 init, bash가 같이 실행된다. 화면은 쉘에서 vi를 실행시켜서 bahs의 자식으로 vim.basic까지 실행된 것을 볼 수 있다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./wsl2.png&apos; data-alt=&apos;Figure 2. 실행된 vim.basic의 기본 정보&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6513c40c09e0a0277a29cf24e33d94a9/bbbf7/wsl2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 98.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABw0lEQVR42qVS2W7bMBDk/39bgT40SeOoSXVbFEWJFE+ROjqy28Co08BGBxSxWHFml9wheS9Z3zecV207WhvXbVpWPy9hXU/BPC17PG8bduRdjNp7F+JgHeFC5GmapSltGta2RZG3lHLOkTkej33P66p6e309PD/vv9qWd92PJEl/vrWck0GNcuDWuqqqBiEopXVdCykRMMaQYaxjDKLFMAyQE0JghyL6JVzptB2BeUZrd8CGQIR1h5I3lMYYkVpPuA7ecc78JmvvqjxFq1prZJcbgJNKDsY7kL3WZj7hFjLOsI53tNLOEmk03tliSJjBH5XPAb4QcrR7ZVcWRZZlUkpMYpqmcIHpCuf80PfSGKKsReUQIiQxg6bB21GMGoplWeJ6f0k45/Y2QzDeE+X2ykrpeZkpbXAaF4v/QIixR82TC6Q1Oxl1lFLGWjghL3LYwH8ENICCkIB5kiSBl4l2ripL2At66FArqLn1Gtv2ktVfvh3yI4NVHx8ezTQRzBrzOb/h55YybpLKOL/fHPV3k+B7N81lcJM9z+RbANn1Qvs+8n9V/oCsjAneT/csYwyGIkZFso7XvK/uWYcs+/r09L0ofgF+L4MW2uYJaQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 2. 실행된 vim.basic의 기본 정보&apos; title=&apos;&apos; src=&apos;/static/6513c40c09e0a0277a29cf24e33d94a9/efd7b/wsl2.png&apos; srcset=&apos;/static/6513c40c09e0a0277a29cf24e33d94a9/08678/wsl2.png 190w,
/static/6513c40c09e0a0277a29cf24e33d94a9/2edd7/wsl2.png 380w,
/static/6513c40c09e0a0277a29cf24e33d94a9/efd7b/wsl2.png 760w,
/static/6513c40c09e0a0277a29cf24e33d94a9/dc896/wsl2.png 1140w,
/static/6513c40c09e0a0277a29cf24e33d94a9/bbbf7/wsl2.png 1280w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 2. 실행된 vim.basic의 기본 정보&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;실행된 vim.basic 프로세스의 기본 정보를 살펴보자. 기본 정보가 표시되어야 하는 곳에 아무 정보도 표시되지 않는 것을 알 수 있다. 고로 우리는 망했어요 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./wsl3.png&apos; data-alt=&apos;Figure 3. 실행된 vim.basic의 메모리 정보&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c0d27cd2de69801d96bc919dcfa02d76/bbbf7/wsl3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 98.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAB2HAAAdhwGP5fFlAAACmElEQVR42oVTiW7bMAzN/39XBnTogCVN4SO+ZNmyJV+S7yt29ux2xXpsIxiFovlI6ok6BEWVSSnynImk6rp5vY/LOtyWaV134zYum327w79g281zMwz9NMuuPyR5TlzX9/1EJGmSBAEVAqlyn5A4josijxhzHcfU9YhFahdsKeLz4iCyjBKSpKlPfaXKJEmAKasKRpqmCM2yDEYQhFVVRXFc1zUqObaNqodcqTRBhrTvumWX2ybzuiz394IA4rmyKBIhwoDKuj6kqtItj+dyut99JhzKLBJcXUpCXnWTagZZ96rpZdOrdqj7qeymephl1fIsP8h+/H7Wz6ZXL3edRI8X0/S55rFnJzwZ3kn34IHxE7bhwni26fnqmx5jQhzaYbBNw7qaaAyEhWGQCg7CsF3X9f5JXpw4ecj5AbzrmnY6n+GKOfd9yjkH8dgue+AHXT6ATcN4enqCK4oj1/XAR7KDv6z8ItM05WX5DoxLAlgI/l8wrkQ1DcAj2n4Bo2GPEME5rvjfYFymrHewbVmarsOVbBMWYCSynTDc+fqVfAJrr2AaBDhz9ne2P1QeAL5cLuM4JYnwyHZmgIdxbHdpmqbrunbTttn2bd/38zwrgOt+wKA+/njcTiuEZVvonDGGY8cxB4V4A1gx1ZCQsTAM0eA4jDth/WBdr9++HYFBjKZplPqIiKLI9TaxLIsQ4m3quZ6Lf6Qeesxsu1W2bet4PIYhQyVd15GcRQy0sV2IT5ALqbFQSvFDCzt4r2zb9sPDg0+plMowDMu6uq6L+i+VHcfZ6C8KEJFmWHKpFFjYXlUFDuq6VKqpazw6GJsizW+FDdK6tn3TqixVUUhMGM0KLmUsZVQUUV7Eu/2HqtdPb5oXV5+eMBg0+AXU4lroD/tZTAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 3. 실행된 vim.basic의 메모리 정보&apos; title=&apos;&apos; src=&apos;/static/c0d27cd2de69801d96bc919dcfa02d76/efd7b/wsl3.png&apos; srcset=&apos;/static/c0d27cd2de69801d96bc919dcfa02d76/08678/wsl3.png 190w,
/static/c0d27cd2de69801d96bc919dcfa02d76/2edd7/wsl3.png 380w,
/static/c0d27cd2de69801d96bc919dcfa02d76/efd7b/wsl3.png 760w,
/static/c0d27cd2de69801d96bc919dcfa02d76/dc896/wsl3.png 1140w,
/static/c0d27cd2de69801d96bc919dcfa02d76/bbbf7/wsl3.png 1280w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 3. 실행된 vim.basic의 메모리 정보&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;메모리 정보를 살펴보자 vim.basic이 0x400000에 매핑되어 있는 것을 볼 수 있다. 어떤 이유에서인지 MS는 역사적으로 0x400000을 좋아하는 것으로 보여진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./wsl4.png&apos; data-alt=&apos;Figure 4. vim.basic의 매핑된 메모리 영역&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/56e167eb0eac174aa8234c37969ef7ee/dc992/wsl4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 84.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAB2HAAAdhwGP5fFlAAACHUlEQVR42lWS2W7bMBBF9f8f1gIBgvTBjZ3ASWNTJCXu2mU5tntn6KUlhOGmM8sdFjvva+e0pU9ora2tnC+reliW+XyaT6f5my1/43Icj9+h78d5lsNYaGOsMZv12juXYgzew8YQYJuUUsgW24TFNI7jMEzTdF6WnXPFXkophFLK8bDWepry0mJBW2O898MwtG0bY1qOx8v5vNVVAU6WpTUW1wjrrPHu6gc4phBwaIMPXdd2XZdSXJblcrmoti2EVIpgg1QxwMBD5skXWw84BETuhwH8NM+AZWoKWVWQCT9FHvg1e6H6ERQLKhlz7PseGFwcOPINVirwTzc4ZjjTBHvfpGaaoDGNB1xqraQiYTwF9DlP3tDkKBFuRILIIKH3A96jZCEgCSOehOWCac2aBSrZwBd0mngsd1hIibSpK46VIi/u3rarbCzYPE85+ANGn5WUhgNSrNwqxrjTlBF7DBM9kRH84XC41axUjswa32vOmbt7zVCupzFAv/kOQ21T1/+1KuuM5vCc0nXbNBCcoi//tqquqnwHr/4Gw+Dk6jHgMOFtZsEeagulK34kaAa9MJbXcyLwhdy5FioqkwiRYdUgclnut1ujpK+qqhSwNV6rUgZC7nZa0ImvdBfj1HXR2o6ctn1qP2tXrMvyabV63e3fhHh+XW+V/vX+/vr1tfr8fFr9fnl7fxPlh9YyRlw9rzfrffnyp/y52vzYqb/W5rNk2CsgPQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 4. vim.basic의 매핑된 메모리 영역&apos; title=&apos;&apos; src=&apos;/static/56e167eb0eac174aa8234c37969ef7ee/efd7b/wsl4.png&apos; srcset=&apos;/static/56e167eb0eac174aa8234c37969ef7ee/08678/wsl4.png 190w,
/static/56e167eb0eac174aa8234c37969ef7ee/2edd7/wsl4.png 380w,
/static/56e167eb0eac174aa8234c37969ef7ee/efd7b/wsl4.png 760w,
/static/56e167eb0eac174aa8234c37969ef7ee/dc896/wsl4.png 1140w,
/static/56e167eb0eac174aa8234c37969ef7ee/dc992/wsl4.png 1178w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 4. vim.basic의 매핑된 메모리 영역&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그럼 최종적으로 0x400000 메모리를 열어보면 이와 같다. 7f 45 4c 46, ELF 실행 파일이 그대로 매핑된 걸 볼 수 있다. 망했어요2 ㅠㅜ~&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;ps
Figure 5. ps -A 결과
서브시스템 내의 세계는 어떨까? ps -A를 해보면 우리가 bash 쉘에서 실행한 것만 출력된다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 새로운 bash 쉘은 새로운 리눅스를 의미할까? bash 쉘을 여러개 띄워서 실행해본 결과 동일한 init의 자식으로 생성되는 것을 알 수 있었다. 더불어 격리된 bash 쉘들에서 실행된 내용은 접근할 수 있는 것으로 보여졌다.&lt;/p&gt;
&lt;p&gt;ps -A에서 출력된 pid는 원래 윈도우에서 보여지는 pid와 일치할까? 확인결과 일치하지 않는 것으로 보여진다.&lt;/p&gt;
&lt;p&gt;이 정도 결과를 토대로 알 수 있는 것은 리눅스 서브시스템에서는 윈도우로의 접근이 불가능한 샌드박스 같은 구조인 것으로 유추해 볼 수 있겠다. 은막 뒤에서 펼쳐지는 마법의 보다 자세한 사항은 &lt;a href=&quot;https://blogs.msdn.microsoft.com/wsl/&quot;&gt;여기를&lt;/a&gt; 참고하자. 피코 프로세스라뉘…​ 그리고 이 핫한 기능의 가장 &lt;a href=&quot;https://github.com/Microsoft/BashOnWindows&quot;&gt;핫한 지점은&lt;/a&gt; 깃허브로 추정된다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;WSL(Windows Subsystem for Linux)의 존재를 우리가 처음 알게 됐을 때 가장 우려한 것은 WSL을 이용한 윈도우 세계로의 접근이었다. 하지만 잠깐 살펴본 바에 의하면 기본적으로는 막혀 있는 것으로 보여진다. 하지만 WOW64를 토대로 보건데 뭔가 강을 건너는 숨겨진 문이 있을지도 모를 일이다. 어쨌든 판도라의 상자 밖으로 나와 버린 PEB도 없는 이 애들을 어떡할지 걱정이다.&lt;/p&gt;
&lt;p&gt;번외 얘기긴 하지만 CEO 한 명 바꼈을 뿐인데 MS 참 열심히 일한다. 이 작품을 감상하면서 다시금 느꼈다. 이러니 저러니 해도 MS가 명실상부한 지구상에서 소프트웨어를 제일 잘 만드는 기업 중에 하나긴 하다는 사실을 말이다. 그런 의미에서 이제 안드로이드도 네이티브로 돌려주는 신기원을 열어주기를 ㅋㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] FreeBSD에서 BOM 제거를 위한 삽질기]]></title><description><![CDATA[각 메이저 진영은 모두 마치 약속이나 한 것처럼 미묘한 차이로 우리를 괴롭힌다. 마이크로소프트와 오픈소스 진영 간의 차이는 역사적으로 더 골이 깊다. UTF16과 UTF32, 파라미터를 UTF16으로 변경하는 것과 기존 함수에 UTF…]]></description><link>https://jiniya.net/ng/2016/07/remove-utf8-bom-on-freebsd/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/07/remove-utf8-bom-on-freebsd/</guid><pubDate>Fri, 29 Jul 2016 11:00:01 GMT</pubDate><content:encoded>&lt;p&gt;각 메이저 진영은 모두 마치 약속이나 한 것처럼 미묘한 차이로 우리를 괴롭힌다. 마이크로소프트와 오픈소스 진영 간의 차이는 역사적으로 더 골이 깊다. UTF16과 UTF32, 파라미터를 UTF16으로 변경하는 것과 기존 함수에 UTF8 변환 기능을 추가하는 것, 64비트 지원을 위해서 LLP64냐 LP64냐 등의 차이는 유명하다. 여기에 또 하나의 골치아픈 차이가 있다. UTF8 소스에 대한 BOM이다. msvc는 BOM이 있는 것만 컴파일을 해주고, gcc는 BOM이 없는 것만 컴파일을 해준다. 둘이서 짜고 우리를 괴롭히는 것 같다. 어떤걸 선택해도 우리는 양쪽 다 만족시킬 수가 없다. 결국 양쪽 다 만족시키기 위해서는 한쪽에다 변환기를 설치해야 한다. 우리는 gcc를 위해서 BOM을 제거하기로 결정했다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1 s/^\xef\xbb\xbf//&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 이 명령어를 이용해서 UTF8 BOM을 제거했다. 한동안 잘 사용했는데 이게 유닉스 진영에서도 문제가 될지는 몰랐다. FreeBSD를 만나기 전까지는 말이다. FreeBSD에서는 위 명령어가 제대로 동작하지 않았고 그 미묘한 차이로 인해 결국 나는 몇 시간을 허비했다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; .bak &lt;span class=&quot;token string&quot;&gt;&apos;1 s/^\xef\xbb\xbf//&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;처음 구글 신이 나에게 알려준 것은 sed의 -i 옵션이 리눅스와 BSD가 다르다는 것이었다. BSD는 -i의 옵션 다음에 원본을 저장할 확장자를 지정해야 한다는 것이었다. 위의 커맨드는 그렇게 변경한 것이다. .bak 파일에 원본을 백업하고 편집된 파일을 원본에다 덮어씌우는 기능을 한다. 명령어 오류가 없이 잘 돌아가는 것 같았다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; .bak &lt;span class=&quot;token string&quot;&gt;&apos;1 s/^\xef\xbb\xbf//&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;.bak &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;1차 시도에 백업 파일을 제거하는 기능을 덧붙인 것이다. 여기까지 하고는 이제는 빌드가 잘 되겠지 하고는 돌렸다. 하지만 빌드는 여전히 되지 않았다. 파일을 열어보니 BOM은 그 자리에 그대로 존재했다. 여기서 가장 많은 시간을 허비했다. 도대체 왜 BOM 제거가 안 되는 것이지? 구글님도 딱히 뾰족한 답을 주지 않았다. 삽질 끝에 알아낸 사실은 FreeBSD에 포함된 sed가 \xef등의 16진수 표현을 지원하지 않는다는 것이었다. \xef등이 아닌 멀쩡한 문자를 넣으면 잘 제거됐다. 구글님은 너가 8진수를 쓰면 될지도 모를껄 이라고 알려줘서 \oNNN을 사용한 표기로 변경해 보았으나 소용이 없었다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; .bak &lt;span class=&quot;token string&quot;&gt;$&apos;1 s/^&lt;span class=&quot;token entity&quot; title=&quot;\xef&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbb&quot;&gt;\xbb&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbf&quot;&gt;\xbf&lt;/span&gt;//&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;.bak &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;bash핵을 사용한 변칙 방법이다. bash에서 $&apos;&apos; 안에 포함된 문자를 변환시킨다는 것을 이용한 방법이다. 여기서 깔끔하게 끝낼 수 있었는데 나는 이때까지 이 명령어를 makefile에 결합해서 사용하는 방법을 몰랐다. 그래서 16진수 표현을 지원하는 awk로 돌아섰다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;NR==1{sub(/^\xef\xbb\xbf/, &quot;&quot;)}{print}&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 명령은 앞선 우리의 sed와 동일한 기능을 한다. 단지 파일에 저장하는 것이 아니라 변경된 내용을 화면에 출력할 뿐이다. awk에서 제자리 편집(in-place edit)를 하는 방법을 찾아 보았다. -i 옵션이 있었지만 FreeBSD에서는 응당 지원하지 않았다. 출력물을 결국 리다이렉션 시켜서 저장하는 방법 밖에는 없었다.&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;NR==1{sub(/^\xef\xbb\xbf/, &quot;&quot;)}{print &gt; {}}&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;find가 엮여 있어서 그냥 리다이렉션 시키기는 쉽지 않았다. 그러다 발견한 것이 awk의 위와 같은 문법이다. print 안에서 리다이렉션 구문을 쓸 수 있었다. 하지만 이렇게 하자 뭔가 잘 동작하지 않았다.&lt;/p&gt;
&lt;h3&gt;#6&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;NR==1{sub(/^\xef\xbb\xbf/, &quot;&quot;)}{print &gt; out}&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러다 -v를 사용해서 변수 값을 지정해서 사용하면 정상 동작한다는 것을 알아냈다. 여기서 FreeBSD를 정복하는 줄 알았지만 여전히 문제가 있었다. 정확한 원인은 모르겠지만 이렇게 저장된 파일은 원본의 전체가 아니라 일정한 길이 이후로 파일이 잘렸다. 전체 버퍼가 다 저장되지 않는 것처럼 보였다.&lt;/p&gt;
&lt;h3&gt;#7&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;awk &apos;NR==1{sub(/^&lt;span class=&quot;token entity&quot; title=&quot;\xef&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbb&quot;&gt;\xbb&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbf&quot;&gt;\xbf&lt;/span&gt;/, &lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;)}{print}&apos; {} &gt; {}&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 다시 쉴이다. 진작 알았으면 좋을 뻔 했다. &quot;sh -c&quot;로 특정 명령을 쉴로 실행할 수 있다는 사실이었다. 그래서 위와 같은 것을 생각해냈지만 결과는 참혹했다. 빈 파일만 덩그러니 남았다.&lt;/p&gt;
&lt;h3&gt;#8&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;awk &apos;NR==1{sub(/^&lt;span class=&quot;token entity&quot; title=&quot;\xef&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbb&quot;&gt;\xbb&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbf&quot;&gt;\xbf&lt;/span&gt;/, &lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;)}{print}&apos; {} &gt; {}.tmp&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;임시 파일로 리다이렉션 시킬 수 밖에 없었다. 이 명령은 정확하게 동작했다.&lt;/p&gt;
&lt;h3&gt;#9&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;awk &apos;NR==1{sub(/^&lt;span class=&quot;token entity&quot; title=&quot;\xef&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbb&quot;&gt;\xbb&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbf&quot;&gt;\xbf&lt;/span&gt;/, &lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;)}{print}&apos; {} &gt; {}.tmp; mv {}.tmp {}&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;임시 파일을 원본으로 덮어씌우는 것을 추가한 이 명령은 완벽했다. 이제 빌드 할 수 있게 되었다.&lt;/p&gt;
&lt;h3&gt;#10&lt;/h3&gt;
&lt;p&gt;몇 시간의 삽질 끝에 동작하는 두 가지 명령어를 알아냈다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;awk &apos;NR==1{sub(/^&lt;span class=&quot;token entity&quot; title=&quot;\xef&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbb&quot;&gt;\xbb&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbf&quot;&gt;\xbf&lt;/span&gt;/, &lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;)}{print}&apos; {} &gt; {}.tmp; mv {}.tmp {}&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 명령은 bash가 필요하지는 않다. 다만 매칭된 파일 개수만큼 sh, awk, mv가 실행된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;find . -type f -exec sed -i .bak $&apos;1 s/^&lt;span class=&quot;token entity&quot; title=&quot;\xef&quot;&gt;\xef&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbb&quot;&gt;\xbb&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\xbf&quot;&gt;\xbf&lt;/span&gt;//&apos; {} \; -exec rm {}.bak \;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 명령은 bash가 필요하다. 다만 sed, rm만 실행되기 때문에 sh가 추가로 실행되는 앞선 명령 보다는 효율적이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] Visual Studio 2008로 nss 빌드 하기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/07/build-nss-with-vs-2008/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/07/build-nss-with-vs-2008/</guid><pubDate>Fri, 29 Jul 2016 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;오픈 소스가 없었다면 우리같이 작은 소프트웨어 기업은 시작도 못했을 것이다. 모든 것을 다 만드려면 사람이 많아야 하고, 필요한 것들을 다 사려면 돈이 많아야 하기 때문이다. 어쨌든 우리같이 작은 기업에게 오픈 소스는 축복이다. 하지만 늘 그렇듯이 버튼 하나 누르면 마법처럼 동작하는 상용 소프트웨어와는 다르게 오픈 소소는 시키는대로 해도 뭔가 안 되는 경우가 많은 것 같다. 물론 요즘은 정확하게 시키는 대로 하면 대체로 비슷한 결과를 얻을 수 있지만, 항상 사람 일이란게 시키는 대로만 하고 살수는 없는 노릇이다. 최근에 mozilla nss를 윈도우에서 빌드하면서도 비슷한 경험이 있었다. Visual Studio 2008을 이용해서 정적 CRT로 빌드를 하려고 했으나 몇 가지 이유로 쉽지 않았다. 여기에 그 기록을 남겨 본다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Windows_Prerequisites&quot;&gt;여기서&lt;/a&gt; MozillaBuild를 받아서 설치한다. 그러면 기본 설치 경로인 mozilla-build에 가보면 start-shell-msvc2013.bat 파일이 존재한다. 해당 파일을 복사해서 2008으로 변경해준다. 해당 파일을 내용을 아래와 같이 수정하면 된다. 64비트를 빌드하고 싶으면 MOZ_MSVCBITS를 64로 변경해주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bat&quot;&gt;&lt;pre class=&quot;language-bat&quot;&gt;&lt;code class=&quot;language-bat&quot;&gt;@ECHO OFF

SET MOZ_MSVCBITS=32
SET MOZ_MSVCVERSION=9
SET MOZ_MSVCYEAR=2008

REM Switch CWD to the current location so that the call to start.shell-bat
REM doesn&amp;#39;t fail if invoked from a different location.
pushd &amp;quot;%~dp0&amp;quot;

CALL start-shell.bat&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;수정했으면 배치파일을 실행한다. 명령 프롬프트가 뜬다. 소스를 다운로드 받을 폴더로 이동한다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;해당 소스 파일 폴더에서 아래 명령어를 입력하면 최신 nspr과 nss 소스 코드를 클론할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;hg&lt;/span&gt; clone https://hg.mozilla.org/projects/nspr
$ &lt;span class=&quot;token function&quot;&gt;hg&lt;/span&gt; clone https://hg.mozilla.org/projects/nss&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;디버그, 정적 CRT를 사용하기 위해서는 아래와 같이 환경 변수를 선언해 준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;USE_DEBUG_RTL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
$ &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;USE_STATIC_RTL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그 다음 nss 폴더로 이동해서 아래와 같이 입력하면 nspr과 동시에 빌드를 진행해 준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; nss
$ &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; nss_build_all&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;우리가 정적 라이브러리를 사용해서 빌드를 하면서 한 가지 문제가 있었다. 아직 수정되지 않은 문제로 보여진다. &lt;a href=&quot;https://hg.mozilla.org/projects/nss/file/3ed709ba186a/cmd/shlibsign/shlibsign.c#l97&quot;&gt;이 함수가&lt;/a&gt; 문제였다. 전체적으로 아래와 같은 코드 흐름이다. 문제는 output_file이라는 변수가 PL_strdup와 PR_Malloc에 의해서 할당되는데 해제는 항상 PL_strfree로 한다는 점에 있다. 물론 PL_strdup와 PR_Malloc이 동일한 DLL에 있거나 정적으로 이 프로그램과 결합한다면 문제가 되지 않는다. 심지어 DLL 형태의 CRT를 사용해도 문제가 되지 않는다. 우리 케이스에서는 이게 문제였다. PL_strdup와 PR_Malloc은 서로 다른 DLL에 있는 함수였고, 이는 서로 다른 힙에 할당된다는 것을 의미했다. PL_strfree에서 크래시가 발생했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;mkoutput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PR_Malloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;output_file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;some_cond&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		output_file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PL_strdup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;optstate&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output_file &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		output_file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mkoutput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input_file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output_file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* allocated by mkoutput function */&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;PL_strfree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output_file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;코드를 아래와 같이 수정해주면 된다. 결국 PL_strdup만 할당한 변수를 사용하도록 통일해 주는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;mkoutput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; in_len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PR_Malloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;in_len &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SGN_SUFFIX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; in_len &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt; SHLIB_SUFFIX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;index &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;PL_strncmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt; SHLIB_SUFFIX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt; SHLIB_SUFFIX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        in_len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; in_len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;output&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;in_len&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SGN_SUFFIX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SGN_SUFFIX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PL_strdup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;PR_Free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;하지만 여기까지 수정을 하면 대체로 빌드가 상당히 진행이 되는데 테스트 빌드를 하는 도중에 오류가 발생한다. 대체로 C11, C14 기능들을 활용한 부분인데 Visual Studio 2008에서 그런걸 기대하기는 힘드니 아래와 같이 환경 변수를 선언해서 해당 부분은 빌드를 하지 않도록 한 다음 빌드를 하면 모두 성공시킬 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;NSS_DISABLE_GTESTS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
$ build nss_build_all&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[일상] 자존심]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/07/self-esteem/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/07/self-esteem/</guid><pubDate>Thu, 21 Jul 2016 10:00:01 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;하이고. 내 자슥인데 얼굴 보믄 모르것나. 영욱아. 내 말 잘 들으래이. 자존심은 미친년 머리에 꽂아놓은 꽃하고 같은 기다. 그 와, 마을마다 미친 아가 하나씩 안 있었나. 머리에 꽃을 꽂고 댕깄다 이가. 그칸데 희한하제? 얼굴을 만지고 때리고 밀고 그캐도 헤헤 거리고 웃던 아가, 머리에 꽃만 만지믄 살쾡이처럼 변해가 덤비는 기라. 지한테는 머리에 꽃이 지 몸보다 더 중요한기라. 사람들은 저기 미치가 저라는갑다 요라지만은, 내가 볼 때는 다 똑같데이. 사람들은 다 지 머리에 꽃 하나씩 꽂고 사는 기라. 아무 쓸모 없는 건데도, 지 몸보다 더 중하다고 착각하고 사는 기 있는 기라. 영욱가, 니한테는 그기 자존심이데이. 니는 가마이 있어도 서동환이 아들이고, 한오그룹 회장이 될 끼다. 동윤이 점마가 아등바등 기가 와도 대통령이 되고 뭐가 되도, 니 발꿈치도 못 따라오는 기다. 그카이 영욱아. 인자 마음 가라앉히고…​&lt;br&gt;
&lt;br&gt;
-- 드라마 추적자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;종종 사람들이 정말 엉뚱한 거래를 할 때가 있다. 손해 볼 것이 뻔한 상황에서도 불나방처럼 달려드는 상황. 대체로 그때 이유는 한결같다. 자.존.심. 아무것도 아닌 그거 하나 지키려고 너무 피곤하게 사는 건 아닌지하는 생각이 절로 든다. 머리에 꽂은 꽃은 꽃이고 나는 난데 말이다. 그 꽃에 지나치게 에고를 투영하면 투영할수록 투영하는 본인만 피곤해질 뿐이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 리디북스 PC용]]></title><description><![CDATA[여렸을 적에는 컴퓨터 책을 많이 읽었었다. 새뱃돈으로 내가 부린 거의 유일한 사치는 컴퓨터 책을 사는 것이었고, 여자 친구랑 영화를 보러 가서도 컴퓨터 책을 끼고 보면서 눈총을 받기도 했었다. 그 책은(The Art Of Unix Programming…]]></description><link>https://jiniya.net/ng/2016/07/ridibooks-for-pc/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/07/ridibooks-for-pc/</guid><pubDate>Mon, 18 Jul 2016 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;여렸을 적에는 컴퓨터 책을 많이 읽었었다. 새뱃돈으로 내가 부린 거의 유일한 사치는 컴퓨터 책을 사는 것이었고, 여자 친구랑 영화를 보러 가서도 컴퓨터 책을 끼고 보면서 눈총을 받기도 했었다. 그 책은(The Art Of Unix Programming) 눈물 없이는 볼 수 없다는 항변을 하는 바람에 더 욕을 먹기도 했었다. 어쨌든 그랬던 나도 언제부턴가 기술 서적을 많이 읽지 않게 되었다. 그러면서 기술 서적에 대한 취향도 다소 바뀌었는데 어렸을 때에는 특정 기술에 대한 세부 사항을 설명하는 책을 많이 읽었다면 지금에서는 그런 책보다는 실용주의 프로그래머, 조엘 온 소프트웨어, 프로그래밍 심리학, Old New Thing, 이펙티브 프로그래밍 등의 이념서나 에세이 류로 분류되는 책을 더 많이 선호한다. 물론 새로운 기술을 접할 때면 개요를 정리한 튜토리얼 성격의 책을 읽기는 하지만 최근에 딱히 새로운 기술이랄만한 것을 접한 기억은 없는 것 같다.&lt;/p&gt;
&lt;p&gt;여튼 자랑은 아니지만 고백컨데 기술 서적을 읽은지가 제법 오래된 것 같다. 간간히 아마존에서 영어 공부한답시고 원서 사서는 조금 보다 말고 한게 전부라 마지막으로 감동적으로 읽은 기술 서적이 뭐였는지도 까마득하다. 배꼽잡고 반성을 많이 해야 하는 상황인 것이다. 그랬던 차에 오늘 우연히 삘이 확 꼽히는 책 제목을 보게 되었다. &quot;7가지 동시성 모델&quot;이라는 책이다. 벌써 제목에서 뭔가 반드시 읽어야 할 것 같은 강한 냄새를 풍긴다. 거기다 번역을 무려 임백준님께서 하셨으며, 목차마저도 깨알같았다. 벌써 나는 리디북스에서 구매하기 버튼을 누르고 있었다. PDF라는 표기가 다소 나를 찜찜하게 하긴 했었다. 그리고 구매해서는 폰으로 책을 열었는데 PDF였다. 폰에서 보기에는 너무 조악한 화면.&lt;/p&gt;
&lt;p&gt;시원시원하게 27인치 모니터로 흡입해 버리겠어, 라는 마음과 함께 PC용 리디북스 버전을 설치했다. 설치하고 계정 로그인을 했다. 하지만 난 곧 실망할 수 밖에 없었다. 그 책은 아래 화면과 같이 어떠한 이유(아마도 저작권이나 유출등의 문제)로 PC용 버전은 지원이 되지 않는다고 나왔기 때문이다. 이뭐병 ㅠㅜ~ 혹시나 하는 마음에 단 한 차례도 들어가 보지 않았던 윈도우 스토어를 들어가 보았다. 그리고 거기다 리디북스를 쳤지만 그런 앱은 존재하지 않았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./ridibooks.png&apos; data-alt=&apos;Figure 1. 리디북스 PC용 버전&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 736px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/27e225f7cd5e324aad52f76eabe30532/bc563/ridibooks.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 52.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACgUlEQVR42iWSzU8TURTFZ+XGv8CVO/8CE+OKmLjTxIQFAn4lGk0XLsAISiq1IRHBUAIxKUICopIAERQVI1AwBaW0ldIPKG3ndT7evJk3M2+mnYFCpdBpHSS5Obk3+Z2cxblULuI2Iu1GxGVsuE7UjLpIyEkvtgqrzuTiU+63E4faSbjdjPwH1l3axjNu/Ml230NK+1tFZql4aFUqlbJlWRWrdFgydncPi4WYfFD76aBp6ej+gjWVKVerFZuyuXL5qGRVTXWT4rABJSJIRJR1AWuKbhLdxCSvkDyUjRg0E9BcS+M4kARR5W0Sa0maD0QBpIMUxIaNYm0HExOKagaqKV6lBZVBqigTCQmQ5wCdYXiU5UUA2CzNbm3T4S02ueGjaF5ZXg34/Cu+XwE77WswPfYjMDG3nMgwAoTrvneR+cHJASdg4E4OFhKzcKxbWJsje5WUbQ6G4s5rtd7G628cD7IQc6KsKNJ2JoUwBgBEl96+flzf21wHOERQssjN7ydmFG4dkf1U1EfF/YGWK5dbujqnHzXxLOJlVcRisUA0ndAAfB7ucFw856qrETRja348/LIh01af/j4q5UsCvUYFVoLuC+fbLtV4Gm5wAp7xh4emvq0G5mKbUZoG3g5Hv9vx3tNMDHPkhfvmmVO3z57uuXeLFCwxG6LiKa6rx9P6vKOzt0+QtQ/Ts939fa/6PQv+ZR6iPz8/fpkYmp0cJLoxPDJaV3v17p1G74BXNUrHZojzWRYJkookIqn5NM0CVmR4LGsmL6qxZDYFIMQ5uwtOkFkBq/puztyTSEFiwhRSdnhRFpXcyTBQsgkk6+j/edz/8aLbar8DlFS7ZzsJa3sSE/4HHdMJ98V2vdUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. 리디북스 PC용 버전&apos; title=&apos;&apos; src=&apos;/static/27e225f7cd5e324aad52f76eabe30532/bc563/ridibooks.png&apos; srcset=&apos;/static/27e225f7cd5e324aad52f76eabe30532/08678/ridibooks.png 190w,
/static/27e225f7cd5e324aad52f76eabe30532/2edd7/ridibooks.png 380w,
/static/27e225f7cd5e324aad52f76eabe30532/bc563/ridibooks.png 736w&apos; sizes=&apos;(max-width: 736px) 100vw, 736px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. 리디북스 PC용 버전&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그나마 옆에 있는 7인치 태블릿에 리디북스를 설치했다. 폰보다는 볼 만하지만 여전히 만족스럽지는 않다. 그러다 리디북스 페이퍼를 잠깐 살펴봤는데 6인치, 역시 조악할게 뻔하다. 이참에 PDF에 최적화된 태블릿을 사야하나 고민중…​ 리디북스가 윈도우 스토어를 어서 빨리 지원해 줬으면 하는 바램이다. 애매하긴 하다. 윈도우 스토어도 PC인가?…​&lt;/p&gt;
&lt;p&gt;심심해서 킨들에서 원서 샘플 다운로드 받아봤는데 퐌타스틱하게 보여진다. 기냥 원서를 샀어야 하는건가? PDF가 만악의 근원인건지 그걸 제대로 보여주지 않는 리디북스 뷰어가 만악의 근원인건지. 내가 그걸 깔끔하게 볼 디바이스를 가지지 않은게 잘못된건지 킁. 여튼 간만에 컴퓨터 책 한 번 읽으려다 심히 좌절중 ㅠㅜ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] Visual Studio Developer Assistant 플러그인]]></title><description><![CDATA[MS에서 Developer Assistant 플러그인이 이제 C++도 지원한다고 발표했다. Developer Assistant…]]></description><link>https://jiniya.net/ng/2016/07/developer-assistant/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/07/developer-assistant/</guid><pubDate>Wed, 13 Jul 2016 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://blogs.msdn.microsoft.com/visualstudio/2016/07/13/developer-assistant-supports-cpp/&quot;&gt;MS에서 Developer Assistant 플러그인이 이제 C++도 지원한다고 발표했다.&lt;/a&gt; Developer Assistant 뭐 이름 그대로 개발자 보조 도구 정도지만 그 녀석이 제공하는 기능을 보면 약간 섬뜩하기도 하다. 기본저인 컨셉은 알려진 접근 가능한 모든 소스 코드의 정보를 토대로 우리가 어떤 일을 Visual Studio에서 코딩하면 되는지 알려주겠다는 것이다. 거창하게 설명하면 이런데 좀 더 쉽게 말하자면 Visual Studio랑 크롬이랑 같이 쓰던거 Visual Studio만 쓰면 되도록 하주겠다는거다. 거기다 크롬에서 검색하는 것보다 좀 더 편하고, 유용하고, 카피하기 편하게 알려주겠다는 취지다.&lt;/p&gt;
&lt;p&gt;크롬, 정확하게는 구글이 우리를 대신해서 코딩하기 시작한지는 제법 됐다. 최근에 들어온 한 신입 직원은 거침없이 &quot;구글에 다 있잖아요&quot;라는 이야기를 했었다. 사실 틀린 말은 아니다. 솔직히 까놓고 말해서 구글의 한계가 우리의 한계인 경우가 다반사다. 그런 지경에서 이제와 크롬 대신 그저 IDE에서 조금 편하게 조금 더 씹어먹기 좋게 결과를 보여주겠다는 것 뿐인데 뭐가 대수인가, 라고 생각할지도 모르겠다. 그런데 내가 나이가 들어서 그럴수도 있겠지만 막연한 느낌인데 마냥 좋아보이진 않는다.&lt;/p&gt;
&lt;p&gt;내 프로그래머로 경력 초기에는 Visual Studio 버전이 6.0이었다. 지금 생각하면 아주 투박한 프로그램이었다. 거기다 윈도우의 온갖 구조체는 많은데 그놈에 IDE는 점(.)을 찍어도, 화살표를 붙여도(→) 제깍제깍 나에게 어떤 것들이 그 다음에 존재하는지를 알려주지를 않았다. 그 당시에도 Visual Basic은 인텔리센스가 광속이었다. 점을 찍기가 무섭게 너가 그럴줄 알았다는 듯이 목록이 떴었다. 하지만 C++은 달랐다. 마치 C++ 프로그래머는 모든 걸 다 외우라는 MS의 계시처럼 느껴졌다. 그래서 그 당시에 나는 흔한 신입 프로그래머들이 그러듯이 VisualAssist라는 도구를 사용했다. 어시스트를 설치하면 인텔리센스가 그나마 좀 똑똑해졌던 것이다. 게다가 파랑과 검정 밖에 없는 단조로운 Visual Studio의 문법 강조 기능도 훨씬 풍부한 색상으로 변했다.&lt;/p&gt;
&lt;p&gt;나는 VisualAssist에 굉장히 만족했었고 내가 작업하는 어떤 환경이든 그걸 설치해서 사용했다. 하지만 회사라는 생태계는 그리 녹록치 않았다. 그시절 그런 툴을 달갑지 않게 바라보는 팀장님이 계셨던 것이다. 그분은 주구장창 나와 같은 프로그래머에게 비난의 화살을 보냈다. 그 편리함에 익숙해지다가 넌 아무것도 모르는 바보 프로그래머가 될 거라고 말이다. 그러면서 자신은 그런 도구 없이 vim, 아니 노트패드로 코딩해도 모든 것을 다 외워서 타이핑 할 수 있다는 이야기를 덧붙였다. 물론 팀장님은 나에게 그리 강력하게 말하진 않았다. 하지만 직속 학교 후배가 몇 분 회사에 있었는데 그 후배들에게는 학교때부터 엄청난 갈굼을 했다는 이야기를 전해들었다. 그때나 지금이나 나는 철학적으로 그 생각에 동의하지 않기에 그러거나 말거나 VisualAssist를 썼다. 그러다 2008 정도 부터는 Visual Studio IDE도 그럭저럭 괜찮은 인텔리센스를 보여줘서 굳이 외부 도구를 설치하진 않는다.&lt;/p&gt;
&lt;p&gt;앞선 일화에서 내가 그 팀장님에게 동의하지 않았던 기본 전제는 그것이었다. 외워서 그것을 통째로 타이핑 할 수 있는 능력이 프로그래밍의 본질이 아니라는 것이다. 나는 그것보다는 그 근간에 흐르는 논리적 사고가 더 중요하다고 생각했다. 구조체 멤버를 외우는 것과 외우지 않는 것이 중요하지 않다. 하지만 그 구조체 멤버를 통해서 무엇을 할 수 있을지, 없을지를 판단하는 것이 더 중요하다고 생각했다. 물론 기본적인 사고 회로를 동작시키기 위해서 암기는 필수다. 아무것도 외우지 않고서는 어떠한 사고도 할 수 없을테니 말이다. 즉, 그 팀장님과 나의 결정적 견해 차이는 엄밀하게 말해서 필수적으로 암기해야 하는 것의 범위에 대한 차이였다고 볼 수 있겠다.&lt;/p&gt;
&lt;p&gt;그랬던 내가 Developer Assistant를 보면서는 이제 꼰대가 되나보다, 라는 생각을 무척 많이 하게 됐다. 캡처 화면 중에 &quot;How do I …​&quot;이란 창을 보고는 말이다. 이제는 프로그래머가 IDE에게 뭘 어떻게 해야 하는지를 물어봐야 하는 세상이 열리려는 순간인 것처럼 보였기 때문이다. 신입 프로그래머들은 그럴지도 모르겠다. 구글에서 검색하던 것이 조금 편리해졌을 뿐이라고. 물론 나는 지금 거기 동의하지만 뭔가 위험한 냄새가 나는 것을 감출 수는 없다. 내 경력 초기에 그 팀장님이 그랬던 것처럼 말이다. 너무 편리한 도구가 프로그래머들의 생각하는 법을 빼앗아갈까봐 두려운 것이다.&lt;/p&gt;
&lt;p&gt;전화가 발명됐을 때 사람들은 그랬다. 이제 사람들은 마주보고 이야기하는 법을 까먹게 될거야. 이메일이 발명됐을 때 사람들은 그랬다. 이제 사람들은 서로 음성으로 대화하는 법을 까먹게 될거야. 메신저가 등장했을 때 사람들은 그랬다. 이제 사람들은 뭔가를 기다리는 법을 까먹게 될거야. 하지만 아직 우리는 살아남았고, 더 편리한 세상에서 살고 있다. Developer Assistant를 사용하는 지금의 프로그래머들이 10년 후에는 나랑 비슷한 글을 쓰고 있기를 바란다. 물론 아마도 그때 그들은 알파고에 대한 우려를 표명하고 있겠지만 말이다 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;여담이지만 앞선 기술의 진보에 대한 우려가 전혀 기우였던 것은 아니다. 우리는 살아남았지만 어느 정도 그 걱정이 반영된 세상에서 살고 있다. 지금 사람들은 과거 사람들보다 덜 마주보고 이야기하며, 덜 음성으로 대화하고, 덜 기다린다. 그리고 분야에 따라서는 완전히 우리의 기능을 마비시키고 있는 것들도 있다. 큰 누나는 후방 카메라가 없으면 후방 주차를 하지 못한다. 나는 네비게이션 없이는 낮선 장소를 정확하게 찾아갈 수 없다. 그리고 내 가족을 넘어서 우리 모두가 느끼고 있는 분명한 사실은 이제 더이상 그 누구도 전화번호를 기억하지 않는다는 사실이다. 예전에 2-30개씩은 외우고 다니던 것이랑은 정말 대조적이다. 우리는 기술의 혜택을 받았지만 동시에 일정 부분 기계가 대신해 주는 부분에 대해서는 불능 상태가 되고 있다. 그런 점에선 10년전 그 팀장님도 우리가 외우는 걸 양보하는 순간 생각하는 법까지 양보하게 될거라 생각한 것인지도 모르겠다.&lt;/p&gt;
&lt;p&gt;언젠가 회사 부장님께서 운전은 장기적으로 승마와 같은 스포츠가 될 것이라는 이야기를 하셨다. 미래 세대는 지금 우리가 승마를 즐기는 것처럼 운전은 서킷에서나 하는 활동에 지나지 않을 것이라는 말씀이었다. 지나가는 농담처럼 한 말이었지만 나는 굉장히 통찰력 있는 이야기라고 생각했다. 또 아마도 그렇게 될 것 같은 느낌이다. 그런 점에서 우리가 기계가 대신해주는 모든 것을 포기했을 때 과연 우리는 무엇을 하고 있을지가 궁금해졌다. 우리 세대는 승마가 없어지고 운전이 생겼다면, 미래 세대는 운전이 없어지고 비행이 생길까? 지금 분위기로 봐서는 그럴 가능성은 별로 없어 보인다. 그저 월e의 한 장면처럼 모두 아무런 활동도 하지 않고 그저 주어진 삶을 사소한 쾌락으로 채우고 있을 것 같다는 느낌 밖에는…​&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 봇 전성시대]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/06/bot-era/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/bot-era/</guid><pubDate>Fri, 10 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;일전에 &lt;a href=&quot;http://news.khan.co.kr/kh_news/khan_art_view.html?artid=201604172105005&amp;#x26;code=990100&quot;&gt;조환규 교수님의 칼럼을&lt;/a&gt; 굉장히 인상적으로 읽었던 적이 있었다. 로봇을 사람에게 맞추기 보다는 사람을 로봇에게 맞추는 것이 훨씬 쉽다는 관점. 그리고 우리가 조만간 로봇들에게 잘 보여야 할 시대가 올지도 모른다는 이야기. 어쩌면 조금 무시무시한 담론이다. 그러나 어쩌겠는가? 세상이 그렇게 변해가는 것을…​&lt;/p&gt;
&lt;p&gt;오늘은 또 &lt;a href=&quot;http://agile.egloos.com/m/5873169&quot;&gt;김창준님의 감동적인 글을&lt;/a&gt; 한토막 읽게 되었다. 어쩌면 지금부터 준비해야할지도 모르겠다는 생각이 팍팍 들었다. 그래서 봇 전성시대를 대비해서 나도 몇 자 끄적여 보려고 한다.&lt;/p&gt;
&lt;p&gt;서버 공간이 부족한 관계로 자세한 내용은 다음에 서버 공간 늘리고 차차 채우는걸로 ㅠㅜ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] pip 환경 배포하기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/06/pip-distribute/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/pip-distribute/</guid><pubDate>Wed, 08 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;파이썬을 사용하면 귀찮은 작업 중에 하나가 환경 바뀌면 라이브러리를 일일이 수동으로 설치해줘야 한다는 점이다. 운영체제를 새로 설치해도 그렇고, 다른 사람에게 알려줄 때에도 그렇다. 그래서 도커를 써야 하나 싶다가도 뭔가 모기 잡으려고 화염방사기 쓰는 것 같은 느낌도 들고, 결정적으로 도커를 모르기도 하고 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;물론 이런 경우만 있는 것은 아니다. 이번에 2.7에서 3.5로 갈아타는 것과 같이 다른 환경으로 이동하는 경우도 있다. 이때에는 진짜 정말 찾아서 설치하는 수 밖에 없다. 그래서 스크립트 돌려보고 오류가 발생할 때마다 찾아서 설치하고 있었다. 그런데 &quot;~ 수 밦에 없다&quot;는 나의 착각이었다. pip는 이미 퐌타스틱한 기능을 내장하고 있었다. 잠시 살펴보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pip freeze &gt; requirements.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 커맨드를 날리는 순간 pip로 설치된 모든 라이브러리의 목록이 requirements.txt에 저장된다. 내가 갈아탄 3.5에서 실행해보니 아래와 같이 나왔다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;click==6.6
Flask==0.11.1
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
pycrypto==2.6.1
PyExcelerate==0.6.7
PyMySQL==0.7.5
requests==2.10.0
six==1.10.0
slackclient==1.0.0
websocket-client==0.37.0
Werkzeug==0.11.10&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제는 이 requirements.txt만 있으면 일일이 그걸 설치하고 있을 필요가 없다. 바로 &quot;install -r&quot;이라는 마법같은 커맨드가 있기 때문이다. 아래와 같이 입력하면 일괄 설치된다. 넘나 편한것. pip 설치 지원 안 하는 라이브러리는 버려도록 해야겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[py] Python 3.5에서 MySQL 사용하기]]></title><description><![CDATA[파이썬에서 대체로 오라클에서 공개한 mysql.connector라는 것을 사용해서 MySQL 처리를 했었다. 이번에 파이썬 2.7.x에서 3.5로 갈아타면서 라이브러리 설치할 일이 있어서 다운로드를 받으러 갔다. 어랏. 3.3버전용, 3.…]]></description><link>https://jiniya.net/ng/2016/06/python-mysql/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/python-mysql/</guid><pubDate>Tue, 07 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;파이썬에서 대체로 오라클에서 공개한 mysql.connector라는 것을 사용해서 MySQL 처리를 했었다. 이번에 파이썬 2.7.x에서 3.5로 갈아타면서 라이브러리 설치할 일이 있어서 다운로드를 받으러 갔다. 어랏. 3.3버전용, 3.4버전용은 있는데 3.5버전용이 없다. 뭐 3.4 버전용으로 되겠지라는 안일한 생각으로 그걸 받으려고 하는데, 로그인에 내 개인 정보까지 요구하는 오라클. 순순히 모든 정보를 바쳐가며 다운로드를 받았건만 그건 3.5를 지원하지 않았다. 괜히 3.3, 3.4 이런식으로 세부적으로 있는게 아니었다. 괜한 시간 낭비…​&lt;/p&gt;
&lt;p&gt;그래서 검색을 좀 해봤더니 오라클 따위거를 쓰지 않아도 대체제가 있었다. 그 중에 하나가 pymysql이다. 설치도 넘나 간단하다. pip에 다음과 같이 입력하면 끝.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pip install pymysql&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사용 방법은 뭐 mysql.connector와 거의 유사하다. 아니 똑같다고 생각하면 될 정도? 아래와 같은 느낌으로 사용하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; pymysql

conn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pymysql&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;host&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;호스트&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;포트&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;유저&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;비번&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; database&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;디비&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
cursor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cursor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
cursor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;execute&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sql 쿼리&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cursor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fetchall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[py] Python 3.5의 pycrypto 임포트 문제 해결]]></title><description><![CDATA[파이썬에서 암호화를 하려면 pycrypto 라이브러리를 사용하면 된다. pip install pycrypto 하면 문제없이 설치되는데 사용하는데 약간의 문제가 있다. Python 3.5가 설치된 환경에서 pip로 인스톨을 하고 아래와 같이 Random…]]></description><link>https://jiniya.net/ng/2016/06/pycrypt-winrandom/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/pycrypt-winrandom/</guid><pubDate>Mon, 06 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;파이썬에서 암호화를 하려면 pycrypto 라이브러리를 사용하면 된다. pip install pycrypto 하면 문제없이 설치되는데 사용하는데 약간의 문제가 있다. Python 3.5가 설치된 환경에서 pip로 인스톨을 하고 아래와 같이 Random을 임포트 하려면 winrandom을 찾을 수 없다는 오류가 발생한다. 파이썬3로 변경되면서 모듈 포함하는 규칙이 바뀌어서 그런 것 같은데 수정하는 방법은 간단하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# c:\Python35&gt;python&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; Crypto &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Random
Traceback &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;most recent call last&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;stdin&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;module&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;c:\Python35\lib\site-packages\Crypto\Random\__init__.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;m
odule&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; Crypto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Random &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; OSRNG
  File &lt;span class=&quot;token string&quot;&gt;&quot;c:\Python35\lib\site-packages\Crypto\Random\OSRNG\__init__.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;module&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; Crypto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OSRNG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nt &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; new
  File &lt;span class=&quot;token string&quot;&gt;&quot;c:\Python35\lib\site-packages\Crypto\Random\OSRNG\nt.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;m
odule&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; winrandom
ImportError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; No module named &lt;span class=&quot;token string&quot;&gt;&apos;winrandom&apos;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우선 문제가 된 위치의 파일을 찾아간다. c:\Python35\lib\site-packages\Crypto\Random\OSRNG\nt.py 이 파일이다. 해당 파일을 열면 아래와 같이 임포트를 하고 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; winrandom&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드 앞에 &quot;from . &quot;을 붙여주면 된다. 고치면 아래와 같은 코드가 된다. 수정된 내용을 저장하고 다시 임포트시켜 보면 잘 되는 것을 알 수 있다. 배터리는 준비돼 있지만 자질구레하게 손이 가는 곳이 많다. 그래도 배러뤼가 있는게 어딘가?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; winrandom&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[소고] 천재성에 관한 통찰]]></title><description><![CDATA[회사를 시작한지 한 1…]]></description><link>https://jiniya.net/ng/2016/06/about-genius/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/about-genius/</guid><pubDate>Sun, 05 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;회사를 시작한지 한 10년 되다보니 만난 직원이 이제는 제법 된다. 그 중에서도 엔지니어로 일하는 직원들에게는 동병상련같은 감정을 많이 느낀다. 나도 그들과 같은 길을 지나왔고, 어쩌면 지금도 그 길을 가고 있기에 비슷한 생각을 많이 하고 또 유사한 고민도 많이 했기 때문이리라. 그런 직원들의 흔한 고민 거리 중에 하나가 주위의 똑똑한 사람과 자신을 비교하면서 생기는 자괴감이다. 한 직원은 이렇게 말하기도 했었다. 한달 내도록 주위를 보면서 &apos;나는 뭔가’라는 생각에 멘탈이 탈탈 털리다가 그나마 입금되는 월급보고 충전된다고…​&lt;/p&gt;
&lt;p&gt;사실 누구나 쉽게 예상하겠지만 우리 회사에는 다들 고만고만한 사람들이 모여서 일을 한다. 물론 경쟁 업체보다는 많이 똑똑한 엔지니어들을 가려 뽑았다는 자부심은 있다. 하지만 대다수가 비슷비슷하지 크게 다르지 않다. 그런데도 직원들의 상당수, 예외적인 사람 일부를 제외한 거의 대부분은 그 사이에서 비교를 하고 그 과정에서 자연스레 발생하는 불필요한 열등감으로 자신을 갉아 먹는다. 나는 대체로 김난도 선생의 비유를 들어 저마다의 시간이 있으니 굳이 비교할 필요 없이 각자의 길을 가면 된다는 조언을 당당하게 해주지만 어쩌면 이 또한 위선적인 모습인지도 모르겠다. 왜냐하면 나도 제법 프로그래밍을 했을 무렵 비슷한 고민에 빠졌었기 때문이다.&lt;/p&gt;
&lt;p&gt;최근에 &quot;사피엔스&quot; 이후로 엄청난 감탄을 하면서 읽은 책이 있었는데 &quot;틀리지 않는 법&quot;이라는 수학 책이다. 그 책의 천재성에 관한 저자의 견해 일부가 워낙 감탄스러워 여기 발췌해 본다. 아마 저자의 말처럼 이 교훈은 분야를 막론하고 비슷한 고민을 하는 거의 모든 사람들에게 적용되는 조언인 것 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;수학을 오래 하다 보면 깨닫게 되는 것은(그리고 나는 이 교훈이 훨씬 더 폭넓게 적용될 것이라고 생각한다) 당신보다 앞선 사람은 늘 있다는 사실이다. 당장 같은 교실에 있든 아니든 말이다. 이제 막 시작한 사람은 좋은 정리를 증명한 사람을 바라보고, 좋은 정리를 증명한 사람은 좋은 정리를 많이 증명한 사람을 바라보고, 좋은 정리를 많이 증명한 사람은 필즈상을 받은 사람을 바라보고, 필즈상을 받은 사람은 수상자들 중에서도 〈핵심〉에 속하는 사람을 바라보며, 그런 사람은 또 언제나 죽은 사람들을 바라볼 수 있다. 거울을 보면서 〈인정하자, 나는 가우스보다 똑똑해〉라고 중얼거리는 사람은 세상에 한 명도 없다. 그런데도 가우스에 비하면 전부 바보인 사람들이 지난 백 년 동안 힘을 합쳐 노력함으로써 역사상 가장 풍성한 수학 지식을 일구어 냈다.&lt;br&gt;
&lt;br&gt;
수학은 대체로 공동 사업이다. 공통의 목표를 추구하는 거대한 지적 네트워크가 만들어 낸 산물을 각자가 조금씩 더 발전시킨다. 비록 아치를 완성하는 최후의 돌을 얹은 사람이 특별한 영예를 누리기는 하지만 말이다. 마크 트웨인은 이 점을 다음과 같이 잘 표현했다. &amp;#x3C;전신이나 증기 엔진이나 축음기나 전화처럼 중요한 물건을 발명하는 데는 천 명의 사람이 필요했지만, 공은 마지막 사람이 다 차지하고 우리는 나머지 사람들을 잊어버립니다.&lt;br&gt;
&lt;br&gt;
이것은 풋볼과도 비슷하다. 물론 한 선수가 경기를 완전히 장악하는 순간이 있기는 하다. 우리가 이후 오래도록 기억하고 기념하고 회상하는 것은 그런 순간들이다. 그러나 그것은 풋볼에서 보통의 상태가 아니고, 이기는 경기라도 대부분은 그런 순간 때문에 이기는 게 아니다. 쏜살같이 달려 나가는 와이드 리시버에게 쿼터백이 눈부신 터치다운 패스를 하는 데 성공했을 때, 우리는 많은 사람들의 협동 작업을 보는 것이다. 쿼터백과 리시버뿐 아니라 수비팀이 뚫고 들어오는 것을 막아서 쿼터백이 제대로 자세를 잡고 던지도록 시간을 벌어 준 공격팀 라인맨들이 있었고, 그 방어는 또 결정적인 순간에 수비팀의 주의를 흩뜨리기 위해서 핸드오프를 하는 척했던 러닝백 덕분에 가능했으며, 그 밖에도 경기를 조직한 공격팀 감독, 클립보드를 든 그의 많은 조수들, 선수들이 잘 뛰고 던질 수 있도록 돌봐 준 훈련 스태프들… 우리는 이 사람들을 다 천재라고 부르진 않는다. 그러나 그들은 천재성이 벌어질 수 있는 조건을 만들었다.&lt;br&gt;
&lt;br&gt;
테리 타오는 이렇게 썼다.&lt;br&gt;
&lt;br&gt;
흔히 떠올리는 고독한(게다가 약간 미쳤을 수도 있는) 천재의 이미지, 즉 기존 문헌을 비롯한 관습적인 지혜들을 무시한 채 남에게 설명할 수 없는 영감에 따라(어쩌면 듬뿍 가해진 고통이 그 영감을 더욱 강화할 수도 있다) 모든 전문가가 골머리를 썩였던 문제에 대해서 놀랍도록 독창적인 해답을 찾아내는 사람의 이미지는 매력적이고 낭만적이지만, 한편으로는 터무니없이 부정확하다. 적어도 현대 수학의 세계에서는 그렇다. 우리는 물론 수학에 대해서 근사하고 심오하고 놀라운 결과들과 통찰들을 갖고 있지만, 그것은 많은 훌륭하고 위대한 수학자들이 수 년, 수십 년, 심지어 수백 년에 걸쳐서 착실히 연구하고 발전시켜 온 끝에 힘들게 얻어낸 누적적 성과이다. 이해의 한 단계에서 다음 단계로 넘어가는 발전은 굉장히 중대한 사건일 수도 있고 심지어 누구도 예상하지 못했던 사건일 수도 있지만, 그래도 그것은 완전히 새롭게 시작된 작업이 아니라 이전 연구들의 토대 위에 구축된 작업이다. …나는 오늘날 수학 연구의 현실이, 즉 직관과 자료와 약간의 행운에 따라 열심히 노력한 결과로 발전이 자연스럽게, 또한 누적적으로 생겨나는 현실이 내가 학생 때 품었던 낭만적 이미지, 즉 수학은 주로 희귀한 〈천재들〉의 신비로운 영감에 따라 발전한다는 이미지보다 훨씬 만족스럽다고 느낀다.&lt;br&gt;
&lt;br&gt;
힐베르트를 천재라고 부르는 건 틀린 말이 아니다. 그러나 그보다는 힐베르트가 해낸 일이 천재적이었다고 말하는 게 더 옳다. 천재성은 어떤 발생한 사건이지, 어떤 종류의 사람이 아니다.&lt;br&gt;
&lt;br&gt;
-- 틀리지 않는 법&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;조금 실용적인 관점에서 다른 분야에 관한 조언이지만 조엘의 이야기도 곁들여 보면 좋겠다. 조엘은 작은 회사를 운영하는 것에 관해서 쓴 것이지만 나는 개인적으로 이 견해가 개인의 발전과 성장에 관한 것이어도 무관하다고 생각한다. 오늘 하루 아주 조그마한 것이라도 새로운 것을 알아냈다면 그걸로도 만족할만한 일이다. 굳이 거창할 필요도 없고, 조급할 필요도 없다. 안그래도 짧은 인생, 스트레스 받으면서 살지는 말자.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;저처럼 작은 회사를 운영한다면, 쏘면서 움직이는 방법은 두 가지 사항을 의미합니다. 장기적인 안목을 키워야 하며, 매일 조금씩 앞으로 나아가야 합니다. 이렇게 하다보면 조만간 당신이 이길 것입니다. 어제 하루동안 제가 한 일이라고는 FogBUGZ에서 컬러 정책을 조금 개선한 사항뿐입니다. 이 정도면 충분합니다. 조금씩 발전해 나가는 겁니다. 날이 갈수록 우리 소프트웨어는 점점 더 좋아지며, 더 많은 고객을 확보할 수 있다는 점을 노릴 뿐입니다. 오라클 정도로 큰 회사가 되고 난 다음에 거대한 전략을 생각해도 늦지 않습니다. 매일 아침 출근해서 에디터를 여는 것만으로도 충분합니다.&lt;br&gt;
&lt;br&gt;
-- 조엘 온 소프트웨어&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[시스템] 엑셀의 한계]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/06/excel-limits/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/excel-limits/</guid><pubDate>Sat, 04 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;대체로 잘 짜여진 프로그램의 많은 부분들의 한계는 대체로 메모리 한계로 주어지는 경우가 많다. 심지어 스와핑해가며 메모리 한계보다 더 많은 데이터를 처리할 수 있도록 해주는 프로그램들도 있다. 그래서 그랬는지 늘 그저 엑셀은 잘 만든 프로그램이니까 행의 개수나 셀에 들어간 글자수 따위에는 제한이 없을거야, 라는 생각을 많이 했었다. 최근에 회사에서 사용하는 엑셀 시트 생성 파이썬 스크립트의 문제를 수정하면서 나는 내 가설이 옳지 않다는 것을 알게 되었다. 생각보다 엑셀에는 제약이 많았다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.office.com/en-us/article/Excel-specifications-and-limits-16c69c74-3d6a-4aaf-ba35-e6eb276e8eaa&quot;&gt;여기를&lt;/a&gt; 참조하면 MS에서 발표한 엑셀의 공식 한계치들을 알 수 있다. 별 대수롭지 않게 생각할 수 있는데 우리 시트가 깨지는 문제의 원인은 행의 개수때문이었다. 행 개수 제한이 대략 105만개인데 실제로 테스트 해 본 바에 의하면 이것보다 적은 데이터도 엑셀이 정상적으로 열지 못하는 경우가 있어서 100만개로 제한을 걸어두었다. 그 다음으로 다소 황당했던 제한은 셀에 포함될 수 있는 글자수다. 이는 32767개로 제한하고 있다. 그런데 지금 해당 페이지에서 보여주고 있는 제약 사항은 그마나 최신 엑셀 프로그램의 제약 사항들이다. 신뢰할 수 있는 자료인지는 모르겠으나 &lt;a href=&quot;http://superuser.com/questions/366468/what-is-the-maximum-allowed-rows-in-a-microsoft-excel-xls-or-xlsx&quot;&gt;이 페이지를&lt;/a&gt; 보면 과거 버전은 더 많은 제약 사항을 가지고 있었던 것 같다.&lt;/p&gt;
&lt;p&gt;사족: 대략 생성된 엑셀 파일은 80메가 정도 크기였다. 정상이라면 통상적으로 엑셀 실행 시에 데이터가 손상되었다는 메시지가 뜨는데, 테스트 과정 중에 이 메시지 만큼이나 자주 엑셀이 잘못된 연산으로 종료되는 것을 목격했다. 지구상에서 소프트웨어를 가장 잘 만드는 회사 중 하나인 MS 제품도 이 정도다. 소프트웨어 개발은 실제로는 우리가 생각하는 것보다 훨씬 어려운 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] retr에서 발생한 line too long 예외 처리하기]]></title><description><![CDATA[파이썬에서 poplib을 사용해서 POP3로 메일을 받아올 때 retr 함수를 사용한다. 보통은 잘 되는데 어쩔 때 이 함수에서 웃기게도 "line too long…]]></description><link>https://jiniya.net/ng/2016/06/python-poplib-maxline/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/python-poplib-maxline/</guid><pubDate>Fri, 03 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;파이썬에서 poplib을 사용해서 POP3로 메일을 받아올 때 retr 함수를 사용한다. 보통은 잘 되는데 어쩔 때 이 함수에서 웃기게도 &quot;line too long&quot;이란 예외가 발생한다. 찾아가보면 아래와 같은 지점에서 예외를 던지는 것을 발견할 수 있다. 이 경우에 옵션은 두 가지다. 하나는 그냥 그 메시지를 무시하거나 다른 하나는 라인을 더 늘리거나.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_getline&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	line &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;readline&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_MAXLINE &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; _MAXLINE&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; error_proto&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;line too long&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;서버가 던져주는 메시지를 무시하기는 힘들다. 그래서 라인을 늘리려고 찾아가보면 아래와 같이 자뻑형 주석과 함께 있는 상수 선언 부분을 찾을 수 있다. RFC 1939는 512글자로 제한하고 있지만 우리는 더 안전하게 하기 위해서 2048을 택했지라는 ㅋㅋㅋ 하지만 행님들 현실 세계에서는 2048로는 부족하긔~ 나는 대인배니까 값을 그냥 20480으로 변경했다 ㅋㅋㅋ~ 당연한 얘기겠지만 고치고 나자 서버로부터 모든 메시지를 안전하게 수신할 수 있었다. 지금으로썬 딱히 이 상수를 변경하는 것 외에는 방법이 없는 것 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# maximal line length when calling readline(). This is to prevent&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# reading arbitrary length lines. RFC 1939 limits POP3 line length to&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# 512 characters, including CRLF. We have selected 2048 just to be on&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# the safe side.&lt;/span&gt;
_MAXLINE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2048&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[py] 이메일 시간(Date) 타입 다루기]]></title><description><![CDATA[파이썬에서 email.message_from_bytes(데이터)로 획득한 메시지의 시간을 다루는 방법을 알아보자. message_from_bytes로 메일 객체를 msg에 저장했다고 가정한다. 우선 시간은 msg['Date…]]></description><link>https://jiniya.net/ng/2016/06/python-email-date/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/python-email-date/</guid><pubDate>Thu, 02 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;파이썬에서 email.message_from_bytes(데이터)로 획득한 메시지의 시간을 다루는 방법을 알아보자. message_from_bytes로 메일 객체를 msg에 저장했다고 가정한다.&lt;/p&gt;
&lt;p&gt;우선 시간은 msg[&apos;Date&apos;]에 들어있다. 늘 그렇듯이 RFC 형식에 맞춰진 필드 정보지만 바로 datetime으로 바꾸기는 쉽지가 않다. 이때 쓸 수 있는 함수들이 email.utils에 있다. 바로 parsedate_tz와 mktime_tz다. 조합해서 만들어보면 msg 객체의 Date를 안전하게 datetime으로 변환하는 방법은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; parsedate_tz&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mktime_tz
timestamp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mktime_tz&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsedate_tz&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 획득한 타임스탬프 갚은 datetime의 fromtimestamp로 변환해서 사용하면 된다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] UTF-8 INI 파일 다루기]]></title><description><![CDATA[A/W 함수 윈도우 API는 문자열을 다루는 경우에 크게 두 종류의 함수를 제공한다. A/W 함수가 그것이다. A 함수는 멀티바이트로 문자열을 처리하는 함수를 의미하고, W 함수는 UTF-16 방식으로 문자열을 처리하는 함수를 의미한다. A…]]></description><link>https://jiniya.net/ng/2016/06/utf-8-ini-file/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/06/utf-8-ini-file/</guid><pubDate>Wed, 01 Jun 2016 15:00:01 GMT</pubDate><content:encoded>&lt;h3&gt;A/W 함수&lt;/h3&gt;
&lt;p&gt;윈도우 API는 문자열을 다루는 경우에 크게 두 종류의 함수를 제공한다. A/W 함수가 그것이다. A 함수는 멀티바이트로 문자열을 처리하는 함수를 의미하고, W 함수는 UTF-16 방식으로 문자열을 처리하는 함수를 의미한다. A 함수는 파라미터 타입으로 char를 W 함수는 wchar_t를 사용하기 때문에 크게 헷갈릴 일도 없고 직관적이다.&lt;/p&gt;
&lt;p&gt;윈도우는 기본적으로 제공하는 ini 파일 조작 API 관련해서 아래와 같이 이런 두 종류의 API를 제공하고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;WINBASEAPI
DWORD
WINAPI
&lt;span class=&quot;token function&quot;&gt;GetPrivateProfileStringA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    __in_opt LPCSTR lpAppName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in_opt LPCSTR lpKeyName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in_opt LPCSTR lpDefault&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;__out_ecount_part_opt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; LPSTR lpReturnedString&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in     DWORD nSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in_opt LPCSTR lpFileName
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

WINBASEAPI
DWORD
WINAPI
&lt;span class=&quot;token function&quot;&gt;GetPrivateProfileStringW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    __in_opt LPCWSTR lpAppName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in_opt LPCWSTR lpKeyName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in_opt LPCWSTR lpDefault&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;__out_ecount_part_opt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; LPWSTR lpReturnedString&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in     DWORD nSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    __in_opt LPCWSTR lpFileName
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;그렇다면 ini 파일의 포맷은?&lt;/h3&gt;
&lt;p&gt;GetPrivateProfileStringA 함수를 사용하면 멀티바이트 형태로 내가 원하는 값들을 지정하고 거기에 해당하는 결과 값을 멀티바이트 형태로 받을 수 있다. 반대로 GetPrivateProfileStringW 함수를 사용하면 UTF-16 형태로 지정하고 결과를 받을 수 있다. 여기까지만 생각하면 심플하고 복잡할 것도 없지만 조금만 더 호기심을 가져보면 뭔가 애매모호한 것들이 많다. 바로 파일의 형태다.&lt;/p&gt;
&lt;p&gt;lpFileName으로 지정하는 파일은 어떤 형태여야 할까? 어떤 코드페이지로 작성된 멀티바이트 ini 파일도 딱딱 맞춰서 읽을 수 있을까? UTF-8 UTF-16 등으로 작성된 유니코드 파일도 마법처럼 인식해줄까? 아니면 A 함수는 멀티바이트 ini 파일에만 써야 하고 W 함수는 UTF-16 ini 파일에만 써야 할까? 등등의 무수히 많은 질문이 올 수 있다.&lt;/p&gt;
&lt;p&gt;아마 대부분의 프로그래머가 해당 API를 사용하면서 그런 의문을 품지는 않았을 것 같다. 왜냐하면 대충 쓰면 적당히 동작하기 때문이다. 그래서 그런지 MSDN에도 lpFileName으로 지정할 수 있는 파일의 형태에 대해서는 어떠한 언급도 없다. 하지만 컴퓨터의 세계에서 적당히 대충은 항상 문제를 일으킨다. 그래서 조금 깊이 있게 살펴보자.&lt;/p&gt;
&lt;p&gt;윈도우에서 제공하는 ini 파일을 다루는 API는 딱 두 종류의 파일에 대해서만 처리할 수 있도록 설계되어 있다. 하나는 시스템 코드페이지로 작성된 멀티바이트(ANSI) ini 파일이고, 다른 하나는 UTF-16으로 작성된 ini 파일이다. 이는 A/W 함수에 상관 없이 사용된다. ini API 내부적으로 파일을 열 때에 RtlIsTextUnicode를 사용해서 파일에서 읽은 내용이 UTF-16인지 아닌지를 판별한다. UTF-16인 경우에 A 함수를 호출하면 파라미터를 RtlAnsiStringToUnicodeString 함수를 사용해서 변환해서 사용하고, 멀티바이트 파일이 인 경우에 W 함수를 호출하면 반대로 RtlUnicodeStringToAnsiString 함수를 사용해서 파라미터를 내부적으로 변환한다.&lt;/p&gt;
&lt;h3&gt;UTF-8 ini 파일을 다루는 방법&lt;/h3&gt;
&lt;p&gt;그렇다면 윈도우 ini API를 사용해서 UTF-8 ini 파일을 다룰 수는 없는 것일까? 결과론적으론 그렇다. 왜냐하면 API 내부적으로 UTF-8 변환을 지원하지 않기 때문이다. 하지만 대체로 많은 경우에 섹션 이름이나, 키 이름 같은 경우는 영어를 사용하는 것이 관례이고, 키에 해당하는 값에만 ANSI 문자가 아닌 다른 문자가 포함되는 경우가 많다. 이렇게 한정된 조건을 가진 UTF-8 ini 파일의 경우에는 윈도우 ini API를 사용해서 조작하는 것이 가능하다.&lt;/p&gt;
&lt;p&gt;사용하는 방법은 간단하다. W 함수를 사용하면 안 된다. 왜냐하면 내부적으로 UTF-8로 인코딩 된 것을 UTF-16으로 디코딩하려고 시도할 것이기 때문이다. 그러니 무조건 A 함수를 사용하고 받은 멀티바이트 결과 값을 MultiBytesToWideChar 등의 함수로 UTF-8을 디코딩해서 UTF-16 문자열로 처리하면 된다.&lt;/p&gt;
&lt;p&gt;요약하면 저장할 때에는 유니코드 문자열을 UTF-8로 인코딩한 다음 ini A계열 함수를 사용해서 저장하면 되고, 읽을 때에는 ini A계열 함수를 사용해서 읽은 값을 UTF-8로 디코딩해서 유니코드 문자열로 변환해서 사용하면 반쪽짜리 UTF-8 ini 파일을 처리할 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] XIGNCODE에 관한 오해 2]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode-4/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode-4/</guid><pubDate>Mon, 28 Mar 2016 15:00:01 GMT</pubDate><content:encoded>&lt;h3&gt;듀얼 프로텍션&lt;/h3&gt;
&lt;p&gt;게임사의 고유 보안 프로그램과 외부 보안 프로그램을 같이 쓰는 것은 어느 한 쪽의 성능이 나쁘기 때문만은 아닙니다. 당연한 일이겠지만 여러분이 집을 보호한다고 할 때 보안은 여러 단계에 걸쳐서 이루어지면 이루어질수록 좋기 때문입니다. 대문에도 경비를 두고, 거실 입구에도 경비를 두고, 안방 문 앞에도 경비를 둘 때, 단순히 대문 앞에만 경비를 둔 것 보다는 도둑이 침입하기 더 어려운 것과 같은 이유입니다. 거기다 외부 보안 솔루션의 경우 게임 내부를 볼수는 없기 때문에 일정 수준 게임 내부와 밀접하게 연계된 부분을 검사하는데에는 한계가 있을 수 밖에 없습니다. 이런 부분에 대해서는 게임사 내부에서 직접적으로 보안 코드를 작성하는 것이 효율적이기 때문에 두개의 보안 장치를 만들어서 사용하고 있는 추세입니다.&lt;/p&gt;
&lt;h3&gt;스팀 연동&lt;/h3&gt;
&lt;p&gt;XIGNCODE3는 스팀 게임과 연동을 지원합니다. 과거에 스팀에 연동된 게임이 있으며 현재에도 연동해서 사용하는데에 아무런 문제가 없습니다. 현재에도 스팀에서 서비스 중인 게임이 있습니다. 스팀 연동이 불가능하다는 것은 사실이 아닙니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./se.png&apos; data-alt=&apos;게임을 삭제해도 xhunter1.sys는 계속 상주한다?&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0a126a0413acf6ac418935efcc15afb0/9aebd/se.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 60.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACvUlEQVR42kVRW0hTcRj/GxXRQ+BDteipt4SMIDVGPRUahhI+pD6I4IxMG5g2pFGaq6UIdqOSrCjB1C4PJZk3yhvonLudbWcXze24ne3MnXN2zs7Zztn1bB0t8sfHd+P3fR/8PuBevEOtKMIrzYyuhTO1iR5baF6fbrJ9vWr+VGf6WOcZb/BPX/dOXMPn5ME5uX/mhm+q0aqS2e7LQJJBUnE2wYfiHMnSmJDikzEqSpMtZ561Fj5tO/u88URvS8GTuxf6yve2XQStpUBxKUdRAhS1R26BdIzMZLdgg63lxdK6mqqKy2VhOjo3uPbzvW12cHXyDTz9Fp774PzctTLUqRlRLY+oNEMd2i/qCZDiycWFidcvVLLa6mNHc3fvypFIJAxDewNuFEO9PsSHoSEGD+A+r9+9iaMev4sMB3Aaj0UCIBOn9HpNe0dDWYlUWlSUe2A/AECpVJohs8EAmQxGnU4MEAzbpiannXYnBFm0Gg1sW01yBIBc9gHIvbRBDo/NvuruLM6T5B3c0/WgE0Hcer3e4XAgCKJb0dpsjoX5eYvFAkFmixkiQoyQCIFHP8bW4umHKvWpUrn6Zv1Aj7K/reZdr8rucC5rlkRARqPVCuu02mWt1mQ0oj6fH0U3g2QqRoCF+XGtaf10xeP8giq1vLq/XX7lXL6sXiZKGCRCdJglSIplI5EIy/G8GARB2NY3KyoNOBod/jZfWtFUeb6wUnq8u6Hq0D6gUquDsazBE/2NJ9xkMi38fcgWMpmMOC/WW5eTHC62Xt6uP3l4X1/PPZZlf83MUiFym5cVSTtzO8j8u5ziCTELU/To6HecJP+vR30BLIBH+QQb4UXbxEM4QUe5eCTKB/EQFeZYyg8SzHo6QQspJpsVhERY3CV+PskTXrfVh8A0jpABF4UjKAJjXgdNbFBBBPPYccxFYeY/fk8ddBDbbioAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;게임을 삭제해도 xhunter1.sys는 계속 상주한다?&apos; title=&apos;&apos; src=&apos;/static/0a126a0413acf6ac418935efcc15afb0/9aebd/se.png&apos; srcset=&apos;/static/0a126a0413acf6ac418935efcc15afb0/08678/se.png 190w,
/static/0a126a0413acf6ac418935efcc15afb0/2edd7/se.png 380w,
/static/0a126a0413acf6ac418935efcc15afb0/9aebd/se.png 480w&apos; sizes=&apos;(max-width: 480px) 100vw, 480px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;게임을 삭제해도 xhunter1.sys는 계속 상주한다?&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;xhunter1.sys 드라이버는 게임을 켜면 로드되고 게임을 종료하면 언로드 됩니다. 해당 사실은 &lt;a href=&quot;http://www.nirsoft.net/utils/driverview.html&quot;&gt;driverview&lt;/a&gt; 등의 프로그램을 이용하면 손쉽게 확인할 수 있습니다. 게임 실행 후에 목록을 보면 xhunter1.sys가 로드돼 있고, 게임 종료 후에 보면 xhunter1.sys가 시스템에서 언로드 됩니다. 시스템에 지속적으로 남아서 모니터링을 하거나 CPU 자원을 소모하거나 하지 않습니다.&lt;/p&gt;
&lt;h3&gt;차단 근거 미표시&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://jiniya.net/ng/2016/03/misunderstanding-about-xigncode/&quot;&gt;지난 글에서도&lt;/a&gt; 적었지만 현재 서비스 중인 게임 중에도 아래와 같이 차단 근거가 표시되도록 설정된 게임도 존재합니다. 따라서 차단 근거를 무조건적으로 표시하지 않는다는 사실은 잘못된 사실입니다. 해당 사항은 옵션으로 처리돼 있으며 표시할 수도 있고, 하지 않을 수도 있는 사항입니다.&lt;/p&gt;
&lt;p&gt;se
Figure 1. CheatEngine이 차단된 경우의 표시 화면
윈도우 10 지원
윈도우 2000을 제외한 윈도우 XP부터 윈도우 10까지 모든 윈도우 버전을 정식 지원하고 있습니다. 따라서 XIGNCODE3 때문에 윈도우 10에서 게임을 정상적으로 구동할 수 없다는 것은 사실이 아닙니다.&lt;/p&gt;
&lt;h3&gt;스플래시 이미지&lt;/h3&gt;
&lt;p&gt;스플래시 이미지는 고객사에서 설정할 수 있는 옵션 사항입니다. &lt;a href=&quot;http://www.wellbia.com/home/ko/pages/xigncode3-reference/&quot;&gt;홈페이지에&lt;/a&gt; 소개된 상당수 이미지가 고객사에서 직접 제작한 스플래시 화면입니다. 스플래시 화면을 지정하지 않을 경우 기본 이미지가 출력되며, 고객사에서 스플래시 이미지를 설정을 원하는 경우 해당 이미지를 사용하고 있습니다. 이 또한 옵션 사항입니다. &quot;대표 이미지 채택 이벤트&quot;라는 이벤트는 진행된적이 없습니다.&lt;/p&gt;
&lt;h3&gt;출시일?&lt;/h3&gt;
&lt;p&gt;XIGNCODE는 2007년 2월에 개발 시작하였으며, 2008년 3월에 1.0 버전이, 2009년 3월에 2.0 버전이, 2010년 6월에 지금의 XIGNCODE3 버전이 출시되었습니다. 2013년 3월에는 안드로이드 제품인 &quot;XIGNCODE for Android&quot;가 출시되었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] XIGNCODE 디지털 서명에 관한 오해]]></title><description><![CDATA[커널 모드 드라이버 개발을 하는데에 디지털 서명은 필수적입니다. 왜냐하면 6…]]></description><link>https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode-3/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode-3/</guid><pubDate>Mon, 28 Mar 2016 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;커널 모드 드라이버 개발을 하는데에 디지털 서명은 필수적입니다. 왜냐하면 64비트 운영체제 부터는 합법적으로 서명이 되지 않은 드라이버는 동작하지 않기 때문입니다. 즉, 아무리 잘 만들어 놓은들 디지털 서명을 받지 않았다면 컴퓨터에서 로드해서 사용할 수 없다는 이야기입니다. 그러니 응당 디지털 서명은 기본 중의 기본이겠지요. 저희가 제공하는 파일 중에 사용자가 접할 수 있는 모든 파일은 VeriSign 인증서를 통해서 서명이 된 후에 배포됩니다. 그러니 적합하지 않은 형태로 디지털 서명이 되어 있다거나 디지털 서명이 되어 있지 않다거나 하는 이야기는 사실이 아닙니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./cert1.png&apos; data-alt=&apos;Figure 1. xhunter1.sys 파일의 등록 정보&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 484px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/bfe6d551fa2e283f9979384c0e8b83d9/6ad3c/cert1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 121.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAIAAAB1KUohAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACP0lEQVR42u1UyW4TQRD1n3ILESSII2cO/AKfEAkJzmFREic4jrFBJI6dzDiz9Cw9q2ezZ+2N8jgEGSVSzoinp1aVpl5XTXdXdfDgdTJ6Ffefx4Pd5NuLaLCbjV463WfS/rbycVv59FTe3zIPtpPB7ry/EwFPd+LRjvZ26+LNk45z9V6enAXmuXUzRFLfVoba9SnYs/GxLg3meBriSeRsEl9mc8WVPnQ89QTZ8TIvF3mZLYtlXmA3iNPc8cJwnlU1Lyv2F4uSlES4Nyed2OxRLhxsI6QzShkDMs6oEJxzMBislJJNNlwITznsRMZXBpbr6qBGKC+KhtA0yxaLZRCECBmmZdWENC1r0jQNqaqKMOEr3ZVYCKFp6uV4MpvNTNO0bcvzfdO0wJ4CJlPQS7IsyZKqqbCbYZq34tjoQYlVVdIWpAVti1u7TYt6hWqVF/LX1YYYQsSjAXs2f8RcBL5nPQzbtjHGTgvP87IkIVT4avf2wPJ8mT6MMIpdP7QcD5m24wVRkhIOmY9WYr6qhd1bIW+/RYtSt4NLSe0Pf05kXcdB3oigzdyDAEYJexiEsqJq1szLuijr9p6PVv/cpmCPP7B18H/xvyLm6/f127tHHKETygRtKmiVDcKbgznC1t1J+J1NGs7AhTF00AlRPy1EmhXporpjkpVhtNAQxu58Hi9hmOkGNFQUJTmMN+yGUUYdmGHe9F1oj0NjFJrf7xgYI6z05fPP6uTQUc+sWe9m/AVdH7vawEdD46rroR/Wxd4v0pVIixWqrgIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 1. xhunter1.sys 파일의 등록 정보&apos; title=&apos;&apos; src=&apos;/static/bfe6d551fa2e283f9979384c0e8b83d9/6ad3c/cert1.png&apos; srcset=&apos;/static/bfe6d551fa2e283f9979384c0e8b83d9/08678/cert1.png 190w,
/static/bfe6d551fa2e283f9979384c0e8b83d9/2edd7/cert1.png 380w,
/static/bfe6d551fa2e283f9979384c0e8b83d9/6ad3c/cert1.png 484w&apos; sizes=&apos;(max-width: 484px) 100vw, 484px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 1. xhunter1.sys 파일의 등록 정보&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./cert2.png&apos; data-alt=&apos;Figure 2. xhunter1.sys 디지털 서명 정보&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 484px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/def56b1d18141516d31dacd49e685887/6ad3c/cert2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 115.26315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAC/ElEQVR42o1Ty27bRhTVXzabOkAKufmMfEmAFGgXRVEkQRZdNIlai1KMLGyjdhw9LIqcofgQ3+8Zzgx7KMZyHBtJri6GI4nnzjnn3hlsx8No+nOoHcbTx+HkMNCG4WRoj366eHnw8dXB5auDixc/ktePosmhPx6G2nA7Ga6fPzx5/MPpkweD7Ydf6WwUGOP1+V9YY/ousY5Dc7pda13qmqdr/loLzclNGuOIvN+c/TLwDS1MWFXXyxVxtlGS1WFcZCWvuaqYLCuBLKomLz/LgpW8da6OBgnViloRohd5upjPlovF6cmJ69hVVSKlkm2rvkwl2rZ1r94OYjKpWJunsWiaNE1c17Vt2/M8atGt7zdN096NriLAo0FkathxzmrGhLjv1bvYGzDRGtlSYm5s27KshuMw6GQVa8qaVzWvGb8TTPXg0Bx3O9dphOgLEzf+bbT6Y2r9+d79/Z1zdOlzxko4cBOl2tMWqvW3HvBgDnCWZfPlamUQg1h04yRpXl/H/eA4CqMwRMMAzvNM11cUjhECIYHvJ2kaRlEcx3mel10Ut2gH/hb/QU1/skWp57nw3HHsta5TSh0HffCyPJdSNQ2/BW5b+RV74SF4maZJLZSlcRxJBfA/n8BKCXUdch8Kny6hFo7ouk4IMQwjCHzRgzEkjHeGIdI07cEdRqlulpTcF90TkVLcMgzF0Gd7Y6OpRVGkO4fgE/bwIgxDNAITsLOcwXWxp41iMGa+WFwtl34QodCHy8vl1Wqz2SRpgt9n8zlKw2qxC7Sdi9ZbdWBN7tqTJAnWNMsYY0EQYCqwgQSwyLMMhhVF3tPGFHPZeji5p80Z34np7eoE9lsh5BeCOzDc78G922I3013snvzTN7HLTiqU+76PVoMULp/8/j5DJwQDj45EcVRgVHpwYPwL9awuWXcp70/c14YzEJIC1wcrE7J1lm8GgTmNCxUneZyWX88kLd2oIk56MTeoz9azowE9e2avNHvx1l6OvpnmfDT77++z45fz89Hs+On/ce/9eRE4ijUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 2. xhunter1.sys 디지털 서명 정보&apos; title=&apos;&apos; src=&apos;/static/def56b1d18141516d31dacd49e685887/6ad3c/cert2.png&apos; srcset=&apos;/static/def56b1d18141516d31dacd49e685887/08678/cert2.png 190w,
/static/def56b1d18141516d31dacd49e685887/2edd7/cert2.png 380w,
/static/def56b1d18141516d31dacd49e685887/6ad3c/cert2.png 484w&apos; sizes=&apos;(max-width: 484px) 100vw, 484px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 2. xhunter1.sys 디지털 서명 정보&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./cert3.png&apos; data-alt=&apos;Figure 3. xhunter1.sys 디지털 서명 인증 경로&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 484px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/85e0b60027a93ae7bb135127cc04ca83/6ad3c/cert3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 122.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAIAAAC+dZmEAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACPUlEQVR42t1Sy27aQBT1Z3bDqiTtvst+SldV1UWkpmmqVIrUKA8SQheVShLAgAGDwRjjGY9tbIzn2bEJFQkQkm2Pjsfj0Zz78D2K/es9Kr1FxbxXeoOud1BpF13vusU8uHqtfs+pRzlYzC8TXObR7x39Q6787pVi1Q6M2s+RdqLfHVnNk37teKAew17BNS4dvSApNyssIKMEGoeK2fnT6tkO9FqdPnQDAD0AvHCKwynZyAiHsYBWUwlB3fPDgdHTO3oQ+FxwSinGOMGYYExJSoKTZeIkZlz4tqpMnIY/iQa9lt7uIAiEoJxhwYlgOEmS2UwuMg6mS0hDE+6PG0owVhMiJj4w9MbBRfXzRXevaHwq6B9PtVqzBx0HAOAHgVgCYxT/E2OSHoWBW6jDw7vpt9tw/yb6Wg5AMJPnnItHYIxJyUJM5Q0mVsAXkNutYs7ki8umBWXyhtiEZ2X+n8Vyzi8UL82ZUCG9hJ/E3GrzNY7jBGdif6yKtVZ4WKfruoZhmMOhaZrjsT1L6H1mWTFlqWlZNly+DqmfM5MnWQXSDp5dT8VDy5HxNK0JIZQ+mUd5hAeR5KfIxN6oqrW7zWaj3dL0TqdvmlEUTVcQLSEMJ/GMpGJo3sYJy4q9f7b/7uxOKkZWJZ0zW1PqRsi+xKLnLNgL5jzP7Gc9VwjheDbFctTPIU4oJTI1GlUVaNVRyJAfoSB+ml4Q2yg2xuFNvdcehv2+pjj1L7B7BfUzqJ9vpd0+NxqnWvlHVz3rV/b/AmPrh6Le9gnhAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 3. xhunter1.sys 디지털 서명 인증 경로&apos; title=&apos;&apos; src=&apos;/static/85e0b60027a93ae7bb135127cc04ca83/6ad3c/cert3.png&apos; srcset=&apos;/static/85e0b60027a93ae7bb135127cc04ca83/08678/cert3.png 190w,
/static/85e0b60027a93ae7bb135127cc04ca83/2edd7/cert3.png 380w,
/static/85e0b60027a93ae7bb135127cc04ca83/6ad3c/cert3.png 484w&apos; sizes=&apos;(max-width: 484px) 100vw, 484px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 3. xhunter1.sys 디지털 서명 인증 경로&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;더욱이 64비트 윈도우 부터는 오브젝트 필터링 콜백이라는 것을 사용하기 위해서는 마이크로소프트에 용도를 통보한 후에 고도를 할당 받아서 사용해야 합니다. 이것은 상기 디지털 서명처럼 반드시 해야 하는 일은 아니지만 정상적인 업체라면 해야 하는 그런 일 입니다. 당연히 저희 또한 마이크로소프트 측에 드라이버의 용도에 관한 통보를 했고 해당 고도를 할당 받아서 사용하고 있습니다. 이는 마이크로소프트 홈페이지를 참고하시면 아래와 같이 정보가 노출되는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./altitude.png&apos; data-alt=&apos;Figure 4. xhunter1.sys 오브젝트 필터링 콜백 고도&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 699px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b1cda3cee7d4a8ae374aa9e4277bfa95/6a959/altitude.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 18.421052631578945%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAcUlEQVR42nWO2RYDIQhD/f9vrbiw2LGITWdea54CnBuSiKiUUms1s/WTMzOW7i7MY4xY4QclUVGVa87lHhF7b1WrtcEjDrf5mXFQKkStd8QAe2BhyZngReSVM0q9r+sI9xu+O6+HwWfMZtpag0f6+qcvIaTpdvImFRQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 4. xhunter1.sys 오브젝트 필터링 콜백 고도&apos; title=&apos;&apos; src=&apos;/static/b1cda3cee7d4a8ae374aa9e4277bfa95/6a959/altitude.png&apos; srcset=&apos;/static/b1cda3cee7d4a8ae374aa9e4277bfa95/08678/altitude.png 190w,
/static/b1cda3cee7d4a8ae374aa9e4277bfa95/2edd7/altitude.png 380w,
/static/b1cda3cee7d4a8ae374aa9e4277bfa95/6a959/altitude.png 699w&apos; sizes=&apos;(max-width: 699px) 100vw, 699px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 4. xhunter1.sys 오브젝트 필터링 콜백 고도&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;추가로 인증서 유효 기간에 대해서 말씀 드리면 인증서의 동작 방식은 인증서가 유효한 기간 내에 서명이 된 것인지를 체크하는 구조입니다. 따라서 아래 파일을 보면 인증서가 2014.1.23부터 2016.3.24까지 유효한데 파일은 2015.6.4에 인증되었다는 것을 나타냅니다. 이 파일의 경우 인증서 유효 기간이 지난 후에도 정합성을 인정 받는 파일입니다. 따라서 드라이버 코드가 변경되지 않는 이상 인증서 때문에 새로운 파일을 배포 하거나 할 필요는 없습니다. 더 자세한 내용이 궁금하신 분들은 마이크로소프트 설명 페이지를 참고하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./cert4.png&apos; data-alt=&apos;Figure 5. xhunter1.sys 디지털 서명 인증서 유효기간&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/7f94af0715657b52ed4801a93e1717d9/dface/cert4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACEUlEQVR42j1Ry04UQRSdX/MT3Ctx6cb4Fy5QE3Vn3BlCBBcKigs3hpCwGCAKgyYGAaVfM931nnpXdZW3Z4CTm+ru3Dr3nHt6xH49x2fr/Hyd/VmrJ2+K49f47C07X2t+rU3Hj8nhI3Tyanb0BP1YbY6GopNnZPIUf39Zbz8ckenPKfZFheqZoCJw1UuTlemVz+zqC73YYDLVdYOJMDZo44fSxoQs652R7I7hm1HEKDFG5wEppwgPXW2x83fNFJfFpdLKOWsWsEb5PqvyM5BPmNDOD535fK61dnDL6pCgvc0vN8FIVRVt17Zt10ybqqqEoDBaVUBGEyFtjAEhVBQFnMC3Zkne4hcbKecYnPfeLRBCTAtfqtoZKTSxLgFZSokxJgR3gHZm/FJ5g8vUtjNCaYcQIcRaG4OPt2TnUwwh3wD8I9QOsZXb4u8mZMMZATtCCGD6AfZaWePTDjFwSwnFS2lCYh9gtiy2xOWm67PgbC4lJMIY45w7Z25tnxrXaw1xKkj7WgF27q/JsLPRylgbFgDdvg835O5k8XdiTv1QOYErzjGspcqP8ur90FwkBPqzpqZclNO2xkYUOyPe/pYuz3WCJYfSCd6FDB3P+OKTKj7AvNjH2GfrkzLRQpDGD5Ty60ju35XjB3K8og5W1OGKXNbBPTa+L/fv0NNVUh6Qf9/I1S4t9li5Byctdquz3Xby4j8B8ZAbMewZkgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Figure 5. xhunter1.sys 디지털 서명 인증서 유효기간&apos; title=&apos;&apos; src=&apos;/static/7f94af0715657b52ed4801a93e1717d9/dface/cert4.png&apos; srcset=&apos;/static/7f94af0715657b52ed4801a93e1717d9/08678/cert4.png 190w,
/static/7f94af0715657b52ed4801a93e1717d9/2edd7/cert4.png 380w,
/static/7f94af0715657b52ed4801a93e1717d9/dface/cert4.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;Figure 5. xhunter1.sys 디지털 서명 인증서 유효기간&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그리고 더 많은 기술적인 설명이 필요한 내용인데 드라이버를 정상적인 방식으로 로드하기 위해서는 반드시 레지스트리에 그 값을 기록해야 합니다. 그래야 윈도우에서 그 정보를 알고 드라이버를 로드해 주기 때문입니다. 더 자세한 내용을 설명하기 위해서는 너무 많은 기술적인 내용을 설명해야 하기에 이쯤에서 줄이도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;그러니 더 이상 디지털 서명이 잘못된 파일이라던지 드라이버가 잘못된 형태로 운용되고 있다는 오해는 가지지 않았으면 하는 바램입니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] XIGNCODE 요구 권한에 관한 오해]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode-2/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode-2/</guid><pubDate>Sat, 26 Mar 2016 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;권한에 관해서 궁금해 하시는 분들이 많이 계신 것 같습니다. 도대체 왜 일게 서드파티 보안 프로그램이 그것도 시스템의 모든 곳에 접근할 수 있는 &quot;관리자 권한&quot;을 요구하는지에 대해서 의문이 없다면 그게 더 이상한 일일 겁니다. 저라도 당연히 의문을 가졌을 것 같습니다. 그래서 오늘은 그런 권한에 얽힌 오해를 조금 풀어보려고 합니다.&lt;/p&gt;
&lt;h3&gt;권한이란 무엇이고 왜 필요할까?&lt;/h3&gt;
&lt;p&gt;이 글을 컴퓨터에 관한 전문 지식이 없는 분들도 보실 수 있기에 권한 이라는 것이 정확하게 어떤 것이고 왜 필요한지에 대해서 먼저 설명을 드려야겠습니다. 권한은 쉽게 말하면 방문을 여는 키와 같다고 보시면 됩니다. 집에 방이 세 개 있다고 가정해 봅시다. A, B, C라는 방이죠. 여기에서 아빠는 A, B, C에 모두 들어갈 수 있는 키를 가지고 있고, 아들은 C 방에 들어가는 키만 가지고 있습니다. 이 상황에서 모든 방을 다 들어가 볼 수 있는 사람(여기에서는 아빠)를 관리자 권한이라고 부르며, 일부 제한된 자신의 접근 구역에만 접근할 수 있는 사람(여기에서는 아들)을 사용자 권한이라고 통상적으로 부릅니다. 집에서는 아빠는 잠겨 있는 모든 방에 접근할 수 있지만, 아들은 C에만 접근할 수 있습니다. A, B가 궁금해도 키가 없으니 접근을 하지 못하는 것이죠. 컴퓨터에서도 마찬 가지입니다. 어떤 파일을 읽기 위해서는 권한이 필요합니다. 거의 대부분의 파일을 읽을 수 있는 권한이 관리자 권한, 자신의 파일만 읽을 수 있는 것이 사용자 권한이죠.&lt;/p&gt;
&lt;p&gt;자 이제 앞의 상황에서 도둑이 들어서 어떤 방에 숨어있다는 다소 엉뚱하면서도 황당한 상상을 해 봅시다. 도둑이 A나 B 방에 숨고, 문을 잠궈버렸다면 아들은 도둑을 발견할 수 있을까요? 없을까요? 당연히 없을 겁니다. 반대로 C 방에 숨었다면 아들도 발견할 수 있습니다. 하지만 아빠의 입장은 다릅니다. 도둑이 어디에 숨어있든지 방문을 열고 볼 수 있기 때문에 도둑을 찾을 수 있습니다. 결국 권한이 높다는 것은 더 많은 것을 찾고 발견할 수 있다는 것을 의미합니다.&lt;/p&gt;
&lt;p&gt;게임 보안 솔루션이 권한을 요구하는 것도 동일합니다. 매크로나 해킹툴을 사용하여 게임 경험을 해치는 불법 사용자를 가려내는 것이 저희의 임무입니다. 권한이 낮다면 앞에서 아들과 같이 불법 사용자가 C방에 숨은 경우만 찾아낼 수 있습니다. 반대로 관리자 권한을 가졌다면 어디에 숨어있든지 찾아낼 수 있을 겁니다.&lt;/p&gt;
&lt;h3&gt;빈대 잡으려다 초가삼간 태우는게 아닌가?&lt;/h3&gt;
&lt;p&gt;이런 권한의 메커니즘을 이해한 다음의 문제는 조금 철학적입니다. 높은 권한이 있다면 더 많은 부분을 검사해서 발견해 낼 수 있다는 건 알겠지만 그게 과연 옳은 결정이냐는 것입니다. 여기에 대한 가치 판단은 저마다 다르고 상황마다 다를 수 있습니다.&lt;/p&gt;
&lt;p&gt;일반적으로 해킹툴이 별로 없고 거의 대다수 사용자가 정상 플레이를 하고 있는 게임이라면 당연히 권한을 최소한으로 요구하는 것이 맞을 겁니다. 왜냐하면 게임 플레이를 하면서 해킹툴 사용자를 만날 일도 별로 없는데 높은 권한으로 많은 검사를 할 필요가 없기 때문입니다. 반면에 해킹툴이 너무 많고 거의 대부분의 사용자가 어떻게든 불을 켜고 해킹툴을 사용하려는 게임이라면 관리자 권한을 요구할 수도 있을 겁니다. 물론 관리자 권한을 요구한다고 그런 모든 것을 발견하고 막을 수는 없겠지만 어쨌든 발견할 수 있는 확률은 높아지니까요.&lt;/p&gt;
&lt;p&gt;결국 요약하면 이런 겁니다. 높은 권한은 해킹툴을 발견할 가능성이 높아지지만 사용성이 떨어지고, 낮은 권한은 해킹툴을 발견할 가능성은 낮아지지만 사용성은 높아지는 겁니다. 즉, 이는 어떤 한 가지를 일방적으로 고수할 문제가 아니라 그 사이에서 게임 운영자가 자신들의 게임에 맞게 적당히 절충하면 되는 문제입니다. 음, 우리 게임은 해킹툴 사용자가 너무 많으니까 지금 당장은 높은 권한을 유지해서 발견 가능성을 높이자라던지, 아니면 우리 게임은 거의 대부분이 선량한 사용자니까 낮은 권한으로 하돼 추후 문제가 생기면 다시 조정하겠다는 것과 같이 말이죠. 결국 여기에는 절대적으로 옳은 정답은 없으며 각각의 상황에 맞춰서 해킹툴 발견 가능성과 사용성 중에서 어느 것을 더 중시할지를 고르면 되는 문제입니다.&lt;/p&gt;
&lt;h3&gt;옵션&lt;/h3&gt;
&lt;p&gt;결국 앞의 절충의 문제라는 것 까지 이해했으면 솔루션 개발자 입장에서의 정답은 무엇일까요? 옵션입니다. 게임 운영자가 자신의 게임 특성에 맞춰서 적절하게 설정해서 사용할 수 있도록 만들어 주는 것이죠. 고정해 놓는 것이 아니라 변동 가능하도록 구성하는 겁니다. XIGNCODE3도 마찬가지 입니다. 다양한 고객사들의 입맞에 맞추기 위해서 권한 레벨을 아래와 같이 세 분류로 조정해서 적절하게 설정해서 사용할 수 있도록 가이드를 해드리고 있습니다. 낮음으로 사용하시길 원하는 경우에는 게임 권한 설정에 따라서는 아예 &quot;관리자 권한&quot;을 요구하지도 않으며 &quot;커널 모드 드라이버&quot;를 설치 및 로드하지도 않습니다. 보통 단계는 얻을 수 있는 상황인데 얻지 못하면 페널티가 주어지는 것이며, 높음 단계는 항상 &quot;관리자 권한&quot;을 요청하는 단계입니다. 그러니 저희가 무조건적으로 &quot;관리자 권한&quot;을 요구한다는 것은 정확한 사실이 아니라는 점 꼭 기억해 주셨으면 좋겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./auth-level.png&apos; data-alt=&apos;XIGNCODE3 권한 범위&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 568px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f9e6a209b7ef4b64b2adf9595e137375/d63a8/auth-level.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 61.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB3UlEQVR42oVSS5KiQBDljC4M2nbhCZgzeAmvMh1h9Ah0qIvpcOcngOL/VaCKls+ATDiv0FnMal4FSVZmVuarzBKiKIqjaLlcbrfb729vlLLr9fr1PxRFUde1wBgLggApggFDKo44jv+Rj/XXFYYhpVRYLBaz2UySvkmSNB6PXx+YTERRxF8UXyBfJhNue/pep9PpaDSaz+fC8XDY7/e73W6z2cjySlVVWVF+vL/LsgzLh6oqisIllvqBq8mr1Xq9Rtjnz08B1O/3e5LEWZZBr6uyLKuqrH5xNG3bVnXVNE1VcQkT3M2gIVCAte97XADW2+3WdV2L1XWIw8nuibbvuQ8WKFz+7hHwrBxFoW3bjus4jqvruqHr2JqmSUzi2Lbne3DYtgULWuW5rmVZvu8L6DsywWfohmEQdDLP80uaUsag4C6UUYyG8W3GCoYhMcoBl+AHweVywQA0TTscDoSYvu+BBIrEceIBvoe0tmWhNDihJiEEdRzXfdJGQYSBGjFNx7Y0TcdhHuE4aZalAyjN0zRDZc4nzXLMGQ8DDuQ7no66pmFsBiGn0wknTdDg9WNcD+yCwE/i5Hw+o0ySJGEUCWBfVTXcPJq3iBTFF+jwOeFrmnIAhoLuPHS838f2Dw/XatY41aJeAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;XIGNCODE3 권한 범위&apos; title=&apos;&apos; src=&apos;/static/f9e6a209b7ef4b64b2adf9595e137375/d63a8/auth-level.png&apos; srcset=&apos;/static/f9e6a209b7ef4b64b2adf9595e137375/08678/auth-level.png 190w,
/static/f9e6a209b7ef4b64b2adf9595e137375/2edd7/auth-level.png 380w,
/static/f9e6a209b7ef4b64b2adf9595e137375/d63a8/auth-level.png 568w&apos; sizes=&apos;(max-width: 568px) 100vw, 568px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;XIGNCODE3 권한 범위&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] XIGNCODE에 관한 오해들]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/03/misunderstanding-about-xigncode/</guid><pubDate>Fri, 25 Mar 2016 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;최근 게임 커뮤니티에서 저희 제품에 대한 오해가 많이 생기고 있는 것 같습니다. 게이머들이 좋아하는 보안 제품을 만드려고 했는데 오해만 잔뜩 키운것 같아서 한 명의 게이머로써 착찹한 생각이 많이 듭니다. 건설적인 비판은 새겨 들어야겠지만 원색적인 비난이나 잘못된 사실로 인한 오해는 바로 잡을 필요가 있다고 생각됩니다. 특히나 최근 제 개인 메일이나 블로그 댓글로 문의가 많이 와서 여기에 최근 게이머들 사이에서 유통(?!)되고 있는 대표적인 몇 가지 오해에 대한 해명을 해볼까 합니다.&lt;/p&gt;
&lt;h3&gt;SSD 수명을 단축시킨다.&lt;/h3&gt;
&lt;p&gt;일반적으로 SSD의 경우 재기록 가능 회수가 한정되어 있습니다. 재기록 가능 회수란 쉽게 말하면 점토판에 쓰여진 내용을 지우고 다른 내용을 기록하는 것을 말합니다. 그 회수가 10번이라면 지우고 새로운 내용을 기록하는 것을 10번하고 나면 새 점토판을 사야 한다는 의미입니다. 여기에서 중요한 것은 내용을 지우고 새로 기록하는 회수가 한정되어 있다는 의미입니다. 따라서 적혀져 있는 내용을 읽는 것과 수명은 크게 상관이 없습니다.&lt;/p&gt;
&lt;p&gt;일반적인 보안 프로그램의 경우 디스크에 존재하는 프로그램의 정체(?!)를 파악하기 위해서 해당 파일의 내용을 읽습니다. 단순히 읽기 동작만 있을 뿐 랜섬웨어처럼 해당 파일의 내용을 변경하고 새로 기록하는 등의 행위를 하지는 않습니다. 따라서 이는 앞선 비유에 따르면 순수하게 점토판의 내용을 읽는 것과 동일하므로 SSD의 수명과는 크게 상관이 없습니다.&lt;/p&gt;
&lt;p&gt;요약해보면 여러분이 사용하는 SSD의 수명은 토렌트나 랜섬웨어, 다운로드 프로그램에 의해서 단축될 수 있지만 파일의 내용을 주로 읽기만 하는 보안 제품 때문에 수명이 일반적이지 않은 수준으로 단축되는 일은 없습니다. 저희 제품도 마찬가지구요. 그러니 안심하셔도 됩니다.&lt;/p&gt;
&lt;h3&gt;동영상 파일에 접근 하고 심지어는 그 파일을 외부 서버로 전송한다.&lt;/h3&gt;
&lt;p&gt;여러분의 동영상 파일이나 개인 데이터 파일에 아무 이유 없이 접근하지는 않습니다. 일부 조건들이 충족될 경우 해당 파일들이 검사 대상 목록에 추가되기도 합니다. 하지만 이렇게 말해도 여전히 실행 파일도 아닌 동영상 파일에 접근하는 이유가 이해가 되지 않으실 수 있습니다. 아이러니하게도 저희가 동영상 파일을 읽은 이유는 해당 파일이 진짜 동영상 파일이 맞는지 확인하기 위함입니다.&lt;/p&gt;
&lt;p&gt;일반적으로 avi, mp4 등의 확장자는 동영상이라고 생각하지만 사실 해당 파일들의 내용물이 동영상이 아닌 실행 가능한 코드인 경우도 존재합니다. 그리고 그런 것들이 탐색기에 의해서는 실행되지 않지만 특수한 목적으로 제작된 프로그램에 의해서는 실행이 가능해 지기도 합니다. 따라서 파일의 확장자가 아닌 진짜 파일의 정체를 알아내기 위해서는 해당 파일의 일부를 읽는 동작을 할 수 밖에 없습니다. 이는 로컬 PC에 존재하는 파일의 형태를 파악하기 위함이지 다른 목적은 전혀 없습니다. 더욱이 많은 사용자 분들께서 오해하고 있는 것처럼 해당 파일을 외부 서버로 전송하거나 하는 일은 없습니다.&lt;/p&gt;
&lt;h3&gt;개인 정보를 유출시킨다.&lt;/h3&gt;
&lt;p&gt;인터넷을 통해서 연결이 가속화될수록 개인 정보는 점점 더 중요한 이슈로 부각됩니다. 연결을 위한 욕망 만큼이나 개인 정보를 보호하고 싶은 욕망도 강하지요. 어쨌든 이런 이유로 많은 국가에서 다양한 형태로 개인 정보에 대한 법적 규제를 가지고 있습니다. 잘 아시겠지만 우리가 즐기고 있는 게임도 더 이상 주먹구구식 코흘리게 사업이 아닙니다. 그말인즉 개인 정보에 관한 법적 규제를 엄격하게 받고 있다는 의미입니다.&lt;/p&gt;
&lt;p&gt;게임에 함께 포함되는 서드파티 제품도 동일한 규제를 적용 받습니다. 개인 정보 보호에 관한 감사를 받으며, 제품 도입 시에 서비스 지역에서 시행되고 있는 개인 정보 보호법에 부합하는지에 대한 법률 검토 또한 함께 받습니다. 따라서 여러분께서 우려하시는 것처럼 개인 정보를 무단 수집하거나 함부로 유출하는 일은 없습니다. 게임이 서비스 되는 지역의 개인 정보 보호법과 게임 내에서 출력되는 최종 사용자 라이선스 계약(EULA)을 엄격하게 준수하고 있습니다. 안심하셔도 됩니다.&lt;/p&gt;
&lt;h3&gt;듀얼 클라이언트를 차단한다.&lt;/h3&gt;
&lt;h3&gt;VMWare, VirtualBox, SandBoxie 등의 정상 프로그램이 탐지된다.&lt;/h3&gt;
&lt;h3&gt;게임에 특정 키보드, 마우스를 사용할 수 없다. (게임사 정책에 의해 사용이 제한된 하드웨어)&lt;/h3&gt;
&lt;p&gt;차단 근거를 표시하지 않는다.
저희는 게임사에 게임 보안에 사용할 수 있는 도구를 제공할 뿐 정책을 제공하지는 않습니다. 위와 같은 내용들은 모두 게임사의 정책에 기인한 것이지 저희가 임의로 설정하는 내용이 아닙니다. 저희가 하는 일은 게임사에서 수립한 정책대로 동작하는 프로그램을 공급하는 것이 전부입니다. 나머지는 모두 저희 권한 밖의 일이랍니다.&lt;/p&gt;
&lt;h3&gt;윈도우 커널 모드 드라이버를 설치한다. 따라서 루트킷이다.&lt;/h3&gt;
&lt;p&gt;보안 제품이 완전한 검사를 수행하기 위해서는 관리자 권한이 필요합니다. 당연한 이야기이겠지만 권한이 낮은 상태에서 권한이 높은 대상을 검사할 수는 없기 때문입니다. 그냥 단순 비유를 들자면 선생님이 학생을 검사할 수는 있지만, 학생이 선생님을 검사하기는 힘든 뭐 그런 것이라고 이해하시면 됩니다. 이러한 완전한 권한을 가지기 위해서 저희 제품 또한 커널 모드 드라이버를 설치하여 로드하고 있습니다.&lt;/p&gt;
&lt;p&gt;여기에 대해서는 기술적인 많은 이야기들이 필요하지만 몇 가지 사실들만 나열하겠습니다. 1) 여러분께서 알고 계시는 거의 모든 게임 보안 제품은 커널 모드 드라이버를 설치합니다. 2) 해당 제품들 중의 일부는 프로세스를 숨기거나 강제 종료를 막거나 키보드 후킹을 하는 등의 루트킷스러운 기능을 가지고 있기도 합니다. XIGNCODE3의 드라이버는 일반적인 윈도우 사용자 경험을 위배하는 이와 같은 기능은 전혀 포함하고 있지 않습니다. 3) XIGNCODE3에 포함된 커널 모드 드라이버 또한 앞서 기술한 것과 마찬가지로 게임사의 정책을 따르고 있습니다. 커널 모드 드라이버 설치를 원하지 않는 게임의 경우에는 게임 실행 시점에 커널 모드 드라이버를 설치 및 로드 하지 않습니다.&lt;/p&gt;
&lt;h3&gt;게임이 끝나도 남아서 계속 모니터링한다.&lt;/h3&gt;
&lt;p&gt;해외 게임 보안 제품 중에 일부 이러한 제품이 있습니다. 하지만 저희 제품은 아닙니다. 여러분이 게임을 종료하는 순간 저희의 모든 기능은 중단됩니다. 남아서 모니터링을 한다거나 시스템 자원을 소모 한다거나 하지 않습니다. 자동 재시작 프로그램으로 등록되지도 않습니다. 저희 제품의 생명 주기는 게임과 완전히 동일합니다. 여러분이 게임을 구동하면 XIGNCODE3가 함께 구동되며 게임을 종료하면 XIGNCODE3도 함께 종료됩니다.&lt;/p&gt;
&lt;h3&gt;해외에서는 사장되었다.&lt;/h3&gt;
&lt;p&gt;이 글을 작성하는 현 시점을 기준으로 저희 제품은 국내보다 해외에 더 많이 공급되어 있습니다. 아프리카를 제외한 거의 모든 지역에서 서비스되는 게임에 탑재되어 있습니다. 따라서 해외에서 사장되었다는 이야기는 정확한 사실이 아닙니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] 신뢰할 수 있는 루트 인증서 자동 업데이트]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/02/disable-root-auto-update/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/02/disable-root-auto-update/</guid><pubDate>Fri, 26 Feb 2016 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;윈도우에서 신뢰할 수 있는 루트 인증서를 삭제 했음에도 마법처럼 루트 인증서가 계속 생기는 경우가 있다. 신뢰할 수 있는 루트 인증서와 없는 인증서에 대한 업데이트가 자동으로 이뤄지기 때문에 발생하는 현상이다. 테스트를 위해서 이 기능을 꺼버려야 하는 경우가 있는데 그때는 레지스트리에서 설정을 변경해주면 된다. 아래 레지스트리 값들을 이용하면 해당 기능을 오프시킬 수 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot\DisableRootAutoUpdate&lt;/code&gt;&lt;br&gt;
값 1은 신뢰할 수 있는 CTL의 Windows 자동 업데이트를 사용하지 않도록 설정합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot\EnableDisallowedCertAutoUpdate&lt;/code&gt;&lt;br&gt;
값 1은 신뢰할 수 없는 CTL의 Windows 자동 업데이트를 사용하도록 설정합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\AutoUpdate\RootDirUrl&lt;/code&gt;&lt;br&gt;
공유 위치(HTTP 또는 FILE 경로)를 구성합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;더 자세한 설명이 필요하다면 아래 페이지를 참고하면 되겠다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://technet.microsoft.com/ko-kr/library/dn265983.aspx&quot;&gt;https://technet.microsoft.com/ko-kr/library/dn265983.aspx&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 빈 배]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2016/02/empty-boat/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/02/empty-boat/</guid><pubDate>Mon, 15 Feb 2016 14:00:01 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;한 사람이 배를 타고 강을 건너다가&lt;br&gt;
빈 배가 그의 작은 배와 부딪치면&lt;br&gt;
그가 비록 나쁜 기질의 사람일지라도&lt;br&gt;
그는 화내지 않을 것이다.&lt;br&gt;
&lt;br&gt;
그러나 그 배 안에 사람이 있으면&lt;br&gt;
그는 그에게 피하라고 소리칠 것이다.&lt;br&gt;
그래도 듣지 못하면 다시 소리칠 것이고&lt;br&gt;
마침내 욕설을 퍼붓기 시작할 것이다.&lt;br&gt;
&lt;br&gt;
이 모든 일은 그 배안에 누군가 있기 때문에 일어난다.&lt;br&gt;
그러나 그 배가 비어 있었다면&lt;br&gt;
그는 소리치지 않을 것이고 화내지도 않을 것이다.&lt;br&gt;
&lt;br&gt;
세상의 강을 건너는 그대 자신의 배를&lt;br&gt;
그대가 빈 배로 만들 수 있다면&lt;br&gt;
아무도 그대와 맞서지 않을 것이다.&lt;br&gt;
아무도 그대를 상처 입히려 하지 않을 것이다.&lt;br&gt;
&lt;br&gt;
— 장자, 빈 배&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;오늘 발견한 울림이 있는 장자의 글. 장자는 진짜 천재임에 틀림이 없다. 어떻게 저런 생각을 한거지 ㅋㅋ~ 부딪힌 배를 비었다 생각하면 화낼 일도 없고, 내 배를 비우면 싸울 일도 없겠지…​ 하지만 비어 있지 않은걸 비었다 생각하고, 가득 차 있는 것을 비우는 것이 참 쉽지 않다는 게 함은정 ㅋ~ 또 반대로 생각하면 무관심이면 싸울 일도 없겠지만, 애정이 있으니 그나마 치고 박는 건 아닐까라는 생각도 들공…​ 인생 살이라는게 참 쉽지는 않다. 맘대로 되지도 않공.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] PIC 옵션의 정체]]></title><description><![CDATA[gcc에 보면 -fPIC이란 옵션이 있다. PIC 코드를 생성한다는 옵션이다. PIC라는건 Position Independent Code…]]></description><link>https://jiniya.net/ng/2016/01/position-independent-code/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/01/position-independent-code/</guid><pubDate>Mon, 04 Jan 2016 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;gcc에 보면 -fPIC이란 옵션이 있다. PIC 코드를 생성한다는 옵션이다. PIC라는건 Position Independent Code, 직역하면 위치 독립적인 코드 정도로 나온다. 난 지금껏 이 옵션이 재배치에 관한 옵션인줄 알았다. 즉, -fPIC을 지정하면 재배치 정보가 있어서 아무 주소에나 로드할 수 있고, 지정하지 않으면 고정 주소로 로드되는 뭐 그런걸 상상한 것이다. 한동안 그렇게 잘못된 지식을 가지고도 별 문제 없이 지냈는데 최근에 한 업체와 일을 하면서 잘못 알고 있었다는 것을 깨닫게 되었다. 반성하는 차원에서 PIC 옵션에 관한 내용을 정리해 놓는다.&lt;/p&gt;
&lt;p&gt;우선 PIC라는건 재배치랑은 상관이 없다. gcc에서 so로 모듈을 생성하겠다고 하면 기본적으로 재배치 정보를 포함해서 아무 주소에나 로드할 수 있도록 모듈을 만들어 준다. 그럼 재배치랑 연관 있어 보이는 위치 독립적인 코드란 무엇일까? 결론만 말하면 재배치가 필요 없는 코드라고 보면된다. 그렇다면 재배치가 필요 없는 코드는 어떻게 만들까라는 의문을 가질 수 있다. 그건 &lt;a href=&quot;http://www.jiniya.net/lecture/maso/pe5.pdf&quot;&gt;바이러스&lt;/a&gt; 라는 글의 재배치 섹션에 나와 있는 것과 같은 방법을 사용한다고 보면 된다. 컴파일러가 그 일을 대신해 주는 것이다. RealOffset 같은 함수가 절대 주소 참조 시마다 들어가야 하기 때문에 -fPIC 옵션을 지정할 경우 코드가 커지는 것이다.&lt;/p&gt;
&lt;p&gt;여기까지 읽고 도대체 뭔 소리야, 라고 할지도 모르겠다. 더 자세한 설명은 아래 글을 참고하자.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries&quot;&gt;http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries&quot;&gt;http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;http://eli.thegreenplace.net/2011/11/11/position-independent-code-pic-in-shared-libraries-on-x64&quot;&gt;http://eli.thegreenplace.net/2011/11/11/position-independent-code-pic-in-shared-libraries-on-x64&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 더 행복한 한 해를 꿈꾸며...]]></title><description><![CDATA[난 내가 하고 싶은 것만 한다. 하기 싫은 건 하지 않는다. 
2…]]></description><link>https://jiniya.net/ng/2016/01/being-happy/</link><guid isPermaLink="false">https://jiniya.net/ng/2016/01/being-happy/</guid><pubDate>Mon, 04 Jan 2016 12:00:01 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;난 내가 하고 싶은 것만 한다. 하기 싫은 건 하지 않는다.&lt;br&gt;
&lt;br&gt;
25년 그리 긴 시간은 아니지만…​
내가 살아오면서 지킨 단 한가지의 원칙이 있다면 저것일 것 같다.
난 하고 싶은 것만 했다. 재밌는 일들만 했고, 재미없는 것들은 하지 않았다.&lt;br&gt;
&lt;br&gt;
거기에 특별한 가치관이나 판단 기준은 없었다.
단지 하고 싶고 재밌으면 하는 것이고, 그렇지 않으면 하지 않는 것이다.&lt;br&gt;
&lt;br&gt;
하지만 오늘 문득 든 생각은 점점 하루하루 더해질수록 저러한 나의 생활 방식에
많은 가치관이 더해진다는 점이다. 하기 싫지만 xx때문에 해야 하고,
하고 싶지만 yy때문에 못하는 일들이 점점 늘어나는 것이다.&lt;br&gt;
&lt;br&gt;
이런 생각이 들자 순간 기분 나빴다.
그래서 난 과감하게 14만원, 계절학기 6학점을 머릿속에서 지워버렸다.
없던 일로 하기로 했다. 재미없는 수업이고 그다지 하고 싶지 않아서였다.&lt;br&gt;
&lt;br&gt;
포기하면 이렇게도 마음이 가벼워 지는 것을 왜 굳이 꼭 쥐고 있었나 모르겠다…​
그 일 외에도 즐길만한 일들이 산더미 처럼 쌓여 있는데…​ ㅡ.ㅡ#&lt;br&gt;
&lt;br&gt;
— 사탕... 2005&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;25살에 당차게 저런 생각을 했던 나의 35살, 2015년은 그때와는 사뭇 달랐다. 이유가 붙어서 어쩔 수 없이 해야만 하는 일이 줄기차게 늘어났고 나를 위한 시간은 정말 쥐꼬리만큼도 없었다. 게다가 그 모든 일들은 계절학기처럼 쉬이 포기할 수 있는 일들도 아니었다. 더러 잠깐 포기하는 경우에는 주변에서 엄청난 비난과 원망을 들어야 했다. 그런 시간이 오래되니 나중에는 마치 내가 무얼 좋아하는지도 모르는 사람처럼 돼 버렸다. 무엇을 할 때 행복한지도 기억하지 못하는 좀비처럼 말이다. 그런 내가 측은해 보였다. 남이야 뭐라든 나라도 재밌어야 주변 사람도 재밌게 해줄 수 있지 않을까? 내가 호흡기를 해야 내 아이도 해 줄 여유가 생기는 법처럼 말이다. 그래서 새해 벽두엔 모든 핀잔과 원망을 뒤로한체 드라마 정주행을 했다. 물론 상당한 외압이 있었지만 나는 행복했다.&lt;/p&gt;
&lt;h3&gt;리멤버: 아들의 전쟁&lt;/h3&gt;
&lt;p&gt;포토닉메모리(본 것은 죄다 기억하는)를 가진 주인공이 알츠하이머에 걸린 아버지의 누명을 풀기 위해서 변호사가 되어서 복수를 하는 내용의 법정 드라마다. 포토닉메모리를 가진 주인공으로 훈훈한 유승호 나와 주시고, 히로인으로 더 훈훈한 박민영씨가 출연해 주신다. 일단 주연 배우들의 비주얼이 훈훈해서 먹고 들어가는데 내용 또한 그렇게 구리진 않다. 퍼즐 조각을 엮기 위한 억지스러운 설정으로 보여지는 부분들도 있지만 대체로 개연성있게 스토리가 진행된다. 스토리 진행이 엄청 빠르다는 건 덤. 거기다 와이프 말마따나 코리안 멜로 코드가 아직까지는 많지 않다. 끝으로 최신 유행하고 있는 베테랑 흥행 코드가 깔려 있다. 유승호가 싸우는 세력이 재벌2세다. 그리고 조연으로 나오는 박성웅씨 의상, 연기가 압권이다, 황정민삘난다. 여튼 이런 전차로 1회 보고 나서 냅다 6회까지 정주행했다. 7회 분이 이번주 수욜 방영하는데 본방 사수할 것 같은 드라마…​&lt;/p&gt;
&lt;h3&gt;블러드&lt;/h3&gt;
&lt;p&gt;뱀파이어 + 의학물 정도의 드라마. 주연 배우는 알 수 없는 하이틴 스타로 추정되는 남자 배우고 악역으로 지진희씨가, 히로인으로 구혜선이 나온다. 왠만하면 지진희씨가 나오는 드라마는 피하는 편인데 구혜선이 나와서 봤다는 썰이 있다. 1회 보고는 접을려고 하다가 본게 아까워서 몇 편 더 봤는데 냅다 정주행하게 되었다. 그 여파로 와이프에게 캐갈굼, 캐욕, 급기야 네번째 50일 촬영에 끌려가는 비극이 있었지만 최선을 다해서 20회까지 사수했다. 끝에는 지루해서 빨리감기를 좀 많이 했다.&lt;/p&gt;
&lt;p&gt;스토리 설정이 참신한데 한 감염학자(의학자)가 해외 어딘가에서 뱀파이어 이야기를 듣고 시체를 발굴해서 뱀파이어 바이러스를 만들어 낸다는데서 출발한다. 그 바이러스에 감염되면 뱀파이어가 되는데, 뱀파이어는 뭐 우리가 익히 알고 있는 그 뱀파이어다. 밝은거 못 보고, 체온 낮고, 심박 빠르고, 피 보면 환장하고, 20대의 젊음을 한 250년 정도 유지하다가 죽는 그런…​ ㅋㅋ~ 그렇게 연구를 하던 랩실의 3명이 감염자가 되는데 다른 사람들은 이걸 폐기하자 그러고 지진희는 세상 밖으로 꺼내야 한다고 하면서 싸움이 난다. 늘 그렇듯이 악역이 교수와 친구 2명을 모두 죽이고 독차지 하면서 이야기가 시작된다. 그런데 그 죽인 친구 둘은 캠퍼스 커플이고, 감염된 뱀파이언데 그 사이에서 자식이 태어났으니 그게 주인공이다. 그렇게 둘이서 세월이 흘러 흘러 한국의 한 병원에서 만나서 지지고 볶는 그런 썰이다.&lt;/p&gt;
&lt;p&gt;첨에는 의학물적인 내용이 더러 나와서 우왕 내가 안 본 의학 드라마도 있었넴, 게다가 액션까지 했는데,…​ 가면 갈수록 코리안 멜로와 알 수 없는 뱀파이어 호러물로 변질되면서 쩜쩜점했다. 끝은 이미 뻔했지만 본 게 아까워서 끝까지 정주행하는 예를 갖췄다.&lt;/p&gt;
&lt;h3&gt;행복의 기원&lt;/h3&gt;
&lt;p&gt;새해 벽두를 그냥 드라마만 냅다 정주행한것처럼 보이지만 와이프의 눈총과 육아를 병행해야 했던 시간에는 책도 읽었다. 한권은 행복에 관한 how보다는 why에 대한 답을 담고 있는 &quot;행복의 기원&quot;이란 책이다. 그냥 단순한 싸구려 자기계발서의 주장을 담고 있는 책은 아니고 과학적인 연구 결과를 바탕으로 써진 책이다. 그래서 그런지 내용이 팍팍 와 닿았다. 성격이 중요하고 유전이 상당한 영향을 미친다는 것에 다소 충격을 받았지만 말이다.&lt;/p&gt;
&lt;p&gt;그리고 책에서 밝히는 또 하나의 충격적인 사실 중에 하나가 있다. 윤종신씨인지 유희열씬지가 방송에서 음악 열심히하고 그러는게 다 여자한테 잘 보이려고 하는거라고 했었던 말이 팩트라는 것이다. 진화론적 근거가 있는 이야기라는 사실. 공작새의 꼬리처럼 생존과는 별 상관 없어보이지만 이성에게 어필하기 위해서 그러는게 맞다는 다소 어이없지만 황당한 이야기. 인생 뭐 별 거 없다. 베토벤도 모짜르트도 여자한테 잘 보이려고 밤을 새며 작곡했다는 썰~ 그럼 혹시 토발즈와 카맥도? ㅋ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;유학 시절, 지도 교수가 쓴 논문을 읽은 적이 있다. 제목은 &apos;행복은 기쁨의 강도가 아니라 빈도다&apos;. 나는 이것이 행복의 가장 중요한 진리를 담은 문장 중 하나라고 생각한다.&lt;br&gt;
&lt;br&gt;
지금 나는 왜 이모양으로 살고 있는가? 우리는 이런저런 이유를 떠올린다. 부모를 잘 만나서, 혹은 잘못 만나서, 대학 전공 때문에, 기타 등등. 조금씩은 모두 관련이 있겠지만 무엇을하며 어떤 인생을 사느냐를 결정하는 데 상당히 큰 몫을 차지하는 것은 바로 자신의 성격이다.&lt;br&gt;
&lt;br&gt;
다시 말하지만 행복의 원인 중 사람들이 가장 과대 평가하는 것이 돈과 같은 외적 조건이다. 이 챕터에서는 반대로 행복에 절대적인 영향을 미치지만, 대부분이 미처 생각지 않는 요인에 대해 살펴보려 한다. 어떤 것이 그렇게 중요할까? 오랫동안 행복을 연구한 석학들을 한 자리에 모아놓고 그 질문을 한다면 대답은 거의 비슷할 것이다.&lt;br&gt;
&quot;유전. 더 구체적으로는 외향성.&quot;&lt;br&gt;
&lt;br&gt;
행복의 핵심을 한 장의 사진에 담는다면 어떤 모습일까? 이 책의 내용과 지금까지의 다양한 연구 결과들을 총제적으로 생각했을 때, 그것은 좋아하는 사람과 함께 음식을 먹는 장면이다. 문명에 묻혀 살지만, 우리의 원시적인 뇌가 여전히 가장 흥분하며 즐거워하는 것은 바로 이 두가지다. 음식, 그리고 사람.&lt;br&gt;
&lt;br&gt;
행복은 거창한 것이 아니다. 모든 껍데기를 벗겨내면 행복은 결국 이 한 장의 사진으로 요약된다. 행복과 불행은 이 장면이 가득한 인생 대 그렇지 않은 인생의 차이다. 한마디 덧붙인다면 &quot;The rest are details.&quot; 나머지 것들은 주석일 뿐이다.&lt;br&gt;
&lt;br&gt;
-- 행복의 기원, 서은국&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;가끔은 겪하게 외로워야 한다&lt;/h3&gt;
&lt;p&gt;김정운 교수의 신간이다. 왠만하면 자기계발서는 읽지 않는 편인데, 김정운 교수가 쓴 책이라 재미 삼아 읽었다. 내용도 그냥 가볍게 읽기 좋은 책으로 보여진다. 김정운 교수 팬이긴 한데 그의 &quot;에디톨로지&quot;는 정말 읽기 힘들어서 읽다 말았었다. 가볍게 개념만 편식하는 걸로 ㅋㅋ~ 근데 이 책은 그냥 심심풀이로 읽기 좋다. 김정운 교수는 이런 책이 어울린다는 개인적인 생각…​&lt;/p&gt;
&lt;h3&gt;행복하자~&lt;/h3&gt;
&lt;p&gt;할아버지는 주당이셨다. 평생 반주를 하셨는데, 나중에는 술이 주고 밥이 부가 될 지경이었다. 노환으로 병원에 입원해 계섰을 때 엄마가 첨으로 와인을 사드렸는데 이런 술이 있냐며, 왜 진작 자신에게 사주지 않았냐는 이야기를 했다고 한다. 병원에서도 노환이니 좋아하시면 그냥 드리는 것도 괜찮다고 해서 와인을 종종 드시면서 마지막 병원 생활을 하셨다.&lt;/p&gt;
&lt;p&gt;아빠는 내기 바둑과 장기, 고스톱에 빠져서 평생을 살았다. 돌아가시고 엄마한테 들어서 안 사실이지만 아빠의 도박 편력이 장난이 아니었다. 그렇게 평생을 좋아하더니 마지막 까지도 집 앞 공원에서 내기 장기를 두고는 가셨다. 병원에서 칼륨 수치를 관리해야 한다고 짠 걸 드시지 말라고 하셨을 때 한 말씀이 생각난다. 죽으면 죽었지 먹고싶은건 먹어야겠다고 말이다. 여튼 그렇게 아빠는 자기가 하고 싶은 걸 다 하시고 가셨다.&lt;/p&gt;
&lt;p&gt;어떤게 정답인지는 모른다. 당장의 쾌락을 따르며 사는게 좋은건지, 아니면 근엄하게 사는게 좋은건지 말이다. 하지만 이것 저것 따질것 없이 그냥 지금 행복하게 사는게 중요한 건 아닐까? 얼마간 더 사는 것보다 오늘 재미난 일을 하고 행복하게 사는게 더 소중하지 않을까? 내일은 오지 않을 수도 있으니 말이다. 당장 가진 오늘을 더 재미있고 행복하게 영위하는게 훨씬 더 좋지 않을까라는 생각. 생각이 여기까지 미치니 참으로 유전이란 걸 무시못하는건가 싶기도 하다. 여튼 2016년은 행복한 일로 가득한 한 해가 되길 소망해 본다. 맛집블로그로 전환될지도 모르겠다 ㅋㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[블로그 이동]]></title><description><![CDATA[어느날 갑자기 워드프레스가 너무 복잡한 것 같은 생각이 들어서 블로그를 옮겼습니다. 링크가 이곳으로 돼 있어서 이곳으로만 오는 분들이 계신 것 같아서 포스팅합니다. 새로운 주소는 http://www.jiniya.net/ng…]]></description><link>https://jiniya.net/wp/archives/15217</link><guid isPermaLink="false">https://jiniya.net/wp/archives/15217</guid><pubDate>Mon, 04 Jan 2016 12:00:01 GMT</pubDate><content:encoded>&lt;p&gt;어느날 갑자기 워드프레스가 너무 복잡한 것 같은 생각이 들어서 블로그를 옮겼습니다.&lt;/p&gt;
&lt;p&gt;링크가 이곳으로 돼 있어서 이곳으로만 오는 분들이 계신 것 같아서 포스팅합니다.&lt;/p&gt;
&lt;p&gt;새로운 주소는 &lt;a href=&quot;http://www.jiniya.net/ng%EC%9E%85%EB%8B%88%EB%8B%A4&quot;&gt;http://www.jiniya.net/ng입니다&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;혹시 즐겨찾기를 사용하시는 분이라면 &lt;a href=&quot;http://www.jiniya.net%EC%9D%84&quot;&gt;http://www.jiniya.net을&lt;/a&gt; 추가해 두시면 됩니다.&lt;/p&gt;
&lt;p&gt;해당 주소로 가시면 알아서 새로운 주소로 이동시켜 준답니다.&lt;/p&gt;
&lt;p&gt;늦었지만 새해 복 많이 많이 받으세요 !!!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 모던 C++에서 훅 코드란?]]></title><description><![CDATA[다른 블로그 구경하다가 재미난 코드를 발견해서 옮겨봅니다. 훅 루틴인데요. 모던 C++을 사용하니 정말 간결하네요. C++의 르네상스가 다시 오는건지 ㅋㅋ~ 신세계군요. 망할 XP만 없다면 빨리 넘어갈텐데 ㅠㅜ~ decltype(A)는 A…]]></description><link>https://jiniya.net/ng/2015/12/hook-with-modern-cpp/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/12/hook-with-modern-cpp/</guid><pubDate>Wed, 30 Dec 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;다른 블로그 구경하다가 재미난 코드를 발견해서 옮겨봅니다. 훅 루틴인데요. 모던 C++을 사용하니 정말 간결하네요. C++의 르네상스가 다시 오는건지 ㅋㅋ~ 신세계군요. 망할 XP만 없다면 빨리 넘어갈텐데 ㅠㅜ~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;decltype&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;timeGetTime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; HooktimeGetTime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; DWORD &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;decltype(A)는 A의 타입을 반환합니다. 예전에 훅 루틴 만들때마다 원형 복사해서 함수 포인터 다시 typedef하던 때를 떠올리면 정말 심플합니다.&lt;/p&gt;
&lt;p&gt;&quot;&lt;a href=&quot;&quot;&gt;&lt;/a&gt; {}&quot;는 람다 함수입니다. &quot;&lt;a href=&quot;&quot;&gt;&lt;/a&gt; -&gt; DWORD {}&quot;는 파라미터는 없고 리턴 값은 DWORD인 람다 함수라는 말이죠.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우에서 llvm-obfuscator 사용하기]]></title><description><![CDATA[Clang은 LLVM을 백엔드로 사용하는 C 계통의 언어를 컴파일해주는 컴파일러다. LLVM을 백엔드로 사용하기 때문에 컴파일 타임에 뭔가를 해줄 수 있다는 장점이 있다. 그런 것 중에 하나로 난독화를 들 수 있다. obfuscator-llvm…]]></description><link>https://jiniya.net/ng/2015/12/clang-with-mingw-w64/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/12/clang-with-mingw-w64/</guid><pubDate>Fri, 18 Dec 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;Clang은 LLVM을 백엔드로 사용하는 C 계통의 언어를 컴파일해주는 컴파일러다. LLVM을 백엔드로 사용하기 때문에 컴파일 타임에 뭔가를 해줄 수 있다는 장점이 있다. 그런 것 중에 하나로 &lt;a href=&quot;https://github.com/obfuscator-llvm/obfuscator&quot;&gt;난독화를&lt;/a&gt; 들 수 있다. obfuscator-llvm은 LLVM에 난독화 기능을 추가한 버전이라고 보면 된다. 소개 페이지에 나와 있는 것처럼 LLVM IR레벨에서 작업하고 있기 때문에 LLVM을 백엔드로 사용하는 언어와 타겟 머신을 모두 지원한다는 장점이 있다. 제작자들이 첨에는 학교에서 &lt;a href=&quot;http://crypto.junod.info/spro15.pdf&quot;&gt;논문으로 쓰다가&lt;/a&gt; 아이디어가 괜찮아서 &lt;a href=&quot;https://strong.codes/&quot;&gt;스타트업을 차린 것으로 보여진다.&lt;/a&gt; 어쨌든 이걸 쓰면 컴파일 타임에 나의 코드에 난독화를 적용할 수 있는 것이다. 응당 사용하지 않을 이유가 전혀 없다. 그럼 한 번 살포시 시작해보자.&lt;/p&gt;
&lt;p&gt;우선은 Clang을 윈도우에서 어떻게 쓸지부터 알아야 한다. 정말 많은 글들이 있지만 &lt;a href=&quot;http://blog.johannesmp.com/2015/09/01/installing-clang-on-windows-pt2/&quot;&gt;이 글에&lt;/a&gt; 나와있는 방법이 가장 좋았다. Clang에다 런타임라이브러리와 링커는 mingw-w64껄 쓰는 방법이다. 글에 나와 있는 방법대로 하면 대체로 모두 잘 된다. 내가 조금 골탕먹은 것은 mingw-w64를 선택할 때 스레딩 모델을 Win32로 선택했던 것이었다. Win32로 선택하면 C++11부터 추가된 스레드 기능을 사용하지 못한다. 그러니 POSIX로 선택하는 것이 바람직하다 하겠다. 예외의 경우 64는 SEH로 32는 Dwarf를 받아서 썼다. 그렇게 했더니 아래 코드가 깔끔하게 컴파일이 되었다. &quot;clang++ -std=c++14 hello.cpp -lpthread&quot;라는 명령어로 아래 코드가 깔끔하게 컴파일이 되었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;thread&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;chrono&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PrintMsg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; try_cnt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; try_cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[%03d] %s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;this_thread&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep_for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;chrono&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;thread1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;PrintMsg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;thread2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;PrintMsg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cat&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;thread3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;PrintMsg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;monkey&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	thread1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	thread2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	thread3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 컴파일한 결과물을 사용하면 별 문제는 없는데 덕지덕지 온갖 이상한 DLL을 많이 임포트하는 경향이 있다. 그래서 용량이 큰 C++ 라이브러리를 제외하고 정적으로 컴파일하고 싶으면 &quot;clang++ -std=c++14 hello.cpp -static -static-libgcc -lpthread -Wl,-Bdyanmic -lstdc++&quot;와 같이 입력하면 된다. 여튼 뭐 컴파일은 그렇다. 그렇다면 이제 llvm-obfuscator를 써보자.&lt;/p&gt;
&lt;p&gt;난독화 함수를 찾기 쉽도록 아래와 같이 익스포트 되도록 함수를 선언해주자. 뒤에 속성으로 따라 붙는 것이 fla, bcf, sub 난독화 기법을 이 함수에 적용하겠다는 것을 의미한다. 오픈소스 버전은 세 가지 기능만 제공하고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;__declspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dllexport&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PrintMsg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; try_cnt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;__attribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;__annotate__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;fla&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;__attribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;__annotate__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bcf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;__attribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;__annotate__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sub&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./normal.png&apos; data-alt=&apos;난독화가 적용되지 않은 PrintMsg 함수. 코드만큼 어셈도 단순하다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b0e18ac996e6f3bfe2ef91379cf14984/dface/normal.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 102.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB/ElEQVR42o1UiY7aMBTk//+p2u2FWs6FkjsQQg7i+IpzOuTYfQtoVbULwXqyZMWjNzNvnNHrefV9D7tpkijKoTQd76OIl7w4Fa+31+hv8G7H47hgTGpmND0svCTABTl/eQDsOJzzirHKdZPZL6T4lhpabdMPgt/3/T4BcMKloqGfa1VFuuZvGZXdje7/0oa2lFSThft9N9aIpruuouDTqR3uHIZZmsosPRkWUiPdSw8+iREVXd99Dqa09DwBaruur+u2abq27auqLfImKUVW5zazTWwf8yOvuMPhohMXMRxpSUcXzl3XnUdFoyhjrNxs0POzM9n+MYhpIScv5ZXgO8Vr/a+ZAREoQydPX1zvCF5VPBWM0fS87hlm2/QKNsnvxX68nS385ca3uCg+7tybM3CGUU2X7jd7rBNNCUzDoISUH6bedBuygXHBuXxZheO1FrAIZ5TRUspmeFSHQ3JJGPBXNhgLyHaeyxIGMQy+0AbNuo7Xa6R6ji+Co0CVPA0nbLtl8DAAPJ37T/OVGlgH6nshE2n1SLY5QjmANwoy7RgnomwKqKZthzuDVEIKRqv5yvuqT5bhy8xdKZaPSX7f7Stt+BNA5/ki+DEzjcCNBMJMPKQZDANkkkjLJvsgDhOEshhnrCjrR0YFSSyFqBU1mmkmEgTeBmSmlp9rfgMTK3hYYtTRwgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;난독화가 적용되지 않은 PrintMsg 함수. 코드만큼 어셈도 단순하다.&apos; title=&apos;&apos; src=&apos;/static/b0e18ac996e6f3bfe2ef91379cf14984/dface/normal.png&apos; srcset=&apos;/static/b0e18ac996e6f3bfe2ef91379cf14984/08678/normal.png 190w,
/static/b0e18ac996e6f3bfe2ef91379cf14984/2edd7/normal.png 380w,
/static/b0e18ac996e6f3bfe2ef91379cf14984/dface/normal.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;난독화가 적용되지 않은 PrintMsg 함수. 코드만큼 어셈도 단순하다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./obfuscated.png&apos; data-alt=&apos;난독화가 적용된 PrintMsg 함수. 함수가 점프 코드로 분산되고 길고 어려워진다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/628f81a88e7b905e5f4434ce8f9e4960/dface/obfuscated.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 151.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAIAAACjcKk8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAADoUlEQVR42pVVyXLjNhTkZ+cLcs0HJKcccssllcolU5maSmzLHo8tWYu1UaJEUSIJrtgBAlAeRXvKdnliB0KpQJENovt1P3nHJ2O7rRnTCLHDgWhtjm8N7+nF3V1SFGKzqdbrUin7/8D9fpwkdB+RBBF9FEQRZdR7wdMpYkwdInY5mt9Gg7AKM5bD7w4+b4LH45RzHUV4NEIX59Htvr+Kd868783jMRKiiXakd+P3pqNBPBiHSziINuZt8HyeK9VEIf10PQHkIl+Mt6vZfdE0nXj2NN23wJlSBsBnt7O7w2iWTYfBMkDRnkRY4VfeTIgqCp7nHC6gPM65RlsulLCcacakjOrIL/yYxlR/QOzngs+olkRh1jCvqmRZCpgA7rxRVWIf0f2OIZqnNJmli4JXTFOmzxH7DTEfS1pL+IW9NAk4bBfim+Hmy+Zukc+JYErCcd6h9mSClDbhhvz5z/DM/zxKx5PtejkvdWNeF8y127bTWtsJFifYD9IMcWNaCdzDex8X7gEOlx5ogrEgRNrH4Zx9BMCWjimGJaaSchXUYkIEYgrIMKGFBzqDn9OUwaOwhpISomERHrJNGcYknqazPT7kPKvlLzv8fUSuK0ELnkHxXppEygakvhouz1dX19EXHwWQMzjN64LBATteMCGJ8Fwc04vLzefbTc2oUJpS3XJp758YHe2JdYvwrDUAhdvGmLLkYE8hVJ6zsuAGXPmw9WnYpp2A72SxzgPCux1OUwrHAMKwoTFOawvlFQ04iSyyxbZqyef8p1XxXVCeIVYlNAZneVCPbn6NZLglt+PNp9nlh+VfS7RaHw5Sg2+hbqKxtLGwtoCA72eC3d8jsGcY4vPrZX/hI5oVpCZV803BToVtCQHnJCHAmVBOOXf26Kx7NlqeJ6G+cs4yDq0DItGZ5tEbR8iWNpprEVa7Pd4jhkrxa1j/sMc3hcCnsteeEAa6B0zArFYlLBDiYM9BMIdIgz2CLGSKKyO1nTJ9RXWiTCONgK2fcfb9tmmc2tCqNxuuiyDDVZmr/zDJg++BfBCUIFiWsUE/7t/EoPxJDNc1UPcime7oYSwh/V0wOrc8SdIRSkIkqXndZkNdFOz3kq+p5ERiyIYH1gU/QieCR6MI1DZlIfYHvI6SSTIFqUbxBJgXvKjlHxH58UCGlaSFyME/L/u2kM02wH9fzT7e93rh5TaLcqSMeSMYrlMbBEtS0jaDVLTOaz3vTv8YrXHdsXkajH8B19u12n8tR7AAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;난독화가 적용된 PrintMsg 함수. 함수가 점프 코드로 분산되고 길고 어려워진다.&apos; title=&apos;&apos; src=&apos;/static/628f81a88e7b905e5f4434ce8f9e4960/dface/obfuscated.png&apos; srcset=&apos;/static/628f81a88e7b905e5f4434ce8f9e4960/08678/obfuscated.png 190w,
/static/628f81a88e7b905e5f4434ce8f9e4960/2edd7/obfuscated.png 380w,
/static/628f81a88e7b905e5f4434ce8f9e4960/dface/obfuscated.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;난독화가 적용된 PrintMsg 함수. 함수가 점프 코드로 분산되고 길고 어려워진다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;내가 사용한 버전은 llvm-3.6.1 브랜치 코드를 기준으로 작업했다. 사용해보면 윈도우에서 /dev/random을 찾을 수 없다는 버그가 있는데 lib/Transform/Obfuscation/CryptoUtils.cpp 파일의 prng_seed 함수를 아래와 같이 수정해주면 정상 동작하도록 만들 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_WIN32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;_WIN32_LEAN_AND_MEAN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;Windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;Ntsecapi.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CryptoUtils&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prng_seed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_WIN32&lt;/span&gt;&lt;/span&gt;

	LLVMContext &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ctx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; llvm&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getGlobalContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HCRYPTPROV prov&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptAcquireContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;prov&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PROV_RSA_FULL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CRYPT_VERIFYCONTEXT &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CRYPT_SILENT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptGenRandom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prov&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;BYTE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			ctx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emitError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Twine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CryptGenRandom fail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;CryptReleaseContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prov&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ctr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Once the seed is there, we compute the&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// AES128 key-schedule&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;aes_compute_ks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ks&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		seeded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		ctx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emitError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Twine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CryptAcquireContext fail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// ... 기존 코드 ...&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[cpp] API 세트 DLL 이름 바인딩하기]]></title><description><![CDATA[윈도우 7이 등장하면서 kernel32.dll을 살펴보면 이상한 부분이 하나 생겼습니다. 바로 IAT 부분인데요. api-ms-win-core-console-l1-1-0.dll 같은 이상한 DLL로 부터 우리가 원래 익히 알고 있는 API…]]></description><link>https://jiniya.net/ng/2015/12/api-set-dll-name-binding/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/12/api-set-dll-name-binding/</guid><pubDate>Thu, 17 Dec 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;윈도우 7이 등장하면서 kernel32.dll을 살펴보면 이상한 부분이 하나 생겼습니다. 바로 IAT 부분인데요. api-ms-win-core-console-l1-1-0.dll 같은 이상한 DLL로 부터 우리가 원래 익히 알고 있는 API들을 임포트 하고 있는 것이죠. 그런데 api-ms-win-core-console-l1-1-0.dll 같은 것에 실제 코드가 포함돼 있냐하면 그것도 아닙니다. 헐~ 멍밍하게 되는데요. &lt;a href=&quot;http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html&quot;&gt;그 당시에 발견한 문서에서&lt;/a&gt; 기본적인 메커니즘을 알게 되어서 해당 문서에 나와 있는 DLL 이름들만 하드 코딩해서 사용을 했었습니다.&lt;/p&gt;
&lt;p&gt;이후에 윈도우 8이 나왔고, 8.1이 출시됐고, 윈도우 10이 나오고, 이제는 윈도우 10 TH2까지 나왔습니다. 저 문서에 있는 내용 만으로 뭔가가 정상 동작하기에는 뭔가 한참 모자랄만큼 운영체제가 많이 나왔죠. 어제 해킹툴을 테스트하다가 코드가 정상적으로 동작하지 않는 것을 발견했습니다. 바로 위에서 우리가 하드 코딩한 DLL 말고도 온갖 요상한 DLL이 많이 생긴게 원인이었습니다. 그래서 이 많은 DLL 이름을 어쩌지 하는 찰나에 관련 설명을 담고 있는 &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/hh802935(v=vs.85).aspx&quot;&gt;MSDN 문서를&lt;/a&gt; 발견하게 되었습니다. 목록이 엄청 길죠. API 세트에 사용되는 온갖 DLL 이름이 다 나와있습니다. 이 테이블을 기초로 DLL 이름을 매핑해주는 함수를 확장시켰더니 마법같이 잘 동작했습니다. 역시 MSDN ㅋㅋ~ 그런데 뭔가 좀 아쉽죠. 모두 입력 시켜서 동작하게는 만들었지만 도대체 이 이름들은 어디서 오며 운영체제는 어떻게 그걸 매핑시키는지 궁금한거죠~ 은막 뒤의 비밀이 궁금하다랄까요.&lt;/p&gt;
&lt;p&gt;자동으로 될 일은 없고, 운영체제도 어디에선가는 매핑을 시킬텐데 그 자료를 알게 되면 굳이 이걸 일일이 입력하고 있지 않아도 되지 않을까라는 생각이었습니다. 그 생각으로 오늘 LoadLibrary 코드를 좀 살펴봤는데요. 비밀을 알아냈습니다. LoadLibrary 내부에서 PEB에 저장된 ApiSetMap이란 자료 구조를 참조해서 DLL 이름을 리다이렉트 시키고 있었습니다. 풉. 역시 마법은 없었습니다. ApiSetMap이란 걸 알게 되었으니 관련 키워드로 검색을 해봤습니다. 자료가 많지는 않은데 친절하게 리버싱해 둔 자료가 있었습니다.&lt;/p&gt;
&lt;p&gt;전체적인 메커니즘은 런타임 DLL 이름 해석 &lt;a href=&quot;http://blog.quarkslab.com/runtime-dll-name-resolution-apisetschema-part-i.html&quot;&gt;Part 1&lt;/a&gt;, &lt;a href=&quot;http://blog.quarkslab.com/runtime-dll-name-resolution-apisetschema-part-ii.html&quot;&gt;Part 2&lt;/a&gt;에 잘 나와 있습니다. 관련 자료를 토대로 만든 실제 코드는 &lt;a href=&quot;http://www.xchg.info/wiki/index.php?title=ApiMapSet&quot;&gt;위키 글을&lt;/a&gt; 참고하면 됩니다.&lt;/p&gt;
&lt;p&gt;간략하게 전체 구조를 리뷰해보면 모든 데이터의 근간은 apisetschema.dll에 있습니다. 윈도우는 부팅할 때 그 DLL의 .apiset 섹션 데이터를 토대로 메모리에 API 세트 이름 매핑 자료를 로드합니다. 그리고 이후 프로세스가 생성되면 PEB의 ApiSetMap에다가 해당 자료를 참조할 수 있도록 데이터를 매핑시켜줍니다. 이제 LoadLibrary를 호출하면 PEB의 ApiSetMap을 뒤져서 매칭되는 DLL이면 이름을 리다이렉트 시켜주는 것이죠. 결국 하드코딩한 테이블을 사용할 것이 아니라면 ApiSetMap을 어떻게 뒤지는지 알아야 합니다.&lt;/p&gt;
&lt;p&gt;앞선 위키 글의 경우 윈도우 7을 기초로 작성해서 제가 사용하는 윈도우 8.1에서는 동작하지 않는 문제가 있었습니다. 그래서 윈도우 8.1에서 동작하도록 코드를 한 번 만들어 보았습니다. 런타임 DLL 이름과 매핑되는 실제 DLL 이름을 출력해 줍니다. 위키 글에 있는 코드는 ApiSetMap 구조체 버전이 2인 환경입니다. 아래는 버전이 4인 환경일 때의 구조체 정보랍니다. 윈도우 10은 또 업그레이드가 되었겠죠?&lt;/p&gt;
&lt;p&gt;덧) 현재까지 알려진 ApiSetMap 자료 구조 버전은 총 세 개입니다. 윈도우 7에 포함된 구조가 2버전이고, 윈도우 8에 포함된 구조가 4버전입니다. 윈도우 10에는 6버전 구조로 변경이 되었네요. 아래 코드는 윈도우 8의 ApiSetMap 버전 4를 출력하는 기능을 합니다. 당연히 2나 6에서는 정상 동작하지 않습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;ADD_PTR&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_API_SET_MAP_DATA_ENTRY&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG flags&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG name_offset&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG name_length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG value_offset&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG value_length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; API_SET_MAP_DATA_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PAPI_SET_MAP_DATA_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_API_SET_MAP_DATA&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG flags&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	API_SET_MAP_DATA_ENTRY entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ANYSIZE_ARRAY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; API_SET_MAP_DATA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PAPI_SET_MAP_DATA&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_API_SET_MAP_ENTRY&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG flags&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG name_offset&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG name_length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG alias_offset&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG alias_length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG data_offset&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; API_SET_MAP_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PAPI_SET_MAP_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;



&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_API_SET_MAP&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG version&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG flags&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	API_SET_MAP_ENTRY entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ANYSIZE_ARRAY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; API_SET_MAP&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PAPI_SET_MAP&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	PVOID name_ptr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG_PTR api_set_map&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	PAPI_SET_MAP pasm&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	PAPI_SET_MAP_DATA pasmd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	WCHAR name&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	api_set_map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__readfsdword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	api_set_map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;api_set_map &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x38&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


	pasm &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PAPI_SET_MAP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; api_set_map&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; pasm&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		name_ptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ADD_PTR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pasm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pasm&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name_offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name_ptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pasm&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name_length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		pasmd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PAPI_SET_MAP_DATA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ADD_PTR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pasm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pasm&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data_offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%ls =&gt; [%d]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pasmd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG j &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; pasmd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			name_ptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ADD_PTR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pasm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  pasmd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value_offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token function&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name_ptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pasmd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value_length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; %ls&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[시스템] 블록 암호화의 연산 모드란?]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/ng/2015/12/blcok-cipher-mode-operation/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/12/blcok-cipher-mode-operation/</guid><pubDate>Sat, 12 Dec 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;암호는 용어도 많고 알고리즘도 어렵고, 구조도 복잡합니다. 그런 암호 중에서도 블록 암호화를 공부하면 연산 모드란 것을 만나게 됩니다. 어떤 거냐구요? &lt;a href=&quot;https://msdn.microsoft.com/ko-kr/library/system.security.cryptography.ciphermode(v=vs.110).aspx&quot;&gt;바로 이런 겁니다.&lt;/a&gt; 이런 상수를 만나면 으례 그냥 아무거나 넣거나 디폴트 값을 사용하곤 하지만 오늘은 한 걸음 더 파헤쳐보는 시간을 가져보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;블록 암호화는 기본적으로 블록 단위로 특정 키를 사용해서 암호화를 하는 것을 의미합니다. 특별한 언급이 없는한 대칭키를 사용하는 구조가 대부분이죠. 암호화를 수행한 키를 암호를 해독할 때에도 사용한다는 겁니다. 그렇다면 이런 대칭형 블록 암호화 기법의 가장 큰 문제점은 무엇일까요? 네, 맞습니다. 똑같은 블록, 똑같은 키라면 결과물이 똑같다는 거죠. 어느 정도 패턴이 드러날 수 밖에 없다는 이야깁니다. 아래 이미지를 보면 이해가 빠릅니다. 세 가지 그림이 있는데 왼쪽이 원본, 가운데가 연산 모드 없이(ECB) 블록 암호화를 수행한 것, 오른쪽은 ECB가 아닌 연산 모드를 선택해서 블록 암호화를 수행한 겁니다. 어떤가요? 기본적인 ECB의 경우 이미지가 변형되었지만 우리는 이 이미지가 펭귄이란 것을 인식할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./modeop.png&apos; data-alt=&apos;기본인 ECB 연산 모드가 왜 위험한지를 보여주는 짤. 암호화를 했지만 우리는 펭귄을 볼 수 있다는거~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0421859522ad948e79d1513a5ca1f39d/dface/modeop.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACSElEQVR42iVSz1PTQBTOn+TR8eqMM3r3inovCElL2yS7mx+km4DIwbMHZbw4OnoHO4wOo/woTSHCtE1JmpRxZChNAi2koYkP/Obt7nv7vm/evjfLJEmcZdneXn17eydNE/APDy2EkCzL5VJZEEVJklRVXVlZ0RaoXtEpBasYlL5efsXc3IxB8GLq6YP794IgAH9/v8Fy3Pz8/OzMy+lcLp/neJ6nBuWRgEQRYYQJBneBKkyWjoPoauMzJ7EPf2zu/BcXCoVisUgwznMAFiHRMBZFRGRCZAlhjCRCKKUMsKvVb0dHVqNhPn82BaFlHYA4z+XZ2QI7x03P5ARB0A2KsEgQISImBGqLVKswyXj04d2bIIig4SePH52e/m23mqAtFUrsrMCxfG56RuAFQ18kSJJhALCgvEg0XWcu3Y+tVeb72vvN6pf1JWYyWP995JTLBVmV5uZKLFsUsQiPNHQDkVtHkmVFkSQsGxWNuQrt0130c+3t10+rf3ZwlgUH1mGZLwGpzPPQOUweI7S0vLSgSBVFUzVF0xRZVXVqMP1+eBbEYTRM0/QqyW4maf/srFar1ev1fdM0YRKm6TjHlmVt/dqq1XYBjboJt62WzVxE0UU0uIAjCoeX0Wg0HI1GcRxfx9eAeDy+juMkSSDb758P7jC8I0zSCdPtuh2747qw267rdDp2u9Vut227bTebzWNApwMXQOh6HhiEx44DjPNBcCv27wBp3/cc1/E9z/M9v9t13K7fg+g22+v1HAeS7snJSRiGwQA+VPAPUD3Rrx7Za58AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;기본인 ECB 연산 모드가 왜 위험한지를 보여주는 짤. 암호화를 했지만 우리는 펭귄을 볼 수 있다는거~&apos; title=&apos;&apos; src=&apos;/static/0421859522ad948e79d1513a5ca1f39d/dface/modeop.png&apos; srcset=&apos;/static/0421859522ad948e79d1513a5ca1f39d/08678/modeop.png 190w,
/static/0421859522ad948e79d1513a5ca1f39d/2edd7/modeop.png 380w,
/static/0421859522ad948e79d1513a5ca1f39d/dface/modeop.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;기본인 ECB 연산 모드가 왜 위험한지를 보여주는 짤. 암호화를 했지만 우리는 펭귄을 볼 수 있다는거~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이렇게 패턴이 드러나는 문제를 해결하기 위해서 나온 것이 연산 모드입니다. 거창하게 설명했지만 대단한 건 아니고 블록 암호화의 연산 전후에 규칙적으로 변형을 가하는 것을 의미합니다. 아래는 많이 사용하는 CBC 연산 모드에 대한 이미지 입니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 601px; margin-bottom: 16px;&apos; data-url=&apos;./601px-CBC_encryption.svg.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/20017187563e47a19455cb871ac8be40/f6e13/601px-CBC_encryption.svg.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 40.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAyklEQVR42nWRiw6CMAxFUREGioCAAQV14Ov/v9COHE1d4pKTQOntbi9B8HsWwl44CsarF8JJ2HiaHfXtp+AaciEVDsJDsDyv6Em45Cp0wpp6xLvVJi7CS7gLA4MqBAaRI1P1WOF6GnX5vE6CZbfWhMuOddygEhdPxIXijKGei+cTsobBoWVgRt05qVUUOb0xQwfch16+s0uX001oVUOKg4kfoDPsVVzGH7hEMOIooikl9JGVdX41miL4c0rWahG3rN8grtS3nvy/5w1yfwlPRgjG9QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;601px CBC encryption svg&apos; title=&apos;&apos; src=&apos;/static/20017187563e47a19455cb871ac8be40/f6e13/601px-CBC_encryption.svg.png&apos; srcset=&apos;/static/20017187563e47a19455cb871ac8be40/08678/601px-CBC_encryption.svg.png 190w,
/static/20017187563e47a19455cb871ac8be40/2edd7/601px-CBC_encryption.svg.png 380w,
/static/20017187563e47a19455cb871ac8be40/f6e13/601px-CBC_encryption.svg.png 601w&apos; sizes=&apos;(max-width: 601px) 100vw, 601px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;보면 일반적인 블록 암호화보다 입력 파라미터가 하나 더 있습니다. IV라는 건데요. 직역하면 초기 벡터로 암호에 영향을 주는 또다른 팩터라고 이해를 하면 되겠습니다. CBC 모드를 보면 그냥 블록 암호화를 하는 것이 아니라 암호화를 하기 전에 IV와 XOR을 수행한 다음 그 결과물을 블록 암호화를 시킵니다. 다음 블록의 경우에는 IV가 그 전 블록의 암호화한 결과 값이 됩니다. 따라서 블록 별로 어떤 컨텍스트에서 암호화가 되느냐에 따라 동일한 소스에 동일한 키로 암호화를 하더라도 결과 값이 달라집니다. 그말은 궁극적으로 기본적인 블록 암호화 기법보다 패턴을 알아내기가 훨씬 어려워진다는 걸 의미합니다.&lt;/p&gt;
&lt;p&gt;연산 모드를 설명한 &lt;a href=&quot;https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation&quot;&gt;위키 페이지를&lt;/a&gt; 참고하면 다양한 연산 모드가 소개되어 있으니 한번 살펴보도록 합시다. 연산 모드 설명 옆에 병렬 처리, 랜덤 읽기 지원 여부를 비교해 둔 표도 같이 있으니 함께 살펴보면 더 많은 공부가 될 것 같기도 합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 부스트 라이브러리 CRC32 계산하기]]></title><description><![CDATA[부스트에는 참 많은 기능이 있죠. CRC 계산하는 루틴도 포함되어 있습니다. 그것도 사용하기가 너무 너무 쉬워요.
그럼 일반적으로 많이 사용하는 32비트 CRC를 계산 루틴을 한 번 살펴볼까요 ㅋ~ crc.hpp 일단 인클루드 해 주시구요. crc…]]></description><link>https://jiniya.net/ng/2015/12/calc-crc32-using-boost/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/12/calc-crc32-using-boost/</guid><pubDate>Thu, 10 Dec 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;부스트에는 참 많은 기능이 있죠. CRC 계산하는 루틴도 포함되어 있습니다. 그것도 사용하기가 너무 너무 쉬워요.
그럼 일반적으로 많이 사용하는 32비트 CRC를 계산 루틴을 한 번 살펴볼까요 ㅋ~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/crc.hpp&quot;&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;crc_32_type crc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	crc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;process_bytes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bytes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bytes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%08x\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; crc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;crc.hpp 일단 인클루드 해 주시구요.&lt;/li&gt;
&lt;li&gt;crc_32_type이 우리가 계산할 32비트 CRC를 계산하는 클래스 타입입니다.&lt;/li&gt;
&lt;li&gt;process_bytes로 CRC 계산할 버퍼를 계속 공급해 주시면 됩니다. 버퍼 포인터와 크기라는 건 뭐 그냥 아시겠지요?&lt;br&gt;
참고로 한번에 넘기기 큰 데이터는 분할해서 process_bytes를 호출하면 됩니다.&lt;/li&gt;
&lt;li&gt;checksum 메소드를 사용하면 계산된 32비트 CRC 값이 넘어 옵니다.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[[cpp] 16진수 헥사 인코딩의 정석]]></title><description><![CDATA[최근에 퍼지 해시(fuzzy hash), 롤링 해시(rolling hash), 지역 민감 해시(Locality-sensitive hash) 등으로 불리는 코드를 좀 찾아보고 있었습니다. 대체로 ssdeep을 많이 사용하는 것 같은데 ssdeep…]]></description><link>https://jiniya.net/ng/2015/11/hex-encoding/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/11/hex-encoding/</guid><pubDate>Thu, 26 Nov 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;최근에 퍼지 해시(fuzzy hash), 롤링 해시(rolling hash), 지역 민감 해시(Locality-sensitive hash) 등으로 불리는 코드를 좀 찾아보고 있었습니다. 대체로 ssdeep을 많이 사용하는 것 같은데 &lt;a href=&quot;http://ssdeep.sourceforge.net/&quot;&gt;ssdeep&lt;/a&gt;의 경우 안타깝게도 GPL 이더군요. 그래서 다른 종류는 뭐가 있나 하고 알아보던 중에 트렌드마이크로에서 공개한 TLSH를 찾았습니다. &lt;a href=&quot;https://en.wikipedia.org/wiki/Locality-sensitive_hashing#TLSH&quot;&gt;위키피디아에는 TLSH란&lt;/a&gt; 보안과 디지털 포렌직 프로그램을 위해 설계된 지역 민감 해싱 알고리즘이라고 나와 있습니다. 그쵸. 바로 우리가 찾던 그 녀석이죠. 걔다가 착하게도 아파치 2.0 라이선스라는 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;형님들이 작성한 코드를 좀 보다가 재미난 부분이 있어서 올려봅니다. 바이너리 데이터를 16진수 헥사 코드로 인코딩하는 코드입니다. 아래처럼 작성되어 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;to_hex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; psrc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; pdest &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; HexLookup&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;513&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;000102030405060708090A0B0C0D0E0F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;101112131415161718191A1B1C1D1E1F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;202122232425262728292A2B2C2D2E2F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;303132333435363738393A3B3C3D3E3F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;404142434445464748494A4B4C4D4E4F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;505152535455565758595A5B5C5D5E5F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;606162636465666768696A6B6C6D6E6F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;707172737475767778797A7B7C7D7E7F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;808182838485868788898A8B8C8D8E8F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;909192939495969798999A9B9C9D9E9F&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;A0A1A2A3A4A5A6A7A8A9AAABACADAEAF&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; pwHex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;HexLookup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; pwDest&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;pdest&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;len&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pwDest&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pwHex&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;psrc&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		pwDest&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; psrc&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;pwDest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// terminate the string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 뭐 특별할 건 없지만 00부터 FF까지 테이블을 작성한 형님들의 노고에 박수를 ㅋㅋㅋ~ 통상적으로 배열을 만들면 &quot;0123456789ABCDEF&quot; 정도 만들어서 사용하기 마련인데요. 한땀한땀 성능을 생각하신 형님들께서는 친히 00부터 FF까지를 모두 테이블에 담아버렸습니다.&lt;/p&gt;
&lt;p&gt;테이블을 룩업 하는 과정은 더 C언어 스러운데요. 문자열 테이블을 USHORT 포인터로 변환해서 2바이트씩 한번에 복사해 버림으로써 불필요한 연산을 최소화해주셨습니다. 0을 넣는 부분에는 깨알같이 &quot;terminate the string&quot;이란 주석까지 ㅋ~ 장인 정신이 묻어나는 코드가 이닐수가 없네요. 코드를 보면서 &quot;0123456789ABCDEF&quot;만 만들어서는 쉬프트와 더하기를 남발했던 저는 배꼽 반성을 했습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/trendmicro/tlsh&quot;&gt;TLSH GitHub 저장소를&lt;/a&gt; 보면 코드와 함께 발표한 논문 자료와 다른 알고리즘(ssdeep, sdhash)과의 비교 자료도 함께 있는데요. 굉장히 인상적입니다. 이런게 바로 리서치가 아닐까 싶네요. 사족을 하나 더 달자면 그간 트렌드마이크로를 그닥 의미 없는 백신 제품이라 생각했는데 이 코드 하나로 저에게는 기업 이미지가 굉장히 좋아졌습니다. 물론 그렇다고 트렌드마이크로 백신을 산다는 소리는 아닙니다 ㅋㅋㅋ&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 출산 이모저모]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/ng/2015/11/about-childbirth/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/11/about-childbirth/</guid><pubDate>Wed, 11 Nov 2015 15:00:01 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./chaerin1.jpg&apos; data-alt=&apos;여긴 어디? 난 누구?&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f8e21cedf6c81b9e3a4a86ba2f70264d/953fe/chaerin1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQP/2gAMAwEAAhADEAAAAXuyJwXBwdf/xAAcEAABAwUAAAAAAAAAAAAAAAABAAIDBBAREjH/2gAIAQEAAQUCp5GNUsYJ1dbCHP/EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/ARn/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwFX/8QAHRAAAQIHAAAAAAAAAAAAAAAAAgARARIgMTJRkf/aAAgBAQAGPwJivtOJSvxZRo//xAAZEAADAQEBAAAAAAAAAAAAAAAAARExQVH/2gAIAQEAAT8hVdNrYUKbwGzChD0WIf/aAAwDAQACAAMAAAAQ7w//xAAXEQEBAQEAAAAAAAAAAAAAAAABABEh/9oACAEDAQE/EGONhf/EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/EKP/xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMVFBcf/aAAgBAQABPxAGqJsQeByHDvbhUO8+ymdHxuUtIYoUcOWAI4T/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;여긴 어디? 난 누구?&apos; title=&apos;&apos; src=&apos;/static/f8e21cedf6c81b9e3a4a86ba2f70264d/953fe/chaerin1.jpg&apos; srcset=&apos;/static/f8e21cedf6c81b9e3a4a86ba2f70264d/8ccab/chaerin1.jpg 190w,
/static/f8e21cedf6c81b9e3a4a86ba2f70264d/ea4c8/chaerin1.jpg 380w,
/static/f8e21cedf6c81b9e3a4a86ba2f70264d/953fe/chaerin1.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;여긴 어디? 난 누구?&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;지난주 할머니와 음력 생일이 똑같은 기염을 토하면서 어여쁜 딸이 세상 밖으로 나왔다. 누나들에게 매번 애들한테 왜그리 집착하며 사는지 점쩜쩜이라고 말을 하면, 누나들은 항상 니 애 낳아 보라는 대꾸를 했었다. 아직 일주일도 안 된 딸을 보면서 그말이 틀리지 않았음을 실감한다. 세상의 모든 부모들이 왜 그런지 말이다. 아이와 자식은 다른 느낌이다. 그냥 자고 있는 것만 보고 있어도 열심히 살아야겠다는 생각이 절로 든다. 뭔가 잘해줘야 할 거 같다는 느낌이 팍팍든다. 위험한 생각이 들때면 와이프랑 그래도 우린 맘충이, 빠충이는 되지 말자며 다짐한다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;출산은 정말 시트콤 같았다. 와이프가 점심 때쯤 진통이 온다며 병원에 전화를 했다. 대략 5-10분 간격으로 온다고 말을 하고는 남편 퇴근하고 가도 되냐고 물으니 간호사가 지금 당장 오라고 했다는 것이다. 와이프의 콜을 받고 부리나케 병원으로 달려갔다. 원래 검사를 하던 의사는 없어서 다른 의사가 태동 검사를 하고 내진을 했는데, 뭐 자궁이 하나도 안 열렸고 진통도 별로 없는거 같다며 아직 한참이나 남았을 거 같은데 왜 왔냐는 늬앙스로 이야기를 했다.&lt;/p&gt;
&lt;p&gt;누구나 한번쯤 겪는다는 빠꾸를 맞고는 앞에서 항정살에 7분 김치찌게를 먹었다. 밥을 먹는데도 와이프는 연신 배가 아푸다고 했다. 의사가 하도 완강하게 이야기해서 설마 벌써 그렇겠냐며 5분 간격으로 정확하게 오면 가자고 했다. 그리고는 내심 오늘은 아니라는 생각을 많이 했었다. 엄마는 눈이 뒤집힐정도로 아플 때 병원을 가야 한다는 말을 했었다. 그런데 와이프는 너무 평온해 보였다. 진통이 올때 아파했지만 눈이 뒤집힐 지경은 아니었다.&lt;/p&gt;
&lt;p&gt;회사 들어가기도 애매하고 혹시 몰라 집에 있었다. 앱으로 계속 시간 측정을 했다. 5분 내로 진통은 계속 왔지만 우리는 아니라고 생각했다. 설마 의사가 그랬는데 불과 2-3시간 지났는데 시작됐겠어? 이건 아닐꺼야 그런 생각이었다. 저녁 먹을즈음에도 진통은 3-4분 간격으로 계속 왔다. 엄마가 뭐라도 먹어야 애도 낳는다는 말에 일단 밥을 먹자고는 배달 음식을 시켰는데, 그 배달 음식이 딱 도착하기가 무섭게 양수가 터졌다.&lt;/p&gt;
&lt;p&gt;병원을 향해 달려갔다. 퇴근 시간인데다 서울대입구 4거리는 늘 헬게이트, …​ 와이프는 정말 눈이 뒤집히고 있었다. 눈물을 흘렸다. 어쨌든 병원에 도착했고 바로 분만실로 갔다. 간호산지 조산산지 뚱땡이가 왜 이제 왔냐며 뭐라고 했다. 아침에 있었던 일을 이야기 했지만 의미는 없었다. 벌써 자궁이 5cm이나 열렸다고 했다. 30분쯤 지나자 7cm, 한시간 좀 넘어서는 8cm가 열렸다고 했다. 무통은 의미가 없다고 했다. 일찍 와야 맞을 수 있는데 이미 다 지나가서 지금은 맞을 수가 없다는 이야기. 와이프는 절규를 했다. 무통과 제왕절개를 욕과 함께 미친듯이 요구했지만 그저 바라볼 수 밖에 없었다.&lt;/p&gt;
&lt;p&gt;뚱땡이 간호사는 정말 불친절했다. 틱틱거리며 와이프에게 시종일관 명령과 지시의 태도를 보였다. 아픈데 그러니 말이 통할리가 없다. 난감한 상황. 하지만 3시간쯤 지나 출산이 임박했을 때 해결사가 들어왔다. 벌써 사람 다루는 폼새가 남달랐다. 특히나 목소리가 너무 좋았는데 마치 최면에 걸려서 그 말을 꼭 따라야 할 것 같은 그런 목소리였다. 와이프는 어렵지 않게 그 사람의 말을 따라했고, 몇 분 지나지 않아서 아이가 나왔다. 병원온지 3시간 50분 만에 순산했다. 의사가 오고 아기가 너무 쉽게 나와 좀 어이가 없었다. 힘주세요. 한 번 더 하는데 나왔다. 엉겹결에 탯줄을 끊었다. 채린이가 그렇게 태어났다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./chaerin2.jpg&apos; data-alt=&apos;어서와, 이런 세상은 처음이지&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1556b980ed49b0c8fce4c95bf4807b66/953fe/chaerin2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgX/xAAWAQEBAQAAAAAAAAAAAAAAAAADAQL/2gAMAwEAAhADEAAAAXKMKmmaSXP/xAAaEAEBAAMBAQAAAAAAAAAAAAABAgADEhEi/9oACAEBAAEFApPM2kpsPrmQq6Mqnr//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAbEAABBAMAAAAAAAAAAAAAAAAAAQIhMSJBUf/aAAgBAQAGPwLhWbiChZ2Kf//EABgQAQEBAQEAAAAAAAAAAAAAAAERIQBB/9oACAEBAAE/IT3SPFx5XFCk7WYnGSOcBExyEXV7/9oADAMBAAIAAwAAABCjP//EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxDRn//EABYRAQEBAAAAAAAAAAAAAAAAAAABQf/aAAgBAgEBPxDUf//EAB0QAAIBBAMAAAAAAAAAAAAAAAERACFBUWExkbH/2gAIAQEAAT8QfgTkui0FQiqVHvVIFYqAg5UuhcsP2IhEIBQR2FglT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;어서와, 이런 세상은 처음이지&apos; title=&apos;&apos; src=&apos;/static/1556b980ed49b0c8fce4c95bf4807b66/953fe/chaerin2.jpg&apos; srcset=&apos;/static/1556b980ed49b0c8fce4c95bf4807b66/8ccab/chaerin2.jpg 190w,
/static/1556b980ed49b0c8fce4c95bf4807b66/ea4c8/chaerin2.jpg 380w,
/static/1556b980ed49b0c8fce4c95bf4807b66/953fe/chaerin2.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;어서와, 이런 세상은 처음이지&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;의사가 그랬다. 상위 10% 들 정도로 순산했다고. 물론 거기 순위를 메긴다는게 우습긴 하지만 정말 쑨풍 나온 것 같긴 했다. 와이프 한테도 채린이한테도 고맙다. 옆에서 지켜보는 것도 보통 고통이 아니기 때문이다. 무통과 제왕절개를 외치는 것을 가슴으로는 백번도 더 시켜주고 싶지만 머리로 말려야 한다는게 결코 편하지는 않기 때문이다. 나도 힘들었는지 그날 새벽 옷을 갈아 입으로 집으로 가서는 씻겠다고 욕조에 물을 받아놓고 그 안에서 잠이 들어버렸다 ㅋㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;사실 난 대한민국 복지에 대해서 크게 느낀 바가 없다. 내 급여에서 상당한 금액의 의료보험료와 고용보험료가 나가지만 크게 병원을 간 적도, 실업 급여를 받은 적도 없다. 더 많은 국민연금을 내지만 그 연금을 잘 수령할지는 미지수다. 더 (체감상) 천문학적인 소득세를 내고 있지만 정말 이렇게까지 뜯어가야 하나 싶은 생각만 있었다. 그나마 약간 느낀게 엄마가 암 수술을 했을 때 중증 환자로 5%의 비용으로 치료를 받는 걸 보고는 의료보험은 그나마 제구실을 한다는 생각을 했었던게 전부였다.&lt;/p&gt;
&lt;p&gt;그런데 이번에 아이를 낳고 보니 생각보다 우리나라가 그리 구리지는 않다는 생각이 많이 들었다. 우선 부탁한적도 없는데 자연분만에 드는 일체의 비용을 국가에서 부담해 주었다. 거기다 청각 검사와 대사 증후군 검사를 무료로 해주고, 그것도 모자라 결핵 예방접종도 해줬다. 병실료와 영양제 값만 나온 청구서를 보고는 참 고맙다는 생각을 했다. 관악구에 출생신고를 하러 가서는 선물을 안 줘서 조금 실망했지만 육아수당을 준다는 이야기를 듣고는 좋다는 생각이 들었다. 그것도 소득수준에 관계없이 준다는 데 감사한 마음이 많이 들었다. 물론 여기서 끝이 아니다. 아이를 어린이집에 보낼 경우 모든 비용을 국가에서 부담한다. 그것도 초등학교 입학할때까지 모든 비용을 말이다.&lt;/p&gt;
&lt;p&gt;보건소도 나쁘지 않다. 임신 중에도 각종 검사와 약을 지원해주고, 출산 후에도 상당히 많은 신생아 예방 접종을 지원해준다. 그것도 보건소에 가서 맞아야 된다고 생각을 했었는데 대부분의 큰 병원이 모두 제휴가 되어 있어 그냥 병원에서 맞아도 비용을 다 국가에서 지불해준다. 참 편리한 시스템이라는 생각이 들었다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;프로그래머는 숙명적으로 무엇인가의 이름을 지으며 살아간다. 언젠가 인터넷 설문조사에서는 프로그래머가 느끼는 고충 중에 당당하게 1위로 이름짓기(Naming)가 올라와 있었다. 어쨌든 그렇게 이름을 수도 없이 지으며 산다. 그래서 그랬을까? 와이프의 임신 소식을 들었을 때 이름이 뙇 떠올랐다. 딸이면 채린이라 짓고, 아들이면 태성이라 지으리라. 심지어 아들 이름은 한자까지 떠올랐다. 클 태에 이룰 성으로 지어야지 ㅋ~&lt;/p&gt;
&lt;p&gt;병원에서 퇴원하는 날 난 엘티이급으로 출생신고를 했다. 하지만 이름을 가지고 잡음이 좀 있었다. 엄마가 어디서 지었냐는 출처를 계속 캐물었기 때문이다. 어디서 지었냐? 그렇다 우리나라 사람들은 이름을 대체로 스스로 짓지 않는다. 어딘가에 위탁한다. 철학관, 작명소 같은 곳 말이다. 사주도 풀고 그런단다. 내가 지었다는 말을 결코 신뢰하지 못할 우리 엄마를 위해서 월정사 명월스님에게 지었다는 이야기를 했다. 그러자 엄마가 조금 안심을 한다. 대기업 회장님들도 찾아가는 유명한 스님이라고 하자 더욱 신뢰를 하셨다. 우습지만 그게 현실이었다.&lt;/p&gt;
&lt;p&gt;결혼을 하는 날짜도, 이사를 가는 날짜도, 이사를 가는 방향도, 애 이름도, 사업을 할지 말지도, 유학을 갈지 말지도, 우리 나라 사람들은 대체로 스스로 뭔가를 결정하지 못하는 것 같다. 다 좋은게 좋은거고 조심해서 나쁠건 없다는 이야기를 한다. 그렇게 잡은 결혼 날짜에는 미친듯이 비가 왔다. 그제야 하는 말. 비 오는 날 결혼하면 잘산다는 이야기. 이건 뭐 피할 수가 없다 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;이것도 좋고, 저것도 좋고, 다 좋은데 이름 하나쯤은 내가 지어주고 싶었다. 내가 생각하는 딸에 대한 애정이랄까? ㅋ~&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;산후조리원과 산후도우미, 어린이집에 관해서도 할 이야기가 많지만 시간 관계상 이쯤에서 마치는 걸로 ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;&apos; data-url=&apos;./chaerin3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/700fcfb749715b01b52675383f2d7e18/0eb09/chaerin3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACpUlEQVR42hXPyU4TAQCA4XkET140GhO8GDUeNIYLEo0SDTHgATVoJVIRlKAitlKsQFukC0tL0g1K9226Tfdpp8u0022mlO7DdGMzGuNbWB/gS/4fQEzcBCT2mwQ25UIuCqYR0KXgmliv7Et09fdxnWDGs7MUtm5EnDLUq/Fp2HreiHi6jzF0abL/DODZZYYsfI9iAZIxIuAm6pCirp00DO1h0SKOVfeJapEoF/AikS7mccQutolfq9hDPNqNDw/OAqqFARX7iXn5pV/+KaznxUFJPuqp5DNkqUDVylS1RJYLtXKhuJft+rBt3SmdsghpWzN35ocvAKLxq3x6n45DQ/ScOLiZcusiFn0lEepU949b1OlR55CsHGDRaipWLuSjDgmkmLaujykY95eeXQZ4tGsrE3fVnDHEICACaiFrVidaacCOZhLuZNGT5sHpYbuVQcmIr7uQhrUxJz9oYFpET0UT1wHWyBUuvV/+bTSgWS3FHHz2vJz5kbJISUhH2TT/fafRyBNVNFxEQynfLuaXxaG1kHnOtjEIvH/UwxztnRnpdcgWi8lAhcDKmSQOakm7qgHbj8jySeuA9JlLYXfSaUxA8lRAhrrXQsbPDskw8Hbg4tzzW5zJe04pk4DN+USoXsi0qVp39ZiqHVP1Tq1cQ9ylqD/ltSa9yi6OQ0LYOJsKioDZh+d/0HtlXx+b1yZTRj4OaXDYVUwiZAGv7+FVHMuFPXGPOe4xRJwqzLed9G7FXMJsTNVuE8Dy6LnNdzeVrEHV8guXlBtULjpl7JBtJ+bWRSFNFFKhXjXm12ABTRpWp4PbaXi7kLG32viv3xQgmOqRMm4bV4dByRvz1heHmhuyihLdvKAWR0z5OJiPgXjElEMM2bA2FzOUCE+zmTn9Wf/z9+gfvTCoWK8QzGMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;chaerin3&apos; title=&apos;&apos; src=&apos;/static/700fcfb749715b01b52675383f2d7e18/0eb09/chaerin3.png&apos; srcset=&apos;/static/700fcfb749715b01b52675383f2d7e18/08678/chaerin3.png 190w,
/static/700fcfb749715b01b52675383f2d7e18/2edd7/chaerin3.png 380w,
/static/700fcfb749715b01b52675383f2d7e18/0eb09/chaerin3.png 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 100인 기업은 얼마나 많을까?]]></title><description><![CDATA[언젠가 모 회사 분과 이야기를 하다 그런 말을 들었다. 회사가 어려운데 구조조정을 하지 않는 이유 중에 하나가 대표의 욕심 때문이라는 이야기였다. 대표가 일정 수준 이상이 되는 규모로 회사를 유지하려는 욕심이 있다는 말이었다. 100인 기업, 10…]]></description><link>https://jiniya.net/ng/2015/10/company-size/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/10/company-size/</guid><pubDate>Fri, 30 Oct 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;언젠가 모 회사 분과 이야기를 하다 그런 말을 들었다. 회사가 어려운데 구조조정을 하지 않는 이유 중에 하나가 대표의 욕심 때문이라는 이야기였다. 대표가 일정 수준 이상이 되는 규모로 회사를 유지하려는 욕심이 있다는 말이었다. 100인 기업, 100억 매출 이런 상징적인 이미지를 가지고 싶어한다는 말이었다. 난 상징적인 이미지보다는 실속을 더 따지는 편이라 100명이서 100억 버는 회사 보다는 2명이서 3억 버는 기업이 더 좋을텐데라는 생각을 했었다. 그리고 막연하게 100명, 100억 하는 회사가 흔하지는 않아도 자부심을 가질만큼 귀하지는 않을 것 같다고 상상했다.&lt;/p&gt;
&lt;p&gt;그런데 현실은 아니었다. 어제 팩트 체크를 보다가 우연히 아주 충격적인 사실을 알게 되었기 때문이다. 사업 분야를 불문하고 우리나라에 존재하는 모든 기업 중에 100인 이상의 종업원을 고용한 기업이 무려, 당황스럽게도 0.8%밖에 되지 않는다는 사실이었다. 아래 그림처럼 말이다. 8%도 아니고, 무려 0.8%다. 소프트웨어 기업은 일반적인 기업보다 보통 작은 규모인 경우가 많으니 100인 기업은 비율이 훨씬 더 낮을지도 모른다. 더 충격적인 사실은 10명 이상 고용한 사업체도 전체 기준으로 봤을 때는 상위 15% 안에 포함된다는 사실이다. 30인 이상은 상위 4%에 포함된다. 헐~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./fact.png&apos; data-alt=&apos;JTBC 팩트 체크&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0242affe62f6b0674437b3d03c4031ca/abf7b/fact.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACoElEQVR42g3NWVMSAQAA4H1qSkcF1AFxCTmWc9ldlt0F9uDYhRVYBUTlyPJOLcYmtWk8OkZrPDJNm3RQ0RRRQaemhx6cmuq9XvtB9f2BD2hkMy1CrhWhdUab2e6EUdKBERjFuDmeCUVpIeIT42IinUjf684OxNP9fEdPT99Ifno2EEkCtcHBW/bADTlYpzTKWi1KHarSOUALHklke3P3pa676Tsjmezo6PCjXGZQSmZ87fFYKjc4lmdDMaABIhqbNQqVXqW1tuhgvY3S2wkT5vV4BEGMBMPhcLSjMx4NiqLH1y6E40EpyYUlDy9yYgyQN2uaWoxylb4RNKvbHHoLobcREEozDN+V8UUSnNQd6skEYx1iwBfj+RgdijJCOxuKUD4ekCvb5Ep9g1IHQYjGTEJsh4HrNOKsi+RpJkYSQkBMsH6JcPlJyo9QHOr1O+mAiw0iHgaok6lr5aBaY1mcGNfaGXNyzNQ9biB5C85hdNiJe5GJBTQ1ALsYs5MyO90OinN6AzgdQN0MIFOA9XJQJleBoLZJbYK4JCT1G3DO4WJxgsMeLCBf/+LH310Dk1hIsqGEHSUR3I2RtBUjAEVTW0OjpuZmPW5z/H9UEGnkU/DUGrZZxdfLyPFPR+mX8+q36+jatV2xbn+yTjyDo70wI1gdOFBTo6iTqfRa02gmm+0bum3EUMqPh1NoNAuL3UYqqMVZHeEzuHkdGVBTghqmWo1wi9bUrASBz+fl4rs326srS/OzB1tb5f2948JueW/n4qBQOdy7OCpWSh+rpyfV01K1VKqclC7PL66ql6en5WLxEPjz49v1WWH9ydDK9NDy1PDazOjG3MON+fzb2fzm/OTW88fvX858WHy682pu9/V8YflFYW2puLl6vr/75eLsH2lZwszRX5DdAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;JTBC 팩트 체크&apos; title=&apos;&apos; src=&apos;/static/0242affe62f6b0674437b3d03c4031ca/abf7b/fact.png&apos; srcset=&apos;/static/0242affe62f6b0674437b3d03c4031ca/08678/fact.png 190w,
/static/0242affe62f6b0674437b3d03c4031ca/2edd7/fact.png 380w,
/static/0242affe62f6b0674437b3d03c4031ca/abf7b/fact.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;JTBC 팩트 체크&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;팩트 체크니까 구라 자료는 아닐꺼라 생각했지만 0.8%는 다소 충격적이었다. 그리고 화면에는 나오지 않은 30-49인, 50-99인의 세부적인 비율도 궁금해서 좀 찾아봤는데 아마도 JTBC의 자료는 고용노동부에서 발표한 아래 자료에 기반하고 있는 것으로 보였다. 아래 자료 수치대로하면 30-49인은 전체 사업체 중에 2%를, 50-99인은 전체 사업체 중에 1.25%를 차지한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./company.png&apos; data-alt=&apos;고용노동부 2013 기업 규모별 사업체수 통계&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 608px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f0f301ff88cc78e2aa2ecb56fbb3958d/5db90/company.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACAUlEQVR42h2QW3ObMBCF+f9/og996XT60Jm0nThtpqmbPnQy9qRxwAYkgYQkJAQGgy9cBOniF420R7vn2+OgpApoudpmz1u5dsUW5ztiXJRvsdkEektyP8pdlMHTQ8Yn5mWnCS9V3ghdOx8WwbuP6/efXz/dbW5+rJZP0cNf9OX++fsf//cq/vrz5XbpPq7p3aP37eFlsfQWy9eb+3+3S+/XE3HWm9ALWBjrmOdptidUECqlKnwUB5gpU3FpcMRFmku99xHFVPDUeD6mSeqQmAqZZnlRHuphGLgQ8JymKUl4FMXjOB2PxyBEzfE0TW+cC50ZuMAvyhInIDGOmdAmK6q+twmXjMu2GxjjUUwv7dA0J4RJVTWzmgiRalBBYolwAhztQiRUZvbVYMdUacZF1w/gT+bmvu16+FkdGijCRaa6Hyy0ylQ5IY4CRKTKgBt4TF5A1doRThjfdb21FjI41A0UZ2xtrmqqlHYQoT7CEeP7qh6nab+vIJwZIVUkopeuh7WVNmV1GGFnIcEZVEoTSpnjI7IFa5YUZT3at7I8CKkAAdwwidoWnCdIswR1nIupyuDCkjkRZxdidwepMcCGkZAqONtxguUxic8Qjh2BubxyKZ1xOavQjKN4dnZ3fpyIoqphmfOl1VkOkQAn5xICs+PY9f3p3EJzdai1yWGcuPL/B6lCU0tngZ2VAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;고용노동부 2013 기업 규모별 사업체수 통계&apos; title=&apos;&apos; src=&apos;/static/f0f301ff88cc78e2aa2ecb56fbb3958d/5db90/company.png&apos; srcset=&apos;/static/f0f301ff88cc78e2aa2ecb56fbb3958d/08678/company.png 190w,
/static/f0f301ff88cc78e2aa2ecb56fbb3958d/2edd7/company.png 380w,
/static/f0f301ff88cc78e2aa2ecb56fbb3958d/5db90/company.png 608w&apos; sizes=&apos;(max-width: 608px) 100vw, 608px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;고용노동부 2013 기업 규모별 사업체수 통계&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그런데 뭔가 좀 이상하다. 100인 이상 기업이 전체의 0.8% 밖에 되지 않는데 내 주변 사람들은 거의 대다수가 100인 이상 기업에 다니기 때문이다. 그건 사업체 수가 아닌 해당 사업체에서 근로하는 근로자수를 비교해야 비로소 의문이 풀린다. 옆에 있는 상용 근로자를 기준으로 데이터를 뽑아보면 아래와 같이 나온다. 100인 이상 기업체 수는 전체 기업체에서 0.8%를 차지하지만 해당 업체에 근무하는 상용 근로자 수는 전체 근로자에서 27%를 차지한다. 그러니 100인 이상 기업에 근무하는 사람은 쉽게 찾을 수 있는 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./employee.png&apos; data-alt=&apos;기업 규모별 종사자수 계산&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 292px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e3fc24458a67fc4126e041fe5c565495/73e11/employee.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 83.6842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACOklEQVR42mWT25qjIBCEff/3m3gW8DgCCqImnmK2kJl8u1mvRPqnqujWO/Z9HEczjo/H4/n77Pt+HAdeluUxzdM8zyhYluU8z33f7vc7vjwei/c89vDm34KgquvX6+UYB5/PoyyLKI7TJP66+XowKJiMTtI0jqNeaQ9Fxgx1XQkh/4bxYKmVisKwFSLLMmNGfIGYEDxKUq21h6JBK0aZkBZ+27bweSqFLdo0DWP58AvLThZlhbDeui6C84xQwcV/yhaGQ5Dwr5S+4K2THRcSwT2Ucv7NWx6EkRQ/4m/bfScpo0r1sN07eN84bxOkgDKkmqbGOk3Trus/4GEYKKV1XcLncF3Y83kgJqEMW8i8FXnBOY/jWMruA0ZLoFkWOaEUF3Zez6A1WmOM8bZtLYqirqqbH/RKfcLTnCBzngdR5JQBm0FHUYyltV2WJTLj+Cwj0zSjYNu2X+WJMYZG5nmBkE55NMjCrDIWdVXWTSMl9/3AxX7D0zjiaDQ2I2Qw5uVsDxopLuV9h2Bd13nOfD/se/WGXc9hm2QkSZJrwk58gZ00zawyYEItXFVlEITqXxihKMmwSxlzth0cx4kbzx2dhO1rjBM3CQ5GKY7GdUoh0DBr+7pOp6w1WrVt6LA9m5Cv263r+w/baZIUeR6GkR1Pq3zO04h/A2fZCYMmeMwwYT8T/lbGDLZtKwVPU5fZKuOHJITidmyrsFeURVVW39+t7Dow67qCt3X3GZOktcqL3IyTu4V1WfCraD38ATMqvgsROxpOAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;기업 규모별 종사자수 계산&apos; title=&apos;&apos; src=&apos;/static/e3fc24458a67fc4126e041fe5c565495/73e11/employee.png&apos; srcset=&apos;/static/e3fc24458a67fc4126e041fe5c565495/08678/employee.png 190w,
/static/e3fc24458a67fc4126e041fe5c565495/73e11/employee.png 292w&apos; sizes=&apos;(max-width: 292px) 100vw, 292px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;기업 규모별 종사자수 계산&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;다시 앞으로 돌아와 보면 몇 해 전 내가 했던 상상은 현실이 아니었다. 100인 이상 종업원을 가진 기업은 나의 상상보다 훠얼씬 더 작았다. 0.8%라니, 거기다 그 인원으로 100억 매출을 하는 회사는 훠얼씬 더 작을지도 모른다. 대표 입장에서는 충분히 가지고 싶을 만한 상징적인 이미지라는 생각이 들었다. 물론 회사 외형이나 규모가 전부는 아니지만 말이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 실시간 자식 윈도우 크기 조정]]></title><description><![CDATA[위에서 정의된 상수들은 WM_SYSCOMMAND의 WPARAM으로 전달될 때 그 진가가 발휘됩니다. 상수가 의미하는 바는 위의 주석에 잘 나와있습니다. 위에서부터 표준 윈도우의…]]></description><link>https://jiniya.net/ng/2015/08/child-window-resize-magic-message/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/08/child-window-resize-magic-message/</guid><pubDate>Tue, 18 Aug 2015 15:00:01 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZLEFT&lt;/span&gt;           &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF001&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from left&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZRIGHT&lt;/span&gt;          &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF002&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from right&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZTOP&lt;/span&gt;            &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF003&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from top&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZTOPLEFT&lt;/span&gt;        &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF004&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from top left&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZTOPRIGHT&lt;/span&gt;       &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF005&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from top right&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZBOTTOM&lt;/span&gt;         &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF006&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from bottom&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZBOTTOMLEFT&lt;/span&gt;     &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF007&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from bottom left&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_SZBOTTOMRIGHT&lt;/span&gt;    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF008&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// resize from bottom right&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt;    &lt;span class=&quot;token macro-name&quot;&gt;SC_DRAGMOVE&lt;/span&gt;         &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xF012&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;              &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// move by drag&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위에서 정의된 상수들은 WM_SYSCOMMAND의 WPARAM으로 전달될 때 그 진가가 발휘됩니다. 상수가 의미하는 바는 위의 주석에 잘 나와있습니다. 위에서부터 표준 윈도우의 8방향에서 사이즈를 변경하는 것과 마우스 이동 시 사용할 수 있는 메시지입니다.&lt;/p&gt;
&lt;p&gt;그럼 도대체 위 메시지를 윈도우에 전달하면 어떤 일이 일어나는지 살펴봅시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;SendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WM_SYSCOMMAND&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SC_DRAGMOVE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 위와 같이 메시지를 보낸다면, hwnd라는 핸들을 가진 윈도우의 위치는 그때부터, 마우스를 드래그 하는 방향으로 위치가 변경됩니다. 윈도우가 자식이든 아니든 상관 없습니다. 단지 메시지를 받은 윈도우는 마우스의 변화에 맞게 저절로 위치가 변경되는 겁니다.&lt;/p&gt;
&lt;p&gt;이러한 방법은 자식 윈도우의 위치를 제어할때에도 유용하지만, 캡션과 프레임을 없앤 스킨이 들어간 다이알로그를 제어할때에도 유용하게 사용할 수 있습니다. 제공되는 샘플 소스에는 실행 시간에 8방향에서 사이즈를 변경하는 것과 마우스 드래그에따라 움직이는 Static 윈도우를 보여주고 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//! Static에서 WM_LBUTTONDOWN이 발생했을때 오는 통시 메시지&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param wParam 은 컨트롤 아이디 이다.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param lParam 은 사용되지 않는다.&lt;/span&gt;
LONG &lt;span class=&quot;token class-name&quot;&gt;CdynresizeDlg&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OnMsgStLBDn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WPARAM wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; IDC_MOVE&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;ReleaseCapture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 드래그하면서 움직이는 메시지를 날린다.&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;SendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WM_SYSCOMMAND&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SC_DRAGMOVE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; IDC_RESIZERB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;ReleaseCapture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 오른쪽 아래를 드래그 하면서 사이즈가 변경되는 메시지를 날린다.&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;SendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WM_SYSCOMMAND&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SC_SZBOTTOMRIGHT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[시스템] 엄격함과 느슨함 그 사이 어디쯤...]]></title><description><![CDATA[몇 해 전 지인이 앱스토어 카테고리…]]></description><link>https://jiniya.net/ng/2015/06/between-strictness-and-looseness/</link><guid isPermaLink="false">https://jiniya.net/ng/2015/06/between-strictness-and-looseness/</guid><pubDate>Mon, 29 Jun 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;몇 해 전 지인이 앱스토어 카테고리 1등을 먹어서 아주 수입이 짭짤했다는 이야기를 들었다. 사촌이 땅을 사면 배가 아프게 마련이고, 주변에서 누군가 뭔가를 이루면 자연스레 나도 할 수 있을 것 같다는 근자감에 불타오르게 된다. 야심차게 앱스토어 개발자 등록을 했었다. 소녀시대 퍼즐 앱을 만들겠다는 포부를 가지고는 자료를 수집하기 시작했는데 딱 거기서 끝났다. 한줄의 코딩도 없었고, 공부도 하지 않았다. 내가 개발자 등록을 하고 유일하게 한 거라곤 iOS 베타 버전을 먼저 설치해 보는 정도였다. 돈이 아까워서 설치한 베타 버전이었다. 하지만 엎친 데 덮친 겪으로 베타 버전에 버그가 많아서 그마저도 계륵같은 존재였다. 돈이 아까웠지만 맥북을 사지 않았다는데 마지막 위안을 삼았다. 그렇게 앱 개발은 레드오션이라며 여유가 신포도를 다루듯 나의 머릿속에서 영영 멀어졌다.&lt;/p&gt;
&lt;p&gt;그렇게 영원히 잊혀질 것 같았던 앱 개발을 작년 말부터 친구 녀석이 나에게 다시 세뇌시키기 시작했다. 자기 주변에서는 다 앱 개발을 해서 대박을 쳤다는 이야기였다. 처음 한두번은 그냥 웃어 넘겼지만 녀석의 집요한 이야기 끝에 난 세뇌돼 버렸다. 그러던 한 날 밤이었다. 핸드폰을 만지작 거리며 침대에서 다큐를 보고 있는데, 이놈에 다큐 홈페이지 네비게이션 시스템이 당췌 어이가 없을 정도로 불편한 것이었다. 평소 좋아하던 다큐였기에 그날 코딩에 들어갔다. 그래 이 다큐를 나처럼 편하게 보고 싶어 하는 사람이 얼마나 많겠어 하면서 코딩을 했고 몇 일 사이 베타 버전이 나왔다. 풉, 혼자 만족해 하면서 스토어에 올렸다. 반응은 냉랭했다.&lt;/p&gt;
&lt;p&gt;친구 녀석한테 하소연을 했더니 그런건 너같은 사람이나 보는 거고, 게임 동영상을 보는 게 훨씬 잘 될 거라는 이야기를 했다. 똑같은 앱에 컨텐츠만 바꿔서 올렸다. 다큐가 게임으로 바뀐 앱이었다. 어랏, 그런데 제법 사람들이 다운 받기 시작했다. 광고 수입도 올라온다. 노트북을 질렀다. 설 연휴에 본격적으로 개발해 보겠다는 심산이었다. 그런데 거기서 끝났다. 생각보다 잔손이 너무 많이 갔고, 좀 하다 보니 재미가 없어졌다. 재미난 사실은 그렇게 앱 업데이트를 끊은지가 어언 몇 달이 지났는데도 지금도 꾸준히 광고 수입이 발생한다는 점이다. 이대로 계속 간다면 손익 분기점은 40개월 남았다. 올레, 핡~&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;돈은 못 벌었지만 안드로이드 앱 프로그래밍은 나에게는 신선한 충격이었다. 충격이었다는 말은 배울 것도 많았고, 생각할 거리도 여럿 제공을 했다는 말이다. 그 중에 한 가지를 이야기 하려고 한다. 최근에 페북 앱이 링크를 브라우저로 돌리지 않고 직접 내장 웹뷰에서 보여주는 방식으로 변경해서 테스트를 해보았는데 페북 웹뷰에도 이 처리는 포함되지 않은 것으로 보여진다.&lt;/p&gt;
&lt;p&gt;거창하게 말했지만 사실 요는 간단하다. 아래 페이지처럼 페북 내장 웹뷰에서 제대로 렌더링이 되지 않는 페이지가 있다는 것이다. 지금 모바일 환경이라면 여기서 테스트를 해볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./inven.png&apos; data-alt=&apos;웹뷰에서 인벤 동영상 링크는 어디로 사라진 것일까???&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 308px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2a375177778e5b64a4f0b3b8885e042f/9e38b/inven.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 136.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAErElEQVR42qVUWU8bVxSeB6h4QKIgCqimLAG6EIggCQkoghhDwNQspRiwkqZpq25QEUpC0yRVWvEbKBKQqA9pIlJZqVkLFLBZjG0IRNhmvOExqwFjbGPjBeyxb884UJGEPvXTp6NP58y5c88yg9FotITExHhaVByNFhgYiPkREREB/tjYWLAhISFhYWFgIyMjk5OTQYf6ERQUhIlEIolYIhZOTE5Ojo6O8vl8gUAwNjYGetwPEGKxGMTExMTU1LRAMApReBgs5vGQdrvLarWqVKrNzU2LxWIybev1q0tLiwRBGI1GvV6PEPL5kMWF7B7kJEH77A4nOLHtbZNGswBQKpUajUar1arUalyhwXEljs/LZPL5+XmFQqGmnGqlSq0jdAB43mw2Y21tbVBGQkJCXFwcFBkTExsfH8e8FF3EPJ+bm19ZyWaxWPn5+dnZ2XQ6ncHIjY6Ojo8/AYW3t7djzc3NAQEBUVFR0I+IiLfCwiLTToVfrQ7Oy8tks6tv3Gioqampra2tq6urrq4uZrHeDA6OCg9/IyCgpaUFW1tbk0ql09NUJ4TCCT5/bHL84dxsx8DgMI/3J6Cjo4PL5f7x5Mlvjx8/+fmXjov0h2fP9Tc1rZtM2N7+PpRuMBgUOL6xsUHoCLF4Si5XLC7qoFSoDcYBgtBqF7TadUK3v2rwrOtJm23P7caEEuFPd3+4d+f2ndu37jY2NDXdu/Vj47VrVysrK69cvgKWw+GwAZXs8rLy8qryr66XlX5cQc9jwKWwnl5eAaugoJTJZDHLigsrPiopZhWnpqTQaG9DFxkMBvQpKyvrIj3nTNq5pAuhBez0zIzMpHcTW1tbsT7BIIdTcfnzT77+7NP6L78oL2GVlBQXFlx6PykJjmhoaGi8ebPmm2+/q62tv17PriqvYnPAZGZk3X9wH3v0+6PUrDNppTmJ9LMnsk7nZNM/LGR9kJHyHvNkamFaSlF6alF6csGpk0zQaadLzsdcSEj9PuYdZmjbrw8w7QLB7eJ1jvR3Dg10D/8NPR8VjP81PNAvGRwQD/H4XUf5dITXKegeUUK0h9DqMPQ/gMGikl6f1+vzkF4S6AX4yAMNIcq6PaQb4Dmk1+0m3RDAjEaDTDYjkz3f2FjxL/g8WLn8uVarUavnYdNlslmTyej/Nnyvvlmv3+fzdyQSq1jskkh2pVI7jjumpqwymUMkss3MWCEkkbxYJfRKOuZ0os1NtL2NdDrYM2Q2U3p9nXKurFAaxOoqIsnjavZbONBLWZ+f6HX+Z8OgcvLFlXyHF/MdnuP1HvD45D2vfcewsjkntSwvbSkURqVyC8dBrM/NmQnimEKPJpMk6XK67BaLfWcHrANoszmsVsfOjnN3dw/gcr3EI6DmDGM+KM4/Da/PdyD8muK/AngE/oZBl589Q4uLVH/lcrS1heDCIMCjUiH4AUqlaHkZLSxQTo/n5W6Dl8tFIhGamUFjY2h6GvH5aHiY8giFaHYWdXWhyUnqBd3d1NwOG+hPVihQby/q60M9PdTZkDk3h4aGkFpNiYEBKnlwEI2PIxx/bc57e8hup2izURoOdrvR7i6CBXK5KAEhWDGHg/IfSf4HqF+vuMqBAWsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;웹뷰에서 인벤 동영상 링크는 어디로 사라진 것일까???&apos; title=&apos;&apos; src=&apos;/static/2a375177778e5b64a4f0b3b8885e042f/9e38b/inven.png&apos; srcset=&apos;/static/2a375177778e5b64a4f0b3b8885e042f/08678/inven.png 190w,
/static/2a375177778e5b64a4f0b3b8885e042f/9e38b/inven.png 308w&apos; sizes=&apos;(max-width: 308px) 100vw, 308px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;웹뷰에서 인벤 동영상 링크는 어디로 사라진 것일까???&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;원래 저 비어있는 자리에는 유튜브 동영상이 나와야 함에도 나오지 않고 있는 것이다. 아마 첨에 이런 일을 당하면 아 모바일을 지원하지 않나 보구나 라고 생각하기 쉽상인데, 크롬으로 들어가보면 기가막히게 보인다. 도대체 왜? 그래서 웹뷰는 뭐 한계가 있나보다 하고 넘어가려고 해도 뭔가 찜찜하다. 왜냐하면 오페라나 파이어폭스에서도 정상적으로 보이지 않기 때문이다. 그렇다면 크롬이 무슨 특수한 처리를 해주고 있다는 것인데…​ 도대체 크롬은 무슨 짓을 하고 있는 것일까?&lt;/p&gt;
&lt;p&gt;그냥 크롬이 외계인과 접촉했다고 넘어가기에는 용납이 되지 않았다. 난 너무 장인이니까 ㅋㅋㅋ~ 거기다 누구도 신경쓰지 않았지만 경쟁 앱에게 보여주고 싶었다. 난 웹뷰에서 인벤 동영상 페이지도 렌더링 하지롱, 이라고 말이다. 하지만 집요하게 검색했으나 관련 글을 찾기가 쉽지 않았다. 그렇게 한동안 이 문제에 대해서 제법 고민을 했는데 신이 가엽게 여기셨는지 어느날 갑자기 계시가 내리듯이 어떤 생각이 머리를 스쳤다. 그리곤 그 상상대로 만들어 봤는데 얼추 크롬과 비슷하게 동작하는 것을 볼 수 있었다. 하지만 그 결과는 날 재차 의문에 빠트렸다. 이게 과연 옳은 길일까라는 생각이 들었기 때문이다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;우선 인벤의 동영상 링크를 보면 아래와 같은 구조로 소스가 코딩되어 있다. 플래시 플레이어를 사용하는 유튜브 링크다. 지금 유튜브 링크는 모두 iframe 형식으로 변경이 되었다. 즉, 인벤이 만든 이 코드는 예전 유튜브 코드로 모바일 환경에서는 적합하지 않은 코드다. 그러니 응당 보이지 않는 것이 정상일 것이다. 그러면 도대체 크롬은 어떻게 보여주고 있는 것일까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;embed&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;allowscriptaccess&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;never&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;650&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;366&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token attr-name&quot;&gt;pluginspage&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.macromedia.com/go/getflashplayer&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.youtube.com/v/l9yD5r1AsNo?version=3&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;amp;&quot;&gt;&amp;amp;amp;&lt;/span&gt;hl=ko_KR&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;amp;&quot;&gt;&amp;amp;amp;&lt;/span&gt;rel=0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/x-shockwave-flash&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;wmode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;transparent&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;allowfullscreen&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token attr-name&quot;&gt;allow&amp;amp;#83;criptaccess&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;never&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 650px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 366px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;내가 생각해 본 방법은 저걸 그대로 보여주는 건 말이 안 되니 저걸 통째로 고쳤을거란 생각이 들었다. 왜냐하면 어차피 저 코드에 렌더링할 페이지 주소는 모두 나와 있기 때문에 iframe으로 대체 시키는 것이 어렵지 않기 때문이다. 바로 아래와 같이 말이다. 아래 코드는 문서에 있는 embed를 죄다 찾아서 iframe으로 변경하는 일을 한다. 실제로 안드로이드 웹뷰에서 인벤 페이지를 로딩한 다음 아래 자바스크립트를 샤샥 돌려주면 깔끔하게 비디오 화면이 출력되고 재생도 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; elem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;embed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; elem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; obj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;iframe&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; elem&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; elem&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;frameBorder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; elem&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/v/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/embed/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	elem&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parentNode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replaceChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; elem&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;그냥 단편만 살펴본다면 크롬의 이 재치있는 생각은 나쁠게 없어 보인다. 모바일 준비가 되지 않은 유튜브 링크를 포함한 거의 모든 사이트를 정상적으로 렌더링할 수 있게 만들어주니까 말이다. 하지만 다른 한편으론 나빠 보이기도 한다. 페이지 제작자가 자신이 실수했다는 사실을 인지하기까지 시간을 오래 걸리도록 만든다는 점을 첫번째 문제로 들 수 있다. 왜냐하면 잘못됐다는 사실을 즉각 알려줘야 빨리 고칠 수 있는데 저런 식으로 내부적으로 변형시키는 과정을 통해서 페이지가 정상적으로 렌더링돼 버리면 제작자 입장에서는 문제가 없는 것으로 오해할 수 있기 때문이다. 두번째 문제는 더 심각한데 이런 문제들이 심화되면 사용자들이 특정 브라우저에 강하게 종속될 수 있다는 점이다. 에고가 강한 페이지 제작자가 크롬에 최적화 됐고 다른 브라우저가 이상하다고 말하는 상황을 예로 생각해 볼 수 있겠다. 그렇다면 그 페이지를 꼭 이용해야 한다면 크롬을 사용할 수 밖에 없다. 어디서 많이 본 장면 같지 않은가? 맞다. 인터넷 익스플로러의 몇 년전 모습이다. 그때도 IE는 모질라에서 주구장창 오류를 뿜어대는 스크립트들도 무슨 재준지 기가 막히게 오류 없이 돌려주곤 했었다. ActiveX는 말할 것도 없다. 이제는 그 자리를 크롬이 메우고 있는게 아닐까라는 생각이 잠시 들었다.&lt;/p&gt;
&lt;p&gt;가용성과 하위호환성을 위해서 얼마만큼 느슨해져야 하는 것일까? 또 표준을 지키기 위해서 얼마만큼 엄격해져야 하는 것일까? 물론 여기에 답은 없다. 어떤 사람들은 가용성과 하위호환성에 더 높은 가치를 두기도 하고, 또 어떤 사람들은 순결한 상태에 더 높은 가치를 두기도 한다. 다만 프로그래머 입장에서 한 가지 바램이 있다면 업계를 주도하는 키 플레이어들은 좀 엄격해졌으면 하는 바램이다. 왜냐하면 그들만이 사용자를 변화시킬 힘이 있기 때문이다. 하지만 실상은 메이저 업체들은 계속 알 수 없는 파편화를 주도하고 정작 힘없는 오픈소스들만 표준을 잘 지키는 형국인것 같아 씁쓸한 기분이 든다.&lt;/p&gt;
&lt;p&gt;-- 2014.06.20&lt;/p&gt;
&lt;p&gt;다행이도 이 글을 쓰는 사이 (적어도 12개월+) 인벤은 페이지를 고쳤다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] MmProbeAndLockPages/MmMapLockedPages 함수에 관한 고찰]]></title><description><![CDATA[일반적으로 커널 모드 드라이버에서 사용자 영역의 주소를 고정시키기 위해서는 아래와 같은 함수 호출을 사용한다. MmProbeAndLockPages/MmMapLockedPages 두 함수 모두 인자에 KernelMode/UserMode…]]></description><link>https://jiniya.net/wp/archives/14045</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14045</guid><pubDate>Fri, 26 Jun 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;일반적으로 커널 모드 드라이버에서 사용자 영역의 주소를 고정시키기 위해서는 아래와 같은 함수 호출을 사용한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;mdl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IoAllocateMdl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token function&quot;&gt;MmProbeAndLockPages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mdl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserMode&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;KernelMode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
kptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MmMapLockedPages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mdl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserMode&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;KernelMode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
&lt;span class=&quot;token comment&quot;&gt;// kptr을 통해서 유저 메모리 address에 접근할 수 있음  &lt;/span&gt;
  
&lt;span class=&quot;token function&quot;&gt;MmUnmapLockedPages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;kptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mdl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token function&quot;&gt;MmUnlockPages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mdl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token function&quot;&gt;IoFreeMdl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mdl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;MmProbeAndLockPages/MmMapLockedPages 두 함수 모두 인자에 KernelMode/UserMode가 들어간다. 그런데 그 친절한 MSDN 조차도 이 값을 어떻게 지정해야 하며, 그게 어떤 효과를 가져오는지에 대해서 자세히 설명을 해주지 않고 있다. 단지 MmMapLockedPages의 두 번째 인자는 드라이버라면 대체로 KernelMode를 지정하면 된다 정도의 코멘트만 있다. 심각한 문제는 설명이 이렇다보니 블루스크린이 발생하면 이 값을 막 바꿔주다 발생하지 않는 값이 있다면 아 이렇게 쓰는거구나 하면서 엉뚱하게 변경해 버리는 일이 생긴다는 점이다. 헐~ 대박… 여튼 그래서 각 함수의 KernelMode/UserMode의 의미에 대해서 살펴보는 시간을 가져볼까 한다.&lt;/p&gt;
&lt;p&gt;MmProbeAndLockPages에 두번째 인자는 mdl이 가리키는 영역이 사용자 주소 공간인지 커널 공간인지를 판별하기 위해서 사용된다. UserMode를 넣게 되면 MmProbeAndLockPages 함수가 실질적인 동작을 하기 전에 mdl이 가리키는 영역이 사용자 영역을 벗어나는지 벗어나지 않는지를 점검하는 코드가 추가적으로 실행된다. 만약 사용자 접근 공간(일반적으로 4G 32비트 시스템에서 2G까지)을 벗어나는 영역을 포함하고 있으면 실질적인 동작을 수행하지 않고 ACCESS_VIOLATION 예외를 발생시킨다.&lt;/p&gt;
&lt;p&gt;MmMapLockedPages 함수의 모드 파라미터는 MmProbeAndLockPages와는 다른 목적이다. 이 함수에서 KernelMode/UserMode가 결정하는 일은 최종적으로 생성될 kptr이 유저 영역에 매핑될지 커널 영역에 매핑될지 결정하는 역할을 한다. 즉, 이 파라미터는 mdl이 가리키는 메모리 공간과는 전혀 상관이 없다. 최종적으로 우리가 사용할 포인터를 어느 영역 주소로 정할 것인지를 지정하는 역할을 한다. 그러니 드라이버라면 응당 KernelMode를 쓰는 것이 일반적일 것이다.&lt;/p&gt;
&lt;p&gt;여기서 벌어지는 BSOD의 관전 포인트는 MmProbeAndLockPages 함수로 커널 영역을 가리키는 쓰레기 포인터가 넘어간 경우에 발생한다. 이 경우에 KernelMode가 인자로 넘어갔다면 논페이지드 영역에서 잘못된 참조가 발생할 수 있고 그랬다면 BSOD로 이어진다. 반면에 쓰레기 포인터가 넘어오더라도 UserMode를 지정했다면 커널 영역을 가리키는 포인터이기 때문에 ACCESS_VIOLATION 예외가 발생하고 __try/__except로 예외를 잡아서 동작을 지속시킬 수 있다. 이 경우에 설명이 부실하다보니 쓰레기 포인터가 넘어온 걸 고쳐야 함에도 UserMode로 파라미터를 바꾸고는 아주 이상한 경우에 발생하는 커널 모드 문제를 해결했다며 커밋을 하는 어처구니 없는 경우가 발생한다. 뉴요커 프로그래머라면 이런 실수를 하지 않도록 주의하자~~~ @.@&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./dp.png&apos; data-alt=&apos;의외로 이런 경우가 많다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5642ad9b69de58a3af34cba1232491db/407f2/dp.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADdUlEQVR42mMImHQ/ad6jhDmP4uc8Spj7KG72QyAjaubD2DmPUuY/jgYyZj8CkklzH4MEZz1MW/A4bjZIgf+k+wwWdWfCJlyKmHg5buqV+KlXUmZeTZ5xNaT/UtSkSwnTLidOA4pfjpxwMXnGlchJIMHUmVeTpl8L7rtkUn2KoW39/aY198DoQf3q+w2r7zeueQBkN6191LLhafumZ83rnrSsf9K49lHzukdNax83rH4IVNy89j5QI8OBqx8OXPuw/+qnPScuHDt76vTFCxu27VizadvOA7sXLp0/ceqkLVvXrtuw8vCJg6fPHjl9csexsxcOXP984Op7oEaGQ1ffH7r67uDVjweO7r96ce+pY1sOH1i7Z/faY0fW5mf4Whkq5Ce51BSF7N859dy+6ae2tZ44uuXg9a9ALUCNDOfvfTh/7/35+5+PnTowZ1Z3TEx4RnpcbXXR6tWz+jrzI4Pso0PsCtP8J5X6bZ6QcGJr55mTO84/+Hr+7nugRoZbTz7dfPzh9rPvR45sjIu0FxDgERHk5uRg8vOxWDK3sroyMczL0tdc3dNMI8pUZEmN6+ljm28/+3Hr8QegRob7zz/fffrx2bvfk6dO8fJyVlSQFhcTlpIU1VSX93E393Y3tzIz0dXSsjAzsVEXjbUU7Omoe/7x/92nH4AaQZrvPP306u2XpAknJYJblBTEZWUl1FSktLUULUw0vF0Mw/3sbEzN9ZXkgrQk/HWFi8qK33z5f+cJTPPdZ59fvfqUseOb4ZL75vZ2QgJcUrLSSooy8jKiyjJyphqGVupKMSYy/UGqZa6iMfGJb76iaX75MWHlba19P0yC42SkZNLjw6I9Df1M1KwUNe10NV315Tx0xOKtJcocuLuqsp6hOfv1+5/RhY2iy89rePjLScvZmmo1pTrURpvneGvF2ymkuyo5aApbKIlG67DObcl+iqL5yQegSwL8QxgsPVQN9WUk+Pn5Of3cDSJ8jPwsZKzV+V10+QylWDVE2LW4GMrSYl6B/PwepPneM2Bof3r0+sfaTTu7u/sXLVm2cvXqeQsWLly8ZNmKFdNmzp0+e96EqbP6J03r65/c0ty8dv3mx29+ASMIqJHhyeuvQPT41ZdXH3+///H/9ed/rz7+ff3pL5Dx5vPfd1/+A9H7b//fff3/9ss/IPnyw2+gYoguAG06EBzXQ2dwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;의외로 이런 경우가 많다.&apos; title=&apos;&apos; src=&apos;/static/5642ad9b69de58a3af34cba1232491db/407f2/dp.png&apos; srcset=&apos;/static/5642ad9b69de58a3af34cba1232491db/08678/dp.png 190w,
/static/5642ad9b69de58a3af34cba1232491db/2edd7/dp.png 380w,
/static/5642ad9b69de58a3af34cba1232491db/407f2/dp.png 520w&apos; sizes=&apos;(max-width: 520px) 100vw, 520px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;의외로 이런 경우가 많다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] 변태 패커, Upack]]></title><description><![CDATA[PE 포맷의 각종 잘(?!) 사용되지 않는 Size 필드들을 가지고 장난쳐서 파일을 오버레이 시키곤 하는 변태 패커 중에 Upack…]]></description><link>https://jiniya.net/wp/archives/15072</link><guid isPermaLink="false">https://jiniya.net/wp/archives/15072</guid><pubDate>Fri, 26 Jun 2015 14:00:01 GMT</pubDate><content:encoded>&lt;p&gt;PE 포맷의 각종 잘(?!) 사용되지 않는 Size 필드들을 가지고 장난쳐서 파일을 오버레이 시키곤 하는 변태 패커 중에 Upack이 있다. 자세한 설명은 &lt;a href=&quot;http://www.reversecore.com/53&quot;&gt;이 글을&lt;/a&gt; 참고하도록 하고,… 언젠가 나도 한 번 당했었는데 웬만한 필드는 다 계산해서 사용하기에 문제가 없다고 생각했는데 섹션 헤더를 구하는 부분에 문제가 있었다. 흔히 별 생각 없이 아래와 같은 코드를 사용하고 있었는데 이게 Upack으로 패킹된 파일에는 문제가 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;PIMAGE_NT_HEADERS nt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 적절한 NT 헤더 포인터&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
PIMAGE_SECTION_HEADER sec&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
sec &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_SECTION_HEADER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OptionalHeader에 SizeOfOptionalHeader 필드가 있는데 그 값이 일반적인 값이라면 위 코드는 큰 문제 없이 동작한다. 그런데 Upack은 다르다. SizeOfOptionalHeader를 가지고 장난질을 치기 때문에다. 그래서 아래와 같이 해당 필드 값을 토대로 계산을 해 주어야 정확한 섹션 헤더 위치를 얻을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;\  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;GetSectionHeaderFromNt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; \  
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_SECTION_HEADER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; \  
&lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OptionalHeader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;FileHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SizeOfOptionalHeader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;덧) 자매품 &lt;a href=&quot;http://www.jiniya.net/wp/archives/4250&quot;&gt;UPX의 함정도&lt;/a&gt; 있다 ㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 시작하는 프로그래머를 위한 10원짜리 조언 몇 개…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/10460</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10460</guid><pubDate>Mon, 22 Jun 2015 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;개인적인 경험에 기반에 쓴 것이니 너무 심각하게 받아들이진 말자. 모든 글이 그렇지만 취할건 취하고 버릴건 버리면 된다. 직접 해보니 도움이 된 것들도 있고, 지금 시점에 돌아보니 했었으면 더 좋았을 것 같다고 느낀 것들도 있고 그렇다. 참고로 태생적으로 머릿속에 포인터와 재귀 호출 스택 프레임이 내장된 프로그래머들을 위한 글은 아니라는 점 명심하자!!! (자매품 &lt;a href=&quot;http://www.jiniya.net/tt/675&quot;&gt;개발자를 위한 드래곤볼&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;연애를 하자. 일반적으로 프로그래머들의 커뮤니케이션 스킬이 다른 직종 사람들에 비해서 떨어지는 것은 사실이다. 인정할 건 인정하자. 그런 점들을 보완해주는데 연애만큼 좋은게 없다. 자신의 바닥도 보고 겸손해지기도 한다는 점에서 여러 좋은 점들이 있으니 프로그래밍 공부만큼 연애에도 관심을 가지고 꼭 해보기를 추천하고 싶다. 특히 요즘은 돈 든다고 안 하는 추세도 있는것 같은데 그 돈 투자해 보는게 손해는 아닌 것 같다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;빨리 시작하는 편이 유리한 건 어쩔 수가 없다. 대학교때 컴퓨터 학원에서 C언어를 일년정도 가르친 경험이 있다. 그때 난 어른과 어린 학생들 사이의 명백한 차이가 있는 걸 알게 되었다. 어른들은 무엇인가 자신이 납득할 수 있는 이유가 없다면 잘 받아들이지를 못하고, 또 지루한 과제를 반복하지 못한다는 특징이 있다. 천재 프로그래머인 리누스 토발즈도 그의 자서전에서 밝혔지만 처음 작성한 프로그램은 Hello, World였다. 어린 학생들은 그 단순한 Hello, World 조차도 글자를 바꿔가면서 만드는 과정에서 재미를 느끼는데 어른들은 그렇지가 않다. 그래서 연습이 부족해질수밖에 없고 그러니 당연히 진도가 더디다. 어리다는 것은 지루한 것도 반복할 만큼 호기심이 많다는 것을 의미하기 때문에 지루한 초반 과정을 버티는데 정말 좋다. 더불어 시간이 많다는 것도 장점이다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;늦게 시작했더라도 체력이 좋다면 다행이다. 고등학교 때 알던 녀석 중에 한 명이 2년 내도록 놀다가 3학년 때 일년 바짝 공부 해서 의대를 갔었다. 사실 그 누구도 그 친구가 의대에 진학할 것이라고는 생각지도 못했었기에 다소 충격이었다. 물론 같이 놀았던 친구 녀석들은 부러워 한 정도로 끝났지만 3년 내도록 공부하고 수능을 망친 친구들의 상실감은 이루 말할 수가 없었다. 그 의대에 간 녀석의 장점은 강철 체력이라는 점이었다. 남들이 하루 밤샐 수 있다면 녀석은 3일쯤은 거뜬히 멀쩡하게 밤샐 수 있었다. 대학교 때에도 비슷한 선배가 있었다. 늦게 프로그래밍을 시작했는데 전산소에서 일주일씩 밤새는건 기본인 선배였다. 이상엽씨가 쓴 Visual C++ 6.0 바이블 한글 파일을 들고 다니면서 하루종일 전소에 앉아서 코딩을 하곤 했었다. 난 다소 의아했었는데 지금은 MIT에 유학을 갔던 정말 똑똑한 형이 옆에서 그랬다. 저렇게 체력이 좋은 아이들은 이길 수가 없다고… 그러니 체력 관리가 중요하다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;책을 많이 읽는 것이 여러모로 도움이 된다. 책을 읽는다는 사실이 여러분을 더 똑똑하고 유능한 프로그래머로 만들어준다는 것을 의미하진 않는다. 하지만 적어도 바보같은 프로그래머가 되지 않도록은 만들어 준다는 점에 50원 정도는 걸 수 있을 것 같다. 그러니 책을 부지런히 읽자.&lt;/p&gt;
&lt;p&gt;책을 많이 읽지 않는 사람들이 하는 흔한 실수 중에 하나가 이해가 되지 않는다고 &lt;a href=&quot;http://www.jiniya.net/wp/archives/2539&quot;&gt;계속 1장만 보는 것이다.&lt;/a&gt; 모든 것은 유기적으로 연결되어 있으니 당장 이해가가지 않는 부분이 있더라도 냅두고 끝을 향해 달려가자. 끝을 보고 나면 자연스레 1장은 저절로 이해가 되기 마련이다. 참고로 그때도 이해가 되지 않으면 한번더 끝까지 보면된다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;영어를 잘하는 것이 막판 광역 버프를 받는 지름길이다. 직업 프로그래머를 하면서 다양한 프로그래머들을 만났다. 그중에 더러는 늦게 프로그래밍을 시작한 사람도 있었고, 나보다 훨씬 더 일찍 시작한 사람도 있었다. 그런데 한 가지 신기한 사실은 처음에는 실력 차이가 많이 나는데 한 3년 정도가 지나면 거의 실력이 비슷해진다는 점이었다. 그때부터는 누가 언제 시작했는지 보다는 해당 도메인 지식을 누가 더 빨리 습득할 수 있는가가 실력을 결정짓는 주요한 요소가 된다. 안타깝게도 거의 모든 프로그래밍 자료는 영어인 경우가 대부분이다. 따라서 나중에 줄창나게 버프를 받기 위해서는 영어는 필수적으로 할 수 있어야 한다.&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;대학 교육을 받은 프로그래머들 중 상당수가 기본적인 전산 지식을 중요하게 여기고 도메인 지식을 가볍게 여기는 경향이 있다. 하지만 아이러니하게도 대부분의 경우에는 기본적인 전산 지식보다는 도메인 지식이 중요하다. MS나 구글같은 회사에서 도메인 지식보다 기본 지식을 가진 똑똑한 직원을 뽑는다는 소리를 듣고 그게 중요하다고 생각하는 경우가 많다. 그런데 정말 아주 많이 안타까운 사실은 우리 대부분은 그런 똑똑한 사람들이 아니라는 것이다. 현실을 직시하자. 평범한 우리에겐 기본적인 전산 지식만 가지고 있는 상태에서 도메인 지식을 스펀지처럼 빠르게 빨아들이는 능력이 없는 경우가 상당수다. 그러니 자신이 하고 싶은 도메인을 일찍 정하고 해당 지식을 빨리 습득하는 것이 중요하다. 백신 업체에 취직하고 싶은데 그림판만 매일 만들고 있는건 도움이 되지 않는다는 말이다. 물론 이 말이 기본 지식이 중요하지 않다는 것을 의미하진 않는다. 컴퓨터 공학과에서 열심히 공부한 대다수 졸업생의 기본적인 전산 지식은 도찐개찐인 경우가 많기 때문에 그게 여러분을 돋보이게 만들어주지 않는다는 의미다.&lt;/p&gt;
&lt;h3&gt;#6&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/tt/609&quot;&gt;코드를 많이 읽는 것이 중요하다.&lt;/a&gt; 대학을 졸업한 대부분의 프로그래머가 오픈소스 프로젝트 코드를 수정하는 것은 둘째치고 읽지도 못하고 심지어는 빌드도 못하는 경우가 많다. 이는 정말 큰 문제다. 적어도 여러분이 직업 프로그래머를 하려고 한다면 기본적인 코드는 읽고 이해하고 수정하는 것이 가능해야 한다. 여러분의 경력 대부분의 시간 동안 새로운 코드를 쓰는 시간보다는 다른 사람이 이미 만들어둔 코드를 수정하고 고치는 작업을 하는 경우가 많기 때문이다. 남이 작성한 코드를 읽고 이해하는 능력이 없다면 직장 생활 자체가 매우 힘겨워질 수 있다. 자신이 주력하는 분야의 오픈 소스 코드를 매일 일정 분량 이상씩 읽도록 하자. 물론 참여하기까지 한다면 금상첨화다.&lt;/p&gt;
&lt;h3&gt;#7&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/tt/405&quot;&gt;코드를 읽는 것 만큼이나 쓰는 것도 중요하다.&lt;/a&gt; 많은 사람들이 생각을 잘 하면 코딩도 잘 할거라 전제하는데 생각하는 것과 코딩하는 것은 조금 다른 측면이 있다. 머리보다 손이 기억한다는 말이 있다. 그러니 알고 있는 것이라도 반복적으로 구현해 보는 것이 좋다. 그리고 심심할 때 유용하진 않더라도 작은 프로그램을 직접 많이 만들어 보도록 하자. 코딩도 연습할 수 있고 전체 프로젝트를 기획부터 릴리즈까지 해볼 수 있는 좋은 훈련이 된다.&lt;/p&gt;
&lt;h3&gt;#8&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.codinghorror.com/the-ultimate-code-kata/&quot;&gt;블로그나 위키를 만들자.&lt;/a&gt; 그리고 그곳에 자신이 공부한 것들을 정리해서 올려놓자. 이건 정말이지 여러가지 장점이 있는데 1) &lt;a href=&quot;http://www.jiniya.net/wp/archives/13258&quot;&gt;세상 사람들이 내가 무슨 일을 했는지 알 수 있게 해준다&lt;/a&gt;, 2) 긴 글을 작성하는 훈련을 할 수 있다, 3) 나만의 지식 기반을 구축할 수 있다, 등등 장점은 수도 없이 많다. 그러니 꼭 이 활동을 지속적으로 하자. 보는 사람이 없어도 꾸준히 하는 것이 중요하다. 그리고 본인 생각에 정말 보잘것 없는 것들도 무조건 올리도록 하자. 우리가 구글링해서 알 수 있는 대부분의 지식은 다른 사람들이 그렇게 별 볼 일 없다고 생각하면서 올려둔 지식인 경우가 대다수다. 하찮다 생각하지 말고 꾸준히 정리하고 공개하는 습관을 들이도록 하자.&lt;/p&gt;
&lt;h3&gt;#9&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/archives/10719&quot;&gt;다양한 문화 생활을 경험해 보자.&lt;/a&gt; 드라마도 보고, 영화도 보고, 미술관도 가고, 뮤지컬도 보고, 음악회도 가고, 콘서트도 가고, 만화책도 보고, 게임도 하자. 다 피가 되고 살이 된다. 개그콘서트와 웃찾사를 보는게 꼭 시간 낭비만은 아니다. 오히려 컴퓨터만 주구장창 하는 사람들보다 더 넓은 시각을 가질 수 있게 만들어 준다는 점에 100원은 걸 수 있다. 파이썬 개발자 귀도 반 로섬도 몬티 파이썬의 팬이었다. 그러니 맘놓고 보자. 스트레스 해소도 하고… ㅋㅋㅋ~&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/ylsiAy8azFo?si=cSxI2glNkTxV9hNE&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h3&gt;#10&lt;/h3&gt;
&lt;p&gt;컴퓨터 공학과를 졸업한다고 모두 프로그래머가 되어야 하는 것은 아니다. 컴퓨터를 좋아한다고 프로그래머가 되어야 하는 것도 아니다. 그리고 심지어는 프로그래밍이 좋다고 직업 프로그래머가 될 필요가 있는 것도 아니다. 직업 프로그래머가 되는 것에 관해서 진지하게 생각해보자. 그리고 학교에서 시간이 있을 때 아르바이트던 인턴이던 직업 프로그래머로써의 경험을 조금은 가져 보는 것이 좋을 것 같다. 돈을 받고 프로그래밍을 한다는 것이 어떤 느낌인지에 대해서 약간은 알아둘 필요가 있기 때문이다. 아마도 재미삼아 만들때와는 사뭇 다른 느낌인 경우가 많을 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 와우와 롤은 불법 프로그램이 없을까?]]></title><description><![CDATA[SNS에 모 분이 게임업계 `불법 프로그램`과의 전쟁 선포라는 링크와 함께 와우나 롤처럼 앵벌이 아닌 게임을 만들라는 조언을 붙여놨다. 와우나 롤처럼?! 문득 든 생각이 와우나 롤 해보시긴 하셨나요, 라는 질문을 팍 던지고 싶었다. #…]]></description><link>https://jiniya.net/wp/archives/15002</link><guid isPermaLink="false">https://jiniya.net/wp/archives/15002</guid><pubDate>Fri, 19 Jun 2015 23:59:59 GMT</pubDate><content:encoded>&lt;p&gt;SNS에 모 분이 &lt;a href=&quot;http://www.dt.co.kr/contents.html?article_no=2015061502100831102001&quot;&gt;게임업계 `불법 프로그램`과의 전쟁 선포&lt;/a&gt;라는 링크와 함께 와우나 롤처럼 앵벌이 아닌 게임을 만들라는 조언을 붙여놨다. 와우나 롤처럼?! 문득 든 생각이 와우나 롤 해보시긴 하셨나요, 라는 질문을 팍 던지고 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;요즘 와우는 몰라도 예전 와우의 경우는 정말 오토 돌리기 좋은 게임이었다. 난 것도 모르고 매번 레이드 갈 때 마다 낚시를 손수 꼬박 꼬박 했는데 오토를 돌리고 나서는 신세계를 경험했다. 자고 나니 가방에 물고기가 넘쳐났기 때문이다. 이래서 오토, 오토 하는구나 싶었다. 그간의 그 상대적 박탈감이란 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;블리자드도 이를 모르진 않는다. &lt;a href=&quot;http://www.pcinvasion.com/blizzard-win-legal-case-against-world-of-warcraft-bot-company&quot;&gt;그래서 봇 제작사에 소송을 걸기도 한다.&lt;/a&gt; 하지만 이런 경우는 널리 널리 퍼진 봇인데다 영리성을 추구하는 경우만 해당하는 것이고, 사용자들끼리 만들어서 공유하는 것까지 근절하기는 상당히 힘든 실정이다. 직접 개발한 warden이란 보안 솔루션도 탑재하고 있지만, 성능은 물음표(?) 정도로…&lt;/p&gt;
&lt;p&gt;롤은 전략/액션 게임이니 덜할 것 같지만 더하다. 원래 사용자끼리 승패를 가르는 게임에 핵이 더한 법이다. 왜냐하면 승부에 집착하게 되기 때문이다. “롤 핵”으로만 검색해도 절찬리 성업중인 다양한 불법 프로그램들이 나온다. 절망적인 사실은 롤은 스킨/캐릭을 팔아서 돈을 버는 구존데, 그걸 봉인 해제시키는 무료 툴도 존재한다. 물론 유료로 사는 핵들은 기능이 훨씬 강력하다. 거의 반자동 게임이 가능할 지경인 수준… 롤 커뮤니티에서도 관련된 불만은 수도 없이 제기됐고, 라이엇도 이를 모르진 않는 것 같다. 어떻게 대응을 하는지는 지켜볼 문제지만 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;워크래프트2 모뎀 플레이 시절엔 디스컨넥트에게, 디아블로1을 즐기던 때에는 트레이너에게, 스타크래프트가 유행하던 시기엔 맵핵에게 고통 받았습니다. 월드 오브 워크래프트에 빠져 있던 시기에는 오토봇에게 상대적 박탈감을 느낄 수 밖에는 없었습니다. 블리자드 키드를 자처할 만큼 게임에 푹 빠져 살았지만 온라인 게임 속에는 항상 해킹이 공존했습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;무턱대고 일단 까고 보고 외산 게임이라고 괜찮을 거 같다는 생각은 좀 버리는 게 좋지 않을까라는 생각이다. 이런것도 일종의 사대주의가 아닌가라는 생각까지 들 지경이다. &lt;a href=&quot;http://www.wellbia.com&quot;&gt;회사 홈페이지에&lt;/a&gt; 나와 있는 그 블리자드 키드가 나인데, 진짜 블리자드 게임만 줄창나게 했지만 “불법 프로그램”이 없었던 시점은 단 한 차례도 없었다. 이 세상에 존재하는 온라인 게임치고 불법 프로그램으로부터 자유로운 게임은 없다는 생각이다. 만약 있다면 그 누구도 불법 프로그램을 제작할 만큼의 값어치를 못 느끼는 게임일 가능성이 높지, 보안이나 게임성이 우수해서라고 보기는 힘든 것 같다. 범죄와 마약이 없는 국가를 찾기가 힘든 것과 같은 이치 아닐까나?!&lt;/p&gt;
&lt;p&gt;덧) 게임 내 불법 프로그램 근절에 관심이 많으신가요? 그럼 &lt;a href=&quot;http://www.jiniya.net/wp/archives/6174&quot;&gt;이 글도&lt;/a&gt; 함께 읽어보시길 감히 추천드립니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 물리적인 한계들…]]></title><description><![CDATA[초등학교 때 였다. 요즘은 PC방에 거의 자취를 감춰 버렸지만 그 당시만 해도 아케이드 게임을 들여놓은 오락실이 동네마다 엄청 많이 있었다. 10…]]></description><link>https://jiniya.net/wp/archives/7585</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7585</guid><pubDate>Fri, 19 Jun 2015 23:59:58 GMT</pubDate><content:encoded>&lt;p&gt;초등학교 때 였다. 요즘은 PC방에 거의 자취를 감춰 버렸지만 그 당시만 해도 아케이드 게임을 들여놓은 오락실이 동네마다 엄청 많이 있었다. 100원 짜리 동전 한두개를 가지고 오락실을 가면서 난 항상 고민에 빠지곤 했다. 그 부족한 자원을 가지고 오락실에서 가장 오래 시간을 때울 수 있는 방법을 찾아야 했기 때문이었다. 인기 있는 게임을 하는 것은 재미는 있었지만 위험 부담이 너무 컸다. 중학생이나 고등학생 형들이 연결하기 일쑤였고, 나의 황금같은 100원은 순식간에 하늘 나라로 증발해 버리기 때문이었다. 그래서 구석 한켠에 아무도 하지 않는 오래된 RPG 게임을 하면서 시간을 죽이기도 했다. 나름 최적화된 투자였다.&lt;/p&gt;
&lt;p&gt;세월이 흘렀고, 세상은 많이 변했다. 그때는 G.O.D 가사에 나오는 것처럼 대부분의 집들에서 자장면이 외식 메뉴였지만 요즘은 웬만한 가정에서는 집밥 보다도 못한 메뉴로 전락해 버렸다. 거리에 차도 늘었고, 고급 레스토랑도 늘었고, GDP도 눈에 띄게 늘었다. 그런데 아이러니 하게도 모든게 풍족해 보이지만 여전히 우리는 늘 리소스 부족에 시달린다. 컴퓨터도 그렇다. 난 486 컴퓨터에서 C 프로그램을 짤 때에도, 펜티엄에서 짤 때에도, 듀얼코어에서 짤 때에도, 항상 리소스는 부족했다. 게임보안 제품을 만들면서는 더 심해졌다. 게임이란 것이 원체 헤비 프로그램이기 때문에 동시에 돌아갈려면 CPU 점유율 0.01%에도 쩨쩨하게 굴어야 하고, 메모리를 아끼기 위해서 고속 서칭 알고리즘을 포기해야 하기도 한다. 그래도 이런 것들은 비교적 귀여운 축에 속하는 고민이었다는 것을 난 최근에야 깨달았다. 물리적인 한계가 있다는 사실을 속속 깨달았기 때문이다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;최근에 GIT 저장소를 UTF-8로 업그레이드 하는 작업을 단행했다. 이전 버전의 GIT의 경우에는 UTF-8을 지원하지 않아서 일부 한글 파일들이 제대로 저장소에 업로드가 되지 않는 문제가 있었다. UTF-8로 된 저장소로 변경하고 나서는 그런 일이 없었다. 업그레이드 작업은 무척이나 간단한 명령어 몇 개로 가능했지만 안타깝게도 이 작업은 애꿏은 나의 하루를 모두 소비해 버렸다. 문제는 이랬다. 우리는 4-5년 전에 구매한 델 서버를 소스 저장소로 사용하고 있었다. 뭐 델 서버라고 하는데 뭔가 엄청난 건 아니고 그냥 좀 더 견고하게 만들어진 그런 하드웨어일 뿐이다. 성능이 특별히 뛰어나거나 하지는 않다. 그간 이 서버는 단 한 차례도 문제를 일으킨 적이 없어서 잘 사용하고 있었다. 그런데 저장소를 업그레이드 하고 나서는 이상하게 저장소를 클론하는데 지나치게 오랜 시간이 걸렸다. 도대체 문제가 무엇인지 알 수 없었다. 당연히 내가 바꾼 거라곤 GIT 저장소 뿐이니 그 부분을 의심할 수 밖에는 없었다.&lt;/p&gt;
&lt;p&gt;하지만 문제는 서버에 있었다. 우리가 구매한 델 서버는 4년이란 시간을 감안하더라도 놀랍게도 고작, 고작 1기가 바이트의 메모리가 달려 있었다. 그런데 더 놀라운 사실이 있다. 난 뭐 1기가 바이트라고 한들 GIT 저장소를 운영하는데는 충분한 메모리라고 생각했던 것이다. 그런데 그건 터무니 없는 나의 생각이었다. GIT 클론 명령은 오브젝트를 압축하는 작업을 하는데 그 작업 과정에서 엄청나게 많은 메모리를 요구했다. 문제의 그 저장소를 클론하려면 1기가에 육박하는 메모리가 필요했다. 만약 재수없게 동시에 두 사람이 클론하는 경우에는 시스템은 메모리 부족으로 그 어떤 서비스도 동작하지 않는 엄청난 사태가 발생했다.&lt;/p&gt;
&lt;p&gt;그래 메모리 그 까이꺼 얼마한다고 늘리면 되는 것 아닌가, 라는 생각에 델 서버를 뜯었다. 하지만 현실은 그리 녹록치가 않았다. 뭔가 호환도 되지 않는 이상한 메모리가 하나 달려 있었기 때문이다. 다른 메모리를 끼우면 동작하지 않았다. 뜯어본 델 서버는 더 가관이었다. 보드부터 시작해서 당췌 확장 가능한거라곤 아무것도 없었다. 말 그대로 재앙이었다. 그냥 조립 피씨를 한 대 구매해서 옮겨야 겠다는 생각을 했다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;XIGNCODE3는 별도 옵션 없이 로그 서버를 무상으로 제공한다. 고로 고객님들께서는 적용하는 그 순간부터 발생하는 모든 로그와 통계 정보를 실시간으로 볼 수 있는 아름다운 신세계를 경험할 수 있다. 그런데 후발 주자로써 제품의 차별성을 두기 위해서 시작한 이 정책이 생각보다 골치아픈 존재가 되었다. 왜냐하면 고객에겐 공짜로 제공되지만 우리는 공짜로 사용할 수 있는 것이 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;우리가 사용하는 서버는 IDC에 10Mbps에 물려있는데, 사실 이제껏 한번도 트래픽에 대해서 생각을 해본 적이 없었다. 그것도 이유인 즉슨 몇십만되는 동접 게임도 큰 문제 없이 로그를 받았기 때문이다. 그래서 와 웹서버는 짱짱맨 이러면서 트래픽은 기억의 저편으로 날려 보냈다. 그런데 그게 아니었다. 지난 주에 대규모 게임을 런칭하면서 웹 서버가 다운되는 어처구니 없는 상황을 경험했기 때문이다. 10Mbps에서 우리 웹 서버는 이 지경이었다. 남부순환로로 출퇴근을 해 보았다면 이래서는 안 된다는 걸 일찍 알았어야 할 일이다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 621px; margin-bottom: 16px;&apos; data-url=&apos;./traffic2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/183f59c6a556ee74327f46133815ea11/41b39/traffic2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 36.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABMUlEQVR42mWO2W6DMBBF+f/fSaIAbmgJmw0ijSDeMIQtwWBeSL6ghvat1tHRHd3RyMY8z1JKpeZJqT/Pc98/7vXva5qmvdfNuBW60vxuvt9voyyryyUdn+307KZhZc1Dp+Rjlg8l+9VDv7ayk1U90ErJrq6KZVkMffuaxjg0SWSthNb/gLdMoZ2bh2y3J/4xh87yehlClGkC8bpnkwhsbCHcjACBGluP2LMz+3hzrdvpmCFH9q1BGYf+mUUWTwCLAUM2RbY2SwDXY2Ax36JnE+8PGuqaPLLxbp+7p2mS+ts1DKIIOLHjXr0ggzBLUI7g95eHPj59cIKOGwEXoSBOgiTVhHHsI88fh9YYpSzKElOOc0owpxomKC0oLigpqBC0FKQUtBCEC8y49o1xUd+nSf0AFIZbitfD0WMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;traffic2&apos; title=&apos;&apos; src=&apos;/static/183f59c6a556ee74327f46133815ea11/41b39/traffic2.png&apos; srcset=&apos;/static/183f59c6a556ee74327f46133815ea11/08678/traffic2.png 190w,
/static/183f59c6a556ee74327f46133815ea11/2edd7/traffic2.png 380w,
/static/183f59c6a556ee74327f46133815ea11/41b39/traffic2.png 621w&apos; sizes=&apos;(max-width: 621px) 100vw, 621px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;인간적으로 10Mbps 라인에 이게 무슨 짓이냐고 가비아에서 따질만도 하다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;일단 10Mbps라는 말은 10메가 비트를 일초에 전송한다는 말이다. 그러니 8로 나누면 초당 꼴랑 1.25메가 바이트를 전송할 수 있다는 결론에 도달한다. 60을 곱하면 분당 75메가 바이트를 전송할 수 있다. 우리 로그가 서버가 요구하던 용량은 게임에 따라 다르지만 헤비 게임을 기준으로 기존에 210메가 바이트 정도였던 거 같다. 그런데 75메가를 전송할 수 있는 라인에 그 정도는 버벅대면서 그럭저럭 돌아갔던 것이다. 이번에 추가된 게임은 트래픽 기준으로 분당 340MB메가 바이트를 필요로 했다. 그 지경이 되니 웹서버가 정지했다. 많은 고민을 했지만 피같은 돈을 들여 더 대역폭이 높은 라인을 사용하는 것 외에는 딱히 방법이 없었다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;퇴근하러 나갔다가 배란다에서 커피를 마시는데, 새로 들어온 분석팀 직원이 담배를 피우러 와서는 묻는다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;너님: 서버 메모리 좀 올려주시면 안되요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;나님: 왜요?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;너님: 계속 메모리 폴트 나요 ㅠㅜ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;나님: 2번 서버 아직도 그래요?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;너님: 아뇨. 거의 전부 다 그래요.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;나님: 헉. 그래도 메모리 추가는 안 되요. 서버 한 대당 메모리 1기가 추가하면 월에 만원 추가되거든요.&lt;/p&gt;
&lt;p&gt;나님: 스크립트 새로 고쳐 놓을께요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;-- 2012. 07. 03.&lt;/p&gt;
&lt;p&gt;지금도 가난하지만 정말 가난했던 시절 이야기다. 델 서버는 조립식 서버로 교체됐고, 올초에는 저장소를 github으로 변경했다. 가비아는 모두 클라우드 서비스로 옮겼고 더 이상의 회선 문제는 없다. 물론 트래픽 비용이 발생한다는 점은 추가됐다. 로그 서버 인스턴스도 겁 없이 하이엔드를 사용하기도 한다. 월 만원 때문에 파이썬 코드 최적화 시킨답시고 메모리 해제를 강제로 하는 방법을 찾지 않아도 되니 개발자 입장에서 많이 편해졌다. 물리적 한계에 봉착해 보면 돈이 있으면 많이 편하다. 그러니 일단 많이 벌고 볼 일인듯 ㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 불편한 경제학]]></title><description><![CDATA[통상적으로 또 역사적으로 모든 이들이 같은 거래에 동의할 때 투자자들은 우려할 필요가 있다. – 오펜하이머펀드 수석 전략가 p16…]]></description><link>https://jiniya.net/wp/archives/2963</link><guid isPermaLink="false">https://jiniya.net/wp/archives/2963</guid><pubDate>Thu, 18 Jun 2015 23:59:57 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;통상적으로 또 역사적으로 모든 이들이 같은 거래에 동의할 때 투자자들은 우려할 필요가 있다. – 오펜하이머펀드 수석 전략가 p167&lt;br&gt;
&lt;br&gt;
친구가 부자가 되는 모습을 옆에서 지켜보는 것만큼 사람들의 안락과 판단력을 혼란스럽게 만드는 것은 없습니다. 차라리 친구 말고 다른 사람이 부자가 되는 것이 속 편합니다. – p227&lt;br&gt;
&lt;br&gt;
과거를 공부하지 않는 사람들은 똑같은 오류를 되풀이하고, 과거를 공부하는 사람들은 오류에 빠지는 다른 길을 찾아낸다 – 찰스 울프 p291&lt;br&gt;
&lt;br&gt;
세계 경제 차원에서 보면 환율의 자동조절기능을 통해서 어느 한 나라가 지속적으로 너무 많은 무역흑자를 독식하는 일이 방지되는 것입니다. – p441&lt;br&gt;
&lt;br&gt;
국가의 진정한 부는 치러낸 고통의 크기에 비례한다. – p457&lt;br&gt;
&lt;br&gt;
공황에서 살아남기 위해서는 다른 자산이 아니라 유일한 부인 화폐를 보유해야 합니다. – p586&lt;br&gt;
&lt;br&gt;
“부채의 상환은 (실질) 부채잔액의 증가를 따라잡지 못하며, 부채를 갚을수록 더 많은 (실질) 부채가 쌓인다”고 했던 무서운 부채의 역설이 현실로 나타나고 있는 것입니다. – p582&lt;br&gt;
&lt;br&gt;
– 불편한 경제학, 세일러&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[cpp] PE 파일에서 매니페스트 추출하기]]></title><description><![CDATA[PE 파일의 매니페스트에는 많은 정보가 담겨 있다. 주요하게는 해당 실행 파일이 어떤 CRT…]]></description><link>https://jiniya.net/wp/archives/14975</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14975</guid><pubDate>Thu, 18 Jun 2015 23:59:56 GMT</pubDate><content:encoded>&lt;p&gt;PE 파일의 매니페스트에는 많은 정보가 담겨 있다. 주요하게는 해당 실행 파일이 어떤 CRT와 바인딩이 되는 것인지, 또 해당 실행 파일을 실행하기 위해서 필요한 권한은 무엇인지 등의 정보가 담겨 있다. 그 외에도 실행 파일을 실행하는데 각종 필요한 정보가 계속 추가되고 있다. 매니페스트 파일을 지원하지 않는 컴파일러를 사용하던 시절에는 아래와 같은 매니페스트 xml 파일을 직접 작성해서 실행 파일의 리소스로 포함시켜줘야 했지만 요즈음 Visual Studio는 매니페스트 파일 생성을 도와 주고 있기 때문에 프로젝트 설정에서 각종 세부 사항을 설정하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&apos;1.0&apos; encoding=&apos;UTF-8&apos; standalone=&apos;yes&apos;?&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;assembly&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;urn:schemas-microsoft-com:asm.v1&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;manifestVersion&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;1.0&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;trustInfo&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;urn:schemas-microsoft-com:asm.v3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;security&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;requestedPrivileges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;requestedExecutionLevel&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;asInvoker&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;uiAccess&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;requestedPrivileges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;security&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;trustInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;assembly&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;보안 프로그램을 만드는 경우에는 종종 이러한 매니페스트 파일의 내용의 추출이 필요할 때가 있다. PE 파일에서 직접 매니페스트 XML을 추출하기 위해서는 리소스 섹션을 참고하면 된다. 매니페스트 XML 파일의 PE 파일에 RT_MANIFEST 타입의 1번 리소스로 추가되기 때문이다. 로드된 모듈의 경우에는 FindResource 함수를 사용해서 손쉽게 해당 항목을 찾을 수 있지만 로드되지 않은 모듈의 경우에는 이 작업이 쉽지 않다. 이 경우에는 직접 PE 파일에서 리소스 섹션을 뒤져서 항목을 찾아야 한다. 아래 FindResourceDirectoryEntryWithId 함수는 rd 리소스 블록에 포함된 블록 중에 ID가 넘어온 id 파라미터와 일치하는 블록 정보를 찾아서 반환하는 역할을 한다. 해당 함수를 사용해서 루트 블록에서 RT_MANIFEST를 찾고, 그 다음 해당 블록의 1번 리소스를 찾으면 매니페스트 정보를 추출할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;PIMAGE_RESOURCE_DIRECTORY_ENTRY
&lt;span class=&quot;token function&quot;&gt;FindResourceDirectoryEntryWithId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PIMAGE_RESOURCE_DIRECTORY rd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; USHORT id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	PIMAGE_RESOURCE_DIRECTORY_ENTRY entry&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	entry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_RESOURCE_DIRECTORY_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;rd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG cnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;NumberOfNamedEntries &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; rd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;NumberOfIdEntries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NameIsString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; entry&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아래 GetManifestStringFromBuffer 함수는 PE 파일을 읽어들인 버퍼에서 매니페스트 문자열을 추출하는 방법을 보여주고 있다. 리소스 섹션을 찾은 다음 해당 섹션에서 RT_MANIFEST 블록을 찾고, 다시 1번 ID 블록을 찾은 다음 정보를 복사한다. 실행 파일에서 매니페스트 문자열을 추출하는 전체 프로젝트 소스 코드는 &lt;a href=&quot;/codewiz/assets/files/2015/dump_manifest.7z&quot;&gt;여기에서&lt;/a&gt; 다운로드 받을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL
&lt;span class=&quot;token function&quot;&gt;GetManifestStringFromBuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCVOID abuffer
								&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T buffer_size
								&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPSTR manifest
								&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T manifest_size
								&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PSIZE_T required_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG sec_cnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	PIMAGE_SECTION_HEADER sec &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	PIMAGE_DATA_DIRECTORY dd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	PUCHAR buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PUCHAR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; abuffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	PIMAGE_NT_HEADERS32 nt32 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetNTHeaders32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		sec_cnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nt32&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;FileHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NumberOfSections&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		sec &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetSectionHeaderFromNT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		dd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;nt32&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OptionalHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DataDirectory&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;IMAGE_DIRECTORY_ENTRY_RESOURCE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		PIMAGE_NT_HEADERS64 nt64 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetNTHeaders64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt64&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			sec_cnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nt64&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;FileHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NumberOfSections&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			sec &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetSectionHeaderFromNT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt64&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			dd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;nt64&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OptionalHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DataDirectory&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;IMAGE_DIRECTORY_ENTRY_RESOURCE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sec &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;dd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	PVOID rptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dd&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;VirtualAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; sec_cnt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		PVOID sptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sec&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VirtualAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		PVOID eptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sec&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Misc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VirtualSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rptr &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; sptr &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rptr &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; eptr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			PIMAGE_RESOURCE_DIRECTORY root&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			
			ULONG diff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rptr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			root &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_RESOURCE_DIRECTORY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sec&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PointerToRawData &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; diff&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// RT_MANIFEST 리소스 블록을 찾는다.&lt;/span&gt;

			PIMAGE_RESOURCE_DIRECTORY_ENTRY entry&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			ULONG_PTR man_id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; RT_MANIFEST&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			entry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindResourceDirectoryEntryWithId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; man_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// RT_MANIFEST 리소스 블록 아래 ID가 1인 리소스를 찾는다.&lt;/span&gt;

			PIMAGE_RESOURCE_DIRECTORY rd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_RESOURCE_DIRECTORY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; entry&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OffsetToDirectory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			entry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindResourceDirectoryEntryWithId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_RESOURCE_DIRECTORY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; entry&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OffsetToDirectory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			entry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_RESOURCE_DIRECTORY_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;rd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			PIMAGE_RESOURCE_DATA_ENTRY data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_RESOURCE_DATA_ENTRY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; entry&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OffsetToData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			PVOID pdata&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			pdata &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OffsetToData &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; sec&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VirtualAddress &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; diff&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;required_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;required_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;Size &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;manifest_size &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;Size &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token function&quot;&gt;SetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ERROR_INSUFFICIENT_BUFFER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

			&lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;manifest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pdata&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;Size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			manifest&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;Size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 돈, 뜨겁게 사랑하고 차갑게 다루어라]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/1189</link><guid isPermaLink="false">https://jiniya.net/wp/archives/1189</guid><pubDate>Thu, 18 Jun 2015 23:59:55 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;나는 이제 수단을 갖게 되었으므로 편안한 삶을 즐기고자 했다. 그러나 나는 내 기쁨을 마음껏 누릴 수가 없었다. 나의 철학적 현실주의와 뛰어난 증권 감각 덕택으로 나는 갑부가 되긴 하였으나 그 대신 다른 많은 것을 잃어버렸다. 내 소원은 성취되었지만 내 눈앞에 펼쳐진 세상은 너무도 슬펐다. 내가 좋아했던 친구들은 대부분 파멸했다. 그들은 공황을 거치면서 돈과 지위를 잃어버렸으며 앞으로 어떻게 살아가야 할지도 막막했다. 그와 반대로 나는 내가 꿈꿔 왔던 호화스러운 것을 모두 가질 수 있었다. 멋진 호텔, 레스토랑, 자동차, 이 모든 것을 누릴 수 있을 정도로 내 지갑은 항상 두둑했다. 그러나 그것을 같이 즐길 사람이 없었다. 화기애애한 분위기는 식었고, 즐거운 웃음이 사라진 그 자리에는 고통과 음침한 분위기만이 자리했다. 나는 정말 외톨이가 되었다. 어디든 살 수 있는 것 천지였지만 난 살 마음이 생기지 않았다. 친구들이 단 한 잔의 커피로 만족해야만 할 때 나는 샴페인과 귀한 상어 알을 먹을 수 있다는 사실이 내게 행복을 주지 않음을 그제야 알았다. 내 상황은 그 전보다 훨씬 나빠졌다. p227&lt;br&gt;
&lt;br&gt;
…&lt;br&gt;
&lt;br&gt;
이 전략은 오늘날에도 젊은 머니매니저들에게 매우 인기 있는 방법으로, 그들은 이것을 일컬어 포트폴리오 보험이라고 칭한다. 참 말도 안 되는 소리다. 왜냐하면 이 보험은 마치 화재로부터 집을 보호하기 위해 집을 판다는 식이기 때문이다. 나는 경험많은 사람들조차 어떻게 그럴 수 있는지 이해할 수 없다. p179&lt;br&gt;
&lt;br&gt;
…&lt;br&gt;
&lt;br&gt;
아주 열정적인 투자자였으나 런던 공황 때 재산을 몽땅 잃어버린 아이작 뉴턴 경은 이러한 분위기에 대해 다음과 같이 말한 바 있다.&lt;br&gt;
&lt;br&gt;
“천체 운동은 센티미터와 초 단위로 측량할 수 있으나, 정신 나간 군중이 시세를 어떻게 끌고 갈지는 정말 알 수 없다.” p172&lt;br&gt;
&lt;br&gt;
…&lt;br&gt;
&lt;br&gt;
주가지수 선물거래를 위한 증거금 비율이 아주 낮았기 때문에 1987년 이 시장은 고삐 풀린 망아지처럼 뛰어다녔다. 시카고에서 하루에 거래된 S&amp;#x26;P 500 지수 선물 계약이 뉴욕 증시에서 거래된 주식의 가치보다 많은 적도 있었다. 선물시장이 주도권을 쥐게 됨에 따라, 개가 꼬리를 흔드는 것이 아니라 꼬리가 개를 흔드는 상황이 연출된 것이다. p176&lt;br&gt;
&lt;br&gt;
…&lt;br&gt;
&lt;br&gt;
주식 투자자들은 성공하면 자기가 잘났기 때문이라고 하고, 실패하면 남의 탓으로 돌리기를 좋아한다. 가해자가 누구인지 바로 결정되었다. 프로그램 매매를 주도하던 컴퓨터에게 모든 죄가 돌아갔다. 불쌍한 컴퓨터가 가해자가 되어 버렸다. 만약 사람들이 신선하지 못한 생선을 포크와 나이프로 먹어 복통이 일어나면 그것을 포크와 나이프 탓으로 돌릴 것인가? 잘못된 것은 신선하지 못한 생선이듯, 이 문제는 사실 증권시장의 골든보이들이었다. p180&lt;br&gt;
&lt;br&gt;
– 돈, 뜨겁게 사랑하고 차갑게 다루어라, 앙드레 코스톨라니&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[cpp] 작업 영역 정확하게 구하는 방법]]></title><description><![CDATA[일반적으로 작업 영역을 구할때는 아래와 같은 코드를 많이 사용합니다. SystemParametersInfo의 SPI_GETWORKAREA…]]></description><link>https://jiniya.net/wp/archives/3470</link><guid isPermaLink="false">https://jiniya.net/wp/archives/3470</guid><pubDate>Thu, 18 Jun 2015 23:59:54 GMT</pubDate><content:encoded>&lt;p&gt;일반적으로 작업 영역을 구할때는 아래와 같은 코드를 많이 사용합니다. SystemParametersInfo의 SPI_GETWORKAREA를 사용하여 작업 표시줄을 제외한 작업영역을 구하는 방법입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;RECT rc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;SystemParametersInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SPI_GETWORKAREA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;rc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 방법에는 한가지 단점이 있습니다. 작업표시줄의 자동 숨김 옵션을 활성화하면 전체 화면을 작업 영역으로 구하는 것이죠. 자동 숨김으로 하더라도 작업 표시줄이 완전히 사라지는 것이 아니라 미세하게 두께를 차지하기 때문에 약간의 높이가 있습니다. 때로는 이 미세한 영역도 정교하게 처리해 주고 싶을 때가 있습니다. 그럴 땐 SPI_GETWORKAREA를 사용할 수 없습니다.&lt;/p&gt;
&lt;p&gt;GetWorkArea는 자동 숨김 옵션을 활성화한 경우에도 항상 정확하게 작업 표시줄 영역을 구해주는 함수입니다. lprc로 RECT 구조체의 포인터를 넘겨주면 절대적인 작업 영역을 구해서 넘겨줍니다. 별로 중요하다거나 어려운 부분은 없습니다. 단지 한가지 알아두면 유용한 것은, 작업 표시줄이 어떤 위치에 바인딩 되어 있는지를 구하기 위해서는 SHAppBarMessage API를 사용한다는 점 입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GetWorkArea 함수 코드&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/getworkarea.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetWorkArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPRECT lprc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    SIZE    szScreen&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    HWND    hShell &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindWindowW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;Shell_TrayWnd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    
    szScreen&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetSystemMetrics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SM_CXSCREEN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    szScreen&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetSystemMetrics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SM_CYSCREEN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token function&quot;&gt;SetRect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lprc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; szScreen&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; szScreen&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;hShell&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    RECT        rcTaskbar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    SIZE        szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      
    APPBARDATA  AppBarData&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    POINT       pt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    POINT       ptMouse&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        
    &lt;span class=&quot;token function&quot;&gt;GetWindowRect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hShell&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;rcTaskbar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rcTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;right &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; rcTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;left&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rcTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bottom &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; rcTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;top&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        
    AppBarData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cbSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; AppBarData&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token function&quot;&gt;SHAppBarMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ABM_GETTASKBARPOS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;AppBarData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AppBarData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uEdge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; ABE_TOP&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; 
        lprc&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;top &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cy&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
            
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; ABE_BOTTOM&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; 
        lprc&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;bottom &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cy&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
            
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; ABE_LEFT&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; 
        lprc&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;left &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;          
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
            
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; ABE_RIGHT&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; 
        lprc&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;right &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; szTaskbar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아래와 같은 테스트 코드로 두 가지 방법을 비교해 보면 작업 표시줄의 항상 숨김 옵션을 끈 경우에는 결과 값이 동일하지만 해당 옵션을 활성화한 경우에는 GetWorkArea가 구한 영역이 조금 더 작다는 것을 보실 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	RECT rc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
	&lt;span class=&quot;token function&quot;&gt;SystemParametersInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SPI_GETWORKAREA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;rc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d %d %d %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;top&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;right&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bottom&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;GetWorkArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;rc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d %d %d %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;top&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;right&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bottom&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[cpp] 동적 연결 라이브러리 동작 원리]]></title><description><![CDATA[항공기 사고의 74%는 이륙후 3분간, 착륙전 8분간 동안 발생한다고 한다. 이를 두고 ‘마의 11분’이란 표현을 쓰기도 한다. 이는 크리티컬한 작업에 있어서 시작과 끝이 얼마나 중요하고 위험한지를 나타내는 부분이라고 볼 수 있다. 윈도우 DLL…]]></description><link>https://jiniya.net/wp/archives/10447</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10447</guid><pubDate>Thu, 18 Jun 2015 23:59:53 GMT</pubDate><content:encoded>&lt;p&gt;항공기 사고의 74%는 이륙후 3분간, 착륙전 8분간 동안 발생한다고 한다. 이를 두고 ‘마의 11분’이란 표현을 쓰기도 한다. 이는 크리티컬한 작업에 있어서 시작과 끝이 얼마나 중요하고 위험한지를 나타내는 부분이라고 볼 수 있다. 윈도우 DLL을 사용할 때에도 대부분의 오류가 항공기 사고와 유사하게 DLL을 메모리에 적재하는 시점이나 해제하는 시점에 발생한다. 이는 윈도우가 DLL 목록을 관리하는 방식의 특수성에 기인한다. 이번 시간에는 이런 특수성에 대해서 살펴보고 이륙이나 착륙 과정에서의 사고를 피하기 위해서는 어떤 부분에 신경 써야 하는지 알아본다.&lt;/p&gt;
&lt;p&gt;로더 락(Loader Lock)
윈도우는 로드된 DLL을 PEB(Process Environment Block)의 Ldr 필드를 통해서 관리한다. Ldr 필드는 &amp;#x3C;리스트 1&gt;에 나와 있는 _PEB_LDR_DATA32 구조체를 가리킨다. _PEB_LDR_DATA32 구조체에는 현재 로더의 동작 상태를 나타내는 플래그와 로드된 DLL의 목록을 저장하고 있는 3개의 리스트(InLoadOrderModuleList, InMemoryOrderModuleList, InInitializationOrderModuleList)로 구성되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 _PEB_LDR_DATA32 구조체&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_PEB_LDR_DATA32&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG Length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    BOOLEAN Initialized&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID32 SsHandle&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LIST_ENTRY32 InLoadOrderModuleList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LIST_ENTRY32 InMemoryOrderModuleList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LIST_ENTRY32 InInitializationOrderModuleList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID32 EntryInProgress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    BOOLEAN ShutdownInProgress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID32 ShutdownThreadId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; PEB_LDR_DATA32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PPEB_LDR_DATA32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;LoadLibrary와 같은 DLL을 로드하는 함수나 로더 내부적으로 DLL을 로딩하는 경우에 로더는 해당 DLL을 로딩하고 _PEB_LDR_DATA32의 리스트에 해당 DLL의 정보를 추가한다. 마찬가지로 DLL이 메모리에서 언로드되는 경우에는 리스트에서 요청한 DLL을 제거한다. GetModuleHandle과 같이 특정 DLL을 찾는 경우에는 모듈 리스트를 순회하면서 들어온 정보와 매치되는 DLL이 있는지를 찾는다.&lt;/p&gt;
&lt;p&gt;이와 같이 DLL의 관리에는 _PEB_LDR_DATA32라는 프로세스 내부의 유일한 구조체가 사용되며, 해당 구조체의 정보는 다양한 윈도우 API에 의해서 수시로 변경된다. 이 말은 해당 구조체에 대한 접근은 직렬화될 필요가 있다는 것을 의미한다. 구조체에 대한 접근이 동기화 되지 않는다면 다중 스레드에서 구조체의 내용을 변경할 경우에 구조체 내용물이 오염되는 현상이 발생할 수 있기 때문이다. 윈도우에서는 _PEB_LDR_DATA32 구조체에 대한 접근을 직렬화 시키기 위해서 로더 락이라는 것을 사용한다. 로더 락은 PEB 내부에 존재하며 크리티컬 섹션으로 구현되어 있다. 따라서 _PEB_LDR_DATA32를 사용하는 모든 API들은 로더 락을 획득한 다음 작업을 한다고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 2&gt;와 &amp;#x3C;리스트 3&gt;에는 이러한 로더 락의 특징을 보여주는 예제를 담고 있다. 두 개의 스레드를 생성해서 각각의 스레드가 a.dll과 b.dll을 로드한다. 각각의 DLL은 &amp;#x3C;리스트 3&gt;에 나와 있는 것과 같이 DLL이 초기화 되는 부분에서 자신의 이름을 출력한다. 만약 DLL이 로드되는 것이 직렬화 되지 않는다면 메시지 박스 두 개가 동시에 화면에 출력될 것이다. 하지만 DLL이 로드되는 작업은 직렬화가 이루어지기 때문에 절대로 두 개의 메시지 박스가 동시에 화면에 나타나는 법은 없다. 항상 하나의 메시지 박스를 닫아서 작업을 완료해야 다음 DLL의 메시지 박스가 출력된다. LoadLibrary 부분을 MessageBoxW 함수로 바꿔가면서 예제를 실행해보면 그 차이를 보다 쉽게 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 실행 파일 소스&lt;/strong&gt;
&lt;a href=&quot;http://www.jiniya.net/codewiz/assets/files/2015/loaderlock1.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;

ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;ThreadProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    LPCWSTR name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCWSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; param&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;user32.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    HANDLE threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ThreadProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;a.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ThreadProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;b.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;WaitForMultipleObjects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; threads&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 DLL 소스&lt;/strong&gt;
&lt;a href=&quot;http://www.jiniya.net/codewiz/assets/files/2015/loaderlock2.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;

BOOL APIENTRY &lt;span class=&quot;token function&quot;&gt;DllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; HMODULE m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; DLL_PROCESS_ATTACH&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;MessageBoxW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;a.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;a.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MB_OK&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;DllMain에서 주의할 점
앞서 프로세스 내부의 DLL 정보를 관리하기 위해서 _PEB_LDR_DATA32라는 구조체를 사용한다는 것과 해당 구조체에 대한 접근을 로더 락을 통해서 직렬화 시킨다는 것을 배웠다. 이 단순한 사실이 DllMain을 작성하는 데에는 상당한 제약 사항을 불러온다. DllMain은 로더 락을 획득한 상태에서 호출되기 때문에 사소한 함수 호출도 데드락이나 크래시로 이어질 수 있다. &amp;#x3C;표 1&gt;에는 이러한 관점에서 DllMain에서 피해야 할 작업들의 목록이 나와 있다. 해당 작업들은 특수한 가정이 적용되는 상황이 아니라면 가급적 사용하지 않는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DllMain에서 피해야 할 작업들&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LoadLibrary, LoadLibraryEx 호출&lt;br&gt;
해당 함수들은 의존성 루프를 생성할 수 있고 의존성 루프는 데드락이나 크래시를 유발할 수 있다.&lt;/li&gt;
&lt;li&gt;다른 스레드와 동기화&lt;br&gt;
데드락을 유발한다.&lt;/li&gt;
&lt;li&gt;로더 락을 획득하려는 코드가 가지고 있는 동기화 오브젝트를 획득하려는 시도&lt;br&gt;
데드락을 유발한다.&lt;/li&gt;
&lt;li&gt;CoInitializeEx를 사용한 COM 스레드 초기화&lt;br&gt;
특정 조건이 충족될 경우 CoInitializeEx는 LoadLibraryEx를 호출한다.&lt;/li&gt;
&lt;li&gt;레지스트리 관련 함수들&lt;br&gt;
이 함수들은 advapi32.dll에 구현되어 있다. advapi32.dll이 초기화 되지 않았다면 크래시가 발생할 수 있다.&lt;/li&gt;
&lt;li&gt;CreateProcess 호출&lt;br&gt;
프로세스 생성은 다른 DLL을 로드할 수 있다.&lt;/li&gt;
&lt;li&gt;ExitThread 호출&lt;br&gt;
DLL_PROCESS_DETACH 과정 중에 스레드를 종료하면 로더 락을 다시 획득하도록 만들 수 있다.&lt;/li&gt;
&lt;li&gt;네임드 파이프나 네임드 오브젝트 생성&lt;br&gt;
윈도우 2000에서 네임드 오브젝트 생성은 터미널 서비스 DLL에서 구현되어 있다. 해당 DLL이 초기화 되어 있지 않다면 크래시가 발생할 수 있다.&lt;/li&gt;
&lt;li&gt;CRT에 포함된 메모리 관리 함수 사용&lt;br&gt;
DLL 버전의 CRT를 사용한다면 해당 DLL이 초기화되어 있지 않을 수 있다.&lt;/li&gt;
&lt;li&gt;user32.dll이나 gdi32.dll에 포함된 함수 사용&lt;br&gt;
일부 함수들은 다른 DLL을 로드할 수 있고, 이 때문에 크래시가 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그럼 좀 더 세부적으로 왜 이런 금기 사항들이 생겼는지에 대해서 알아보도록 하자. 첫 번째 금기 사항은 LoadLibrary의 호출이다. LoadLibrary의 호출은 새로운 DLL을 로딩하는 일이기 때문에 당연히 로더 락을 획득하는 시도가 발생할 수 있다는 것을 알 수 있다. 하지만 앞서 로더 락은 크리티컬 섹션으로 구현되어 있다고 했다. 윈도우에서 크리티컬 섹션은 재귀적으로 획득하는 것이 가능하도록 설정돼 있기 때문에 현재 스레드가 로더 락을 획득한 상태에서 LoadLibrary를 호출하는 것은 일견 문제가 없어 보이기도 한다. 실제로 DllMain에서 LoadLibrary를 사용해보면 큰 문제 없이 정상 동작하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;이렇게 잘 동작하는 LoadLibrary를 왜 굳이 호출하지 않도록 권고하는 것일까? 이유는 해당 호출을 인정할 경우에 특수한 상황에서 발생하는 문제들을 잠재적으로 같이 허용하는 셈이 되기 때문이다. 대표적인 예가 의존성 루프를 생성하는 것을 들 수 있다. 예를 들면 이런 상황이다. P라는 프로그램이 A.DLL을 로드한다. A.DLL은 DllMain에서 B.DLL을 로드한다. B.DLL은 DllMain에서 A.DLL을 로드한 다음 A.DLL의 Func라는 함수를 사용한다. 이때 이 Func라는 함수는 A.DLL이 초기화가 다 완료되지 않은 상태에서 호출되기 때문에 문제가 발생할 수 있다. &amp;#x3C;리스트 4&gt;에는 이 경우에 대한 소스 코드가 나와 있다. 해당 예제를 수행해 보면 &amp;#x3C;화면 1&gt;에 나타난 것과 같이 Func 실행 부분에서 msg 값이 초기화가 완료되지 않아서 NULL 값이 출력되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;이 예제의 경우에는 의존성 루프가 2단계이고 모든 DLL을 우리가 만들었기 때문에 원인을 쉽게 찾을 수 있다. 하지만 이런 의존성이 여러 곳에서 긴 단계에 걸쳐서 발생하는 경우에는 찾기도 힘들뿐더러 예측하지 못했던 동작들이 발생할 수 있다. 따라서 가급적 DllMain에서는 LoadLibrary 호출을 피하는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 의존성 루프로 인한 오류 발생 예제&lt;/strong&gt;
&lt;a href=&quot;http://www.jiniya.net/codewiz/assets/files/2015/loaderlock3.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// P 소스 코드&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;a.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// A.DLL 소스 코드&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;

LPCWSTR msg&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL APIENTRY &lt;span class=&quot;token function&quot;&gt;DllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; DLL_PROCESS_ATTACH&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a.dll DLL_PROCESS_ATTACH\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			HMODULE m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;b.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;Init Complete&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a.dll DLL_PROCESS_ATTACH 완료\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__declspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dllexport&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MSG =&gt; %ws\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;// B.DLL 소스 코드&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;FuncT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL APIENTRY &lt;span class=&quot;token function&quot;&gt;DllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; DLL_PROCESS_ATTACH&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;b.dll DLL_PROCESS_ATTACH\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			HMODULE m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;a.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			FuncT func &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FuncT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Func&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		
			&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;b.dll DLL_PROCESS_ATTACH 완료\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;화면 1 P 실행 화면&lt;/strong&gt;
두 번째 시나리오인 다른 스레드와 동기화를 생각해보자. DllMain에서 T라는 스레드를 종료 시키기 위해서 T의 종료 이벤트를 시그널 하고 WaitForSingleObject로 T를 대기한다고 가정해보자. 이 경우에 T는 종료 이벤트가 시그널 되었기 때문에 스레드 종료를 위해서 ExitThread가 호출될 것이다. ExitThread가 호출되면 DLL_THREAD_DETACH 이벤트를 호출하기 위해서 일부 DLL에 대해서는 DllMain이 호출되어야 한다. 이는 바로 로더 락 획득을 의미한다. 그런데 a.dll의 DllMain에서 로더 락을 획득한 상태에서 T가 종료되길 대기하고 있기 때문에 T의 ExitThread는 로더 락을 획득할 수가 없다. 따라서 데드락에 빠지게 된다. &amp;#x3C;리스트 5&gt;에는 이러한 시나리오를 통해서 데드락에 빠지는 예제가 나와 있다. 해당 DLL을 로딩하는 프로그램은 자동으로 데드락에 빠진다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 스레드 동기화로 인한 데드락 발생 예제&lt;/strong&gt;
&lt;a href=&quot;http://www.jiniya.net/codewiz/assets/files/2015/deadlock.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;
HANDLE exit_event&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;ThreadProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exit_event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

BOOL APIENTRY &lt;span class=&quot;token function&quot;&gt;DllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; HMODULE m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD reaspm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; DLL_PROCESS_ATTACH&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            exit_event &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            HANDLE thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ThreadProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;SetEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exit_event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;간단하게 두 가지 경우에 발생하는 문제만 살펴보았지만 다른 경우의 문제점들도 동일하게 모두 로더 락을 획득한 상태라는 특수성 때문에 발생하는 문제들이다. 숙련된 윈도우 프로그래머의 경우에도 이러한 제약 사항들에 대해서 단지 정상 동작한다는 이유로 크게 신경을 쓰지 않기도 한다. 하지만 이는 바람직한 자세가 아니다. 언제든지 해당 코드들은 문제를 발생시킬 수 있기 때문이다. 특수한 가정이 덧붙여지는 상황이 아니라면 해당 코드들을 DllMain에서 사용하는 일은 반드시 피하도록 해야 한다.&lt;/p&gt;
&lt;p&gt;초기화 지연 전략
DllMain에서 피해야할 많은 작업들에 대해서 배웠다. 그렇다면 만약 DLL의 초기화에 반드시 피해야 할 작업이 있다면 어떻게 해야 할까? 그럴 때는 DllMain에서 초기화를 시키는 것이 아닌 초기화를 지연시키는 방법을 사용해야 한다. 일반적으로 가장 좋은 방법은 &amp;#x3C;리스트 6&gt;에 나와 있는 것과 같이 DLL 초기화, 클린업 함수를 익스포트 시키는 방법이다. DLL을 사용하는 프로그래머가 DLL 로딩 후에 해당 함수를 명시적으로 호출해서 초기화와 클린업을 수행하도록 만드는 것이다. 하지만 후킹 DLL과 같은 경우에는 이러한 방법을 사용하기가 까다로운 경우가 많다. 그런 경우에는 DllMain에서 초기화 코드를 담고 있는 스레드를 생성해서 나중에 초기화가 수행되도록 만드는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 초기화/종료 함수를 사용한 초기화 지연&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;__delcspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dllexport&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; HRESULT &lt;span class=&quot;token function&quot;&gt;InitDLL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 실제 DLL 초기화 작업&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;__declspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dllexport&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CleanupDLL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 실제 DLL 클린업 작업&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;DLL_PROCESS_DETACH에 관한 오해
DLL_PROCESS_DETACH는 DLL이 메모리에서 해제되는 시점, 그러니까 FreeLibrary가 호출되서 해당 DLL의 레퍼런스 카운트가 0이 되는 시점과 프로세스가 종료되는 시점에 호출된다. 이러한 특성 때문에 상당히 많은 윈도우 프로그래머가 DLL_PROCESS_DETACH에 대해서 도시전설 같은 믿음을 가지고 있다. 하나는 TerminateProcess로 종료되는 경우에는 DLL_PROCESS_DETACH 이벤트가 발생한다는 것이고, 다른 하나는 DLL_PROCESS_DETACH가 프로세스 종료 처리에 적합한 위치라고 생각한다는 점이다. 하지만 이는 둘 다 심각하게 잘못된 믿음이다.&lt;/p&gt;
&lt;p&gt;프로세스 종료를 만들어내는 두 가지 API, ExitProcess와 TerminateProcess의 구현을 살펴보면 &amp;#x3C;리스트 7&gt;에 나타난 것과 같다. 코드에 나타난 것처럼 두 함수 모두 궁극적으로는 NtTerminateProcess를 호출해서 작업을 완료한다. 둘의 차이라면 ‘shutdown process’의 진행 여부에 있다. 이 ‘shutdown process’의 진행 과정의 일환으로 호출되는 것이 DLL_PROCESS_DETACH다. 따라서 TerminateProcess로 종료될 때에는 당연히 DLL_PROCESS_DETACH 이벤트가 발생하지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 ExitProcess와 TerminateProcess의 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ExitProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token function&quot;&gt;NtTerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    &lt;span class=&quot;token comment&quot;&gt;// shutdown process  &lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;NtTerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
&lt;span class=&quot;token function&quot;&gt;TerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token function&quot;&gt;NtTerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Process&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리가 ExitProcess의 구현에서 눈치채야 할 다른 중요한 시사점은 바로 NtTerminateProcess를 호출한 다음 ‘shutdown process’를 진행한다는 점입니다. 여기에는 굉장히 중요한 점이 내포되어 있다. 바로 우리 DLL이 FreeLibrary가 아닌 프로세스 종료 때문에 DLL_PROCESS_DETACH가 호출된다면, 그 시점에는 그 어떠한 스레드도 살아 있지 않다는 점이다. NtTerminateProcess(NULL, ExitCode)를 거치는 순간 해당 프로세스의 모든 스레드는 강제로 터미네이트(Terminate)되기 때문이다.&lt;/p&gt;
&lt;p&gt;결론을 다시 정리해보면 이렇다. DLL_PROCESS_DETACH는 TerminateProcess로 종료되는 경우에는 이벤트가 발생하지 않으며, 모든 스레드가 강제로 종료된 다음에 호출될 수 있기 때문에 종료 작업을 하는 위치로는 적절하지 않다는 점이다.&lt;/p&gt;
&lt;p&gt;DllMain에서의 예외
DLL_PROCESS_ATTACH 이벤트에서 DllMain이 FALSE를 리턴한다면 윈도우는 DLL_PROCESS_DETACH 이벤트를 사용해서 DllMain을 다시 호출한 다음 해당 DLL을 메모리에서 제거한다. 반면에 DLL_PROCESS_ATTACH 수행 과정 중에 DllMain에서 예외가 발생한다면 운영체제는 DLL_PROCESS_DETACH 이벤트 통보 없이 해당 DLL을 즉시 메모리에서 제거한다.&lt;/p&gt;
&lt;p&gt;윈도우는 DllMain의 실패 처리와 관련해서 기본적으로 위와 같은 입장을 가지고 있다. 이 부분이 표면적으로는 FALSE를 리턴하면 DLL_PROCESS_DETACH가 호출되고, 예외가 발생하면 메모리에서 바로 제거된다는 내용을 담고 있는 것처럼 보여지지만 사실상 이 내용은 DllMain에서 절대로 예외를 발생시켜서는 안 된다는 이야기를 담고 있다. 그 이유는 CRT 때문이다.&lt;/p&gt;
&lt;p&gt;CRT는 멀티스레드 환경을 지원하기 위해서 FLS(Fiber Local Storage)라는 것을 사용한다. CRT 초기화 루틴에서 FlsAlloc(_freefls)를 호출해서 FLS 공간을 할당한다. 물론 이렇게 할당된 공간은 DLL_PROCESS_DETACH 이벤트에서 CRT가 직접 제거한다. 코드로 살펴보면 &amp;#x3C;리스트 8&gt;에 나타난 것과 같은 구조가 된다. 실제 DLL의 시작은 CrtDllMain이라는 CRT 코드에서 시작되고 해당 코드에서 각종 초기화를 한 다음 우리가 작성한 OurDllMain을 호출해 주는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 DllMain 호출 구조&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL CALLBACK &lt;span class=&quot;token function&quot;&gt;CrtDllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HINSTANCE instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; DLL_PROCESS_ATTACH&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
        flsindex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FlsAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_freefls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OurDllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; DLL_PROCESS_DETACH&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
        BOOL r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OurDllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
        &lt;span class=&quot;token function&quot;&gt;FlsFree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flsindex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
  
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그런데 이 구조에서 OurDllMain에서 예외가 발생한다면 CRT가 할당한 FLS 공간이 문제가 된다. 왜냐하면 우리가 만든 OurDllMain에서 예외가 발생하면 CRT에서는 FlsAlloc을 사용해서 FLS 공간을 할당했지만 DLL_PROCESS_DETACH가 호출되지 않아서 그 공간을 회수할 기회를 가지지 못하기 때문이다.&lt;/p&gt;
&lt;p&gt;“몇 바이트 메모리 누수가 일어나는 것이 큰 문제일까?”라고 생각할 수 있다. 하지만 이 문제는 단순히 FLS 공간에 대한 메모리 누수만 일어나는 것으로 마무리되는 문제가 아니다. 윈도우 운영체제는 FLS에 등록된 것들을 프로세스 종료 시점에 모두 다시 회수하려고 시도한다. 이는 FlsAlloc에 지정된 콜백 함수를 호출해서 이루어진다. &amp;#x3C;리스트 8&gt;의 코드에서는 _freefls 함수가 그것이다. 즉, 우리가 예외를 발생시켜 DLL이 메모리에서 즉시 제거되고 나면 엉뚱하게 프로세스 종료 시점에 운영체제가 사라진 메모리 번지를 가리키는 _freefls를 호출하려고 하다가 크래시가 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;DllMain에서는 절대로 예외를 발생시켜서는 안 된다. 왜냐하면 그 예외가 앞서 설명한 것과 같이 CRT의 코드에 영향을 미칠 수 있기 때문이다. &amp;#x3C;리스트 9&gt;에 나타난 것과 같이 DllMain에서 수행하는 작업 과정에서 발생할 수 있는 모든 예외를 봉쇄하고 예외가 발생한 경우에는 그냥 FALSE를 리턴하는 것이 현명하다. 그러면 적어도 다른 프로그램에 민폐는 안 끼칠 수 있다. 그렇지 않다면 민폐를 끼치고 엉뚱한 지점에서 크래시가 발생하는 문제가 생길 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 예외 처리기를 통해서 DllMain에서 발생하는 예외를 차단하는 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /Eha 옵션으로 컴파일해야 모든 예외를 잡을 수 있다.&lt;/span&gt;
BOOL APIENTRY &lt;span class=&quot;token function&quot;&gt;DllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; HMODULE m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD reaspm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// .. DllMain에서 처리해야 할 작업들&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;lpreserved의 용도
끝으로 DllMain의 마지막 파라미터인 lpreserved에 대해서 알아보자. DllMain의 세 번째 인자는 void 포인터 타입의 lpreserved다. 흔히 그냥 추후 사용을 위해서 예약돼 있다고 막연하게 생각할 수 있는데 이 값은 윈도우 내부적으로 사용되는 값이다. 그리고 그 의미는 다음과 같다.&lt;/p&gt;
&lt;p&gt;DLL_PROCESS_ATTACH 시점에는 지금 로드되는 DLL이 LoadLibrary와 같은 함수를 사용해서 동적으로 로딩된다면 NULL을, 그렇지 않고 임포트 테이블을 사용해서 정적으로 로딩된다면 NULL이 아닌 값을 가진다.&lt;/p&gt;
&lt;p&gt;DLL_PROCESS_DETACH 시점에는 FreeLibrary 호출로 인해서 메모리에서 제거되는 경우에는 NULL을, 그렇지 않고 프로세스 종료로 인해서 DLL이 제거되는 경우에는 NULL이 아닌 값을 가진다.&lt;/p&gt;
&lt;p&gt;이런 파라미터는 DLL의 로딩을 최적화하는 용도로 사용된다. &amp;#x3C;리스트 10&gt;의 코드는 CRT의 DLL_PROCESS_DETACH 코드의 일부를 발췌한 것이다. 이 코드를 살펴보면 lpreserved 값을 조사해서 NULL일 때만 클린업 코드를 호출하는 것을 볼 수 있다. 이유는 NULL이 아닌 경우에는 프로세스가 종료되는 시점이고 우리가 일일이 리소스를 파괴하지 않아도 운영체제가 알아서 모든 리소스를 제거할 것이기 때문이다. 해당 클린업 호출을 하지 않음으로써 보다 빠르게 DllMain이 완료될 수 있도록 만들어주는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 CRT의 DLL 클린업 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifndef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_DEBUG  &lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; lpreserved &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;/* _DEBUG */&lt;/span&gt;  &lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;/* 
         * The process is NOT terminating so we must clean up... 
         */&lt;/span&gt;  
        &lt;span class=&quot;token comment&quot;&gt;/* Shut down lowio */&lt;/span&gt;  
        &lt;span class=&quot;token function&quot;&gt;_ioterm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
        &lt;span class=&quot;token function&quot;&gt;_mtterm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
        &lt;span class=&quot;token comment&quot;&gt;/* This should be the last thing the C run-time does */&lt;/span&gt;  
        &lt;span class=&quot;token function&quot;&gt;_heap_term&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;/* heap is now invalid! */&lt;/span&gt;  
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifndef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_DEBUG  &lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;/* _DEBUG */&lt;/span&gt;  &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 위대한 기업에 투자하라]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/1191</link><guid isPermaLink="false">https://jiniya.net/wp/archives/1191</guid><pubDate>Thu, 18 Jun 2015 23:59:52 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;중세 시대는 서구 세계 대부분이 생존에 필요한 물자조차 부족했고, 인간의 삶이 무척 고달팠던 시절이었다. 그 무렵 고급 두뇌의 상당 부분이 쓸데없는 문제에 몰두했던 것도 중요한 이유였다. 당시 이 세상에 천사의 숫자가 얼마나 되는지 따위의 논쟁을 하느라 허비했던 노력의 절반만이라도 굶주림과 질병, 궁핍과 싸우는 데 돌려졌더라면 어떤 일이 벌어졌을지 한번 상상해보라. 오늘날 주식 투자와 관련된 일을 하고 있는 고급 인력들이 향후 경기 동향을 예측하기 위해 바치고 있는 노력의 단 얼마만이라도 보다 생산적인 목적에 사용한다면 정말로 놀라운 결과를 가져올 수 있을 것이다.&lt;br&gt;
&lt;br&gt;
위대한 기업에 투자하라, 필립 피셔&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;맞는 말이다. 생산자는 없고 죄다 빨대 꽂으려는 놈들만 있으니…&lt;/p&gt;
&lt;p&gt;맘같아선 진짜 광합성을 배우던지 해야지 ㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] 빌게이츠의 인생 충고 11가지]]></title><description><![CDATA[RULE 1 Life is not fair – get used to it. 인생이란 원래 공평하지 못하다. 그런 현실에 대하여 불평할 생각하지 말고 받아들여라. 
RULE 2 The world won’t care about your self…]]></description><link>https://jiniya.net/wp/archives/10284</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10284</guid><pubDate>Thu, 18 Jun 2015 23:59:51 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;RULE 1&lt;/strong&gt;&lt;br&gt;
Life is not fair – get used to it.&lt;br&gt;
인생이란 원래 공평하지 못하다. 그런 현실에 대하여 불평할 생각하지 말고 받아들여라.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 2&lt;/strong&gt;&lt;br&gt;
The world won’t care about your self-esteem. The world will expect you to accomplish something BEFORE you feel good about yourself.&lt;br&gt;
세상은 네 자신이 어떻게 생각하든 상관하지 않는다. 세상이 너희들한테 기대하는 것은 네가 스스로 만족하다고 느끼기 전에 무엇인가를 성취해서 보여줄 것을 기다리고 있다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RULE 3&lt;/strong&gt;&lt;br&gt;
You will NOT make 40 thousand dollars a year right out of high school. You won’t be a vice president with car phone, until you earn both.&lt;br&gt;
대학교육을 받지 않는 상태에서 연봉이 4만 달러가 될 것이라고는 상상도하지 말라.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 4&lt;/strong&gt;&lt;br&gt;
If you think your teacher is tough, wait till you get a boss. He doesn’t have tenure.&lt;br&gt;
학교선생님이 까다롭다고 생각되거든 사회 나와서 직장 상사의 진짜 까다로운 맛을 한번 느껴봐라.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 5&lt;/strong&gt;&lt;br&gt;
Flipping burgers is not beneath your dignity. Your grandparents had a different word for burger flipping they called it Opportunity.&lt;br&gt;
햄버거 가게에서 일하는 것을 수치스럽게 생각하지 마라. 너희 할아버지는 그 일을 기회라고 생각하였다.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 6&lt;/strong&gt;&lt;br&gt;
If you mess up,it’s not your parents’ fault, so don’t whine about your mistakes, learn from them.&lt;br&gt;
네 인생을 네가 망치고 있으면서 부모 탓을 하지 마라. 불평만 일삼을 것이 아니라 잘못한 것에서 교훈을 얻어라.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 7&lt;/strong&gt;&lt;br&gt;
Before you were born, your parents weren’t as boring as they are now. They got that way from paying your bills, cleaning your clothes and listening to you talk about how cool you are. So before you save the rain forest from the parasites of your parent’s generation, try delousing the closet in your own room.&lt;br&gt;
당신이 태어나기 전에는 부모님의 인생도 괜찮았다. 그들의 인생이 재미없게 된 건 당신의 재미있는 인생을 뒷바라지해야 했기 때문이다. 부모님 세대가 열대우림을 망친다고 분노하기 전에 자기 방의 옷장 안이나 제대로 정리할 일이다.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 8&lt;/strong&gt;&lt;br&gt;
Your school may have done away with winners and losers, but life has not. In some schools they have abolished failing grades and they’ll give you as many times as you want to get the right answer. This doesn’t bear the slightest resemblance to ANYTHING in real life.&lt;br&gt;
학교는 승자나 패자를 뚜렷이 가리지 않을 지 모른다. 어떤 학교에서는 낙제제도를 아예 없애고 쉽게 가르치고 있다는 것을 잘 안다. 그러나 사회 현실은 이와 다르다는 것을 명심하라.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 9&lt;/strong&gt;&lt;br&gt;
Life is not divided into semesters. You don’t get summers off and very few employers are interested in helping you find yourself. Do that on your own time.&lt;br&gt;
인생은 학기처럼 구분되어 있지도 않고 여름 방학이란 것은 아예 있지도 않다. 네가 스스로 알아서 하지 않으면 직장에서는 가르쳐주지 않는다.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 10&lt;/strong&gt;&lt;br&gt;
Television is NOT real life. In real life people actually have to leave the coffee shop and go to jobs.&lt;br&gt;
TV는 현실이 아니다. 현실에서는 커피를 마셨으면 일을 시작하는 것이 옳다.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;RULE 11&lt;/strong&gt;&lt;br&gt;
Be nice to nerds. Chances are you’ll end up working for one.&lt;br&gt;
공부 밖에 할줄 모르는 “바보” 한테 잘 보여라. 사회 나온 다음에는 아마 그 “바보” 밑에서 일하게 될지 모른다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;--&lt;/p&gt;
&lt;p&gt;빌게이츠가 하지 않았는데 한 걸로 유명해진 것 같은 충고…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[정보] 세이노칼럼: 장사꾼보다는 사업가가 되라]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/13043</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13043</guid><pubDate>Thu, 18 Jun 2015 23:59:50 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;새벽마다 아파트단지에서 세차를 대행해준다는 독자가 나에게 “어떻게 하면 수입을 더 늘릴 수 있느냐”는 질문을 한 적이 있다. 사람들은 세차 차량의 수를 늘리는데만 관심을 갖는다. 그러나 일의 대가를 육체가 움직이는 시간 만큼만 비례하도록 만들게 되면 평생 가난을 못 벗어난다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;내 답변은 “세차만 하면 안된다”는 것이다. 세차 차량의 숫자를 늘리는 것은 두번째 문제이다. 나라면 우선 “저에게 일을 주셔서 감사합니다. 정성껏 세차했지만 혹시라도 불만이 있으시면 전화해 주십시오”라고 적힌 명함을 돌린다. 새벽에 세차를 하고 낮에는 세차방법과 차량정비에 대해 공부할 것이다. 몇개월 후 “경비실에 키를 맡기시면 냉각수와 세척액 오일 체크는 무료로 해 드립니다”라는 선전지를 돌린다. 다시 몇개월 후 냉각수와 세척액 오일교환 서비스를 실시하고 좋은 제품을 싼 가격에 판다. 가짜나 유사품이 많은 세상이므로 반드시 어느 회사 제품을 사용했는지를 고객에게 눈으로 확인시킨다. 타이어의 공기압도 확인하여 준다. 고객별로 모든 내용을 기록하는 것은 물론이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;겨울철에는 “염화칼슘이 차를 부식시킨다고 합니다. 제가 알아보니 차량 세척 비용은 얼마라고 합니다만 세차장까지 일부러 시간을 내셔서 다녀오셔야 합니다. 선생님의 귀중한 시간을 아껴드리고자 출근하시기 전 혹은 퇴근하신 뒤에 제가 세차장에 차를 맡기고 찾아오는 서비스를 해 드립니다. 다만 세차비에 얼마를 더 주시면 됩니다”라는 내용의 선전지를 뿌린다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;물론 인근 세차장과 협의해 가격 할인을 받아 놓는다. 또 “밧데리가 방전되어 당황해 하시는 분들을 위하여 제가 밧데리 한 개를 준비했습니다. 동네 정비업체에 전화를 걸어 밧데리를 갖고 오라고 하실 때의 절반 가격에 빌려드립니다”라는 선전지도 배포한다. 무료로 1회 광택 서비스를 해주고 “계속 원하시면 얼마입니다”라고 알린다. 눈이 오면 출근전 앞창 유리를 닦아주기도 한다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;나의 목표는 고객들의 신뢰를 받고 고객이 조그마한 불편이라도 느끼는 것을 눈치 빠른 머슴처럼 대신하여 주되 대가는 받겠다는 것이다. 이점은 중요한 사실이므로 꼭 기억하라. 고객이 많아지면 사람을 고용하고 철저히 감독한다. 그리고 다른 아파트 단지를 찾아 나선다. 신청하는 사람이 많아 감당 못할 서비스 부분은 해당 가격을 인상시키고 주머니가 얇은 고객은 떨어내 고객의 수를 조정한다. 욕심이 앞서 감당 못할 수의 고객을 받아들이는 짓은 절대 하지 않는다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;여기서 독자들은 내가 1년 후를 생각하며 구조체를 만드는 과정에 주목해야 한다. 오늘 수입이 많았다고 좋아하는 사람은 장사꾼이고 오늘은 손해가 났어도 1년후를 생각하며 고객에게 한 약속과 신뢰를 지키는 사람은 사업가이다. 물론 나는 사업가이다. 장사꾼은 작은 돈은 벌 수 있어도 큰 돈은 못 번다. 무슨 일을 하든지 장사꾼이 되지 말고 사업가 정신을 가져야 한다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 세이노&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[일상] 일요일의 단상…]]></title><description><![CDATA[매번 그냥 늘어지게 쉬고 싶다는 말을 입버릇처럼 달고 다녔다. 그래서 오늘은 그냥 늘어지게 쉬었다. 얼마만인지 ㅋㅋ~ #…]]></description><link>https://jiniya.net/wp/archives/3518</link><guid isPermaLink="false">https://jiniya.net/wp/archives/3518</guid><pubDate>Thu, 18 Jun 2015 23:59:49 GMT</pubDate><content:encoded>&lt;p&gt;매번 그냥 늘어지게 쉬고 싶다는 말을 입버릇처럼 달고 다녔다. 그래서 오늘은 그냥 늘어지게 쉬었다. 얼마만인지 ㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;어제는 정말 기분이 꿀꿀한 날이었다. 하루 종일 기분이 좋다가 막판에 아주 꿀꿀해진 그런 날. 기분 좋지 않은 반전이 있었던 날. 어쨌던 정말 현진건의 “운수 좋은 날” 같은 그런 느낌의 하루였다. 지나고보니 그런 생각이 들었다. 결국은 내 탓이다. 기분이 좋은 것도 내 탓이고, 기분이 나쁜 것도 내 탓이고 말이다.&lt;/p&gt;
&lt;p&gt;주식을 하면서 배운 한 가지 사실은 높은 수익을 얻는 것보다는 손실을 보지 않는 것이 훨씬 크다는 점이다. 일종의 방어적 프로그래밍과 같은 그런 원리다. 실컷 신나게 수익을 올려도 한번 실수를 하면 물거품 되는 것은 시간 문제다. 그런데 그 물거품 된 것을 복구하기 위해서는 곱절의 노력이 필요한 셈이다. 어쨌든 어제 내가 느낀 점은 좋은 선택을 고심하기 보다는 나쁜 선택을 하지 않도록 주의해야 겠다는 거? ㅎㅎ~&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;꿀꿀한 기분에 푹 자고 났더니 오후다. 일어나기가 싫어서 침대맡에 머리를 파묻고는 한참을 더 잤다. 그래도 침대에서 기어나오기 싫어서 엊저녁에 보다만 책을 집어 들었다. 에쿠니 가오리의 “냉정과 열정 사이”. 한참된 책인데 내가 산 건 아니고, 아마 우리 누나가 산 책인듯 싶다. 집에 있길래 읽어 보려고 집어왔다. 에쿠니 가오리를 제법 좋아한다고 생각하면서도 이 책은 읽어보질 못했었다.&lt;/p&gt;
&lt;p&gt;소설은 제법 낭만적이었다. “사람이 있을 곳이란, 누군가의 가슴속밖에 없는 것이란다.”&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;나에게 자기애의 가장 극한 표현은 요리다. 뭔가 집밥을 해먹고 나면 나 자신에게 그래도 쪼금은 덜 미안해진다. 한동안 요리하는 거에 취미가 들려서 한창 해먹다가 요즘은 좀 뜸했다. 바쁘기도 했고. 어쨌든 오늘은 근사한 집밥을 해먹고 싶어서 간만에 밥을 했다. 된장을 끓이고 갈치를 굽고, … 결국 뭐 다 엄마표 협찬 제품이지만 다 늘어놓고 보니 간만에 제법 진수성찬이다. 실컷 먹고는 잽싸게 치웠다.&lt;/p&gt;
&lt;p&gt;입가심용 아이스크림이 다 떨어져 버린 것을 한탄하다가 오래된 꿈틀이와 짱셔요를 발견했다. 잽싸게 먹었다. 꿈틀이는 괜찮았는데 짱셔요는 하나도 안셨다. 오래되서 그런지 애가 상태가 좀 메롱이 된 듯한 느낌. ㅎㅎ~&lt;/p&gt;
&lt;p&gt;— 2010. 11. 14.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 가르쳐라. 그리하면 배울 것이다.]]></title><description><![CDATA[Q: 만약 회사에서 신입이 들어 왔는데, 저에게 그 신입의 기술을 올려 주라는…(한마디로 하루…]]></description><link>https://jiniya.net/wp/archives/4791</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4791</guid><pubDate>Thu, 18 Jun 2015 23:59:48 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt;&lt;br&gt;
만약 회사에서 신입이 들어 왔는데, 저에게 그 신입의 기술을 올려 주라는…(한마디로 하루 1 시간씩 과외 비스무리) 임무를 준다면…그걸 해야 할까요?…말아야 할까요?… 제가 꼭 그일을 해야 하는지요…회사에서 그 일을 할줄 아는 사람이 저 밖에 없는데… 회사 입장에서는 후일을 대비한 것 같고요…저는 제 나름대로 회사에서 제 장점이 있으니 유리한 입장인데…&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt;&lt;br&gt;
저도 처음 회사를 다닐 때 사수분이 그런 마인드를 가지고 계셔서 아주 고생했던 기억이 나는군요. 저한테 가르쳐주고 나면 자신은 뭐 먹고 사냐고 그런 말씀을 하셨더랬죠. 그래서 늘 컴파일러나 소스를 줄 때 계속 파일 하나를 빼고 주던지 하는 식으로 해서 아주 골탕을 먹었습니다. ㅎㅎㅎ^^ 물론 지금은 사이 좋게 지냅니다~&lt;br&gt;
&lt;br&gt;
사람의 머리에서 머리로 전달될 수 있는 기술 몇 가지를 가르쳐 줬다고 자신의 밥줄을 걱정해야 할 정도라면 많이 반성해야 한다고 봅니다. 저도 프로그래머로 몇 해 동안 일했지만, 제가 가진 경쟁력은 제가 알고 있는 win32 api개수도, 제가 만들어 논 라이브러리 코드도, 제가 알고 있는 윈도우 시스템 지식도 아니라고 봅니다. 제가 신입 사원에 비해 가지는 가장 큰 경쟁력은 경험이겠죠. 몇 해 동안 일한 경험.&lt;br&gt;
&lt;br&gt;
만약 회사에서 그러한 경험과 노하우를 전부 무시하고 기술이 전수되었다고 퇴사를 권고한다면 그런 회사는 오래 다닐 필요가 없다고 봅니다.&lt;br&gt;
&lt;br&gt;
물론 저도 오래 일한 것은 아니지만 일하면서 느낀 점은 기술이라는 것은 정말 별것 아니라는 점이었습니다. 기술보다는 사람을 얻는 것이 훨씬 더 값어치 있는 일이라 생각되네요. 지금 밑에 들어온 신입 사원에게 성심 성의껏 가르쳐 주세요. 혹시 나중에 그 분한테 도움을 청할 일이 생길지도 모르니까요~&lt;br&gt;
&lt;br&gt;
끝으로 덧붙여 기술이라는 것은 자신의 머릿속에 묶어둬 봤자 아무 쓸모 없습니다. 그것을 활용하고 알리고 할 때 효용이 생기는 것이죠~ 만약 모두가 자신의 머릿속에 가둬 놓았다면, 아마 지금도 동굴 속에서 추위에 떨면서 살고 있었겠죠~~~&lt;br&gt;
&lt;br&gt;
&lt;a href=&quot;http://groups.google.com/group/microsoft.public.kr.vc.qna/browse_thread/thread/e58e4cf0d44a9c96&quot;&gt;http://groups.google.com/group/microsoft.public.kr.vc.qna/browse_thread/thread/e58e4cf0d44a9c96&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;http://stephenslighthouse.com/wp-content/uploads/2010/02/learning_pyramid.jpg&quot; alt=&quot;&quot; title=&quot;learning_pyramid&quot;&gt;&lt;/p&gt;
&lt;center&gt;**가르치는 행위는 가장 좋은 학습 방법이다.**&lt;/center&gt;</content:encoded></item><item><title><![CDATA[[정보] 놀라운 비디오 세상]]></title><description><![CDATA[93년인가 94년엔가? 리눅스를 처음 접했을 때 가장 답답한 마음은 제대로 된 튜토리얼이 없다는 것이었습니다. 책대로 그대로 했는데도 되는 것은 정말 하나도 없었습니다. 처음 X-window…]]></description><link>https://jiniya.net/wp/archives/4242</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4242</guid><pubDate>Wed, 17 Jun 2015 23:59:47 GMT</pubDate><content:encoded>&lt;p&gt;93년인가 94년엔가? 리눅스를 처음 접했을 때 가장 답답한 마음은 제대로 된 튜토리얼이 없다는 것이었습니다. 책대로 그대로 했는데도 되는 것은 정말 하나도 없었습니다. 처음 X-window 화면을 봤을 때는 감동이었죠. 이후에도 저는 리눅스 환경에서 여러 가지 일을 다양한 문서를 따라하면서 해 봤지만 늘 뭔가 잘 안되었죠. 아마 제가 글을 제대로 이해하는 능력이 부족하거나 저의 시스템이 특이해서 그랬다고 생각하지만, 아마도 다른 사람이 제대로 하는 것을 한 번이라도 TV에서 봤다면 저의 시행착오는 극적으로 줄지 않았을까란 생각을 해봅니다. 물론 요즘이라고 이런 일들이 벌어지지 않는 것은 아닙니다. 아주 문서화가 잘되어 있고, 그대로 따라해도 안되는 경우는 많습니다. 이런 것들이 텍스트의 한계라고 봅니다. 아무리 친절한 캡쳐 화면도 전부를 다 보여줄수는 없죠. 그런 점에서 비디오는 정말 큰 장점을 가지고 있습니다. 또한 인프라의 발전으로 그런 것들이 점점 다가오고 있습니다. 더욱 놀라운 사실은 프로그래밍 분야에도 성큼 다가왔다는 겁니다. 물론 주옥같은 웹캐스트야 오래전부터 있었지만 이렇게 HOWTO 같은 시리즈의 비디오가 잘 정리된 페이지는 첨 본 거 같네요. 역시 MS ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn2.microsoft.com/en-us/visualc/bb496952.aspx&quot;&gt;http://msdn2.microsoft.com/en-us/visualc/bb496952.aspx&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] ARP 테이블 열거하기]]></title><description><![CDATA[프로그램 내에서 ARP 테이블을 뒤져야 할 때가 있다. ARP란 주소 해석 프로토콜로 IP의 실제 MAC 어드레스를 구하기 위해서 사용되는 프로토콜이다. 반대로 RARP라는 것도 있다. ARP…]]></description><link>https://jiniya.net/wp/archives/10188</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10188</guid><pubDate>Wed, 17 Jun 2015 23:59:46 GMT</pubDate><content:encoded>&lt;p&gt;프로그램 내에서 ARP 테이블을 뒤져야 할 때가 있다. ARP란 주소 해석 프로토콜로 IP의 실제 MAC 어드레스를 구하기 위해서 사용되는 프로토콜이다. 반대로 RARP라는 것도 있다. ARP는 네트워크의 아주 하부에 존재하는 레이어로 굉장히 중요한 역할을 한다. 실제로 네트워크 레이어를 구축할때에도 아마도 제일 먼저 만들어야 하는 부분이다.&lt;/p&gt;
&lt;p&gt;매번 ARP를 요청하는 것은 시스템으로 봐서는 굉장히 멍청한 짓이다. 왜냐하면 IP에 해당하는 MAC 어드레스가 매번 바뀌지는 않기 때문이다. 그래서 시스템은 ARP 요청 정보를 일정 시간동안 캐시에 저장해 놓고 캐시에 저장된 요청이 오면 캐시에 있는 정보를 그대로 보내준다. ARP 캐시를 부려면 커맨드 창에서 arp -a를 입력하면 된다. 이 목록을 구하는 함수를 만들어 보도록 하자~&lt;/p&gt;
&lt;p&gt;아래는 ARP 테이블을 열거하는 함수를 보여준다. 첫번째 인자로 열거 콜백 함수를 두번째 인자로 콜백함수에 포함될 사용자 정의 파라미터를 넣어주면 된다. 그러면 함수는 ARP 테이블의 한 행마다 fCallback함수를 호출해 준다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ARP 테이블 열거 함수&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/enumarptbl.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BOOL&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CALLBACK &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;CBENUMARPTBL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MIB_IPNETROW &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

NPDUTILAPI
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;EnumArpTbl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CBENUMARPTBL fCallBack&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID pUserData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    DWORD       cbBuffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;        &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pBuffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    DWORD       result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    MIB_IPNETTABLE  &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    DWORD       i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    MIB_IPNETROW    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetIpNetTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MIB_IPNETTABLE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; pBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cbBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; ERROR_INSUFFICIENT_BUFFER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pBuffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        pBuffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cbBuffer&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        result  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetIpNetTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MIB_IPNETTABLE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;pBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cbBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; NO_ERROR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       
    
    pTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MIB_IPNETTABLE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;pBuffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; pTable&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;dwNumEntries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pTable&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fCallBack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pUserData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pBuffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;CBENUMARPTBL 함수의 첫번째 인자로 넘어오는 MIB_IPNETROW는 다음과 같이 정의된 구조체다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_MIB_IPNETROW&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 어댑터의 인덱스 번호 &lt;/span&gt;
  DWORD dwIndex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

  &lt;span class=&quot;token comment&quot;&gt;// 물리 주소의 길이. 통상적으로 6이 된다. 왜냐하면 mac 주소는 6바이트이기 때문이다. &lt;/span&gt;
  DWORD dwPhysAddrLen&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 물리 주소. 보통은 mac 주소가 된다. &lt;/span&gt;
  BYTE bPhysAddr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAXLEN_PHYSADDR&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ip 주소 &lt;/span&gt;
  DWORD dwAddr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 다음과 같은 값을 가질 수 있다. (4 Static,3 Dynamic,2 Invalid,1 Other) &lt;/span&gt;
  DWORD dwType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; MIB_IPNETROW&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PMIB_IPNETROW&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우8 관리자 권한으로 프로그램 실행 시키기]]></title><description><![CDATA[윈도우8에 많은 것들이 변경됐습니다. 그 중에 하나가 UAC 정책입니다. 예전에 UAC를 끄면 UAC가 없는 것과 동일했는데 윈도우…]]></description><link>https://jiniya.net/wp/archives/9876</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9876</guid><pubDate>Wed, 17 Jun 2015 23:59:45 GMT</pubDate><content:encoded>&lt;p&gt;윈도우8에 많은 것들이 변경됐습니다. 그 중에 하나가 UAC 정책입니다. 예전에 UAC를 끄면 UAC가 없는 것과 동일했는데 윈도우8 그게 변경됐습니다. 아예 없는 것이 아니라 관리자 권한 요구가 매니페스트에 포함된 프로그램에게는 사라지는 것과 동일한데 그렇지 않은 프로그램의 경우 UAC를 꺼도 그 프로그램은 일반 권한으로 실행됩니다. 프로그래밍이나 테스트 작업을 하는 사람에게는 조금 불편합니다. 완전히 꺼버리는 방법도 있는데 보안상 그닥 권해 드리고 싶지 않습니다. 관리자 권한으로 자주 사용하는 프로그램의 등록 정보에서 아래 항목을 체크하면 그 프로그램만 관리자 권한으로 실행할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 377px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우8_관리자_권한으로_프로그램_실행_시키기.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ef4845278a64bf11b8b75dadc53bf763/fdd90/%EC%9C%88%EB%8F%84%EC%9A%B08_%EA%B4%80%EB%A6%AC%EC%9E%90_%EA%B6%8C%ED%95%9C%EC%9C%BC%EB%A1%9C_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8_%EC%8B%A4%ED%96%89_%EC%8B%9C%ED%82%A4%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 136.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAEFElEQVR42o1UW2/jVBDu30ThrWKF+ANI/A3YCxLSsg88ELrs9gbdLmm3zeZiO4nj3OM4TZz4fju+Hju2EzNxYNtCkBiNP00m/s4Zf2fmHHz5svPk1eiwGH/xMz78CRVejAsv2MKz8Wff9QvP2c+/5wALT0eFZ8PCsxG8cFiMvvpROnny9fNvfjj4tmSct7RfSOM1Zb6mjKOaXKwIRzWpWFkWq2KxKhzVlV/r0htSeUtpxy10TDvHLfuqpT59Jx+cNdX5qM20mroqa9JyMhrIkiDwsw7dmE+5fofud9ph4CWrYIX9JPLj0A88J1vZF2394LxtRYEtiLJumJpmWBYClyRF1w1BEFXNgKQsyUtBUjVtsRSXgmjZXpalJ5R6cNG1PUvv9cfdXp9ud7jJlOl0CYIcjthWi2kz3cFgiBAyTctzXYRs0zQDHGZZdtoAcgf5QVBvj+ke2+wMKyRD0AOS7hGtbr3V6455D6+yx7bebPG0uSVbPg5bQ54ZzhpdttYa0IM7gpkQzJjqcsOZ6kYbvFpHyXo/GUfxnZnI7oZH6RxteCsdyPFIiSdaMlZWrIw7i2CuR3vIvzFWliXcdNrr9Vl2suDnkqxu31hv1rnl8SNLUkhucnIbyKkkydyEm895jpuMR6yiqIsF3+8PuOlssVjcTe+i6B87rz+REzgbCR5ZFkURtLVtG+DvYItgaZruJacIOYZhmKah63oQBPhf5nkekDe5pVv2PXkN5MDH8AesucPd520e2L5v3goWc9wU1PL9IMotDMOdVJt99mDnXG0LIcPQNehGAzrU0jUdlkiSZFfFviZ5INhyKfL8nOd5QRBsx/F833EckOp/kS0EFDAXHqhiG7mu57mQXa1W/02GsteRIikwPpZhWqZpQ92GAcNlW6amKA6ysR/EcM6gQu7rbasm92oHq8QJAtvHluch3zdztKF4jF2MVWQDPt55p3YHZURVfXtqvy+hi0v8oZwRVFojwNd1MnciqVTjciW6KW/99mPw/iqj6qdt4+C8oWWV2zHNtAly0KTnY9YQJVOSALXlUl0sdUFcB3iN8QaHWw+jBC6Dj7fbeT6nVFjGdTwT+tF2VF0XZQVGX9MNWVUlRZFVDcp86EmcZPXKaUOBsu2sVlHfHNsXl0Hpyv/jaod5cB1e3yTlyurD7b3flPFlKSOrZ20zVzsJCaZZJ+sUSZFko1arNZs03aJJgoSj/zQPe+b5jDazGHs+dGSEcQj3U444ilbbAH6HUZwkcZxAAA55SGRpdALf/K5jZhHyXRS4CHso9G0X6aYms8OeKgnIUHVZGHTbwx5jabILTQzZxXyDzd/h6n1VMXs8ojjUnP7lJGtUB8o1zVf6cn2kQVxqzkqNWW2oUhMTsNyTenPrZVn7E6xrrSB2CigpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;   8                      md 0&apos; title=&apos;&apos; src=&apos;/static/ef4845278a64bf11b8b75dadc53bf763/fdd90/%EC%9C%88%EB%8F%84%EC%9A%B08_%EA%B4%80%EB%A6%AC%EC%9E%90_%EA%B6%8C%ED%95%9C%EC%9C%BC%EB%A1%9C_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8_%EC%8B%A4%ED%96%89_%EC%8B%9C%ED%82%A4%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/ef4845278a64bf11b8b75dadc53bf763/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EA%B4%80%EB%A6%AC%EC%9E%90_%EA%B6%8C%ED%95%9C%EC%9C%BC%EB%A1%9C_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8_%EC%8B%A4%ED%96%89_%EC%8B%9C%ED%82%A4%EA%B8%B0.md_0.png 190w,
/static/ef4845278a64bf11b8b75dadc53bf763/fdd90/%EC%9C%88%EB%8F%84%EC%9A%B08_%EA%B4%80%EB%A6%AC%EC%9E%90_%EA%B6%8C%ED%95%9C%EC%9C%BC%EB%A1%9C_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8_%EC%8B%A4%ED%96%89_%EC%8B%9C%ED%82%A4%EA%B8%B0.md_0.png 377w&apos; sizes=&apos;(max-width: 377px) 100vw, 377px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;종종 반대로 실행된 프로그램 입장에서 현재 실행된 프로세스가 관리자 권한으로 실행됐는지 아니면 일반 권한으로 실행됐는지를 체크할 필요가 있는 경우가 있는데요. 이때는 아래 코드에 나와 있는 것과 같이 프로세스 토큰을 사용해서 관리자 권한인지를 조회해 보면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;관리자 권한 체크 코드&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/is_admin.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;shared_ptr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; vsptr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL
&lt;span class=&quot;token function&quot;&gt;IsProcessUserAdmin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE process&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BOOL &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;is_admin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	HANDLE token&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenProcessToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TOKEN_QUERY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	vsptr &lt;span class=&quot;token function&quot;&gt;token_closer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CloseHandle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG gsize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetTokenInformation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TokenGroups&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gsize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gsize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; ERROR_INSUFFICIENT_BUFFER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UCHAR&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; gbuffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	gbuffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gsize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	PTOKEN_GROUPS ginfo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PTOKEN_GROUPS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gbuffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetTokenInformation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TokenGroups&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ginfo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gsize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gsize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	PSID admin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	SID_IDENTIFIER_AUTHORITY auth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SECURITY_NT_AUTHORITY&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AllocateAndInitializeSid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;auth
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SECURITY_BUILTIN_DOMAIN_RID
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DOMAIN_ALIAS_RID_ADMINS
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	vsptr &lt;span class=&quot;token function&quot;&gt;sid_closer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;FreeSid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ginfo&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;GroupCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;EqualSid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ginfo&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;Groups&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Sid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;is_admin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;is_admin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	BOOL is_admin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsProcessUserAdmin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;is_admin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; is_admin &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;admin&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;not admin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[소고] 강력한 언어란? …]]></title><description><![CDATA[Rica…]]></description><link>https://jiniya.net/wp/archives/977</link><guid isPermaLink="false">https://jiniya.net/wp/archives/977</guid><pubDate>Wed, 17 Jun 2015 23:59:44 GMT</pubDate><content:encoded>&lt;p&gt;Rica님 블로그를 구경하다가 알게 된 페이지입니다. 학생들이 쓴 에세이를 모아둔 페이지인데 재미있는 글들이 많이 있네요. 처음에 읽은 글이 제법 재밌어서 금방 다 읽겠지, 라는 생각으로 덤볐는데 한번에 다 읽기가 생각보다 좀 빡쎄군요. ㅋㅋ~ 다음에도 읽을 요량으로 링크를 저장해 놓습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ropas.snu.ac.kr/~ta/4190.310/essays/&quot;&gt;http://ropas.snu.ac.kr/~ta/4190.310/essays/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2009년 2번째 에세이 부분을 전부 읽었는데요. &amp;#x3C;해커와 화가&gt;의 저자 폴 그레이엄 아저씨가 쓴 글들을 바탕으로 에세이를 적어오는 것이 과제였다고 추측됩니다. 주로 좋은 프로그래밍 언어란 무엇인가에 대한 것들을 논하고 있죠. 폴 그레이엄 아저씨의 글들을 읽어 보신 분들은 아시겠지만 그레이엄 아저씨는 Lisp 애호가 입니다. 그가 창업한 Viaweb도 Lisp를 사용해서 성공할 수 있었다고 &amp;#x3C;해커와 화가&gt;에 나와 있죠.&lt;/p&gt;
&lt;p&gt;제가 2009년 2번째 에세이를 전부 읽고 느낀 점은 딱 두가지 였습니다. 1) 국내 최고 학부답게 학생들이 글을 잘 쓴다, 2) 원문에 대한 딴지를 거는 글은 거의 없다는 겁니다. 결론은 대부분 함수형 언어의 칭찬으로 끝이 납니다. 근데 읽고나니 뭔가 좀 쎄한 느낌이 드네요.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 인과관계]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/1055</link><guid isPermaLink="false">https://jiniya.net/wp/archives/1055</guid><pubDate>Wed, 17 Jun 2015 23:59:43 GMT</pubDate><content:encoded>&lt;p&gt;언젠가 워크샵 술자리에서 이사님께서 해주신 우스개 소리 중에 이런 이야기가 있었습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;한 과학자가 파리를 가지고 실험을 하고 있었습니다. 한 날은 파리의 청력을 실험하기 위해서 파리를 앉혀 두고는 옆에서 손뼉을 쳤다고 합니다. 그러자 파리가 그 소리에 놀래서 달아났습니다. 과학자는 이어서 파리의 날개를 떼고는 다시 파리 옆에서 손뼉을 쳐서 소리를 냈습니다. 그러자 이 번에는 파리가 날아서 도망을 가지 못하고 그 자리에 그대로 있었습니다. 이를 본 과학자는 그 날 노트에 이렇게 적었다고 합니다. “파리의 귀는 날개에 달려 있다.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 이야기를 들은 사람들은 멍청한 과학자를 생각하지만 실상은 우리는 멍청하지 않다고 생각하지만 저런 실수를 곧잘합니다. 많은 사람들이 우울증에 걸린 사람들이 알콜 중독에 걸리기도 쉽다고 생각합니다. 하지만 연구 결과에 의하면 사람들이 우울증에 걸려서 알콜 중독에 걸리기 보다는 알콜 중독에 걸려서 우울증에 걸린다고 합니다. 또 우리는 기분이 좋아서 웃는다고 생각하지만, 반대로 웃으면 기분이 좋아지기도 한답니다.&lt;/p&gt;
&lt;p&gt;애매한 문제도 많이 있습니다. 생각의 속도가 빨라서 책을 빨리 읽는 건지, 아니면 책을 빨리 읽다 보면 생각의 속도가 빨라지는건지. 인식이 개선되면(중요한 일을 하고 있다고 판단되면) 처우가 개선되는 것인지(연봉이 올라가는 것인지) 아니면 처우가 개선되면 인식이 개선되는 것인지 같은 것들 말이죠. 찾아보면 더 있을 수도 있겠죠. 여튼 인과관계를 정확하게 판단하는 일은 생각처럼 쉬운 일은 아닌 것 같습니다. 많은 경우에 우리는 농담에 등장한 과학자처럼 행동하고 있는지도 모르겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[2011년 5월 7일…]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/wp/archives/4150</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4150</guid><pubDate>Wed, 17 Jun 2015 23:59:42 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;집에서 사용하는 마우스가 또 고장이 났다. 증상은 똑같다. 왼쪽 마우스 버튼. 그냥 클릭을 해도 더블 클릭으로 인식되는 경우가 종종 발생한다. 별로 불편할 것 같지 않은 이 고장은 사람을 좀 미치게 만든다. 결국 늘 그랬던 것처럼 지금은 오른쪽, 왼쪽 버튼을 바꿔서 쓰고 있다. 매번 이런 고장이 발생하는 걸 보니 내가 마우스 쓰는 패턴이 이상하다는 생각도 좀 든다. 예전에는 집에 굴러 다니는 것들이 MS 마우스였는데, 지금은 어디 하나 마땅하게 대체해서 사용할 마우스도 없다. A/S를 보내야 하나 심하게 고민하고 있다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;집에 사용하던 모니터가 고장나서 얼마전에 27인치 모니터를 새로 질렀다. 신세경이다. 24인치와 27인치의 차이란 ㅋㅋ~ 한 3년 사용한 것 같은데 무상 A/S가 안될것 같아서 그냥 바꿨다. 원래 사용하던 것도 만족스럽게 사용했는데 이번 것이 더 좋은 것 같다. 단지 강화 유리 처리가 돼서 집에서 사용하면 좀 반들거린다는 단점이 있지만.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;4월 이었나 회사 사람이 mp3 파일을 줬다. 그런데 그 중에 몇개가 소리통에서 플레이 되지 않는 문제가 있었다. 특히 이소라의 바람이 분다가 플레이가 제대로 되지 않는게 안타까웠다. 알송은 참 잘도 플레이를 하는데 말이다. 그래서 몇 일 전부터 이 문제를 고쳐야 겠다고 생각하고는 작년에 덮어둔 소스 코드를 꺼내서 보게 되었다. 그리고 고쳐서 릴리즈를 하였다.&lt;/p&gt;
&lt;p&gt;언젠가 회사 직원이 그런거 뭐하러 만드냐고 물어본 적이 있었다. 그 친구는 여행 다니고, 술 마시는 걸 좋아하는데 여행은 왜 가고, 술은 왜 마시냐는 질문을 해주고 싶었다. 세상 일이 모두 어떤 목적이 있어서 하는건 아닌데 말이다. 재미삼아 만들어 보는 거지 ㅋㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;난 제법 책 읽는 것도 좋아하고 글을 쓰는 것도 좋아하는데 요즘은 도통 글 쓰는 일을 하고 싶지가 않다. 왜 그런지를 곰곰히 생각해 봤는데 작년 말부터 올초까지 너무 재미없는 글쓰기를 회사에서 너무 많이 해버린 탓인것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우 종료시키기]]></title><description><![CDATA[프로그램을 작성하다 보면 종종 윈도우 시스템을 종료 시켜야 하는 상황이 발생합니다. Windows 9x의 경우에는 단순히 ExitWindowsEx API를 호출함으로써 윈도우를 종료 할 수 있으나, NT 계열에서는 그게 되지 않습니다. 그 이유는 NT…]]></description><link>https://jiniya.net/wp/archives/4072</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4072</guid><pubDate>Wed, 17 Jun 2015 23:59:41 GMT</pubDate><content:encoded>&lt;p&gt;프로그램을 작성하다 보면 종종 윈도우 시스템을 종료 시켜야 하는 상황이 발생합니다. Windows 9x의 경우에는 단순히 ExitWindowsEx API를 호출함으로써 윈도우를 종료 할 수 있으나, NT 계열에서는 그게 되지 않습니다. 그 이유는 NT 계열에서 도입된 권한 체계 때문입니다. 시스템을 종료시키는 API를 사용하려면 Shutdown 권한을 가지고 있어야 합니다. 아래 코드는 NT 계열에서 Shutdown 권한 획득후 윈도우를 종료 시키는 방법을 보여주고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ExitWindowsExHelper 함수&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/exitwindowsexhelper.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ExitWindowsExHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    HANDLE hToken&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    TOKEN_PRIVILEGES tkp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    &lt;span class=&quot;token comment&quot;&gt;// Get a token for this process. &lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenProcessToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;TOKEN_ADJUST_PRIVILEGES &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; TOKEN_QUERY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hToken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 


    &lt;span class=&quot;token comment&quot;&gt;// Get the LUID for the shutdown privilege. &lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LookupPrivilegeValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SE_SHUTDOWN_NAME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;tkp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Privileges&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Luid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    tkp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PrivilegeCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// one privilege to set &lt;/span&gt;
    tkp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Privileges&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Attributes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SE_PRIVILEGE_ENABLED&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    &lt;span class=&quot;token comment&quot;&gt;// Get the shutdown privilege for this process. &lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;AdjustTokenPrivileges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;tkp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PTOKEN_PRIVILEGES&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    &lt;span class=&quot;token comment&quot;&gt;// Cannot test the return value of AdjustTokenPrivileges. &lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; ERROR_SUCCESS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    &lt;span class=&quot;token function&quot;&gt;ExitWindowsEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EWX_POWEROFF&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[올빼미형 인간]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4540</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4540</guid><pubDate>Wed, 17 Jun 2015 23:59:40 GMT</pubDate><content:encoded>&lt;p&gt;고백하건데 나는 올빼미형 인간이다. 난 이제껏 내가 그냥 태어날 때 부터 올빼미형 인간이었다고 생각했다. 그런데 내가 올빼미형 인간이 된 것은 다름 아닌 진화에 의한 것이 아닐까란 생각이 들었다. 내가 올빼미가 된 사연은 다름아닌 컴퓨터 때문이다. 난 14살 때 처음으로 내 컴퓨터를 가지게 됐다. 그때 내가 컴퓨터를 할 수 있는 시간은 학교를 마치고 집으로 돌아온 다음 밖에 없었다. 그렇게 학창 시절을 보내고는 대학을 들어갔다. 이제는 더 올빼미가 될 수 밖에 없다. 일단 낮 시간은 여자 친구도 만나야 하고 엄마가 청소도 하고 시끄럽다. 집중이 되지 않으니 일을 할 수가 없다. 자연스럽게 내가 컴퓨터를 할 수 있는 시간은 고스란히 새벽 시간 밖에는 없다. 여친느님도 엄마도 잠드는 바로 그 시간, 황금 시간. ㅋㅋ~ 자연스럽게 나는 새벽에 일을 할 수 밖에 없었다. 이렇게 10년이 넘는 시간을 일을 했다. 이제는 어쩔 수 없이 올빼미가 될 수 밖에 없는 것이다.&lt;/p&gt;
&lt;p&gt;회사를 와도 사정은 다르지 않다. 회사의 낮 시간은 사실 진득하게 코딩을 할 수 있는 시간이 아니다. 특히 보안 업체의 하루는 전쟁터와 같다. 여기저기 해킹툴이 나오고 업데이트 요청이 있고, 사용자 로그가 접수되고, 업데이트가 있고, … 한마디로 헬이다. 무한 인터럽트는 자연스런 현상이다. 그나마 우리 회사는 연구실이 분리되어 있어서 소란스럽지는 않은데 그래도 안에 사람이 많이 있다보니 자연스럽게 집중하기는 힘들다.&lt;/p&gt;
&lt;p&gt;각종 소음들. 한번은 기계식 키보드를 개발자가 샀길래 집에 가서 쓰라고 돌려보낸 적이 있다. 또각 또각 하는 소리에 당췌 코딩을 할 수 없었기 때문이다. 물론 나도 내가 쓸 때에는 기계식 키보드를 사용하는 걸 좋아한다. 그 손맛과 함께 그 소리마저 뭔가 경쾌하게 들리는 법이다. 요즘은 핸드폰을 두고 가는 개발자들이 있어서 전쟁 중이다. 자리에 두고 갔을 때 전화가 오면 다른 사람들이 피곤하니 좀 들고 다니라고 해도 당췌 들고 다니질 않는다. 물론 다 그런건 아니고 말 안듣는 한 명이 있다. 물론 난 상황이 좀 나은 편인데 회사를 시작했기 때문에 이러한 결정을 내가 컨트롤할 수 있기 때문이다. 즉, 내가 대장이다. 그렇게 모든 변수들을 통제해도 사실 낮 시간은 코딩을 진득하게 하거나 디버깅을 하기에는 소란스럽다. 시끄럽고, 인터럽트가 많이 걸리기 때문이다. 자연스럽게 회사에서도 나는 새벽에 일을 할 수 밖에 없다. 0시에서 7시. 내가 가장 많은 코드를 작성한 시간이고, 가장 많은 버그를 잡은 시간이다.&lt;/p&gt;
&lt;p&gt;한번은 이런 일이 있었다. 레거시 코드가 도저히 관리가 되지 않아서 전체를 새롭게 작성한 일이 있었다. 세명이 한 일주일 작업했는데 도저히 진도가 나가지 않았다. 코드가 크지는 않았다. 다해서 3만 라인이 조금 안되는 컴포넌트였다. 그렇게 진도가 나가지 않았다. 그렇게 지지부진 하다 일주일이 지나고 안되겠다 싶어서 작성하던 코드를 다 버리고 밤에 혼자서 작업을 새로 했다. 그러자 이틀만에 동작하는 결과물을 얻을 수 있었다. 물론 밤시간 이틀을 말한다. 그때 느꼈다. 아. 내가 이래서 올빼미가 됐구나.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 황당 옵션 이야기…]]></title><description><![CDATA[XIGNCODE3에는 현재 대략 16…]]></description><link>https://jiniya.net/wp/archives/11194</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11194</guid><pubDate>Wed, 17 Jun 2015 23:59:39 GMT</pubDate><content:encoded>&lt;p&gt;XIGNCODE3에는 현재 대략 160개의 옵션이 있다.&lt;/p&gt;
&lt;p&gt;초기에 황당했던 경우가 있었는데 한 업체에서 스플래시를 꺼달라는 요청에 스플래시는 끄는 옵션을 만들었는데 스플래시를 보여주는 옵션이 있었던 것이다. 이 옵션이 황당한 이유는 끄는 옵션을 오프로 켜는 옵션도 오프로 하는 경우에는 옵션이 충돌하는 일이 발생하기 때문이다. 물론 이 또한 릴리즈를 담당하는 직원의 질문으로 알게 되었다. 그 이후로 옵션은 긍정 성향의 옵션만 만들겠다고 다짐했는데 여전히 우후죽순이다.&lt;/p&gt;
&lt;p&gt;어제 내일부터 CBT를 시작하는 업체에서 새로운 기능이 필요하다면 이런 저런 옵션을 만들어 달라는 이야기를 했다. 그래서 해당 옵션을 만들어 주고는 코드 정리를 하는데 예전에 그것과 똑같은 옵션을 이미 만들어 놓은 것이 보이는 게 아닌가? 사실 이제 나도 어떤 옵션이 정확하게 어떤 범위에 영향을 미치는지 예측하기가 힘들때도 있다. 핡~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] GetProcAddress를 편리하게 사용하는 방법]]></title><description><![CDATA[윈도우의 경우 9x와 NT 계열의 함수 세트가 틀린 경우가 있다. 9x에만 존재하는 함수가 있는가 하면, NT에만 존재하는 함수도 있다. 이러한 경우 한 프로그램이 두가지 환경에서 모두 동작해야 하는 경우에 주로 LoadLibrary…]]></description><link>https://jiniya.net/wp/archives/11204</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11204</guid><pubDate>Wed, 17 Jun 2015 23:59:38 GMT</pubDate><content:encoded>&lt;p&gt;윈도우의 경우 9x와 NT 계열의 함수 세트가 틀린 경우가 있다. 9x에만 존재하는 함수가 있는가 하면, NT에만 존재하는 함수도 있다. 이러한 경우 한 프로그램이 두가지 환경에서 모두 동작해야 하는 경우에 주로 LoadLibrary를 사용해서 해당 함수들을 동적으로 불서서 사용한다. 물론 그 외에도 동적으로 불러쓰는 경우는 매우 많다.&lt;/p&gt;
&lt;p&gt;이렇게 LoadLibrary를 통해서 함수를 불러 쓸 때 가장 불편한 점은 함수 포인터를 반환받는 과정이다. 함수 하나하나 마다 모두 GetProcAddress로 함수 포인터를 받아야 하기 때문이다. 이러한 과정을 좀 더 간소화 시킬 수 없을까? 여기에 대한 답이 &lt;a href=&quot;http://www.codeproject.com%EC%97%90&quot;&gt;www.codeproject.com에&lt;/a&gt; 나와있다. 바로 가변 인자를 사용한 방법이다. 아래 함수는 실제 원문에 있던 함수를 약간 수정한 버전이다. 출구를 하나로 통일하고, 함수 로드에 실패한 경우에는 항상 DLL을 언로드 하도록 변경했다. 실제 원문은 &lt;a href=&quot;http://www.codeproject.com/dll/dllease.asp&quot;&gt;http://www.codeproject.com/dll/dllease.asp&lt;/a&gt; 에서 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GetProcAddresses&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/getprocaddresses.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL &lt;span class=&quot;token function&quot;&gt;GetProcAddresses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; HINSTANCE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;hLibrary&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR lpszLibrary&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INT nCount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    BOOL bRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    va_list va&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;va_start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; va&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nCount &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;hLibrary &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadLibrary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; lpszLibrary &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        FARPROC &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; lpfProcFunction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        LPSTR lpszFuncName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        INT nIdxCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; nIdxCount &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; nCount &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            lpfProcFunction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;va_arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; va&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FARPROC&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            lpszFuncName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;va_arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; va&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPSTR &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;lpfProcFunction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 
                &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;hLibrary&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                lpszFuncName &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                lpfProcFunction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                bRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            nIdxCount&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        bRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;va_end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; va &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bRet &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;hLibrary &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;FreeLibrary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;hLibrary&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; bRet&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사용하는 방법은 무척이나 간단하다. 첫번째 인자로 리턴받을 DLL인스턴스 핸들을, 두번째 인자로 DLL 파일명을, 세번째 인자로 로드할 함수 갯수를, 그 다음부터는 함수 포인터의 포인터와, 함수명을 교대로 적어주면 된다. 말로하니 매우 복잡한데, 실제 사용예를 보면 금방 알 수 있다. 아래는 kernel32.dll에서 CreateFileW와 CloseHandle 함수를 로드하는 방법을 보여준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HINSTANCE hinst&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;GetProcAddresses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hinst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;kernel32.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fnCreateFileW&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CreateFileW&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fnCloseHandle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CloseHandle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[기억1]]></title><description><![CDATA[이제는 흐릿해진 기억인데 아마도 초등학교 3-…]]></description><link>https://jiniya.net/wp/archives/8711</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8711</guid><pubDate>Wed, 17 Jun 2015 23:59:37 GMT</pubDate><content:encoded>&lt;p&gt;이제는 흐릿해진 기억인데 아마도 초등학교 3-4학년 정도 였던 것 같다. 그 해 여름 난 우리 동네에 있는 갈비집 형들과 놀았던 기억이 있다. 신기한 사실은 난 그 형들을 그 전에도 알았고, 그 후에도 알았지만 그 해 여름 말고는 친하게 놀았던 기억이 거의 없다. 근데 무슨 이유였는지 그 해 여름에는 퍽이나 붙어 다니면서 자주 놀았다.&lt;/p&gt;
&lt;p&gt;갈비집 아저씨는 자식이 세 명 있었다. 아들, 아들, 딸이었는지 아들, 딸, 아들이었는지 잘 기억이 나질 않는데 아무튼 아들이 둘이었고 딸이 하나였다. 셋 다 나보다는 나이가 많았다. 그 당시 우리 동네에는 두만이라는 전설적인 깡패가 있었다. 내가 한글을 배우던 무렵부터 동네 녀석들한테 듣게 된 전설인데 사실 초등학교를 졸업할 때까지 그 전설의 깡패를 실제로 마주한 적은 없었다. 그런데 소문에는 그 전설의 깡패를 대적할 수 있는 유일한 사람이 갈비집 큰 형이라는 이야기가 있었다.&lt;/p&gt;
&lt;p&gt;갈비집은 제법 컸다. 큰 마당이 있었고 그 속에 건물이 대략 세 개 정도 있었다. 주인 아저씨는 장사가 잘되서 나중에는 호텔 뒷편 건물에 분점을 내기도 했었다. 그 해 여름을 나는 매일같이 그 형들과 갈비집 마당에서 의미없는 장난을 하고 놀았다. 우리가 가장 많이 한 장난은 개미를 잡아서 싸움을 붙이는 것이었다. 마당에는 큰 개미들이 정말 많았다. 우리는 그 중에 두 마리를 잡은 다음 더드미를 뜯어서 싸움을 붙였다. 왜 그런 장난을 했는지는 모르겠지만 우리는 그게 재밌다고 생각했다. 사실 난 그 때나 지금이나 왜 더드미를 뜯으면 개미들이 싸우는지 모른다. 그런데 형들이 그렇게 싸움을 붙였고, 그러면 실제로 개미들은 싸우는 것처럼 보였다.&lt;/p&gt;
&lt;p&gt;무던 덥던 날이었다. 약간은 꿉꿉하기도 했다. 난 어김없이 갈비집으로 갔고 형들과 의미없는 장난질을 치고 있었다. 그러다 그 큰 형이 오늘은 진짜 재미있는 걸 보여주겠다며 따라오라고 했다. 거미가 싸우는걸 구경시켜 준다고 했다. 우리는 그 마당의 구석진 곳으로 이동했고 거기엔 실제로 거미가 있었다. 거미집을 아름답게 쳐놓고 있었다. 형은 그 평화로운 거미집에 개미를 넣었다. 그리고 난 티비가 아닌 현실 세계에서 거미가 어떻게 먹이를 잡는지 구경할 수 있었다. 거미집에 떨어진 개미는 아무런 저항도 하질 못했다. 시종일관 열세였다. 내가 받았던 가장 큰 충격은 거미가 그 개미를 실을 풀어서 칭칭 감는 장면이었다. 배가 불러서 나중에 먹으려고 그러는지는 알 수 없었지만 진짜 와우에나 나오는 것처럼 거미는 흰 실을 풀어서 개미를 칭칭 감았다. 거의 다 감길 무렵 그 형은 안되겠다며 성냥에 불을 붙여서 거미집에 던졌다. 지금도 생생하게 기억날만큼 굉장히 쇼킹한 장면이었다. 그 사건을 끝으로 아마도 난 그 갈비집에 더는 놀러가질 않았던 것 같다.&lt;/p&gt;
&lt;p&gt;내가 그 형제의 소식을 마지막으로 들은 건 고등학생 때였다. 부모님께서 우연찮게 그 갈비집 이야기를 했는데, 얼마 전에 작은 아들이 오토바이를 타다가 교통 사고로 죽었다는 이야기였다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[예비군 퇴소 풍경~]]></title><description><![CDATA[월요일부터 수요일까지 예비군 동미참 훈련을 받고 있습니다. 처음엔 와…]]></description><link>https://jiniya.net/wp/archives/10041</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10041</guid><pubDate>Wed, 17 Jun 2015 23:59:36 GMT</pubDate><content:encoded>&lt;p&gt;월요일부터 수요일까지 예비군 동미참 훈련을 받고 있습니다. 처음엔 와 3일씩이나 이걸 어케 받으라고 하는 기분으로 갔는데 첫 째날, 둘 째날 갔다 오니 생각보다 할만하네요. 예비군 훈련장 경치가 너무 좋아서 사실 좀 놀랬습니다. 맨날 사무실에 틀어박혀서 바깥 세상에 단풍이 드는지, 하늘이 저렇게 높은지 보지도 못하고 지냈는데 거기 가서 실컷 보고, 멍때리고 하니 그것도 나름 좋네요. 뭐니뭐니해도 최고는 도시락먹고 벤치에 드러누워 자는 오침인 것 같습니다. 양지바른 곳에 자리잡고 누워 자니 그것만한 신선 놀음이 없더군요. ㅋ 평소 일상에 치여 놓치고 있던 많은 것들에 대해서 생각해볼 수도 있는 좋은 기횐 거 같습니다.&lt;/p&gt;
&lt;p&gt;저는 3년찬데, 2년을 학교에서 받았습니다. 그래서 사실 동미참 훈련은 처음 받는 거나 다름 없죠. 훈련장에서 훈련 마치고 나올 때 부러운 사람이 많더군요. 신분증받고 걸어 나가면서는 집 가까운 사람들이 부럽습니다. 주차장 즈음을 지날 때에는 차를 가지고 온 사람들이 부럽더군요. 그리고 정문을 나서면 애인이 데리러 온 사람이 젤 부럽습니다. 예비군 훈련 마쳤다고 데리러 오는 사람들도 있더군요. 차 가지고 데리러 온 사람들은 그나마 이해가 되는데 어제는 날씨도 추훈데 아리따운 아가씨께서 초미니 스커트를 곱게 차려입으시고는 누군가를 기다리고 있더군요. 좀 황당했습니다. 사실은 부러운 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;— 2007.10.30&lt;/p&gt;</content:encoded></item><item><title><![CDATA[김태희 얼굴 사수하기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/2999</link><guid isPermaLink="false">https://jiniya.net/wp/archives/2999</guid><pubDate>Wed, 17 Jun 2015 23:59:35 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./CAP201008161239.jpg&apos; data-alt=&apos;CAP201008161239&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/543f17ac203626be9438caf30b3f7f43/a3e66/CAP201008161239.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 166.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAhABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMEAv/EABcBAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAY86MMUbxTvimem0XGawdg//xAAeEAACAQMFAAAAAAAAAAAAAAABAgADEiIEEBQxMv/aAAgBAQABBQJVVglkYLK1KxBiOMZqDmEDbVgxiJaI3tep/8QAFxEAAwEAAAAAAAAAAAAAAAAAARARIP/aAAgBAwEBPwFCTH//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AV//xAAhEAABAwMEAwAAAAAAAAAAAAABABEhAhASIjFBUQMgof/aAAgBAQAGPwLUfqL7d5IYolePTJ7sQeaVTkxFO1oYE8upMev/xAAgEAACAQMEAwAAAAAAAAAAAAABEQAhMUEQUXGBobHw/9oACAEBAAE/IeqiKxt4OQEM9RyoiN4zFQSqJgRjnSDehU8wYqpg4DSHlsJYIjYxqRdwAYxPrqe6ZPM//9oADAMBAAIAAwAAABC0Bo50L//EABgRAAIDAAAAAAAAAAAAAAAAABAxARFB/9oACAEDAQE/EKEmMYP/xAAXEQADAQAAAAAAAAAAAAAAAAAAAREg/9oACAECAQE/EKUadx//xAAgEAEAAgICAgMBAAAAAAAAAAABABEhMUGRUXGhscHh/9oACAEBAAE/EOcBayBiqv29Qtg4IBODl+w6biilG3+dyjQddFq4Htj1kngFFIorbnM1SQFLixxotIHYOdkKo13mFW2Vj5LLZrWB/IgkkGL4gA1mDKRWE1+z7TZ7fRD5E//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;CAP201008161239&apos; title=&apos;&apos; src=&apos;/static/543f17ac203626be9438caf30b3f7f43/a3e66/CAP201008161239.jpg&apos; srcset=&apos;/static/543f17ac203626be9438caf30b3f7f43/8ccab/CAP201008161239.jpg 190w,
/static/543f17ac203626be9438caf30b3f7f43/ea4c8/CAP201008161239.jpg 380w,
/static/543f17ac203626be9438caf30b3f7f43/a3e66/CAP201008161239.jpg 480w&apos; sizes=&apos;(max-width: 480px) 100vw, 480px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;CAP201008161239&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./CAP201008161237.jpg&apos; data-alt=&apos;&amp;quot;CAP201008161237&amp;quot;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/49c7db0b252f27e0ba379b92fc1c7649/a3e66/CAP201008161237.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 166.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAhABQDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAIDBQQB/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAAB8o28OW1vkzZwsz07Rcc1wTB//8QAHxAAAgIBBAMAAAAAAAAAAAAAAQIAAxIEEBETIjEy/9oACAEBAAEFAuo8Lwx6Wl74VZkVTUHzCBtrgxiJiI32vqf/xAAXEQEAAwAAAAAAAAAAAAAAAAARARAg/9oACAEDAQE/ASoDH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BX//EACAQAAEEAQQDAAAAAAAAAAAAAAEAAhEhEDEyQWEDEiD/2gAIAQEABj8Cti2uaDp2ticel4hFzOCDy1N9oIbpioBPMqzXz//EACEQAAICAgAHAQAAAAAAAAAAAAABESExQRBRYXGBkbHw/9oACAEBAAE/IXFkcZvQqWguhQrsRuMDFeFH0XBOaVi9iyKzSROh9HITBEHJJ21mRJa0frwfY2+5/9oADAMBAAIAAwAAABDQFo50L//EABkRAAIDAQAAAAAAAAAAAAAAAAABEBExQf/aAAgBAwEBPxBWKG02OR//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREg/9oACAECAQE/EKUadx//xAAgEAEAAgIBBQEBAAAAAAAAAAABABEhMUFRcZGhsWHB/9oACAEBAAE/EBisC9m+iFqWS1Fbgz0lYXAyt78y0WKp+uD2zlZyurKs75mHJqapIULixxotIHYKdkKo15zMW2Vj5LLZrWB/kQSSDF6QAazBlIrCa+59TZ3fCHsT/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;&amp;quot;CAP201008161237&amp;quot;&apos; title=&apos;&apos; src=&apos;/static/49c7db0b252f27e0ba379b92fc1c7649/a3e66/CAP201008161237.jpg&apos; srcset=&apos;/static/49c7db0b252f27e0ba379b92fc1c7649/8ccab/CAP201008161237.jpg 190w,
/static/49c7db0b252f27e0ba379b92fc1c7649/ea4c8/CAP201008161237.jpg 380w,
/static/49c7db0b252f27e0ba379b92fc1c7649/a3e66/CAP201008161237.jpg 480w&apos; sizes=&apos;(max-width: 480px) 100vw, 480px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;&quot;CAP201008161237&quot;&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;맛폰을 처음 샀을 때 이러고 놀았다. 지금은 그 어떤 설정도 변경하지 않지만 말이다. 그때는 의욕에 넘쳐서 루팅하고 패치하고 그랬던 것 같은데. 그때나 지금이나 여전히 느린건 마찬가지… 제발 내가 사용하는 모든 걸 제외하고 그 어떤 것도 백그라운드로 돌지 않았으면 좋겠다. 내가 산 하드웨언데 왜 그게 기본적으로 안될까낭? 잡스가 관리자 권한에 대한 설정을 애시당초 제대로 설계하지 않았다에 진짜 백만표 던지고 싶다. 내가 산 하드웨어 내가 관리자가 아니면 누가 관리자란 말인가? 팀쿡인가? 아님 이재용인가? ㅠㅜ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[py] 파이썬 문자열 0 채우기…]]></title><description><![CDATA[시작 회사 웹 시스템 소스 코드를 보다가 다른 사람이 다음과 같이 코드를 작성해 놓은 것을 보았다. 뭔가 께림칙한 이 느낌. 일단 삭제. 내 생각 다음과 같이 고쳤다. zfill 그런데 이미 있었다.]]></description><link>https://jiniya.net/wp/archives/4190</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4190</guid><pubDate>Wed, 17 Jun 2015 23:59:34 GMT</pubDate><content:encoded>&lt;h3&gt;시작&lt;/h3&gt;
&lt;p&gt;회사 웹 시스템 소스 코드를 보다가 다른 사람이 다음과 같이 코드를 작성해 놓은 것을 보았다.&lt;br&gt;
뭔가 께림칙한 이 느낌. 일단 삭제.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1234&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;0&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; s&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;내 생각&lt;/h3&gt;
&lt;p&gt;다음과 같이 고쳤다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;%07d&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;zfill&lt;/h3&gt;
&lt;p&gt;그런데 이미 있었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zfill&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[블랙 기업]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/13950</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13950</guid><pubDate>Wed, 17 Jun 2015 23:59:33 GMT</pubDate><content:encoded>&lt;p&gt;얼마 전 들은 직원들의 불만 사항 중에 하나가 “고객 복지도 중요하지만 노동자 복지도 중요하다고 생각한다”는 것이었다. 그러면서 떠오른 동영상 하나. 그리곤 드는 생각. 열심히 한다고 했지만 잘하진 않았던 것 같다. 우린 아니겠지, 라고 생각하지만 그 어떤 기업도 이 잣대로부터 자유로울 수도 없다는 생각도 들었다. 퐁티의 말처럼 신체를 가지고 있는 한 폭력은 숙명인 것처럼 기업을 하는 한 착취도 숙명이 아닌가라는 생각이 들었다. 구조가 그렇고, 시스템이 그렇다. 그냥 뭔가 이상한것 같다는 생각이 계속 든다.&lt;/p&gt;
&lt;div class=&quot;video-container&quot;&gt;
    &lt;video controls&gt;
        &lt;source src=&quot;http://ebsvod.ebs.co.kr/ebsvod/cul/2014/bp0papb0000000009/1m/20140701_130500_m10.mp4&quot; type=&quot;video/mp4&quot;&gt;
        Your browser does not support the video tag.
    &lt;/video&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;우리는 순진무구함과 폭력을 선택하는 것이 아니다.&lt;/p&gt;
&lt;p&gt;폭력의 종류를 선택하는 것이다.&lt;/p&gt;
&lt;p&gt;우리가 신체를 가지고 있는 한 폭력은 숙명이다.&lt;/p&gt;
&lt;p&gt;– 휴머니즘과 폭력, 메를리 퐁티&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;한창 와우를 할 때 였다. 그당시 너무 심취해서는 거의 와우에 빠져 살다시피 했었다. 그러던 어느날 어려운 던전 보스를 잡고 우리는 뭉쳤다. 모임에 나가 보니 대다수가 대학생이었고, 내가 두 번째로 나이가 많았다. 새파란 대학생들이 그런다. 형 그래도 우리는 게임 폐인은 아니잖아요. 그 당시 나는 밥 먹을 시간도 없어서 짜장면을 먹으며 게임을 했었고, 그 친구들은 나보다 더 많은 시간을 접속해 있는 아이들었다. 그만큼 우리는 자신과 관련된 것들에 대해서는 정당한 평가를 하지 못하는 것 같다. 그 대학생 공대장을 비웃을 일이 아니었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[오해]]></title><description><![CDATA[199…]]></description><link>https://jiniya.net/wp/archives/12771</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12771</guid><pubDate>Wed, 17 Jun 2015 23:59:32 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./오해.md_0.jpg&apos; data-alt=&apos;출처: 위키피디아&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 360px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/62eb3949e93d8730600326fc0bcaa105/543cd/%EC%98%A4%ED%95%B4.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 63.68421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEAf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAFconmlGE//xAAaEAADAAMBAAAAAAAAAAAAAAAAAQIDEyEE/9oACAEBAAEFAtUorzwaZE+Vj66P/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAgEFAAAAAAAAAAAAAAAAAAEQAhExQWH/2gAIAQEABj8CXTJuLupx/8QAGRABAQEAAwAAAAAAAAAAAAAAAQARIUGB/9oACAEBAAE/IdGRRYyOxBHCppukfZBv/9oADAMBAAIAAwAAABDYz//EABURAQEAAAAAAAAAAAAAAAAAAAAh/9oACAEDAQE/EEf/xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAgEBPxCq/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARMSFBgf/aAAgBAQABPxACqChQCtezmbNHPkrBR6RgRSAzd2You6jEer25/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;출처: 위키피디아&apos; title=&apos;&apos; src=&apos;/static/62eb3949e93d8730600326fc0bcaa105/543cd/%EC%98%A4%ED%95%B4.md_0.jpg&apos; srcset=&apos;/static/62eb3949e93d8730600326fc0bcaa105/8ccab/%EC%98%A4%ED%95%B4.md_0.jpg 190w,
/static/62eb3949e93d8730600326fc0bcaa105/543cd/%EC%98%A4%ED%95%B4.md_0.jpg 360w&apos; sizes=&apos;(max-width: 360px) 100vw, 360px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;출처: 위키피디아&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;1993년 뉴욕 타임즈에 한 장의 사진이 게재됐다. 수단의 한 아이가 죽어가고 있고, 그 옆에는 독수리가 그 아이가 죽기만을 기다리고 있는 사진. 독수리는 죽은 고기만 먹기 때문에 아이가 죽기를 기다리고 있었던 것이다. 이 사진이 게재된 뉴욕 타임즈에는 항의 전화가 빗발쳤다. 도대체 이 사진을 찍은 사진 작가는 뭐하는 놈이냐? 저 상황이 사진이나 찍고 있을 때냐? 아이를 구하는게 먼저 아니냐? 누구나 사진을 보고 느낄 법한 항의들. 그만큼 사진은 많은 이들에게 충격적이었다. 이듬해 사진을 찍은 사진 작가 케빈 카터는 그 공로를 인정받아 퓰리처상을 수상했고, 그 후 얼마뒤 자살했다. 물론 사람들의 비난 때문인지 아닌지는 모르겠지만 말이다…&lt;/p&gt;
&lt;p&gt;진실은 이렇다. 케빈은 수단 내전의 참상을 알리기 위한 사진을 촬영하기 위해서 수단에 있었다. 한날 그는 보호소를 떠난 좀 먼곳의 실제 상황을 알기 위해 떠나서는 위 장면을 목격했다. 잽싸게 사진을 찍고는 독수리를 쫓아냈다. 하지만 아이는 구하지 못했다. 전염병이 많아서 구호 활동을 하러 온 사람들과 현지인의 직접적인 신체 접촉은 차단되어 있었기 때문이다. 뉴욕 타임즈는 그가 찍은 사진을 잘 알아봤고 수단 내전의 참상을 알리기 위해서 신문에 게재했다. 사람들은 뉴욕 타임즈의 의도대로 엄청난 감정의 폭풍을 경험하고 내전의 참상을 알게 됨과 동시에 사진에 대한 온갖 비난들을 쏟아냈다. 그런 상황을 지켜본 퓰리처 재단은 퓰리처 상을 수여했다. 그리고 얼마뒤 사진 작가 케빈은 자살했다.&lt;/p&gt;
&lt;p&gt;그 사진을 찍은 작가, 게재한 뉴욕 타임즈, 분노한 사람들, 상을 수여한 퓰리처 재단…&lt;/p&gt;
&lt;p&gt;사실 누구도 잘못하지 않았다. 하지만 사진 작가는 자살을 했다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;오해 – 법정&lt;/p&gt;
&lt;p&gt;‘나는 당신을 죽도록 사랑합니다’라는 말의 정체는&lt;/p&gt;
&lt;p&gt;‘나는 당신을 죽도록 오해합니다’일지도 모른다.&lt;/p&gt;
&lt;p&gt;누가 나를 추켜세운다고 해서&lt;/p&gt;
&lt;p&gt;우쭐댈 것도 없고,&lt;/p&gt;
&lt;p&gt;헐뜯는다고 해서 화를 낼 일도 못 된다.&lt;/p&gt;
&lt;p&gt;그건 모두가 한쪽만을 보고 성급하게 판단한&lt;/p&gt;
&lt;p&gt;오해이기 때문이다.&lt;/p&gt;
&lt;p&gt;오해란 이해 이전의 상태가 아닌가.&lt;/p&gt;
&lt;p&gt;문제는 내가 지금 어떻게 살고 있는가에 달린 것이다.&lt;/p&gt;
&lt;p&gt;실상은 말 밖에 있는 것이고&lt;/p&gt;
&lt;p&gt;진리는 누가 뭐라 하든 흔들리지 않는다.&lt;/p&gt;
&lt;p&gt;온전한 이해는 그 어떤 관념에서가 아니라&lt;/p&gt;
&lt;p&gt;지혜의 눈을 통해서만 가능하다.&lt;/p&gt;
&lt;p&gt;그 이전에는 모두가 오해일 뿐이다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[의사와 환자]]></title><description><![CDATA[Breaking AV Software…]]></description><link>https://jiniya.net/wp/archives/12965</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12965</guid><pubDate>Wed, 17 Jun 2015 23:59:31 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; margin-bottom: 16px;&apos; data-url=&apos;./dp.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5642ad9b69de58a3af34cba1232491db/407f2/dp.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADdUlEQVR42mMImHQ/ad6jhDmP4uc8Spj7KG72QyAjaubD2DmPUuY/jgYyZj8CkklzH4MEZz1MW/A4bjZIgf+k+wwWdWfCJlyKmHg5buqV+KlXUmZeTZ5xNaT/UtSkSwnTLidOA4pfjpxwMXnGlchJIMHUmVeTpl8L7rtkUn2KoW39/aY198DoQf3q+w2r7zeueQBkN6191LLhafumZ83rnrSsf9K49lHzukdNax83rH4IVNy89j5QI8OBqx8OXPuw/+qnPScuHDt76vTFCxu27VizadvOA7sXLp0/ceqkLVvXrtuw8vCJg6fPHjl9csexsxcOXP984Op7oEaGQ1ffH7r67uDVjweO7r96ce+pY1sOH1i7Z/faY0fW5mf4Whkq5Ce51BSF7N859dy+6ae2tZ44uuXg9a9ALUCNDOfvfTh/7/35+5+PnTowZ1Z3TEx4RnpcbXXR6tWz+jrzI4Pso0PsCtP8J5X6bZ6QcGJr55mTO84/+Hr+7nugRoZbTz7dfPzh9rPvR45sjIu0FxDgERHk5uRg8vOxWDK3sroyMczL0tdc3dNMI8pUZEmN6+ljm28/+3Hr8QegRob7zz/fffrx2bvfk6dO8fJyVlSQFhcTlpIU1VSX93E393Y3tzIz0dXSsjAzsVEXjbUU7Omoe/7x/92nH4AaQZrvPP306u2XpAknJYJblBTEZWUl1FSktLUULUw0vF0Mw/3sbEzN9ZXkgrQk/HWFi8qK33z5f+cJTPPdZ59fvfqUseOb4ZL75vZ2QgJcUrLSSooy8jKiyjJyphqGVupKMSYy/UGqZa6iMfGJb76iaX75MWHlba19P0yC42SkZNLjw6I9Df1M1KwUNe10NV315Tx0xOKtJcocuLuqsp6hOfv1+5/RhY2iy89rePjLScvZmmo1pTrURpvneGvF2ymkuyo5aApbKIlG67DObcl+iqL5yQegSwL8QxgsPVQN9WUk+Pn5Of3cDSJ8jPwsZKzV+V10+QylWDVE2LW4GMrSYl6B/PwepPneM2Bof3r0+sfaTTu7u/sXLVm2cvXqeQsWLly8ZNmKFdNmzp0+e96EqbP6J03r65/c0ty8dv3mx29+ASMIqJHhyeuvQPT41ZdXH3+///H/9ed/rz7+ff3pL5Dx5vPfd1/+A9H7b//fff3/9ss/IPnyw2+gYoguAG06EBzXQ2dwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;dp&apos; title=&apos;&apos; src=&apos;/static/5642ad9b69de58a3af34cba1232491db/407f2/dp.png&apos; srcset=&apos;/static/5642ad9b69de58a3af34cba1232491db/08678/dp.png 190w,
/static/5642ad9b69de58a3af34cba1232491db/2edd7/dp.png 380w,
/static/5642ad9b69de58a3af34cba1232491db/407f2/dp.png 520w&apos; sizes=&apos;(max-width: 520px) 100vw, 520px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;Breaking AV Software&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;회사 생활을 하다보면 참 재미난 일이 많이 있는데 그 중에 젤 황당한 일이 의사와 환자가 뒤바뀌는 경우다. 보통은 의사가 환자를 진단하고, 환자는 의사의 처방전을 받아 들이기 마련이다. 그런데 주객이 전도되서는 의사가 환자에게 처방전을 물어보고, 환자가 의사에게 처방을 지시하는 경우들이 종종 있다. 황당하게도 말이다. 그리고 말미엔 꼭 탈이 난다. 내가 의사인지 환자인지, 내가 처방전을 쓰는 입장인지 받아야 하는 입장인지를 잘 판단하는 게 회사 생활의 기본인 것 같은데도 어려운것 같기도 하고 그렇다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[세상의 모든 문제가 그렇게 틀리면서 배우기 때문이란다]]></title><description><![CDATA[우진아, 1…]]></description><link>https://jiniya.net/wp/archives/4085</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4085</guid><pubDate>Wed, 17 Jun 2015 23:59:30 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/SUfTEc82yQs?si=-zh7Ne19OC8nqivY&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;우진아,&lt;/p&gt;
&lt;p&gt;12번 수학문제를 틀리는 것을 두려워하지 마라&lt;/p&gt;
&lt;p&gt;몇 번의 시험&lt;/p&gt;
&lt;p&gt;몇 번의 만남&lt;/p&gt;
&lt;p&gt;그리고 몇 번의 헤어짐&lt;/p&gt;
&lt;p&gt;몇 번이 될지 모르는 입사 면접&lt;/p&gt;
&lt;p&gt;너는 앞으로도 수많은 문제들을 만나고&lt;/p&gt;
&lt;p&gt;결정해야 될지도 모른단다&lt;/p&gt;
&lt;p&gt;수학은 틀려야 한다&lt;/p&gt;
&lt;p&gt;그것도 용감하게 틀려야 한다&lt;/p&gt;
&lt;p&gt;세상의 모든 문제가&lt;/p&gt;
&lt;p&gt;그렇게 틀리면서 배우기 때문이란다&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[숫타니파타]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/13519</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13519</guid><pubDate>Wed, 17 Jun 2015 23:59:29 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;집착 없이 세상을 걸어가고&lt;/p&gt;
&lt;p&gt;아무것도 가진 것 없이&lt;/p&gt;
&lt;p&gt;자기를 다스릴 줄 아는 사람&lt;/p&gt;
&lt;p&gt;모든 속박을 끊고&lt;/p&gt;
&lt;p&gt;괴로움과 욕망이 없는 사람&lt;/p&gt;
&lt;p&gt;미움과 잡념과 번뇌를 벗어 던지고&lt;/p&gt;
&lt;p&gt;맑게 살아가는 사람&lt;/p&gt;
&lt;p&gt;거짓도 없고 자만심도 없고&lt;/p&gt;
&lt;p&gt;어떤 것을 내것이라 집착하지도 않는 사람&lt;/p&gt;
&lt;p&gt;이미 강을 건너 물살에 휩쓸리지 않는 사람&lt;/p&gt;
&lt;p&gt;이 세상이나 저 세상이나 어떤 세상에 있어서도&lt;/p&gt;
&lt;p&gt;삶과 죽음에 집착이 없는 사람&lt;/p&gt;
&lt;p&gt;모든 욕망을 버리고 집 없이 다니며&lt;/p&gt;
&lt;p&gt;다섯 가지 감각을 안정시켜&lt;/p&gt;
&lt;p&gt;달이 월식에서 벗어나듯이 붙들리지 않는 사람&lt;/p&gt;
&lt;p&gt;모든 의심을 넘어선 사람&lt;/p&gt;
&lt;p&gt;자기를 의지처로 하여 세상을 다니고&lt;/p&gt;
&lt;p&gt;모든 일로부터 벗어난 사람&lt;/p&gt;
&lt;p&gt;이것이 마지막 생이고 더 이상 태어남이 없는 사람&lt;/p&gt;
&lt;p&gt;고요한 마음을 즐기고&lt;/p&gt;
&lt;p&gt;생각이 깊고&lt;/p&gt;
&lt;p&gt;언제 어디서나 깨어 있는 사람&lt;/p&gt;
&lt;p&gt;– 숫타니파타 490-503&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[여유에 관한 발칙한 생각]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/wp/archives/13503</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13503</guid><pubDate>Wed, 17 Jun 2015 23:59:28 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/ajCYQL8ouqw?si=NzhLl_5WjPWkowtG&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; **Let it be** &lt;/div&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;회사 직원과 둘이 점심을 먹으면서 이런 저런 이야기를 했다. 그 친구 왈 요즘은 너무 여유가 없다는 이야기를 했다. 그도 그럴것이 인원은 한정돼 있고 사이트는 계속 늘어나니 예전엔 조금씩 있던 여유가 지금은 한톨도 없다는 이야기를 한다. 그러면서 뭔가 새로운 일을 하고 싶어도 여유가 없으니 당장 코앞에 벌어진 일만 할 수 밖에 없다는 푸념을 했다. 조곤 조곤 하는 이야기를 듣고 있노라니 많이 공감이 갔다. 단지 시키는 입장에서는 왜 이것도 안되고 저것도 안되냐고 닥달하기 쉽지만 직접 일을 하는 입장에는 사소한 거 하나를 처리하는 데에도 시간이 걸리는 게 일이 아닌가라는 생각을 왜 못했나 싶었다. 난 메모리 액세스 속도를 기대했는데 사실 I/O는 SSD도 아닌 하드디스크도 아닌 플로피디스크였던 것이다. 섹터 찾는데도 시간이 걸리는 물리적인 한계가 있었던 것이다.&lt;/p&gt;
&lt;p&gt;여유가 많이 없어졌군. 이런 생각을 하면서 회사로 복귀했다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;저녁 무렵. 집 근처에 사는 후배 녀석을 만났다. 집 앞 콤마라는 커피숍에 앉아서는 이런 저런 이야기를 하는데 녀석도 비슷한 이야기를 한다. 의료 정보쪽 회사에서 프로그래머로 일하고 있는데 일이 쉽지가 않은 것이다. 사실은 회사 정책을 탐탁치 않아 하는 분위기 였다. 그 회사는 규모도 크고 매출도 제법 되는 회산데 회사에서 후배가 하는 프로젝트에 돈을 쓰기 보다는 다른 신사업에 돈을 쏟아 붓는다는 것이었다. 현재 그 회사의 캐시카우는 후배가 하는 프로젝트임에도 말이다.&lt;/p&gt;
&lt;p&gt;그래서 난 그런 말을 했다. 경영자가 미래 사업 방향을 그 신사업으로 정했다면 그건 어느 정도 납득이 되는 이야긴거 같다고. 그래서 진짜 네가 힘든게 뭐냐고 물었더니 회사 직원과 똑같은 이야기를 한다. 여유가 없다는 것이다. 이건 뽑아 먹어도 적당히 뽑아 먹어야 하는데 정말 토나오는 상황이라는게 그 친구의 말. 예를들면 이런 식이었다. 그 친구가 일주일에 통상적으로 처리해야 하는 레드마인 이슈가 10개라면 의욕도 있고 회사에서 어느 정도 인정도 받고 있어서 15개 정도를 처리하겠다고 열심히 하는데 그 중간 중간에 하나도 아니고 시도 때도 없이 인터럽트와 추가 이슈가 들어온다는 이야기였다.&lt;/p&gt;
&lt;p&gt;듣고 있는데 참 남 일 같지 않다는 생각이 들었다. 특히나 점심 때 그런 이야기를 들었으니 ㅠㅜ~ 회사 생활이라는게 참 쉽지 않구나라는 생각. 녀석은 들어가면서 그랬다. 남의 돈 버는게 어디 쉽나요…&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;지난번 블로그에 &lt;a href=&quot;http://www.jiniya.net/wp/archives/13045&quot;&gt;코드의 색깔을 찾아서&lt;/a&gt;라는 글에 문제를 냈었다. 몇 분이 답을 보내주었는데 모르는 분이 한 분 포함돼 있었다. 관심가져 주신게 고맙기도 하고 어떤 분인지 만나 보고 싶기도 해서 연락을 해서는 만났다. 만나서 통성명을 하고 인사를 하는데 큰 형님이셨다. 그러면서 이런 저런 좋은 이야기를 많이 했었다. 게임 업계에 있다가 지금은 제조 쪽에서 프로그래밍을 하고 계시다고 했다. 재밌는 문제 푸는 걸 좋아해서 한번 해봤다는 이야기를 했다.&lt;/p&gt;
&lt;p&gt;그 이야기 중간에 이런 이야기가 있었다. 그래도 연구소장 정도 되니까 블로그에 코드 색깔 스크립트나 짜서 올리고 하는 여유가 있는 것 같다고. 직원들 입장에서는 그런 걸 할 시간이 없지 않겠냐는 이야기. 형의 그 이야기를 나도 반박하지는 않았다. 내가 봐도 우리 회사 직원들은 바빠서 그런 일을 할만한 시간이 없다고 생각됐기 때문이었다. 그래서 내가 생각해도 회사 직원 입장에서는 바빠서 아마 그럴 시간은 없는게 맞는것 같다는 이야기를 했다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;비오는 오후 사무실에 의자에 앉아서 창밖에 내리는 비를 물끄러미 바라보며 커피를 한 잔 하고 있는데 갑자기 그런 생각이 들었다. 이 여유란 것도 어떻게 보면 빈익빈 부익부가 심할 수도 있겠다라는 생각. 나는 사실 여유가 많은 편이다. 커피를 한 잔 하고 싶으면 쉴 수도 있고, 코드 쓰다가 머리 아프면 잠시 나갔다 올 수 도 있고, 집에서 일하고 싶으면 집에서 일한다. 그러니 어쩌면 직원 입장인 친구들보다는 새로운 것들이나 문제점을 찾기가 훨씬 더 쉬운 위치에 있는지도 모른다. 그리고 그런 일들이 쌓이면서 내가 훨씬 더 여유를 많이 가질 수 있는 위치에 있게 되고 말이다. 결국 선순환과 악순환인 두 개의 피드백 루프가 있다면 어쩌다보니 난 재수가 좋아서 선순환의 피드백 루프에 들었던게 아닌가라는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;지금 당장 문제를 해결할 시간도 없는데 go, rust, f# 같은 언어를 주목할 필요가 있다는 이야기는 그 친구들에게는 어쩌면 밥이 없으면 빵을 먹으라는 말처럼 들리지 않았을까? 내리는 빗방울만큼 생각도 많아지는 오후…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[40대 개발자는 뭐 먹고 사나요?]]></title><description><![CDATA[김종득님이 얘기 하시는 것처럼 제가 대학교 다닐 때에 선배들이 30살 되면 프로그램 못짠다고 이런 얘기를 하셨고요. 근데 보니까 그 얘기 하시던 선배들은 프로그램 못짜던 선배였어요. 제가 30살 되니까 4…]]></description><link>https://jiniya.net/wp/archives/14748</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14748</guid><pubDate>Wed, 17 Jun 2015 23:59:27 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;김종득님이 얘기 하시는 것처럼 제가 대학교 다닐 때에 선배들이 30살 되면 프로그램 못짠다고 이런 얘기를 하셨고요. 근데 보니까 그 얘기 하시던 선배들은 프로그램 못짜던 선배였어요. 제가 30살 되니까 40살 되면 프로그램 못짠다고 이런 얘기를 많이 하시는데 근데 그 얘기 하시는 분들이 또 프로그램 못 짜던 분들이 그런 얘기 하셨던 것 같구요.&lt;/p&gt;
&lt;p&gt;– 송재경&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;30대 중반까지 코딩하는 입장에서 전적으로 틀린 말은 아니라고 생각한다. 그런데 반전은 한살 한살 먹으면서 느끼는게 점점 더 똑똑해지기 보다는 멍청해지기가 쉽다는 점이다. 예전보다 똑똑함이나 총명함을 유지하기가 정말 쉽지 않은 것 같다. 20대 때 프로그램 좀 짠다고 했던 사람이 30까지 그 실력을 유지하거나 발전시키기가 생각만큼 녹록치 않다는 말이다. 그러니 그 나이 또래 때 그럭저럭 한다고 생각해도 나이들면 쉽게 쉽게 추락하고 도태돼 버리는 게 아닐까라는 생각. 물론 신입만큼 하기야 쉽겠지만 말이다. 해외에는 나이든 엔지니어가 많다고 해도 &lt;a href=&quot;http://www.jiniya.net/wp/archives/8185&quot;&gt;그래프를 보면 쭉쭉 줄어들기는&lt;/a&gt; 마찬가진거 같다. 그나마 인력 풀이 크니깐 살아남는 사람이 상대적으로 많은 게 아닐까라는 생각이 많이 든다.&lt;/p&gt;
&lt;p&gt;대체로 출연자들이 대박 욕 먹은 동영상이긴 하지만 찬찬히 한 번 들어볼 필요는 있는 내용이 아닐까 싶다. 욕해도 그게 현실이기도 하고…&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/9bKP3rEzW4s?si=Yy6BdVQ1CgSlgR7N&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/vgl1SO8aOPs?si=FdTHnNtlu0PNd2lD&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/U6YpaL1kWZw?si=oTcfYZ6Hg_w5wpKI&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title><![CDATA[애플, 맥, OS X, iOS 관련 내용들…]]></title><description><![CDATA[#0 기본적으로 윈도우와 HOME/END 키 동작 방식이 다름 HOME/END 키 동작 방식 변경 방법 http://mwholt.blogspot.kr/2012/09/fix-home-and-end-keys-on-mac-os-x.html #…]]></description><link>https://jiniya.net/wp/archives/13524</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13524</guid><pubDate>Wed, 17 Jun 2015 23:59:26 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;기본적으로 윈도우와 HOME/END 키 동작 방식이 다름&lt;/p&gt;
&lt;p&gt;HOME/END 키 동작 방식 변경 방법&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://mwholt.blogspot.kr/2012/09/fix-home-and-end-keys-on-mac-os-x.html&quot;&gt;http://mwholt.blogspot.kr/2012/09/fix-home-and-end-keys-on-mac-os-x.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;컨트롤 대신 대부분 단축키가 윈도키에 조합됨&lt;/p&gt;
&lt;p&gt;ctrl + c =&gt; win + c&lt;/p&gt;
&lt;p&gt;ctrl + tab =&gt; win + tab&lt;/p&gt;
&lt;p&gt;ctrl + p =&gt; win + p&lt;/p&gt;
&lt;p&gt;ctrl + z =&gt; win + z&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다윈 커널 소스&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://opensource.apple.com/source/xnu/xnu-2422.90.20/&quot;&gt;http://opensource.apple.com/source/xnu/xnu-2422.90.20/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;top 소스 코드&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://opensource.apple.com/source/top/top-89.1.2/&quot;&gt;http://opensource.apple.com/source/top/top-89.1.2/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 우공이산의 지혜]]></title><description><![CDATA[나에게 20살은 자유를 의미했다. 경제 활동을 시작하면서 난 부모님에게서 독릴할 수 있었고, 모든 결정을 내 멋대로 할 수 있었다. 대학도 그랬다. 난…]]></description><link>https://jiniya.net/wp/archives/8560</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8560</guid><pubDate>Wed, 17 Jun 2015 23:59:25 GMT</pubDate><content:encoded>&lt;p&gt;나에게 20살은 자유를 의미했다. 경제 활동을 시작하면서 난 부모님에게서 독릴할 수 있었고, 모든 결정을 내 멋대로 할 수 있었다. 대학도 그랬다. 난 1년 동안 거의 학교에 가지 않았다. 물론 학교는 갔었지만 수업을 듣지 않았다. 사실 내 수업보다 여자친구 수업을 더 많이 들었었다. 당연히 나의 성적표는 대부분 F로 채워졌다. F가 아닌 과목은 거의 대부분 내 앞에 있었던 신명진이란 여자 아이가 출석을 부를 때 내 이름을 자기 이름으로 잘못 들어서 대출한 과목이었다. 학사경고였다. 시쳇말로 쓰리고면 제적이었기에 두번째 학사경고를 받았을 때 귀댁의 자녀가 위기에 처했다는 전화가 집으로 왔다. 내가 받았다면 난 제적을 당했을지도 모른다. 다행이 엄마가 받았고 집에는 난리가 났다. 그 등살에 난 2학년 부터는 수업을 조금씩 듣기 시작했다.&lt;/p&gt;
&lt;p&gt;그렇게 참가한 기초 전자 전기 실험에서 그 형을 처음 만났다. 당시 난 병특을 준비하고 있었고, 그 형은 병특을 마치고 학교를 복학한 상태여서 우리는 금방 친해졌다. 가끔 술도 한잔 하면서 이야기를 많이 했었는데 영어를 잘했으면 좋겠다는 이야기를 하는 나에게 형은 병특을 시작하면 영어 단어를 하루에 하나씩 외우라는 판에 박힌 조언을 해줬다. 진짜 정말 너무 어처구니가 없어서 형한테 욕을 할 뻔 했다. ㅋ~ 난 당현하게 형은 영어를 못할 거라는 생각을 가지고 있었다.&lt;/p&gt;
&lt;p&gt;우리는 더 많은 실험을 했고, 더 많이 친해졌고, 더 많은 사실을 알 수 있었다. 그러다 약간 놀랄만한 사건이 하나 있었다. 한날은 형이 실험을 하러 오면서 뭘 보고 있기에 뭐냐고 하니깐 아이트리플이라고 했다. 난 IEEE를 그렇게 읽는다는 걸 그때 처음 알았다. 그리고 학교에서 무료로 볼 수 있는 잡지를 직접 구독하는 사람이 우리과에 있다는 사실에 두 번 놀랬다. 형은 나에게 싸게 구독할 수 있는 요령을 알려주었지만 난 받아들이지 않았다. 그리고 얼마되지 않아서 더 놀라운 사실을 접했다. 나에게 하루에 영어 단어를 하나씩 외우라고 조언했던 그 형이 학교 신문에 났기 때문이었다. 그것도 무려 ACM 대학생 논문 경진대회 대상을 수상했다는 명목으로 말이다.&lt;/p&gt;
&lt;p&gt;난 놀래서 형한테 왜 그런 이야기를 안했냐니 대단한게 아니라서 말을 안했다는 허무한 대답을 들었다. 그러면서 어떻게 그런 대회에서 상을 탔냐고 도대체 어떤 논문이었냐고 어떻게 그런 생각을 해내게 됐냐고 꼬치꼬치 캐물었다. 형은 답했다. 그냥 앉아있다 이렇게 하면 더 좋지 않을까라는 생각에 써서 냈다고. 학비가 없어서 좀 더 간절했다는 더 어처구니 없는 대답. 멘붕~&lt;/p&gt;
&lt;p&gt;난 병특을 시작했다. 영어를 잘하고 싶다는 생각은 있었지만 형의 조언은 상콤하게 씹었다. 사실 생활하는데 영어가 그닥 필요하지 않았기 때문이다. 그때나 지금이나 난 영어 라이팅을 배우고 싶은데 쉽지가 않다. 그러면서 그냥 형은 원래 타고날 때부터 머리가 좋았겠지, 엄마 뱃속에서 영어를 배웠다고 생각했다.&lt;/p&gt;
&lt;p&gt;국방부 시계는 간다고 나의 병특도 어느새 끝이났다. 사실 돌아보니 너무 금방 끝이 났다. 난 영어 단어를 하나도 외우지 않았다. 형은 졸업을 했고 카이스트에 석사로 갔다. 학교 앞에서 한 번 만날 일이 있었다. 난 복학하면서 잔뜩 유학 거품이 들어 있었던터라 GRE를 준비한답시고는 겉멋에 찌들어 살고 있었다. 그날도 그랬다. 난 워드 스마트를 보면서 이런 단어를 내 평생에 한 번은 쓸까라면서 멘붕에 빠져있는데 형이 들어왔다. 옆에 책을 한 권 끼고 있었는데 날 좌절하게 만들기에 충분했다. 내가 중딩인지 고딩인지 그때 보던 능률 보카를 끼고 온 것이다. 당시 형은 GRE를 준비하는 게 아니라 실제로 GRE를 치던 시점이라 너무 어처구니가 없었다. 그리곤 형이 단어를 하나씩 외우라고 한 조언이 빈 말이 아님을 알 수 있었다. 능률 보카에 형광펜을 칠하면서 보고 있었기 때문이다.&lt;/p&gt;
&lt;p&gt;복학 이펙트는 오래가지 않았다. 한 학기 반짝하고는 난 또 그냥 그런 학교 생활을 했다. 난 학점을 메꾸지도 못했고, 유학을 가지도 못했다. GRE는 한 번 쳐보지도 못했다. 그만큼 빨리 포기했다. 반대로 형은 GRE에서 상당한 수준의 점수를 받았고, MIT로 유학을 떠났다.&lt;/p&gt;
&lt;p&gt;이런 이야기를 하면 많이들 그 형은 원래 천재였고, 1학년부터 착실히 공부를 했으며, 그래서 그런 엄청난 결과를 얻었을 거라는 이야기를 한다. 하지만 웃긴 사실은 그 형도 학사경고를 받았으며, 1학년 때에 술을 많이 마시고는 모텔을 간적이 있었다고 했다. 모텔에 가서도 술판이 한창 벌어졌는데 같이 술을 마시던 선배가 너무 술을 마니 마셔서 수영을 하자는 제안에 모텔 바닥에서 수영을 한적이 있었다고 했다. 차마 무엇과 함께 수영했는지는 상상에 맡기겠다.&lt;/p&gt;
&lt;p&gt;너무나 많은 시간이 지났다. 난 여전히 우공이산의 지혜를 머리로만 이해한다. 회사에 2년만에 신입 개발자가 첫 출근을 했다. 난 제프리 리처의 Windows via C/C++을 건내며 앞으로 한달간 이 책만 씹어먹어도 위대한 시스템 프로그래머가 될 수 있다는 이야기를 해 주었다. 이 똑같은 이야기를 난 몇 차례 했었는데 그 어떤 신입 개발자도 그 책을 씹어먹진 않았다. 너무 시시하다는 반응이 대부분이었다. 참 안타까운 일이 아닐 수 없다. 난 이 바닥에서 10년을 일했고, 그래도 나름 못한다기 보다는 잘한다는 평을 받으면서 일했다. 개인적으로도 경쟁력은 있다고 생각해 왔었다. 그런데도 난 여전히 100번도 더 읽었던 Windows via C/C++에서 힌트를 얻고 제프리 리처가 1999년도에 쓴 글을 읽으면서 감탄한다. 촌스럽다고 느끼지만 현실은 그렇다.&lt;/p&gt;
&lt;p&gt;형을 마지막으로 본게 9년전 카이스트였던 것 같다. 그때 우리는 10년 후를 이야기 했었다. 같이 간 형은 입사한 대기업 부사장이 되겠다고 했고, 난 벤처기업을 차리겠다는 이야기를, 그리고 형은 미국에 가서 자리를 잡겠다는 이야기를 했다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/13369&quot;&gt;내년 초여름이면 꼭 10년이 된다.&lt;/a&gt; ㅎㅎ~ 같이 갔던 형은 여전히 그 대기업에 다니지만 부사장이 되기에는 아직 힘들어 보이고, 나는 그때 말한 것처럼 성공하진 못했지만 벤처를 시작하긴 했다. 형은 MIT 연구소로 스카웃되서 갔고, 여전히 MIT에 있다. 형의 안부가 궁금해지는 새벽녘이다. 그 옛날 400원짜리 캔커피 뽑아서는 전소 앞에 쪼롬히 앉아서 조교 씹던게 엊그제 같은데 시간이 이리도 빨리 흘렀다. 하루는 더디 흘러도, 10년은 훌쩍 가버리는 게 세월이 아닌가 싶다.&lt;/p&gt;
&lt;p&gt;쉬워 보이는 것도 꾸준히 하는 일은 우리가 생각하는 것보다 훨씬 더 효과적인 방법인지도 모른다. 왜냐하면 거의 모든 사람들이 빠른 길을 찾는다는 명분 아래 정작 아무 것도 하지 않고 시간을 보내기 때문이다. 마치 병특 때의 나처럼 말이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[재미난 게 없어요…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4902</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4902</guid><pubDate>Wed, 17 Jun 2015 23:59:24 GMT</pubDate><content:encoded>&lt;p&gt;나이 들어 친구든 지인이든 주변에서 제일 많이 듣게 되는 말 중에 하나가 “재미난 게 없어요”라는 말인 것 같다. 근데 그런 말 하는 사람들 대부분이 실상은 아무 것도 하지 않으면서 저절로 재미있어 지기를 바란다는 점이다. 그런 사람들에게 꼭 보여주고 싶은 테드 영상. 내가 느끼는 기분을 더 잘 표현한 &lt;a href=&quot;http://wangmul.egloos.com/3317027&quot;&gt;왕멀님의 블로그 글&lt;/a&gt;…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 화…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/14712</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14712</guid><pubDate>Tue, 16 Jun 2015 23:59:23 GMT</pubDate><content:encoded>&lt;p&gt;회사를 경영하는 형이 일 처리를 제대로 하지 못한 팀장에게 화를 냈다며 자책하는 이야기를 했다. 그러면서 뭐가 정답인지도 잘 모르겠다는 이야기도 덧붙인다. 세상에 뭐 그리 딱 떨어지는 정답이 있기야 하겠는가만은… 잘못된건 잘못됐다고 지적할 수 있어야 발전이 있지 않을까라는 생각이 들었다. 나는 완벽하지 않더라도 말이다…&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./화.md_0.png&apos; data-alt=&apos;생존한다는 건 장난이나 놀이가 아니다. 생각보다 훨씬 복잡하고 어렵고 힘든 일이다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 515px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fdf487eada1106d459f6e18d2648251a/70021/%ED%99%94.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 25.263157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA1ElEQVR42h1P27KDIAz0/z+wc+ppBcRyEaiAIreXriZMsuzObJKB8+XxN75e0ziO74k+x3+ptTLWuK+2Tmpz5tJ7zzm31q7ar5pLwXdQWi8fQQjVemWcE8reE+GcU8oInRljUmkhpFRq5gt4gImweeZC6cGsq5BiohR2KSUfYgih1Ap8nhkPDbC1DlwymPOAlo6Y0mCMJYwppf3m4e+DR1hjN+9jjBhprNtuyTq37xGT3RdEsNbday+ffT96a/CudxRkq+1mCta4ri0A19klQwRVa/0BSPoW+b81OnQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;생존한다는 건 장난이나 놀이가 아니다. 생각보다 훨씬 복잡하고 어렵고 힘든 일이다.&apos; title=&apos;&apos; src=&apos;/static/fdf487eada1106d459f6e18d2648251a/70021/%ED%99%94.md_0.png&apos; srcset=&apos;/static/fdf487eada1106d459f6e18d2648251a/08678/%ED%99%94.md_0.png 190w,
/static/fdf487eada1106d459f6e18d2648251a/2edd7/%ED%99%94.md_0.png 380w,
/static/fdf487eada1106d459f6e18d2648251a/70021/%ED%99%94.md_0.png 515w&apos; sizes=&apos;(max-width: 515px) 100vw, 515px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;생존한다는 건 장난이나 놀이가 아니다. 생각보다 훨씬 복잡하고 어렵고 힘든 일이다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./화.md_1.jpg&apos; data-alt=&apos;일단 성공하면 다 용서되는 불편한 진실…&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/aede35c023e8d2d701cb2dae89385a8d/953fe/%ED%99%94.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUCBAP/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAH01F6ScriJ0hgH/8QAGxAAAgMBAQEAAAAAAAAAAAAAAQMAAgQREzL/2gAIAQEAAQUCUtZUzwUL8NxpaKr0kxehQpKfHOz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAhEAABBAEDBQAAAAAAAAAAAAABAAIRIQMQEjEiI0Fhcf/aAAgBAQAGPwJk4QaQ34OfScWippAB5pd3r++FDmWNOJ0//8QAHRABAQACAgMBAAAAAAAAAAAAAREAITFBEFFhcf/aAAgBAQABPyFSQTuG8rSOkGakGonBhJQIEMSNB05HC8F9/fEFIqm8lP7n/9oADAMBAAIAAwAAABCnxz7/xAAVEQEBAAAAAAAAAAAAAAAAAAARIP/aAAgBAwEBPxBj/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHRABAAIDAQADAAAAAAAAAAAAARExACFBYRBxkf/aAAgBAQABPxBihTPVF3gnIESpTycShYaEjoj6w+/AagoyU0lgGkcAury/2AR/Y78HkEqmhk9wcsgIA4Tn/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;일단 성공하면 다 용서되는 불편한 진실…&apos; title=&apos;&apos; src=&apos;/static/aede35c023e8d2d701cb2dae89385a8d/953fe/%ED%99%94.md_1.jpg&apos; srcset=&apos;/static/aede35c023e8d2d701cb2dae89385a8d/8ccab/%ED%99%94.md_1.jpg 190w,
/static/aede35c023e8d2d701cb2dae89385a8d/ea4c8/%ED%99%94.md_1.jpg 380w,
/static/aede35c023e8d2d701cb2dae89385a8d/953fe/%ED%99%94.md_1.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;일단 성공하면 다 용서되는 불편한 진실…&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[리뷰] 회사원]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/10791</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10791</guid><pubDate>Tue, 16 Jun 2015 23:59:22 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 678px; margin-bottom: 16px;&apos; data-url=&apos;./회사원.md_0.jpg&apos; data-height=&apos;640&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dd6fa8b6c5b9d5dd0d56788c37951200/b98e4/%ED%9A%8C%EC%82%AC%EC%9B%90.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 142.6315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAdABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgUE/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAHKvECw5yGWRpZc8eav/8QAHBABAQACAgMAAAAAAAAAAAAAAgEAIQMREiNC/9oACAEBAAEFAoKkh0tYUjlXrm5Js8cWUUX6l8OHrP/EABURAQEAAAAAAAAAAAAAAAAAABAB/9oACAEDAQE/ASH/xAAVEQEBAAAAAAAAAAAAAAAAAAAQAf/aAAgBAgEBPwEp/8QAHBAAAQQDAQAAAAAAAAAAAAAAAAECETEQEiFB/9oACAEBAAY/AkgvDopbL7OHbLBCLJq68c9LP//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExYXGh/9oACAEBAAE/IQjPs2m3D5MHI+Ilm7a/kSDdQdEPPZ3yrMjzARtotzl9GsE6qf/aAAwDAQACAAMAAAAQQ/Pw/8QAFhEBAQEAAAAAAAAAAAAAAAAAEBEh/9oACAEDAQE/EMhB/8QAFxEAAwEAAAAAAAAAAAAAAAAAARARIf/aAAgBAgEBPxDagNwr/8QAHxABAAMAAgEFAAAAAAAAAAAAAQARITFBgVFhccHw/9oACAEBAAE/ECJsNWaIj1AIPZFpr4gAKOc1LMLAtonZUBy4LuvUfcDHFx5mYUvj4RxTqB+dxSOKgzSYHPaEmR7XdgNgvbs//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;    md 0&apos; title=&apos;&apos; src=&apos;/static/dd6fa8b6c5b9d5dd0d56788c37951200/b98e4/%ED%9A%8C%EC%82%AC%EC%9B%90.md_0.jpg&apos; srcset=&apos;/static/dd6fa8b6c5b9d5dd0d56788c37951200/8ccab/%ED%9A%8C%EC%82%AC%EC%9B%90.md_0.jpg 190w,
/static/dd6fa8b6c5b9d5dd0d56788c37951200/ea4c8/%ED%9A%8C%EC%82%AC%EC%9B%90.md_0.jpg 380w,
/static/dd6fa8b6c5b9d5dd0d56788c37951200/b98e4/%ED%9A%8C%EC%82%AC%EC%9B%90.md_0.jpg 678w&apos; sizes=&apos;(max-width: 678px) 100vw, 678px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;넌 일이 좋냐?&lt;/p&gt;
&lt;p&gt;오늘 진짜 이상하시네. 아까도 사고 내고.&lt;/p&gt;
&lt;p&gt;과장님은 싫으세요?&lt;/p&gt;
&lt;p&gt;나야 그냥 하는 거고. 오래했으니까.&lt;/p&gt;
&lt;p&gt;일인데요. 뭐. 좋고 싫고가 어딨어요?&lt;/p&gt;
&lt;p&gt;저 고등학교도 짤렸잖아요. 어디가서 이만큼 벌어요?&lt;/p&gt;
&lt;p&gt;불만 없어요, 저는. 위에 말이나 잘해줘요. 월급 좀 제대로 받게.&lt;/p&gt;
&lt;p&gt;부족해? 지금 받는 거?&lt;/p&gt;
&lt;p&gt;네. 불안정 하자나요. 언제 짤릴지도 모르고.&lt;/p&gt;
&lt;p&gt;야, 너 이제 스무 살이야.&lt;/p&gt;
&lt;p&gt;네.&lt;/p&gt;
&lt;p&gt;넌 뭐 되고 싶은 거 없냐고?&lt;/p&gt;
&lt;p&gt;부자요. 떼부자.&lt;/p&gt;
&lt;p&gt;한 5년 바짝 벌어가지고 미국으로 뜰라구요.&lt;/p&gt;
&lt;p&gt;마이애미, LA 이런데 가서 백인 여자들 두세 명씩 끼고…&lt;/p&gt;
&lt;p&gt;과장님은 어땠는데요? 과장님 스무 살 때요?&lt;/p&gt;
&lt;p&gt;나?&lt;/p&gt;
&lt;p&gt;가수 되고 싶었지.&lt;/p&gt;
&lt;p&gt;왜 안 하셨는데요?&lt;/p&gt;
&lt;p&gt;안 하긴. 못한거지.&lt;/p&gt;
&lt;p&gt;가수 별거 없어요. 인기 떨어지면 안 한 것만 못하지.&lt;/p&gt;
&lt;p&gt;꼭 해본 것처럼 말한다.&lt;/p&gt;
&lt;p&gt;아는 사람이 했어요. 가수.&lt;/p&gt;
&lt;p&gt;그래. 누군데?&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[cpp] 실수 랜덤 값 생성하기, 2001]]></title><description><![CDATA[C 표준 랜덤함수는 정수의 랜덤값만 생성합니다. 일반적으로 실수 랜덤값은 아래와 같은 나눗셈을 통해서 취득할수 있습니다. 아래 코드는 low에서 high…]]></description><link>https://jiniya.net/wp/archives/4972</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4972</guid><pubDate>Tue, 16 Jun 2015 23:59:21 GMT</pubDate><content:encoded>&lt;p&gt;C 표준 랜덤함수는 정수의 랜덤값만 생성합니다. 일반적으로 실수 랜덤값은 아래와 같은 나눗셈을 통해서 취득할수 있습니다. 아래 코드는 low에서 high사이의 실수 랜덤값을 생성하는 함수입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; low&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    d &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; RAND_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;low &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;high &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; low&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;참고로 한가지 더 적으면 터보씨에 있는 랜더마이즈(randomize)함수는 아래와 같은 매크로를 통해 동일하게 정의할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;randomize&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;srand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;실수 랜덤 값은 도대체 뭐에 쓸려고 생성한걸까? 사고 실험인가?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 10진수를 16진수로 변환하는 함수, 2002]]></title><description><![CDATA[직 로더를 만들면서 제작한 함수 중에 하나입니당. 테이블을 사용하면 깔끔하게 된다는 점이 돋보이는 소스 입니당. 그럼 다들 한번 찬찬히 뜯어 보세염. — 13년 지나서 보니 그다지 돋보이진 않는 것 같은데…]]></description><link>https://jiniya.net/wp/archives/4965</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4965</guid><pubDate>Tue, 16 Jun 2015 23:59:20 GMT</pubDate><content:encoded>&lt;p&gt;직 로더를 만들면서 제작한 함수 중에 하나입니당. 테이블을 사용하면 깔끔하게 된다는 점이 돋보이는 소스 입니당. 그럼 다들 한번 찬찬히 뜯어 보세염.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dec2hex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;4&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;5&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;6&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;7&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;8&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;9&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;C&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;D&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;E&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;F&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;d &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d &lt;span class=&quot;token operator&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token function&quot;&gt;ReverseStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;13년 지나서 보니 그다지 돋보이진 않는 것 같은데…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] freeaddrinfo 사용 시 주의해야 할 점]]></title><description><![CDATA[http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx The freeaddrinfo function was added to the Ws2_32.dll on Windows XP and later…]]></description><link>https://jiniya.net/wp/archives/4668</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4668</guid><pubDate>Tue, 16 Jun 2015 23:59:19 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The freeaddrinfo function was added to the Ws2_32.dll on Windows XP and later. To execute an application using this function on earlier versions of Windows (Windows 2000, Windows NT, and Windows Me/98/95), then you must include the Ws2tcpip.h file and also include the Wspiapi.h file.&lt;/p&gt;
&lt;p&gt;간단번역: freeaddrinfo는 Windows XP 이후에 추가 했으니, 그전 운영체제에서 사용하려면 ws2tcpip.h는 물론 wspiapi.h를 포함시키렴.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 다시보는 assert, 2002]]></title><description><![CDATA[다들 C언어를 처음 배울때 ASSERT…]]></description><link>https://jiniya.net/wp/archives/5014</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5014</guid><pubDate>Tue, 16 Jun 2015 23:59:18 GMT</pubDate><content:encoded>&lt;p&gt;다들 C언어를 처음 배울때 ASSERT라는 매크로를 배우게 된다.별로 의미없이 지나치게 되는 매크로의 하나인데, 사실 알고보면 저것 만큼 디버깅 시간을 줄여주는 매크로는 없다는 생각이 요즘 든다. 버그의 대부분의 근거는 함수 파라미터의 실수나 리턴값의 오류에 기인한다고 할 수 있다. 그런 버그를 원천 봉쇄할 수 있는 방법이 바로 위의 ASSERT 매크로를 사용하는 것이다. 예를 들어 아래 함수를 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next_char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 함수의 입력값으로는 NULL포인터가 절대로 들어가서는 안된다. 그런 에러를 원천 봉쇄 할 수 있는 방법이 바로 아래와 같은 방법이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next_char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token function&quot;&gt;ASSERT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 만약 위의 코드에 NULL값이 입력값으로 들어오면 함수는 동작하지 않고 프로그램은 오류메세지를 출력하면서 종료될 것이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 입력 버퍼에 관한 진상, 2001]]></title><description><![CDATA[그동안 잘못 알고 있었던 상식중에 입력버퍼에 관한 내용이 있어서 올려봅니다. 제 홈페이지를 통해서도 잘못 전파된 내용이 많을 것 같다는 생각이 드네염. 보통 scanf를 통해서 입력을 받을때 엔터 한번에 쭈루룩 다음 scanf…]]></description><link>https://jiniya.net/wp/archives/4940</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4940</guid><pubDate>Tue, 16 Jun 2015 23:59:17 GMT</pubDate><content:encoded>&lt;p&gt;그동안 잘못 알고 있었던 상식중에 입력버퍼에 관한 내용이 있어서 올려봅니다. 제 홈페이지를 통해서도 잘못 전파된 내용이 많을 것 같다는 생각이 드네염. 보통 scanf를 통해서 입력을 받을때 엔터 한번에 쭈루룩 다음 scanf함수까지 넘어가는 것을 본 적이 있을 겁니다. 그런 것들을 보면 보통 scanf하기전에 입력 버퍼를 비우기 위해서 fflush함수를 사용하라고 하는데, 이 fflush라는 놈이 표준안에 정의를 보면 표준 출력에 대해서만 정의되어 있고, 표준 입력에 대해서는 아무런 동작을 하지 않는다는 것입니다. 따라서 fflush(stdin)하는 것은 undefined behavior, 즉 정의되지 않은행동. 따라서 사용하지 말아야 할 행동입니다.&lt;/p&gt;
&lt;p&gt;그러면 scanf가 쭈루룩 넘어가는 진상은 과연 어디에 있는가? 입력 버퍼를 비우는 방법은 없는 것인가? 하는 두가지 의문이 드실 겁니다. 일단 첫번째 문제에 대해서 한번 살펴보도록하죠^&lt;/p&gt;
&lt;p&gt;scanf는 특성상 개행문자를 입력받지 않는다고 합니다. 따라서 \n을 입력버퍼에 그대로 남겨두게 되고, 다음 번 scanf가 그놈때문에 자동으로 넘어가는 현상이 생기게 되는 것입니다. 따라서 scanf다음에 getchar()등으로 개행문자를 소비해주는 입력함수를 넣어주면 그런 문제를 막을 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;scanf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그럼 두번째 질문인 입력버퍼에 대해서 알아보도록 하죠. 일반적으로 키보드의 입력 버퍼를 비우는 행동은 표준함수로 제공되지 않습니다. 따라서 그런 행동들은 운영체제나 컴파일러 제조사에 따라 다르다는 이야기입니다. 일반적으로 dos시절에는 아래 함수를 사용해서 입력 버퍼를 비울 수 있었습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;kbhit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;getch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 gcc를 사용하는 경우에는 stdio.h에 정의된 flushall함수를 사용해서 입력 버퍼를 비울 수 있습니다.&lt;/p&gt;
&lt;p&gt;일반적으로 scanf의 경우 입력받은 값이 잘못된 경우 이전 상태로 복원시키는 방법을 전혀 제공하지 않습니다. 따라서 보통의 경우 입력은 문자열로 fgets등을 통해서 입력받은후 sscanf내지는 자신이 직접 제작한 입력함수를 통해서 파싱해 내는 것이 일반적입니다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;참 내가 썼지만 깜찍했네 ㅋㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우8 취약점 완화 관련 API]]></title><description><![CDATA[윈도우 8하면 보통 현란하게 바뀐 시작 화면을 떠올린다. 인터넷을 접한 사람들은 시작 버튼이 없어졌다는 사실 또한 떠올릴 것이다. 그만큼 윈도우 8의 UI 변화는 많은 사람들에게 충격적이었다. 그 UI…]]></description><link>https://jiniya.net/wp/archives/10414</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10414</guid><pubDate>Tue, 16 Jun 2015 23:59:16 GMT</pubDate><content:encoded>&lt;p&gt;윈도우 8하면 보통 현란하게 바뀐 시작 화면을 떠올린다. 인터넷을 접한 사람들은 시작 버튼이 없어졌다는 사실 또한 떠올릴 것이다. 그만큼 윈도우 8의 UI 변화는 많은 사람들에게 충격적이었다. 그 UI 변화를 두고 호불호가 많이 나뉘기도 한다. 하지만 윈도우 8의 모든 변화가 단지 표면적으로 드러나는 앱 월드와 데스크톱 월드의 통합 내지는 UI 표현의 변화, 또는 사라진 시작 버튼에만 있는 것은 아니다. 우리에게 직접 나타나지 않는 내부에도 상당히 많은 변화가 있었다. 이런 내부의 경우 굉장히 혁신적인 변화임에도 관심을 가지고 살펴보지 않으면 잘 알기 힘든 부분이라 크게 평가되고 있지 못한 점이 안타깝다.&lt;/p&gt;
&lt;p&gt;윈도우 8은 내부에도 엄청난 변화가 있었다. 하지만 윈도우 8을 만든 개발자들은 비스타에서 충분히 많은 교훈을 얻었기 때문에 그 엄청난 변화를 우리가 직접 느낄 수 있도록 만들지는 않았다. 즉, 내부 구조의 변화도 겉으로 드러나는 표면적인 부분의 변화는 극히 제한적이라는 의미다. 하지만 상당히 많은 부분이 개선되었고 또 기존 것들과 충돌을 일으키지 않는 범위 내에서 실험적인 다양한 기능들이 추가되었다. 그런 변화 중에서도 보안과 관련되어 있으면서도 데스크톱 응용 프로그래머들이 알아두면 도움이 될 만한 UAC 정책 변화와 새롭게 추가된 프로세스 보안 정책에 대해서 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;사용자 계정 컨트롤(UAC) 정책 변경
사용자 계정 컨트롤은 윈도우 비스타부터 도입된 개념으로 프로그램이 관리자 권한이 필요한 작업을 수행할 때에 사용자에게 그 행위를 보고함으로써 위험한 작업이 은밀하게 발생하는 것을 방지하는 것을 의미한다. 원래 권한 개념이 크게 부각되지 않은 윈도우에서 그나마 택할 수 있는 정책이었지만 권한을 줬다가 다시 가져오는 작업은 그리 수월하지 않았다. UAC는 비스타를 가로막는 가장 강한 허들이 되었고, 그로 인해서 시장에서 비스타는 실패한 운영체제로 낙인 찍히게 되었다. 윈도우 7은 그런 교훈을 바탕으로 UAC를 좀 더 다듬어서 사용자를 덜 귀찮게 만들어서 내놓는 형태로 사용자와 타협했다.&lt;/p&gt;
&lt;p&gt;하지만 사실상 타협했다는 표현은 좀 어폐가 있다. 그도 그런 것이 거의 대부분의 윈도우 7 사용자는 UAC가 기본적으로 켜져 있음에도 굳이 옵션을 조정해서 UAC를 끈 상태로 운영체제를 사용하기 때문이다. 그래서 윈도우 8에서는 UAC 기능을 끄는 것과 관련해서 아주 미세하게 설정을 조율했다.&lt;/p&gt;
&lt;p&gt;기존의 윈도우 비스타와 윈도우 7에서는 사용자 계정 컨트롤을 가장 낮은 단계로 설정하는 경우에는 UAC가 없는 것과 동일하게 되었다. 즉, 가장 낮은 단계는 UAC를 끄는 것과 같은 맥락이었다. 하지만 윈도우 8부터는 더 이상 그런 상식이 통용되지 않는다.&lt;/p&gt;
&lt;p&gt;윈도우 8에서 사용자 계정 컨트롤을 가장 낮은 선택할 경우에 경고창은 출력되자 않지만 프로그램의 권한 컨트롤은 여전히 적용된다. 이 말이 무슨 의미냐 하면 기존의 윈도우의 경우 UAC가 가장 낮은 단계인 경우에는 오른쪽 버튼을 눌러서 관리자 권한으로 실행 메뉴를 전혀 사용할 필요가 없었다. 왜냐하면 매니페스트에 상관 없이 UAC가 꺼지면 모든 프로그램이 자동으로 관리자 권한으로 실행되었기 때문이다. 하지만 윈도우 8부터는 UAC가 가장 낮은 단계로 설정하더라도 여전히 관리자 권한으로 실행 메뉴를 사용해야 한다.&lt;/p&gt;
&lt;p&gt;이를 직접 확인해 보기 위해서는 UAC를 가장 낮은 단계로 설정한 다음 실행 메뉴를 통해서 명령창을 실행하고 관리자 권한을 필요로 하는 명령어를 입력해보면 알 수 있다. &amp;#x3C;화면 1&gt;나타난 것과 같이 권한이 없어서 명령어가 실패하는 것을 볼 수 있다. 이런 문제 때문에 윈도우 8의 탐색기에는 &amp;#x3C;화면 2&gt;에 나타난 것과 같이 관리자 권한으로 명령창을 실행하는 메뉴가 추가돼 있다. 이 메뉴를 통해서 관리자 권한으로 실행된 명령창에서 동일한 명령어를 입력하면 정상적으로 수행되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./윈도우8_취약점_완화_관련_API.md_0.png&apos; data-alt=&apos;화면 1 UAC가 꺼진 상태에서 관리자 권한이 필요한 작업을 수행하면 실패한다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8fe5a18944df70c347b26f3deb087c8a/3c503/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 65.26315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABQklEQVR42mNImnI6adbNpDn3kufeTZpzJ2nO3YRZN+MmnYmdeDq8+1hEz/HwnmMRvSfiZlyPn3kTiBJm3IiYeau+cv6UxsUMhi6R4iJCsnLysnJy4hIS8goKYuLi0tIy0jKyvGAgLCTMzsHBwMjIyMQEREzMzAxMzOwcnLXT1jGYuEUK8XMBtQkLCQkKCvDx8kqIi4mKCAsK8IsIC7GysjAxA/UxMsAAhM3GzNA2fTWDlW+iqBA/0B4RERFBQUF+fn4hISEBAQE+Pj4gm4uLiwEVQDSzszD2zNvEoG7px87CwMsHAqysrAyEAFxz99yNDHKGriAhJma4HATA1eHTLG/oBuQwMbNgVUqazUNFs7yhO9jPrMBEQAxiAlnDxMHK3D13E/k2983fyGAUWCyhYSmr7yyj50gkktZ1UDR0qpuzFwBfHVQmVoY0bwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 1 UAC가 꺼진 상태에서 관리자 권한이 필요한 작업을 수행하면 실패한다.&apos; title=&apos;&apos; src=&apos;/static/8fe5a18944df70c347b26f3deb087c8a/3c503/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_0.png&apos; srcset=&apos;/static/8fe5a18944df70c347b26f3deb087c8a/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_0.png 190w,
/static/8fe5a18944df70c347b26f3deb087c8a/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_0.png 380w,
/static/8fe5a18944df70c347b26f3deb087c8a/3c503/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_0.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 1 UAC가 꺼진 상태에서 관리자 권한이 필요한 작업을 수행하면 실패한다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./윈도우8_취약점_완화_관련_API.md_1.png&apos; data-alt=&apos;화면 2 탐색기에는 관리자 권한으로 명령창을 실행하는 메뉴가 생겼다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/89bcb0b446658d84dc93451ae02ee0b4/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 53.68421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB20lEQVR42nWRS2tTQRTH52P6JWJpshFcuBHcCm4quGsasGKSdaWUVtT4CIglaUwba9qb5ia59877PZPruQmCKA6/OcwM53/mPNC9F7NG6+JBd7XblfUO23mtnvf7Ly+6j45mu23d6Iqdw7zWTGqteb0t6h3ZaItaRz3e6z992EL3m8PDd5dSKsykUJYre3P7M89TTGmGKaaCS8VEBRfKOK+MBVuW8XQs0cfRQjJSEI4J1dYJ4/b3D6bTREA4jKWU683y3gshlFJGqxBCWbrBDUNP9l5NrsbaBkwYxC64f/+lt8oziFVgXBR4lWVZgbWx2hhKmdZ6XcKKHwYpan8jC8wJYTmmWUE2qUXYxjrAOl/hA5yhNMaYgFwqcdkbpuhsfCVpjgnX2viNk3M+xHWI0QMhBiCu4V0IySgFuxWfTzk66M3ni1xXbahUldgH0PzJVkwZz/OMUrrRlsNEo+an9C4n8befdeF/YmgJrX4W258HiULn12MlllwFZbx2ATontYPzX1RThJo5hynEbdq3Ck2WBvoeo11H42WWzb7Pri/xMlF0JckSEHgB12KZSJzSVcLzu2hFWdrRjKPmZ34yFm9/hLOJOx6pN0Oxgf/L0QCsAHs8lJ2v9NkJ/gXeCVh2schbEwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 2 탐색기에는 관리자 권한으로 명령창을 실행하는 메뉴가 생겼다.&apos; title=&apos;&apos; src=&apos;/static/89bcb0b446658d84dc93451ae02ee0b4/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_1.png&apos; srcset=&apos;/static/89bcb0b446658d84dc93451ae02ee0b4/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_1.png 190w,
/static/89bcb0b446658d84dc93451ae02ee0b4/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_1.png 380w,
/static/89bcb0b446658d84dc93451ae02ee0b4/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_1.png 760w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 2 탐색기에는 관리자 권한으로 명령창을 실행하는 메뉴가 생겼다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;UAC를 끄더라도 권한 컨트롤이 여전히 수행된다는 것은 프로그램을 그냥 실행시켰을 때 매니페스트에 관리자 권한을 요구하는 표시가 되어 있다면 경고창 없이 그 프로그램을 관리자 권한으로 실행시켜 주지만 그렇지 않은 경우에는 UAC가 가장 낮은 단계로 설정돼 있더라도 일반 권한으로 해당 프로그램을 실행시킨다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;UAC 설정은 HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System 경로에 있는 일부 키 값을 통해서 조정된다. 윈도우 8에서는 UAC에서 가장 낮은 단계를 선택하더라도 &amp;#x3C;화면 3&gt;에 나타난 것과 같이 EnableLUA 값이 0이 아닌 1로 설정돼 있는 것을 볼 수 있다. &amp;#x3C;표 1&gt;에는 사용자 계정 컨트롤 설정 값에 따른 UAC 관련 레지스트리 값의 변화가 나와 있다. 표를 살펴보면 다른 부분은 모두 같지만 가장 낮은 단계를 선택한 경우에는 EnableLUA 값이 달라진 것을 볼 수 있다. 이 값을 윈도우 7과 똑같이 조작하면 UAC가 완전히 꺼지도록 만들 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./윈도우8_취약점_완화_관련_API.md_2.png&apos; data-alt=&apos;화면 3 UAC 설정 관련 레지스트리 키&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/593a056b2924b229380cdcc0fe0ad2c1/8a72f/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 41.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABlUlEQVR42kWPWWvbQBRG/e/7B2pIk/SpT6VQ+lIolNiliRVD21iWHGubkTTWrllkrdZojZQW+nDh4zsc7r2LN19PyxVerunbFVmu2c0mf/9Y3myK65/J1V3wbh1e359vhfJ2LvOZCsWVUH78pn368GOhuWl3ycoizxlChmhDmDIyDm3fcYrDLKHj2NdlXmTn15DladI19ZS3ZrIA0WUcuqYdqtwz9T8QoiiK27YbhgHZnq4BjCmjzIRmVVV1Xaua5ofROI4bCb3KY9c0bdtULFZty05YMrFh6CHCNrQQNIIgUo7HKIw55+JePDneLMvOP5k3bddxEkjIsvt+GGe7N6zo8735IJ8SQlRVJZhyXkvyIYzwxJ8AWYBwPps3fX1hHpKAAQkmWZY3DVcM/8uDJRycM6XH5yOOySSL0t7zw0mWUPr/Z155rinaplWk57+bPR97tjUNiUJkAobjS5mbQKeUTHxv0sVq7ynQkQ1P1q3fsrpT0AG4z9CXdOeXDLY7bbtThSflcadOjWy4mh0Dl6GAfhf9FzCCq3Wof330AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 3 UAC 설정 관련 레지스트리 키&apos; title=&apos;&apos; src=&apos;/static/593a056b2924b229380cdcc0fe0ad2c1/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_2.png&apos; srcset=&apos;/static/593a056b2924b229380cdcc0fe0ad2c1/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_2.png 190w,
/static/593a056b2924b229380cdcc0fe0ad2c1/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_2.png 380w,
/static/593a056b2924b229380cdcc0fe0ad2c1/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_2.png 760w,
/static/593a056b2924b229380cdcc0fe0ad2c1/8a72f/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_2.png 780w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 3 UAC 설정 관련 레지스트리 키&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;표 1 UAC 설정에 따른 레지스트리 키 값&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;설정&lt;/td&gt;
&lt;td&gt;윈도우 7&lt;/td&gt;
&lt;td&gt;윈도우 8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;항상 알림&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 2&lt;br&gt;PromptOnSecureDesktop: 1&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 2&lt;br&gt;PromptOnSecureDesktop: 1&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;설정 변경 시에만 알림&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 5&lt;br&gt;PromptOnSecureDesktop: 1&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 5&lt;br&gt;PromptOnSecureDesktop: 1&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;설정 변경 시에 알림&lt;br&gt;화면 흐리게 하지 않음&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 5&lt;br&gt;PromptOnSecureDesktop: 0&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 5&lt;br&gt;PromptOnSecureDesktop: 0&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;알리지 않음&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 0&lt;br&gt;PromptOnSecureDesktop: 0&lt;br&gt;EnableLUA: 0&lt;/td&gt;
&lt;td&gt;ConsentPromptBehaviorAdmin: 0&lt;br&gt;PromptOnSecureDesktop: 0&lt;br&gt;EnableLUA: 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이 사소한 변화를 통해서 시작 버튼도 없애버린 마이크로소프트가 우리에게 얼마나 UAC를 강요하고 싶어하는지를 엿볼 수 있다고 생각한다. 보안을 생각했을 때 이런 변화가 결코 나쁜 변화는 아니다. 하지만 관리자 권한 매니페스트가 없는 프로그램을 자주 관리자 권한으로 실행해야 하는 사용자에게는 분명 예전보다는 불편해진 점이기도 하다. 이 때에는 프로그램의 호환성 속성을 사용하면 도움이 된다. &amp;#x3C;화면 4&gt;에 나타난 것과 같이 호환성 설정 부분에서 항상 관리자 권한으로 실행하도록 만들어주는 옵션을 선택하면 해당 프로그램은 매니페스트에 관리자 권한 요구 속성이 없어도 관리자 권한으로 실행시켜 준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./윈도우8_취약점_완화_관련_API.md_3.png&apos; data-alt=&apos;화면 4 항상 관리자 권한으로 실행하도록 설정&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 377px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c2dff0bf6dc5b7c42ecd2cfc6fdc16cc/fdd90/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 136.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAAsTAAALEwEAmpwYAAADrklEQVR42o1UW3PbVBDO32Tctwwdhj/ADH8DmpYZZkofeMCkQNIW2oeUh45jW7Yly5ZvshxLtqwjHV2O7ndLrGQISXGAnaP1eqXvnN39ds/JZ89Hj1/MT5vppz+Ep9+TxrNF4xnfOFt88vWk8ZR/9I0AuvFk3jibNc7m8MFpM/78O+Xy8RdPv/z25Ksr4w2Nf6SMlz3zZc84b6NmSz5vK83Wtnm9a17L5x31p47yM6X+0sMXNLlgnAvafk9rT96hk9cDTZwPWXqgawgr2+V8ihRZltYjpi+uhMmImYyGUeBlSZCEfhb7aeQHnlMm9tuhfvJmaMWBLe+QbpgYG5ZFYCmKquuGLO80bIATKWgrKxrGm+1uK+8s2yvL/LKnnbwd256lc5PFmJsww5GwXLGjcbdLzeY8TbNDdjydzgghpml5rkuIbZpmEEZlWb7qA3hE/CDoDBcMxw9GsxbFdpkpxXBdetyhufFC8sKkvC/7otKvBhXY8sOInknsbN0f8216ykxvuuyyyy56Y2G21ty4CJN9nO2Pg8M4vTEz5BYSyUVSSFY+RelcTZc4W6gJj8LRJhD1+Aj4V9Yqy0xYrThuwvPLjSQqSKu+2Bf7Wmr7nmQ5OIsaPARwrihIWAqiKAnCcjHnVVXbbKTJZCqs1pvN5mZ1E8cfnby/BWfAjQIPQrvdDmpr2zaov4xKg+R5fhScE+IYhmGahq7rQRCE/xDP8wBc1JJX6L/BewAHfggvYM+DPqRX3JFjOVcFSwVhBdXy/SCuJYqiQ6mKY3Ln5LraFiGGoWPoRgM61NKxDltkWXaI4liT3CnYdruTJFGSJFmWbcfxfN9xHCjV/wJbBCAgLjwQRWW5rue54E2S5GFwnbOqYbMKmByIgchrfgjGGPaBaqdp+tDJuR+GBzIty6xHx6p4tqt4IATYAvRt/T6iKjeJ43m+53pJXAd5P1NI/F+oynhegNmF0ZWkDUwshA0KGgbOhN6pGd8fo6o+2XH9KlSLaKq2UxTIH2MdIQQ9i5D6Xzzbju/7SZpUctDwm6YHqh+YKlyDs6jLDjpUp0f1KKrfbrcHA4ahGapLAfW383Bknl8zJoA9HzoyDsMI7qdah3GcVAb8j2IIAIIAAxb4wVHm8SXcYe9GZhkT3yWBS0KPRL7tEt3EiJ9xmiITQ9ORPB0PZxxrYeRCE4N3Ixah+RtcvS9aJieRnkAGqz8XxRvXU/V3RmpNUGeOwb4arK/66/ZM6y1N0B84hROt5x/wHyKYwG0NK7BAAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 4 항상 관리자 권한으로 실행하도록 설정&apos; title=&apos;&apos; src=&apos;/static/c2dff0bf6dc5b7c42ecd2cfc6fdc16cc/fdd90/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_3.png&apos; srcset=&apos;/static/c2dff0bf6dc5b7c42ecd2cfc6fdc16cc/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_3.png 190w,
/static/c2dff0bf6dc5b7c42ecd2cfc6fdc16cc/fdd90/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_3.png 377w&apos; sizes=&apos;(max-width: 377px) 100vw, 377px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 4 항상 관리자 권한으로 실행하도록 설정&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;우리가 만드는 프로그램도 사용자가 알아서 저렇게 설정해 주기를 원할 수 있지만 사용자 친화적인 프로그램이라면 이러한 설정을 메뉴를 통해서 옵션으로 제공하는 것도 나쁘지 않다. 프로그램으로 해당 옵션을 조정하는 방법은 간단한 레지스트리 조작으로 할 수 있다. 호환성 플래그를 설정하는 레지스트리 키는 아래 경로를 살펴보면 된다. 해당 경로를 이동하면 &amp;#x3C;화면 5&gt;에 나타난 것과 같이 호환성이 설정된 프로그램의 목록이 나타난다. 키 값은 해당 프로그램의 경로가 되고, 데이터는 설정된 값을 나타낸다. 관리자 권한으로 실행을 하기 위해서는 RUNASADMIN이라는 문자열을 추가해 주면 된다.&lt;/p&gt;
&lt;p&gt;HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers&lt;/p&gt;
&lt;p&gt;HKLM\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;윈도우8_취약점_완화_관련_API.md_4.png&apos; data-alt=&apos;화면 5 항상 관리자 권한으로 실행 기능이 켜진 프로그램의 AppCompatFlags 레지스트리 값&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 649px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/37c542521605041ccac85203f5f57941/1bcec/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 35.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABd0lEQVR42iWNS0/bQBSF/Xu7bAoItv0HXaNW4rlALU0JSViwAUJAJIiHzWQc2/Ejtic2juOxPZ4ZJzHjIn26+s6Rjq705WiycRpv/k2+ncaN33PhW0283co3TvyvR5PGsbn5J9xpZYLts7S+zaTRxLs/2j+/70lXT2Cia1DVURD4aKYbluvNCsbTnAgyASlwmi9wmmb5PE4IZWle0OWqb2DpSXeSQHFsJ46igpCZ59oqCAO0KtmS05LTZcnzPDMNg1E6dRzkI0JIVVWv1kJSprQknmMOgQI1zUCuC17BQNZfoPUoa0NZk6H5HoTaWCso1dUxHEHGy3psY0lxOcsMdfRgTxHj3A+if8/JwZAcDrODQfbrPm0pOWcMzUKxWSTY81D4Hovxi4WlZxPzzB5DYFtWFAbzebSu1lWNOJ+yqj4bEde1r+pefE6k/Uv1ogfOruX2jdLuvZ3fKJ1b0OmBbn8k5OIOCrpC/sduH5xfK53+aAD9k1vrAzLIam9Iww/OAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 5 항상 관리자 권한으로 실행 기능이 켜진 프로그램의 AppCompatFlags 레지스트리 값&apos; title=&apos;&apos; src=&apos;/static/37c542521605041ccac85203f5f57941/1bcec/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_4.png&apos; srcset=&apos;/static/37c542521605041ccac85203f5f57941/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_4.png 190w,
/static/37c542521605041ccac85203f5f57941/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_4.png 380w,
/static/37c542521605041ccac85203f5f57941/1bcec/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_4.png 649w&apos; sizes=&apos;(max-width: 649px) 100vw, 649px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 5 항상 관리자 권한으로 실행 기능이 켜진 프로그램의 AppCompatFlags 레지스트리 값&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;취약점 완화 방안
예전에 스타크래프트란 게임을 한창 즐기던 시절 게임 잡지에 “스타크래프트 상에서 최고의 수비는 상대를 공격하는 것”이란 기사가 실린 것을 본 적이 있다. 그 당시만 해도 우주방어테란만 고집했던 터라 내심 그 기사를 좀 무시했었다. 하지만 이후 임요환 선수가 등장하면서 모든 것이 달라졌다. 고질적으로 공격이 느리던 테란의 단점을 드랍쉽으로 커버하면서 정말 최고의 수비는 방어가 아닌 공격에서 나온다는 것을 온몸으로 보여줬기 때문이었다. 시시한 게임 이야기라고 생각하면 오산이다. 이 전략은 게임 속뿐만 아니라 현실 세계에서도 얼마든지 통용되는 전략이기 때문이다.&lt;/p&gt;
&lt;p&gt;모든 프로그래머들은 버그가 없는 프로그램, 보안 취약성이 없는 프로그램을 만들고 싶어한다. 하지만 안타깝게도 현대 프로그램은 그 규모와 복잡도가 너무나 커져 버려서 사실상 그런 프로그램을 만든다는 것은 거의 불가능에 가까워졌다고 할 수 있다. 매일같이 보고되는 수많은 취약점, 제로데이 공격들이 그 근거라고 할 수 있겠다. 이러한 이슈가 발생할 때 마다 프로그래머는 빠르게 관련 문제를 수정하지만 수정한 것을 배포할 때쯤엔 또 다른 버그와 취약점이 기다리고 있다. 이미 속도에서 경쟁이 안 되는 상태가 돼 버린 것이다.&lt;/p&gt;
&lt;p&gt;그래서 임요환 선수같이 똑똑한 프로그래머들이 조금 다른 생각을 하기 시작했다. “왜 우리만 항상 이렇게 당해야 하지? 우리도 똑같이 해커를 공격할 방법은 없는 것일까?”라는 생각에서 출발한 전략이 바로 취약점 완화 방안이다. 이 방법의 전략은 단순하다. 어차피 늘 상 있는 버그, 취약점은 인정하겠다는 것이다. 하지만 그런 것들을 알고 있는 해커라고 하더라도 그걸 공격하는 코드를 만드는 것은 어렵도록 만들겠다는 취지다. 그래서 모든 취약점 완화 방안은 근본적인 대책은 아니다. 하지만 이런 사소한 것들이 여러 개 모이면 공격자 입장에서는 다양한 환경에서 항상 정상적으로 동작하는 코드를 만드는 일이 예전보다 훨씬 어려워지기 때문에 공격의 속도가 늦어지고 악성 코드를 만드는 데에 더 많은 비용이 투입되도록 만드는 장점이 있다.&lt;/p&gt;
&lt;p&gt;시스템 프로그래머가 아니라면 이러한 방법이 있었다는 것을 모르는 경우가 많지만 사실 윈도우가 취약점 완화 기능을 만들기 시작한지는 제법 오래됐다. 많이 알려진 기능으로는 2002년에 처음 소개된 VIsual C++의 /GS 기능이 있다. 이 기능을 사용하면 스택 오버플로 공격을 통해서 임의의 코드를 실행하는 것을 억제할 수 있다. 2003년에는 SafeSEH라는 기능이 개발됐다. 이미지에 기록된 예외처리 핸들러만 실행하도록 운영체제에서 제한한 것이다. 2004년에는 데이터 실행 방지(DEP) 개념이 소개됐다. 이 기능은 프로그램 내의 스택과 힙과 같은 영역에서 코드가 실행될 수 있는 것을 제한한 기능이다. 윈도우 비스타가 출시되던 2006년에는 주소 공간 배치를 랜덤화 하는 ASLR이라는 기술이 소개됐다. 이 기술은 /DYNAMICBASE 플래그가 지정된 DLL의 로드 주소를 랜덤하게 결정하는 기술이다. 이 기술과 함께 윈도우 핵심 DLL들은 모두 이 플래그를 사용하도록 변경됐기 때문에 윈도우 비스타 이후에는 주소가 하드 코딩된 형태로 시스템을 공격하는 코드는 더 이상 동작하지 않게 되었다. 윈도우 8에는 이런 기존의 취약점 완화 기능들을 보다 향상시키는 한편 새로운 취약점 완화 기능들이 대거 추가했다. 새롭게 추가된 기능에 대해서 하나씩 살펴보도록 하자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
이 정책이 적용된 프로세스는 로드되는 모든 DLL에 대해서 강제로 주소 공간 배치 랜덤화(ASLR) 기능을 적용한다. /DYNAMICBASE가 지정되지 않은 구형 DLL 또한 강제로 랜덤한 주소에 로드하도록 만든다는 의미다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON_REQ_RELOCS&lt;/strong&gt;&lt;br&gt;
이 정책은 앞서 설명한 강제로 ASLR을 적용하는 것에 더불어 재배치 정보가 없어서 랜덤한 주소에 로드할 수 없는 모듈의 경우에는 DLL의 로드를 실패 처리한다. 이 정책이 지정된 프로세스에는 재배치 정보가 포함되지 않은 DLL은 아예 로드 자체가 불가능해진다는 의미다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_HEAP_TERMINATE_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
이 정책이 지정되면 힙이 손상되는 경우에는 자동으로 해당 힙을 파괴한다. 힙 오버플로나 힙의 메타 정보를 사용한 공격이 발생하는 과정에서 공격자 코드의 결함으로 힙의 정보가 손상되는 경우에는 해당 힙을 바로 파괴해 버리도록 만든다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
스택을 포함한 bottom-up 할당기가 적용되는 메모리 할당에 ASLR을 적용한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
bottom-up 할당기의 할당 범위를 1테라 바이트 주소 공간까지 확장한다. 네이티브 64비트 프로그램에만 적용된다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
잘못된 핸들을 사용하는 경우에 즉시 예외가 발생한다. 이 플래그가 설정되지 않은 프로세스에서는 실패 값이 반환된다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
win32 서브시스템과 관련된 코드는 유저 모드와 커널 모드에 모두 코드가 존재하면서 상호 정보를 교환하기 때문에 윈도우 구조상 가장 취약한 부분이라고 할 수 있다. 이 정책이 적용된 프로세스는 win32 서브시스템과 관련된 API 호출이 원천적으로 봉쇄된다. 이 말은 쉽게 말하면 user32.dll에 있는 API를 호출할 수 없도록 만드는 옵션이라고 생각하면 된다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON&lt;/strong&gt;&lt;br&gt;
높은 수준의 보안성을 유지해야 하는 프로그램에 있어서 AppInit이나 윈도우 훅과 같은 알려진 시스템 루트를 통한 침투는 굉장히 취약한 부분이다. 이러한 기능은 일반적인 프로그램에서도 많이 사용하기 때문에 악의적인 목적의 공격인지를 판단하는 것이 더욱 어렵다. 이 정책이 적용된 프로세스는 이러한 알려진 시스템 루트를 통해서 DLL이 로딩되는 것을 원천적으로 차단된다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;프로세스 취약점 완화 정책 설정&lt;/h3&gt;
&lt;p&gt;윈도우 8에서 추가된 다양한 취약점 완화 정책들을 살펴보았다. 그렇다면 도대체 이 정책들은 어떻게 설정할 수 있는 것일까? 윈도우 8에서는 그런 목적을 위해서 2개의 함수가 추가됐다. 취약점 완화 정책을 설정하기 위해서 SetProcessMitigationPolicy, 취약점 완화 정책을 조회하기 위해서 GetProcessMitigationPolicy 함수가 추가됐다. 각 함수의 원형은 &amp;#x3C;리스트 1&gt;에 나와 있는 것과 같다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 SetProcessMitigationPolicy/GetProcessMitigationPolicy 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;SetProcessMitigationPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
PROCESS_MITIGATION_POLICY MitigationPolicy
&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID lpBuffer
&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T dwLength
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;GetProcessMitigationPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    HANDLE hProcess
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PROCESS_MITIGATION_POLICY MitigationPolicy
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID lpBuffer
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T dwLength
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수 사용방법은 간단하다. SetProcessMitigationPolicy의 경우 현재 프로세스에 대해서만 적용되며, GetProcessMitigationPolicy 함수의 경우에는 첫 번째 인자로 넘어간 프로세스의 정책을 구한다. MitigationPolicy에는 &amp;#x3C;표 2&gt;에 나타난 것과 같은 상수 각을 사용할 수 있다. buffer에는 MitigationPolicy에 지정한 상수에 맞는 구조체의 포인터를, dwLength에는 해당 구조체의 크기를 넘겨주면 된다.&lt;/p&gt;
&lt;p&gt;표 2 MitigationPolicy 값&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MitigationPolicy 값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ProcessDEPPolicy&lt;/td&gt;
&lt;td&gt;데이터 실행 방지(DEP) 정책을 설정한다.&lt;br&gt;buffer에는 PROCESS_MITIGATION_DEP_POLICY 구조체 포인터를 전달한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ProcessASLRPolicy&lt;/td&gt;
&lt;td&gt;주소 공간 배치 랜덤화 정책을 설정한다.&lt;br&gt;buffer에는 PROCESS_MITIGATION_ASLR_POLICY 구조체 포인터를 전달한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ProcessStrictHandleCheckPolicy&lt;/td&gt;
&lt;td&gt;엄격한 핸들 체크 정책을 설정한다.&lt;br&gt;buffer에는 PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY 구조체 포인터를 전달한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ProcessSystemCallDisablePolicy&lt;/td&gt;
&lt;td&gt;시스템 호출 금지 정책을 설정한다.&lt;br&gt;buffer에는 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY 구조체 포인터를 전달한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ProcessExtensionPointDisablePolicy&lt;/td&gt;
&lt;td&gt;프로세스 확장 포인트 금지 정책을 설정한다.&lt;br&gt;buffer에는 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY 구조체 포인터를 전달한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;#x3C;리스트 2&gt;에는 ProcessStrictHandleCheckPolicy 정책을 구하고 설정하는 예제가 나와 있다. 프로그램을 살펴보면 첫 번째 VirtualAllocEx는 ProcessStrictHandleCheckPolicy 정책이 설정되기 전에 호출되었기 때문에 일반적인 호출과 같이 함수 실패로 처리된다. 하지만 두 번째 VirtualAllocEx의 경우에는 해당 정책이 설정된 다음에 잘못된 핸들을 사용해서 호출하고 있기 때문에 예외가 발생해서 프로그램이 크래시 되도록 만든다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON 테스트&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/mitigation1.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;_WIN32_WINNT&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;0x0602&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Windows.h&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE process &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x4444&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;VirtualAllocEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_COMMIT &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; MEM_RESERVE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;First VirtualAllocEx Call\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY splc1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetProcessMitigationPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ProcessStrictHandleCheckPolicy
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;splc1
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;splc1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DisallowWin32kSystemCalls: %d\n&quot;&lt;/span&gt;
                 &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; splc1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RaiseExceptionOnInvalidHandleReference&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY splc2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    splc2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RaiseExceptionOnInvalidHandleReference &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    splc2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HandleExceptionsPermanentlyEnabled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetProcessMitigationPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ProcessStrictHandleCheckPolicy
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;splc2
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;splc2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SetProcessMitigationPolicy fail %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY splc3&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetProcessMitigationPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ProcessStrictHandleCheckPolicy
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;splc3
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;splc3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DisallowWin32kSystemCalls: %d\n&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; splc3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RaiseExceptionOnInvalidHandleReference&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;VirtualAllocEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_COMMIT &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; MEM_RESERVE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Second VirtualAllocEx Call\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 2&gt;의 예를 살펴보면 프로그램이 정책을 설정하기 전에는 여전히 해당 정책으로 금지하려는 동작이 수행 가능한 것을 알 수 있다. 이를 보면 당연히 공격자 입장에서 정책이 설정되기 직전에 공격을 한다면 타이밍 공격이 가능하다는 것을 알 수 있다. 더불어 앞서 살펴보았던 정책 중에 ASLR과 같은 것들은 주소 공간의 변화에 대한 것들이라 프로그램이 실행된 이후에 설정하는 것은 아무 의미가 없다. 왜냐하면 이미 프로그램이 실행됐다는 것은 프로그램 실행에 필요한 DLL이 거의 다 로드됐다는 의미이기 때문이다. 따라서 사실상 이런 정책은 앞서 소개한 API를 통해서 설정하는 것 보다는 프로세스 생성시에 지정하는 것이 가장 큰 효과를 가질 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 3&gt;에는 프로세스 생성 시에 정책을 설정하는 것을 보여주고 있다. 실행하면 PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON 정책을 설정한 다음 파라미터를 추가해서 자기 자신을 다시 실행한다. 다시 실행되면 if문의 코드는 수행되지 않고 뒤쪽의 현재 정책을 출력하고 user32.dll을 로드하는 코드가 수행된다. 이 경우에는 시작 시점에 이미 win32k 시스템 호출 금지 정책이 적용됐기 때문에 user32.dll의 로드가 실패해서 모듈 주소가 0으로 출력되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON 정책 테스트&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/mitigation2.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        STARTUPINFOEXW si &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        PROCESS_INFORMATION pi&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        WCHAR cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;StringCbPrintfW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;\&quot;%s\&quot; dummy_args&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        UCHAR buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        LPPROC_THREAD_ATTRIBUTE_LIST attr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPPROC_THREAD_ATTRIBUTE_LIST&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        SIZE_T size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;InitializeProcThreadAttributeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; ERROR_INSUFFICIENT_BUFFER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        attr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPPROC_THREAD_ATTRIBUTE_LIST&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; UCHAR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;InitializeProcThreadAttributeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        ULONG policy 
        &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;UpdateProcThreadAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attr
                                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
                                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
                                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;policy
                                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;policy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;DeleteProcThreadAttributeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        si&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StartupInfo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;si&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        si&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lpAttributeList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; attr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CreateProcessW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmd
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EXTENDED_STARTUPINFO_PRESENT
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;si&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StartupInfo
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;pi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;DeleteProcThreadAttributeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hProcess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;DeleteProcThreadAttributeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY plc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetProcessMitigationPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ProcessSystemCallDisablePolicy
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;plc
                                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;plc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DisallowWin32kSystemCalls: %d\n&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; plc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DisallowWin32kSystemCalls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user32.dll =&gt; %p\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;user32.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 3&gt;의 코드에 MessageBoxW와 같은 win32 서브시스템을 사용하는 함수를 정적으로 호출하는 코드를 추가한 다음 프로그램을 다시 실행하면 &amp;#x3C;화면 6&gt;에 나타난 것과 같이 정상적으로 응용 프로그램을 시작할 수 없다는 메시지가 출력되고 프로그램이 실행되지 않는다. 이는 해당 함수가 정적으로 바인딩 됐기 때문에 운영체제 로더가 user32.dll을 로드해야 하는데 그 또한 정상적으로 수행할 수 없기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./윈도우8_취약점_완화_관련_API.md_5.png&apos; data-alt=&apos;화면 6 응용 프로그램 시작 실패 메시지&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 490px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/aded2bbc8fb82f47219d11a87b3eea17/ce5c5/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 35.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABR0lEQVR42oXLzUrDQBAH8LyntnqoeQGfwCcQPEi19CTYKqIgXhSqqMWWIrYU0ybNVz/SJJtNSPqRZnebZN024MWDw4/hP8MMx1/N+OqCr8wOqnOmcOnnS9puUcqX9L3yeOe0lyuKLOfO1cL2hq8E+zfk5Oi6fHjM3XVW8pwKfipBOvDowE1FEPcsImSmkWAiFtim76QZAaQKiG8/A64NaPTVnL7UDDCRpK6qieORapojyxp7LoDQhtCyLcOa6OZEg44JgOE4JqW0pYdc26Fus67Xnk3PVYe6Nhqy7vk+IgRvsYAwRpvC2SbCZPOshVxDWVKa4jiJE1ZpnKSsr9cJwusMJpmYYeMK4VVEaEzqUsA1ZZ+iIJz70TL4hcLZXyRa+K5tjJS+0IWG8tCQuYu63RCd12/nTfjHew/WOlP2c/8hP7WUs0f1B8VLa/dkvwf0AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 6 응용 프로그램 시작 실패 메시지&apos; title=&apos;&apos; src=&apos;/static/aded2bbc8fb82f47219d11a87b3eea17/ce5c5/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_5.png&apos; srcset=&apos;/static/aded2bbc8fb82f47219d11a87b3eea17/08678/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_5.png 190w,
/static/aded2bbc8fb82f47219d11a87b3eea17/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_5.png 380w,
/static/aded2bbc8fb82f47219d11a87b3eea17/ce5c5/%EC%9C%88%EB%8F%84%EC%9A%B08_%EC%B7%A8%EC%95%BD%EC%A0%90_%EC%99%84%ED%99%94_%EA%B4%80%EB%A0%A8_API.md_5.png 490w&apos; sizes=&apos;(max-width: 490px) 100vw, 490px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 6 응용 프로그램 시작 실패 메시지&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우 찾기]]></title><description><![CDATA[FindWindow 함수는 탑레벨 윈도우 중에서 원하는 윈도우를 찾는 기능을 한다. 탑레벨 윈도우란 desktop 윈도우를 부모로 갖는 윈도우를 말한다. 첫 번째 인자에는 찾고자 하는 윈도우의 클래스 이름을 넣어주면 된다. NULL…]]></description><link>https://jiniya.net/wp/archives/4363</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4363</guid><pubDate>Tue, 16 Jun 2015 23:59:15 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;FindWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCTSTR lpClassName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR lpWindowName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;FindWindow 함수는 탑레벨 윈도우 중에서 원하는 윈도우를 찾는 기능을 한다. 탑레벨 윈도우란 desktop 윈도우를 부모로 갖는 윈도우를 말한다. 첫 번째 인자에는 찾고자 하는 윈도우의 클래스 이름을 넣어주면 된다. NULL을 지정할 경우에는 윈도우를 찾을 때 클래스 이름은 무시하고 찾는다. 두 번째 인자로 찾고자 하는 윈도우의 윈도우 이름을 넣어준다. 첫 번째 인자와 마찬가지로 NULL을 넣을 경우 이 항목은 무시된다. 윈도우의 핸들이 리턴 된다. 윈도우가 없다면 NULL이 리턴 된다. FindWindow(“#32770″, “TEST”)와 같이 사용할 경우 클래스 이름이 #32770이고 캡션이 TEST인 윈도우를 찾는다. FindWindow(“#32770″, NULL)과 같이 사용할 경우엔 캡션에 관계없이 클래스 이름이 #32770인 윈도우를 찾는다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwndParent
                  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HWND hwndChildAfter
                  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR lpszClass
                  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR lpszWindow&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;FindWindowEx는 특정 윈도우의 자식 윈도우 중에서 원하는 윈도우를 찾아준다. 첫 번째 인자로 찾고자 하는 윈도우의 부모 핸들을 넣어준다. 만약 NULL을 넣게 되면 FindWindow와 마찬가지로 Top 윈도우를 찾는다. 두 번째 인자로 검색 시작이 될 자식 윈도우를 넣어준다. 일반적으로 윈도우는 많은 자식 윈도우를 가지고 있다. 그 중에서 특정 자식 윈도우 다음부터 검사하고 싶은 경우 이 인자를 사용하면 된다. NULL을 지정할 경우 처음부터 검사한다. 세 번째, 네 번째 인자는 FindWindow의 인자와 같은 의미를 가진다. 리턴 값도 FindWindow와 동일하다. 아래 코드는 위에서 찾은 다이알로그의 자식 중에 확인 버튼을 찾는 것을 보여준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND hwnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;32770&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;TEST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
HWND button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;BUTTON&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;확인&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 두 함수 외에도 직접적으로 윈도우를 찾는 함수는 아니지만 도움이 되는 함수가 있다. GetNextWindow와 GetWindow가 그것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetNextWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hWnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT wCmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;GetNextWindow는 z-order 상에서 다음에 있는 윈도우나 이전에 있는 윈도우를 찾는 기능을 한다. 첫 번째 인자로 검색 대상이 될 윈도우를 넣어주면 된다. 두 번째 인자는 GW_HWNDNEXT나 GW_HWNDPREV중에 하나를 넣으면 된다. GW_HWNDNEXT를 넣을 경우 z-order 상에서 다음에 존재하는 윈도우를 리턴 하고, GW_HWNDPREV를 넣을 경우 z-order 상에서 이전에 존재하는 윈도우를 리턴 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hWnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT uCmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;GetWindow는 대상 윈도우로부터 특정한 관계에 있는 윈도우를 찾는 기능을 한다. GetNextWindow의 일반화된 버전이라고 생각할 수 있다. 첫 번째 인자로는 대상이 되는 윈도우를 넣으면 된다. 두 번째 인자로는 다음 목록에 있는 것 중에 하나를 넣어주면 된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;GW_CHILD&lt;br&gt;
대상 윈도우의 자식 중에서 z-order가 가장 위에 있는 윈도우를 리턴 한다. 만약 대상 윈도우의 자식이 없다면 NULL을 리턴 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GW_ENABLEDPOPUP&lt;br&gt;
Windows 2000/XP이상에 적용되는 값이다. 대상 윈도우 다음윈도우 중에서 팝업 윈도우를 찾아서 리턴 한다. 팝업 윈도우가 없는 경우엔 NULL을 리턴 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GW_HWNDFIRST&lt;br&gt;
같은 계층의 윈도우 중에서 가장 높은 z-order를 가지는 윈도우를 리턴 한다. 만약 대상 윈도우가 Top 레벨 윈도우라면 Top 레벨 윈도우 중에서 가장 높은 z-order를 가지는 윈도우를 리턴 한다. 만약 대상 윈도우가 자식 윈도우라면 형제 윈도우 중에서 가장 높은 z-order를 가지는 윈도우를 리턴 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GW_HWNDLAST&lt;br&gt;
같은 계층의 윈도우 중에서 가장 낮은 z-order를 가지는 윈도우를 리턴 한다. 만약 대상 윈도우가 Top 레벨 윈도우라면 Top 레벨 윈도우 중에서 가장 낮은 z-order를 가지는 윈도우를 리턴 한다. 만약 대상 윈도우가 자식 윈도우라면 형제 윈도우 중에서 가장 낮은 z-order를 가지는 윈도우를 리턴 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GW_HWNDNEXT&lt;br&gt;
대상 윈도우의 다음 z-order를 가지는 윈도우를 리턴 한다. GetNextWindow의 두 번째 인자에 사용되는 의미와 동일하다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GW_HWNDPREV&lt;br&gt;
대상 윈도우의 이전 z-order를 가지는 윈도우를 리턴 한다. GetNextWindow의 두 번째 인자에 사용되는 의미와 동일하다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GW_OWNER&lt;br&gt;
대상 윈도우의 소유자 윈도우를 리턴 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetDesktopWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Desktop 윈도우를 구하는 함수다. 모든 Top 레벨 윈도우는 이 윈도우의 자식이다. 또한 Spy++에서 가장 위에 표시되는 윈도우 이기도 하다. 인자는 없고 리턴 값이 Desktop 윈도우 핸들이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetShellWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Shell 윈도우를 구하는 함수다. Shell 윈도우는 작업 표시줄 윈도우를 말한다. 인자는 없고 리턴 값은 Shell 윈도우 핸들이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetForegroundWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Foreground 윈도우 핸들을 구하는 함수다. Foreground 윈도우란 사용자와 상호 작용을 하고 있는 윈도우를 말한다. Windows가 멀티태스킹 시스템 이지만 사용자와 상호 작용을 하는 윈도우는 하나밖에 없다. 인자는 없고 리턴 값이 foreground 윈도우 핸들이다. Foreground 윈도우가 없는 경우 NULL을 리턴 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetParent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hWnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;부모 윈도우를 구해주는 함수다. 인자로 대상 윈도우 핸들을 넣어주면 부모 윈도우 핸들을 리턴 한다. 만약 대상 윈도우가 top 레벨 윈도우 이거나 함수 수행에 실패한 경우 NULL을 리턴 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetTopWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hWnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 자식 윈도우(자식 윈도우 중에서 z-order가 가장 높은 것)를 구하는 함수다. 인자로 윈도우 핸들을 넣어주면 첫 번째 자식 윈도우를 리턴 한다. 자식이 없거나 동작이 실패한 경우 NULL을 리턴 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HWND &lt;span class=&quot;token function&quot;&gt;GetAncestor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT gaFlags&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;조상 윈도우를 구하는 함수다. 첫 번째 인자로 윈도우 핸들을, 두 번째 인자로 다음 목록에 있는 값 중에 하나를 넣어주면 된다. 리턴 값은 첫 번째 인자로 전달된 윈도우에 대한 조상 윈도우 핸들이다. 전달된 윈도우가 탑 레벨 윈도우일 경우 NULL이 리턴 된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GA_PARENT&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;부모 윈도우를 리턴 한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GA_ROOT&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;최 상단 부모 윈도우를 리턴 한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GA_ROOTOWNER&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;최 상단 부모 윈도우를 소유한 윈도우를 리턴 한다.&lt;/p&gt;
&lt;p&gt;끝으로 앞서 배운 함수를 통해서 특정 윈도우의 하위에 존재하는 모든 윈도우를 열거하는 방법을 알아보자. GetWindow 함수와 재귀 호출 함수를 사용하면 손쉽게 구현할 수 있다. 아래 이렇게 구현해 본 ScrabWindow 함수가 있으니 참고해 보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;모든 자식 윈도우를 수집하는 ScrabWindow 함수&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/scrabwindow.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BOOL&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CALLBACK &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ScrabWindowCallback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL
&lt;span class=&quot;token function&quot;&gt;ScrabWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ScrabWindowCallback cb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	HWND c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; GW_CHILD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; GW_HWNDNEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ScrabWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

BOOL
CALLBACK
&lt;span class=&quot;token function&quot;&gt;PrintWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%08x\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hwnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;ScrabWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetDesktopWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PrintWindow&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[cpp] 초간단 암호화, 2001]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4975</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4975</guid><pubDate>Tue, 16 Jun 2015 23:59:14 GMT</pubDate><content:encoded>&lt;p&gt;자신의 데이터에 어떤 기준으로 락을 걸고 싶을때가 있습니다. 하지만 막상 금방 코드를 작성하려면 방법이 잘 떠오르지 않는것이 이런 암호와 관련된 것들이죠. 몇가지 간단한 방법들을 여기서 소개해 드리도록 하겠습니다. 실질적으로 높은 수준의 보안을 유지할 수는 없는 방법들입니다. 간단하고 이해하기 쉬우며 암호의 원리를 알아보도록 하죠.&lt;/p&gt;
&lt;p&gt;암호는 기본적으로 상대방과 나와의 약속입니다. “내가 이렇게 원래 데이터를 바꿀테니 너는 이러이러케해서 원본데이터를 봐라”라고 하는 것들이 암호의 핵심입니다. 그런데 요즘 비번같은 암호의 경우는 비복원 방식을 사용하는 경우가 대부분입니다. 비복원이라는 말은 데이터가 암호와만 되고 역으로 추출해 내기는 힘들다는 이야기 입니다. 즉 abc가 zdsalkfj223으로 바뀌었을때, 이 바뀐 zds…이 abc로 돌아올 수는 없다는 이야기입니다. 반대로 복원 가능한 암호는 암호화 된 데이터로부터 원본 데이터를 그대로 복원해 낼 수 있습니다.&lt;/p&gt;
&lt;p&gt;가장 간단한 암호와 기법으로는 고전적인 방식의 시저 암호가 있습니다. 즉 데이터를 상대방과 약속을 하고 일정한 수를 가감하거나 가산하는 방식을 말합니다. a=&gt;b가 되면, c=&gt;d가 되는 식입니다.. 코드의 구현은 아주 간단하겠죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;SEED&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Encrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
       &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; SEED&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Decrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
       &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; SEED&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음으로는 더욱 간단한 방법으로 암호라고 하기는 힘들지만 데이터를 반전시키는 방법을 사용할 수 있습니다. 이런 경우의 암호는 주로 텍스트 파일 등을 에디터로 봐서는 보기 힘들게 하는 정도의 보안 수준에 사용하면 좋겠죠. 암호화와 복원이 한 함수로 이루어 집니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;EncDecrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
       &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;끝으로는 사용자가 지정한 패스워드에 기반한 암호 알고리즘입니다. 소스 설명은 생략하도록 하겠습니다. 간단해서 보시면 금방 아! 하실수 있을것 같네염. 위 홤수와 마찬가지로 암호화와 복원이 한 함수로 이루어 지며, pwd에는 비번을 입력해 주시면 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;EncDecrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pwd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token comment&quot;&gt;// 아래 맵은 256개의 문자로 초기화 시켜 주시면 됩니다... &lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;acvkjasewr23478cxvlkjdflk2349ds8fxcv,masfkjer234&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pwd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
       map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pwd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;^=&lt;/span&gt; map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;p&gt;일반적으로 실질적인 보안을 생각한다면 위와 같이 직접 만든 암호화 알고리즘을 사용하는 것은 좋지 않습니다. 수학적으로 검증된 기존 알고리즘을 사용하는 것이 안전합니다. 하지만 기존 암호화 알고리즘을 공부하고 또 그것을 코드로 직접 구현하는 일이 그리 쉽진 않지요. 그럴때에는 기존에 만들어둔 라이브러리를 사용하면 손쉽게 암호화, 복호화를 하실 수 있습니다. 아래는 윈도우에 포함된 암호화 API를 사용해서 RC4 알고리즘을 이용해서 암, 복호화를 수행하는 코드를 보여주고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RC4 암호화 함수&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/rc4.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! RC4를 사용한 암호화 함수&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbKey 는 암호화 하는데 사용되는 키 버퍼&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param dwKeySize 는 암호화 하는데 사용되는 키 버퍼의 크기&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbPlaintText 는 암호화 하는데 사용되는 원문&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbCipherText 는 암호화 된 문장이 저장될 버퍼(원문의 크기 이상이어야 함)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param dwHowMuch 는 암호화 하는데 사용되는 원문의 크기&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \return GetLastError의 반환값, 성공한 경우 0 리턴&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \remark 모든 버퍼는 문자열이 아닌 바이트 스트림으로 간주해야 함.&lt;/span&gt;

DWORD &lt;span class=&quot;token function&quot;&gt;Encrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              DWORD dwKeySize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbPlaintext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbCipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              DWORD dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HCRYPTPROV  hProv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HCRYPTKEY   hKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HCRYPTHASH  hHash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    DWORD       dwBuff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    BOOL        dwRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pbCipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pbPlaintext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptAcquireContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                                &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                                &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                                PROV_RSA_FULL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                                CRYPT_VERIFYCONTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptCreateHash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CALG_MD5&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptHashData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pbKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwKeySize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptDeriveKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CALG_RC4&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hHash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CRYPT_EXPORTABLE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptEncrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pbCipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;dwBuff&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; DWORD dwLastError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        dwRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dwLastError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CryptDestroyKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CryptDestroyHash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CryptReleaseContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; dwRet&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;RC4 복호화 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! RC4를 사용한 복호화 함수&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbKey 는 암호화 하는데 사용되는 키 버퍼&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param dwKeySize 는 암호화 하는데 사용되는 키 버퍼의 크기&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbCipherText 는 암호화된 버퍼&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbPlaintText 는 암호가 해독된 원문(암호화된 버퍼 크기 이상이어야 함)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param dwHowMuch 는 암호화된 버퍼 크기&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \return GetLastError의 반환값, 성공한 경우 0 리턴&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \remark 모든 버퍼는 문자열이 아닌 바이트 스트림으로 간주해야 함.&lt;/span&gt;

DWORD &lt;span class=&quot;token function&quot;&gt;Decrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              DWORD dwKeySize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbCipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbPlaintext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
              DWORD dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HCRYPTPROV  hProv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HCRYPTKEY   hKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HCRYPTHASH  hHash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    DWORD       dwBuff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    DWORD       dwRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pbPlaintext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pbCipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwHowMuch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptAcquireContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                               &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                               &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                               PROV_RSA_FULL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                               CRYPT_VERIFYCONTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptCreateHash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CALG_MD5&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptHashData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pbKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwKeySize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptDeriveKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CALG_RC4&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hHash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CRYPT_EXPORTABLE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CryptDecrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pbPlaintext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;dwBuff&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; DWORD dwLastError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        dwRet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dwLastError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CryptDestroyKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CryptDestroyHash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hHash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CryptReleaseContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hProv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; dwRet&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;RC4를 이용한 암, 복호화 테스트 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! 바이트 버퍼를 헥사값으로 출력하는 함수&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param pbText 는 출력될 바이트 버퍼&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \param dwLength 는 출력될 바이트 버퍼 크기&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \return 은 없음&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//! \remark 이 함수는 출력을 완료한 후 개행함&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PrintByte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pbText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD dwLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    DWORD   i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    CHAR    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;szHexaMap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0123456789ABCDEF&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; dwLength&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;putchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szHexaMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pbText&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x0f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;putchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szHexaMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pbText&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;putchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;putchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;\n&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    UCHAR   szPlainText&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    UCHAR   szChipherText&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    UCHAR   szDecryptText&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    UCHAR   szKey&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pohang&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    DWORD   dwBuffSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; szPlainText&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    DWORD   dwKeySize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; szKey&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;PrintByte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szPlainText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwBuffSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Encrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwKeySize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; szPlainText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; szChipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwBuffSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;PrintByte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szChipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwBuffSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Decrypt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwKeySize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; szChipherText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; szDecryptText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwBuffSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;PrintByte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szDecryptText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dwBuffSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[소고] 극과 극은 통한다: 위대한 기업과 블랙 회사는 어쩌면 같은 건지도…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/14592</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14592</guid><pubDate>Fri, 22 May 2015 23:59:13 GMT</pubDate><content:encoded>&lt;p&gt;작년인지 제작년인지 알리바바가 미국 증시에 상장을 했다. 시총은 아마존을 제꼈고, 알리바바 회장인 마윈은 세계에서 손꼽히는 거부가 되었다. 걸출한 성공을 거둔 잭 마, 자본주의 사회답게 거대한 부를 축적한 그를 동경하는 눈들이 많다. 매스컴에서는 그에 관한 다큐를 제작해서 방영하기도 했다. 얼마전 페북에서는 그의 명함을 받았다고 자랑스럽게 공개하는 사람도 있었다. 그 명함 한 장이 무엇이라고… 여튼 이쯤하면 기업가치고는 스타덤에 올랐다고 할 수 있겠다.&lt;/p&gt;
&lt;p&gt;그런 그의 위대함을 조금이나 배우고자 그에 관한 다큐를 꼼꼼히 살폈다. 그러다 다소 놀라운 장면을 목격하게 되었는데 다름아닌 아래 동영상이었다. 아래 영상은 알리바바 초창기인 1999년에 마윈이 직원들에게 이야기하는 것을 녹화한 화면이다. 첫째는 뭐 나름 비전 제시라고 할 수 있겠다. 하지만 두 번째 부분에서는 정말 뿜찌 않을 수 없었다. 어떻게 저런 이야기를 얼굴 표정 하나 변하지 않고 저리도 진지하게 이야기 할 수 있을까?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;second, we need to learn the hard working spirit of Sillicon Valley. If we go to work at 8am and go home at 5pm, this is not a high tech company and Alibaba will never be successful. If we have that kind of 8am-to-5pm spirit, then we should just go and do something else.&lt;br&gt;
&lt;br&gt;
둘째, 우리는 실리콘 밸리의 워크홀릭 정신을 배울 필요가 있습니다. 만약 우리가 8시에 출근해서 5시에 퇴근한다면, 그건 높은 기술력을 가진 회사라 할 수 없습니다. 그리고 알리바바는 결코 성공하지 못할 겁니다. 만약 우리가 8시 출근, 5시 퇴근 따위의 정신을 가지고 있다면 그만두고 다른 일을 하는 것이 옳을 겁니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위대한 기업과 블랙 회사, 사기꾼과 위대한 기업가는 같은 건지도 모른다. 진실과 거짓의 차이는 누가 더 뻔뻔하냐와 덜 뻔뻔하냐 정도의 차이밖에, 위대한 기업가와 사기꾼은 성공했냐 실패했냐 정도의 차이밖에는 없는게 아닐까라는 위험한 생각이 머릿속을 뱅뱅 헤집고 다닌다. 정말 요지경속이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./극과_극은_통한다_위대한_기업과_블랙_회사는_어쩌면_같은_건지도.md_0.jpg&apos; data-alt=&apos;실리콘밸리도 도찐개찐, 마윈 회장이 잘 배운 건지도 ㅋㅋ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2ce7867184b5557024ad6d07ce6b6805/953fe/%EA%B7%B9%EA%B3%BC_%EA%B7%B9%EC%9D%80_%ED%86%B5%ED%95%9C%EB%8B%A4_%EC%9C%84%EB%8C%80%ED%95%9C_%EA%B8%B0%EC%97%85%EA%B3%BC_%EB%B8%94%EB%9E%99_%ED%9A%8C%EC%82%AC%EB%8A%94_%EC%96%B4%EC%A9%8C%EB%A9%B4_%EA%B0%99%EC%9D%80_%EA%B1%B4%EC%A7%80%EB%8F%84.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGQABAAIDAAAAAAAAAAAAAAAAAAIEAwUG/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGdjlbJJXJj2Ioan//EABoQAAMBAQEBAAAAAAAAAAAAAAECAwATBBH/2gAIAQEAAQUCkk+QnHesAXySLgr8OixAqo6f/8QAFREBAQAAAAAAAAAAAAAAAAAAEAH/2gAIAQMBAT8BIf/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EAB8QAAIBAwUBAAAAAAAAAAAAAAABEQIDEBIhMTJikf/aAAgBAQAGPwKiaLfB0s/R6UkvOJIeNhn/xAAcEAEAAwACAwAAAAAAAAAAAAABABEhMVEQQWH/2gAIAQEAAT8hWyVOrPYkD6IZw4l/COyh0dx3wTwfFVxS6Wz/2gAMAwEAAgADAAAAEDf3/wD/xAAYEQEAAwEAAAAAAAAAAAAAAAABABARIf/aAAgBAwEBPxAF4TYsa//EABcRAQEBAQAAAAAAAAAAAAAAAAABETH/2gAIAQIBAT8QZUXr/8QAIBABAAIBAwUBAAAAAAAAAAAAAQARMSFBURCBkbHB0f/aAAgBAQABPxB00CMVrW9Mx2y5R6qHWtCXixCoFlckVzGEtXzvBWUUjt0YKEXXibpgQf2f/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;실리콘밸리도 도찐개찐, 마윈 회장이 잘 배운 건지도 ㅋㅋ~&apos; title=&apos;&apos; src=&apos;/static/2ce7867184b5557024ad6d07ce6b6805/953fe/%EA%B7%B9%EA%B3%BC_%EA%B7%B9%EC%9D%80_%ED%86%B5%ED%95%9C%EB%8B%A4_%EC%9C%84%EB%8C%80%ED%95%9C_%EA%B8%B0%EC%97%85%EA%B3%BC_%EB%B8%94%EB%9E%99_%ED%9A%8C%EC%82%AC%EB%8A%94_%EC%96%B4%EC%A9%8C%EB%A9%B4_%EA%B0%99%EC%9D%80_%EA%B1%B4%EC%A7%80%EB%8F%84.md_0.jpg&apos; srcset=&apos;/static/2ce7867184b5557024ad6d07ce6b6805/8ccab/%EA%B7%B9%EA%B3%BC_%EA%B7%B9%EC%9D%80_%ED%86%B5%ED%95%9C%EB%8B%A4_%EC%9C%84%EB%8C%80%ED%95%9C_%EA%B8%B0%EC%97%85%EA%B3%BC_%EB%B8%94%EB%9E%99_%ED%9A%8C%EC%82%AC%EB%8A%94_%EC%96%B4%EC%A9%8C%EB%A9%B4_%EA%B0%99%EC%9D%80_%EA%B1%B4%EC%A7%80%EB%8F%84.md_0.jpg 190w,
/static/2ce7867184b5557024ad6d07ce6b6805/ea4c8/%EA%B7%B9%EA%B3%BC_%EA%B7%B9%EC%9D%80_%ED%86%B5%ED%95%9C%EB%8B%A4_%EC%9C%84%EB%8C%80%ED%95%9C_%EA%B8%B0%EC%97%85%EA%B3%BC_%EB%B8%94%EB%9E%99_%ED%9A%8C%EC%82%AC%EB%8A%94_%EC%96%B4%EC%A9%8C%EB%A9%B4_%EA%B0%99%EC%9D%80_%EA%B1%B4%EC%A7%80%EB%8F%84.md_0.jpg 380w,
/static/2ce7867184b5557024ad6d07ce6b6805/953fe/%EA%B7%B9%EA%B3%BC_%EA%B7%B9%EC%9D%80_%ED%86%B5%ED%95%9C%EB%8B%A4_%EC%9C%84%EB%8C%80%ED%95%9C_%EA%B8%B0%EC%97%85%EA%B3%BC_%EB%B8%94%EB%9E%99_%ED%9A%8C%EC%82%AC%EB%8A%94_%EC%96%B4%EC%A9%8C%EB%A9%B4_%EA%B0%99%EC%9D%80_%EA%B1%B4%EC%A7%80%EB%8F%84.md_0.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;실리콘밸리도 도찐개찐, 마윈 회장이 잘 배운 건지도 ㅋㅋ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 윈도우 10 버전 구하기]]></title><description><![CDATA[윈도우 XP 시점인가를 기점으로 VerifyVersionInfo라는 함수가 생겼다. 등록 정보에서 호환성 모드를 설정한 경우에 GetVersion/GetVerionEx…]]></description><link>https://jiniya.net/wp/archives/14774</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14774</guid><pubDate>Thu, 23 Apr 2015 23:59:12 GMT</pubDate><content:encoded>&lt;p&gt;윈도우 XP 시점인가를 기점으로 VerifyVersionInfo라는 함수가 생겼다. 등록 정보에서 &lt;a href=&quot;http://jiniya.net/tt/25&quot;&gt;호환성 모드를&lt;/a&gt; 설정한 경우에 GetVersion/GetVerionEx 함수가 페이크 값을 리턴하면서 원본 값을 구하기 위해서 생긴 함수였다. 근데 이게 윈도우 10 되면서 또 무용지물이 되었다.&lt;/p&gt;
&lt;p&gt;윈도우 10부터 매니페스트에 윈도우 10을 타겟으로 컴파일되지 않은 바이너리는 GetVersion/GetVersionEx/VerifyVersionInfo 모두 페이크 값을 전달하도록 변경됐기 때문이다. 이뭐병 ㅠㅜ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Applications not manifested for Windows 8.1 or Windows 10 Technical Preview will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases. To manifest your applications for Windows 8.1 or Windows 10 Technical Preview, refer to Targeting your application for Windows.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx&quot;&gt;https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;원본 값을 구하고 싶은 경우에는 &lt;a href=&quot;https://github.com/DarthTon/Blackbone/blob/master/contrib/VersionHelpers.h&quot;&gt;VersionHelpers.h&lt;/a&gt;에 포함된 IsWindows10OrGreater 함수를 사용하면 된다. 결국은 RtlGetVersion 이라는 함수를 사용해서 버전을 구하는 꼼수를 보여주고 있다. 이 무슨 병신같은 시츄에이션인지 ㅠㅜ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] 슬랙 윈도 네이티브 애플리케이션 폰트 변경하기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/14752</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14752</guid><pubDate>Thu, 26 Mar 2015 23:59:11 GMT</pubDate><content:encoded>&lt;p&gt;그간 윈도 환경에서 슬랙은 네이티브 앱이 없고 크롬 확장으로 사용해야 해서 다소 불편함이 있었습니다. 그런 불편함을 알았는지 드디어 슬랙에서 윈도 네이티브 프로그램을 &lt;a href=&quot;https://wellbia.slack.com/apps&quot;&gt;절찬리 배포하기&lt;/a&gt; 시작했습니다. 반가운 마음에 깔아보았는데 시작부터 이건 비주얼에 큰 실망을 안겨주는 군요 ㅠㅜ~ 안타깝게도 폰트 설정을 찾아보았으나 쉽게 찾을 수가 없었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./슬랙_윈도_네이티브_애플리케이션_폰트_변경하기.md_0.png&apos; data-alt=&apos;폰트 이건 아니잖아~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 576px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e90f94b184e83a6b06caddb27ce4b2be/694da/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABmElEQVR42pWRzWrCQBSF85Au9AHEjYgIoi5c+AyCWxFcuap02y6EgnSh4EJKrbXmrzEzJjPJZDL5qabXBKQtCvYskjvn3m84yZWeH++eHu5lfbd+3xKHU0+I8MsPYiZiLmLXD7mIjsfkoiRTXcvrF+oFFmEA76lHHC8tuEW5zQTwxyu0lL0I8xXkIMq3iL7plrZ3ZER9EV5ksrvgKR1TWYRuZE1R9a2qbRRNVrXX9censcN4bxiGqmoIIYxOMhF2HIdSSgiRsjuCIADHtgl44Huet8eYcw5Dtm1no4y5tm1R5v2KDXAcxz8j7UxztVqZpnkt8wU4azDGFEWBAgJblvU/2HXdxWKxXC673W6lUpnP52AeDoebYIxxu91utVrNZrNQKAwGg5tgUBRF/X6/0Wh0Op1arZbL5er1+mw2O/MX4CiKM17X9VKpVC6Xq9VqsVjM5/NwnEwm0IKBQ6q/cBCEsC3YDSxmPB73er3hcDgajaCeTqfw52BbsD/f9yHaXziMTgIe2kIIKMJUqR35qcCE1vkDkyT5Bs+kzRsAgIbuAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;폰트 이건 아니잖아~&apos; title=&apos;&apos; src=&apos;/static/e90f94b184e83a6b06caddb27ce4b2be/694da/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/e90f94b184e83a6b06caddb27ce4b2be/08678/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_0.png 190w,
/static/e90f94b184e83a6b06caddb27ce4b2be/2edd7/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_0.png 380w,
/static/e90f94b184e83a6b06caddb27ce4b2be/694da/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_0.png 576w&apos; sizes=&apos;(max-width: 576px) 100vw, 576px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;폰트 이건 아니잖아~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;혹시나 방법이 있나 싶어서 구글신에게 물어보았더니 친절한 &lt;a href=&quot;http://blog.hinaloe.net/2015/03/24/change-font-of-slack-for-windows/&quot;&gt;일본 블로그에서&lt;/a&gt; 해결 방법을 찾을 수 있었습니다. 아래 방법대로 하면 폰트를 변경하실 수 있습니다.&lt;/p&gt;
&lt;p&gt;node-js깔고 아래 명령어를 치면 app.extract 디렉터리에 소스 코드가 풀립니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm install -g asar
cd %LOCALAPPDATA%/slack/app-1.0.0/resources
asar e app.asar app.extract&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;압축 풀린 디렉터리에 가서 “/src/ssb/app.js” 파일을 열어 보면 아래와 같은 부분이 있습니다. ko-KR이 아니라 ja-JP로 되어 있습니다. 그 부분을 아래와 같이 고쳐주면 됩니다. MS PGothic 찾아서 죄다 앞에다 원하는 폰트를 적어주면 됩니다. 저는 Malgun Gothic으로 설정했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;layouts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ko-KR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Figure out what the default font family for messages currently is&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; fontFamily &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cssom&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fontFamily&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&apos;Lato&apos;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Lato&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Lato,&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Lato, Malgun Gothic, MS PGothic,&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;수정 다 했으면 &quot;asar p app.extract app.asar&quot; 명령어를 입력해서 파일을 다시 패키징해주면 됩니다. 그리고 슬랙을 껐다 키면 아름답고 미려한 폰트를 구경하실 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./슬랙_윈도_네이티브_애플리케이션_폰트_변경하기.md_1.png&apos; data-alt=&apos;바로 이거죠~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 578px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1d87f7602d6628e614e3eb56298afa2c/8c7b4/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 67.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABzElEQVR42o1TO4/iMBDmX1KAqKCgQAhEQ0VBgWj4BUh0Jzp0HRI6CkpaKHaB1cp5OySbF3bsPG+c3LLc7Z7uvsTSeMbffM7MpIJenl3X0VSVMR7HcZZleZ6L9R+o/Pj+zbB8ScWm7ZvO7c2jbsAsj1xdarwR3SaUxZBNIC+e0izJsGjILde/OgG82tU1LM90AscnURQVjL8rw/ICcpYxMuxX1XpC+CSZz0g3LIeFIaWUkFsQBIVBwEFu4BBgjAkybAxdU2RJlSVNVTA2FBmZpqECFEWWZQkhXddME4Pt+YHIKRKFFfgAHgmEBSAf55FlWb7vc85ZyIooF96IE0qTNP24NpAhWG7KSoDe5XJBCEGuu/N+IEvT7DO5PARq5/MZDIzxZrORJEmE0l+VToH5kOsL5e12u1wuZ7NZrVYbj8eP+o99+kLZ87zJZNLtdkejUaPR6Pf7p9Pp3+QS8/l8MBgAczgcVqvVVqs1nU5h8u7MP8lQRwhDCmgmyDabzV6v1+l06vV6u91eLBZwc6gFnEmS5BMZWsIYzAC053A4rFar9Xq92+32+/3xeNQ0zbZt+JxiSML0t1bleVwAlCFF+W8k7yid/B3FwH4o/wR66gVag1uZuwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;바로 이거죠~&apos; title=&apos;&apos; src=&apos;/static/1d87f7602d6628e614e3eb56298afa2c/8c7b4/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_1.png&apos; srcset=&apos;/static/1d87f7602d6628e614e3eb56298afa2c/08678/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_1.png 190w,
/static/1d87f7602d6628e614e3eb56298afa2c/2edd7/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_1.png 380w,
/static/1d87f7602d6628e614e3eb56298afa2c/8c7b4/%EC%8A%AC%EB%9E%99_%EC%9C%88%EB%8F%84_%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C_%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%8F%B0%ED%8A%B8_%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0.md_1.png 578w&apos; sizes=&apos;(max-width: 578px) 100vw, 578px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;바로 이거죠~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[일상] 좋은 날]]></title><description><![CDATA[#0 2014. 12. 19. FRI, 회사 창업하고 처음으로 직원들에게 인센티브가 지급됐다. 만으로 꼭 8년 하고도 3개월 정도가 된 시점. 생각보다 오래 걸렸고, 생각보다 오래 걸렸다. 26살에 처음 창업 대열에 끼어들던 나는 한…]]></description><link>https://jiniya.net/wp/archives/14481</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14481</guid><pubDate>Fri, 13 Feb 2015 23:59:10 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/9X5Kcr8hXmI?si=BnXyFyqlXv-38k6u&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;2014. 12. 19. FRI, 회사 창업하고 처음으로 직원들에게 인센티브가 지급됐다. 만으로 꼭 8년 하고도 3개월 정도가 된 시점. 생각보다 오래 걸렸고, 생각보다 오래 걸렸다. 26살에 처음 창업 대열에 끼어들던 나는 한 3년 하면 성공할 줄 알았었다. 지금 대표를 하고 있는 형은 처음 대표로 취임하던 날 2년만 해보자는 이야기를 했었다. 우리는 너무 어렸고, 너무 쉽게 생각했다. 그래서 그런지 예측은 다 빗나갔다. 3년이 지났을 땐 5년 정도 하면 성공할 줄 알았다. 5년이 지났을 땐 더 이상 날짜를 기약하지 않게 되었다. 나이도 들었고, 목표 보다는 과정을 보는 눈도 생겼기 때문이다. 어쨌든 그런 희망고문 같은 판타지가 우리를 버티게 해주었는지도 모를 일이다. 우리는 매일같이 쪽팔리지 말자, 좋은 날이 올거야, 라는 말을 주문처럼 외우면서 살았다.&lt;/p&gt;
&lt;p&gt;인센티브가 지급되던 장면은 나에겐 약간 아이러니하게 느껴졌다. 왜냐하면 그 자리에서 인센티브를 받고 기분 좋아하는 직원들이 아닌 그 자리에 있었어야 할, 하지만 있지 못하는 사람들이 떠올랐기 때문이다. 짧은 의식같은 행사가 끝났을 무렵 내 머릿속에 가장 먼저 떠오른 것은 안나 카레니나의 첫 문장이었다. 왠지 이 문장이 지금의 모든 분위기를 대변하는 것 같다는 느낌이 들어서였다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All happy families are alike; each unhappy family is unhappy in its own way.&lt;br&gt;
&lt;br&gt;
행복한 가정은 서로 닮았지만, 불행한 가정은 모두 저마다의 이유로 불행하다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 안나 카레니나, 톨스토이&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;회사를 하면서 내가 기억하는 핵심 장면들이 몇 있다. 첫 번째 장면은 2007년 초, 우리가 처음 게임 보안 제품을 만들기로 한 날이었다. 모 게임사에서 펀딩을 해서 시작하게 된 사업이었는데 지금도 별볼일 없는 우리를 믿고 투자해준 그 회사가 신기할 따름이다. 나는 이 일을 우리 회사에 있어서 가장 큰 빅딜이었다고 생각하는 편이다. 지금 대표인 형이 그 계약을 성사시켰는데, 그 공로를 인정 받아(?!) 이듬해 우리 회사의 두 번째 대표가 되었다.&lt;/p&gt;
&lt;p&gt;두 번째 장면은 2008년 중순, 우리가 만든 제품으로 처음 매출을 올린 날이었다. 지금 생각해보면 참 조촐한 첫 매출이었지만 통장에 외화가 꽃혔다는 이유로 우리는 즐거워하며 회식을 했었다.&lt;/p&gt;
&lt;p&gt;세 번째 장면에 오늘을 포함시키기로 했다. 얼마가 됐든 약속한 것보다 조금이라도 더 줄 수 있다는 게 쉬운 일이기도 하고, 어려운 일이기도 하다. 그러나 어쨌든 그런 일이 처음이기도 하고 회사가 여기까지 잘 도착했다는 사실이 대견하기도 한 것 같아 포함시키기로 했다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;이상하게도 이 좋은 날 옛날 생각이 많이 떠올랐다. 제품 소개차 나간 미팅 자리에서 제품이 엣지 없다는 소리를 들었던 날도 있었고, 제품은 좋은데 검증이 안 된 것 같다며 레퍼런스를 확보하고 오라는 이야기를 들었던 날도 많았다. 회사가 망하면 어쩌냐는 소리를 들었던 수많은 자리가 있었고, 세번씩이나 똑같은 업체에 미팅을 하고는 돌아오는 차 안에 난데없이 거미가 나타난 적도 있었다. 더 어처구니없게도 우린 그걸 보며 이게 아침 거미인지 밤 거미인지 하면서 미신을 뒤적거리며 그 업체와 계약이 될지 안 될지를 점치기도 했었다. 정말 좋은 기회라고 싱글벙글하면서 나간 미팅 자리가 우리를 음해하는 세력이 꾸민 장례식 자리가 됐었던 어처구니 없는 상황도 있었다. 참 많은 일들이 있었다.&lt;/p&gt;
&lt;p&gt;향수에 젖어서는 예전 일기장을 뒤적거려 보았다. 난 특이하게도 힘들면 일기를 쓰는 습관이 있는데, 회사를 하면서는 2010년, 2011년 일기가 많다. 회사를 하고 제법 시간이 흐르기도 한데다 그 당시에는 마치 모든 일이 멈춰버린 것 같은 상황들이 많았기 때문이었다. 꿈틀거릴수록 뭔가 점점 더 나빠지는 느낌들이 나를 엄습했던 시기이기도 했다. 어쨌든 그래서 그 당시에는 제법 부지런히 일기를 썼었다. 다시 살펴보니 회사도 나도 귀엽기도 하고 깜찍하기도 하고 그렇다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2010. 01. 27. WED&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
그날 밤을 새며 M과 둘이서 HACK.DLL을 분석했지만 답을 찾지 못했다. 사실 분석에 있어서는 우리 둘 다 초보였다. 우리는 Themida로 패킹된 프로그램을 디버깅 하는 방법도 Yoda Crypter로 패킹된 DLL을 언팩하는 방법도 몰랐다. 닥치고 초보였던 것이다. 그러면서 사내에 이런 교육이 절실하다는 사실을 깨닫게 되었다. 게임 보안 제품을 만드는 회사에서 해킹툴 DLL을 분석할 수 있는 사람 한 명 없다니, 이 얼마나 아니러니 한 사실인가? 좀 쪽 팔리는 사실이기도 했다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2010. 01. 28. THU&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
저녁에는 K가 첫 월급 턱이라고 밥을 샀다. 개발팀, QA팀 합해서 7명이 가서 순두부를 먹었다. 3명이었던 팀원이 갑자기 이렇게 늘어나니 관리가 통 안된다는 생각이 들었다. 물론 이제는 회식을 한 번 하기에도 부담스러운 인원이 된 것은 두말할 필요도 없다. 팀이 점점 나의 손을 떠나는 느낌이 많이 든다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;요즘은 회사의 느낌이 죽 끓이는 것 같다는 생각을 많이 한다. 마치 사인 곡선처럼 좋았다, 나빴다를 반복하는 것이다. 어쩌면 나 스스로 점점 더 자신감을 잃어가는 과정은 아닌지 모르겠다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2010. 01. 30. SAT&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
거의 밤을 새우다 싶이 하고는 오후 2시에 퇴근을 했다. H도 밤샘 작업이 있다고 그때 마친다고 했기 때문이었다. 결국 HACK.DLL 분석 작업 마무리를 못했다. 월요일에 T에게 헬프 메일을 보내야겠다. 찜찜한 기분으로 집으로 왔다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;엉망진창인 집. 내 생활의 한 조각, 아니 전부를 보여주는듯 했다. 내 방은 엉망진창이고, 그건 내 생활 또한 엉망진창이라는 것을 나타내기 때문이다. 일주일을 돌아본다. 내가 이 방에서 한 일이라곤 쓰러져 몇 시간 잠을 자고 씻고 출근하는 것이 전부였다. 온통 양말과 수건으로 널부러진 방을 보기만 해도 머리가 아팠다. 정리가 필요했다. 이 방에도, 내 삶에도…&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2010. 02. 21. SUN&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
느즈막히 출근을 했다. 어제 작업하던 V 모듈 마무리 작업이 있었다. CDN에서 N 코드를 다운로드 받아서 실행하는 부분을 추가할 계획이었다. 작업을 하려고 PC를 켜고 Visual Studio를 정리했다. 그러고는 늘상 하듯이 브라우저를 켜고 모니터링 사이트를 방문해 보고는 했다. 그러다 엄청난 사실을 알게 되었다. XIGNCODE로 영문 위키 페이지가 생성되어 있는 것이었다. 물론 내용은 안습이었다. 최악의 보안 프로그램이다. 막는게 하나도 없다와 같은 이야기였다. 조금 충격적이었다. 사실 많이 충격적이었다. 나중에 다시 보니 페이지는 지워지고 없었다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;최고의 보안 제품을 만들겠다는 일념으로 3년을 넘게 달려왔다. 그런데 ‘worst anti cheat’라는 수식어라니. 자존심이 좀 상하기도 하고, 좀 얼떨떨 하기도 하고 그랬다. 한동안은 코딩도 못했다. 이내 마음을 다잡았다. 아직 갈 길이 많이 남았다는 생각을 했다. 그래도 유저들이 우리 제품을 인식하고 있다는 긍정적인 신호로 받아들이기로 했다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2010. 02. 23. TUE&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
엄청난 하루였다. 어제 수정한 V 모듈이 오늘 패치된 것이다. 패치는 정말 감동 그 자체였다. 커뮤니티에는 핵이 완전히 사라졌다고 좋아하는 글들이 올라왔고 핵의 숙주인 DG에는 빨간불이 들어왔다. N 코드는 의외로 별 문제 없이 잘 동작했다. 그런데 문제는 V 모듈에 있었다. 새롭게 추가한 DirectX 훅 체크 코드의 if문이 엉뚱하게 붙어 있었던 것이다. else if가 되어야 하는데 독립 if문으로 해버린 사소한 실수였다. 그 덕분에 게임 스트리밍 서비스를 사용하는 많은 정상 유저가 끊기는 일이 발생했다. 코드를 고치는 것은 간단했지만 실제 업데이트에 적용 되러면 얼마간 시간이 걸릴 것으로 보인다. 다시한번 실시간 업데이트의 필요성을 절감했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
![](./x3beta4.png)  
**가장 힘들었던 그해 6월, 우리의 세번째 판올림 XIGNCODE3 베타 버전이 나왔다.**
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 347px; margin-bottom: 16px;&apos; data-url=&apos;./x3health.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/374165dfe39289402db882259528a27b/c8500/x3health.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 53.68421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABWElEQVR42n1RS07DMBTs2ViyYsFZWHIAWHABlpyBj7gDEpuWNh8nTk3SJv7EduzUcRqcRAVaqRlZtmW98cybN5MlZ4wVaU4xs227H9B1nTEGY1wyRglRSgrBK1mlWUYwpg6EaK1ntCAJiMEyggB1A0aylBKtExAEMIZFsXUlnrcCYRT4XhxBzkVPxnkBQZyibPO9lUyQgu2McWSt1RpCZ0opXdfaXRilTrwsmRBylJkV6Wb+uQj9ACXIn3vewt9kOcldhYhB1DS2O49ZXSmKaVmWSilGmTO5higOoyzLkiQxg4shhr6Xfb/Gtgby/5/cswsphhBzjtIUIWTtpPL+gO6Qc2ebdvlluDDWurSdqT+tE/KRctsXvX2g1cWlvb7ayUrVtaqqs8pH5GG/fw5v7l6fbh8FLn8nN0VumsbNghC6q9Uc5A8vwbvHxximeh6Ptm31gOmETsg/FlJ011ZnpjQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;x3health&apos; title=&apos;&apos; src=&apos;/static/374165dfe39289402db882259528a27b/c8500/x3health.png&apos; srcset=&apos;/static/374165dfe39289402db882259528a27b/08678/x3health.png 190w,
/static/374165dfe39289402db882259528a27b/c8500/x3health.png 347w&apos; sizes=&apos;(max-width: 347px) 100vw, 347px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;근 2년간 700번의 새로운 엔진 빌드. 우리는 거의 매일 새로워졌다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 572px; margin-bottom: 16px;&apos; data-url=&apos;./xx3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/25941b5ad33f9ac0308250c2642837f6/698d8/xx3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 32.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAA7CAAAOwgEVKEqAAAAA8ElEQVR42mWPTU8DIRCG+f9/oAcPXoyJmujNgzWe6sHEeFa7i223+0VZCwvsgPuBA1oT0yeTl2GS92Ugi5vL54drxlmel/WOCymbvWiV0toAgOkCFgFrtDF4Bwgj00EHZHFxdX92mhdlts5W602WbSldpSlNE4oNpR/LJMm3xfvbsq6ZEFIpJWVQTCcemTxYpzuYfhhDjZFDE4fT5P9DtBYOWovLgO2HsR+QcYiOEDv5P0cMiuHj7xPk9mQ2P58xvivLGquoKlyvqhnnTdN84p57IbDDz/ojyOvj08vdXMhWGfN1wLmgNh4o1rq+H47N339qUyQgE6K6AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xx3&apos; title=&apos;&apos; src=&apos;/static/25941b5ad33f9ac0308250c2642837f6/698d8/xx3.png&apos; srcset=&apos;/static/25941b5ad33f9ac0308250c2642837f6/08678/xx3.png 190w,
/static/25941b5ad33f9ac0308250c2642837f6/2edd7/xx3.png 380w,
/static/25941b5ad33f9ac0308250c2642837f6/698d8/xx3.png 572w&apos; sizes=&apos;(max-width: 572px) 100vw, 572px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./x3rep.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dde73cdd1630e472ec230cecfe155474/dface/x3rep.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 83.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACO0lEQVR42m2TiXKiQBCGff83i9lKRKMIgoICIvc1g6Am+w2zcY/aLqqrmem/++9jZmkz8J1yGRXqs8+dG4tGDp+Pxzje7vf77ab057d8/SGzLM+DMIrTPCuqumllfxVCNm0rpazrGt22bd/3X/+TmRQiCsM8z0TXjePQS3m9XvEehkEIgQFea37Rf4Evl4vjOMfjMQiC8/m83+8PhwO/SZKgPc/b7ewgCLl1XRfnx+PxGxxFEae4nk4nDH7xA4ZflmVo3/cJgQNxOfk3s2ma8STkxGmE/TDQJ/jrmruug7mY5Pu8p3kzChKyb5qGC061h66NuJZl7ZQ4m42J7boU5VmW7Tju1DApcSItBcOZzBiccFcU5cfHer3evL8vXl7m4JfL5evrD2zP8xUYhkVRVFVZVRW2HizEuSvLcrvdhmEE7Zoxtl3TtHBM0wzaCkxBVV3neZ6mKReEqKdfSgjDEKr0j55BnY5MzF16RBoFphP0kCRwTicBCXMqB2wYBslXqxWGNQnMF4uFHhi06e6oF1BrTrWmflw1GIN1eEbBU4FJRAchRuYTDI9HBg4R7jRtYGBs2yYKo0bD/FfmJAj2rssaBKtVYBj+29t+Ps89jzvIK7CxpEidHLcNTTdNmqrAse9fptkk01cWRZokbDvDKyaheF7YfXpbWp4bOjvHMavrHTwIB2FIbGhTHsxH1Q+1asxuuA567W680ye4qUs9xk7wrpRUJTNXh+AZHvNleGmSlmXRNHVd1YTU4J8HJa9dLR9xHwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;x3rep&apos; title=&apos;&apos; src=&apos;/static/dde73cdd1630e472ec230cecfe155474/dface/x3rep.png&apos; srcset=&apos;/static/dde73cdd1630e472ec230cecfe155474/08678/x3rep.png 190w,
/static/dde73cdd1630e472ec230cecfe155474/2edd7/x3rep.png 380w,
/static/dde73cdd1630e472ec230cecfe155474/dface/x3rep.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./xx8.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a65c57e968dbb325f2ec7a09e1fbb40a/dface/xx8.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 23.684210526315788%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAvklEQVR42j1Pyw6DMAzj/79uQ+wMzatpGZvUTsAuMNPDrKhN6tpJujlnFUHknOd5joAZSndXNfdkKFVzSjG6gzNjUYtxeb06ARcjo3S/CCZRxQmxiHADZMLUXEQoxDAt7t9t67jvdRio7024iS8JfnETonkIIaVEHKC8Ok6TDo9wvy1mnRIhjIiJMPI4jlBRA2wwMJpBD99rt0Zh0uf7ve07xlZPCY5Y+QPUiqOUgru2vL3VWso/39b1OI7zPH9UHg9p5K/MPQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xx8&apos; title=&apos;&apos; src=&apos;/static/a65c57e968dbb325f2ec7a09e1fbb40a/dface/xx8.png&apos; srcset=&apos;/static/a65c57e968dbb325f2ec7a09e1fbb40a/08678/xx8.png 190w,
/static/a65c57e968dbb325f2ec7a09e1fbb40a/2edd7/xx8.png 380w,
/static/a65c57e968dbb325f2ec7a09e1fbb40a/dface/xx8.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 464px; margin-bottom: 16px;&apos; data-url=&apos;./xx91.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/9e8fbb1c60839a9ae26193ae369eca47/0359b/xx91.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABUElEQVR42o1R2W6DQAzk/3+vraIqsPe9wC6QbMKVdIhaVX3rWAJLnvGO7epyLb7Nrh2GcZqmS87per2uB5ZlPeL4vDDP8/qdHti2rTJGnc+1NVopqbVumpoQLgRnlDLOCNAQC5KUpGkoJagQimgY45XgvD7X0AguPk8nxjkBp6mbcy2EQIuP9zd6yBi8XS7TNE7DOA7DkNJQdW0rpdRKGmvxMmUUFqwzAKdMKw1PeBNdQvQGFGNgE5Kcx6qNwVnr4cxAK/F3FiMoMOCOMYYCDDBG0SZ63/e9Q83oW7lX1kUujTJeSEO5FspJbQhT1nksL6fUdx0EMQbYfv5FlfLY9qlPGKjc7uvtvszLVm5Y9X7UH79UpI8ffItLKbhWHkueyrptOMY837d9f/4DFa4aMLYL2liHaY51WB9iG8I0Dh4ZIoTU9z6Ermuxmhjj/ur+BRPw9J4cdE1EAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xx91&apos; title=&apos;&apos; src=&apos;/static/9e8fbb1c60839a9ae26193ae369eca47/0359b/xx91.png&apos; srcset=&apos;/static/9e8fbb1c60839a9ae26193ae369eca47/08678/xx91.png 190w,
/static/9e8fbb1c60839a9ae26193ae369eca47/2edd7/xx91.png 380w,
/static/9e8fbb1c60839a9ae26193ae369eca47/0359b/xx91.png 464w&apos; sizes=&apos;(max-width: 464px) 100vw, 464px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; margin-bottom: 16px;&apos; data-url=&apos;./x3s.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/992cbbd84811e49ffea562a134185d62/abf7b/x3s.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 26.31578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA7ElEQVR42h3NYU+EMAwG4O2QjQGDjbGt2wAxknheTjxBz/jB//+3LDZPmrbJm5Kn5O4v8vdS/JzFOnPBHgRH2dHzU8EOuJbHJeM5RYLRktGKU5KsWuawPMIy+ecxjNFHsGOEBDaBm1LwfZeCG4KbByj5CcPFfx4R8M0Ytbc1WBl8E70MToKrcUApqAHaBG3wkuUZpQSdKGEZqfHz9dy9vXbrRX9czbbabe139O4+0c3ft7Cv9uvmt9VVJS+KgnMuhKhLIStGxmn53pcA0LRGa6t1r5QxxuPcKiulUq3pjFfKGtOnGJ2zEQsDVv8BDREXihIMZXwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;x3s&apos; title=&apos;&apos; src=&apos;/static/992cbbd84811e49ffea562a134185d62/abf7b/x3s.png&apos; srcset=&apos;/static/992cbbd84811e49ffea562a134185d62/08678/x3s.png 190w,
/static/992cbbd84811e49ffea562a134185d62/2edd7/x3s.png 380w,
/static/992cbbd84811e49ffea562a134185d62/abf7b/x3s.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;그리고 우리가 얻은 것: ‘worst anti cheat’에서 조금은 자부심을 가질 만한 평가들&lt;/strong&gt;  &lt;/center&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;세상에 &lt;a href=&quot;http://www.woowahan.com/?page_id=6104&quot;&gt;훨씬 더 좋고&lt;/a&gt; &lt;a href=&quot;http://www.jennifersoft.com/docs/jennifersoft-jobs.html&quot;&gt;훨씬 더 대단한&lt;/a&gt; 회사들이 많이 있다. 대단하지 않은 작은 성취지만 기분 좋은 마음에 몇 자 끄적여 봤다. 왜냐하면 난 용뼈를 먹고도 뛸듯이 좋아했던 사람이니까… 거기에 비하면 이건 훨씬 더 대단한 일 아닐까낭?!…&lt;/p&gt;
&lt;center&gt;
![](./wow.png)  
**이 별거도 아닌 아이템 하나 먹고 난 세상을 다 가진 줄 알았었다.**
&lt;p&gt;&lt;strong&gt;와우에 적용될 그 날을 기다리며…&lt;/strong&gt;&lt;/center&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 방어적 프로그래밍]]></title><description><![CDATA[위와 같은 코드를 줬더니 그대로 사용해서 “buffer[written] = ‘\0′;” 구문에서 written이 MAX_BODY_CONTENT보다 크면 어쩌냐는 이야기를 했다. 그랬더니 dn->ToBuffer 함수가 실패한 경우에도 written…]]></description><link>https://jiniya.net/wp/archives/14694</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14694</guid><pubDate>Thu, 12 Feb 2015 23:59:09 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HRESULT &lt;span class=&quot;token function&quot;&gt;SomeFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

	SIZE_T written&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;xch&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MAX_BODY_CONTENT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HRESULT hr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dn&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToBuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;written&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SUCCEEDED&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;written&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 코드를 줬더니 그대로 사용해서 “buffer[written] = ‘\0′;” 구문에서 written이 MAX_BODY_CONTENT보다 크면 어쩌냐는 이야기를 했다. 그랬더니 dn-&gt;ToBuffer 함수가 실패한 경우에도 written에 값이 저장되냐는 둥, 소스가 더 커도 실제 크기가 written에 넘어오냐는 등의 질문을 한다.&lt;/p&gt;
&lt;p&gt;dn-&gt;ToBuffer 함수가 어찌 동작하든 간에 if문 하나만 추가하면 안전해지는 문제 아니냐는 말을 했더니 기어코 소스 코드를 찾아내서는 그렇게 반환하는 경우는 없는것 같다고 궁시렁거리는 신입 프로그래머의 패기. dn-&gt;ToBuffer 함수가 내일 동작이 바뀌어서 그런 값을 반환하면 어쩔거냐고 했더니 그제서야 if문을 추가한다.&lt;/p&gt;
&lt;p&gt;다른 함수에 불필요한 가정을 추가하지 말자. 불필요한 가정이 필요하다면 그 가정이 사실인지 반드시 확인하자 (ASSERT가 됐든 if가 됐든). 그리고 다른 함수가 정상 동작할 거라는 일말의 기대도 하지 말자.&lt;/p&gt;
&lt;p&gt;돈을 받고 갈켜줘도 시원찮을 판에 월급 주며 갈켜주는데도 엉뚱 소리를 하니 속에 천불이 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;참 갑갑한 현실…&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;&apos; data-url=&apos;./[플밍노트]_방어적_프로그래밍.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/abebf59db012b5e1939bae0dbfc9cfdb/953fe/%5B%ED%94%8C%EB%B0%8D%EB%85%B8%ED%8A%B8%5D_%EB%B0%A9%EC%96%B4%EC%A0%81_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGtcS4rMor/xAAeEAABAwQDAAAAAAAAAAAAAAABAAIDBBESExQiMf/aAAgBAQABBQLfZSVJaea9E9pDmfF//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhABAAIDAQAAAAAAAAAAAAAAAAExETJBYf/aAAgBAQAGPwJs4pM+Ky//xAAbEAEAAwADAQAAAAAAAAAAAAABABEhMUFhkf/aAAgBAQABPyGulAiKumZKOviFUQnNRmM8QQUn0z//2gAMAwEAAgADAAAAEMvf/8QAFREBAQAAAAAAAAAAAAAAAAAAEDH/2gAIAQMBAT8Qh//EABYRAAMAAAAAAAAAAAAAAAAAAAEQIf/aAAgBAgEBPxAVf//EABwQAQEBAAIDAQAAAAAAAAAAAAERADFhIXGBwf/aAAgBAQABPxBKcAXvDhLDFDlUp3pRJnsnjC+SEBxGfuvk/Tf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 0&apos; title=&apos;&apos; src=&apos;/static/abebf59db012b5e1939bae0dbfc9cfdb/953fe/%5B%ED%94%8C%EB%B0%8D%EB%85%B8%ED%8A%B8%5D_%EB%B0%A9%EC%96%B4%EC%A0%81_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D.md_0.jpg&apos; srcset=&apos;/static/abebf59db012b5e1939bae0dbfc9cfdb/8ccab/%5B%ED%94%8C%EB%B0%8D%EB%85%B8%ED%8A%B8%5D_%EB%B0%A9%EC%96%B4%EC%A0%81_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D.md_0.jpg 190w,
/static/abebf59db012b5e1939bae0dbfc9cfdb/ea4c8/%5B%ED%94%8C%EB%B0%8D%EB%85%B8%ED%8A%B8%5D_%EB%B0%A9%EC%96%B4%EC%A0%81_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D.md_0.jpg 380w,
/static/abebf59db012b5e1939bae0dbfc9cfdb/953fe/%5B%ED%94%8C%EB%B0%8D%EB%85%B8%ED%8A%B8%5D_%EB%B0%A9%EC%96%B4%EC%A0%81_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D.md_0.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;안개가 짙은 길을 주행할 땐 일단 서행하렴. 눈 앞에 갑자기 차가 나타날 수 있단다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;운전이나 코딩이나 방어가 중요하다는 거…&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[[cpp] 함수 디자인]]></title><description><![CDATA[회사의 신입 개발자가 아래와 같은 함수를 만들었다. URL의 페이지를 긁어 오는 함수다. url에는 긁어올 웹 페이지 주소를 지정해서 함수를 호출하면 해당 웹 페이지를 긁어오는데 성공하면 check에 TRUE가 반환되고 string…]]></description><link>https://jiniya.net/wp/archives/14684</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14684</guid><pubDate>Wed, 11 Feb 2015 23:59:08 GMT</pubDate><content:encoded>&lt;p&gt;회사의 신입 개발자가 아래와 같은 함수를 만들었다. URL의 페이지를 긁어 오는 함수다. url에는 긁어올 웹 페이지 주소를 지정해서 함수를 호출하면 해당 웹 페이지를 긁어오는데 성공하면 check에 TRUE가 반환되고 string에는 페이지 내용이, 실패한 경우에는 check에 FALSE가 반환되고, string은 빈 문자열이 넘어온다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BOOL &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;check&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 디자인의 칭찬할 점은 함수의 리턴 값을 중의적인 내용으로 사용하지 않았다는 점에 있다. 리턴 문자열이 빈 문자열(“”)이면 오류라고 식별하는 것처럼 디자인해서 리턴 값에 성공/실패의 의미와 페이지 내용을 같이 담지는 않았다는 의미다.&lt;/p&gt;
&lt;p&gt;하지만 둘 중에 어떤 것을 리턴 값으로 선택하는지에 대해서는 생각이 조금 짧았다. 왜냐하면 함수 내용을 살펴보면 check는 함수의 수행 지점에 상관 없이 항상 덮어쓰기가 일어나지만 리턴 문자열은 성공한 경우에만 덮어쓰면 되기 때문이다. 이런 점을 생각했다면 check를 리턴 값으로 삼는 것이 좋았을 것이다. check를 리턴 값으로 선택하면 실패한 경우에 문자열 복사가 발생하지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;일반적으로 개발자들이 많이 사용하는 함수 디자인 패턴이 있다. 그런 디자인 패턴에는 일반적으로 함수를 디자인한 사람의 생각과 그 함수를 사용하는 사람이 전제할 수 있는 내용들이 있다. 많이 사용되는 디자인을 살펴보면 다음과 같은 형태들이 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;url에 const가 붙어있기 때문에 입력으로 사용되는 값임을 유추할 수 있다. buffer는 레퍼런스이기 때문에 반드시 값이 지정되어야 한다는 것을 의미한다. BOOL은 함수의 성공 여부를 리턴 한다고 기대할 수 있다. 실패한 경우에는 GetLastError같은 함수나 errno 같은 전역 변수를 사용해서 추가적인 오류 코드를 확인할 수 있도록 설계된 경우가 대부분이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HRESULT &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 경우에 바뀐건 BOOL이 HRESULT가 된 것 뿐이다. GetLastError를 사용할 필요 없이 실패 원인을 직접 반환하겠다는 의도다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HRESULT &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;buffer가 레퍼런스에서 포인터로 변경됐다. 이 값이 필요 없는 경우에는 NULL을 지정해도 된다는 것을 의미한다. 물론 이 관습을 모든 함수가 따르는 건 아니다. 대체로 그렇다는 말이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HRESULT &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;buffer가 문자열 클래스에서 문자열 포인터로 변경됐다. buffer는 size 만큼을 담을 수 있다는 것을 의미한다. 이 경우에 size가 문자 개수냐 바이트 수냐는 애매하다. 함수 설명에 어떤 내용을 의미하는지 명시할 필요가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HRESULT &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;GetPage란 함수가 메모리를 할당해서 buffer에 반환하겠다는 의도다. 이렇게 디자인 된 함수는 통상적으로 어떤 함수를 사용해서 buffer를 해제해야 하는지를 명시하고 있는 경우가 대부분이다. buffer의 사용이 끝나면 해당 함수를 통해서 메모리 해제를 해주어야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반환 값이 WCHAR *이 된 함수다. 이 함수 또한 GetPage 내부에서 메모리 할당을 하겠다는 생각이 깔려있다. 실패한 경우에는 통상적으로 NULL이 반한되고 세부적인 원인은 GetLastError등의 별도 함수를 사용해서 알 수 있도록 디자인된 경우가 대부분이다. 또한 앞선 함수와 마찬가지로 반환 값을 어떤 함수를 사용해서 해제해야 하는지를 명시하는 경우가 대부분이다. 반환값 사용이 끝나면 해당 함수를 통해서 메모리 해제를 해주어야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HANDLE &lt;span class=&quot;token function&quot;&gt;GetPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반환 값이 HANDLE이 된 함수다. 이 경우에는 핸들을 통해서 페이지 내용을 조회할 수 있는 함수와 핸들을 닫는 함수가 존재한다는 것을 의미한다. 각각 어떤 함수를 사용해야 하는지를 명시할 필요가 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 올바른 의사 결정과 조직 구성원의 감정, 그리고 황금알을 낳는 거위]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/wp/archives/14583</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14583</guid><pubDate>Mon, 12 Jan 2015 23:59:07 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;바야흐로 평가의 계절이 돌아왔다. 사람이 사람을 평가한다는 게 참 우습지만 조직의 자원 분배라는 측면을 고려한다면 평가는 필연적일 수밖에 없다는 생각이 들기도 한다. 모두가 평등하게 보상을 받는 사회주의 시스템의 말로를 우리는 똑똑히 보았다. 유토피아적인 퐌타지를 자극하지만 인간의 욕망을 거세한 다음 남는 것은 무기력감밖에 없었다는 사실을 우리는 모두 알고 있다. 조직도 비슷하다는 생각이 든다. 회색 빛깔 조직이 되지 않으려면 아주 단순한 사실, 조직을 위해 더 기여한 사람은 더 나은 보상을 받아야 한다, 라는 사실을 상기할 필요가 있다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/archives/3803&quot;&gt;몇 해 전 여기에 관한 글을 하나 적은 기억이 난다.&lt;/a&gt; 한 3년 지났는데 지금 읽어봐도 참 공감이 간다. 그사이 내가 깨달은 한 가시 사실이 있다면 황금알을 낳는 거위의 배를 가르지 않기 위해서는 생각보다 엄청난 노력이 필요하다는 점이다. 특히나 조직이 커지면 커질수록 불가능에 가까워지는 것 같다. 지수 함수의 그것처럼 빠른 속도로 말이다. 100명, 1000명, 10000명이 되는 조직에서는 그 일이 얼마나 힘들지 상상조차 되지 않는다.&lt;/p&gt;
&lt;p&gt;최근에 나는 황금알을 낳는 거위를 보호하기 위해서 많은 노력을 했다. 다양한 사람들과 많은 이야기를 했고, 황금알을 낳는 거위가 다른 사람들이 보기에도 황금알을 낳는 거위처럼 보이도록 만들기 위한 작업들도 했다. 하지만 그런 작업들이 결코 순탄치는 않았다. 그 과정에서 더러는 유혹도 있었고, 회유도 있었고, 역설득도 있었고, 협박도 있었다. 참 이 조그만 조직 사람들을 설득하기도 쉽지 않다는 생각을 많이 했다. 나 좋자는 것도 아니고 다 잘되자는 건데 말이다. 물론 그 황금알을 낳는 거위가 없어진다고 우리가 망하진 않을 것이다. 단지 엄청나게 불편하고 느려지고 바보 같아질 뿐이겠지만 말이다.&lt;/p&gt;
&lt;p&gt;어쨌든 난 최근의 이런 경험을 통해서 한가지 사실을 깨달았다. 대부분의 조직에서 조직 구성원들이 황금알을 낳는 거위의 배를 갈라버리는 이유는 그들이 바보여서도 아니고, 그들이 정치적이어서도 아니고, 단지 배를 찢어버리는 게 그들의 삶을 더 편안하게 만들어주기 때문이란 사실이다. 마치 한약이 몸엔 좋지만 입에 쓴 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“인생은 B와 D 사이의 C다”라고 장 폴 사르트르는 말했다. B는 탄생을(Birth), D는 죽음을(Death), C는 선택을(Choice) 나타낸다. 우리 인생은 매 순간 선택의 연속이고, 그 선택의 합이 누군가의 인생이라는 말이다. 조직도 틀리지 않다. 현재 어떤 조직의 상태는 그 조직의 설립 이후 지금까지의 의사 결정의 총합이다. 그래서 올바른 의사 결정은 조직의 생존을 위해서 매우 중요하다. 특히나 작고 힘없는 조직의 경우에는 더 그렇다. 왜냐하면 여분의 버퍼가 없기 때문에 잘못된 의사 결정 한번으로 몽땅 도루묵이 돼 버릴수도 있기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;올바른 의사 결정이 조직의 생사를 결정할만큼 중요하기 때문에 조직 입장에서는 올바른 의사 결정을 내리는 것 자체가 굉장히 중요한 일이다. 따라서 올바른 의사 결정을 내리는 사람들이야 말로 조직의 관점에서는 황금알을 낳는 거위라고 부를 수 있다. 하지만 정말 아이러니하게도 조직 구성원에게는 이 황금알을 낳는 거위가 그다지 매력적으로 비춰지진 않는다. 올바른 의사 결정이 이해 당사자의 입장에서는 그다지 매력적이지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;회사에서 새로운 제품을 만들자는 의사 결정을 내렸다고 생각해보자. 새로운 제품을 만들기 위해서 신규 인력을 충원한다면 이야기가 다르겠지만 기존 조직 구성원만으로 새로운 제품을 만든다면 당연히 그 제품을 추가적으로 만들어야 하는 개발팀 입장에서는 반대할 수밖에 없다. 왜냐하면, 당장 자신들의 일이 늘어나기 때문이다. 그들의 시각에서는 새로운 제품 개발이 올바른 의사 결정이라 하더라도 탐탁지 않게 생각되는 것이다.&lt;/p&gt;
&lt;p&gt;주말에 인터넷 서핑을 하다가 회사 제품이 탑재된 게임과 관련한 취약점 정보가 공유되는 것을 보게 되었다. 그런데 이미 그 취약점은 패치된 것이었다. 월요일 출근해서는 패치 담당자들에게 패치 요청을 이야기한다. 지극히 당연한 일이 벌어진 것처럼 보인다. 하지만 패치 담당자 입장에서는 일견 기분이 나쁠 수도 있다. 갑자기 추가적인 패치를 해야 하는 일이 생긴 것이기 때문이다. 특히나 이미 패치된 취약점이 반영되지 않았다는 것은 그 사이트의 업데이트가 쉽지 않을 수도 있기 때문에 더 골치아픈 일이 생긴 것이다. 그러니 취약점이 있어서 패치를 해야 한다는 누가봐도 토를 달기 힘든 의사 결정 앞에서도 기분은 썩 좋지 않다.&lt;/p&gt;
&lt;p&gt;분석팀에서 해킹툴을 분석하다 취약점을 하나 찾았다. 런 타임에 결정돼야 하는 CRC가 링크 타임에 결정되도록 알고리즘을 만들어 둔 것이다. 물론 그 해킹툴은 이미 다른 로직을 통해서 차단이 되고 있다. 그걸 개발팀 담당자에게 가서 이야기를 한다. 이건 런 타임에 계산되야 효과가 있는데 링크 타임에 결정되니 효과가 없고 그래서 이런 취약점이 생긴다. 이 경우에 개발팀 담당자에 따라서 여러 케이스가 발생할 수 있다. 이 이야기를 이해 못하는 개발팀 담당자가 있을 수 있다. 얘가 또 왜 피곤한 이야기하지, 라고 생각하고 그냥 흘려 넘긴다. 이해는 하는데 그 해킹툴이 막힌걸 아는 담당자라면 이미 막혔는데 왜 그런 소리를 하느냐고 답변하기도 한다. 그 개발자가 문제를 제기한 분석가보다 상급자라면 최악의 경우가 생길수도 있다. 니가 뭘 안다고 이래라 저래라야, 라는 이야기를 할 수도 있다. 이랬든 저랬든 결국 모든 반응은 한 가지 지점을 가리킨다. 왜 나한테 와서 추가적인 일감을 만들어놓느냐는 것이다. 그 이야기의 옳고 그름이 중요한게 아니라 말이다.&lt;/p&gt;
&lt;p&gt;이렇듯 대다수 조직에서의 올바른 결정이란 결국 누군가를 불편하게 만드는 것이다. 누군가를 불편하게 만든다는 건 불편해지는 누군가는 그 의사 결정에 좋은 감정을 가지기가 쉽지 않다는 것을 의미한다. 그러니 조직을 위해 지속적으로 올바른 의사 결정을 내리거나 제시하는 어떤 사람이 있다면 그 사람은 광역으로 질타를 받을 가능성이 농후하다. 왜냐하면 다양한 사람들을 불편하게 만들었기 때문이다. 불편한 의사 결정의 희생양이 된 사람들은 그 의사 결정의 옳고 그름을 떠나서 자신의 일이 늘어나거나 상해버린 감정을 먼저 생각하기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;서 있으면 앉고 싶고, 앉으면 눕고 싶고, 누우면 자고 싶는게 사람 심리다. 조직도 똑같다. 새로운 변화는 두렵기 마련이고, 굴러 가면 굴러 가던대로 굴러가려는 관성이 생기게 마련이다. 그게 편하기 때문이다. 사람의 본성이 그러니 올바른 의사 결정을 싫어하는 다수를 뭐라고 할 수는 없는 노릇이다. 하지만 분명한 하나는 다수가 외면하기 때문에 올바른 의견을 제시하는 사람을 기피한다면 조직 내에는 그 누구도 좋은 의견을 제시하지 않을 거라는 점이다. 다수가 불편해지더라도, 욕먹을 각오를 하고 그런 이야기를 해주는 사람을 지지하고 보호해 줄 필요가 있다. 그래야 조직도 한걸음 전진할 수 있다.&lt;/p&gt;
&lt;p&gt;처음 소스 코드 저장소를 사용하자는 말에 직원들은 자신들의 실수를 감시하려는 목적이 아니냐는 어처구니 없는 이야기를 했었다. 빌드 시스템을 만들 때에는 귀찮게 이런 걸 왜 만드냐는 이야기를 들었다. 웹 지원 시스템을 만들 때에는 이런 게 필요하냐는 이야기를 들었고, 디자인을 바꿔야 한다는 이야기를 했을 땐 니가 하라는 소리까지 들어서 직접 하기도 했었다. 레드마인을 쓰는 과정도 순탄치는 않았고, 최근에 슬랙을 사용하자는 이야기를 했었을 땐 어처구니 없게도 대화를 감시하려는 목적이 아니냐는 이야기를 듣기도 했었다. 안드로이드 버전을 만들 땐 이런 건 돈도 안되잖아요, 라는 이야기를 수도 없이 들었다. 돈을 벌고 안 벌고는 니가 판단할 문제가 아니라는 말을 수도 없이 했었다. 돌아보면 지금은 당연한 것들이지만 그 어떤 것도 쉽지 않았다. 당연한 것들이지만 받아들여지지 않은 것도 수도 없이 많다. 그래도 그나마 나는 권한이 있기에 쉬웠다.&lt;/p&gt;
&lt;p&gt;일 더하기 일은 이다. 이렇게 말하든 저렇게 말하든 일 더하기 일은 이다. 여기서 중요한 건 일 더하기 일은 이라는 사실을 말했다는 게 중요하지 그걸 이렇게 말했느냐 저렇게 말했느냐가 중요하지는 않다. 사람에 따라서는 장황하게 말하는 걸 좋아하는 사람도 있을 수 있고, 간략하게 말하는 걸 좋아하는 사람이 있을 수도 있다. 자신의 기호에 맞다 안 맞다가 중요한게 아니다. 그 이야기를 한 사람이 자신보다 직급이 높은지 낮은지가 중요한 것도 아니다. 제일 중요한 건 그 사람이 말한 컨텐츠가 옳으냐 아니냐가 중요하다. 적어도 옳다면 그 사람 말을 진지하게 들어줄 필요가 있다. 지금 당장 실행할 수 없다고 하더라도 말이다. 그래야 하는 가장 큰 이유는 그 불편함을 만드는 바로 그 사람이 당신의 배를 채워주는 부가가치를 창출하는 사람이기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;모두가 미리부터 전사하겠노라는 말은 하지만 막상 적의 칼날이 눈앞에 닿으면 목 자르는 형틀이 뒤에 있더라도 도망쳐 버려서 죽을 수 없게 됩니다. 그것은 사와 민이 죽을 수 없어서가 아니라 위에 있는 자가 할 수 없게 했기 때문입니다. 입으로는 상을 준다 하고 주지 않으며 처벌한다고 말하고는 실행하지 않아 상과 벌이 확실치 못하기 때문에 사와 민이 죽어 주지 않는 것입니다.&lt;/p&gt;
&lt;p&gt;– 한비자&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[신의 생각]]></title><description><![CDATA[우리가 생활하는 실제 세계가 이럴지도 모른다.…]]></description><link>https://jiniya.net/wp/archives/13653</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13653</guid><pubDate>Thu, 20 Nov 2014 23:59:59 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;&apos; data-url=&apos;./신의_생각.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ece2503092ae18eaad70165843b9d399/0eb09/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADCElEQVR42hWSW28aRxiG97JqLtg57OxhZndnDywYsAOYgzks7AJeY3AMPhBjwK0jN02qRm4apZGipIrUq/Y39C/0R/bzzUgjzfd+8z7vq5AeR2du8FAnl75xW6DXAT3z7LuKeuqQuTRWBbSUaOnhuaQLnwxtNHXQQqKYa4mroKYJd3wi1bGAF+QmJBe+vauY6yJbBvrLCN36ZBvq22LpzRGf5XMzG5aRDmdtW9Fih009NOS4a5FdxO6L+lWerkOyCo3LCM1dsgrQqwivAu9D01iE7NTT5p7aNllDKFrD0hOJxoJ0TW2b125CbezufYnpOo8yh6Q2mUmy9PRt5H9s6ZmkbYskAnUtvesoqMLAAE0cfGSSuQur8ETId3W6CtFEoNgCXdS3yMwVbw/0scw1dfVYqIe62XEVsm+QkW2e5c2hRAnHQ4F7lvtbja3z1qagLT2S8tzIpJnj/lIlqUA1HXYYfVercwU3LdTn6tRmqYu7HKUcjwR/qPhXpeHfL7Kvi97r9PuBRkaCbSMy4KRloZFNW/zJcy7h1mXRuyo/0c5sNLDIxNY3kXext/h3d//f4/Tb5Xc9gmHnzDGmvjEPgK4+lMZQKjDD1lHp1w6eOMZ5qJ/5OOFowllq1/5Mk38W5bvDZzVMTiR94YM0EEGJgHY8RUWObbqJgCeOOeqaQEhtMHWfsmNX/n4Y/NE0zv1cnaIxKAq1b7LMA4TV25Y7iRQMBrYR2xRgGDcMdGTCiTsWuvaMxwP+ocrelTG0asTRscDguSdQKsy2Y8RSoQOXXAfaXYGMbVxnastgJ170vl3+NvA/tdjH5/zxObryc4mV65oERJsGmtgQFetCwzq2eFlir/boqST7DFyhsQ2tDD4fRX/F/H1Vf1uGhL3HOkSAhxxKgjMHPsgOIaqGSTLX/rFiTQO1rgMC6AxeSH5f1u6L9HWR/7TPfz4wHkrGD3tk4lCIFt60zCdgtMO1TJJz31pGPAvpxNFTaa4K3puatSvhdRjuqmJT0i7y+ZsqVIjGgl0EPPZ5P/gflnOb+c6WoaoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 0&apos; title=&apos;&apos; src=&apos;/static/ece2503092ae18eaad70165843b9d399/0eb09/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_0.png&apos; srcset=&apos;/static/ece2503092ae18eaad70165843b9d399/08678/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_0.png 190w,
/static/ece2503092ae18eaad70165843b9d399/2edd7/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_0.png 380w,
/static/ece2503092ae18eaad70165843b9d399/0eb09/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_0.png 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;우리가 생활하는 실제 세계가 이럴지도 모른다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;6월에 상당히 재미난 과학책을 한 권 읽었습니다. “신의 생각”이란 책인데, 심심하신 분들은 한번 읽어보길 권해 드리고 싶네요. 시간 가는 줄 모르고 읽게 되는 묘한 매력이 있는 책입니다. 책의 논지는 결국 모든 출발점에는 정보가 있었고, 그 정보는 아마도 숫자였을꺼라는 뭐 그런 내용입니다. 그런 생각을 가졌던 물리학자들의 발자취를 따라가는 그런 책이지요. 책을 너무 감명 깊게 읽어서 서평을 써야지 하고 있다가 늘 그렇듯이 흐지부지 되었습니다. 그렇게 한동안 잊고 있다가 오늘 Reinhard Vz님께서 공유한 유튜브 동영상을 보는데 잊었던 그 내용들이 다시금 새록새록 머릿속에 떠올라, 내친김에 몇 자 끄적여 봅니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;결국 테그마크에 따르면 ‘실재계’는 인간의 능력으로는 도저히 이해할 수 없는 심오한 수학적 실재가 인간이 의식할 수 있는 수준으로 투사된 것에 지나지 않는다. 한마디로 그것은 허상일 뿐이다. 흡사 스크린 위에 비춰진 영화의 영상과 음악, 음향이 0 또는 1의 형태로 DVD 홈에 새겨진 심오한 현실과 극명한 차이를 보이는 것처럼 말이다. 그런 의미에서 스크린 위에 투사된 영화를 진정한 ‘현실’로 인식하는 것은 망상이라 하겠다. 스크린 위에 펼쳐지는 영화는 한낱 환영일 뿐, 진정 유일한 실체는 오로지 DVD 안에 정보로만 기록되어 있다.&lt;/p&gt;
&lt;p&gt;– 신의 생각, 이고르 보그다노프,그리슈카 보그다노프&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;물론 아직까지 완전히 증명된 것은 아니지만 오늘날 π는 소위 ‘우주－수’일 가능성이 있다고 여겨진다. 그것이 무슨 의미일까? 아주 기막힌 사실을 의미한다. 한마디로 여러분은 π 속에서 여러분이 원하는 것은 무엇이든 다 찾아낼 수 있다는 말이다! 가령 여러분의 생년월일은 물론, 여러분의 모습이 찍힌 최초의 사진, 혹은 이 순간 여러분이 손에 쥐고 있는 책(커버 사진과 같은 세세한 것을 모두 포함해서)까지도 전부! 사실상 우주－수는 모든 것, 우주에 존재했던 정말 모든 것을 품고 있다. 심지어는 미래에 존재하게 될 모든 것까지도. 그저 우리가 찾고 있는 것을 암호화해놓은 숫자열을 발견할 때까지 그저 멀리, 상상할 수 없을 만큼 멀리 나아가기만 하면 된다.&lt;/p&gt;
&lt;p&gt;하지만 미국의 수학자 그레고리 카이틴이 지적한 것처럼 바로 거기에서 모든 역설이 시작된다. “π는 무한수이지만, 동시에 기하학적으로는 직선 위의 한 점에 불과하다.” 지당한 말씀이다! π란 실제 직선 위의 두 점 3.1과 3.2 사이 그 어딘가에 찍힌 작은 점, 그 이상도 이하도 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;그럼에도 다른 점과 그리 다를 것도 없는 이 ‘점’은 세계 곳곳에서 열광적인 반응을 만들어냈다. 가령 1980년대에는 ‘파이 데이’라는 기념일까지 만들어져, 매년 전세계 수학자들을 한자리에 불러 모으고 있다. 사실상 π의 탄생을 기념하겠다는 취지에서 만들어진 이 날은 π의 첫번째 세 자리 숫자(3, 1, 4)를 따서 3월 14일로 정해졌다. 흥미롭게도 이 날은 1879년 3월 14일 태어난 아인슈타인의 생일과도 겹친다.&lt;/p&gt;
&lt;p&gt;– 신의 생각, 이고르 보그다노프,그리슈카 보그다노프&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이쯤 읽고 나면 누구나 그렇듯 정말 파이에 그 모든 것이 다 들어 있을까 궁금해지기 마련이죠. 그래서 얼마나 긴 파이가 계산되었나 찾아보게 되었습니다. 아래 링크가 그런 파이 내용을 담고 있는 사이트 입니다. 그래서 그 안에서 몇몇 분들의 생년원일을 찾아봤는데 약속이나 한 것처럼 모두 그 거대한 파이 속에 있었습니다. 당연히 없는 사람들도 있겠지만 그건 어쩌면 아직 계산되지 않은건 아닐까라는 어처구니 없는 상상의 나래를 펼쳐 보기도 했습니다. 너무 심심해서 미칠 지경인 분들은 아래 사이트에서 자신의 생년월일을 한 번 찾아보는 소소한 재미를 누려 보시는 것도 좋을 것 같아요 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://piworld.calico.jp/estart.html&quot;&gt;http://piworld.calico.jp/estart.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.eveandersson.com/pi/digits/1000000&quot;&gt;http://www.eveandersson.com/pi/digits/1000000&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 302px; margin-bottom: 16px;&apos; data-url=&apos;./신의_생각.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/731916bec83ca8ffba7eda614bcc5067/83034/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 16.842105263157894%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA3UlEQVR42mMwMzOTYQACDw8PvoSEBKPo6GhbIFvZ1dXVPDY2VriwsDAiMzPTJSMjw9be3t4iNDTUPjg42ASohSs8PNwqMjIyAKgnDCgem5eXp8NgYWEhzc/PL6CmpiYCNMQJyDczNDSUDwwMtPDz8+PV0tKSU1dXl7K1tVW0s7MzdHFxMfH29ja2srIyAbJtLC0tNVRUVERVVVWlgeLSDMnJyXogFwJpoYiIiEigoZ7+/v4Gubm5/gEBAWoMUAAUE0hKSnIGYsfExET7kJAQoPIID6CvZKFKmOrr65kAEw85wM8qb7cAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 1&apos; title=&apos;&apos; src=&apos;/static/731916bec83ca8ffba7eda614bcc5067/83034/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_1.png&apos; srcset=&apos;/static/731916bec83ca8ffba7eda614bcc5067/08678/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_1.png 190w,
/static/731916bec83ca8ffba7eda614bcc5067/83034/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_1.png 302w&apos; sizes=&apos;(max-width: 302px) 100vw, 302px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;라마누잔의 파이 공식&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이게 인간의 머리에서 나올 수 있는 공식이란 말인가? 핡~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;파이 하면 또 빼놓을 수 없는 사람이 바로 라마누잔인데요. 꿈 속에서 신이 불러준 내용을 적었다는 그의 말이 진짠지 거짓인진 모르겠지만 정말 사람이 상상해 냈다고 하기엔 공식이 참 뷁스럽지요 ㅋㅋ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;사실상 몇 년 전 괴델은 불완전성 정리를 모든 우주에 적용해보는 연습을 했다. 그때 그는 우주의 의미는 우주만 가지고는 절대 알아낼 수 없다는 논리학적으로 명쾌한 결론에 도달했다. 우주 안의 의미를 발견하려면 반드시 우주 바깥의 원인이 필요했다. 한마디로 괴델은 신의 존재에 대해 자신만의 ‘증명’을 해나가는 과정에서, 요컨대 이 작업이 실은 자신이 기존 연구에서 발견한 것을 순전히 형식적인 차원에서 더욱 보강하는 것에 지나지 않는다는 사실을 깨달았다. 몇 달 뒤 그는 괴델판 ‘존재론적 증명’의 초안을 완성했다. 이 연구서에서 우리는 괴델의 논리전개 과정을 따라가다 마지막에 이런 결론에 도달하게 된다. “고로 신은 존재한다.”&lt;/p&gt;
&lt;p&gt;– 신의 생각, 이고르 보그다노프,그리슈카 보그다노프&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이런 생각을 괴델만 한 건 아닐겁니다. 논리적으로 증명한건 괴델이겠지만요 ㅋㅋ~ 중학교 땐지 고딩땐지 링이라는 소설이 유행했었는데 그때 링을 읽고는 그런 이야기를 했던 기억이 떠올랐습니다. 그때 그 친구는 우리가 살고 있는 이 세상이 어쩌면 거대한 고래 뱃속인지도 모른다고 했었던 기억이 나네요. 어쨌든 링3편의 “날 그 쪽으로 데려가줘”라는 대사는 당시엔 정말 충격과 공포 그 자체였습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 270px; margin-bottom: 16px;&apos; data-url=&apos;./신의_생각.md_2.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/eae20ca27fe9d509fc998c41cc6fc618/bf933/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 147.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGQAAAwADAAAAAAAAAAAAAAAAAAECAwQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAHkOsrnWASnKJAJ/8QAGRABAAMBAQAAAAAAAAAAAAAAAQAQMREh/9oACAEBAAEFApy3XcV8jf8A/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8BKf/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAAIBBQAAAAAAAAAAAAAAAAAQQQIgITGB/9oACAEBAAY/AiF0pMaUW//EABwQAQEAAgMBAQAAAAAAAAAAAAERACEQcYFBYf/aAAgBAQABPyGVgDjrdusnWDBZYNY/tkV4YOwnuLRBfzk8f//aAAwDAQACAAMAAAAQtxqN/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAQEf/aAAgBAwEBPxAMEXb/xAAWEQEBAQAAAAAAAAAAAAAAAAABEBH/2gAIAQIBAT8QVmDP/8QAHRABAAIDAAMBAAAAAAAAAAAAAQARITFBUWGBwf/aAAgBAQABPxAWEluf2NgBNruoBtEW68SrbUPkZxMQ0tVeBQc2e5tLltuo/wBQaMf0CpRhBX2AspXHZU//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 2&apos; title=&apos;&apos; src=&apos;/static/eae20ca27fe9d509fc998c41cc6fc618/bf933/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_2.jpg&apos; srcset=&apos;/static/eae20ca27fe9d509fc998c41cc6fc618/8ccab/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_2.jpg 190w,
/static/eae20ca27fe9d509fc998c41cc6fc618/bf933/%EC%8B%A0%EC%9D%98_%EC%83%9D%EA%B0%81.md_2.jpg 270w&apos; sizes=&apos;(max-width: 270px) 100vw, 270px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;링3 루프: 날 그쪽으로 데려가줘&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Digital physics is grounded in one or more of the following hypotheses; listed in order of decreasing strength. The universe, or reality:&lt;/p&gt;
&lt;p&gt;is essentially informational (although not every informational ontology needs to be digital)&lt;/p&gt;
&lt;p&gt;is essentially computable (the pancomputationalist position)&lt;/p&gt;
&lt;p&gt;can be described digitally&lt;/p&gt;
&lt;p&gt;is in essence digital&lt;/p&gt;
&lt;p&gt;is itself a computer (pancomputationalism)&lt;/p&gt;
&lt;p&gt;is the output of a simulated reality exercise&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://en.wikipedia.org/wiki/Digital_physics&quot;&gt;http://en.wikipedia.org/wiki/Digital_physics&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;책을 덮고나서 흥미가 생겨 위키 페이지를 살펴봤습니다. 디지털 물리학이라, 네오가 왜 갑인지 알 것 같지 않나요?! ㅋㅋㅋ~ 그리고 아래는 오늘 유튜브에서 보았다는 동영상입니다. 블랙홀의 표면에 정보가 기록된다는 부분에서 쇼름이… 핡~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;결국은 다 매트릭스?! ㅋㅋ&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] argc, argv가 필요할 때에…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/14350</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14350</guid><pubDate>Thu, 30 Oct 2014 23:59:58 GMT</pubDate><content:encoded>&lt;p&gt;우리 회사 제품 코드는 크게 커밋 정책이 두 가지로 나뉘어져 있다. 아무나 손쉽게 커밋할 수 있는 공간과 내가 리뷰를 한 다음에 머지 해주는 공간이다. 당연히 전자는 빠르고, 새로운 것들이 손쉽게 추가되는 반면 후자는 더디고 어렵게 작업된다. 프로그래머 입장에서는 후자의 경우 빠꾸(리젝) 당하는 일도 많기 때문에 얼마간 자존심이 상하는 지점이기도 하다. 하지만 난 이런 정책이 우리 제품 코드를 보다 안정적이면서 빠르게 변화할 수 있도록 만들어 준다고 생각한다.&lt;/p&gt;
&lt;p&gt;가끔, 대체로 어떤 문제가 발생했을 때, 내가 리뷰하지 않은 코드들에 대해서도 검토하는 일을 하는데 어제도 그런 일이 있었다. 그런데 생각보다 그 부분이 나에겐 다소 충격이었다. 비슷한 상황에 빠질 많은 초보 프로그래머에게 도움이 될 것 같아서 여기에 내용을 조금 옮겨 본다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;첫 번째 부분은 argc, argv였다. 윈도우 창을 띄우는 WinMain을 가진 프로그램이었는데, 프로그램 동작 과정 중에 커맨드라인 파싱 작업이 필요했던 것 같다. 그 프로그래머는 argc와 argv를 얻기 위해서 WinMain의 lpszCmdLine을 파싱하는 코드를 WinMain 내부에 작성해 두었다. 나중에 사용할 곳도 없지만 lpszCmdLine의 부족한 부분을 메우기 위해서 argv[0]는 GetModuleHandle을 사용해서 추가해주는 일도 잊지 않았다.&lt;/p&gt;
&lt;p&gt;내가 충격을 받은 점은 다음과 같은 사실이었다. 1) 그 복잡한 파싱 for 문을 왜 함수로 빼지 않았을까, 2) 그 복잡한 파싱 for 문에 왜 커맨드 라인 파싱에 대한 일체의 고려도(따옴표, 역슬래시같은) 되어 있지 않을까? 3) 왜 이렇게 단순화한 버전을 만들면서 이미 다른 사람이 만들어 둔 내용을 사용하지 않았을까?&lt;/p&gt;
&lt;p&gt;즉, 결론은 이랬다. 그 파싱 구문들은 굉장히 부적절하고 아주 많은 경우에 잘못된 파싱 결과를 가져오는 코드였다. 실제로 그 프로그램은 argv[1]만 필요로 하기 때문에 심지어는 lpszCmdLine을 직접 평가하는 작업이 더 적절했을 수도 있다. 이런 여러가지 가능성을 제쳐두고 그 프로그래머는 아주 조악한 코드를 자신이 직접 만드는 길을 선택했다.&lt;/p&gt;
&lt;p&gt;argc, argv가 필요한 윈도우 프로그램을 만든다면 &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dn727674.aspx&quot;&gt;__argc, __argv, __wargv&lt;/a&gt; 같은 좋은 지원 도구들이 있다. 직접 만들 필요가 없다. 이미 검증된 파싱 루틴을 통해서 우리가 원하든 원하지 않든 WinMain이 시작되는 지점에 이미 그 데이터는 우리가 사용할 수 있도록 모두 준비되어 있다. 그러니 그저 가져다 쓰기만 하면 된다. 바퀴를 새로 만들고 이미 다 파싱해 놓은 걸 다시 또 파싱하겠다고 호기를 부릴 필요는 없다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;내가 두번째로 충격을 받은 부분은 한 곳이 더 있었는데 아래와 같은 코드였다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__argc &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__argc &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;도대체 드 모르간의 법칙을 생각나게 하는 이 코드는 무엇일까? 이 코드를 이해하기 위해서는 얼마간 에디터의 도움이 필요했다. 마지막 괄호를 지웠다 다시 썼을 때 에디터가 그 닫기 괄호가 어디에 매핑되는지를 알려주었기 때문이었다. 에디터의 도움이 없었다면 난 다시 스페이스를 사용해서 이 조건문의 실제 의미를 일일이 파악해야 했으리라.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__argc &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; __argc &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;대체로 많은 경우에 괄호가 없도록 조건문을 구성하는 것이 훨씬 읽기 쉬운 코드를 만든다. 위 코드는 에디터의 도움이 없이도 쉽게 의미하는 바를 눈치챌 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__argc &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;의미를 고려한다면 그 조건문은 위와 같이 더 단순화 될 수도 있다. 왜냐하면 그 코드는 argv[1]에 접근 할 수 있는지를 검증하기 위한 용도로 사용되고 있었기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;같은 현상을 설명하는 두 개의 주장이 있다면, 간단한 쪽을 선택하라&lt;/p&gt;
&lt;p&gt;given two equally accurate theories, choose the one that is less complex&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://ko.wikipedia.org/wiki/%EC%98%A4%EC%BB%B4%EC%9D%98_%EB%A9%B4%EB%8F%84%EB%82%A0&quot;&gt;오컴의 면도날&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;오컴의 면도날이라는 말이 있다. 난 이 말이 프로그래밍에도 적용된다고 생각한다. 대부분의 경우에 간단한 쪽을 선택하는 편이 읽기도 좋고, 단순하며, 안정적인 좋은 코드를 만든다. 그래서 래리 월(펄의 창시자) 아저씨가 최고의 프로그래머 덕목 중 하나로 게으름을 꼽았는지도 모르겠다. 게으른 사람은 적어도 남들이 만든 걸 또 만들거나, 단순한 걸 두고 복잡한 걸 선택하지는 않을 테니 말이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[반갑다(?!), 윈10]]></title><description><![CDATA[많은 이들의 기대를 저버리고 윈9이 아닌 윈10이 출시됐습니다. 어제 윈도 10이 발표됐습니다. 많은 사람들의 윈 9일거라는 추측을 무너뜨리고 9은 건너뛰고 10이 출시됐습니다. 왜 1…]]></description><link>https://jiniya.net/wp/archives/14318</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14318</guid><pubDate>Thu, 02 Oct 2014 23:59:57 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; margin-bottom: 16px;&apos; data-url=&apos;./반갑다(!),_윈10.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f4f5107eebbfee7583cbdf7be879fb7c/5d5ad/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 104.21052631578948%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAE2ElEQVR42k2Re1SSZxzHn8CpLW1zTtO1ss1qbantdL8sp55sq86s/iixnVq1mVEuNQUBBVRgXvBWkuDSoLQ8ZqbCC+8LL/CimIDghcvQEiqbW01FzdzZads57tVT257zeZ7/Puf7/L4/0Oac+H3a02Ppt/T295h7H4088UxNT0xOTkxOeaampmdmpp/Pn/HJ6b9nJ5Pujq+6NOq0W202G34B5pqc++uF6ye7y2F12QeG+i1P7jsfDzoeOu1PBu1TT38eGx/77dmzP2Y8c3MvTraOh1eMuJ1W67xuA/RG/WW0P/Om7mwtkipR4y/5Gppap/peoj7T1E2uV18RSvjV9fRmezk6EskfCsy3Q129gw477oNobnMgvc2XDoO0dpAunSet3fei1JuFJbrnou9YHSei1WQSODe6ImfsfMvzZdxfi9rMDwdt/bicUKMMZMJv58J+DAWBAhEpMiIVImZKCdmKXbec2y5r2SfI1LM5Pum/1Btf1vW89Mt7ViazuAdtA7h8WtwWwlb45yBeVAhkyXAWZUoBDXk/WQK/GZG69sQO7tB6hj04e5QNv4wRzXqzx8qhXrdzQU6olIblI34MGODOv3I2HExuqF1/IPmzc5vSFVEZ6pVUZ0Tuw+VU91v0B6VS86vkpOyuDQy1PwteQleAzHmZkCUFFCTsgrgjYaOOFG1K3CZOTNi5R3b2iJJyqvPLOKSq2TA8ZB8YsILdnKZPOFBQHurPeC3PJ6tWnxOOJG2dNWr+bKqQH47ZGw9rGt0GaDQxXltxU++677DZ7GAzrz04V4a37UODCBQZjhcFnxmXRY9IW54K2B7qIfnR+Pg4qCilszD53tE4dYlE04mp5HIF2MppD2LIgtgqvPBFWf99e9UFcVdijObQDuPBKPHXR3bth04moKQ96i/2avgNGKaG5QoYxAq6PuCigSyld/brtnE5SxGQcauEV1QpEF4qqTicnMErrOaViZg/XErK4HKutWCoEkYQEF+jCOdBi+mIL00OXiXLwEXoY3arpJBRX10m5LJYqcdUN0XwtYomAftGo4R/oxVqb+vuNoDYK3cii6VLc1RL6P+TM6HVjNYi8nkhryTtm+9SD+5jp5ClVT/eZmY2XK4Ttmi0GqXZYga7S6Wr8qE3qHJ8z4soMpz5mRnK0ONXdXGpmtgL6MZvNdtSsK0k/WaSPiS2YWVCjQS5pzXrlAawsSZtk0C8prArtAAJLVAtoAzlYO8y6iPSt0fSYqJYOz9lHok6c2flqcawU40rUpr5LXpbr8lgNAH/PEFg3u2AXDSACQcwkQUU7+Rii5kicAWAq0RwCwDxRwSanaYf5/bNgDIn567Rqrd06/uAH00byERD8hF8w8QFvCjtRIqKQKsOECwNqXtvsQQQRet8KeZa09Nmh8enpJ91W69HNVKZClR2DhtHPJhrAnNPaF0T2uFx1f0x0+PZ442toBz4iLyBBADhWh+KxSunh5DXBwr6yiDjY4elr8cIKFJHpc5VjA4Vqx9UYMOVHQ9qDYOCDvcxiSKYn7W88nhQ+elIUcGHvK5lnM4Art4nv4N8Qy9WmKplJrC/5t4WPraBq1zHVX8lMmwvVSZeRzYUoaQqxeZi6YHrhZ9Xqfhtln0i3ZoSXUR55/ryjrWlWDhfG87X/gOpT6o40ubMLwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         10 md 0&apos; title=&apos;&apos; src=&apos;/static/f4f5107eebbfee7583cbdf7be879fb7c/5d5ad/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_0.png&apos; srcset=&apos;/static/f4f5107eebbfee7583cbdf7be879fb7c/08678/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_0.png 190w,
/static/f4f5107eebbfee7583cbdf7be879fb7c/2edd7/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_0.png 380w,
/static/f4f5107eebbfee7583cbdf7be879fb7c/5d5ad/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_0.png 610w&apos; sizes=&apos;(max-width: 610px) 100vw, 610px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;많은 이들의 기대를 저버리고 윈9이 아닌 윈10이 출시됐습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;어제 윈도 10이 발표됐습니다. 많은 사람들의 윈 9일거라는 추측을 무너뜨리고 9은 건너뛰고 10이 출시됐습니다. 왜 10인가에 대한 여러가지 억측 유머가 난무한 날이기도 했지요. 티맥스 윈도우 9 때문에 10이 됐다는 설, 8.1이 실제는 9이었다는 설, 맥 운영체제 버전에 맞추기 위해서 10을 했다는 설, 기존에 9이라고 알려진 걸 너무 많이 뜯어고치다 보니 완전 새로운 운영체제가 돼서 10을 했다는 설등 온갖 설들이 난무했습니다. 물론 진실은 안드로메다에 있겠지요. 어쨌든 발표된 윈도 10은 기존의 8 시리즈에서 지적됐던 많은 문제들을 개선했고, 또 새로운 기능이 다수 추가된 아주 혁.신.적.인 운영체제라고 합니다. 흥망은 뚜껑열어봐야 알겠지만요. MS의 발표에 따르자면 그렇다는 겁니다.&lt;/p&gt;
&lt;p&gt;MS 말이 사실인지 확인하기 위해서 저도 테크니컬 프리뷰를 설치해 보았습니다. 윈도 10을 먼저 경험해 보고 싶으신 분들은 &lt;a href=&quot;http://windows.microsoft.com/en-us/windows/preview-iso&quot;&gt;여기&lt;/a&gt;에서 다운받아 설치해 보시면 되겠습니다. 일단 설치하고 가장 눈에 띄는 건 시작 버튼이 돌아온 거네요. 저에겐 크게 필요하진 않았던 부분이지만 인상적이긴 한 것 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./반갑다(!),_윈10.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c21f574b63bc0892c53a481c368e9b33/dface/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 101.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACa0lEQVR42pWTzYrUQBDH84yCFx/Bh/AFvAviZRG8CJ714kFFcEEQdz52MpnufKfT3ekk3Z3ufE0y1syg7MoeZv8URTXkR9W/uuM8/7B79s59crV++vYWihcfQ4RDd7Pbeb7nYUYFpeJm4d0sdwuIFVqu8NYLEQrSlDooiP04X22xi6M0F4SVVVXjNPDjQCo97edx2Pf9OAzjcM6n6LoeslNwzhgthRBFYY0py9Jqm3S57NV+2jd9045tN3ZQQLaDOR733TiNUDi/F8s4TgCNwqiua900Rpu4JXpo7GCpzmUn67bmDWcNY5oKU6hODfvhDC/W61uEEOeFOkobbeM2b0ZTWYEEZg1vB6t7XdoSMChghMNJThCEQRhB1FKZtqtqdYbPnau2og0bp+HwkJySJiREaeB1TXWY2s6qRhm/yWRfz4dxPszn+Aecjn/hl5/Iq8/Zm2tz9bN/fd29/6WVNL5Ng1wm0YHTimWME37MtFBSzXc7XyP1dUm+rNj3TfFtU/zYMC1hYVlWyJxNBa9L4ElR0VpybXV7b+wIbyPk0jSUguqSGy2VMrnNVF/VXc0tl4OklsJuH/CMEN5sXIR8QvIsI6wQjbJBm+WlqQT4O+pkdJ6maZ7mu3KSOE7TVBTwRorTSxFwW+3Uj/C4jrr/+fwfnCR4B9eMovCoNCVKN4fL5PgYb91tFEXxSSTLldaXwpTSNEmyLMvBdJ5zfhz7UhhG3Xm7wA+SCNpmQRBJqS4e2w/c243nedCYEALrg7u6FGaUJXEC/WFz8Hsxxh/hGfbsbb04ScjJsxDlIzwDgBFyXRdjDM7Lsroc/gNv6mmr4U+T2AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         10 md 1&apos; title=&apos;&apos; src=&apos;/static/c21f574b63bc0892c53a481c368e9b33/dface/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_1.png&apos; srcset=&apos;/static/c21f574b63bc0892c53a481c368e9b33/08678/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_1.png 190w,
/static/c21f574b63bc0892c53a481c368e9b33/2edd7/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_1.png 380w,
/static/c21f574b63bc0892c53a481c368e9b33/dface/%EB%B0%98%EA%B0%91%EB%8B%A4(!)%2C_%EC%9C%8810.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;우리는 또 수많은 비공개 구초체를 한땀한땀 추가해야 할 뿐이고…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;시스템 프로그래머 입장에서 새로운 운영체제 발표는 사실 그닥 달갑지는 않은 일입니다. 왜냐하면 운영체제의 비공개된 부분을 사용하기 때문에 그걸 또 죄다 조사해서 맞춰주어야 하거든요. 어려운 작업은 아닌데 단순하고 무식하며 반복적이고 타이핑 실수가 발생하면 엄청나게 골치아파지는 그런 까탈스런 부분이죠. 그래서 설레임보다는 두려움이 앞서기도 합니다. 하지만 포스의 어두운 면과 밝은 면은 항상 공존하는 것처럼 제품을 판매하는 입장에서는 좋은 일이기도 합니다. 허들이 하나 더 추가되는 것이거든요. 왜냐하면 새로 진입하려는 사람들 입장에서는 새로운 운영체제를 추가적으로 지원해야 하는 부담감이 생기게 되는 것이고, 유사 제품을 만드는 회사들에게도 발빠르게 대응하지 않으면 먼저 지원한 제품에게는 차별적인 마케팅 포인트를 내주는 셈이 되기도 하거든요. 아직도 윈 10이 지원되지 않는 보안 제품을 사용하고 계신가요? 뭐 이런거죠? ㅋㅋ~&lt;/p&gt;
&lt;p&gt;직업 프로그래머로 있었던 동안에 지원해야 했던 윈도 클라이언트 운영체제는 95, 98, 2000, XP, VISTA, 7, 8, 8.1에 이어서 아홉번째로 10인데요. 어떤 느낌의 운영체제일지 궁금하네요. 제발 내부적으로 크게 바뀌지 않았기를 미리 빌어봅니다. MS개발자느님들 저에게 자비쩜. 1년에 한번은 좀 빡쎄지 않나요(??!!)…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[예제의 중요성, 복붙 프로그래밍의 위험성]]></title><description><![CDATA[ExampleSlot의 핸들릭을 가진 해킹툴 프로그램 간만에 해킹툴을 하나 살펴보고 있었습니다. 특징적인 게 메일슬롯을 사용하는데 ExampleSlot이란 이벤트 핸들릭이 있었습니다. ExampleSlot…]]></description><link>https://jiniya.net/wp/archives/14297</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14297</guid><pubDate>Mon, 15 Sep 2014 23:59:56 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 615px; margin-bottom: 16px;&apos; data-url=&apos;./예제의_중요성,_복붙_프로그래밍의_위험성.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e3ecb55b5ef191219a83bbfc50df7699/8ab79/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 94.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAIAAAAf7rriAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACq0lEQVR42oVTa1ObQBTN//8R2k5n/NBa66i109hqYpKqIYGwPJbHAlleIYCJFQivJHRJ1H7QtDtnLnDZM/ee+2i8O/i6d3K3d9LfP6P2T6n3Z8ODJnfU1T93tBrdDTra1vOpgw5b8OOVeHTcPvzwpcHxChRlCFUJqhAqAi+RF1lCqqJLEoKiKsuaqurkgoaw7XhBMHucx+lDZIy9huUGvu+7Djm253lFUZRlWRR5uXmQkxPkeZZlxBLfarVcrVZVtbb83w3Hu1ftwJol06g0rMl9OE/iNErS2A8TwMeilHFCnmR5scyy4gWLeDF2g4bpBGNspllWVRUejwEA7IilOY5vt6VWi6KZYEhXeb4mv9e12Z5lUWgWIbshSZukRFxTz0NIU2RZ1nX19tagKFE35rxQZdlrMiJk64lcEJc3mSAVKbJCyBoh9/uipj3w/G6yE5qmtU3bMk0AuKe0Wy14fU2xIByxO8lEM8Y4TdNaM8YsyzI0PWAB+HkptFt3zChgmNeaV8/kkHRoq9nzJgiRxsqSpm3SvhMRmnPc68hlniPTrzWHQbjVPJ1ODcMgshHGRLA5HMrG+EF4o2CLOFbwtCZb1l/NHOAAC2iOF1pteN2hwP80m6TPaU02MQa1ZmYIOO7ySmy3+yM2YEZv9vmp2q47yTaRXdclgqEIBUVRej3t5gbI8gxw/+pzEATZ85Douo5UVcNY7/fxYFBrJkOy6cUb1SaRbdvZRnZsSxQEgeNZEUqdjtLt0jx/z4Kd1R7bvm05ruuF4cwwsCyroigJkqoMae38XPnetJsXcz+I4iR6jKIorpGQvUnq2SZbVC1XWZzmSVos8jItymxri5KsYF4WKfnM18XyBYSZPkY2WcmrHjNkIcXAwQgOGHEXqGeQaxetX6fffhw3e38AZ6ECiuy6o5EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                       md 0&apos; title=&apos;&apos; src=&apos;/static/e3ecb55b5ef191219a83bbfc50df7699/8ab79/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_0.png&apos; srcset=&apos;/static/e3ecb55b5ef191219a83bbfc50df7699/08678/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_0.png 190w,
/static/e3ecb55b5ef191219a83bbfc50df7699/2edd7/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_0.png 380w,
/static/e3ecb55b5ef191219a83bbfc50df7699/8ab79/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_0.png 615w&apos; sizes=&apos;(max-width: 615px) 100vw, 615px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;ExampleSlot의 핸들릭을 가진 해킹툴 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;간만에 해킹툴을 하나 살펴보고 있었습니다. 특징적인 게 메일슬롯을 사용하는데 ExampleSlot이란 이벤트 핸들릭이 있었습니다. ExampleSlot이라고 네임드 이벤트 이름을 지은 것도 웃긴데, 핸들릭도 어처구니 없는 그런 해킹툴이었죠. 메일슬롯으로 아주 중요한 데이터가 오가는 것 같아서 관련 함수를 살펴보고 있었습니다. 그러다 이 모든 시츄에이션을 설명해주는 MSDN 예제를 만나게 되었습니다. 그제서야 해커가 왜 그런 ㅂㅅ같은 짓을 했는지 자연스럽게 이해가 되더군요. MSDN 예제를 그대로 복사, 붙여넣기 했는데 그 예제에 핸들릭이 있었던 것이죠. 아무 생각없이 사용하다 벌어지는 정말 웃픈 상황이었습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 505px; margin-bottom: 16px;&apos; data-url=&apos;./예제의_중요성,_복붙_프로그래밍의_위험성.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8aef95a0fa5b38e69c21f4eb6d307eff/eccca/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 81.57894736842105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABx0lEQVR42pVT25KrIBD0/78yUTHGIPfhLtlWs9mtPJzaM4UUIk3PdI/dVmsIIeWSUwp7eO+Dc1RrJU8pJbxjDj54ooKTRBkjp9ZaF2Iex5Gvd2MNmxgbxxUhZIhRKYlNxDlpJZM1JGVQypOrdeu29vQ+3u/e2DTPk5Ri27bn36KrteDWy4WvwizLPaaIXaT0no9ox/oY7RgnOMY4z3N/vfT95TbdkGoIL/wb3J6fizdztc5xzok8alsePMb0j1QPfDtv6aAb2HwIJRcsrLXOWikEJDn3U0nCSROMIuWC/WR2zk63qe97xtgwDEpKuIJyiBysM6RndWfidpPTohdJSpKkSDsYDzQDZoBjjMHk1n6p3Zr2+mEeD8OBxOL6uFLyZSsvcCkA99d+APnu04/Iu2zWa8BmzYVdZzWPgtXv27vzjJArqNEcnK+o+Tcz6hQkZ72sduWW51p+agZT8MkYTd6XUk/Aa36n8G37p1XoaqLgrIHOOefn/wSYEfXs3gD+ldMqgtJo4GNoj06WCnmhB5USSmocxa/yVntjI775mQ2K8xpTibHGWGIoMdW0v0JUGBEj/roAJAzewSXng/y5bQ1bW2t/T/sLkIqgdyZe7yYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                       md 1&apos; title=&apos;&apos; src=&apos;/static/8aef95a0fa5b38e69c21f4eb6d307eff/eccca/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_1.png&apos; srcset=&apos;/static/8aef95a0fa5b38e69c21f4eb6d307eff/08678/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_1.png 190w,
/static/8aef95a0fa5b38e69c21f4eb6d307eff/2edd7/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_1.png 380w,
/static/8aef95a0fa5b38e69c21f4eb6d307eff/eccca/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_1.png 505w&apos; sizes=&apos;(max-width: 505px) 100vw, 505px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;CloseHandle은 배고플 때 먹으려고 아껴두었죠.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://msdn.microsoft.com/ko-kr/library/windows/desktop/aa365785(v=vs.85).aspx&quot;&gt;핸들릭을 가진 MSDN 예제&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;언젠가 발표자료에서 보았던 이 그림이 생각나더군요. 생각 없이 코딩하는 프로그래머가 너무 많은 것 같습니다. 생각을 합시다. 머리는 폼으로 달려있는 건 아니잖아요. 물론 남 말 할 때는 아니지만 말입니다. 어쨌든 복사, 붙여넣기 할 때에는 그 코드가 어떤 코드든지, 누가 작성한 코드든지 한번 더 꼼꼼히 검토해 봐야 한다는 걸 잊지 맙시다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; margin-bottom: 16px;&apos; data-url=&apos;./예제의_중요성,_복붙_프로그래밍의_위험성.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5642ad9b69de58a3af34cba1232491db/407f2/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADdUlEQVR42mMImHQ/ad6jhDmP4uc8Spj7KG72QyAjaubD2DmPUuY/jgYyZj8CkklzH4MEZz1MW/A4bjZIgf+k+wwWdWfCJlyKmHg5buqV+KlXUmZeTZ5xNaT/UtSkSwnTLidOA4pfjpxwMXnGlchJIMHUmVeTpl8L7rtkUn2KoW39/aY198DoQf3q+w2r7zeueQBkN6191LLhafumZ83rnrSsf9K49lHzukdNax83rH4IVNy89j5QI8OBqx8OXPuw/+qnPScuHDt76vTFCxu27VizadvOA7sXLp0/ceqkLVvXrtuw8vCJg6fPHjl9csexsxcOXP984Op7oEaGQ1ffH7r67uDVjweO7r96ce+pY1sOH1i7Z/faY0fW5mf4Whkq5Ce51BSF7N859dy+6ae2tZ44uuXg9a9ALUCNDOfvfTh/7/35+5+PnTowZ1Z3TEx4RnpcbXXR6tWz+jrzI4Pso0PsCtP8J5X6bZ6QcGJr55mTO84/+Hr+7nugRoZbTz7dfPzh9rPvR45sjIu0FxDgERHk5uRg8vOxWDK3sroyMczL0tdc3dNMI8pUZEmN6+ljm28/+3Hr8QegRob7zz/fffrx2bvfk6dO8fJyVlSQFhcTlpIU1VSX93E393Y3tzIz0dXSsjAzsVEXjbUU7Omoe/7x/92nH4AaQZrvPP306u2XpAknJYJblBTEZWUl1FSktLUULUw0vF0Mw/3sbEzN9ZXkgrQk/HWFi8qK33z5f+cJTPPdZ59fvfqUseOb4ZL75vZ2QgJcUrLSSooy8jKiyjJyphqGVupKMSYy/UGqZa6iMfGJb76iaX75MWHlba19P0yC42SkZNLjw6I9Df1M1KwUNe10NV315Tx0xOKtJcocuLuqsp6hOfv1+5/RhY2iy89rePjLScvZmmo1pTrURpvneGvF2ymkuyo5aApbKIlG67DObcl+iqL5yQegSwL8QxgsPVQN9WUk+Pn5Of3cDSJ8jPwsZKzV+V10+QylWDVE2LW4GMrSYl6B/PwepPneM2Bof3r0+sfaTTu7u/sXLVm2cvXqeQsWLly8ZNmKFdNmzp0+e96EqbP6J03r65/c0ty8dv3mx29+ASMIqJHhyeuvQPT41ZdXH3+///H/9ed/rz7+ff3pL5Dx5vPfd1/+A9H7b//fff3/9ss/IPnyw2+gYoguAG06EBzXQ2dwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                       md 2&apos; title=&apos;&apos; src=&apos;/static/5642ad9b69de58a3af34cba1232491db/407f2/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_2.png&apos; srcset=&apos;/static/5642ad9b69de58a3af34cba1232491db/08678/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_2.png 190w,
/static/5642ad9b69de58a3af34cba1232491db/2edd7/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_2.png 380w,
/static/5642ad9b69de58a3af34cba1232491db/407f2/%EC%98%88%EC%A0%9C%EC%9D%98_%EC%A4%91%EC%9A%94%EC%84%B1%2C_%EB%B3%B5%EB%B6%99_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98_%EC%9C%84%ED%97%98%EC%84%B1.md_2.png 520w&apos; sizes=&apos;(max-width: 520px) 100vw, 520px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;생각 없는 프로그래머가 너무 많아요. 머리는 폼이 아니라는거~ ㅋㅋ&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[MmIsAddressValid와 PTE]]></title><description><![CDATA[다른 메모리에 접근할 일이 많은 보안 드라이버에서 자주 사용되는 함수 중에 하나가 MmIsAddressValid 함수다. MmIsAddressValid…]]></description><link>https://jiniya.net/wp/archives/14290</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14290</guid><pubDate>Mon, 15 Sep 2014 23:59:55 GMT</pubDate><content:encoded>&lt;p&gt;다른 메모리에 접근할 일이 많은 보안 드라이버에서 자주 사용되는 함수 중에 하나가 MmIsAddressValid 함수다. MmIsAddressValid 함수는 접근하려는 메모리가 제대로 된 메모리인지 검사하는 코드다. 그런데 이 함수에서 말하는 valid의 의미는 생각보다 많이 좁다. 단순히 할당되서 접근할 수 있는 메모리를 의미하는 것이 아닌 실제로 물리 메모리에 존재하는 것들에 대해서만 valid 하다고 판단하기 때문이다. 즉, 페이지 아웃된 메모리는 접근할 수 있지만 MmIsAddressValid 함수는 FALSE를 리턴한다는 말이다.&lt;/p&gt;
&lt;p&gt;그렇다면 페이지 아웃된 메모리까지 넓혀서 접근 가능한 커널 메모리를 체크하려면 어떤 방법이 있을까? 의외로 방법이 없는 것으로 추정(?!) 된다. ProbeForRead 같은 함수를 생각해 볼 수 있는데 해당 함수는 사용자 메모리에 대한 접근 여부를 체크하는 함수다. 커널 메모리를 넣으면 그냥 예외를 발생시키도록 설계돼 있다. 그.래.서. 결국 커널 영역 메모리의 할당 여부를 체크하려면 PDE, PTE를 직접 체크하는 수 밖에는 없다. 아마도…&lt;/p&gt;
&lt;p&gt;직접 체크하는 방법을 구현하려면 PDE, PTE 따위의 구조외 윈도우에서 그것들을 어디에다 매핑시키는지 주소 공간 따위를 알아야 한다. 이게 또 처음 접해보면 다소 생소한 부분이다. 그때 참고하면 도움이 될만한 글이 있어서 소개해본다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blogs.msdn.com/b/ntdebugging/archive/2010/02/05/understanding-pte-part-1-let-s-get-physical.aspx&quot;&gt;PTE 이해하기 1편&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blogs.msdn.com/b/ntdebugging/archive/2010/04/14/understanding-pte-part2-flags-and-large-pages.aspx&quot;&gt;PTE 이해하기 2편&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blogs.msdn.com/b/ntdebugging/archive/2010/06/22/part-3-understanding-pte-non-pae-and-x64.aspx&quot;&gt;PTE 이해하기 3편&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[가상 함수 테이블 보호하기]]></title><description><![CDATA[클라이언트 코드 보안은 여러모로 복마전 같은 느낌이 강하다. CPU…]]></description><link>https://jiniya.net/wp/archives/14277</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14277</guid><pubDate>Fri, 05 Sep 2014 23:59:54 GMT</pubDate><content:encoded>&lt;p&gt;클라이언트 코드 보안은 여러모로 복마전 같은 느낌이 강하다. CPU가 최종적으로 코드를 실행 시키기 때문에 사실상 해커가 코드를 분석하는 것을 완전하게 막는 방법은 없다. 게다가 현대적인 프로그램들은 이미 그 규모가 어마어마하게 크기 때문에 어떤 지점에서 어떤 공격이 벌어질지 사실상 예측하는 것이 불가능하다고 할 수 있다. 이런 이유로 클라이언트 코드 보안 영역에서는 줄기차게 해커와 경쟁을 벌일 수 밖에 없는 구조다. 상황이 이렇다보니 사실상 코드 보안에 대한 해법 보다는 해커와의 비용 경쟁으로 귀결되는 경우가 많다. 그래서 여기엔 해법(solution) 보다는 완화 방안(mitigation method)이 주를 이룬다.&lt;/p&gt;
&lt;p&gt;최근 몇 년 사이 가장 각광받는 클라이언트 코드 공격 기술 중의 하나가 가상 함수 테이블 후킹 기법이다. 이 기법이 유행하게 된 데는 여러가지 이유가 있겠지만 가장 큰 이유는 공격 대상을 찾기가 쉽다는 것과, 한번 찾으면 쉽게 바뀌지 않는다는 점이라고 할 수 있다. 거대한 소프트웨어를 만들기 위해서는 필연적으로 레고 블록 같은 컴포넌트 기술이 발전할 수 밖에 없다. 그런 컴포넌트 기법 중에 사실상 업계 표준이 된 것은 COM이다. COM의 ABI(application binary interface)가 C++의 가상 함수 테이블의 구조로 이루어졌기에 광범위한 곳에서 C++의 가상함수 테이블과 유사한 바이너리 체계를 사용하게 되었다. 컴포넌트 인터페이스가 가지는 또 하나의 주요한 특징은 한번 정의되고 나면 바꾸기가 쉽지 않다는 점이다. 왜냐하면 여기저기 얽혀있는 경우가 많고, 심지어는 외부의 모듈들이 내부 컴포넌트를 참조하는 경우도 있기 때문이다. 이런 사실은 결국 해커 입장에서는 한번 공격하면 오랫동안 지속시킬 수 있다는 것을 의미하기 때문에 공격 비용이 낮아진다는 것과 같은 말이 된다. 해커 입장에서는 아주 빨대를 꽂기에 좋은 지점이지만 방어하는 입장에서는 한두군데가 아니기 때문에 아주 뼈아픈 지점이다.&lt;/p&gt;
&lt;p&gt;그럼 실제로 공격이 어떤 방법으로 이루어지고 그걸 또 어떤 방식으로 방어할 수 있는지 알아보도록 하자. [리스트 1] 에는 간단한 가상 함수 테이블을 후킹하는 코드가 나와 있다. ICharacter 클래스는 체력을 구하는 GetHP 함수와, 체력을 설정하는 SetHP 함수를 가지고 있다. main을 살펴보면 캐릭터를 생성하고 10씩 체력을 감소시켜 가기 때문에 코드가 정상적으로 수행됐다면 90부터 0까지 값이 출력되어야 한다. 하지만 예제에서는 GetHP 함수를 HookGetHP로 대체했기 때문에 체력이 줄어들지 않고 모두 100으로 출력된다. 이런 원리로 게임에서 무적 핵이 만들어지곤 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 vftable 후킹 예제&lt;/strong&gt;
&lt;a href=&quot;/codewiz/assets/files/2015/vftablehook.cpp&quot;&gt;소스 코드 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ICharacter&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;GetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;SetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; hp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Romeo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ICharacter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; hp_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;Romeo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; hp_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;GetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hp_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;SetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; hp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; hp_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;HookGetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HookVftable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID obj&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; vf_idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID hook_fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;or_fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG_PTR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;xobj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; obj&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG_PTR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;vft &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; xobj&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;or_fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;or_fn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; vft&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;vf_idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG oldp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;VirtualProtect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;vft&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;vf_idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hook_fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;oldp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	vft&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;vf_idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; hook_fn&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;VirtualProtect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;vft&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;vf_idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hook_fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; oldp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;oldp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ICharacter &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;chr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Romeo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;HookVftable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HookGetHP&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		chr&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chr&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; chr&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서도 말했지만 이런 코드 공격은 게임에서만 벌어지는 것은 아니다. 인터페이스가 존재하는 모든 프로그램들이 공격 대상이 될 수 있다. 특히나 웹 브라우저 같은 프로그램은 해커에게 아주 좋은 먹잇감이 되곤 한다. Internet Explorer 10 버전부터는 이러한 가상 함수 테이블 변조를 방지하기 위해서 주요 인터페이스 코드에 VTGuard란 것이 적용되었다.&lt;/p&gt;
&lt;p&gt;VTGuard의 원리는 간단하다. 가상 함수 테이블 끝에 추가적인 필드를 붙여서 중간의 함수 메소드 값이 변경되었는지 검사하는 방식이다. [그림 1]에 나와 있는 것과 같이 테이블 끝에 vtguard에 해당하는 값을 넣어서 중간에 값이 변경되었는지 검사할 수 있다. vtguard에 VirtualMethod1, 2, 3, 4, …의 CRC 값이 담겨 있다면 앞선 가상 함수들이 호출될 때 테이블의 무결성을 검증할 수 있다. 물론 그 검증하는 코드는 모든 가상 함수의 앞쪽에 붙어 있어야 할 것이다. 물론 이 VTGuard라는 기법 자체도 가상 함수 변조를 완전히 막는 솔루션은 아니다. 왜냐하면 해커가 가상 함수의 값을 변경하고, 그에 맞춰서 vtguard의 값도 업데이트 한다면 우회할 수 있기 때문이다. 서두에 언급한 것과 같이 가상 함수 변조를 조금 더 어렵게 만드는 취약점 완화 방안이라고 생각하면 될 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 257px; margin-bottom: 16px;&apos; data-url=&apos;./가상_함수_테이블_보호하기.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f33f6b9c4ebcfc343dad793545c985a9/7101e/%EA%B0%80%EC%83%81_%ED%95%A8%EC%88%98_%ED%85%8C%EC%9D%B4%EB%B8%94_%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 71.57894736842105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADgUlEQVR42kWS21NTVxyF8wf5UocWxci0L0yrTKmQIncRofAHoBVoxxlkcKiWixkBaakwpUVuTcJFAlhMQu6ggdxvtMpNmISLaB86rXz9nfPShzVn77XPXufbax+NVqulra2Nrq77dHZ2cl+vp7u7m56eHlEvvb2ihw/p6+2hr+8Hfuzvp180ODjIT48eMTAwIOMBhoaGaG1tRZOTk0MiHsPtdrJkteDzPcdiWcRmteJ22FldWyUUChCLxUgkYjjsSyx7PdjtNjweN6FgEJfbzeHhIaOjo2i057MZM5oxTi0wYZpj3DjLyMQMY4ZZxkWG6adMzT5TNW22YJS5YWpe9sxx57t2bly/TmNjk3rK+vp6NFnnP2HBd8CcZ5sZxwYzrg3mV3aYXFrHZE0yMutjaMrHpH0Dw7MERmuCx2Y/qzvQ2NKJLv8LKq9epby8nJqaGgnUfozVv89K8i9ckSM8sTd448e4o0e4wgc4QmkcwX3c4rvEU3ybf4+1Tbh1R09JUaEEfUVtbS11dXVozkrgU19aCLeE8CVPnK8we7eELobJEmdsbpVfZ3zMODdUYpM1zmOh9qyf8G2rnstfFlB17RrXRCrhmXPZWANpniff4YkKnZAsJ96xHH+r0jiCKZyhA3VNmSvrVjmvfwsJ7KJQl68euaqqiurqajSZWdnMK4TeHaYVQvemEG5jsMTUvsYXAgw/WZNuNzHZ1lVv4vcw9vg/NLV0SYd5XLlSSWVlpRqqyTyrxaYQJt6qFB6hWJHxcuIYT+QQR2BPCPdV3xM9lI6lQ982wdfQdLuD/Et5VFRUqFJCNR+eOcf8ixRm6XBy6Q/p6hWzQjmxGJZbjTE27+eX6RdMS4dG6VTR8MwKjuR7Gpo7uJSXS1lZmSolVJORmYUt8oZoCgI7J4R2Ub+uSJkHX58Q3kP1/9d7Ivtws7mdvM8vUlpaJipVQzUZGR/hdMQJh1P4/bsEAruEZByNHhD077Dm2yIaSRMJK0oRlAr84sfjR/JD3yY39wLFxcUUFRVRUlIit3z6NMfLLvgzwUkiAutx/vavkLYtcuSyk3YuceR1si/PlNMGySj/xkLwMsm9hq/J+ewClwsLKRQpoZoPTp3C1NLMYsf3LLbfw3y3DUNHN5N3OxluusnPDQ2M3PqG3+QdY0sL9gd6rPouvD0PuCG3+unFXHQFBeh0OjX0Py0cSWssySt4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;               md 0&apos; title=&apos;&apos; src=&apos;/static/f33f6b9c4ebcfc343dad793545c985a9/7101e/%EA%B0%80%EC%83%81_%ED%95%A8%EC%88%98_%ED%85%8C%EC%9D%B4%EB%B8%94_%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/f33f6b9c4ebcfc343dad793545c985a9/08678/%EA%B0%80%EC%83%81_%ED%95%A8%EC%88%98_%ED%85%8C%EC%9D%B4%EB%B8%94_%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0.md_0.png 190w,
/static/f33f6b9c4ebcfc343dad793545c985a9/7101e/%EA%B0%80%EC%83%81_%ED%95%A8%EC%88%98_%ED%85%8C%EC%9D%B4%EB%B8%94_%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0.md_0.png 257w&apos; sizes=&apos;(max-width: 257px) 100vw, 257px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;그림 1 vtguard 구조&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;가상 함수 테이블 변조가 프로그램의 심각한 취약점이 되면서 많은 컴파일러들이 VTGuard와 유사한 메커니즘을 속속 추가하고 있다. 보안 프로그래머 입장에서는 새로운 방어 기법과 컴파일러 옵션을 이해하는 것도 중요하지만 가장 원론적인 구성 원리를 체득하기 위해서는 그 메커니즘을 직접 구현해 보는 것이 가장 좋다. [리스트 2]에는 VTGuard를 구현할 수 있는 기본적인 매크로를 추가해 두었다. 살펴보면 가상 함수 끝에 엔트리를 추가하기 위해서 DECL_VT_GUARD라는 것을, vtguard 값의 초기화를 위해서 생성자에는 INIT_VT_GUARD를, 그리고 모든 멤버 함수 앞에는 가상 함수 테이블의 무결성을 검증하기 위한 CHECK_VT_GUARD 매크로가 추가됐다. 각각의 매크로를 구현해서 [리스트 1]의 코드와 연결했을 때 프로그램이 정상적으로 실행되지 않도록 만들어 보자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 VTGuard의 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Romeo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ICharacter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; hp_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;Romeo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;INIT_VT_GUARD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; hp_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;GetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CHECK_VT_GUARD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hp_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;SetHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; hp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CHECK_VT_GUARD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; hp_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;DECL_VT_GUARD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;덧) 여러분의 해법을 기다리고 있답니다. 썩 잘 만들었다고 생각하신다면 codewiz at gmail dot com으로 보내주세요. &lt;a href=&quot;http://www.jiniya.net/wp/archives/12367&quot;&gt;함께 할 만한 일이 있을지도 모르잖아요&lt;/a&gt; ^^;;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[윈도우 2k: kernel32, ntdll 함수 덤프]]></title><description><![CDATA[MSDN 도움말에서 윈도우 2000이 사라진지 참 오래됐지요. 그럼에도 불구하고 여전히 윈도우 2000에서 돌아가는 프로그램을 만들어야 하는 개발자라면 과연 이 API가 윈도우 200…]]></description><link>https://jiniya.net/wp/archives/14265</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14265</guid><pubDate>Thu, 04 Sep 2014 23:59:53 GMT</pubDate><content:encoded>&lt;p&gt;MSDN 도움말에서 윈도우 2000이 사라진지 참 오래됐지요. 그럼에도 불구하고 여전히 윈도우 2000에서 돌아가는 프로그램을 만들어야 하는 개발자라면 과연 이 API가 윈도우 2000에 있는건지 없는건지 참 헷갈리는 경우가 많습니다. 그래서 써야 할까 말아야 할까? 동적 바인딩을 해야할까? 그냥 써도 될까? 궁금한거죠. 그러다 까딱 잘못하면 뭐 함수를 찾을 수 없다는 엄청난 오류에 봉착하곤 합니다. 그래서 매번 테스트 해보거나 윈도우 2000에서 dependency walker에 넣어서 보곤 했는데요. 귀찮아서 한번 덤프를 떠봤습니다. 저같은 고민을 하는 개발자라면 도움이 될지도 모르겠습니다. 윈도우 2000에 포함된 kernel32.dll과 ntdll.dll에 포함된 함수 덤프 정보입니다. 다소 스압이 있을지도 모르니 주의하시길 ㅋ~&lt;/p&gt;
&lt;p&gt;덧) 특정 DLL의 익스포트 함수 목록을 추출하는 방법이 궁금하신 분들은 &lt;a href=&quot;/codewiz/assets/files/2015/dump_eat.7z&quot;&gt;dump_eat 프로젝트 소스 코드를&lt;/a&gt; 다운로드 받아보세요.&lt;/p&gt;
&lt;h3&gt;kernel32.dll 정보&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// kernel32.dll
   1 0001B65B AddAtomA
   2 0000DF58 AddAtomW
   3 0004639D AddConsoleAliasA
   4 00046366 AddConsoleAliasW
   5 00047187 AllocConsole
   6 000355B2 AllocateUserPhysicalPages
   7 00016C75 AreFileApisANSI
   8 00045AF4 AssignProcessToJobObject
   9 0002B9F6 BackupRead
  10 0002BC52 BackupSeek
  11 0002C5B9 BackupWrite
  12 0002ABAC BaseAttachCompleteThunk
  13 0002C7D7 Beep
  14 000423C9 BeginUpdateResourceA
  15 000421D2 BeginUpdateResourceW
  16 0003C271 BindIoCompletionCallback
  17 00044B59 BuildCommDCBA
  18 00044AE3 BuildCommDCBAndTimeoutsA
  19 00044A90 BuildCommDCBAndTimeoutsW
  20 00044B09 BuildCommDCBW
  21 000374F3 CallNamedPipeA
  22 000028B5 CallNamedPipeW
  23 000382B3 CancelDeviceWakeupRequest
  24 00030DFA CancelIo
  25 0003C4D4 CancelTimerQueueTimer
  26 0000301C CancelWaitableTimer
  27 0003C38F ChangeTimerQueueTimer
  28 0003DF83 ClearCommBreak
  29 0003DF91 ClearCommError
  30 00005C50 CloseConsoleHandle
  31 00009168 CloseHandle
  32 0001F8CB CloseProfileUserMapping
  33 00021580 CmdBatNotification
  34 0003DB27 CommConfigDialogA
  35 0003DA4B CommConfigDialogW
  36 0001076D CompareFileTime
  37 0000D3D4 CompareStringA
  38 0000E2FB CompareStringW
  39 00009A1D ConnectNamedPipe
  40 000040CC ConsoleMenuControl
  41 0002DDC9 ContinueDebugEvent
  42 00004856 ConvertDefaultLocale
  43 00020E6C ConvertThreadToFiber
  44 000146C0 CopyFileA
  45 000324D4 CopyFileExA
  46 00014736 CopyFileExW
  47 00020069 CopyFileW
  48 0004876A CreateConsoleScreenBuffer
  49 000239D8 CreateDirectoryA
  50 0002E0A8 CreateDirectoryExA
  51 0001F9FD CreateDirectoryExW
  52 0001DFF5 CreateDirectoryW
  53 00014CEA CreateEventA
  54 0001B259 CreateEventW
  55 00020D7E CreateFiber
  56 00020D96 CreateFiberEx
  57 000157E2 CreateFileA
  58 0000C8DA CreateFileMappingA
  59 000143E4 CreateFileMappingW
  60 0000C351 CreateFileW
  61 00045CFA CreateHardLinkA
  62 00045D4D CreateHardLinkW
  63 000099CD CreateIoCompletionPort
  64 0004594B CreateJobObjectA
  65 000459B0 CreateJobObjectW
  66 00016DA5 CreateMailslotA
  67 00016CAF CreateMailslotW
  68 0000A4F6 CreateMutexA
  69 0001D584 CreateMutexW
  70 00036D7A CreateNamedPipeA
  71 00022806 CreateNamedPipeW
  72 000206B1 CreatePipe
  73 0001C0A0 CreateProcessA
  74 0001BF86 CreateProcessInternalA
  75 00011BA0 CreateProcessInternalW
  76 00038628 CreateProcessInternalWSecure
  77 0000B252 CreateProcessW
  78 000133C3 CreateRemoteThread
  79 00006890 CreateSemaphoreA
  80 0001EAD5 CreateSemaphoreW
  81 0004583F CreateTapePartition
  82 000095C2 CreateThread
  83 0003C31A CreateTimerQueue
  84 0003C33B CreateTimerQueueTimer
  85 0003C50F CreateToolhelp32Snapshot
  86 00006DC4 CreateVirtualBuffer
  87 00002FE4 CreateWaitableTimerA
  88 00020B94 CreateWaitableTimerW
  89 0002DDFB DebugActiveProcess
  90 0002D9F6 DebugBreak
  91 000303DF DefineDosDeviceA
  92 000148BE DefineDosDeviceW
  93 00057090 DelayLoadFailureHook
  94 0000DFA9 DeleteAtom
  95          DeleteCriticalSection =&gt; NTDLL.RtlDeleteCriticalSection
  96 00020E22 DeleteFiber
  97 0001BEEA DeleteFileA
  98 0000D9F9 DeleteFileW
  99 0003C4B0 DeleteTimerQueue
 100 0003C41B DeleteTimerQueueEx
 101 0003C3D0 DeleteTimerQueueTimer
 102 00041972 DeleteVolumeMountPointA
 103 00041B33 DeleteVolumeMountPointW
 104 0001D626 DeviceIoControl
 105 0001C912 DisableThreadLibraryCalls
 106 00009A9D DisconnectNamedPipe
 107 0002D1D3 DnsHostnameToComputerNameA
 108 0002D13B DnsHostnameToComputerNameW
 109 00007B91 DosDateTimeToFileTime
 110 00039A1B DosPathToSessionPathA
 111 00017417 DosPathToSessionPathW
 112 00005C98 DuplicateConsoleHandle
 113 0000E960 DuplicateHandle
 114 00042746 EndUpdateResourceA
 115 000425DA EndUpdateResourceW
 116          EnterCriticalSection =&gt; NTDLL.RtlEnterCriticalSection
 117 0004ACB8 EnumCalendarInfoA
 118 0004ACD4 EnumCalendarInfoExA
 119 0004D407 EnumCalendarInfoExW
 120 0004D3EB EnumCalendarInfoW
 121 0004AD06 EnumDateFormatsA
 122 0004AD1E EnumDateFormatsExA
 123 0004D423 EnumDateFormatsExW
 124 0001814F EnumDateFormatsW
 125 0004AEB0 EnumLanguageGroupLocalesA
 126 0004D3A9 EnumLanguageGroupLocalesW
 127 0003695F EnumResourceLanguagesA
 128 00023BC7 EnumResourceLanguagesW
 129 0003673A EnumResourceNamesA
 130 00001530 EnumResourceNamesW
 131 00036545 EnumResourceTypesA
 132 00036ADD EnumResourceTypesW
 133 0004AEE0 EnumSystemCodePagesA
 134 0004D3D9 EnumSystemCodePagesW
 135 0004AE9A EnumSystemLanguageGroupsA
 136 0004D393 EnumSystemLanguageGroupsW
 137 00017BA1 EnumSystemLocalesA
 138 00018127 EnumSystemLocalesW
 139 0004ACF0 EnumTimeFormatsA
 140 00018139 EnumTimeFormatsW
 141 0004AECA EnumUILanguagesA
 142 0004D3C3 EnumUILanguagesW
 143 00045813 EraseTape
 144 0003E1AD EscapeCommFunction
 145 0000E01A ExitProcess
 146 00005F3B ExitThread
 147 000031EF ExitVDM
 148 00017208 ExpandEnvironmentStringsA
 149 0001A0EC ExpandEnvironmentStringsW
 150 0004699E ExpungeConsoleCommandHistoryA
 151 00046990 ExpungeConsoleCommandHistoryW
 152 00035E47 ExtendVirtualBuffer
 153 00039397 FatalAppExitA
 154 00039350 FatalAppExitW
 155 000393DE FatalExit
 156 0000D1B2 FileTimeToDosDateTime
 157 0000EA21 FileTimeToLocalFileTime
 158 000095E2 FileTimeToSystemTime
 159 000045A6 FillConsoleOutputAttribute
 160 0004872D FillConsoleOutputCharacterA
 161 0004874D FillConsoleOutputCharacterW
 162 00016410 FindAtomA
 163 0002EAD1 FindAtomW
 164 0000EE4B FindClose
 165 0001B2CF FindCloseChangeNotification
 166 000249A2 FindFirstChangeNotificationA
 167 0001B6AB FindFirstChangeNotificationW
 168 0001D88F FindFirstFileA
 169 00030748 FindFirstFileExA
 170 0000C96C FindFirstFileExW
 171 00007770 FindFirstFileW
 172 0004048D FindFirstVolumeA
 173 00040738 FindFirstVolumeMountPointA
 174 00040B52 FindFirstVolumeMountPointW
 175 00003F28 FindFirstVolumeW
 176 00023D67 FindNextChangeNotification
 177 00010275 FindNextFileA
 178 0000CCB3 FindNextFileW
 179 000405CC FindNextVolumeA
 180 00040C5F FindNextVolumeMountPointA
 181 00040EB5 FindNextVolumeMountPointW
 182 00021E34 FindNextVolumeW
 183 0001D38D FindResourceA
 184 00014B2C FindResourceExA
 185 0000B82D FindResourceExW
 186 0000B622 FindResourceW
 187 00004052 FindVolumeClose
 188 0001B2CF FindVolumeMountPointClose
 189 000045C3 FlushConsoleInputBuffer
 190 0001C9CC FlushFileBuffers
 191 0001132B FlushInstructionCache
 192 0000E2C6 FlushViewOfFile
 193 0004AD44 FoldStringA
 194 0001AD12 FoldStringW
 195 00016DEF FormatMessageA
 196 00006DA1 FormatMessageW
 197 0004739A FreeConsole
 198 0000A8A4 FreeEnvironmentStringsA
 199 0000A8A4 FreeEnvironmentStringsW
 200 0000DFDA FreeLibrary
 201 0000FFE9 FreeLibraryAndExitThread
 202 0000754C FreeResource
 203 000355D9 FreeUserPhysicalPages
 204 00006E63 FreeVirtualBuffer
 205 00048E8F GenerateConsoleCtrlEvent
 206 0000FE74 GetACP
 207 00023F24 GetAtomNameA
 208 0000DF68 GetAtomNameW
 209 0003EFCA GetBinaryType
 210 0003EFCA GetBinaryTypeA
 211 00020F84 GetBinaryTypeW
 212 0000B732 GetCPInfo
 213 0004AEF2 GetCPInfoExA
 214 00050CF3 GetCPInfoExW
 215 0004A4C6 GetCalendarInfoA
 216 00004EDC GetCalendarInfoW
 217 0003E2AE GetCommConfig
 218 0003E43C GetCommMask
 219 0003E4BA GetCommModemStatus
 220 0003E538 GetCommProperties
 221 0003E5E9 GetCommState
 222 0003E87C GetCommTimeouts
 223 00014B16 GetCommandLineA
 224 0001386F GetCommandLineW
 225 00031D43 GetCompressedFileSizeA
 226 00031D64 GetCompressedFileSizeW
 227 0001631F GetComputerNameA
 228 00001779 GetComputerNameExA
 229 0001C5F7 GetComputerNameExW
 230 0000F7C8 GetComputerNameW
 231 00046505 GetConsoleAliasA
 232 000468F9 GetConsoleAliasExesA
 233 0004663F GetConsoleAliasExesLengthA
 234 00046637 GetConsoleAliasExesLengthW
 235 000468E7 GetConsoleAliasExesW
 236 000464E0 GetConsoleAliasW
 237 000467B3 GetConsoleAliasesA
 238 000465D2 GetConsoleAliasesLengthA
 239 000465C4 GetConsoleAliasesLengthW
 240 0004679D GetConsoleAliasesW
 241 0000465B GetConsoleCP
 242 00049746 GetConsoleCharType
 243 00046C80 GetConsoleCommandHistoryA
 244 00046B0A GetConsoleCommandHistoryLengthA
 245 00046AFC GetConsoleCommandHistoryLengthW
 246 00046C6A GetConsoleCommandHistoryW
 247 00022291 GetConsoleCursorInfo
 248 00049911 GetConsoleCursorMode
 249 000220DB GetConsoleDisplayMode
 250 00048C35 GetConsoleFontInfo
 251 00048D5C GetConsoleFontSize
 252 000479C5 GetConsoleHardwareState
 253 00046D91 GetConsoleInputExeNameA
 254 00046E12 GetConsoleInputExeNameW
 255 00047478 GetConsoleInputWaitHandle
 256 00004710 GetConsoleKeyboardLayoutNameA
 257 000494F7 GetConsoleKeyboardLayoutNameW
 258 0000C0DA GetConsoleMode
 259 00049554 GetConsoleNlsMode
 260 0000C16D GetConsoleOutputCP
 261 0001CEAA GetConsoleScreenBufferInfo
 262 00046D2A GetConsoleTitleA
 263 0000EDB2 GetConsoleTitleW
 264 00049505 GetConsoleWindow
 265 0004AA47 GetCurrencyFormatA
 266 00053056 GetCurrencyFormatW
 267 00048DC4 GetCurrentConsoleFont
 268 00015813 GetCurrentDirectoryA
 269 0001BAC7 GetCurrentDirectoryW
 270 0001E0C8 GetCurrentProcess
 271 0000B8F4 GetCurrentProcessId
 272 00015633 GetCurrentThread
 273 000110D1 GetCurrentThreadId
 274 00017A38 GetDateFormatA
 275 00018893 GetDateFormatW
 276 0003DCE2 GetDefaultCommConfigA
 277 0003DC06 GetDefaultCommConfigW
 278 00055438 GetDefaultSortkeySize
 279 0003824E GetDevicePowerState
 280 0000ACF8 GetDiskFreeSpaceA
 281 0001AE60 GetDiskFreeSpaceExA
 282 0001AE8E GetDiskFreeSpaceExW
 283 0000AD29 GetDiskFreeSpaceW
 284 0000A6B4 GetDriveTypeA
 285 000067A7 GetDriveTypeW
 286 0001092C GetEnvironmentStrings
 287 0001092C GetEnvironmentStringsA
 288 0000733F GetEnvironmentStringsW
 289 0000614F GetEnvironmentVariableA
 290 0000BB88 GetEnvironmentVariableW
 291 0001BC2B GetExitCodeProcess
 292 0001F362 GetExitCodeThread
 293 00015134 GetFileAttributesA
 294 0003112C GetFileAttributesExA
 295 0001DCC7 GetFileAttributesExW
 296 0001B5CE GetFileAttributesW
 297 0000B0C4 GetFileInformationByHandle
 298 0001D0D4 GetFileSize
 299 0001D109 GetFileSizeEx
 300 00005E40 GetFileTime
 301 0001544F GetFileType
 302 00007A45 GetFullPathNameA
 303 00005D07 GetFullPathNameW
 304 000356C0 GetHandleInformation
 305 00048ADF GetLargestConsoleWindowSize
 306 0001278D GetLastError
 307 00055456 GetLinguistLangSize
 308 000106E0 GetLocalTime
 309 0000A132 GetLocaleInfoA
 310 00007786 GetLocaleInfoW
 311 00037D4E GetLogicalDriveStringsA
 312 000029BF GetLogicalDriveStringsW
 313 0000E4DB GetLogicalDrives
 314 00040164 GetLongPathNameA
 315 00021A72 GetLongPathNameW
 316 00035CB6 GetMailslotInfo
 317 00014C44 GetModuleFileNameA
 318 00010FB7 GetModuleFileNameW
 319 0000AB06 GetModuleHandleA
 320 00010182 GetModuleHandleW
 321 00036F92 GetNamedPipeHandleStateA
 322 00037071 GetNamedPipeHandleStateW
 323 00037290 GetNamedPipeInfo
 324 00021179 GetNextVDMCommand
 325 00011191 GetNlsSectionName
 326 0004A825 GetNumberFormatA
 327 00022C57 GetNumberFormatW
 328 000489D7 GetNumberOfConsoleFonts
 329 00048A26 GetNumberOfConsoleInputEvents
 330 00048B85 GetNumberOfConsoleMouseButtons
 331 00011562 GetOEMCP
 332 0001449E GetOverlappedResult
 333 00039573 GetPriorityClass
 334 0000ACAE GetPrivateProfileIntA
 335 00015F45 GetPrivateProfileIntW
 336 0002F005 GetPrivateProfileSectionA
 337 0002EAE1 GetPrivateProfileSectionNamesA
 338 0002EAFA GetPrivateProfileSectionNamesW
 339 00023726 GetPrivateProfileSectionW
 340 0000EC3E GetPrivateProfileStringA
 341 0000D957 GetPrivateProfileStringW
 342 0002EB13 GetPrivateProfileStructA
 343 0002EC24 GetPrivateProfileStructW
 344 0000E6A9 GetProcAddress
 345 000173D7 GetProcessAffinityMask
 346 0000AC86 GetProcessHeap
 347 00016C9C GetProcessHeaps
 348 000398B6 GetProcessIoCounters
 349 00039883 GetProcessPriorityBoost
 350 00039617 GetProcessShutdownParameters
 351 00039692 GetProcessTimes
 352 0001C933 GetProcessVersion
 353 00039705 GetProcessWorkingSetSize
 354 00011538 GetProfileIntA
 355 00016420 GetProfileIntW
 356 0002EF51 GetProfileSectionA
 357 00023710 GetProfileSectionW
 358 0000C905 GetProfileStringA
 359 0000AB2B GetProfileStringW
 360 0000FE7A GetQueuedCompletionStatus
 361 0001A1E1 GetShortPathNameA
 362 0001E1CC GetShortPathNameW
 363 000149DF GetStartupInfoA
 364 00017109 GetStartupInfoW
 365 0000AF0D GetStdHandle
 366 00017B2B GetStringTypeA
 367 000223CA GetStringTypeExA
 368 00017CB0 GetStringTypeExW
 369 00006658 GetStringTypeW
 370 00019A86 GetSystemDefaultLCID
 371 00015150 GetSystemDefaultLangID
 372 0001F14B GetSystemDefaultUILanguage
 373 0000EDED GetSystemDirectoryA
 374 0000FF1C GetSystemDirectoryW
 375 0001AAA4 GetSystemInfo
 376 000207D1 GetSystemPowerStatus
 377 000069F9 GetSystemTime
 378 0002D737 GetSystemTimeAdjustment
 379 000072E5 GetSystemTimeAsFileTime
 380 00019796 GetSystemWindowsDirectoryA
 381 000078B2 GetSystemWindowsDirectoryW
 382 000458A5 GetTapeParameters
 383 0004578F GetTapePosition
 384 00045934 GetTapeStatus
 385 000070D4 GetTempFileNameA
 386 0001D962 GetTempFileNameW
 387 00013B81 GetTempPathA
 388 00006476 GetTempPathW
 389 00003050 GetThreadContext
 390 0000C1C4 GetThreadLocale
 391 0000A545 GetThreadPriority
 392 0003BB69 GetThreadPriorityBoost
 393 0002DFF6 GetThreadSelectorEntry
 394 00020D1E GetThreadTimes
 395 00015594 GetTickCount
 396 0001796C GetTimeFormatA
 397 0001B481 GetTimeFormatW
 398 00015177 GetTimeZoneInformation
 399 000115AD GetUserDefaultLCID
 400 000115AD GetUserDefaultLangID
 401 0001E96D GetUserDefaultUILanguage
 402 0003F3F3 GetVDMCurrentDirectories
 403 0001EB3A GetVersion
 404 00013C2D GetVersionExA
 405 0000E8A7 GetVersionExW
 406 0001199F GetVolumeInformationA
 407 000109E7 GetVolumeInformationW
 408 00040ECB GetVolumeNameForVolumeMountPointA
 409 000076EC GetVolumeNameForVolumeMountPointW
 410 00041E15 GetVolumePathNameA
 411 00041F32 GetVolumePathNameW
 412 00009C00 GetWindowsDirectoryA
 413 0000B810 GetWindowsDirectoryW
 414 00035668 GetWriteWatch
 415 0000E2B6 GlobalAddAtomA
 416 0000727B GlobalAddAtomW
 417 000116B4 GlobalAlloc
 418 0003599B GlobalCompact
 419 0001596E GlobalDeleteAtom
 420 00009F88 GlobalFindAtomA
 421 0000CC0B GlobalFindAtomW
 422 000354A9 GlobalFix
 423 00015B74 GlobalFlags
 424 000132AF GlobalFree
 425 000248EE GlobalGetAtomNameA
 426 0000DF91 GlobalGetAtomNameW
 427 00014344 GlobalHandle
 428 0001E6AF GlobalLock
 429 00009D2A GlobalMemoryStatus
 430 000025DB GlobalMemoryStatusEx
 431 00007416 GlobalReAlloc
 432 00014286 GlobalSize
 433 000354E2 GlobalUnWire
 434 000354BE GlobalUnfix
 435 0000B426 GlobalUnlock
 436 000354D3 GlobalWire
 437 0003C6D1 Heap32First
 438 0003C590 Heap32ListFirst
 439 0003C63F Heap32ListNext
 440 0003C7DD Heap32Next
 441          HeapAlloc =&gt; NTDLL.RtlAllocateHeap
 442 000073F4 HeapCompact
 443 0001AE05 HeapCreate
 444 00035A18 HeapCreateTagsW
 445 00014567 HeapDestroy
 446 000359EE HeapExtend
 447          HeapFree =&gt; NTDLL.RtlFreeHeap
 448 00035B0E HeapLock
 449 00035A31 HeapQueryTagW
 450          HeapReAlloc =&gt; NTDLL.RtlReAllocateHeap
 451          HeapSize =&gt; NTDLL.RtlSizeHeap
 452 00035A4D HeapSummary
 453 00035B21 HeapUnlock
 454 00035AA1 HeapUsage
 455 0001B240 HeapValidate
 456 00035B34 HeapWalk
 457 0002EAAA InitAtomTable
 458 0001BE13 InitializeCriticalSection
 459 00015157 InitializeCriticalSectionAndSpinCount
 460 0000A96D InterlockedCompareExchange
 461 0001C23D InterlockedDecrement
 462 00008FBC InterlockedExchange
 463 00013E7C InterlockedExchangeAdd
 464 0001C22C InterlockedIncrement
 465 000488FC InvalidateConsoleDIBits
 466 000150C4 IsBadCodePtr
 467 00006AE2 IsBadHugeReadPtr
 468 0000A4E6 IsBadHugeWritePtr
 469 0000F0F7 IsBadReadPtr
 470 0001BE4B IsBadStringPtrA
 471 000159F3 IsBadStringPtrW
 472 0001A055 IsBadWritePtr
 473 0000CC8D IsDBCSLeadByte
 474 0001871B IsDBCSLeadByteEx
 475 0000191E IsDebuggerPresent
 476 000062D7 IsProcessorFeaturePresent
 477 0003828B IsSystemResumeAutomatic
 478 000060C4 IsValidCodePage
 479 0004BF19 IsValidLanguageGroup
 480 00017D7E IsValidLocale
 481 00017859 LCMapStringA
 482 00019CA1 LCMapStringW
 483          LeaveCriticalSection =&gt; NTDLL.RtlLeaveCriticalSection
 484 000105CF LoadLibraryA
 485 00010606 LoadLibraryExA
 486 0001A952 LoadLibraryExW
 487 000152C5 LoadLibraryW
 488 00038FAD LoadModule
 489 0000A63A LoadResource
 490 0001C13B LocalAlloc
 491 0003599B LocalCompact
 492 000163DF LocalFileTimeToFileTime
 493 0002A48E LocalFlags
 494 0001C1C6 LocalFree
 495 0002A594 LocalHandle
 496 000128A2 LocalLock
 497 00014F2B LocalReAlloc
 498 000359B0 LocalShrink
 499 000154D4 LocalSize
 500 000127F8 LocalUnlock
 501 0001E4E4 LockFile
 502 00030C21 LockFileEx
 503 0001154E LockResource
 504 00035600 MapUserPhysicalPages
 505 00035627 MapUserPhysicalPagesScatter
 506 00006533 MapViewOfFile
 507 0001D74A MapViewOfFileEx
 508 0003CE25 Module32First
 509 0003CD6F Module32FirstW
 510 0003CF91 Module32Next
 511 0003CEF1 Module32NextW
 512 0001ED51 MoveFileA
 513 0001274C MoveFileExA
 514 00001CDA MoveFileExW
 515 000166A0 MoveFileW
 516 00010C86 MoveFileWithProgressA
 517 00010CF0 MoveFileWithProgressW
 518 00009BBA MulDiv
 519 000078FF MultiByteToWideChar
 520 00011138 NlsConvertIntegerToString
 521 00019071 NlsGetCacheUpdateCount
 522 0004BEF8 NlsResetProcessLocale
 523 00017658 OpenConsoleW
 524 00019184 OpenDataFile
 525 00014EDA OpenEventA
 526 0001162C OpenEventW
 527 0000BF59 OpenFile
 528 0000C1D1 OpenFileMappingA
 529 0000C222 OpenFileMappingW
 530 00045A17 OpenJobObjectA
 531 00045A84 OpenJobObjectW
 532 0001AFA6 OpenMutexA
 533 0001AFF7 OpenMutexW
 534 000091B9 OpenProcess
 535 0001DB3A OpenProfileUserMapping
 536 0001F491 OpenSemaphoreA
 537 00013D96 OpenSemaphoreW
 538 0003BAC1 OpenThread
 539 0003A5F7 OpenWaitableTimerA
 540 0003A664 OpenWaitableTimerW
 541 00024539 OutputDebugStringA
 542 0002D9FC OutputDebugStringW
 543 00047D60 PeekConsoleInputA
 544 00047D7C PeekConsoleInputW
 545 0003730E PeekNamedPipe
 546 00001B4D PostQueuedCompletionStatus
 547 000457E7 PrepareTape
 548 000166F6 PrivCopyFileExW
 549 000319F6 PrivMoveFileIdentityW
 550 0003CA16 Process32First
 551 0003C960 Process32FirstW
 552 0003CB70 Process32Next
 553 0003CAD0 Process32NextW
 554 0001A355 ProcessIdToSessionId
 555 00020B6D PulseEvent
 556 0003E916 PurgeComm
 557 0001651F QueryDosDeviceA
 558 0000A2A6 QueryDosDeviceW
 559 00045B3C QueryInformationJobObject
 560 0000AA7D QueryPerformanceCounter
 561 00016F20 QueryPerformanceFrequency
 562 000301F1 QueryWin31IniFilesMappedToRegistry
 563 000030AB QueueUserAPC
 564 00020F64 QueueUserWorkItem
 565 0000A48C RaiseException
 566 000220AB ReadConsoleA
 567 0002225C ReadConsoleInputA
 568 00047DB4 ReadConsoleInputExA
 569 00047DD1 ReadConsoleInputExW
 570 00047D98 ReadConsoleInputW
 571 000044D6 ReadConsoleOutputA
 572 0004854A ReadConsoleOutputAttribute
 573 0004850C ReadConsoleOutputCharacterA
 574 0004852B ReadConsoleOutputCharacterW
 575 00048098 ReadConsoleOutputW
 576 00023603 ReadConsoleW
 577 000144DA ReadDirectoryChangesW
 578 00006582 ReadFile
 579 00030D56 ReadFileEx
 580 00030E21 ReadFileScatter
 581 00022AA8 ReadProcessMemory
 582 00049B85 RegisterConsoleIME
 583 000499D5 RegisterConsoleOS2
 584 00004116 RegisterConsoleVDM
 585 0000C6DC RegisterWaitForInputIdle
 586 00020ECB RegisterWaitForSingleObject
 587 0003C1B8 RegisterWaitForSingleObjectEx
 588 000025A2 RegisterWowBaseHandlers
 589 00003243 RegisterWowExec
 590 000117F4 ReleaseMutex
 591 0001565A ReleaseSemaphore
 592 00023D98 RemoveDirectoryA
 593 00023DB0 RemoveDirectoryW
 594 00001EE4 ReplaceFile
 595 0003492C ReplaceFileA
 596 00001EE4 ReplaceFileW
 597 00038295 RequestDeviceWakeup
 598 00038230 RequestWakeupLatency
 599 0000BF41 ResetEvent
 600 0003569A ResetWriteWatch
 601 0000BEE4 ResumeThread
 602          RtlFillMemory =&gt; NTDLL.RtlFillMemory
 603          RtlMoveMemory =&gt; NTDLL.RtlMoveMemory
 604          RtlUnwind =&gt; NTDLL.RtlUnwind
 605          RtlZeroMemory =&gt; NTDLL.RtlZeroMemory
 606 000492A5 ScrollConsoleScreenBufferA
 607 000492C2 ScrollConsoleScreenBufferW
 608 0000E540 SearchPathA
 609 00019BA4 SearchPathW
 610 00050B1F SetCPGlobal
 611 0004A5F8 SetCalendarInfoA
 612 0004CB09 SetCalendarInfoW
 613 0003E995 SetCommBreak
 614 0003E9A3 SetCommConfig
 615 0003EA34 SetCommMask
 616 0003EACA SetCommState
 617 0003EDE7 SetCommTimeouts
 618 0002D025 SetComputerNameA
 619 0002D0EB SetComputerNameExA
 620 0002CF5E SetComputerNameExW
 621 0002CA9A SetComputerNameW
 622 00048EF9 SetConsoleActiveScreenBuffer
 623 000493B4 SetConsoleCP
 624 00046C96 SetConsoleCommandHistoryMode
 625 00017814 SetConsoleCtrlHandler
 626 0004776D SetConsoleCursor
 627 00049020 SetConsoleCursorInfo
 628 000498AE SetConsoleCursorMode
 629 00048FC3 SetConsoleCursorPosition
 630 00047871 SetConsoleDisplayMode
 631 000492F5 SetConsoleFont
 632 00047A89 SetConsoleHardwareState
 633 00049352 SetConsoleIcon
 634 00046EA7 SetConsoleInputExeNameA
 635 0001E9B1 SetConsoleInputExeNameW
 636 00047B19 SetConsoleKeyShortcuts
 637 00049808 SetConsoleLocalEUDC
 638 000493A9 SetConsoleMaximumWindowSize
 639 00047BBF SetConsoleMenuClose
 640 00006076 SetConsoleMode
 641 00049699 SetConsoleNlsMode
 642 00046A60 SetConsoleNumberOfCommandsA
 643 00046A4E SetConsoleNumberOfCommandsW
 644 00049A2C SetConsoleOS2OemFormat
 645 000494AE SetConsoleOutputCP
 646 00047C16 SetConsolePalette
 647 00048F66 SetConsoleScreenBufferSize
 648 0000460B SetConsoleTextAttribute
 649 00004073 SetConsoleTitleA
 650 000243A9 SetConsoleTitleW
 651 000490E2 SetConsoleWindowInfo
 652          SetCriticalSectionSpinCount =&gt; NTDLL.RtlSetCriticalSectionSpinCount
 653 00010C18 SetCurrentDirectoryA
 654 0000FB16 SetCurrentDirectoryW
 655 0003DE9D SetDefaultCommConfigA
 656 0003DDC1 SetDefaultCommConfigW
 657 0000F2A6 SetEndOfFile
 658 00023650 SetEnvironmentVariableA
 659 00006038 SetEnvironmentVariableW
 660 0001ABA9 SetErrorMode
 661 0000B608 SetEvent
 662 00035795 SetFileApisToANSI
 663 0002040E SetFileApisToOEM
 664 0001B36A SetFileAttributesA
 665 0001B386 SetFileAttributesW
 666 0001D7CC SetFilePointer
 667 00001C2A SetFilePointerEx
 668 0001E638 SetFileTime
 669 0001154E SetHandleCount
 670 00022FBB SetHandleInformation
 671 00045C06 SetInformationJobObject
 672 00049FFE SetLastConsoleEventActive
 673 000148AB SetLastError
 674 00029F44 SetLocalTime
 675 0001F16C SetLocaleInfoA
 676 0001F1D5 SetLocaleInfoW
 677 00013914 SetMailslotInfo
 678 000382D1 SetMessageWaitingIndicator
 679 00009AD9 SetNamedPipeHandleState
 680 00020AA2 SetPriorityClass
 681 0003984F SetProcessAffinityMask
 682 0001F05E SetProcessPriorityBoost
 683 00002F71 SetProcessShutdownParameters
 684 0001DD9F SetProcessWorkingSetSize
 685 0000D089 SetStdHandle
 686 000381E3 SetSystemPowerState
 687 0000183D SetSystemTime
 688 000018EC SetSystemTimeAdjustment
 689 000458FA SetTapeParameters
 690 00045750 SetTapePosition
 691 0003A97F SetTermsrvAppInstallMode
 692 000175AB SetThreadAffinityMask
 693 0003BBEE SetThreadContext
 694 00009655 SetThreadExecutionState
 695 0003C0E9 SetThreadIdealProcessor
 696 0001CDA0 SetThreadLocale
 697 0001B593 SetThreadPriority
 698 0003BB35 SetThreadPriorityBoost
 699 0002D625 SetTimeZoneInformation
 700 0003C45B SetTimerQueueTimer
 701 0000BC57 SetUnhandledExceptionFilter
 702 0003F2C9 SetVDMCurrentDirectories
 703 00037DF1 SetVolumeLabelA
 704 00037E4E SetVolumeLabelW
 705 00041311 SetVolumeMountPointA
 706 0004163C SetVolumeMountPointW
 707 00017546 SetWaitableTimer
 708 0003E0F1 SetupComm
 709 000477CA ShowConsoleCursor
 710 0003A468 SignalObjectAndWait
 711 0001504C SizeofResource
 712 0001AC6E Sleep
 713 0001AC7C SleepEx
 714 0003BC10 SuspendThread
 715 0001F93F SwitchToFiber
 716 0003C15D SwitchToThread
 717 00009B45 SystemTimeToFileTime
 718 0002D788 SystemTimeToTzSpecificLocalTime
 719 00045B18 TerminateJobObject
 720 00038DC3 TerminateProcess
 721 00017584 TerminateThread
 722 0003A96D TermsrvAppInstallMode
 723 0003CC2A Thread32First
 724 0003CCDB Thread32Next
 725 0000D279 TlsAlloc
 726 0000EA53 TlsFree
 727 00015D42 TlsGetValue
 728 0000A8C5 TlsSetValue
 729 0003C927 Toolhelp32ReadProcessMemory
 730 0000AB4F TransactNamedPipe
 731 0003EE87 TransmitCommChar
 732 00035E98 TrimVirtualBuffer
 733          TryEnterCriticalSection =&gt; NTDLL.RtlTryEnterCriticalSection
 734 00036D3F UTRegister
 735 00036D77 UTUnRegister
 736 0003BD2B UnhandledExceptionFilter
 737 00010538 UnlockFile
 738 00010570 UnlockFileEx
 739 00006135 UnmapViewOfFile
 740 00049C2E UnregisterConsoleIME
 741 000030D0 UnregisterWait
 742 00020F32 UnregisterWaitEx
 743 00042512 UpdateResourceA
 744 00042428 UpdateResourceW
 745 0004A0CC VDMConsoleOperation
 746 0003F0D8 VDMOperationStarted
 747 00023123 ValidateLCType
 748 00015E41 ValidateLocale
 749 0004C173 VerLanguageNameA
 750 0004C129 VerLanguageNameW
 751          VerSetConditionMask =&gt; NTDLL.VerSetConditionMask
 752 00019FF4 VerifyConsoleIoHandle
 753 000027B6 VerifyVersionInfoA
 754 00007304 VerifyVersionInfoW
 755 0001175C VirtualAlloc
 756 00011776 VirtualAllocEx
 757 00035EB1 VirtualBufferExceptionHandler
 758 0001E2DC VirtualFree
 759 0001E2F3 VirtualFreeEx
 760 000025AE VirtualLock
 761 0001C0F8 VirtualProtect
 762 0001C112 VirtualProtectEx
 763 0001A14C VirtualQuery
 764 0001A163 VirtualQueryEx
 765 00016C44 VirtualUnlock
 766 0003EF06 WaitCommEvent
 767 0002DB7E WaitForDebugEvent
 768 0001ABE4 WaitForMultipleObjects
 769 0000BD39 WaitForMultipleObjectsEx
 770 00011B0C WaitForSingleObject
 771 0001C468 WaitForSingleObjectEx
 772 0003757C WaitNamedPipeA
 773 00002962 WaitNamedPipeW
 774 0000A994 WideCharToMultiByte
 775 00009C1D WinExec
 776 0001C3FE WriteConsoleA
 777 00047F26 WriteConsoleInputA
 778 00047C8C WriteConsoleInputVDMA
 779 00047CA8 WriteConsoleInputVDMW
 780 00047F42 WriteConsoleInputW
 781 0004839D WriteConsoleOutputA
 782 000486E1 WriteConsoleOutputAttribute
 783 000486A3 WriteConsoleOutputCharacterA
 784 000486C2 WriteConsoleOutputCharacterW
 785 00048380 WriteConsoleOutputW
 786 0000C0C0 WriteConsoleW
 787 0001C24E WriteFile
 788 00030DA8 WriteFileEx
 789 00030EED WriteFileGather
 790 0000198E WritePrivateProfileSectionA
 791 0002F159 WritePrivateProfileSectionW
 792 0000A869 WritePrivateProfileStringA
 793 0001CCB6 WritePrivateProfileStringW
 794 0002ED41 WritePrivateProfileStructA
 795 0002EE40 WritePrivateProfileStructW
 796 00017303 WriteProcessMemory
 797 0000197C WriteProfileSectionA
 798 0002EF67 WriteProfileSectionW
 799 00023353 WriteProfileStringA
 800 0001CCA0 WriteProfileStringW
 801 00045872 WriteTapemark
 802 00010F74 _hread
 803 0001F332 _hwrite
 804 0000A8F1 _lclose
 805 00022ACF _lcreat
 806 0000997F _llseek
 807 0001CDD5 _lopen
 808 00010F74 _lread
 809 0001F332 _lwrite
 810 0001DF5C lstrcat
 811 0001DF5C lstrcatA
 812 0000A22C lstrcatW
 813 0001D453 lstrcmp
 814 0001D453 lstrcmpA
 815 0001D141 lstrcmpW
 816 00006A6C lstrcmpi
 817 00006A6C lstrcmpiA
 818 0001A18D lstrcmpiW
 819 0001E471 lstrcpy
 820 0001E471 lstrcpyA
 821 00008FFC lstrcpyW
 822 0000FA6D lstrcpyn
 823 0000FA6D lstrcpynA
 824 0000BE4E lstrcpynW
 825 00015D89 lstrlen
 826 00015D89 lstrlenA
 827 0000D20C lstrlenW&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;ntdll.dll 정보&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// ntdll.dll
   1 000213CD PropertyLengthAsVariant
   2 00021336 RtlConvertPropertyToVariant
   3 00021296 RtlConvertVariantToProperty
   4 0003C7B6 RtlUlongByteSwap
   5 0003C7BB RtlUlonglongByteSwap
   6 0003C7B1 RtlUshortByteSwap
   7 00012D38 CsrAllocateCaptureBuffer
   8 0000E6DA CsrAllocateMessagePointer
   9 00009778 CsrCaptureMessageBuffer
  10 0001652A CsrCaptureMessageString
  11 0001BA35 CsrCaptureTimeout
  12 0000917D CsrClientCallServer
  13 000100CA CsrClientConnectToServer
  14 0000E6C6 CsrFreeCaptureBuffer
  15 0001B96A CsrIdentifyAlertableThread
  16 00004BCC CsrNewThread
  17 0001BAA7 CsrProbeForRead
  18 0001BA5F CsrProbeForWrite
  19 0001B999 CsrSetPriorityClass
  20 0002144B DbgBreakPoint
  21 00018C08 DbgPrint
  22 00021504 DbgPrintReturnControlC
  23 0002158D DbgPrompt
  24 0001BD9F DbgSsHandleKmApiMsg
  25 0001BD59 DbgSsInitialize
  26 0001BFDC DbgUiConnectToDbg
  27 0001C1B3 DbgUiContinue
  28 0001C0CC DbgUiWaitStateChange
  29 0002144D DbgUserBreakPoint
  30 00021644 KiRaiseUserExceptionDispatcher
  31 000215CC KiUserApcDispatcher
  32 000215DC KiUserCallbackDispatcher
  33 000215F8 KiUserExceptionDispatcher
  34 00012577 LdrAccessResource
  35 00006A42 LdrAlternateResourcesEnabled
  36 00008A24 LdrDisableThreadCalloutsForDll
  37 000218E7 LdrEnumResources
  38 000216DE LdrFindEntryForAddress
  39 0001640C LdrFindResourceDirectory_U
  40 00007134 LdrFindResource_U
  41 00001278 LdrFlushAlternateResourceModules
  42 00011C8C LdrGetDllHandle
  43 00012B73 LdrGetProcedureAddress
  44 00004AF2 LdrInitializeThunk
  45 00006A6F LdrLoadAlternateResourceModule
  46 00003261 LdrLoadDll
  47 0000679D LdrProcessRelocationBlock
  48 000112C9 LdrQueryImageFileExecutionOptions
  49 0001DF85 LdrQueryProcessModuleInformation
  50 0000DD8E LdrShutdownProcess
  51 0000E42E LdrShutdownThread
  52 0000CBAE LdrUnloadAlternateResourceModule
  53 0000B5DF LdrUnloadDll
  54 0001DDF5 LdrVerifyImageMatchesChecksum
  55 000465B4 NPXEMULATORTABLE
  56 0004FF22 NlsAnsiCodePage
  57 0004F314 NlsMbCodePageTag
  58 0004F318 NlsMbOemCodePageTag
  59 0000F610 NtAcceptConnectPort
  60 00016066 NtAccessCheck
  61 00005E52 NtAccessCheckAndAuditAlarm
  62 0001650E NtAccessCheckByType
  63 0000F9C8 NtAccessCheckByTypeAndAuditAlarm
  64 0001AFDD NtAccessCheckByTypeResultList
  65 0001AFEB NtAccessCheckByTypeResultListAndAuditAlarm
  66 0001AFF9 NtAccessCheckByTypeResultListAndAuditAlarmByHandle
  67 0000E50B NtAddAtom
  68 0001B007 NtAdjustGroupsToken
  69 00008816 NtAdjustPrivilegesToken
  70 0001B015 NtAlertResumeThread
  71 0000CD6F NtAlertThread
  72 0001558D NtAllocateLocallyUniqueId
  73 0001B023 NtAllocateUserPhysicalPages
  74 0001B031 NtAllocateUuids
  75 00015459 NtAllocateVirtualMemory
  76 0001B03F NtAreMappedFilesTheSame
  77 0001B04D NtAssignProcessToJobObject
  78 0000CD99 NtCallbackReturn
  79 0001B06C NtCancelDeviceWakeupRequest
  80 0001B05E NtCancelIoFile
  81 00008C51 NtCancelTimer
  82 0000C6A4 NtClearEvent
  83 00004D93 NtClose
  84 00003679 NtCloseObjectAuditAlarm
  85 0000F61E NtCompleteConnectPort
  86 0000E57A NtConnectPort
  87 00008553 NtContinue
  88 0001B486 NtCreateChannel
  89 0001B07D NtCreateDirectoryObject
  90 00009FFD NtCreateEvent
  91 0001B08B NtCreateEventPair
  92 0000F9BA NtCreateFile
  93 00005EB6 NtCreateIoCompletion
  94 0001B099 NtCreateJobObject
  95 00007E08 NtCreateKey
  96 000024B1 NtCreateMailslotFile
  97 00007E16 NtCreateMutant
  98 0001651C NtCreateNamedPipeFile
  99 0001B0A7 NtCreatePagingFile
 100 00005EC4 NtCreatePort
 101 00003B9E NtCreateProcess
 102 0001B0B5 NtCreateProfile
 103 000135BF NtCreateSection
 104 0000B153 NtCreateSemaphore
 105 0000FA3D NtCreateSymbolicLinkObject
 106 000127AE NtCreateThread
 107 000169D5 NtCreateTimer
 108 00016BCD NtCreateToken
 109 0001B0C3 NtCreateWaitablePort
 110 00023AC7 NtCurrentTeb
 111 00009153 NtDelayExecution
 112 000037D5 NtDeleteAtom
 113 0001B0D1 NtDeleteFile
 114 000077CA NtDeleteKey
 115 000010A5 NtDeleteObjectAuditAlarm
 116 00009D81 NtDeleteValueKey
 117 000150D4 NtDeviceIoControlFile
 118 0001B0DF NtDisplayString
 119 00007724 NtDuplicateObject
 120 00015AE8 NtDuplicateToken
 121 0000C394 NtEnumerateKey
 122 00014A5A NtEnumerateValueKey
 123 0001B0ED NtExtendSection
 124 0001B0FB NtFilterToken
 125 0000EBA6 NtFindAtom
 126 0001570D NtFlushBuffersFile
 127 00014940 NtFlushInstructionCache
 128 000023B5 NtFlushKey
 129 0000A419 NtFlushVirtualMemory
 130 0001B109 NtFlushWriteBuffer
 131 0001B115 NtFreeUserPhysicalPages
 132 0000EC81 NtFreeVirtualMemory
 133 00007126 NtFsControlFile
 134 00016BDB NtGetContextThread
 135 0001B123 NtGetDevicePowerState
 136 000024BF NtGetPlugPlayEvent
 137 0001B131 NtGetTickCount
 138 0001B13D NtGetWriteWatch
 139 0001B14B NtImpersonateAnonymousToken
 140 00009D39 NtImpersonateClientOfPort
 141 00004DA1 NtImpersonateThread
 142 0001B159 NtInitializeRegistry
 143 0001B167 NtInitiatePowerAction
 144 0001B175 NtIsSystemResumeAutomatic
 145 0001B494 NtListenChannel
 146 0001B181 NtListenPort
 147 0001B18F NtLoadDriver
 148 0001B19D NtLoadKey2
 149 00016BE9 NtLoadKey
 150 0000BF81 NtLockFile
 151 000010B3 NtLockVirtualMemory
 152 000087DC NtMakeTemporaryObject
 153 0001B1AB NtMapUserPhysicalPages
 154 0001B1B9 NtMapUserPhysicalPagesScatter
 155 0000AE4F NtMapViewOfSection
 156 00006C1A NtNotifyChangeDirectoryFile
 157 00006CFA NtNotifyChangeKey
 158 00016BF7 NtNotifyChangeMultipleKeys
 159 0001B4A2 NtOpenChannel
 160 00009D8F NtOpenDirectoryObject
 161 0001149E NtOpenEvent
 162 0001B1C7 NtOpenEventPair
 163 00015337 NtOpenFile
 164 0001B1D5 NtOpenIoCompletion
 165 0001B1E3 NtOpenJobObject
 166 000061CC NtOpenKey
 167 00014AA4 NtOpenMutant
 168 00005B01 NtOpenObjectAuditAlarm
 169 000023C3 NtOpenProcess
 170 0000E717 NtOpenProcessToken
 171 00008AEC NtOpenSection
 172 0001255F NtOpenSemaphore
 173 00006151 NtOpenSymbolicLinkObject
 174 000024CD NtOpenThread
 175 00001EB3 NtOpenThreadToken
 176 0001B1F1 NtOpenTimer
 177 00001F74 NtPlugPlayControl
 178 00016C05 NtPowerInformation
 179 000165D5 NtPrivilegeCheck
 180 0001B1FF NtPrivilegeObjectAuditAlarm
 181 000010C1 NtPrivilegedServiceAuditAlarm
 182 0000BFC4 NtProtectVirtualMemory
 183 00016C13 NtPulseEvent
 184 00009FEF NtQueryAttributesFile
 185 0000E964 NtQueryDefaultLocale
 186 000051D0 NtQueryDefaultUILanguage
 187 00005510 NtQueryDirectoryFile
 188 00016C21 NtQueryDirectoryObject
 189 0001B20D NtQueryEaFile
 190 0001285D NtQueryEvent
 191 0001346B NtQueryFullAttributesFile
 192 000148F0 NtQueryInformationAtom
 193 0000F6AF NtQueryInformationFile
 194 00003BAC NtQueryInformationJobObject
 195 0001B21B NtQueryInformationPort
 196 00013351 NtQueryInformationProcess
 197 00008571 NtQueryInformationThread
 198 00005B0F NtQueryInformationToken
 199 0000455F NtQueryInstallUILanguage
 200 0001B229 NtQueryIntervalProfile
 201 0000BD4F NtQueryIoCompletion
 202 00007EBB NtQueryKey
 203 0001B237 NtQueryMultipleValueKey
 204 0001B245 NtQueryMutant
 205 000107D8 NtQueryObject
 206 0001B253 NtQueryOpenSubKeys
 207 000152DD NtQueryPerformanceCounter
 208 0001B261 NtQueryQuotaInformationFile
 209 000112BB NtQuerySection
 210 000038C7 NtQuerySecurityObject
 211 0001B26F NtQuerySemaphore
 212 00005EA8 NtQuerySymbolicLinkObject
 213 0001B27D NtQuerySystemEnvironmentValue
 214 00007D11 NtQuerySystemInformation
 215 000148E2 NtQuerySystemTime
 216 00011775 NtQueryTimer
 217 0000CBA0 NtQueryTimerResolution
 218 000062D2 NtQueryValueKey
 219 00015AA3 NtQueryVirtualMemory
 220 0000E588 NtQueryVolumeInformationFile
 221 0000366B NtQueueApcThread
 222 00014B92 NtRaiseException
 223 0001B28E NtRaiseHardError
 224 0000C552 NtReadFile
 225 0001B29C NtReadFileScatter
 226 0000F6A1 NtReadRequestData
 227 0000DEE6 NtReadVirtualMemory
 228 00004BB2 NtRegisterThreadTerminatePort
 229 00015475 NtReleaseMutant
 230 00008E81 NtReleaseSemaphore
 231 0000BEA7 NtRemoveIoCompletion
 232 0001B2AA NtReplaceKey
 233 0000E596 NtReplyPort
 234 00009161 NtReplyWaitReceivePort
 235 000039BC NtReplyWaitReceivePortEx
 236 0001B2B8 NtReplyWaitReplyPort
 237 0001B4B0 NtReplyWaitSendChannel
 238 0001B2C6 NtRequestDeviceWakeup
 239 00005290 NtRequestPort
 240 0000916F NtRequestWaitReplyPort
 241 0001B2D4 NtRequestWakeupLatency
 242 00016C2F NtResetEvent
 243 0001B2E2 NtResetWriteWatch
 244 0001B2F0 NtRestoreKey
 245 00008FB7 NtResumeThread
 246 00016C3D NtSaveKey
 247 0001B2FE NtSaveMergedKeys
 248 0000808A NtSecureConnectPort
 249 0001B4BE NtSendWaitReplyChannel
 250 0001B4CC NtSetContextChannel
 251 00016C4B NtSetContextThread
 252 0001B30C NtSetDefaultHardErrorPort
 253 0001B31A NtSetDefaultLocale
 254 0001B328 NtSetDefaultUILanguage
 255 0001B336 NtSetEaFile
 256 00008563 NtSetEvent
 257 0001B344 NtSetHighEventPair
 258 0001B352 NtSetHighWaitLowEventPair
 259 0000EE28 NtSetInformationFile
 260 0001B360 NtSetInformationJobObject
 261 0001B36E NtSetInformationKey
 262 000107E6 NtSetInformationObject
 263 00013B6D NtSetInformationProcess
 264 0000A1E0 NtSetInformationThread
 265 00016C59 NtSetInformationToken
 266 0001B37C NtSetIntervalProfile
 267 000086C0 NtSetIoCompletion
 268 00016C67 NtSetLdtEntries
 269 0001B38A NtSetLowEventPair
 270 0001B398 NtSetLowWaitHighEventPair
 271 0001B3A6 NtSetQuotaInformationFile
 272 00011F97 NtSetSecurityObject
 273 0001B3B4 NtSetSystemEnvironmentValue
 274 000010CF NtSetSystemInformation
 275 0001B3C2 NtSetSystemPowerState
 276 000010DD NtSetSystemTime
 277 0000C1DA NtSetThreadExecutionState
 278 00008C5F NtSetTimer
 279 00018958 NtSetTimerResolution
 280 0001B3D0 NtSetUuidSeed
 281 0000AA1B NtSetValueKey
 282 0001B3DE NtSetVolumeInformationFile
 283 0001B3EC NtShutdownSystem
 284 0001B3FA NtSignalAndWaitForSingleObject
 285 0001B408 NtStartProfile
 286 0001B416 NtStopProfile
 287 0001B424 NtSuspendThread
 288 0001B432 NtSystemDebugControl
 289 0001B440 NtTerminateJobObject
 290 0000DD80 NtTerminateProcess
 291 0000DFC2 NtTerminateThread
 292 00004BC0 NtTestAlert
 293 0001B44E NtUnloadDriver
 294 00016C75 NtUnloadKey
 295 00010312 NtUnlockFile
 296 000024DB NtUnlockVirtualMemory
 297 0000A3D8 NtUnmapViewOfSection
 298 00016C83 NtVdmControl
 299 00013233 NtWaitForMultipleObjects
 300 00014086 NtWaitForSingleObject
 301 0001B45C NtWaitHighEventPair
 302 0001B46A NtWaitLowEventPair
 303 000023A7 NtWriteFile
 304 0001B478 NtWriteFileGather
 305 0000816A NtWriteRequestData
 306 0000815C NtWriteVirtualMemory
 307 00012445 NtYieldExecution
 308 00023C36 PfxFindPrefix
 309 00023ACE PfxInitialize
 310 00023AE2 PfxInsertPrefix
 311 00023BBA PfxRemovePrefix
 312 0004A215 RestoreEm87Context
 313 00016E81 RtlAbortRXact
 314 0000A2E0 RtlAbsoluteToSelfRelativeSD
 315 0000C258 RtlAcquirePebLock
 316 00008098 RtlAcquireResourceExclusive
 317 00008D24 RtlAcquireResourceShared
 318 00009C9C RtlAddAccessAllowedAce
 319 000170C1 RtlAddAccessAllowedAceEx
 320 000249B3 RtlAddAccessAllowedObjectAce
 321 000014A2 RtlAddAccessDeniedAce
 322 00024938 RtlAddAccessDeniedAceEx
 323 000249F9 RtlAddAccessDeniedObjectAce
 324 000025A9 RtlAddAce
 325 000241C4 RtlAddActionToRXact
 326 00014D6D RtlAddAtomToAtomTable
 327 00016EBA RtlAddAttributeActionToRXact
 328 00024955 RtlAddAuditAccessAce
 329 00024982 RtlAddAuditAccessAceEx
 330 00024A40 RtlAddAuditAccessObjectAce
 331 000246B6 RtlAddCompoundAce
 332 0004D817 RtlAddRange
 333 000027E1 RtlAdjustPrivilege
 334 000042B0 RtlAllocateAndInitializeSid
 335 000089B1 RtlAllocateHandle
 336 0004C2AD RtlAllocateHeap
 337 000148FE RtlAnsiCharToUnicodeChar
 338 000286AD RtlAnsiStringToUnicodeSize
 339 000114AC RtlAnsiStringToUnicodeString
 340 00001739 RtlAppendAsciizToString
 341 00028C4F RtlAppendStringToString
 342 0000BEB5 RtlAppendUnicodeStringToString
 343 00011E2C RtlAppendUnicodeToString
 344 000241FE RtlApplyRXact
 345 00016FDA RtlApplyRXactNoFlush
 346 0000551E RtlAreAllAccessesGranted
 347 00025434 RtlAreAnyAccessesGranted
 348 0002948B RtlAreBitsClear
 349 00006B32 RtlAreBitsSet
 350 000298DD RtlAssert
 351 0001E7BA RtlCallbackLpcClient
 352 0002B0B6 RtlCancelTimer
 353 0002B447 RtlCaptureStackBackTrace
 354 0000E5A4 RtlCharToInteger
 355 00021448 RtlCheckForOrphanedCriticalSections
 356 0002C841 RtlCheckRegistryKey
 357 0001742C RtlClearAllBits
 358 00006AE0 RtlClearBits
 359 00010701 RtlCompactHeap
 360 0000529E RtlCompareMemory
 361 00011961 RtlCompareMemoryUlong
 362 00028B57 RtlCompareString
 363 0000AF43 RtlCompareUnicodeString
 364 0002ECEC RtlCompressBuffer
 365 000091F2 RtlConsoleMultiByteToUnicodeN
 366 00016D07 RtlConvertExclusiveToShared
 367 000169FA RtlConvertLongToLargeInteger
 368 00016CC8 RtlConvertSharedToExclusive
 369 0000A6D5 RtlConvertSidToUnicodeString
 370 0001F770 RtlConvertToAutoInheritSecurityObject
 371 0001F9A8 RtlConvertUiListToApiList
 372 0003C97E RtlConvertUlongToLargeInteger
 373 0000B5BC RtlCopyLuid
 374 00025231 RtlCopyLuidAndAttributesArray
 375 0004E0BE RtlCopyRangeList
 376 0001F333 RtlCopySecurityDescriptor
 377 00009CB8 RtlCopySid
 378 00025114 RtlCopySidAndAttributesArray
 379 00002949 RtlCopyString
 380 0000EC8F RtlCopyUnicodeString
 381 0000F857 RtlCreateAcl
 382 0001F462 RtlCreateAndSetSD
 383 0000AABF RtlCreateAtomTable
 384 000179CA RtlCreateEnvironment
 385 0004B425 RtlCreateHeap
 386 0001E5A9 RtlCreateLpcServer
 387 00003CCB RtlCreateProcessParameters
 388 0001FFBA RtlCreateQueryDebugBuffer
 389 0002C867 RtlCreateRegistryKey
 390 0000F96F RtlCreateSecurityDescriptor
 391 00011388 RtlCreateTagHeap
 392 0000FE89 RtlCreateTimer
 393 000174C0 RtlCreateTimerQueue
 394 000125AB RtlCreateUnicodeString
 395 000110F0 RtlCreateUnicodeStringFromAsciiz
 396 0002F2BC RtlCreateUserProcess
 397 0001F6FE RtlCreateUserSecurityObject
 398 0002F671 RtlCreateUserThread
 399 00022EA5 RtlCustomCPToUnicodeN
 400 0002F788 RtlCutoverTimeToSystemTime
 401 00003F82 RtlDeNormalizeProcessParams
 402 0002AEF4 RtlDebugPrintTimes
 403 0002ED40 RtlDecompressBuffer
 404 0002ED85 RtlDecompressFragment
 405 0001F78E RtlDefaultNpAcl
 406 0001886A RtlDelete
 407 00001445 RtlDeleteAce
 408 00014EB2 RtlDeleteAtomFromAtomTable
 409 00007BF9 RtlDeleteCriticalSection
 410 000188AF RtlDeleteElementGenericTable
 411 0002FC28 RtlDeleteNoSplay
 412 0004DE5D RtlDeleteOwnersRanges
 413 0004DD1C RtlDeleteRange
 414 0002C88D RtlDeleteRegistryValue
 415 000011DE RtlDeleteResource
 416 0000CD4E RtlDeleteSecurityObject
 417 0000437C RtlDeleteTimer
 418 00029CE6 RtlDeleteTimerQueue
 419 00029D7E RtlDeleteTimerQueueEx
 420 0000721E RtlDeregisterWait
 421 0000722C RtlDeregisterWaitEx
 422 00024AFA RtlDestroyAtomTable
 423 00003CAB RtlDestroyEnvironment
 424 00027AE7 RtlDestroyHandleTable
 425 0004B16C RtlDestroyHeap
 426 00003CAB RtlDestroyProcessParameters
 427 0002009B RtlDestroyQueryDebugBuffer
 428 00006BD6 RtlDetermineDosPathNameType_U
 429 000289BB RtlDnsHostNameToComputerName
 430 00003454 RtlDoesFileExists_U
 431 00011982 RtlDosPathNameToNtPathName_U
 432 0000ED36 RtlDosSearchPath_U
 433 00005480 RtlDowncaseUnicodeString
 434 0001ECF3 RtlDumpResource
 435 00024BD4 RtlEmptyAtomTable
 436 0001ED36 RtlEnableEarlyCriticalSectionEventCreation
 437 0003C84D RtlEnlargedIntegerMultiply
 438 0003C863 RtlEnlargedUnsignedDivide
 439 0003C858 RtlEnlargedUnsignedMultiply
 440 00009103 RtlEnterCriticalSection
 441 0002DA86 RtlEnumProcessHeaps
 442 0002FED7 RtlEnumerateGenericTable
 443 0002FF76 RtlEnumerateGenericTableWithoutSplaying
 444 00009AD9 RtlEqualComputerName
 445 000030E8 RtlEqualDomainName
 446 00025211 RtlEqualLuid
 447 000107F4 RtlEqualPrefixSid
 448 0000810F RtlEqualSid
 449 0000A18F RtlEqualString
 450 00015523 RtlEqualUnicodeString
 451 0002506A RtlEraseUnicodeString
 452 00009DA4 RtlExpandEnvironmentStrings_U
 453 0002D70D RtlExtendHeap
 454 0000361D RtlExtendedIntegerMultiply
 455 0001854E RtlExtendedLargeIntegerDivide
 456 0000BDA7 RtlExtendedMagicDivide
 457 0003C7C4 RtlFillMemory
 458 00018538 RtlFillMemoryUlong
 459 00008903 RtlFindClearBits
 460 0000897A RtlFindClearBitsAndSet
 461 0002962D RtlFindLastBackwardRunClear
 462 00029796 RtlFindLeastSignificantBit
 463 000293CA RtlFindLongestRunClear
 464 00006226 RtlFindMessage
 465 000296F8 RtlFindMostSignificantBit
 466 00029542 RtlFindNextForwardRunClear
 467 0004E30C RtlFindRange
 468 00028E18 RtlFindSetBits
 469 000290BF RtlFindSetBitsAndClear
 470 0000F93B RtlFirstFreeAce
 471 000161BC RtlFormatCurrentUserKeyPath
 472 00009F47 RtlFormatMessage
 473 0001329F RtlFreeAnsiString
 474 000037E3 RtlFreeHandle
 475 0004C7D3 RtlFreeHeap
 476 0000F7B4 RtlFreeOemString
 477 0004E181 RtlFreeRangeList
 478 00004332 RtlFreeSid
 479 0001329F RtlFreeUnicodeString
 480 0002F726 RtlFreeUserThreadStack
 481 00030329 RtlGUIDFromString
 482 000304D4 RtlGenerate8dot3Name
 483 000117E4 RtlGetAce
 484 0002B0F2 RtlGetCallersAddress
 485 0002ECA8 RtlGetCompressionWorkSpaceSize
 486 00005F92 RtlGetControlSecurityDescriptor
 487 0000B385 RtlGetCurrentDirectory_U
 488 00013241 RtlGetDaclSecurityDescriptor
 489 00018B4D RtlGetElementGenericTable
 490 0004E485 RtlGetFirstRange
 491 0000C127 RtlGetFullPathName_U
 492 00011712 RtlGetGroupSecurityDescriptor
 493 0001526E RtlGetLongestNtPathLength
 494 0004E4D9 RtlGetNextRange
 495 0000495C RtlGetNtGlobalFlags
 496 00008058 RtlGetNtProductType
 497 000116D9 RtlGetOwnerSecurityDescriptor
 498 00002ACA RtlGetProcessHeaps
 499 0002539B RtlGetSaclSecurityDescriptor
 500 00027AA0 RtlGetSecurityDescriptorRMControl
 501 00010F8A RtlGetUserInfoHeap
 502 00003034 RtlGetVersion
 503 00017193 RtlIdentifierAuthoritySid
 504 00012237 RtlImageDirectoryEntryToData
 505 000101F2 RtlImageNtHeader
 506 00013146 RtlImageRvaToSection
 507 00031150 RtlImageRvaToVa
 508 0001E7A7 RtlImpersonateLpcClient
 509 0000F7C9 RtlImpersonateSelf
 510 0000FFC3 RtlInitAnsiString
 511 000059D6 RtlInitCodePageTable
 512 00003B15 RtlInitNlsTables
 513 00010F30 RtlInitString
 514 0001566D RtlInitUnicodeString
 515 00003C9D RtlInitializeAtomPackage
 516 00005A97 RtlInitializeBitMap
 517 000311C0 RtlInitializeContext
 518 00015749 RtlInitializeCriticalSection
 519 000047F3 RtlInitializeCriticalSectionAndSpinCount
 520 0002FE18 RtlInitializeGenericTable
 521 0000421E RtlInitializeHandleTable
 522 00023E8C RtlInitializeRXact
 523 0004D800 RtlInitializeRangeList
 524 0000CA94 RtlInitializeResource
 525 0000E4E1 RtlInitializeSid
 526 00017AD2 RtlInsertElementGenericTable
 527 0002BC00 RtlInt64ToUnicodeString
 528 00013B7B RtlIntegerToChar
 529 00005CAB RtlIntegerToUnicodeString
 530 0004E653 RtlInvertRangeList
 531 000030C2 RtlIsDosDeviceName_U
 532 00018B3F RtlIsGenericTableEmpty
 533 00017C10 RtlIsNameLegalDOS8Dot3
 534 0004E1BC RtlIsRangeAvailable
 535 00013E34 RtlIsTextUnicode
 536 00010688 RtlIsValidHandle
 537 0001507C RtlIsValidIndexHandle
 538 0003C83A RtlLargeIntegerAdd
 539 0003C92E RtlLargeIntegerArithmeticShift
 540 000313B9 RtlLargeIntegerDivide
 541 0003C959 RtlLargeIntegerNegate
 542 0003C8E0 RtlLargeIntegerShiftLeft
 543 0003C907 RtlLargeIntegerShiftRight
 544 0003C96B RtlLargeIntegerSubtract
 545 0002B826 RtlLargeIntegerToChar
 546 00009134 RtlLeaveCriticalSection
 547 0000C68E RtlLengthRequiredSid
 548 00008FF6 RtlLengthSecurityDescriptor
 549 0000E2CB RtlLengthSid
 550 0002FA9A RtlLocalTimeToSystemTime
 551 0000C837 RtlLockHeap
 552 000026A7 RtlLookupAtomInAtomTable
 553 0002FE82 RtlLookupElementGenericTable
 554 0000A1EE RtlMakeSelfRelativeSD
 555 0000BE24 RtlMapGenericMask
 556 0004E572 RtlMergeRangeLists
 557 00001C66 RtlMoveMemory
 558 000078A1 RtlMultiByteToUnicodeN
 559 00004C66 RtlMultiByteToUnicodeSize
 560 0001F193 RtlNewInstanceSecurityObject
 561 0001F202 RtlNewSecurityGrantedAccess
 562 00001256 RtlNewSecurityObject
 563 0000FA4B RtlNewSecurityObjectEx
 564 00003A8A RtlNormalizeProcessParams
 565 0000D02E RtlNtStatusToDosError
 566 0002FF6C RtlNumberGenericTableElements
 567 000293FA RtlNumberOfClearBits
 568 00029440 RtlNumberOfSetBits
 569 000286AD RtlOemStringToUnicodeSize
 570 000052E6 RtlOemStringToUnicodeString
 571 00005361 RtlOemToUnicodeN
 572 0000313E RtlOpenCurrentUser
 573 00031526 RtlPcToFileHeader
 574 00024E99 RtlPinAtomInAtomTable
 575 00018980 RtlPrefixString
 576 0000ACE6 RtlPrefixUnicodeString
 577 0002CBC5 RtlProtectHeap
 578 00014F83 RtlQueryAtomInAtomTable
 579 0000B181 RtlQueryEnvironmentVariable_U
 580 0000253A RtlQueryInformationAcl
 581 00020363 RtlQueryProcessBackTraceInformation
 582 0002015F RtlQueryProcessDebugInformation
 583 0002055A RtlQueryProcessHeapInformation
 584 00020A3E RtlQueryProcessLockInformation
 585 0002C420 RtlQueryRegistryValues
 586 0001EF7F RtlQuerySecurityObject
 587 0002D5A2 RtlQueryTagHeap
 588 0002C939 RtlQueryTimeZoneInformation
 589 00013D6F RtlQueueWorkItem
 590 000316C8 RtlRaiseException
 591 00031780 RtlRaiseStatus
 592 00001B06 RtlRandom
 593 00012025 RtlReAllocateHeap
 594 0002FD08 RtlRealPredecessor
 595 0002FCD7 RtlRealSuccessor
 596 00007150 RtlRegisterWait
 597 0000C268 RtlReleasePebLock
 598 0000857F RtlReleaseResource
 599 00031275 RtlRemoteCall
 600 00003BBA RtlResetRtlTranslations
 601 000027A9 RtlRunDecodeUnicodeString
 602 00002741 RtlRunEncodeUnicodeString
 603 0002FA6A RtlSecondsSince1970ToTime
 604 0002FA33 RtlSecondsSince1980ToTime
 605 00024427 RtlSelfRelativeToAbsoluteSD2
 606 0000130F RtlSelfRelativeToAbsoluteSD
 607 00017453 RtlSetAllBits
 608 000252B2 RtlSetAttributesSecurityDescriptor
 609 00004EED RtlSetBits
 610 000252ED RtlSetControlSecurityDescriptor
 611 0000DD34 RtlSetCriticalSectionSpinCount
 612 00004F72 RtlSetCurrentDirectory_U
 613 0002EE40 RtlSetCurrentEnvironment
 614 00009CE4 RtlSetDaclSecurityDescriptor
 615 0000AFDB RtlSetEnvironmentVariable
 616 00002035 RtlSetGroupSecurityDescriptor
 617 0002461C RtlSetInformationAcl
 618 00029BD9 RtlSetIoCompletionCallback
 619 00001FF2 RtlSetOwnerSecurityDescriptor
 620 000028AE RtlSetSaclSecurityDescriptor
 621 00027AC3 RtlSetSecurityDescriptorRMControl
 622 0001EF3C RtlSetSecurityObject
 623 0001EF5D RtlSetSecurityObjectEx
 624 0000BC20 RtlSetThreadPoolStartFunc
 625 0002CA5A RtlSetTimeZoneInformation
 626 0002AFEB RtlSetTimer
 627 00021448 RtlSetUnicodeCallouts
 628 0002D260 RtlSetUserFlagsHeap
 629 00001EC1 RtlSetUserValueHeap
 630 0001E694 RtlShutdownLpcServer
 631 0004B906 RtlSizeHeap
 632 00018859 RtlSplay
 633 00016E35 RtlStartRXact
 634 00017BA1 RtlStringFromGUID
 635 00008154 RtlSubAuthorityCountSid
 636 000153A5 RtlSubAuthoritySid
 637 0002FCBC RtlSubtreePredecessor
 638 0002FCA1 RtlSubtreeSuccessor
 639 00004C87 RtlSystemTimeToLocalTime
 640 0000349A RtlTimeFieldsToTime
 641 0002F9AB RtlTimeToElapsedTimeFields
 642 00016629 RtlTimeToSecondsSince1970
 643 00005E60 RtlTimeToSecondsSince1980
 644 000081FE RtlTimeToTimeFields
 645 00031953 RtlTraceDatabaseAdd
 646 000317A8 RtlTraceDatabaseCreate
 647 000318BB RtlTraceDatabaseDestroy
 648 00031CE1 RtlTraceDatabaseEnumerate
 649 00031981 RtlTraceDatabaseFind
 650 00031C87 RtlTraceDatabaseLock
 651 00031C93 RtlTraceDatabaseUnlock
 652 00031913 RtlTraceDatabaseValidate
 653 0000A130 RtlTryEnterCriticalSection
 654 0002868F RtlUnicodeStringToAnsiSize
 655 0001335F RtlUnicodeStringToAnsiString
 656 000284D5 RtlUnicodeStringToCountedOemString
 657 0001246E RtlUnicodeStringToInteger
 658 0002868F RtlUnicodeStringToOemSize
 659 000031E2 RtlUnicodeStringToOemString
 660 0002308E RtlUnicodeToCustomCPN
 661 0000C6B2 RtlUnicodeToMultiByteN
 662 000102D8 RtlUnicodeToMultiByteSize
 663 00012EEA RtlUnicodeToOemN
 664 00006341 RtlUniform
 665 0000C872 RtlUnlockHeap
 666 0000EA4A RtlUnwind
 667 0000CC2C RtlUpcaseUnicodeChar
 668 0000B2AD RtlUpcaseUnicodeString
 669 000283DD RtlUpcaseUnicodeStringToAnsiString
 670 0001735D RtlUpcaseUnicodeStringToCountedOemString
 671 00003739 RtlUpcaseUnicodeStringToOemString
 672 00023235 RtlUpcaseUnicodeToCustomCPN
 673 00015788 RtlUpcaseUnicodeToMultiByteN
 674 00010320 RtlUpcaseUnicodeToOemN
 675 00002078 RtlUpdateTimer
 676 00012451 RtlUpperChar
 677 00028C07 RtlUpperString
 678 0002DB14 RtlUsageHeap
 679 0000F8A7 RtlValidAcl
 680 0002794F RtlValidRelativeSecurityDescriptor
 681 00005ED2 RtlValidSecurityDescriptor
 682 0000ED77 RtlValidSid
 683 00001C9F RtlValidateHeap
 684 0002D9C0 RtlValidateProcessHeaps
 685 00013C7F RtlVerifyVersionInfo
 686 0002B4E9 RtlWalkFrameChain
 687 0002E076 RtlWalkHeap
 688 0002C7EC RtlWriteRegistryValue
 689 0004E7E1 RtlZeroHeap
 690 0003C7F5 RtlZeroMemory
 691 00031E7F RtlpNtCreateKey
 692 00031EED RtlpNtEnumerateSubKey
 693 00031EE1 RtlpNtMakeTemporaryKey
 694 0000A05A RtlpNtOpenKey
 695 0000A077 RtlpNtQueryValueKey
 696 00031EBC RtlpNtSetValueKey
 697 000123AA RtlpUnWaitCriticalSection
 698 00012313 RtlpWaitForCriticalSection
 699 000286AD RtlxAnsiStringToUnicodeSize
 700 000286AD RtlxOemStringToUnicodeSize
 701 0002868F RtlxUnicodeStringToAnsiSize
 702 0002868F RtlxUnicodeStringToOemSize
 703 0004A1EC SaveEm87Context
 704 00013D37 VerSetConditionMask
 705 0000F610 ZwAcceptConnectPort
 706 00016066 ZwAccessCheck
 707 00005E52 ZwAccessCheckAndAuditAlarm
 708 0001650E ZwAccessCheckByType
 709 0000F9C8 ZwAccessCheckByTypeAndAuditAlarm
 710 0001AFDD ZwAccessCheckByTypeResultList
 711 0001AFEB ZwAccessCheckByTypeResultListAndAuditAlarm
 712 0001AFF9 ZwAccessCheckByTypeResultListAndAuditAlarmByHandle
 713 0000E50B ZwAddAtom
 714 0001B007 ZwAdjustGroupsToken
 715 00008816 ZwAdjustPrivilegesToken
 716 0001B015 ZwAlertResumeThread
 717 0000CD6F ZwAlertThread
 718 0001558D ZwAllocateLocallyUniqueId
 719 0001B023 ZwAllocateUserPhysicalPages
 720 0001B031 ZwAllocateUuids
 721 00015459 ZwAllocateVirtualMemory
 722 0001B03F ZwAreMappedFilesTheSame
 723 0001B04D ZwAssignProcessToJobObject
 724 0000CD99 ZwCallbackReturn
 725 0001B06C ZwCancelDeviceWakeupRequest
 726 0001B05E ZwCancelIoFile
 727 00008C51 ZwCancelTimer
 728 0000C6A4 ZwClearEvent
 729 00004D93 ZwClose
 730 00003679 ZwCloseObjectAuditAlarm
 731 0000F61E ZwCompleteConnectPort
 732 0000E57A ZwConnectPort
 733 00008553 ZwContinue
 734 0001B486 ZwCreateChannel
 735 0001B07D ZwCreateDirectoryObject
 736 00009FFD ZwCreateEvent
 737 0001B08B ZwCreateEventPair
 738 0000F9BA ZwCreateFile
 739 00005EB6 ZwCreateIoCompletion
 740 0001B099 ZwCreateJobObject
 741 00007E08 ZwCreateKey
 742 000024B1 ZwCreateMailslotFile
 743 00007E16 ZwCreateMutant
 744 0001651C ZwCreateNamedPipeFile
 745 0001B0A7 ZwCreatePagingFile
 746 00005EC4 ZwCreatePort
 747 00003B9E ZwCreateProcess
 748 0001B0B5 ZwCreateProfile
 749 000135BF ZwCreateSection
 750 0000B153 ZwCreateSemaphore
 751 0000FA3D ZwCreateSymbolicLinkObject
 752 000127AE ZwCreateThread
 753 000169D5 ZwCreateTimer
 754 00016BCD ZwCreateToken
 755 0001B0C3 ZwCreateWaitablePort
 756 00009153 ZwDelayExecution
 757 000037D5 ZwDeleteAtom
 758 0001B0D1 ZwDeleteFile
 759 000077CA ZwDeleteKey
 760 000010A5 ZwDeleteObjectAuditAlarm
 761 00009D81 ZwDeleteValueKey
 762 000150D4 ZwDeviceIoControlFile
 763 0001B0DF ZwDisplayString
 764 00007724 ZwDuplicateObject
 765 00015AE8 ZwDuplicateToken
 766 0000C394 ZwEnumerateKey
 767 00014A5A ZwEnumerateValueKey
 768 0001B0ED ZwExtendSection
 769 0001B0FB ZwFilterToken
 770 0000EBA6 ZwFindAtom
 771 0001570D ZwFlushBuffersFile
 772 00014940 ZwFlushInstructionCache
 773 000023B5 ZwFlushKey
 774 0000A419 ZwFlushVirtualMemory
 775 0001B109 ZwFlushWriteBuffer
 776 0001B115 ZwFreeUserPhysicalPages
 777 0000EC81 ZwFreeVirtualMemory
 778 00007126 ZwFsControlFile
 779 00016BDB ZwGetContextThread
 780 0001B123 ZwGetDevicePowerState
 781 000024BF ZwGetPlugPlayEvent
 782 0001B131 ZwGetTickCount
 783 0001B13D ZwGetWriteWatch
 784 0001B14B ZwImpersonateAnonymousToken
 785 00009D39 ZwImpersonateClientOfPort
 786 00004DA1 ZwImpersonateThread
 787 0001B159 ZwInitializeRegistry
 788 0001B167 ZwInitiatePowerAction
 789 0001B175 ZwIsSystemResumeAutomatic
 790 0001B494 ZwListenChannel
 791 0001B181 ZwListenPort
 792 0001B18F ZwLoadDriver
 793 0001B19D ZwLoadKey2
 794 00016BE9 ZwLoadKey
 795 0000BF81 ZwLockFile
 796 000010B3 ZwLockVirtualMemory
 797 000087DC ZwMakeTemporaryObject
 798 0001B1AB ZwMapUserPhysicalPages
 799 0001B1B9 ZwMapUserPhysicalPagesScatter
 800 0000AE4F ZwMapViewOfSection
 801 00006C1A ZwNotifyChangeDirectoryFile
 802 00006CFA ZwNotifyChangeKey
 803 00016BF7 ZwNotifyChangeMultipleKeys
 804 0001B4A2 ZwOpenChannel
 805 00009D8F ZwOpenDirectoryObject
 806 0001149E ZwOpenEvent
 807 0001B1C7 ZwOpenEventPair
 808 00015337 ZwOpenFile
 809 0001B1D5 ZwOpenIoCompletion
 810 0001B1E3 ZwOpenJobObject
 811 000061CC ZwOpenKey
 812 00014AA4 ZwOpenMutant
 813 00005B01 ZwOpenObjectAuditAlarm
 814 000023C3 ZwOpenProcess
 815 0000E717 ZwOpenProcessToken
 816 00008AEC ZwOpenSection
 817 0001255F ZwOpenSemaphore
 818 00006151 ZwOpenSymbolicLinkObject
 819 000024CD ZwOpenThread
 820 00001EB3 ZwOpenThreadToken
 821 0001B1F1 ZwOpenTimer
 822 00001F74 ZwPlugPlayControl
 823 00016C05 ZwPowerInformation
 824 000165D5 ZwPrivilegeCheck
 825 0001B1FF ZwPrivilegeObjectAuditAlarm
 826 000010C1 ZwPrivilegedServiceAuditAlarm
 827 0000BFC4 ZwProtectVirtualMemory
 828 00016C13 ZwPulseEvent
 829 00009FEF ZwQueryAttributesFile
 830 0000E964 ZwQueryDefaultLocale
 831 000051D0 ZwQueryDefaultUILanguage
 832 00005510 ZwQueryDirectoryFile
 833 00016C21 ZwQueryDirectoryObject
 834 0001B20D ZwQueryEaFile
 835 0001285D ZwQueryEvent
 836 0001346B ZwQueryFullAttributesFile
 837 000148F0 ZwQueryInformationAtom
 838 0000F6AF ZwQueryInformationFile
 839 00003BAC ZwQueryInformationJobObject
 840 0001B21B ZwQueryInformationPort
 841 00013351 ZwQueryInformationProcess
 842 00008571 ZwQueryInformationThread
 843 00005B0F ZwQueryInformationToken
 844 0000455F ZwQueryInstallUILanguage
 845 0001B229 ZwQueryIntervalProfile
 846 0000BD4F ZwQueryIoCompletion
 847 00007EBB ZwQueryKey
 848 0001B237 ZwQueryMultipleValueKey
 849 0001B245 ZwQueryMutant
 850 000107D8 ZwQueryObject
 851 0001B253 ZwQueryOpenSubKeys
 852 000152DD ZwQueryPerformanceCounter
 853 0001B261 ZwQueryQuotaInformationFile
 854 000112BB ZwQuerySection
 855 000038C7 ZwQuerySecurityObject
 856 0001B26F ZwQuerySemaphore
 857 00005EA8 ZwQuerySymbolicLinkObject
 858 0001B27D ZwQuerySystemEnvironmentValue
 859 00007D11 ZwQuerySystemInformation
 860 000148E2 ZwQuerySystemTime
 861 00011775 ZwQueryTimer
 862 0000CBA0 ZwQueryTimerResolution
 863 000062D2 ZwQueryValueKey
 864 00015AA3 ZwQueryVirtualMemory
 865 0000E588 ZwQueryVolumeInformationFile
 866 0000366B ZwQueueApcThread
 867 00014B92 ZwRaiseException
 868 0001B28E ZwRaiseHardError
 869 0000C552 ZwReadFile
 870 0001B29C ZwReadFileScatter
 871 0000F6A1 ZwReadRequestData
 872 0000DEE6 ZwReadVirtualMemory
 873 00004BB2 ZwRegisterThreadTerminatePort
 874 00015475 ZwReleaseMutant
 875 00008E81 ZwReleaseSemaphore
 876 0000BEA7 ZwRemoveIoCompletion
 877 0001B2AA ZwReplaceKey
 878 0000E596 ZwReplyPort
 879 00009161 ZwReplyWaitReceivePort
 880 000039BC ZwReplyWaitReceivePortEx
 881 0001B2B8 ZwReplyWaitReplyPort
 882 0001B4B0 ZwReplyWaitSendChannel
 883 0001B2C6 ZwRequestDeviceWakeup
 884 00005290 ZwRequestPort
 885 0000916F ZwRequestWaitReplyPort
 886 0001B2D4 ZwRequestWakeupLatency
 887 00016C2F ZwResetEvent
 888 0001B2E2 ZwResetWriteWatch
 889 0001B2F0 ZwRestoreKey
 890 00008FB7 ZwResumeThread
 891 00016C3D ZwSaveKey
 892 0001B2FE ZwSaveMergedKeys
 893 0000808A ZwSecureConnectPort
 894 0001B4BE ZwSendWaitReplyChannel
 895 0001B4CC ZwSetContextChannel
 896 00016C4B ZwSetContextThread
 897 0001B30C ZwSetDefaultHardErrorPort
 898 0001B31A ZwSetDefaultLocale
 899 0001B328 ZwSetDefaultUILanguage
 900 0001B336 ZwSetEaFile
 901 00008563 ZwSetEvent
 902 0001B344 ZwSetHighEventPair
 903 0001B352 ZwSetHighWaitLowEventPair
 904 0000EE28 ZwSetInformationFile
 905 0001B360 ZwSetInformationJobObject
 906 0001B36E ZwSetInformationKey
 907 000107E6 ZwSetInformationObject
 908 00013B6D ZwSetInformationProcess
 909 0000A1E0 ZwSetInformationThread
 910 00016C59 ZwSetInformationToken
 911 0001B37C ZwSetIntervalProfile
 912 000086C0 ZwSetIoCompletion
 913 00016C67 ZwSetLdtEntries
 914 0001B38A ZwSetLowEventPair
 915 0001B398 ZwSetLowWaitHighEventPair
 916 0001B3A6 ZwSetQuotaInformationFile
 917 00011F97 ZwSetSecurityObject
 918 0001B3B4 ZwSetSystemEnvironmentValue
 919 000010CF ZwSetSystemInformation
 920 0001B3C2 ZwSetSystemPowerState
 921 000010DD ZwSetSystemTime
 922 0000C1DA ZwSetThreadExecutionState
 923 00008C5F ZwSetTimer
 924 00018958 ZwSetTimerResolution
 925 0001B3D0 ZwSetUuidSeed
 926 0000AA1B ZwSetValueKey
 927 0001B3DE ZwSetVolumeInformationFile
 928 0001B3EC ZwShutdownSystem
 929 0001B3FA ZwSignalAndWaitForSingleObject
 930 0001B408 ZwStartProfile
 931 0001B416 ZwStopProfile
 932 0001B424 ZwSuspendThread
 933 0001B432 ZwSystemDebugControl
 934 0001B440 ZwTerminateJobObject
 935 0000DD80 ZwTerminateProcess
 936 0000DFC2 ZwTerminateThread
 937 00004BC0 ZwTestAlert
 938 0001B44E ZwUnloadDriver
 939 00016C75 ZwUnloadKey
 940 00010312 ZwUnlockFile
 941 000024DB ZwUnlockVirtualMemory
 942 0000A3D8 ZwUnmapViewOfSection
 943 00016C83 ZwVdmControl
 944 00013233 ZwWaitForMultipleObjects
 945 00014086 ZwWaitForSingleObject
 946 0001B45C ZwWaitHighEventPair
 947 0001B46A ZwWaitLowEventPair
 948 000023A7 ZwWriteFile
 949 0001B478 ZwWriteFileGather
 950 0000816A ZwWriteRequestData
 951 0000815C ZwWriteVirtualMemory
 952 00012445 ZwYieldExecution
 953 000382C5 _CIpow
 954 000467F7 __eCommonExceptions
 955 00046000 __eEmulatorInit
 956 00049A66 __eF2XM1
 957 00048335 __eFABS
 958 00046DD7 __eFADD32
 959 00046DFF __eFADD64
 960 00046E4A __eFADDPreg
 961 00046E4F __eFADDreg
 962 00046E51 __eFADDtop
 963 00048346 __eFCHS
 964 00048526 __eFCOM
 965 00048449 __eFCOM32
 966 00048472 __eFCOM64
 967 00048517 __eFCOMP
 968 00048432 __eFCOMP32
 969 0004845B __eFCOMP64
 970 000484FB __eFCOMPP
 971 000490CE __eFCOS
 972 00049F37 __eFDECSTP
 973 00047216 __eFDIV32
 974 0004722A __eFDIV64
 975 000472E3 __eFDIVPreg
 976 00047220 __eFDIVR32
 977 00047234 __eFDIVR64
 978 0004723E __eFDIVRPreg
 979 00047243 __eFDIVRreg
 980 00047245 __eFDIVRtop
 981 000472E8 __eFDIVreg
 982 000472EA __eFDIVtop
 983 00048356 __eFFREE
 984 00046D87 __eFIADD16
 985 00046DAF __eFIADD32
 986 000483F7 __eFICOM16
 987 00048420 __eFICOM32
 988 000483E0 __eFICOMP16
 989 00048409 __eFICOMP32
 990 000471EE __eFIDIV16
 991 00047202 __eFIDIV32
 992 000471F8 __eFIDIVR16
 993 0004720C __eFIDIVR32
 994 00047AF8 __eFILD16
 995 00047B09 __eFILD32
 996 00047B13 __eFILD64
 997 00046F64 __eFIMUL16
 998 00046F98 __eFIMUL32
 999 00049F54 __eFINCSTP
1000 00046000 __eFINIT
1001 000481A0 __eFIST16
1002 000480AE __eFIST32
1003 0004819B __eFISTP16
1004 000480A9 __eFISTP32
1005 00048253 __eFISTP64
1006 00046CC6 __eFISUB16
1007 00046D93 __eFISUB32
1008 00046D79 __eFISUBR16
1009 00046DA1 __eFISUBR32
1010 00048708 __eFLD1
1011 00047A79 __eFLD32
1012 00047ACF __eFLD64
1013 00047BC9 __eFLD80
1014 00049ED0 __eFLDCW
1015 0004A071 __eFLDENV
1016 00048773 __eFLDL2E
1017 00048795 __eFLDLN2
1018 000487A6 __eFLDPI
1019 00048744 __eFLDZ
1020 00046FDA __eFMUL32
1021 0004701E __eFMUL64
1022 0004706B __eFMULPreg
1023 00047070 __eFMULreg
1024 00047072 __eFMULtop
1025 00046A66 __eFPATAN
1026 00046A2A __eFPREM
1027 00046A50 __eFPREM1
1028 000491DB __eFPTAN
1029 0004738D __eFRNDINT
1030 0004A0AB __eFRSTOR
1031 00049FFE __eFSAVE
1032 00046A5F __eFSCALE
1033 00049173 __eFSIN
1034 0004A2CA __eFSQRT
1035 00047C84 __eFST
1036 00047F22 __eFST32
1037 00047D4D __eFST64
1038 00049F16 __eFSTCW
1039 00049F82 __eFSTENV
1040 00047C2A __eFSTP
1041 00047F1D __eFSTP32
1042 00047D48 __eFSTP64
1043 000482DA __eFSTP80
1044 00049F22 __eFSTSW
1045 00046DBB __eFSUB32
1046 00046DE3 __eFSUB64
1047 00046E0B __eFSUBPreg
1048 00046DC9 __eFSUBR32
1049 00046DF1 __eFSUBR64
1050 00046E26 __eFSUBRPreg
1051 00046E2B __eFSUBRreg
1052 00046E2D __eFSUBRtop
1053 00046E10 __eFSUBreg
1054 00046E12 __eFSUBtop
1055 0004869A __eFTST
1056 000484F1 __eFUCOM
1057 000484E2 __eFUCOMP
1058 00048484 __eFUCOMPP
1059 00048674 __eFXAM
1060 0004835C __eFXCH
1061 00048A03 __eFXTRACT
1062 00046A87 __eFYL2X
1063 00046A8E __eFYL2XP1
1064 0004A18D __eGetStatusWord
1065 000386DE __isascii
1066 00038730 __iscsym
1067 000386F3 __iscsymf
1068 000386EB __toascii
1069 0000C5A8 _alldiv
1070 00007A9F _allmul
1071 000160D6 _alloca_probe
1072 000387F1 _allrem
1073 000388A3 _allshl
1074 000388C2 _allshr
1075 0003891A _atoi64
1076 0000DB68 _aulldiv
1077 0000DB91 _aullrem
1078 00007D61 _aullshr
1079 000160D6 _chkstk
1080 00051028 _fltused
1081 00002CDA _ftol
1082 00038AB4 _i64toa
1083 00038BD4 _i64tow
1084 000189D2 _itoa
1085 00001B59 _itow
1086 00038A8A _ltoa
1087 00038B78 _ltow
1088 00038C05 _memccpy
1089 00038C58 _memicmp
1090 00038CF0 _snprintf
1091 00008E0E _snwprintf
1092 00038D65 _splitpath
1093 00011634 _strcmpi
1094 00011634 _stricmp
1095 00017DD3 _strlwr
1096 00004DE6 _strnicmp
1097 00002D01 _strupr
1098 00038F4F _tolower
1099 00038F6A _toupper
1100 00038B5D _ui64toa
1101 0000FE10 _ultoa
1102 00038BA6 _ultow
1103 00018D01 _vsnprintf
1104 00001FA5 _wcsicmp
1105 00038F98 _wcslwr
1106 00012DD7 _wcsnicmp
1107 00038FC2 _wcsupr
1108 00038FEC _wtoi
1109 0003900F _wtoi64
1110 00038FEC _wtol
1111 000393F2 abs
1112 00039032 atan
1113 0001673E atoi
1114 000166E3 atol
1115 000390E9 ceil
1116 000391B5 cos
1117 0003924F fabs
1118 00039304 floor
1119 0003862C isalnum
1120 0003853D isalpha
1121 000386B6 iscntrl
1122 00002C85 isdigit
1123 00038688 isgraph
1124 00038593 islower
1125 0003865A isprint
1126 00038604 ispunct
1127 00002CA3 isspace
1128 0003856B isupper
1129 000393D0 iswalpha
1130 0000C629 iswctype
1131 00007FA3 iswdigit
1132 000393E1 iswlower
1133 00018AE8 iswspace
1134 00017DF6 iswxdigit
1135 000385C9 isxdigit
1136 000393F2 labs
1137 000393FD log
1138 00001B87 mbstowcs
1139 000394E2 memchr
1140 00039583 memcmp
1141 0003962F memcpy
1142 0001109B memmove
1143 00039950 memset
1144 000382DE pow
1145 000399A8 qsort
1146 00039B6A sin
1147 00017E20 sprintf
1148 00039C16 sqrt
1149 00039CBC sscanf
1150 00039D62 strcat
1151 00005B1D strchr
1152 00039E02 strcmp
1153 00039CF6 strcpy
1154 00039E83 strcspn
1155 00039EC0 strlen
1156 00039F37 strncat
1157 00002D4E strncmp
1158 00008824 strncpy
1159 0003A084 strpbrk
1160 00017EC0 strrchr
1161 0003A0BD strspn
1162 00017EE7 strstr
1163 0003A10C strtol
1164 000180CD strtoul
1165 0000423D swprintf
1166 0003A271 tan
1167 00002D26 tolower
1168 00015A1E toupper
1169 0003A30F towlower
1170 000180E4 towupper
1171 0003A32A vsprintf
1172 000121E4 wcscat
1173 00012544 wcschr
1174 0000972D wcscmp
1175 0000C23F wcscpy
1176 0000CA53 wcscspn
1177 000152EB wcslen
1178 00006459 wcsncat
1179 0000EBD1 wcsncmp
1180 0000BCE6 wcsncpy
1181 0000DF7B wcspbrk
1182 0000F661 wcsrchr
1183 00016A11 wcsspn
1184 0000456D wcsstr
1185 00008B39 wcstol
1186 0003A446 wcstombs
1187 0001815A wcstoul&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[MFC 위성 DLL 취약점]]></title><description><![CDATA[MFC 7.0부터 위성 DLL이란게 추가된 것 같습니다. 이게 머 위성 DLL하니 말이 거창한데 리소스 DLL을 분리시켜 놓고 시스템 언어에 맞게 리소스 DLL…]]></description><link>https://jiniya.net/wp/archives/14240</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14240</guid><pubDate>Wed, 03 Sep 2014 23:59:52 GMT</pubDate><content:encoded>&lt;p&gt;MFC 7.0부터 위성 DLL이란게 추가된 것 같습니다. 이게 머 위성 DLL하니 말이 거창한데 리소스 DLL을 분리시켜 놓고 시스템 언어에 맞게 리소스 DLL을 로드하는 것을 의미하나 봅니다. 상세 기능은 &lt;a href=&quot;http://msdn.microsoft.com/en-US/library/8fkteez0.aspx&quot;&gt;여기 링크&lt;/a&gt;를 참고하시면 됩니다. 근데 안타깝게도 MFC 개발팀에서 이 기능을 만들면서 초기에 소소한 실수(?!)를 하는 바람에 취약점이 생겼나 보네요. 머 대단한 취약점은 아니고 LPK.DLL이나 USP10.DLL 같이 임의의 코드가 리소스 DLL에 감염돼 있으면 실행되는 취약점입니다. 그럼 왜 생겼는지 한 번 살펴볼까요?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아래는 VS 2008의 위성 DLL 로드 부분 코드입니다. MFC에 포함된 appcore.cpp의 _AfxLoadLangDLL 코드의 일부입니다. 보면 리소스 DLL을 LoadLibraryEx를 통해서 로드하는데 안타깝게도 마지막 인자가 0입니다. 0이라는 말은 그냥 일반 DLL 처럼 로드하겠다는 의미죠. 리소스 DLL에 악성 코드가 감염되어 있었다면 같이 실행될 수 있다는 것을 의미합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pfnFindActCtxSectionString &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;pfnFindActCtxSectionString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Load using the dll name only...&lt;/span&gt;
	hInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LoadLibraryEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pszFilename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Load using the full path...&lt;/span&gt;
	hInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LoadLibraryEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szLangDLL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;취약한 VS 2008 위성 DLL 로드 부분&lt;/strong&gt;
아래는 VS 2013의 appcore.cpp의 _AfxLoadLangDLL 함수 부분을 발췌한 내용입니다. 살펴보면 LoadLibraryEx를 할 때 마지막 인자에 LOAD_IMAGE_AS_DATAFILE을 넣어서 DllMain이 실행되지 않도록 하고 있습니다. 악성 코드에 감염되어 있다고 하더라도 해당 코드가 실행되지는 않는다는 것을 의미하죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;hInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LoadLibraryExW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szLangDLL
           &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
           &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; LOAD_LIBRARY_AS_IMAGE_RESOURCE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hInstance &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// if library load failed using flags only valid on Vista+, ...&lt;/span&gt;
	hInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LoadLibraryExW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;szLangDLL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LOAD_LIBRARY_AS_DATAFILE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;안전한 VS 2013 위성 DLL 로드 부분&lt;/strong&gt;
&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이런 사실을 알게 된다면 굳이 위성 DLL 기능이 필요 없다면 기능을 사용하고 싶지 않을 수도 있는데요. 위성 DLL은 MFC DLL의 DllMain에서 아래와 같은 코드에 의해서 로드됩니다. 보시면 알겠지만 일반적인 상황이라면 제어할 수 있는 제어 플래그가 없습니다. 그도 그럴것이 뭐 DllMain이니깐염.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD dwLen &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleFileName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rgchFullModulePath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dwLen &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	TCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pszFilename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;PathFindFileName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rgchFullModulePath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pszFilename &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; rgchFullModulePath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// filename portion of path ...&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pszFilename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// the buffer passed to AfxLoadLangResourceDLL is filled with the path ...&lt;/span&gt;
		g_fLoadingResourcesForMFCDLL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		hLangDLL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AfxLoadLangResourceDLL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MFC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		g_fLoadingResourcesForMFCDLL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

AFX_MODULE_STATE&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; pState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AfxGetModuleState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
pState&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;m_appLangDLL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hLangDLL&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;VS 2013 MFC DLL DllMain 부분&lt;/strong&gt;
&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 MFC 취약점에 얽혀 있다면 빠져 나가는 방법으로는 1) VS를 업그레이드 한다. 2) MFC DLL을 새로 빌드해서 사용한다. 3) MFC DLL 바이너리를 패치 한다, 정도가 있겠습니다. 바이너리를 패치하는 게 가장 쉬워 보일 수도 있습니다. 플래그 값만 교정해주면 되니까요. 아래처럼 리소스 DLL을 LoadLibraryEx 해서 로드하는 부분을 찾아서 0을 2로 변경해 주면 됩니다. mfc71.dll을 사용하신다면 일이 조금 골치아파질수도 있겠네요.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 619px; margin-bottom: 16px;&apos; data-url=&apos;./MFC_위성_DLL_취약점.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/070a527497535ed2addc4e8a9f44c652/80833/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 34.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABYklEQVR42kWQ2W6DMBBF+f/P6ZpGqA2kbaouaiuWJISwJNjGYAwJGDAEXKd96DzMSDNnpKujqKo6mdwg1GWZoFSkaQvh0baTOK4Y645H3nUDRMe8KbKKFvXBSIx3+O5Sl9ZUmc206fTOtlvORdeNwyCEGGXJgVAZBPnh0DoO6ceONW1VN7zn/dCfxpMElPv7B1WdmmYDoajr8XReir/nJGEYs7LkppmSonR3iWmSGLFf4Iwpj/PZ4lkzDeSsyS5AGMUZiUkaFzn2tqGzDqI90DXje2ks3r7Vu6+l5VUllQDNUuVl8fT2+vT1CW0rgSDCMUgwkJ2kcLsNl5YPkL/be4EfeqG73a8dF/lhRnNU0Fi5uLy6ub3++GgBFBEY6/o/dhRJc0TG9vyCQk5IXhwo8PudJcBGXgdF1/X5XFut2iiStoemkW9S29kbxpXv5WXZblakCjm2mKNR4jRDKPh+ZIz/AN/Ge5aTSu64AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;MFC    DLL     md 0&apos; title=&apos;&apos; src=&apos;/static/070a527497535ed2addc4e8a9f44c652/80833/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_0.png&apos; srcset=&apos;/static/070a527497535ed2addc4e8a9f44c652/08678/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_0.png 190w,
/static/070a527497535ed2addc4e8a9f44c652/2edd7/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_0.png 380w,
/static/070a527497535ed2addc4e8a9f44c652/80833/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_0.png 619w&apos; sizes=&apos;(max-width: 619px) 100vw, 619px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;mfc100.dll을 사용하신다면 LoadLibraryEx에 사용되는 마지막 플래그를 0에서 2로 변경해 주시면 됩니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 617px; margin-bottom: 16px;&apos; data-url=&apos;./MFC_위성_DLL_취약점.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/eb1735b2e56495d35666ebffa24a34ce/8a174/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABe0lEQVR42k2R21KDMBCGef8X8kJH69gLT0UKaZsSEAkEGjkFCCpFEpdSHXcyO5md/ef7d9d4fl5dXl5YluBcS6m01uOoIODz/i5dt2jbPgiqIvvKhEgkY03cH4epTY2GbTt3dzcYN4xB96zSv+Juv8+77ohxHhYxa1ghq7wckmTUp5jEy+XCskrf1wipJNEzHHKWdZTWIPa80gowLdih4bxspdQzw1ivbSAjVEOp79UwzOQp53kHtkEcRfVnN8qvTzEUzq6l4bnHcBx0e3uNcQ3MOFZN89+2BMOt7Gkgev6haqVT3cb6o9Nn26b5clpYtdloztVcncUn20LKI0LcpGuceG9Jeuy/Z+xEfnx8WiyuHKdx3bPmv20wLGVvWem0s6hCW55n3V+DAaeCmU1TwMIOBwWT/5E5l4RMp9puM0JKPzrYFCOfVaWuKi2ENlar+6eH5cbZpYym7I1FQRS6UUhiSl49l+zdMCCvvsdTCq/IY49QvEuRHexx/AMIEu+VxgSmCAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;MFC    DLL     md 1&apos; title=&apos;&apos; src=&apos;/static/eb1735b2e56495d35666ebffa24a34ce/8a174/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_1.png&apos; srcset=&apos;/static/eb1735b2e56495d35666ebffa24a34ce/08678/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_1.png 190w,
/static/eb1735b2e56495d35666ebffa24a34ce/2edd7/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_1.png 380w,
/static/eb1735b2e56495d35666ebffa24a34ce/8a174/MFC_%EC%9C%84%EC%84%B1_DLL_%EC%B7%A8%EC%95%BD%EC%A0%90.md_1.png 617w&apos; sizes=&apos;(max-width: 617px) 100vw, 617px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;mfc71.dll을 사용하시나요? 일단 눈물 좀 닦고. 상상력을 발휘해 보세요.&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[뉴스타파 전국 유해 물질 데이터 지도]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/14215</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14215</guid><pubDate>Thu, 28 Aug 2014 23:59:51 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;주거지에 유해물질 유출… 세월호 이후도 안전대책은 제자리&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;내 집 주변에 위험물질이? 전국 유해물질 데이터 지도 공개&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;뉴스타파에서 전국 유해물질 데이터 지도를 공개했습니다. 참, 잘했어요. 짝짝짝. 심심해서 좀 살펴봤는데요. 씁쓸한 뒷맛만 남는군요. 지도가 궁금하신 분은 &lt;a href=&quot;https://www.google.com/fusiontables/embedviz?q=select+col2+from+1Vq_jabeFv6xRKWSiNn7GFjZc1TmFhOPSyg-R_vOh&amp;#x26;viz=MAP&amp;#x26;h=false&amp;#x26;lat=37.00650005319146&amp;#x26;lng=127.65704403161624&amp;#x26;t=1&amp;#x26;z=9&amp;#x26;l=col2&amp;#x26;y=5&amp;#x26;tmplt=7&amp;#x26;hml=GEOCODABLE&quot;&gt;여기서&lt;/a&gt; 살펴보시면 됩니다. 집 주변 한 번 확인해 보세요. 하나라도 유해물질 보관하는 곳이 있다면 포풍민원질로 공무원들을 쪼으도록 합시다. 그래야 그나마 조금이라도 철저하게 관리되겠지요.&lt;/p&gt;
&lt;p&gt;하루가 멀다하고 무슨 사건 사고가 이리 많이 터지는지 참 어처구니가 없는 시절이네요. 다들 몸조심 하세용 ^^;;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./뉴스타파_전국_유해_물질_데이터_지도.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dbadb1967d1c0681b223d3a303076704/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACf0lEQVR42hXSyW7bVgCFYb7/S3STIonrxlUGU4EHQbUoiqM4XvLOA+/AyUnbLFoUbV1ldZY/cPB5ApWaAafQpNky2VV3d0Gzif9Ms1Nb31fN8edwfR18uw7WpE5meaOwz7vDZJWVvccxGDhcRrEu1g2orPOr5G//kJvidsDJJHMG9uf0uDuTm3j5JR0O+asG+k4+KRp7mEaKwS+LMzTzg/pN/JL1Oe82ksBZQeP4l3VaR/mbjgm8uwqG16dvP53//Xie/Wzwsv4w4FKR0zEtfoz+8wv0VVytshglWjVeZr1YyHHRwoNEt6D44XMK3p3+uMr+eZO+eG3lV+X9fUZfRS+fyl7xj10YjbicJBgNxX1KYIK7iOKSE/93F+LuXX3ecfJQdXfebfH8Nnu5Kf56alPUXJv2VEcHyTsua0YqRsrRMmeIU1iwpG1rAGMqT1KljBy9t8F6E89lt53pRtfBJdWnG626eVSjYcs4rJcxaSf3UtC8CgHaA3IkPB8M9aLj+zb9YNBe4pKBAKNYVLcOPU1WzlYuo3KOS91SlWlLn23u2EPVJoPqRkM83Iake6IikgKg8lGAeEDxcL7WAxosVBZJDQU9O35enGK4UWjXlNu0uAc48hjnghbLpcJBix8YPLAuTYOAklrS2ln2PNtJS00zI6rvouodA3caphI/eJj0mvej5QXxIU+YaCTNuvqEir3pG6epNZiKhIBHmm0FyCiMCPwgm0fV/er1sHIGY5wX5DMzzeVVh88ax7rZWoYniSgLAdwOXXhBAtAnRvay3zl2WEjjYYaUbCctarrDIlysmMR3W0u1MX2m68TQUpMC04KyXLBHTkMnsq8rG0n1P8AMjoQfgC1rAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                     md 0&apos; title=&apos;&apos; src=&apos;/static/dbadb1967d1c0681b223d3a303076704/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_0.png&apos; srcset=&apos;/static/dbadb1967d1c0681b223d3a303076704/08678/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_0.png 190w,
/static/dbadb1967d1c0681b223d3a303076704/2edd7/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_0.png 380w,
/static/dbadb1967d1c0681b223d3a303076704/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_0.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;강남, 유해물질이 뭔가요? 씹어먹는 건가요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./뉴스타파_전국_유해_물질_데이터_지도.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/52ca7a1133e3e7bc7c256c2d9c829879/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACWklEQVR42h2SW3PTMBCF/f+f+BHMMMPwBJ0WHkhJb2mTOLEjS5Zl3S8rWXbSduAHIHjf3XO+PafKySyTszAq3oi+Vry1Gm+HOyUfMjiu9hOwZNuerGn7jJtrLa+HfqXEw2R/VTOo90vwQFuyYqxWBvXj7jj8GOUeK/JYHyV97I4rIbsiE5wRvG73d/j0yPpdFXwn9D2S3zt5axS20PXqIZj6DGOLbl5a5K1NQU1B5KgyaOuo8+Q8ufMcKqx/RpAqtODGJWrCd4TfZ3ug3VqI3gKdQSfPg2FT1P+vkNfFxMCNIZUP5H0WGehliQDAyIbTr+3xQQhxXpwwaI7GO6JU69zgDA4WaXkS8pijqTQ/CHLPTl+Gw4emadb7Z0FvTohGL8Fi47HRSBsS7ACGhUABxmDHYgECK8uUSGQsFvRJCNXQQYgDxmVaTp5TsROyLXEkxxl/2etvHrpLEfV1Y64rnRoUrpxt9LA1glrdbE/bzfN2il7JE+NbB+ycQ0qKh4a6fYjibU4pi5R4ReTVQd+4whZojKOxlOI1qjdcDka2jhMHo4XBAsvJZTCqgMCgfO+Kbcs3xjIpDtEhI7Hh6Niue/LYdvUUlBP0PEMhVOw4J7ukQstzdNJtmdhWoBurB9t/subU041gu7Z/6vtVjw602S3ZFeB58jnQ5Nkc9ZJ9jnouXwiy8urJ8L0nH0f3xNwmmH95lKrh+q5Hp+h5ibBovl6gkBfbl6zfXueSRQJVBYcX6KzCL+NnLG+txFI+S94hdL+/W3lNzwtMoM6z+/P7rbTqsoTXBYJl0bG/KxyedwIQXfwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                     md 1&apos; title=&apos;&apos; src=&apos;/static/52ca7a1133e3e7bc7c256c2d9c829879/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_1.png&apos; srcset=&apos;/static/52ca7a1133e3e7bc7c256c2d9c829879/08678/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_1.png 190w,
/static/52ca7a1133e3e7bc7c256c2d9c829879/2edd7/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_1.png 380w,
/static/52ca7a1133e3e7bc7c256c2d9c829879/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;구로, 생각보단 작은뎅?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./뉴스타파_전국_유해_물질_데이터_지도.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/be85fb91963b667c838b535fe3896f9b/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACmElEQVR42hVRSW/zVAD0HwcJznBEHDhyQRX9qPi6QJv0y9bYSbzFy7Oft7f5vXpf4sQt/YSEuYxGmhlpNCNtvHFmf11qUQ4XuSBlRlMSoBjiJKxKceqbIucTjpfhNUWc09eiyVhQF7zvKul0ase3cblzoC3naYgDPeNxmRGaeIHnCBYLBjnzu0YIjgkNU4GzjA19/X946JuP97NlGjBwSFYKkXVNdjmfJplTGCcQYwDRInTXfuQCdWctHxE49m3ZNbk0Xvp/Pt45Dl8s1aIyfRW5QG1T9G01OSYSxl4IdJiY8t3N888/eftNdNTOQzecWqkq6pKAIXywfJqkBiucsmTnvq5LgcMjjkyOHMvRNW3/5/fffv7uG+w7JLLrKjsNJ4lGMXLtlqos8gNr5miPGKdlVU2tgLYJbTmJzIC7pvpoq7Jrba3d3x5YmtEd5YqEKON5eXkbpyaU2EvlyjkuUTpNkUJ7S7Djek4cWOCwsr7MrINsuCtCXJLMWKxIe9hpfnnuirbKcuYz4bvB9al2+rqh2LAdRV/MjacHV154u7Wzflb/uktQCJ0Vgp50f/xXgQWkIEj0nKO2ENM2qn9bkpUdspUceouHl19/2Xx5oSk63F7LN7+Hu3kWGUWaSL8po0leEIe7aIM4iAI9CgyYqDqYbU3zj0Nzv4rnVzfa3mS+Ln+6+vzjD2B7G+zWDAJpej2r7L5pUpESBAiBPjkgAlJRUIaixFUcX7eV3fz66X4JD3OwnlXs2GSiLrDkIrOuium0LOOOoWBmJghgmrR5kiWrNNH6iuR1F6bN3hVb1TmoRuw9NXwFoCFtwPMx2rQlbqoMkzgMdMySFAWcwJxqVaoPp+7t0n+M3df3YbiMdde/FvXS4k+G+A939JoVnj+dhQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                     md 2&apos; title=&apos;&apos; src=&apos;/static/be85fb91963b667c838b535fe3896f9b/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_2.png&apos; srcset=&apos;/static/be85fb91963b667c838b535fe3896f9b/08678/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_2.png 190w,
/static/be85fb91963b667c838b535fe3896f9b/2edd7/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_2.png 380w,
/static/be85fb91963b667c838b535fe3896f9b/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_2.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;송도, 이건 뭔가요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./뉴스타파_전국_유해_물질_데이터_지도.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/abfb77d0de8ab95e01f7bce5e81f2ab2/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACK0lEQVR42iWSy27UQBBF/d98DRsEW3ZIMAKJTQYnMyRMEnsytttuu99d/QoSaEK4TqRaWO2qurdOVZWCzYkeSywlFeoCmRiISGvDH0sip4yc8FgyeaeN0SVnLZjoL/RYV+S14B2SUnS8v17YVYpm7ZXDa0Qy5G2KIcTg0UA8yOEiutGqvrJGsO6OsyMfD7dtd/j5jtRlTiUnH4NNwcFXCA6lcKSXZrj/pubWKCHEsfLoGqyYOj7gaSk5enVv1QBNssIqXgoaheB58p3m+xQoBmf0mlkhCSadkXIeiHxOKUUddZPi6jyGtPSfx+ZDdlz210TrRBCDCadYdeSJCVJaC+28h1WfcrH8MJ9qZ5jgjRh/iOkXBsEvkAOaBI5m5qcaxcGCA0UKEZZzdCvw6OVQ/5k2uXm/NBvMu84f3ZqwsnDBa4CsYGONHFCWogd2wMe4f33/b94+849h+2bqrwyGz4QAP2+F4CejpsqpeW0THDltlyklT14i4xzYE/v+rHbnOOr5pm8vX7cNw6d2r5YBSpWaJ5S9sJWS9zAGjDFSInmm4SkL0lKyu7m7sCBcAru7Ubx3ZsGBVBSwRkwSzDL27WGUrbLz75LRzlsJR14JNTYkr/yLhp5HqHuzwG8FhzCAesixpa3bTcNqbUWMVulpkScs1qkhuQ4Lt2oCOZwtmuKjQiUCa1jEuH/Y1M2n3fHrPdvvus31tNnefIG2mPb97VscQH5Jhj6Y5+T/A7poxnxNUwQOAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                     md 3&apos; title=&apos;&apos; src=&apos;/static/abfb77d0de8ab95e01f7bce5e81f2ab2/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_3.png&apos; srcset=&apos;/static/abfb77d0de8ab95e01f7bce5e81f2ab2/08678/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_3.png 190w,
/static/abfb77d0de8ab95e01f7bce5e81f2ab2/2edd7/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_3.png 380w,
/static/abfb77d0de8ab95e01f7bce5e81f2ab2/dface/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_3.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;유출지, 개수가 중요한 건 아니라는거…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 382px; margin-bottom: 16px;&apos; data-url=&apos;./뉴스타파_전국_유해_물질_데이터_지도.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b752ac3db512f9f9fb1e9c3245ac64f9/29984/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 158.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAgCAIAAACdAM/hAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAGNklEQVR42nWU61Mb5xXG9Xd0ppPpF+dLJ+m4aepMnDbTyad0XDzNEDuNnaSxM3Xj2HFwjOPLFEhczCVgg4AYMDLBllhdVtpdIZBW2JJWErrsfWV0QxcLJAsJWRJYITZI2r6SgM6k6cw7O3uZ33nOnvOcI1lby2TX8sV8diMbWc+vFp6sFnOpTDKcTITTjxPJ5UhyORoKU5EQgzhSsGdTz4t7R7JRzOdya+vFfCEbe5IOlorpzGoyk02mM/F4kFiOuGNhd+ah8inds+CwQu4tjKtgXHUHjqXyubV06Um0+CRZTIc2CssrqRShgRgcWQrYGYFJ+G2i0C16P81bu5GFjE4QMba8A3vCPxr5zfRqOrwUXU4u0/eNd65cvvTHP8B9XaTHppeNZwSlyHWWqasV52dek3IMDWE+sSEuQcgfpmxPFbYczm7ghvuj51pkx45CVy56cW0i5PWbFQnbuBgfF12nqu6PA/o+eVe/yv0DgMGRoGxFz1V0dBkVxNvdQ+/+6pftTU3Spj/bp2XZ7NLK4ygByQR1X4G4GneNx0IWl3xI2ntPVxOvSBoxULYKk1uTo/rjrxw4/cpvbjW9PXH6n7QT592OictfWKFbtEXnZ/BowCoQqnvScTUNyibWYJSrGvgqxm5pXet3xlSfvfrSV68dGP/LoYkj78C9PYsLM0uE8sFtqUs14VuAzaOdFK4xUEUNWW0oV1BOVFgK30lnpe2jn7780tX9vx0+dfJKc7O+q+M+JDfcGlRfPLvIWONhgrjTx5lVatWsxvNM0shZS22jiGu65Yvpj97veO3giX372psOXTjwe+jSeQf6fTwZ8mKTlFG+EqGDpCmwAPsSWSVZTxthqyizHUisP/QJ0KUWqPXc1ImP2vfvb/vTmwQCpSJu3nA3HmVpo8pJzK/EyGR0QaBIhWV9p2BqsmJYFM2o1Tx4k7HOOaek1w8evPG3o2HanMuH56U95H1b3O/VS/si8VD2MU+zAYVjcwdGmApoPSrHZ/q7H0yNadu+HD1+VHbxfMBtjAkWr3o0GQ3nVhbDlBmkkIqRVHhVRYk7MGi1lhMhxGcf6TKNDECd3abhPtmH78lbLxgHe9zwODp8HZcNB72WZEpIBOzQmBbagzFgFUEcg1jpqU+mWi/c/PgDzo4zRk2Ee0Ca4Zlv2745/NbktcsBr9mtHLGNf9vRfERpTu6ZpKL3iTJs6TsprGg93/XWmzb5SDxGxVh90OcIUPNTl1u+fOfwyLF3h099Irt4bnroBurISYC/G8oIL2qdxQfYPDbQa1Xe4ayw36b0WeQ+izIVIqY6/tX/9+PY9XbSbbHeHUF6eiGisJs2V9VQVf18lJmDoO5ri37Wq510QQOMdkCwwfFHUS9ucKIQPtCr6mpvfeNA8+9el9t2WlXBeFFBlAjEEKcMFgyy3btNDHe41COs6e6jIBEMCdrB/ntft/WfPHGj+a8Xfv1i25mvtQ1vY2z9n8lSNpdCrrV1Hn474NQGCTgZ96wkHwaD3NjZ0/CV1q73j5x8cd/pF37Re6hZ5VwHNarBWrpq5MsLS2VChyrP/EPzzb+dsPxRxGWaHPTbUOfcHNzbiV36/GZL59AI+tWxsxNKTr9Y2ydgnoFDqrNUAUJJiwqibY4Q74k+tPN282TXzTOvHzSZPGZPWiEz3P78vBoTsLCICRWgB2ZRogMkX55nCyjOwaNjbly7HHBwgRju4DUzvu+HlCb/cx39XENtzXKbCPUMYco6umIWNlGmrqxlRCNTWmAjLjJkn9GTQmKGKlGLy7P0hkHYrok0tg0jovUR1NHbQjSvpeubBIjjvi0TWzJym/PuwIw7M8sDpqxjKjXP13dt3cK1A5TmmKc4ndVQu9UGVzCfeq5s4LaBYUC42oZgq3su2F30wA6iw78xy/4Iovx3h+lrCgCoM+CR/wm2A9eHH2RUu5E03jasAr6BHbqn9j8kSK2K1YMCEuS4623w57yo9Gyr7CUNLSJ15Z+Su6cBY2wdrpWBFTWWrIPgnHqMXVpD6PL/w+qkiNBbKvezHWWgBg+MBgi1Xaue5wugh9jPwWitutsIvW2gS8zS7kjqWHF6Lq40BhWGAAiENhrzc9kCTWAVHflcbwv9BxMznJHvHq+AAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                     md 4&apos; title=&apos;&apos; src=&apos;/static/b752ac3db512f9f9fb1e9c3245ac64f9/29984/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_4.png&apos; srcset=&apos;/static/b752ac3db512f9f9fb1e9c3245ac64f9/08678/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_4.png 190w,
/static/b752ac3db512f9f9fb1e9c3245ac64f9/2edd7/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_4.png 380w,
/static/b752ac3db512f9f9fb1e9c3245ac64f9/29984/%EB%89%B4%EC%8A%A4%ED%83%80%ED%8C%8C_%EC%A0%84%EA%B5%AD_%EC%9C%A0%ED%95%B4_%EB%AC%BC%EC%A7%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A7%80%EB%8F%84.md_4.png 382w&apos; sizes=&apos;(max-width: 382px) 100vw, 382px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;유해물질 청정지역, 강원도로 오세염!!!&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[RPC를 APC로 구현하면 망하는 이유]]></title><description><![CDATA[어제 새 기능 버그를 잡고 있었는데 생각보다 일이 커졌다. 결국 RPC가 필요하다는 결론에 도달했다. RPC를 뭐로 만들지 고민을 한참했다. 어떤게 제일 손 안데고 코풀 수 있는 방법일까(?!) 고민한 끝에 APC…]]></description><link>https://jiniya.net/wp/archives/14201</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14201</guid><pubDate>Tue, 26 Aug 2014 23:59:50 GMT</pubDate><content:encoded>&lt;p&gt;어제 새 기능 버그를 잡고 있었는데 생각보다 일이 커졌다. 결국 RPC가 필요하다는 결론에 도달했다. RPC를 뭐로 만들지 고민을 한참했다. 어떤게 제일 손 안데고 코풀 수 있는 방법일까(?!) 고민한 끝에 APC를 사용한 꼼수로 구현하기로 했다. 메커니즘은 완벽했다. 마치 APC는 나에게 RPC 구현을 위해서 만들어 둔 통로처럼 느껴졌다. 둘다 procedure call이니 뭐 도찐개찐이기도 하고. 여튼 그렇게 지루한 코드를 제법 쓰고는 얼추 만들어서 테스트를 하는데 이건 뭐지?! 주구장창 크래시!!! 그러다 찾아본 QueueUserAPC 도움말. 설명을 해놔도 안 읽은 내 잘못이 컸다 ㅠㅜ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note Queuing APCs to threads outside the caller’s process is not recommended for a number of reasons. DLL rebasing can cause the addresses of functions used by the APC to be incorrect when the functions are executed outside the caller’s process. &lt;strong&gt;Similarly, if a 64-bit process queues an APC to a 32-bit process or vice versa, addresses will be incorrect and the application will crash.&lt;/strong&gt; Other factors can prevent successful function execution, even if the address is known.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/ms684954(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/windows/desktop/ms684954(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;믿을거라곤 이벤트와 뮤텍스, 그리고 파일맵 밖엔 없는듯… 아님 파이프가 나을래나?&lt;/p&gt;
&lt;p&gt;뭔가 일이 쉽게 풀린다 했지… ㅠㅜ&lt;/p&gt;
&lt;p&gt;오늘은 장사 접고 낼 해야겠다…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[윈도우 스토어 앱 개발하긔~]]></title><description><![CDATA[iOS가 판도라의 상자를 연 이후로 요즘만큼 개발자들이 피곤한 시대가 또 있었을까 싶다. 초창기 윈도우 프로그래머로 일하던 시절에는 윈도우 9x…]]></description><link>https://jiniya.net/wp/archives/14118</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14118</guid><pubDate>Thu, 31 Jul 2014 23:59:49 GMT</pubDate><content:encoded>&lt;p&gt;iOS가 판도라의 상자를 연 이후로 요즘만큼 개발자들이 피곤한 시대가 또 있었을까 싶다. 초창기 윈도우 프로그래머로 일하던 시절에는 윈도우 9x만 없다면 뭐든지 다할수 있을 것 같다는 말들이 유행했었다. 그렇게 영원이 악몽같이 존재할 것 같던 윈도우 9x도 윈도우 비스타와 윈도우 7의 출현으로 역사의 뒤안길로 사라졌다. 그렇게 잠시나마 태평성대가 오나 싶더니만 iOS와 함께 온갖 종류의 플랫폼이 우후죽순 등장해 버렸다. 이제는 차라리 비슷했던 9x를 지원하는게 좋았다는 생각마저 들 정도다. 갈라파고스도 진짜 이보다는 상태가 나았지 싶다. iOS, 안드로이드, 윈폰, 블랙베리 같은 온갖 종류의 디바이스가 세상 밖으로 출몰해 버렸고 똑똑한 프로그래머라는 소리를 들으려면 그 온갖 종류의 디바이스에서 동작하는 프로그램을 다 만들 줄 알아야 하는 시대가 도래한 것이다. API 세트도 다르고, 언어도 다르며, 심지어는 OS, 더 나아가서는 CPU까지 다른 환경에 익숙해져야 하는 골치아픈 세상이 돼 버렸다.&lt;/p&gt;
&lt;p&gt;이쯤되니 요즘엔 윈도우가 PC 시장에서 그랬던 것처럼 누군가가 그냥 독점해 버렸으면 좋겠다는 마음마저 든다. 사용자에게는 선택권이 제한되고 개발 생태계에도 좋지 않은 일이란 걸 알지만 이런 온갖 종류의 디바이스에 들어가는 프로그램을 만들어야 하는 프로그래머의 고충도 보통 일은 아니기 때문이다. 하나 하기에도 바쁜데 하나 배우면 또 하나가 튀어나오는 식이다. 그.래.서. 요즘 개발자들은 정말 피곤하다.&lt;/p&gt;
&lt;p&gt;그런 피곤한 개발자들에게 윈도우 스토어 앱이라는 신세계가 또 열리고 있다. 지금은 시장 지배력이 낮지만 영원히 낮으라는 법은 없고, 아직까진 경쟁자가 별로 없는 블루오션 시장이라는 매력도 있는 그 윈도우 스토어 말이다. 남들보다 조금 일찍 배에 올라타려는 프로그래머를 위해서 스토어 개발에 관한 이야기를 몇 자 끄적여 보려고 한다. 모든 플랫폼이 그렇겠지만 기본적인 환경을 구축하고 돌아가는 메커니즘을 이해하고 나면 나머지는 그저 소소하게 변경된 API와 언어 뿐이라 생각보단 금방 접근할 수 있다. 그럼 이제 윈도우 스토어 프로그래밍에 관해서 한 번 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;백문이 불여일견이랬다. 일단 한 번 만들어보자. Visual Studio 2013을 사용하길 추천한다. 그리고 영문판으로 설치하길 권장한다. 이번에 컴퓨터를 새로 사면서 한글 윈도우를 설치했는데 내가 한 일 중에 가장 병신같은 짓이었던 것 같다. 프로그래머라면 영문판을 쓰자. 그게 검색하기도 편하고 문제 해결하기도 수월하다. Visual Studio 2013을 설치하고 Project, New를 선택하면 아래와 같은 깜찍한 다이알로그가 출력된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/372fbec30b9aba24f10c498ad588041d/dface/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABx0lEQVR42nVR23LTMBD1X9Nh2v5GH/kLHoEZLm1pSpmQ0FAcJ47txrauliVZ8iXpSoZAmHK0K2l25uw5KwXo+gW+OSOTc3L7V0zO0c0pnkD9DC4QUEw+vIzenYRvT7aXp1AHVhAtrr7M0jBGaak2ufSh4m0VLtOfEFHyWNACi4dVHq63D8sNZpJwRSuVYxGk4ecfURHFeclsTpqSNpgZROVqGXMmMCaMcUoZQkTpZhj2w+5PBAp9q4TOt49Db/cOO0htzHw6b22rtW4cdKP1ANRjBIbOoUdeFG9m5XVs1pWrNtauorWSCoEiocjDGON673ZHZDhs27/6RC/e09ezelS+n90bbWqAqKWUsIOLZ5Th6Fpbs1JyJEjJOW+MzZJMKw13XlUV7Iwxygghoq7/JaOyFLU6uGq7fno3lXUtlRQeXddBHcZ+xnblWvND1dj27vYrkCsHpyqlsn7mI9uNJ5dFAe0PykrpxXwBQ4JfN7UQo/2+d9qQvYdT7oc9QQhjDP/yS9nYy49XWZomSZJ6ZGmWeMRrt8Am9Aos+650u15Fy9Ct8T+6frDWQm8YFXLU6X5fem8A4Mi8Ukm8GR9m8Lb7o3f5L54AWGXV4TtPCPUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 0&apos; title=&apos;&apos; src=&apos;/static/372fbec30b9aba24f10c498ad588041d/dface/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_0.png&apos; srcset=&apos;/static/372fbec30b9aba24f10c498ad588041d/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_0.png 190w,
/static/372fbec30b9aba24f10c498ad588041d/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_0.png 380w,
/static/372fbec30b9aba24f10c498ad588041d/dface/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_0.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;윈도우 스토어 앱 프로젝트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Visual C++, Store Apps 아래에 우리가 선택할 수 있는 프로젝트 형태가 있다. 유니버셜 앱이라고 표기된 것은 PC 윈도우, 윈도우 폰 환경에서 모두 동작하는 앱을 개발하는 것을 의미한다. Windows Apps는 PC 윈도우에서 동작하는 앱을, Windows Phone Apps는 윈폰에서 돌아가는 앱을 개발하는 것을 의미한다. 유니버셜 앱이라고 특별한게 있는 건 아니고 공통 코드가 Shared로 빠져 있고, 각각 디바이스에 맞는 프로젝트 두 개가 생성되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;프로젝트 종류도 여러가지가 있는데 Blank App은 그냥 비어있는 앱을, DLL은 네이티브 DLL 코드를, Static Library는 정적 라이브러리 코드를, Windows Runtime Component는 윈도우 런타임을 사용하는 DLL을 만드는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;유니버셜 앱의 Blank App을 선택하고 프로젝트명을 halo로 만들어 보자. 만들고 나면 솔루션 탐색기가 아래와 같이 구성된 것을 볼 수 있다. CTRL + F5를 눌러서 실행해 보자. 윈도우8 환경이라면 그냥 실행될 것이다. 개발자 환경 등록이 되지 않았으면 뭐 자질구레하게 묻는데 MS 계정으로 로그인해서 인증을 해주도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/cea0c5e8c7c7fcbb90c37b7338e48393/f8bcd/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 126.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAIAAAC+dZmEAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAD3klEQVR42o1TS28bVRSeP8gKAgsWiAUKrVSqUhKogEYxVAToBhaEuEClskorkaRV7BDl4aTYCXFc25mx5/2eO/bYmRnbE8/DHo85YzePpgHx6czVle5853zn3O9iU4mFz77+5VOIrx5AfDwzPzW7MD3zw0dfzF///KdbMz9PzyanEslPYB1HIgm/3bn363Qiib3x3pe3Ew9v3k1evzN/a/a3m3cfTHz47cS1++9c+w4C9m9NzsH6dhxzb37wzcTk3Ls37r9/+8eJyXvY9/NPsofsZrayspZb3z1aTue2ctXVjYMnT3eWUtnUViGzTz1dL+zupojicq7A/XUoPM9zeVxbfJbDko+e6XWb4lDxiKnQMl7lKU4jKKlc4csES7KqjExWNBASrAap6Jai2zKyRLW5nnmBPVpctSyzVm8cm3atZpimXTcahtG0Wp3jY9Nxup7fC4Ke5/Vdb+B5AYTr+qZp7uVx7PHKJtJUUZAYhtM0JEsyQpCkwTIsw7CW3Y6iYT8cDAYRfOEgguj1B8PhsEpL2OLSer/ndS1N4hmgRVHUH6E3AhCGY0COU0CimMxI2NJqBnYtqykQXLVCkhSF43i5XOYFgSCIYuGwVMYlSZJleRC9Tk7twK7jOO2W00akIrJAtlotqO0Hvu97gACaDnrR5coyVI7JoDOKBk1D1jSVohlNUZEe96/IioY01/NGwkF6dEYmz8iu5/tuV2vWJVXjWEbghWqlwgtitUKQJCnLyhn/CnKv34eT7N4+z4uiKEmCxLIcQoihaSYeO8PzvKKojuOMyINXyNAY5JZVpMoSzwnwO2QQBbF74gZ+0O2edNptYML8z8nshZ79ICjihI4Q1KIoigXxgljTa7qu9/q94QW8lM0q2MLDFVk2imWWLLHp9O72zsHW9n46nUmlM3+uP9/YyKbWdrYzB38fHGX3irm9Uv6wUj7iRMlY28xjvz9e63YDQdRkXpOpEoETB/myIGmGYdXqZt2IQ4RTWVfVujRakd5sd9y9fPV0YD2wYGg3RIQUjuPB3JZtjmHb9rjVK2T/MXKY5wd930PNuox0mqJ4DtxWpSj6RaFQLJbAYHCVL686isLw1Wk7JydOp6PWDfAFQzNQXACIsm234MiyrDH5cuVT2WDGIF/CNRVkC1CcommW4ZqNplE3rpRNcSq2PPJ213WdhkPihKqqUJlmWAPaNu1jIBtGbKH/IFu2bWkmXHIsVhQZmnXdcz9ewjl5LNuHFxQEqGariiJKoiSIMML4v2jwOv8COTV2WAgPpt1oofhhcNDn8N9xuXIYhvHMO44FN3tshf3w/5D/AdHqHnS4R9VmAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 1&apos; title=&apos;&apos; src=&apos;/static/cea0c5e8c7c7fcbb90c37b7338e48393/f8bcd/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_1.png&apos; srcset=&apos;/static/cea0c5e8c7c7fcbb90c37b7338e48393/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_1.png 190w,
/static/cea0c5e8c7c7fcbb90c37b7338e48393/f8bcd/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_1.png 350w&apos; sizes=&apos;(max-width: 350px) 100vw, 350px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;스토어 앱 솔루션 탐색기&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CTRL + F5를 눌러서 앱을 실행하면 어디서 실행되는 것일까? 센스 있는 프로그래머라면 알아차렸겠지만 CTRL + F5를 눌렀을 때 시스템에 설치되거나 해서 실행되지는 않는다. 아래와 같이 디버그 빌드된 폴더에서 실행된다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 556px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/28fac8718e0b5d9d82e16384493adbed/68b51/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 67.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACF0lEQVR42m1SyW7VMBTNV7IHJHis2fAjrPkLumBFK4pYI1G16XtxbOclL4PtOJ4yc9IBtRVXVzd2nDP43kTp+Sd+/rG4eC8uP4jL3X1t7vPHVrEtvr+7+fo6Pntze/YWa/lzd/flLnr1+eLLt1+jupFl3JY3VtwiZ8dHwybLR4vKRsODpr5NnSJBk6FLh44io6s8CDv2w2S63FrFj5XuTCPaVtuibFpt6kblRV2c6nGa13VdkMs6Leu8rNE6emd0CP0yB6w6hPHTPE3TOAxD6PtxeyL6ZZnHcdSdNc5NM4iWqO+yOP7DGAerlEqKynSFMXb9XwCs2g7WQgjzPEX7ovt9HR/2e++9Uko0VadAF2O7mYTFJzH0vZQS5oQQ1rlI6IFxXhQ5yJSSTSOU0kmSZJyXZWm6zcIyP3DAPAQAVqr1PkTKj1I0xnQ4A1/dNHXdcM5IQjhjWXY8nU5lWaEHd+BhAxvTKuVDiEo9QM0Ys4EbUVUlI7eccZpSxlir9VPzALeqhRIoNuWi8lIKvMUZKLTWh/0hpZQQFGatux/PI7iXD7YB9tGx1vEhySiuXeBtH/rrK/Sep2lKCXXOP2vYvztL6QAulSMwSGme52ANzvGE8SxjlKFhGPqzUcF2C9sGFb9GVCt7IIRAnB+FlPCvW0VhOyEY6Is5Y1SP3ZYwFSnbErbHbHA9a22/HcutYZTq57IvlL0PfwHTZgoq+PYMvgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 2&apos; title=&apos;&apos; src=&apos;/static/28fac8718e0b5d9d82e16384493adbed/68b51/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_2.png&apos; srcset=&apos;/static/28fac8718e0b5d9d82e16384493adbed/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_2.png 190w,
/static/28fac8718e0b5d9d82e16384493adbed/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_2.png 380w,
/static/28fac8718e0b5d9d82e16384493adbed/68b51/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_2.png 556w&apos; sizes=&apos;(max-width: 556px) 100vw, 556px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;Debug 빌드 폴더&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그렇다면 여기에서 의문이 생긴다. 스토어에는 무슨 파일을 올리는 거지? 릴리즈로 빌드하면 뭔가 패키지 파일이 나올까? 하지만 그렇게 해봐도 패키지 파일은 나오지 않는다. 패키지 파일을 만들기 위해서는 Visual Studio 2013의 프로젝트 메뉴 아래 있는 스토어 메뉴를 활용해야 한다. 메뉴를 선택하면 아래와 같이 나오는데 여기서 Create App Packages 메뉴를 선택하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 577px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/72512e0999c441908c015f3491c53b1e/32e64/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 86.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAC50lEQVR42lVT6+vjRBTNXy/oB1n0J4iyuoIs7Mqi4iqsLPh1F7RuH3k0TZrmOY9kJslMHk2bpJ70BwsOt5dL6eGce+6p4fjU9PjGIR/s1DkWGGy/2B04OmrrENNlpstX23hjJ6Z9svaxFzDTCcNUGjv7FCT1xmV+rAt1y+ulqByPiY75xfGzP9/+sl7/9esfrz95ePnkmxdfPn316cPzz7549vD0J2O19o5xvXM52NL8wsqZV7eYnbcOtXwZxDTY/9YUb63dmx9evv7x1e/fPv/54fsXT75+9vlX3xlekLknYR5y1D4o6R2c8AFqD7GKSFNVuq4brdvh3Letvgz9ZThjnsarwYsWzB9sYnm5cxQh7QG+88/Qn/J2GIbb7TZP0zhO4zRNM8b5eh1RRkoqL6osr4DyTFywNpUTK6elV7eIqLbtAFZKUUqllPMM5JVznqWZoZprkCqALb8Ac0Q7IO818noBEwKMkLIsywofIURd1xjQjaLsvbDa7hlq7RAnkNB8r4kvzA0wbdtmWUYZI4QwxjAnSUopgWH0EEonKHFtkONCeXXj2LmcCjBnGvJAkhEahRHjudawEF+oWqm7YYlemdnKpCuThPQMn8AJw7B/TDXWU6qO4xhSsbYGutFFXsByo6lcmrwj8Xsl12Xxb6esx+q13audyF1RDae0dAMWZpV34kEimehJ3nHZGf7RO/iB5R79U+weT5brM1HJWnNZSaVF1RTlaHrC8sXGYW6kEn5hEKUXOwzbjXZ7BDtD3+7p2ski0iEwazuFkdhZVNety7cuxW/so8SOCO/dS20EQUAJwQFw/Hl5Swr+Xu/DMPL9Q5YxUY84Af4kIA/SJuFnpBh2LOCikMgAknO7v3le+mpzoJTBHp5LUY3ID0RtoM7lXlRHtIepYaaNx/R9fI/gfzYuPD2fe930AC8RutfOyx9jy3BF2hi3/7+PYAVc3+mm40Vn+8w6UNvnWydNWEfFwOQlJvV/rvaY5Mj5lwwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 3&apos; title=&apos;&apos; src=&apos;/static/72512e0999c441908c015f3491c53b1e/32e64/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_3.png&apos; srcset=&apos;/static/72512e0999c441908c015f3491c53b1e/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_3.png 190w,
/static/72512e0999c441908c015f3491c53b1e/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_3.png 380w,
/static/72512e0999c441908c015f3491c53b1e/32e64/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_3.png 577w&apos; sizes=&apos;(max-width: 577px) 100vw, 577px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;스토어 메뉴&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;종종 스토어 메뉴 자체가 활성화가 되어 있지 않은 경우도 있다. 그런 경우에는 솔루션 탐색기의 Package.appxmanifest 파일을 선택해서 연다. 그럼 아래와 같은 화면이 출력될 것이다. 거기서 Packaging 항목에 있는 버전 정보를 수정해주면 활성화 된다. Packaging 항목에 보면 Publisher 항목이 있는 그 부분이 디지털 서명을 선택하는 항목이다. 시스템에 설치된 인증서가 있다면 거기서 선택해주면 해당 인증서로 서명이 된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/082b3a8c3b8d354adc57700833b098b0/dface/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 38.421052631578945%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABFElEQVR42j1Q2ZKEIAz0/z9w10edwgPkSJBDthzdBqempWI40t1JZ40tR7nvO8bIxO8Ga23OuR0GIrqu6zxPJgoh4NZ7v66ylNJpvVnrHJHRFSgjR0opJNbZrUIbY1C2N6SUEJkZSSeEwCXI5opFbXqVcsWnVIgx5YwV8TDn4yi5bbFqguJJTHgJGSGmZVmJ2e+791UE8SjlAJ5Y/+WvAXktJmJs0DASAF5h2zlGJ49b/zA1QGNtcM5BvEN7vlYxGjbWPbJYXwtIMDMMhb2Hu77vf357eIR493qN4zCAQkoJvjYMsDU9sDDDVP40ibaPx/anZzGJZZ5hUkwzprTvoRZ6v2g3SBqlGxEVa8KcwxdgTCn9A8mVw5uCcTddAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 4&apos; title=&apos;&apos; src=&apos;/static/082b3a8c3b8d354adc57700833b098b0/dface/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_4.png&apos; srcset=&apos;/static/082b3a8c3b8d354adc57700833b098b0/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_4.png 190w,
/static/082b3a8c3b8d354adc57700833b098b0/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_4.png 380w,
/static/082b3a8c3b8d354adc57700833b098b0/dface/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_4.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;Package.appxmanifest&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Create App Package 메뉴가 활성화되면 선택해서 패키지 파일을 만들 수 있다. 처음 물어보는 항목이 MS 계정과 연동해서 업로드 하겠냐는 질문인데 연동 작업을 할게 아니라면 NO를 선택해 주면된다. 그렇게 앱 패키지를 생성하면 마지막에 어떤 폴더에 생성이 되었는지 알려주는 화면이 출력된다. 클릭해서 해당 폴더로 이동해보면 아래와 같이 패키지 파일이 생성된 것을 볼 수 있다. halo.Windows_1.0.0.1_Win32_Debug.appxupload 파일을 스토어에 업로드하면 된다. halo.Windows_1.0.0.1_Win32_Debug_Test 폴더에 들어가보면 halo.Windows_1.0.0.1_Win32_Debug.appx 파일이 존재한다. 그 파일을 통해서 시스템에 직접 설치해 볼 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 507px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_5.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2d27ef19993df10a6f3d22d40a4ea73d/f03ec/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 43.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABfUlEQVR42o2QzU7jMBSF86QghDq8AAuegw0vwYLFjMRISEhAO7NBlDJimJKmjZ1/x/lxYzu2Y3vcIirYcfX5+PgufK7t5b9OivFxdjtCt9+a30d4PKonG8V3W8ajajxKrg9fvu/Nf+w7Da8Oqsmm7/D2zy5PL342YEKLaba46cuHCkycqvrJIauZqmeyemLo0bHOH1gxFfjxDe982t2DTsqBc9p1iPKhY4L1siGsIbyXQ8cF6XqHUNpaa6zVW5Sx3jBoY5RSQ8+JYHGFK9I2GJdZlqZJsl6Ttm1KhNI0dV7rYYcQvddSyxkzenurMS69Fy6K2s9lzM6YXdN7DSs/WDV1zRiTUjAulMRF+g/CLAQwR2WByrxAUZw4QhDlCKnBRRvtxsYtX6zAMgh834cwSuIYr/s5yJ79+M8rnIMiiEsfln+D5DmIZy+hazoflV0rrFfUdLGCMYRpklJKAQD6/Qkfhtzsb9b9kHZre/Aw4UsYhcsVADBLMkKI/XL9ByF37BvOD/Y0AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 5&apos; title=&apos;&apos; src=&apos;/static/2d27ef19993df10a6f3d22d40a4ea73d/f03ec/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_5.png&apos; srcset=&apos;/static/2d27ef19993df10a6f3d22d40a4ea73d/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_5.png 190w,
/static/2d27ef19993df10a6f3d22d40a4ea73d/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_5.png 380w,
/static/2d27ef19993df10a6f3d22d40a4ea73d/f03ec/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_5.png 507w&apos; sizes=&apos;(max-width: 507px) 100vw, 507px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;생성된 앱 폴더&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;스토어에 올리지않고 appx 파일을 시스템에 설치하기 위해서는 윈도우 그룹 정책을 변경해 주어야 한다. 실행 프롬프트에서 gpedit.msc를 실행하자. 그럼 아래와 같이 그룹 정책 편집기 화면이 출력된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 562px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_6.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/83e2339d21a2af8e357d0f98f0cd3281/a4f00/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 50.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB/0lEQVR42jWOSY/TQBCF/VM5IIKAjDjzCxAXNEIgIQ5wAIkRHLgwg8ISRckkTiab4yyO7cRLb+mO7fbu7METhqdPT69KVaoSSP2Z23zq1J94jaLbKHpikTeL81JhevlALz1UrgrKZQGUH3PxzDvh1M9g+ZHy/P74xT1BH14p04ltDiW5j6CqqWMEZ7LUosTIYicJaBKynDQnWp7IA11vQg4qwlQVNYsZxqgmm5Dh1gAMNTDSkYldRH1IfUQDzEKL+CbmBvJO7lo0NZSqEKEaZ6qq6pZt7fd7w7K//Sy/+1o+/1R6c/H77ZfKx5L04Xv7T1tvjuwbBdVlQxwaNRlJ3V9CCKucTgwTrLLseDwSsuh1u51OR5bl3CVJ6vb6sjxwnWXk83zA91gcBWEYR6Rzu0ztfl+SdU0Nosi2bULwepVt1ussTZMkzrJsu924Hm/3FQ163ZGuAYb4luOOEMAqQ2PLAsC2kjSFCENvjfyt47qHw+F40m671sDycy95Wc1eX6fn1eRV4zBRWkIIKi7sqepsPp9hDDHGCC8QWcRxtPqv/D7ntz/vcu33u902zyFuC9SoQ0QtgLkfEepAwpTpTB4pw7G6YF7eAZA6XsCDOIjSO8I4TPfMFAWl8b7f/AG064XRIvMm+edzMS8du8Os9tJuU+uGmnfk/RxmS2Bw8RdvUgVIm/yoxQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 6&apos; title=&apos;&apos; src=&apos;/static/83e2339d21a2af8e357d0f98f0cd3281/a4f00/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_6.png&apos; srcset=&apos;/static/83e2339d21a2af8e357d0f98f0cd3281/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_6.png 190w,
/static/83e2339d21a2af8e357d0f98f0cd3281/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_6.png 380w,
/static/83e2339d21a2af8e357d0f98f0cd3281/a4f00/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_6.png 562w&apos; sizes=&apos;(max-width: 562px) 100vw, 562px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;gpedit.msc 실행&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;여기서 로컬 컴퓨터 정책 =&gt; 컴퓨터 구성 =&gt; 관리 템플릿 =&gt; Windows 구성 요소 =&gt; 앱 패키지 배포 항목으로 이동해보자. 그럼 “Allow all trusted apps to install (모든 신뢰할 수 있는 앱을 설치할 수 있음)” 함목이 있는 것을 볼 수 있을 것이다. 기본적으로 비활성화 돼 있다. 그걸 선택해서 활성화시킨 다음 재부팅을 하면 appx 패키지를 설치할 수 있다. 정책을 바꾼 다음 재부팅을 해보자.&lt;/p&gt;
&lt;p&gt;재부팅을 했으면 앱을 명령 프롬프트에서 설치하기 위해서는 파워쉘의 add-appxpackages를, 제거하기 위해서는 remove-appxpackages를 사용하면 된다. “add-appxpackages appx파일명”을 입력하면 해당 앱이 설치되는 것을 볼 수 있다. 아래는 그렇게 앱을 설치하는 화면을 보여준다. 디버그로 실행해서 이전에 설치된 인스턴스가 있기에 제거후에 다시 설치시키는 장면이다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 597px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_7.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c71ea19757a3531e6f9b8ea1bfd103c6/f523d/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_7.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 87.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADd0lEQVR42i2RWW8aVxTHz8wAA0ZYMBgIYLZhsRlmWMyw743ipDY2TVwCNk5UOzI2BrPOYBjSqi+VqiZfoc+tHPWhD32p1MhuqiRSv1Qv40pHR/97z/Y798Kbn0bt0XggDvrisC8MBUlA/nLUb/f7J53Oq273tNebzARxIV6O++PZRHw9FRaiMJ3/+8cbOL84c2V7TKnDVnr+Unej0PHmL0KVrj9/7i92PLlzf7Zt4I6N3Iu1UEu/2bBHWja24ch03v/5C8y3NxKAJ7UrWY06SJJhkkyr1RmSzKnVqRVNVKN5qCIZnEjjijyOO3TrlJFd03mtrtI/f/0KkzIdBAjiWAggDBAD4AA2ADYBfABRAAaAl/0yjSA3SB2HK7cszN37G+iXaScqw7GonI0yXAARuYVP7rUFEMLwEK4MIMMIP65ArT1m5gMq7pZpO5qDY/cz47L3ACQB2OVkDHlapXtg5OwUY6NYhyFo09G0s/gBYc/K9LI9jqUACgAPAfJyi4Q8lpHJ73Va3stP6n3K1bCF+xsVX5TpJR6Bo4BXteqiOJshuG5g7AbGamCQcBoYC9IUY6SCelMM8zXAd7QS7SwfrFWmzWgrAvMjPAy3EyoboXISKjehcsiGdIBQeQkSUdh0TsxdVdq/0DHNJXatQmsRJ47xMpVVtnUZGK0dkJ8dYbOE2qNz2Vc9JkPArXM7nPkldrXiowAyhKqEKWKYMoEpcpgigiuTmLKAvgRXppAGPKCx6s0p01rcbOIpQ8RMP1kWNw5rmsBzS6RhCjeoUN0cO6S45/pQ3Rpt6oMHRraOLh9Emxb+RBs91fNn+viZnn9lyY8+3t7AlTDyPrqOVMXI3nXiqcQ/lZgvha3aPPhkwu6Im4/H3O4UhbidCbs9DD0e8jWR3xdKRz98un0HwmzC7UqpZ7P0gZSrL0rN72J7YvZria9dR3cFpOP708yBhCxaFeK168rR95XDbysvfvx89w66w6twVUp+JaafzWJVgd+fbu2hGiG+L6JjZGfCbA+c+Qt3sWNOntozbbp86Sqc+x8Jn+9u4KTTNaaGzsKVo9B3l4Z0ZWTP9pyFgS3bs6QurZnueu7KVRw4in1bpmfk21r2VMt+QyUGH29/g5/fvpyOj19Pjxfi/14SWkhIkyNJbM2F1kK8NxRCx8PpqDnp16Xpy0+/z/8DuPPjntNRgqIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 7&apos; title=&apos;&apos; src=&apos;/static/c71ea19757a3531e6f9b8ea1bfd103c6/f523d/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_7.png&apos; srcset=&apos;/static/c71ea19757a3531e6f9b8ea1bfd103c6/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_7.png 190w,
/static/c71ea19757a3531e6f9b8ea1bfd103c6/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_7.png 380w,
/static/c71ea19757a3531e6f9b8ea1bfd103c6/f523d/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_7.png 597w&apos; sizes=&apos;(max-width: 597px) 100vw, 597px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;파워쉘을 통해 앱 설치 및 제거&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;파워쉘을 통해서 시스템에 직접 설치하면 아래 화면에 나오는 것처럼 Program Files 폴더의 WindowsApps 폴더에 빌드한 앱이 설치된 것을 볼 수 있다. WindowsApps 폴더는 기본적으로 관리자 권한을 가져도 들어가 볼 수 없다록 권한 설정이 되어 있다. 내부를 살펴보기 위해서는 해당 폴더의 소유자를 관리자로 변경해 주어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_8.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5600b4e84abef57654eb90be5c72fe9b/8c3ad/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_8.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACB0lEQVR42l2S247TMBCG85I8x24FlGt4DO655QE4bCUkLgoIsUAXBG1zcA62k/gcx3FOTFqQ6I6skeXM7/+bcYK7zdXn18+O755U28f8w5p/XNfbR5DFp/U5F+8f/np1FW5W+zfX0WZ12lwd3l4fb1bB0xcvHzz/fvM1nB2vq6w1TIvSt2roDKyxb0bf9E733vSnk2XvICvvdFCjrW7HYRic66xBWuu8IFVZKW2qmmV5Qcu6aWyeY0JKQkshFSG0wKRmPLDlbTfMnWtBP01D0xiljJDNPM/jOHrvu86P49D3vj8Fl5pWzBg7TWNg6G3OLC6KplkEbdt5VwuGKK0wxoAzXwaUARRka22g8RdSd7bR07R8c673LSb5DqUFtAAVDi7oOtiALRQYrZVSkISUgau+HbM6jmNaEM459OOs5DVO04wxBieUlhBFgc9ocKOUi1gqFfR8l1CRJCgOI1AmcWxgPAU+7g91VQshodn/sReZlH+dQZxSmaA0iWIwQQgZYwqMw2MIK01T33nQTOeuANucsfXi7NmOcHI4/o7CCOaAUgRQWZaFYRhHMcD7S2ezYMuzf+D5D0yj/f6nEAq+wYSBJ89yQMjSTGkFD3aJ/U+sTmLOUBTuGRfABuLGmJLSKAbbtO+He09lLsV3tIKyGAynkzNMFeacwz+FyT1bCGvh8uWdjTF/AJW4z2A9m/CZAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 8&apos; title=&apos;&apos; src=&apos;/static/5600b4e84abef57654eb90be5c72fe9b/8c3ad/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_8.png&apos; srcset=&apos;/static/5600b4e84abef57654eb90be5c72fe9b/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_8.png 190w,
/static/5600b4e84abef57654eb90be5c72fe9b/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_8.png 380w,
/static/5600b4e84abef57654eb90be5c72fe9b/8c3ad/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_8.png 550w&apos; sizes=&apos;(max-width: 550px) 100vw, 550px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;WindowsApps 폴더&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이렇게 개발한 appx 패키지를 친구한테 주고, gpedit 설정을 변경하는 것 까지 알려주어도 친구는 앱이 실행되지 않는다는 문제를 호소할 수 있다. 이벤트 로그를 살펴보면 0x80073CFC 오류가 발생하는 것을 볼 수 있다. 개발자 라이선스 갱신이 되지 않아서 발생하는 문제다. 관리자 권한으로 파워쉘을 실행한 다음 Show-WindowsDeveloperLicenseRegistration 명령어를 입력해서 개발자 라이선스를 갱신해 주면 문제가 해결된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;지금까지 앱 설치 및 배포에 관한 기본적인 방법들을 살펴보았다. 이제 개발적인 측면을 살펴보도록 하자. Windows 8이 출시되면서 아래 그림과 같이 앱을 위한 WinRT API가 추가되었다. 앱 개발은 그 API를 사용해서 쪼물닥 거리는 것이라 생각하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; margin-bottom: 16px;&apos; data-url=&apos;./윈도우_스토어_앱_개발하긔~.md_9.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/083b2571a3bf8c33eb0b10208b585cc7/3e510/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 49.473684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACbUlEQVR42gFiAp39AB9Anh8ycx8eLx4eNB8fNTs7UDo5UDc2TTs8UD4+Ui8vRRscMh4dMhweOCknPUc+R0U/ST44QkdASDEuQQA1T6g2WHs8Y0RAa0NCbkJVe1ZQelFNeUxJcFRLc1dReFJGbkdHcEdEa0keZoUfdZ8kbZcgcpwodJwcaJUATWC0UISCXLBUYrlQaMBQe8ZqbL9YYbxIWq1WWatWccFgdMVgcsVdb7xdE6zTALf/BaTsALX6BKrxBqnwAENYr0p8f2G4RGauXWCvUFGbVVmpTm2zZGO1TVelUWStXHi5b3a4bGCoVhajyQez9Qae4AOv7gel5gui4wBLYLJHdoVbrE1msF1drlBVoFhfrFdytmllsFpTn1Zjrlp2uG9zt2paplQnqs0rwPkOouMRtPAOqOgjq+YAPVSsSniFbb5Ta7pWbLtXbrxYfcJqgMNuf8Nuc75daLlRaLlSabtRZ7NVFqbOALP3CKHjBLHxBqfoCqTmAD1Uq1B9i3nHWofKcYXKbX3HZHHBVYXKbX/HZXfDXHbDXIbKcIfMb3G7WRehywCq8Qmc3wGp6weh5Aec4QA9VKxTgIh8zk19y1R7ylJ9zFSL0WeJ0GWL0GeHz2J5yVF6yVN9zFN4wlcmpckWsfITnt4asOwPouMZouEAR12sR26dVZeJVpWLVpWKVZaLYJuTYp6SYZySX5uRW5qMXJuNXZuMW5eQQJTHO5rZK4zOLZTVLI/RMIzOAEdfqDpdrzlsxDttxDttxDlrw0l3yFmCzVeBzVF8ylF8y1V/zFaAzVR+y1qAwUVwt0Rwt0RvtkZxuEFqs8WmFd1fsUGxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 9&apos; title=&apos;&apos; src=&apos;/static/083b2571a3bf8c33eb0b10208b585cc7/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png&apos; srcset=&apos;/static/083b2571a3bf8c33eb0b10208b585cc7/08678/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png 190w,
/static/083b2571a3bf8c33eb0b10208b585cc7/2edd7/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png 380w,
/static/083b2571a3bf8c33eb0b10208b585cc7/efd7b/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png 760w,
/static/083b2571a3bf8c33eb0b10208b585cc7/dc896/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png 1140w,
/static/083b2571a3bf8c33eb0b10208b585cc7/78873/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png 1520w,
/static/083b2571a3bf8c33eb0b10208b585cc7/3e510/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8A%A4%ED%86%A0%EC%96%B4_%EC%95%B1_%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%94~.md_9.png 1616w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;윈도우 8 개발 아키텍처&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/br211369.aspx&quot;&gt;마이크로소프트 공식 페이지를&lt;/a&gt; 살펴보면 C++ 개발자를 위해서는 두 가지 종류의 API가 제공되고 있는 것을 볼 수 있다. 하나가 그림에 있는 Windows Runtime이고 다른 하나가 Win32 and COM API다. Win32 and COM API가 지원된다늬? 그럼 그냥 다 쓸 수 있는건가? 라고 생각하면 천만의 말씀이다. &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/br205762.aspx&quot;&gt;앱을 위해서 지원되는 API 목록을&lt;/a&gt; 보면 알겠지만 굉장히 제한적으로 지원되는 구조다. GetProcAddress는 있지만, GetModuleHandle은 없고, LoadLibrary는 없지만 LoadPackagedLibrary는 있는 것과 같은 식이다. CreateProcess는 당연히 없을 수도 있겠다고 생각이 들지만 CreateThread 마저도 없다. 결국 스레드를 쓰려면 Windows Runtime에 있는 Windows.System.Threading에서 지원해 주는 것을 사용할 수 밖에 없다. 이말은 기존 코드를 100% 재활용할 수는 없다는 것을 의미한다. 어떠한 형태로든 일정 수준 이상의 포팅 작업이 필요하다는 것을 의미한다. 물론 그렇다고 모두 다 새로 만들 필요는 없다. 이미 우리를 대신해 &lt;a href=&quot;http://blogs.msdn.com/b/shawnhar/archive/2012/03/12/createthread-for-windows-8-metro.aspx&quot;&gt;CraeteThread를 포팅해 주신 감사한 분들이&lt;/a&gt; 있기에 우리는 선검색 후포팅 하면 되겠다.&lt;/p&gt;
&lt;p&gt;오픈 소스를 활용해 개발을 진행하고 있다면 기존의 코드가 문제가 될 수 있다. 대다수 오픈 소스들이 _WIN32 전처리기가 있으면 윈도우 환경으로 인식하고 기존의 윈도우 API를 사용해서 코딩한 부분이 많이 존재하기 때문이다. 이런 경우는 범용적으로 컴파일되게 만들기 위해서는 좀 더 세분화해서 조건을 판단할 필요가 있다. 예를들어 아래와 같은 오픈 소스 코드가 문제가 될 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_WIN32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MyFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; param &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드의 경우 데스크톱 프로그램으로 컴파일 할 때는 VirtualAlloc이 존재하기 때문에 문제가 되지 않지만, 스토어 앱으로 개발할 때에는 VirtualAlloc이 없기에 문제가 된다. 당연히 윈도우 헤더부터 시작해서 MS에서도 이런 문제들을 겪었을 것이다. 그래서 이 상황을 판단할 수 있는 전처리기 매크로가 추가됐다. 아래 전처리기들이 그것이다. 위에서부터 PC앱, 폰앱, PC앱+폰앱, 데스크톱 애플리케이션 개발을 구분할 수 있는 전처리기다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;WINAPI_FAMILY_PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI_PARTITION_PC_APP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;WINAPI_FAMILY_PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI_PARTITION_PHONE_APP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;WINAPI_FAMILY_PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI_PARTITION_APP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;WINAPI_FAMILY_PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI_PARTITION_DESKTOP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;전처리기를 통해서 앞선 코드를 고쳐보면 다음과 같이 고칠 수 있다. 앱 개발 환경이면 malloc을 사용해서 컴파일하도록 만들어주는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_WIN32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MyFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;WINAPI_FAMILY_PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI_PARTITION_APP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; param &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; param &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;당.연.한. 소리겠지만 그 많은 소스 코드에 API 호출을 다 찾아서 이런 쌩쑈를 하고 있을 수는 없다. 좀 더 편리하게 문제를 해결하기 위해서는 API 자체를 포팅하는 것이 좋다. 다음과 같이 헤더를 만들어서 앱 개발 환경일 때에도 그 API가 존재하는 것처럼 만들어 주는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//windows_app.h&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;WINAPI_FAMILY_PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI_PARTITION_APP&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;inline&lt;/span&gt;
LPVOID
WINAPI
&lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와같이 존재하지 않는 API를 포팅한 헤더를 만든 다음에는 그 헤더를 프로젝트에 포함시켜 주면 된다. 전체 참조 되는 헤더에 같이 추가해주면 데스크톱과 앱 개발 환경에서 모두 빌드 문제가 없도록 손쉽게 만들 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[BSOD: 신호와 소음]]></title><description><![CDATA[#0  2008 베이징 올림픽 개막식을 장식한 화려한 블루스크린 드라이버 개발자 10명을 불러다 놓고 어떤 말을 제일 싫어하십니까, 라고 물어보면 10명 모두 BSOD를 제일 싫어한다고 대답할 것이다. 그만큼 BSOD…]]></description><link>https://jiniya.net/wp/archives/14056</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14056</guid><pubDate>Tue, 22 Jul 2014 23:59:48 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;&apos; data-url=&apos;./BSOD_신호와_소음.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5ea1548c2f3c066099b8b79087d39e9f/953fe/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABzmKvYqJJr//EABkQAAIDAQAAAAAAAAAAAAAAAAABAhARIf/aAAgBAQABBQKK0ccpHXX/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAWEQEBAQAAAAAAAAAAAAAAAAAAEiH/2gAIAQIBAT8BxT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAZEAADAAMAAAAAAAAAAAAAAAAAAREQIUH/2gAIAQEAAT8hq0PSscuKVZwZ/9oADAMBAAIAAwAAABCoD//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxDFbL//xAAXEQEAAwAAAAAAAAAAAAAAAAABEBEh/9oACAECAQE/ELBsP//EABkQAQEBAQEBAAAAAAAAAAAAAAERACExYf/aAAgBAQABPxBpwAdV3AE+OlDlyGVD8i90DJv/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;BSOD        md 0&apos; title=&apos;&apos; src=&apos;/static/5ea1548c2f3c066099b8b79087d39e9f/953fe/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_0.jpg&apos; srcset=&apos;/static/5ea1548c2f3c066099b8b79087d39e9f/8ccab/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_0.jpg 190w,
/static/5ea1548c2f3c066099b8b79087d39e9f/ea4c8/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_0.jpg 380w,
/static/5ea1548c2f3c066099b8b79087d39e9f/953fe/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_0.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;2008 베이징 올림픽 개막식을 장식한 화려한 블루스크린&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;드라이버 개발자 10명을 불러다 놓고 어떤 말을 제일 싫어하십니까, 라고 물어보면 10명 모두 BSOD를 제일 싫어한다고 대답할 것이다. 그만큼 BSOD는 드라이버 개발자에게는 제일 듣기 싫은 말이다. 자다가도 경기를 일으키고, 소리만 나와도 소스라치게 놀라며, 화면에 파란 도트만 보여도 커널 개발자를 겁에 질리게 만들어 버리는 녀석이 바로 BSOD다. BSOD는 Blue Screen Of Death의 약자로 우리말로 번역하면 죽음의 블루스크린 정도 되겠다. 2008년 베이징 올림픽 개막식에서 발생한 블루스크린이 전세계 공중파를 타면서 이제는 일반인들도 블루스크린이 뭔지를 알게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 466px; margin-bottom: 16px;&apos; data-url=&apos;./BSOD_신호와_소음.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/04e7de6ff6f0d28717a5691c7738f593/9e695/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 101.57894736842105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUEAgb/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAAB5xU5dxfbkVIklT64Rf8A/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIDBAASMRH/2gAIAQEAAQUCsTM8g2XILG0V8ePigBb/AHBz/8QAFREBAQAAAAAAAAAAAAAAAAAAEAH/2gAIAQMBAT8BKf/EABYRAAMAAAAAAAAAAAAAAAAAAAIQMf/aAAgBAgEBPwEYhi//xAAdEAEAAwABBQAAAAAAAAAAAAABAAIREBIxQXGB/9oACAEBAAY/AmppU8TTSHUO+pV4A7Sn3n//xAAbEAEBAQADAQEAAAAAAAAAAAABABEhMUGhwf/aAAgBAQABPyF0OA8bJNEPRto08KJ2AIxR1tjRAHRfP+LLov/aAAwDAQACAAMAAAAQ5BD8/8QAGBEAAgMAAAAAAAAAAAAAAAAAADEBECH/2gAIAQMBAT8QlmjV/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERMRD/2gAIAQIBAT8QhpBtXDPn/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBkaGxwf/aAAgBAQABPxDFfxlg2p8gnRhAkvAmrlObCBWpwUtJV9xS5V3uA1QAUEMAWXLp9zwCf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;BSOD        md 1&apos; title=&apos;&apos; src=&apos;/static/04e7de6ff6f0d28717a5691c7738f593/9e695/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_1.jpg&apos; srcset=&apos;/static/04e7de6ff6f0d28717a5691c7738f593/8ccab/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_1.jpg 190w,
/static/04e7de6ff6f0d28717a5691c7738f593/ea4c8/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_1.jpg 380w,
/static/04e7de6ff6f0d28717a5691c7738f593/9e695/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_1.jpg 466w&apos; sizes=&apos;(max-width: 466px) 100vw, 466px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;커널 개발자가 극혐하는 블루스크린이 출력된 티&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;BSOD에 대한 두려움을 경계한 개발자들은 BSOD 화면 보호기를 만들어서 담력을 키우기도 하고, 여자친구에게 블루스크린이 출력된 티셔츠를 선물해 보기도 하지만 큰 소용은 없다. 급기야 MS 개발자들은 윈도우 8부터는 블루스크린 이미지를 아주 친근한 형태로 변경했다. 색상을 파스텔톤의 파란색으로 바꾸었고, 화면에는 이모티콘도 넣었다. 블루스크린이 떴지만 쫄지말고 웃으라는 MS 개발자의 패기를 보여준다고 할 수 있겠다. 이런 노력에도 불구하고 커널 개발자들은 여전히 BSOD를 무서워 한다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; margin-bottom: 16px;&apos; data-url=&apos;./BSOD_신호와_소음.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/221e58d5c4724a75e2147dbd3ab473a7/e7448/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAsklEQVR42p2S6wrCMAyFWxWcInibuuk/X0DwLV27i25rwV/iix6bUXVgKVj4CGnhJCdNGZMIx3GVhYoHOVINHiYe5Tg/MbuCiW8JLm3O/eJhjtMDUQF2Ib0l6xDv6BYLTCsc74gbbFuK6warGommWUyyaa0pt3hS4aCxU8ReI+5KJAqponxc0lw+26b5B3PksmdYeGYWVNvYW9RYdsxv1DAqXa/l3rP44Y9P0lsPl76dvwA6eFfI3gf2DQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;BSOD        md 2&apos; title=&apos;&apos; src=&apos;/static/221e58d5c4724a75e2147dbd3ab473a7/efd7b/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_2.png&apos; srcset=&apos;/static/221e58d5c4724a75e2147dbd3ab473a7/08678/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_2.png 190w,
/static/221e58d5c4724a75e2147dbd3ab473a7/2edd7/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_2.png 380w,
/static/221e58d5c4724a75e2147dbd3ab473a7/efd7b/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_2.png 760w,
/static/221e58d5c4724a75e2147dbd3ab473a7/e7448/BSOD_%EC%8B%A0%ED%98%B8%EC%99%80_%EC%86%8C%EC%9D%8C.md_2.png 900w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;윈도우 8은 블루스크린 이미지를 친근하게 개선했다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이렇게 설명하니 블루스크린이 뭔가 대단한 것처럼 보이는데 사실은 그냥 커널 영역에서 발생하는 프로그램 오류에 불과하다. 일반 응용 프로그램이 오류를 발생시키면 “잘못된 연산을 수행하였습니다”같은 아주 친절한 메시지를 뿜꼬는 프로그램이 종료되는 정도로 끝이 난다. 그런 똑같은 일이 커널 영역에서 발생하면 드라이버 하나가 죽고 끝나는 것이 아니라 블루스크린이 발생하고 시스템은 정지된다. 동일한 오류지만 파급 효과가 다른 것이다. 하나는 프로그램만 죽고 끝나고, 다른 하나는 시스템 전체가 죽는…&lt;/p&gt;
&lt;p&gt;윈도우 9x 시절에는 블루스크린이 너무나 자주 발생해서 사람들은 블루스크린이 발생하는 줄도 몰랐다. 그저 또 껐다 켜야 하는구나라고 생각했다. 하지만 윈도우 2000이상부터 NT 커널이 도입되면서 블루스크린은 생각보다 보기 힘든 일이 되었다. 이후에도 다양한 보안 프로그램에서 많은 블루스크린을 발생시키곤 했지만 이 또한 MS의 꾸준한 노력으로 요즘은 정말 블루스크린 보기가 쉽지 않아졌다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;거창하게 썰을 풀었는데, 요는 이렇게 마주하기 싫은 블루스크린을 최근 다시 마주하게 되었다는 이야기를 하고 싶었던 것이었다. 따끈따끈한 신작 게임에 적용을 진행하면서 발생한 문제인데 당.연.히. 원인은 나의 어처구니 없는 멍청함에 있었다. 나의 멍청함을 인식하는데 다소 시간이 걸렸는데, 그 과정에 문제 해결을 방해하는 소음이 한 몫 했다.&lt;/p&gt;
&lt;p&gt;첫번째는 어째서 그 게임에서만 밥 먹듯이 블루스크린이 발생하냐는 점이었다. 그런 문제라면 적어도 이전에 수도 없이 적용된 게임에서 응당 발견되었어야 하지 않았을까라는 생각이었다. 결과론적으로 그 게임에서만 발생하는 이유가 있었고, 그 문제가 그 전에는 전혀 발견될 수 없는 종류의 문제였다. 둘째는 블루스크린에 출력된 함수 파라미터와 관련한 데이터들이 우리의 생각을 오염시켰다. 실제로 우리가 참고한 글에 나온대로 파라미터를 수정하면 블루스크린이 발생하지 않았기 때문이었다. 하지만 이는 최종적으로 함정같은 존재였다.&lt;/p&gt;
&lt;p&gt;이런 이유로 크래시 덤프 문제를 해결하는 과정이 생각보다 복잡 다단했다. 최종적으로는 정말 아주 사소한 문제에서 이 모든 것이 비롯됐다는 것을 알게 되었고, 그 도화선이 된 부분은 정말 실소를 금할 수 없을 정도로 어처구니 없는 내용이었다. 그래서 여기에 그 내용을 소개하면 다소 도움이 되지 않을까라는 생각에 글을 써본다.&lt;/p&gt;
&lt;p&gt;덤프의 내용은 다음과 같다. 논페이지드 영역에서 페이지 폴트가 발생해서 블루스크린이 발생한 것이다. 콜스택을 살펴보면 MmProbeAndLockPages라는 함수에서 참조하려고 한 논페이지드 영역이 존재하지 않는 영역이라 발생했다는 것을 알 수 있다. 이 문제와 관련된 내용을 다음 몇 차례의 글을 통해서 살펴볼 생각이다. 혹시 관심있는 독자 분들이 있다면 &lt;a href=&quot;/codewiz/assets/files/2015/conan.7z&quot;&gt;여기에서&lt;/a&gt; 관련 파일을 받을 수 있다. 64비트 시스템에서 conan_ldr을 관리자 권한으로 실행하면 블루스크린이 발생하는 것을 재현할 수 있다. conan.dmp는 그렇게 생성한 미니덤프 파일이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;kd&gt; !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except,
it must be protected by a Probe.  Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: ffffffff825f0000, memory referenced.
Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.
Arg3: fffff80002af3798, If non-zero, the instruction address which referenced the bad memory
	address.
Arg4: 0000000000000005, (reserved)

Debugging Details:
------------------


Could not read faulting driver name

READ_ADDRESS: GetPointerFromAddress: unable to read from fffff80002d0f100
 ffffffff825f0000 

FAULTING_IP: 
nt!MmProbeAndLockPages+118
fffff800`02af3798 410fb601        movzx   eax,byte ptr [r9]

MM_INTERNAL_CODE:  5

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x50

PROCESS_NAME:  conan_ldr.exe

CURRENT_IRQL:  0

TRAP_FRAME:  fffff8800454f6d0 -- (.trap 0xfffff8800454f6d0)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000
rip=fffff80002af3798 rsp=fffff8800454f860 rbp=fffff8800454fca0
 r8=fffffa8001cd5cf0  r9=ffffffff825f0000 r10=0000000000000001
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei ng nz ac pe nc
nt!MmProbeAndLockPages+0x118:
fffff800`02af3798 410fb601        movzx   eax,byte ptr [r9] ds:5480:ffffffff`825f0000=??
Resetting default scope

LAST_CONTROL_TRANSFER:  from fffff80002b545b3 to fffff80002ad7bc0

STACK_TEXT:  
fffff880`0454f568 fffff800`02b545b3 : 00000000`... : nt!KeBugCheckEx
fffff880`0454f570 fffff800`02ad5cee : 00000000`... : nt! ?? ::FNODOBFM::`string&apos;+0x43801
fffff880`0454f6d0 fffff800`02af3798 : fffffa80`... : nt!KiPageFault+0x16e
fffff880`0454f860 fffff880`04baf04f : fffffa80`... : nt!MmProbeAndLockPages+0x118
fffff880`0454f970 fffffa80`01cd5cc0 : 00000000`... : conan+0x104f
fffff880`0454f978 00000000`00000000 : 00000000`... : 0xfffffa80`01cd5cc0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;덤프를 살펴보면 알겠지만 크래시 시점에 주요하게 관여된 함수로 MmProbeAndLockPages, MmMapLockedPages가 있다. 덤프를 제일 먼저 분석한 엔지니어는 아래 내용을 토대로 드라이버의 코드의 함수 파라미터를 고쳐야 한다는 이야기를 했었다. 덤프 분석에 떡밥 내지는 힌트 정도로 살펴보면 좋을 것 같다. 앞으로 차차 살펴보겠지만 여러분이 MmProbeAndLockPages와 MmMapLockedPages 함수에 사용되는 AccessMode의 용도에 관한 아래 글들의 내용에 대해서 충분히 상세히 알고 있다면 그것만으로도 자부심을 가져도 될 것 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The better idea would be to pass Irp-&gt;RequestorMode as the second parameter to MmProbeAndLockPages. In this case, if the requestor is UserMode and the buffer is a kernel address the API will immediately raise an exception instead of potentially crashing. Calling ProbeForWrite yourself would basically give you the same effect (it also checks to make sure the buffer supplied is a user address), which is why I asked if you were making this call earlier as it would point to this being a different type of bug.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://osronline.com/ShowThread.cfm?link=236232&quot;&gt;http://osronline.com/ShowThread.cfm?link=236232&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;If AccessMode is KernelMode and MmMapLockedPages cannot map the specified pages, the system issues a bug check. (For this reason, drivers should use MmMapLockedPagesSpecifyCache when available; that routine returns NULL on failure, rather than causing a bug check.) If AccessMode is UserMode and the specified pages cannot be mapped, the routine raises an exception. Callers that specify UserMode must wrap the call to MmMapLockedPages in a try/except block. For more information, see Handling Exceptions.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/ff554622(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/windows/hardware/ff554622(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;앞으로 추가적인 몇 개의 글을 통해서 이 덤프의 정확한 원인을 추적하는 작업을 해 볼 생각입니다. 그전에 덤프에 대한 나름의 의미 있는 해석을 내렸다고 생각하는 분들은 codewiz at gmail.com으로 메일 주세요. &lt;a href=&quot;http://www.jiniya.net/wp/archives/12367&quot;&gt;함께 할만한 일들이 있을지도 모르잖아요&lt;/a&gt; ㅎㅎ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[드라이버 개발 환경 설정]]></title><description><![CDATA[시스템 설치할 때마다 여기 저기 검색해서 찾기 귀찮아서 정리한 페이지!!! NTSTATUS 코드표 https://msdn.microsoft.com/en-us/library/cc704588.aspx windbg 심벌 경로 srv*C:\WebSymbols…]]></description><link>https://jiniya.net/wp/archives/14027</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14027</guid><pubDate>Wed, 16 Jul 2014 23:59:47 GMT</pubDate><content:encoded>&lt;p&gt;시스템 설치할 때마다 여기 저기 검색해서 찾기 귀찮아서 정리한 페이지!!!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NTSTATUS 코드표&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/cc704588.aspx&quot;&gt;https://msdn.microsoft.com/en-us/library/cc704588.aspx&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;windbg 심벌 경로&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;srv*C:\WebSymbols*&lt;a href=&quot;http://msdl.microsoft.com/download/symbols&quot;&gt;http://msdl.microsoft.com/download/symbols&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;윈도 XP 커널 디버그 설정&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;boot.ini 편집&lt;/p&gt;
&lt;p&gt;multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”Debugging with Cable” /fastdetect /debug /debugport=COM1 /baudrate=115200&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;윈도 Vista+ 커널 디버그 설정&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;msconfig 들어가서 Advanced에서 디버그 옵션을 켜면됨&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;virtualbox 이미지&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;미리 구워논 이미지가 없으면 아래 사이트에서 다운로드 받아서 사용하면 편리함&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.modern.ie/en-us/virtualization-tools&quot;&gt;https://www.modern.ie/en-us/virtualization-tools&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WDk 7.1.0&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=11800&quot;&gt;http://www.microsoft.com/en-us/download/details.aspx?id=11800&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Windows Vista+ Debug Filter 설정&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;설정 안 하면 DbgPrint 출력안뎀. &lt;a href=&quot;/files/debug_filter.reg&quot;&gt;귀찮으면 레지 파일 다운받기&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter]&lt;/p&gt;
&lt;p&gt;“DEFAULT”=dword:0000000f&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;virtualbox 커널 디버깅용 파이프 설정&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;직렬포트, 호스트 파이프, 생성, \.\pipe&amp;#x3C;name&gt;&lt;/p&gt;
&lt;p&gt;windbg pipe 체크, 포트에 \.\pipe&amp;#x3C;name&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[우분투에서 네트워킹 안될때]]></title><description><![CDATA[VM 같은 거 복사했을 때 우분투에서 네트워킹 안되면 아래 파일을 지우고 재부팅해 봅시다. rm -rf /etc/udev/rules.d/70-persistent-net.rules shutdown -r now…]]></description><link>https://jiniya.net/wp/archives/14020</link><guid isPermaLink="false">https://jiniya.net/wp/archives/14020</guid><pubDate>Thu, 10 Jul 2014 23:59:46 GMT</pubDate><content:encoded>&lt;p&gt;VM 같은 거 복사했을 때 우분투에서 네트워킹 안되면 아래 파일을 지우고 재부팅해 봅시다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1&gt;rm -rf /etc/udev/rules.d/70-persistent-net.rules&lt;/h1&gt;
&lt;h1&gt;shutdown -r now&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;랜카드 맥어드레스가 변경되서 그런걸로 추정되는데…&lt;/p&gt;
&lt;p&gt;어쨌든 파일 지우고 나면 인터페이스가 정상적으로 인식됩니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[by accident]]></title><description><![CDATA[#0 점심 먹고 커피를 마시고 있었다. 이런 저런 이야기를 하다가 어쩌다가 나왔는지 by accident…]]></description><link>https://jiniya.net/wp/archives/13961</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13961</guid><pubDate>Fri, 04 Jul 2014 23:59:45 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;점심 먹고 커피를 마시고 있었다. 이런 저런 이야기를 하다가 어쩌다가 나왔는지 by accident에 관한 이야기가 나왔다. 별 일 아닌 일이었지만 뭔가 재미있는 구석도 있는 것 같아서 여기다 옮겨 적어 본다. 사건의 전말은 이렇다. 한 독일 업체에서 우리쪽으로 아래와 같은 내용의 문장이 포함된 메일을 한 통 보냈다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;we found out by accident that Xigncode is writing logs on the Live Server.&lt;br&gt;
&lt;br&gt;
우리는 XIGNCODE가 라이브 서버에서 로그를 기록하는 것을 우연히 발견했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그걸 본 우리쪽 커뮤니케이션 담당자가 accident 부터 끊어서는 아래와 같은 질문을 보냈다. 이게 사고/사건이라니 무슨 의미냐고 재차 질문을 한 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;accident that Xigncode is writing logs on the Live Server.&lt;br&gt;
&lt;br&gt;
XIGNCODE가 라이브 서버에서 로그를 기록하는 사건(?!)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그랬더니 업체쪽에서는 사고가 있었다는 말이 아니라 by accident를 구글 번역기를 돌려서는 이게 우연히라는 영어 표현이라는 답장을 아래와 같이 보내왔다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“By accident” is an expression in English language. Google translation says it means임의in Korean language.&lt;br&gt;
&lt;br&gt;
“by accident” 영어에 있는 표현(숙어)이다. 구글 번역기는 그것의 의미가 한국말로 임의라고 나에게 말해주었지.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;커피를 마시다 이 이야기를 전해 들은 나는 핸펀으로 그 메일을 검색해서 살펴보고는 이걸 어떻게 이렇게 해석해서 재차 질문할 수 있지라는 생각을 했다. 그리곤 이 이야기를 전해준 직원에게 네이버 영어 사전에서 by accident를 찾아서 보여주며 이거 아니냐는 말을 건냈다. 그걸 들은 친구는 동료를 보호하기 위해서 accidently라고 썼어야 명확했을 거라는 힘겨운 실드를 쳤다. 한참을 듣고 계시던 사장님께서 한 말씀 덧붙인다. 야, 그게 표현이 뭐가 그리 중요하니 적당히 알아듣고 해달라는대로 처리해주면 되는 거잖아. 신택스가 아니라 시맨틱에 집중하라는 말씀.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;커피 마시고 올라와서는 친구 녀석이랑 톡질을 하다가 이 이야기가 다시 올라왔다. 영어 선생님을 하는 그 친구한테 우리 회사에서 이런 일이 있었다는 이야기를 하는데 그 친구는 내가 하는 말을 잘못 알아들어서는 내가 “we found out by accident that Xigncode is writing logs on the Live Server.”라는 문장을 썼다고 이해를 했다. 친구왈 “맹구야, 동사하고 목적어 사이에 부사가 있잖아”라는 이야기를 한다. “we found out that Xigncode is writing logs on the Live Server by accident.”라고 써야 한다는 말이다. 그래서 다시 네 말이 무슨 말인지 알겠는데 블라블라블라 긴 이야기를 돌고 돌아 사건의 전말을 전달했다. 친구왈 독일애들 그렇게 안 봤는데, 똑똑하지 않은 것 같다는 이야기를 한다. 난 걔들 입장에서도 외국어라는 말을 덧붙였다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; margin-bottom: 16px;&apos; data-url=&apos;./by_accident.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fe0eacd9822135db9bfc4e271171bac1/abf7b/by_accident.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 82.10526315789475%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACF0lEQVR42n1Ty3LiMBDk/z9qUyk4ANkkJFBJsC2MJVsPW/LbZI0Ab8thq3II2we5a6TRdM/Ik/V6/fL6slws5vMF1tXz86+7u+VyOZ1OH5+ettsP8Pl8vlqtZrPZb4dHa0/DiMnDwxKB1/Vms1nf398vFosgIG7nMly+wQXceuXX5K7rjNY8SbIsY5TFjKVp1tRNXdVYmqZp27Zru7IsHW/a2sWA+ny5THBBWeSe5+92OxrRfbgnhGw/tu9v7yC+5wPEJyEJ9zuHwA8CRAiRSrnkrms5FzwRSikQFPrzecXhcBgrtxAxflsorcfq2J0M1lZS6jzXWaZSJaGf0lypqqpw9JvBHzBBC5qiSGE0TU2eKylFuOeUCiHAjTG4BYarsiqKAuRryU0+Vh4GyGGMCi5wNEkSmEnRvTTVmeZCaK1hJ0k4wgDnIBJ+TqfT2LCqcCGJokpy5Crkdn332R/6vj9aex7hpnS+fJGr7P7c79N9kZfa6DhLIkkFLpHc534Q+xCC7tz0fDr2Mg7TTDMSeP7aZwFjDIZ5wquqRs+stTeTre0ZI9BLSUADIkfEIvZiT+caIznf7vjkeLZhutsJIlIJq9DszCsZ8QizR2//O6phwKuLeYw5ORSFMbnRxmRmRI53cjP5Ym3JXYWyqgwm4XkqijBWYzTeFE6gvbc9n44sCTFkJ5eLJAyTiDJJ3+mbzNW/n+nn5L+cA4AIWwYEygAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;by accident md 0&apos; title=&apos;&apos; src=&apos;/static/fe0eacd9822135db9bfc4e271171bac1/abf7b/by_accident.md_0.png&apos; srcset=&apos;/static/fe0eacd9822135db9bfc4e271171bac1/08678/by_accident.md_0.png 190w,
/static/fe0eacd9822135db9bfc4e271171bac1/2edd7/by_accident.md_0.png 380w,
/static/fe0eacd9822135db9bfc4e271171bac1/abf7b/by_accident.md_0.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.grammarly.com/handbook/grammar/adjectives-and-adverbs/28/an-adverb-between-a-verb-and-its-direct-object/&quot;&gt;부사의 위치. 어렵지? 아마 어려울거야?&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;&lt;br&gt;  
&lt;p&gt;심심해서 부사의 위치를 찾아봤다. 머 당연한 이야기겠지만 영어 선생님인 놈이 틀릴 일은 없다. 부사는 동사와 그 동사의 목적어 사이에는 쓰지 않는 거란다라고 친절히 알려준다. 돌고 돌고 돌아서 다시 실드를 쳤던 직원 말을 재차 실드를 쳐보자면 “we accidently found out that Xigncode is writing logs on the Live Server.”라고 썼어야 한다는 말이었을 것이다.&lt;/p&gt;
&lt;p&gt;명확해야 한다는 관점만 놓고 본다면 업체간 공식적인 커뮤니케이션에서는 그냥 부사 형용사 따위는 없는게 더 좋지 않을까라는 생각이 든다. 우연히 발견했든, 면밀히 뒤지다 발견했든, 발견한 사실이 중요하지 그걸 한정짓는 한정 문구는 그닥 중요한 내용은 아니니 말이다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;별 일 아닌 이 사건이 재미있게 느껴졌던 이유는 동일한 사건을 바라보는 관점이 사람마다 너무나 극명하게 차이가 나타났기 때문이었다. 나는 어떻게 by accident를 모르고 accident that이라고 끊어서 해석할 수 있냐는 관점을, 담당자를 실드 치던 직원은 by accident가 아니라 accidently를 썼으면 명확했을 거라는 입장을, 사장님은 by accident든 accidently든 알아들었으면 적당하게 조치를 취해주면 되지 문법 그거 따져서 무엇하겠느냐는 말씀을, 영어 선생님인 친구는 미개인도 아닌 우리가 21세기에 어떻게 동사와 목적어 사이에 부사 따위를 쓸 수 있지라는 반응을 보였다. 하나 같이 다 틀린 말도 아니고, 딱 하나를 집어서 이게 정답이라는 입장도 없다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;임백준씨는 &lt;a href=&quot;http://www.zdnet.co.kr/column/column_view.asp?artice_id=20131118093913&amp;#x26;type=det&quot;&gt;한 칼럼에서&lt;/a&gt; “버그는 프로그래머의 숙명이다. 김밥을 마는 손에 밥풀이 묻는 것처럼, 비트와 바이트를 만지는 손에는 버그가 달라붙는다.”라는 이야기를 했었다. 퍽이나 멋진 표현이라는 생각을 했었는데 이 말이 비단 프로그래머에게만 적용되는 이야기는 아닌 것 같다. 영어로 커뮤니케이션을 하는 직원들도 소통을 하다보면 실수를 할 수 있는 것이다. 하루에도 몇 통씩 영어로 메일을 읽고, 쓰고, 영어로 메신저질을 하다 보면 자연스레 실수할 때도 있는 법이다. 그걸 두고 by accident를 모르고 accident that으로 끊어서 해석을 하냐고 뭐라고 한 건 아닌지라는 생각에 괜스레 미안해졌다.&lt;/p&gt;
&lt;p&gt;언어는 불완전하고 커뮤니케이션은 어렵다. 상황은 복잡하고 입장은 다양하다. 이런 생각들이 머리속을 파고드니 그냥 우리가 죽자살자 집착하는 모든 일이 위에서 쳐다보면 죄다 우스워 보일수도 있겠다는 생각이 들었다. 그러다 떠오른 법정 스님의 시 한 수.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;오해 – 법정&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;‘나는 당신을 죽도록 사랑합니다’라는 말의 정체는&lt;br&gt;
&lt;br&gt;
‘나는 당신을 죽도록 오해합니다’일지도 모른다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;누가 나를 추켜세운다고 해서&lt;br&gt;
&lt;br&gt;
우쭐댈 것도 없고,&lt;br&gt;
&lt;br&gt;
헐뜯는다고 해서 화를 낼 일도 못 된다.&lt;br&gt;
&lt;br&gt;
그건 모두가 한쪽만을 보고 성급하게 판단한&lt;br&gt;
&lt;br&gt;
오해이기 때문이다.&lt;br&gt;
&lt;br&gt;
오해란 이해 이전의 상태가 아닌가.&lt;br&gt;
&lt;br&gt;
문제는 내가 지금 어떻게 살고 있는가에 달린 것이다.&lt;br&gt;
&lt;br&gt;
실상은 말 밖에 있는 것이고&lt;br&gt;
&lt;br&gt;
진리는 누가 뭐라 하든 흔들리지 않는다.&lt;br&gt;
&lt;br&gt;
온전한 이해는 그 어떤 관념에서가 아니라&lt;br&gt;
&lt;br&gt;
지혜의 눈을 통해서만 가능하다.&lt;br&gt;
&lt;br&gt;
그 이전에는 모두가 오해일 뿐이다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[비행운]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12776</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12776</guid><pubDate>Thu, 03 Jul 2014 23:59:44 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;─ 신기해요. 어떤 음악을 들으면, 그 곡을 제게 처음 알려준 사람이 생각나요. 그것도 번번이요. 처음 가본 길, 처음 읽은 책도 마찬가지고요. 세상에 그런 게 있다는 걸 알려준 사람이 떠올라요. ‘이름을 알려준 사람의 이름’이라고 해야 하나? 그런 건 사물에 영원히 달라붙어버리는 것 같아요.&lt;/p&gt;
&lt;p&gt;나는 ‘아니, 내가 이렇게 멋있는 말을 하다니!’ 하고 혼자 감탄했다. 하지만 ‘선배의 쪽지’는 더 근사했다.&lt;/p&gt;
&lt;p&gt;─ 우리가 신을 잊을 수 없는 이유도 아마 그 때문일 거야.&lt;/p&gt;
&lt;p&gt;– 비행운, 김애란&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;김애란의 소설을 좋아한다. 달작지근한 문장으로 글을 읽는 재미를 흠뻑 느끼게 해주기 때문이다. 평범한 문장도 그녀의 글 속에서는 힘을 발한다. “우리가 신을 잊을 수 없는 이유도 아마 그 때문일 거야”라는 이 평범한 문장도 김애란이 만들어 낸 장면 속에서는 기가 막힌다. 아마 그 누구라도 소설 속에서 그 문장을 만난다면 해머로 머리를 한 대 맞는 느낌일거라는데 500원은 걸 수 있다. 그렇다고 그녀가 단지 언어의 연금술사이기 때문에 팬을 자처하는 것은 아니다. 소설 속 이야기들이 묘하게 소설이 아니라 진짜 우리 이야기 같다는 생각이 들기에 그녀의 소설을 더 좋아하는 것 같다. 주인공의 현실에 격하게 공감하면서도 이상하게 마음이 조금은 편해진다. 그래서 책을 덮을 즈음엔 신묘하게도 힐샤워를 받은 느낌이 드는 오묘한 마력이 있다.&lt;/p&gt;
&lt;p&gt;비행운도 그런 소설 중에 하나다. 이야기 하나하나가 모두 남의 일 같지 않은 그런 소설이다. 바로 옆에 있는 친구나 가족, 학교 선배나 후배, 또는 직장 상사나 동료들의 이야기라는 생각이 절로 든다. 달달한 문장에 취했다가도 주인공의 씁쓸한 현실을 보면 마음이 그리 편하진 않다. 우리 모두에게 이제는 행운이 함께 했으면 좋겠다는 생각이 드는 소설. 소설 속 주인공 모두에게, 그리고 또 지구에서 2014년을 보내고 있는 사람들 모두에게, May the Force be with you.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[시스템] 저수준 API 후킹 시에 유의할 점]]></title><description><![CDATA[저수준 API…]]></description><link>https://jiniya.net/wp/archives/4601</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4601</guid><pubDate>Tue, 01 Jul 2014 23:59:43 GMT</pubDate><content:encoded>&lt;p&gt;저수준 API를 후킹할 때에는 해당 훅 대상이 되는 함수에 대해서 면밀하게 살펴야합니다. 그렇지 않을 경우에는 엉뚱한 부분 때문에 디버깅에 상당히 많은 시간을 잡아먹을 수 있습니다.&lt;/p&gt;
&lt;p&gt;흔히 저지르는 실수는 훅 함수 내에서 후킹 대상 함수보다 높은 수준의 API를 호출하는 것입니다. 뭔소린가 싶은데 그냥 쉽게 설명하면 RtlAllocateHeap 따위의 함수를 후킹해놓고 해당 후킹 함수 내에서 동작을 살피기 위해서 OutputDebugStringW 따위를 호출하는 행위를 조심해야 한다는 것을 의미합니다. OutputDebugStringW 함수는 내부적으로 유니코드 문자열을 멀티바이트 문자열로 변경하기 위해서 힙을 할당하는 함수를 사용하는데 그러면 다시 후킹 함수가 호출되고, 그러면 다시 OutputDebugStringW가 호출되고, 다시 후킹 함수가 호출되고, 다시 OutputDebugStringW가 호출되고 하는 무한 재귀 루프에 빠져버립니다. 결국 스택을 다 소진할 때까지 반복하다 크래시가 발생하는 것이죠.&lt;/p&gt;
&lt;p&gt;위와 같은 단순한 경우 외에도 좀 복잡한 경우도 있습니다. 후킹을 하는 대상 함수가 특정한 시스템 락을 획득한 상태에서 호출되는 함수이고, 후킹 함수 내에서 호출하는 API가 그 락을 다시 요청하는 경우에 문제가 발생할 수 있습니다. 락이 재귀적으로 획득할 수 있도록 구성된 경우에는 문제가 없지만 재귀적으로 획득할 수 없도록 구성된 경우에는 문제가 발생할 수 있습니다.&lt;/p&gt;
&lt;p&gt;그래서 저수준 API를 후킹하는 함수를 작성할 때에는 해당 후킹 함수 내부에서 호출하는 함수 중에 혹시나 다시 후킹 함수를 호출하게 될 가능성이 있는건 없는지를 꼼꼼히 살펴야 합니다. 물론 함수를 본다고 해당 함수가 어떤 내부 함수를 호출하는지를 다 알수는 없는 법이죠. 결론은 그냥 후킹 함수는 최대한 간단하게 작성하는 것이 좋습니다. 없는듯이 작성하고, 복잡한 연산은 훅 함수가 아닌 다른 곳에서 처리하도록 보류 시키는 것이 좋은 전략입니다. 당연한 소리지만 그것보다 더 좋은 전략은 후킹을 사용하지 않는 겁니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 메일 메트릭]]></title><description><![CDATA[#0 난 엄마 뱃속부터 테일러리즘을 싫어했다고 느낀다. 200…]]></description><link>https://jiniya.net/wp/archives/13762</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13762</guid><pubDate>Thu, 19 Jun 2014 23:59:42 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;난 엄마 뱃속부터 테일러리즘을 싫어했다고 느낀다. 2008년 여름 처음 팀장이 되면서 약간의 관리 업무를 맡게 될 당시에도 그런 생각은 확고했다. 자유와 여유, 그 모든 것이 주어진다면 인간은 무한대의 창조성을 발휘할 것이라 믿었다. 동일한 환경이 주어진다면 모두 공평하게 노력할 것이라 생각했다. 그렇게 몇년이 흘렀다. 안타깝게도 나의 가설은 틀린 것처럼 보였다. 2011년 10월에 작성한 아래 노트는 그런 생각 변화를 보여준다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 370px; margin-bottom: 16px;&apos; data-url=&apos;./메일_메트릭.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dfd298c01b04ce5e4dd12b99229b3e2c/3ac6e/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 24.736842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAArklEQVR42o2P3Q7CIAyF9/4P6eYPUGjHGAPMHJseool3xpPetOk5X9ut6xrjrLQSdkTWsRv6PpXy/EPdvu/b9liWJYTJGKP17dT3I+RHYcEQBY0i3iNfSi4555RTM78zjuPIKRER7FhldiyMxjm+nAfMlVKGWktaS4tlUD/mWuu9FA3u9TqHQJawhwiDTyyllGOMuG6JkZ0dfTtnq/VLTo3swuSBtxDYItroH/+/ADW/HBQictSJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 0&apos; title=&apos;&apos; src=&apos;/static/dfd298c01b04ce5e4dd12b99229b3e2c/3ac6e/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_0.png&apos; srcset=&apos;/static/dfd298c01b04ce5e4dd12b99229b3e2c/08678/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_0.png 190w,
/static/dfd298c01b04ce5e4dd12b99229b3e2c/3ac6e/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_0.png 370w&apos; sizes=&apos;(max-width: 370px) 100vw, 370px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;2011년 10월에 작성한 노트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;물론 난 지금도 테일러리즘을 싫어한다. 그리고 인간이 인간을 관리한다는 생각 자체도 너무 우습다고 생각한다. 똑같은 인간끼리 뭘 관리한다는 말인가? 하지만 기존의 생각과는 다른 몇 가지 생각은 확실하게 변했는데, 그 중 하나가 일등은 일등대로의 방식이 있고, 꼴찌는 꼴찌의 방식이 있다는 생각이다. 많은 교과서에서 말하는 좋은 기업의 조건이나 관리 방식은 사실상 내가 생각했을 때에는 일등의 방식이다. 최고의 인재를 모아서 물쓰듯 자본을 쓸 수 있는 환경에서나 가능한 일들이란 이야기다. 동일한 사항을 그렇지 않은 환경에 적용한다면 당연히 여러가지 문제점이 발생할 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;어쨌든 그맘때부터 난 한 가지 생각은 뚜렸했다. 1) 사람은 관리할 수 없지만 업무는 관리할 수 있다. 2) 측정 불가능한 업무는 관리 불가능하다. 3) 자동화된 측정이 아닌 사람을 통한 측정은 효과가 불투명하다. 이런 전제 아래에서 나는 업무와 관련된 상당히 많은 데이터를 수집하고 분석하기 시작했다. 일부는 직원들에게 공유하기도 했고, 일부는 그냥 혼자 데이터를 보고 넘기기도 하는 형태다. 이런 내용을 토대로 한 가지 발견한 사실은 직원들의 업무에는 종류를 불문하고 엄청난 양의 불균형이 존재하고, 그것에 대해서 대부분의 직원들은 자각하지 못한다는 사실이다. 그런 데이터 중에 하나가 메일 메트릭이다. 우리 회사 지원 업무의 상당수는 메일을 통해서 이루어지는데 그 업무 회수를 측정한 자료다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 612px; margin-bottom: 16px;&apos; data-url=&apos;./메일_메트릭.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/19469b2454ca7dad15283442daf365d6/dbf98/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 58.42105263157894%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACWklEQVR42iWSS2/TQBDH8zkQx0pW3nESP+LYjlPb8bt24l07dpwEJyhNK0WKSgqi4l0FUKlUDkgg9QAcUHvgChzgAN+MSbLSrkaz/5/+s7OTyeVyxWKxWq3SNN1sNlutlqqqURSl6SRJktF4PBgMFEWBPNyChiRJ0ANFEESmWCqVKxWaouBOkiQgTdMaJMkkTUfDYTqZwGmaJuTb7TZoKIqqVCqFQiGbzWbq9TrLMBzHAdnpdEB3sFuu63me60LkwN7xoAElIKVSCcwzguqg5SXf5PZlWdd10PV6PYxxEARhCEeAMYKM4ziGYciyzPM8FA/m+Xw+I5pB/9V3qS1rHcWxbfDzfX9Lhv3tghgyruvuzAVBYBhmV3mmoeP769vradufnvTnjzzbwFsSehbHMZwQQyHdbte2bXgXdI5lWWjwBqY1fLi++Tcv45Mr/+FHy+hgv9cPcNTvR1tngBHC8H7LssBZFEWAoecbmNJw+uLL73RPO3p7+vz9WbQfzlZ4OA2jeDQ9RAHUjQPUg9aZlq2qCsAMOO/gqoJGzz7/Hd3hZu8+vTm/HRLa+s/12dHxZBxf/JonKD5+HC5emoZuaJqsqrwgUPVauVzewKTk4OXlDb7LjZ6er5Yf/D1u9e3nA2MxROjJ1x/zurd4HZ9eJVZLDWcX9zpIbtCSUa/VNl8FQ0IzrMgxvChpmmbpqum4UGXX83wchL7ruF7XdQ50ta1ZpiI1WYZq8OC8GRLYxUKhTJI0TcEAiC1J3pcU3ez5KPCsro8MQ4fZgnyTY2sU/DBZLOSzuSxBEP8B44LUzV4F9PoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 1&apos; title=&apos;&apos; src=&apos;/static/19469b2454ca7dad15283442daf365d6/dbf98/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_1.png&apos; srcset=&apos;/static/19469b2454ca7dad15283442daf365d6/08678/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_1.png 190w,
/static/19469b2454ca7dad15283442daf365d6/2edd7/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_1.png 380w,
/static/19469b2454ca7dad15283442daf365d6/dbf98/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_1.png 612w&apos; sizes=&apos;(max-width: 612px) 100vw, 612px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
7명의 직원이 근 한달간 메일 업무를 한 내용을 정리한 그래프다. 일반이라고 표시된 것은 업데이트가 아닌 일반 메일로 주로 업체에서 특정 사항에 대한 문의나 요청을 한 것에 대한 회신의 회수를 의미하고, 업데이트는 우리 제품의 새로운 업데이트 안내 메일을 발송한 회수를 표시한 것이다. 그러니 일반은 약간 (업체에 의해서 강제된) 비자발적 메일, 업데이트는 자발적 메일 발송이라고 볼 수 있다. 물론 업데이트 또한 요청에 의해서 발송되는 경우도 있기 때문에 100% 자발적 메일 발송이라고 보기에는 무리가 있다.&lt;/p&gt;
&lt;p&gt;이 그래프를 살펴보면 눈에 확 들어오는 것은 당연 1번 직원이다. 이 직원이 지난 한 달간 발송한 모든 메일은 3번 직원부터 7번 직원까지의 메일을 다 합친 것 보다 많다. 자발적 메일 발송이라 볼 수 있는 업데이트의 경우는 그 정도가 더 심한데 1번 직원을 제외한 나머지 직원을 다 합친 수치와 맞먹는다는 점이다. 얜 뭐지? 슈퍼맨인가 하는 생각이 절로 들게 마련이다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 609px; margin-bottom: 16px;&apos; data-url=&apos;./메일_메트릭.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4755f33110e33d5d51475f14ff503688/71467/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.89473684210527%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACRElEQVR42oVRSW/TQBj1v2k2x0uczUlsjxMnjpd4iT124sSpklCWClRQkAJRkaCIpRc4VEJqASHCpRKI7cAVDly594T4J3ypkZC4MCONPr1v3rz3vSGymUyeothCoVwu12o1WZZxgONxPBwOp9PpaDSK4zgMAkmSoAt3WJbN5/PZbDaVShEkSdI0XSwWoYcQarfbQJtMtqMoms/n4ziezWZQA57wS6USwzDASqfTBMPQlWpVkpAoioqiaJqm63rPNG3btmDblmmagACe8Hme5ziOoigQJ2iKxMvjYPFUbPDdrgZXHcfxPA/7foDh8KEGBHBVVZvNZr1eB/E/ZJYiR4dfooNTJPC6sRHs9/sY4yAIwhCGhRcwIICDOFgTBCGZHJwTHEt5Bx/8/TctqeH2XVie5yfMwfmCOhE3DAOcw3SVSuUv2b73ybm9hsbO0bdw52bfNnEQDsIQkvsPmaVJ7e5HfflKaXem61/+lTv9nhqF57axH/jexrbn/2M7CXwzc2f/nbp4LjcV//jMmi7w9qX5w1MPh/GF3cnOVdeFuDRD1yAw+MskMJpmcrkcweRz8q23rRsngiSbz8608TX74ip8+dNxvejB++Gjz5ahjffuW0HcbjXVTqdarXIFlsqTmUxmQ5auv5B3nwgiUg+/dweX9XjPePzVsh1r9bq3WvcMHR/9MKZL1Q7c5QkvoJrU4lEnnU4R8F00WyiWypVyRUQykuWWoqi6ASY1w+xqm5AUtSshuSGiGuoUChzNciTFpLa2fgMt29m14fLDDQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 2&apos; title=&apos;&apos; src=&apos;/static/4755f33110e33d5d51475f14ff503688/71467/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_2.png&apos; srcset=&apos;/static/4755f33110e33d5d51475f14ff503688/08678/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_2.png 190w,
/static/4755f33110e33d5d51475f14ff503688/2edd7/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_2.png 380w,
/static/4755f33110e33d5d51475f14ff503688/71467/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_2.png 609w&apos; sizes=&apos;(max-width: 609px) 100vw, 609px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
위 그래프는 해당 기간 동안에 하루 평균 몇 통의 메일을 보냈는지를 나타내는 그래프다. 1번 직원의 고충이 좀 더 선명하게 드러나는데 나머지 직원과의 비교는 둘째 치더라도 이 직원이 하루 평균 7통의 메일을 보낸다는 사실에서 심각한 격무에 시달리고 있음을 알 수 있다. 8시간 근무라고 가정했을 때 통상적으로 한 시간에 한 통의 메일을 보냈다는 점이다. 업무 일수가 아닌 단순 기간으로 나눈 통계이기 때문에 업무 일수로 나눈다면 그 정도가 훨씬 심해질 것이다. 실제로 1번 직원은 “요즘 정말 정신없이 바빠서 뭔가 다른 걸 생각할 엄두가 나지 않는다”라는 이야기를 했다. 그말이 그저 하는 엄살은 아니라는 걸 보여주는 그래프인 것 같아 더 씁쓸하다.&lt;/p&gt;
&lt;p&gt;이쯤되면 몇 가지 생각이 들게 마련이다. 왜 이 친구들은 동일한 업무를 수행함에 있어서 이 정도로 심각한 불평등 상황에 직면했는데 이 상황을 개선하려고 하지 않을까가 그 첫번째 의문이다. 이 정도면 사실 데이터를 뽑지 않아도 1번 직원이 과도하게 격무에 시달린다는 생각을 할 법하고 업무 배분을 좀 더 새롭게 할수도 있을 것 같은데 그러지 않는다는 점이다. 두번째는 왜 다른 직원들은 1번 직원의 이런 초과 업무에 대해서 도와주지 않을까라는 생각이 들기도 한다. 옆에 동료가 평균 한 시간에 한통의 메일을 써야 할 정도로 정신이 없다면 옆에서 보기 딱해서라도 몇 개 정도는 내가 도와줄게요라고 말할수도 있지 않을까하는 점이다. 그런데 대부분의 경우 그런 일은 거의 벌어지지 않는다. 물론 그렇다고 사이가 좋지 않은 것은 아니다. 옆에서 보기엔 참 화기애애해 보인다.&lt;/p&gt;
&lt;p&gt;이런 모든 걸 차치하고서라도 내가 생각하기에 더 재미난 사실은 저 업무에 참여한 모든 직원이 다들 우린 똑같이 힘들다고 말한다는 점이다. 3, 4, 5번 직원은 비슷한 수준의 업무 강도를 느끼고 있다고 생각할 수 있지만 그들이 1, 2번 직원과 똑같이 힘들다고 한다면 그건 분명 공평한 일은 아니다. 그런데 이상하게도 보상에 아주 근소한 차이가 있다면 3, 4, 5, 6, 7번 직원은 불만을 느끼거나, 불공평하다고 느끼거나, 내가 개인적인 친밀감 같은 것을 토대로 잘못된 판단을 내리고 있다고 생각한다. 그러니 이 상황에서 공정한 보상이 주어진다면 1, 2번 직원은 다소 실망할 것이고, 불균등한 보상이 주어진다면 3, 4, 5, 6, 7번 직원이 실망할 것이다. 벤담의 공리주의를 따른다면 균등한 보상이 주어지는 것이 맞는 상황인 것이다. 하지만 쳐다보는 입장은 또 그게 마음이 편하진 않다. 그래서 다른 부분에서 그들이 더 보상을 받을 수 있도록 기회적인 요소를 추가해서 균형을 맞추고 싶어한다. 그런데 또 웃긴것은 기회적인 요소를 여기에다 추가를 하면 그 기회에서 제외된 나머지 직원들은 내가 친밀감 따위를 토대로 기회를 제공하는 사람이라고 생각해 버린다는 것이다. 그러니 모두가 공평하게 행복한 상황은 애초에 만들 수가 없다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 615px; margin-bottom: 16px;&apos; data-url=&apos;./메일_메트릭.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6c19dc079679c58db4398460ea15149e/8ab79/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 51.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABDElEQVR42l1QW46DMAzMxQA7D+I4wG5b1Er8lH5073+EdWJBoaPRxIk9WIwhImut2yB13/fP5/p6vf7e72VZ1nUVlcevMTGalBjQAgBWaEEViVPRROLcW7uGEMw4/fhh9t6HCl9hz5BVOqBdLWKMhnN249354M7Quc/V+a+BYs7MYrZirhuO2/R61L2l0Yg52fGBzltEfZUDy6FyUoXW1ZzI5hn5UuPqEFrcwtu+8FHlwcxcBvmGwwP5ijSB78GW/KFrKxtom031pe3aRkIzOXMJXhqyOCSII+QZ8h34BnyFJLxA+gWaMI6VgxD6IRAbyb3rOltXOflfycNiyTnEQIOLOfDkaDiqp7Gwp3/DP6FO8INgrgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 3&apos; title=&apos;&apos; src=&apos;/static/6c19dc079679c58db4398460ea15149e/8ab79/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_3.png&apos; srcset=&apos;/static/6c19dc079679c58db4398460ea15149e/08678/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_3.png 190w,
/static/6c19dc079679c58db4398460ea15149e/2edd7/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_3.png 380w,
/static/6c19dc079679c58db4398460ea15149e/8ab79/%EB%A9%94%EC%9D%BC_%EB%A9%94%ED%8A%B8%EB%A6%AD.md_3.png 615w&apos; sizes=&apos;(max-width: 615px) 100vw, 615px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
상황을 좀 더 세밀하게 이해하기 위해서는 결과만 바라볼 것이 아닌 원인도 같이 고려해야 한다. 그런 이면을 보여주는 것이 이 그래프다. 그래프는 지난 한달간 우리에게 적어도 1회 이상 요청 메일을 보낸 업체를 보여주고 있다. 60여개 정도의 업체에서 1통 이상의 요청이나 문의 메일을 보냈는데 살펴보면 데이터가 좀 재미있다. 바로 요청의 대부분을 자주 요청하는 업체에서 거의 독식하고 있다는 점이다. 특히나 1위를 기록한 업체는 근 100여번의 요청을 했는데, 전체에서 차지하는 비중이 무려 16%에 이른다. 당연한 이야기겠지만 그 업체 담당자가 1번 직원이다. 이 업체는 일 평균 2.43통의 요청 메일을 보냈는데, 내가 생각하기에 거기에 병목 지점이 있다. 즉, 그 업체가 지속적으로 뭔가를 요청하는 메일을 보낸다는 것은 상황이 좋지 않다는 것을 의미하기 때문이다. 우리에게 요청을하지 않아도 문제를 해결할 수 있도록 개선된다면 100통의 메일을 처리할 필요가 없어진다는 점이다. 그리고 실제로 그 업체에서 요청하는 상당수 메일을 살펴보면 개선할 여지가 있는 요청 메일이다.&lt;/p&gt;
&lt;p&gt;물론 1번 업체의 요청 메일 하나를 개선한다고 1번 직원의 격무가 사라지는 것은 아니다. 어느 정도 완화되겠지만 그 요청 메일을 차치하더라도 다른 직원과의 격차는 굉장히 크다. 당연히 유능한 관리자라면 그 격차가 줄 수 있도록 방향을 제시해 주어야 한다. 가장 이상적인 상태라면 저 모든 직원들이 일 평균 3통 정도의 메일을 처리하는 상태라 할 수 있을 것이다. 그 이상이 넘어간다면 추가 인원 투입이 필요한 시점이라고 할 수 있다. 하지만 테일러 할아버지, 아니 고조 할아버지가 와도 저 상황을 개선할 수는 없다. 아주 잠깐 동안의 평형 상태는 만들 수 있어도 한달만 지나면 딱 지금의 그래프와 똑같은 상황이 만들어지기 때문이다. 실제로 과거 데이터가 그것을 말해주고 있다. 이 업무가 균등해지기 위한 유일한 길은 업무에 참여하는 모든 사람이 불균등함이 존재한다는 사실을 인정하고 그걸 개선하려고 노력할 때에만 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;종종 직원들한테 하는 이야기 중에 하나가 체인이 빠진 자전거 바퀴를 돌리고 있는 것 같다는 말이 있다. 우리 회사 직원들은 다들 열심히 일한다. 옆에서 보기 안스러울 정도로 열심이다. 그런데 가끔 그 이면을 살펴보면 체인이 빠진 자전거 바퀴를 열심히 돌리고 있는 것 같아서 씁쓸할 때가 많다. 조금만 변화를 주어도 극적으로 상황을 개선할 수 있음에도 그런 변화를 아무도 만들려고 하지 않는다. 그저 바퀴를 더 열심히 굴리는 일에만 집중할 뿐이다. 현실에 치여서 그러질 못한다는 이야기를 많이 하는데 그래서는 전투에선 이길 수 있을지 몰라도 전쟁에서는 패할 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;작은 업체는 항상 모든 게 부족하다. 돈도 부족하고, 사람도 부족하고, 시간도 부족하다. 예전에 우리가 1.0 버전을 만들고 있을 때 회사에 같이 계셨던 분은 그랬었다. 우리는 돈도 없고 사람도 없으니 1.0을 만드는 것 외에는 할 수 있는게 없다. 그때 난 모든게 부족해도 2.0을 설계하고 만들어야 한다는 이야기를 했었다. 아마 그때 우리가 1.0만 만들고 있었다면 지금도 1.0만 있거나 아니면 망했을 것이다. 현실이 아무리 각박하고 초라해도 미래를 위해서 일정 시간을 떼어내서 투자해야 한다. 다윗이 골리앗을 이기는 유일한 길이 바로 거기에 있기 때문이다.&lt;/p&gt;
&lt;p&gt;언젠간 우리 회사 직원들도 다들 이런 생각을 가졌으면 좋겠다는 생각을 해본다. 스스로 자신의 업무를 측정하고, 분석해서 문제점을 찾고, 개선해 나갈 수 있는 방향을 토론하는 그런 분위기가 된다면 더할 나위 없이 좋겠다는 생각도 해보지만 한편으론 너무 많은 것을 바라는 건 아닐까라는 생각에 조심스럽기도 하다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Allman Style]]></title><description><![CDATA[Allman vs K&R 답없는 종교 전쟁을 또 다시 시작하자는 이야기는 아니구요. 페북에 재미난 그림이 있어서 퍼왔습니다. Allman과 K&R 스타일을 비교한 것 같은데요. 전 개인적으론 Allman…]]></description><link>https://jiniya.net/wp/archives/13372</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13372</guid><pubDate>Wed, 18 Jun 2014 23:59:41 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./Allman_Style.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3a777bd6929d3ae349ce88c99f322b4d/b0db9/Allman_Style.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 70.52631578947368%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACbUlEQVR42k1SaW/aQBDlhyQ+Fh/Y2MZ72eu1MWAOhxIICTQCHEiBpkqqqv//Y8eQSpGe1rPj93ZGM68R+D0d0Vsl1HSmqgSAEFPgqn0GqoIh1nVmGlFN0GqOplEdscZy9XI8/9nuzrPZ8/KxWn//MSmfDq/vi4ddebfav75vNqfFYjeePB0O76vVfrXePz8f3379LUbLhhfkxXA+HD/ItCyKZb8/Z7wAfZpNhRiv1odiuOzmMyFGg8FiUj7mvdnddH03/S6SSQMZ4lYlNypRNHaj0luVIiOCjIaY3uSKRhW9hqrD35pw4ZALgTe0JsNhIcU4lb0sGYik8HHW9ruGJUw7AUDg+92YD/N0kMm+lEWUjLxOTWioOhFxyXCWMp5zwYkwWiQIe01TwG8ABEEnx6Ese8l9VxQy9XHidTLIQ2XiB13Hp1EURzju+NR0iNfJv4prqkMcFtkuNWxstogfdi9iREKc2y63KEUm1k0Mlf0vYmTEmPYdL7JCajgYWbh+/SpWdAxzIyz3sQzC1O+kAU6DMG8a/8VmjElOaOYFIggTQIhlB8PrMUybWXZi28JxpOumrivdtmy1pGWnVisBmLa8nKLlSqedAiCAaz0ww4rg0/a6MHYF3AOL0Qi4TdO5hihsC2LosO3nsMJ6cxqFLV6bajRN7nhZVb1ttqdtddrv347Hj+rl53Z7qqoTWGo+35zPv0+nj832uNmdX48f4Ch4FLZYV4au2l7G+aicrPLevcy+RaKMxDgSQ3Ab5cNYjEPS59FIptNETikbfVY2rPiyj/jaIbStIqahCAwEgGSdRxx6hhN8dnFedBX/A4xdrdLh1J8hAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Allman Style md 0&apos; title=&apos;&apos; src=&apos;/static/3a777bd6929d3ae349ce88c99f322b4d/b0db9/Allman_Style.md_0.png&apos; srcset=&apos;/static/3a777bd6929d3ae349ce88c99f322b4d/08678/Allman_Style.md_0.png 190w,
/static/3a777bd6929d3ae349ce88c99f322b4d/2edd7/Allman_Style.md_0.png 380w,
/static/3a777bd6929d3ae349ce88c99f322b4d/b0db9/Allman_Style.md_0.png 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;Allman vs K&amp;#x26;R&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;답없는 종교 전쟁을 또 다시 시작하자는 이야기는 아니구요. 페북에 재미난 그림이 있어서 퍼왔습니다. Allman과 K&amp;#x26;R 스타일을 비교한 것 같은데요. 전 개인적으론 Allman 스타일을 선호합니다. 이유는 &lt;a href=&quot;http://en.wikipedia.org/wiki/Indent_style&quot;&gt;위키 페이지에&lt;/a&gt; 나와 있는 아래 코드와 같은 장점들 때문입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//while (x == y)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;somethingelse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//for (int i=0; i &amp;lt; x; i++)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//while (x == y)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;somethingelse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;HAS_GETCH&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 이 이야기 끝에는 블록 단위로 복사, 붙여넣기 편하다는 장점이 위치할 것 같습니다. K&amp;#x26;R 스타일을 사용할 경우 블록 단위 복사, 붙여넣기를 하려면 결국 셀 선택을 해야하는 불편함이 있거든요. 물론 이런 이야기를 하면 사이비 프로그래머니까 창조성 없는 복붙 프로그래밍이나 하는것 아니냐는 반론을 감수하긴 해야겠지요. 창조적인 프로그래머 아저씨, 리누스 토발즈옹은 K&amp;#x26;R에 대한 신념을 언급한 적이 있었지요.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;C 스타일과 관련돼서 항상 튀어나오는 다른 이슈는 괄호를 어디다 위치시키냐 하는 것이다. 인덴트 사이즈와 다르게, 다른 것을 배제하고 한 가지 배치 전략을 선택하는 것은 아주 조금의 기술적인 이유밖에 없다. 그러나 좋아라 하는 방법은 열기 괄호는 라인 끝에 위치시키고, 닫기 괄호는 라인의 처음에 위치시키는 것이다. 이러한 방법은 커닝헌과 리치와 같은 선지자들이 우리에게 보여준 것이기도 하다. 아래와 같이 될 것 이다.&lt;/p&gt;
&lt;p&gt;if (x is true) {&lt;/p&gt;
&lt;p&gt;    we do y&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;그러나, 거기에는 함수라는 한가지 특별한 경우가 있다. : 그것들은 다음과 같이 열기 괄호를 다음 줄의 시작에 위치시킨다.&lt;/p&gt;
&lt;p&gt;int function(int x)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;    body of function&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;전세계에 분포한 이단자들은 이것은 모순이다... 음 불완전하다...,라는 주장을 펼친다. 그러나 바르게 생각하는 모든 사람은 (a) K&amp;#x26;R은 올바르며 (b) K&amp;#x26;R도 옳다는 것을 알고 있다. 게다가, 함수는 어쨌든 특별하다 (C에서 함수는 중첩이 불가능하다).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/lecture/translate/linux_kstyle.html&quot;&gt;리눅스 커널 코딩 스타일, 리누스 토발즈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;여러분은 어떤 스타일을 선호하시나요? 특별한 이유가 있으신가요?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 분급]]></title><description><![CDATA[정동진, 이곳이 해가 뜨는 곳이기에… 부디 좋은 곳에서 편히 쉬시길… #…]]></description><link>https://jiniya.net/wp/archives/13362</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13362</guid><pubDate>Tue, 17 Jun 2014 23:59:40 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;정동진, 이곳이 해가 뜨는 곳이기에…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;부디 좋은 곳에서 편히 쉬시길…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;정동진에서 서른네 살의 노동자가 자살했다. “이곳이 해가 뜨는 곳이기에”라는 말을 유서에 남겼다. “더 이상 누구의 희생도 아픔도 보지 못하겠으며 조합원들의 힘든 모습도 보지 못하겠기에 절 바칩니다”라는 말도 유서에 적혀 있다. 막 꽃피어야 할 한창나이의 젊음이 자신의 최후로 선택한 정동진엔 오늘도 변함없이 해가 뜬다. 그가 전하고 싶었던 소망과 절망감을 다시 또 알려주기라도 하는 듯이.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;삼성전자서비스 직원인 그의 지난달 월급은 45만원 정도였다고 한다. 그 전달에는 70여만원이었다. 분당으로 받는 급여를 뜻하는 ‘분급’에 의해 지급된 것이라 한다. 분급이라는 말. 근래 들어본 가장 끔찍한 단어이다. 이런 임금체계를 현실로 시스템화하는 곳이 바로 삼성이다. 이동시간, 고객에게 설명하는 시간, 수리 준비 시간 등을 다 빼고 오직 제품 고치는 시간만 계산해 1분당 225원을 받는 노동자라니. 이런 끔찍한 착취 앞에 저항하지 못한다면 우리는 대체 누구이며, 내일은 또 무엇을 할 수 있을까. 무노조 경영의 악착같은 착취를 ‘초일류기업’의 세련된 이미지로 포장하는 이건희 일가의 재산 13조원을 만들어준 노동자들 중 누구는 백혈병과 희귀병으로 죽어가고 누구는 견디다 못한 자살로 죽어간다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;전세계 139개 나라 중 한국의 노동권이 최하위인 5등급으로 분류되었다는 뉴스가 흘러나온다. 여기가 대한민국호가 서 있는 자리다. 해 뜨는 곳 정동진으로 노랗게 해가 진다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;-- &lt;a href=&quot;http://www.hani.co.kr/arti/opinion/column/638861.html&quot;&gt;한겨레, 김선우 시인·소설가&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;얼마 전 “코딩 호러가 들려주는 진짜 소프트웨어 개발 이야기”란 책을 사러 서점을 가는 길에 서점에 책이 없을 수도 있겠다 싶어서 지하철 앞에서는 핸펀으로 재고 검색을 하다 핸펀을 떨어뜨렸다. 핸펀을 바닥과 접촉시키는 일이야 늘상 벌어지지만 그날은 재수가 없었는지 액정이 깨져 버렸다. 갤럭시 S4 LTE-A, 산지도 얼마 안된 핸펀 액정이 또 깨지다뉘. 절망하면서 핸펀을 다시 켜는데 어랏. 액정이 아예 켜지지도 않았다. 진짜 액정이 깨진 것이다. 액정 앞에 강화유리(?!)가 깨진게 아니라. 고약한 일이 벌어진 것이다.&lt;/p&gt;
&lt;p&gt;이를 어쩌지 하면서 삼성전자 서비스 센터를 갔다. 서비스 센터 앞에서는 전형적인 블랙 컨슈머 흉내를 낸다. 천연덕스럽게 액정이 안 나와서 왔다며 바보 코스프레에 들어갔다. 센터 직원 아저씨가 친절하게 안경 닦는 천으로 닦더니 안이 깨져서 화면이 나오질 않는다고 외부에서 충격을 가한 것 같다는 설명을 덧붙였다. 모르겠다는 표정을 지으니 오른쪽 모서리에 스크래치가 난 자국을 문제 삼으며 이쪽으로 충격이 가해지면서 안에 있는 액정이 깨졌을 것이란 놀랍도록 정확한 추론을 펼쳤다. 난 여전히 모르겠다는 표정을 지으며 오른쪽 모서리는 원래 그랬고, 충격을 가한 적도 없으며, 그 충격을 가해서 안쪽 액정이 깨졌다는 것을 내가 증명해야 하는 문제냐고 했다. 증명이란 단어에 아저씨는 머리가 조금 아파하는 표정을 짓더니 안에다 물어보고 오겠다고 했다. 그리곤 잠시 후 나오더니 원래 공짜로 되지 않는 것인데 애매한 상황이라 공짜로 해주는 것이라며 10만원 상당의 액정 모듈 교체를 공짜로 해주었다. 친절 사원 쓰는 곳에 난 센터 직원 아저씨 이름 옆에 짱짱맨을 적어주며 기분 좋게 나왔다.&lt;/p&gt;
&lt;p&gt;난 삼성이란 기업을 그다지 좋아하지 않았다. 그런데 그 공짜 수리 사건으로 급 호감이 갔다. 담에도 삼성 폰을 사야지 이러면서. 더 부끄러운 사실은 이 쪽팔린 공짜 수리 사건을 무슨 무용담이라도 되는양 의기양양하게 주변에 떠벌리고 다녔다는 점이다. 당연한 이야기겠지만 그 무용담에서 삼성이란 기업은 철저하게 착한 기업으로 각색돼 있었다. 물론 이런 행위에 드는 비용 일체가 핸드폰 가격에 포함돼 있고, 그래서 우리가 호구처럼 비싼 가격에 핸드폰을 사야한다는 사실을 모르지도 않는 사람이 그랬다는 사실이 더 창피할 뿐이다. 분급이란 기사를 보니 있으니 이런 나의 어리석은 행동이 더 민망하게 느껴졌다. 다음엔 꼭 LG 폰을 사야겠다. 옵지3가 잘 빠졌다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 360px; margin-bottom: 16px;&apos; data-url=&apos;./분급.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/62eb3949e93d8730600326fc0bcaa105/543cd/%EB%B6%84%EA%B8%89.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 63.68421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEAf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAFconmlGE//xAAaEAADAAMBAAAAAAAAAAAAAAAAAQIDEyEE/9oACAEBAAEFAtUorzwaZE+Vj66P/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAgEFAAAAAAAAAAAAAAAAAAEQAhExQWH/2gAIAQEABj8CXTJuLupx/8QAGRABAQEAAwAAAAAAAAAAAAAAAQARIUGB/9oACAEBAAE/IdGRRYyOxBHCppukfZBv/9oADAMBAAIAAwAAABDYz//EABURAQEAAAAAAAAAAAAAAAAAAAAh/9oACAEDAQE/EEf/xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAgEBPxCq/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARMSFBgf/aAAgBAQABPxACqChQCtezmbNHPkrBR6RgRSAzd2You6jEer25/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;   md 0&apos; title=&apos;&apos; src=&apos;/static/62eb3949e93d8730600326fc0bcaa105/543cd/%EB%B6%84%EA%B8%89.md_0.jpg&apos; srcset=&apos;/static/62eb3949e93d8730600326fc0bcaa105/8ccab/%EB%B6%84%EA%B8%89.md_0.jpg 190w,
/static/62eb3949e93d8730600326fc0bcaa105/543cd/%EB%B6%84%EA%B8%89.md_0.jpg 360w&apos; sizes=&apos;(max-width: 360px) 100vw, 360px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;죽은 고기만 먹기에 소녀가 죽기를 기다리는 독수리&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;내가 바라보는 자본주의의 민낯&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;난 자본주의를 딱 저 사진처럼 느낀다. 따스함이란 없는 무자비한 약육강식의 세계, 일말의 공정함도 기대하기는 힘든 시스템. 이건 비단 사용자와 노동자 사이의 관계에서만 그런 것은 아니다. 기업이 제품을 파는 일도 똑같다. 좋은 제품을 만들면 잘 팔릴 것 같지만 꼭 그렇지도 않다. 그 중간에 온갖 정치, 음해, 공작 같은 것들이 있고, 시장을 비정상적으로 왜곡시키는 광고나 마케팅 효과도 있기 때문이다. 지금 한껏 주가를 올리고 있는 그 표절 게임만 해도 그렇다. 지나가는 게임 개발자 100명에게 물어보면 100명 모두 그 게임이 그렇게 매출 순위가 높은 게임이 되는 건 공정하지 않다고 말할 것이다. 하지만 시장에서 그 게임은 엄청난 매출을 올리고 있다. 내가 바라보는 자본주의 시장은 그렇다. 제 아무리 좋은 걸 만들어도 하나도 못 팔 수도 있고, 쓰레기를 만들어도 날개 돋친 듯 팔릴 수도 있다.&lt;/p&gt;
&lt;p&gt;가끔 직원들과 이야기를 하다보면 깜짝 놀랄때가 있는데, 그들이 나와는 정반대의 세계관을 가지고 있을때다. 자본주의 시스템에 대해서 굉장한 퐌타지와 이데아를 가지고 있는 경우라 할 수 있겠다. 난 그런 이야기를 들을 때마다 내가 세상을 너무 냉소적으로 바라보고 있거나 잘못 알고 있었던 것일까, 라는 생각을 했다. 왜냐하면 그들 말에 따르자면 구조조정이란 단어는 세상 밖으로 나오지도 않았을 것이고 전 지구를 협동조합이라는 가장 우수한 조직 시스템이 장악했을 것이기 때문이다. 그런데 현실은 뉴스에 감기처럼 달고 나오는 게 구조조정이고, 주식회사라는 시스템이 전 지구를 뒤덮었다.&lt;/p&gt;
&lt;p&gt;이런 묘한 아이러니 속에서 난 도대체 왜일까라는 의문이 생겼고 자본주의를 좀 더 제대로 알아야 겠다는 생각에 얼마 전 “자본주의 이해하기”라는 책을 샀다. 이 책을 통해서 난 자본주의 시스템에 대해서 충격을 더 받게 되었는데 그 이유는 내가 무엇을 상상하든 그 이상으로 자본주의는 냉정하고 차갑고 비정하며, 또한 무기력한 시스템이었기 때문이었다. 그 중에 하나가 실업 문제에 대한 결론이었다. 사실 분급이라는 게 따지고 따지고 따지고 또 따지고 들어보면 좋은 일자리가 많이 없다는 결론으로 더 파고 들면 실업 문제로 귀결된다고 할 수 있다. 책에서는 실업에 대해서 아래와 같이 너무나도 냉혹한 결론을 너무나도 논리 정연하게 기술하고 있기에 일말의 반박을 할 여지조차 주지 않고 있었다. “고용주도 노동자들도 이러한 상황을 개선할 수 없다”라는 결론은 정말이지 떨떠름할 따름이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;케인스는 이 논리를 거부했다. 그에 따르면 실업은 임금이 너무 높아서 생기는 문제가 아니라, 노동이 생산한 재화에 대한 수요가 너무 적기 때문에 발생하는 것이다. 그리고 “문제가 생산물에 대한 대한 수요가 불충분하기 때문이라면 해결책은 임금을 낮추는 것이 아니라 높이는 것”이라고 케인스는 말했다. 그는 사람들이 물건을 사기 위해 지불하는 소득의 근원이 임금이고 경제의 산출물에 대한 수요의 상당 부분이 바로 임금에 의해 뒷받침되므로, 고임금은 수요의 증가를 낳고, 수요의 증가가 이번에는 산출의 증가로, 고용의 증가로, 그리고 실업의 감소로 이어질 것이라고 생각했다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;케인스의 이론이 보여주는 것은 1) 자본주의는 실업을 해결할 수 있는 자동적 메커니즘을 갖고 있지 못하며, 2) 자본주의 경제에서 실업은 비자발적인 것이며 임금이 낮아진다고 해도 실업은 사라지지 않을 것이라는 점이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;… 중략 …&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;셋째, 고용주의 입장에서 임금을 낮추는 것이 이윤 극대화에 도움이 되지 않을 수도 있다는 것이다. 최적 임금 w’보다 임금이 낮으면 단위 노동비용은 오히려 상승한다. 임금을 낮추어 비용을 절감할 수 있지만 그 결과 노동강도(e)가 낮아지고 산출량이 감소해 임금 하락으로 얻은 비용 절감분보다 노력 지출량 저하에 따른 손해가 더 커지기 때문이다. 즉 고용주는 임금을 w’이하로 낮출 유인을 갖지 않는다. 현재 임금수준 w’보다 낮은 수준에서도 기꺼이 일할 용의가 있는 사람들이 있더라도 이들을 낮은 임금으로 고용하려고 하지 않는다. 임금을 낮춤으로써 단위 노동비용이 상승할 것을 우려하기 때문이다. 이 결론은 중요하다. 바로 우리가 4장에서 본 케인스의 주장, 즉 실업자들이 현재보다 낮은 임금수준을 받아들일 용의가 있음에도 실업은 사라지지 않을 것이고, 바로 이 때문에 자본주의 경제에서 비자발적 실업은 보편적인 현상이라는 주장과 일맥상통하기 때문이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;실업 상태에 놓여 있는 사람들이 현행 임금보다 낮은 임금을 받아들일 용의가 있음에도 일자리를 찾지 못한다는 사실은 자본주의사회에서 실업이 항구적일 수 있다는 것을 의미한다. 더 나아가 노동시장에서 초과 공급이 존재하는 상황에서도 임금이 더는 하락하지 않을 것임을 말해준다. 초과 공급이 존재하고 더 낮은 임금을 받아들일 준비가 되어 있음에도 아무도 이들을 데려가려고 하지 않는다. 고용주도 노동자들도 이러한 상황을 개선할 수 없다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;-- 자본주의 이해하기, 새뮤얼 보울스, 리처드 에드워즈, 프랭크 루스벨트&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;언젠가 친구네 회사가 회식비와 경비 일체에 대해서 3개월간 시험적으로 제한을 없앴다는 이야기를 했다. 즉, 회식 때 마음껏 먹고 마시고 놀아도 된다는 것이다. 니들이 한강에서 요트를 타고 선상 파뤼를 하며 회식을 하더라도 다 처리해 주겠다는 대인배적 마인드라 할 수 있겠다. 이 사건과 몇 가지 행동을 두고 친구 녀석은 회사 대표가 착한 사람 같다는 표현을 썼었다. 그때 난 그 사람이 절대 착하지 않다고 이야기를 했다. 그 사람이 그렇게 제한을 풀고 복지를 늘리고 하는 것도 다 이유가 있기 때문일거라는 막연한 소리만 했었다. 그런데 “자본주의 이해하기”라는 책을 보면 그 대표가 왜 그런 행동을 하는지를 너무나도 논리 정연하게 설명해 놓고 있다. 두 글자로 그 대표가 취하는 행동에 대해서 기술하고 있는데 단어가 너무 언짢아서 차마 여기다 옮겨 적기는 좀 그런 것 같다. 궁금하신 분들은 책을 사서 읽어 보도록 하자.&lt;/p&gt;
&lt;p&gt;난 더 많은 사람들이 이런 책을 읽고 자본주의 시스템이 돌아가는 기본적인 원리나 생리에 대해서 알아야 한다고 생각한다. 현실을 사는데는 퐌타지나 이데아 보다는 이러한 차가운 진실들이 더 도움이 된다고 믿기 때문이다. 게임의 법칙을 알아야 게임에서 이길 확률이 올라갈 것이고, 적어도 지더라도 왜 졌는지 원인 분석은 될 테니까 말이다. 그런데 진짜 아이러니 한 사실은 이런 책을 읽지 말아야 할 사람들은 더 꼼꼼하게 밑줄 쳐가면서 읽고 정작 읽고 이해해야 할 사람들은 막연하게 퐌타지만 가지고 세상을 살아간다는 점이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1890년 촬영된 이 사진은 높다란 마천루 안에 은밀하게 숨겨진 뉴욕 빈곤층의 생활을 보여주고 있다.&lt;br&gt;
&lt;br&gt;
노동자의 노령 연금과 의료비를 보장하려는 기업은 없었다.&lt;br&gt;
&lt;br&gt;
법원 역시 작업 중 입은 재해는 노동자가 책임져야 하며 근로기준법은 위헌이라고 판결했다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;미국 노동자들은 거대한 기업 권력에 관해 이렇게 밝혔다.&lt;br&gt;
&lt;br&gt;
우리는 투표를 통해 그들을 쓰러뜨릴 수 있지만 투표함은 그들이 점유하고 있죠.&lt;br&gt;
&lt;br&gt;
우리는 법원에서 정의를 찾을 수 있지만 법원은 그들이 세운 겁니다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;… 중략 …&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;1903년 2월 대로우는 이렇게 변론했다.&lt;br&gt;
&lt;br&gt;
미국의 문명이 광부와 노동자들의 굶주림으로 이루어졌고&lt;br&gt;
&lt;br&gt;
겨우 열두서너살 된 아이가 먼지 날리는 무연탄 광산에서 석탄을 주워 생활을 영위한다면&lt;br&gt;
&lt;br&gt;
빨리 이 문명을 포기하고 새로운 문명을 시작하는 것이 인류에게 좋을 것이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;-- 기업의 힘 E04&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;자본주의 역사가 정확하게 어떻게 되는지는 모르겠지만 100년 전에도 지금과 비슷했던 것은 틀림이 없는 것 같다. 인간은 역사로부터 아무것도 배우지 못하는 존재라고들 한다. 그래서 역사는 반복되는지도 모르겠다. 불평등이 극에 달했던 시스템은 모두 파괴되고 붕괴되었다. 자본주의 시스템이 아슬아슬한 줄타기를 하며 계속 유지될지 아닐지는 모르겠지만 부디 힘을 가진 높으신 분들이 바리케이드의 역사를 잊지 않는 지혜를 가졌으면 하는 바램이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;최고의 시절이자 최악의 시절, 지혜의 시대이자 어리석음의 시대였다. 믿음의 세기이자 의심의 세기였으며, 빛의 계절이자 어둠의 계절이었다. 희망의 봄이면서 곧 절망의 겨울이었다. 우리 앞에는 모든 것이 있었지만 한편으로 아무것도 없었다. 우리는 모두 천국으로 향해 가고자 했지만 우리는 엉뚱한 방향으로 걸었다. 말하자면, 지금과 너무 흡사하게, 그 시절 목청 큰 권위자들 역시 좋든 나쁘든 간에 오직 극단적인 비교로만 그 시대를 규정하려고 했다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;-- 두 도시 이야기, 찰스 디킨스&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[iOS 입문]]></title><description><![CDATA[#0  Android 78.1%, iOS 17.6%, Windows Phone 3.0%, From IDC 아이폰 하면 무슨 느낌이 드시나요? 제가 처음 쓴 맛폰이 갤s였고, 그 담에 아이폰4를 썼습니다. 갤s 쓰다가 아이폰4를 쓰니 신세계였죠. 갤s…]]></description><link>https://jiniya.net/wp/archives/13532</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13532</guid><pubDate>Thu, 05 Jun 2014 23:59:39 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 576px; margin-bottom: 16px;&apos; data-url=&apos;./iOS_입문.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1519c572a876b90622dda350ec57d35b/694da/iOS_%EC%9E%85%EB%AC%B8.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 64.73684210526316%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACSElEQVR42l1SS2/TQBDOX+GUd/NO1CR27F3bu07cpPb6mTRChdCEHEACRKUeCrRFSNBDoQLUSxGVOFFx4XFDghtI9MaFA78CceeLfICyWsszO9+3M9/sJJLJZCaTWVpaqlQqjUZjeXmZcz4MQ9fzxuOx7wpXiCga6rqOEADlchlgUFKpVAK/fD5fKpXq9Xqr1VIUhXHetX3XD6az6ejSXLiuM+jhRoTa7TZgAIOSTqcT2Wy2WCzWarVms6koHWSgvHe4Tr/vuc+eH0yPvs6OvgXX7nMDEQ18wAAuFAogJuK0qEeWJF2jKrNOr0q/7lSfbvDRKHLHV4Y396cnP9a2j7mhYcmyHBefy+USsVroIaoi6+a23/q9eeF6wOhq6HleAMWWIS7O109+2pPbBukoKkHyarUK4oIMC75GVEnvvpyz17Om6QSjMAjjFY1E3wx2T/29N4zIhFK05hwZPk65Tpz9z86tQ9+2gjCKFwxv1RI3DsSjT8zQCCEAQ/a5zIRQXDzYe+dsvfAG3SAaxolhwHW2jhFitAPY38xoWKxZUVSDyOZ0p//4zPECz+n7QYgNQ3hB/8lZd7ZrqBI0A4yGgZhA0+JuS5KsoXLG+L231oOPztqGK2xsGHBxiBClVJIkgEFZdBvPhUeLK18k1yizbH3zlfHwC9/5wHfew4C7ONQoAOfe+d8Ja7elhXJdM5nB/Ik+uYvN/MtwMSHo6P8Thg93QH25XGrJxDS7FqMrVq+/0hODnm2ZtqUKYTPTJBonqhrPNiipVOoPKgDjF36YHhYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;iOS    md 0&apos; title=&apos;&apos; src=&apos;/static/1519c572a876b90622dda350ec57d35b/694da/iOS_%EC%9E%85%EB%AC%B8.md_0.png&apos; srcset=&apos;/static/1519c572a876b90622dda350ec57d35b/08678/iOS_%EC%9E%85%EB%AC%B8.md_0.png 190w,
/static/1519c572a876b90622dda350ec57d35b/2edd7/iOS_%EC%9E%85%EB%AC%B8.md_0.png 380w,
/static/1519c572a876b90622dda350ec57d35b/694da/iOS_%EC%9E%85%EB%AC%B8.md_0.png 576w&apos; sizes=&apos;(max-width: 576px) 100vw, 576px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.idc.com/getdoc.jsp?containerId=prUS24676414&quot;&gt;Android 78.1%, iOS 17.6%, Windows Phone 3.0%, From IDC&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아이폰 하면 무슨 느낌이 드시나요? 제가 처음 쓴 맛폰이 갤s였고, 그 담에 아이폰4를 썼습니다. 갤s 쓰다가 아이폰4를 쓰니 신세계였죠. 갤s는 좀 아니었거든요. 아이폰4는 그랬습니다. 견고하고 빈틈없고 단단했습니다. 된다고 약속한 기능은 확실하게 동작했습니다. 아이폰4를 쓰면서 음악이 튀는 현상을 저는 경험해 본 적이 없었습니다. 쓸만한 스마트폰이었습니다. 하지만 결정적인 단점이 있었는데 바로 제 폰이 아니라 잡스횽 폰 같다는 느낌이었습니다. 저는 폰에 있는 파일들이나 시스템 설정들 또는 제가 필요한 데이터를 알아서 잘 관리할 수 있음에도 아이폰은 저에게 그런 여지를 허락하지 않더군요. 윈도용 아이튠즈는 정말 가관이었습니다. 다시 안드로이드 폰으로 갈아탈 수 밖에 없었죠. 그렇게 &lt;a href=&quot;http://www.jiniya.net/wp/archives/9960&quot;&gt;안드로이드 입문&lt;/a&gt;을 한지도 일년 넘는 시간이 지났습니다.&lt;/p&gt;
&lt;p&gt;그간 아이폰의 시장 점유율을 유심히 지켜보았습니다. 내심 속으로는 아이폰의 점유율이 과거 맥이 그랬던것처럼 쪼그라들길 바랬습니다. 하지만 그건 단순한 제 바램일 뿐이었습니다. 아이폰은 너무나 견고하게 자신만의 독자적인 세력과 점유율을 유지하고 있는 것처럼 보여집니다. 네 맞습니다. 아이폰 코딩을 시작할 시점이 됐다는 말이죠. 멀티 플랫폼 시대의 개발자는 정말 피곤한 직업인 것 같습니다. 과거 윈도우만 해도 먹고 사는데 문제가 없었던 시절이 그립네요. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;많은 사람들이 아이폰 보안이 좋다고 이야기합니다. 견고하다고 하죠. 안드로이드가 그렇게 두드려 맞는 동안에도 아이폰은 크게 이슈가 없었던 것 같습니다. 전 뭐 엔지니어로써 아이폰이라고 그닥 크게 보안성이 뛰어나다고 생각하진 않습니다. 막아 놓은 것들이 많고 사용자가 안드로이드 대비 적으니 덜 뚫린다고 생각하는 입장입니다. 어쨌든 그렇게 첩첩산중 막고 또 막고, 가리고 또 가리고, 숨기고 또 숨기고 해서 아이폰을 구매한 사용자에게는 제법 안전하다는 인식을 제공하고 있는 것 같습니다. 그렇다면 앱스토에 앱을 올리는 개발자 입장에서는 어떨까요?&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 577px; margin-bottom: 16px;&apos; data-url=&apos;./iOS_입문.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dfee6193ffa602e10ed54985e92ea0e8/32e64/iOS_%EC%9E%85%EB%AC%B8.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 77.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABcklEQVR42o2S646CMBCF+/5P5N/94QOsWsGVSwLeoDcosAvF0j1CYtR1E75MJoe20zmdQKrVWn6uKkobz6u325vwfRNFJgy7IGj3+29KbZoOzg3WDs8QtlxSzws9L/B9f7MJd7svShE7StMoEnl+ieOr7zswDO4ZwhYL+vHB0TCK6iBAroJA7/cIkyQuz12auvX6fbEVAmGy7DoKy/mVc4hBqQGCMZtltijg2P6BtMbkqjxzLrQum0ZVlarrn763ziGGe7yD9F0nxQ3OWKEUMufcdN3N5GO8g1xH7MMkJ21nQEzf33pxXhSFHIEwxrh/rD7ZxjlUZll2uVyOxyM0Y6yD7Rk82Z662dmQotRCyLIs4RZZKYXcY9pziquqgmdUwjY853le17WbB7n7fBnGtP3yeV+ZBCm1FlKiW9M0yFrrtm1xVz+CcdzzIxgzFgkeifFizrANz3hCkiTjXyNOp1OaptjFyuFwOJ/PU8bJOI6llL81J18Pg9u+OAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;iOS    md 1&apos; title=&apos;&apos; src=&apos;/static/dfee6193ffa602e10ed54985e92ea0e8/32e64/iOS_%EC%9E%85%EB%AC%B8.md_1.png&apos; srcset=&apos;/static/dfee6193ffa602e10ed54985e92ea0e8/08678/iOS_%EC%9E%85%EB%AC%B8.md_1.png 190w,
/static/dfee6193ffa602e10ed54985e92ea0e8/2edd7/iOS_%EC%9E%85%EB%AC%B8.md_1.png 380w,
/static/dfee6193ffa602e10ed54985e92ea0e8/32e64/iOS_%EC%9E%85%EB%AC%B8.md_1.png 577w&apos; sizes=&apos;(max-width: 577px) 100vw, 577px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;알만한 사람들은 다 아는 치트계의 블루오션 iOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;맞습니다. 지옥이죠. 그 잘난 샌드박스 덕분에 여러분이 할 수 있는건 아마 거의 없을 겁니다. 아이폰을 구매한 사용자가 맘먹고 앱을 공격하겠다고 생각하는 순간 앱은 감옥(샌드박스) 속에서 속수무책 당할 수 밖에 없습니다. 요즘 치트 좀 하는 사람들은 다 공공연히 알고 있는 사실이지만 아이폰은 치트계의 진정한 블루오션입니다. 앱을 보호해 줄 그 어떤 보안장치도 없거든요. 여러가지 이유가 있지만 삼성 공화국인 국내에서는 사용자가 많지 않아서 다소 무시 당했다는 점도 한 몫 했다고 봅니다. 하지만 더이상 그렇게 방치하기에는 아이폰 점유율이 무시할 수준은 아닌 것 같습니다. 아이폰이 독점적인 점유율을 누리는 국가들도 있고, 탈옥을 하지 않고도 앱을 위변조해서 사용하는 기법들도 속속 등장하는 지금, 이제는 뭔가 필요할 때가 되긴 한 것 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;&apos; data-url=&apos;./iOS_입문.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/64829644cf4f3228a817a7ab83bf5b68/0eb09/iOS_%EC%9E%85%EB%AC%B8.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 98.42105263157895%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAErElEQVR42m2Oe0xTdxzFfzomMILEguiA6aToUKriA0Xmg23ObaDLdI/4yNx0usTpposj4mZji0hL3+W2t71tubfvW6AUCrS4IlBoxZLFdYJWBUvHoA5BFNrSB3/tur89+eSbk29ycg7IylxBoVDWU/K2Fmw+9vVhtVbldrtpNDoAYPeO/M8/3XP8q31njpf88sNBetlR5pXjnKvfCq6dhKtOSRinwQIQB16hBQSvLYyLX7QoOSkpjZSSlZG2mpy5IW/Vtk1r9hTlffz+pkOlhWDNrm05RQVvF+Rn5edlUnKXryYvycpYvCw9OS0tcXFKfFJSXHzCgoWvLABgeQElo3Bj5s5NbxVvyd5XmLt/d95n7xGsO1C8dv+utaVFuSXv5pYU5X60/Z0Ptqwu3pyzc312Ye7KLTmZlBUgbsUykEEC6SkgLRksSQRLEsDSRJCRCJYTJgGkJYD0N8CbyWBlCiCTFpJT47JTXyenxpNJCWQSYLGqq5iMiuuVVyroZdTfzpeXff/zTwdPHNn/zZclxw7tOfDh9k+K8/fu2LivcN3ereQdeVmbc9I3rCStyUhZtRTwKlkQq6ZWVKuEMQIdotbJ1BoYqxVI6xQqXIbqJIhaJGpQIEY5bJAKtSIWyquQMC8L6OeBXCxXwKhMXAsLEYgngbhiiAsjkEwilHCruDAPUghhGU+IcLhSFhNmXIMqqXxaOfvXC8zys8DabO1s7+y22bt+77ZZbvbe7HV2OZxdvX09jqZ6k5gnQgSwlFuDcAUwmyOpZvAqqBVlF+gXz1HPnwYdFluryWIymE16UyPebDa2tTRaWoxt1mYLrtSr5UocVemI8VKZGobVYgjhMNQQy4TycXEluM6tgwVyrc6EmW5gaqMKw1Wo4f+rU8o1uArHMa0eVekVqE6m0EpgVMjRS/htaqhFwQRXaWIqleO2dXuqWP3tHY1N7aaGNlzTYNAacVVdva6hQV+PKzUGTKWTK8x6TaMKOfrFEeqlS0yGAChkemaNcoTNbydlm6UNnV19LaYb5kYLgcVsdTluuXocjo4Op+1Gr7Xtjt3WZTb8+N0pEYMm4bPBgdLDJ0+c++evewbMbHV6/L6xx0M+75B3+OHwkOfhg4HBwT/vDP7RP+i6NXC7516fvaMJJ2YP9TUP2DDgdLg0yvpAKBKbnw8HgtPTM1OT0xP/TjwZ9/tHR8e83pFHnpH7A75Bd5PFyUPMpnqjUVEz7Gq9360Ho74xNWZC5QZYpBaLNWJIWcNHBVwZlwWzGVB1Jb+KVn2Nep1+mXbh3MUzp87SL5XfrMNG+ls9dj2Ynnpm73TV8DAhB4UEKrFQI4U0MlirkGpRqRZDNCiiVEoxmRBm0yphNqtVWzt02zriMg85DCAcDAZnAqHA3FwoPBeMECYUCM0FiM9saOZ58PnUzNMnL/y+Kd+DMc+dcY9r4p7T7+709ZuHnQYQjYSi0XAsFp2fjxGKRqOxSDgSngvPEXkiPDn7dHzG750e9Ux67/of3B6/ax93d/zdTzTrQDT6MkwkYrFINBp56aPhSISYMRsKPgs8n5idHH3x5PH06P2nXrf/ocs/YB9z23yu5kc92v8AkQyOqOn7oEwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;iOS    md 2&apos; title=&apos;&apos; src=&apos;/static/64829644cf4f3228a817a7ab83bf5b68/0eb09/iOS_%EC%9E%85%EB%AC%B8.md_2.png&apos; srcset=&apos;/static/64829644cf4f3228a817a7ab83bf5b68/08678/iOS_%EC%9E%85%EB%AC%B8.md_2.png 190w,
/static/64829644cf4f3228a817a7ab83bf5b68/2edd7/iOS_%EC%9E%85%EB%AC%B8.md_2.png 380w,
/static/64829644cf4f3228a817a7ab83bf5b68/0eb09/iOS_%EC%9E%85%EB%AC%B8.md_2.png 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;Objective-C도, BSD도, MACH도, 샌드박스도 아니었다. 최고의 진입장벽… 맥 그 자체!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;치트의 공격에 손가락만 빨고 있는 여린 앱들을 위해서 iOS 연구를 시작했습니다. 맥 미니도 사고, 버렸던 아이폰4도 다시 켜서는 운영체제 업데이트도 했습니다. 애플에 개발자 등록도 하고 드디어 Xcode를 켰습니다. 이제 아이폰의 속살을 좀 들여다 볼까 하는데 난관에 봉착했습니다. 아이폰 개발은 그렇게 바로 시작할 수 있는게 아니더군요. 내 아이폰에 내가 만든 코드를 넣기 위해서는 여러 수십만 단계를 더 거쳐야 한다는 사실을 알게 되었습니다. 헐~ 블로그 검색질로 따라하면서 온갖 인증서를 만들고 온갖 디바이스 정보를 넣어서 등록을 했습니다. 드디어 모든 단계를 마쳤다고 생각했는데 거기가 또 끝이 아니더군요. 맥에서 아이폰을 인식하지 못하는 아스트랄한 상황이 벌어진 것이었습니다. Objective-C를 쳐다보기도 전에 탈진할 것 같은 상황. 모든 iOS 개발자들이 존경스러워지는 순간이었습니다.&lt;/p&gt;
&lt;p&gt;장치관리자가 있긴 있는건지?! 이 상황을 어떻게 해야 하는건지 도무지 몰라서 맥 좀 사용한 친구 녀석한테 어케 해야 하냐고 물어봤더니 아이튠즈를 다시 설치하라고 하더군요. 그렇게 몇 번의 재부팅을 거치고 나서야 드디어 마법처럼 인식이 되었습니다. 아이폰4 화면에 텅 빈 Hello, World! 앱이 뜨는데 뻥 좀 보태서 예전 X 윈도우를 처음 띄우고는 X 아이콘을 마주했을 때처럼 눈물이 약간 났습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;어떤 시스템에서 동작하는 보안 솔루션을 만들기 위해서 제일 처음 검토해야 하는 것은 당연한 소리겠지만 우리가 할 수 있는 것과 할 수 없는 것을 구분하는 작업입니다. 그래야 그 시스템에서 우리가 만들 수 있는 것과 만들 수 없는 것을 명확하게 알 수 있거든요.&lt;/p&gt;
&lt;p&gt;iOS의 속살을 파헤치기 전까지 저는 그저 안드로이드와 유사한 권한 체계를 통해서 운영체제를 구성했다고 생각했습니다. 다만 안드로이드가 읽기 권한을 줬다면 iOS는 읽기 권한 마저 제거했다고 어렴풋이 추측했을 뿐이었죠. 하지만 완전 번지수를 잘못 짚었던 착각이었습니다. iOS는 단지 리눅스/BSD의 기본 권한 체계를 사용한 권한 장난질로 샌드박스를 구현하고 있는 게 아니었습니다. 진짜 샌드박스가 있는 구조더군요. 이 말은 우리가 특정 파일에 접근할 수 있는 모든 권한을 가졌다 하더라도 샌드박스에서 그 파일 접근을 불허하면 파일 열기에 실패한다는 이야기입니다. 그럼 iOS 샌드박스가 어떤 것들을 제한하는지 한 번 살펴봅시다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;iOS — the Sandbox as a jail&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Inability to break out of the app’s directory. The app effectively sees its own directory (/var/mobile/Applications/) as the root, similar to the chroot (2) system call. As a corollary, the app has no knowledge of any other installed apps, and cannot access system files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;역주: 너희 영역 말고는 쳐다볼 엄두도 내지 마셈. 백신?! 스캐너?! 만들 수도 없고 만들 필요도 없음.&lt;/strong&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Inability to access any other process on the system, even if that process is owned by the same UID. The app effectively sees itself as the only process executing on the system.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;역주: 다른 프로세스 접근?! 꿈도 꾸지 마셈. 번지수 잘못 짚었음.&lt;/strong&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;
&lt;p&gt;Inability to directly use any of the hardware devices without going through Apple’s Frameworks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;역주: 우리가 만들어 준 것만 우리한테 허락 받고 쓰셈. 필요해도 없으면 그냥 손가락만 빨도록…&lt;/strong&gt;&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;
&lt;p&gt;Inability to dynamically generate code. The low-level implementations of the mmap (2) and mprotect (2) system calls are intentionally modified to circumvent any attempts to make writable memory pages also executable.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;역주: 난독화? 그딴거 만들고 싶어도 못만들거임. 정 만들고 싶으면 인터프리터, 트랜슬레이터 정도 고려해보셈.&lt;/strong&gt;&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;
&lt;p&gt;Inability to perform any operations but a subset of the ones allowed for the user mobile. Root permissions for an app (aside for Apple’s own) are unheard of.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;역주: 우리 혼자 짱짱맨. 서드파티가 뭔가요? 씹어먹는 건가요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;– Mac OS X and iOS Internals, Jonathan Levin&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;말 그대로 감옥이죠. 되는 게 없다고 보는 게 맞는 것 같습니다. iOS는 아니지만 맥 OS의 샌드박스 기능이 궁금하신 분들은 &lt;a href=&quot;http://reverse.put.as/wp-content/uploads/2011/06/The-Apple-Sandbox-BHDC2011-Paper.pdf&quot;&gt;The Apple Sandbox&lt;/a&gt;를 같이 참고해 보시면 도움이 될 것 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;iOS 샌드박스를 보면서 느낀 점은 구글과는 정말 철학 자체가 다르다는 생각이었습니다. 구글의 안드로이드는 아래 크로미움 샌드박스 디자인 원칙에 나와 있는 것처럼 기존의 있는 것을 활용하자는 생각이 강합니다. 바퀴를 새로 만들지 말자는 입장이죠. 그래서 안드로이드도 권한 장난질로 얄팍하게 흉내낸 샌드박스 구조로 되어 있습니다. 물론 세세하게 TrustedBSD까지 올라가서 바퀴를 누가 만들었냐를 따지자는 것도 아니고, 옳다 그르다를 따지자는 것도, 좋다 나쁘다를 가리자는 것도 아닙니다. 그간 애플의 행보를 보자면 바퀴를 새로 만드는 것을 좋아하는 것처럼 느껴졌다는 이야깁니다. 적어도 저한테는요…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Design principles&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do not re-invent the wheel:&lt;/strong&gt; It is tempting to extend the OS kernel with a better security model. Don’t. Let the operating system apply its security to the objects it controls. On the other hand, it is OK to create application-level objects (abstractions) that have a custom security model.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;역주: 기술 부심 부리겠다고 바퀴 따위 새로 발명하지 말자.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://www.chromium.org/developers/design-documents/sandbox&quot;&gt;Sandbox, The Chromium Projects&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 280px; margin-bottom: 16px;&apos; data-url=&apos;./iOS_입문.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/9c24af181c00b4ac1e3a820c632a0972/2a48b/iOS_%EC%9E%85%EB%AC%B8.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAIAAACjcKk8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAADRUlEQVR42mXVx1IjQQwG4Hlf3oNnoIoD6QY3jrt7o4iLTTC2sU02mSUHB9J+0wIveHXo0qhbv6Rf6p5sampqbGxscnJydHR0fHx8enr6V5KJiYmhoaHh4eGRkRGfP5L8/JSBgYHBwcFsc3OzUqlYy+VytVqt1+vb29uNRmMzCQs7YyNJKFtbW8vLy2tra1mz2dzY2GB1Dsr+/v7x8XGtVmsmub29PTg4cJo9PEE/Pj6+J8m63W6r1Wq3290kz8/PdOvLywu7lc5OsXY6Hbv0tyQZYJCiUU5PT3d2di4uLqpJrq6uxNnb2+tZHh4e3r9I1gOmdD5Ftvf394Lc3d1JksLC07FvzqIdHh5GhUdHR/S+E33y9im5s5xnZmZ4csPT+vq6VHd3d1msR0noZ2dn/wNlCFxYWODDs5JEbSsrKzpRLBaXlpZWV1cLhYKOIBzK+fm5MAKoLgP/O8ni4qITfMpJuNGh6LZWgaCzCyMXxaou77ND1svLS/QCtnFzc/MnCSPOnp6eEG6LXVO08CNtkWdnZ+3h3DmsOqHC8L++voYIoq9J/2rmHEMnN1lYTR8irHNzc6VSqZBETAmaCJE0MndmQhWSFMMfYU7DUn8tCZ5i+ItJ2FUuqdzZADE5xMFqAwRu6KIhVi+l41i0TQmojrIz8+iQykUItn1yljZlfn4+LpAA6pdwkAIFR3naK0mUCt6qBECaBzfaTok7p7ToFl0LMsRKDIQTW0lAsPCXTuzaOjk5iauiHL38YDtuwnOS7qfEeMcA9031VyVTPTDZxpOibGwzBgTc19fXdpI+z9xZ32ToNM96Elgyj8qtCLfqRV8iuTPqFcxZtWKqk7M1XjLQ2LbylEK8Id/usz1zC14/4jFzK+SPJJ+mSkXiOwZdw3p05GkTNMatRGwMVoTVYRaV956x3gOWOytMx41b3MR4IoXtPclArSDi6aXHbOYPIGuMcTjT+ZgZQ+LcapL1JJQYYVvR6gxP8UqrB5CsojfRpHiMI22f8STHROTO4KWt5lISwWFBZI+fQZCPPJ9BBMvHxUAjVjRMDfDENLRCxZ+A7hmIKaS3kngzBM+dJWwkOMdzKZRV5BhvofTGIOhf9IVR/tHnv8G/QwCx0UBUAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;iOS    md 3&apos; title=&apos;&apos; src=&apos;/static/9c24af181c00b4ac1e3a820c632a0972/2a48b/iOS_%EC%9E%85%EB%AC%B8.md_3.png&apos; srcset=&apos;/static/9c24af181c00b4ac1e3a820c632a0972/08678/iOS_%EC%9E%85%EB%AC%B8.md_3.png 190w,
/static/9c24af181c00b4ac1e3a820c632a0972/2a48b/iOS_%EC%9E%85%EB%AC%B8.md_3.png 280w&apos; sizes=&apos;(max-width: 280px) 100vw, 280px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;XIGNCODE3의 역사가 iOS에서도 함께합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그닥 쉽지는 않았습니다. 맥을 새롭게 익히는 것도 Xcode에서 Objective-C++ 접착제 코드를 만드는 것도, BSD 시스템 콜을 익히는 것도요. BSD에서 시스템 프로그래밍을 해본 경험은 없고, 맥은 더더욱 새롭기에 이 생경한 시스템에 익숙해지는 것은 생각보다 쉽지 않았습니다. 물론 샌드박스도 한 몫 했지요. 여튼 그런 아주 험난한 과정을 거치긴 했지만 결국 우리가 안드로이드에서 사용했던 대다수 기법들이 거의 모두 아이폰에도 동일하게 적용할 수 있다는 사실을 확인했습니다. 이제 곧 XIGNCODE3 for iOS가 출시된다는 말이죠.&lt;/p&gt;
&lt;p&gt;이 글이 재앙이 될 프로그래머 분들을 위해서 초콜렛을 하나 준비했습니다. 애플이 굉장히 폐쇄적인 줄 알았는데 생각보다 거의 오픈 소스에 가깝더군요. BSD 라이선스라 굳이 그럴 필요도 없을 것 같은데 말입니다.&lt;/p&gt;
&lt;p&gt;xnu 커널 소스 코드&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://opensource.apple.com/source/xnu/xnu-2422.90.20/&quot;&gt;http://opensource.apple.com/source/xnu/xnu-2422.90.20/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;top 소스 코드&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://opensource.apple.com/source/top/top-89.1.2/&quot;&gt;http://opensource.apple.com/source/top/top-89.1.2/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ps 소스 코드&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://opensource.apple.com/source/adv_cmds/adv_cmds-153/ps/&quot;&gt;http://opensource.apple.com/source/adv_cmds/adv_cmds-153/ps/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./iOS_%EC%9E%85%EB%AC%B8.md_4.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;strong&gt;일단 폰부터 테스트 하구요. 패드는 그 다음에 하는걸로…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;애플빠는 아닙니다. 결코 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#6&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 566px; margin-bottom: 16px;&apos; data-url=&apos;./iOS_입문.md_5.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/563cd5ba5c32516412b550781cca2b24/7ef45/iOS_%EC%9E%85%EB%AC%B8.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 176.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAjCAYAAACU9ioYAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAJjElEQVR42iWWeVDU5xnHf51p2k4yMeYwXogHciOyHAJyLodcC8JyL+susMvuCiv3IiDLLSC34Mp9KCCggAEPYoxWDV4xmkNjTJp2kqbTdpK0iZNOx0zMfPqb6fvP+/7zPu/zPN/3+5lHkIV5ok70JW1vOKb6wxysaaZYm4aXhxuennZEhwXj6W6LW6A73jIZu/ZmcfhIO/qKWoyHW3n6j7/x9eef8fPTq9w6a0Hw9XLDpItnuMPMwkcPGRg8hlktxzswFPvIZPRpqdRqlGwOUuOaYSavxER5dSMTY2OsvHedC0NHmW2s5spkO12FaoQQfx/qyoq5evsD/vjwCXXFWQTtsEW6S8LLe8rwMp6hoXuCmtwickpbOGXpYGLAQmVhLk35WZiiQhjLN9Chi6FKGYDg4+5KYvQelIUHCYpJwFss1W67DRs2WvFiXA+rS+7hXjpHZNkYycXtTIgZLcyOo1enIdstIT3AA0PabiwNBur27EJY/9sXcLJ1RurrSWxkKBJ3CY5WG9n2xjpeU1lYnW5hnX6K1QWLxJV1MmDpJC09kXxjDqa8fSyd6GBx6jCH8tNpTklAiF+/CW1QOPuV6URHhCCPiSbbw5+wzVvxyTKxU9vGWkULW2Q5ePvuRmM4QHpOLiqVipjwMMyqeFqLdHjZWKHbl4ZgCAplKFVBRXY+IVHpJMQqMIaHovG2xlyQSFuDURTBQKNZgSoplLCIRDKSUoiJiEDq6ky2gzXhG14n9LUXibLZiBC9xZpKeRS62EDyNL4og13RxEQS6WFLcW4Kf38yw9fvjzLbU8XxehOtpjxG+7pRS/1o9nWhz/4NCreu43SKJ00JuxFCE7JwisknOlJOcWUuMWKWIeI5OCSOqCAfZnsPcGO6kaa8BI4211CmSkC/L4OUzdvIsrUl0suTgj0ezOUFURDpgzBz/c/EaVpIk0aSFZNGUsUkdc3ldLRW4bkrgPjoWBaGzPz1/X7Oz4+hUyXhL/5diYMHvm4+BDo7IHNxIH6HCzHbbRFydHJadErqs9QUKZSYVGn0nThIw7BRVDONkiIzxTlaaisL0CcHUJ4dgiJSgu369fjbb0XpYU2qhxWZga4kSOwQjuwvoS4lhNb9ckz7U2g0elNXLeHAAUec3f1RqAz4BMeyzsaHtRu3s93Jk60Ou3F66QWCNr+K0tuOMn8JRf5uRDhaI5zvGWBMfH2+vZyhUjn1yRKaYt0o8LVh3ZoNNOrTCPfZif22rTjb2xESEIgxW4edgyOBosu6lf48PJrC8aRdBAf7I9y8XMNwWx7L872c7Tdz6WQDKxdaODfbib1UjyZLi7unJxJHB+y3bECjUrJ4/hYeAXuQStxZyPXmh/tGvmyTkum3A2H5ZAHj3RmMN6QyU6Hm/EAN1cYUWkrVbJRk4BTXwDbR09a+GtZ7ZGHlGMSq1zYjcfMVredMcZgbncnejGT6kxkqQbi+0Mu3X33KyvQQZ7QpWJRJmPbtZbjF/Gucvu65TNWAPKMNQ9l5yupnCEluRZJcRHRUBJlhuwh3d8TPwxk/NycCnO0RGrLDGS5LpC/HmzmdPTVBdigSfDEa1c+7Bt56dvdMO8tDfXyyPMnK2RNUGaqZfPsa+0Sb7XZx5qBsMwOxr1DtvgrZ6wLClbOnOX1ikLuX57j3zhnmFqYYnhpnaXn5+c0j/c/erhX7Oabj/eUYLk71MlvZwJO3+qlVJhOx043SaC+q/NeTtXMTCi8nhH99/z3p2kL6z33M0tlLnBkY4trVazz/+Zfnd08tPpvsPMXcsUrODCUy2dtEY9FJagqaOS36fU4Ea49RIyocRYU0gPFDRQifP/mMPWGRyORm+ocWePzoC3766Sf+/eMPz985d/LnM6dOMDQyjd5YRkGRhsqKPFTZKualUnoLdBw3ZXNon56VdhVTRXKERw8/or2xnmPdfbT1DPKc/68fnz7lQO5+qmtrGZuYJ0+toqSwiGwxmLGgkMbgEGY1OSJcFbg6BVKfEU2rOhqhONcgwnUX+9UZJEn9OdFcyd2lMa7Mz6AXLzRmplCYmYkuPYnq/fs5nKdDp9cjd/HEkqJn1GCgUx5KfpSMw0mBCIEOouTbt2O/+gU0QTZiT/w5c0jJUJaS2jwFk23VjFraaa6t5FhdAQPdtfTny7nk7MPUKkcW3N3I8HUnJ9yPXq1I7ABnCRFuDuz1eBOF3yY0EZtI9femVZXDcbWXWEYQrQo/SsK3UBFqTXvqDubzgnlvzVba7d8Uufkyr296hdLkKIZigxBc/yCwdtUfcLaywnXNGgLdPSjV6nFfvxY3O2v8PVzY5eqIVpFIQ2MzDb19qNMSSfd4hbiIl4hIcCfVx4Zz5Qa6PaUInQ1ZRMan4JNTgqs6j5SqI9R19aHMTsPO2Ql7EQI7ffwobGxhuH+Yytx8HP0C2bLtVfZG7MQUEcm0owvm4EhcNjojHL//BRcvLVE/eA7tyA2M976mq6uC7OpK3CLkIlEC8QiRIU3WkKvPpbzAgPZQFV5TVwifeYB5+l1SO8+ScGwG/8Y+hKbREUbL9lIcG0FFXj2lF+5T1dODoTCH7WK5Wx3sCI1PJioxgxhlJqFyJdLYFBIf/BPdN79iOH+H8tFBKmbmyH70X4TC474UGXeQV7cXQ203CcWVjE+28vhSM12qKPqzZdy/UE/nrU9Ju/wDxot3MN/4Cx0fP6P+q1+5NjXBTHkzI8OnaPjmFwTruCi2RsWyW5GCVByE7MN1uO0pIFmWQIsylKPFch6fO8TJDz/B0tHKsSPiHHT7PjNLH3BlcIT33prixHgPp2ZqWbr7CEF4I43IoEKaynupLj2CKqOQ31klsMY6jsHOGi5O1HN3LIv5D1aY7rYwnBxO08J1BrosLOdlUqdPoqdQRV26FI1MtN5vNsiJi9awuHCWc0tXaTXXssZGxqub48hSaemsL2JhpJwrNwe4fOc013q1XLzQLQZRM14j52RREn+abuDzG+PcnVcg/N4qCb/UNjSHb2A4dBm9aZQ3XbS8uDacqsxwLAfTaa0ooqpcTVV9CZdvLvDgQhPtQb7cHq3ku8ulfFrsyC8rZv7z5RWEwcFJSkoa0Ji6MHdPk7jPRLLCSJGpjGsLjdyZq+SWJZDFHiMVB7SMLC7zztIAE4oQbh/N4puzCpY6bHhyIZ3v7r2LcPncLNenhrm9coHF2T4WJ/vF/QSnJnr55MEK3315jcen4/n2poWlkV4GmnKZfruRmIJQse9RmLRRyGWBxKZH8OFnD/kfS+I7yTF9WAgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;iOS    md 5&apos; title=&apos;&apos; src=&apos;/static/563cd5ba5c32516412b550781cca2b24/7ef45/iOS_%EC%9E%85%EB%AC%B8.md_5.png&apos; srcset=&apos;/static/563cd5ba5c32516412b550781cca2b24/08678/iOS_%EC%9E%85%EB%AC%B8.md_5.png 190w,
/static/563cd5ba5c32516412b550781cca2b24/2edd7/iOS_%EC%9E%85%EB%AC%B8.md_5.png 380w,
/static/563cd5ba5c32516412b550781cca2b24/7ef45/iOS_%EC%9E%85%EB%AC%B8.md_5.png 566w&apos; sizes=&apos;(max-width: 566px) 100vw, 566px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;iOS 버전도 준비 중이신가요? 그럼 더더욱 &lt;a href=&quot;http://www.wellbia.com&quot;&gt;XIGNCODE3&lt;/a&gt;죠.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;느낌아니까… ㅋ~&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 벌써 10년…]]></title><description><![CDATA[#0 2004년 8월 2…]]></description><link>https://jiniya.net/wp/archives/13369</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13369</guid><pubDate>Sat, 31 May 2014 23:59:38 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2004년 8월 28일. 병역특례의 끝이 한달여 남짓 남은 그때. 학교 선배가 서울을 왔다며 연락이 왔다. 취직이 잘 안 돼 고민하던 형이었는데 떡하니 대기업엘 붙었다는 이야기를 했다. 자축을 하자며 들떠 있던 우리는 만나서 몇 마디 하다가는 그 분을 보러 가자는 이야기를 했다. 계획도 없었고, 약속도 없었다. 그렇게 고속터미널에서는 대전행 버스를 탔다. 목적지는 KAIST. 우리의 정신적 지주였던 선배가 있던 곳이었다.&lt;/p&gt;
&lt;p&gt;깜짝 놀래켜 주자며 출동한 우리는 금새 문제에 봉착했다. KAIST를 왔지만 정작 선배가 어느 건물에서 공부하는지도, 어디에 있는지도 몰랐던 것이다. 물어물어 선배의 연구실이 있는 곳을 찾았지만 문은 잠겨 있고 선배는 연락이 닿질 않았다. 서울에서 여기까지 왔는데 정말 아스트랄한 상황. 하지만 궁하면 통한다 했던가 겨우겨우 선배 본가의 전화 번호를 알아 내서는 연락을 했다. 어머니께서 받으셨는데 집에도 연락을 잘 하지는 않는데 아마 출강 갔을 거라는 이야기를 했다. 그리고는 지금쯤 도착할거라는 이야기를 덧붙였다. 여기까지 왔는데 어쩔 수 없는 노릇. 기다려 보기로 했다. 제법 지루할만큼 시간이 지났을 때였다. 마치 TV는 사랑을 싣고에 나오는 것처럼 멀리서 선배가 걸어오는 모습을 보게 되었다. 그렇게 기적처럼 우리는 KAIST에서 만났다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;우리가 찾아간 선배는 학교에서 기인으로 통하는 형이었다. 기계과로 입학해서는 전자과를 거쳐 컴공까지 왔다. 학교 다닐때 전산실에서 우연히 떠오른 아이디어를 ACM에 제출했는데 그해 최우수 논문상을 받았다. 형은 컴공과에 와서도 취미삼아 다른과에서 개설한 양자역학 수업을 들었다. 난 그당시 양자역학이 그렇게 어려운 학문인지도 몰랐다. 가난한 고학생임에도 IEEE를 정기 구독했었다. 도서관에서 무료로 볼 수 있는데도 말이다. IEEE를 아이트리플이라고 읽는다는 것도 형이 가르쳐줬었다 ㅋㅋ~ GRE를 치러 간다는 사람이 팔짱에는 능률보카를 끼고 있었고, 더 황당한 건 그러고도 GRE에서 상당히 높은 점수를 받았다는 사실이다. 시스템 프로그래밍 수업을 같이 들을 때였다. 내가 온갖 문자열 처리 함수로 SIC/XE 어셈블러를 주먹구구식으로 만들고 있을 때 형은 파스 트리라는 신세계를 나에게 보여줬었다. 형이 테이블에 명령어를 추가하자 마법같이 명령어들이 번역됐다.&lt;/p&gt;
&lt;p&gt;컴공과 교수님 한분은 형에게 네 정체가 뭐냐는 질문을 했었고, 다른 교수님은 카멜레온 같다는 이야기를 했었다. 가난했지만 형은 자기 밥값을 털어서는 술값으로 용돈을 다 날려 책을 못사는 후배 책값을 대주는 그런 사람이었다. 말수는 적었지만 필요할때면 후배들에게 &lt;a href=&quot;http://jiniya.net/tt/592&quot;&gt;정말 멋진 이야기&lt;/a&gt;들을 한번씩 해주기도 했었다. 구도에서 공부를 할때면 종종 예쁜 여학생들이 같이 공부하자며 형에게 선물이며 추파를 던지곤 했는데 형은 절대로 넘어가는 법이 없었다. 형의 첫사랑은 고등학교 때였는데 그 여학생이 수녀가 됐다는 진짜 드라마 같은 이야기만 반복했다. 공부하는 머신이라고 놀려대면 형은 태연하게 그랬다. 대학교 1학년때 술마시고 모텔에서 수영한 적이 있었다고…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아무 연락도 없이 찾아온 우리가 귀찮을수도 있을텐데 형은 싫은 내색 하나 없이 KAIST 구석구석을 구경시켜 주었다. 구경하면서 드라마 카이스트와는 정말 다르구나 하는 생각만 연신 하고 있었다. 형은 그 당시 KAIST에서 석사 과정으로 안테나 공부를 하고 있었다. 여기 아이들은 과고 출신이라 빠르게 졸업한 애들이 많아서 어리고 똑똑한 친구가 정말 많다는 이야기를 했다. 우리가 우스개소리로 걔들이 똑똑하긴 한데 형이 1등이죠? 했더니, 형은 아주 해맑은 얼굴로 그렇긴 하다고 했다. 진짜 말 그대로 괴짜였고, 기인이었다.&lt;/p&gt;
&lt;p&gt;그날 우리는 KAIST를 돌아다니며 정말 많은 이야기를 했었다. 그도 그럴것이 같이 간 형은 대기업에 입사해서는 이제 사회에 첫 진출을 하는터라 풍운의 꿈을 잔뜩 가지고 있었고, 난 지긋지긋한 병특이 끝나고 학교로 복학할 단꿈에 젖어 있었다. 안테나를 공부하던 선배는 얼른 석사를 마치고 미국으로 유학갈 꿈에 부풀어 있었다. 그렇게 20대의 우리는 모든 걸 가진듯 했고, 모든 걸 가질 수 있을 것 같다는 포부에 가득차 있었다. 이런 저런 이야기를 하다가 KAIST 어딘가에서 각자 독사진을 찍어주며 10년 후에는 뭘 하고 있을지 말해보자는 이야기를 했었다. 그리고 10년 후에 여기서 다시 보자며… (손발이 오그라드는 ㅋㅋㅋ)&lt;/p&gt;
&lt;p&gt;나름 장난기 충만해서는, 또 나름 정말 진지하게 우리는 이야기를 했다. 취직한 형은 입사한 그 회사의 부사장이 되겠다고 했다. 왜 사장이 아니라 부사장인지는 좀 의문이다. 아마 그 당시에 사장은 너무 멀고 부사장 정도는 될 수 있다고 자신했던 것 같다. 난 제법 구체적이었는데 20명 정도 규모의 회사에 20-30억 매출하는 그런 벤처를 창업해서 CTO를 하겠다는 이야기를 했다. 내 이야기도 좀 웃긴데 창업을 하겠다고는 CEO가 아닌 CTO를 지목했다는 점이다. 우리의 정신적 지주였던 KAIST 선배는 ARM과 같은 회사를 창업하겠다는 이야기를 했다. 형은 ARM이 칩 설계만 하고 제조를 하지 않는 점과 그 일이 굉장한 고부가가치 사업이라는 점에 집중했었다. 형이 계속 해오던 일도 칩설계 쪽이라 뭔가 잘 맞는 것 같기도 했다. 근데 선배의 이야기에서도 의문인게 칩 설계하면 INTEL을 떠올릴법 한데 ARM을 지목했다는 점이다. 물론 지금에 와서는 ARM이 INTEL을 견제할정도로 컸지만 그 당시는 잘나가는 변방의 벤처 정도였다.&lt;/p&gt;
&lt;p&gt;그렇다. 여기엔 한가지 공통점이 있었다. 우리는 모두 약간씩 마이너한 근성을 가지고 있었다는 점이다. 그래서 죽이 잘 맞았는지도 모를일이다. 어쨌든 2004년 8월 28일은 다소 그런 말도 안되는 꿈들을 이야기하고, 서로 그 정도는 할 수 있을거라며 다독거려주는 그런 따뜻한 여름 날이었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;얼마 전 그때 같이 KAIST로 무작정 떠났던 학교 선배를 만났다. 둘이 마주 앉아서는 양꼬치를 뜯으며 이런 저런 이야기를 한다. 형은 지금까지 그때 입사한 회사를 다니고 있는데 지금은 다소 대기업에 회의적인 입장이 되었다. 거기다 최근에는 고강도의 구조조정이 시작되서 약간 사내 분위기가 살벌하다는 이야기를 했다. 요즘엔 첼로 연주에 한창 빠져 있는데 조금 있으면 연주회를 한다고 했다. 초대할테니 꼭 오라는 말을 덧붙였다. 그런 온갖 이야기 끝에 KAIST 선배 이야기가 또 올라왔다. 마주 앉은 형이 긁는다. 미쿡으로 가자고, 그때처럼 가서 놀래켜 주자고 말이다. 선배의 조언을 들으면 앞으로 10년은 또 문제 없이 헤쳐나갈 수 있을 것 같다고 했다. 그러고는 내가 가겠다면 자기는 갈 수 있다는 최후의 허세 카드를 작렬한다. 나도 질 수 없기에 알겠다고, 내가 연락처를 수소문 해보겠다며, 연락되면 바로 떠나자고 맞불을 놓았다.&lt;/p&gt;
&lt;p&gt;헤어지고 집에 돌아와서는 구글에다 KAIST 선배의 영문 이름을 입력한다. MIT 연구소 페이지로 연결됐다. 거기에 형은 내가 아는 메일 주소로 기재돼 있었다. 2-3년 전 연락이 끊긴 그 메일 주소. 다시 메일을 보내볼까? 아니면 연구소에 형의 근황을 물어볼까? 하는 생각을 하다 그냥 관두기로 했다. 메일을 제대로 쓸 수 있는 정신이 아니었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/gMbqagfXSWw?si=LB1-hSAPwc8StGVC&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt;   &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;진짜 말하는대로, 생각하는대로 되는게 인생이고 꿈이란 사실&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;10년 사이 내가 배운 한 가지&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;양꼬치 사건은 한때 호기로 남아 기억의 저편으로 넘어가고 있을 무렵이었다. 어젠가 그제 코드 여기저기를 수정하다 정말 오래된 코드가 Visual Studio에 로딩됐다. 바이너리를 변환하는 유틸리티 코드였다. 막내 녀석이 최근 해커들이 바이너리 파일에 있는 익스포트 이름과 디버그 정보에 있는 pdb 경로로 꿀을 빨고 있다는 제보를 했던 터라 그 부분을 지워버리는 코드를 추가하기 위해서 프로젝트를 열었던 것이다. 코드 수정 작업은 간단했다. 수정하고 테스트 하고 커밋을 하려는데 그 파일에 주석 처리된 함수가 마음에 걸렸다. 지워버릴까 라는 생각과 놔두자는 생각 사이의 갈등이었다. 아주 오래된 코드였지만 그때 기억이 선명하게 났기 때문이었다. 그날이 언제였는지 궁금해서 블로그를 뒤졌더니 날짜가 나왔다. &lt;a href=&quot;http://jiniya.net/tt/738&quot;&gt;2008년 11월 19일&lt;/a&gt;. 그 주석 처리된 코드는 패딩을 제거하는 코드였다. 압축 효율이 떨어져서는 만들어놓고 주석 처리를 해둔 터였다. 시간이 참 많이 흘렀다는 감상에 잠시 젖었다 결국은 그 코드를 제거하지 않고 커밋했다.&lt;/p&gt;
&lt;p&gt;몇년이 지났는지를 머리속으로 곰곰 헤아리다 다시 그 KAIST의 밤이 떠올랐다. 10년이 지났는지 안 지났는지가 궁금해진 것이다. 2004년 인거 같기도 하고 2003년인거 같기도 하고 그랬다. 그러다 그날 찍은 사진의 EXIF 정보에서 정확한 날짜와 시간을 알아냈다. 2004-08-28 21:06. 그랬다. 올해가 꼭 10년이 되는 해였다.&lt;/p&gt;
&lt;p&gt;야심한 밤에 10년 전 어린 내가 꾸었던 꿈을 마주한다. 아마 그때는 벤처, CTO 이런 단어에 허세가 가득차 있었던 건 아닐까라는 생각에 웃음이 난다. 그리곤 이내 현재 상황과 그 꿈을 오버랩 시켜본다. 2006년 9월에 창업한 회사의 CTO가 되었고, 회사 규모도 그때 내가 예측했던 범주에 다가가고 있다. 이제는 사실 그 꿈이 불가능보다는 가능이 훨씬 더 쉬운 상황이 돼 버렸구나 하는 느낌이 들었다. 신기한 사실은 그 꿈을 그때 이후로 상기한 적이 거의 없었는데 현재 상황이 그때 내가 말한 상황과 얼추 비슷한 시츄에이션이 됐다는 점이다. 시크릿의 끌어당김의 법칙 같은 말들을 개소리로 치부하면서 사는 입장인데 그 순간 만큼은 진짜 그런게 있는것도 아닐까라는 느낌이 잠시 들었다.&lt;/p&gt;
&lt;p&gt;형들도 그날 이야기들을 기억하고 있을지를 추측해본다. 그리곤 이내 우리가 진짜 다시 10년 만에 재회한다면 이번엔 무슨 꿈을 말할지를 곰곰 떠올려본다. 내가 지난 10년간 배운게 있다면 진짜 생각하는대로 말하는대로 이루어진다는 것이다. 그래서 감당하기 힘들만큼 아주 큰 꿈을 말할지 아니면 그저 소박한 꿈을 말하는 것이 좋을지가 고민됐다. 어떤 걸 말하는게 좋을지 정하진 못했지만 진짜 신중하게 말해야 겠다는 다짐은 분명히 했다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;꿈이 없는 시대라고 한다. 이제 더 이상 예전 세대의 영광은 없을 거라는 말들을 한다. 하지만 피끓는 청춘들은 지금 이 순간에도 어디에선가 우리가 10년전 그랬던 것처럼 미래를 꿈꾸며 이런 저런 이야기를 하고 있을 것 같다. 그런 청춘들에게 꼭 하나 보여주고 싶은게 있다. 회사를 같이 창업해서 지금 대표를 하고 있는 형이 몇 해전 우리가 아주 힘든 시기를 지나고 있을 때 메일로 보내준 &lt;a href=&quot;http://www.sadjunu.com/zboard/zboard.php?id=cartoon&amp;#x26;page=6&amp;#x26;sn1=&amp;#x26;divpage=1&amp;#x26;sn=off&amp;#x26;ss=on&amp;#x26;sc=on&amp;#x26;select_arrange=headnum&amp;#x26;desc=desc&amp;#x26;no=150&quot;&gt;“‘포기[抛棄]’에 관한 단상[斷想] …”&lt;/a&gt; 이라는 웹툰이다. 그 웹툰을 보면서 우린 쪽팔리지 말자는 이야기를 했었다.&lt;/p&gt;
&lt;p&gt;모든 꿈이 그렇겠지만 이루어 나가는 과정은 그리 순탄하지도 않고 녹록하지도 않을 수 밖에 없다. 그 험난한 과정을 버티기 위해서 가장 먼저 구비해야 하는 아이템이 있다면 아마 ‘인내’가 아닐까라는 생각을 해본다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#6&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;중요한 신제품을 만들어내는 것은 대개 시간이 걸리는 일이다. 프렌드피드는 6년 전의 지메일이 그랬던 것처럼 지속적인 변화와 개선을 필요로 한다. 프렌드피드는 많은 가능성을 보여주고 있지만 아직은 “성장하고 있는 중”이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;내가 기대하는 바는 커다란 성공이라는 것이 여러 해에 걸친 노력을 요구하는 일이며, 이러한 원칙에 반하는 예는 (아직 제대로 된 수입을 올리지 못하고 있는 유튜브 정도를 제외하면) 거의 없다는 사실이다. 페이스북은 매우 빠르게 성장했지만 사실은 벌써 5년 정도가 지났다. 래리와 세르게이는 구글을 1996년에 시작했는데, 내가 1999년부터 구글에서 근무하기 시작했을 때만 해도 구글을 아는 사람은 별로 없었다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;하룻밤 사이에 성공을 거둔다는 개념은 상당히 왜곡된 생각이며, 심지어 위험하기까지 하다. 뭔가 새로운 것을 시작한다면 멀고 긴 여행을 염두에 둬야 한다. 물론 굼뜨게 행동하는 것을 변명하려는 것은 아니다. 그와 반대로 매우 빠르게 움직여야 한다. 그렇게 하지 않으면 그것은 너무나 먼 장거리 여행이라서 목적지에 도달하지 못할 수도 있다! 근검절약 정신이 중요한 것도 같은 이유에서다. 산의 중턱에 도달했을 때 먹을 것이 다 떨어져서 굶어죽기를 바라는 사람은 아무도 없기 때문이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://paulbuchheit.blogspot.kr/2009/01/overnight-success-takes-long-time.html&quot;&gt;Overnight success takes a long time, Paul Buchheit&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; margin-bottom: 16px;&apos; data-url=&apos;./벌써_10년.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fefbe8c9640a3950a04a32796e9e76f4/d9f49/%EB%B2%8C%EC%8D%A8_10%EB%85%84.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 152.63157894736844%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAfCAIAAABoLHqZAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAGlElEQVR42kVV2VcaaRYvFguoKgqKvUARQQi4sLggRBREjKJJXJLuRNExKihQLEVVsSkISTRJnxg1mz1mOWbp03N6zszDvPfTnDn91g/90E/zME/zf8yHzpn5Hqrqfuf7/e69v3u/WxCfzxdcLiFYAkHL4AvgNrBaG7Cw9W4Zl/tCfuvZQvBbL+gKfAkUYChmtzlIUi9oAWAYFl1ytIEzwLhiF155usRD/3UrEKoUKoe979bc7dhKzO5wIAgqFiMGsiMcCnd1mSEIgi+J/k/BF0BXTDar3e8LuFwDq8srjxsPs1RuazOxsrJ23Te2NH8nQ+WcLg8IERyGr/IRtChA2DxcRowFJkLjk65+z+pyrLG726ztvzx9fXZ2vhXfvrv0DeCiqNzU1DSKYjweXyQSXaXZylmt0Q0P+iYnpjyugbXYHxp7tYeN5tHzFxcXn968fbOxvlHI0ulkOpvJ378X02pJHo935R/i8/jmLot3yBeZvOF0ehJbiceN5sHjxyfHJx8+Xrx7/z5DZUtMMZfJAf8ZKr++HjdbrMAtDLcBIaD+PicA34jMDHiGFxfv0PnCo4ePTk9Oz999eP/xIzCLbKmQY+gsTaWzqWQ2EplpE8L/A7uv+wKT4Rse19BqbC2VpNYfbB4ePvn06fPXH76yDFMtVViaKzJFOsvkMkxseQ3HZa2weXx+b59rbDQ4MT4xNOClUumD5sNqZffpk2cvjk+OT0/oPF0qlirFcrVY5QpFOsfuJNIatbYlGGgDV797cuIGwHuHRnYS2/Xdvf1a/eTk9I/vPzw/fpFMJhkaRF4sFrgyW2bzXD5T6DKZgdKQTCZ3uwYmQpFgYMLv9QPP+7VatVx5+uzZxecvX3/4whRotkBXSyWOLnA0x+ZZhubcLo+Ax4MM+vYB99DC3EJkYmo8EKTSFKhTba92eHD48tXrd+/O67U6W2B2S+USw5ZYrpCjgX6h8RAf4kEggFH/2HQkOj4aCvjHQKma9UZ9r370/Oj8/Pzk5atGo8kx3G6lms/m6Fy+BS5wc9FZ0N6QzWoLjAb9I4GJYOT2rQUqRQFws9E8fnH86eLixz/9uLtb29+rU+nU3K25SrFSLBTz2cLdpbuoBGmBw6Epv3d09f7q1kacSqb3d+tPDg7fvn1zBPBfvlQqVYBJpZLBcJClWSbP0hl660FcSRCQw+EAOWvVOnCrguPhxNb2dwdPQ4HQ7MwsaM+f/vxTvbafSWXobD62GisXixxQLVvIpDPtJAlJUSm4aCJYpCIIg0YhlyIKmRwRI2qlKr4Vr7WUr1ZK1eZ+o8wWC7k8k2eS8RSg67XaILFIhCIoIsa0auXSzHhm89upcY/b0e7u7TbqVVqFrNdu93lH1lZiRZYrc6UCzSR3qPhmwuv2QIhEgooRHMUQRIJKJAad1mw0mNq1U0H/wszo6IC5z2rQEBJbl5Gl6TLHZals64aks+FgCIDFOILJUQzHEAyViEUwoEDEEpCIqA2WSaUaJUGq5Q6bmWPYaqXM5GlwyeOJ7cW5WUiKoDJUqsABtuUZzB4+BIER0yZsAxkRclyjUgJTJpOFQ6GV+/d3tnf2QbfHd+7OL0CETKIlpFIJqlbgHRrM5TBxyZuLEVd0zNmuJtQKuQzHlHJUgaM8CDRka/L4zJ0+g95A6qDY3KSjs9dvMTW2ojVq/qi0/tvf//bqu73z48Z02E9qlc4+x2xkcNDZqVXKTSSQECfkCILAYBpDm7PTcgnZq9O4OzXXjO2uDpVC0iaGRToFoVMrO/U6cwdJyDERLFDIMbUSBx9KQiLHgVYwNNht6DGSeoVCAPGGrlmt7R1OW8/Og7hRgSuliArHgYhgTAvbBIgYVspQNYHbTSajTqWSoVB00LM8PeuydOtwmRbHFZjUYbXfic5c0yoRGO412+dHbN0aBJeI5FJQT4kcQx0mi7XDAAoI7cdjdlKnxTADodLKCAwW4bDIQEgtWlXUiSemHamwecyEWbREfxc5aNGPWMlAT4dJp2pXK6CXmW8yN6+vBV2TLnOgp3vO25ePum4P9AxbTNN9ZNCu7+vQOjs0PjMZ7TNuBGyVm/3UpEMKC6UiIXSWnaemBo43Zv7584fPjxJnxXu//uVZMza1OtS1NmJd9Xav+7rXvOblIfOSu2varg+ZyX5S2fp9gbqd7UTpueF//PXi37//cpq5+Toz+69ff/6+nFjxGAFmdbhzedB4z21c7G+f7dFHbOSYRec3a0kcEfCg/wB++sHLTTxatgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;   10  md 1&apos; title=&apos;&apos; src=&apos;/static/fefbe8c9640a3950a04a32796e9e76f4/d9f49/%EB%B2%8C%EC%8D%A8_10%EB%85%84.md_1.png&apos; srcset=&apos;/static/fefbe8c9640a3950a04a32796e9e76f4/08678/%EB%B2%8C%EC%8D%A8_10%EB%85%84.md_1.png 190w,
/static/fefbe8c9640a3950a04a32796e9e76f4/2edd7/%EB%B2%8C%EC%8D%A8_10%EB%85%84.md_1.png 380w,
/static/fefbe8c9640a3950a04a32796e9e76f4/d9f49/%EB%B2%8C%EC%8D%A8_10%EB%85%84.md_1.png 400w&apos; sizes=&apos;(max-width: 400px) 100vw, 400px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;불이 켜지지 않는다고 조급해 할 필요는 없다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;**모든 배선이 끝나면 불은 마법처럼 한 순간에 들어온다.**&lt;strong&gt;포기하지 않고 한땀 한땀 열심히 배선을 해야 하는 이유가 거기에 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[[소고] 증명 하기…]]></title><description><![CDATA[#0 올초에 경리 면접을 볼 때였다. 대표님과 둘이 회의실에 앉았다. 2…]]></description><link>https://jiniya.net/wp/archives/13258</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13258</guid><pubDate>Mon, 26 May 2014 23:59:37 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;올초에 경리 면접을 볼 때였다. 대표님과 둘이 회의실에 앉았다. 20대 중반의 대학을 갓 졸업한 파릇파릇한 여학생이 왔다. 면접 전에 이력서를 잠깐 훓어보았는데 굉장히 특이한 이력의 소유자였다. 경리를 채용하는데 무려 국립대학교 컴퓨터 공학과를 우수한 성적으로(?!) 졸업한 친구가 지원한 것이었다. 신기하다는 생각과 함께 면접을 시작했다. 사실 경리를 뽑는데 내가 물어볼 만한 질문이 크게 많지는 않다. 내가 경리 직원이 해야 하는 업무에 대해서 잘 아는 것도 아니고 추후에 업무 지시를 할 일이 많지도 않기 때문이다. 어떤 친구인지 보는 정도가 전부다. 3가지 정도 질문을 했던 것 같다. 우리 회사가 뭐하는 회사인지 아는지, 좋아하는 게임이 있는지, 컴퓨터 공학과를 졸업했는데 경리를 지원한 계기가 뭐냐 같은 것들…&lt;/p&gt;
&lt;p&gt;그렇게 면접이 이어지는데 순간 이 모든 상황이 너무 우습다는 생각이 들었다. 왜냐하면 국립대학교 컴퓨터 공학과를 우수한 성적으로 졸업하고, 해외 봉사 활동을 했으며, 토익 성적도 나쁘지 않고, 다른 곳에서 인턴 경험까지 있는 이 친구가 조그만 업체의 연봉도 그다지 높지 않은 경리 자리를 꿰차기 위해서 자신의 이력서에 비어 있는 시간 동안에는 무엇을 했는지, 왜 그런 선택을 했는지를 일일이 답하고 있었기 때문이다. 오버스펙도 이런 오버스펙이 없을텐데. 그 친구는 그 자리에 앉아서는 나름 최선을 다해서 자신의 빈틈을 답변을 통해서 메우고 있었던 것이다.&lt;/p&gt;
&lt;p&gt;그 상황이 더욱 아이러니하게 느껴졌던 이유는 그 친구를 선택할지 말지 고민하며 구름위의 심판자처럼 앉아 있는 두 사람이 불과 2-3시간 전에는 그다지 상황도 좋지 않은 중견기업 하청 업체 앞에서 똑같은 과정을 거치고 있었다는 점이다. 물론 그때는 그 두명이 온갖 것들에 대한 답변을 해주면서 자신들의 존재를 온몸으로 증명해야 하는 입장이었다. 그냥 그런 상황 자체가 너무 우습고 어처구니 없게 느껴졌다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;10년 전이었다. 부산에서 병특 자리를 알아보던 나는 부산에서 그나마 괜찮은 GIS 업체 면접실에 앉아 있었다. 임원 중에 포공 출신이 있었는지 면접 대기실엔 유달리 포공 학생들이 많았다. 다들 뭘 그리도 많이 출력해 왔는지 마치 그 많은 서류 더미들이 자신의 존재를 증명해 주기라도 하듯 신주단지 모시듯이 살펴보며 읽고 또 읽고, 외우고 또 외우고 있었다. 그리곤 종이 한 장 없이 뻘쭘하게 앉아 있는 나에게 무슨 프로젝트에 참여해 봤냐는 질문을 했다. 나는 참여해 본 프로젝트가 없다고 했다. 그러다 내 차례가 와서는 면접실로 이동했다. 면접실 그 자리… 나는 80만원 급여의 병특 자리를 얻기 위해 지난 여름 방학에 내가 캐나다 스탠리 파크에서 무얼 했는지까지 이야기를 해야 했다. 최종적으로 한명 뽑는 그 자리에 뽑혔지만, 일주일 정도 다니다 때려쳤다. 아직도 빈정거리는 말투로 질문을 하던 면접관의 인상이 선하다.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 562px; margin-bottom: 16px;&apos; data-url=&apos;./증명_하기.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2fe49c1eca339256fa2e2f02353ad541/a4f00/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 13.684210526315791%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAmklEQVR42hXJ2xaCIBAAQP//5zK0Tveig0jqkhFxcd21mtcp1lcoL/3F+NamBlJrQ/dK4PN9cNt7X8nubEZ458f4Lw1JDbG+QXWDWtrCDKPpn86nCZcJ6Spxf2BR80rMmx2KDYp6LgUfT6wNpkwZGV6+7WxvXRHCJ4aAODHTDyICkJSkFGlNTcNKsW7IuV/NRPOyUM7J+3eM4QskDKdaS+fI4wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 0&apos; title=&apos;&apos; src=&apos;/static/2fe49c1eca339256fa2e2f02353ad541/a4f00/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/2fe49c1eca339256fa2e2f02353ad541/08678/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_0.png 190w,
/static/2fe49c1eca339256fa2e2f02353ad541/2edd7/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_0.png 380w,
/static/2fe49c1eca339256fa2e2f02353ad541/a4f00/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_0.png 562w&apos; sizes=&apos;(max-width: 562px) 100vw, 562px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;글쓰다 궁금해서 찾아봤더니 그 당시 그래도 나름 부산에서 잘 나가던 그 업체, 망했다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;이후에 이직을 하면서 면접을 서너 번 정도 더 볼 기회가 있었다. 그 모든 면접이 전부 그렇게 유쾌한 경험은 아니었다. 자신의 존재를 스스로 증명해야 하는 일이 원래 다 그렇게 비루하고 구차한 법이다. 그러면서 자연스레 나중엔 내가 증명을 하는 입장이 아닌 시키는 입장으로 살아야겠다는 생각을 했다. 당시엔 적어도 그게 편해 보였다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;대학교 4학년 여름 방학. 지인들 덕에 무리에 끼여서 창업을 할 수 있는 기회가 생겼다. 난 그때까지만해도 적어도 이 일이 나를 증명하는 입장에서 증명을 시키는 입장으로 바꿔줄거라 믿었다. 인생을 온통 핑크빛으로 낙관하는 풋내기 20대였던 나는 아무 생각 없이 그렇게 창업에 동참했다.&lt;/p&gt;
&lt;p&gt;하지만 사업을 시작한다는 것은 그 어떤 일보다 더 많은 증명을 나에게 요구했다. 스타트업이 제품을 만든다는 자체가 정말 상상도 못할 온갖 증명을 다해야 하는 일이란 걸 미처 몰랐던 것이다. 특히나 B2B 형태의 사업은 그 정도가 더 심하다. 넌더리 날 정도로 많은 증명을 필요로 한다. 이 제품이 실질적으로 효과가 있는지, 안정적인지 등에 관한 건 증명 축에도 끼지 못한다. 3-4년 전까지만 해도 내가 가장 빈번하게 그리고 가장 충격적으로 들었던 증명 요구 중에 하나는 회사가 망하지 않는다는 걸 증명하라는 이야기였다. 사실 그걸 어떻게 증명하겠는가? 미래에 벌어질 일을 내가 신도 아닌데 어떻게 개런티한단 말인가? 정말 터무니 없는 말이고 요구다. 그런데 그런 것들을 증명하고 다독이고 해야 겨우 한 카피 제품을 팔 수 있는게 사업이고, 시장이었다.&lt;/p&gt;
&lt;p&gt;이건 여담인데 우리 이야기는 아니지만 모 업체는 외국 회사와 계약하면서 대한민국에 전쟁이 나면 어떻게 하냐는 이야기를 들었다고 한다. 그런데 더 황당한건 그 업체는 그 상황에 대한 대안을 증명함으로써 그 거래를 성사시켰다는 이야기. 이런게 B2B다 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그런 넌더리 나는 요구들에 대해서 때로는 증명하며, 때로는 영업력으로 뛰어 넘으며 몇 년 동안 착실히 일했다. 그 시간 동안 우리는 적어도 두개 정도 제품에 대해서 제품-시장 핏을 달성했다고 생각한다. 그말인 즉슨 그 제품들에 대해서는 더이상 과도하게 불필요한 증명 요구를 받지는 않는다는 이야기고, 제품의 기능적인 측면외의 부차적인 것들이 우리의 발목을 잡는 회수가 많이 줄었다는 의미다. 어쨌든 스스로 뭔가를 증명하지 않아도 알아주는 사람들이 있다는 것은 분명 행복한 일이다.&lt;/p&gt;
&lt;p&gt;그렇게 한동안 증명이 뭔지를 잊고 살았던 나에게 오늘 한 장의 페이퍼가 도착했다. 종이에 씌여진 질문들의 면면을 살펴본다. 종이에 씌여진 질문들이 향하는 지점은 한 곳이다. 너네 회사가 얼마나 괜찮은 회사인지, 얼마나 기술력이 있는 회사인지를 증명하라는 이야기다. 잊었던 증명을 또 해야 하는 상황이 왔구나라는 생각. 페이퍼에 소설을 몇 자 끄적이다 다짐했다. 기필코 반드시 몇 년 후에는 이 따위 증명을 다시는 요구 받지 않겠노라고…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;면접을 보던 경리, 업체 앞에서 프리젠테이션을 하던 우리, 그리고 그 수많은 제품 판매 과정들을 생각해 본다. 지긋지긋한 증명을 해야 하는 과정은 끝이 없어 보인다. 그러다 불현듯 그런 생각이 들었다. 이 지긋지긋한 증명 요구를 끊을 수 있는 유일한 길은 세상에서 요구하는 그 모든 것에 대해서 미리 다 증명을 해 놓는게 아닌가라는 생각?!&lt;/p&gt;
&lt;p&gt;… 생각의 퀀텀 점프 …&lt;/p&gt;
&lt;p&gt;많은 프로그래머들이 오픈 소스 활동을 하는 것에 회의적이다. 당장 돈이 되지 않는 일이기도 하고, 현업에 치여서 바쁜데 그런 것까지 할 시간이 있겠냐는 생각이 지배적이다. 하지만 증명이란 관점에서 바라보면 좀 다른 생각이 든다. 오픈 소스 활동을 시작하고 그것이 쌓이는 순간 적어도 우리가 칠판 앞에 서서는 내가 이 바보같은 문제를 풀 수 있는 사람인지 아닌지, 리스트에서 성이 “김”씨인 사람이 몇 명인지 헤아리는 프로그램을 작성할 수 있는 사람인지 아닌지, 멀티스레드 환경에서 동기화 처리를 할 줄 아는 사람인지 아닌지 따위를 증명하기 위해서 시간 낭비를 하지는 않아도 될 것이라는 생각말이다.&lt;/p&gt;
&lt;p&gt;github 계정을 만들고 그간 만들어 두었던 조악한 소스 코드라도 업로드를 해야겠다는 다짐을 했다. 적어도 그 작업들이 나중에 혹여나 프로그래머 신영진을 증명해야 하는 일이 생기더라도 그 귀찮은 작업들을 건너뛰게는 만들어줄거란 생각이 들어서였다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 403px; margin-bottom: 16px;&apos; data-url=&apos;./증명_하기.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/487983c3744553a176f6d85301b67390/ecda3/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUDBAH/xAAYAQADAQEAAAAAAAAAAAAAAAAAAQIDBP/aAAwDAQACEAMQAAABz6Iug66Yk4qY69GfR//EAB4QAQABAwUBAAAAAAAAAAAAAAEDAhETABIhIjEy/9oACAEBAAEFAoZDdlLX4EKjsEbqr6jqcR5//8QAGBEAAgMAAAAAAAAAAAAAAAAAABEBAhD/2gAIAQMBAT8BYpK5/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEQETH/2gAIAQIBAT8BKQ8j/8QAHhAAAgEDBQAAAAAAAAAAAAAAAAECEBEhIjFBgZH/2gAIAQEABj8CzZjj2R0x2HfArI49GKn/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhMXGBkaH/2gAIAQEAAT8hpxgiHdrdvDUGrc3NrsQHsJmPMIrew+8U8x2x/9oADAMBAAIAAwAAABCbEAL/xAAaEQACAgMAAAAAAAAAAAAAAAAAARARITFx/9oACAEDAQE/EMFqBbb4Uj//xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxDssx3h/8QAHBABAAMBAQEBAQAAAAAAAAAAAQARITFRgWFx/9oACAEBAAE/EKXXMHVFX5ABbYFXjLjvJHFnciUcOCx/IwNpmH2/Isol3gwVou+/2Ew5XfkIt1fgT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 1&apos; title=&apos;&apos; src=&apos;/static/487983c3744553a176f6d85301b67390/ecda3/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_1.jpg&apos; srcset=&apos;/static/487983c3744553a176f6d85301b67390/8ccab/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_1.jpg 190w,
/static/487983c3744553a176f6d85301b67390/ea4c8/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_1.jpg 380w,
/static/487983c3744553a176f6d85301b67390/ecda3/%EC%A6%9D%EB%AA%85_%ED%95%98%EA%B8%B0.md_1.jpg 403w&apos; sizes=&apos;(max-width: 403px) 100vw, 403px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;앤디워홀은 이런 말을 했다고 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;유명해진다는 건 어쩌면 자신이 앞으로 해야 할 모든 증명을 한순간에 다 해버리는건 아닐까?!&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[유튜브의 위엄: 구글 프로그래머가 돈을 많이 버는 이유]]></title><description><![CDATA[이것이 의미하는 것은, 복사본이 원본의 일부분이거나 느린 동작으로 실행되거나 오디오와 영상의 질을 낮춘다 해도 우리는 일치되는 것을 찾아낼 수 있다는 것입니다. 그리고 우리는 이것을 비디오가 유튜브에 등록 될 때마다 하는데 그것은 1분당 2…]]></description><link>https://jiniya.net/wp/archives/13221</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13221</guid><pubDate>Wed, 21 May 2014 23:59:36 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;이것이 의미하는 것은, &lt;strong&gt;복사본이 원본의 일부분이거나 느린 동작으로 실행되거나 오디오와 영상의 질을 낮춘다 해도 우리는 일치되는 것을 찾아낼 수 있다는 것입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그리고 우리는 이것을 비디오가 유튜브에 등록 될 때마다 하는데 그것은 1분당 20시간 분량이 넘습니다. 이 시스템의 규모와 속도는 정말 엄청난 것입니다.&lt;/p&gt;
&lt;p&gt;우리는 겨우 비디오 몇 개를 이야기하고 있는 것이 아닙니다. 우리는 지금 매일 업로드 되는 100년 분량 이상의 비디오들을 새롭게 업로드 되는 것들 및 기존의 비디오와 비교하는 것, 우리가 보통 말하는 사이트의 모든 내용을 스캔 하는 것을 이야기하고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이것은 36,000명의 사람들이 36,000개의 모니터를 매일매일 휴식 시간도 없이 들여다 보고 있는 것과 마찬가지 입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;– 유튜브는 저작권에 대하여 어떻게 생각하는가&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;정말 쩐다는 말 밖에는 안 나오네요. 구글 프로그래머는 분명히 기필코 반드시 외계인과 결탁했을 가능성이 농후합니다. 그렇지 않고서야… 이건 지구인의 기술력이 아니잖아요 ㅋㅋ~ 심심하신 분들은 &lt;a href=&quot;http://deminoth.tumblr.com/post/65396678669/jeff-dean-facts&quot;&gt;제프 딘의 진실&lt;/a&gt;도 한 번 살펴보세요. 쓰러집니다. (다시 봐도 진짜 욱기네요 ㅋㅋㅋ)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[닥터 이방인]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/13225</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13225</guid><pubDate>Tue, 20 May 2014 23:59:35 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;&apos; data-url=&apos;./닥터_이방인.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a7697558e465e4729eb998ad3f1e41d1/953fe/%EB%8B%A5%ED%84%B0_%EC%9D%B4%EB%B0%A9%EC%9D%B8.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGQABAAIDAAAAAAAAAAAAAAAAAAMEAQIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAZpM7Ea4K1Qs6Il//8QAHBAAAgICAwAAAAAAAAAAAAAAAQIDEgAEISIj/9oACAEBAAEFAiGuY2dK0xJVLmTpVXyXiHXHkrmv/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFREBAQAAAAAAAAAAAAAAAAAAASD/2gAIAQIBAT8BY//EAB0QAAICAQUAAAAAAAAAAAAAAAABESECEkFRYYL/2gAIAQEABj8Clt12cMjJml43FjyV3BI3vB6Ef//EABsQAQADAQEBAQAAAAAAAAAAAAEAESFBYTHx/9oACAEBAAE/IR7ImGNyGi9NZbEvm8jn4q9ZBLtHSABV5CDHp2G6PxNRT957P//aAAwDAQACAAMAAAAQ5MdC/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAREP/aAAgBAwEBPxAdsI5//8QAGREBAAIDAAAAAAAAAAAAAAAAAQAQETFB/9oACAECAQE/EBMvCO6//8QAIBABAAICAQQDAAAAAAAAAAAAAREhADFRQWFxsYGRwf/aAAgBAQABPxCKPDUC4ThBhtRh4TzTjQES7NqvrWJmlIiSSh7w4YZAWrvx3wS3USek6+5wdxxbU7fnC8Fpe8iPbiXDJZ4I/M//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 0&apos; title=&apos;&apos; src=&apos;/static/a7697558e465e4729eb998ad3f1e41d1/953fe/%EB%8B%A5%ED%84%B0_%EC%9D%B4%EB%B0%A9%EC%9D%B8.md_0.jpg&apos; srcset=&apos;/static/a7697558e465e4729eb998ad3f1e41d1/8ccab/%EB%8B%A5%ED%84%B0_%EC%9D%B4%EB%B0%A9%EC%9D%B8.md_0.jpg 190w,
/static/a7697558e465e4729eb998ad3f1e41d1/ea4c8/%EB%8B%A5%ED%84%B0_%EC%9D%B4%EB%B0%A9%EC%9D%B8.md_0.jpg 380w,
/static/a7697558e465e4729eb998ad3f1e41d1/953fe/%EB%8B%A5%ED%84%B0_%EC%9D%B4%EB%B0%A9%EC%9D%B8.md_0.jpg 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;개연성 (蓋然性)[개ː연썽]&lt;/p&gt;
&lt;p&gt;[명사] &amp;#x3C;논리&gt; 절대적으로 확실하지 않으나 아마 그럴 것이라고 생각되는 성질.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;드라마 작가가 아직 개연성에 대해서 배우질 못한 듯. 꿈에서 생각나는 대로 써도 이거보다는 더 말이 되는 스토리가 나올것 같은 느낌?! 창작자에 대한 최소한의 존중을 하고 싶어도 이건 뭐 ㅠㅜ~ 의학, 정치, 스릴러, 액션, 히어로, 러브 스토리 다 짬뽕하고 싶었던 욕심이었을까? ㅋㅋ~&lt;/p&gt;
&lt;p&gt;하도 기가차서 드라마 작가를 찾아보기는 또 첨인듯…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 덤프의 색깔을 찾아서…]]></title><description><![CDATA[덤프 이미지 분석은 내가 갑~ 왼쪽에 그림이 덤프 이미지입니다. 화욜날 간만에 댓글의 reinhard, zoops 횽들을 만나서 술을 한 잔 했습니다. 그러면서 이런저런 이야기를 하는데 reinhard…]]></description><link>https://jiniya.net/wp/archives/13168</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13168</guid><pubDate>Thu, 15 May 2014 23:59:34 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 410px; margin-bottom: 16px;&apos; data-url=&apos;./덤프의_색깔을_찾아서.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3545fb8df5eadc20714c2e9849d9954b/cb1d0/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADEklEQVR42hXOWU8TawDG8RcTL1xuqkHF6AUV3Fq2VC0UBUVxoXSjrVVbZun0nc7WmWmn0w0UitKWKlKgliBioKDR5ByPhyPXR+M5X8GvoLEFK5po9ALH5Jfn7kn+gOon/W7S74F+NyQVHsigEL/KpIcdlcqWb9+rEvw5SJCZuDw/KGdILMHBLOtOQ2eWdgKcwDAfQkCUIFAIvRASkETd132ZlOXDB7BWBk9n8WA8nBsKRTBnxG5jb2B+kzGF2CcZKxBoVhLFkMCLFCfQDM+yAkuzPmlyzLW+Dj5vgL+L/onJAuLuOVK/3aDf12mo1rc23w2SKW83iAlyIhiNiXJUkCNCOBqUY2FJZOKFKaT0EZQq4O0zm5ycPaUzNGm393Tvb9erNHU1D2VL2tsBJCEUEiVJkGRRlkOyFJQioRBPx6dzSLkM1tbB63+YMT7WoTvZbtjZ3rqrQbOtVVc7G8GeDngBQ1CMj2J9FAdplqQ4P8VTNETFe5mr65+qlPKVv9L/v1phb/RaupudpjbjlWaTsWuQhE/iJBCwAI9xPBLgUC6AcRzGcjjtuy6Oj7gqFbCxAVZfJuanH82MBV4tXPtzwb36HFnJOcZpvED5gK3a1FdtVtgVe8x9e82Oml7jDlvi8tmPpd/ZL4v9AiHO3c//uzhxJx64OxpdDqJ/JLkx4TboqzUrHLUWp9rqUFvtaour3mrcZ49ZO5Xnxmew9JjIDhBLqcDySGzYj2Rx54gHu4N5KJgEDSqNolGlVVar0mhUxxt3H1Nv1V7rUn/5WvXjO7iXp4ozcD4CFyLscjLwZIifCnlSuE3GJNBW19R2qMlQ36w/1Nhy4KihrqXz2AndwZPQcaSkZK+BFzPWqSE8iHtWM+4XoqtI9YyS3pTHlg8zoPeS2XLFeqHz0khi+Mv7cvHB3K2glE/PTo/3l8rgUwW8WzTdhOdRu+2/PFJI8rm4n+6xZPn+MArB6RZ9h85w4nBjXIr+3NxcXF4aGEyMT8yNDvX9/AE2N0F2QBcNc7nb4TcF9CbmEk1nLmtrvI4u+8WOXzq4R0lSKyOaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;            md 2&apos; title=&apos;&apos; src=&apos;/static/3545fb8df5eadc20714c2e9849d9954b/cb1d0/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_2.png&apos; srcset=&apos;/static/3545fb8df5eadc20714c2e9849d9954b/08678/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_2.png 190w,
/static/3545fb8df5eadc20714c2e9849d9954b/2edd7/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_2.png 380w,
/static/3545fb8df5eadc20714c2e9849d9954b/cb1d0/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_2.png 410w&apos; sizes=&apos;(max-width: 410px) 100vw, 410px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;덤프 이미지 분석은 내가 갑~ 왼쪽에 그림이 덤프 이미지입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;화욜날 간만에 &lt;a href=&quot;http://www.jiniya.net/wp/archives/13045&quot;&gt;댓글의 reinhard, zoops 횽들을&lt;/a&gt; 만나서 술을 한 잔 했습니다. 그러면서 이런저런 이야기를 하는데 reinhard 님께서 드미트리옹께서 크래시 덤프의 이미지를 만들어서 재미를 보고 계셨다는 이야기를 해주시더군요. 제가 또 드미트리옹과 페친 아니겠습니까? 드미트리옹의 책도 다 샀는데 눈 뜬 장님이었더군요. 책 표지 자체가 크래시 덤프 이미지였다는 사실을 알고는 충격과 공포에 빠졌습니다. 역시 사람은 아는만큼 보인다는 옛 이야기가 다 헛말이 아니었습니다. 핡~&lt;/p&gt;
&lt;p&gt;그래서 저도 해봤습니다. 제가 가진 게임 덤프 파일 중에 하나를 돌려보았지요. 가운데 텅 빈 공간이 웬지 무한한 우주 공간에서 찰나의 순간을 살다가는 인간이라는 존재의 한없는 고독함을 나타내 주고 있는듯한 느낌입니다 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./덤프의_색깔을_찾아서.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c81d4930175d620c9bf2298f7e9c14f3/b0db9/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAACK0lEQVR42qWU35KaMBjF4/au+hargm7v1EfoCrSuBZypuEIArYJ/rivofVXQfeWeL4F1d6a96PSXL8nJycGRmRBmWdbItkejkWla34BJWJaNbqJhpMEyzXLDtq0SFobBbDabC2hGnwk5m4UhqcVi8QPM5yHWKJFGKAgC5roe59z1vClwpx4n4Xme7/sYOcfguQiJESAjki6eYtvNFqxXa/z6Ko63m00cRRDRMorjeLlYRstlDBlF69UK/ipabdYbSCRZmqRJkhz26T5NoTHuE4jkkO4P+wOc3W5H/ecu2YkoiR3F0pT5BP5/4HM0KQOaQ7RC00YQcO7jNWjLLwZ6mEsrDKTNaS1DYl28vC/e3pOI3/OZc2OMmgiewWQyfb7hTJzvYDweO9Qp6zhsOBw+DZ4GX8GXwWDw9MrwjURGLLE9oFARY7VatVqtScq59rquvufj+yWrVCp3gspfwA7Vn7bY3Y0P/1KUZ/9F+4H4JGgLWq1ikqhq64FChdd+AzudTnmeXwVZlkHnl/ycZefzOc/yy+XyIri+XKGxifzxF3E8HhkX4IspDpM8HMXB4vKc0Bnhvlt8Gq48LDhIrNvt9nrdbqdDBUF0ekRpFg4tO9IRAg5rKK16U6031PuGUm8qDUVtqsKhUu5R5JOJJKqptusK7UKzvmb0dZ1K0zVd1w1DM+AYmm7AedS0xz5VvxRwPvf7csnErULXELAJumhGpbALSzTTkh7dQML5DWXiR4dGFqCEAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;            md 1&apos; title=&apos;&apos; src=&apos;/static/c81d4930175d620c9bf2298f7e9c14f3/b0db9/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_1.png&apos; srcset=&apos;/static/c81d4930175d620c9bf2298f7e9c14f3/08678/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_1.png 190w,
/static/c81d4930175d620c9bf2298f7e9c14f3/2edd7/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_1.png 380w,
/static/c81d4930175d620c9bf2298f7e9c14f3/b0db9/%EB%8D%A4%ED%94%84%EC%9D%98_%EC%83%89%EA%B9%94%EC%9D%84_%EC%B0%BE%EC%95%84%EC%84%9C.md_1.png 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;한 게임의 크래시 덤프&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;글을 보고는 바이너리를 이미지로 변환을 어떻게 하시는지 궁금해 하시는 분들이 계시는 듯 하여 소스 코드도 같이 올려드립니다. 지난 번에 작업한 스크립트 파일은 앞에 비트맵 헤더 붙이고 귀찮아서 뒤에다 0으로 전부 패딩을 넣었었는데요, 이번 버전은 비트맵 의도대로 중간 중간에 패딩을 넣도록 한 버전입니다. bin2img.py input.tar output.bmp 하시면 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;py&quot;&gt;&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token triple-quoted-string string&quot;&gt;&apos;&apos;&apos;

	Copyright 2014 YoungJin Shin &amp;lt;codewiz@gmail.com&gt;

	bin2img.py input.tar output.bmp

&apos;&apos;&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; math
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; struct
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; sys

BPP &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt;
BPP_BYTES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; BPP &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;
BMP_HDR_SIZE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;
DIB_HDR_SIZE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;
DPI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2835&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetImageFileSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	px &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ceil&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sz &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;BPP_BYTES&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	wpx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ceil&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sqrt&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	xbytes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;floor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wpx &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; BPP &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wpx &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; xbytes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wpx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wpx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; xbytes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetBmpHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sz&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; struct&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pack&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;=BBLHHLLLLHHLLLLLL&apos;&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x42&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x4d&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sz &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; BMP_HDR_SIZE &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; DIB_HDR_SIZE
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BMP_HDR_SIZE &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; DIB_HDR_SIZE
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DIB_HDR_SIZE
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; h
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BPP 
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sz
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DPI
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DPI
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPadBuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	pad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		pad &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; struct&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pack&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;=B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pad

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BinaryToImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bin_path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; img_path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	inf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bin_path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rb&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token builtin&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; inf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	inf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	buffer_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	fsz&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wbytes_pad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; GetImageFileSize&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	hdr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; GetBmpHeader&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fsz&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	outf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;img_path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;wb&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	outf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hdr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	wbytes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; BPP_BYTES
	pad_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wbytes_pad &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; wbytes

	pos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		remain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buffer_size &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; pos
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; remain &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; wbytes&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
			pad_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wbytes_pad &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; remain

		outf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pos &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pos &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; wbytes&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

		outf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GetPadBuffer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pad_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		
		pos &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; wbytes

	outf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	BinaryToImage&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[소고] 당신의 코드는 무슨 색깔인가요?]]></title><description><![CDATA[언젠가 학교 선배가 자바스크립트 코드 컨테스트에서 누군가가 코드 바이트를 줄이기 위해서 PNG…]]></description><link>https://jiniya.net/wp/archives/13045</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13045</guid><pubDate>Sat, 10 May 2014 23:59:33 GMT</pubDate><content:encoded>&lt;p&gt;언젠가 학교 선배가 자바스크립트 코드 컨테스트에서 누군가가 코드 바이트를 줄이기 위해서 PNG에다 코드를 인코딩해서 사용했다는 이야기를 했습니다. 문득 그 이야기를 곱씹다가 내가 만든 코드는 무슨 색깔일까 하는 생각이 들더군요. 이 거대한 코드를 컬러로 바꾸면 무슨 그림이 나올까, 하는 생각. 그래서 한 번 해봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; margin-bottom: 16px;&apos; data-url=&apos;./당신의_코드는_무슨_색깔인가요.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8815cdce7b6afe0473e320a96a750c63/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 99.47368421052632%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAAB20lEQVR42l2TzW7iQBCE+2WIOWG8jwBE/BxxkNY2e1iQwD+YSDEEOyecJ09V9zg4+Wh6aqqaHCYzMvJ9f+z/CYLxOEBHBdQ+CwkI2DA18kdjlTpA5KnD81DecDiEHgwGusPWo//kDTWy1GMxlTiKkiSO9cu+hcAKtokFydZQa5u4NImiSIoizwty6lGcihyfE/1csxIfDUoboFlIrqRp5kiz9HjUQjseDgd02DaWZ7lp/BRN2vZTcQvW9n5v7y1Bv/9A3damUdI0zcdH09RNXePbUNZaTX273egqDX06NFVjQHa73V7rF/v9XqN9z3DQ+09Lrtf3a48fG+Vi7fIYeO8C4WG68+6ww7TzL7X03Lv/RKFFRyaTyXQ6nU1nAEuHKjpmzRzPz0gmHbJcLpZ9Vg85n88XD+igf29Wq5XgazYm+38EEy5yu4VbTGhJGIYvIVmv15Dawxdls9l0oQ6wwWRkPxC9XrhOqbs+WcYD1Mukp0b5uLR6WrmbyAX3+y+qBzaREce28K300X0UR7K158MHFOs8Vz6gf/aqYr4nm0jcg7M3Bi38bwO9B7+o6F/cwOUhLKmqSiCq6g2o46JKedP+7TnRJZByPr+eQVmiwNlB8eoSZrolmpUmvgCEM7nxamUqpwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 0&apos; title=&apos;&apos; src=&apos;/static/8815cdce7b6afe0473e320a96a750c63/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png&apos; srcset=&apos;/static/8815cdce7b6afe0473e320a96a750c63/08678/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png 190w,
/static/8815cdce7b6afe0473e320a96a750c63/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png 320w&apos; sizes=&apos;(max-width: 320px) 100vw, 320px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;XIGNCODE3 250M&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;레거시 코드를 제외한 XIGNCODE3 전체 소스 트리를 이미지로 변환한 겁니다. 어떤가요? 처음에 결과를 보고는 적잖게 당황했습니다. 내가 만든 코드가 이렇게 칙칙한 회색 빛깔이었다늬, 이러면서 말이죠. 결과를 보기 전까지 전 총쳔연색의 아주 아름다운 뭔가가 나타날거라 상상했거든요. 늘 상상과 현실은 거리가 있게 마련이죠 ㅋㅋ~ 그래도 뭔가 가로 줄무늬가 나이테 같기도 하고 퇴적암의 퇴적층 같기도 한 그런 느낌도 들긴 했습니다. 풉, 맞습니다. 우리만 당하고 있을 순 없죠. 다른 프로젝트 소스 트리에 대해서도 스크립트를 돌려봤습니다. ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; margin-bottom: 16px;&apos; data-url=&apos;./당신의_코드는_무슨_색깔인가요.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4aabe7519f97a453c9c6e976d96396cb/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 98.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAABd0lEQVR42mVUAbaEIAjkWn+7wO+bbJrW/W/ygQF1385uhgOmDRDtgj8g/S1Gwgy+JLPhnaAsYM6cBw5BBs2D0mElD11BRzoCKdkgWyxUcEm3RzBIATmVsNTMZN604IjLkfFkevNbYMPJdhsM4zrFlsMqe55wIYKptdZ7b4bruqpc7WqB4eqtY6xVQ4SXOGJDDjFCDxUk+ENuuhF7CMSTP0FeX8eL6KGvksyRgTwMAb0UP68vbNtrmxNn1NgcwpC+B9AmLgXeObx92tBCQNPb+/3cz/Pc920ThXtb69/69UaoqE8kSWQk1ZPub4tSO7wISZImnIkSgnFGtU4Syn+WMJvasy4zSifPx69FOjbM2cuPBje9az/w0i3xFGRZa7vUUg3F8G1L1U3SPcWmlaoHfS4z8goGJVmXleAJpx8fBHS+fyDEsK+BjPvvHpH7iKHTmuU8cX+XYcvPHKVYK3nUiFSW5DzFTojs1yguOyd6zJvNJWiXRhvzD3Qea+6qlLSLAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 1&apos; title=&apos;&apos; src=&apos;/static/4aabe7519f97a453c9c6e976d96396cb/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png&apos; srcset=&apos;/static/4aabe7519f97a453c9c6e976d96396cb/08678/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png 190w,
/static/4aabe7519f97a453c9c6e976d96396cb/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png 320w&apos; sizes=&apos;(max-width: 320px) 100vw, 320px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;boost 150M&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; margin-bottom: 16px;&apos; data-url=&apos;./당신의_코드는_무슨_색깔인가요.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0e11d2c0da1e6d42dc8d6bcb05a9fc56/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 99.47368421052632%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAABCElEQVR42qWT627DIAyFz5OVSVnTBEKqKZc/I3n/x5gvkBJWpqn94mD72JVqAuhfpuswn5nmaZrlEaIoflkWiR8iLONsBcfUdIdt33YhOgqE6BJFGljawVEI9KaWXWtiXNCGki18h6B/2/ZduR1WHjWq/6qy4eMN0DTNJ9GI0UKpKho/Q3V6YYy5FJgLi6YKNWgVt0Qr/BE/xDYC+lyDG9gEd4LSweb5kDolxnh/mRGuiq2pRwHrsqrR0dUl45SvQoxEAU9/7EDOLd+acv/oJxRj/Bf+qYqvN0C62Ay546KXN19Pf5ef7h7ZUFdFo1aDJIp+TX3qWoze00C8+DiY974YUQWfOGb+AR5YY/gHRX8aAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 2&apos; title=&apos;&apos; src=&apos;/static/0e11d2c0da1e6d42dc8d6bcb05a9fc56/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_2.png&apos; srcset=&apos;/static/0e11d2c0da1e6d42dc8d6bcb05a9fc56/08678/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_2.png 190w,
/static/0e11d2c0da1e6d42dc8d6bcb05a9fc56/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_2.png 320w&apos; sizes=&apos;(max-width: 320px) 100vw, 320px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;chromium 1.5G&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;XIGNCODE3 프로젝트는 그래도 밝은 편이었습니다. 부스트랑 크로미움 소스 코드에 비하면 말이죠 ㅋㅋㅋ~ 이 그림들을 보고 있노라뉘 이제부터 소스 코드에 대해서는 청사진(blue print)이 아니라 흑사진(black print)이라는 표현을 써야 할지도 모르겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; margin-bottom: 16px;&apos; data-url=&apos;./당신의_코드는_무슨_색깔인가요.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fda27d980dd83172332668f974e82094/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAEaElEQVR42gXBWW/aBgAAYP+Gvk3TpElVD6naemyporVKaQKhJkAo92GMwcY3BoMPjLE5CsYcJdwhNCEsXZImitJ1q6p27cMe97P2fUDkRXGjLL54dHn6WC/9CuMBXU2HR5LAmbpvH1UK7PAd2pNQ7g0uL7ucFj6cRfYK8ubHU4f4ErDfhtxCRVM54dZgRLjMXpUm6XCMV8bva8XesEit5As3jD0POpoecD3l2IAwGqs6BnzBFgZSbXmf6s7VNDQzqB4dpRWqARbKN3k8H20XrjBtjzyQB+rbM7awn3afM+IHT1MMbiSPmmIdWIzqgW6GGpi+swwhoK9J51gBOcbB+J4ESv44tOZMhpZXPvWSWReU/B6X8TMfN0FPAIn5DWDHwW7r8fSrpJEohpg/1eTRYk20qfQWIuMQO7AK8KssHPFJC0/DCPDBggDXpMV6JYKyt12AeiffZf3H7DVzry6CAcEaVRLxAuXM70yf0RXtxl6zOkWpsaj9MAhSJT8XstYtO7l2pOE37UC9eMUzemPDQO7rma301BSbeTeXbpUyYM98EG8O+uKycqwRB1labxIoX4oz9BrPuc7d2gQYPdWd7b5C7lUzJllN6Ctx0WWiFcu998NikeTJKT/Xmb779OS/0jFs0Z1hNoJn2a3uuRyVgA6N6TZZBzXf3NLiYIWXoXpPoxg3N0o6ah+xxREFKbtOUJqky6V2viEmsFqnnemfMSgN/KiVrETAFge3R57ybpQINTyUjORHTHRAxw/mZhbubt+6f/f7Z5vYmkzZtslr7+lqGCX3U9dh4E7psT2ABF07F/agQNVPKq0I9S8G1YxCxmsJP40m7yJV/L6FiFhtjdB3hWx2hiqPwIfIfiBgBTLRZl54ajyRx1iZuLAQrV2cy1tD02Iad7o9aMwVy2cyxZu+nM2V01I5PivQRdK7FnP9hPwMvCvm/j4ajnjMti+teJGnlmdErRcdseoBPCI/D+0sW6JfRwqfvjU61/Wl0JvCny6b2Zk6lNyA8tBrVozaYFDJ1VrU/BV2/Ha9DLWRB38xqOc3AkS6A56sOiowUW+Txi7Ke6MXmjrvNhuoBiQUMyjY6UILzGLWKTomPXERgys+dlXtew9HZn9AZ9OIDqfIQ/il6a1KkH9yqHiXdfKzAHihoORdnl18PZTqjaBre8Knv06+yPJYwsO1BeY6YxX+Cfh74pc8hHxgEO1dKTPH32YdnVhxCoSMlWIOkTfnG+XPArWptOMxTTlPMhMLho/VvDSTdrrb+FwljQupdAWVD1z9hCKh51PkOAcE5MbIrMpvYsKG50SItVQOjZsSd4Jh3KPNmKEoeFMbEZqmNzopcvRcPTF6ry9F9arKdSZAfULWHc14jPhD5feas1my3MJxJ43HwQQoBpa/O/DCVqX0jcc/ZFO9FuLuzdHhEl2041rAABizg8zy7Vb/eUe7UTOgWTJkqdrs/6Q6k91culmkr4peKQ7hKS8rVOdgoC2dntS/LHrWVTL6P1Z1EUNS9QxtAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 3&apos; title=&apos;&apos; src=&apos;/static/fda27d980dd83172332668f974e82094/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_3.png&apos; srcset=&apos;/static/fda27d980dd83172332668f974e82094/08678/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_3.png 190w,
/static/fda27d980dd83172332668f974e82094/dd4a7/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_3.png 320w&apos; sizes=&apos;(max-width: 320px) 100vw, 320px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;XIGNCODE3 250M&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;우중충한 그림들에 다소 충격을 받았을 여러분을 위해서 조금 희망적인 이야기가 필요할지도 모르겠습니다. 사실 회색빛깔이 전부는 아닙니다. 그 회색빛깔 사이로 무한 확대 작업을 해보면 실질적으로 그 내부에는 이와 같이 총천연색으로 이루어져 있거든요. 이쯤에서 채플린옹의 이야기를 한번 떠올려주면 되겠습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Life is a tragedy when seen in close-up, but a comedy in long-shot.&lt;/p&gt;
&lt;p&gt;인생은 가까이서 보면 비극이지만 멀리서 보면 희극이다.&lt;/p&gt;
&lt;p&gt;– Charles Chaplin&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 118px; margin-bottom: 16px;&apos; data-url=&apos;./당신의_코드는_무슨_색깔인가요.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/40087a931af132a42d65106251c374dd/48743/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 55.93220338983051%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABqUlEQVR42hWRa3IcIQyE5z6plCv2egAJvQXMeNe+/3GCfyKpqe6vj8DuiJSZMFA9U75GdykEc61nME+7SL1+ftS3Vt4+sIA1ON/Pt8ff46NIqG/RIiWchQw6P7pN1EBpvaT35KZB+hr+j6HxFmxF4XFkD4ocZt71GibufA148PqK9ZR8+TC/7bnGen1dt/gQoxp+rWvEcRp6u7oqJfr2C6IOJW1FiEVjDqspKuYmOkf4UnYhclc4yjblJVqNcOSQNbau42mF95ESQ4Fku4cQ/PAyjqJYexFjOxq4RDx9Juu8t8fJks3BkfQhztJ1pd4/qUZW99ZYKzCngR3wjlKaZqknNKIJGxLt2XCSLrALGJNZm9s7baeNdeNppoo6jz+ViXqTM3a0j5NMB6QAWxeFDX3BXpvvgm65vGID+FQwpq85DwLuO36uyGnS7wi0sBha0HZDztwoXGpxh9ivXoCR7uXT8vBea20Vf9lsM9l3zluXAzRoQifo2TbADWTiMtq/yndeSCQTjrTczXL3pvBymZo4GyoOte94DreA3kWmsFVEq8LUH78DuOZ/rQGi+WRcyMAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 4&apos; title=&apos;&apos; src=&apos;/static/40087a931af132a42d65106251c374dd/48743/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_4.png&apos; srcset=&apos;/static/40087a931af132a42d65106251c374dd/48743/%EB%8B%B9%EC%8B%A0%EC%9D%98_%EC%BD%94%EB%93%9C%EB%8A%94_%EB%AC%B4%EC%8A%A8_%EC%83%89%EA%B9%94%EC%9D%B8%EA%B0%80%EC%9A%94.md_4.png 118w&apos; sizes=&apos;(max-width: 118px) 100vw, 118px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;매직아이같은 이 색깔의 코드는 무엇에 쓰는 물건일까요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이 코드의 비밀을 알아낸 분은 codewiz at &lt;a href=&quot;http://gmail.com&quot;&gt;gmail.com&lt;/a&gt;으로 메일을 보내 주시면 감사하겠습니다.****&lt;a href=&quot;http://www.jiniya.net/wp/archives/12367&quot;&gt;같이 할만한 일이 있을지도 모르잖아요 ^^;;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 책임…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12954</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12954</guid><pubDate>Thu, 08 May 2014 23:59:32 GMT</pubDate><content:encoded>&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;&apos; data-url=&apos;./책임.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a5a56458f2a9c3e9b84218bce4ccc612/a22ce/%EC%B1%85%EC%9E%84.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAABA//EABQBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAQDcIeVkn//EABoQAAICAwAAAAAAAAAAAAAAAAEDAAIRIjP/2gAIAQEAAQUCXUZuNjFkhLes/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABsQAAEEAwAAAAAAAAAAAAAAAAEAAhARIUFx/9oACAEBAAY/AqOUYYdgp3Y//8QAHRABAAEDBQAAAAAAAAAAAAAAAQARITEQQWGBof/aAAgBAQABPyFlIcG0yWzSZQQNwD2T2tP/2gAMAwEAAgADAAAAEMgP/8QAFhEAAwAAAAAAAAAAAAAAAAAAEBEh/9oACAEDAQE/EHB//8QAFxEAAwEAAAAAAAAAAAAAAAAAARARIf/aAAgBAgEBPxDBq//EAB4QAQACAQQDAAAAAAAAAAAAAAEAESEQMVGhgZHw/9oACAEBAAE/EM/YFJ0ZQYyuBw1Fe6/EMMJgFDZ7fc+Vzp//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;   md 1&apos; title=&apos;&apos; src=&apos;/static/a5a56458f2a9c3e9b84218bce4ccc612/a22ce/%EC%B1%85%EC%9E%84.md_1.jpg&apos; srcset=&apos;/static/a5a56458f2a9c3e9b84218bce4ccc612/8ccab/%EC%B1%85%EC%9E%84.md_1.jpg 190w,
/static/a5a56458f2a9c3e9b84218bce4ccc612/ea4c8/%EC%B1%85%EC%9E%84.md_1.jpg 380w,
/static/a5a56458f2a9c3e9b84218bce4ccc612/a22ce/%EC%B1%85%EC%9E%84.md_1.jpg 680w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;“제가 남 탓을 할 수 없는 까닭은 제가 최종 책임자이기 때문입니다. 책임은 제게 있습니다.” – 버락 오바마&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;blockquote&gt;
&lt;p&gt;사고 이튿날, 박근혜 대통령이 실종자 가족이 모여 있는 진도 실내체육관을 찾았다. 이 자리에서 대통령은 이런 말을 한다. “있을 수 없는 일이 일어난 데 대해 철저한 조사와 원인 규명을 해서, 책임질 사람은 모두 엄벌토록 할 것이다.” 많은 언론은 이 발언을 대통령의 단호한 의지를 보여준다는 식으로 보도했다.&lt;/p&gt;
&lt;p&gt;하지만 이 발언의 핵심은 다른 데 있었다. 이 결정적 발언으로 대통령은, ‘시스템의 최종 책임자’에서 ‘구름 위의 심판자’로 자신을 옮겨놓았다. 시스템이 무너져내리는 가운데, 최종 책임자는 자신의 책임을 말하는 대신 ‘책임질 사람에 대한 색출 의지’를 과시하는 단죄자의 자리를 자연스럽게 차지했다. 침몰하는 시스템에서, 대통령은 그렇게 가장 먼저 ‘탈출’했다.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://www.sisainlive.com/news/articleView.html?idxno=20059&quot;&gt;시사인&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;http://img.viewsnnews.com/article/2014/04/2313191807338200.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 클라우드의 역습]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/13018</link><guid isPermaLink="false">https://jiniya.net/wp/archives/13018</guid><pubDate>Sat, 03 May 2014 23:59:31 GMT</pubDate><content:encoded>&lt;p&gt;몇해전 클라우드에 관해서 &lt;a href=&quot;http://www.jiniya.net/wp/archives/6103&quot;&gt;깜찍한 글을&lt;/a&gt; 하나 썼었다. 제법 당시 상황을 잘 반영했는지 반응이 그리 나쁘지 않았다. 지금 시점에서 생각해보면 정말 깜찍한 글이 아닐 수 없다. 왜냐면 그 사이 우리는 거의 모든 서비스를 죄다 클라우드로 전환했기 때문이다. 더 아이러니한 사실은 세포 덩어리로 옮겼다는 점 ㅋㅋㅋ~ 한치 앞도 모르는게 사람 일이다. 어쨌든 지금 우리는 물리 서버 대비 거의 절반 가격에 서버를 돌리고 있다. 더 큰 대역폭의 네트워크 회선은 덤일뿐 ㅋ~&lt;/p&gt;
&lt;p&gt;그간 만족하면서 잘 썼는데 오늘 장애가 발생했다. 처음에는 우리 문젠줄 알았는데 알고보니 클라우드 서비스 자체의 장애 상황인 것 같다. 열심히 고치고는 있는 것 같지만 4시간이 지나도 상황은 개선될 조짐조차 보이질 않고 ㅠㅜ~ 손가락만 빨고 앉아 있을 수 밖에 없는 작금의 사태가 참 안타깝다.&lt;/p&gt;
&lt;p&gt;세상에 모든 것이 다 그렇지만 클라우드 또한 양날의 검이다. 편리한 만큼 문제가 생기면 손쓸 방법이 없는건… 거대 기업의 기술력을 믿을 뿐 ㅠㅜ~ 제발 한번만 살려주세요. 담부터는 비싸도 미쿡에다 서버를 만들겠습니다.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 604px; margin-bottom: 16px;&apos; data-url=&apos;./클라우드의_역습.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/cd10bdc6c2d72fe57bc8a7b341b0eb0a/1994c/%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%9D%98_%EC%97%AD%EC%8A%B5.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 54.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABnUlEQVR42nVQ2XKjMBD0//9bah3HODanxH0JAboBJ9usyVbtw6q6pgahnu7p0zh0TOhlWZ7/P9u2CSEGzge9crONduv1VsvlpGeWF2XfttZabZQ12mqNan7q61hjnLXOaLc/UIs148BOcmZpWceECqWl0gXXKdfZaPLJ0NH00mrrlLHKOGnsD5yyS9Ozk1lX6Zai6Zp+KNqun+ayG4KE+gkNSBrS9BElcZr5UeLHBPdBTD79MCRUuRXkJ+CeX3bbsX59l0138T69uw8CyYokK0heRDSNaUaLCp9gkrzUy7aTpV3aYezHuWF8lJpNIq+aqmPAMEvcj1INk8A9+n4SHZ+4kCDuZMyYlAHAhBlEcP7w3s6X8/UGC+jfr7dflyvqx+2OG/RxmsPmQRbGvYAeCllZp2WV121W1UXdYRxczNoCEHjhUP5rG3U2Djt7j8B7+Pcg8v/Egw2xcJjQRxgjMzQRzcA6lF9T4Ry2sRLZQypRoZkWVTtw2OFCYVU2SQTBZ3mk/Y+ytj2fMDgiKURe2Qbk0IxJhl8t43ij3PobkUBiyuioH2QAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         md 0&apos; title=&apos;&apos; src=&apos;/static/cd10bdc6c2d72fe57bc8a7b341b0eb0a/1994c/%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%9D%98_%EC%97%AD%EC%8A%B5.md_0.png&apos; srcset=&apos;/static/cd10bdc6c2d72fe57bc8a7b341b0eb0a/08678/%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%9D%98_%EC%97%AD%EC%8A%B5.md_0.png 190w,
/static/cd10bdc6c2d72fe57bc8a7b341b0eb0a/2edd7/%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%9D%98_%EC%97%AD%EC%8A%B5.md_0.png 380w,
/static/cd10bdc6c2d72fe57bc8a7b341b0eb0a/1994c/%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%9D%98_%EC%97%AD%EC%8A%B5.md_0.png 604w&apos; sizes=&apos;(max-width: 604px) 100vw, 604px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;오늘의 교훈&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;**동아시아에는 서버를 만드는게 아니란다…**&lt;strong&gt;똑같은 상황이 미쿡과 동아시아에서 발생한다면 어디가 먼저 고쳐지겠니???&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;덧) 8시간만에 장애는 해결됐다. 그러고도 안 살아나서 초큼 당황했는데 침착하게 파워쉘로 강제 종료하고 켜니 잘 켜졌다. 서버가 다시 살아나서 천.만.다.행… 그래도 매 시간 서비스 상태를 알려주는 페이지를 통해서 작업 진행 상황을 알려줘서 덜 당황할 수 있었다. 역시MS. 우리가 손가락만 빨면서 침묵한건 함정 ㅠㅜ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[역린, 2014]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12968</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12968</guid><pubDate>Fri, 02 May 2014 23:59:30 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;작은 일도 무시하지 않고 최선을 다해야 한다.&lt;/p&gt;
&lt;p&gt;작은 일에도 최선을 다하면 정성스럽게 된다.&lt;/p&gt;
&lt;p&gt;정성스럽게 되면 겉에 배어 나오고&lt;/p&gt;
&lt;p&gt;겉에 배어 나오면 겉으로 드러나고&lt;/p&gt;
&lt;p&gt;겉으로 드러나면 이내 밝아지고&lt;/p&gt;
&lt;p&gt;밝아지면 남을 감동시키고&lt;/p&gt;
&lt;p&gt;남을 감동시키면 이내 변하게 되고&lt;/p&gt;
&lt;p&gt;변하면 생육된다.&lt;/p&gt;
&lt;p&gt;그러니 오직 세상에서 지극히 정성을 다하는 사람만이 나와 세상을 변하게 할 수 있는 것이다&lt;/p&gt;
&lt;p&gt;– 중용 23장&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;소문난 잔치에 먹을 거 없다고 했던가? 그렇게 광고를 해댄 것에 비해서는 큰 임팩트는 없었던 영화. 내용이 인상 깊지도 않았고, 액션이 박진감 넘치지도 않았고, 영상이 화려하지도 않았다. 보고 나서 기억에 남는건 중용 23장과 한지민의 미모 정도?!&lt;/p&gt;
&lt;p&gt;고전이 괜히 고전은 아니라는 생각. 그 어떤 상황 어떤 시대에 읽어도 의미가 통하는 걸 보면…&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 358px; margin-bottom: 16px;&apos; data-url=&apos;./역린,_2014.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ba345ecfe1749d86484d79e8b94846cc/af061/%EC%97%AD%EB%A6%B0%2C_2014.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 123.6842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAZABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEBQL/xAAVAQEBAAAAAAAAAAAAAAAAAAACAf/aAAwDAQACEAMQAAABelsUt4oQ6zq8wLVOhT//xAAdEAACAwACAwAAAAAAAAAAAAABAgADBBESIiMz/9oACAEBAAEFArF4BJS0qXmg+ehuXqs9el+srYRVE0fSVz//xAAWEQADAAAAAAAAAAAAAAAAAAABIDH/2gAIAQMBAT8BET//xAAWEQADAAAAAAAAAAAAAAAAAAABIDH/2gAIAQIBAT8BNT//xAAhEAACAgECBwAAAAAAAAAAAAAAAREhAhJBEyIxUWFygf/aAAgBAQAGPwJuCOI4a3JVmGKW9i5VXRi1D7ujRla28DV04F9EZ+zP/8QAHBAAAgMBAQEBAAAAAAAAAAAAAREAITFBUXGh/9oACAEBAAE/IbgIdeTwYzNRSDKYh0a9MUWEaH2IQJJuqghXzHwSkMENj1DQbWCn7IG/U1F//9oADAMBAAIAAwAAABDgPrP/xAAYEQADAQEAAAAAAAAAAAAAAAAAAREhQf/aAAgBAwEBPxCEzM6VrSH/xAAYEQADAQEAAAAAAAAAAAAAAAAAATERIf/aAAgBAgEBPxBng6UUP//EACIQAQACAAUEAwAAAAAAAAAAAAEAESExQVGxYXGh8IGR0f/aAAgBAQABPxBXSJuA0czVvE5rzGq4BJqSzkNQ4ri30wlAh1TRydpfL3s6VdZfEs4N7jucxDckRj+DDjQ2eg6/bPebE8RzPfbz/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;    2014 md 0&apos; title=&apos;&apos; src=&apos;/static/ba345ecfe1749d86484d79e8b94846cc/af061/%EC%97%AD%EB%A6%B0%2C_2014.md_0.jpg&apos; srcset=&apos;/static/ba345ecfe1749d86484d79e8b94846cc/8ccab/%EC%97%AD%EB%A6%B0%2C_2014.md_0.jpg 190w,
/static/ba345ecfe1749d86484d79e8b94846cc/af061/%EC%97%AD%EB%A6%B0%2C_2014.md_0.jpg 358w&apos; sizes=&apos;(max-width: 358px) 100vw, 358px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;한지민은 이뻤다. 이건 팩트 ㅋ~&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 스프레드, 스프레드, 스프레드]]></title><description><![CDATA[#0 서울에서는 삼성전자 주식이 5만원에 거래되고, 부산에서는 삼성전자 주식이…]]></description><link>https://jiniya.net/wp/archives/9292</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9292</guid><pubDate>Thu, 24 Apr 2014 23:59:29 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;서울에서는 삼성전자 주식이 5만원에 거래되고, 부산에서는 삼성전자 주식이 8만원에 유통된다면 우리는 무엇을 할 수 있을까? 맞다. 채소 가게를 하는 아저씨도 서울에서 삼성전자 주식을 사서는 부산에서 그 주식을 모조리 팔아 버릴 것이다. 한 주를 팔 때마다 3만원의 차익이 생기기 때문이다. 말도 안되는 이야기 같지만 통신이 발달하지 않은 예전에는 흔하게 있었던 일이다. 말 그대로 정보가 돈이던 시절이었다.&lt;/p&gt;
&lt;p&gt;하지만 통신이 발달했고 이제 더 이상 이런 말도 안되는 일은 벌어지지 않는다. 머나먼 미쿡 땅의 주식 가격도 소말리아나 대한민쿡이나 그놈이 그놈이다. 물론 요즘이라고 이런 일들이 아예 없는 것은 아니다. 우리가 인지하지 못하는 찰나의 순간을 컴퓨터가 포착해서는 이런 거래들을 성사시키곤 한다. 어쨌든 이렇게 차이가 발생하는 것을 두고 우리는 스프레드가 존재한다는 표현을 쓰곤 한다.&lt;/p&gt;
&lt;p&gt;그런데 이 스프레드가 타이밍 만큼이나 게임 보안에서는 아주 중요한 이슈 중에 하나다. 솔루션 업체 입장에서는 스프레드를 제로에 가깝게 만드는 것이 중요하다. 어떻게 이것을 줄일 것이냐를 고민해야 하고, 이 스프레드를 적게 만드는 제품이 좋은 제품이라고 할 수 있다. 기술력이 유사한 제품이라면 이 스프레드 관리가 그 제품 평판의 전부라고 할 수 있을 정도로 굉장히 중요한 요소다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_스프레드,_스프레드,_스프레드.md_0.jpg&apos; data-alt=&apos;지금 밤 하늘에 찬란하게 빛나는 것 갈지만 600만년 전의 모습일수도 있다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d64d59bb154740dc5e74d30f800ce0ee/09658/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.89473684210527%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACA//EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABAgXc1uJT/8QAGhAAAwADAQAAAAAAAAAAAAAAAAECAxESMf/aAAgBAQABBQLiRYhqE58dPR//xAAYEQACAwAAAAAAAAAAAAAAAAAAARIhUf/aAAgBAwEBPwGCZWH/xAAYEQACAwAAAAAAAAAAAAAAAAAAARIiUf/aAAgBAgEBPwGbRbT/xAAYEAACAwAAAAAAAAAAAAAAAAAAMQEgIf/aAAgBAQAGPwLJGKn/xAAcEAADAQACAwAAAAAAAAAAAAAAAREhMUFRYXH/2gAIAQEAAT8h2t0K5eCQ17ozj6IY7H5p/9oADAMBAAIAAwAAABCsL//EABcRAQADAAAAAAAAAAAAAAAAAAABETH/2gAIAQMBAT8Q0ypf/8QAFxEBAAMAAAAAAAAAAAAAAAAAAAERMf/aAAgBAgEBPxDHCx//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhMUFRYYH/2gAIAQEAAT8Q8+dmvJVsfOZWDqdMEguIpSqlrzEtJK9s/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;지금 밤 하늘에 찬란하게 빛나는 것 갈지만 600만년 전의 모습일수도 있다.&apos; title=&apos;&apos; src=&apos;/static/d64d59bb154740dc5e74d30f800ce0ee/a6335/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg&apos; srcset=&apos;/static/d64d59bb154740dc5e74d30f800ce0ee/8ccab/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg 190w,
/static/d64d59bb154740dc5e74d30f800ce0ee/ea4c8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg 380w,
/static/d64d59bb154740dc5e74d30f800ce0ee/a6335/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg 760w,
/static/d64d59bb154740dc5e74d30f800ce0ee/06dbb/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg 1140w,
/static/d64d59bb154740dc5e74d30f800ce0ee/2d81f/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg 1520w,
/static/d64d59bb154740dc5e74d30f800ce0ee/09658/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_0.jpg 2048w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;지금 밤 하늘에 찬란하게 빛나는 것 갈지만 600만년 전의 모습일수도 있다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;우라가 겪는 첫번째 스프레드는 시간 스프레드다. 무슨 이야기냐면 우리가 수집해서 관찰하는 해킹툴과 실제 게임에서 사용되는 해킹툴 사이에 존재하는 시간 차이를 의미한다. 안타깝게도 대부분의 게임 보안 업체는 게임사에서 수집한 내지는 신고 받은 해킹툴을 차단하는 패치를 만들어서 게임사에 전달하는 과정을 따른다. 별 문제 없어 보이는 이 과정속에 엄청난 함정이 숨어있다. 바로 시간이다. 왜냐하면 게임사에서 수집을 해서 게임 보안 업체에 전달을 할 정도면 사실 그 해킹툴은 버얼써 구석기시대 해킹툴일 가능성이 높기 때문이다.&lt;/p&gt;
&lt;p&gt;이 정도로 느린 속도로 해킹툴을 추적해서는 답이 없다. 그래서 조금 똑똑한 게임 보안 업체들은 사람들을 고용해서 직접 해킹툴을 찾아 나선다. 처음에는 국내 해킹툴을 수집하기 위한 아르바이트생들을 고용한다. 그러다 사이트가 늘어나면서 어라 중국에서 해킹툴이 제조되는 경우가 많네 라는 생각과 함께 중국어를 하는 친구들을 채용한다. 그런데 중국이 전부가 아니다. 태국 해킹툴을 찾기 위해서 태국어를 하는 사람을, 히브리어 해킹툴을 찾기 위해서 히브리어를 하는 사람을 고용해야 한다는 사실을 깨닫게 된다. 물론 이 모든 것이 안 하는 것보다는 좋겠지만 사실상 이런 방식을 통해서 실질적인 효과를 보기란 쉽지 않다. 더욱이 현재 게임 보안 업체가 벌어들이는 수익으로 이런 짓을 했다가는 단언컨대 곧 망한다. 물론 우리 아빠가 빌게이츤데요 하는 친구들은 예외다.&lt;/p&gt;
&lt;p&gt;그럼 어떻게 해야 할까? 백엔드 시스템을 강화해야 한다. “Writing Solid Code”란 책을 보면 저자는 그렇게 이야기한다. 버그를 찾아 나서서는 곤란하다고, 버그가 있는 즉시 우리에게 다가와서는 깜찍하게 저 여기 버그 있어요. 좀 봐주세요. 이렇게 인사를 하도록 만들어야 한다는 것이다. 시간 스프레드를 제어하기 위해서 게임 보안 업체에서 해야 하는 일도 이와 동일하다. 누군가 해킹툴을 제작하면 제가 지금 해킹툴을 제작하고 있거든요. 관심 좀 가져주세요. 이렇게 자동으로 보고가 되는 시스템을 만들어야 한다. 누군가 취약점을 공격하고 있으면 제가 지금 이 취약점을 발견해서 꿀을 빨고 있어요. 이렇게 자동으로 보고가 되고 솔루션 개발자가 적절한 조치를 취할 수 있도록 만들어져야 한다.&lt;/p&gt;
&lt;p&gt;물론 이상계에서는 이런 형태의 보고가 아닌 시스템이 자동으로 학습해서 사이트에 대한 제어 수준을 적당히 조절하는 형태로 동작하긴 할 것이다. 하지만 현실 세계에서 그 정도 수준까지 바라기는 힘들다. 그저 자동으로 문제가 있다는 사실이나 해킹툴이 어떤 방식을 통해서 제작되고 있는지만 보고 되어도 시간 스프레드를 줄일 수 있는 유용한 시스템이 된다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_스프레드,_스프레드,_스프레드.md_1.png&apos; data-alt=&apos;우리는 매 순간 모든 사이트의 보안 수준을 체크한다. 모두 AWESOME이길 바라면서…&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/7542833230304f13f7162fc09789c298/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 61.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB0ElEQVR42l1Q227aQBScld2PsJS+WulbioGmSaPcXivloconR/2CiAZC8WXZ9YXE9toLhCLo4SDaqvZoNGf2rOccYzQejZ5Hgx+Dh+8Pj4PHLT8beg9ij//8vYad2VrX62a9tVuCSU2t6uXrknhVrVZmZQu7sRujjc0ttZFPPU3WvJk33Kv7k58nV9Or2+b2ZnnTHXaDYXCWnHXGnXN5fqEu+mH/Or3ujXv9qH+ZXgY66Mle56lzl93BL3xkEIXAAlgCU4YCckCzzgDJuuDSQtQCEbzcw7E+Rgx34jqZ48wdJ3aciDlhJsiDKZlfHbdwMcSRPuJkBZEIpNiFS/58yoEpB+b/CJqogagE5XkzDx9SHwncsXA13DmcBA4NEsIlM4JLWh605LLCuxeBJ7zX3iFZCbS8c3LYMGUoHmH/F1IWlFwKhLzzN+V3EnwKxWeNLxb9CL0JuiG6MfMfESEIEUxwWuK0EB+f8ZUuV5lfKZRSrA22SxQxqKw1mgxthkqjzWFSGC5LhV8t5pVoC6ysByn9OEGciLLCfI4wRBQjisgnc6flFNywQxihLJHngk7r2oPWvlKYzURrsVggjnfXCGROp3/FHnRqDF5eBJlN4/0GjuJvy+Pci/YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;우리는 매 순간 모든 사이트의 보안 수준을 체크한다. 모두 AWESOME이길 바라면서…&apos; title=&apos;&apos; src=&apos;/static/7542833230304f13f7162fc09789c298/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_1.png&apos; srcset=&apos;/static/7542833230304f13f7162fc09789c298/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_1.png 190w,
/static/7542833230304f13f7162fc09789c298/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_1.png 380w,
/static/7542833230304f13f7162fc09789c298/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;우리는 매 순간 모든 사이트의 보안 수준을 체크한다. 모두 AWESOME이길 바라면서…&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;게임 보안 업체에서 겪는 두번째 스프레드는 보안 수준 스프레드다. 이는 비단 게임 보안에서만 문제되는 이야기는 아니다. 모든 보안 관련 요소의 가장 중요한 부분 중에 하나다. 윈도우가 왜 보안 업데이트의 디폴트 옵션을 강제 설치로 해 두었는지를 보면 알 수 있다. 허구헌날 보안 패치를 해도 사용자가 설치해서 적용하지 않으니 윈도우는 취약한 운영체제라는 오명을 쓰게 된 것이다. 게임 보안 솔루션도 이와 마찬가지다. 제 아무리 좋은 대응 좋은 기능을 만들어도 고객에게 적절한 속도로 공급되지 않으면 무용지물이다.&lt;/p&gt;
&lt;p&gt;이런 이야기를 하면 으레 듣는 소리가 그게 뭐가 힘든가요, 기능 만들기가 어려워서 그렇지 고객에게 공급하는거야 그냥 뿌리면 되는 거 아닌가요, 라는 이야기들이다. 한번도 B2B로 뭔가를 해본 적이 없는 사람들이 하는 소리다. 이게 생각보다 쉽지 않다. 특히나 사이트가 한두군데일때야 쉽겠지만 100개, 200개, 1000개, 2000개가 되면 전혀 다른 문제가 된다. 우선은 그 많은 사이트에 동일하게 기능을 제공하는 것도 어려울 뿐더러 보안 패치를 업데이트 하지 않는 사용자처럼 적용하지 않는 업체들도 많기 때문이다. 이는 정말 어떤 기술적인 문제가 아니라 전적으로 해당 업체를 지원하는 지원 담당자의 역량에 따른다.&lt;/p&gt;
&lt;p&gt;그럼 지원 담당자들을 쪼으면 되지 않냐는 이야기도 할 법한데 이게 전혀 다른 문제다. 패치를 전달하는 것과 고객이 그 패치를 적용하게 만드는 것에는 하늘과 땅 만큼의 차이가 있기 때문이다. 패치를 전달하는 거야 누구나 할 수 있지만, 고객이 적용하게 만드는 것은 누구나 할 수 있는 문제가 이니다. 볼펜 하나를 던져주고 그것을 팔아보라는 문제와 동일하다. 팔 수 있는 사람과 그렇지 않은 사람이 있는 것이다. 여튼 이 문제에 있어서는 전적으로 훌륭한 지원 담당자를 채용하는 것 외에는 답이 없다.&lt;/p&gt;
&lt;p&gt;그렇다고 결국 지원 담당자의 역량이니 손놓고 있으면 된다는 생각은 곤란하다. 모든 세부 사항이 다 그렇겠지만 추적 관찰 가능한 상태에 있는 것과 그렇지 않은 것에는 천지 차이가 있기 때문이다. 그렇다고 이걸 일일이 사람한테 시켜서 수동으로 만드는 것도 문제가 있다. 백방 오류가 발생하고 수집 시간이 더디기 때문이다. 모든 사항이 자동으로 추적 관찰 되도록 만들어야 한다. 그래야 모두가 현재 우리 서비스 품질 수준에 대해서 정확하게 인지할 수 있고 어떤 곳을 어떻게 더 강화해야 하는지를 판단할 수 있다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_스프레드,_스프레드,_스프레드.md_2.png&apos; data-alt=&apos;160개가 넘는 옵션들. 이 값들에 따라 깡통이 되기도 하고, 이지스함이 되기도 한다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 604px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b1433adc03d25a4840ac0fed47183a00/1994c/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 55.78947368421052%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABx0lEQVR42k2Si46jMAxF+ZOZTglpaSEP8iCEEJ5DoVBm9v8/Zg3VSitdWVEk29fHDtBjJtqlRIui1M6rsoJHKtTXJQZ9Rpd7JnXlGbkZigTFikaSRIJgQaIgfK7ajbnq+nkd19e0/UK0TZtk8ny9fSAsbfV4/XgVL/qzl2ErQ4idPPfyHITzwkxNmTG+KdveNl1RtyCe24RL6JwKXTStYLHjYc4i6GxYVOxCe2duGsaKwreQDCVs3Vb9t3JVGN8gmUgN/5rHdXY2DEGm5ajk6Eiel/9tj+sG+l5eVTeE8f2f7Q1sv/Ld9gBSEM+j2m2vqXYJUcBJWgfM4IHvBGjBzDswnklbMhJriliKebqjgpilOADawvZSeN+PzTh1j7mbnmBeGPumzU3RTnMh4l58+QyBqiPWGYLkJzc14wWM6rredUNmLFX5nYsTvkIyhZm7QR0zA6ec7qiKY+wALSvNPaE5bBgaGl+D7UtCr4ThJD1oK/jPaFwylB9L1nQvAeTfwB4AbJjXefszb7/T9qOsg844IR9hBEUf277npz4dGw4B1VsBmhaSV3Bhb1r7kn1DlYaeJxyf8HFhzmcsBrcASaTHkVE4sugvTtOLiPAfcUMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;160개가 넘는 옵션들. 이 값들에 따라 깡통이 되기도 하고, 이지스함이 되기도 한다.&apos; title=&apos;&apos; src=&apos;/static/b1433adc03d25a4840ac0fed47183a00/1994c/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_2.png&apos; srcset=&apos;/static/b1433adc03d25a4840ac0fed47183a00/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_2.png 190w,
/static/b1433adc03d25a4840ac0fed47183a00/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_2.png 380w,
/static/b1433adc03d25a4840ac0fed47183a00/1994c/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_2.png 604w&apos; sizes=&apos;(max-width: 604px) 100vw, 604px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;160개가 넘는 옵션들. 이 값들에 따라 깡통이 되기도 하고, 이지스함이 되기도 한다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;마지막 스프레드는 옵션 스프레드다. 우리는 프로그래머가 많지 않고, 코드를 매번 새롭게 컴파일하는 것에는 위험 부담이 따른다는 것을 일찍이 알고 있었기에 대부분의 기능들에 대해서 옵션 처리가 되도록 만들었다. 요즘은 그 정도가 더 심해져서 기능이 있는 곳에 옵션이 있어야 한다는 주의로 만들고 있다. 어쨌든 풍부한 옵션은 프로그래머가 직접 개입하지 않아도 특정 문제들을 빠르게 해결할 수 있는 가능성을 제공한다는 장점이 있다.&lt;/p&gt;
&lt;p&gt;하지만 항상 포스의 어두운 면과 밝은 면이 공종하는 것처럼 이 또한 장점만 있는 것은 아니다. 옵션을 제어하는 사람이 충분히 숙련된 엔지니어라면 문제가 없겠지만 옵션 사항의 정확한 동작 구조에 대해서 잘 모르는 담당자라면 문제가 심각해진다. 왜냐하면 그 친구가 패치 생성 시에 옵션을 어떻게 지정했는지에 따라 제품이 깡통이 되기도 하고 이지스함이 될 수도 있기 때문이다. 더욱이 자동화된 추적 장치가 없다면 담당자 입장에서는 자신이 옵션을 변경했었다는 사실을 까먹는 경우도 많다.&lt;/p&gt;
&lt;p&gt;옵션 사항에 대해서도 스프레드가 자동으로 관리될 수 있도록 담당자가 패치 빌드를 생성하면 매번 어떤 옵션 설정이 잘못되어 있음을 자동으로 노티해 주는 장치가 필요하다. 더불어 모든 사이트의 옵션 사항들에 대해서 일괄되게 추적할 수 있는 시스템을 가지는 것이 중요하다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;맥도날드가 전 세계에서 가장 유명한 햄버거 가게가 된 비결은 딱 두 가지라고 한다. 하나는 서울의 빅맥과 뉴욕의 빅맥의 맛이 납득할 수 있는 범위 내에서 동일하다는 것, 다른 하나는 어떤 바보가 오더라도 맥도날드의 프로시저대로만 하면 유사한 품질의 빅맥을 만들어 낼 수 있다는 점이다. 분야는 다르지만 맥도날드는 스프레드를 잘 제어해서 균등한 품질의 제품을 생산했기 때문에 성공했다고 할 수 있다. 게임 보안도 다르지 않다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_스프레드,_스프레드,_스프레드.md_3.png&apos; data-alt=&apos;해킹툴을 어떻게 숨기나요?&lt;br&gt;&lt;br&gt;해킹툴을 실행하고 XIGNCODE3가 못보게 종이로 가리세요 ㅋㅋ&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 540px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0547e138bf79f7f0c1d38764434e67fa/03ec9/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 111.05263157894738%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAE+0lEQVR42m2S+09TZxjHz3+w7If9NGPigiTb3A9iNmacZg4BUVEqCqIUgXIpDLquLb1AaWlLW057Ts/99Jz2nN5BQBEGw8uWDI3YTpgGGcaQbV6WCbS02ovg9hM7uF/35vu+7/O8ySffvM/zAM+fPXv65ElqPZEUlFxfTyTSL1PCHY+vCvttlIjH15KJxPbTymoul93YeL25uSEISK5Fnz+dXX4cffJHLBF/uLqysLq6uBZfWltdjK8tJpOP1hOP1lYWXsYfCel6/Nf0q+Vs+vdU6nEmswykf4s+/fnHcDDC8EFfaGhoaOTP+7eWpkODFgVjlFEQhDgQ54Cz39Sv1XXrDXqJVKJUtQ+HqPnYDDDM+8YDlzg6YLLRaiNGwux1l5VXNNtqymXHD7eL21ob1fUXOqpOS0pKq8qOV32097Pi0mLUYbl5bRowWUGbg3ahPOjiLE6vEFgbxeoTR6CGatmxooZjFVKprkmiaGlRSjvVFy627i08UFRSgsK2H65/D3TpTToLZoO8VqfXBvFjo1NjfEDfVG84L+o8VdZSIeqSa7Vqg77X0md1KLr0rW0yO+icmLg6dy8KyNU9mn7cCnOmAXYA8V+bmL45dcNPkiZpg1JcbVIrYVs/4nRgLhjHcDfNhEKDS4tLW1tbKysvgDa5SmVCLIjPCHrsqH9qfHpy7LvhQBiz26w9OtjaD4MO2OF0QRCKIBiG4wRF0p6ZW3disSggaZfJeyEz4uuDeBAPTVyZHB8eG/SFOMpNuhAcglEHhDghBIYQxIWhGEGQbjdLuVmjxQKIm6Qd3Q4zGuyDAg5icGx4bDQ8HPGFfCxHYwSJ4jiMIhCMCD2DYdTlQhFU4CEIFlXXAFV1Dc1dViPs15pBEA2OhkcuBSIhzs8zXkbwIGkKp3EER2HXW23zJEGYzeZ9+w8AovO1YpnRCPnVZtIO+wVyyB8KeP0sxbC0INZNMds8SmAuFHMhAkwRhE6nzfv4E+DUufPiDr0RCioNhNXBR/hgxBfwulmO8XAs53F73JSHJhmSoAmMxIR/Q04SRzs7O3buzgfKq6rPNCp6Qd+3PbjF7g1z/jDvD3A87+W9LMe6PQz9H+zGcQpxCV0DCQxtbGrckZcHlJ+tOlkj1Vs9cg1ssjAB1hfkfD6B9HAexrsNC+Y0S1MMIZgTJIaiJIGdPVedv2cPcPLMmaMV4h4T/Y3KYTASPoYT6sy/9aQIt1AdcAA194EateHrDlWtuKGotLTw4MGd+fknReXAidOnDx6p1OhRuWpA2+1ygqTdivUZYJ1uQKm0dHb0NkvUdbUykai+7Gh1QcGBnXm79hUWFB8tMhk1QHll5f7D5QotKFP0d2kcKrVTqbTL5QJmaJd2tzarGy/Ka2vaRBV1ZaVVBQWf7/4w/2JdJWjthh0m4FBJ8Qd7CiXS7jqJskXaLW3raWnRNEm66uvkF2raKivqy0qrS49UHvri+KcFX72/Y9e7771zqvxLrUrap1cCFOM29w8MDV6NhC8PRa5cvjQxMnR1RJi00GjQG/bRPEtzFOFBEbcTxHp7jboejddDCDM8PTUG/DNz+83Cwsa9e2/mf9mYm0vPzmajsczdaDYW25yfz8zN/z3z09bm5tb/LWD52o3745MPJ6cXp64L5/Pbd/6ajQp6cTeWuv8g+eDBq7m5XCqVzeUymWw6nclk0tmskOVe53L/AgC4+mU7zvqcAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;해킹툴을 어떻게 숨기나요?&lt;br&gt;&lt;br&gt;해킹툴을 실행하고 XIGNCODE3가 못보게 종이로 가리세요 ㅋㅋ&apos; title=&apos;&apos; src=&apos;/static/0547e138bf79f7f0c1d38764434e67fa/03ec9/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_3.png&apos; srcset=&apos;/static/0547e138bf79f7f0c1d38764434e67fa/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_3.png 190w,
/static/0547e138bf79f7f0c1d38764434e67fa/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_3.png 380w,
/static/0547e138bf79f7f0c1d38764434e67fa/03ec9/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_3.png 540w&apos; sizes=&apos;(max-width: 540px) 100vw, 540px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;해킹툴을 어떻게 숨기나요?&lt;br&gt;&lt;br&gt;해킹툴을 실행하고 XIGNCODE3가 못보게 종이로 가리세요 ㅋㅋ&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_스프레드,_스프레드,_스프레드.md_4.png&apos; data-alt=&apos;온라인과 모바일 환경에서 모두 효과성이 검증된 게임 보안 솔루션은 XIGNCODE3가 유일합니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 566px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a97136d8c92264184be42a15cfa5aabd/7ef45/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 46.8421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABaUlEQVR42n1RXUvDQBDM//8vPkihWKyCLYViHiohfbASmvbS3FfucjFtLl+9OEYU9MFhGZa7253ZPe9C04IcLpQ2UtZCWM4RndbDMCilNptNEATb7TYMQ7DWum3b4Rve++3taT4/3d3tJxMyne5ubvRy6Z6eBudMUfi+v1qtUBlFUZZlw294TojrGD2Y855z5G58Z61NkiTP87Isodn3/d/i0tqqd0a1/flS9Z1t20tdn629Xq8mz992u0xKKUSulFYq1xoJDtCr6zqvMIZRylKWEsIY44xBB57RuKqqmJCU8zhJqJQJY+ATY+mIuq69pmm+XGEkzjkYPqFWwXSWva7XxyDYPT8nYfjm+/HLyz4I9lGEdcCah/aoFEJQSgkhqIf+IY7LpmnXazad0sfHZDZjDw/p/f1xNjsvFsPX5pzzIAs1/AoEwehijMEsn9fGOCkHrZ1Sv+L7tzw8heBpRFEUP5t049j/4wNEJfJ3IWpQ5gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;온라인과 모바일 환경에서 모두 효과성이 검증된 게임 보안 솔루션은 XIGNCODE3가 유일합니다.&apos; title=&apos;&apos; src=&apos;/static/a97136d8c92264184be42a15cfa5aabd/7ef45/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_4.png&apos; srcset=&apos;/static/a97136d8c92264184be42a15cfa5aabd/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_4.png 190w,
/static/a97136d8c92264184be42a15cfa5aabd/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_4.png 380w,
/static/a97136d8c92264184be42a15cfa5aabd/7ef45/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C%2C_%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C.md_4.png 566w&apos; sizes=&apos;(max-width: 566px) 100vw, 566px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;온라인과 모바일 환경에서 모두 효과성이 검증된 게임 보안 솔루션은 XIGNCODE3가 유일합니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GCC 공유 라이브러리 심벌 문제 (Draft)]]></title><description><![CDATA[몇해전에 boost의 ABI와 관련된 글을 적은 일이 있다. http://www.jiniya.net/wp/archives/7543 그때 우리는 문제를 -Dboost=boost2로 해결을 했는데 최근에 동일한 문제가 발생했다. 이번엔 boost…]]></description><link>https://jiniya.net/wp/archives/12820</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12820</guid><pubDate>Fri, 04 Apr 2014 23:59:28 GMT</pubDate><content:encoded>&lt;p&gt;몇해전에 boost의 ABI와 관련된 글을 적은 일이 있다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/7543&quot;&gt;http://www.jiniya.net/wp/archives/7543&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;그때 우리는 문제를 -Dboost=boost2로 해결을 했는데 최근에 동일한 문제가 발생했다. 이번엔 boost 같은 외부 라이브러리가 아닌 libstdc++.so라는 G++ 공유 라이브러리가 문제였다. 대다수 업체는 libstdc++.so.6을 사용하는데 한 업체에서 아주 오래된 libstdc++.so.5를 사용하면서 문제가 생긴 것이다.&lt;/p&gt;
&lt;p&gt;libstdc++.so.5와 libstdc++.so.6은 ABI가 호환되지 않는다. &lt;a href=&quot;http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html&quot;&gt;http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;그래서 이번에 이 문제에 대한 근본적인 원인에 대해서 파헤쳐 보게 되었다. 근본적인 원인은 boost 글에도 있는 것처럼 심벌을 다른 so 파일에서 찾는 것이 문제다. 간단한 예제를 만들어서 테스트 해 보자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;a.cpp 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Foo in liba.so\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BarA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;BarA in liba.so\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;b.cpp 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Foo in libb.so\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BarB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;BarB in libb.so\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;main.cpp 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BarA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BarB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;BarA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;BarB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 아래와 같이 컴파일을 해보자&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;g++ -shared -o liba.so a.cpp
g++ -shared -o libb.so b.cpp
g++ -L. -o main main.cpp -la -lb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 553px; margin-bottom: 16px;&apos; data-url=&apos;./GCC_공유_라이브러리_심벌_문제_(Draft).md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/52c074f163958dad3d0d5923458ee8ed/d35da/GCC_%EA%B3%B5%EC%9C%A0_%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC_%EC%8B%AC%EB%B2%8C_%EB%AC%B8%EC%A0%9C_(Draft).md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 32.631578947368425%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABJ0lEQVR42mPIWPE+HYwyV31MW/IicdaNhJnXE2fdTJ57N3nevaTZt5Nn306adQsoDpTNWv0pY8W71IWPF5b0r8ltZIhILYnOqg1OKvaOyg6Mz3cNSfaPyXUJTLD1jrL3jbHziYYje784B/8EB/94e/8E58CE6WuOMLg7WgUH+AX4eJoZ6Rnoahnp6hjr6xrqaRvqaYGRNhwZ6GoCkaGulr6OprG+5prNOxk8XF38A4N8fP2srKwtzC2N7UyMzIyNjU2NTXAiI2NTMzPTlZv2MLg6O3p6+Tg7u9jZOzg7uhj7mBhaEaHZ1GT15r0MOqpyetrqelpq+trq+tpqBpoaBtoaBjr4kL62hrGu+uIVaxmcQjKcI/Kcw3OhKIwwcgrNdYvI7Vl2EAAcyoYrvbYALgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;GCC                 Draft  md 0&apos; title=&apos;&apos; src=&apos;/static/52c074f163958dad3d0d5923458ee8ed/d35da/GCC_%EA%B3%B5%EC%9C%A0_%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC_%EC%8B%AC%EB%B2%8C_%EB%AC%B8%EC%A0%9C_(Draft).md_0.png&apos; srcset=&apos;/static/52c074f163958dad3d0d5923458ee8ed/08678/GCC_%EA%B3%B5%EC%9C%A0_%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC_%EC%8B%AC%EB%B2%8C_%EB%AC%B8%EC%A0%9C_(Draft).md_0.png 190w,
/static/52c074f163958dad3d0d5923458ee8ed/2edd7/GCC_%EA%B3%B5%EC%9C%A0_%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC_%EC%8B%AC%EB%B2%8C_%EB%AC%B8%EC%A0%9C_(Draft).md_0.png 380w,
/static/52c074f163958dad3d0d5923458ee8ed/d35da/GCC_%EA%B3%B5%EC%9C%A0_%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC_%EC%8B%AC%EB%B2%8C_%EB%AC%B8%EC%A0%9C_(Draft).md_0.png 553w&apos; sizes=&apos;(max-width: 553px) 100vw, 553px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;결과를 보면 libb.so의 BarB에서 호출하는 Foo가 libb.so에 있는 Foo가 아닌 liba.so에 Foo로 링크된 것을 알 수 있다. 티끌만한 것도 찾아서 공유하는 정신이 GNU 스럽다고 할 수 있겠지만 심벌 이름이 충돌 나는 경우에는 여간 성가신 문제가 아닐 수 없다. 특히나 boost 같이 우리가 컴파일 하는 경우에는 -Dboost=boost2같은 꼼수라도 쓰겠지만 컴파일 할 수 없는 심벌인 경우에는 문제가 많아진다.&lt;/p&gt;
&lt;p&gt;물론 GNU 애들도 바보가 아닌 이상 이런 문제가 굉장히 성가시다는 걸 몰랐을 리는 없다. 그래서 만들어진 -Wl,-Bsymbolic 이라는 마법같은 옵션이 있다. so 파일을 링크할 때 저 옵션을 넣어주고 링크하면 so 파일 내의 심벌을 먼저 참조하도록 설정된다.&lt;/p&gt;
&lt;p&gt;참고할만한 글&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://bottomupcs.sourceforge.net/csbu/x4012.htm&quot;&gt;http://bottomupcs.sourceforge.net/csbu/x4012.htm&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 사설 서버 대응 전략]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/2014/01/strategy-for-dealing-with-private-servers/</link><guid isPermaLink="false">https://jiniya.net/2014/01/strategy-for-dealing-with-private-servers/</guid><pubDate>Fri, 14 Mar 2014 23:59:27 GMT</pubDate><content:encoded>&lt;p&gt;어느 분야나 난제 혹은 미제 같은 문제들이 항상 있기 마련이다. 이런 문제들은 새롭게 도메인에 접근하는 이들에게는 자신의 존재감을 증명할 수 있는 새로운 기회로 다가가기도 하고, 기존에 그 분야에 일하는 종사자들에게는 혹 같은 느낌이기도 하고, 실제로 피해를 당하는 입장에서는 골치 덩어리이기도 하다.&lt;/p&gt;
&lt;p&gt;게임 보안 분야에서는 사설 서버 혹은 무료 서버라고 불리는 것들도 이런 문제 중에 하나다. 현재까지 해당 문제에 대해서 이렇다 할만한 뚜렷한 대응책도 존재하지 않고, 문제가 발생해 버리면 사실상 통제하기도 힘든 상태다. 그렇다고 사설 서버 문제가 심각하지 않은 것도 아니다. 일부 유명 게임의 경우에는 사설 서버가 웬만한 정식 게임 서비스보다 규모가 더 큰 경우도 심심찮게 존재한다.&lt;/p&gt;
&lt;p&gt;사설 서버란 정식으로 인가 받지 않은 사람 또는 회사가 게임을 불법적으로 서비스하는 행위를 말한다. 사설 서버는 어찌 보면 온라인 게임이란 서비스와 그 유래를 같이 한다고 볼 수 있다. 온라인 게임의 초창기에 유행했던 사설 서버 중에 하나로 프리 배틀넷이 있다. 초창기 배틀넷은 스타크래프트란 게임을 구매한 사용자들끼리 인터넷을 통해서 같이 게임을 즐길 수 있도록 만들어주는 중계 서버 역할을 했다. 배틀넷에 접속하기 위해서는 게임을 구매한 내역에 해당하는 시디키라는 것이 있어야 한다. 시디키가 없다면 불법 복제로 간주되어 배틀넷 서버에 접속할 수가 없다. 불법 복제가 만연하던 시절, 불법 복제 사용자들의 배틀넷 욕구를 채워준 것이 프리 배틀넷이다. 프리 배틀넷은 스타크래프 제작사인 블리자드가 운영하는 것이 아닌 개인이 임의로 서버를 구축해서 운영하는 사설 서버였기 때문에 불법 복제 시디로 게임을 하는 사용자도 접속할 수 있었다.&lt;/p&gt;
&lt;p&gt;초창기 사설 서버는 프리 배틀넷과 마찬가지로 이윤 창출 보다는 개인의 호기심과 참을 수 없는 무한 공유 정신에 그 기반을 두고 있다. 그렇기에 이윤과는 무관한 경우가 많았고 운영 또한 영세하게 이루어지는 경우가 많았다. 하지만 요즘의 사설 서버는 이런 초창기 목적과는 많이 달라졌다. 대부분 영리를 목적으로 유료로 운영하는 경우가 많고, 규모 또한 경우에 따라서는 무척 크기도 하다. 게임사 입장에서는 당연히 정식 서비스로 유입되어야 하는 트래픽을 사설 서버에게 뺏기는 셈이 되기 때문에 상당한 피해를 본다고 할 수 있다. 프리 배틀넷의 경우에도 영세한 규모이긴 하지만 블리자드 입장에서는 시디 구매로 이어져야 할 수요가 프리 배틀넷의 존재 때문에 연결되지 않았기 때문에 일정부분 피해를 입었다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 이렇게 게임사의 골치를 썩이는 사설 서버는 도대체 왜 생겨나는 것일까? 자본주의 사회에서 벌어지는 모든 나쁜 문제들이 그렇겠지만 이 또한 그 근본적인 원인에는 ‘돈’이 있다. 불법적으로 손쉽게 돈을 벌려고 하는 사설 서버 운영자, 그들에게 바이너리 파일이나 소스 코드를 유출시켜 부당한 이윤을 취득하고 싶어하는 게임 퍼블리셔나 게임 개발사의 관계자, 정식 서비스의 비싼 컨텐츠 사용료를 감당하지 못하기에 보다 저렴한 비용으로 컨텐츠를 체험해 보고 싶어하는 사용자 들의 이해관계가 복잡하게 얽혀서 사설 서버 생태계는 유지된다.&lt;/p&gt;
&lt;p&gt;그렇다면 무료 사설서버야 그렇겠지만 유로로 운영하는 사설 서버는 어떻게 유지되는 것일까? 게이머 입장에서는 어차피 굳이 비용을 지불해야 한다면 합법적인 서비스를 이용하는 편이 마음도 편할 테니 말이다. 여기에도 정말 다양한 이유가 있다.&lt;/p&gt;
&lt;p&gt;첫째는 가격이다. 유료로 운영한다고는 하지만 정식 서비스 보다는 훨씬 저렴한 비용으로 즐길 수 있는 경우가 대부분이다. 이는 사설 서버의 경우에는 정식 서비스만큼 충분한 수의 운영 인력을 유지할 필요도 없고, 정식 서비스의 인기에 편승해서 운영하는 것이기 때문에 별도로 마케팅 비용을 지출할 필요도 없다. 그리고 가장 중요한 문제이지만 사설 서버 운영자는 게임 컨텐츠 개발에 투입되는 비용 중 단돈 1원도 지불하지 않았기 때문에 정식 서비스보다는 훨씬 저렴하게 운영해도 유지가 되는 것이다.&lt;/p&gt;
&lt;p&gt;둘째는 접근 가능한 컨텐츠의 범위다. 정식 서비스에서는 제공하지 않은 게임 마스터가 사용할 수 있는 아이템을 사용해 볼 수 있다거나, 정식 서비스에서는 절대로 불가능한 터무니 없는 능력치의 아이템이나 이동 불가능한 지역과 갈은 컨텐츠를 사용해 볼 수 있다. 심지어는 드물긴 하지만 사설 서버가 정식 서비스보다 더 빠르게 신규 컨텐츠를 제공하는 경우도 있다. 말이 안 되는 것 같은데, 이게 가능한 이유는 게임사에서 대규모 패치를 하기 전에는 일반적으로 일정 기간 전부터 관련 컨텐츠 파일을 조금씩 클라이언트에 미리 전달하는 경우가 있기에 가능하다. 이렇게 미리 전송된 클라이언트 정보를 분석해서 사설 서버에서 컨텐츠를 먼저 오픈해 버리는 것이다.&lt;/p&gt;
&lt;p&gt;끝으로 대다수 경우는 아니지만 정식 서비스보다 더 나은 운영 품질을 사설 서버가 제공하기에 그곳에서 게임하는 사용자들도 존재한다. 정식 서비스의 경우에는 아무래도 규모가 크다 보니 소규모 커뮤니티와 같은 친밀감은 느끼기가 힘들다. 하지만 사설 서버는 상대적으로 사용자가 적기 때문에 운영자와 유대감을 형성하기가 훨씬 더 쉽다는 측면이 있다.&lt;/p&gt;
&lt;h3&gt;사설 서버의 탄생 배경에 따른 대응 전략&lt;/h3&gt;
&lt;p&gt;사설 서버가 무엇인지 그리고 그 생태계가 어떻게 구성되는지에 대해서 살펴 보았다. 지금부터는 기술적으로 사설 서버가 만들어지는 경로에 대해서 살펴보도록 하자. 이 내용을 이해하는 것은 무척 중요한 문제인데, 왜냐하면 생성 경로에 따라서 대응 전략도 달라져야 하기 때문이다. 사설 서버는 크게 세가지 정도의 경로를 통해서 만들어진다.&lt;/p&gt;
&lt;p&gt;첫째는 서버 바이너리 파일이 유출되는 경우다. 여기에도 세부적으로 유출되는 여러 가지 요인이 있다. 게임 개발사나 게임 운영사의 관계자가 유출시키는 경우, 바이너리 파일이 담겨 있는 서버가 해킹 당해서 해커에 의해 탈취되는 경우, 심지어는 게임 서버 자체가 물리적으로 도난 또는 교체되는 경우도 있다.&lt;/p&gt;
&lt;p&gt;바이너리 유출을 원천적으로 차단할 수 있는 방법은 없다. 인재의 경우는 각종 보안 장치들을 강화해서 절대 그런 일이 없도록 만들겠다는 의지를 불태울 수 있겠지만 미봉책에 불과할 뿐이다. 왜냐하면 누군가는 반드시 파일에 접근해서 작업할 수 있는 높은 권한을 가질 수 밖에 없기 때문이다. 그런 사람이 나쁜 마음을 먹는다면 얼마든지 사고는 벌어질 수 있다. 따라서 사람을 거쳐서 유출되는 것을 원천적으로 차단한다는 것은 불가능에 가깝다. 서버 머신의 물리적인 도난도 자연재해와 마찬가지로 벌어진다면 그걸 피할 방법은 사실상 없다. 그나마 대응할 수 있는 영역이 해킹을 해서 파일을 탈취하는 행위다. 이 경우는 각종 보안 시스템을 강화해서 일정 수준 이상의 보안 수준을 유지함으로써 어느 정도 대비를 할 수 있다.&lt;/p&gt;
&lt;p&gt;바이너리 파일 유출의 경우 사전에 방지할 수 있는 근본적인 방법은 없기 때문에 파일 유출이 벌어지더라도 의미가 없도록 만드는 사후 대응 전략이 보다 효과적이다. 인가되지 않은 곳에서 바이너리 파일을 들고 가서 서버를 켜더라도 정상적으로 동작하지 않도록 만드는 것이다. 이런 전략의 하나로는 게임 서버에 대한 인증 서버를 두는 방법이 많이 사용된다. 게임 서버가 별도의 인증 서버의 인증을 통과해야만 동작하도록 만드는 것이다. 통상적으로 이러한 인증 서버를 마스터 서버라고 부른다. 마스터 서버가 단순한 온/오프 식의 인증 처리만 해서는 사실상 소용이 없다. 파일을 탈취할 정도라면 그 정도 인증은 손쉽게 무력화 시킬 수 있기 때문이다. 그보다는 좀 더 복잡한 대응이 필요하다. 일반적으로는 게임 서버 구동에 필요한 각종 데이터를 마스터 서버에 의존하도록 만드는 방법을 많이 사용한다. 해당 데이터는 마스터 서버와의 인증이 되는 순간 마스터 서버로부터 전송을 받고 파일로 기록은 하지 않는 형태로 구성해야 한다. 그래야 실질적으로 바이너리 파일 유출에 대한 통제를 할 수 있다. 물론 이 경우에도 마스터 서버가 가지고 있는 데이터 셋이나 마스터 서버의 바이너리가 똑같이 다 유출된다면 막을 방법은 없다. 하지만 마스터 서버의 경우 서버간 통신만 발생하기 때문에 서버 자체를 게임 개발사에서 보유할 수 있다는 점 때문에 유출의 위험성이 일반 게임 서버 보다는 훨씬 낮다는 정도로 생각하는 것이 좋겠다.&lt;/p&gt;
&lt;p&gt;두 번째 유출 경로는 소스 코드가 유출되는 경우다. 이 경우도 바이너리 유출과 마찬가지로 사람을 통해서 유출되는 경우가 있을 수 있고, 해커에 의해 탈취 당하는 경우가 있을 수 있다. 소스 코드 유출이기 때문에 앞선 바이너리 유출 보다는 상황이 더 심각하지만 안타깝게도 앞선 바이너리 유출과 마찬가지로 원천적인 차단 방법은 존재하지 않는다. 이 경우에 할 수 있는 사후 대응은 서버의 구조를 확 변경하는 작업이지만 이 또한 쉽지 않다. 사전에 예방할 수 있는 방법으로는 소스 코드를 분산 배치 시키는 방법을 들 수 있다. 해커가 소스 코드를 탈취하더라도 게임 서버의 전체 코드가 아닌 일부 코드가 되도록 만드는 것이다.&lt;/p&gt;
&lt;p&gt;마지막 생성 경로는 말 그대로 해커들의 리버싱을 통해서 만들어지는 경우를 들 수 있다. 클라이언트와 해당 클라이언트가 정식 서버와 통신하는 내용을 토대로 상상에 나래를 펼쳐서 서버를 바닥부터 직접 제작하는 것이다. 이렇게 무식하게 만드는 경우가 있을까 싶지만 오래된 게임들의 경우는 상당 시간 동안 분석이 진행되기 때문에 이렇게 직접적으로 모두 제작한 사설 서버가 나오기도 한다. 이런 서버는 게임 서버의 상태가 불안정하다는 점과 정식 게임 서버는 윈도우 기반인데 사설 서버는 리눅스 기반으로 만들어지는 경우와 같이 정식 게임 서버와는 전혀 다른 플랫폼으로 제작되는 경우가 있다는 점이 특징이다.&lt;/p&gt;
&lt;h3&gt;사설 서버와 보안 코드&lt;/h3&gt;
&lt;p&gt;현대적인 게임 제작에는 천문학적인 금액이 투입되는 만큼 보안에도 철저하게 신경을 쓰는 추세로 바뀌고 있다. 다양한 보안 장벽을 통해서 물리적인 보안에 대해서 강화를 해 나가는 동시에 게임 프로그램 자체의 보안에도 많은 신경을 쓴다. 그러다 보니 자연스럽게 외부 보안 코드를 사용하기도 하고, 내부 개발팀에서 제작한 보안 코드를 사용하기도 한다. 그러다 보면 게임 프로그래머 입장에서는 자연스럽게 왜 그런 코드들을 통해서 사설 서버에 대응할 수 없는지 궁금증이 생긴다. 여기에는 기존 보안 코드 체계가 가진 구조적인 특징에 기인한다고 할 수 있다. 사설 서버가 만들어지는 자세한 과정을 통해서 왜 기존 보안 코드 체계가 사설 서버에 대응력을 가지지 못하는지에 대해서 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 1&gt;에는 일반적인 온라인 게임 구조가 나와 있다. 게임 클라이언트가 있고, 네트워크를 통해서 게임 서버에 접속해서 게임을 하는 구조의 많은 게임들이 &amp;#x3C;그림 1&gt;과 같은 구조로 동작한다. 요즘은 여기에다 별도로 추가적으로 외부 보안 솔루션 코드나 게임사에서 개발한 자체 보안 코드를 추가하는 작업을 한다. 그렇게 하면 &amp;#x3C;그림 2&gt;와 같은 구조로 게임 구성이 변경된다. 기존의 게임 클라이언트/서버에 각각 보안 코드와 인터페이싱하는 부분이 추가되어 있다.&lt;/p&gt;
&lt;p&gt;게임 클라이언트에 추가된 보안 코드는 각종 해킹툴 탐지, 게임 클라이언트의 무결성 검증, 정상적인 게임 서버와 통신을 하는지에 대한 체크 등을 수행한다. 게임 서버에 탑재된 보안 코드는 게임 서버가 정상적인 게임 클라이언트와 통신을 하고 있는지에 대한 인증을 수행한다. 각각의 코드를 통해서 우리는 게임 클라이언트와 서버 모두에서 양쪽을 검증할 수 있는 체계를 갖출 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private1.png&apos; data-alt=&apos;그림 1 일반적인 게임의 클라이언트/서버 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0e32958ce95f241a75ae18d1a3402769/f537a/private1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 14.210526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAvUlEQVR42mNwVAj7H2qe8T/du+K/h0bsb3eVuP8uyhFTGYAglCGUmQEJ2Nvbs4BokLyHavx/N7Xo36leZf/DLbP+OyqE/3dRifzP4KQYDhZI8yr/760dDzUwcqK3XJSgi2q4pqtajKKzapQSiHZUjtC21wrlcVGKnOQBVOejkwA2MNouD6QHjBlARJhF5v9k99L/XppxKC60l4/nMDZOY4VhC4tQTpgL3ZXj/vsbJP9Ociv5HwM00FUlCmwgAGzZUW7Y6ErvAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 1 일반적인 게임의 클라이언트/서버 통신 구조&apos; title=&apos;&apos; src=&apos;/static/0e32958ce95f241a75ae18d1a3402769/efd7b/private1.png&apos; srcset=&apos;/static/0e32958ce95f241a75ae18d1a3402769/08678/private1.png 190w,
/static/0e32958ce95f241a75ae18d1a3402769/2edd7/private1.png 380w,
/static/0e32958ce95f241a75ae18d1a3402769/efd7b/private1.png 760w,
/static/0e32958ce95f241a75ae18d1a3402769/dc896/private1.png 1140w,
/static/0e32958ce95f241a75ae18d1a3402769/78873/private1.png 1520w,
/static/0e32958ce95f241a75ae18d1a3402769/f537a/private1.png 1730w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 1 일반적인 게임의 클라이언트/서버 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private2.png&apos; data-alt=&apos;그림 2 게임 보안 적용 후의 클라이언트/서버 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a2bd2149d0b9c04a82568c038d7a19de/f537a/private2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 41.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbElEQVR42p2Pz0sCQRTH3+aakIeiIDNjq7U1TaWDBFsXI130EFHUqrithkalKUKFRUUDHTp16N9wDOyv61A7vXa2H7eQ/MKHefMd3ve9AQRgKEkMYzGG8TjDSOTd9tAC0AFRMKe3J5Kz5TFOatqcSAIRtYXCnhYsYiZkvFezF8xcb7GUnGfpYIEBb0ZRRAyHEaNRRK+Xce91yF2ANB3V5U1pQ9EDnLSsS+qSPp4JlXJZ5QA3Y9WP+tYtVrQ2ZpSSAw+kKAgU/X5qb0rR4+nY3ssHgAq27HoIvkWAOHV6Iaem5vO97OJ+x0g2n/NrtW5KLlAO9JHwBz9vkAzszGg+zfvbwTdwIOSL7zv0lxO4OlWcTfiPRmAQEfI1yDgRVfNU7DWupU7jZq57ThRaa09Soy7QfwXqOrj4eXju2ju+cuPlQ5DdPS7j/dMKtu58WDnjnxsgsHw6vFtqurDc8r5dPySsMxKyjLrLMhtu6xNRtopWEXIXZAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 2 게임 보안 적용 후의 클라이언트/서버 통신 구조&apos; title=&apos;&apos; src=&apos;/static/a2bd2149d0b9c04a82568c038d7a19de/efd7b/private2.png&apos; srcset=&apos;/static/a2bd2149d0b9c04a82568c038d7a19de/08678/private2.png 190w,
/static/a2bd2149d0b9c04a82568c038d7a19de/2edd7/private2.png 380w,
/static/a2bd2149d0b9c04a82568c038d7a19de/efd7b/private2.png 760w,
/static/a2bd2149d0b9c04a82568c038d7a19de/dc896/private2.png 1140w,
/static/a2bd2149d0b9c04a82568c038d7a19de/78873/private2.png 1520w,
/static/a2bd2149d0b9c04a82568c038d7a19de/f537a/private2.png 1730w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 2 게임 보안 적용 후의 클라이언트/서버 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 3&gt;에는 &amp;#x3C;그림 2&gt;와 같은 상황에서 해커가 게임 클라이언트를 공격하면 어떤 일이 벌어지는지를 보여준다. 해커는 게임 클라이언트 파일을 언팩하고 보안 코드와 연동된 부위를 제거하는 작업을 진행해서 게임 클라이언트에 포함된 보안 장치들을 무력화 시킨다. 이렇게 할 경우 게임 클라이언트가 구동하더라도 보안 코드는 아예 실행되지 않는다. 앞서도 언급한 것처럼 서버 쪽에 보안 코드가 있다면 그를 통해서 클라이언트의 무결성을 검증할 수 있다는 가능성은 있기 때문에 &amp;#x3C;그림 3&gt;의 단계에서는 아직까지 어떻게든 대응 해볼 수 있는 상태다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private3.png&apos; data-alt=&apos;그림 3 논클라이언트/바이패스 프로그램의 동작 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/27e456d0c6801c6364a285968df56e74/f537a/private3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 41.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABtUlEQVR42n2P60vbYBTG37bJHPjBscEUhVabpJNR8UMV6lAye40ofnC2zXJppBbX1nSR6OqltsFt+EEE/TeaDPTvW/P2mFfMlDH3wAMP5/LjHJRhRJyeKmFpUce19WOcY6V+jpHAqxcRsoLpcfUNH9FeEd9nZFFZVtzMejP5mNzfFg6w+tHA6WgJExbKc2XIsSqUeRNqq21YmdbwCrcFAqeJmWhhxHM4xRUmiElOvs+9zsfKRcGbWYtvDxrrp1DJtoBwiFE6KtrEpYW6LS3pTpb93EtFxdsMW0wiT5Z3JXqQn0nP++pGeKf0ZN74VfpQd3wOeqrlyY1IIrFDPykFnrHfQwtjGxE+wr9E/9LSqDL1F/B/Cvg7AmoO/anKjYBdb72197qsbXQYp9kO26pOOcpXOn7/poUeX37Ico1KqrvUjX4S7untScfscg5hEBaqmAEwzyagcxGHs6u5wbcfYageUFDdH0qR5UIBhXygn6v7oc0vRzQcnjO4ezkL36/nweiOQsUMAlJ12pXqQXevw7itnzN9uUG5ik4PFP15oLb74lO5GQLNGP59cp5wTSvmyo2QS1h3Ncak9u+MUAkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 3 논클라이언트/바이패스 프로그램의 동작 구조&apos; title=&apos;&apos; src=&apos;/static/27e456d0c6801c6364a285968df56e74/efd7b/private3.png&apos; srcset=&apos;/static/27e456d0c6801c6364a285968df56e74/08678/private3.png 190w,
/static/27e456d0c6801c6364a285968df56e74/2edd7/private3.png 380w,
/static/27e456d0c6801c6364a285968df56e74/efd7b/private3.png 760w,
/static/27e456d0c6801c6364a285968df56e74/dc896/private3.png 1140w,
/static/27e456d0c6801c6364a285968df56e74/78873/private3.png 1520w,
/static/27e456d0c6801c6364a285968df56e74/f537a/private3.png 1730w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 3 논클라이언트/바이패스 프로그램의 동작 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 4&gt;는 &amp;#x3C;그림 3&gt;과는 반대로 해커가 게임 서버 쪽을 공격한 예가 나와 있다. 게임 서버를 유출 시키거나 게임 프로토콜을 리버싱해서 직접 만든 서버를 운영하는 것이다. 이 경우에도 클라이언트 쪽에는 보안 코드가 있기 때문에 이를 통해서 합법적인 게임 서버로의 접근인지에 대한 유효성을 간접적으로 검증할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private4.png&apos; data-alt=&apos;그림 4 사설 서버의 동작 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8a86ab8c8edd76abf40e8707a140aeb9/f537a/private4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 14.210526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAsElEQVR42k2PTQrCQAyF0zpQoUVxV1p0qJ0plP7QAwizEPdCF4J4Am9ToWtX3sjbzOI507FiIDxCkpcvhDQFyhLIMqCqNBgDiEYyYXRBf2Fq9tUR2x3QdRqc2z2XQQBCGAJ5DtQ1kCTaDFvDgQ6vzVleylNxy47yurfa531F93dk+g+s1g5ASqBtHZDvG0PPw3SlaYAomg0nwkGIQCnF5nxyvvwR2k+E0CgKRxfHdg8fWGhe1FdvXo0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 4 사설 서버의 동작 구조&apos; title=&apos;&apos; src=&apos;/static/8a86ab8c8edd76abf40e8707a140aeb9/efd7b/private4.png&apos; srcset=&apos;/static/8a86ab8c8edd76abf40e8707a140aeb9/08678/private4.png 190w,
/static/8a86ab8c8edd76abf40e8707a140aeb9/2edd7/private4.png 380w,
/static/8a86ab8c8edd76abf40e8707a140aeb9/efd7b/private4.png 760w,
/static/8a86ab8c8edd76abf40e8707a140aeb9/dc896/private4.png 1140w,
/static/8a86ab8c8edd76abf40e8707a140aeb9/78873/private4.png 1520w,
/static/8a86ab8c8edd76abf40e8707a140aeb9/f537a/private4.png 1730w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 4 사설 서버의 동작 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 3&gt;에 나와 있는 클라이언트 측의 공격이나 &amp;#x3C;그림 4&gt;에 나와 있는 서버 쪽의 공격이 단편적으로 벌어지는 경우에는 여전히 반대쪽의 보안 코드가 있기 때문에 무엇을 해볼 수 있는 여지가 있다. 진짜 무서운 일은 이 둘이 결합했을 때 벌어진다. &amp;#x3C;그림 5&gt;에는 이렇게 클라이언트와 서버 쪽을 모두 공격해서 둘 다 교체한 상태를 보여준다. 말 그대로 클라이언트, 서버 모두 변조된 상태고, 둘 모두에서 보안 코드는 제거되었다. 이런 구조적인 특징 때문에 이 상황에서 보안 코드가 할 수 있는 일은 아무것도 없다. 이건 사실 클라이언트, 서버의 공격이라고 하기 보다는 아예 또 다른 게임이 하나 더 만들어진 것과 같은 상황이라고 할 수 있다. 안타깝지만 불편한 진실은 현실 세계에서 통용되는 대다수의 사설 서버가 &amp;#x3C;그림 5&gt;와 같은 구조로 동작한다는 점이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private5.png&apos; data-alt=&apos;그림 5 논클라이언트/바이패스와 사설 서버가 결합한 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/184254d7f326bb34416218c424c6e170/f537a/private5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 41.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABb0lEQVR42p2P20oCURSGlyfyrrCgNHJydOjAXCQmBRWSTlYQEdGY6UxKSKhMB6yEqJii7rroAXoCtxf1Bj1X6PZvJoIkCqoPPlhrbfbiX6SEszwV2ua5eYOX1895OpJrpcM5LEW2VSI4UgG9PyEU+mz1wEY/vcDdItrCwAAQj7cwMcEhyxzRKIfXy2lZ2kU6omM3UUN57QKr40W+KhWxIhWyiqj0KqIaTErqsK0qrgUp/eh7JcrA5QKfnOxgbAyYmgJGRgArAaXELLNVZypsZ85opsSdRlLMPiuRzCxZmGQ66QPrw3vdIZq16if4/Q1LBkFg8PmYNWPUzeLophCL7Xu6Ro4f/B0Lg1roy8JvsZI47LQwzU/t3r4gX3WwSn2I1UyJHV2FmwcXAtMNd1M79MjvJ5vkpL+wV3Oidh3A5b2Mm4fpztltEKVTN0onPUn7XVXJ9aeFuuFp5yrO9vFVuF2/k1v5qrutGZ6OZvxv4RvSY40n5mbzwQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 5 논클라이언트/바이패스와 사설 서버가 결합한 구조&apos; title=&apos;&apos; src=&apos;/static/184254d7f326bb34416218c424c6e170/efd7b/private5.png&apos; srcset=&apos;/static/184254d7f326bb34416218c424c6e170/08678/private5.png 190w,
/static/184254d7f326bb34416218c424c6e170/2edd7/private5.png 380w,
/static/184254d7f326bb34416218c424c6e170/efd7b/private5.png 760w,
/static/184254d7f326bb34416218c424c6e170/dc896/private5.png 1140w,
/static/184254d7f326bb34416218c424c6e170/78873/private5.png 1520w,
/static/184254d7f326bb34416218c424c6e170/f537a/private5.png 1730w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 5 논클라이언트/바이패스와 사설 서버가 결합한 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;사설 서버 대응의 가장 본질적인 어려움은 &amp;#x3C;그림 5&gt;와 같은 단계가 일단 되고 나면 해당 상황까지 해커가 만든 결과물을 제어하는 일이 사실상 통제 불가능한 상황에 도달한다는 점에 있다. 이게 무슨 말이냐 하면 &amp;#x3C;그림 5&gt;의 단계에 이르면 그 어떤 방법으로도 이미 유포된 사설 서버를 제어할 수 없다는 의미다. 게임에 보안 코드를 강화하고 추가적인 바이너리 패치를 하고, 서버 구조를 변경하여도 이미 사설 서버용으로 배포된 과거의 클라이언트와 서버는 여전히 동작 가능하기 때문이다. 최근 인터넷에서 논란이 되고 있는 ‘잊혀질 권리’라는 것이 사설 서버에는 존재하지 않는 셈이다. 법적 대응을 제외하고 과거 버전으로 운영되는 사설 서버에 대응할 방법은 전혀 없다.&lt;/p&gt;
&lt;p&gt;사설 서버 문제를 제대로 바라보기 위해서는 우리가 무엇을 도난 당하고 있는지에 대해서 냉철하게 생각할 필요가 있다. 과연 우리는 무엇을 도난 당한 것일까? 서버 코드, 게임 서버 머신, 프로토콜 설계, 클라이언트의 동작 구조, 클라이언트 소스 코드 이런 것들일까? 안타깝지만 본질은 그곳에 있지 않다. 사설 서버 운영자가 저런 것들을 모두 들고 있다고 해서 사용자들이 거기에 비용을 지불하는 것은 아니기 때문이다. 게임사에서 도난 당한 진짜 보물은 게임 사용자들이 비용을 지불하는 본질, 바로 게임 컨텐츠에 있다.&lt;/p&gt;
&lt;p&gt;문제의 본질이 컨텐츠에 있다는 것이 어떻게 보면 사설 서버 대응의 새로운 가능성을 제시해 준다. 온라인 게임은 운영이 지속되는 동안 컨텐츠 또한 지속적으로 업데이트된다. &amp;#x3C;그림 5&gt;와 같은 단계가 되면 과거 버전까지의 컨텐츠는 모두 도난 당한 것이라고 생각할 수 있지만 앞으로 만들 컨텐츠까지 도난 당한 것은 아니다. 따라서 우리가 충분히 신경 쓴다면 앞으로 생산할 컨텐츠는 사설 서버로부터 보호할 수 있다. 사설 서버 대응의 초점은 바로 신규 컨텐츠 보호에 맞추어야 한다.&lt;/p&gt;
&lt;h3&gt;플랫폼으로서의 보안&lt;/h3&gt;
&lt;p&gt;아이러니하게도 보안의 관점에서 보자면 사설 서버에 대한 대응은 클라이언트 측면에서 먼저 이루어져야 한다. 앞서도 살펴본 것과 같이 클라이언트 측의 보안 코드가 너무 쉽게 제거된다는 것에서 모든 문제가 출발하기 때문이다. 일반적으로 클라이언트 보안 코드의 무결성은 게임 서버에 의존하는 경우가 많다. 하지만 사설 서버의 경우에는 게임 서버가 독립적으로 제작되기 때문에 이러한 방식이 통하지 않는다. 따라서 클라이언트 자체적으로 게임과 분리가 어렵도록 만드는 작업을 먼저 해야 한다.&lt;/p&gt;
&lt;p&gt;그렇다면 보안 코드와 게임은 왜 손쉽게 분리될까? 이는 소프트웨어 공학적으로 이야기하면 보안 코드와 게임 코드 사이에 결합도가 높지 않기 때문이다. 소프트웨어 공학적으로만 이야기하자면 좋은 구조인 셈이다. 하지만 이렇게 결합도가 낮다는 것은 해커 입장에서는 손쉽게 떼어낼 수 있다는 것을 의미한다. 이뿐이 아니다. 통상적으로 보안 코드가 외부 확장 모듈에 존재하는 경우가 많은데 이는 해커들의 작업을 더욱 쉽게 만든다.&lt;/p&gt;
&lt;p&gt;이런 논의가 출발에는 대부분 보안 코드의 노출되는 API 종류를 늘리고 API가 게임과 인터페이싱 하는 형태를 복잡하게 만들어서 결합도를 높여야 한다는 의견이 나온다. 하지만 이는 크게 의미 없는 행위다. 왜냐하면 인터페이스 코드가 아무리 복잡해져도 여전히 보안 코드는 게임 구동에 필수적인 요소는 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;약간 생각을 바꿔서 이런 질문을 해보자. 왜 보안 코드는 손쉽게 제거할 수 있는데 운영체제 코드는 제거할 수 없을까? 보안 코드를 제거하듯이 게임에서 윈도우 관련 코드를 제거하고 리눅스에서 실행시킬 수는 없을까? 왜 보안 코드보다 윈도우 코드를 제거하는 일이 어려울까? 윈도우 코드도 모두 외부 확장 모듈에 존재하는데 말이다.&lt;/p&gt;
&lt;p&gt;그건 바로 윈도우 코드와 보안 코드가 게임에 가지는 의미가 다르기 때문이다. 보안 코드는 없어도 게임이 실행되는데 아무런 영향이 없지만 윈도우 코드가 없으면 게임이 실행조차 될 수 없다는 의미다. 즉, 앞서 API를 복잡하게 만들자는 생각은 형식론적인 관점에서 결합도를 높이자는 이야기다. 하지만 이런 전략은 도움이 되지 않는다. 왜냐하면 아무리 형식론적인 관점에서 결합도를 높여봤자 내용적인 측면에서 여전히 보안 코드는 게임 구동을 위한 필수 요소는 아니라는 점에는 변함이 없기 때문이다. 형식적인 측면에서의 결합도를 높이는 작업이 아닌 내용적인 측면에서의 결합도를 높여야 한다.&lt;/p&gt;
&lt;p&gt;보안 코드 자체가 게임에게 일종의 플랫폼으로 다가가야 한다. 게임이 실행되기 위해서는 반드시 필요한 서비스들이 있다. 파일을 읽고 쓰는 작업, 메모리를 할당하고 해제하는 작업, 외부 확정 모듈을 로드하고 언로드하는 작업, 그래픽 드라이버를 구동시키고 화면 제어를 하는 작업, 사운드 카드를 제어하는 작업 등등. 실제로 게임이 구동되기 위해서는 반드시 필요한 핵심 서비스들이 있다. 일반적으로 이러한 서비스는 운영체제에서 제공해 준다. 하지만 이제는 보안 코드에서 이러한 서비스들을 제공해 주도록 변경해야 한다. 설령 그것이 운영체제와 게임 사이에서 대리인 역할만 할지라도 말이다. 그렇게 내용적인 측면의 결합도가 높아져야 해커 입장에서 본질적으로 보안 코드를 제거하기가 어려워진다.&lt;/p&gt;
&lt;h3&gt;프로토콜 보호&lt;/h3&gt;
&lt;p&gt;게임 클라이언트와 보안 코드 사이의 내용적인 결합도를 일정수준 이상으로 높였다면 그 다음은 프로토콜을 손볼 차례다. 해커 입장에서 사설 서버를 제작하기 위해서는 반드시 게임 프로토콜을 전부 이해해야 하기 때문에 프로토콜은 매우 중요한 부분이다. 중요한 부분이지만 여기에도 대응하기가 쉽지 않은 부분이 있다. 바로 완성된 게임의 경우에는 게임 프로토콜을 손쉽게 변경할 수 없다는 점이다. 게임 서비스의 안정성과도 밀접한 연관이 있기 때문이다.&lt;/p&gt;
&lt;p&gt;모든 보안이 그렇겠지만 프로토콜이 노출되지 않도록 만드는 것은 불가능하다. 일단 프로토콜은 노출된다는 것을 전제에 두고 생각해야 한다. 따라서 프로토콜을 복잡하게 만들어서 절대 분석하지 못하도록 만들겠다는 전략보다는 프로토콜이 노출되더라도 손쉽고 안전하게 전체 구조를 변경할 수 있는 장치를 만드는 것이 더 좋은 전략이다. 여기에도 게임을 처음부터 새롭게 만든다면 프로토콜 설계를 그러한 방식으로 할 수 있겠지만 이미 만들어진 게임이라면 전체 구조를 변경할 수 있는 장치를 추가하는 것도 쉬운 일은 아니다. 이럴 때 쓸 수 있는 전략 중에 하나가 바이트 스트림 변형기를 이용하는 방법이다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 6&gt;에는 기존 게임 클라이언트, 서버에 스트림 변형기가 추가된 구조를 보여준다. 게임 클라이언트와 서버가 직접 통신하던 전에 방식이 아니라 네트워크 어댑터라고 불리는 스트림 변형기를 통해서 통신을 진행한다. 이렇게 하면 기존의 프로토콜 코드는 손대지 않고서 네트워크를 통해서 전송되는 바이트의 형태만 변형해서 실제로 프로토콜이 변경된 것처럼 보여지게 만드는 작업을 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private6.png&apos; data-alt=&apos;그림 6 게임 클라이언트와 서버 사이에 네트워크 어댑터 추가&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c8c1a3ef59c1df6c613f8fc7d840aacc/2561a/private6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 90.52631578947368%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEc0lEQVR42lWPa0xTZxjH39LC2DKRe0AoTI0oDBB0m3Kx4MLUycp90AI9vekmtFBAjJRbC4iLdAK67Jp929dBuciljIGIOJS46L4sMWwalyy7Ai0LWE7PefacFxbZh3/+7/t/fu//OYeQgRWgsqP6loH0r2xpmScDyxwZ2wAy5ExB5jXi8ADNhHnfynPWjtnIujBbJCLh0rfMSced3JEZF3dwykkVPeHyYClLRp7ho79TcOFhkVDet8zGTTq5o8gmTrm4JFTQiJMlQ/8Adj0i4gEnbnBC6KgLXp1chb0TLoj5ZhUix12818AK5zXGgmTrC8UOTvgTLtqxCnGUXYUDyGIhR248Ay/7yk+EONy/kImNp8SBGnVv+tiWJjaeoP7E7DCZdCciu0QzYTa6jXOwAvcbzmdJamb7B6nHLL3psvYeWaa1J52qnSoto/1qqszymexI876MDEtkmsz6aZrM0i3bmv/nwpvUjLbe9LSmLlIQrFgqDC6F3IBiHgVU/pvKD1SwilAN5IWUnSgMViQXhzCQH6Tgcv3fhbzA51xeQAkUBCuhIKQUiHyX6o+cSIY3F3RuWMtsbF22lW1RXmGbFVdY1UHjem6YBnKitFk50apkeZgalLHn3B3qbtb4ppm9kNvBtjPdbH1OO5sbybDy8HKWFESol4qkOmDiKnkmzgBMbCVoE6tBE28Exe4zrEL6HhRKdSfyo8oOlUjPQlGUltMkVEF5TAVltIlV9E2RVAuFERogOYGar94J1A6+7afqP7mjzH7Kr8x+ckcpdXmA5mt5oHbydIg6KTtUu0cepBuXB2n6KUO5Tfa0n8qOnF0erBkkTK2oT2UiN/T1Lw5XtYYPVzaFUH/fvHNYVUMGcf5t+XkSX1rrnSCchUyYCYyRsmHDugu+Q+U1ZJypEX1B9HW+axqTF1y8tJ+3ffIWXL4mg57Ps6Ht6hugNUk8FQ2+oK31zdCbxJnCWV3lxXX2pkHXx1lw+boMrn2ZA+etr3D6OjHoa30XCWP0XlEZvTcYo4+7yhzhNjbscpuaot1n6/zdKoNkTVfjA2VGyTHGJJFp8VxukKyfqdvprmwIRz7SXd0odetML60zRgmoDN4/klKDz5qiUgyaWn/+0vVTYO0+TlXdGgPF50QedZ0PKCskGSUGcaa61kfIuBrrARDYpq5UaOvNAn19CKc0ikBp8F4kra3izrYW8YfWVrHNbCa2RpT5IrE1N4ptbRZxF+YfWRpe2NPRRPYKZyFrbhQhK0J20y0tlOuxtEgaCNwmD2GOPEV/DLPkyf80R37G/Hf0ZPQU1F80287cpnqM+a/oM4SfEy3BHQIw78fDw0MAD+IBvt8HsBDOI8DBfQL8PDmK5+PwQARYwsFCBMAPryObCHB/N8AdHw7uYcccWSQwjVun8dGtlz2wkISDBFQsx38X4YEpwgrL+GksnCaZcBcLaRaOpcmb7N39HMx4s7gIkHlEEF6CW/TCIwxU01v3m/g181g4i4U38Qvv0Zyj8+2swM1RX/wXtID38iVVLRIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 6 게임 클라이언트와 서버 사이에 네트워크 어댑터 추가&apos; title=&apos;&apos; src=&apos;/static/c8c1a3ef59c1df6c613f8fc7d840aacc/efd7b/private6.png&apos; srcset=&apos;/static/c8c1a3ef59c1df6c613f8fc7d840aacc/08678/private6.png 190w,
/static/c8c1a3ef59c1df6c613f8fc7d840aacc/2edd7/private6.png 380w,
/static/c8c1a3ef59c1df6c613f8fc7d840aacc/efd7b/private6.png 760w,
/static/c8c1a3ef59c1df6c613f8fc7d840aacc/dc896/private6.png 1140w,
/static/c8c1a3ef59c1df6c613f8fc7d840aacc/2561a/private6.png 1180w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 6 게임 클라이언트와 서버 사이에 네트워크 어댑터 추가&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 6&gt;에는 네트워크 어댑터를 통해서 통신이 진행되는 실질적인 과정이 나와 있다. 왼쪽이 클라이언트, 오른쪽이 서버인 경우에 클라이언트에서 서버로 전송하는 과정을 나타낸 그림이다. 왼쪽부터 살펴보면 프로토콜 레이어에서 내려온 바이트를 전송 큐에 넣은 것을 최종적으로 전송하기 전에 네트워크 어탭터를 통해서 바이트 스트림을 변형해서 전송한다. 마찬가지로 서버 쪽에서도 받은 데이터를 네트워크 어댑터를 통해서 바이트 변환을 복구한 다음 수신 큐에 데이터를 넣는 구조로 되어 있다. 이렇게 작성할 경우에 기존 프로토콜 코드는 건드리지 않고 실질적으로 네트워크를 통해서 전달되는 패킷의 구조를 다르게 변형시킬 수 있다. 더불어 해커가 네트워크 어댑터 코드를 분석했다고 하더라도 해당 어댑터 코드만 새롭게 변형해서 손쉽게 다른 구조로 변경할 수 있다는 장점이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;private7.png&apos; data-alt=&apos;그림 7 네트워크 어탭터를 통한 송수신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/f537a/private7.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 41.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwElEQVR42mNwUY7466wY/jfKJudvhl/lXzeVqN9uylH/nRQjQhiAIJQhlJkBCmBsN5XIYFegGne16N/JHiV/Yx3y/zorhf8FmcXgrhr3300l9n+cfdH/DO/q/54a8X891RL/e6jE4TQQJOehmvDfRyf5b5Zfzf8k17L/IHNAmMFZKWIVCIdbZq6Kss1Z7awSudJJKWKDi0qYBUhzPUM9E8xAGBskB/TVeg/1mJUxDnmrI6yyVsHMYUAGlgpB8sbGaawMxAFGEGEtGSpnL2/PgVWFrXioojEDioGMODDcQJAeD4ZcdriO6GzGWclFvGsK6lRWFdWprc6pkF4Znc20ITqXBeLlegaEl6HseKBcdBbj+sxyiZUlDRqrC+tUVycX8a+KzmJexZBYxPQit0bwf0Ov0b+2ydb/y9tU/qaWMf5PLeSOMGCYKOpm6KviqhaqCMJuWr4qpgz1EinFHGGppYz/S5sV/7VMNPvfMtH8f26N8P+kIqb/DDE5LE/j8zj+lzXr/C5v0fuTUSb+KzaX6X9cLhs4ll31XLnt5eM5QBjEBrswjy04Npf5f0aZ2K+KFv0/JY2afxILuP/EZLP8AQA13KQAKben+AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 7 네트워크 어탭터를 통한 송수신 구조&apos; title=&apos;&apos; src=&apos;/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/efd7b/private7.png&apos; srcset=&apos;/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/08678/private7.png 190w,
/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/2edd7/private7.png 380w,
/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/efd7b/private7.png 760w,
/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/dc896/private7.png 1140w,
/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/78873/private7.png 1520w,
/static/b8ff8b40e51f02a4f74aa1f49d6e90c6/f537a/private7.png 1730w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 7 네트워크 어탭터를 통한 송수신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 7&gt;의 네트워크 어댑터의 경우에는 기존 프로토콜 코드를 하나도 수정하지 않고 변형하는 형태이기 때문에 변형이 바이트 단위의 작업으로 제한된다. 결국 비트 연산 외에는 할 수 있는 작업이 없다. 비트 단위의 연산 또한 문맥을 고려하기 어렵기 때문에 궁극적으로 대칭적인 구조의 변형 작업밖에는 할 수 없다는 단점이 있다. 이런 단점을 극복하기 위해서는 결국 바이트 단위가 아닌 조금 더 큰 규모에서 변형을 가할 수 있어야 한다. 추가적인 개발 리소스 투입이 가능한 상황이라면 프로토콜을 이중화 시키는 방법 또한 생각해 볼 수 있다. 프로토콜 이중화란 기존 프로토콜을 새로운 형태의 프로토콜로 감싸는 작업을 하는 것을 말한다. 물론 신규 프로토콜은 일정 양의 데이터를 전송하는 기능을 하는 메타 프로토콜이기 때문에 복잡하게 구성할 필요는 없다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 리소스 관리]]></title><description><![CDATA[전통적으로 프로그래밍의 가장 복잡한 문제 중에 하나가 리소스 관리다. — 작성하는 중인 글… 코드만 참고합시다. — 이 구조의 가장 핵심은 변수들의 초기화다. 위 코드는 모든 변수가 정상적으로 초기화 되지 않았기 때문에 if(!resourcea…]]></description><link>https://jiniya.net/wp/archives/12805</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12805</guid><pubDate>Fri, 14 Mar 2014 23:59:27 GMT</pubDate><content:encoded>&lt;p&gt;전통적으로 프로그래밍의 가장 복잡한 문제 중에 하나가 리소스 관리다.&lt;/p&gt;
&lt;p&gt;— 작성하는 중인 글… 코드만 참고합시다. —&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;xstatus &lt;span class=&quot;token function&quot;&gt;some_func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	xstatus s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	xhandle resourcea&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	xhandle resourceb&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	resourcea &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateResourceA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;resourcea&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;goto&lt;/span&gt; $cleanup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	resourceb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateResourceB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;resourceb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;goto&lt;/span&gt; $cleanup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SUCCESS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

$cleanup&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resourcea&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;FreeResourceA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resourceb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;FreeResourceB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 구조의 가장 핵심은 변수들의 초기화다. 위 코드는 모든 변수가 정상적으로 초기화 되지 않았기 때문에 if(!resourcea)나 if(!resourceb)에 걸리면 의도하지 않은 결과가 나올 수 있다. 상기 패턴으로 코드를 만들 때 가장 신경써야 하는 부분은 아래와 같이 변수를 정상적으로 초기화 시켜 주는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;xstatus &lt;span class=&quot;token function&quot;&gt;some_func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	xstatus s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FAIL&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	xhandle resourcea &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	xhandle resourceb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	xhandle resourcea &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateResourceA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;resourcea&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	xhandle resourceb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateResourceB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;resourceb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// processing...&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;FreeResourceA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;FreeResourceB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;초보 프로그래머들이 많이 하는 루프 내 리소스 관리 실수. break에 걸리는 순간 이전에 획득한 리소스가 정상적으로 해제되지 않는다. if(!resourceb) 구문을 타는 순간이다.&lt;/p&gt;
&lt;p&gt;C++의 RAII를 활용하자. 머리가 들 아프다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 사이드 이펙트, 그리고 함수 디자인]]></title><description><![CDATA[위와 같은 함수를 생각해 봅시다. url로 넘어온 경로를 다운로드 해서 buffer에다 저장하는 함수입니다. 결과 상태를 리턴 합니다. 그런데 이 함수에는 한 가지 단점이 있습니다. 웹 서버가 40…]]></description><link>https://jiniya.net/wp/archives/12789</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12789</guid><pubDate>Wed, 12 Mar 2014 23:59:26 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Downloader&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	xstatus &lt;span class=&quot;token function&quot;&gt;DownloadUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 함수를 생각해 봅시다. url로 넘어온 경로를 다운로드 해서 buffer에다 저장하는 함수입니다. 결과 상태를 리턴 합니다. 그런데 이 함수에는 한 가지 단점이 있습니다. 웹 서버가 404 오류 같은 것을 뿜어도 성공을 리턴한다는 것이죠. 404 페이지를 그냥 다운로드 받습니다. 뭐 함수 디자인이 그렇게 된 것이니 버그는 아닌 셈이죠. 여기에다 404 오류 코드 같은 결과 값을 알 수 있는 기능을 추가한다고 생각해 봅시다. 어떻게 작업 하는 것이 좋을까요? 당연한 이야기겠지만 그 결과값은 DownloadUrl 함수를 수행하는 동안에만 알 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Downloader&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	xulong return_code_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	xstatus &lt;span class=&quot;token function&quot;&gt;DownloadUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// processing&lt;/span&gt;
		return_code_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_return_code&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; status&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	xulong &lt;span class=&quot;token function&quot;&gt;GetReturnCode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; return_code_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 코드는 그러한 작업을 해 본 한 가지 샘플 코드입니다. DownloadUrl의 인터페이스를 수정하지 않아서 기존 코드와의 호환성을 유지 시켰습니다. 그리고 GetReturnCode라는 함수를 추가해서 DownloadUrl을 수행하는 동안 발생한 리턴 코드 값을 확인할 수 있도록 하는 인터페이스를 추가했죠. 호환성을 유지하면서 잘 확장한 디자인 같아 보이지만 이는 함정입니다.&lt;/p&gt;
&lt;p&gt;첫번째 문제는 DownloadUrl과 GetReturnCode 사이에 어떠한 연관성도 찾을 수 없다는 점입니다. 즉, 이 클래스의 내부를 보지 않은 프로그래머가 DownloadUrl의 리턴 코드 값을 확인하기 위해서 GetReturnCode를 호출해야 한다는 점을 알 수 없습니다. 매뉴얼을 보고 익혔다고 하더라도 나중에 계속 기억하기가 쉽지 않죠.&lt;/p&gt;
&lt;p&gt;두번째는 스레드 세이프하지 않다는 점입니다. DownloadUrl 함수를 호출하면 return_code_ 값이 변경됩니다. 이렇게 함수 호출로 인해서 다른 상태 값이 변경되는 것을 우리는 사이드 이펙트라고 부릅니다. 일반적으로 이러한 사이드 이펙트가 많으면 많을 수록 스레드에 안전하도록 만들기가 어렵고 복잡해 집니다. 특히나 요즘 같이 멀티 스레드가 대세인 환경에서는 다른 프로그래머에게 이 함수는 스레드 세이프하지 않아. 라고 아이기를 해주어야 하죠.&lt;/p&gt;
&lt;p&gt;끝으로 마지막 문제는 스레드 세이프하지 않다는 점에 더해서 그 스레드 세이프하지 않음을 외부에서 제어할 방법이 전혀 없다는 점입니다. DownloadUrl과 GetReturnCode를 하나로 외부에서 묶기가 힘들다는 것이죠. 결국 외부에서 묶으려면 이를 포장한 Downloader2라는 클래스를 새로 만들어서 소스 코드 전체에 그 녀석을 쓰는 방법 밖에는 없습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Downloader&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	xulong return_code_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	xstatus &lt;span class=&quot;token function&quot;&gt;DownloadUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DownloadUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	xstatus &lt;span class=&quot;token function&quot;&gt;DownloadUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xpulong rcode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t buffer_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// processing&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rcode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;rcode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_return_code&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; status&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드는 일반적으로 올바른 방향의 재구조화된 코드를 보여줍니다. 앞선 코드와 가장 큰 차이점은 사이드 이펙트를 없앴다는 점입니다. 기존 함수 인터페이스는 유지하고 새로운 return_code를 전달 받는 함수 시그니처를 추가했습니다. 기존 함수 코드는 새로운 함수에 옮겨 쓰고, return_code 인자가 있는 경우에는 해당 값을 전달하도록 만든 것이죠. 그리고 기존 함수는 새로운 함수를 호출하도록 만들어서 소스 코드의 중복을 없애고 있습니다.&lt;/p&gt;
&lt;p&gt;대체로 함수형 언어가 멀티 코어에 유리한 이유는 사이드 이펙트가 없기 때문입니다. 함수 디자인을 할 때에도 대체로 사이드 이펙트가 없도록 디자인 하는 것이 멀티 스레드, 멀티 코어 환경에서 훨씬 수월하게 동작할 수 있도록 만드는 지름길입니다. 함수에 어떤 사이드 이펙트가 존재한다면 이게 반드시 필요한 것인지 항상 물어보는 습관을 가지는 것이 중요하겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 당신의 메모리는 안녕하십니까?]]></title><description><![CDATA[640K ought to be enough for anybody. 640K는 누구에게나 충분한 메모리다. – Bill Gates 한 시대를 풍미했던 컴퓨터 엔지니어, 컴퓨터로 쌓을 수 있는 최고의 부를 거머쥔 사람, 빌 게이츠도 한때 640K…]]></description><link>https://jiniya.net/wp/archives/12674</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12674</guid><pubDate>Thu, 19 Dec 2013 23:59:25 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;640K ought to be enough for anybody.&lt;/p&gt;
&lt;p&gt;640K는 누구에게나 충분한 메모리다.&lt;/p&gt;
&lt;p&gt;– Bill Gates&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;한 시대를 풍미했던 컴퓨터 엔지니어, 컴퓨터로 쌓을 수 있는 최고의 부를 거머쥔 사람, 빌 게이츠도 한때 640K 메모리면 온세상 프로그램을 다 돌릴 수 있다고 생각했던 시절이 있었던 것 같다. 빌 게이츠가 실제로 저 말을 했는지 안 했는지는 모르겠지만 한 가지 분명한 사실은 저 이야기가 통용되던 때로부터 시간이 한참은 흘렀다는 점이다. 그 사이 CPU도 변했고, 운영체제도 변했고, 프로그램도 변했다. 이제는 640K로만 돌아가는 프로그램이 있다면 그게 더 신기할 지경인 세상이다.&lt;/p&gt;
&lt;p&gt;현대적인 프로그램은 상상하기도 힘들만큼 많은 메모리를 사용한다. 그중에 백미는 역시 게임이다. 게임은 여전히 가장 많은 메모리와 CPU 자원을 필요로 하는 프로그램 중에 하나다. 게임 보안 소프트웨어는 그런 프로그램과 동시에 실행되어야 하기 때문에 다양한 제약 사항들이 존재한다. 메모리도 그 중 하나다. 모 게임의 경우에는 게임 보안 솔루션 때문에 대규모 컨텐츠 패치가 불가능한 상황이라 우리 제품으로 윈백한 경우도 있었다. 보안 제품이 너무 많은 메모리를 사용했던 것이다. 어쨌든 많은 메모리를 필요로 하는 게임, 그리고 동작하기 위해서는 반드시 메모리를 사용할 수 밖에 없는 보안 솔루션의 한집 살이가 쉽지 않다는 사실에는 이견의 여지가 없다.&lt;/p&gt;
&lt;p&gt;CPU 이슈는 종종 제기됐지만 메모리 이슈는 크게 부각되지 않았기에 우리는 그간 메모리가 안녕하신줄 알았다. 하지만 최근에 출시한 따끈따끈한 게임은 기존 게임들보다는 더 많은 메모리를 필요로 했기에 메모리는 안녕하지 못했다. 우리는 그 핫한 게임과 한집 살림을 하기 위해서 몇 가지 주요한 기능들을 포기해 가면서 메모리를 좀 더 아껴쓰게 만드는 작업들을 했는데 이 과정이 생각보다 재밌었기에 여기에 조금 소개해볼까 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;처음 제기된 이슈는 메모리 단편화였다. 사실 우리가 터무니 없이 많은 메모리를 사용하지는 않기 때문에 단편화에 영향을 줬다면 딱 하나 밖에는 없다. ASLR(Address Space Layout Randomization)이다. 우리는 지난 글에도 썼지만 코드의 분석을 어렵게 하기 위해서 ASLR을 사용한다. 코드를 메모리 여기 저기에 분산 배치시키는 기능을 의미한다. 그런데 이게 아주 큰 연속적인 공간을 필요로 한다면 문제가 될 수 있다. 우리는 이 옵션을 껐고, 게임은 잘 동작했다. 이렇게 문제가 해결되는 것처럼 보였다. 나중에 시간나면 단편화에 영향을 최소한으로 주는 ASLR 알고리즘을 만들어야겠다는 생각을 하면서…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그런데 그 사라졌을 것 같은 이슈는 사라진 게 아니었다. 단지 지연됐을 뿐이었다. 게임을 오래하면 단편화 문제가 계속 발생한다는 것이었다. ASLR을 껐지만 우리도 게임 실행 중 메모리 할당과 해제를 반복하기 때문에 당연히 영향을 줄 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;게임 메모리 단편화에 단 한톨의 영향도 끼치지 않겠다는 생각으로 대규모 토목 공사가 시작됐다. 메모리 풀을 만들고 덩어리 메모리를 할당하는 곳은 모두 그 풀에서 동작하도록 구조를 변경하는 작업이 진행됐다. 그러면 할당과 해제를 반복해도 초기에 고정된 풀 내에서만 벌어지기 때문에 게임에 주는 영향은 최소화할 수 있기 때문에 게임 내 메모리 단편화 현상을 피할 수 있다는 생각에서였다.&lt;/p&gt;
&lt;p&gt;ASLR을 끈 것이나, 메모리 풀을 사용해서 집중된 영역에 뭔가를 배치시키는 것 자체가 지난 글에서 언급한 보안성과는 전혀 상관없는 내용이다. 하지만 현실 세계에서는 응당 안정성이 보안성에 우선한다. 일단 게임을 할 수 있어야 핵을 잡든 말든 중요한 것 아니겠는가?&lt;/p&gt;
&lt;p&gt;대규모 토목 공사인 줄 알았지만 그렇게 많이 고칠 필요는 없었다. 덩어리 메모리를 사용하는 곳이 크게 많지는 않았기 때문이다. 토목 공사가 끝날 즈음에 난 초기 풀 크기로 통크게 100메가 바이트를 지정했다. 풀은 두개를 사용했다. 그러니 시작과 동시에 할당은 아니더라도 메모리 공간은 200메가 바이트를 깔고 들어가는 셈이었다. 물론 우리가 그 정도로 많은 메모리를 사용하지는 않지만 어떤 경우에도 게임 내 단편화 현상에 영향을 주고 싶지는 않았기에 느낌대로 크게 잡아 버렸다. 이때까지만 해도 난 단편화 문제라 보고 받았기 때문에 이는 현명한 선택이라 생각했다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 대규모 토목 공사도 새로 출시한 핫한 게임을 만족시키기엔 부족했다. 이 시점부터 난 게임 프로그래머와 직접 대화할 수 있었고 실질적인 문제가 단편화가 아니라는 사실을 알게 되었다. 게임 자체가 2기가 바이트에서 거의 간당 간당하게 돌아가기 때문에 서드 파티 프로그램이 너무 많은 공간을 사용하면 문제가 된다는 것이었다. 64메가 바이트 정도 안쪽으로 공간이 집중될 수 있었으면 좋겠다는 이야기를 했다. 즉, 문제는 단편화도 단편화지만 메모리 공간 자체가 많이 부족하다는 의미였다.&lt;/p&gt;
&lt;p&gt;메모리가 이리도 싼 세상에, 심지어 핸드폰도 2기가 넘는 메모리를 탑재하는 시대에 메모리 타령이라니 조금 이상하게 들릴지도 모르겠다. 우리가 여기서 이야기하는 메모리 한계는 실제 물리 메모리가 아니다. 거의 대부분 주소 공간에 관한 이야기다. 주소 공간이란 한 프로그램이 한번에 사용할 수 있는 메모리 공간이라고 생각하면 된다. 16기가 바이트의 메모리를 탑재하고 있다고 16기가 바이트를 다 쓸 수 있는게 아니기 때문이다. 64비트 CPU, 64 운영체제, 64 응용 프로그램이라면 가능하겠지만 게임은 아직 그런 환경을 고려하기란 쉽지 않다. 어쨌든 32비트를 고려해야 하기 때문에 결국은 32비트 응용 프로그램에서 발목이 잡힌다. 윈도우 환경에서 일반적으로 32비트 응용 프로그램이 사용할 수 있는 주소 공간은 2기가 바이트로 제한된다.&lt;/p&gt;
&lt;p&gt;이런 상황에서 주소 공간을 낭비하는 가장 대표적인 형태는 VirtualAlloc의 잘못된 사용에서 발생한다. 32비트 환경에서 윈도우는 할당 단위로 64KB(0x10000)를 사용하고, 페이지 크기로 4KB(0x1000)을 사용한다. 할당 단위가 64KB이기 때문에 VirtualAlloc을 64KB의 배수가 아닌 다른 값으로 사용하면 쓸 수 없는 주소 공간, 슬랙이 생겨버린다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;PVOID ptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x8000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_COMMIT &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; MEM_RESERVE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 간단한 할당 코드를 살펴보자. 32KB를 한번에 할당하기 위해서 VirtualAlloc을 호출했다. 메모리가 있다면 위 호출은 정상적으로 실행돼서 ptr에 어떤 값을 반환할 것이다. 보통 이런 호출은 어떠한 문제도 없다. 하지만 공간이 모자란 경우에는 이런 호출 조차도 사치가 된다. 앞서도 이야기 했지만 윈도우는 64KB 할당 단위를 사용하기 때문에 위와 같이 호출해 버리면 ptr 다음의 32KB는 사용할 수 없는 공간, 죽은 메모리 공간이 되기 때문이다. 슬랙을 없애기 위해서는 아래와 같은 형태로 메모리를 꼼꼼하게 사용해야 한다. 아래 코드는 64KB 영역을 예약하고 32KB만 물리 메모리를 할당하는 것을 의미한다. 나중에 32KB가 더 필요하면 ptr 뒤쪽의 32KB를 할당해서 사용할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;PVOID ptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x10000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_RESERVE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x8000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_COMMIT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 것들을 완전히 꼼꼼하게 관리하기 위해서는 별도의 풀 메모리 매니저 API를 만들어야 한다. 단지 읽고/쓰기 위한 공간을 할당하기 위한 목적이라면 그냥 힙 관련 API를 사용하는 것이 바람직하다. 힙 API도 내부적으로 큰 덩어리들에 대해서는 VirtualAlloc을 사용하기 때문에 보통 프로그래머들이 생각하는 것처럼 속도 저하가 그리 심하지는 않다. 뭐 직접 메모리 매니저를 구현하는 비용 생각하면 그놈이 그놈인 경우가 다반사다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;풀 크기야 일부러 크게 잡아둔 것이었기 때문에 100MB라고 된 부분을 그냥 10MB로 바꿔버리면 된다. 우리에게 적합한 최소 크기에서 조금의 마진이 있는 형태로 풀 크기를 조정하는 작업을 진행하면서, 게임 프로그래머의 고민을 조금이나마 도와 주기 위해서 게임 메모리 공간을 살펴보기로 했다. 내가 제일 먼저 한 일은 게임이 더 이상 진행 불가가 된 상황의 메모리 맵을 추출하는 일이었다. 다행이도 꼼꼼한 게임 프로그래머는 우리에게 풀 덤프 파일을 제공해 주었고 거기나 난 아래와 같은 거대한 메모리 맵을 손쉽게 추출할 수 있었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  BaseAddr EndAddr+1 RgnSize     Type       State      Protect       Usage
-------------------------------------------------------------------------------------------
*        0    10000    10000             MEM_FREE    PAGE_NOACCESS   Free 
*    10000    20000    10000 MEM_MAPPED  MEM_COMMIT  PAGE_READWRITE   
\* 20000 21000 1000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* 21000 30000 f000 MEM\_FREE PAGE\_NOACCESS Free 
\* 30000 34000 4000 MEM\_MAPPED MEM\_COMMIT PAGE\_READONLY ActivationContextData 
\* 34000 40000 c000 MEM\_FREE PAGE\_NOACCESS Free 
\* 40000 42000 2000 MEM\_MAPPED MEM\_COMMIT PAGE\_READONLY ActivationContextData 
\* 42000 50000 e000 MEM\_FREE PAGE\_NOACCESS Free 

...

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;엄청난 분량의 로그가 출력됐다. 게임이 정말 많은 메모리를 사용하고 있다는 것을 알 수 있었다. 그 로그 중에서 진짜 할당이 실패했는지 조사하기 위해서 비어 있는 영역만 따로 모아서 크기 순으로 정렬을 해서 살펴보았다. 그랬더니 아래 나와 있는 것처럼 가장 큰 덩어리가 0xF0000 크기의 영역이었다. 15MB 정도를 한번에 할당할 수 있는 영역이다. 하지만 게임이 할당한 것으로 보이는 메모리 중에는 20MB 가까운 메모리도 있었기에 그정도 크기를 요청했다면 실패했을 수도 있겠다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;게임 프로그래머의 이야기처럼 여기저기 단편화된 메모리 조각들도 있었다. 아래 리스트에서도 연한 글씨로 표시된 6d10c000, 4df31000 영역은 조각난 메모리 영역으로 공간은 비어있지만 실제로 그 메모리의 앞쪽 영역은 사용할 수 없는 부분이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;**\* 7b320000 7c220000 f00000 MEM\_FREE PAGE\_NOACCESS Free 
\* 712f6000 72180000 e8a000 MEM\_FREE PAGE\_NOACCESS Free 
\* 7e1c0000 7f030000 e70000 MEM\_FREE PAGE\_NOACCESS Free** 

* 6d10c000 6def0000   de4000             MEM_FREE    PAGE_NOACCESS     Free 
* 4df31000 4ed00000   dcf000             MEM_FREE    PAGE_NOACCESS     Free 

**\* 4baf1000 4c560000 a6f000 MEM\_FREE PAGE\_NOACCESS Free 
\* 67570000 67d40000 7d0000 MEM\_FREE PAGE\_NOACCESS Free** 

...

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음으로 할당된 영역만 따로 뽑아서 살펴보았다. 메모리가 그렇게나 많이 필요한 상황은 아니라고 생각했기에 할당 단위의 문제라 생각했다. 앞서 설명한 것과 같이 VirtualAlloc의 사용 방법을 변경하면 상당히 많은 메모리를 절약할 수 있을거라는 믿음이 있었다. 로그의 출력 결과는 나의 이론을 뒷받침하는 것처럼 보였다. 0x12000, 0x11000 등의 크기로 할당된 무수히 많은 메모리 공간들이 보였다. 빙고~ 이 영역들을 없애면 게임이 훨씬 더 많은 공간을 가용 메모리로 사용할 수 있겠다는 생각이 들었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;* 584d0000 5998a000  14ba000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE      
|-568c2000 57500000 c3e000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* 5e3b0000 5ee5c000 aac000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  

...

\* 440b0000 440c2000 12000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* dda0000 ddb1000 11000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* dde0000 ddf1000 11000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* de20000 de31000 11000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* de40000 de51000 11000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  
\* de60000 de71000 11000 MEM\_PRIVATE MEM\_COMMIT PAGE\_READWRITE  

...

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;시간만 있었다면 이 단계에서 성급하게 증명하려 들었을 것 같다. 메모리 매니저 API까지 제공하는 보안 솔루션 하면 간지 나니깐. 하지만 중요한 외부 미팅이 있었기에 생각은 여기서 멈출 수 밖에 없었다. 결과론적으로 그게 나를 구했다.&lt;/p&gt;
&lt;p&gt;오늘 출근해서는 메모리 매니저 API를 구현하려고 연습장을 꺼내 들고는 끄적거리는데 생각보다 복잡했다. 우리 풀 매니저를 그냥 게임 API에 연결해서 사용하면 되는데 문제는 VirtualAlloc 따위를 후킹했을 때 훅 함수에서 다시 VirtualAlloc이 호출되는 불상사를 없애야 한다는 점이었다. 모든 동적 할당을 봉쇄한 코드를 새로 작성해야 해서 성가신 작업이었다. 그렇다고 검증도 안된 것을 게임사에 적용해 달라고 하기도 무리수.&lt;/p&gt;
&lt;p&gt;어떡하지? 어떡하지? 하고 있는데 좋은 생각이 떠올랐다. 이게 진짜 의미있는 짓인지 알아보자는 생각이었다. 과연 내가 이 변경을 통해서 얼마나 많은 슬랙 공간을 확보할 수 있을까? 뭐, 이 이론적인 가능성이 괜찮다면 게임사에다 이야기 할수도 있겠다는 생각이었다. 이 작업을 하기 위해서 할당된 메모리 크기 별로 카운트를 추출했다. 게임사에서 32KB 이상의 메모리 할당에 VirtualAlloc을 사용한다 했으니 우리의 관심 영역인 32KB(0x8000) 이상 128KB(0x20000) 이하의 메모리에 대해서 먼저 조사를 했다. 이 영역에 사용된 크기별 카운트는 아래 목록에 나와 있는 것과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;00008000: 30
00009000: 39
0000a000: 33
0000b000: 11
0000c000: 35
0000d000: 20
0000e000: 51
0000f000: 240
00010000: 4996
00011000: 403
00012000: 16
00013000: 10
00014000: 8
00015000: 12
00016000: 4
00017000: 5
00018000: 6
00019000: 3
0001a000: 4
0001b000: 4
0001c000: 4
0001d000: 6
0001e000: 1
0001f000: 12
00020000: 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 목록에 대해서 완벽한 메모리 풀을 만들었다면 얼마나 많은 슬랙 공안을 확보할 수 있을까? 0x11000으로 할당된 403개의 공간이 나를 향해 빵긋 웃는듯이 보였다. 하지만 이내 그건 초심자의 행운 같은 것임을 깨달았다. 계산 결과는 생각과 달랐기 때문이다. 위 메모리 할당에 사용되는 총 공간은 404MB인데 슬랙으로 낭비는되는 공간은 단지 27MB였다. 헐~ 물론 404MB대비 27MB는 작은 비율은 아니다. 비율에 희망을 걸면서 전체 메모리 할당 내역을 상대로 계산을 확장했다. 그랬더니 할당에 사용된 총 공간은 1331MB였는데 슬랙으로 낭비되는 공간은 꼴랑 40MB에 불과했다. 맙.소.사~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#6&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;엄마가 그랬다. 얘야 되도록 파이썬을 사용하렴. 성급한 최적화만큼 멍청한 일도 없단다. CPU 보다는 네 시간이 항상 더 소중하다는걸 기억해야지. 그렇다. 성급하게 일을 안 벌리길 잘한것 같다는 생각 ㅋ~&lt;/p&gt;
&lt;p&gt;40MB가 작은 메모리가 아닐수도 있다. 마치 티핑 포인트 같은 지점일수도 있다. 단지 20MB만 더 있으면 다시 해제/할당의 사이클을 반복하면서 게임이 계속 진행됐을 수도 있다. 하지만 이는 너무 억척스러운 가정이라는게 함정.&lt;/p&gt;
&lt;p&gt;이슈가 끝날 즈음 그런 생각이 들었다. 64비트 시대가 멀지 않았구나. 1MB의 제약을 벗어나려 32비트의 세계가 도래한 것처럼 2GB도 어느새 너무 좁은 공간이 되어 버렸다. 뭐 맛폰 CPU가 64비트로 가는 세상이니 말 다했지.&lt;/p&gt;
&lt;p&gt;한집 살림을 위한 안정성은 어느 정도 확보했으니 다시 보안성을 위해서 풀을 쪼개고 할당을 랜덤화할 차례… 뫼비우스의 띠 위를 걷고 있는 듯한 이 느낌은 뭐지. 하앍~&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/_Wn31YK0VSM?si=J9vgANHe8KOHaxN8&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;center&gt;
&lt;p&gt;&lt;strong&gt;이 글을 끝까지 읽었다면 이제 커피 한잔의 여유를 가져 보아요…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;사실 슬랙이 그리 나쁜 건 아니랍니다. 버퍼 오버런을 우아하게 허용해주는 관대함을 가졌죠 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;메모리도 인생도 그렇게 조금은 여백이 필요합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 하드닝에 관하여…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12520</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12520</guid><pubDate>Thu, 21 Nov 2013 23:59:24 GMT</pubDate><content:encoded>&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_0.png&apos; data-alt=&apos;인터넷에 이런 기사가 떠돌 땐 그저 남 일인 줄 알았다…&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 345px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ab7764cef08d3d0b87fe0f243ce534b9/fa8f5/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 115.78947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAFM0lEQVR42n1TaVBTVxi9LtixQCWBJAqo0Iph0ehEZCmCVSpCFcEaZV9UbMWxLVVQIyEDRYuKEjYbbFVcsBYtAyiEAgEXEoKBhFUQqwUCSci+kIUEkvSGmf7pdHreed878y3n3bl3Lng9MkpraXvBYNXUN3L7BujPO1rbX7zq5jC7umGS0zvQ1NpGa6Z3c/tqnzY9e8lsam1ve874g/5MJpeDSb4ANjFYbPqzjnd/jXH7Bwdfj/Rw+9mcXjg5NPwGukM9LRJPTE6NT/DGeZNjE7yxcZ5WqwNv3r77va4Bll8wOqF9YzP9VQ+3ue1556tuFrunoZkOfQ1Go8ViMZst/wJQqWcE0xKJTCFTqKRylUgig1quVMnkSqmVKrFELhBJoBaKJFBDIZLIDQarHZjR6gRSpUyuksgVYolMMA2DQiiSiqVysVQBNV8onhZLYR6Ozc+b5ubn5+bmzQvLAFKRaGyge0YtVWsMCtWsQqWd0WjU6hkY4atSq+fmjNZ+K4yGf2A0Gs1mE+jt6qopu8ab4vMEYqFwGvYZZ2d1+ln4aLUaSB386qzU6bR6nW5Wr4cupnnrz8GUVC+bMRoslhElrGmGxUq+UmMyzBr1s/+5SRDzZovJbDGbTKCd0dfcQBsZ7mFLxLDQMS57L9dBoVfyh/uZnG5GD4fZP9DJ4TKH+rr6uayxEa5i8vUwlyHk80H97ZK0QFReDL6KHN/5tNIyJxkb6mp9RC0hRsdGO4XtRgQGfbhps40ndlG4HzI1dC0xDvfm3vFzBM/qh3dB3c3ib0JWXUkOjPVakeBtR4zF+7rb+6CAD9om2MshJNAe77/cx9NmtTPwdF8W7Y8pSQ+ZqDmbl4B7/Nsd0FBZmhW29seEgEgPh+hNGKyLnb8XKjvetyB5664NmDAcav8B5+goDG79cvzH9rHbXG6cCld1lF79Kqju8T3QRXt0PT08N8bf33GJD3Jp2u51TUUxLcXxLYUH85L8IvEueeQt6Rkeu8Mc9wVj8uN8aUVHzO/qqJlf1D66C6qrKjMTI+6cT0nCOcXiEN9Ged86sycvOSjroG9tfhT50NZCkl/qMffEWNdTie4lSZvbr6YY39ZVkaPp9fdBWSkF64rMOxJZEOV9eT/28A63gni/RvKXjbkx3T8fY1JSvo9fHxnqeCJiVXkslnrA7eHRzYO3T1CTcKyGB6DierHdErB9PTpjm3PpYf8n2ZGUxIDKjKjyk/se5hMY5SknQ9fux9nmhKEr4rwpcdjmCwRN771bXwe+rLkLqKVF9ovBjnXIDH9U5k7XfIJXRtRG6tE9NzIOXDuzt/aHqPQIry3uDunBq64nbLhzBN9ZdlQ78OuttK2s2vugoozi+AHY5YHI3oYhhbqc3b6SfGjjpZTt5VmE9JgAIsEH64Z0QDm4uDgFb1pTnIhnl6XKmVRqIo795AEopRQuByDQ2TYvAFka4XolFFMY7nxir3dqxIbknWtCcGh7Bzs0egXK6SOko32YrxvjWhK/8WIJAcuurwLMluqLxz97kA/PJrGdcphVcby1KMkVYxvkg8J7IFcgbDErkWgMAoNGYDBIlKNddcmpOR5ttK1YOt4P+IO0m8Qd5LRPOTWZQ82X378sGG3P/WQ1AgCwCGIxWLIULLWxxmXLFsPk3s9xOkGTSdViMgiBaHyooij39Onv+jtqtIopjUqsk43+8tOlzKxMEukciUTMIWcv8DyZfJ6UQ7x4IUfM45i0f5qMKqDR6ERCiUqhVig0UFuv4QL/B+aFq2q2WP4G1d5MhPV9nIgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;인터넷에 이런 기사가 떠돌 땐 그저 남 일인 줄 알았다…&apos; title=&apos;&apos; src=&apos;/static/ab7764cef08d3d0b87fe0f243ce534b9/fa8f5/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_0.png&apos; srcset=&apos;/static/ab7764cef08d3d0b87fe0f243ce534b9/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_0.png 190w,
/static/ab7764cef08d3d0b87fe0f243ce534b9/fa8f5/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_0.png 345w&apos; sizes=&apos;(max-width: 345px) 100vw, 345px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;인터넷에 이런 기사가 떠돌 땐 그저 남 일인 줄 알았다…&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;아침에 눈을 떴는데 이상한 느낌이 들었다. 말을 하려고 하는데 목소리가 나오지 않는 기이한 현상이 벌어진 것이다. 침 삼킬 때 따끔 거리는 일은 있었어도 목소리가 아예 나오지 않는 이런 경우는 첨이라 어이가 없었다. 조금 이러다 말겠지 했는데 생각보다 오래간다. 래리 페이지가 목소리를 잃었다며 두문불출할 때만 했었어도 그냥 먼 산 불구경 하듯 딴나라 이야기라 생각했는데, 막상 내가 당해 보니 이게 보통 일이 아니다. 단 한 차례도 말하는 걸 특별하다 생각하지 않았는데 말이 나오지 않으니 일상 생활이 거의 불가능할 지경, A부터 Z까지 되는 게 하나도 없다. 멘붕 ㅠㅜ~&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;이 모든 사단의 발단은 요상한 해킹툴 하나에 있다. 그 녀석이 정체를 드러낸 것은 지난 주였다. 해킹툴이 잔뜩 올라오는 사이트에 우리 보안 제품이 적용된 게임의 해킹툴도 올라왔다. 평소에 그냥 왜 다른 업체들이 그 해킹툴을 안 막을까 너무 궁금했던 차였다. 왜냐하면 파일도 구하기 쉬우니 그냥 패턴으로라도 막으면 될텐데 왜 저렇게 버젓이 운영되도록 놔둘까하는 호기심이 있었다. 사이트가 너무 많아서 관심의 사각지대에 있나 보다라고 혼자 생각해보기도 했었다.&lt;/p&gt;
&lt;p&gt;평소 생각처럼 패턴 차단을 먼저 시도했는데, 그 다음이 가관이었다. 그 해킹툴이 전혀 다른 모습으로 돌아온 것이다. 그것도 2시간만에. 그때 진실을 마주하게 되었다. 다른 업체들이 안 막는 게 아니라 못 막는 거였구나. 다시 패치를 했다. 또 2시간. 또 패치를 했다. 또 2시간. 그맘때쯤 녀석이 그리 호락호락한 놈은 아니라는 사실을 인지하게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_1.png&apos; data-alt=&apos;해킹툴의 바지런한 업데이트. 너도 힘들지? 죽겠지? ㅋㅋㅋ&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 295px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0a8937754a3803ffb3bd03f9de4af25a/60cc9/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABiElEQVR42l3SWY/iQAwE4Pz/vwZoJQ4t983AQggJtxCQ+Yg187B+6FS73VUud5Jtmh2yLM/zLMt2u91yuZxMJtb9fr9YLObzuTWSs9lsOp0Oh8PD4SBzPp+TvCiOxyOUV+H+er3ebrdFUWw2m39V2Eo6StMUvt1u8Ol0SvZp6g4dB6FATRcEXZNZrVbj8dipC5L9fr/ZbEqWZZmQvVwuaAAUiNXBVu0FKRYFugu66OL5fCY+iqIfmqPRiDFbWBGfAJ/KFOD6+xP3+z1Beb1esQLBogLOfqYYyVAWX1WoeTweCb6Ys5boDAYDDqOLTqfDoV6s3W6X1Var5aYjzX88I/tVjsnhCkwQDtshEEOOeL1eCcGYk4fhNqRsjT3mLElWWa/XY/VPFZLv9/uj7N0MHPC2YRK2HqsI57qLGvnQ/1+ZGvpQtrLHG3GDcCF+r0ajUavVgI8yPsphmzJiUpJF9efBMr/KMQuVHvmjjD5+SQ4ptNttDm1h/m3N3Jz1YmvaZOv1OtmyLL8BnHbGlrJbkCkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;해킹툴의 바지런한 업데이트. 너도 힘들지? 죽겠지? ㅋㅋㅋ&apos; title=&apos;&apos; src=&apos;/static/0a8937754a3803ffb3bd03f9de4af25a/60cc9/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_1.png&apos; srcset=&apos;/static/0a8937754a3803ffb3bd03f9de4af25a/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_1.png 190w,
/static/0a8937754a3803ffb3bd03f9de4af25a/60cc9/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_1.png 295w&apos; sizes=&apos;(max-width: 295px) 100vw, 295px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;해킹툴의 바지런한 업데이트. 너도 힘들지? 죽겠지? ㅋㅋㅋ&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;어쨌든 그때부터 개발팀은 무한분석, 불꽃코딩, 밤샘, 지원팀은 매일같은 업데이트를 하게 되었다. 물론 업체 측에서도 해킹툴 척결의 의지가 있었기에 업데이트를 상당히 우호적으로 적용해 주었고 일정 수준 이상의 성과를 보이고 있다. 오늘이 꼭 10일째 되는 날인데, 우리는 그 사이에 무려 7번의 업데이트를 했다. 사실 주말 빼고는 매일 업데이트를 했다고 할 수 있다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;이번 해킹툴 차단에 결정적 기여를 한 사람은 다름아닌 막내였다. 녀석과 2시간 짜리 공방을 벌이던 때 면역 체계 이론에 빠삭한 막내가 HIV(에이즈 바이러스)에 대응하는 전략에서 가져온 새로운 아이디어를 제안했다. 평소 나도 생명체에서 답을 찾아야 한다는 생각이 강했던터라 귀담아 듣게 되었는데 생각보다 좋은 전략이었다. 그래서 막내의 아이디어를 당장 구현했다. 사실 크게 구현이 어려운 부분은 없는 아이디어라 다음날 구현할 수 있었고 패치에 적용했다.&lt;/p&gt;
&lt;p&gt;내심 막내도 나도 기대했다. 난 6시간만 버티면 좋겠다고 했는데 결국 그날은 10시간을 버텼다. 물론 대박은 그 시간이 아니었다. 녀석의 실수를 끌어낸 것이다. 지속적인 패치로 피로도가 누적됐는지 해커가 핵심 구성 모듈 중의 하나를 날것 그대로 방출한 것이다. 이 또한 막내가 발견했다. 막내의 발견 이후에도 난 다른 작업 때문에 바빠서 그 모듈을 분석하지 않고 있었는데 막내가 그 모듈의 핵심적인 기능 대부분을 분석해서 알려주었다. 막내가 분석하지 못한 내용은 같이 앉아서 분석을 했는데 우리는 그날 야근을 하면서 녀석의 수법을 모두 알아낼 수 있었다. 몇가지 참신한 기법도 있었지만 역시나 리버싱엔 능하지만 코딩은 잘 못하는 전형적인 해커였다.&lt;/p&gt;
&lt;p&gt;지피지기면 백전백승이라고 했던가? 녀석의 수법을 회피할 수 있도록 전체적인 구조를 재구성 하는 작업을 했다. 이건 생각보다 빡쎈 작업이라 다소 시간이 걸렸다. 그리고 그 주 주말엔 XIGNCODE3의 가장 강력한 기능 중에 하나를 준비했다. 4년 만이었다. 여기까지 기어온 네오는 녀석이 두 번째. 그 패치는 14일 적용됐고, 해커는 아직도 47.5차원 어디쯤에서 방황하는 중이다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;해커의 주된 공격 방식은 코드 조작(tampering)이다. 우리 코드를 제멋대로 패치해서 정상적으로 기능들이 동작하지 않도록 만드는 것이다. 이런 작업은 주로 패치할 대상 주소가 몇 개나 되는지에 의존하는데 우리는 다년간 이런 공격을 많이 받았기 때문에 폭탄을 제거하기 위해서는 여기저기 잘라야 하는 선들이 상당히 많다. 하지만 리버싱에 능한 그 녀석은 그 모든 선을 다 찾아서 잘라 버렸다. 이러면 VM 코드니, CRC 체크니 말하는데 그냥 그런 것들을 수행하는 부분 모두가 세트 메뉴로 다 패치됐다고 생각하는 게 속 편하다. 우리가 날것 그대로 방출된 모듈을 분석하기 전까지는 정말이지 발가벗고 녀석과 대적하는 느낌이었다. 그 정도로 녀석의 리버싱 능력은 탁월했다. 우리는 그 능력을 봉쇄하기 위해 다양한 하드닝 전략을 생각했는데 여기에 10개 정도만 추려서 소개해보면 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;필요한 코드는 필요한 시점에 로드되야 한다. 보통 프로그램은 실행과 동시에 모든 필요한 코드가 로딩된다. 이래서는 문제가 있다. 한번에 패치 대상 주소를 모두 확보할 수 있기 때문이다. 핵심 코드는 그 코드가 필요한 그 순간에만 존재하도록 만들어야 한다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;모든 코드는 언제든지 재기동 될 수 있어야 한다. 우리 몸의 세포는 매일 새롭게 태어난다. 심지어 뼈도 매일 조금씩 변화해서 10년이 지나면 완전 새로운 뼈로 태어난다. 이것과 마찬가지로 모든 구성 요소는 필요한 시점에 언제든지 새롭게 재기동 될 수 있어야 한다. 재기동 시키면 지속적으로 해당 컴포넌트들에 가해진 패치를 무력화 시킬 수 있다. 마치 드래곤볼의 피콜로 처럼 팔이 잘리면 조금 있다 다시 팔이 살아나는 것과 같은 시스템을 만들어야 한다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;해커에게 동일한 형태로 표출되는 코드가 다른 동작을 수행할 수 있도록 구성해야 한다. 세포가 동일한 구조로 되어 있지만 눈과 코와 귀와 입처럼 다른 기관으로 분화되는 것과 같은 이치다. 해커에겐 표면적으로 동일하게 보여지지만 실제로는 다른 동작을 하도록 만들어야 한다는 말이다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;코드 변조 여부를 스스로 인지할 수 있어야 한다. 보통은 CRC 체크 코드 등을 별도의 작업 단위로 구성하는 경우가 많다. 이런 건 그냥 소용없는 짓이다. 마치 그 코드가 원래 수행하려고 했던 일 자체가 CRC 체크인 것처럼 만들어야 한다. CRC 체크 코드와 원래 수행하는 코드 사이의 결합도를 아주 높여야 한다는 것이다. 샴쌍둥이들처럼 떼는 것 자체가 불가능하도록 만들어야 한다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;때로는 느슨한 랜덤 시드가 효과적이다. 하이엔트로피 짱짱맨을 외치는 사람들이 많다. 하지만 몇몇 부분에 있어서는 해커에게 그건 변하지 않는다는 것을 인식시키는 것이 훨씬 효과적이다. 변하지 않는다고 생각하고 내 PC에서 잘 되니까 릴리즈 했는데 그 순간 변해버린다면 제 아무리 날고기는 해커도 당황할 수 밖에 없다. 그래서 아주 느슨한 랜덤 시드를 섞어 쓰는 것이 효과적이다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;스레드 경계, 예외 경계, IPC 경계, 운영체제 콜백 경계를 활용해야 한다. 보통 코드는 직렬화된 순서로 진행된다. 이런 구조는 아주 쉽게 트레이스되고 분석된다. 그 트레이스 흐름을 끊을 수 있는 것들이 이런 장치들이다. 코드 내에서 이런 장치가 지속적으로 자주 등장하도록 만들어야 한다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;전체 코드가 메모리 상의 특정 영역에 집중돼 있으면 곤란하다. 분산 배치시켜야 한다. 이는 관련 코드를 스캔하는 속도를 떨어뜨리고 더 찾기 어렵게 만든다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;리버싱을 어렵게 만드는 방법 보다는 분석을 다 한 다음에도 프로그래밍을 어렵게 만드는 방법이 효과적이다. 탐지 기반 설계보다는 회피 기반 설계가 더 효과적이라는 의미다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;9&quot;&gt;
&lt;li&gt;탐지와 보고의 거리는 멀수록 효과적이다. 둘이 가깝다는 건 그냥 그 루틴은 쓸모가 없다는 것과 같다. 최대한 멀게 만들어라.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;ol start=&quot;10&quot;&gt;
&lt;li&gt;포인터 전역 변수는 피해라. 모든 데이터는 아주 은밀한 방식으로 숨겨야 한다. 전역 변수는 고양이에게 생선을 던져주는 것과 같은 형태다. 인코딩 같은 건 소용도 없으니 아주 은밀한 데이터 저장 방식을 고려해야 한다. 7번과 같은 이치다. 코드 뿐만 아니라 데이터도 분산 배치되어야 한다는 것을 의미한다.&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;/blockquote&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;실무를 주로 하다보면 이론적인 부분이 취약해지기 마련이다. 앞서 우리가 생각한 방법들도 사실 경험적인 추론에 의한 것들이지 수학적으로 코드 조작에 대응할 수 있는 방법들은 아니다. 잘 알겠지만 가장 효과적인 방법은 모든 코드를 알고, 그 원리를 알더라도 공격하기가 힘든 수학적인 근간이 있는 방법들이다. 이런 점에서 이번 싸움을 하면서 난 anti tampering이라든가 tamper proofing 같은 기법들에 관심이 생기기 시작했다. 그 과정중에 2009년에 발간된 기념비적인 책을 하나 찾게 되었는데 바로 Surreptitious Software란 책이다. 조작 방지에 관한 내용만 전문적으로 다루고 있는 책인데 실무적인 지식 보다는 이론적인 부분에 포커스가 있다. 사실 뭐 반반 짬뽕이라고 보면 된다. 나같은 사람이 보기에 편하게 쓰여진 책인 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_2.jpg&apos; data-alt=&apos;올해의 꿀통: Surreptitious Software&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ef82d3ad1b36ef89abea87152ef1e3e7/0cdb7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBQT/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAAB2a4QHQCU0hdgb//EABsQAAICAwEAAAAAAAAAAAAAAAECAxIABBAR/9oACAEBAAEFAneuX5tE0jm9fJVDKqjn/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAECEBFBUXH/2gAIAQEABj8CN0vRRadYZF8r/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARECExQZH/2gAIAQEAAT8hPubd+YFAXcIAFO0qCL7y8CuN3GWdOsf/2gAMAwEAAgADAAAAEIjH/P/EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxAyE//EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAECAQE/EGP/xAAeEAEAAQQCAwAAAAAAAAAAAAABEQAhMUEQUaGx8P/aAAgBAQABPxAkg3i9o8ua1g+lMokES7pDaQkGILZ+tTDFBKxdh1PBaKDAcoNACko3WuP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;올해의 꿀통: Surreptitious Software&apos; title=&apos;&apos; src=&apos;/static/ef82d3ad1b36ef89abea87152ef1e3e7/0cdb7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_2.jpg&apos; srcset=&apos;/static/ef82d3ad1b36ef89abea87152ef1e3e7/8ccab/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_2.jpg 190w,
/static/ef82d3ad1b36ef89abea87152ef1e3e7/0cdb7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_2.jpg 300w&apos; sizes=&apos;(max-width: 300px) 100vw, 300px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;올해의 꿀통: Surreptitious Software&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;중간에 Arxan 이야기도 잠시 나와서 나름 반가웠다. 내가 그토록 애타게 찾아 헤맸던 수학적인 근간이 있는 알고리즘도 몇 개 발견할 수 있었다. 대박~ 대부분의 수학적인 기반의 코드들이 그렇듯이 결과론적으론 아주 심플한데 해커 입장에서는 구토를 유발케하는 그런 코드들이다. 알고리즘이 궁금한 분들은 책을 사서 읽어보도록 하자. 여기 공간이 협소해서 알고리즘을 다 소개하기에는 무리가 따를 것 같다. 당연한 소리겠지만 여러분이 코드 보안에 신경써야 하는 분야에서 일하고 있다면 100만원을 주고 사도 돈이 아깝지 않은 책이다. 너무 싼가? ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_3.png&apos; data-alt=&apos;알고리즘 하나로 회사를 차리기도 한다. 반가워요, Arxan&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 494px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/defb18abe219856dbe4f09488b4294fd/7f4de/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.78947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABT0lEQVR42j1R2W6DMBDk/z8q5OAKeaJKC9jY65NQE5HmB0InRu1ILHvNeL1OlmWx1nZd1zQNY0wr1fe9lPLzeh0Azlnf3263dV1fr9caf+sfknmex3FEWUeABi3ExjnrvbF2CmGcJmS+59nDhoCMde7n+UyQ7TkbpBRELQ7ljAshhVD1pU337JRRWQ150aX7dpfywxGWHY7dLh2bj2T+amWWy7xQZUVFac61qy+mOpuy0nnhzjWdMp3ltm2h6LQWjMFqojBNCT4pBsG5d84ohUsqKeEoItzfGgxujdYIMSpYAnMRDUJMIM/3u7YW8bvLOc45gQNCTCqtY9qB470HGbJwcD8sK3k8HsYY1FDYHHRDAgTC4bEbGRDgYP3o2UrYcRJCoIg4KW2DAWhCiOVvdmPqOAhCOJB7k+FBBnr/h7xfKwI+8iYCIUS3NthlWX4BLPXYesU4jcoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;알고리즘 하나로 회사를 차리기도 한다. 반가워요, Arxan&apos; title=&apos;&apos; src=&apos;/static/defb18abe219856dbe4f09488b4294fd/7f4de/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_3.png&apos; srcset=&apos;/static/defb18abe219856dbe4f09488b4294fd/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_3.png 190w,
/static/defb18abe219856dbe4f09488b4294fd/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_3.png 380w,
/static/defb18abe219856dbe4f09488b4294fd/7f4de/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_3.png 494w&apos; sizes=&apos;(max-width: 494px) 100vw, 494px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;알고리즘 하나로 회사를 차리기도 한다. 반가워요, Arxan&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_4.png&apos; data-alt=&apos;그럴듯해 보이지만 결국은 그냥 여기저기서 크로스로 체크하겠다는 말&lt;br&gt;&lt;br&gt;때로는 포장이 더 중요할 때도 ㅋㅋㅋ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 513px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/468985f72f1048c7e3a8bf1a7f334cea/7fe11/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABNklEQVR42oWS246CQBBE+f+PQzEEEwiXBA2CgNxBgWWPtDtx9YF+mNA9VdXVPWjLVvz8xfeVtkmepsl13TAMv/nau/x3T5jjONZ13XXdtIbABP8ip2nqeR4IReMchiGOY67meUbitMbj8fjsjPb5fAbx0XxYo6qqpmk4RR1wURSovMhJkhyPR3CS5nnOkLfbDUIQBHCQBnC/3/u+930fC3TSyEGAQyzLMvh4lilIy7K8Xq8UoyhibW3bUuEUC5phGJZlyZC2bR8OBxyqsQEhKup8IwSTCv2fZErSjaCqJiflCntUSC+Xy263YwRWyCkN/r2z4zi6rr/vXD0SDfimP7bZCPt/ktULczI/OwT6rohDijhnqUhgW+11+w/DobwwNNM09/s9H9Jsm4xD+DSXKWCK52VZfgEwNfBN1dkumQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그럴듯해 보이지만 결국은 그냥 여기저기서 크로스로 체크하겠다는 말&lt;br&gt;&lt;br&gt;때로는 포장이 더 중요할 때도 ㅋㅋㅋ~&apos; title=&apos;&apos; src=&apos;/static/468985f72f1048c7e3a8bf1a7f334cea/7fe11/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_4.png&apos; srcset=&apos;/static/468985f72f1048c7e3a8bf1a7f334cea/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_4.png 190w,
/static/468985f72f1048c7e3a8bf1a7f334cea/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_4.png 380w,
/static/468985f72f1048c7e3a8bf1a7f334cea/7fe11/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_4.png 513w&apos; sizes=&apos;(max-width: 513px) 100vw, 513px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그럴듯해 보이지만 결국은 그냥 여기저기서 크로스로 체크하겠다는 말&lt;br&gt;&lt;br&gt;때로는 포장이 더 중요할 때도 ㅋㅋㅋ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;보안 코드들이 다 그렇지만 우리 코드도 점점 더 필요한 기능을 수행하는 코드보다 메타 코드가 늘어나고 있다. 주로 매크로 기능을 하는 코드들인데 더미 코드를 삽입한다거나 코드 구조를 변경한다거나 CRC 체크를 한다거나 하는 코드들이다. 메타 코드가 늘어날수록 원본 코드의 가독성은 떨어지고 버그는 코드 속에 더 은밀하게 숨겨진다. 요즘은 이런 것들을 매크로가 아닌 다른 방법으로 할 수 없을까 궁리중이다. 코드 위빙(code weaving)이라 불리는 기법들인데 C/C++같은 저급 언어의 컴파일 타임 내지는 컴파일된 결과물에 수행하기에는 다소 어려움이 있는 것 같다. 노가다가 답인가? ㅠㅜ~&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;어쨌든 그놈 덕분에 우리는 훨씬 더 강력한 기능들을 많이 추가할 수 있었다. 고맙긴 하지만 그래도 이젠 우리가 헤어져야 할 시간. 겁나 디버깅 중인 것 같은데 너도 ROE를 생각해야 하지 않겠니? 단언컨대 그 시간에 다른 게임 디버깅 하면 훨씬 수월할거야. 그럼 이제 바이, 짜이찌엔, 그리고 사요나라 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_5.png&apos; data-alt=&apos;사실 해커에게 이런 소리 듣는 안티 치트 솔루션은 흔치 않습니다. ㅋ~&lt;br&gt;&lt;br&gt;최선을 다해서 싸워드리겠습니다. 느낌 아니까~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 602px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5314ee1ec51c9ea326ed7be0b9037fe4/d1b94/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 23.684210526315788%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAsUlEQVR42j1OUQ6FIAzjIoIQE80DhQEbcP+LvYKJ/SBd15UqYclEMaVaS8m5lFJrTXPk1lrOFGOEyMwglAh7EHiu61JEBOs98Tz3PR1EPnjr7HEc1tp9352zbgHjS7DCqxCPVGS33kUEl1zrGINnk1kFosDUhBdyziyzFL5RY/RS4WB4cIMTVAKHTxb43S3ae0f6OyNFoav3vxBQO3gfgPM8oXx4YoSoP2ybNtoYo7X+A0pZNskJ1GtpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;사실 해커에게 이런 소리 듣는 안티 치트 솔루션은 흔치 않습니다. ㅋ~&lt;br&gt;&lt;br&gt;최선을 다해서 싸워드리겠습니다. 느낌 아니까~&apos; title=&apos;&apos; src=&apos;/static/5314ee1ec51c9ea326ed7be0b9037fe4/d1b94/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_5.png&apos; srcset=&apos;/static/5314ee1ec51c9ea326ed7be0b9037fe4/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_5.png 190w,
/static/5314ee1ec51c9ea326ed7be0b9037fe4/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_5.png 380w,
/static/5314ee1ec51c9ea326ed7be0b9037fe4/d1b94/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_5.png 602w&apos; sizes=&apos;(max-width: 602px) 100vw, 602px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;사실 해커에게 이런 소리 듣는 안티 치트 솔루션은 흔치 않습니다. ㅋ~&lt;br&gt;&lt;br&gt;최선을 다해서 싸워드리겠습니다. 느낌 아니까~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_하드닝에_관하여.md_6.png&apos; data-alt=&apos;보다 유쾌한 게임 경험을 제공하기 위해 항상 노력하겠습니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/38220aea1fcc0dc1e11709f1c7f4dd57/984b6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 52.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB60lEQVR42k1S2ZLaMBD0/39UUkVtEqjF+JKRbfkG37DAYhbIS2dmSKXy0DWWZHX39MiKoxgqCJGmGYxJkZoMVbVD07RIYoMkMiiLCnGUIM8K1NUeRV6hbXp0bY++G9B1Iwaqx+MJVkhky+UKWkdQKoTvK2xsF7btCLlhgbJG23ZEMGAcJ1Qk4Kx9+E6AwFVw3j1au9jVDSxWyEwu6mVe4nj4oMs9Ak9hG2iEvoZySchRdDmAiTPoMHoRrT3qIMXj8cT9/hBYTBTpGFlawCSptBtpg8W3BX4ufuHt+w8s31awVxvYSxueHSDeGrT7VhyN4wF3IhRSglUTAWdUl1Qpm/JvPkM/oqPKrWacHV3m/abpJLfz5YLz+RPTeMQ4TIKJyC1uN6bgCyLlsJmcB9LsGgmdBXgwWkUSg7TrhVAEf6OQUgT8754EexK39rwg+0JCkOCHA7mgyZEq43y64HQ6S77s4kD1MH3QZCfMty88n7+l5RM5tlzbg+v4iLYxYp1IljmhyEqa5k4Gxs7TpJDBZUkmyOm8oCGWRU3rnM4zehU5LL3V8t44L3Zy+bziep0F83z7r97+7V/n195Me+zwRt+3+Uu6sHTIzgwppOKQ8+TpsTtxSW+QXfB3Xe4l61Lyfrljp6+OCqzfN/gDJPDWfMLvRmMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;보다 유쾌한 게임 경험을 제공하기 위해 항상 노력하겠습니다.&apos; title=&apos;&apos; src=&apos;/static/38220aea1fcc0dc1e11709f1c7f4dd57/984b6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_6.png&apos; srcset=&apos;/static/38220aea1fcc0dc1e11709f1c7f4dd57/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_6.png 190w,
/static/38220aea1fcc0dc1e11709f1c7f4dd57/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_6.png 380w,
/static/38220aea1fcc0dc1e11709f1c7f4dd57/984b6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%95%98%EB%93%9C%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%98%EC%97%AC.md_6.png 630w&apos; sizes=&apos;(max-width: 630px) 100vw, 630px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;보다 유쾌한 게임 경험을 제공하기 위해 항상 노력하겠습니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 마소 30주년에 부쳐…]]></title><description><![CDATA[9…]]></description><link>https://jiniya.net/wp/archives/12561</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12561</guid><pubDate>Tue, 19 Nov 2013 23:59:23 GMT</pubDate><content:encoded>&lt;p&gt;96년 초여름. 생일 선물로 뭘 받고 싶은지 물어보는 친구 녀석에게 난 겁 없이 마이크로소프트웨어라는 잡지를 말했다. 중학생이라 큰 돈이 없었던 친구 녀석은 고맙게도 용돈을 탈탈 털어서 마소를 선물해줬다.. 그게 내 인생 첫 번째 마소였다. 친구의 선물이기도 했고 너무 신기하기도 했기에 난 마소를 신주단지 모시듯이 두고는 심심할 때마다 펼쳐서 읽었던 기억이 난다. 물론 내가 그 당시 마소에 실린 글 중에 이해하는 글은 단 하나도 없었다. 시쳇말로 흰 건 여백이고, 검은 건 글인 수준이었다. 하지만 난 마소를 읽고, 또 읽으면서 막연하게 내가 어른이 된다면 여기 글을 쓴 아저씨들과 비슷한 일을 하는 사람이 될지도 모르겠다는 생각을 했었던 것 같다.&lt;/p&gt;
&lt;h3&gt;마소, 그리고 프로그래머&lt;/h3&gt;
&lt;p&gt;고등학교 시절부터는 상황이 조금 나아졌다. 동아리에서 회비로 정기 구독을 했기에 언제나 최신 마소를 마음껏 볼 수 있었다. 대학생 때에는 도서관에서 이번 달 마소를 모두 공짜로 볼 수 있었지만 국내 유일의 프로그래밍 잡지가 폐간되지 않기를 간절히 바라는 마음으로 정기 구독을 하기도 했었다 (그시절 프로그램 세계라는 프로그래밍 잡지가 폐간 됐었다). 마소 필자가 된 이후로는 지금까지 증정본을 받아서 보는 호사를 누리고 있다. 결국 난생처음 생일 선물로 마소를 받은 다음 거의 17년 동안 마소를 끼고 살았던 셈이다.&lt;/p&gt;
&lt;p&gt;17년을 함께한 마소를 돌아보면 역설적이게도 기술 보다는 사람이 더 많이 기억에 남는다. 비베 관련 글을 많이 쓰시던 신승근님의 비베 책만 몇 천 권 읽었다는 글을 보면서는 대학교 연구 도서관에 있는 전공 관련 서적을 모조리 다 읽어 버리겠다는 패기에 불타 오르기도 했었고, 나성언님의 인터페이스 저널을 통해서 선배 프로그래머들은 일상에서 어떤 생각을 하는지 조금이나마 훔쳐볼 수 있었다. 안윤호님의 칼럼은 늘 동경의 대상이었다. 저분의 내공은 얼마나 깊을까라는 생각을 하면서 매번 연재되는 글들을 기다렸던 기억이 난다. 주니어 코너에 있었던 황헌주님의 초보 개발자의 일기장을 보면서는 나도 막연하게 직업 프로그래머로 생활하게 된다면 저런 일상을 보낼까라는 생각을 하기도 했었고, 터보 C 정복의 저자로 유명하신 임인건님 같은 대가의 짤막한 인터뷰라도 실리는 날에는 그 글을 끼고 다니면서 나도 먼 훗날 반드시 훌륭한 프로그래머가 되고야 말겠다는 꿈을 키웠다. 일면식도 없는 김성우님은 가장 훌륭한 글쓰기 선생님이었다. 엔지니어에게 글쓰기가 왜 중요한지, 재미있는 글을 쓰기 위해서는 어떤 과정들을 거쳐야 하는지에 대해서 길잡이가 되어준 고마운 글들을 많이 써주셨다.&lt;/p&gt;
&lt;p&gt;또한 마소는 나에게 세상에 나 같은 사람이 또 있다는 사실을 발견하게 해 준 잡지이기도 했다. 어린 시절 주변에는 나와 같은 생각을 하는 친구들이 흔치 않았다. 대부분의 친구 녀석들은 메모리를 최적화 시켜서 19금 게임을 실행시키는 정도의 컴퓨터 지식으로 만족했다. 그 프로그램들이 어떤 원리로 동작하는지, 그것들을 만들기 위해서는 무엇을 배워야 하는지에 대해서 궁금해 하는 친구들은 없었다. 물론 학교 선생님들은 더 몰랐다. 호기심을 해결할 창구도 없었고, 같은 주제를 가지고 열띤 토론을 할만한 친구도 전무했다. 외딴 섬에 혼자 떨어져 있는 느낌이었던 나에게 마소는 세상에 나 같은 사람이 수도 없이 많이 있다는 사실을 알려준 고마운 존재였다.&lt;/p&gt;
&lt;p&gt;학생 시절 나는 마소를 통해서 먼저 이 길을 걸어간 선배 프로그래머들의 주옥 같은 조언을 들을 수 있었다. 직업 프로그래머로 일하는 동안에 마소는 동시대를 살아가는 다른 프로그래머들의 다양한 고민과 생각을 엿볼 수 있는 창문과도 같은 역할을 해주었다. 마소는 항상 나에게 가장 기술적인 잡지인 동시에 가장 사람 냄새 나는 잡지였다.&lt;/p&gt;
&lt;h3&gt;전업 프로그래머를 꿈꾸는 후배들에게&lt;/h3&gt;
&lt;p&gt;나를 포함한 대부분의 프로그래머가 그렇지만 처음 시작할 때에는 누구나 위대한 프로그래머를 꿈꾼다. 몇 일 은둔해서는 새로운 구조의 그래픽 엔진을 뚝딱 만들어내는 존 카맥, 겨울 방학에 심심해서 만들기 시작한 운영체제가 전세계에서 가장 잘 나가는 오픈소스 운영체제가 된 리누스 토발즈, 크리스마스 휴가 기간에 심심해서 만든 파이썬이 NASA에서도 사용하는 프로그래밍 언어가 된 귀도 반 로섬 같은 전설의 프로그래머를 상상하는 것이다. 설상가상으로 거의 대부분의 프로그래머들은 열심이만 하면 자신도 그런 위대한 프로그래머가 될 수 있다는 환상을 가진다.&lt;/p&gt;
&lt;p&gt;처음 시작하던 시절 나 또한 그런 생각이 있었다. 노력하면 위대한 프로그래머가 될 수 있다는 생각과, 내가 제법 똑똑한 프로그래머라는 착각에 빠져 있었다. 물론 그런 착각은 그리 오래가지 않았다. 10년 정도가 지난 지금 내가 업계에서 배운 한 가지 사실은 나는 그냥 철저하게 평범한 지적 수준을 가진 보통 프로그래머라는 것이다. 이런 사실을 깨달았을 때 난 굉장히 심각한 자괴감에 빠졌었다. 갑자기 방향을 잃은 느낌이었다. 아마 프로그래머란 직업에 더 강한 열망을 가진 독자일수록 먼 훗날 나와 같은 상황에 봉착할 확률이 많을 것 같다는 생각이다. 난 방황의 과정 속에서 두 가지 중요한 사실을 발견했다. 부족한 내가 지금까지 직업 프로그래머로 살아가는데 든든한 버팀목이 되고 있기에 잠깐 소개해볼까 한다.&lt;/p&gt;
&lt;p&gt;내가 알게 된 첫 번째 사실은 세상에는 다양한 사람들만큼이나 다양한 문제가 있다는 점이다. 위대한 프로그래머가 반드시 필요한 아주 복잡하고 어려운 문제도 있지만, 평범한 프로그래머도 풀 수 있는 가벼운 문제들도 산재해 있다. 당연히 천재 프로그래머 몇 명이 모두 해결할 수는 없는 노릇이다. 세상에 존재하는 조만가지의 문제를 모두 해결하기 위해서는 보통 수준의 프로그래머도 아주 많이 필요하다. 결국 우리가 모두 다 리누스 토발즈나 존 카맥처럼 되겠다는 생각을 가질 필요도 없고, 그렇게 될 필요도 없다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;두 번째는 사람을 이해하는 프로그래머가 되는 것이 중요하다는 점이다. 10년이란 기간 동안 다양한 프로그래머들을 만났다. 창업을 한 이후에는 개발사에 SDK를 공급하는 업무적 특성 때문에 상대적으로 외부 개발자들과 협업할 기회가 많았다. 그렇게 많은 프로그래머들을 만났는데 사람을 이해하는 프로그래머는 정말 드물었다. 기계와 친숙하고 코딩에 능숙하지만 사람과의 의사 소통에는 젬병인 프로그래머가 비일비재했다. 물론 전문 지식은 다소 부족하지만 사람을 이해하는 능력이 뛰어난 프로그래머도 간혹 있었다. 협업이란 측면에서는 당연히 후자 쪽이 훨씬 일하기 수월했다. 이는 의사 소통 능력이 뛰어나다는 점만으로도 아주 특별한 프로그래머가 될 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;의사소통 능력을 키우려면 어떻게 해야 할까? 당연한 이야기겠지만 그 답은 기계나 전공 서적에 있지 않다. 바로 인문학에 있다. 인문학은 나와 다른 사람들이 이 세상에 존재하는 것을 인식하고, 그 차이를 인정하는 것에서 출발한다. 따라서 인문학을 공부한다는 것은 나와 다른 생각을 가진 수많은 사람들을 포용하는 능력을 키울 수 있다는 것을 의미하기도 한다. 프로그래머가 철학과 고전을 읽어야 하는 이유가 바로 여기에 있다. 고전과 철학 책이 재미 없는 독자라면 연애를 적극 권장해 주고 싶다. 자신과 다른 타인을 이해하고 자신의 바닥을 경험하는데 연애만큼 좋은 수단도 없기 때문이다.&lt;/p&gt;
&lt;h3&gt;60살의 마소를 꿈꾸며&lt;/h3&gt;
&lt;p&gt;많은 사람들이 마소가 최신 트렌드를 충분히 반영하는 잡지가 되기를, 인터넷에서 찾을 수 없는 고급 지식이 실리는 잡지가 되기를 희망한다. 그런데 난 여기에 조금 회의적이다. 활자화돼서 인쇄되는 시간에 벌써 트렌드는 넘어가기 마련이다. 그 정도로 요즘은 빠르다. 인터넷에 없는 고급 지식이 담기길 소망하는 것은 더욱 힘든 일이다. 요즘은 스택오버플로우에 없다면 아직까지 궁금해 한 사람이 단 한 명도 없다는 것을, 구글에 없다면 이 세상에는 없는 지식이라는 말이 나올 정도로 인터넷과 커뮤니티가 발달했다. 사실 우리가 상상할 수 있는 거의 모든 지식이 인터넷에 있다고 해도 과언이 아니라는 이야기다. 특히나 IT쪽 정보는 그 정도가 더 심하다. 그러니 거기에도 없는 정보를 담는다는 말은 조금 어폐가 있는 것 같다.&lt;/p&gt;
&lt;p&gt;나는 마소가 동시대를 살아가는 다양한 프로그래머의 이야기를 담는 잡지가 되기를 소망한다. 앞서간 선배 프로그래머의 조언, 우리 시대 프로그래머의 생각, 그리고 프로그래머를 꿈꾸는 학생들의 고민을 충실하게 담고 있는 잡지가 됐으면 하는 바램이다. 우리가 닿을 수 없는 넘사벽 개발자들의 이야기는 인터넷에도 책에도 얼마든지 있다. 하지만 2013년 대한민국을 함께 살아가는 프로그래머들의 이야기를 담을 수 있는 잡지는 단 하나 마소 밖에는 없다. 마소가 더 많은 프로그래머들에게 사람 냄새 풍기는 잡지로 다가가기를 희망해 본다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[전 우주적 게임 보안 솔루션, XIGNCODE3 프로젝트에 참여할 프로그래머를 찾고 있습니다.]]></title><description><![CDATA[XIGNCODE3 개발 프로젝트에 참여할 C/C++ 윈도우 시스템 프로그래머를 찾고 있습니다. 영어 읽기는 기본, C/C…]]></description><link>https://jiniya.net/wp/archives/12367</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12367</guid><pubDate>Wed, 25 Sep 2013 23:59:22 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.wellbia.com&quot;&gt;XIGNCODE3 개발 프로젝트에 참여할 C/C++ 윈도우 시스템 프로그래머를 찾고 있습니다.&lt;/a&gt; 영어 읽기는 기본, C/C++을 잘하면 좋고, 윈도우 시스템에 대한 이해가 있으면 더 좋고, 파이썬을 다룰 줄 알면 금상첨화, 유닉스 계통 운영체제를 다뤄봤으면 완벽하죠. 새로운 코드를 작성할 수 있을 정도로 능력자라면 정말 땡큐겠지만, 그냥 저냥 있는 코드 보면서 이해할 수 있고, printf 넣어가면서 디버깅 해서 문제점을 찾을 수 있는 정도의 능력만 가져도 감사할 따름입니다.&lt;/p&gt;
&lt;p&gt;“저는 웹 프로그래머 입니다. 저는 드라이버 개발만 하는데요. 저는 C/C++ 프로그래머라 루아나 파이썬은 모릅니다.”와 같이 지나치게 편협한 수준의 범주에 자신을 국한시키는 프로그래머, 투덜이 스머프형 프로그래머는 정중히 사양하겠습니다. 새로운 명령 체계를 가진 CPU, 새로운 아키텍처의 컴퓨터가 주어지더라도 매뉴얼만 있다면 주소록 정도는 간단하게 작성할 수 있는 수준의 사고력을 가지신 분들을 환영합니다. 모르는 건 죄가 아니지만 배우겠다는 의지가 없거나 배우는 속도가 너무 더디면 함께 일하기 힘들기 때문입니다. 일정 수준 이상의 수학적 사고 회로를 뇌에 탑재하신 분이면 좋겠다는 욕심도 초큼 있습니다.&lt;/p&gt;
&lt;p&gt;끝으로 게임 보안 이라는 분야에 관심이 있었던 분, 내지는 안드로메다 해커도 놀랄만큼 위대한 게임 보안 솔루션을 진짜 한번 만들어보고 싶다, 라는 당찬 포부를 가지신 분들이면 최고겠지요. 이런 연유로 스스로 동기부여가 확실하게 되는 분이었으면 좋겠다는 바램도 눈꼽만큼 있습니다.&lt;/p&gt;
&lt;p&gt;개발팀 분위기는 조용하게 혼자 연구하고 뭔가 속닥속닥 만드는 거 좋아하시는 분이라면 편하게 일할 수 있는 환경입니다. 물론 좀 액티브하고 토론하는거 좋아하고 하는 분이면 더 좋을 것 같지만 그런 분들은 흔치 않지요. 대체적으로 거의 모든 일을 스스로 알아서 잘해야 합니다. 누가 이거저거 일일이 정해주고 시키고 해야지 일을 할 수 있는 분이라면 안타깝지만 우리와는 잘 맞지 않을 것 같네요. 스스로 일을 만들고, 계획을 세우고, 결국에는 해내는 주도적인 성향을 가지신 분을 선호합니다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;최고 근무 환경 -&gt; 최고 프로그래머들 -&gt; 최고 소프트웨어 -&gt; 수익 -&gt; 최고 근무 환경&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 조엘의 피드백 루프: 어디서 시작하든 상관은 없다. 어디든 진입이 힘들다는 건 함정.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;우리는 조엘의 피드백 루프를 믿습니다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/831&quot;&gt;최고의 프로그래머가 얼마나 희소한지, 얼마나 중요한지 뼈저리게 알고 있습니다.&lt;/a&gt; 따라서 자금이 허락하는 한도 내에서 최고의 근무 환경을 만들기 위해서 노력하고 있습니다. 물론 자금이 허락하는 한도가 부족하다는 함정이 있긴 합니다.&lt;/p&gt;
&lt;p&gt;소프트웨어 개발에서 가장 중요한 요소는 &lt;a href=&quot;http://sangminpark.wordpress.com/2011/09/13/%EC%98%81%EC%9B%85-%EC%97%86%EB%8A%94-%EB%82%98%EB%9D%BC/&quot;&gt;개념의 일관성(conceptual integrity)&lt;/a&gt; 이라고 생각합니다. 소수 정예로 설계하고 만드는 것이 좀 더 효율적이라고 생각합니다. 우리가 만드는 소프트웨어가 그리 크지 않기 때문이기도 하구요. 어중이 떠중이 머리수만 늘리면 된다는 생각을 혐오합니다.&lt;/p&gt;
&lt;p&gt;그 프로젝트에 참여하는 프로그래머는 몇 명인가요, 라는 질문보다는 그 프로젝트엔 누가 참여하나요, 라는 질문을 더 좋아합니다. 네. 맞습니다. 사람 중요한지 아는 회사입니다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;모든 프로그래머는 두 개의 모니터를 가져야 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;모든 프로그래머는 빠른 컴퓨터를 가져야 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;모든 프로그래머는 자신이 선택할 수 있는 마우스와 키보드를 가져야 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;모든 프로그래머는 편안한 의자를 가져야 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;모든 프로그래머는 빠른 인터넷 접속 환경을 가져야 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;모든 프로그래머는 정숙한 작업 환경을 가져야 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
  &lt;br&gt;
&lt;p&gt;-- &lt;a href=&quot;http://www.codinghorror.com/blog/2006/08/the-programmers-bill-of-rights.html&quot;&gt;프로그래머 권리장전, Jeff Atwood&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./전_우주적_게임_보안_솔루션,_XIGNCODE3_프로젝트에_참여할_프로그래머를_찾고_있습니다_.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/506608767fefc9fc467df7cbc3882c6a/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAUC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAHaNiK6YNf/xAAaEAADAQEBAQAAAAAAAAAAAAAAAgMBEhEi/9oACAEBAAEFApt6I/ctppSnRjsp9Mf/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwFH/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BV//EABoQAAIDAQEAAAAAAAAAAAAAAAABESExQVH/2gAIAQEABj8C1KPSU1XGXBhRJ//EABoQAQADAAMAAAAAAAAAAAAAAAEAESFBUZH/2gAIAQEAAT8h3lPk5aEa7GGbRvdlkoATYdMRfE//2gAMAwEAAgADAAAAEHwP/8QAFhEBAQEAAAAAAAAAAAAAAAAAABFR/9oACAEDAQE/EIvH/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEh/9oACAECAQE/EMiH/8QAHhABAQACAQUBAAAAAAAAAAAAAREAITFBUWFxkaH/2gAIAQEAAT8QoOzsobdZsfytDG6L1y5SQHKfcYwJR5W93JE48IJ+42JfB0T3n//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 XIGNCODE3                           md 0&apos; title=&apos;&apos; src=&apos;/static/506608767fefc9fc467df7cbc3882c6a/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_0.jpg&apos; srcset=&apos;/static/506608767fefc9fc467df7cbc3882c6a/8ccab/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_0.jpg 190w,
/static/506608767fefc9fc467df7cbc3882c6a/ea4c8/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_0.jpg 380w,
/static/506608767fefc9fc467df7cbc3882c6a/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_0.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;프로그래머라면 응당 최고급 컴퓨터를 써야 한다고 생각합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;우린 CPU 보다는 소중한 존재니까염 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;  
&lt;h3&gt;#2&lt;/h3&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./전_우주적_게임_보안_솔루션,_XIGNCODE3_프로젝트에_참여할_프로그래머를_찾고_있습니다_.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ce4f0a6e0b0ee0d7371845b33e345c4b/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.73684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAEDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABaKhoEZL/AP/EABsQAAIDAAMAAAAAAAAAAAAAAAISAQMRACIx/9oACAEBAAEFAmjjdYswVMp8KrU//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAECAQE/AQyf/8QAHxAAAQQABwAAAAAAAAAAAAAAAAECESESIjIzgZKh/9oACAEBAAY/Atodk9E1diJHJNFYeUP/xAAcEAACAgIDAAAAAAAAAAAAAAABEQAhQWExUXH/2gAIAQEAAT8hL26uKSOmV0h3MAai3gAKrcKsHBnyNDFtn//aAAwDAQACAAMAAAAQIx//xAAXEQEAAwAAAAAAAAAAAAAAAAAAASEx/9oACAEDAQE/EJ1T/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhcf/aAAgBAgEBPxBiwU//xAAdEAEBAAICAwEAAAAAAAAAAAABEQAhMUFRcZGh/9oACAEBAAE/ENNvrgEDn5lxckpHWh+3DMJeoceOvWUXXsQsGrmoHCo7jrDfEAITsO5n/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 XIGNCODE3                           md 1&apos; title=&apos;&apos; src=&apos;/static/ce4f0a6e0b0ee0d7371845b33e345c4b/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_1.jpg&apos; srcset=&apos;/static/ce4f0a6e0b0ee0d7371845b33e345c4b/8ccab/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_1.jpg 190w,
/static/ce4f0a6e0b0ee0d7371845b33e345c4b/ea4c8/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_1.jpg 380w,
/static/ce4f0a6e0b0ee0d7371845b33e345c4b/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_1.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;도서비 따위 아끼지 않습니다. 느낌 아니까…&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;  
&lt;br&gt;
&lt;p&gt;저는 거의 대부분의 컴퓨터 지식을 책을 통해 배웠습니다. 지금도 책은 지식을 습득할 수 있는 가장 저렴하고 효과적인 수단이라고 믿고 있습니다. 요즘은 인터넷 검색이면 충분하다는 생각을 가지신 분들도 많은데, 인터넷에 존재하는 파편화된 지식은 절대로 책이 제공하는 총체적인 지식을 대체할 순 없다는 생각입니다. 책을 통해 틀을 세우고, 틀 사이에 존재하는 간극을 인터넷 검색과 토론을 통해서 메우는 것이 맞다는 생각입니다. 그런고로 도서비는 아끼지 않습니다. 보고 싶은 책이나 자료는 모두 구비해 드립니다. 일년에 책을 12권 보다 적게 읽고, 인터넷 검색이면 충분하다고 생각하시는 프로그래머라면 알러지가 생길지도 모르겠습니다. 적어도 한번쯤은 기술 서적을 읽으면서 가슴 벅차 본 느낌이 있는 분들을 사랑합니다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;카맥은 거창한 수사 같은 것은 혐오했지만, 다그쳐 물으면 적어도 나름대로 한 가지 의견을 피력하곤 했다. “정보화 시대에 장벽이란 없다. 장벽은 자기가 만드는 것이다. 새롭고 원대한 것을 계획하고 개발하는 데 수백만 달러의 자본이 필요치 않다. 냉장고에 채울 피자와 다이어트 코크, 작업에 쓸 값싼 PC, 그리고 해내겠다는 의지만 있으면 된다. 우리는 바닥에서도 잤다. 물이 불은 강도 걸어서 건넜다.”&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 둠, 데이비드 커시너&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; margin-bottom: 16px;&apos; data-url=&apos;./전_우주적_게임_보안_솔루션,_XIGNCODE3_프로젝트에_참여할_프로그래머를_찾고_있습니다_.md_2.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4064179dfc214c65c5cbb3715bcd89f7/95cb2/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDAf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAAByTrlqXI//8QAGxAAAwACAwAAAAAAAAAAAAAAAQIDABESITL/2gAIAQEAAQUC2q5YmiSTSDye0ko4f//EABYRAQEBAAAAAAAAAAAAAAAAAAEQIf/aAAgBAwEBPwFMn//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AVf/xAAdEAABAgcAAAAAAAAAAAAAAAAAARACESExQYGh/9oACAEBAAY/AqCTwW40Wm//xAAcEAEBAQABBQAAAAAAAAAAAAABEQBBITFhgaH/2gAIAQEAAT8hQAi+FukJa4NEOr0yUXdw4Y+6TSu//9oADAMBAAIAAwAAABCXL//EABcRAAMBAAAAAAAAAAAAAAAAAAABEVH/2gAIAQMBAT8QjRHp/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERUf/aAAgBAgEBPxCxk4f/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhMUGRsf/aAAgBAQABPxBzW/WfiXIW2K2e/Joij1iK6RAa2nyDcTmMPSwbVe/J/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 XIGNCODE3                           md 2&apos; title=&apos;&apos; src=&apos;/static/4064179dfc214c65c5cbb3715bcd89f7/95cb2/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_2.jpg&apos; srcset=&apos;/static/4064179dfc214c65c5cbb3715bcd89f7/8ccab/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_2.jpg 190w,
/static/4064179dfc214c65c5cbb3715bcd89f7/ea4c8/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_2.jpg 380w,
/static/4064179dfc214c65c5cbb3715bcd89f7/95cb2/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_2.jpg 520w&apos; sizes=&apos;(max-width: 520px) 100vw, 520px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;버닝하는 여러분을 위해 에너지 드링크와 컵라면은 상시 제공됩니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;참이슬 후레시와 헛개 컨디션은 흔치 않은 아이템 ㅋㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;  
&lt;h3&gt;#4&lt;/h3&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./전_우주적_게임_보안_솔루션,_XIGNCODE3_프로젝트에_참여할_프로그래머를_찾고_있습니다_.md_3.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fd18960eb894e21c53c1b77d862d893e/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_3.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEA//EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAUeXQCcP/8QAGRAAAgMBAAAAAAAAAAAAAAAAAQIAEiER/9oACAEBAAEFAg4lQ0I1VzpCXM//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAEAAwEAAAAAAAAAAAAAAAAAARAhMf/aAAgBAQAGPwKsQ6yX/8QAGxAAAwACAwAAAAAAAAAAAAAAAAERMVEhYXH/2gAIAQEAAT8hyklytGVM6Gpk8S7HPyKkiUs3SU//2gAMAwEAAgADAAAAENPP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8Qqv/EABwQAQEBAAIDAQAAAAAAAAAAAAERAHGxITFB4f/aAAgBAQABPxAiFoW1fGlWA4usv9Uj+c6L7HWpETBOcs6i+b//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 XIGNCODE3                           md 3&apos; title=&apos;&apos; src=&apos;/static/fd18960eb894e21c53c1b77d862d893e/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_3.jpg&apos; srcset=&apos;/static/fd18960eb894e21c53c1b77d862d893e/8ccab/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_3.jpg 190w,
/static/fd18960eb894e21c53c1b77d862d893e/ea4c8/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_3.jpg 380w,
/static/fd18960eb894e21c53c1b77d862d893e/7fbea/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_3.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;열린 환경을 지향합니다. 신입이 뭘 알아, 따위의 소리는 하지 않습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;모든 걸 볼 수 있고, 모든 걸 바꿀 수 있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;&lt;br&gt;  
&lt;p&gt;소스 코드에 겹겹이 접근 제한을 걸고, 개발 PC 인터넷을 끊고, 안그래도 사양이 떨어지는 개발 PC에 복잡한 보안 소프트웨어 설치를 강요하고, USB를 포함한 저장 장치는 들고 들어갈 수도 없고, 개발 PC가 있는 방에 들어가기 전에 소지품 검사를 하고, 모든 소지품은 사물함에 보관한 다음에 개발 PC에 접근할 수 있는 회사들이 많이 있습니다. 사람을 믿지 못하는거죠. 프로그래머도 사람이니까요. 근데 이런 곳에서 무슨 창조성이 발휘 되겠습니까? 그리고 그리 한들 잘될까요? 의문입니다.&lt;/p&gt;
&lt;p&gt;기본적으로 우리는 함께 일하는 사람을 신뢰합니다. 자신의 PC 보안은 알아서 잘 지킬 수 있다고 판단합니다. 소스 코드에 대한 접근 제한도 없습니다. 모든 걸 볼 수 있고, 모든 걸 바꿀 수 있습니다. 큰 회사에서 일하면서 도대체 이놈에 모듈은 어떻게 만든건지도 모른체 갑갑함 속에서 개발했다면 모든 것을 통제할 수 있는 상태에 있는 여기가 바로 천국일지도 모르겠네요. ㅋ~&lt;/p&gt;
&lt;p&gt;그러다 사고나면 어쩌냐구요? 소스 코드 유출이 큰 문제라는 생각은 하지않습니다. 우리가 판매하는 것은 300만 라인의 오픈 소스와 30만 라인의 소스 코드가 컴파일된 바이너리 파일도, 10만개가 넘는 패턴 오브젝트를 포함한 데이터베이스 파일도 아닌 해킹툴을 차단할 수 있는 우리의 능력이라고 생각하기 때문입니다.&lt;/p&gt;
&lt;p&gt;물론 현재 버전의 코드가 유출되더라도 내일의 XIGNCODE3는 그때의 기술과는 다른 버전이 될 거라는 자신감이 있기 때문이기도 합니다. 우리는 코드를 설명하는 장황한 매뉴얼을 만들지 않습니다. 언제나 코드와 매뉴얼 사이에는 불일치가 있다고 생각하기 때문에 최대한 코드를 이해하기 쉽게 쓰고, 그런 코드만 보고도 매뉴얼 수준의 이해를 할 수 있는 사람과 함께 일하기를 희망합니다. 코드 작성할 시간도 없는데 앉아서 MSDN 만들고 있을 수는 없잖아요. — 조엘 아저씨가 말했듯 MSDN이 친절한 이유는 윈도우가 소스 코드를 제공하지 않기 때문입니다. — 그리고 더 중요한 건 그 매뉴얼을 만드는 사이 전체 코드는 열두번도 더 바뀌기 때문에 언제나 매뉴얼은 틀릴 수 밖에 없다는 맹점을 가지고 있기도 하구요.&lt;/p&gt;
&lt;p&gt;이랬든 저랬든 한 가지 확실한 사실은 우리는 프로그래머 여러분들에게 실오라기 하나 걸치지 않은 아주 투명한 환경을 제공한다는 것입니다.&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;최고의 실력자를 뽑을 수 없다는 것 누구보다 잘 알고 있습니다. 그래서 염치없이 최고로 잘하는 사람을 뽑습니다, 라는 소리 따윈 하지 않습니다. 현실적인 수준에서 우리와 같이 일할 수 있는 사람을 찾고 있습니다. 앞서도 말했듯이 당장은 관련 지식이 좀 부족하더라도 빠르게 배울 수 있는 분들을 더 환영합니다. 특히 이쪽 분야에 진지하게 관심이 있고, 정말 제대로 된 제품 한번 만들어 보겠다는 의지가 있는 분들이었으면 좋겠습니다.&lt;/p&gt;
&lt;p&gt;구구절절 떠들었는데 지원은 어떻게 하냐구요? codewiz 앳 wellbia 닷 com으로 메일 주시면 됩니다. 이력서와 간단한 자기소개서를 보내 주셔도 되고, 지속적으로 관리하는 자신의 블로그나 인터넷 사이트가 있는 경우에는 해당 사이트 주소만 보내주셔도 됩니다.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 497px; margin-bottom: 16px;&apos; data-url=&apos;./전_우주적_게임_보안_솔루션,_XIGNCODE3_프로젝트에_참여할_프로그래머를_찾고_있습니다_.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1a76c050422bb5ec3444bd9f613d3681/c8b0d/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 28.421052631578945%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABMElEQVR42lWRh27CMBCGef8XKyqlhFJCGRkkZHiRCLIgJn/PTlSplizd8uf/7mago/ULeZridDjS9RD6PoIgRNd1qKsKbdugrms0TWNjbdva+yDbxO73ymAw92rMjPHse3jHE+L4As45WM6g1BVKSqRJCikEWJaDM44rxU0N5wJlUdhcluZEGTD3J6DWGoefPfb7AyRBBBVflSSgGsFCIUkS65vPyrJEQfGyKMHok+7xtArfvGoE9r22CndbFzk9MAqUUqMaxq1vlKQ0FgOUBsyojgnrcyGnlifgMABHUrdzd9h+bbD8WGK9crD9drEh3/lcwVk6cFbr0abc4n2BLGMkpkfTdv+BZimXKLKLiM8xovAM7+RNM0zI9hGdI6q5IPADO+sojHC7jcvQr+Gv5V9hbMBkJdhfUwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 XIGNCODE3                           md 4&apos; title=&apos;&apos; src=&apos;/static/1a76c050422bb5ec3444bd9f613d3681/c8b0d/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_4.png&apos; srcset=&apos;/static/1a76c050422bb5ec3444bd9f613d3681/08678/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_4.png 190w,
/static/1a76c050422bb5ec3444bd9f613d3681/2edd7/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_4.png 380w,
/static/1a76c050422bb5ec3444bd9f613d3681/c8b0d/%EC%A0%84_%EC%9A%B0%EC%A3%BC%EC%A0%81_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98%2C_XIGNCODE3_%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90_%EC%B0%B8%EC%97%AC%ED%95%A0_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A5%BC_%EC%B0%BE%EA%B3%A0_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_.md_4.png 497w&apos; sizes=&apos;(max-width: 497px) 100vw, 497px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;건방진 중2병 해커의 허세…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;해커들에게 보안이 뭔지 따끔하게 가르쳐 줄 수 있는 실.력.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;그리고 정말 제대로 된 게임 보안 솔루션을 만들어 보고 싶다는 열.정.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이 두 가지를 가지고 있다면 지금 바로 지원하세요.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[서비스 지원의 품격]]></title><description><![CDATA[얼마 전 모 업체 대표님과 저녁에 술을 마셨습니다. 바(BAR…]]></description><link>https://jiniya.net/wp/archives/12338</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12338</guid><pubDate>Fri, 13 Sep 2013 23:59:21 GMT</pubDate><content:encoded>&lt;p&gt;얼마 전 모 업체 대표님과 저녁에 술을 마셨습니다. 바(BAR)를 갔는데, 그 바 주인 아줌마가 아침에는 광고 일을 하는 분이었어요. 같이 술을 마시던 대표님이 원래 광고 쪽에서 유명하셨던 분이라 클라이언트가 누구냐는 질문을 했습니다. 주인 아줌마는 뻘쭘해 하며 별로 유명하지 않다고 얼버무렸습니다. 재차 이어진 대표님의 질문. 주인 아주머니는 자신은 하청의 하청이라며 자신의 클라이언트도 아니라는 식으로 부끄러워 하면서 업체명을 이야기 했습니다. 그때 질문을 했던 대표님께서 그러셨습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;광고쟁이가 클라이언트를 부끄러워하면 그건 자격이 없는 사람이다. 광고 쟁이는 자신의 고객이 유명하거나 유명하지 않거나, 또는 돈을 많이 주거나 적게 주거나 상관 없이 그 업체가 세상에서 최고의 제품을 만든다는 생각으로 광고를 만들어야 한다. 한치라도 클라이언트에 대해서 부끄럽다거나 별로라는 생각을 가지는 순간 그 쟁이는 아웃이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;술도 제법 마셨고, 너무 늦은 시간까지 이어진 술 자리라 피곤하기도 해서 정확한 문구가 기억나진 않지만 대략적인 뉘앙스는 비슷했던 것 같습니다. 저 이야기를 듣고는 저도 조금은 부끄러운 생각이 들었습니다. 그리곤 저 정도 생각을 하니까 한 업체의 대표를 하고 있고, 또 그 회사가 성공하고 있는 거구나, 라는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;최근에 저희 회사도 고객이 제법 생겼습니다. 동시 접속자가 많은 게임도 있고, 적은 게임도 있습니다. 매출 순위에서 1위를 하는 게임도 있고, 목록에 오르지도 못하는 게임도 있습니다. 상대적으로 계약 금액이 높은 게임도 있고, 낮은 게임도 있습니다. 잘 만든 게임도 있고, 그렇지 않은 게임도 있습니다. 유명한 게임도 있고, 아무도 모르는 게임도 있습니다.&lt;/p&gt;
&lt;p&gt;이렇게 모두 다 다른 게임들이지만 한 가지 공통점이 있다면 모두 우리가 만든 보안 솔루션을 사용하기로 결정한 게임이라는 점입니다. 그러니 우리에겐 다 같은 게임이고, 모두 다 최고의 게임입니다. 하지만 마음 한 켠에서는 그렇지 않은 생각도 있었던 것이 사실입니다. 유명세에 따라 그들의 요구사항에 차등을 두려는 저질스런 생각이 있었던 것이죠.&lt;/p&gt;
&lt;p&gt;그날 술자리를 파하고 집으로 돌아오면서 그런 생각이 들었습니다. 우리가 만든 XIGNCODE3라는 솔루션을 탑재하고 서비스가 되고 있는 게임이라면, 단 한 명의 사용자만 그 게임을 즐긴다 할지라도 그 게임이 우리의 얼굴이라는 생각입니다. 그러니 우리는 그 게임의 표면적인 지표와는 상관없이 그 게임이 해킹으로 피해를 입지 않도록 최선을 다해서 서비스를 제공할 의무가 있고, 반대로 그 업체는 최고의 서비스를 받을 권리가 있는 겁니다.&lt;/p&gt;
&lt;p&gt;웰비아닷컴에서 단 하루만 서비스를 받은 고객일지라도 그 회사 참 친절하다, 고맙다, 라는 생각이 드는 그런 회사였으면 좋겠습니다. 사내에 있는 모든 사람이 고객에게 항상 가난한 마음가짐을 가지고 있는 회사였으면 하는 바램입니다. 서비스 지원의 품격을 아는 센스 있는 사람들이 모여있는 회사이길 소망해 봅니다. 느낌 아니까…&lt;/p&gt;
&lt;p&gt; 18
 152&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[원 데이 (One Day)]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12317</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12317</guid><pubDate>Fri, 13 Sep 2013 23:59:20 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; margin-bottom: 16px;&apos; data-url=&apos;./원_데이_(One_Day).md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ae515f573e373dfbba4d0b74fc3f0b4c/56d4e/%EC%9B%90_%EB%8D%B0%EC%9D%B4_(One_Day).md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAGVU1JRFAf/xAAbEAABBAMAAAAAAAAAAAAAAAACAAEREwMxQf/aAAgBAQABBQIYXaiWnoZFiKf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAADAAMBAAAAAAAAAAAAAAAAARESMjNh/9oACAEBAAY/AvSQ1EzKtM6M/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARIWExQf/aAAgBAQABPyGtBu3xiGFlandOpsvQexkRqP8A/9oADAMBAAIAAwAAABAEz//EABYRAAMAAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxAxf//EABYRAQEBAAAAAAAAAAAAAAAAAAARIf/aAAgBAgEBPxCRj//EABsQAQADAQADAAAAAAAAAAAAAAEAESExQXHh/9oACAEBAAE/EHbVKsoY43hG73IBjcd5C7NocfMHTuFcalpV7Ps//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      One Day  md 0&apos; title=&apos;&apos; src=&apos;/static/ae515f573e373dfbba4d0b74fc3f0b4c/56d4e/%EC%9B%90_%EB%8D%B0%EC%9D%B4_(One_Day).md_0.jpg&apos; srcset=&apos;/static/ae515f573e373dfbba4d0b74fc3f0b4c/8ccab/%EC%9B%90_%EB%8D%B0%EC%9D%B4_(One_Day).md_0.jpg 190w,
/static/ae515f573e373dfbba4d0b74fc3f0b4c/ea4c8/%EC%9B%90_%EB%8D%B0%EC%9D%B4_(One_Day).md_0.jpg 380w,
/static/ae515f573e373dfbba4d0b74fc3f0b4c/56d4e/%EC%9B%90_%EB%8D%B0%EC%9D%B4_(One_Day).md_0.jpg 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;사랑을 부르는 낭만의 도시, 파리~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;영화 ‘클래식’을 재미있게 봤다던 친구 녀석이 추천해줘서 ‘원 데이’란 영화를 보게 되었습니다. 앤 해서웨이가 나오는 영환데, 전 정말 앤 해서웨이가 이렇게 예쁜 배우라는 사실을 처음 알았습니다. 그녀의 딱딱한 영국식 억양 마저도 귀여워 보이게 만드는 묘한 매력이 있더군요.&lt;/p&gt;
&lt;p&gt;영화는 사랑하는 한 남자를 멀리서 지켜보는 한 여자에 관한 이야깁니다. 이 영화를 보면 딱 두 가지 사실에 놀랄 겁니다. 아름다운 영상에 한번 놀라고, 앤 해서웨이의 미모에 또 한번 놀랄 거예요. 물론 덱스터 역을 맡은 배우도 토나오게 잘생겼습니다. 수려하게 이어지는 영상에 고요하게 물 흐르듯 흐르는 스토리는 가슴을 짠하게 만듭니다. 특히나 마지막 회상 장면을 볼 때에는 정말이지 가슴이 먹먹해 지더군요.&lt;/p&gt;
&lt;p&gt;영화 후반부에 나오는 이안의 대사가 참 가슴에 와 닿았습니다. 진짜 사랑이란 어쩌면 이런게 아닐까, 라는 생각…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ian: She made you decent, and in return you made her so happy, so happy.&lt;/p&gt;
&lt;p&gt;이안: 그녀는 너를 훌륭하게 만들어 줬어. 그리고 너는 그녀를 웃게 만들어줬지. 정말 기쁘게.&lt;/p&gt;
&lt;p&gt;– One Day, 2011&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Emma: Whatever happens tomorrow, we had today.&lt;/p&gt;
&lt;p&gt;엠마: 내일 무슨 일이 있든지간에 우린 오늘 하루를 살았어.&lt;/p&gt;
&lt;p&gt;– One Day, 2011&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 21
 1&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[건축학개론]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5882</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5882</guid><pubDate>Thu, 12 Sep 2013 23:59:19 GMT</pubDate><content:encoded>&lt;p&gt;주말에 정말 오랜만에 영화관에서 영화를 봤다. 우연찮게 서점에 갔다가 영화나 볼까하는 생각이 들어서 즉흥적으로 윗층에 있는 영화관으로 향했다. 오랜만에 가는 영화관이라 그랬을까? 실패하고 싶지 않다는 생각에 아이뻐 앱을 가지고 평점도 보고, 소감도 보고 이러면서 뭘 볼지를 한참을 고민했다. 첨에는 화차를 보려고 했었다. 접때 화차 감독님이 나온 두드림 방송이 퍽이나 감동적이었기 때문이었다. 근데 나의 손가락은 벌써 건축학개론을 선택하고 있었다. 이유야 머 단순하다. 후훗. 수지짱에 가인느님까지… 이거야 뭐, 영화가 똥망이라 하더라도 눈은 즐겁지 않겠냐는 생각이었다.&lt;/p&gt;
&lt;p&gt;그런데 영화는 생각보다 대박이었다. 특히 그 납뜩이 역할이 진짜 제대로였다. 조금 지루할라치면 한번씩 등장해서는 빵빵 터트려줬다. 주인공이 손목 때리는거 보통 사이에서는 하는거 아니지 않냐는 택도 아닌 질문을 했을 때 납뜩이의 받아치는 대사, “그럼 뭐할까? 아구창이라도 날릴까?” 여기서 진짜 쓰러질뻔 했다. ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 영화를 보고 나온 남자들의 98%는 SNS에 xxx 개론의 누구 누구가 떠오른다는 글을 남긴다고 한다. 영화를 보고 나오는 그때, 나도 제일 처음 떠오른 생각은 컴퓨터 개론 수업이었다. 물론 안타깝게도 나는 개론의 그녀가 떠올라서 생각났다기 보다는 그냥 나는 무얼 들었나 하는 생각에서였다.&lt;/p&gt;
&lt;p&gt;내가 들었던 컴퓨터 개론은 정말 생각하기도 싫을 만큼 끔찍한 수업이었다. 교수님은 수면제 그 자체였고, 강의실은 지하였으며, 강의실 크기에 비해서 수강한 학생이 너무도 많아서 들어가기만해도 갑갑했다. 거기다 공대 수업 아니겠는가? ㅋㅋ~ 한 2-3번 듣다가 그 담부터는 전부 여친 수업을 듣거나 학교 앞 CNN(만화방)에서 죽치고 있었던 것 같다.&lt;/p&gt;
&lt;p&gt;그 수면제 교수님은 학점 깐깐하게 주기로 유명했기에 난 당연히 F를 받았다. 복학해서 그 수업을 재수강 했는데, 개론 수업이 없어져서 Visual Basic을 대체 과목으로 들어야 했다. 정말 속으로는 감사합니다를 한 백 번 외쳤던 것 같다. ㅋㅋㅋ&lt;/p&gt;
&lt;p&gt;Visual Basic은 1학낸 때의 개론 수업보다는 좀 나았다. 일단 수업이 지상이었고, 학생도 딱 숨어서 수업 듣기 좋을 정도로 있었고, 거기다 Visual Basic은 그냥 땅짚고 헤엄치기 ㅋㅋ~ 재수강이 아닌 1학년들이 조금 불쌍하게 보였다. 나 말고도 재수강을 하는 사람이 부지기수였고, 병특을 마치고 온 사람들도 더러 있었기 때문이었다. 복학한 시점에 들은 수업이라 수업은 정말 꼬박꼬박 들어갔었던 것 같다. 그 수업엔 그래도 공대 치고는 괜찮은 여학생들이 더러 있었는데 풋풋한 감정을 느끼기엔 너무 닳고 닳은 나이가 아니었나라는 생각…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;영화 전체를 관통하는 플롯인 첫사랑을 15년 만에 만난다는 설정은 정말 공감갔다. 누구나 한 번쯤 가지는 경험 아닐까? 물론 영화처럼 내가 건축가가 됐는데 첫사랑이 집 지어 달라고 오는 경우는 쉽지 않겠지만 말이다. 나한테 첫사랑이 찾아와서는 대뜸 이런 저런 프로그램을 짜달라고 하는 일은 더 없겠지? 여튼 보통 사람이라면 이런 식으로 첫사랑을 다시 대면하는 경우는 거의 없을 것이다. 대부분 머 뻔한 동창회를 통해서 다시 만나곤 한다.&lt;/p&gt;
&lt;p&gt;나도 동창회에서 그런 경험을 한 적이 있는데 정말 욱겼다. 그 아이는 진짜 첫사랑이었는데, 내 인생에 있어서 처음이자 마지막인 짝사랑이었다. 여튼 그 초등학교 동창을 10년이 훌쩍 지나 대학생 때 알럽스쿨이라는 불륜 제조기를 통해서 다시 만나게 됐다. 시간이 많이 지났고 어떻게 변했을지 무척 궁금해 했던 기억이 난다. 설레이는 마음으로 모임을 나갔는데. 하앍~ 여전히 너무 아름다운 것이 아닌가? ㅋㅋ~ 깜짝 놀랐다. 10년이 훌쩍 지나서 만났는데도 난 그 아이 앞에서 한 번도 제대로 이야기를 하지 못했던 것 같다. 첫사랑은 첫사랑이더라는 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;건축학개론이 밋밋한 스토리에도 불구하고 퍽이나 감동적인 이유는 아마도 이 영화가 큰 억지를 가지고 있지 않기 때문인 것 같다. 영화 속의 모든 소재가 실제로 누구에게나 있을 법한 그런 것들이다. 개론 수업에서 만난 첫사랑, 돈많은 선배, 연애 상담해 주는 친구, 실타래처럼 엉켜버린 관계, 그리고 첫사랑을 한참만에 만난다는 설정까지. 누구나 흔히 겪어 봄직한 이야기라 많은 사람들의 공감을 사는 것 같다는 생각이 든다.&lt;/p&gt;
&lt;p&gt;몇 년 전이긴 한데 19살 꼬맹이하고 소개팅을 했던 적이 한 번 있었다. 사람들이 다 미쳤다고 하기는 하는데 그 소개팅 느낌이란 마치 사촌동생 밥사주고 커피사주고, 고민 상담해주는 느낌이었다. 그때 그런 생각이 들었다. 아, 내가 만약 이 애랑 만난다면 그건 진짜 범죄 행위가 될수도 있겠다. 그 친구가 평생 한 번 경험할 수 있는 풋풋한 사랑을 할 기회를 내가 박탈할지도 모른다는 생각이 들었기 때문이다.&lt;/p&gt;
&lt;p&gt;뭐든지 시기가 있다는 말을 많이 한다. 난 풋풋한 사랑을 할 수 있는 결정적 시기가 그리 길지 않다고 생각한다. 나이 들어서도 얼마든지 열정적이고 격렬한 사랑을 할 수도 있다. 하지만 절대로 풋풋한 사랑을 다시 할 수는 없다. 왜냐하면 처음이 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;풋풋함이란 처음에만 느낄 수 있는 감정이다. 그래서 그런 풋내나는 사랑은 영원히 추억할 수 밖에는 없다. 영화 보는 내내 좋았던 그 시간들이 생각났다. 걱정도 없었고, 생각도 없었고, 그냥 막 살아도 뭔가 될 것 같은 가능성만 있었던 그런 시기에 했던 풋풋한 사랑이란…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;일단 우리가 어떤 경험을 하고 나면, 다시는 그 경험을 하기 이전처럼 세상을 볼 수 없게 된다는 것이다. 우리가 어떤 경험을 하는 순간부터 그 경험은 과거, 현재, 그리고 미래를 보는 렌즈의 일부가 되어 우리가 보는 것들을 조성하고 왜곡한다. 이 렌즈는 안경처럼 밤에 벗어서 침대 곁 탁자에 놓아둘 수 있는 것이 아니다. 이 렌즈는 마치 강력접착제로 우리의 눈동자에 영원히 붙여 놓은 콘택트렌즈와 같다.&lt;/p&gt;
&lt;p&gt;– 행복에 걸려 비틀거리다, 대니얼 길버트&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[연기 (緣起) …]]></title><description><![CDATA[벤자민 버튼의 시간은 거꾸로 간다, 200…]]></description><link>https://jiniya.net/wp/archives/12269</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12269</guid><pubDate>Wed, 11 Sep 2013 23:59:18 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;벤자민 버튼의 시간은 거꾸로 간다, 2008&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;가끔 생각해보면 정말 그 모든 일들이 기적만 같습니다. 그 모든 과정에 아주 사소한 일 하나만 달랐어도 아마 지금 저는 어떻게 됐을지 모르니깐 말입니다. 물론 더 잘됐겠죠? ㅋㅋㅋ~ 이런 걸 보면 불교의 ‘연기’라는 말이 실감납니다. 우리가 지금 이렇게 존재하고 있다는 건, 그 자체로도 이미 말도 안되는 기적같은 일들이 모두 맞아 떨어진 결과입니다. 아마 태엽을 감아서 다시 지금처럼 만들어 보라고한다면 우린 절대 성공할 수 없을 겁니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;인터넷 수업을 듣지 않았다면,&lt;/p&gt;
&lt;p&gt;인터넷 수업 레포트로 홈페이지 만드는 과제가 나오지 않았다면,&lt;/p&gt;
&lt;p&gt;내가 과제를 무시했다면,&lt;/p&gt;
&lt;p&gt;그 회사 사장이 약속을 지켰다면,&lt;/p&gt;
&lt;p&gt;빡쳐서 그 회사를 때려치지 않았다면,&lt;/p&gt;
&lt;p&gt;그 회사 사장이 전력선 통신에 미치지 않았다면,&lt;/p&gt;
&lt;p&gt;그 회사 사장이 엉뚱한 회장을 섭외하지 않았다면,&lt;/p&gt;
&lt;p&gt;그 회장이 회사를 말아먹지 않았다면,&lt;/p&gt;
&lt;p&gt;회사가 망하는 과정에 병무청에 아는 사람이 없었다면,&lt;/p&gt;
&lt;p&gt;교수님 아들이 같은 학번의 동창이 아니었다면,&lt;/p&gt;
&lt;p&gt;홈페이지 과제를 내주신 교수님이 소개해 준 다른 회사가 정상적인 회사였다면,&lt;/p&gt;
&lt;p&gt;그 회사에 다단계에 미친 실장만 없었다면,&lt;/p&gt;
&lt;p&gt;그 당시 잉여로운 시간이 없었다면,&lt;/p&gt;
&lt;p&gt;객기에 그 회사를 뛰쳐나오지 않았더라면,&lt;/p&gt;
&lt;p&gt;그 팀장이 내 이력서를 그냥 흘려 보냈더라면,&lt;/p&gt;
&lt;p&gt;그 채용 담당자가 전화를 받지 않는다고 두 번 전화하지 않았다면,&lt;/p&gt;
&lt;p&gt;회사 이름만 듣고 홈페이지를 들어가보지 않았다면,&lt;/p&gt;
&lt;p&gt;먼저 면접 본 회사에서 나를 그렇게 무시하지 않았더라면,&lt;/p&gt;
&lt;p&gt;그 회사에 동향에 동성을 가진 실장님이 안계셨다면,&lt;/p&gt;
&lt;p&gt;그 날 DOM 모임에 참석하지 않았더라면,&lt;/p&gt;
&lt;p&gt;내가 술을 안마셨다면,&lt;/p&gt;
&lt;p&gt;그때 팀원이 나를 좋게 소개해 주지 않았더라면,&lt;/p&gt;
&lt;p&gt;그때 내가 시건방진 미친 소리를 안했더라면,&lt;/p&gt;
&lt;p&gt;내가 잉여 시간에 인터넷 활동을 안했더라면,&lt;/p&gt;
&lt;p&gt;그 회사 사장이 미쳐서 우리를 다 자르지 않았더라면,&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;살면서 우리는 다양한 사건 속에 놓이고 그 사건들에 대한 반응은 피드백되서 우리에게 새로운 사건으로 또 주어집니다. 결국 우리는 무수히 많은 상호작용 속에서 존재하는 것이죠. 이러한 상호작용의 결과가 지금의 ‘나’를 만들고 있는 겁니다. 운명이라는 것이 있다면 사건에 대한 우리의 반응, 내지는 선택의 모음이 아닌가라는 생각을 해봅니다.&lt;/p&gt;
&lt;p&gt;당신은 오늘 어떤 선택을 하셨나요?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Life is C between B and D.&lt;/p&gt;
&lt;p&gt;인생은 태어남(Birth)과 죽음(Death) 사이에 있는 선택(Choice)이다.&lt;/p&gt;
&lt;p&gt;– Jean Paul Sartre&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 1
 17&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[모바일 게임 보안 솔루션: XIGNCODE3 for Android]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12153</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12153</guid><pubDate>Thu, 29 Aug 2013 23:59:17 GMT</pubDate><content:encoded>&lt;p&gt;모바일 게임 보안 솔루션 분야에 &lt;a href=&quot;http://www.jiniya.net/wp/archives/9960&quot;&gt;출사표를&lt;/a&gt; 던진지도 제법 시간이 지났습니다. 관련 제품이 전무한 상태이고, 저희 쪽에서도 직접적으로 광고를 하고 있지는 않은 상태라 아직도 많은 분들께서 모바일 게임 쪽에는 안티 해킹 솔루션이 없다고 알고 계신 경우가 많은 것 같습니다. 이런 안타까운 현실을 조금 개선하고자 요즘 가장 핫한 모바일 게임 보안 솔루션인 &lt;a href=&quot;http://www.wellbia.com/dp/&quot;&gt;XIGNCODE3 for Android&lt;/a&gt;의 기능에 대해서 잠깐 소개를 해보는 시간을 가져볼까 합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;역사는 반복된다고 했던가요? 모바일 시장을 보고 있으면 온라인 게임 보안 시장의 예전 모습을 보는 듯한 느낌이 많이 들곤 합니다. 온라인 게임 보안의 초기 시장의 경우에도 많은 게임 업체에서 외부 솔루션 업체는 믿지 못한다는 생각으로 직접 하겠다고 덤빈 경우가 많았습니다. 물론 안타깝게도 대부분 결과가 좋지 않았습니다. 그런 과도기를 거친 후에는 매출이 일정 수준 이상인 게임들은 통상적으로 게임 보안 솔루션을 필수적으로 탑재하는 시대가 오게 되었습니다.&lt;/p&gt;
&lt;p&gt;시간이 흘러 흘러 최근에는 게임 출시 전에 사용자들이 제일 먼저 묻는 질문 중에 하나가 이런 것들이 되었습니다. 안티치트 솔루션이 무엇이냐? 해킹 방지 대책이 무엇이냐? 이런 현상을 반영하듯 요즘은 외부 솔루션 업체만으론 힘에 부치기에 게임사 내부에도 별도의 보안팀을 두어서 외부 솔루션 업체가 특화시키지 못하는 — 외부 솔루션 업체는 특성상 범용적인 보안을 할 수 밖에는 없답니다. — 게임의 세부 사항들에 대한 보안을 강화해 나가는 추세입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 483px; margin-bottom: 16px;&apos; data-url=&apos;./모바일_게임_보안_솔루션_XIGNCODE3_for_Android.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/01d7f6960a7eb81af52937ab32af2118/a3f7c/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 52.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACDklEQVR42l2S22/TMBjF82dy0QK9sNJudB20WkFsCNax0o2LeBgIiZeBNCREeRkPvEwwgQTtGKs0LhJT2zhJO9auceI4aeMbzloVxEnsHB9/v/h7sAKhHQQB55wxNp7/NUMRRikLRRkdbgkhFAc5rutKRymVEaWjvfEynEOScsGtAHrMkyFhJIRt23bxX5gNxcMjTpbywwQXdb/pUDTfuv3CKofFPPyXghDCGP8HSzOggQyPSGfAA3lO4XD1YedxAsxmzGtbzvYO/hrCEMGuezyGOeOYepDY0shw/XijQ7rv0IfTjXhEm5oEGflONC+qWnLf/6EYvdZWd1vWBTQgnMgON+HbhfZyFe3+7P+6at58cPQoZ85fAOmUfiUBMkl9dkrPxsD0J1wN2y4079UDTWLykbrVLqlaKqZdmjHyCZBTtek4uHweZKMgG9GyEZCLh+HMDt5TXORcb85lW/kveK8+aLyGm2e0aBQkY3pSBZMpEEnqibQeWTLO5nV1wZhYNNQ5/VwanKrgz4rve1XwpGzcWGsUnukra83F51qxbN59CZbetO6/N4ofW8WKeWffLNXaqzVj+Xt7ZdcsVczCb6+myBviub7suI+wYCLwiIcPsVd3eujAP+hZlut4to2Q6xPCIXQDIhzH6/epRBQRig8Hl7QQTvBNg68s6D3trnecjmXZlg3FyZUaVY68+AOpwDM9uDQbGwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;              XIGNCODE3 for Android md 0&apos; title=&apos;&apos; src=&apos;/static/01d7f6960a7eb81af52937ab32af2118/a3f7c/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png&apos; srcset=&apos;/static/01d7f6960a7eb81af52937ab32af2118/08678/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png 190w,
/static/01d7f6960a7eb81af52937ab32af2118/2edd7/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png 380w,
/static/01d7f6960a7eb81af52937ab32af2118/a3f7c/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png 483w&apos; sizes=&apos;(max-width: 483px) 100vw, 483px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;모바일 핵 탐지 카운트. 모바일 해킹, 온라인 못지 않습니다. 자바는 거들뿐…&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;먼저 모든 솔루션이 그렇겠지만 과연 이게 필요한가, 과연 그 조악한 모바일 디바이스에서 해킹을 시도하는 사용자가 당췌 얼마나 될까라는 의문을 가질 수 있습니다. 우선 그 질문에 대한 답변을 먼저 하자면, 단언컨대 모바일 환경의 해킹 시도는 온라인의 그것 못지 않게 심각합니다.&lt;/p&gt;
&lt;p&gt;아직 블랙마켓이 형성되기 전이라 전문 프로그래머들이 진출하진 않았습니다. 바야흐로 초딩의 시대죠. 하지만 만만하게 볼 초딩이 아닙니다. 상상력 하나는 끝짱이거든요. 몇몇 메모리 조작 도구들이 개발되었고 초딩들은 그것들을 하염없이 개조해고, 개조하고, 또 개조해서 우회 엔진이라 말하며 웹사이트에 올립니다. 거기서 끝이 아니죠. 그 올려진 도구를 사용해서 밤새도록 끊임없이 앱의 메모리를 염탐하고 조작하고 있습니다. 이런 초딩 인구가 집계가 되지 않을 정도로 많다는 카더라 통신도 있습니다.&lt;/p&gt;
&lt;p&gt;더 심각한 상황은 엄마가 컴퓨터는 끄라고 하지만 핸드폰을 끄라는 소리는 하지 않기 때문에 핸드폰이라는 디바이스는 초딩들에게 24시간 열려있습니다. 이런 연유로 초보 해커인 초딩들은 오늘도 밤새도록 이불 밑에서 앱 메모리를 탐색하면서 어딘가 허점은 없을까? 아이템을 공짜로 훔칠순 없을까? 연구하고 또 연구하고 있습니다. 여기다 초딩의 영웅심이 더해지면 해킹툴 유포 속도는 빛의 속도에 근접하게 됩니다. 인정받고 싶어하는 그들의 욕구 때문에 절대로 알아낸 지식을 혼자만 알고 끝내는 법이 없지요. 어떻게는 짜투리 지식도 공유하고 또 공유합니다. 집단 지성 풀이 만들어지는 겁니다. 특히나 요즘 초딩들은 조기 교육 덕분에 영어 리소스에 손쉽게 접근할 수 있습니다. 이런 사실은 그들이 아주 고급스런 인터넷 정보에 접근할 수 있음을 의미하지요. 더불어 더 이상 그들이 초딩의 지식 한계에 머무르지는 않는다는 것을 의미하기도 합니다. 이쯤되면 메이저 업체에서 만든 앱들도 난자 당하는 건 시간 문제라는 걸 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;게임이 인기를 끌면 끌수록 모여드는 초딩은 늘어나고 게임은 더 많은 해킹 위협에 노출됩니다. 컨텐츠 개발에 힘써야 할 게임 프로그래머들이 변수 오프셋을 변경하고 값을 암호화 시키는 작업에 더 많은 시간을 투자하게 됩니다. A를 A라 저장하지 못하는 그야말로 난감한 상황이 됩니다. 게이머들의 컨텐츠 소모 속도는 빨라지고, 게임 프로그래머의 개발 속도는 더뎌집니다. 결국 개발한 앱은 컨텐츠 경쟁력에서 뒤쳐질 수 밖에 없습니다. 심지어는 실컷 만들어 놓고, 사용자도 많은데 매출은 없는 기형적인 구조가 되기도 합니다.&lt;/p&gt;
&lt;p&gt;이쯤되면 아 뭔가, 우리를 대신해서 이 초딩 집단을 컨트롤해 줄 현자가 필요하겠구나, 라는 생각이 듭니다. 안드로이드 시스템에 해박한 지식을 가진, 리눅스를 적어도 커널 1.2 때부터는 사용해 왔던, X윈도우 커서 앞에서 눈물을 한번쯤 흘려 본 똑똑한 시스템 프로그래머가 필요한 시점인거죠.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;안드로이드의 가장 큰 홀은 다름 아닌 자바입니다. 자바는 그냥 게이머들에게 소스 코드를 던져주는 것과 똑같습니다. 변수값을 암호화해도 암호화 키나 시드 값을 알아내기가 정말 쉽습니다. 자바 코드는 너무 쉽게 디컴파일이 되고, 그걸 다시 컴파일해서 리패키징 하는 작업은 ‘식은 죽 먹기’입니다. 해킹 앱을 변조해서 새로 만들어내는 방법은 이미 튜토리얼 수준으로 공개돼 있어서 컴퓨터에 접근할 수 있는 초딩이라면 누구나 30분 내에 자신만의 독자적인 신규 해킹 앱을 제조해 낼 수 있는 수준입니다.&lt;/p&gt;
&lt;p&gt;주먹구구 식으로 해킹 앱 패키지명 몇 개를 추가하는 것으로는 공격의 속도를 감당할 수 없습니다. 마치 UCC 처럼 해킹 앱을 제작해서 배포하는 수준이기 때문에 기존의 해시 시스템으로도 대응하기가 힘든 속도입니다.&lt;/p&gt;
&lt;p&gt;XIGNCODE3 for Android는 온라인에서 검증된 우수한 패턴 처리 시스템과 백엔드 시스템을 사용해서 이렇게 초딩들이 마구잡이로 만들어내는 변종 앱들을 신속하게 처리할 수 있는 구조를 가지고 있습니다. 더욱이 저희는 Android 환경의 APK 전용 패턴 시스템을 별도로 제작했습니다. 이 방식을 통해서 초딩들이 허구헌날 새로 만들어내는 변종 앱들에 대해서도 패턴 변경 없이 놀라울 정도로 높은 수준의 진단율을 유지할 수 있는 구조를 가지고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아주 잘 다듬어진 패턴 시스템이지만 무력화 시키는 것이 불가능하지는 않습니다. 그 벽을 뚫고 넘어온 친구들에게 우리는 루팅 체크라는 아름다운 선물을 제공해 주고 있습니다. 안드로이드 환경에서 다른 앱 메모리를 변조하기 위해서는 루트 권한 획득이 필수적이기 때문에 해킹 앱들은 필수적으로 루트 권한을 획득해야 합니다.&lt;/p&gt;
&lt;p&gt;한가지 안타까운 점은 기존의 잘못된 상식 때문에 이 기능의 효용 가치가 너무나 심각하게 훼손 됐다는 점입니다. 기존 앱들, 심지어 금융앱에서도 루팅 체크를 su나 supersu의 존재를 체크하거나 특정 경로의 존재 유무를 체크하는 방식을 사용하고 있습니다. 잘 아시겠지만 이 방식을 우회하는 것은 정말 쉽습니다. 요즘 루팅 앱에서는 임시 언루팅이라는 이름으로 그러한 기능을 제공해 주고 있습니다. 반대로 이 방식의 치명적인 단점은 루팅 됐다는 사실 만으로 앱 실행을 차단한다는 점입니다. 루팅이란 자신의 돈으로 산 디바이스의 주인 권리를 찾겠다는 말인데 이걸 찾았다고 앱 실행을 제한한다는 것은 조금 이상합니다. 특히 금융 앱이 아닌 앱들에서는 이러한 허들은 앱을 사용하는 접속자를 늘리는데 도움이 안 되는 방식임에 틀림없습니다.&lt;/p&gt;
&lt;p&gt;당연히 저희는 기존의 파일, 경로 체크와 같은 조악한 방식의 루팅 체크를 사용하지 않습니다. 우리는 진짜 시스템 프로그래머잖아요. 직접 프로세스에 접근해서 관련 조사를 수행합니다. 이 방식을 우회하기 위해서는 리눅스 커널을 새로 디자인하거나 시스템 전체의 동작 방식을 변경하는 아주 복잡한 작업이 필요합니다. 그래서 우회하기가 쉽지 않죠. 더불어 루팅 됐다는 사실만으로는 차단 하지 않기 때문에 동접 건전성을 유지할 수 있습니다.&lt;/p&gt;
&lt;p&gt;루팅 앱을 체크하는 문제가 쉽게 느껴질 수 있습니다. 하지만 생각보다 쉬운 문제는 아닙니다. 바로 권한 페널티가 있기 때문입니다. 안드로이드 환경은 기본적으로 루팅을 불법으로 간주하고 있습니다. 따라서 정상 어플리케이션이 루트 권한을 요구하기란 쉽지 않습니다. 물론 루팅 단말에서만 권한을 요구할 수 있지만 그것 또한 정상적인 운영체제 경험을 위배하기 때문에 좋은 전략이라고 볼 수는 없습니다.&lt;/p&gt;
&lt;p&gt;이런 연유로 안드로이드 환경에서는 통상적으로 해킹툴은 모든 권한을 가지고 있고, 보안 제품은 제한된 권한을 가질 수 밖에는 없습니다. 이렇게 권한 차이가 발생하는 것을 두고 우리는 권한 페널티가 존재한다고 이야기합니다. 결국 낮은 권한을 가진 프로그램이 높은 권한을 가진 프로그램을 탐지해야 하는 문제라는 것이죠. 이 이야기를 쉽게 말하면 다른 우주에 있는 범죄자를 잡는 것과 똑같다고 생각하시면 됩니다. 우주 끝이 어딘지도 모르는데 우주 밖에 있는 범죄자를 잡아야 한다뉘 욱기죠. 그래서 어려운 문제입니다.&lt;/p&gt;
&lt;p&gt;XIGNCODE3 개발 팀은 다년간 이런 환경에서 작업을 해 왔고 권한 페널티에 있어서는 누구보다 전문가 입니다. 모두가 드라이버 설치를 강제할 때 그걸 옵션으로 했고, 모두가 64비트 프로세스를 띄울 때 WoW64에서 모든 것을 처리하도록 만들었습니다. 단언컨대 권한 페널티에 있어서 우리보다 전문가는 없다고 자부합니다. 우리는 낮은 권한에서 높은 권한을 가진 오브젝트를 검사하는 다양한 전략과 전술을 알고 있습니다. 이런 온라인 보안에서의 실전 경험은 모바일 보안에서도 당연히 진가를 발휘할 수 밖에 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;완벽한 보안 솔루션이란 없습니다. 물론 저희도 완벽하진 않습니다. 다만 빛의 속도로 완벽해지는 것을 추구하는 한 솔루션입니다. 여러분의 게임을 서버 기반으로 디자인 했기 때문에 안전하다고 생각하실지도 모르겠습니다. 하지만 여전히 자동 플레이는 큰 문제이며, 오픈 플랫폼인 안드로이드의 취약점을 공격하는 것에 대해서는 속수무책일 수 밖에 없습니다. 알려진 공격루트를 허용하는 것과 차단하는 것 사이에는 하늘과 땅만큼의 차이가 있다는 점을 꼭 기억할 필요가 있습니다.&lt;/p&gt;
&lt;p&gt;모바일 게임 보안, 이제 선택이 아닌 필수입니다.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 483px; margin-bottom: 16px;&apos; data-url=&apos;./모바일_게임_보안_솔루션_XIGNCODE3_for_Android.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/01d7f6960a7eb81af52937ab32af2118/a3f7c/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 52.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACDklEQVR42l2S22/TMBjF82dy0QK9sNJudB20WkFsCNax0o2LeBgIiZeBNCREeRkPvEwwgQTtGKs0LhJT2zhJO9auceI4aeMbzloVxEnsHB9/v/h7sAKhHQQB55wxNp7/NUMRRikLRRkdbgkhFAc5rutKRymVEaWjvfEynEOScsGtAHrMkyFhJIRt23bxX5gNxcMjTpbywwQXdb/pUDTfuv3CKofFPPyXghDCGP8HSzOggQyPSGfAA3lO4XD1YedxAsxmzGtbzvYO/hrCEMGuezyGOeOYepDY0shw/XijQ7rv0IfTjXhEm5oEGflONC+qWnLf/6EYvdZWd1vWBTQgnMgON+HbhfZyFe3+7P+6at58cPQoZ85fAOmUfiUBMkl9dkrPxsD0J1wN2y4079UDTWLykbrVLqlaKqZdmjHyCZBTtek4uHweZKMgG9GyEZCLh+HMDt5TXORcb85lW/kveK8+aLyGm2e0aBQkY3pSBZMpEEnqibQeWTLO5nV1wZhYNNQ5/VwanKrgz4rve1XwpGzcWGsUnukra83F51qxbN59CZbetO6/N4ofW8WKeWffLNXaqzVj+Xt7ZdcsVczCb6+myBviub7suI+wYCLwiIcPsVd3eujAP+hZlut4to2Q6xPCIXQDIhzH6/epRBQRig8Hl7QQTvBNg68s6D3trnecjmXZlg3FyZUaVY68+AOpwDM9uDQbGwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;              XIGNCODE3 for Android md 0&apos; title=&apos;&apos; src=&apos;/static/01d7f6960a7eb81af52937ab32af2118/a3f7c/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png&apos; srcset=&apos;/static/01d7f6960a7eb81af52937ab32af2118/08678/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png 190w,
/static/01d7f6960a7eb81af52937ab32af2118/2edd7/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png 380w,
/static/01d7f6960a7eb81af52937ab32af2118/a3f7c/%EB%AA%A8%EB%B0%94%EC%9D%BC_%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_XIGNCODE3_for_Android.md_0.png 483w&apos; sizes=&apos;(max-width: 483px) 100vw, 483px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;약은 약사에게 진료는 의사에게, 보안은 XIGNCODE3가 하는 걸로 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.wellbia.com/dp/&quot;&gt;XIGNCODE3 for Android&lt;/a&gt;는 검증된 유일한 모바일 게임 보안 솔루션입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[어느 택시 기사 아저씨의 조언]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12120</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12120</guid><pubDate>Thu, 22 Aug 2013 23:59:16 GMT</pubDate><content:encoded>&lt;p&gt;강남에서 저녁 먹고, 술을 한 잔 하고는 집에 오는데 피곤해서 택시를 탔다. 친구 녀석이 같은 방향이라 떨궈주고 가려고 같이 탔는데, 가는 길에 기사 아저씨와 친구 사이에 약간 실랑이가 있었다. 기사 아저씨가 실수로 길을 조금 돌아간 것이다. 결국 공은 나에게 왔고, 난 피곤해서 그냥 가자고 했다.&lt;/p&gt;
&lt;p&gt;그 일 때문에 친구가 내리고 택시 기사 아저씨와 이런 저런 이야기를 하게 됐다. 대기업에서 28년 근무하시고는 얼마 전에 정년 퇴직 하셨다는 아저씨. 몇 마디 안에 그 아저씨의 지식이나 철학적 사유의 깊이가 범상치 않음을 느낄 수 있었다. 그래서 나도 모르게 이런저런 이야기를 털어놓게 됐는데, 의외로 생면부지의 택시 기사 아저씨에게 뜻깊은 조언을 들을 수 있었다.&lt;/p&gt;
&lt;p&gt;물론 뭐 뻔하다면 뻔한 이야기이긴 하다. 하지만 그날 난 쉬운 길을 택하며 자기 합리화를 한 껏 하고 있던 시점이라 아저씨의 이런 이야기는 나에게 의미있는 일침이 되었고, 내가 저지를 뻔 한 더 큰 실수를 막아주었다.&lt;/p&gt;
&lt;p&gt;나 자신도 내 맘에 안 드는데, 남이 내 맘에 들기가 어디 쉽겠는가. 욕심을 버리자. 마음을 비우고.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;당신과 직장 상사와 부하 직원으로 만나는 그 사람들도 사실 직장 내 관계라는 그 사소한 조건 하나만 떼고 나면 당신과 하나도 다를 것이 없는 사람입니다. 그들을 내치는 것은 쉽습니다. 그것보다 그들에게 기회를 주고 방향을 제시하는 것이 리더의 역할입니다. 물론 경우에 따라서는 많은 기회를 제공했음에도 조직 내에서 함께 일하기엔 정말 힘든 사람들도 있을겁니다. 그런 경우에도 마지막 말은 꼭 아껴두세요. 헤어질 때 여운을 조금 남겨 놓는 편이 당신 인생에 큰 도움이 될 겁니다. 인생이란 정말 신비로워서 나중에 그 사람을 어떤 장소, 어떤 위치에서 어떻게 만나게 될지 절대로 알 수 없답니다.&lt;/p&gt;
&lt;p&gt;만약 당신이 그 사람들에게 존중받길 원한다면 반대로 그 사람들을 먼저 존중하는 습관을 가지는 것이 중요합니다. 화를 내고, 욕을 하고, 재떨이를 던지는 일은 누구나 할 수 있는 일입니다. 하지만 상대를 진심으로 이해하고 존중하는 일은 그 누구도 쉽게 하지 못한다는 점을 꼭 기억하세요.&lt;/p&gt;
&lt;p&gt;– 하계에 거주하신다는 어느 택시 기사님의 말씀&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;나는 문관이고 상대는 무관이라 하여 그를 괄시해서는 안 되며, 나는 세력이 강하고 상대는 힘이 약하다 하여 교만하게 대해서는 안 되며, 나는 현명하고 그는 어리석다 하여 그를 무시해서는 안 되며, 나는 늙었는데 그는 젊다 하여 서글퍼 해서도 안 된다. 엄숙하고 공손하고 겸손하고 온순하여 예의를 잃지 않으며, 화평하게 하여 뒤틀리고 막힘이 없게 하면 정과 뜻이 서로 통할 것이다.&lt;/p&gt;
&lt;p&gt;– 목민심서, 정약용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 153
 32&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[인생은 불공평한 것~]]></title><description><![CDATA[there is always inequity in life. Some men are killed in a war and some men are wounded, and some men never leave the country, and some men…]]></description><link>https://jiniya.net/wp/archives/12095</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12095</guid><pubDate>Tue, 06 Aug 2013 23:59:15 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;there is always inequity in life. Some men are killed in a war and some men are wounded, and some men never leave the country, and some men are stationed in the Antarctic and some are stationed in San Francisco. It’s very hard in military or in personal life to assure complete equality. Life is unfair.&lt;/p&gt;
&lt;p&gt;삶에는 언제나 불공평한 점들이 존재합니다. 어떤 사람은 전쟁에서 죽고, 어떤 사람은 부상을 입고, 어떤 사람은 절대로 해외로 나갈 수 없고, 어떤 사람은 남극에 주둔하고, 어떤 사람은 샌프란시스코에 주둔합니다. 군대나 개인의 삶을 100% 공평하도록 보장하는 것은 매우 힘든 일입니다. 인생은 불공평합니다.&lt;/p&gt;
&lt;p&gt;– John F. Kennedy: “The President’s News Conference,” March 21, 1962.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;기회는 평등하겠지만 결과는 결코 평등할 수 없다. 결과가 공평하다는 건 어느 누군가에게는 평등하지 않다는 것이기 때문에 말 자체가 넌센스 같기도 하다. A는 휴가 일수가 20일인데, 난 왜 10일이지, B는 인센티브를 100원 받았는데 난 왜 없지, C는 쉐프가 요리해 준다는데 난 왜 쉐프가 없지, 수영장은, 바리스타는, … 이 모든 것에 대한 대답을 딱 한마디로 해주면 당신은 그걸 받을 만큼 뛰어나지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;회사는 직원을 채용하면서 모든 직원이 다 뛰어나길 기대하진 않는다. 잘하는 사람도 있고, 못하는 사람도 있다. 소녀시대같은 슈퍼스타가 필요한 부분도 있고, 묵묵히 그 뒤에서 그들의 치장을 도와줄 아티스트들이 필요한 경우도 있다. 그런데 아티스트들이 왜 우리는 소녀시대 같지 않냐고 한다면 뭐라고 대답해야 할까? 거울을 보라고 해야 할까? 반대로 생각해보자. 돌려서 회사에서 당신은 왜 소녀시대 같지 않냐고 묻는다면 뭐라고 대답할 건가? 그 미칠듯이 많은 사람들이 소녀시대는 줄서서 보려고 기다리면서 왜 당신은 기다리지 않은 것일까?&lt;/p&gt;
&lt;p&gt;누구도 당신의 능력이 타인과 동등해야 한다고 요구하지 않았다. 그러니 당신도 이제 세상을 향해서 결과가 공평해야 한다는 주장은 좀 접도록 하자. 이마트에서 3000원에 파는 한라봉을 재래시장에서 5000원에 판다고 상인에게 따져 무엇하겠는가? 이마트에 가서 사 먹든가, 한라봉을 먹지 말든가해야지.&lt;/p&gt;
&lt;p&gt; 10
 5&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[토속촌 기행]]></title><description><![CDATA[#0    고 노무현 전대통령이 맛있다고 해서 일약 스타덤에 오른 삼계탕집이 있으니 바로 종로에 있는 토속촌이다. 이 삼계탕집이 얼마나 유명하냐면 일개 삼계탕 집임에도 국세청의 세무조사까지 받았었다. MB…]]></description><link>https://jiniya.net/wp/archives/12001</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12001</guid><pubDate>Tue, 06 Aug 2013 23:59:14 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; margin-bottom: 16px;&apos; data-url=&apos;./토속촌_기행.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e47f0bbe78b96e458018751c07a5991a/ba98e/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAADAf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHTYRhcaHnR2MLaP//EABsQAAIDAAMAAAAAAAAAAAAAAAECAAMREhMg/9oACAEBAAEFApghsUQclDa06FmDDXhLnx//xAAWEQEBAQAAAAAAAAAAAAAAAAARABD/2gAIAQMBAT8BI3//xAAWEQEBAQAAAAAAAAAAAAAAAAARABD/2gAIAQIBAT8BZ3//xAAfEAACAQIHAAAAAAAAAAAAAAAAAgEQIRESIDJBgdH/2gAIAQEABj8CLthSOS7dG9aZlI80f//EAB0QAQEBAAICAwAAAAAAAAAAAAERACExEEFRYbH/2gAIAQEAAT8hG+8qU3chLdFDX7g9krefRjWtEyF2nr50kBZz9sef/9oADAMBAAIAAwAAABCA1r7/xAAXEQADAQAAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EEMX/8QAFREBAQAAAAAAAAAAAAAAAAAAASD/2gAIAQIBAT8QYP/EAB0QAQEAAwEAAwEAAAAAAAAAAAERADFBIRBhcZH/2gAIAQEAAT8QJF2S4hWlBPJcXsx3wv8AXHRNpm18j0xeqop+35kZb9nsxUxHmMrH3KfTFROm1s3nw6mAOf/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 0&apos; title=&apos;&apos; src=&apos;/static/e47f0bbe78b96e458018751c07a5991a/ba98e/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_0.jpg&apos; srcset=&apos;/static/e47f0bbe78b96e458018751c07a5991a/8ccab/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_0.jpg 190w,
/static/e47f0bbe78b96e458018751c07a5991a/ba98e/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_0.jpg 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;  &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./토속촌_기행.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/79ea7b100038ff93e6575e6e9591c182/7fbea/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEFAgT/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAU9zM7pnKJ//xAAaEAEBAQADAQAAAAAAAAAAAAACAQMABBES/9oACAEBAAEFAtIfk+DOdX2aNI3C8NQn/8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQMBAT8BV//EABYRAQEBAAAAAAAAAAAAAAAAAAARIf/aAAgBAgEBPwGsf//EAB0QAAICAQUAAAAAAAAAAAAAAAABAhFhEiExQYH/2gAIAQEABj8C3XpVpxeS41WTT0clKbR//8QAGhABAQEAAwEAAAAAAAAAAAAAAREAITFBUf/aAAgBAQABPyGzFPimDTyBOmQVuUrInB9hqONkZHg7/9oADAMBAAIAAwAAABDD/wD/xAAWEQEBAQAAAAAAAAAAAAAAAAABEDH/2gAIAQMBAT8QRTI//8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/EADLj//EAB0QAQADAAEFAAAAAAAAAAAAAAEAESExQVFhcbH/2gAIAQEAAT8QpiZFHTssHKulp83zK1FchvoqMVRFja+QCQR3SF+ug1P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 1&apos; title=&apos;&apos; src=&apos;/static/79ea7b100038ff93e6575e6e9591c182/7fbea/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_1.jpg&apos; srcset=&apos;/static/79ea7b100038ff93e6575e6e9591c182/8ccab/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_1.jpg 190w,
/static/79ea7b100038ff93e6575e6e9591c182/ea4c8/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_1.jpg 380w,
/static/79ea7b100038ff93e6575e6e9591c182/7fbea/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_1.jpg 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;고 노무현 전대통령이 맛있다고 해서 일약 스타덤에 오른 삼계탕집이 있으니 바로 종로에 있는 토속촌이다. 이 삼계탕집이 얼마나 유명하냐면 일개 삼계탕 집임에도 &lt;a href=&quot;http://www.joseilbo.com/news/htmls/2013/02/20130214171660.html&quot;&gt;국세청의 세무조사&lt;/a&gt;까지 받았었다. MB가 그렇게 꼼꼼하게 털어주시는 바람에 더 유명해졌는지도 모르겠다. 어쨌든 매번 가보자는 말만 하다가 이번 주말에 첨으로 가보게 되었다.&lt;/p&gt;
&lt;p&gt;12시에 보기로 했는데 너무 과한 시간이었다. 1시간 늦춰서 한시에 삼계탕 집엘 갔다. 실제로는 더 늦은 시간이었는데도 사람들이 빼곡히 줄을 서 있었다. 헐. 무슨 삼계탕을 줄서서 먹지, 라고 생각했는데 여기까지 왔으니 줄을 일단 서고 봤다. 저 뒤에 주차장까지 한 50미터는 줄을 서 있었다. 그 줄에서 약간 기대를 가졌다. 진짜 맛있나? 이러면서… 그런데 실제로 삼계탕을 받아들고 먹으면서는 맛은 개인의 취향이니 다 다를 수 있다는 생각을 했다. 소문난 잔치에 먹을 것 없다는 속담을 떠올리면서 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;국물은 보통 삼계탕 집보다는 조금 더 진한 수준이었는데 닭이 무슨 돌닭이 나오는 느낌이었다. 단단해도 너.무. 단단했다. 심지어 해체가 잘 안 될 지경, 큭~ 잘 익었음에도 딱딱했다. 그냥저냥 먹을만한 삼계탕이었는데, 줄서서 막 찾아가서 먹고 싶을 정도의 삼계탕은 아니라는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;개인적으로 서울에서 가 본 삼계탕 집 중에서는 &lt;a href=&quot;http://www.xn--989ar29a23aj97a5kg.com/index.php?mid=map_hq&quot;&gt;호수 삼계탕&lt;/a&gt;이란 곳이 제일 괜찮았다. 예전에 고등학교 친구가 놀러와서 데리고 간 적이 한 번 있었는데, 이번에도 놀러와서는 그 집에 가자는 이야기를 했었다. 그 시크한 놈이 그런 말을 하기에 어지간히 괜찮았나 보다 라고 속으로 생각만 했다. 멀어서 그냥 족발 사줬는데 족발이 어쩌고 저쩌고 어찌나 궁시렁 되던지 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;난 서울이 참 사람 살기에 좋은 곳은 아니라는 생각을 많이 한다. 가장 주된 이유는 사람이 많아도 너무 많기 때문이다. 잘 싸돌아 뎅기지도 않지만 가끔 어디 나갈 일이 있어서 지하철을 한번씩 타보면 정말 숨이 탁탁 막힌다. 물론 지하철 뿐만이 아니다. 어딜 가나 사람이 토나올 정도로 많다. 그런데 진짜 역설적인 사실은 그렇게 싫어하는 이유 넘버원이 바로 나를 서울에 살 수 밖에 없게 만드는 이유라는 점이다. 죄다 서울에 있으니 다른 곳에 있으면 결국 매번 서울로 와야 하는 것이다. 실제로 이날 만났던 후배 녀석도 부산에서 사업을 하다 일주일에 서울을 2-3번씩 와야 하는 어처구니 없음에 결국 서울로 왔다.&lt;/p&gt;
&lt;p&gt;어쨌든 이렇게 사람 많은 서울도 한가지 장점은 있는데 바로 볼 게 많다는 점이다. 어딜가나 뭐가 많다. 그리고 세미나든 뭐든 죄다 일단 서울은 하고 본다. 그러니 보고 싶은 게 많고 구경하는 거 좋아하는 사람들한테는 참 좋은 곳이기도 하다. 이날도 삼계탕 집에서 나와서는 광화문 쪽으로 가다 &lt;a href=&quot;http://www.much.go.kr/MuPageLink.do&quot;&gt;대한민국 역사 박물관&lt;/a&gt; 이란 곳이 있어서 들어가 보게 되었다. 그런데 생각보다 재밌었다. 다음에 시간 나면 설명할 때 정주행을 한 번 하고 싶을 정도였다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 240px; margin-bottom: 16px;&apos; data-url=&apos;./토속촌_기행.md_2.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/db0545e7eb07cf92120990a28b27b5c9/6e1d3/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIDBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAbqQUMXcIgkTRbTLLxH/xAAeEAABAwQDAAAAAAAAAAAAAAABAAIRAxIhMQQQMv/aAAgBAQABBQKVdlXYE3N0aDYHGaF5QHR3/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8BKf/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABkQAAIDAQAAAAAAAAAAAAAAAAARASAhUf/aAAgBAQAGPwITrknRTlP/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhMRBBUWH/2gAIAQEAAT8h1JmF8KNm0x4Sq6Y1VmPZcGWjC+kuhE1wqeiP/9oADAMBAAIAAwAAABDM6wD/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEQH/2gAIAQMBAT8QzEUr/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEREP/aAAgBAgEBPxDIiH//xAAeEAACAgICAwAAAAAAAAAAAAABEQAhMUEQcVGhsf/aAAgBAQABPxCljHsDbXL3DnYMm3WYQDM7cKS2JlkIWdB+O/UKETjaJQf2UqBBHTSgoFHweMnYn//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 2&apos; title=&apos;&apos; src=&apos;/static/db0545e7eb07cf92120990a28b27b5c9/6e1d3/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_2.jpg&apos; srcset=&apos;/static/db0545e7eb07cf92120990a28b27b5c9/8ccab/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_2.jpg 190w,
/static/db0545e7eb07cf92120990a28b27b5c9/6e1d3/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_2.jpg 240w&apos; sizes=&apos;(max-width: 240px) 100vw, 240px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;학교 추첨하는 뺑뺑이 기계, 실제로 뺑뺑이를 돌렸다는 사실이 조금 충격적이었다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;하기야 후세 아이들은 어떻게 의사 난수 생성 함수로 뺑뺑이를 돌렸지 하면서 웃을지도 모를일이다 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; margin-bottom: 16px;&apos; data-url=&apos;./토속촌_기행.md_3.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1699f310f9d8403db8aebf731e42ba34/95cb2/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_3.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABjZjo5haV/8QAGhABAAIDAQAAAAAAAAAAAAAAAQACAwQRIf/aAAgBAQABBQIwkdclqcsWeqk8Z//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAAMBAQAAAAAAAAAAAAAAAAABMSAh/9oACAEBAAY/AqyvHT//xAAbEAADAAIDAAAAAAAAAAAAAAAAAREhQVFxkf/aAAgBAQABPyGwJ7QexIf08L2VOh25n//aAAwDAQACAAMAAAAQvM//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAwEAAwAAAAAAAAAAAAABABEhMUFR8P/aAAgBAQABPxCuxXtMwrq8s5oHtgAE21D1hDXy4b2zmE//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 3&apos; title=&apos;&apos; src=&apos;/static/1699f310f9d8403db8aebf731e42ba34/95cb2/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_3.jpg&apos; srcset=&apos;/static/1699f310f9d8403db8aebf731e42ba34/8ccab/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_3.jpg 190w,
/static/1699f310f9d8403db8aebf731e42ba34/ea4c8/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_3.jpg 380w,
/static/1699f310f9d8403db8aebf731e42ba34/95cb2/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_3.jpg 520w&apos; sizes=&apos;(max-width: 520px) 100vw, 520px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./토속촌_기행.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6ae697bae50cc6ac50682467b5099410/dface/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 71.57894736842105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAD3klEQVR42iWT2U/UdxTFf+mDfaiJTdqnvvShSWOhaWwjFS2yBKWIVVutS8EBGYZt2JRV2QQEAUeQbRbmB8OswMAwwsAg0IEBBQoFgoCA2ipptEnT+D98+oU+fHMfvrnnnnPPudLtvFRUsT+RnZpKUY6agiwV11OuknjlAj9ERXEiNIyTx0OJOPYdwYe/JSw4mLCjwURHhBP42ad8dOAAAQcD2f/Bft6TJKSivALaWzS0tnbS0NCG2WLGbrVgMso03tNQWV5FWXEFRTcKyExJJ1WZglqVRnpSMheijvPJxx9yKvIkh776GmkX8HZ5GQ2au9Tf12OyOfF4XXgnPPT29dDwQEtF+R0K80tQp18n/qqK2CsJxF5S8OPZS8REhBAU+DlxvySgVKp5f98+JI2mGr1ei6nbg29+idWtBZ79scja5gy+mXFM9l40jQaKiirJyswnQaFCpUwn7so1zkRHcyL4EIkKJZnpN/ji4JdIZouOji4bdrefkalFfl9bYfvPFda2F3j5ao7HsxOM+cbpNNuoqKgjO7NAAKoF2yQunLtI6DcBnD99mgwBePHnq0gWm0zvwAgO9xTt1hH8iyv8+26Vd39P82bDxes5mZ11N5P+URrbzFRWN6FW56OIU3HuzGVOhYcQFXIEVWIaWRn5gqHNQlf3MCaLi0HvJHPLq+zsLPHPX9O83Rrm7bMBttZ9eP1PsPUN0aS3U17ZSHb2LbG3TJSKeMIPB6CIjSdZmYZkdTh4oHXQZBigd3ge3+JzlrZ3ePriOS/fvGbj1QuWt7ZYe7HBtBg2+dsSnfZBauq13CyuofRWCZejg4XsGDLVeUgGo4myKgN1zU6a5SE6nVMM+jfoH1/GO7vBo/lNxubWmV/fZmppk4fjgqlrjDa5j9p7OvJyy/ZyHBMaJPaYi6TV6alv6qVF9mDu92Ny+hmeXkfu8eEYnGFgfBHrwAyusQXabaPozB7aLYO0GR00t8qUlNwhLyOZqCMBwnlhSrvchaV/Srj8eK/xoe8p7l9XBUtRfau4J5bpHZnbA+72zGITaegZ9NFld/OgyUBtTR1lNwu59P1RzkZFIhk7Hcj2MTrs4xjMo1j6/FgFuHtiBbOQ3+XcZfqEnqHZvSQ0G5zoO4VcTTvl5bXU3qkWl1RKctx5Ig4HIumNVvRdHgE2LBwcENVLh8NH99C8iJGXto4hjEKqqfsRLYYetEbxdFY097Xcrb5H6c1i8nNyUCclEBl0UJgi99Aqu9B2uMR0F7JtQjCbxibk7w5pMfbTanT+/69z0Krrpqm5g4b7LVRV1FBceIvcrByy0lLFbR/jP/V54wyUIdUIAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 4&apos; title=&apos;&apos; src=&apos;/static/6ae697bae50cc6ac50682467b5099410/dface/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_4.png&apos; srcset=&apos;/static/6ae697bae50cc6ac50682467b5099410/08678/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_4.png 190w,
/static/6ae697bae50cc6ac50682467b5099410/2edd7/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_4.png 380w,
/static/6ae697bae50cc6ac50682467b5099410/dface/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_4.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;한 파독 광부의 일기, 1964.11.10 맑음, 하나님은 나를 이러한 곳까지 인도하여 주시었다…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;100년 뒤엔 한 프로그래머의 애환이 담긴 일기가 전시될지도, 미리미리 일기 써두자 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;전시된 한 파독 광부의 일기는 정말이지 굉장히 인상적이었다. 날짜며 내용을 한참을 들여다 봤다. 특히나 일기 중앙에 있는 ‘생’과 ‘사’란 글자는 이 일기의 백미였다. ‘생’이란 글자는 빗금 채우기를 했고, ‘사’라는 글자는 빨간색으로 적으면서 이 일기의 작성자의 예술적 감각을 한눈에 알 수 있게 했다. 아마 전시하는 측에서도 그런 글자의 임팩트를 생각해서 이 페이지를 펼쳐둔 게 아닐까라는 막연한 추측을 해봤다. 물론 다른 한편으론 그가 그곳에서 느꼈을 고통, 외로움, 생경함 등으로 얼마나 힘들었을지를 단적으로 보여주는 것 같아 조금은 씁쓸했다. 이런 분들이 있었기에 우리가 이제는 이만큼 살 수 있게 된 게 아닐까? 넘겨가며 뒷페이지를 조금 더 들여다보고 싶었으나 전시물이라 이 페이지만 볼 수 있다는 사실이 조금 안타까웠다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;광화문 교보문고를 가는 길에 세종대왕 동상이 있는 곳에서 무료 가훈 써주기 행사를 하고 있었다. 줄이 길지 않아 우리도 쓰자고 했다. 후배 녀석이 논어에 나오는 한 구절을 고르기에 나도 똑같은 내용으로 골랐다. 한땀한땀 정성스레 화선지에 쓴 글자를 받아드는데 필체가 제법 마음에 들었다. 개발팀 한 귀퉁이에 걸어 놓고는 압박해야 겠다는 생각과 함께… ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; margin-bottom: 16px;&apos; data-url=&apos;./토속촌_기행.md_5.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/bccbd145d6cbde081e00f68dfa111d34/8c3ad/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 59.47368421052632%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7DAAAOwwHHb6hkAAADC0lEQVR42iWT228TZxDF9z9qKqVSCVIFEkU8VOkTL6FpSwGRligBVYACxAGaQu4327G9Xl921058I3ES3x07tmPHN+JcoPTP+XW8fRitvm92zpwzZz7l28FBBr4aYHDga64PXeWHmze4e2eEe6OjTIyN8ffbt6zNvcP0qaT2kiTMIPsfYiRjEUzVhd+rMvvqBVOT44zfv4cydGWIG999z/CPtxkZ/Y2798f4/dEE06//YnZukVW7Ey2oE4kn2E+lyeYLZHN5DtIZErt7+HWTpTU7T55O8fjP5yjPp6ZZnp1HUz3o4RA7wiKVSVEsFajWjqgdV2i26jQaNTrdJq12g+7HphWNk5qVq1RKLCwusrRqR3n67AUuX5CgaRIwTHYFMJ1NC5sDykcl6o2qBXrSanD5qcfH0za9sy4XF6d0On3QYwE9plwusubYRHn85BlOj4ZbVXF7NbKFHKXyIYflEifNOmdS2I/qcZXLz+dcfDrj/KLHP18uhWXLYt2V6Kvp1ysPH46zvqnyaGKSn37+hemZGd69n2PmzRsM08DhdGCEDN7Pz+MP+AmFTevs82lofg3b6xk+7MSJRiMEQ1soI3d+Zd3pYW3DzivbDBsOJ75ggJc2myU/Go8QEUddHrcABnBsOsnkMpgCapg6S8tL6HoAl3iwFY2jDA/fZmV9U7qGxMm4uJfmqHokbubFmEOZWYd2t02t0eDLv59F7hnNdouz81O6vQ49GUer2xIj05hbEZRbt4aZX94QVkFxOcx2LEa+WCCVzYgxKXKFAvWTujBN4HS58Pal+nx45Bt0OtmTzSgkd8kdFv8HvH7tJrMLq3gNg4A4HY5EyEvyIJMRt7PkBLxcrbB3cMB2NGqNIZZIWOfkzg5ZaVopFS0S4UgU5crVa9hkdbTVFby6IYMOWD9HpCghBf31SWWy7MsoCtKoKO73G/UBshJ76ZTcFyx1fiOEMvjNEJMP/mDhpQ27qrEiW+9W+5LEAJdqvQQ9vI3q1/EGdHkdSQyRpukhzO2Y5MPooTB2tyovyuQ/wsazwACYJpgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 5&apos; title=&apos;&apos; src=&apos;/static/bccbd145d6cbde081e00f68dfa111d34/8c3ad/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_5.png&apos; srcset=&apos;/static/bccbd145d6cbde081e00f68dfa111d34/08678/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_5.png 190w,
/static/bccbd145d6cbde081e00f68dfa111d34/2edd7/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_5.png 380w,
/static/bccbd145d6cbde081e00f68dfa111d34/8c3ad/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_5.png 550w&apos; sizes=&apos;(max-width: 550px) 100vw, 550px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;사실 이 날 후배를 만난 이유는 “코딩호러의 이펙티브 프로그래밍”이란 책을 선물하려는 생각에서였다. 그냥 보내줘도 되지만 만난지도 오래돼서 얼굴이나 볼 겸 만났다. 올해 읽은 책 중에 “코딩호러의 이펙티브 프로그래밍”은 “페르시아 왕자 개발일지”만큼 흥미진진한 책이었다. 지지난주 였나? 주말 저녁에 &lt;a href=&quot;http://www.benjaminlog.com/entry/effective-programming&quot;&gt;김재호님께서 올리신 서평&lt;/a&gt;을 보고는 12시간을 못참고 강남까지 한달음에 달려가 책을 샀다. 나도 3번 넘게 읽는 책은 “조엘 온 소프트웨어”, “모어 조엘 온 소프트웨어”, “해커와 화가” 였기 때문이라 더 기대가 됐다. 교보문고는 너무 더워서 그 옆 조용한 커피숍에서 그 내용을 들이켰는데 정말이지 감동적이었다. 더러는 평소 생각하는 바와 일치하는 부분이 있어서 반갑기도 했다.&lt;/p&gt;
&lt;p&gt;책 내용이 너무 좋아서 개발팀 애들에게 한권씩 돌려야 겠다는 생각을 했다. 그래서 다음날 책을 들고 가서는 한 녀석에게 정말 감동적인 책이었다고 보여줬는데, 그 녀석이 그랬다. 이런 책이 진짜 도움이 돼요? 흠,… 핡~ 아무리 좋은 보석이 있어도 그걸 볼 준비가 돼 있어야 보이는구나 싶었다. 어쩌면 아직 이 친구들에게는 WOW64에서 시스템 리다이렉션이 어떤 부분에서 발생하는지, PEB가 왜 듀얼 구성이 되는지와 같은 테크니컬한 내용을 하나씩 차례차례 설명해 주는 책들이 더 갚어치가 있을수도 있겠다는 생각이 들었다. 그래서 주변에 읽을만한 사람들에게 선물해야 겠다고 맘을 바꿨다.&lt;/p&gt;
&lt;p&gt;후배 녀석도 책을 한 권 사줬는데, 하루키의 신작 “색채가 없는 다자키 스쿠루와 그가 순례를 떠난 해”였다. 전반부 조금 읽었는데 하루키 소설의 전형적인 도입부를 보는 듯한 느낌이었지만 재미는 있다는 생각이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; margin-bottom: 16px;&apos; data-url=&apos;토속촌_기행.md_6.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/769cd6d2ada0565bf1116ea6d455a3f4/9aebd/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 177.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAAACXBIWXMAARlAAAEZQAGA43XUAAAHgElEQVR42oWQeVRT2RnA3/89PTNF6zgeQSBsypCEzYUlLAkveSGLsiciRBYhLAETAREXhkEHa6mOoI4DKFswkEAAsTPT1krVGRUZlmNLCKuDHgEhhCUhC8m7vYGejqenPf3O733nd7/7fe/ddxEXgqu7p8t2h18fOnjQzcvLi0jg0n5lZ/fxRx/bws7OztXN3c3NzX73nn1EJ+Kh3zo7uTg67nFycrK3t0cUinZFu7ylrVkOo12hVMq/7aqXbkZzs7SpWdrV0S5vlUlbWnu+U3Y/bGiRylpbZW1tbTKZDAH/L9YBMP1HZX19ZmbGbDYjln/FxtZj3oBsQKC/WzP9+fVq9ZCmalDTN6sf1RgG53WrZuvbNzO9vb1arfaXL3dN6RpUq7KxNZjrVaudU7qOSV3TqK1yf1rXM21bto2vfT+jBwA3Gm2n+WV4YME4vGAcXDA9eWd4tWhSLZla1GvPZw3KKV3dyAp8y4s5w8M363+a0VtxfGvkv/zz1o7Jglf8tFTwdPHCC035y6Xyl5prQ9q/vV1XTKzZejbnEQsOttiwboIDsxVYcWC04MLe95yed1eHtLdeLVcOasv6llIezj96C2/Q1gNH/udtW3D89Yr5/bpli4V1y7x+Y8Vk/bAH6Zxc6ZpcgVkJ84RN/s0fp1cfTK9+mLunVpQTtjaFalGuWkDQB3Oh3e9oPXPYg7mIntmInjl0i80lrWeWen+Wdt8mMNt2H8wHy6f9mlQHpWqEqXyd1KFmKcaFj2bzH89xet5gXTPM7hmYIZHdM8zO1/T2CVQ+RpONovJxevskKlPFKMfC740gofXDOW1D7MYhftd4as8Er3OM3znO6xwX3J841j0e26FmyFQQWvMrSl0/tXE4rHGY1jDAV7yi3OlH9t8bJTf+w0+qCmwdC2xVB7eNBbepQxVj4YpxilwNK/4to7DHt3mEeHd4/z3bklg/7FHzk2fdAFJ65sbnZ2+Vltw8X3zjQ84VV8N8obgaNpRuyrnC61BKT1efL6oqKbxecuorBGAoCKMAlGoTegRgoDagM+kA24S5CYbijAgLNRREhANaGAilQEfMLPZCUfFacjJISsazc/C0NFwoxGNirBiGs1g4m21hMk0YZsCYega2itJXIlADh2MUCOASMbAiZxsatHkiwEsAaSkgRQCyMsFRPhAkW/k8S3ycns/TxUYb6BEGJraOMQwY3cTlmASCNTQCwakcE4VpDWeDyDiAxdjg8nFmrJmdoKdHrdO4Oka0gRFtomDagHADBTWHRS4HRCz4UgwhGLIioegLqPqCML0kRCcJWZNQtHmBSxBRgEYUsJwftJgToBUFzucFjgiDx7JCFnKD5nMPvcsNWBQFIvgkCUzuxSe9oOATRKsNknUcug0oG6NEmJf7PJ7cdnl0w232sSuYIlnUnhujJMQy/NnsX0LWnvnoX3gaB0hg1BuoyJtsyggZf0XeGCYbnn/2cxPhdT1h5YknGPEzDoWbB0mI7pnbdL/i/TOe/oXz2guyaYhkHiIZB0lQTMMky9/JxgGyaZAMi8tPvSDr/UTTkL9ukGUcJCJgkgh+jgZTQUC9D4x64SOeYIwIBai9wJgXmIBnIQI1EUwQwTgRqDa3VJ5gdC+sIM/lB/oUPs/lfi87AvraD/Z3Bj6W+fwg9/+x1f8Hme/TFr/eJp/eRp9nrQeeSP3/Wu/9ROo30BXc1x74Y+sBhHs4KjEpJSMzOz09Mzs790hUrCQrt/5yZdnZc6L8fCaTk5qalpOTg2GsuLgEoVBYVl5WWFSYeCw5OjoeYUUyEuJjCgrEv79SUXmlQnzqZM3lS2++/+725YunCk9eOF+ccSK14svPGxu/qa2thnK6SHIskc/lsA5z2QjGYPJ5R4tPn7lypfLqH65drvhdeWnZtUsVkvxTAkFK6vHUkpLikpIzpRfOFxUUXK64lJmRmSXMys4SRjJZSCQHPZ5+rKhEIi4UQcq/vAA9LStFJM6moiEYC71y9YvkVH4YlcJLjC0szo9NOJKTl5FwNCZREI8cP1yQl/RFFu98alRRXlLZidgzOYml4uMXj7FOJtCzuZTU1KhCIe8sjyESJpwVp1yMDs+MR7N59Fw+lod8w9Z9jelvYqvXUc1V6vxX1PdXw+crQ2evUReq6dpr4QtV6NL1CM1NxsqtyOVqugZSRV+sQjW32atII9daG6ep5egVaUCZCTogGaA9HSiFoE2AKzNAjwh8KwbtSeBeFGiNBU1c/A4Lb44DdUwcyQttPi2qzubektBkebSm7NA7WaF1ovD6PFpDRnCNMKRGzJBKsBZh8N30/XdyQ1pygqQZATVibm3mobuIvftuySF2nF/Qp4Sdn9rvoDJC/QN8d+zatn2XHZNLPxLL+WT39m07f8OOwuISoz6x3wahUAOYHPquPTsQgrNrNyouD+TvdHR0sHfkcg+zWBx7+z0QgeC4SJTv5OTi4OB0Ij3jZL54y6OjY9PS0p2dXRACwdXPnUhy83QiEBydnL19fEhkb4c9jh5793n7+JK9fTw89sK6q6u7m7sHFGeCCxF2+Pi6uXv8Exjx+50eLF/fAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 6&apos; title=&apos;&apos; src=&apos;/static/769cd6d2ada0565bf1116ea6d455a3f4/9aebd/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_6.png&apos; srcset=&apos;/static/769cd6d2ada0565bf1116ea6d455a3f4/08678/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_6.png 190w,
/static/769cd6d2ada0565bf1116ea6d455a3f4/2edd7/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_6.png 380w,
/static/769cd6d2ada0565bf1116ea6d455a3f4/9aebd/%ED%86%A0%EC%86%8D%EC%B4%8C_%EA%B8%B0%ED%96%89.md_6.png 480w&apos; sizes=&apos;(max-width: 480px) 100vw, 480px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;후배 녀석이 개발한 프로그램, 에브리싱.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;커피 마시면서 녀석이 요즘 개발하는 프로그램 이야기를 들었다. 에브리싱이라는 노래방 프로그램을 개발하고 있는데 사운드 처리하는 부분에서 조금 애를 먹었다고 했다. 도중에 오픈 소스 프로그램을 안드로이드 환경으로 포팅하는 과정에 실패해서 다른 방법을 선택했다는 이야기도 했다. 그 오픈소스가 조금 복잡한 라이센스였는데, 난 오픈소스를 가져다 쓸때는 라이센스 문제를 항상 꼼꼼하게 체크해야 한다는 이야기를 해줬다. 그 외에도 후배 녀석이 XIGNCODE에 적용하면 좋을만한 여러가지 요즘 트렌드한 내용들을 이야기 해줬다. 난 정말 상상도 못했던 엄청난 이야기들이라 정말 기뻤다.&lt;/p&gt;
&lt;p&gt;대학시절 프로그래밍 과제를 한다고 주위 사람들의 소스 코드를 크게 참고한 적은 없었다. 물론 인터넷 소스는 무지하게 참고했다. 간혹 소스 코드를 봐 달라는 이야기를 하는 친구들도 있었는데 그렇게 흥미로운 소스는 없었다. 그러다 한 날 레드 블랙 트리 과제를 하고 있는데, 녀석이 와서는 자기는 벌써 다했다는 이야기를 했다. 그래서 잠깐 녀석의 소스 코드를 봤는데 깜짝 놀랐다. 정말 잘 짰기 때문이었다. 처세에는 조금 둔한 친구긴 한데, 그래도 그 프로그래밍 실력만큼 잘 됐으면 좋겠다는 생각이 든다.&lt;/p&gt;
&lt;p&gt;대한민국 역사 박물관에서 SM엔터테인먼트에 있는 연예인들이 나오는 스크린이 있었다. 보아가 나오는데 녀석이 그랬다. 우와 보아 이사님이네요. 보아 이사님이라… 우리가 생각하는 NO.1 부르던 꼬꼬마 권보아도 회사라는 조직 속에서 만나면 보아 이사님이 될수도 있다는 생각이 들었다. 그래도 보아 이사님이라뉘. 나름 신선한 충격 ㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[안윤호님 칼럼 소개를 빙자한 자랑질 ㅋㅋ~]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/12040</link><guid isPermaLink="false">https://jiniya.net/wp/archives/12040</guid><pubDate>Tue, 06 Aug 2013 23:59:13 GMT</pubDate><content:encoded>&lt;p&gt;대학시절 &lt;a href=&quot;http://www.jiniya.net/wp/archives/1208&quot;&gt;나성언님의 칼럼&lt;/a&gt;과 안윤호님의 마소 칼럼을 즐겨 읽었습니다. 나성언 님의 칼럼은 에세이 스타일에 일상에서 느낀 점들을 기술과 연관시켜 풀어내는 글들이 많았던 반면 아마추어 커널 해커라고 소개된 안윤호님의 칼럼은 상당히 테크니컬한 내용들을 많이 담고 있었습니다. 때로는 시대를 앞서 나가기도 하고, 때로는 과거를 꿰뚫는 철학적 통찰을 담기도 하는 등 정말 흥미진진한 내용들이 많았습니다. 막연하게 나도 나중에 글을 쓴다면 그런 글을 쓰고 싶다는 생각을 많이 했었습니다. (&amp;#x3C;- 마음만 먹는다고 되는 건 아니지요 ㅋ~)&lt;/p&gt;
&lt;p&gt;그랬던 꼬꼬마 프로그래머인 저도 마소에 소소한 글을 쓰면서 언젠가 한번은 &lt;a href=&quot;http://www.imaso.co.kr/?doc=bbs/gnuboard.php&amp;#x26;bo_table=article&amp;#x26;page=569&amp;#x26;wr_id=32050&quot;&gt;안윤호님&lt;/a&gt;에 대해서 물었던 기억이 있습니다. 그.런.데. 놀라운 일이 몇일전 제가 &lt;a href=&quot;http://www.jiniya.net/wp/archives/11877&quot;&gt;“국내 프로그래머 블로그”&lt;/a&gt;란 글을 올리고 벌어지게 되었습니다 ㅋㅋㅋ~ 바로 존경해 마지않는 안윤호님과 페친이 된 것입니다. 사실 전 뭐 페북을 별로 안 해서 페친된 걸 자랑질 하는 건 아니구요. 어린 시절 저의 우상이었던 분께 제가 발견되었다는 기쁨을 좀 자랑질하고 싶었습니다 ㅋㅋㅋ~&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 523px; margin-bottom: 16px;&apos; data-url=&apos;./안윤호님_칼럼_소개를_빙자한_자랑질_ㅋㅋ~.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c90c18b0fc3a7f52c7f8c45a1d5581af/c53f8/%EC%95%88%EC%9C%A4%ED%98%B8%EB%8B%98_%EC%B9%BC%EB%9F%BC_%EC%86%8C%EA%B0%9C%EB%A5%BC_%EB%B9%99%EC%9E%90%ED%95%9C_%EC%9E%90%EB%9E%91%EC%A7%88_%E3%85%8B%E3%85%8B~.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 88.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACk0lEQVR42o1UO2tUQRS+f8BC0FpQIQhWQoISwSqFYBe0thB/hqWNnaCg+QFiEoyFYNQtUgjaGpKYZDe7bu7e57xfd+5z45m7mkRIgoePwxmY7zznjBcmaLM7oExwaYQ0ShswtHaGNlmeF0VRnghjrPdmcfnho8e7vUEQM0S4ziyTGdCAbDLbNM3BKVKUldftdjudDmPc2hykVfnBf0gJZKW0H8SjMIbge4PhYOj7o5ALKYSilNd1fRYZMpRSWWuzzEKixiUMJRuoNbN2fHrajkyl6oexn6AQ05Cywf7I1R/GnEuID42Be+MxYDzR/0ZOsPixwzZ24o1NvL6tuSzKcpKCkKrIi8PbEybopnEG+PXowlJ8YXZz6s7PS7PJ9Xvpem+faER036cR0kLZXwFLsB6M6H7IhyHT5o87qMujr96G56Y3Lt/uXZwJrszJ7b6uakipKKqyBKMsQFd1XlQTVHUNkUFa8sJieP6mf3Vu99pcMD3Pt3pUG0JYiikgSTEmDIAIBWDKQaeYQEfBr0deLw6n7vo35kcz94e3HuidvipKxgTjAhpmMvdapNIAaAHlnDJOKIe+OLLe2pPLn8T7L3xplb/7XApVH4xhvI1rTFMfw5GM3dHmhYdkhm1F84pkJc+rhGrnta6gurLFoXEcVV3BK/CE0JJrRhjFPE1cnbAk4LVq+c7RGWQooz/0YdgxAg8iQThOkVAKHnlbF3T7BEDPHXltrfPs6ZOEGj9MEcZRjIIoiRIUIw5Dtrm756Rpqr/6KPLXb9+XVlYQFQHkTFiUpMCHkYQJDmIUQUpKQXsJhcUTMCfGZVtUG/nDx9XnL16mhI8i5AaLSd9PhVtm2Gr4EmBxrJr8DVkmtVbGwAcxIf8GYgDiEXIXgtIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                        md 0&apos; title=&apos;&apos; src=&apos;/static/c90c18b0fc3a7f52c7f8c45a1d5581af/c53f8/%EC%95%88%EC%9C%A4%ED%98%B8%EB%8B%98_%EC%B9%BC%EB%9F%BC_%EC%86%8C%EA%B0%9C%EB%A5%BC_%EB%B9%99%EC%9E%90%ED%95%9C_%EC%9E%90%EB%9E%91%EC%A7%88_%E3%85%8B%E3%85%8B~.md_0.png&apos; srcset=&apos;/static/c90c18b0fc3a7f52c7f8c45a1d5581af/08678/%EC%95%88%EC%9C%A4%ED%98%B8%EB%8B%98_%EC%B9%BC%EB%9F%BC_%EC%86%8C%EA%B0%9C%EB%A5%BC_%EB%B9%99%EC%9E%90%ED%95%9C_%EC%9E%90%EB%9E%91%EC%A7%88_%E3%85%8B%E3%85%8B~.md_0.png 190w,
/static/c90c18b0fc3a7f52c7f8c45a1d5581af/2edd7/%EC%95%88%EC%9C%A4%ED%98%B8%EB%8B%98_%EC%B9%BC%EB%9F%BC_%EC%86%8C%EA%B0%9C%EB%A5%BC_%EB%B9%99%EC%9E%90%ED%95%9C_%EC%9E%90%EB%9E%91%EC%A7%88_%E3%85%8B%E3%85%8B~.md_0.png 380w,
/static/c90c18b0fc3a7f52c7f8c45a1d5581af/c53f8/%EC%95%88%EC%9C%A4%ED%98%B8%EB%8B%98_%EC%B9%BC%EB%9F%BC_%EC%86%8C%EA%B0%9C%EB%A5%BC_%EB%B9%99%EC%9E%90%ED%95%9C_%EC%9E%90%EB%9E%91%EC%A7%88_%E3%85%8B%E3%85%8B~.md_0.png 523w&apos; sizes=&apos;(max-width: 523px) 100vw, 523px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;선생님 제가 영광입니다. 눈물 좀 닦고 ㅠㅜ 저도 자랑질 좀 ㅋㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;예전 &lt;a href=&quot;http://www.jiniya.net/wp/archives/831&quot;&gt;“고음내기”&lt;/a&gt;라는 글에서 소개했었지만 안윤호님의 칼럼 중에서도 &lt;a href=&quot;http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039129985&amp;#x26;type=det&quot;&gt;“기술 유전자”&lt;/a&gt;라는 표현과 함께 데이비드 커틀러를 소개한 내용은 그때나 지금이나 저에게는 굉장히 인상적이었습니다. 개인적으로 소프트웨어 개발에서 가장 중요한 부분은 &lt;a href=&quot;http://sangminpark.wordpress.com/2011/09/13/%EC%98%81%EC%9B%85-%EC%97%86%EB%8A%94-%EB%82%98%EB%9D%BC/&quot;&gt;“개념의 일관성(conceptual integrity)”&lt;/a&gt;이라고 생각하는데요. 큰 소프트웨어에서 그런 것들을 홀로 설계할 수 있는 사람들은 그리 많지 않다는 게 제 생각입니다. 그래서 “기술 유전자”라는 게 존재할 수 밖에 없지 않을까라는 생각을 하기도 하구요.&lt;/p&gt;
&lt;p&gt;어쨌든 안윤호님의 칼럼은 지금 읽어보아도 큰 도움이 될 것 같습니다. 아마 이쯤되면 대부분 아 그거 어떻게 구해서 읽지?!, 라며 궁금해 하실 것 같은데요. 제가 한땀한땀 폼 서치 변수를 입력해서 모아 보았습니다. 한번에 모.두. 즐기세요 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://search2.zdnet.co.kr/search.asp?pageNum=1&amp;#x26;frmdate_year=2001&amp;#x26;frmdate_month=1&amp;#x26;frmdate_day=1&amp;#x26;todate_year=2013&amp;#x26;todate_month=08&amp;#x26;todate_day=13&amp;#x26;code_idx=all&amp;#x26;kwd=%EC%95%88%EC%9C%A4%ED%98%B8&quot;&gt;안윤호님 칼럼 보기&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[국내 IT 블로그]]></title><description><![CDATA[양질의 IT 정보가 올라오는 블로그도 한 번 모아 보았습니다. 즐찾, RSS 추가는 필수랍니다. http://kwang82.hankyung.com/ http://archvista.net/ http://goodhyun.com/ http://mrpyo…]]></description><link>https://jiniya.net/wp/archives/11897</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11897</guid><pubDate>Fri, 02 Aug 2013 23:59:12 GMT</pubDate><content:encoded>&lt;p&gt;양질의 IT 정보가 올라오는 블로그도 한 번 모아 보았습니다.&lt;/p&gt;
&lt;p&gt;즐찾, RSS 추가는 필수랍니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://kwang82.hankyung.com/&quot;&gt;http://kwang82.hankyung.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://archvista.net/&quot;&gt;http://archvista.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://goodhyun.com/&quot;&gt;http://goodhyun.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://mrpyo.com/&quot;&gt;http://mrpyo.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sungmooncho.com/&quot;&gt;http://sungmooncho.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.dongpyo.com/blog/&quot;&gt;http://www.dongpyo.com/blog/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://vcnc.tistory.com/&quot;&gt;http://vcnc.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sanbaek.com/&quot;&gt;http://sanbaek.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wangsy.com/blog/&quot;&gt;http://wangsy.com/blog/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://interpiler.com/&quot;&gt;http://interpiler.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://estima.wordpress.com/&quot;&gt;http://estima.wordpress.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jimmyrim.com/&quot;&gt;http://www.jimmyrim.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mickeykim.com/&quot;&gt;http://www.mickeykim.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://subokim.wordpress.com/&quot;&gt;http://subokim.wordpress.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.iamday.net/&quot;&gt;http://www.iamday.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://xenix.kr/&quot;&gt;http://xenix.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://trendinsight.biz/&quot;&gt;http://trendinsight.biz/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://lovesera.tistory.com/&quot;&gt;http://lovesera.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; 1
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[국내 프로그래머 블로그]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11877</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11877</guid><pubDate>Thu, 01 Aug 2013 23:59:11 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://jiniya.net/tt/440&quot;&gt;예전에도 한 번 프로그래머 블로그 목록을 올린 적이 있었는데요.&lt;/a&gt; 살펴보니 그사이 정말 많은 블로그들이 역사의 뒤안길로 사라진 것 같습니다. 안타까운 현실입니다 ㅠㅜ~ 구글 리더 서비스 종료에 발맞춰서 아직까지 비콘 시그널이 전송되는 블로그를 한 번 정리해 봤습니다. 항상 저에게 큰 통찰을 주시는 고마운 분들이기도 합니다. 실제로 프로그래머가 아닌 분도 몇 분 계신데 제 생각에 프로그래머 만큼이나 이 바닥 사람들에게 큰 통찰을 제공하신다는 생각이 들어서 포함시켜 보았습니다. 즐찾, RSS 추가는 필수랍니다 ㅋ~&lt;/p&gt;
&lt;p&gt;**자, 이제 그러면 여러분의 꿀통을 공개해 볼까요?&lt;/p&gt;
&lt;p&gt;나만 알고 있기엔 너무나 안타까운 초강추 블로그가 있다면 제보해 주세요 !!!**&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://whiteship.me/&quot;&gt;http://whiteship.me/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://moogi.new21.org/tc/&quot;&gt;http://moogi.new21.org/tc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://zetlos.tistory.com/&quot;&gt;http://zetlos.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://hongyver.pe.kr/&quot;&gt;http://hongyver.pe.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.naver.com/gloryo/&quot;&gt;http://blog.naver.com/gloryo/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://greemate.tistory.com/&quot;&gt;http://greemate.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.pyrasis.com/main/&quot;&gt;http://www.pyrasis.com/main/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.naver.com/delmadang&quot;&gt;http://blog.naver.com/delmadang&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://toyfab.tistory.com/&quot;&gt;http://toyfab.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://kippler.tistory.com/&quot;&gt;http://kippler.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.rkttu.com/&quot;&gt;http://www.rkttu.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://lunapiece.net/&quot;&gt;http://lunapiece.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.sysnet.pe.kr/&quot;&gt;http://www.sysnet.pe.kr/&lt;/a&gt; &lt;a href=&quot;http://blog.naver.com/techshare&quot;&gt;http://blog.naver.com/techshare&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://agile.egloos.com/&quot;&gt;http://agile.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.daum.net/gdocument&quot;&gt;http://blog.daum.net/gdocument&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://gleamynode.net/articles/&quot;&gt;http://gleamynode.net/articles/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.naver.com/drvoss&quot;&gt;http://blog.naver.com/drvoss&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.talk-with-hani.com/&quot;&gt;http://www.talk-with-hani.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://minjang.egloos.com/&quot;&gt;http://minjang.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://jamestic.egloos.com/&quot;&gt;http://jamestic.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.benjaminlog.com/&quot;&gt;http://www.benjaminlog.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://jacking.tistory.com/&quot;&gt;http://jacking.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sangminpark.wordpress.com/&quot;&gt;http://sangminpark.wordpress.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://youngrok.com/Home&quot;&gt;http://youngrok.com/Home&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://rein.kr/blog/&quot;&gt;http://rein.kr/blog/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.dahlia.kr/&quot;&gt;http://blog.dahlia.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://micingamja.egloos.com/&quot;&gt;http://micingamja.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://zextor.tistory.com/&quot;&gt;http://zextor.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://j.mearie.org/&quot;&gt;http://j.mearie.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://parkpd.egloos.com/&quot;&gt;http://parkpd.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://arload.wordpress.com/&quot;&gt;http://arload.wordpress.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://freesearch.pe.kr/&quot;&gt;http://freesearch.pe.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.gsong.pe.kr/wp/&quot;&gt;http://www.gsong.pe.kr/wp/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://kkamagui.tistory.com/&quot;&gt;http://kkamagui.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://naggingmachine.tistory.com/&quot;&gt;http://naggingmachine.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://npcode.com/blog/&quot;&gt;http://npcode.com/blog/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://xrath.com/&quot;&gt;http://xrath.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://bugsfixed.blogspot.kr/&quot;&gt;http://bugsfixed.blogspot.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://madchick.egloos.com/&quot;&gt;http://madchick.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://eslife.tistory.com/&quot;&gt;http://eslife.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://khmirage.tistory.com/&quot;&gt;http://khmirage.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.devgrapher.com/&quot;&gt;http://blog.devgrapher.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://pragmaticstory.com/&quot;&gt;http://pragmaticstory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://anyflow.net/&quot;&gt;http://anyflow.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.doortts.com/&quot;&gt;http://blog.doortts.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://kingori.egloos.com/&quot;&gt;http://kingori.egloos.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://jhrogue.blogspot.kr/&quot;&gt;http://jhrogue.blogspot.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://jz.pe.kr/&quot;&gt;http://jz.pe.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dishdev.me/&quot;&gt;http://dishdev.me/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sirini.net/&quot;&gt;http://sirini.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://npteam.net/&quot;&gt;http://npteam.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://rhea.pe.kr/&quot;&gt;http://rhea.pe.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.naver.com/agebreak&quot;&gt;http://blog.naver.com/agebreak&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://charsyam.wordpress.com/&quot;&gt;http://charsyam.wordpress.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://kblog.popekim.com/&quot;&gt;http://kblog.popekim.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://zpacket.blogspot.kr/&quot;&gt;http://zpacket.blogspot.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.gamedevforever.com/&quot;&gt;http://www.gamedevforever.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://bomjun.tistory.com/&quot;&gt;http://bomjun.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://forensic-proof.com/&quot;&gt;http://forensic-proof.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://iam-hs.com/&quot;&gt;http://iam-hs.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://window31.com/&quot;&gt;http://window31.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; 3832
 2367&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[좌.절.금.지]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11906</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11906</guid><pubDate>Tue, 30 Jul 2013 23:59:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;당시 아인슈타인이 친구에게 보낸 편지를 보면 그가 얼마나 깊은 절망에 빠져 있었는지를 쉽게 짐작할 수 있다. “우리 부모님은 나 때문에 행복한 적이 거의 없었어. 특히 내 학비를 대기 위해 정말 어려운 생활을 해오셨지. … 지금의 나는 무위도식하면서 부모님과 친척들에게 짐만 될 뿐이야. … 이렇게 사느니 차라리 죽어버리는 게 낫다는 생각이 들어……”&lt;/p&gt;
&lt;p&gt;– 평행 우주, 미치오 카쿠&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;전 인류를 통틀어 가장 똑똑하다고 일컬어지는 아인슈타인도 취직을 못해서 힘들었던 적이 있었다. 이런 불세출의 천재도 그런데, 하물며 보통의 사람은 어떻겠는가… 그러니 절망하거나 좌절하지 말자. 아인슈타인도 취직을 못해서 고생한 적이 있었다. 다시 적어 놓고 봐도 욱기긴 하다. 아인슈타인이 취직을 못했다니 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;당신이 겪고 있는 그 엄청나게 지랄맞고 당신을 미츄어 버리게 만드는 그 짜증나는 일도 언젠간 다 지나가고 추억이 될 날이 올 것이다.&lt;/p&gt;
&lt;p&gt;그러니 어쨌든 좌.절.금.지.&lt;/p&gt;
&lt;p&gt; 54
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[F# 101]]></title><description><![CDATA[F# 인트로덕션: 강연 하시는 분이 유머 감각이 좀 있으십니다. 욱겨요 ㅋ~ 학부 전공이 컴퓨터 공학이었습니다.…]]></description><link>https://jiniya.net/wp/archives/11592</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11592</guid><pubDate>Wed, 24 Jul 2013 23:59:09 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;F# 인트로덕션: 강연 하시는 분이 유머 감각이 좀 있으십니다. 욱겨요 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;학부 전공이 컴퓨터 공학이었습니다. 4년을 다녔는데 항상 아쉬웠던 점은 함수형 언어에 관한 수업을 듣지 않은 것이라는 생각이 많았습니다. 학교에 함수형 언어 수업이 있었는지는 잘 모르겠네요. 어쨌든 MIT의 “컴퓨터 프로그램의 구조와 해석” 같은 책들을 보면서 전 항상 프로그래머로써 촌스럽다는 생각을 많이 했었습니다.&lt;/p&gt;
&lt;p&gt;그럼 졸압하고 혼자 공부하면 됐지 않냐구요? 네. 옳은 말씀입니다. 하지만 항상 함수형 언어들은 한가지 맹점을 가지고 있었는데 제가 사용하기에 그다지 실용적이지 않다는 점이었습니다. 심지어 임베딩을 해서 쓰기에도 적합한 타겟을 물색하기가 쉽지 않았죠. 그렇게 시간은 하염없이 흘러갔습니다.&lt;/p&gt;
&lt;p&gt;시대가 많이 변했죠. CPU는 하나라고 가정되던 세상에서 핸드폰 속에도 쿼드코어가 들어가는 시대가 됐습니다. 멀티 스레드 프로그래밍은 이제 일반적인 화두가 돼 버렀죠. 구글을 기점으로 마치 새로운 기법인마냥 “맵-리듀스”란 용어가 한때 업계를 휘젓기도 했습니다. 바야흐로 함수형 언어가 다시 각광을 받을 수 있는 시대가 된 것이죠.&lt;/p&gt;
&lt;p&gt;함수형 언어는 기본적으로 사이드 이펙트에서 자유롭기 때문에 명령형 언어(C,C++,Python, …)에 비해서 병렬화를 하기가 엄청 수월하다는 장점이 있습니다. 더불어 위 인트로덕션 동영상에도 나오지만 함수형 언어를 이용한 문제 해결 과정은 정말이지 문제 자체에만 집중할 수 있게 해준다는 느낌이 강하죠. 문제를 풀기위한 구질구질한 작업들은 잠시 잊어도 되는 것입니다. 당연히 생산성이 향상될 수 밖에 없겠죠.&lt;/p&gt;
&lt;p&gt;이런 시대적 흐름에 발맞춰 MS에서는 F#이라는 .NET용 함수형 언어를 개발했습니다. MS가 개발한 언어답게 Real-World에서 바로 사용할 수 있을 정도로 실용성이 강조됐습니다. 기존 .NET 프레임워크를 잘 활용할 수 있도록 구성돼 있죠. 특히나 제가 느낀 인상은 MS가 상당히 공을 들이고 있다는 점입니다. &lt;a href=&quot;http://msdn.microsoft.com/en-us/vstudio/hh388569.aspx&quot;&gt;F# 배우기&lt;/a&gt; 페이자만 보더라도 정말 토나오죠. MVP 리드도 F# MVP를 간절하게 찾고 있는 모양이예요. 이러니 저리니 해도 일자리를 구한다는 의미라면 사실 F#이란 언어가 크게 시장성이 있지는 않을 겁니다. 그래도 배워두면 여러분의 강력한 무기 중에 하나가 될 거라는 점은 장담할 수 있을 것 같아요.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 577px; margin-bottom: 16px;&apos; data-url=&apos;./fs0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ed48662f94a64fd9613d68ab9825be3e/32e64/fs0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 39.473684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA7UlEQVR42pVQ2ZKEIBDz//9xdjxQR7kvlUPZoE/7tkOlqKQhpJvmuq5SypsPo55BHvnP1aSUQ8jSmy1u1Vy+MSvtOkKN3XM6Y8zfBJdm34NUjjK9rFIqCxljCiFhP0Ks5Oa1eMSczz9maBiEtADjeqGKi0oguTDglXAjhMXrxm73mCnEVM1IIyMlE+0Jfb3neeZdv5CJQQ4jbfulJ6zt19fP1A5rN6xt90Fx/AilXGPttlIltWOspn0WQZlhzHCuKTc4UtrfQym08wDX0C/Q5PM8jmis18ZrXXFz90h8B8z4VEhjvPM7YiDReSnlFwHyzEz31AupAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;fs0&apos; title=&apos;&apos; src=&apos;/static/ed48662f94a64fd9613d68ab9825be3e/32e64/fs0.png&apos; srcset=&apos;/static/ed48662f94a64fd9613d68ab9825be3e/08678/fs0.png 190w,
/static/ed48662f94a64fd9613d68ab9825be3e/2edd7/fs0.png 380w,
/static/ed48662f94a64fd9613d68ab9825be3e/32e64/fs0.png 577w&apos; sizes=&apos;(max-width: 577px) 100vw, 577px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;MVP 계의 블루오션 F#, 지금 시작하세요 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;함수형 언어는 리그 오브 레전드 리그와 비슷한 특징을 하나 더 가지고 있는데요. 게임 방송을 보면 와 저렇게 하면 쉽게 되겠구나 라고 생각되는데 막상 직접 해보면 생각처럼 잘되지 않습니다. 함수형 언어도 남들이 풀어놓은 솔루션을 볼 때면 와 이거 정말 쉽네, 저렇게 간단하게 되는구나, 라고 생각되는데, 막상 스크래치해서 처음부터 만들어 내려면 하나부터 열까지 생각이 탁탁 막히는 느낌이 들겁니다. 바로 명령형 언어에 너무 익숙해져버린 뇌 때문이죠. 함수형 언어를 배울 때 가장 먼저 익혀야 하는 것은 함수형 시각으로 문제를 생각하는 방식입니다. 최근에 “Real-World Functional Programming”이란 책을 한 권 구입했습니다. 서문에 이런 저의 생각이 잘 나와 있더군요 ㅋ~ 물론 본문은 아직 시작을 못했습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Real-World-Functional-Programming-With-Examples/dp/1933988924/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1374631648&amp;#x26;sr=8-1&amp;#x26;keywords=practical+functional+f%23&quot;&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; margin-bottom: 16px;&apos; data-url=&apos;./fs1.jpg&apos;&gt;
      &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQBBQP/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABu9YMY7bRfGtGLAX/AP/EABwQAAMAAgMBAAAAAAAAAAAAAAECAwAEESMxM//aAAgBAQABBQK1nSknL4PNsdyAhs2vrFeZZ//EABcRAQEBAQAAAAAAAAAAAAAAAAEQITH/2gAIAQMBAT8BHYdn/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAx/9oACAECAQE/AWOT/8QAHBAAAgICAwAAAAAAAAAAAAAAARECEAADMWGB/9oACAEBAAY/AlFYBLlOvM1Hq4Gv/8QAHRABAAEEAwEAAAAAAAAAAAAAAQAQESExQWFxwf/aAAgBAQABPyHWpbkmlCzDvMFrL3gO3CC9Xp7qgy8Ibi4PtP/aAAwDAQACAAMAAAAQh8+8/8QAFxEBAAMAAAAAAAAAAAAAAAAAEAERMf/aAAgBAwEBPxCSxuf/xAAXEQADAQAAAAAAAAAAAAAAAAABECEx/9oACAECAQE/EAgWC//EAB8QAQABAwQDAAAAAAAAAAAAAAERACExEEFRwWGBkf/aAAgBAQABPxBoVu5GWfNGoSgEyDBm0H2kJJG7vV5weCeaOlYIBzn2F0JTc7qKQbANrS60/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;fs1&apos; title=&apos;&apos; src=&apos;/static/558bd4a3bfd497fe8031b3c84200b31d/0cdb7/fs1.jpg&apos; srcset=&apos;/static/558bd4a3bfd497fe8031b3c84200b31d/8ccab/fs1.jpg 190w,
/static/558bd4a3bfd497fe8031b3c84200b31d/0cdb7/fs1.jpg 300w&apos; sizes=&apos;(max-width: 300px) 100vw, 300px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
    &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This book is different from many other programming books available today. It doesn’t focus only on a specific programming language or library. Instead, it use the presented languages and libraries to explain &lt;strong&gt;a way of thinking&lt;/strong&gt; — a way of thinking that becoming increasingly important and has influenced many recent technologies.&lt;/p&gt;
&lt;p&gt;– Real-World Functional Programming, Tomas Petricek &amp;#x26; Jon Skeet&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;최근에 우리는 .NET 환경을 적극 활용하는 방향으로 전환했습니다. 전 F#으로 패턴 스캐닝 엔진을 새롭게 쓰는 작업을 하고 있습니다. .NET이 일반화된 환경이기도 하고, MONO 같은 오픈 소소를 활용하면 손쉽게 멀티 플랫폼의 장점을 누릴수도 있기 때문입니다. 보안적인 측면에서도 네이티브와 듀얼 구성을 한다면 다양성 측면에서는 오히려 보안이 한층 더 강화된다고 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;감히 예측컨데 앞으로는 함수형 언어로 생각을 할 수 있는 프로그래머와 그렇지 않은 프로그래머로 나뉘는 시대가 올 겁니다. 미리미리 함수형 사고 회로를 뇌에다 설치하는 작업을 해 두도록 합시다. 설령 그런 시대가 오지 않아도 손해 보진 않을 거예요 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt; 1
 1&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[나이는 정말 숫자에 불과합니다…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11796</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11796</guid><pubDate>Tue, 23 Jul 2013 23:59:08 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./나이는_정말_숫자에_불과합니다.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ce8c357cda465dab8832273de3d5d724/dface/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsSAAALEgHS3X78AAACr0lEQVR42mVU2W7aUBT0//9EIzVSQ18ihT40C9AoDgQS9h0DYQcDZjMGA5GmZw6QVu3D6HJ9uXPmzBnbsOoWXl5iCIdDeH42kctl0W630el2MBgOYNsjjMdjzGYOttsNfN8XbPX32nOxdl0sFnNMJhOFUalUEImEUa1WUa/X0em0MRoN5XCMqTPFdDoRshnm8xlWq9X/pOs1lsulFlTCTDaj6prNphJWqxX0el2s3BU2G0/Bi8Rut8PhcBDssd/vZe/D80i4gCOF7bENIxaLasuDwUDUdYS4gaG0yopUZ9u2trRaLfUiFZ1VLRYLhSOd2KORcPRhhEIh5LJZ9Pt9tFotWXuYTo5tOo4j7Y/0kud5cMWv9doVtdtPsP3NZqPPWdS4vf2p/vV6PVXY7XaVgApIQNA7quLKM5Kwdbbt+7uTl2fCu1tYVg3NRkM9rNWqqtYT79T8ra8XzzgTnfE34ZKEpmlqTOhVV6JCMnpIRcdJbk9TPYKD+Re+/IfDcWWQRiIR1wlXJT5cORySM3uMgSuV9/vDp7qPj4/TpI+gf2x1Lp4zs8brawLlcklhWRbaMhiSDodDJaRn8/lcPXV08lN9znMOzJn+ySr3RiqVQrFYRKlUUtRqNUWpVFRP6/WGnjfEY+aTw2NBWsNV4yWxIdlAighhEplMBslkEolEAvl8XonK5bJa0Gq15fJRMWP1/t7SNFDZUnM413ySlFYZUQl2TILN1qmkUCjg7e0N0WgUj4+PeHoykU6nhehd4lWTQpVjVk9tUiVVszBFGA8PD/IuR5AQwkIhD079RzCI+/s78Mw0n1Q9u6A97CCdTiEWi+meAiqV8rGYDNYIymUi8isi73QY3wMBBAJXuLz8iouLL7q/vr7G1dU3BG9uYMoXiR+TeDwu5Dmxx1L1BC35DbYkSEHnf7fpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 0&apos; title=&apos;&apos; src=&apos;/static/ce8c357cda465dab8832273de3d5d724/dface/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_0.png&apos; srcset=&apos;/static/ce8c357cda465dab8832273de3d5d724/08678/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_0.png 190w,
/static/ce8c357cda465dab8832273de3d5d724/2edd7/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_0.png 380w,
/static/ce8c357cda465dab8832273de3d5d724/dface/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_0.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;환갑의 나이에도 이렇게 불꽃코딩하시면 저희는 부끄럽지요 ㅠㅜ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;어제부터 아주 성가신 문제를 하나 보고 있었습니다. 사실 중요한 부분도 아닌데 엔지니어의 지적 호기심이랄까요? ㅎㅎ~ 여튼 반쯤만 해결된 상태입니다. 오늘 문제를 좀 집중해서 보려고 윈도우 소스 코드를 좀 뒤적거렸습니다. 모니터로 보니 당췌 산만해서 중요한 부분이고 몇 줄 안 되는 것 같아서 출력 버튼을 눌렀지요. 근데 무려 52페이지가 출력돼 버려서 적잖게 당황스러웠습니다. 거기까진 생각보다 파일 내용이 많았구나 이러면서 그러려니 했는데… 파일 위쪽 주석에 적힌 이름이 저를 멘탈붕괴 상태로 만들어 버렸습니다. 선명하게 적힌 Dave N. Cutler, 그 옆에 날짜는 절 더 당황스럽게 만들었지요. 26-Oct-2000.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 419px; margin-bottom: 16px;&apos; data-url=&apos;./나이는_정말_숫자에_불과합니다.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/887e56bffa84ccffa5f82ac7d37736c1/96e9b/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 20%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAjUlEQVR42o2ODQ7DIAiFe/9j2mmNsbY61Ip/e113gBFC3oN8wKK1llKOPgyZ1a9nPscc879YlFJCiN47DHd22fnLR46xxCMfEKGEPe2JEzGFK0DAcuMbfn2jtQZTe8WYCoHJNWMLKqxLDiQ0pkh894OttcaY53JpRZPG4u29ySABQCDBo4kOMNiHnHN+ACQT5jSd+CPGAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 1&apos; title=&apos;&apos; src=&apos;/static/887e56bffa84ccffa5f82ac7d37736c1/96e9b/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_1.png&apos; srcset=&apos;/static/887e56bffa84ccffa5f82ac7d37736c1/08678/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_1.png 190w,
/static/887e56bffa84ccffa5f82ac7d37736c1/2edd7/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_1.png 380w,
/static/887e56bffa84ccffa5f82ac7d37736c1/96e9b/%EB%82%98%EC%9D%B4%EB%8A%94_%EC%A0%95%EB%A7%90_%EC%88%AB%EC%9E%90%EC%97%90_%EB%B6%88%EA%B3%BC%ED%95%A9%EB%8B%88%EB%8B%A4.md_1.png 419w&apos; sizes=&apos;(max-width: 419px) 100vw, 419px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.jiniya.net/wp/archives/289&quot;&gt;요즘은 내가 대세… 17년만에 소스 코드 물려 받았지요 ㅋ&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;네. 그렇죠. 그렇게 밑에 똑똑하고 코딩 잘하는 애들 줄줄이 비엔나처럼 있겠지만 중요한 부분 코딩 맡기시려니 미덥지 않으셨던 거 이해합니다. 그래도 환갑의 나이에 이건 좀 지나치신 건 아니신지. 너무 부끄럽잖아요. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;제가 오늘 본 부분이 AMD64로의 주요한 포팅 작업이었던 것 같군요. 다 확인은 안 해 보았지만 2002년까지 그의 작업이 확인됐습니다. 큭~ 이후 윈도우 애저를 만드시고, 무려 2013년 현재에도 칠순의 나이에 Xbox One 디벨로퍼로 활약하시는 당신은 진짜 초큼 어이가 없습니다. 진정 초사기 캐릭이신거죠? ㅋㅋㅋ~ 분발해야겠습니다. 칠순의 할아버님도 이렇게 열심히 코딩하시는데…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Windows NT&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Cutler left Digital for Microsoft in &lt;strong&gt;October 1988 and led the development of Windows NT.&lt;/strong&gt; Later, he worked on targeting Windows NT to Digital’s 64-bit Alpha architecture (itself based on the Prism design),[citation needed] then on Windows 2000. After the demise of Windows on Alpha (and the demise of DEC), &lt;strong&gt;Cutler was instrumental in porting Windows to AMD’s new 64-bit AMD64 architecture.&lt;/strong&gt; He was officially involved with the Windows XP Pro 64-bit and Windows Server 2003 SP1 64-bit releases. He moved to working on Microsoft’s Live Platform in August 2006. Dave Cutler was awarded the prestigious status of Senior Technical Fellow at Microsoft.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows Azure&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At the 2008&lt;/strong&gt; Professional Developers Conference, Microsoft announced Azure Services Platform, a cloud-based operating system which Microsoft is developing. During the conference keynote, &lt;strong&gt;Cutler was mentioned as a lead developer&lt;/strong&gt; on the project, along with Amitabh Srivastava.[5]&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Xbox&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;As of January 2012, a spokesperson for Microsoft has confirmed that Cutler is no longer working on Windows Azure, and has since joined the Xbox team.[6] No further information was provided as to what Cutler’s role was, nor what he was working on within the team.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In May 2013&lt;/strong&gt;, Microsoft announced the Xbox One console, and Cutler was mentioned as having worked in the development of host OS portion of the system running inside the new gaming device. &lt;strong&gt;Apparently Cutler’s work was focused in creating an optimized version of Microsoft’s Hyper-V Host OS specifically designed for Xbox One.&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://en.wikipedia.org/wiki/Dave_Cutler#Windows_NT&quot;&gt;http://en.wikipedia.org/wiki/Dave_Cutler#Windows_NT&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[boost 라이브러리 집중 분석]]></title><description><![CDATA[시쳇말로 C 언어는 2시간 배워서 20년 써먹고, C++은 20년 배워서 2시간 써먹는다는 이야기가 있다. 그만큼 C 언어는 간결하고 핵심적인 기능만 포함한 언어인 반면, C++은 복잡하고 다양한 기능이 포함돼 있다. 나는 C 언어를 배운지는 2…]]></description><link>https://jiniya.net/wp/archives/11769</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11769</guid><pubDate>Tue, 23 Jul 2013 23:59:07 GMT</pubDate><content:encoded>&lt;p&gt;시쳇말로 C 언어는 2시간 배워서 20년 써먹고, C++은 20년 배워서 2시간 써먹는다는 이야기가 있다. 그만큼 C 언어는 간결하고 핵심적인 기능만 포함한 언어인 반면, C++은 복잡하고 다양한 기능이 포함돼 있다. 나는 C 언어를 배운지는 20년, C++은 13년 정도 됐다. 그간 주로 일했던 도메인이 보안이라 성능 이슈가 주요하고 네이티브 코드를 많이 작성해야 했기에 주력 프로그래밍 언어는 언제나 C++이었다. 그렇게 오래 함께한 언어임에도 C++은 여전히 어려운 언어이고, 지금까지도 항상 공부해야 하는 언어다. 물론 이런 현상은 단지 내가 멍청하기 때문만은 아닌 것 같다. 실제로 C 언어의 창시자인 Brian Kernighan 할아버지도 그런 의견을 피력했던 적이 있었기 때문이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;때때로 나는 C 대신 C++을 사용해서 프로그램을 작성합니다. 제가 생각하기에 C++은 모든 기능을 내장하기 때문이라고 하더라도 매우 큰 언어입니다. 어떤 크기의 C 프로그램을 작성하든지 저는 75, 80, 90% 정도의 언어 기능을 사용합니다. 다시 말하면 어떤 종류의 프로그램이든 간에 대부분의 C 언어 기능이 유용하다는 점 입니다. 이와는 대조적으로 제가 C++을 사용한다면 언어의 10% 정도도 사용하지 못합니다. 그리고 나머지 90%는 제가 이해하고 있다고 생각하지 않습니다. 이러한 점들에서 전 C++은 너무 크다고 말합니다. 그러나 C++은 큰 프로그램을 작성하는데 필요한 많은 기능들을 제공합니다. 객체를 만드는 것이 가능하며, 내부적인 정보의 표현을 보호할 수 있습니다. 그래서 결국 내부를 보지 못하게 만드는 훌륭한 외관을 표현할 수 있습니다. C++은 제가 생각하기에 아주 방대한 양의 유용한 메카니즘을 가지고 있습니다. 그리고 그것은 C 언어가 당신에게 주지 못하는 점 입니다.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://www.cs.cmu.edu/~mihaib/kernighan-interview/&quot;&gt;Brian Kernighan, 2000&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;기존의 C++이란 언어 자체도 방대한 기능으로 무장한 언어였지만 모던 C++로 불리는 C++11과 C++13, C++14로 불리며 지금 계속 개정 작업이 진행되고 있는 신규 표준은 훨씬 더 방대한 내용을 담고 있다. 상당히 최신 기술들이기 때문에 아직까지도 골수 C++ 프로그래머들도 이러한 기능을 잘 모르는 경우가 많다. 기능을 지원하는 컴파일러들이 제한적이기 때문에 실용성이 없다고 주장하는 입장도 많이 있다. boost는 이런 간극을 메워줄 수 있는 주요한 라이브러리다. 표준에 채택된 기능을 상당수 포함하고 있고, 추후 표준에도 적극적으로 라이브러리 기능들이 제안되고 있기 때문이다. 더불어 C++11을 지원하는 새로운 컴파일러를 사용하지 않더라도 boost를 사용하면 새로운 표준 라이브러리 기능들을 사용할 수 있기 때문에 더욱 효과적이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;왜 boost인가?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;boost의 주요 기능을 소개하기에 앞서서 왜 이런 복잡한 형태의 라이브러리를 사용해야 하는지에 대해서 먼저 알아보는 것이 중요한 것 같다. 왜냐하면 인식이 조금씩 바뀌고 있지만 여전히 boost와 같은 형태의 복잡하고 거대한 라이브러리를 사용하는 것에 대해서 회의적인 프로그래머들이 상당수 있기 때문이기도 하고, 무엇을 공부함에 있어서 그 필요성을 절감하고 공부하는 것과 단지 다른 사람들이 쓴다고 하니까 배우는 것에는 큰 차이가 있기 때문이기도 하다.&lt;/p&gt;
&lt;p&gt;반대하는 쪽 주장의 면면을 살펴보면 이렇다. 1) 버그가 있다. 2) 너무 복잡하다. 3) 내가 만드는 걸 선호한다.&lt;/p&gt;
&lt;p&gt;이 중에서 버그 이야기를 먼저 해보자. 결론만 먼저 말하면 사실 이런 주장을 하는 프로그래머치고 boost의 버그를 정확하고 명백하게 보여주는 프로그래머는 없었다. 대부분 그들이 도입하면서 겪었던 일부 문제들을 가지고 boost의 버그로 말하는 경향이 있는데 여기에는 boost 라이브러리의 사용법을 명확하게 몰라서 생긴 문제가 거의 대다수였다. 즉, 돌려 말하면 윈도우 API를 잘못 사용해서 잘못된 결과를 얻어놓고서는 윈도우 API의 버그라고 말하는 경우와 동일한 경우가 대부분이라는 점이다. 백 번 양보해서 제대로 된 버그를 발견했다고 치더라도 그걸 고쳐서 오픈소스 커뮤니티에 기여하면 된다. boost와 같은 라이브러리의 경우 전세계 수많은 개발자들이 지켜보고 있기 때문에 그 어떤 프로젝트보다도 결함이 신속하고 빠르게 고쳐진다. 적어도 버그 문제에 있어서는 직접 작성하는 것보다 훨씬 고품질의 결과를 얻을 수 있다는 점은 인정하자.&lt;/p&gt;
&lt;p&gt;너무 복잡하다. 맞다. boost 라이브러리는 영문 정식 명칭이 library가 아닌 libraries로 돼 있을 만큼 정말 엄청나게 다양한 라이브러리의 묶음이다. 걔 중에는 유용한 것들도 있지만 당연히 사용하는 쪽 입장에서는 불필요한 부분도 많이 있다. 하지만 이는 다시 생각해보면 복잡해서 잘 모르는 부분은 사용하지 않으면 그만이다. boost를 사용한다고 해서 거기 있는 모든 라이브러리를 몽땅 써야 하는 것은 아니다. 더욱이 boost의 경우에 템플릿 기반의 라이브러리라 대다수 코드들은 헤더를 포함하지 않으면 그 어떤 코드도 우리 프로젝트에 영향을 미치지 않는다.&lt;/p&gt;
&lt;p&gt;끝으로 꼭 직접 만든 것만 믿는 프로그래머들이 있다. 하지만 이건 정말이지 바보 같은 생각이다. 왜냐하면 조금만 시각을 달리하면 직접 만든 건 결국 하나도 없기 때문에다. 심지어 C++이란 언어 자체도 직접 만든 것은 아니다. 컴파일러도 마찬가지다. 그러니 직접 만든 것만 쓰겠다는 생각은 자신의 시야를 너무 좁은 곳에 두는 관점이라는 걸 명심하자.&lt;/p&gt;
&lt;p&gt;자 그럼 이제 반박을 떠나서 boost와 같은 외부 라이브러리 사용의 긍정적인 측면을 살펴보도록 하자. 버그의 정반대 측면인 안정성을 들 수 있다. boost와 같은 검증된 라이브러리는 수많은 프로그램에서 사용되고, 전세계에 분포한 다양한 개발자들이 프로젝트에 참여하고 있다. 보는 눈이 많은 만큼 훨씬 더 안정적일 수 밖에 없다. 혹여 사용하다가 결정적인 버그를 발견했다손 치더라도 오픈 소스이기 때문에 수정해서 사용할 수 있고, 커뮤니티에 기여하는 경우에는 다음부터는 유사한 문제를 겪는 프로그래머가 없도록 도와 줄 수도 있다.&lt;/p&gt;
&lt;p&gt;다음은 멀티 플랫폼이다. 요즘 컴퓨팅 환경의 트렌드를 한 마디로 요약하자면 멀티 플랫폼이다. 컴퓨터가 들어가지 않은 디바이스를 찾기 힘들 지경이다. 자동차, 세탁기, 냉장고, TV, 핸드폰, 손목시계, 안경 등 우리가 상상할 수 있는 모든 곳에는 컴퓨터가 탑재되고 있다. 그만큼 프로그래머들은 고달픈 시대다. 한가지 플랫폼만 했어도 충분했는데 이제는 이쪽 저쪽을 다 신경 써야 하기 때문이다. 이럴 때 가장 좋은 것이 이식성이 있는 소스 코드다. boost의 경우 다양한 환경에 대한 추상화 계층을 사용하기 때문에 boost::asio와 같은 비동기 입출력 라이브러리를 사용한다면 우리는 Windows, BSD, Linux 등과 같은 플랫폼에 상관 없이 그 플랫폼에 얼추 최적화된 구현을 바로 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;끝으로 가장 결정적인 이유는 좋은 라이브러리를 써봐야 좋은 라이브러리를 만들 수 있기 때문이다. 컴퓨터 공학을 가르치는 대학의 경우 대부분 소스 코드 베끼기가 실력 향상에 좋지 않다는 이유로 소스 코드 보는 행위를 장려하지 않고 있다. 안타깝게도 이런 현상 때문에 제대로 된 코드를 쓸 줄 아는 프로그래머가 그렇게도 드문 것 같다. 다른 사람이 만든 소스 코드, 또는 선배 프로그래머들이 만든 소스 코드를 봐야지 아 이런 식으로 짜는 구나를 알 수 있다. 파서를 strstr로 짜고 있는 프로그래머, 함수 포인터를 몰라서 switch/case를 일일이 열거하고 있는 프로그래머를 보면 정말이지 어디서부터 이야기를 해야 할지 답이 안 나오는 지경이다. 직접 만들더라도 많은 사람들이 사용하는 좋은 구조에 대해서는 알아두는 것이 도움이 된다는 점을 꼭 기억하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;shared_ptr&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아마도 boost 라이브러리를 접했던 프로그래머의 절반 이상이 shared_ptr 이라는 스마트 포인터 하나를 사용하기 위해서 접했다고 해도 과언이 아닐 만큼 boost 보다 더 유명한 클래스다. 이제는 C++11에 포함돼 있기 때문에 std::shared_ptr 형태로 사용할 수 있다. 하지만 아직 C++11을 지원하는 컴파일러를 사용할 수 없는 환경이라면 boost는 여전히 강력한 대안이다.&lt;/p&gt;
&lt;p&gt;C++11 이전의 표준에 포함됐던 유일한 스마트 포인터 클래스는 auto_ptr 클래스였다. auto_ptr의 경우 소유권 이전에 대해서 다소 난해한 정책을 가지고 있어서 스마트 포인터를 처음 접하는 프로그래머에게 좋지 않은 인상을 남기는 허들 역할을 톡톡히 했다. &amp;#x3C;리스트 1&gt;에는 전형적인 auto_ptr의 잘못된 사용을 보여주고 있다. auto_ptr의 경우에는 복사 시에 소유권이 이전되는 데 이게 상황에 따라서 상당히 미묘한 많은 문제를 일으킨다. 더욱이 이런 특징 때문에 결정적으로 STL 컨테이너와는 전혀 연동을 할 수 없기 때문에 반쪽 짜리 스마트 포인터라는 오명을 가지기도 했었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 auto_ptr의 소유권 이전 문제를 보여주는 전형적인 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;memory&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;iostream&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Value&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; val_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Value ctor&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Value dtor&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;auto_ptr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Value&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    param&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;val_ &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    auto_ptr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Value&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; Value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    pa&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;val_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pa val_ = &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; pa&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;val_ &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fn 호출 시작&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pa&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fn 호출 끝&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pa val_ = &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; pa&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;val_ &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;auto_ptr의 소유권 이전 문제를 개선한 것이 boost의 shared_ptr이다. shared_ptr은 내부적으로 레퍼런스 카운팅을 사용하기 때문에 복사하더라도 해당 객체를 참조하는 포인터가 모두 사라지는 경우에만 실질적으로 객체 파괴 작업이 일어난다. 복사 시에 레퍼런스 카운트를 증가시키고, 파괴 시에는 레퍼런스 카운트를 감소시켜 0이 되는 경우에 실제로 객체를 파괴하도록 만들어져 있기 때문이다. 이런 장점 때문에 auto_ptr과 달리 STL 컨테이너에 넣어도 안전하다.&lt;/p&gt;
&lt;p&gt;shared_ptr은 레퍼런스 카운팅이라는 기본적인 장점에 추가적으로 커스텀 파괴자를 지원하기 때문에 스마트 포인터의 활용도를 한층 더 높일 수 있다는 장점도 있다. &amp;#x3C;리스트 2&gt;에는 세 개의 파일 리소스를 사용해서 처리를 하는 일반적인 루틴을 보여주고 있다. 이 경우에 사용하는 리소스가 추가될 때마다 인덴트 깊이가 깊어져서 코드가 보기 힘들어지는 경향이 있다. 실제로 스마트 포인터가 없는 COM 코드에서는 이러한 코드가 일반적이다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 2&gt;의 코드를 가독성이 좋도록 개선한 버전이 &amp;#x3C;리스트 3&gt;에 나와 있다. 변경된 코드에서는 실패 시에 바로 함수 실행을 리턴하도록 만들었다. 하지만 이렇게 할 때에도 매 실패 시점마다 프로그래머가 현재 획득한 리소스와 해제해야 할 리소스 목록을 알고 있어야 한다는 단점이 있다.&lt;/p&gt;
&lt;p&gt;이런 코드의 경우 가장 깔끔한 해결 방법은 기존의 레거시 파일 처리 루틴을 사용하지 않고 RAII(Resource Acquisition Is Initialization) 형태로 설계된 파일 클래스를 사용하는 것이 정답이다. 하지만 현실 세계에 존재하는 수많은 레거시 코드를 일일이 그런 형태로 래핑하는 것은 너무 이상적인 이야기일 수 밖에 없다. 이런 경우에 중간 단계의 절충안으로 shared_ptr을 사용할 수 있다. &amp;#x3C;리스트 4&gt;에는 shared_ptr의 커스텀 파괴자를 사용해서 자원을 관리하는 코드가 나와 있다. shared_ptr이 파괴될 때 fclose가 호출되기 때문에 파일 포인터 자원이 자동적으로 소거된다. 이 코드에서 프로그래머는 자원 생성 시에만 파괴 루틴을 등록하고 이후에는 해당 자원에 대해서는 신경 쓰지 않아도 되기 때문에 실수할 가능성이 줄어들고 그만큼 자원 관련 버그도 줄여준다. 예외 발생 시에도 자원을 안전하게 파괴할 수 있다는 것은 추가적인 장점이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 파일 포인터 자원 3개를 사용하는 일반적인 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;MergeFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCSTR dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR src1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR src2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    dfp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        sfp1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            sfp2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// 실제 처리할 작업&lt;/span&gt;

                &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 실패시 리턴 방식을 사용한 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;MergeFile2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCSTR dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR src1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR src2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    dfp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    sfp1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    sfp2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 실제 처리할 작업&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 shared_ptr을 사용하여 자원 관리를 하는 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/shared_ptr.hpp&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;shared_pt&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; vsptr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;MergeFile3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCSTR dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR src1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCSTR src2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    dfp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    vsptr &lt;span class=&quot;token function&quot;&gt;dfp_closer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dfp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fclose&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    sfp1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    vsptr &lt;span class=&quot;token function&quot;&gt;sfp1_closer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fclose&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    sfp2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    vsptr &lt;span class=&quot;token function&quot;&gt;sfp2_closer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sfp2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fclose&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 실제 처리할 작업&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;bind&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;boost에서 shared_ptr 다음으로 유명한 것을 들자면 단연코 bind가 될 것이다. 유연하게 설계된 클래스가 얼마나 효율적으로 기존 시스템과 마찰 없이 잘 결합될 수 있는지를 단적으로 보여주는 클래스라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;bind은 기본적으로 함수 호출 객체를 만들어주는 역할을 한다. &amp;#x3C;리스트 5&gt;에는 기본적인 사용 방법이 나와 있다. fn이라는 기존 함수에 a, b, c, d, e 파라미터로 1, 2, 3, 4, 5를 전달해서 호출하는 함수 객체를 만드는 것을 보여주고 있다. 해당 함수 객체를 호출하면 결과 값은 15가 출력된다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 6&gt;에는 플레이스홀더를 사용해서 bind 객체를 생성하는 것을 보여준다. _1로 표시된 자리에 해당 함수 객체를 호출할 첫 번째 파라미터가 들어간다는 의미다. 따라서 이 함수 객체를 호출할 때에는 _1 자리에 들어갈 파라미터를 넣어주어야 한다. 예제에서는 10을 넣어주었다. 따라서 이 객체는 최종적으로 fn(1, 2, 10, 4, 5)를 호출하는 결과를 보여준다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 7&gt;에는 플레이스홀더를 두 개 사용한 예제가 나와 있다. _1에는 첫번째 파라미터가, _2에는 두번째 파라미터가 들어간다. 따라서 이 함수 객체를 사용할 때에는 2개의 파라미터를 넣어주어야 정상적으로 호출된다. 예제 코드의 bind는 최종적으로 fn(1, 11, 10, 4, 5)를 호출하는 것과 동일한 기능을 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 기본적인 bind 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/bind.hpp&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a = %d, b = %d, c = %d, d = %d, e = %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; d &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 bind 플레이스홀더 사용 예제 1&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 bind 플레이스홀더 사용 예제 2&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;boost::bind의 경우 클래스 멤버 함수에도 동일하게 적용할 수 있다. &amp;#x3C;리스트 8&gt;에는 멤버 함수에 bind를 적용한 코드가 나와 있다. 이 코드에 나와 있는 두 bind 호출은 모두 최종적으로 bob.Say(“Hello”)를 호출하는 역할을 한다. boost::bind는 파라미터를 지정하는 경우 값을 복사하는 형태로 동작하기 때문에 내부 동작을 보여주기 위해서 생성자, 복사 생성자, 소멸자에 각각 printf를 추가해 놓았다.. 출력된 내용을 살펴보면 첫 번째 bind의 경우에는 지속적으로 객체가 복사되고 있음을 확인할 수 있다. 이를 제거하기 위해서는 boost::ref를 사용하면 된다. 첫 번째 bind 코드를 boost::bind(&amp;#x26;Man::Say, boost::ref(bob), “Hello”)()와 같이 고쳐서 테스트를 해보면 값이 복사되지 않는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 멤버 함수에 bind 적용 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/bind.hpp&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Man&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string name_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;Man&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s ctor\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name_&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;Man&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Man &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s cctor\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name_&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Man&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s dtor\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name_&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Say&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s: %s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name_&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Man &lt;span class=&quot;token function&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Man&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Say&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bob&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Man&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Say&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;bind의 객체가 복사된다는 특징은 shared_ptr과 같은 스마트 포인터와 결합하면 좀 더 유연한 동작을 가능하게 한다. &amp;#x3C;리스트 9&gt;에는 shared_ptr 객체를 참조하는 bind 예제가 나와 있다. bind가 객체를 복사해 두었기 때문에 bob.reset 이후에도 객체가 파괴되지 않고 살아있어서 정상적으로 멤버 함수 호출이 이루어진다. 실질적인 bob 객체는 bind 함수 객체를 담고 있는 function 객체가 사라질 때 같이 소멸된다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 9&gt;의 코드에서 객체를 복사하지 않고 boost::ref를 사용해서 직접 참조했다면 bob.reset 시점에 객체가 사라지고 이후 호출되는 fn(“Hello”)는 사라진 객체를 참조하게 되기 때문에 크래시가 발생하는 문제점이 생긴다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 shared_ptr 객체의 멤버 함수를 참조하는 bind 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/shared_ptr.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/bind.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/function.hpp&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; boost&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    shared_ptr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Man&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Man&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; fn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Man&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Say&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bob&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    bob&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 9&gt;의 코드에도 잠깐 등장하지만 bind 결과 함수 객체를 저장해놓고 함수 포인터와 같이 지속적으로 사용하기 위해서는 boost::function 클래스를 사용하면 된다. function 클래스의 템플릿 파라미터로 함수 원형을 넣어주면 된다. &amp;#x3C;리스트 9&gt;의 예제 코드의 fn은 반환값이 없으며(void), 파라미터로 문자열을(const char *) 가지는 함수 객체를 만들겠다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;C++에 익숙하지 않은 프로그래머의 경우에는 여기까지만 이야기하면 이걸 도대체 어디에다 사용하겠다는 건지 의아해 하는 경우가 많다. 그런 경우라면 &amp;#x3C;리스트 10&gt;에 나와 있는 것과 같은 코드가 도움이 된다. 예제 코드에서는 벡터 멤버를 출력하기 위해서 이터레이터를 만들고 printf를 사용해서 벡터 멤버를 출력하고 있다. 하지만 이를 boost::bind를 사용하면 &amp;#x3C;리스트 11&gt;에 나와 있는 것과 같이 간단하게 한 줄로 해결할 수 있다. 코드가 짧다는 것을 실수할 가능성은 줄어들고, 가독성은 좋아진다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 이터레이터를 사용해서 벡터 멤버를 출력하는 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vector&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ints&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    vector&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;iterator it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 vector&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;iterator end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; \&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 11 boost::bind를 사용해서 벡터 멤버를 출력하는 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vector&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;algorithm&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/bind.hpp&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; boost&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ints&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;for_each&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;printf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; \_1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;thread&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;멀티스레드란 환경이 이제는 표준적인 프로그래밍 환경으로 자리잡은 것 같다. 하지만 스레드를 플랫폼마다 지원하는 방식의 차이가 있어서 표준적인 방식으로 사용하기에는 아직 문제가 많다. 이런 경우에는 boost::thread를 사용하면 손쉽게 멀티 플랫폼을 지원하는 스레드 코드를 작성할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 12&gt;에는 간단한 스레드 작성 코드가 나와 있다. 기존의 윈도우 스레드 구조와 크게 다르지 않은 코드다. boost::thread 생성자로 스레드 함수 포인터와 파라미터를 전달해서 스레드를 생성시키고 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;윈도우 프로그래밍을 하면 게시판에 올라오는 흔한 질문 중에 하나가 클래스 멤버 함수를 스레드로 구동시키는 방법에 관한 것이다. 컨텍스트에 관한 개념이 없어서 하는 질문인데 기존 윈도우 코드로만 해결하려면 정적 메소드를 만들고 파라미터로 객체 인스턴스를 전달하는 복잡한 과정을 거쳐야 한다. 하지만 boost에서는 boost::bind를 이용하면 손쉽게 클래스 멤버 함수도 스레드로 호출할 수 있다. &amp;#x3C;리스트 13&gt;에는 boost::bind를 사용해서 클래스 멤버 함수를 스레드로 호출하는 예제가 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 12 boost::thread 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/thread.hpp&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ThreadProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;th1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ThreadProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mark&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;th2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ThreadProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    th1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    th2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 13 클래스 멤버 함수를 스레드로 호출하는 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/thread.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boost/bind.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Man&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
 std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string name\_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

 &lt;span class=&quot;token function&quot;&gt;Man&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; \&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 name\_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Say&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; \&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[%d] %s: %s\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name\_&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;c\&lt;span class=&quot;token function&quot;&gt;_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 Man &lt;span class=&quot;token function&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 Man &lt;span class=&quot;token function&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Mark&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 
 boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;th1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Man&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Say&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bob&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;thread &lt;span class=&quot;token function&quot;&gt;th2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;boost&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Man&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Say&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mark&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bye~&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

 th1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 th2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;언어를 넘어서&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;최근에는 C/C++의 영향력이 급격하게 줄어들고 있는 모양새다. 다양한 요인이 있겠지만 아무래도 첫 번째 요인은 컴퓨팅 파워가 놀랍도록 좋아진 점을 들 수 있을 것 같다. 이제는 더 이상 몇 바이트, 몇 나노초를 계산해가면서 프로그래밍하지 않아도 되는 세상이다. 또 다른 요인으로는 과거와는 다르게 프로그램에 기대하는 요구사항이 폭발적으로 증가했다는 점도 들 수 있다. 고객의 요구사항은 시시각각 변하고, 살아남는 프로그램이 되기 위해서는 그러한 요구사항의 변화를 빠른 속도로 대처해야 한다. 그런 점에서 정적인 언어인 C++은 다소 불리할 수 밖에 없었다.&lt;/p&gt;
&lt;p&gt;모던 C++은 이러한 생산성에 관한 취약점을 극복하기 위해서 다양한 기능들을 추가했다. boost 라이브러리 같은 것들을 사용하면 기존 C++ 컴파일러를 사용해서도 제한적이나마 편리한 신규 기능들을 체험해 볼 수 있다. 하지만 이 모든 사실 이전에 반드시 기억해야 할 것은 C++이 항상 우리에게 주어진 문제를 푸는 최선의 도구는 아니라는 점이다.&lt;/p&gt;
&lt;p&gt;C++ 언어를 사용하는 프로그래머의 경우 포인터를 다룬다는 점에서 나름 자부심이 많이 있는 편이다. 그래서 그런지 언어에 대한 자부심도 남다른 편인 것 같다. 하지만 모든 문제를 C++로 풀 필요는 없다. 주어진 문제를 해결하는데 적합한 도구를 사용하면 된다. C++로도 풀 수 있는 것이지 다른 대안 언어만큼 쉽게 풀 수 있는 것은 절대로 아니다. 그러니 C++ 언어의 새로운 기능을 꾸준히 탐색하는 것만큼이나 C++이란 언어의 도그마에 빠지지 않도록 각별히 주의해야 할 것 같다. 세상에 주어진 다양한 문제만큼이나 그 문제들을 독창적으로 해결할 수 있는 언어도 많다. 우리는 단지 적절한 도구를 사용해서 그 문제들을 풀기만 하면 되는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;boost 기능에 대해서 정리가 잘 된 슬라이드~ 백문이 불여일슬라이드 ㅋ~&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[치킨 게임]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11731</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11731</guid><pubDate>Mon, 22 Jul 2013 23:59:06 GMT</pubDate><content:encoded>&lt;p&gt;흔하게 시장 지배 기업이 신규 진입자를 제거하기 위해서 사용하는 전략 중에 하나가 &lt;a href=&quot;http://rigvedawiki.net/r1/wiki.php/%EC%B9%98%ED%82%A8%20%EA%B2%8C%EC%9E%84&quot;&gt;치킨 게임&lt;/a&gt;입니다. 가격을 내려서 출혈 경쟁을 하고 경쟁자가 사라지면 독점의 이익을 누리겠다는 것이죠. 그래서들 보.통.은. 누군가 새롭게 등장만 하면 와~ 치킨 게임으로 쟤들 죽여버리자, 라고들 단순하게 생각을 많이 하는데요. 이게 치킨 게임이 통하는 분야가 있고 안 통하는 분야가 있습니다. 그러니 스킬을 시전하기 전에는 충분히 생각을 잘 해보는 것이 중요합니다. 자승자박 할 수가 있거든요.&lt;/p&gt;
&lt;p&gt;흔한 세탁소를 한다고 생각해봅시다. 복잡한 세탁이 아닌 정말 단순한 원룸 총각의 각종 빨래물을 세탁하는 세탁소입니다. 이 경우에 기존에 시장을 장악하고 있는 세탁소에서는 신규 세탁소를 가격으로 제압할 수 있습니다. 왜일까요? 여기에는 서비스 품질이 크게 중요한 요소가 아니기 때문입니다. 이놈이나 저놈이나 비슷비슷하기 때문에 가격이 싸면 장땡인거죠. 그리고 주요 고객층인 원룸 총각은 세탁물을 조금 더 반짝반짝하게 하는데 더 많은 비용을 지불할 의사가 없습니다. 자신이 하기엔 귀찮고 누군가 대신 해준다면 가장 싼데가 장땡이라고 생각하기 때문에 이런 전략이 통할 수가 있습니다.&lt;/p&gt;
&lt;p&gt;반대의 경우를 생각해 봅시다. 우리 동네에 베스킨라빈스 알스크림 가게가 새로 들어왔습니다. 기존에 마트를 하던 사장님께서 뿔났습니다. 알스크림 가격 50% 할인. 베스킨라빈스 망할때까지. 이랬습니다. 통했을까요? 아마 50% 할인한 사장님만 죽어났을 겁니다. 왜일까요? 본질적으로 차이가 나기 때문입니다. 베스킨라빈스와 죠스바 사이에는 가격으로 메울수 없는 본질적인 차이가 있기 때문이죠. 가격이 10배나 비싸지만 조금 더 맛있는 알스크림을 먹고 싶은 사람들은 그 가격을 지불하고 베스킨라빈스 알스크림을 사먹을 의사가 있기 때문에 여기엔 치킨 게임이 통할 수가 없는 겁니다.&lt;/p&gt;
&lt;p&gt;이론적으로 맛있는 알스크림을 먹기 위해 충분한 비용을 지불할 의사가 있는 고객으로부터 알스크림 가게를 유지하기 위한 비용 이상만 수익을 창출할 수 있다면 상대방이 가격을 0으로 만든다고 하더라도 가게를 영.원.히. 운영할 수 있습니다. 반대로 50% 할인 정책을 내세운 마트 사장님 입장에서는 가격을 0으로 내린다고 하더라도 베스킨라빈스 고객은 영원히 죠스바를 사먹으로 가게에 오는 일은 없을 겁니다. 그러니 베스킨라빈스 고객을 유치할 순 없고, 기존 고객에게 가격만 내리는 꼴이 됐으니 손해는 결국 마트 사장님만 보게 되는 셈이죠.&lt;/p&gt;
&lt;p&gt;자본주의 사회에서 가격은 가장 강력한 무기입니다.&lt;/p&gt;
&lt;p&gt;하지만 가장 강력한 무기라고 해서 그게 또 전부라는 말은 아닌거죠.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;이건 좀 다르긴 한데, 이야기를 조금 더 확장하면 동일한 내용이 채용 시장에서도 통용됩니다. 보통의 입사 지원자들은 자신의 연봉을 낮게 부르는 것이 가장 강력한 무기라고 생각합니다. 하지만 이 또한 앞선 치킨 게임과 마찬가지로 통용되는 분야가 있고, 아닌 분야가 있는 것이죠. 실질적으로 개인이 생산할 수 있는 부가가치가 뻥튀기 될 수 있는 시장일수록 사실 연봉과 같은 가격은 중요한 요소가 되지 않습니다. 반대로 세탁소같은 구조의 분야에서 일하면서 자신의 연봉을 고고하게 책정하고 있다면 그 또한 경쟁력이 없는 셈이겠죠. 중요한 요소는 여러분이 하려고 하는 일이 부가가치 뻥튀기가 되는 분야(중력에 자유로운 직업)인지 아닌지가 중요한 요소라는 점이죠.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[광고: 애플, 우리의 서명]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11651</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11651</guid><pubDate>Mon, 15 Jul 2013 23:59:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;초큼 멋진 애플의 이미지 광고&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그렇습니다.&lt;/p&gt;
&lt;p&gt;중요한 건 바로 제품이 주는 경험.&lt;/p&gt;
&lt;p&gt;사람들이 어떻게 느낄까?&lt;/p&gt;
&lt;p&gt;삶이 더 좋아질까?&lt;/p&gt;
&lt;p&gt;존재할 만한 이유가 있는걸까?&lt;/p&gt;
&lt;p&gt;단 몇개의 위대한 것을 얻기 위해&lt;/p&gt;
&lt;p&gt;그 몇 배의 시간동안 우리는 노력합니다.&lt;/p&gt;
&lt;p&gt;우리의 손길이 닿는 모든 아이디어가 사람들의 삶에 닿을 수 있을 때까지&lt;/p&gt;
&lt;p&gt;당신은 무심코 지나칠 수도 있겠지만 언제나 느낄 것입니다.&lt;/p&gt;
&lt;p&gt;이것이 우리의 서명&lt;/p&gt;
&lt;p&gt;그리고 이것은 우리의 전부입니다.&lt;/p&gt;
&lt;p&gt;– 애플, 우리의 서명&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 난독화는 만병통치약인가요?]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11516</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11516</guid><pubDate>Mon, 15 Jul 2013 23:59:04 GMT</pubDate><content:encoded>&lt;p&gt;“난독화”란 용어가 보안 업계에 들불처럼 퍼지고 있습니다. 이 단어를 누가 처음 꺼냈는지는 모르겠지만 요즘은 마치 이 녀석을 빼고는 보안을 말할 수 없다는 분위기가 돼 가는 것 같아서 안타깝기 그지 없는 실정입니다. 그 가운데는 너무 많은 약장수들이 있는 것도 한 몫 하는 것 같습니다. 할머니들을 모아놓고 약을 파는 약장수나 컴퓨터를 사용하는 업계 전반의 공포심을 상대로 장난치는 그들이나 본질적으로 다른 점은 없지 않나라는 생각이 듭니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_난독화는_만병통치약인가요.md_0.png&apos; data-alt=&apos;약장수가 너무 많아요. UPX 들고 와서 난독화라고 팔기 부끄럽지 않나요?&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 409px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4ac858a23e13f1053e9736130fe90d0a/ff023/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAC/ElEQVR42j1Ry27bRhTlH/YHmmVRoOi2XaZAkTbJOinSOkEKtEUS1U5kPaxYokRTkSmKskjOkMMZkuJDfIiUaD5kyXbTXUdG4cFd3Jl7zr33nGHq9Q+HR7Xa4dvOSfPv2uH7Rr03YOv1erPVaLXbtXdvfv/zjx7b/XBcb7Wb7VazVns3OBve3t6UZckYBmodt9/+dcj3R4PesNvhRmdir8Nx7LDf47sn/dOTwYgXz4cSx34anPLdzkAYTaNFkixXTJFXb35hXz5p/fZz4+Bx89ef6i8evX/41cF3Xz57+PWrl09br540nv1w9OLHo4PHDQp79O3r7x88/+aLp0ev+0ye52Nudno8PDsRuI/isCtpM1v6pE14OGJl/uOE6wgirwLJVERDEfGEB8JAOe/JFnKZTVV5jqPMZAcT08QmxmGwCH0/TZfVpjARfTHcub3ZVjefr69vt7efb/75dx+76y1DdbumiwGxkU0gXswDz/YX9sKz/MAJCTQxwLQUU5Fheh/LIFmvMqYqS1lQJE4a98eTs4mpmqZqYdkM7MhF7pgVJW6iSXpoR7G7jJ3/I7CiNFztyXAC5XNlyk8pWR2r6AIBAbjEdwxHYAWJnwrsOZgAfYaACPULZMyQDeereL0n062QigwVazMt9KIiK/N1cZnmkR8hGcELzTGdOZ5jSAgklm7TfGEHl+ucqarKJha4UAxg6EAjyEjSNA6jNE2z9Rqpug6g53hX26vdzW57vdvuaHZFr2VV3k3GliZrRDOJhvcJMjG8MymIDdUgOtEVLfDCJEqWUZKtLrNVlqVZfpkzZVFYmkXFINkgClZEsLCCVbhOg5WHPSABDE3quSzKEi9RR2IviZw4nEd7zfSfiY6BqulANzTDsZ2yKGnXqqzSeHknBBNELHNuajjwA4ov8pyOpLEnU4Q8U4GiAgBd16UuFEWx2WySKFZlBUGdro0QUqayMlWyLKOA8u4wm7KivVUFQhVCSvb9e/J+MtRpFWsYGQaUwTJe3jPLsvwPb8XkCcD0HkoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;약장수가 너무 많아요. UPX 들고 와서 난독화라고 팔기 부끄럽지 않나요?&apos; title=&apos;&apos; src=&apos;/static/4ac858a23e13f1053e9736130fe90d0a/ff023/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png&apos; srcset=&apos;/static/4ac858a23e13f1053e9736130fe90d0a/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png 190w,
/static/4ac858a23e13f1053e9736130fe90d0a/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png 380w,
/static/4ac858a23e13f1053e9736130fe90d0a/ff023/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_0.png 409w&apos; sizes=&apos;(max-width: 409px) 100vw, 409px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;약장수가 너무 많아요. UPX 들고 와서 난독화라고 팔기 부끄럽지 않나요?&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;약장수들은 항상 그렇습니다. 애꾸눈이예요. 무슨 이야기냐구요? 한쪽만 본다는 것이죠. 문제의 본질을 총체적으로 보지 않고 지엽적인 부분만 집중해서 봅니다. 그리곤 그 지엽적인 부분을 전체 문제와 동일시 하는 과정을 거치죠. 결국 그 지엽적인 문제만 해결하는 방법을 가지고 와서 원래 문제를 다 해결할 수 있다고 광고를 합니다. 잘 아시겠지만 보안에서는 말이죠. 완벽이란 없습니다. 그러니 만병통치약도 없지요. 여러분에게 누군가 찾아와서 다 막습니다, 완벽합니다, 이거 하나로 모든 걸 차단할 수 있는 완벽한 솔루션입니다, 그런 이야기를 한다면 일단 의심하고 보는게 맞습니다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;난독화란 기술은 크게 폴리모픽과 메타모픽이라는 테크닉에 기반해서 구현 됩니다. 두 가지 기술의 차이는 아래 글에 상세하게 나와 있습니다. 여러분이 일단 난독화의 진실을 제대로 이해하려면 이 두가지 기술의 차이를 정확하게 하는 게 중요합니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;변이(mutation)는 바이러스 제작자에게는 참 오래된 화두다. 바이러스 제작자들은 백신을 피하기 위해서 바이러스의 다양한 부분들이 변형되도록 연구했다. 이름을 바꾸었고, 내부에서 사용하는 문자열을 변경했다. 그리고 최근에는 백신의 감시를 피하기 위해서 바이러스 코드를 직접 변형하는 기법들을 사용한다. 변이는 바이러스의 출발점부터 지금까지 존재하는 가장 근본적이면서도 가장 강력한 기술이다. 이렇게 음지에서 연구된 ‘변이’라는 기법이 요즘은 난독화라는 이름으로 속속 바이러스가 아닌 일반 프로그램을 보호하는 용도로도 사용되고 있다. 이런 현상을 보면 정말 극과 극은 통한다는 말이 실감나기도 한다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;프로그램 변형 기법을 설명할 때 흔히 등장하는 용어로 메타모픽(metamorphic)과 폴리모픽(polymorphic)이 있다. 이 둘은 모두 morphic이란 어미에서 볼 수 있듯이 원본 프로그램을 변형시켜 새로운 ‘변이’를 만들어내는 방법을 의미한다. 용어 자체가 워낙 비슷하게 생긴 까닭에 용어의 비슷함만큼이나 그 차이가 불분명하게 여기저기 많이 사용되는 경향이 있다. 잠깐 둘의 차이점을 살펴보고 넘어가도록 하자.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;이 두 변형 기법의 가장 근본적인 차이는 원본 회귀 가능성에 있다. 변형 함수를 M, 원본 바이너리를 S, 변형된 바이너리를 D라고 할 때, 이 사이에서는 D = M(S)라는 관계가 성립한다. 여기까지는 메타모픽과 폴리모픽 모두 동일하다. 둘의 차이는 생성된 D에 있다. 만약에 생성된 D로부터 원본 S로 돌아갈 수 있는 역함수 M-1가 존재한다면 이 변형함수 M은 폴리모픽 함수라 하고, 역함수가 존재하지 않는 변형함수라면 메타모픽 함수라 부른다. 즉, 변형된 바이너리에서 원본을 추출하는 것이 가능하다면 폴리모픽, 불가능하다면 메타모픽이란 이야기다. 메타모픽이 폴리모픽보다는 좀 더 상위의 변형 기법임을 알 수 있다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 메타모픽 엔진의 핵심, 코드 교환의 원리, 신영진&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;글에도 나와 있는 것처럼 메타모픽이 변형으로써는 좀 더 상위의 개념입니다. 그런데 시중에 나와 있는 거의 대부분의 난독화 솔루션이라 불리는 것들은 대부분 폴리모픽이란 메커니즘에 기반하고 있는 경우가 많습니다. 이 경우에는 사실 upx와 크게 차이가 없습니다. 패커죠. 메모리 상에서 원본이 드러나기 때문입니다. 물론 그보다 더 조악한 수준의 심벌을 숨겨주는 프로그램을 난독화라고 파는 경우도 많이 있습니다.&lt;/p&gt;
&lt;p&gt;반면 메타모픽 쯤 되면 사실 해커들이 말하는 어레이 몇 개 찾아가지고서는 공략하기 힘든 수준이 됩니다. 하지만 PC 기반의 시중에 출시되어 있는 난독화 솔루션 중에서도 메타모픽이란 기술에 근간을 둔 제품은 거의 없습니다. 제품엔 메타모픽이라고 그럴싸하게 적어놓고 있지만 그렇지 않은 경우가 많습니다. 물론 거기에도 속깊은 사정이 있답니다. 그건 조금 있다가 살펴보기로 합시다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;역사를 아는 것이 중요합니다. 과거를 알아야 미래를 예측할 수 있기 때문이지요. PC 기반 플랫폼에서는 난독화라는 기술은 바이러스 제작자들 사이에서 연구가 됐지만 나중에는 일반 프로그램에도 상당수 차용됐습니다. 이렇게 일반 프로그램에서 사용하게 된 계기는 바로 크랙을 막기 위함이었습니다. 크랙이란 건 주로 실행 파일을 리버싱해서 주요 코드를 바꾼 다음 실행하는 방법을 말합니다. 이런 행위를 막기 위해서 난독화가 도입된 것이죠. 실행 파일 단계에서의 정적 분석을 어렵게 만들기 위한 장치였습니다. 여기까지 들으면 요즘 다른 분야에서 벌어지는 시츄에이션과 얼추 비슷하죠?&lt;/p&gt;
&lt;p&gt;네. 그렇게 초기 수준의 난독화를 도입하자 크랙이 사라졌을까요? 천만의 말씀. 만만의 콩떡이죠 ㅋ~ 크랙하는 사람들은 금방 방법을 찾았습니다. 굳이 실행 파일을 패치하지 않고, 메모리 상의 코드를 직접 패치해도 똑같은 결과가 나온다는 걸 알아내 버린것이죠. 그 전 세대에 개발된 난독화라는 기법이 폴리모픽이란 메커니즘에 기반해서 메모리 상에는 원본이 그대로 드러나는 문제점이 있었기 때문이죠. 이게 이제 다음에 벌어질 일입니다. 어레이라고 불리는 것들이 몇 개 돌아다닐 겁니다. 그런 어레이 몇 개만 입수하면 부산시에 사는 초등학생도 크랙을 할 수 있게 되는 것이죠.&lt;/p&gt;
&lt;p&gt;메모리 패칭에 난독화가 속수 무책이자 보안 업계 사람들은 크게 세 가지 길로 나뉘게 됐습니다. 첫번째 사람들은 난독화를 독자적으로 더 깊게 연구한 사람들입니다. 메타모픽 수준으로 진화한 것이죠. 메모리 상에도 원본 코드가 드러나지 않을 뿐더러 실행할 때마다 바뀌기 때문에 해커 입장에서 패치하기가 곤란하게 만든 것입니다. 그 다음으로는 정적 체크를 선택한 사람들이 있습니다. 파일 뿐만 아니라 메모리 상의 코드가 변경됐는지를 체크하는 코드를 삽입한 겁니다. 끝으로는 동적 방어 메커니즘을 무장한 사람들이 나오게 됐습니다. 메모리 보안이라 불리는 기술이죠. 운영체제를 패칭해서 우리 프로그램이 디버깅 당하거나 메모리가 불법적으로 조작되는 행위를 하지 못하도록 방어하는 것을 말합니다.&lt;/p&gt;
&lt;p&gt;어떻게 됐을까요? 누가 가장 성공했을까요? 물론 여기엔 완벽한 방법도 없고, 또 어떤 한가지가 가장 뛰어나지도 않습니다. 모든 방법을 적절하게 잘 버무려 써야겠지요. 그래도 어쨌든 오늘은 난독화 이야기를 하기로 했으니 메타모픽 쪽으로 선회한 사람들에 대해서만 알아보도록 합시다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;메타모픽으로 선회한 사람들은 어떻게 됐을까요? 과연 그들의 생각처럼 어떤 해커도 그들의 코드를 해독하지 못했을까요? 당연히 아니겠지요. 안타깝게도 그들은 해커의 공격을 받기도 전에 스스로 붕괴할 수 밖에 없었습니다. 너무 큰 문제에 봉착해 버렸거든요. 우리의 튜링옹께서 1936년에 증명을 끝내버린 정지 문제였습니다. 정지 문제란 간단히 말하면 프로그램 P가 주어졌을 때 그 프로그램이 정지할지 하지 않을지 판단하는 프로그램은 작성할 수 없다는 것을 의미합니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;계산 복잡도 이론에서 정지문제(停止問題, halting problem)는 판정 문제의 일종으로 다음과 같이 요약할 수 있다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;프로그램을 설명한 것과 처음 입력값이 주어졌을 때, 이 프로그램에 입력값을 넣고 실행한다면 이 프로그램이 계산을 끝내고 멈출지 아니면 영원히 계속 계산할지 판정하라.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;1936년에 앨런 튜링이 모든 가능한 입력값에 대해 정지문제를 풀 수 있는 일반적인 알고리즘 은 존재하지 않는다는 것을 증명했다. 그러므로 ‘정지문제는 튜링 기계에서 판정할 수 없다’고 한다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://ko.wikipedia.org/wiki/%EC%A0%95%EC%A7%80_%EB%AC%B8%EC%A0%9C&quot;&gt;http://ko.wikipedia.org/wiki/%EC%A0%95%EC%A7%80_%EB%AC%B8%EC%A0%9C&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이게 왜 메타모픽이랑 연관이 될지 궁금할 겁니다. 바로 메타모픽의 얼굴이 너무 많다는 겁니다. 실제로 진짜 메타모픽 엔진은 실행할 때마다 모든 코드가 예측할 수 없는 순서로 재배열, 재구조화되는 과정을 거칩니다. 그런 모든 변종이 정상적으로 동작한다는 것을 보장할 수가 없습니다. 즉, 메타모픽을 적용한 프로그램이 어떤 고객의 PC에서 멈추더라도 그건 전혀 이상한 현상이 아니라는 것이지요. 왜냐하면 그 변종에 대해서는 누구도 검증을 하지 못했거든요. 메타모픽 엔진은 본질적으로 안전성을 검증할 수가 없습니다.&lt;/p&gt;
&lt;p&gt;이쯤에서 JIT 컴파일을 반론으로 들고 나오는 사람들이 있습니다. JIT 컴파일은 메타모픽이랑은 완전 다른 기술입니다. JIT 컴파일은 서로 다른 CPU의 종류에 대해서만 한정적으로 서로 다른 컴파일 결과를 만들어내는 기술이지 동일한 CPU에서 매번 다른 코드를 만들어내는 기술이 아닙니다. 어쨌든, 최고의 메타모픽 엔진은 튜링옹께서 증명하셨던 것처럼 누구도 그것의 안정성에 대해서는 검증할 방법이 없습니다.&lt;/p&gt;
&lt;p&gt;물론 정지 문제만 있었던 것이 아닙니다. 다른 문제도 있었습니다. 바로 자신의 얼굴이 너무 많아서 자신 조차도 이게 정상인지 아닌지를 판단할 방법이 없어진다는 겁니다. 코드가 매번 바뀌기 때문에 진짜 메타모픽 엔진은 변형된 코드에 대해서 예측할 수 없습니다. 따라서 현재 실행되는 코드만 보고 나 스스로 이 코드가 원래 나의 코드인지 아니면 해커가 변형한 코드인지를 분간해 낼 방법이 없어진다는 점입니다. 최고의 메타모픽 엔진으로 보호된 프로그램은 아주 사소한 프로그램 변조도 본질적으로 그 공격을 판단할 방법이 없어지는 묘한 현상이 발생합니다. 자가당착적인 구조죠. 성형에 중독된 여성들이 진짜 자기 얼굴이 어땠는지 까먹는 것과 비슷한 문제라고 보셔도 되겠습니다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://github.int13h.com/webgldoom/doom.html#e1m1&quot;&gt;HTML5를 기점으로 이제 자바스크립트로 둠을 만드는 세상이 도래했습니다.&lt;/a&gt; 요즘 자바스크립트는 더 이상 예전의 자바스크립트가 아니지요. 하지만 잘 알겠지만 자바스크립트는 소스 코드가 브라우저에 그대로 다운로드 됩니다. 게임 입장에서는 쥐약입니다. 핵심 코드들이 모두 날 것 그대로 노출된다는 것이기 때문이지요. 그래서 브라우저 게임 대부분은 지금까지는 서버에서 모든 연산이 가능한 방식의 게임 밖에는 출시되고 있지 않습니다. 클라이언트 연산이 들어가는 게임이 나온다면 정말 쉽게 해킹이 가능할 것이기 때문입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How do I protect my content from pirates?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;The “modern” open-source-based answer to this is, of course, that you shouldn’t: instead, you should architect your application or business so that the value is generated by the service you offer, not in the content delivered to the browser. However, in some cases that may well be unduly idealistic. Your best bet for under those circumstances is to look into JavaScript obfuscators.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;http://learningwebgl.com/cookbook/index.php/WebGL:_Frequently_Asked_Questions#How_do_I_protect_my_content_from_pirates.3F&quot;&gt;http://learningwebgl.com/cookbook/index.php/WebGL:_Frequently_Asked_Questions#How_do_I_protect_my_content_from_pirates.3F&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;WebGL FAQ 페이지에서 발췌한 내용입니다. 컨텐츠를 어떻게 보호할 수 있느냐는 질문입니다. 답은 아이러니하게도 난독화를 적용하는게 현실적인 수준이라는 대답입니다. 요즘 난독화가 자주 등장하는 가장 극적인 이유를 보여주는 한 장면입니다. 개발을 더 빠르고, 더 쉽게 할 수 있는 생산성이 높아지는 도구들을 잔뜩 만들었는데, 결국 사람들이 쉽게 만든다는 건 해커도 쉽게 리버싱 할 수 있는 환경을 만들어 버린 겁니다. 리플렉션 우왕 굳. 이랬는데 그 리플렉션에 사용되는 메타 데이터로 해커도 같이 꿀빨고 있었던 셈이죠.&lt;/p&gt;
&lt;p&gt;어쨌든 계속 이야기 했지만 이 싸움의 끝에는 안타깝게도 난독화가 위치할 수는 없습니다. 폴리모픽은 결국은 원본을 구할 수 있다는 말이고, 메타모픽은 여러가지 문제가 있기 때문입니다. 자바스크립트 난독화 도구도 당연히 난독화 이전 상태로 돌려놓을 수 있습니다. 변수명/함수명은 보기 힘들어지지 않냐구요? 어셈블리 코드도 C 코드 보듯이 보는 친구들입니다. 그런 문자열 몇 개 뭉개졌다고 해독하기 힘들다고 생각하는 건 너무 순진한 생각입니다.&lt;/p&gt;
&lt;p&gt;어떻게 해야 할까요? 네. 맞습니다. 사람이 이해하기 쉽도록 만든 장치를 사용해서 다시 이해하기 어렵게 만드는 우스꽝스러운 일을 해야 합니다. 이해하기 쉽게 만든 장치들을 사용해서 이해하기 어렵게 만든 내용을 해석하는 해석기를 만들어야 한다는 것이다. 자바스크립트 위에 새로운 해석기 레이어를 올려야 한다는 겁니다. 당연한 이야기겠지만 그 해석기가 해석하는 코드는 해커가 이해하기 어려운 수준으로 만들어야 겠지요. 결국은 VM 같은 구조가 되는 겁니다. 그러면 그 해석기 코드는 해커가 이해하기는 힘들기 때문에 기존과 동일한 수준, 내지는 만들기에 따라서는 더 높은 수준으로 분석하기가 힘들게 만들 수 있습니다. 그리고 자바스크립트 상에서 구동되는 코드 체계는 그 해석기가 해석하는 코드가 반드시 있어야 동작하도록 만들어 놓아야 하는 겁니다.&lt;/p&gt;
&lt;p&gt;얘가 도대체 무슨 소리를 하는 거냐고 의아해 하실 거예요. 또 좀 아는 사람들은 그게 말이냐 돼냐? 가능한 소리를 해야지, 라고들 합니다. 그럼 이제 작품 감상을 하러갈 시간이 된 것 같습니다. &lt;a href=&quot;http://bellard.org/jslinux/&quot;&gt;직접 보면 웃음 밖에는 안 나오는 프랑스 컴퓨터 사이언스계의 우주 신, Fabrice Bellard옹의 작품입니다.&lt;/a&gt; 이제 약을 팔아도 이정도는 만들어 놓고 약을 팔도록 합시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_난독화는_만병통치약인가요.md_1.png&apos; data-alt=&apos;어서와. 이런 솔루션은 처음이지?&lt;br&gt;&lt;br&gt;애꾸눈에게 여러분의 보안을 맡기진 마세요.&lt;br&gt;&lt;br&gt;적어도 다양한 양념을 적절히 버무려 쓸 줄 아는 사람들에게 맡기세요.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a30add875aa83d9ebb3c954c66f9a0c7/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABi0lEQVR42k1SWXaDMAz0MUigPyXBmCWQsNhA0qbt/c801cihrx96o3UkSzaXywXX6xV93yt2XYdhGBTpK8sSxbmALSyKolCbUlUV8vxdsXJOY5WrYEIIWNcV3ntQ/3h+4vn1xDxPmKZJm0yid32HpmnQ1A1c5eBKp2TtpVW01qKua5hlWZVoWRYhmQUDgo/2/b5h2zZt8HjctfG6bnEAyQ1h0TzmrOuifnO73eCFcJYJxzFOFYLXAk7tZ49BcpjHht8/39qANcyNje9aw1cZPonCZBaP44hJhGSDIJN8mCOhj0UsHoVsk4lISp315DGt7KVtW/RyBOrcRelKRVuKbuMxKNzRrvMw7nUMHmw/lmmaVpil+zSLwyJNU2RZhvR4RJqlOArSfhPJJPYXf+mUJEmQHBJFY4WVncnOK/Zdr7aTyxH1kvICfq9OhD7q9DP/dDpp051cCfUvvRKIZ/l3JHEuktFXvJ6e57nEz7oS2iT7L4aBSHLWKes67nEXp7uxOBwOKiza9d3+T/gLKXougP0LVuAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;어서와. 이런 솔루션은 처음이지?&lt;br&gt;&lt;br&gt;애꾸눈에게 여러분의 보안을 맡기진 마세요.&lt;br&gt;&lt;br&gt;적어도 다양한 양념을 적절히 버무려 쓸 줄 아는 사람들에게 맡기세요.&apos; title=&apos;&apos; src=&apos;/static/a30add875aa83d9ebb3c954c66f9a0c7/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png&apos; srcset=&apos;/static/a30add875aa83d9ebb3c954c66f9a0c7/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png 190w,
/static/a30add875aa83d9ebb3c954c66f9a0c7/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png 380w,
/static/a30add875aa83d9ebb3c954c66f9a0c7/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%82%9C%EB%8F%85%ED%99%94%EB%8A%94_%EB%A7%8C%EB%B3%91%ED%86%B5%EC%B9%98%EC%95%BD%EC%9D%B8%EA%B0%80%EC%9A%94.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;어서와. 이런 솔루션은 처음이지?&lt;br&gt;&lt;br&gt;애꾸눈에게 여러분의 보안을 맡기진 마세요.&lt;br&gt;&lt;br&gt;적어도 다양한 양념을 적절히 버무려 쓸 줄 아는 사람들에게 맡기세요.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[게임가드 170 오류 코드 해결 방법]]></title><description><![CDATA[gg170
게임가드 170 오류 코드 화면 게임 하시면서 이런 화면을 많이 보셨을 겁니다. 게임가드 구동에 실패해서 발생하는 게임가드 17…]]></description><link>https://jiniya.net/wp/archives/11608</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11608</guid><pubDate>Tue, 09 Jul 2013 23:59:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2013/07/gg170.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2013/07/gg170.png&quot; alt=&quot;gg170&quot;&gt;&lt;/a&gt;
&lt;strong&gt;게임가드 170 오류 코드 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;게임 하시면서 이런 화면을 많이 보셨을 겁니다. 게임가드 구동에 실패해서 발생하는 게임가드 170 오류 코드입니다. 오류 코드가 발생하면 상기 화면과 같이 친절한 메시지 상자를 출력해서 사용자에게 오류가 발생했음을 알려주고 있습니다. &lt;a href=&quot;http://gameguard.co.kr/list01.html&quot;&gt;그런데 안타깝게도 공식 FAQ 페이지에도 관련 오류 코드에 대한 설명이 나와 있지 않아서 전문적인 지식이 없는 분들은 문제점을 해결하기가 힘드실 것 같아요.&lt;/a&gt; 저도 오늘 게임을 하다가 이 오류 코드를 만났는데요. 검색을 해보니 저 외에도 수많은 분들이 이 오류 코드 때문에 고생하시는 것 같아서 해결 방법을 포스팅해 봅니다.&lt;/p&gt;
&lt;p&gt;우선 해당 오류 코드는 게임가드 서비스나 드라이버가 구동이 실패했을 때 발생하는 것으로 추정됩니다. 실패하는 이유는 여러가지가 있을 수 있는데요. 보통은 게임에 관리자 권한이 없거나 백신에서 해당 권한을 차단하는 경우가 있습니다.&lt;/p&gt;
&lt;p&gt;백신을 사용하시는 경우에는 해당 백신을 종료하신 다음에 게임을 실행해 보시구요. 그래서 실행된다면 백신 때문인 겁니다. 그럴 때에는 각자 사용하는 백신 옵션을 조정해서 게임가드에 관련 권한이 부여되도록 설정해 주시면 됩니다.&lt;/p&gt;
&lt;p&gt;다른 주요한 원인은 실행되는 게임에 관리자 권한이 없어서 발생하는 경우입니다. 윈도우 Vista 부터 UAC 라는 것이 생겼습니다. 관리자 권한을 요청하지 않으면 무조건 일반 권한으로 프로그램을 실행시키는 기능입니다. 이런 좋은 운영체제를 사용하면서 보안성을 취약하게 만들기 위해서 일부러 UAC 기능을 꺼두었다면 문제가 되지 않는데, 만약 켜져 있다면 게임이 별도로 관리자 권한을 요청하지 않으면 게임가드도 관리자 권한을 얻지 못해서 170 오류 코드가 발생하게 됩니다. 통상적으로 이런 경우에 게임사에 요청해서 게임 실행파일에 관리자 권한을 요청하는 매니페스트를 추가해 두면 문제가 발생하지 않는데요. 제가 실행했던 반 온라인의 경우에는 게임 실행 파일에 매니페스트가 없어서 UAC를 끄기 전까지는 170 오류 코드를 피할 수가 없었습니다.&lt;/p&gt;
&lt;p&gt;이렇게 매니페스트가 없어서 관리자 권한을 못 받는 게임인 경우에는 임시 방편으로 해당 게임을 항상 관리자 권한으로 실행하도록 옵션을 설정해 주시면 됩니다. 게임 실행 파일이 있는 폴더로 가셔서 게임 실행 파일에 우클릭해서 설정 메뉴에 보시면 아래와 같이 항상 관리자 권한으로 실행하도록 만들어주는 옵션이 있습니다. 이 옵션을 체크한 다음 게임을 실행하시면 됩니다. 그러면 게임 실행 시에 UAC 경고창이 뜨게 됩니다. YES 눌러주면 게임가드가 관리자 권한을 얻을 수 있고, 여러분도 게임을 할 수 있게 될 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2013/07/prop.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2013/07/prop.png&quot; alt=&quot;prop&quot;&gt;&lt;/a&gt;
&lt;strong&gt;게임 클라이언트 프로그램 등록 정보 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; 0
 4&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[마가 끼다…]]></title><description><![CDATA[리비전 그래프… 27/37, 72.97% 성공… 마가 낀게 틀림없다. (<-- 대부분의 쪼다 프로그래머들이 하는 변명 ㅠㅜ) 올들어 총 3…]]></description><link>https://jiniya.net/wp/archives/11218</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11218</guid><pubDate>Wed, 26 Jun 2013 23:59:02 GMT</pubDate><content:encoded>&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 281px; margin-bottom: 16px;&apos; data-url=&apos;./마가_끼다.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/583f907cd600d58fbfbf94edb19cebac/fa392/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 177.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAFR0lEQVR42pVVWW8TVxjNP+tTH9rHqhXioUKiLaICIQIlLCFm6wKkShAQqVGjRC0CFZBKqGhpK0ClLdBs2GIJSRw7OI7j8TIztmff7umZJeBELMlIVzP3zp1zz/d953zTIYTAeoYf+Aiv68UL2HlnE3aOb8Id6ddoLRDxu3Bfx3oBhQgg+JFtLKOYvY9KcQJ6qwy3JMN5XoKbL8FTWxsBjEd4lSsKpFqLlHxMn9iKf7a9i8efvQP11uWNAQZBDKjLOlqSCeE6MO3jWFr+FDV1K2znj/UDBgw5jLnoljHWmELGeYKCVoJv8QDdgOfGeezYaFFu5UfQdfV97L35HiYq1+GZIygUutBspmBZ9zZeFNFaRj1zGwqHpxS49gyK/BdM4wF8X0oAgyAevo8X8/B5ZT0cbUWxbQe2F4SCgaEPorzcTYb7yPBuAgisHmvX2ubx5aOlnUddPoiavA2t1iWuGSyaRsBwY7EIMT0NMTkJIUkQCwsQExMQ6TTE7CxErRatBYYOP4rAg6ulUc7/BmXpNhyt8OLgGPDm7xBn+iFGRyHGxiAyGYihIYjBQYiRYQSj14DvhyBl0rh09WfkczkYxT7MPfgEubHNUIo/xo5h4Tqi/ISgug5hUVuGEc/De8i2Xo9DlusIs2a4Epr6FFTta9RZWdMdguP+G+UjLNzqKodAJoFUGUJrIrD0eN7ks94EGh6gXUM9vxlS9nOYlW95sJf4OFjj5bCq4YuHDHe2ACyWgTxzm5uHKITz50BBgp+/ADm9BdWJLTBmehBM3uehelsOVwCDBHD+b2jNbih6Hxr6Wa5VYCnPUc79B13RuGMcUr0H5VonNG8AQS7LaF4JmOQy+4TVzEBRjqFY2AGldhK6OgGzMYbCfAr16jEsLnbCtZ/CQzmOQNPeBDhP5ZoswDgc+xeoSj88b4rGT0NVf6Cob3B+N5JOlLt8fjVgEDgst42ALg8iwGxc7Wj7HJmm6ITdqFQO0FpqDII2AmsBxYr8V6rcBijEDBpqCrVqNy12moC1cBuH93pAy7pCHw6j1fwOts9w5xcJGGuR6GT4JdkdRaPRB9dTXkrkdYCG0Y9S6QDkehcsL0PAJcpAi5ggmIUqH4FUPoyGcgq+R5GHbTFUxIrM6Jo1DAdQraTIsAdO8AjIEdBOGCJHV3yDunoCmnmGPVFNmkSbEULftwOa5mmUy3uZq92wBRlm2AweU9w5ijp7A42pD1Ef+4D3j+HN0OfzDDE7BzE3F7ObmmJEZjvDfjLcj2ajC44zCYorDtlibPYjNKv7UCt1ollLwecfT1huXDTLioEcZ1UjJsMzkKQDTPp+amwykYWfhJxFgw2gWjvE+0l4gfIy5PZe2Q6o6+exXOphNQ+z4z6M26egNiN5zEGWj/HAFN/3UtDyqkbwqkHA01gq7uWHnWQ4nmjSS45/hjqrH+Y4tKLHKr8V0HV/IthZWOZ56myav0kV884CCn6ZVc3x5zMItTFA612ko5qJsN8AaNsjqFZPQdd6qcM0vksfx54/P8JXk92wgmeUUx9q9SO8n6RT5LcDmuYohT1E4w+TxRzg8IW2gNbSFbQa17G8PAzDmIHrVsnQTQDFmwBP0Fo7WOXtBLwXNQiP1dXM3czdNnabL8hs6a25awM8x25CazUOU4fjkbWAx1GXqVaP0ufnyE7aAKDRi1ptPz/eBdOc5WeTfD5Ibx9iGvriLrSB0RH1QjZLy5IIfJkgo6hIF8l2Meoocd6C9QPGD2FAMnveHhZhO224i2E+TcL0N8YwPj38VGU1B+iK3qT35dedt3bA/wHMeZf1oIHcEwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 0&apos; title=&apos;&apos; src=&apos;/static/583f907cd600d58fbfbf94edb19cebac/fa392/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_0.png&apos; srcset=&apos;/static/583f907cd600d58fbfbf94edb19cebac/08678/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_0.png 190w,
/static/583f907cd600d58fbfbf94edb19cebac/fa392/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_0.png 281w&apos; sizes=&apos;(max-width: 281px) 100vw, 281px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;리비전 그래프… 27/37, 72.97% 성공…&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;마가 낀게 틀림없다. (&amp;#x3C;-- 대부분의 쪼다 프로그래머들이 하는 변명 ㅠㅜ) 올들어 총 37번의 엔진 릴리즈가 있었다. 그림은 그 릴리즈 때마다 태그를 붙여둔 리비전 그래프다. 그런데 우습게도 이 중에 거의 삼분지 일에 해당하는 10번의 릴리즈가 5월 중순부터 5월 말까지 발생했고, 안타깝게도 그 릴리즈에 모두 소소한 문제가 있었다. 물론 지원팀 덕분에 그 파급 효과가 고객에게 미치지는 않았다. 단지 내부적으로 엄청난 피로도가 누적되는 과정이 있었을 뿐이다.&lt;/p&gt;
&lt;p&gt;너무 어처구니가 없어서 릴리즈 노트를 보면서 무엇이 이런 참담한 결과를 가져왔나 꼼꼼히 살펴 보았다. 그 복기 과정을 통해서 난 반드시 기억해야 할 아주 중요한 교훈 두 가지를 얻었는데 다음과 같은 것이었다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;버그 수정과 기능 추가를 한 릴리즈에 묶는 행위가 재앙을 만든 일등 공신이었다. 난 항상 별 생각 없이 기능 추가와 버그 수정이 동시에 일어난 빌드를 릴리즈 했는데 이게 말 그대로 헬 게이트를 여는 원인이 돼 버렸다. 이게 잘 될 때는 기능 추가도 되고 버그 수정도 되는 꿀빠는 일이지만 안 될때는 말 그대로 버그 수정을 했는데 신규로 추가된 기능에서 버그가 또 새롭게 잉태돼서 계속 쓰지도 못하는 코드가 릴리즈 돼 버리는 문제가 있었던 것이다. 버그 수정과 기능 추가를 분리해서 빌드 했다면 적어도 중간에 하나씩은 쓸 수 있는 빌드가 생겼을 것이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;코딩 허세. 코딩 허세. 허세가 문제였다. 10번의 실패한 릴리즈 중에서 8번이 동일한 로직 변경 과정에서 발생했다. 린스타트업과 같은 방식으로 검증을 통해서 차근차근 접근할 수도 있는 부분이었는데 내 허세가 한 번에 완성할 수 있다는 생각을 만든 것이다. 그도 그럴것이 실제로는 아주 간단한 조건을 변경하는 것이었기에 더 쉽게 생각됐다. 하지만 그 사소한 조건의 변화가 미칠 수 있는 파급 효과는 실로 어마어마했다. 내가 무엇을 상상하던 그것보다 훨씬 더 컸다. 그 결과 릴리즈를 8번이나 날려 먹고서야 제대로 만들 수 있었다. 검증 단계를 통해서 접근 했다면 시간은 더 걸리더라도 지원팀에서 검증 작업에 이토록 애를 먹지는 않았을 것이다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 과정 중에서도 내가 잘한 일이 하나 있다. 바로 릴리즈에 개입하지 않았다는 점이다. 회사 초기에는 내가 릴리즈를 할 때도 있었고, 지원팀에서 릴리즈를 할 때에도 내가 개입하는 경우가 많았는데 언제부턴가 본능적으로 내가 개입하지 않아야 문제가 덜 발생한다는 사실을 알게 되었다. 그래서 이런 문제점들이 고객들에겐 표출되지 않을 수 있었다.&lt;/p&gt;
&lt;p&gt;물론 본질적으로 모든 문제는 내가 집중해서 제대로 일하지 않았기 때문에 발생한 일들이다. 그 모든 잘못의 근본적인 원인의 면면을 살펴보면 결국 내가 제대로 프로그램을 만들었으면 애초에 하나도 발생하지 않았을 일들이다. 그래서 더 가슴 아프다.&lt;/p&gt;
&lt;p&gt;자원은 항상 부족하다. 정신 차리고 제대로 일하는 수 밖에는 없다. 작은 업체가 살아남는 방법은 뛰면서 쏘는 방법 밖에는 없으니까 말이다.&lt;/p&gt;
&lt;p&gt;덧) 포스의 어두운 면과 밝은 면은 항상 공존하는 것처럼 이런 참담한 결과가 나쁜 점만 있었던 건 아니었다. 테스트 코드가 훨씬 더 많이 필요하다는 인식이 생겼고, 엔진의 릴리즈 현황을 자동으로 추적할 수 있는 훌륭한 백엔드 시스템도 만들어졌다.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 289px; margin-bottom: 16px;&apos; data-url=&apos;./마가_끼다.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/860c9e4558f8cdc84141dd395e2a0c52/3b5c2/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 138.42105263157896%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAIAAADuuAg3AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAFg0lEQVR42kVVV3MaVxTm5+Yhr5lJcRzFlhM7sWTLtowEQhQVmkAg2tLL0pdlYelVwCIQIETv5eYsTiYzdxhg773fOV85yxm28IcCxuQMCUIOq//oQXNqOya248h2RGwnJJpF0Ty6GRLD3SO0orerxGYUQeMIJxe7dWJ8vfqz7uaomjOUk9oF40JTOB9FizjqhuZVJyo7nyu2WslcL5kdJt7l+RvcKkCbBKeSN1JB2X1KV87oI/7rZtHSK1gM6s8XZ/tBl0QrO/h68OO44R4xTo+ZzxSx+7SewC9rWT2axzjZmHo5i9tMPJP2WKP4kKFU3Qen23JG+q4ShCITU99n9N2Gq5LRkzZRIaoatfFRCx+3vWhCcjo1Rxi/VMkOLDou99MLh/nMgfHaD26EshsoG6UbjBP6AhxYk5qzmtYXU9pFP4imJAc4aKQNWuHbX3/+Tnj6+6IX1KmOGiUz8LQehNA0miQUZu0x4KxHBHoOlSoGjBLR+dvBE87ZTslN2496BB1X04QSoZzTwve6xWidQJPI6MkLRa2GYZZ/IP8pSKSVobSi/4TPegEO2kmybuCo5U/4ZY0ChgaRbFCx6IXQkFgy7nxEhSbRbSe4zVgnjx5fUhbKKPsdHM0oDgLFpuS25UM197TjC7nEWfdVjVBXUjoodZq3ZALy8SPebjpqDxY8JbsNnPoS0ty9Hs1iLDKc304iCCULyTuN/HA5CkfDMv7Xl+CTRtXK4/6WyWruGeyMtzduecsNa6mGtR4dQMfuMFQ+JNAiRgWkHssZQqlZP5SMKCddfz5+63eK4NFiHFVJD2YdX4XBwmkllVOxOv93OAzFg9tA9pBbUs0b54MwOKeUvGOKZrRNRv3XfO7LZEjeaDvInLrTcv6PzBoYKp9G4cuqHyzQmk7NDj9bNfug6S4ltVRItuOfHHVxA3HOPNhYwtgATMgu46gXTNWsHqwDC2SAu1wYXyZ5x+SN7Yqtwzi6NQfAgGxq/MRGilejMGfQ8j7XneBKqHD2HGjdW+EwCzujLHqu4uIdWoLP8mrpe8jDY9mSpdRR33U2pQFUTp7WLoYEbj8367jlrNFiOC2kdHaMh1Dm/GRPfvGumNC2K9ZmyRJ0S0ALrfKjiP+qDkTMKU6Ovu01PdWsoZYzJQllLCir5E0R7xW4H/60G07mvUA5pbuVHwJMIaGBtEBFeVoDEnCqOeO16M9S3kSF5DR543WJIWFOiwC2wt1ZipUE9g06voBbolN9korfCrh7xdQd+JIDHYI2ufgtNMPkjIt+aDkIex3CiPdy3g2UEppvcqwGYcJ7CUI2y2awAHDEThLou1212Q2ntayx9+D024V3yo8g0noa3S7pk+OXz00PKLSZU+sxCb1AsJ8ecWARrLELxoSMBKSgAaQX0x7v730fDUhxjIfL3/s1R6SVpxK8chtO7oECjGfVn8CccRh5LDI0BiLThAIagzbgs5o1Hn96YRC/UR//Ijz6aV7Qobo1rj4sUCo6rABddqIG2UkCuyH6PocQxgCsVT8E5S0m0aLvIo1LzGaBwyKg6TvGc95K3427/n7TDWo3YVoA8gbQlnGP9Uwi2AfrB1ziK+Ef3aanGVNi569cBm4IOzVrvtS9Iqvotdsukpztq6WHpO8a8sthS51Tzw+ufEILM3zU9uLW82REsRpFaBt/RN/040rKeFwPXrZzhkbFhmm+fPjrB5dZAJN8d3gW7TfcpP8aBMtQ6noR2wzDUBEZlE2eA9nkHe4U95/861msljNAvGD0gpBsqr6RBNaPBWRg6eEj3ihiq91wrOdNGfJGdf3+Svjm5upvIBIA4PXQe/KjbYo1yTcPAM4a3ixgJjaVFDC5yykF94KwpYT235BuEpDzZS/IQo4j/wCaplGvMFXzjgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 1&apos; title=&apos;&apos; src=&apos;/static/860c9e4558f8cdc84141dd395e2a0c52/3b5c2/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_1.png&apos; srcset=&apos;/static/860c9e4558f8cdc84141dd395e2a0c52/08678/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_1.png 190w,
/static/860c9e4558f8cdc84141dd395e2a0c52/3b5c2/%EB%A7%88%EA%B0%80_%EB%81%BC%EB%8B%A4.md_1.png 289w&apos; sizes=&apos;(max-width: 289px) 100vw, 289px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;언젠간 이런 시스템을 만들 날이 오겠지? ㅇㅇ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;게이머들에게 공정하다는 느낌을 줄 수 있는 그날을 꿈 꿔 본다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;</content:encoded></item><item><title><![CDATA[레거시 코드 활용 전략~]]></title><description><![CDATA[2002년…]]></description><link>https://jiniya.net/wp/archives/11458</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11458</guid><pubDate>Tue, 25 Jun 2013 23:59:01 GMT</pubDate><content:encoded>&lt;p&gt;2002년 3월, 꿈에 그리던 병역특례 회사에 첫 출근을 했다. 따뜻한 봄 날, 직업 프로그래머로써 내 생애 첫 번째 미션이 주어졌다. 사수의 서버 프로그램을 유지 보수하는 일이었다. 나에게 인수인계를 해 준 선임 프로그래머는 그 주에 회사를 그만두었고, 난 계속 죽는 서버 프로그램을 유지 보수 해야 했다. 신입 프로그래머라 실력보다는 패기가 앞섰던 시기였다. 난 지저분해 보이는 프로그램 코드를 처음부터 다시 짜야 한다고 주장했고, 실제로 그렇게 했다. 하지만 안타깝게도 내가 새로 만든 프로그램은 원래 프로그램보다 더 자주 죽었고, 현대적인 UI를 제외하고는 그다지 나아 보이지 않았다. 결과적으로 원래 프로그램을 유지 보수 하는 만큼의 시간을 더 들이고 나서야 새로운 프로그램이 정상 동작하도록 만들 수 있었다.&lt;/p&gt;
&lt;p&gt;이 이야기를 시작한 이유는 거의 대부분의 프로그래머가 2002년의 나와 똑같은 자세로 레거시 코드를 대하기 때문이다. 이 글을 쓰기 전에 주변에 있는 10명 이상의 프로그래머에게 레거시 코드에 대한 생각과 레거시 코드를 다루는 본인만의 노하우가 있는지를 물어보았다. 정말 재미있게도 그 모든 사람이 하나같이 똑같은 이야기를 했다. 새로 만들어야지. 그 중에 한 명은 레거시란 말 자체가 이미 쓸모 없다는 뉘앙스를 내포하고 있지 않냐는 말까지 덧붙였다.&lt;/p&gt;
&lt;p&gt;11년이 흘렀다. 그사이 난 레거시 코드 때문에 고생도 해보았고, 내가 만든 코드를 레거시 코드라고 부르는 사람들과 만나기도 했다. 그 과정 속에서 생각이 조금 바뀌었다. 레거시 코드를 나쁜 것, 버려야 할 것으로 보던 시각에서 점차적으로 힘들지만 함께 해야 하는 것이라 느끼게 된 것이다. 그리고 그렇게 바뀌게 된 배경에는 레거시 코드가 생겨나는 본질적인 구조에 대해서 알게 되었기 때문이었다. 우리에게 지금 절실하게 필요한 것은 레거시 코드를 리팩토링하는 몇 가지 테크니컬한 기법들이 아니라 그것을 바라보는 프레임을 바꾸는 일인지도 모르겠다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;레거시 코드의 탄생&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;레거시 코드란 오래되고 낡아서 손대기 힘든 코드를 의미한다. 그렇다면 도대체 오래되고 낡아서 손대기 힘든 코드는 어떻게 만들어지는 것일까? 단순히 오래됐기 때문일까? 아니다. 오래된 코드임에도 유지 보수하기 쉬운 코드들은 얼마든지 있다. 그렇다면 왜 어려운 것일까? 대부분의 프로그래머들은 레거시 코드가 조악하게 작성돼서 그렇다고 생각하는 경향이 있다. 하지만 이 또한 진실을 아니다. 레거시 코드는 우리가 생각했던 것과는 전혀 다른 경로로 만들어진다. 레거시 코드의 본질적인 측면을 이해하기 위해서는 이 탄생 배경을 이해하는 것이 필수적이다.&lt;/p&gt;
&lt;p&gt;현대적인 프로그램의 코드 양은 이미 상상을 초월하는 수준으로 방대하다. 이러한 많은 코드 중에서는 프로그램의 업데이트와 함께 지속적으로 변경되는 코드들도 있지만 한 번 만들어 놓은 다음에는 변경이 거의 없는 코드들도 있다. 오래된 저장소에서 작업하고 있다면 변경 이력에 관한 저장소 통계를 내보면 의외로 재미있는 결과를 마주할 수 있을 것이다. 다름아닌 자주 변경되는 부분만 계속 변경된다는 점이다. 변경의 사각 지대에 있는 코드들은 한 번 작성된 이후 몇 년 동안 단 한 줄의 수정도 없는 경우도 많다. 레거시 코드는 바로 이러한 사각 지대에서 발생한다. 오랜 기간 수정이 발생하지 않기에 그걸 아는 프로그래머가 드물어지고 그런 과정이 굳어져서 마치 화석처럼 돼 버리면 레거시 코드가 되는 것이다.&lt;/p&gt;
&lt;p&gt;여기서 생각해 보아야 할 점은 왜 몇 년간 단 한 번의 변경도 없었을까라는 점이다. 이는 두 가지를 의미한다. 하나는 그 코드가 본연의 목적은 잘 수행했다는 이야기고, 다른 하나는 그 코드가 관여한 부분에 요구 사항의 변경이 없었다는 것이다. 즉, 이는 다시 말하면 레거시 코드는 많은 프로그래머들의 생각처럼 단순히 잘못 작성되고 오래된 나쁜 코드가 아니라 오히려 안정된 코드라는 점이다.&lt;/p&gt;
&lt;p&gt;외부 업체에서 제공한 라이브러리의 경우도 크게 틀리지 않다. 외부 업체에서 제공한 라이브러리가 기능을 정상적으로 수행하지 못했거나 버그가 많았다면 레거시 코드가 되기 전에 이미 많은 사람들의 관심 속에서 다른 라이브러리로 교체가 되거나 직접 작성되는 운명을 거쳤을 것이다. 하지만 제한된 기능을 안정적으로 수행하는 라이브러리의 경우에는 프로그래머들의 사각지대에 놓이게 되고 시간이 오래 흐르면 직접 만든 코드와 마찬가지로 화석처럼 굳어져 버린다. 이 경우에 직접 만든 코드보다 상황이 더 좋지 않은 이유는 라이브러리를 개발한 업체가 더 이상 해당 라이브러리를 유지 보수 하지 않는다거나 아예 사라진 경우도 발생할 수 있기 때문이다. 어쨌든 이 경우에도 직접 만든 코드와 마찬가지로 오랜 시간 본연의 기능을 안정적으로 수행했기 때문에 레거시가 됐다는 점에는 변함이 없다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;새로 만드는 이유&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;앞서 레거시 코드는 오래되고 낡아서 손대기 힘들다는 기존의 관점이 아닌 오히려 오랜 시간 묵묵히 자신의 역할을 다했기 때문에 살아남을 수 있었던 안정된 코드라는 관점을 제시했다. 하지만 그럼에도 현실세계의 수많은 프로그래머들은 여전히 레거시 코드를 부정하며 새로 만드는 방법 밖에는 없다고 안달한다. 왜 그런 것일까?&lt;/p&gt;
&lt;p&gt;첫 번째 이유는 안정된 코드가 다루기 쉬운 코드라는 말은 아니기 때문이다. 프로그래밍 패러다임에도 일정한 흐름이 있고 유행이 있다. 구조화된 프로그래밍 기법이 알려지기 전까지 모든 프로그래머들은 goto 구문을 남발하면서 프로그래밍 하던 것을 당연하게 생각했었고, 객체지향 프로그래밍이 유행하기 전의 프로그래머들은 당연히 프로그램은 절차지향적으로 작성해야 한다고 굳게 믿고 있었다. 레거시 코드는 오랜 시간을 버텼고 그 코드를 처음 작성한 프로그래머와 지금 유지 보수를 맡은 프로그래머 사이에는 시차가 존재할 수 밖에 없다. 이러한 시차는 당연하게 유지 보수를 맡은 프로그래머에게는 거대한 장애물 역할을 하는 동시에, 새로 작성하는 것을 택하도록 만드는 인센티브 역할을 한다.&lt;/p&gt;
&lt;p&gt;두 번째 이유는 코드 리딩과 리팩토링에 익숙하지 않기 때문이다. 정말 안타까운 현실인데 대다수의 프로그래머 교육 기관에서 코드 리딩을 제대로 가르치지 않는다. 그 때문에 다른 사람의 코드를 제대로 읽을 줄 아는 프로그래머를 만나기란 정말 ‘하늘에 별 따기’다. 대부분의 프로그래머가 이야기하는 잘못 작성됐기 때문에 다시 만들어야 한다는 주장은 안타깝게도 그걸 해석하는 자신의 이해력이 부족하다는 전제를 내포하고 있다. 일년에 자기 계발서 몇 권 읽는 친구에게 두꺼운 철학책을 읽으라고 권해준다면 철학책 저자의 생각이 오롯이 친구에게 전달되기 보다는 왜곡되기가 쉬운 것과 같은 이치다. 물론 그 철학책을 접한 친구의 평을 듣고 철학책의 가치를 논하기는 더더욱 어려울 것이다.&lt;/p&gt;
&lt;p&gt;세 번째 이유는 새로 만드는 것이 기존의 코드를 유지 보수하는 작업보다 훨씬 더 재미있다는 점이다. 프로그래머들은 코드를 창조해내는 창작자들이다. 그들은 유지 보수 작업을 따분하고 지루한 작업이라고 생각한다. 새로운 코드를 써내려 가는 것을 훨씬 더 좋아한다. 유지 보수 할 수 있는 코드라고 하더라도 새로 만들고 싶어하는 또 다른 이유다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;새로 만들기의 함정&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;레거시 코드를 완전히 새롭게 만드는 일은 그 작업을 수행하는 프로그래머 입장에서는 공부도 되고 개인의 실력 발전도 되겠지만 제품 전체 내지는 조직의 이익에 비추어 본다면 잉여적인 투자라고 할 수 있기 때문에 좋은 선택이라고 보기는 힘들다. 이런 자본 논리 외에도 레거시 코드를 완전히 새롭게 작성하는 것에는 여러 가지 위험 요소가 있다.&lt;/p&gt;
&lt;p&gt;“새로 만들기”라는 과업을 수행할 프로그래머가 대부분의 경우에 레거시 코드의 모든 부분을 완전하게 이해하고 작업하는 경우는 드물다는 점이 가장 큰 위험 요소다. 실제로 앞서 인터뷰를 했던 10명의 프로그래머 모두 레거시 시스템을 완전히 새롭게 작성한 후에는 꼭 “원래 있었던 이 기능이 안 되는 것 같은데요”라는 말을 들었다고 했다. 심지어는 기존에 있었던 이스터에그가 정상적으로 동작하지 않는다는 클레임을 받았던 적도 있었다고 했다. 즉, 기존의 코드를 이용하지 않고 완전히 새롭게 만드는 경우에 기존의 코드가 가지고 있었던 모든 기능을 완전하게 충족시키기란 생각보다 쉽지 않다. 뒤에서 살펴보겠지만 심지어 어떤 경우에는 버그도 기존 코드와 동일하게 가지고 있어야 한다.&lt;/p&gt;
&lt;p&gt;새롭게 작성하는 쪽을 택하는 프로그래머의 경우 대부분 기존 코드를 보기 보다는 전체적인 기능 맥락을 보고 동일한 기능을 수행하는 새로운 코드를 작성하는 경우가 많다. 이 경우에 명세가 기존 코드의 기능을 100% 모두 충족시킨다면 상관 없겠지만 거의 대부분의 경우에 그렇지 않기 때문에 새롭게 작성한 코드는 항상 기존 코드와 100% 호환되지 않는다는 문제를 일으킨다.&lt;/p&gt;
&lt;p&gt;만약에 앞서의 전제를 뒤집어서 만약 그 프로그래머가 100% 기존 코드의 기능을 모두 이해하고 동일한 역할을 수행하는 새로운 코드를 쓴다고 한다면 이 또한 큰 낭비일 수 밖에 없다. 왜냐하면 모든 것을 완벽하게 이해했다면 그 코드를 고치는 일이 새롭게 작성하는 일보다 시간이 덜 걸릴 수 밖에 없기 때문이다.&lt;/p&gt;
&lt;p&gt;프로그래머들의 근거 없는 자신감은 “새로 만들기”라는 거대한 과업을 쉽게 보이게 만들어주는 강력한 인센티브 역할을 한다. 대부분의 프로그래머는 자신이 상대적으로 매우 똑똑하며 아주 특별한 존재라고 생각하는 경향이 강하다. 그래서 자신은 기존의 코드보다 훨씬 더 괜찮은 코드를 더 적은 시간을 투입하고 만들 수 있다는 착각에 빠진다. 하지만 이는 정말 말 그대로 착각일 뿐이다. 새롭게 만들어 보면 결국 기존의 프로그래머가 겪었던 시행착오를 모두 다 똑같이 겪으며 조건문들이 여기저기 덕지덕지 추가될 것이기 때문이다.&lt;/p&gt;
&lt;p&gt;“작은 것이 아름답다”라는 철학에 매료돼 있는 프로그래머의 경우 “새로 만들기” 증상은 더 심해진다. 그들은 항상 레거시 코드를 보면서 너무 복잡하다고 투덜거린다. 하지만 실질적으로 그들에게 완전히 새롭게 작성할 기회를 주었을 때 기존의 레거시 코드보다 더 효율적이고 간단한 구조의 결과물을 만들어내는 경우는 드물다. 왜냐하면 프로그래밍 문제의 복잡도는 어떠한 코딩 테크닉 보다는 문제 자체를 재정의하는 경우에 달성되는 것이기 때문이다. 따라서 기존 문제를 바라보는 시각을 유지한 체 코드만 새롭게 쓴다고 복잡도를 낮출 수 있다고 생각하는 것은 환상이다. 현실 세계에서는 복잡한 것은 복잡할 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;물론 이런 모든 것을 뒤로할 록스타급 프로그래머를 모셔 왔다고 생각해보자. 이 경우에도 항상 새로 만들기를 적용할 수는 없다. 레거시 코드 자체가 워낙 방대한 경우도 있기 때문이다. 똑같은 내용을 동일하게 타이핑 하는 데에도 몇 년이 걸릴 정도로 방대한 레거시 코드 뭉치를 가지고 있다면 이를 새롭게 만드는 일은 프로그래머의 능력을 떠나 개인의 업무로 할 수 있는 작업은 아닐 것이기 때문이다. 그런 일이라면 “새로 만들기”는 또 다른 하나의 거대한 프로젝트가 되어야 할 것이다.&lt;/p&gt;
&lt;p&gt;이런 모든 상황을 고려해 볼 때에 결국 “새로 만들기”는 좋은 선택도 아니고 항상 사용할 수 있는 총알도 아니다. 언젠가 반드시 한번은 레거시 코드를 직접 수정해야 하는 일을 할 수 밖에는 없다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;레거시 코드의 본질적인 어려움&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;결국 피할 수 없는 숙명이라면 레거시 코드를 위해서 코드 리딩과 리팩토링만 열심히 공부를 해 둔다면 되는 것일까? 그렇지는 않다. 레거시 코드를 다루기 위한 기본적인 근간에 코드 리딩과 리팩토링이 있는 것은 사실이지만 레거시 코드는 이런 일반화된 원칙과는 다르게 추가적으로 고려해야 할 부분들이 있다. 이러한 것들이 코드 리딩에 충분히 익숙하다고 하더라도 레거시 코드를 다루는 일을 어렵게 만드는 실체적 허들 역할을 한다. 이제 갓 회사에 입사한 신입 프로그래머 K의 사례를 통해서 이러한 몇 가지 상황을 만나 보도록 하자.&lt;/p&gt;
&lt;p&gt;K는 회사에서 개발 중인 프로그램에서 사용하는 한 모듈의 유지 보수를 맡았다. 코드를 검토하던 도중 &amp;#x3C;리스트 1&gt;에 나와 있는 것과 같은 some_func라는 함수 코드를 보게 되었다. 함수 내부에서 전역 변수인 g_stage 값을 변경하는 것으로 K는 이후 fn1이나 fn2의 작업에 g_stage 값이 영향을 미칠 것이라는 사실을 예측했다. 하지만 실제로 살펴본 fn1과 fn2는 &amp;#x3C;리스트 2&gt;에 나타난 것과 같이 전혀 g_stage 값과는 상관이 없었다. K는 속으로 왜 이렇게 쓸데없는 코드를 추가했냐고 투덜거리며 g_stage 값을 변경하는 부분을 제거했다. 어떻게 됐을까? 아마 K가 예측할 수 없는 엄청난 일들이 벌어졌을 것이다.&lt;/p&gt;
&lt;p&gt;이 사례는 레거시 코드에서 흔히 나타나는 전형적인 예측 불가능한 사이드 이펙트를 보여주고 있다. some_func 호출로 g_stage의 값이 변경된다는 것을 우리는 사이드 이펙트라고 부른다. 그런데 이 코드는 거기서 g_stage 값이 변경되면 무슨 일이 벌어지는지를 보여주지 않는다. 신입 프로그래머들이 흔히 레거시 코드 작업을 하면서 필요 없는 부분이 많아서 제거했다고 하는 내용들이 대다수 이런 것들이다. 물론 교과서에 등장하는 정제된 순수한 세계 속에는 이러한 일이 없겠지만 현실 세계에서 이런 코드들이 비일비재하게 등장한다. 따라서 레거시 코드의 제거는 굉장히 신중하게 해야 한다.&lt;/p&gt;
&lt;p&gt;사이드 이펙트를 예측할 수 없는 코드를 보았을 때 K가 취할 수 있는 행동은 두 가지다. 하나는 g_stage 변수와 some_func의 g_stage 관련 조작을 동시에 제거하는 경우다. 이 경우에는 사이드 이펙트의 대상체가 같이 제거되는 것이기 때문에 동시에 제거해도 문제가 없다면 당초 K의 예측대로 이는 쓸모 없이 추가되어 있는 코드라고 할 수 있다. 이 경우에도 예외 상황은 존재하는데 만약 g_stage가 포함된 이 코드가 라이브러리의 일부 코드이며, g_stage가 외부에 노출된 변수라면 동시에 제거가 되더라도 제거하지 않는 편이 옳다. 왜냐하면 그 사이드 이펙트에 의존하는 외부 프로그램이 존재할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;다른 한 가지 방법은 코드 내에서 g_stage가 하는 역할을 정확하게 조사한 후에 추후에 이 코드를 볼 사람은 K와 같은 의문을 가지지 않도록 g_stage 기능을 새롭게 디자인하는 것이다. 물론 이 경우에는 모든 코드를 면밀히 살펴 보아야 하기 때문에 즉석으로 리팩토링 작업을 하는 것은 좋지 않다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 사이드 이펙트를 예측할 수 없는 코드 1&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; g_stage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;some_func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    g_stage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; STAGE_BEGIN&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    g_statge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; STATE_END&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 사이드 이펙트를 예측할 수 없는 코드 2&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;K는 또 다른 레거시 코드 뭉치에서 &amp;#x3C;리스트 3&gt;과 같은 일반적인 문자열 복사 함수의 코드 구현을 만났다. 보안 관련 책을 열심히 공부했던 K는 이런 방식의 함수 디자인이 좋지 않다고 생각해서 함수를 &amp;#x3C;리스트 4&gt;에 나오는 코드와 같이 문자열 버퍼 크기를 전달 받도록 인터페이스를 수정했다. K는 이제 my_strcpy 함수를 호출하는 부분의 코드만 모두 변경하면 된다고 생각하고는 검색 작업을 했다. 중요한 보안 결함을 수정하는 것 같기도 해서 나름대로 뿌듯하기도 했다. 하지만 그 뿌듯함도 잠시였다. 실제로 이 작업이 그리 간단하지 않다는 것을 알 수 있었기 때문이었다. &amp;#x3C;리스트 5&gt;와 같은 코드가 문제였다.&lt;/p&gt;
&lt;p&gt;이 사례는 고착화된 인터페이스를 변경하는 일이 얼마나 어려운 일인지를 보여준다. 실제로 레거시 코드를 다룬 경험이 많이 없는 프로그래머들은 K처럼 인터페이스 변경을 단순한 코딩 테크닉의 변화로 생각하는 경향이 있다. 하지만 인터페이스라는 것은 단순한 코딩 테크닉 이상을 의미한다. 인터페이스란 그것을 설계한 프로그래머의 사상을 투영하는 성질이 있기 때문에 그걸 변경하는 것은 거대한 작업이 되는 경우가 많다. 이 경우에도 K가 레거시 코드에 대한 경험이 많았다면 버퍼 크기가 들어간 새로운 함수를 만들고 자신이 추가하는 코드에 대해서는 점진적으로 새로운 함수를 호출하도록 변경하는 구조로 가는 것이 좋았을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 일반적인 문자열 복사 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;my_strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dst&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dst&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;src&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 버퍼 크기가 들어간 안전한 문자열 복사 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;my_strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; size_t size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dst&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size_t i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dst&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;src&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;dst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\0&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 버퍼 크기를 전달 받지 않는 일반 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;some_func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 중요한 작업들 ...&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;my_strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 나머지 작업들 ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;마지막 사례를 살펴보자 K는 사내 공용 라이브러리를 유지 보수 하는 업무를 맡았다. 해당 코드를 살펴보던 중에 &amp;#x3C;리스트 6&gt;에 나와 있는 것과 같은 버그가 있는 백분율 계산 함수를 만났다. K는 코드를 보는 순간 100.0을 입력한다는 것이 10.00을 입력했다는 심증을 가졌다. 주석은 그런 K의 생각을 강화시켜주고 있었다. 자신의 존재감을 온몸으로 입증하려던 K는 과감하게 GetPercentage 함수 코드의 10.00을 100.0으로 수정했다.&lt;/p&gt;
&lt;p&gt;어떻게 됐을까? 안타깝게도 이후 상황은 K에게 좋지 않았다. K는 사실 버그를 고쳤지만 버그를 새롭게 만들어 버렸기 때문이다. 문제는 &amp;#x3C;리스트 7&gt;과 같은 코드가 문제였다. 기존의 공용 라이브러리를 사용하던 일부 프로그래머들은 자체적으로 잘못된 계산 결과를 보정해서 사용하고 있었던 것이다. 당연히 이 코드들은 K가 볼 수 없는 곳에서 제작된 것이기 때문에 K가 미라 알고 대처하기에는 힘든 점이 있었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 타이핑 실수가 있는 백분율 계산 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 백분율 계산 함수&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 결과 = a / b * 100&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CalcPercentage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10.00&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 버그가 있는 GetPercentage 함수의 결과를 보정하는 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPercentage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이는 전형적인 레거시 코드의 버그 수정이 가져오는 파급 효과를 나타낸 것이다. 작위적인 것처럼 보이지만 우리 나라 회사의 소스 코드에서 흔하게 벌어지는 풍경이다. 정치가 코드에 개입해 버린 것이다. 결과를 보정해서 사용하는 프로그래머 입장에서는 결과를 보정하거나 자신만의 라이브러리를 만드는 비용보다 GetPercentage 함수를 만든 사람에게 버그 수정을 요청하는 비용이 비교도 되지 않게 높았던 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 똑똑한 K라면 어떻게 해야 했을까? 버그가 수정된 GetPercentage2 함수를 만들고 외부에 GetPercentage 버그가 수정된 GetPercenage2 함수가 만들어졌음을 알린다. 그리고 헤더에는 GetPercentage 함수는 버그가 있으니 사용하지 말라는 경고를 출력하는 안전 장치를 추가해 놓는 것이 좋겠다.&lt;/p&gt;
&lt;p&gt;결국 레거시 코드 작업이 코드 리딩과 리팩토링 이상의 경험이 필요한 이유는 부분을 통해서 전체를 유추해야 함에 있다. 레거시 코드를 다룰 때에 우리는 항상 전체를 다 볼 수 없다. 또한 레거시 코드들은 그들이 살아남은 역사만큼이나 다양한 장치들을 통해서 다른 컴포넌트들과 인터페이싱하고 있다는 점을 항상 염두에 두어야 한다. 그렇기 때문에 레거시 코드에 대한 수정은 가급적 작고 사소한 부분부터 점진적으로 이루어져야 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;레거시 코드를 다루는 전략&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;레거시 코드를 다루는 기본 전략은 너무나 간단하다. 컴퓨터 공학에서 어려운 문제를 풀 때 항상 등장하는 분할 정복법이다. 거대한 레거시 코드를 한번에 모두 다루기는 힘들기 때문에 그걸 작은 문제들로 분할해서 점진적으로 정복해 나가는 것이다.&lt;/p&gt;
&lt;p&gt;분할 정복에서도 레거시 코드를 다룰 때에 가장 중요한 부분은 분할이다. 분할이란 결국 어떤 부분을 수정할지를 선택하는 것이고 그 문제를 거대한 레거시 코드에서 독립적인 부분으로 떼어내야 함을 의미한다. 우리가 수정할 부분이 거대한 시스템에 대해서 완전하게 독립적일 수 있도록 만드는 작업에서 시작해야 한다.&lt;/p&gt;
&lt;p&gt;예를 들어 앞선 &amp;#x3C;리스트 1&gt;에 나오는 some_func 함수의 경우에는 g_stage라는 부분이 의존적이기 때문에 바로 수정하는 것은 좋지 않다. 이 경우에 fn1과 fn2를 호출하는 로직에 변경을 가하고 싶은 경우라면 &amp;#x3C;리스트 8&gt;에 나와 있는 것과 같이 그 부분을 별도로 떼어내서 독립적으로 만든 다음 작업하는 것이 좋다. 이렇게 떼어내게 되면 some_func2 함수는 기존의 레거시 코드와는 완전히 독립적인 코드가 된다. 별도로 테스트 할 수도 있으며 기존 코드와 결과값을 비교하는 테스트를 작성할 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 fn1, fn2 호출 로직 분리&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;some_func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    g_stage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; STAGE_BEGIN&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;some_func2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    g_statge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; STATE_END&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;some_func2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서도 말했지만 레거시 코드에 대한 변화는 작고 사소한 부분부터 점진적으로 이루어져야 한다는 점을 반드시 기억하자. 이는 레거시 코드에 대한 변화는 없을수록 기존 동작 방식을 잘 유지할 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;예를 들어 우리가 해야 하는 일이 기존에 C로 만들어진 &amp;#x3C;리스트 9&gt;와 같은 코드를 클래스로 변환하는 작업이라고 생각해 보자. 이 경우에도 기존 코드들을 해체해서 클래스로 변환시키기 보다는 &amp;#x3C;리스트 10&gt;에 나타난 것처럼 기존 함수를 호출하는 래퍼 클래스를 만드는 것이 좋다. 기존 코드를 해체해서 새로 만드는 경우에는 수정 작업이 많은 만큼 실수할 여지도 늘어나지만 이렇게 래퍼 클래스를 만드는 경우에는 기존 코드가 하는 역할을 래퍼 클래스도 100% 동일하게 수행할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 리비전 리스트를 관리하는 레거시 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HANDLE &lt;span class=&quot;token function&quot;&gt;CreateRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;CloseRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL &lt;span class=&quot;token function&quot;&gt;AddFileToRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE h&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG revision&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL &lt;span class=&quot;token function&quot;&gt;DeleteFileFromRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE h&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 리비전 리스트 래퍼 클래스&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RevisionList&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    HANDLE revlist_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateRevisionListError&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;RevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        revlist_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;revlist_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateRevisionListError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;RevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CloseRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;revlist_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    BOOL &lt;span class=&quot;token function&quot;&gt;AddFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCWSTR path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG revision&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AddFileToRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;revlist_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reivison&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    BOOL &lt;span class=&quot;token function&quot;&gt;DeleteFil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCWSTR path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DeleteFileFromRevisionList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;revlist_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;오래된 미래&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;레거시 코드란 우리가 지금 쓰고 있는 무수히 많은 코드의 오래된 미래다. 우리가 지금 쓰고 있는 코드가 오랜 시간 동안 살아 남는다면 미래의 언젠가는 똑같이 레거시 코드가 될 수 밖에 없을 것이기 때문이다. 레거시 코드가 없는 신생 프로젝트도 마찬가지다. 프로젝트 기간이 길어지고 코드가 늘어나고 하다 보면 미래의 어느 순간에는 반드시 레거시 코드가 생겨날 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;‘레거시 코드는 다루기 힘들고 성가신 코드’라는 인식을 이제는 조금 바꿀 필요가 있을 것 같다. 레거시 코드는 항상 우리 주변에 있고, 다른 코드보다 조금 더 우리의 관심을 필요로 하는 코드일 뿐이다. 그러니 이제 쓰레기통에 버릴 궁리만 하기 보다는 레거시 코드를 이해하려는 마음가짐을 가지도록 하자. 어쩌면 레거시 코드를 다루는 가장 위대한 방법은 열린 마음가짐으로 그 코드를 꺼내서 읽고, 또 읽는 것에 있는지도 모른다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;내게 나무를 자를 8시간이 있다면, 나는 도끼를 가는데 6시간을 쓰겠다.&lt;/p&gt;
&lt;p&gt;– 아브라함 링컨&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[Vista 이상 시스템에 TDI 포팅 시 주의할 점]]></title><description><![CDATA[MS에서 Vista 이상부터 TDI 지원을 끊겠다고 했으나 Windows 8까지 TDI는 여전히 지원되고 있습니다. 하위호환성을 그렇게 쉽게 끊진 못하죠 ㅋ~ 몇 해 전 만들었던 TDI 클라이언트 드라이버가 Vista…]]></description><link>https://jiniya.net/wp/archives/11424</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11424</guid><pubDate>Tue, 25 Jun 2013 23:59:00 GMT</pubDate><content:encoded>&lt;p&gt;MS에서 Vista 이상부터 TDI 지원을 끊겠다고 했으나 Windows 8까지 TDI는 여전히 지원되고 있습니다. 하위호환성을 그렇게 쉽게 끊진 못하죠 ㅋ~ 몇 해 전 만들었던 TDI 클라이언트 드라이버가 Vista 이상에서 동작하지 않는다고 해서 오늘 디버깅을 좀 했습니다. 별거 아닌 곳에서 삽질을 좀 해서 기록을 남겨 놓습니다. 우선 문제는 다른 건 다 잘 되는데 이상하게 TdiConnectionContext만 하면 STATUS_INVALID_PARAMETER가 떨어지는 문제였습니다. 아래와 같은 코드에서 ZwCreateFile이 성공하지 못하는 상황이었죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MY_KERNEL_SOCKET&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;scoket&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
NTSTATUS status&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
IO_STATUS_BLOCK iosb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
PFILE_FULL_EA_INFORMATION ea&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

UNICODE_STRING name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
OBJECT_ATTRIBUTES oa&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;RtlInitUnicodeString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;\\Device\\Tcp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;InitializeObjectAttributes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;oa
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;name
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OBJ_CASE_INSENSITIVE &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; OBJ_KERNEL_HANDLE
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ea &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ExAllocatePool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ea&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; STATUS_INSUFFICIENT_RESOURCES&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ea&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;EaNameLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TDI_CONNECTION_CONTEXT_LENGTH&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ea&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;EaValueLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;RtlCopyMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ea&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;EaName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TdiConnectionContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ea&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;EaNameLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;RtlCopyMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ea&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;EaName&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ea&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;EaNameLength &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ZwCreateFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cfh
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; GENERIC_READ &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GENERIC_WRITE &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; SYNCHRONIZE
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;oa
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;iosb
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FILE_ATTRIBUTE_NORMAL
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FILE_OPEN_IF
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ea
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ea_len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NT_SUCCESS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 요기서 STATUS_INVALID_PARAMETER 발생&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; status&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;처음에 별거 아닌 문제로 보여서 그냥 구글링을 했는데, 저같은 이슈를 겪는 사용자가 의외로 없더군요. 질문은 올라와 있는데 그냥 해결됐다 고맙다 이런 답변만 있는… ㅠㅜ~ 삽질을 좀 하다 문제가 해결이 안 돼서 tdx.sys 드라이버 파일을 열었습니다. 그제야 답이 보이더군요. Windows XP까지는 TDI를 tcpip.sys에서 처리했으나, Vista 부터는 tdx.sys에서 처리하고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 595px; margin-bottom: 16px;&apos; data-url=&apos;./Vista_이상_시스템에_TDI_포팅_시_주의할_점.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0f3aab139b2cf31c9939ef779b04d17f/5acb4/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 16.315789473684212%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAkUlEQVR42k3LSw6CMBSFYfa/CDehJiV1GYQIRCRcTTBp9d4CRejLdqDxH5zJyZdxfmIsF0KEEJzzcaXUbfs0xjWNLIpH3Qy3+wYQ1tWOoyIipRQiaq0zzo95fpAyYe8TRly6Dud5i7iq8ArTullj0uu+WWvjRlwzdhZi+mGid98jAJXlaxguRDuAvTFLSPnw1wf9OqbQyAlpsQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Vista         TDI            md 0&apos; title=&apos;&apos; src=&apos;/static/0f3aab139b2cf31c9939ef779b04d17f/5acb4/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_0.png&apos; srcset=&apos;/static/0f3aab139b2cf31c9939ef779b04d17f/08678/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_0.png 190w,
/static/0f3aab139b2cf31c9939ef779b04d17f/2edd7/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_0.png 380w,
/static/0f3aab139b2cf31c9939ef779b04d17f/5acb4/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_0.png 595w&apos; sizes=&apos;(max-width: 595px) 100vw, 595px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;TdiConnectionContext 인지를 검사하는 루틴&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 443px; margin-bottom: 16px;&apos; data-url=&apos;./Vista_이상_시스템에_TDI_포팅_시_주의할_점.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/192d1cbebd01be28e2bae89863bebc71/4d697/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 32.631578947368425%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABMUlEQVR42mWP23KCMBCGef/3ccqFqIOMGjsKxXAohIMSRSCcpGMtKHSV1ot2Z+fPv7v5ZhNOkkYISeu1rarb6dQcjfTjMcnzrCiKqjqlaVqWJZhHltCEkmUMbzUe8xxCsSxHhDiWZRFiQ0KAYmxh/GN0ncjyO0LY93aU0iAIPM9zicsNBsp4jJvm2nVd23YPvR+Ok2laDIbS0jAYlK/L0Kb0VBck2n5evmDECcLLYjFt21v3G09YVSMwh0Nlmolts8VsL2orcS9I/syK3bw4c8OhgNCyaZo/8G5XGEbSw4pydN1Mw4nqOMOlzNgZ+rdby/E8P5lM6rp+Yr0GQQnLwYRhJcshwIbOVqbNS28svvTXOFEU5/P5/83wu83m/uwo+lCU0Pdz02CaTVeal6U93H0DZMB5pFfdCoAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Vista         TDI            md 1&apos; title=&apos;&apos; src=&apos;/static/192d1cbebd01be28e2bae89863bebc71/4d697/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_1.png&apos; srcset=&apos;/static/192d1cbebd01be28e2bae89863bebc71/08678/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_1.png 190w,
/static/192d1cbebd01be28e2bae89863bebc71/2edd7/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_1.png 380w,
/static/192d1cbebd01be28e2bae89863bebc71/4d697/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_1.png 443w&apos; sizes=&apos;(max-width: 443px) 100vw, 443px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;점프하면 이곳으로 옵니다. EaValueLength가 4인지를 검사하고 있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 621px; margin-bottom: 16px;&apos; data-url=&apos;./Vista_이상_시스템에_TDI_포팅_시_주의할_점.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/faa8fbf89a4c095e65dd0c57462aaaaf/41b39/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 26.31578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA8ElEQVR42lWO0WqDMABF/f//aIcvYyjSNl3ZRMf2Mpib0spqNY1ZYq3GGrFJwGY+yXYeLhcuB64BADBN03GcsZRlqbUehtuYRdERwjkX2235/snihA+DzrI+SS6ct03TdF1nLBbL+fzOsmwA1nVdTzKlHYSMseH1jVN20fo2ypzrttUThus+2vb9ZrP0vCdKiVKq73ulBCEMwnNV8Sg6hV/k2gulpJRCyuuE4XkIAOS6yPfRfo/yHB2PCON8t0vjODscYBAkL370naaEEozxuE6Mt59nswfLWq9WblWxv7cxbjmXYXgKPgp4/umF0P/5BTbwCz+rAn2UAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Vista         TDI            md 2&apos; title=&apos;&apos; src=&apos;/static/faa8fbf89a4c095e65dd0c57462aaaaf/41b39/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_2.png&apos; srcset=&apos;/static/faa8fbf89a4c095e65dd0c57462aaaaf/08678/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_2.png 190w,
/static/faa8fbf89a4c095e65dd0c57462aaaaf/2edd7/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_2.png 380w,
/static/faa8fbf89a4c095e65dd0c57462aaaaf/41b39/Vista_%EC%9D%B4%EC%83%81_%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90_TDI_%ED%8F%AC%ED%8C%85_%EC%8B%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90.md_2.png 621w&apos; sizes=&apos;(max-width: 621px) 100vw, 621px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;64비트 운영체제의 tdx.sys, EaValueLength가 8인지를 검사하고 있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;결론만 말하면 TdiConnectionContext의 EA Value로는 항상 포인터 크기의 핸들만 전달해야 합니다. XP에서는 이런 체크가 없어서 정상적으로 동작했던 것 같네요. 헐~ 아래는 MSDN 전문입니다. 교과서를 열심히 봐야 삽질이 없습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For a connection endpoint, the EaName member is set to the system-defined constant TdiConnectionContext and &lt;strong&gt;the EA value following the EaName array is a client-supplied handle, opaque to the transport driver.&lt;/strong&gt; The transport must save this handle and subsequently pass it back to the client’s registered event handlers for this connection.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/ff565046(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/windows/hardware/ff565046(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이거 말고는 기존 XP 소스를 특별히 변경하지 않아도 잘 동작했습니다. 당연한 거겠지만 ㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[전략 서신: API 후킹을 할 때에 생각해야 할 것들…]]></title><description><![CDATA[안녕. 오늘은 너희들을 위해서 API 후킹이란 기술에 대해서 좀 써볼까 해. 물론 이 글은 API 후킹이 뭐지, 점프 코드를 어떻게 만들지, 트램펄린은 뭐지, 따위를 고민하는 초보 프로그래머를 위한 글은 아니야. 이 글은 적어도 실무에서 API…]]></description><link>https://jiniya.net/wp/archives/11276</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11276</guid><pubDate>Mon, 17 Jun 2013 23:58:59 GMT</pubDate><content:encoded>&lt;p&gt;안녕.&lt;/p&gt;
&lt;p&gt;오늘은 너희들을 위해서 API 후킹이란 기술에 대해서 좀 써볼까 해. 물론 이 글은 API 후킹이 뭐지, 점프 코드를 어떻게 만들지, 트램펄린은 뭐지, 따위를 고민하는 초보 프로그래머를 위한 글은 아니야. 이 글은 적어도 실무에서 API 후킹 코드를 한번쯤은 짜 본 프로그래머를 위한 글이야. API 후킹 코드가 뭐 대단한게 있냐고? 없지. 없는데도 잘 모르는거 같아서 내가 몇 자 적어볼까 해. 니가 뭔데 이 따위 건방진 글을 쓰냐고? 그래. 맨날 버그만 만드는 내가 이런 글을 쓸 자격이 있는지 모르겠다. 그래도 훅 코드를 작성해 본 경험도 많고, 관련 검색어에 후킹도 나오고 하는걸로 봐서 한번 정도는(!?) 주제넘게 이런 이야기를 해도 되지 않을까란 생각이 들어서 감히 몇 자 끄적여 보려고 해.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 430px; margin-bottom: 16px;&apos; data-url=&apos;./전략_서신_API_후킹을_할_때에_생각해야_할_것들.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/83315f3f997fe6f225330ea2a2e22ce4/bc750/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 5.7894736842105265%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAARklEQVR42g3IMQ6AIAwAQP//PEWIIK3oYKAsakpJ46A33kBEAMD82KXFTQLIdb+49xXFR8lFjWsB5cxaqv45WR5nNo7T0T96ojY7D/QZGgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      API                    md 0&apos; title=&apos;&apos; src=&apos;/static/83315f3f997fe6f225330ea2a2e22ce4/bc750/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_0.png&apos; srcset=&apos;/static/83315f3f997fe6f225330ea2a2e22ce4/08678/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_0.png 190w,
/static/83315f3f997fe6f225330ea2a2e22ce4/2edd7/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_0.png 380w,
/static/83315f3f997fe6f225330ea2a2e22ce4/bc750/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_0.png 430w&apos; sizes=&apos;(max-width: 430px) 100vw, 430px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;시작하기에 앞서 먼저 밝히는데 이 이야기는 절.대.로. 너희에게 뭐라고 하는 건 아니니까 오해하지 않았으면 좋겠어. 너희가 무슨 죄가 있겠니. 후킹 라이브러리 하나 안 사주는 사장님이 잘못된 거지. 또 돈 안 된다고 위험한 모듈에 학교 갓 졸업한 인턴 투입하는 사장님이 잘못된 거지. 그런 악덕 사장님 덕에 나중에도 이런 위험천만한 기능을 별 생각 없이 만들 수많은 미래 보안 프로그래머를 위해서 쓰는거니까 절대 오해하지 않았으면 좋겠다. 나도 맨날 버그만 싸질러서 지원팀한테 엄청 미움받고 있어 ㅋㅋㅋ~ 돈 벌면 진짜 QA 해줄 테스트 프로그래머 한 명 뽑아야지 ㅠㅜ~ 눈물 좀 닦고, …&lt;/p&gt;
&lt;p&gt;이 이야기의 시작은 크래시 덤프에서 출발해. 오늘 크래시 덤프를 하나 받았어. 너희들도 보안 업체에서 일하니까 크래시 덤프가 얼마나 토나오는 말인지는 알지? 너네 문제가 아닌 크래시 덤프 파일을 얼마나 많이 접했니? 아마 수도 없이 많을거야. 매일 다른 업체 버그를 수정하는 코드를 만드느라 고생하는 것도 잘 알고 있어. 내가 만든 버그 수정하랴, 다른 사람 버그 수정하랴, 충돌 피하랴. 고생이 이만저만이 아니지 정말. 어쨌든 그 크래시 덤프는 원인이 이랬어.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;0:000&gt; u ntdll!ZwOpenProcess&lt;br&gt;
&lt;br&gt;
ntdll!ZwOpenProcess:&lt;br&gt;
&lt;br&gt;
7709fc00 e9bb223000 jmp 773a1ec0&lt;br&gt;
&lt;br&gt;
7709fc05 33c9 xor ecx,ecx&lt;br&gt;
&lt;br&gt;
7709fc07 8d542404 lea edx,[esp+4]&lt;br&gt;
&lt;br&gt;
7709fc0b 64ff15c0000000 call dword ptr fs:[0C0h]&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;0:000&gt; u 773a1ec0&lt;br&gt;
&lt;br&gt;
773a1ec0 ?? ???&lt;br&gt;
&lt;br&gt;
^ Memory access error in ‘u 773a1ec0′&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;너네도 알겠지만 부연 설명하면 점프 코드를 잘못 싸지른 게 원인인거지. 왜 아무도 안 건드리는 ZwOpenProcess가 저리도 어설프고 불완전하게 후킹됐을까 엄청 고민했어. 처음엔 악성 코드에 감염된 건 줄 알았어. 흔하게 중2병 학생이 코딩한 악성 코드에는 저런 버그는 수도 없이 많잖아. 그런데 안타깝게도 그 PC는 클린한 우리 테스트 PC 였거든. 물론 테스트 PC도 악성 코드에 감염될 수는 있어. 하지만 정말 아쉽게도 그 프로세스엔 다른 훅 코드가 몇 개 더 있었고, 그 모듈 정보를 통해서 난 저 훅 코드가 악성 코드가 아닌 너네가 만든 훅 코드라는 걸 알 수 있었어. 실제로 문제는 e9bb2233다음에 89가 기록돼야 하는데 89가 기록돼지 못한 것이 원인이었거든. 그 번지에 89가 기록됐으면 안전하게 너네 훅 코드로 점프가 이루어졌을거야.&lt;/p&gt;
&lt;p&gt;왜 이런 상황이 벌어졌는지 보기 위해서 본의 아니게 너네 모듈을 좀 살펴봤어. 요약하면 그 모듈은 WH_CBT 훅을 설치해서 훅 루틴에서 몇 개의 API를 후킹하는 모듈이었어. 그런데 내가 보기에 너네가 사용하는 API 훅 설치 코드에 조금 문제가 있다는 생각이 들었어. 내가 왜 그렇게 생각했는지 코드를 보면서 설명하는 시간을 조금 가져보도록 할께.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 598px; margin-bottom: 16px;&apos; data-url=&apos;./전략_서신_API_후킹을_할_때에_생각해야_할_것들.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/089db8614e37149e0b09527e04fff060/02e46/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 54.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABvElEQVR42mVSbW/aMBDmb+/rfsS2HzJNQiBgWRdI2o6VjlakaGQkITFxEkLs+N2eCRNl6ul0fpGfu+eec284HDqOA0CdpigIYJ63hIg8x1JJJpgxRmtt4xZWT3GUNBHEMDyEcR0DBHqe57muSwi5vEvT5iUoKBNRcmBEykqbwuQr3ZSme2Mu1huNRrYy59welFI2AoDW6wIjvviVVX9a+UMb35i10Sdg5/rfpve5M4yRTaqUOFe24LYVd3c7bxbf3+/qmpasZLLr4pLCgieTiaXN2Gt7ELYWz7l8eMjiuF4F0PeTII6EFuZ/602nru/PIfwC4ccw/FSW32yGM3+lLBctpF0MYmiPQdqkFalszFB2EmwwGIzHXw+HDaUvx+NKiByANo6PtrIlv16XTwHIihoxjFnbckwFbViDObZ+6rnf71+rnSTHn/OMULZNCsF0exCkoVGo9uCN2jc332czj9K2E0zaq7Ikm03VYvF7U9Gcy1CZSHNglD5jrwRzXef2dsYYvRIMb7c1Y3K53M/n2XJZIMSxbIR6I5jjxNPpzg7mArbfy46aEO77+fPzeLF4583eP24+UCk7yCvvv55rZULirrlpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      API                    md 1&apos; title=&apos;&apos; src=&apos;/static/089db8614e37149e0b09527e04fff060/02e46/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_1.png&apos; srcset=&apos;/static/089db8614e37149e0b09527e04fff060/08678/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_1.png 190w,
/static/089db8614e37149e0b09527e04fff060/2edd7/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_1.png 380w,
/static/089db8614e37149e0b09527e04fff060/02e46/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_1.png 598w&apos; sizes=&apos;(max-width: 598px) 100vw, 598px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;STEP 1: 훅 대상 코드 추적 부분, 0xe9 루프를 추적하는 루프&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;너네가 작성한 훅 설치 루틴은 크게 세 부분으로 돼 있는데 여기가 그 첫번째 부분인 훅 대상 코드 추적 부분이야. 후킹하려고 하는 NtOpenProcess에 이미 다른 훅이 설치돼 있으면 해당 주소로 점프한 곳을 계산해서 다시 그곳에 점프 코드가 있는지 점검하는 코드로 구성돼 있어. 그런데 여기서 재미난 사실은 아무 생각없이 0xe9를 찾고 있다는 점이야. 무한 루프를 추적하게되면 너네도 같이 무한 루프에 빠진다는 함정이 있어. 쉽게는 “jmp $(e9 fbffffff)” 같은 코드를 들 수 있겠지. 조금 더 영리했다면 루프를 탐지할 수 있도록 이미 스캔한 주소를 목록에 보관하고 비교를 했어야 하는게 아닌가 싶어.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 597px; margin-bottom: 16px;&apos; data-url=&apos;./전략_서신_API_후킹을_할_때에_생각해야_할_것들.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/27a43dbd86251126ac3547f4e04c4e7a/f523d/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 43.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABc0lEQVR42lWRb2/aMBDG8/2/ChLvhrRKtCDGpFQrVf9AlgZKDMaOQ+MkxHMSO/bNBbFmzwvrLN1Pzz133s3N9/2eMSbD8AOhQimTMKFaw2suVW06qzvdduoV4Z9L9IzQUbIoW+/KHTkRbzKZZFkGANZa93adXa1Src0GHSk7xTjfC3wok5RagkGc4NwJF3nj8Zix1FXGmAu8WJCqalFcVB8NaIAarIIogsUDUPpJ2ovAeoPBAGP8z9l5+v6h60ywyuNfMrgtf/v76I1sWPKK3jMum6aDq7zRaNQf28FPT4n7oVj9WO4eNoRxQ1NzIBrhnHPJef0Fz+fzsix7mQ0hlSsYFWsabxP8R1W8Tiudi0bC//JmsxnnvL+wx0dS13q7LY6pzHlTylMm8peo8F2KAMIQ2vYKD4dDd6j+2Ld372WuXuL1koTnHutWee/D6Bu8RXCOeIWn02nf2RgbBEcpNcaFiBs4ABCwFLIUCAUhvu4EAH8BTQ34RhQ5BR8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      API                    md 2&apos; title=&apos;&apos; src=&apos;/static/27a43dbd86251126ac3547f4e04c4e7a/f523d/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_2.png&apos; srcset=&apos;/static/27a43dbd86251126ac3547f4e04c4e7a/08678/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_2.png 190w,
/static/27a43dbd86251126ac3547f4e04c4e7a/2edd7/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_2.png 380w,
/static/27a43dbd86251126ac3547f4e04c4e7a/f523d/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_2.png 597w&apos; sizes=&apos;(max-width: 597px) 100vw, 597px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;STEP 2: VirtualProtect를 사용해서 대상 코드의 프로텍션 속성 변경 부분&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다음으로 VirtualProtect를 이용해서 점프 코드를 삽입할 위치에 프로텍션 모드를 변경하는 코드야. 여기에는 큰 문제는 없어 보이는데 뒤쪽 부분과 결부하면 한가지 아쉬운 점은 VirtualProtect로 변경한 속성을 원복하지 않고 있다는 점이야. 왜 이전 프로텍션 속성으로 다시 변경을 하지 않는지 모르겠어. 다양한 환경을 접하면 알게 되겠지만 CRT에 포함된 일부 코드 중에서도 페이지 속성을 체크하는 코드도 있어. 그런 코드는 PAGE_EXECUTE_READWRITE 따위와 같이 코드에 WRITE 속성이 걸려 있으면 체크해서 오류를 토해내거든. 그러니까 변경한 속성은 꼭 다시 원복시켜 주도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 591px; margin-bottom: 16px;&apos; data-url=&apos;./전략_서신_API_후킹을_할_때에_생각해야_할_것들.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ef6a27081233d7b45b88cbe953eb4266/c1f10/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 71.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACe0lEQVR42nVTW08TQRTeH2aMT8YC5VJU8Kf44E/gwUQfDNGYaPDBh2oADdCWdtsu7NZaeqFsC3Tpbne71+7O3rtXpywGTGRycnJm5nzfNzPnDLK9vZ3P51hWVBSHoiaq6kATRTMM47MuuOTEsaLKwJSAOtJGLBhrrsbqrGAKvMEj5XIZx3Fd1+M4jqIIelm2OU6fTqNGwzxpBY0Tv9WKaoR9NZhe9IFleteZ0MUIihZx/MgwZmA/CKAXRYOmVc/3SVKgBoAdOY4bGWZoO4FuOC5kjcNoBo+Qb9mdg/1DTQMQFoYzQoY2+j01CCICF1tNpXcux/cMZK/0HiW2BFA3AxJMT+2IpMZ1ckhozinRRpuXaHtQndgdxW2qbgd4Z5rXnoYJXYTk6VSBmasIK0fyamJVIVPhV6pipsAslbjlIruEchlUWMakVVxeq0gp1s7OoHGA/Ow/3r9MYcJzXF7HpXVCeVHmnhWZp8fSWo7K5OnlHJPOs4tFbgUVIMVqkU+x1vcb8E7/wY+Lhyg/V5UWq1Iak9NFbj7PpCriQo5+csjOo/wCXIe7mLRYEdOHwiPG+vpXGX+5X39FSpsj58vQ/My6W53xhwa9CeNS501t/LotvmvKb2viBiFsUOanofUReKfX4BApl47qv1qWZd/WWXI51vb9qEcCTtRl1VFsfWIaXuAnCbevfXCwd3yMmZYBJ0E4q/OI1c4vJBjXf4+ogdqj6SFsJ8tK1JIi34Cz2ezu7i4Ad+rMgG5Xmk6DbldMjvOv3h3lQqFQKpWS9kzAgmBeXameF/Z6Ms+bkOVa8z8ECIZhtVrNtm/vPJnYg8EEdhj8Hr4f3Ksbx38AIY3cFJFvPLEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      API                    md 3&apos; title=&apos;&apos; src=&apos;/static/ef6a27081233d7b45b88cbe953eb4266/c1f10/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_3.png&apos; srcset=&apos;/static/ef6a27081233d7b45b88cbe953eb4266/08678/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_3.png 190w,
/static/ef6a27081233d7b45b88cbe953eb4266/2edd7/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_3.png 380w,
/static/ef6a27081233d7b45b88cbe953eb4266/c1f10/%EC%A0%84%EB%9E%B5_%EC%84%9C%EC%8B%A0_API_%ED%9B%84%ED%82%B9%EC%9D%84_%ED%95%A0_%EB%95%8C%EC%97%90_%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC_%ED%95%A0_%EA%B2%83%EB%93%A4.md_3.png 591w&apos; sizes=&apos;(max-width: 591px) 100vw, 591px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;STEP 3: 훅 코드를 덮어쓰는 부분&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;여기가 핵심이야. 특히 연두색으로 표시한 저 부분이 코드를 덮어쓰는 부분인데 내가 크래시 덤프에서 보았던 실패 원인이 여기에 있는 것 같기도 해. mov [eax], ecx라는 부분이 완전하게 이루어지지 못한 거지. 어떤 이유에서였든 말이야.&lt;/p&gt;
&lt;p&gt;자 이제 너네가 작성한 훅 코드를 살펴밨으니 내가 아쉬운 몇 가지 부분을 감히(?!) 언급해 보는 시간을 좀 가져볼까 해. 아마 너네가 다음번 훅 설치 루틴을 작성할 때에는 크게 도움이 될거야. 이런 복잡한 부분을 고려하기 힘들다면 그냥 상용 훅 설치 라이브러리를 사서 쓰길 바래. 그건 그래도 이런 초보적인 방식 보다는 좀 더 다양한 처리가 돼 있거든.&lt;/p&gt;
&lt;p&gt;어쨌든 한번 시작해볼께. 첫 번째는 너네는 함수 도입부가 무조건 5바이트라는 가정을 하고 있어. 왜지? 함수 코드는 너네처럼 변경하는 놈들이 아주 많을 수 있거든. 그리고 너네만 후킹하라고 만들어 놓은 부분도 아니잖니? 그런데 왜 5바이트에 꼭 맞춰져 있을거라는 가정을 하는 거지. “mov edi, edi” 같은 코드를 넣어서 윈도우가 API 도입부를 5바이트로 맞춘 것도 그리 오래되지 않았어. 핫패칭 재미를 쏠쏠하게 보기 시작하면서 넣기 시작한 거거든. 가까운 윈도우 2000만해도 그렇지 않은 함수들이 많이 있어. 그러니까 다음부터 훅 설치 루틴을 작성할 때에는 코드 길이를 계산하는 부분을 반드시 넣어 주면 좋겠어. 그러면 가변적인 코드도 안전하게 후킹할 수 있게 될거야.&lt;/p&gt;
&lt;p&gt;두 번째는 너네 훅 설치 코드에는 재배치 코드가 빠져있어. 그냥 단순히 원본을 카피하는데 그 원본에 상대주소 호출(e8), 쇼트 점프(eb) 같은 코드가 있으면 복사한 지점에서는 제대로 동작을 하지 않겠지. 왜냐하면 호출하는 지점 주소가 바꼈으니까 말이야. 그러니까 코드를 복사하고 나면 반드시 원본 코드에 상대 주소를 사용하는 부분이 있는지를 체크해서 주소를 새로 계산해 줘야해. eb 같은 경우에는 점프 주소가 변경되면 오프셋으로 사용할 공간이 모자랄수도 있거든. 그럴 경우에는 e9같은 걸로 확장시키는 방식을 써줘야 돼. 사실 너네처럼 재배치를 안 하는 코드 때문에 일부 생각있는 사람들은 단순 복사에도 안전한 6바이트 후킹(ff 25)을 더 선호하기도 해. 그런데 너네는 그마저도 5바이트로 가정을 해버려서 교양있는 사람들의 행동도 처참히 실패하게 만들어 버리곤 하지 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;이제부터가 제일 중요한 거야. 프로세스 안에는 있잖아. 너네 말고도 엄청 많은 스레드가 동작하고 있어. 그 스레드들도 항상 너네와 같은 일들을 하려고 할 수도 있고, 심지어는 너네가 변경하려는 곳을 참조하려고 하기도 하거든. 간단한 예, 몇 가지만 생각해 보자. 1) mov [eax], ecx를 하는 도중에 다른 스레드가 너네 코드가 쓰려는 페이지를 VirtualProtect로 쓰지 못하도록 만들어 버리는 상황, 2) mov byte ptr [esi], 0xe9를 한 순간 다른 스레드가 NtOpenProcess를 호출해서 그 코드를 실행시켜 버리는 상황, 3) 너네가 덮어 쓰려는 데 다른 프로그램도 그 주소에 값을 덮어 쓰려는 상황, 등등. 간단한 것만 생각해도 이런데 복잡하게 들어가면 더 다양한 케이스가 있겠지?&lt;/p&gt;
&lt;p&gt;적어도 난 너네가 이런 문제에 대해서 일말의 고민이라도 했다면 InterlockedExchange 정도의 함수는 썼어야 했다고 생각해. 물론 InterlockedExchange 함수를 쓰더라도 5바이트를 덮어써야 하기 때문에 한번에 할 수는 없지. 그래도 적어도 문제가 발생할 수 있는 확률은 낮춰줄 수 있지 않겠니? 그런데 이런 고민 조차도 없다는 게 정말 안타까워. 나도 회사 다니면서 다양한 프로그래머들을 만났지만 이런 이야기들을 하면 항상 그래. 그럴 일이 없다고. 그래서 꼭 코드로 보여줘야 믿지. 아래는 내가 작성해 본 간단한 코드야. VPThread가 동작할 때, 하지 않을 때, InterlockedExchange를 썼을 때, 쓰지 않을 때, 출력되는 문장의 개수를 살펴봤으면 좋겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;process.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tchar.h&quot;&lt;/span&gt;&lt;/span&gt;

UINT 
CALLBACK
&lt;span class=&quot;token function&quot;&gt;VPThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HMODULE ntdll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;ntdll.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FARPROC ntqit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntdll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NtQueryInformationThread&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        ULONG oldp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;VirtualProtect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntqit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_EXECUTE_READ&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;oldp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

UINT
CALLBACK
&lt;span class=&quot;token function&quot;&gt;HookThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HMODULE ntdll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;ntdll.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FARPROC ntop &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntdll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NtOpenProcess&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PUCHAR opcode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PUCHAR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ntop&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PULONG offset &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;opcode&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        __try
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            ULONG oldp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;VirtualProtect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntop&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_EXECUTE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;oldp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            offset&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x11223344&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            offset&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x88776655&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// InterlockedExchange(offset, 0x11223344);&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// InterlockedExchange(offset, 0x88776655);&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EXCEPTION_EXECUTE_HANDLER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


UINT
CALLBACK
&lt;span class=&quot;token function&quot;&gt;WatchThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HMODULE ntdll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;ntdll.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FARPROC ntop &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntdll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NtOpenProcess&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PUCHAR opcode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PUCHAR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ntop&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; PULONG offset &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; PULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;opcode&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        __try
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            ULONG k &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;InterlockedCompareExchange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;offset&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; offset&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; offset&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;k &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x88776655&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; k &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x11223344&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%p\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EXCEPTION_EXECUTE_HANDLER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE t1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_beginthreadex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; VPThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HANDLE t2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_beginthreadex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HookThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HANDLE t3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_beginthreadex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WatchThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;SetThreadPriority&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; THREAD_PRIORITY_TIME_CRITICAL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadPriority&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; THREAD_PRIORITY_TIME_CRITICAL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadPriority&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; THREAD_PRIORITY_TIME_CRITICAL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이쯤되면 이제 내가 이야기 하려는 말을 조금은 이해할 것 같다는 생각이 들어. 다시 한번 쉽게 설명하면 너네가 문지방을 수리하려고 하는데 그 문지방을 넘나드는 수많은 사람들이 있다는 거야. 문지방을 수리하다가 그 사람들과 부딪힐 수도 있겠지? 그럼 어떻게 해야 할까? 그렇지. 문지방을 수리하는 동안에는 사람들이 넘나들지 못하게 해야 하는거야.&lt;/p&gt;
&lt;p&gt;어떻게 하냐면 있잖아. SuspendThread라는 게 있어. 이 놈이 문지방을 넘나드는 사람들을 제어할 수 있게 해주거든. 그러니까 너네가 문지방을 수리하기 전에는 저 함수를 사용해서 사람들의 통행을 제어하는 게 안전하다고 할 수 있어. 그렇다고 단순히 죄다 SuspendThread를 시켜버리면 또 무슨 문제가 있냐면 SuspendThread 시키는 시점에 딱 문지방에 걸려 있는 놈들이 있을 수 있거든. 그런 놈들은 다시 ResumeThread를 하고 조금 있다 안전한 곳으로 이동했을 때 다시 SuspendThread를 해줘야 해. 복잡하지? 엄청 복잡해. 그런데 여기서도 끝이 아니야. 이건 진짜 기본적인 것만 말한거고 더 복잡하고 고려해야 할 내용들도 많이 있어. 시간나면 FlushInstructionCache 같은 API도 같이 공부해 보면 도움이 될 것 같아. 코드 하나 바꾸는데 왜 이렇게 알아야 하는게 많냐고? 너네 프로세스가 아닌 다른 프로세스에 끼어들어서, 그 끼어든 것도 모자라 대상 프로세스의 운영체제 코드를 변경하려는 일을 하려면 이정도 복잡함은 감수해야 하는거야.&lt;/p&gt;
&lt;p&gt;다양한 생각과 함께 깊이 있는 고민을 많이 하다 보면 어느날 문득 깨닫게 될꺼야. 아 인라인 후킹이라는 게 본질적으로 안전할 수가 없구나. 그냥 확률 싸움이구나, 하는 생각 말이야. 그나마 안전한 건 4바이트를 한 번에 변경하는 테이블 후킹 밖에는 없어. 인라인 후킹을 안전하게 하려면 운영체제 스케줄러를 제어하는 수 밖에는 없지. 하지만 그런 방법은 합법적으로 존재하지 않거든. 어쨌든 불완전한 방법이지만 지금은 광범위하게 사용되고 있는 기술인만큼 고민을 많이해서 최대한 안전하게 작성하는 요령을 터득하는 게 중요할 것 같다는 생각이 들어. 그리고 항상 생각해. 이게 과연 필요한가, 이게 과연 최선인가, 다른 방법은 없는가, 라는 것들을 말이야. 후킹을 하지 않는 것이 상책 중에 상책이라는 걸 꼭 명심했으면 좋겠다.&lt;/p&gt;
&lt;p&gt;조금 어설프고 서툴러도 괜찮아. 처음이잖아. 다음 번엔 고민을 좀 더 해서 꼼꼼하게 만들었으면 좋겠어. 아니면 상용 라이브러리를 쓰던지. 아니면 사장님한테 건의해. 그 많은 프로그래머 중에 똑똑한 애 한 명 시켜서 라이브러리 하나 만들자고 말이야.&lt;/p&gt;
&lt;p&gt;잘 지내고. 고생해!&lt;/p&gt;
&lt;p&gt;2013.06.17&lt;/p&gt;</content:encoded></item><item><title><![CDATA[건투를 빈다, 김어준]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/11156</link><guid isPermaLink="false">https://jiniya.net/wp/archives/11156</guid><pubDate>Tue, 21 May 2013 23:58:58 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;나이 들어 가장 비참할 땐 결정이 잘못됐다는 걸 알았을 때가 아니라 그때 아무런 결정도 내리지 못했단 걸 깨달았을 때다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;한 가지는 냉정히 인정하자. 아이디어는 사업이 아니다. 사업 해보지 않은 사람들이 흔히 하는 가장 큰 착각이 바로 그거다. 아이디어가 사업이 되기 위해선 수많은 장애를 넘어야 한다. 첫 번째 장애이자 초짜 대부분을 주저앉게 만드는 건 자본. 아이디어 하나로 손쉽게 자본을 모을 거라 여기는 건 사업을 해보지 않은 자들의 공통된 착각 중 하나다.&lt;/p&gt;
&lt;p&gt;그러나 설사 자본을 마련했다고 하더라도, 그 자본도 결코 사업이 아니다. 자본은 반드시 소진된다. 처음 사업하는 사람들에게 자본이 소진되는 속도는 공포다. 언제나 예상한 것보다 비용은 더 들고 수입은 예상치를 밑돌기 마련이니까. 그게 사업의 이치다. 당연하다. 시장에 갓 등장한 신참을 누가 주목하겠나. 아무리 아이템이 좋아도 시간이 소요되기 마련이다.&lt;/p&gt;
&lt;p&gt;그러나 사실은 자본 소진을 막아줄, 계약조차 사업이 아니다. 계약과 입금은 또 다른 거다. 사업을 하게 되면 계약에서 입금까지 얼마나 먼 거리인지 알게 된다. 통장에 돈이 찍혀 출금하기 직전까진 결코 내 돈이 아니다. 그리고 그런 입금이 안정적으로 지속되게 하는 건 또 다른 문제고. 최소한 6개월은 안정적으로 입금이 찍혀야 비로소 사업이라 할 만한 게 겨우 시작된 거다.&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;p&gt;그러니 만약 앞으로 정말 사업가가 될 생각이라면, 친구의 사업 시작을 오히려 남의 돈으로 공부 할 수 있는 절호의 기회라고 받아들이시라. 그 친구에게 부탁해 참여 기회를 잡으시라. 피해의식은 버리시라. 만약 그러는 게 고개 숙이는 것 같고 자존심 상해 도저히 못 하겠다면, 그런 마인드라면, 당신은 사업 같은 건 안 하는 게 낫겠다. 아무리 작은 사업도 그 정도 고새 숙이는 것보다 백만 배는 더 어려운 거니까.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;더구나 단위시간 내의 생산성이나 속도로만 승부가 나지 않은 일은 앞으로 얼마든지 있다. 기죽지 말고, 스트레스 받지 말고, 감정지수, 창의력, 자신만의 복합적 문제 해결 능력을 배양하시라. 아떻게? 사회적 관계를 확대하고 시대의 맥을 놓치지 말고 인간 심리의 본질을 탐구하고 크로스컬처한 경험을 축적하시라. 그러니까 사람 두루두루 사귀고 문화 경험 많이 하고 연애 많이 하고 여행 많이 가란 소리다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;이번 기회에 스스로 친구를 위해 내가 손해 볼 수 있는 한계는 어디까지인지. 따져보시라. 자신의 바닥이 어딘지 가늠할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;당신이 지불할 수 있는 비용은 어디까진가. 어느 것도 포기할 수 없다고? 그럼 아무것도 가질 수 없는 거다. 어느 것도 포기할 수 없다고 말하는 건 삶에 대한 응석에 불과하다. 어느 것도 포기할 수 없다가 아니라 어디까지 포기할 수 있는지를 생각해야 한다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;자존감이란 그런 거다. 자신을 있는 그대로, 부족하고 결핍되고 미치지 못하는 것까지 모두 다 받아들인 후에도 여전히 스스로에 대한 온전한 신뢰를 굳건하게 유지하는 거. 그 지점에 도달한 후엔 더 이상 타인에게 날 입증하기 위해 쓸데없는 힘을 낭비하지 않게 된다. 누구의 승인도 기다리지 않고 그저 자신이 하고 싶고, 재밌어하는 것에만 집중하게 된다. 다른 사람 역시 어떤 왜곡 없이 있는 그대로 받아들이며.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;사람이 나이 들어 가장 허망해질 땐, 하나도 이룬 게 없을 때가 아니라 이룬다고 이룬 것들이 자신이 원했던 게 아니란 걸 깨달았을 때다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;꿈이니 야망이니 거창한 단어에 주눅 들거나 현혹되거나 지배당하지 말고, 그저 자신이 죽기 전에 해보고 싶은 것들, 가보고 싶은 곳들, 만나보고 싶은 자들 따위의 리스트를 만들라. 그리고 그 리스트를 하나씩 지워가라. 사람이 왜 사느냐. 그 리스트를 지워가며 삶의 코너 코너에서 닥쳐오는 놀라움과 즐거움을 하나도 놓치지 않고 최대한 만끽하려 산다. 최소한 나는 그렇다. 건투를 빈다.&lt;/p&gt;
&lt;p&gt;– 건투를 빈다, 김어준&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[커뮤니케이션의 효율성과 따뜻함 사이 어딘가…]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/wp/archives/10554</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10554</guid><pubDate>Tue, 14 May 2013 23:58:57 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;제법 오래된 일이다. 언젠가 술자리에서 한 팀장이 그랬다. 다 좋은데 제발 “그래서 결론이 뭐예요”라는 이야기는 좀 안 했다면 좋겠다는 이야기. 그 말을 들을 때마다 숨이 막히는 느낌이 든다고 그랬다. 그땐 나도 내 나름의 변명이 있었다. 말하는 사람은 한 명이지만 듣는 사람은 한 사람씩 돌아가면서 한 마디만 해도 그 양이 어마어마하다. 그래서 앞뒤는 자르고 결론이 뭔지만 궁금했던 것이다. 어쨌든 팀장의 그런 고견을 듣고 나서는 주의해야 겠다는 생각을 했다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;얼마 전이었다. 한 업체 미팅을 하는 자리였다. 그때 나와 똑같이 효율성을 중시하는 담당자를 만나게 됐다. 앞뒤 자르고 결론만 듣고 싶어하는 그 담당자에게 적잖게 당황하면서 속으로 생각했다. 아 우리 회사 직원들도 나랑 이야기하면서 어쩌면 이런 기분이 들었을지도 모르겠구나. 난 그 담당자가 제법 마음에 들었는데 그 자리에 참석한 다른 사람들은 크게 좋아하는 분위기는 아니었다.&lt;/p&gt;
&lt;p&gt;미팅을 끝내고 돌아오면서 그런 생각이 들었다. 커뮤니케이션에 있어서 지나치게 효율성을 중시하는 것은 달작지근한 맛을 없앨 수도 있겠다는 생각. 어쩌면 커뮤니케이션에도 조그만 슬랙이 필요한지도 모른다. 그 조그만 슬랙이 낭비처럼 보일지 모르지만 그 조그만 틈이 이야기를 부드럽게 만들어주고 소통을 원활하게 만드는 건지도 모르니 말이다. 이유있는 낭비랄까?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;갑을 프레임이 들불처럼 온 나라를 뒤덮고 있는 요즘이다. 그들의 오염된 관계성에서 벌어질 수 밖에 없었던 일들도 있었겠지만, 어쩌면 우리 모두가 기본적으로 지나치게 효율성만을 추구한 결과는 아닐까라는 생각을 해봤다. 효율성은 조금 버리더라도 그 사이에 약간의 여백과 따뜻함을 채운다면 어쩌면 기존 방식보다 더 효율적인 결과를 얻을지도 모른다. 그리디 메소드가 항상 옵티멀 솔루션을 보장하지 않는 것과 같은 느낌이랄까?… 기독교에서 말하는 “가난한 마음”이 우리에게 간절한 시점이 요즘이 아닌가라는 생각을 해본다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;나는 문관이고 상대는 무관이라 하여 그를 괄시해서는 안 되며, 나는 세력이 강하고 상대는 힘이 약하다 하여 교만하게 대해서는 안 되며, 나는 현명하고 그는 어리석다 하여 그를 무시해서는 안 되며, 나는 늙었는데 그는 젊다 하여 서글퍼 해서도 안 된다. 엄숙하고 공손하고 겸손하고 온순하여 예의를 잃지 않으며, 화평하게 하여 뒤틀리고 막힘이 없게 하면 정과 뜻이 서로 통할 것이다.&lt;/p&gt;
&lt;p&gt;– 목민심서, 정약용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 데이터 마이닝에 관한 소고]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/10597</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10597</guid><pubDate>Mon, 29 Apr 2013 23:58:56 GMT</pubDate><content:encoded>&lt;p&gt;요즘 게임 보안 업계에 부는 바람 중에 하나가 데이터 마이닝이다. 빅데이터와 클라우드같은 요즘 가장 핫한 키워드와 어느 정도 관련성을 가지고 있기도 하고 학계에서 몇 해 전부터 꾸준히 밀고 있는 방법이기도 해서 업계의 조명을 한몸에 받고 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 데이터 마이닝 과연 효과적일까? 사실 난 현재 수준의 데이터 마이닝에 대해서는 조금 회의적이다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/4372&quot;&gt;지난 글&lt;/a&gt;에서도 밝힌 것처럼 지금 시도하는 내지는 주장되는 데이터 마이닝이라는 기법은 그 태생적인 한계를 가지고 있기 때문이다. 그럼에도 요즘 게임 업계에서는 마치 기존 게임 보안 솔루션보다는 데이터 마이닝 쪽의 접근이 훨씬 더 근본적인 문제 해결 방법이라는 인식을 가지는 것 같아서 몇 가지 생각을 좀 덧붙여 보려고 한다.&lt;/p&gt;
&lt;h3&gt;#0. 비용&lt;/h3&gt;
&lt;p&gt;엔씨소프트의 경우 리니지, 아이온, 블소와 같은 게임 로그 데이터가 하루에 2-3TB 가량이 쌓이고, 이를 2개월 가량 저장할 수 있는 데이터 마이닝 시스템을 구축했다고 한다. 이 시스템을 통해서 오토나 작업장 같은 부정 행위를 저지르는 사용자들을 색출해 내고 있다고 한다. 2-3TB를 60일 저장할 수 있다면 그것만해도 180TB의 저장 공간이 필요하다. 오류 등을 생각한다면 더 큰 저장 공간이 필요할 것이다. 이를 안정적으로 저장하고 관리하는 시스템을 구축하는 일만해도 보통이 아니다.&lt;/p&gt;
&lt;p&gt;하지만 문제는 데이터 저장이 아니다. 그 저장된 자료에서 의미있는 데이터를 뽑아내는 과정이 또 보통이 아니다. 오픈 소스 플랫폼을 사용해서 구축했다고 하는데 관련 분야의 인력이 부족한 실정을 고려해 본다면 결국 데이터 마이닝 시스템을 구축하는데에는 생각보다 많은 비용이 든다는 것을 알 수 있다. 게다가 아직까지는 게임 데이터를 마이닝하기 위한 맞춤형 솔루션을 제공하는 업체도 없기 때문에 바닥부터 모든 것을 직접 다 만들어야 한다.&lt;/p&gt;
&lt;p&gt;이쯤되면 결론이 나온다. 선도적인 업체에서 투자적인 목적, 내지는 훨씬 더 높은 수준의 사용자 감시 체계를 만들고 싶은 때에는 유효하겠지만 그렇지 않은 대다수 게임 업체제에서는 비용적인 측면 때문에 도입 자체가 쉽지 않다는 것이다.&lt;/p&gt;
&lt;h3&gt;#1. 속도&lt;/h3&gt;
&lt;p&gt;데이터 마이닝, 말만 들으면 뭔가 우아하고 근사해 보인다. 하지만 이 데이터 마이닝이 힘들 발휘하려면 결국 데이터가 쌓여야 한다. 데이터가 없으면 이 시스템은 그냥 깡통이다. 데이터가 쌓여야 한다는 말은 다르게 설명하면 플레이어가 시스템 기준치에 부합하는 부정 행위를 지속적으로 저질러 주어야 한다는 것을 의미한다. 이렇게 상당한 시간동안 시스템의 감시망에 부합하는 부정 행위를 저지르면 그 윤곽이 마이닝 결과를 토대로 드러나게 되고 그 사용자에 대한 제재를 할 수 있다. 현재 데이터 마이닝 시스템은 속도가 느리고, 그마저도 아주 느린 사후 대응을 할 수 밖에 없는 구조다.&lt;/p&gt;
&lt;p&gt;데이터 마이닝을 사용하는 업체들이 가지는 유일한 제재권은 계정 블럭이다. 계정 블럭도 좀 생각을 해 볼 필요가 있다. 크게 게임 결제 방식에 따라 두 가지로 나뉜다. 부분 유료화 게임과 계정비를 받는 정액제 게임이다.&lt;/p&gt;
&lt;p&gt;부분 유료화 게임의 경우 계정 블럭은 아무런 효용가치도 없다. 다시 계정을 생성하면 그만이다. 이 경우에 다시 세부적으로 나뉘게 되는데 우리 나라처럼 주민 번호라는 희소화된 식별 체계를 가진 경우에는 그나마 다행이다. 하지만 이런 체계를 가진 해외 국가는 거의 없다. 따라서 국내에서 계정 블럭을 사용할 수 있더라도 해외에서는 이를 사용하기가 쉽지는 않다. 물론 XIGNCODE3 와 같은 요즘 게임 보안 솔루션의 경우에는 이런 계정 블럭을 도와줄 수 있는 보조 수단들을 제공하고 있다. 그런 기능을 이용하면 좀 더 효과적으로 대응할 수 있지만 부정 행위를 저지르는 시점에 차단할 수 없다는 근본적인 문제점은 여전히 존재한다.&lt;/p&gt;
&lt;p&gt;다음으로 유료 게임이 있다. 유로 게임의 경우 계정 블럭이 의미하는 바는 블럭 당하는 사용자가 계정비를 날리게 되는 것을 의미한다. 즉, 그 계정비 만큼의 손해가 얼마나 큰지가 이 시스템이 유용성을 판단하는 근거가 된다고 할 수 있다. 그런데 이런 해킹 행위가 벌어지는 인기있는 유료 게임의 경우 계정비가 해킹을 시도하는 사용자 입장에서 의미있는 페널티가 되지 못한다. 실례로 부정 행위를 식별하는데 2일 정도의 시간이 필요하다고 가정 해보자. 그렇다면 이 2일의 시간동안 그 부정행위를 저지르는 사용자가 계정비 이상의 이익을 해킹을 통해서 창줄할 수 있다면 지속적으로 부정 행위를 저지를 수 있는 구조가 된다.&lt;/p&gt;
&lt;p&gt;결국 여기서 중요한 쟁점은 ROE다. 안타깝게도 부정 행위를 색출해기 위해서 걸리는 시간 동안에 작업장에서는 그 계정비를 회수하고도 남는 만큼의 부가가치를 창출할 수 있는 경우가 많다. 만약 이 부가가치를 창출할 수 없다고 판단되면 작업장이나 해커는 사라진다. 그런데 진짜 정말 안타깝게도 그들이 사라지는 이유는 데이터 마이닝 시스템이 제공하는 계정비 + 캐릭 성장 비용 때문이 아니라 해당 게임의 인기가 시들해졌거나 작업장 과다 경쟁으로 아이템 가격이 지나치게 떨어진 경우가 대부분이다.&lt;/p&gt;
&lt;h3&gt;#2. 판단 기준&lt;/h3&gt;
&lt;p&gt;한 플레이어가 게임에서 한 시간내에 연달아 100번의 승리를 하는 것이 사실상 불가능 하다고 생각해보자. 게임 업체는 이를 토대로 기준을 세운다. 마이닝 시스템에서 한 시간내에 연달아 100번의 승리를 한 사용자를 찾는 것이다. 그런데 이런 모든 기준은 정상 사용자가 우연찮게 해낼수도 있기 때문에 게임 업체는 여기에다 허용 오차를 추가한다. 즉, 초범이라던지 어쩌다 한 번인 경우는 패스시켜준다는 의미다. 그걸 넘어서 지속적으로 한 경우에는 실질적인 계정 블럭을 시킨다.&lt;/p&gt;
&lt;p&gt;말만 들으면 그럴듯 해 보인다. 하지만 말만 들었을 때 이야기다. 해커들이 어떻게 할 것 같은가? 영원히 저 룰을 못찾아서 방황하면서 모든 계정을 다 블럭당할까? 절때 아니다. 99번의 승리만 가져가면 잡히자 않는다는 것이 순식간에 퍼진다. 이걸 찾는데 아주 오랜 시간이 걸릴 것 같지만 아이러니하게도 생각보다 아주 손쉽게 발견된다. 심지어는 해커가 그걸 찾으려는 시도를 하지 않음에도 밝혀진다. 바로 사용자에 의해서 말이다. 인기있는 게임의 경우에는 해킹툴 사용자도 광범위하게 퍼져있고 그 사용자들은 제각각 다른 방식으로 해킹툴을 사용한다. 따라서 이런 집단 지성이 모이게 되면 모호할 것 같았던 게임사의 제재 룰도 연립 방정식이 풀리는 것처럼 손쉽게 단 하나의 해가 밝혀진다. 여기에 사람 심리가 더해지면 정보 공유 속도는 더 빨라진다. 해킹툴 사용자 중에 계정 블럭을 당하지 않은 사용자가 있다면 그걸 자랑하고 싶어하는 사람 심리가 생긴다. 마치 대단한 비밀을 알고 있는 것처럼 게시판에서 자랑질을 하게 되도, 그걸 또 증명하기 위해서 소수 사람들과 공유한다. 여기까지 가면 이미 모든 사람이 그 방법을 알게되는 것이나 다름 없다.&lt;/p&gt;
&lt;p&gt;다시 돌아가보자. 게임 업체가 그래서 기준을 조정했다. 90번으로 줄이고 허용 오차도 좀 더 늘리도록 했다. 이번에도 해커는 기준치를 찾는다. 다시 조정한다. 70번에 허용 오차를 왕창 늘린다. 당연히 이번에도 찾는다. 그렇게 기준을 조정하다 보면 어느 순간에는 아주 일반적인 플레이어들이 심심치 않게 해낼 수 있는 수준까지 낮아진다. 마이닝 결과에 노이즈가 너무 많이 섞이고, 결국 데이터는 쓸모없게 되는 구조다.&lt;/p&gt;
&lt;h3&gt;#3. 치명적인 마이너리티 리포트&lt;/h3&gt;
&lt;p&gt;오진은 항상 문제다. 근데 이게 데이터 마이닝에서는 더 치명적이다. 예를들어 사소한 게임 보안 제품의 오진 같은 경우에는 정상적인 사용자의 경우에 다른 컴퓨터를 사용하거나 컴퓨터를 포맷하거나 하는 형태로 플레이를 이어갈 수 있다. 하지만 데이터 마이닝의 결과로 계정 블럭을 당하게 된다면 그 페널티는 엄청나다. 물론 사용자가 소명 절차를 걸쳐서 계정을 다시 복구할 수도 있겠지만 대다수 사용자는 그렇게 하지 않는다. 여기에는 사람의 감정적인 요인이 더 많이 작용하는데 정상적인 나를 이렇게 영구정지 시킨 게임을 내가 돈내고 해야 하는 이유를 찾을 수 없다고 생각하는 사람 심리 때문이다.&lt;/p&gt;
&lt;p&gt;데이터 마이닝을 통한 계정 블럭은 진짜 최후의 수단이며 사용하지 않는 편히 오히려 게임 동접 건전성을 유지하는데 도움이 될지도 모른다. 왜냐하면 해커는 계정 블럭을 당해도 바로 새로운 계정으로 해킹을 이어갈 것이고, 정상 사용자는 사람 심리 때문에 그 게임을 떠날 것이기 때문이다. 결국 오토만 남아 있다가 그마저도 블랙 마켓이 힘을 잃는 순간 게임 속에는 아무도 없는 처참한 현실이 도래할 수 있다. 실제로 작년 하루에 2-3만 개씩의 오토 사용자를 색출해 낸다는 패기를 보여준 온라인 게임이 있었다. 하지만 패기는 패기로 끝난 것 같다. 오픈하고 얼마 지나지 않아서 인기가 시들해졌기 때문이다.&lt;/p&gt;
&lt;h3&gt;#4. 데이터 마이닝 그럼 쓸모 없을까?&lt;/h3&gt;
&lt;p&gt;약점들을 이야기 했지만 현재 수준의 데이터 마이닝도 완전히 쓸모 없지는 않다. 데이터 마이닝 시스템의 가장 큰 장점인 알려지지 않은 해킹툴에 대해서 높은 대응력을 구축할 수 있다는 점 때문이다. 마이닝 시스템을 페널티 없이 모니터링 용도로만 사용하더라도 의미가 있다는 말이다. 어느 정도의 해킹툴 사용자가 존재하는지 아는 것과 모르는 것은 천지 차이기 때문이다. 또 그 사용자의 시스템을 좀 더 집중적으로 분석 한다면 알려지지 않은 해킹툴의 실체에 대해서 판단할 수 있고, 더 나아가서는 모니터링 단계에서 색출한 사용자에 대해선 일반적인 경우와 다른 높은 수준의 보안 정책을 제공할 수도 있다.&lt;/p&gt;
&lt;p&gt;몇해전 우리가 야심차게 진행했다가 포기한 내용 중에 하나가 화이트 기반 정책이 있다. 세상의 모든 깨끗한 바이너리 파일이 웰비아닷컴을 통하도록 만들자는 계획으로 야심차게 진행했지만 게임 업체들의 이해 관계와 깨끗한 바이너리 파일이 우리가 당초 예상한 것보다 너무 많다는 이유 때문에 결국 우리는 방향을 틀었다. 하지만 제한된 환경에서는 이런 것들이 의미있을 수 있다. 일례로 최근에 우리는 서비스하고 있는 게임 퍼블리셔로부터 온라인 게임 대회 서버에만 좀 더 높은 수준의 보안 정책을 유지할 수 있냐는 질문을 받은 적이 있다. 대회 서버에는 제한된 사용자가 참여하고 악성코드와 같은 엉뚱한 것들을 허용할 필요가 없기 때문에 화이트 정책을 사용하기에 안성 맞춤이다. 마찬가지로 데이터 마이닝 시스템의 결과물을 게임 보안 솔루션에 접목한다면 좀 더 효과적인 페널티 정책과 함께 높은 수준의 게임 보안 서비스를 유지할 수 있을지도 모른다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/archives/1497&quot;&gt;세상은 0.1%의 프론티어와 0.9%의 동조자들 그리고 99%의 잉여로 돌아간다고 한다.&lt;/a&gt; 그러니 쓸모에 관계없이 여유 있는 게임 업체라면 이러한 방향의 연구를 지속적으로 수행하는 것이 바람직하다. 그래야 지금의 우리는 아닐지 몰라도 우리의 자식 세대, 내지는 입는 컴퓨터를 초딩때부터 착용할 자식의 자식 세대에는 보다 유쾌하고 공정한 온라인 게임 환경을 접할 수 있을테니 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;덧) XIGNCODE3 개발팀에서는 기존 방식과는 다른 데이터 마이닝과 같은 대안적 게임 보안 솔루션에 대해서도 관심이 많습니다. 이런 백엔드 시스템 구축에 관심이 있거나 경험이 있는 분, 파이썬을 다룰줄 알고 웹 프로그래밍을 어느 정도 할 수 있는 분을 찾고 있습니다. 적어놓고 보니 뭐 맥가이버군요. 작은 회사들이 찾는 사람이 다 그렇겠지만 ㅠㅜ~ 어쨌든 이런 일들에 관심 있으신 분들은 codewiz at wellbia.com으로 연락 주세요.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_데이터_마이닝에_관한_소고.md_0.png&apos; data-alt=&apos;해커는 피하고 게이머는 원하는…&lt;br&gt;&lt;br&gt;평판은 하루 아침에 만들어지지 않습니다.&lt;br&gt;&lt;br&gt;XIGNCODE3는 여러분의 게임을 공정하게 만드는 가장 손쉬운 방법입니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/73fa7017948c6db530fd6ef8d42a9475/5d5ad/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EB%A7%88%EC%9D%B4%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%9C_%EC%86%8C%EA%B3%A0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 132.63157894736844%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAA7AAAAOwAFq1okJAAAEl0lEQVR42m1UC28bRRD2HwcJCQEl0Fag0oKKKmgFKlBKqfpI4taxz68mbtw4ceLz3T7uuXu3t/fy2T6fH2EuKa0qGI9G4939bmdnvpkKJgRj4rqOruuGYVqWZRgUwxKlIggopbZtc84Xi8X5f6QyGBx1Om0QpdlqtdoH+/v9fr+hKL3eATjlbrcLG8fHxyfDYRhFgNlsNm/Bk8kkjqK0lCRNkmmWzaZTsNNsOknT+XweCOFxDltwbJHnH9zMXFdFyPF8maRBHHMpgyjyZMiDwPV81/O4CDwpRRgxT4CfzWbvwZqun9Qbx48f9x89Hjx5MtrZIY0GqtVARzu7J0+fjbZ3wVF3q6Vu78jR6F3kFVVVO3t7/Xb7VW1PHwxcTbNGKseYgSLEMLLHmjUeO5oGDhkOGaXvbyaEQCrgfg2TMJsGEHyayjT1A+kHgZCl9YQAWzq+EIGE94NkWVYxsWVigxLTPDkb7b7E9SbaU5yDXsDg1SCQAxmIwPd9KYJQhoD2uAcC6xVYYi5jLheOyzXd05Cnl9aHFREIuArEF1JIvwxAlAFcfGVRFBWKiHqmqqfq+ExXVR3pmHHPZdyxHdu0Xdt1bccxHfi6Y9qOVS6a1LBMazabVcIwlLKMDT52oTKO40kKNU6BAmDjJImAHFF4SbLLPG8upAIAj0E1feCgazOPgXUY/GyHgw9vYeADfd1ski2Xq2WxLBbFer0us32Z9EW+MAm1qOFYtoEJ1pBJDBMZJjYtYlGETUyB8UTD+kizDLMoihI8LwrIepikPgQep1E6CaJYxgk4JeeiJEwnIVA3m8ZZBlvpPF9vyrhLcHI8QLtVXKtZStNpd9CL0rFbLfyiZioKqFFX8IuX5WKzhet11lBWvn9+8e6K7Hbx8JSONVNHlo7A2pg4mBiaZmi6TYgx1qg6JqAjFWu61NHqkmQAjpstY6+OGorV6VrtDm40cL2B6g3SUMAxWm3cUGizRRQF1fZwsyU7nRUhb8GBbY96h/rRYPzmiA5PPbhW0xjwhFCfUKYjYLgPI2GMTBUJaiSMr/4dDJXZPBdQ3jgGC8WeQC/PZnGagp3mORQ9gXpnGReRbkgAQLY27xpjxvmMsVyIVZblgSjiGPxlkhRxkoch+NNYupbObMRs3TF1k6iXatFxRXDuu24MJBMCWB8Bc3nJGOF5cQiFAmpJ4TPh83w+hYeu18v1qgBdLvNKFMMZMLEHfQM0DYLyT5zMZ9mD+/euX7t667sb39+8eePbb+78ePve3Z/v/nTn/q+/PPjjt+rOdgVeBG0DICA5dCkgp7PpPF+kIa8+vP38yZ/V7UfV5389/fv3nWcPQVv1571u7eRo37LMEuy6LiDfzQdg/AV1N8yx+q9fvTncP+x1jw4PzoaDQf/14UG333vlMadMmOM4BjVNw9KhHRHWxuOxqg0Gx9BUL6vVTz7+aOvKla0rn1/b+vKHWzevf3316ldbX3z2abvVLMHQLhhRk1qAJzolmIJjEMMue5j53PdcwZkHWfifoR/4EjrRhZMwAWDSMh/ak7kejAHoRPgE7FoGnOCbD+X8/PwfEi+dkZlFcDgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;해커는 피하고 게이머는 원하는…&lt;br&gt;&lt;br&gt;평판은 하루 아침에 만들어지지 않습니다.&lt;br&gt;&lt;br&gt;XIGNCODE3는 여러분의 게임을 공정하게 만드는 가장 손쉬운 방법입니다.&apos; title=&apos;&apos; src=&apos;/static/73fa7017948c6db530fd6ef8d42a9475/5d5ad/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EB%A7%88%EC%9D%B4%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%9C_%EC%86%8C%EA%B3%A0.md_0.png&apos; srcset=&apos;/static/73fa7017948c6db530fd6ef8d42a9475/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EB%A7%88%EC%9D%B4%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%9C_%EC%86%8C%EA%B3%A0.md_0.png 190w,
/static/73fa7017948c6db530fd6ef8d42a9475/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EB%A7%88%EC%9D%B4%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%9C_%EC%86%8C%EA%B3%A0.md_0.png 380w,
/static/73fa7017948c6db530fd6ef8d42a9475/5d5ad/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EB%A7%88%EC%9D%B4%EB%8B%9D%EC%97%90_%EA%B4%80%ED%95%9C_%EC%86%8C%EA%B3%A0.md_0.png 610w&apos; sizes=&apos;(max-width: 610px) 100vw, 610px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;해커는 피하고 게이머는 원하는…&lt;br&gt;&lt;br&gt;평판은 하루 아침에 만들어지지 않습니다.&lt;br&gt;&lt;br&gt;XIGNCODE3는 여러분의 게임을 공정하게 만드는 가장 손쉬운 방법입니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[보안 프로그래머란 업에 관해서 …]]></title><description><![CDATA[최근 몇 년 사이에 해킹 사건이 부쩍 늘었다. 잊을만하면 한번씩 대규모 해킹 사건이 발생하면서 이제는 컴퓨터를 모르는 동네 아줌마들도 좀비 PC, DDoS…]]></description><link>https://jiniya.net/wp/archives/10952</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10952</guid><pubDate>Tue, 23 Apr 2013 23:58:55 GMT</pubDate><content:encoded>&lt;p&gt;최근 몇 년 사이에 해킹 사건이 부쩍 늘었다. 잊을만하면 한번씩 대규모 해킹 사건이 발생하면서 이제는 컴퓨터를 모르는 동네 아줌마들도 좀비 PC, DDoS같은 용어를 자연스럽게 사용하는 세상이 돼 버렸다. 해킹이 얼마나 큰 문제인지에 대해서는 온동네 사람들이 다 알고 있다. 그림자가 있어야 빛의 존재가 부각되는 것처럼 이런 상황은 우습게도 상대적으로 보안을 더 돋보이게 만드는 흐름을 만들었다. 그래서인지 요즘 부쩍 보안 쪽 진로를 물어보는 프로그래머들이 늘었다.&lt;/p&gt;
&lt;p&gt;근 10년간 PC 보안 이라는 분야에서 프로그래머로 일하면서 내가 느낀 것은 이 분야만큼이나 성격이 적성에 많이 관여하는 곳도 없다는 생각이다. PC 보안 쪽의 진로에 대해서 약간 이나마 고민하는 사람이 있다면 자신의 성격이 여기에 나열된 것들과 맞는지 잠깐 고민하는 시간을 가져보도록 하자. 진로를 결정하는데 약간이나마 도움이 되지 않을까라는 생각을 해본다. 물론 이런 성격이 아니어도 맡은 업무를 훌륭하게 잘 할 수는 있다. 하지만 일하는 매 순간 순간이 즐겁지 않다는 데에 100원쯤은 걸 수 있을 것 같다.&lt;/p&gt;
&lt;p&gt;변화에 대한 관성이 낮은가? 보안 쪽은 변화가 굉장히 심하다. 왜냐하면 보안 관련 코드는 다양한 코드 중에서도 항상 해커의 첫 번째 공격 대상이 되기 때문이다. 취약점은 감기처럼 보안 제품을 따라 다닌다. 따라서 그 어떤 분야보다 보안 프로그램은 고칠 일이 많다. 취약점이 간단한 것이면 다행인데 어떤 경우에는 설계 전체를 뒤집어야 하는 경우도 있다. 현장에서는 설계 전체를 뒤집는 일도 대수롭지 않게 벌어진다. 그래서 변화에 대한 관성이 강하다면 이쪽 분야에서 일하는 것이 고역일 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;경쟁 상황을 즐기는 편인가? 사람은 크게 경쟁에 대해서 두 가지 다른 반응이 나타난다. 한 부류는 경쟁에 내몰리면 긴장해서 평소보다 실력 발휘가 안 되는 쪽이고, 다른 한 부류는 경쟁할 때 오히려 능력이 돋보이는 집단이다. 당연한 이야기겠지만 전자인 사람들은 경쟁 상황을 본능적으로 싫어한다. 하지만 후자인 사람들은 그런 상황을 즐긴다. 보안은 해커와의 전쟁이 항상 벌어지는 곳이다. 매일 매일을 전쟁 같은 심각한 경쟁 조건 속에서 일한다. 따라서 이러한 상황 자체가 싫다면 이 쪽 일이 본질적으로 즐거울 수가 없다. 해커의 공격에 무력해진 코드를 보면서 어 그래 이번에 이 문제를 고쳐서 다시는 못 뚫게 만들어야지, 라는 생각을 해야 한다. 대신 왜 매일 이렇게 뚫리는 거지, 이 싸움은 언제쯤이면 끝날까, 라는 생각을 한다면 일이 즐거울 수가 없다.&lt;/p&gt;
&lt;p&gt;자존감이 강한가? 보안 쪽 일은 안타깝게도 고맙다는 말을 들을 일이 거의 없다. 왜냐하면 문제가 생기지 않는다면 보안 제품이 잘 막아서 문제가 없는 것이 아니라 공격이 없었다고 사람들은 생각하기 때문이다. 반면에 아주 사소한 문제라도 생긴다면 보안 제품이 왜 그런 것도 방어하지 못하냐는 클레임만 잔뜩 듣는다. 자존감이 낮다면 그런 상황을 버틸 수가 없다. 외부의 비판 속에서도 자신의 성취에 대해서 객관적인 시각을 가질 수 있는 그런 정도의 강한 멘탈이 필요하다.&lt;/p&gt;
&lt;p&gt;윤리적인 사고에 익숙한가? 보안 쪽 일을 하다 보면 옳고 그른 일의 경계가 모호해지는 경우가 많다. 당장의 당근에 눈이 멀어서 범죄를 저지르는 그런 사소한 일을 말하는 것이 아니다. 가령 2차 대전 당시에 독일군의 암호를 해독한 앨런 튜링은 옳은 일을 한 것일까? 반대로 독일군 입장에서 연합군의 암호를 해독한 엔지니어가 있다면 그 사람은 어떻게 판단해야 할까? 조국의 이익을 위해서 다른 나라를 공격하는 악성 코드를 만드는 일은 과연 옳은 일일까? 반대로 객관적인 입장에서 우리나라에 존재하는 나쁜 시설을 파괴하는 코드가 있을 때 그것을 분석해서 차단하는 것이 옳을까? 그 시설이 파괴되도록 놔두는 것이 옳을까? 보안과 악의적인 해킹은 마치 동전의 양면 정도의 차이 밖에 나지 않는 경우가 많다. 윤리적인 추상적 사고나 본인만의 뚜렷한 윤리적 입장 없이 이런 복잡하고 애매모호한 상황에 자주 놓이게 되면 어느 순간 자신이 옳은 일을 하고 있는지 아니면 범죄를 저지르고 있는지 모호해지는 경우가 한두 번이 아니다. 따라서 윤리적인 추상적 사고에 익숙하지 않다면 이 쪽 분야에서 일하는 것이 상당히 위험할 수 있다.&lt;/p&gt;
&lt;p&gt;사실 여기까지만 들으면 보안 프로그래머는 정말 못해 먹을 짓이다. 맨날 고쳐야 하고, 공격 당하고, 욕만 먹고, 게다고 범죄 행윈지 착한 짓인지 분간도 잘 되지 않으니 말이다. 하지만 프로그래머 입장에서 좋은 상황도 여럿 있다.&lt;/p&gt;
&lt;p&gt;우선은 감성적인 부분이 크지 않다는 점이 있다. 여러분이 UI를 하거나 게임을 만들거나 워드프로세서를 만들거나 심지어는 압축 프로그램을 만든다고 해도 거기엔 감성이 작용할 부분이 다분하다. 여러분은 퐌타스틱한 기능이라고 만들었는데 다른 사람들은 싫어할 수 있다는 말이다. 2픽셀 두께가 괜찮아서 그렇게 만들었는데 다른 사람들은 3픽셀을 좋아할 수도 있다. 아트적인 감성이 있는 사람이라면 이런 상황을 즐길 수도 있겠지만 논리적인 감성만 있는 사람이라면 이런 상황이 정말 헬이다. 하지만 보안 쪽 일은 이런 부분이 거의 없다. 정답이 맞고, 제대로 동작한다면 크게 딴지 걸릴 일이 없다.&lt;/p&gt;
&lt;p&gt;미션이 명확하다. 앞선 이야기의 연장선인데 대부분의 도메인에서는 특정 프로그래머의 역량을 가늠하기가 쉽지 않다. 그런데 보안 쪽은 미션이 명확하기 때문에 누가 잘하는지 못하는지가 명확하게 구분된다. 찾아내고 탐지하고 방어하고 치료하면 된다. 매우 쉽다. 그걸 해내는 사람과 그렇지 않은 사람은 눈에 띄게 차이가 난다. 이 말은 돌려 말하면 그 어떤 분야보다 손쉽게 록스타 대접을 받을 수 있다는 의미이기도 하다. 실력만 있다면 말이다. 참고로 문제는 널려 있다. 풀기가 어려워서 그렇지…&lt;/p&gt;
&lt;p&gt;유행은 돌고 돈다. 취약점도 돌고 돈다. 새로운 시스템에서 새로운 취약점이 나오기도 하지만 과거 유행했던 일들이 돌아가면서 다시 재탕되기도 한다. 이 말은 히스토리만 알고 있어도 반쯤은 먹고 들어갈 수 있다는 말이다. 또 새로운 시스템을 구성할 때에도 후배들에게 그렇게 쪼다같이 만들었다가 과거에 A, B, C란 취약점과 D, E랑 충돌나서 x고생 했다는 이야기를 해줄수도 있다. 생각보다 경험과 경력이 든든한 진입 장벽이 되어 주는 곳이기도 하다.&lt;/p&gt;
&lt;p&gt;끝으로 사족을 하나만 덧붙이지만 개인적으로 여러분이 경제적 여유를 가진 상황에 태어났다면 자선 사업을 하기를 권하고 싶다. 여러분의 돈을 나눠주는 일을 하면 우습게도 매일같이 고맙다는 말을 들을 일 뿐이고, 그렇게 골치 아프지도 않고, 실수 한번이 치명적이지도 않다. 그러다 심심해서 코딩 하고 싶은 날에는 남는 시간에 오픈 소스 작업에 기여를 하면서 다시 고맙다는 소리를 들으면 된다. 환상적이다. 물론 여러분이 남에게 나눠주고도 먹고 살 만큼의 경제적 여유를 가지고 있다면 말이다. ㅋ~&lt;/p&gt;
&lt;p&gt;남의 돈을 빌어먹는 업이란 그 자체로 본질적으로 고달픈 일이다. 업이 요구하는 자질과 자신의 성격이 잘 맞다면 그나마 과정 속에서 느끼는 고통은 좀 덜할 것 같다. 성격은 생각보다 쉬이 바뀌지 않는다. 대체적으로 업에 성격을 맞추는 것보단 자신의 성격에 어울리는 업을 찾는 것이 훨씬 더 쉽다. 그러니 다시 한 번 잘 생각해보자. 나는 어떤 사람인지 말이다.&lt;/p&gt;
&lt;p&gt; 12
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[여유를 안 가지면 시간은 언제나 없지~]]></title><description><![CDATA[인터폰 소리에 깨어난다. 이 시간에 누구지? 회사 직원이다. 자꾸 POC…]]></description><link>https://jiniya.net/wp/archives/9627</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9627</guid><pubDate>Tue, 16 Apr 2013 23:58:54 GMT</pubDate><content:encoded>&lt;p&gt;인터폰 소리에 깨어난다. 이 시간에 누구지? 회사 직원이다. 자꾸 POC를 가야 한다는 말만 반복하는 그를 돌려 보내고는 씻고 금방 나가겠다고 했다. 면도도 하는 둥 마는 둥 머리에 물칠만 하고 밖으로 나갔다. 밥 먹을 시간도 없어서 서브웨이 샌드위치 하나로 택시에 올라탔다. 왜 갑자기 POC에 가야 하는지도 모른체…&lt;/p&gt;
&lt;p&gt;꼭 10년 전이었다. 그 당시 내가 일했던 회사에는 BMT가 많았다. 으레 BMT가 그렇듯 우리는 전혀 없던 기능을 전 날 무리하게 구현하거나, 크로스 해킹을 위해서 경쟁사 제품을 무력화 시키면서 밤을 보내곤 했다. 사실 BMT에는 직접 참여도 하지 않는 말단 사원이라 난 나에게 주어진 일만 열심히 하면 됐었다. 다음날 BMT 당일인데 참석해서 프리젠테이션을 해야 하는 실장님이 연락이 안 되는 상황. 급기야 아파트로 찾아 나섰다. 그 장면이 머릿속에서 오버랩 되면서… 나를 찾아 왔던 직원도 십 년 후에는 어디선가 누군가 인터폰으로 깨우는 소리에 일어날지도 모르겠다는 생각을 해봤다.&lt;/p&gt;
&lt;p&gt;얼마 전에 근처 회사에 다니는 학교 후배 녀석이 저녁에 전화를 해 왔다. 시간 있냐는 질문에 당연히 있다고 대답했는데 그 녀석이 정말 신기하다고 했다. 내가 안 바쁘다고 대답한게 한참만이라는 반응이었다. 그 때 머리를 엄청 큰 해머로 두드려 맞는 느낌이 들었다. 아, 내가 뭔가 아주 심하게 잘못 살고 있구나. 후배 녀석과 커피 한 잔 마실 여유도 없이 사는게 내가 원한 삶은 아니었는데 말이지. 무슨 일이 그렇게 중요하다고 바쁘다는 말을 입에 달고 살았지. 반성했다.&lt;/p&gt;
&lt;p&gt;POC 행사를 마치고 돌아오는 택시 안. 일정을 묻는 전화가 여기 저기서 쏟아진다. 다음주까지 해드릴께요. 다음주 수요일까지 드려도 될까요? 늦어서 죄송합니다. 다음주에 해 드리도록 하겠습니다. 그러고보니 지난 주에 다음주에 구현해 준다고 했던 기능들이 생각났다. 오늘이 금요일인데. 어쩌면 난 다음주에 살고 있었던 건 아니었을까?&lt;/p&gt;
&lt;p&gt;여유를 가지자. 조급한 마음만 가지고 일이 빨리 끝나는 건 아니니까 말이다. 어차피 잘 먹고 잘 살자고 하는 거. 냉정하게 생각해보면 그리 죽도록 중요한 일도, 미칠듯이 급한 일도 없다. 쉼표와 빈칸, 그리고 여백이 좀 필요하다. 바람처럼 왔다가 먼지처럼 가는 게 인생사 아니던가 ㅋ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Merovingian&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, of course, who has time? Who has time?&lt;/p&gt;
&lt;p&gt;But then if we do not ever take time, how can we ever have time?&lt;/p&gt;
&lt;p&gt;하지만 여유를 안 가지만 시간은 언제나 없지&lt;/p&gt;
&lt;p&gt;– 매트릭스2 리로디드, 2003&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[프로그래머, 전망보고 선택 하진 맙시다~]]></title><description><![CDATA[#0 우리가 지금 빌게이츠를 꿈꾸는 건 중세 시대에 귀족이 되는 것 만큼 어려운 일이다. 알랭 드 보통 아저씨는 말했다. 일반 사용자용 소프트웨어 세계는 철저하게 승자독식으로 돌아가는 세상이다. 이 동영상이 말하지 않는 것. #…]]></description><link>https://jiniya.net/wp/archives/10772</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10772</guid><pubDate>Mon, 15 Apr 2013 23:58:53 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.ted.com/talks/alain_de_botton_a_kinder_gentler_philosophy_of_success.html&quot;&gt;우리가 지금 빌게이츠를 꿈꾸는 건 중세 시대에 귀족이 되는 것 만큼 어려운 일이다.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;알랭 드 보통 아저씨는 말했다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;일반 사용자용 소프트웨어 세계는 철저하게 승자독식으로 돌아가는 세상이다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이 동영상이 말하지 않는 것.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; margin-bottom: 16px;&apos; data-url=&apos;./프로그래머,_전망보고_선택_하진_맙시다~.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b8679ba184d4fd2deee6e4cdf7c28671/5d5ad/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 38.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABoElEQVR42i2QyUvDQBTG8y+KiKC41ZPL0ZOiIOihVYpKWxWpG4IriihVQVBRamsrisGFarqaZYzRNumkWSYZZxLfZR7fvOX3PqbeMBUV5j/Be0Uq8OCNK3HFck2Dmm4YpoUxNi27Ui4JovgjAwAkQZQ0VSW667oMeRzHkWXAV0qK8q1WFU3TMA2X6K5Ls2dOOjs6WTljObHm1XsqxgxCCMK6Dp0XQc6+CuwntpDrDcY2QiTJfCgd0exkMN4ZvgosZt94urZhWKSRwbTSuc1cL+ykNi5zM4mfk8eaB0WJyN/oFts6kxqKnvfPJ1vCydDhKxEL+TwBpNgN9ev6YiKxH44cPIzvFse33kHV8rlN2xmM33dFUj3RdG8s3T6XGtl8Iuu+gAQhpM1Iln8jUSUWyiytDyy/DCw9ib8G0X3suUSuefqmN3YXiKWbpm5WLwoU1TOD8U/n1+MPgY5iX/fo8FrwtOxjI0SxpWpjbJttm022BM8n99iabvtW02Zd18kYG0L+YJcLTeSOjqumQ4iJH/7NJAzbyQkaB+o2+ld8t/8AY3KcurPLDIEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                       md 0&apos; title=&apos;&apos; src=&apos;/static/b8679ba184d4fd2deee6e4cdf7c28671/5d5ad/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_0.png&apos; srcset=&apos;/static/b8679ba184d4fd2deee6e4cdf7c28671/08678/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_0.png 190w,
/static/b8679ba184d4fd2deee6e4cdf7c28671/2edd7/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_0.png 380w,
/static/b8679ba184d4fd2deee6e4cdf7c28671/5d5ad/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_0.png 610w&apos; sizes=&apos;(max-width: 610px) 100vw, 610px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;이보다 더 승자독식인 세상이 있을까?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 294px; margin-bottom: 16px;&apos; data-url=&apos;./프로그래머,_전망보고_선택_하진_맙시다~.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c69bd711d05ec41fd7de15d2054ddf6b/b27a5/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 126.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAIAAAC+dZmEAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAC90lEQVR42l2U647aMBCF8/7v1N8rVepWoojudoFA7heSkBg7wQnQzxk2W9WyrJnxGXsux/aUsa22yozMzjih0xZB5qfdrbqfgqzdx02Qt29+WXeD16hrdTa/3pNLb2/3x3S7v27i10003e/I0+2RlerHOrTjjd1j0rz89L+9vH9fHc9q8IraHJI2SLu40Puw8qP6bZdvttnvbbI9lkmpw1wdU5WUlyhXZTMA+3Osq87GxcWbptv1apmPxyOOk6Io8jxnDYKgqiqMrFiAIff9EIZRnuVKXVCd8ziOw3AlrKY5T9OEFVkGAlv4AEO2dsTtctFchuqxp/Wl73tr7fl8TtM0juPT6TSfOGCs65pArvPglKZpiMUYg4rz4I7SWnBRFAEFgTPbrF3XcRYwZO4oyxPOSilUFzbBMBE4WGsDghDHcWKKkSkyKwGjCt5DwYHgSZVTD4cj989pP8h5NpZRFOOGjE+W5WmaGdM/C0bAHEsYCJIbZ0kVrRvE71YZAhCwx7VNU3ddi/t6vV6tVjSJmnHhZrPBnqbJdrs1RoPvexNFIQBKi+pJGpI2wSw3IFDFOQQXlgD+2XXU8MieumMlh6Ioff8QBCFMOJ0qUmbWdYOFhgDgIDDkjNeSs0sPgRS6TnE/UyygkSGGsEJUPFFdtZHoszRdWkqfsyyDLRiJkOLT2M9COpJQjidJOEecSYMNfJIkIewkidkiXUELSViROR0XR5KlYIRBYkxiEVYLMSgbYS8kmZMyT5Kgk540fS5GKi+GUrkX7F5VTYWggjwYSMJ8kgTnhSSzPAoBWaUlc4fs0qFFdSQherKC6Chw4+PjY7fbhWGAUUAY9/u9FIUVlU5CEucsN8tYLpc4hK32//G1Je+ZuluS5GH4vr+QRB5DWVbkzDtDpkhwhg/niySSD9sLPaSk0/x9SIdF/vyzXDioPAzdti0rpvknSeA9CdNkAQlt6PD8k/SAabXgXcHwkW8IHBHzhkBLhYgIetE/AEISCMd/KCT5C7WVlq2bLnSwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                       md 1&apos; title=&apos;&apos; src=&apos;/static/c69bd711d05ec41fd7de15d2054ddf6b/b27a5/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_1.png&apos; srcset=&apos;/static/c69bd711d05ec41fd7de15d2054ddf6b/08678/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_1.png 190w,
/static/c69bd711d05ec41fd7de15d2054ddf6b/b27a5/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%2C_%EC%A0%84%EB%A7%9D%EB%B3%B4%EA%B3%A0_%EC%84%A0%ED%83%9D_%ED%95%98%EC%A7%84_%EB%A7%99%EC%8B%9C%EB%8B%A4~.md_1.png 294w&apos; sizes=&apos;(max-width: 294px) 100vw, 294px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;1위부터 10위 까지가 전체의 70%를 차지하는 세상.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;작가와 제빵사의 차이, 투기꾼과 의사의 차이, 사기꾼과 창녀의 차이를 알면 세상이 어떻게 돌아가는지를 조금 더 잘 볼 수 있게 된다. 그것이 추가적인 노동이 전혀 없이도 수입을 열 배, 백 배 늘릴 수 있는 직업과 하나를 더 얻을 때마다 그만큼의(유한한 자원인) 시간과 노력을 또 투입해야 하는 직업 — 다시 말해서 중력에 종속된 직업 — 의 차이다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 검은 백조, 나심 탈레브&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;압정식 사회란 극단화된 승자 독식 사회를 일컫는 말이다. 구성원에 따른 재산이나 소득을 그래프로 그렸을 때 특정 집단 내지는 특정인에게 비정상적으로 편중 현상을 보이게 되면 그 모양이 압정과 유사한 형태를 나타내기에 그렇게 부른다. 양극화의 종착역이라고 할 수 있다. 압정식 사회에서의 평균은 의미가 없다. 한 술집에 술마시는 사람들의 연소득 평균을 계산해서 그 사람들의 소득 계층을 이야기한다고 할 때 그 술집에 빌게이츠 한 명이 들어오면 평균이 전혀 의미가 없어지는 것과 같은 이치다. 결산 시즌마다 발표되는 회사들의 평균 연봉이 쓰잘때기 없이 높은 것도 이런 이유를 일부 반영한다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 압정식 사회는 좋은 것일까 나쁜 것일까? 소득 그래프를 그려 본 사람들은 백이면 구십구는 좋지 않다고 대답할 것이다. 단 한 사람. 모든 것을 가진 사람만 유일하게 좋은 세상이라고 말할 것이다. 하지만 조금만 달리 생각해 보면 사실 도덕적으로 판단하기는 힘든 무수히 많은 압정식 사회가 존재한다. 나심 탈레브 아저씨가 “검은 백조”에서 이야기했던 극단의 왕국들이다.&lt;/p&gt;
&lt;p&gt;싸이의 강남스타일은 몇 달 전 유튜브 최다 조회수 동영상에 등극했고 지금 조회수가 무려 십억 번을 넘었다. 우리 나라 가수들 뮤비 조회수를 어지간히 합쳐도 강남스타일 조회수를 넘기란 어려워 보인다. 해리포터로 유명해진 조앤 롤링 아줌마도 빠질 수 없다. 해리 포터 시리즈는 무려 4억부 이상이 판매됐는데 이 수치는 우라 나라에서 가장 잘나가는 베스트셀러 작가들의 판매부수를 모두 합쳐도 넘기 힘든 수치다. 우리에게 좀 더 친숙한 소프트웨어 세계는 더 심각하다. 검색 엔진 시장에서 구글의 점유율은 90프로가 넘고 모바일 운영체제에서 안드로이드 점유율은 75프로가 넘는다. 데스크톱 운영체제에서 윈도우의 독주는 말하면 입이 아플 정도다.&lt;/p&gt;
&lt;p&gt;여기까지만 듣고보면 으레 사람들은 원래 세상이 승자 독식이야. 자본주의가 그렇지 뭐. 이런 식으로 반응한다. 하지만 전혀 그렇지 않은 세상도 있다. 제 아무리 뛰어난 청소부도 일반적인 청소부보다 열 배 더 많은 공간을 청소하긴 힘들다. 한계가 있다는 말이다. 치과의사도 마찬가지다. 그들이 하루에 진료할 수 있는 환자 수에는 큰 차이가 나타나지 않는다. 검사도 마찬가지다. 그들이 조사하는 사건의 개수는 제한된다. 즉 여기서 언급한 분야는 철저하게 중력이 지배하는 세상이다. 본질적인 구조상 압정식 사회가 될 수 없다는 이야기다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;소프트웨어는, 특히나 일반 사용자용 소프트웨어는 철저하게 압정식 사회다. 승자독식, 약육강식이 지배하는 세상이다. 뛰어드는 모두가 부를 거머쥐는 세상이 아니라 살아남는 단 한 놈이 모두 가져가는 세상이다. 동영상에 나온 것처럼 컴퓨터 프로그래머를 해서 엄청난 부를 거머쥘 수도 있겠지만, 동시에 엄청난 시간과 노력을 투자하고도 땡전 한 푼 못 벌고는 쓸쓸하게 퇴장해야 할 수도 있다.&lt;/p&gt;
&lt;p&gt;카카오톡을 4명이서 2달 개발했다는 이야기가 나오는데 카톡을 유지시키는 데에는 어마어마한 금액이 들어갔다. 창업자가 워낙 펀딩 능력이 뛰어난 분이라 살아 남았지만 진짜 일반 벤처였다면 6달째 기근에 굶주리다 땡전 한 푼 못 벌고는 쓸쓸하게 퇴장해야 했을 수도 있다.&lt;/p&gt;
&lt;p&gt;그러니 저런 장밋빛 미래, 또는 앞으로의 수요, 내지는 전망 따위를 보고 직업을 선택하는 우를 범하진 말자. 직업 선택에는 수요와 전망 보다는 자신의 재능과 적성이 훨씬 더 중요하니까 말이다. 특히나 컴퓨터 프로그래머는 생각보다 훨씬 더 재능이나 적성이 중요한 분야다. 빌 게이츠 동영상만 봐도 그렇다. 마크 주커버그 처럼 여동생들이랑 더 재미있게 놀려고 소프트웨어를 만드는 걸 배우는 학생이 몇 명이 될까?&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/9bZkp7q19f0?si=xiGaYEScpgIROeLK&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;그 누구도 뜨기 전까지는 성공 여부를 예측할 수 없다. 성공한 후에도 왜 떴는지 알 수 없다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;컨텐츠 산업은 그래서 더 어렵다. 소프트웨어 중에서도 게임이 더 어려운 이유.&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 심리학자의 등장…]]></title><description><![CDATA[이질적인 것들의 만남이 때로는 더 환상적이기도 합니다. 최근 1년 사이에 XIGNCODE…]]></description><link>https://jiniya.net/wp/archives/10719</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10719</guid><pubDate>Fri, 12 Apr 2013 23:58:52 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/Ao0e2ckFicU?si=epU8iscR1FYNF8HI&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;center&gt;
&lt;p&gt;&lt;strong&gt;이질적인 것들의 만남이 때로는 더 환상적이기도 합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
   &lt;br&gt;
&lt;p&gt;최근 1년 사이에 XIGNCODE를 개발하면서 가장 큰 재미를 본 내용들은 대부분 사회공학적인 방법이었습니다. 결국 해커도 사람이고, 해킹툴을 사용하는 사람도 사람입니다. 이 인간이라는 한계를 넘어설 수는 없다는 게 제 생각입니다. 물론 그걸 뛰어넘는 이상한 사이코패스 같은 사람들도 있지만 그건 어디까지나 절대 다수는 아니잖아요. 이런 맥락에서 사회공학적인 기법은 심플하면서도 심오하면서도 뭔가 근원적인 매력을 가지고 있습니다. 하지만 이를 받아들이는 업체 사이에서는 아직도 갈팡질팡 하는 경향이 조금 있는 것 같습니다. 이런 전략을 아주 반기는 곳도 있고, 의구심을 품는 곳도 있고 그렇거든요. 설익은 상태죠.&lt;/p&gt;
&lt;p&gt;좀 더 재미있는 사실은 엔지니어가 많은 업체일수록 이러한 방식을 극도로 꺼려 하는 경향이 있다는 점 입니다. 사회공학적인 방법들을 사이비로 치부해 버리죠. 엔지니어들은 뭔가 어렵고, 심오하고, 복잡하고, 코딩하고 이런 걸 좋아하지만 사실 그런 것들은 웬만큼 실력이 비슷한 상대들 끼리는 뻔한 수 밖에는 안 됩니다.&lt;/p&gt;
&lt;p&gt;예전에 모 업체가 — 요즘 인터넷 기사에 줄기차게 등장하는 그 업체입니다. — 매번 보안 업체들 다 모아놓고 BMT를 시켰습니다. 마지막 관문은 크로스 해킹. 당연한 이야기겠지만 크로스 해킹을 방어하는 보안 제품은 하나도 없었습니다. 그러면서 보안 업체를 소집한 그 갑님께서는 이야기합니다. 제대로 만든 게 하나도 없으니 도입하지 않겠다. 요즘 하도 언론에 나오길래 꼬시다는 생각을 조금 했었습니다.&lt;/p&gt;
&lt;p&gt;국내 제품이 그렇지 뭐, … 라는 이야기가 여기저기서 들리는 것 같은데요. 근데 여러분이 자알 알고 계시는 외산 제품들도 똑같아요. 말만 들으면 알법한 그 엄청나게 큰 업체에서 만드는 소프트웨어들도 아주 손쉬우 방법에 당하거든요. 수십만라인 짜리 거창한 기능을 코드로 구현해 놓지만 몇 줄짜리 간단한 스크립트로 우회가 되는 경우도 부지기숩니다. 마치 괴델의 불완전성의 원리처럼 소프트웨어는 본질적으로 취약점을 가지고 태어나는지도 모릅니다. 폰 노이만식 아키텍처의 한계인지도 모르구요.&lt;/p&gt;
&lt;p&gt;마이크로소프트만 봐도 알 수 있잖아요. 취약점을 제거할 수 없기에 취약점 완화 방안을 내놓습니다. 즉, 공격은 여전히 가능한데 좀 더 어렵게 만들겠다는 거죠. 가능은 한데 경제적인 효용을 없도록 만드는 전략입니다. 이 정도가 최선입니다. ROE 따지는게 다 이유가 있는 거거든요. 어쨌든 기술이란게 좀 그렇습니다. 게임 보안 제품도 똑같거든요. 업체끼리 덤비면 사실 장난감 수준 밖에는 안 됩니다. 서로 쉬쉬하는 루프홀만 열거해도 일톤 트럭으로 옮겨야 할 지경이지 않을까 싶네요…&lt;/p&gt;
&lt;p&gt;감히 예측하건데 앞으로 사회공학적인 방법을 사용한 진단 기법들의 시대가 도래할 겁니다. 그럼 어떻게 돼냐구요? 네. 게임 보안 팀에 데이터 분석가 다음으로 심리학자가 초빙된다는 것을 의미하지요. &lt;a href=&quot;http://www.inven.co.kr/webzine/news/?news=55233&quot;&gt;똑똑한 라이엇 게임즈는 벌써 시작했군요.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;시스템 프로그래머 분들도 이제 마음을 조금 여시고 데이터 분석가와 심리학자, 그리고 뇌 과학자와 협업하는 방법을 배워야 할 때입니다. 코딩만 할 게 아니라 인문학 책도 좀 읽고, 커피숍 가서 사람들 구경도 좀 하고, 그 사람들이 도대체 왜, 그 비싼 돈을 주고 커피를 마시는 지에 관한 철학적인 생각도 좀 해 볼 때 입니다. 마음을 여세요. 프로그래밍이 전부라고 생각하는 순간 우물안 개구리 신세를 면하기 힘들거예요. 바야흐로 크로스오버, 퓨전이 대세인 시대입니다.&lt;/p&gt;
&lt;p&gt;후킹, 필터, 리버싱, 빅데이터, 클라우드, 가상화, NoSQL 같은 테크니컬한 지식 보다 깨진 유리창 이론, 2080 법칙, 나르시시즘, 플라시보 효과, 베르테르 효과, 낙인 효과 같은 이론이 훨씬 더 중요한지도 모릅니다. 결국은 다 사람이잖아요. 좀 더 넓게 생각할 필요가 있습니다. 이건 사이비가 아닙니다. 더 효과적인 방법이죠. 항상 ROE를 생각하세요. 어쨌든 아직은 자본주의로 돌아가는 세상이거든요.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 0을 향한 질주…]]></title><description><![CDATA[우리도 항상 제로의 영역을 꿈꾼답니다 ㅋ~ #0 XIGNCODE…]]></description><link>https://jiniya.net/wp/archives/7777</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7777</guid><pubDate>Thu, 11 Apr 2013 23:58:51 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/ttHpgjjVqCQ?si=sW1qujq-JGCb0Nor&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt;   &lt;/div&gt;
&lt;center&gt;
&lt;p&gt;&lt;strong&gt;우리도 항상 제로의 영역을 꿈꾼답니다 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
   &lt;br&gt;
게임은 가장 하드코어한 프로그램 중에 하나죠. 사람들이 하드웨어를 업그레이드하는 주된 원인이기도 합니다. 이런 게임과 동시에 실행돼야 하는 게임 보안 프로그램의 가장 큰 어려움 중에 하나는 게임에 영향을 주지 않아야 한다는 겁니다. 백신 검사를 시켜놓고 게임을 실행해 보세요. 게임이 얼마나 느려지는지 보시면 이 말의 의미를 금방 체감하실 수 있습니다. 게임 보안 프로그래머는 보안 프로그램이 존재 하지만 없는 것처럼 만들기 위해서 상당히 많은 공을 들여야 합니다.
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;XIGNCODE는 가장 공격적인 탐지 루틴을 사용하는 거의 유일한(?!) 게임 보안 제품입니다. 이러한 공격적인 방법을 사용하는 것은 해킹툴 억제력을 높이고 싸움에서 이길 수 있는 유일한 방법이기 때문입니다. 물론 그런다고 해킹툴이 100% 없어지는 것은 아니라는 점은 참고해 두시구요. 상대적으로 좀 더 우수한 해킹툴 제어 품질을 유지할 수 있다는 거겠죠 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_0을_향한_질주.md_0.png&apos; data-alt=&apos;AMD 2.7GHz 싱글 코어에서의 XIGNCODE CPU 점유율&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 579px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/30697a6df719bd65020c29a8128c8d09/ff2d6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 88.94736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADbUlEQVR42o3SXUxTZxjA8afWxikiHz2O6I3AzIQWCnJBAgZ1GXNEs6qlFInJ1EQpIB8loCLGaRkzM3PSgC1qmG1dHC6AJUHdhjEgNrQ5pe1pgWI5PacfFAYtCsxkQyawnpeYbOrFkn+e/G7evBfPAxk1FP90MKFqOvlUkFc1kVTl51X6o05MbpDORBTNRkjfVDgTKZ2LlM6EHZ9NPj17WDFTd04Hv+lHCIfTOkwaLCNW+/AgYbYTVtxsMxIug43uJyijjTYQtNHm1ptHjXa33kIOOT20140bzUB6gmP+wJBj7PnzF/RY0OGaHKEmf58KTAcngoH/FJgaZzA1HsKr+T8o2gt2hz9r3w7WZo5aq07ds31t7Pqoj7nR/GgsgYslYlgShiVgWCIXS+IiYDEpMZzNnMJTxz2+cbAN+lI/58MmuH5T9VFaPITBKi4LPgSIRq2AixDFgL2JDWwokOZ7fRNADHlTMnmwGppVyvisuBBY61gQDrAWtYJ1CB8wYEeyAaDgmMQb+nnI6f++6aq0Stbb16fWXK49X32m9uxX8poLdaj6tyH/pvZMrayj846L9sCwc7xFozlb960Rx5U/tHzXfKXpVsONHxu0rQ2aUHfR/Be0Pytuai8/NXSRLhoMJrqkLFFyBFTXGtN2xYqLoOAkK7cE8oqZRAhiBAmCuJS97yg03BK7KB/0GahGBe9GM6iUjXsOxVfUQ5mcXVK3quJrppNoliPIEMrqOdJzoLmXR7p8YLK6ckVJKamgUjWVn98qk0PlRU7pxdUy1AoqECoRyuVrimpA0y4hXV4YHvV1PehuUbc5n9l7jA9/1Xc8NuhwQmdCvQsT0Wk0t1He/mdOEqyDVO6Xwrj0uNZWbbYkJy5tW2KGgL8zmZ+JykJzB0IGA8HulC2C+OoLlRTtBgtBCj5NgI2gVCp4WdthDbAiWMw9hKNWsAFhPQM2xuw5/5iIdnvAbCMFGbzQASivKfi70//nkeQfQY8tg3RpWfEnOTmduvbqS/IDh/OFoi+EEqEwF/UG+yXCg2LhwTyhqODAZ3uzrygujYb2TNL08nJgaXF6/k//4sL08tLce1t8Pff3Xy+ZXs0tLbxcnH8xSjqg7b6l5+lAd8/A4yfmR72m7h783R714l3d+G2dSd2Bt/9ivtupv3Ov7yed6R/RYALBMQZfsgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;AMD 2.7GHz 싱글 코어에서의 XIGNCODE CPU 점유율&apos; title=&apos;&apos; src=&apos;/static/30697a6df719bd65020c29a8128c8d09/ff2d6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_0.png&apos; srcset=&apos;/static/30697a6df719bd65020c29a8128c8d09/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_0.png 190w,
/static/30697a6df719bd65020c29a8128c8d09/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_0.png 380w,
/static/30697a6df719bd65020c29a8128c8d09/ff2d6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_0.png 579w&apos; sizes=&apos;(max-width: 579px) 100vw, 579px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;AMD 2.7GHz 싱글 코어에서의 XIGNCODE CPU 점유율&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;공격적인 방법이란 달리 말하면 더 많은 연산을 의미하고, 더 많은 연산이란 더 많은 CPU 자원을 의미합니다. 하지만 게임과 동시에 실행되는 게임 보안 제품의 경우는 솔루션의 특성상 CPU 자원을 굉장히 아낄 수 밖에 없습니다. 그래서 우리는 공격적인 방법을 사용하돼 가급적 게임 구동 중에는 CPU 점유율을 거의 제로에 가깝게 유지하려고 애를 씁니다. “0%니까 어 그럼 CPU를 사용하지 않는다는 건가?”라고 생각하면 오산입니다. 0.0001%, 0.00001%씩 사용한다는 말이거든요. 그 1앞에 있는 0을 한없이 늘리기 위한 노력을 불출주야 쉬지 않고 노력 한다는 의미죠.&lt;/p&gt;
&lt;p&gt;일반적으로 싱글코어에서 실행되는 게임에 있어서 2% 이상의 순간 CPU 점유율을 게임 보안 제품이 가져가면 민감한 사용자들이 순간 랙을 체감합니다. 3% 이상의 순간 점유율을 가져가면 조금 둔한 사용자가 끊김을 체감하고, 5% 이상의 점유율을 가져가면 모든 사용자가 랙을 호소합니다. 최소 사양 기준으로 말이죠.&lt;/p&gt;
&lt;p&gt;그래서 어떤 경우에도 순간적으로 CPU 점유율을 과도하게 사용하지 않아야 합니다. 이게 말로만 들으면 굉장히 쉽습니다. 아, 그냥 CPU를 덜 사용하면 되겠구나라고 말이죠. 하지만 사실 윈도우 환경에서 스레드 별로 CPU 쿼터를 지정하는 방법이 공식적으로는 존재하지 않기 때문에 정확하게 게임 보안 제품이 가져가는 CPU 점유율을 제한하는 일은 생각처럼 그리 쉽진 않습니다.&lt;/p&gt;
&lt;p&gt;윈도우 스케줄러가 아닌 선점형 스케줄러를 직접 구현하는 것이 가능하다면 문제가 조금 간단한데 윈도우 환경에서 유저모드에서 그런 스케줄러를 구현하기가 쉽지는 않습니다. 파이버가 비선점형으로 구현된 것만 봐도 알 수 있죠. 물론 커널 스케줄러를 대체하는 방법이 있긴 한데 이는 문서화된 방법도 아닐 뿐더러 시스템 전체적으로 굉장히 리스크가 큰 방법이라 상용 제품에 사용하기엔 힘든 실정입니다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;뭐 천천히 실행하면 되는 걸 가지고 왜 그렇게 호들갑을 떠냐구요. 맞습니다. 하지만 여기엔 다른 쪽에서 우리를 압박하는 요소가 있습니다. 바로 마의 시간입니다. CPU 점유율을 낮추기 위해서 탐지 코드가 무한대로 느려져서는 안 된다는 것을 의미하는 말이죠. 게임 특성에 따라 다르긴 하지만 통상적으로 게임 보안에서 3분과 5분은 굉장히 의미있는 탐지 시간입니다.&lt;/p&gt;
&lt;p&gt;3분 내 탐지가 이루어지면 유료 핵툴인 경우에는 제작자가 핵툴이 패치 됐다는 공지를 올리고 핵툴에 대한 업데이트를 진행합니다. 아주 악성 사용자들의 경우에도 이 시간 내에 탐지가 이루어지면 해킹툴 사용을 보류하는 경향이 높습니다.&lt;/p&gt;
&lt;p&gt;5분 언저리에서 진단이 되거나 이 시간보다 진단이 지연되게 되면 해킹툴 제작자는 패치 됐다는 공지를 하지 않습니다. 사용자들은 이를 하나의 페널티로 인식하지요. 공격적인 사용자의 경우에는 지속적으로 해킹툴을 사용합니다. 5분 내에 탐지되지만 게임 핵툴을 사용하는 사용자가 계속 존재하기 때문에 게이머들은 지속적으로 게임 내에서 해킹툴 사용자를 마주치게 되고 해킹툴이 많다는 인상을 받게 됩니다.&lt;/p&gt;
&lt;p&gt;즉, 마의 시간이란 아무리 늦어도 3분 내에는 해킹툴이 차단이 되어야 하고, 아주 최악의 경우에도 5분 내에는 사용자가 지속적으로 게임 플레이를 할 수 없도록 만들어야 한다는 것을 의미합니다. 이렇게 만들기 위해서는 당.연.한 이야기겠지만 CPU를 쓸 수 밖에는 없죠. 따라서 CPU 자원과 해킹툴 탐지 속도가 사이의 최적값을 찾는 것이 중요합니다. 그래야 CPU 자원을 최소한으로 사용하면서도 탐지 속도도 일정 수준 이상으로 끌어 올릴 수 있거든요.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;이런 이유로 XIGNCODE는 조금은 특이한 디스패칭 전략을 사용합니다. 우리 전략의 핵심은 시점입니다. 우리는 크게 이 시점을 네 가지 기준으로 분류합니다. 첫 번째는 게임이 시작하는 S 시점입니다. 게임의 각종 데이터가 로딩되기를 사용자가 기다리는 시점이죠. 다음으로는 시점은 게임이 시작돼서 사용자가 게임을 즐기는 P 시점이 있습니다. 또 게임을 사용자가 즐기다 게임을 일시 중단한 상태로 다른 작업을 수행하는 L 시점이 있습니다. 윈도우 환경이라면 게임이 액티브 프로세스가 아닌 시점을 의미하겠지요. 끝으로 해킹툴이 탐지된 X 시점이 있습니다. 똑똑한 분들이라면 버얼써 눈치채셨겠지만 이렇게 시점을 구분한 이유는 동일한 루틴도 어떤 시점에 실행되느냐에 따라서 CPU 자원 소모량을 다르게 만들기 위함입니다.&lt;/p&gt;
&lt;p&gt;S 시점은 게임 데이터를 로딩하기 위해서 사용자가 어차피 기다리는 시점이기 때문에 이 시점에 스케줄링 되는 루틴들은 모든 CPU 자원을 활용하는 형태로 구동됩니다. P 시점은 사용자가 실제로 게임을 즐기는 시점이기 때문에 최소한의 CPU를 사용할 수 있도록 스케줄링 됩니다. 또한 뒤에서 살펴보겠지만 점감 프리미엄을 받도록 설계돼 있습니다.&lt;/p&gt;
&lt;p&gt;L 시점의 경우에는 조금 애매합니다. L 시점이 됐다고 바로 모든 CPU 자원 소모가 들어가는 작업을 수행한다면 바로 다시 게임으로 돌아오는 경우에 랙을 체감할 수 있기 때문이죠. 떠난 시간이 일정 수준을 넘어서면 모든 검사 루틴들이 시작 시점과 동일하게 CPU 자원을 많이 소모하는 형태로 동작합니다. 다른 프로세스에게는 미안한 일이지만 어쨌든 게임 플레이라는 입장에서 봤을 때에 페널티가 발생하지는 않기 때문이죠. 마지막으로 X 시점입니다. 이 시점은 우리가 똥을 싸질러도 되는 시점이지요. 가장 아름다운 순간입니다. 크래시 따위도 전혀 무섭지 않은 무적 상태랍니다 ㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;XIGNCODE는 랙을 줄이기 위해서 사회공학적인 기법들이 사용하기도 합니다. 바로 검사 루틴들의 스케줄링 정책입니다. XIGNCODE의 모든 검사 루틴들은 기본적으로 리타르단도 방식으로 스케줄링됩니다. 리타르단도가 뭐냐구요? 점점 느려진다는 말이죠. 왜 점점 느려지게 만들었을까요? 정상 사용자들에게 최대한 피해를 주지 않기 위해서 입니다.&lt;/p&gt;
&lt;p&gt;일반적으로 해킹툴 사용자의 경우 게임 시작과 동시에 해킹툴을 사용하는 경향이 매우 높고, 모든 해킹툴 탐지의 80%는 20% 악성 사용자에게서 발생하는 경향이 있습니다. 신기하지만 2080 법칙은 어디에나 통용되는 것 같아요. 어쨌든 사회공학적으로 착하게 플레이를 하는 사용자들은 지속적으로 착하게 플레이할 가능성이 높다는 거죠. 그래서 XIGNCODE의 모든 검사 루틴은 점감 효과를 받도록 스케줄링됩니다. 게임 시작 후에 일정 시간이 지나면 거의 모든 검사 루틴들이 마치 죽은듯이 동작한다는 의미입니다. 물론 그렇게 되더라도 앞서 말한 3분내 탐지는 가능할 정도 수준으로 동작은 해야겠지요.&lt;/p&gt;
&lt;p&gt;윈도우 사용자라면 윈도우를 사용하면 할수록 빨라진다는 느낌을 받았을 겁니다. 또 어떤 프로그램을 설치해서 처음 실행했을 때 보다는 자주 실행했을 때 그 프로그램의 수행 속도가 더 빨라지는 현상도 느꼈을 텐데요. 운영체제에서 이런 것들을 가능하게 해주는 캐싱 시스템이 존재하기 때문입니다. 대단한 건 아니고 여러분이 자주 요청했던 리소스를 미리 캐싱해놨다가 사용자가 요청하는 시점에 니가 이걸 요청할 줄 알았다하고는 바로 내주는 것이죠. 이 시스템이 재미난 건 대부분의 사용자가 쓰는 프로그램을 반복적으로 사용하기 때문에 굉장히 히트율이 높다는 겁니다. XIGNCODE 개발팀에는 최근에 이런 점에 착안해서 스케줄링 정책에 이런 캐싱 시스템을 도입하려고 하고 있습니다. 즉, 여러분이 게임을 지속적으로 착하게 플레이 하면 할수록 보안 제품으로 인한 성능 페널티는 점점 더 없어지고, 여러분이 해킹툴을 사용하고 뻘짓을 하면 할 수록 여러분의 시스템을 박박 긁는 것이죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_0을_향한_질주.md_1.png&apos; data-alt=&apos;안타깝게도 여기에 은탄환(Silver Bullet)은 없습니다.&lt;br&gt;&lt;br&gt;물론 그렇다고 너무 아쉬워할 필요는 없습니다.&lt;br&gt;&lt;br&gt;최상급 수제 에픽 탄환인 XIGNCODE가 있잖아요.&lt;br&gt;&lt;br&gt;딜이 안 될 때에는 탄환을 먼저 체크해 보세요. 미터기는 저희가 찢어 드리겠습니다.&lt;br&gt;&lt;br&gt;뉴요커 냥꾼이는 앵벌 할 때에도 에픽 탄환을 쓴다는 점. 꼭 기억하세요 ㅋ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/40e890bd5b52e78e1bac3a11ccffd975/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACS0lEQVR42mVSy04UQRTthcHERHwlhigLjZGVJoyEjfAH/ocmLDSGXxGF6FJMXLgybtSViUuVgRGkZ6anu+td1e83r8HTEN1QfXP7VPe9dc89t6y+3Ye5rusMHdu2fc8LTMAZT5Lk+P8aj1sfBPtC1EpX0mT9H2NBrCzNAx0ZZSRTRgUAoYm0NACcScEEZwK+19v5/vHrt/UPn9+++7L+/tPaK//XT0srQ3zOKPNGvu/6rgNPgV3H84bABNu6rpceP719ozMzPTt54eq1S1MT5yZXVlatOIoZFcznxKNGB1VVl2VVnvoTK8rq8OBw+dnzuc7c4sOFzuz81PVbl89feb26ZhVFG1qViEaBpm6a1uPV7DX/8OHR0fKTpQdT04/udxbu3pu/eWdm4uKbFy+tKIiIT6WQjDAUp4RzwhkBEUJcTzBJfYamuhvd7e5mb2Oz1+3+2dn5vbUFXa04jBEqhaqrJgpjREMtJbWGqmUJ8aRUOC4OkyKvsqzI06LIy/GJ/laW5BA8y3J8yuHyAjqDgu9RcGkFGxHgkeMNdocDewhd4ijZa/ba5NCEggotNedScoXKjAjqc4oWPEZJewSogTz+go7Bo4LmNBlpGM/QHqCI4Nrp95jfi8IUI4QZEyA60EGaZsdnlpXEieBKcqkEvJbcT2OVo4WsQDtpnLUgy5F8sH9wNjklLsXdAquWXstZgDPuBvHYaOB6jucMRrvbNiUMDbd0YADaWBgjlMySDMpBCRCBYZsmaRKlJyoIpHHKiU+U0KCAerA4Sv4C24Oea1Ci4zIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;안타깝게도 여기에 은탄환(Silver Bullet)은 없습니다.&lt;br&gt;&lt;br&gt;물론 그렇다고 너무 아쉬워할 필요는 없습니다.&lt;br&gt;&lt;br&gt;최상급 수제 에픽 탄환인 XIGNCODE가 있잖아요.&lt;br&gt;&lt;br&gt;딜이 안 될 때에는 탄환을 먼저 체크해 보세요. 미터기는 저희가 찢어 드리겠습니다.&lt;br&gt;&lt;br&gt;뉴요커 냥꾼이는 앵벌 할 때에도 에픽 탄환을 쓴다는 점. 꼭 기억하세요 ㅋ~&apos; title=&apos;&apos; src=&apos;/static/40e890bd5b52e78e1bac3a11ccffd975/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_1.png&apos; srcset=&apos;/static/40e890bd5b52e78e1bac3a11ccffd975/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_1.png 190w,
/static/40e890bd5b52e78e1bac3a11ccffd975/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_1.png 380w,
/static/40e890bd5b52e78e1bac3a11ccffd975/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_0%EC%9D%84_%ED%96%A5%ED%95%9C_%EC%A7%88%EC%A3%BC.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;안타깝게도 여기에 은탄환(Silver Bullet)은 없습니다.&lt;br&gt;&lt;br&gt;물론 그렇다고 너무 아쉬워할 필요는 없습니다.&lt;br&gt;&lt;br&gt;최상급 수제 에픽 탄환인 XIGNCODE가 있잖아요.&lt;br&gt;&lt;br&gt;딜이 안 될 때에는 탄환을 먼저 체크해 보세요. 미터기는 저희가 찢어 드리겠습니다.&lt;br&gt;&lt;br&gt;뉴요커 냥꾼이는 앵벌 할 때에도 에픽 탄환을 쓴다는 점. 꼭 기억하세요 ㅋ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[좀비 프로세스를 찾아서…]]></title><description><![CDATA[일반적으로 fork…]]></description><link>https://jiniya.net/wp/archives/10585</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10585</guid><pubDate>Thu, 04 Apr 2013 23:58:50 GMT</pubDate><content:encoded>&lt;p&gt;일반적으로 fork 계열을 사용하는 유닉스 운영체제에서는 좀비 프로세스라는 말이 자주 등장합니다. 스티븐스 아저씨의 역작인 유닉스 프로그래밍 책에도 좀비 프로세스에 대한 소개가 여러 차례 등장하지요. 하지만 윈도우 운영체제에서는 좀비 프로세스라는 용어는 생경합니다. 이런 현상을 반영하듯이 스티븐스 아저씨에 필적하는 제프리 리처 아저씨의 역작 “Windows via C/C++”에도 좀비 프로세스라는 용어는 등장하지 않습니다.&lt;/p&gt;
&lt;p&gt;그렇다면 윈도우에는 좀비 프로세스가 없는 걸까요? 결론부터 말하면 그건 아닙니다. 근데 왤케 낯선 걸까요? 그 가장 큰 이유는 윈도우 운영체제가 좀비 프로세스에 대한 정보를 꽁꽁 숨겨 두었기 때문입니다. 작업 관리자에서 좀비라고 표시되는 프로세스나 죽은 프로세스 임에도 죽지 않고 버젓이 표시되는 것을 본 적이 있으신가요? 없을 겁니다. Toolhelp나 PSAPI를 사용해서 프로세스를 열거할 때에 죽은 프로세스가 나타나는 것을 보신 적이 있으신가요? 없을 겁니다. 이는 NT 네이티브 API를 사용해도 똑같습니다.&lt;/p&gt;
&lt;p&gt;그렇다면 이렇게 운영체제가 꽁꽁 숨겨놨는데 무슨 근거로 존재한다고 주장하는 걸까요? 나타나지도 않는데 무슨 근거로 있다고 하는 겁니까, 라고 물어볼지도 모르겠습니다. 당.연.히 일반적이지 않은 방법을 사용해야 그 존재를 찾을 수 있습니다. 좀비를 만나게 되는 경우는 크게 두 가지 경우가 있는데요. 하나는 PID 브루트포스라는 방법으로 무작위 PID를 대입해서 프로세스가 존재하는지를 검사할 때에 이 좀비가 나타나게 됩니다. 다른 하나는 커널 레벨에서 EPROCESS 구조체를 직접 열거하면 만날 수 있습니다.&lt;/p&gt;
&lt;p&gt;뭐 어쨌든 좀비 좀비 거렸는데 그러면 일단 그 좀비 프로세스의 실체를 한 번 살펴볼까요? 아래는 간단하게 notepad를 좀비로 만들고 그 결과를 관찰한 windbg 출력입니다. 이 내용을 보면 좀비 프로세스가 무엇인지 명확하게 알 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;kd&gt; !process 0 0 notepad.exe
PROCESS fffffa8002236b30
    SessionId: 1  Cid: 08dc    Peb: 7fffffdf000  ParentCid: 076c
    DirBase: 3cc09000  ObjectTable: 00000000  HandleCount:   0.
    Image: notepad.exe

kd&gt; !process fffffa8002236b30
PROCESS fffffa8002236b30
    SessionId: 1  Cid: 08dc    Peb: 7fffffdf000  ParentCid: 076c
    DirBase: 3cc09000  ObjectTable: 00000000  HandleCount:   0.
    Image: notepad.exe
    VadRoot 0000000000000000 Vads 0 Clone 0 Private 1. Modified 4. Locked 0.
    DeviceMap fffff8a0016b0200
    Token                             fffff8a001c6a060
    ElapsedTime                       00:00:27.341
    UserTime                          00:00:00.046
    KernelTime                        00:00:00.109
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (5, 50, 345) (20KB, 200KB, 1380KB)
    PeakWorkingSetSize                1799
    VirtualSize                       55 Mb
    PeakVirtualSize                   77 Mb
    PageFaultCount                    1850
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      0

No active threads
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아직도 좀비 프로세스가 뭔지 정확하게 이해하지 못하신 분들을 위해서 첨언하면 이렇습니다. 좀비 프로세스란 프로세스 종료 처리가 모두 완전하게 끝났음에도 프로세스 구조체가 사라지지 않고 남아있는 경우를 말합니다. 즉, 프로세스가 죽고 싶어도 죽지를 못하니 그 증상이 마치 좀비 같다고 해서 좀비 프로세스라고 부르는 거지요. 물론 앞선 windbg 출력에 보이는 것처럼 프로세스 종료에 관한 모든 처리가 끝났기 때문에 좀비 프로세스는 어떠한 주소 공간도, 어떠한 커널 오브젝트도, 어떠한 스레드도 포함하고 있지 않습니다. 단지 커널 구조체와 PID란 자원을 낭비하고 있을 뿐이지요.&lt;/p&gt;
&lt;p&gt;그렇다면 이 좀비 프로세스는 도대체 왜 죽지 않고 이렇게 남아 있는 걸까요? 이유는 간단합니다. 프로세스가 죽었음에도 해당 프로세스를 참조하는 다른 프로세스가 남아 있다면 그 죽은 프로세스는 좀비가 됩니다. 뭐 유닉스에서 fork로 좀비가 생기는 원리랑 동일하다고 생각하시면 됩니다. 아래 프로그램을 사용하면 아주 손쉽게 좀비를 만들 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tchar.h&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    HANDLE process &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OpenProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SYNCHRONIZE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tcstoul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;open error %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;notepad.exe를 실행합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;앞선 코드의 프로그램을 실행합니다. ex) zombie_maker.exe [notepad PID]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;실행한 notepad를 종료합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 상태가 되면 죽은 notepad는 좀비가 됩니다. zombie_maker가 죽은 녀석의 핸들을 잡고 있기 때문이지요. 그 핸들이 닫히기 전까지 notepad는 영원히 좀비 상태로 남아있게 됩니다. 그 핸들이 닫히는 순간 비로소 좀비는 죽을 수 있게 되지요.&lt;/p&gt;
&lt;p&gt;결국 좀비 프로세스란 &lt;a href=&quot;http://jiniya.net/tt/769&quot;&gt;탐색기가 파일 핸들을 잡아서 파일 삭제가 안 되는 것처럼&lt;/a&gt; 누군가 프로세스 핸들을 잡고 있어서 그런 경우가 다반사 입니다. 그럼 주로 어떤 놈들이 잡고 있는 경우가 많을까요? 보안 프로그램, 특히 백신같이 프로세스를 스캔하는 녀석들이 잡고 있는 경우가 많이 있습니다. 다행이 유저 레벨에서 벌어지는 일의 경우에는 핸들을 잡고 있는 프로세스만 종료하면 좀비가 사라지지만 커널 모드 드라이버에서 핸들릭이 발생해서 좀비가 된 프로세스는 재부팅 전까지는 영.원.히 좀비 상태가 된다는 것에 주의해야 합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[에디터 열전]]></title><description><![CDATA[프로그래머에게 도구가 중요합니다. 그 중에서도 에디터는 정말 백미라고 할 수 있죠. 어떤 에디터를 사용하는지로 그 프로그래머의 정체성을 엿볼 수 있다고도 생각됩니다. vi와 emacs…]]></description><link>https://jiniya.net/wp/archives/10567</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10567</guid><pubDate>Tue, 02 Apr 2013 23:58:49 GMT</pubDate><content:encoded>&lt;p&gt;프로그래머에게 도구가 중요합니다. 그 중에서도 에디터는 정말 백미라고 할 수 있죠. 어떤 에디터를 사용하는지로 그 프로그래머의 정체성을 엿볼 수 있다고도 생각됩니다. vi와 emacs의 논쟁은 프로그래밍 언어에 관한 논쟁만큼 오래 되었지요. 오늘 아시는 분이 notepad++에 관한 기능을 물어보셔서 생각난 김에 정리해 봅니다. 예전에 제가 썼었던 &lt;a href=&quot;http://jiniya.net/tt/376&quot;&gt;소스 인사이트에 관한 글&lt;/a&gt;도 참고하시면 좋을 것 같네요.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./에디터_열전.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/24fac61cd544bd1f41861dd88db2c943/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 63.68421052631579%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACNElEQVR42oXQ3UtTcRzH8fNPdLPc3Hl++p1tZzvueWdPPoQhRUZW4EX1FwQRgcMdG6YuosugbsRqoCnVhdBNQSycZ61y5+whp1u2hzR1m4soumvhnUWD1+2b74cv9OBldTa+2/ZwpX73qXJzLi7NxiNziTtLH24vpKLzb6MLqZn51FRMnny0cismzyypbdOLyv17zyAlk9utfdrfrvz4Vo9OSaJgOBEQgn2mXr/V4+QdVs4mMAJPcgwMaD1g9CylY+luBtcYrDYonS9ubm7UatvNZmssHKK6tD4LK9hxFNch2KFuFNdjxCH4DxJBMS3Lm6HCVi2bUbK5/N7eXmRSAijsMQOrnWZYjKAQ8t9QgtABswUqVnYyqrK2lm4dtCYiYQ6BfQLncrNmnqQZtFNc3smqiprJNptNKTJuRJA+m8njBUYjTna+XN7JZdVkMtmeLUXCAO728Gx7NstiFN0pXn2nyqsJWZbXC4XrN64RGOyymoQeCgCUojvN/lisqEq6WCzV6/VwOEQD0ut38TzgDBTNYB3i9VK1/bCtrc8HB62wFDLxTP+A3x9wi6IDcCRBwf+L32fWNzYK5Uq13mhIE+MsoESvQ/Q6RZ/TLdp5C0fR2F9wktRzlh4oXyh9/VJu7O/++vk9MjFG4F2i2+K0G80mEseOk4QWQzVHoKgG0R+jOBaKLSeeLL9+/PzV4os3V0PT/qGRkyOXB89dGhgeDQydD566cETv6Yv9Z0Z9g2eDw1d+A+0bFGnm5WmsAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 0&apos; title=&apos;&apos; src=&apos;/static/24fac61cd544bd1f41861dd88db2c943/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_0.png&apos; srcset=&apos;/static/24fac61cd544bd1f41861dd88db2c943/08678/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_0.png 190w,
/static/24fac61cd544bd1f41861dd88db2c943/2edd7/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_0.png 380w,
/static/24fac61cd544bd1f41861dd88db2c943/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_0.png 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;내가 요즘 대세 Sublime Text&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;요즘 프로그래머들 사이에 가장 핫한 텍스트 에디터인 &lt;a href=&quot;http://www.sublimetext.com/2&quot;&gt;Sublime Text 2&lt;/a&gt;입니다. 파이썬으로 만든 녀석인데 파이썬으로 이렇게 빠르게 동작한다는 게 가능한 줄은 정말 몰랐습니다. C++로 만들고 플러그인만 파이썬 입니다. ㅋㅋ~ 거기다 정말 기가막힌 다양한 기능에 손쉬운 플러그인 설치. 뭐하나 흠잡을데 없는 최고급 텍스트 에디터입니다. 맞아요. 가격이 비싼게 흠이라면 흠이겠군요. 근데 내그웨어인데다 광고가 많이 뜨지도 않기 때문에 무료로도 크게 불편함 없이 사용하실 수 있습니다. 처음 사용하시면 다소 당황할 수 있는데 아래 도움글을 보시고 연습 후에 쓰시면 감칠맛이 백배더 증가하는 버프를 받으실 수 있습니다. 환골탈태한 Sublime Text 3가 곧 출시한다니 엄청 기대되는 시점입니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://windtale.net/blog/sublime-text-tip/&quot;&gt;http://windtale.net/blog/sublime-text-tip/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./에디터_열전.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b6dbdaef82f07dcaa527d29509d6b8da/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACG0lEQVR42k2R627TQBCF/f6vAQhoSsMPEKgVqFJpSgtp0jr23q/e9SVOk7o0TuI0DpPQSoxWR2PvfjpnZ4NOzx30VKfnu1fj7mV+dJEdXhTdy/LwzL4+ta++qzen8t1ZchzVJ/FityLQ5fFt9elLGPRHUvIR57TI89Slo5vPBB9Q/IGgw8HNQRx3EH4/Ct/Cp2BdRo5AOfsoWedn1A9CxmZ35XyxepzX1cMfpTHnt8YgIUOEr71nWS4IHUbxb6FGmAyUjoSMBBuc98NAeu0NXj+1m01b1wulDOcqsV4ITQh3Ps/yMfzBmElpuNDWOq0TLVVvyAM/nS/r6apZt+2mns8llBCJNUKIGCGf+jzPCCUIxVIJSonRSiq4KekNaBCp8bppmvVTs14/Ps6BIYQkieWCxzFyzmVZhjGJo0hKBVtaKyGk4PT8mgTfLm58YrdQ7baua845HLXWMMbAeQ+nwMRxDMwe1gKMKfkV6eBHH03KYruvfzCUtRYUQWy/c36BBQVYaYjAKR5SF4D73X/w/srCJQk0mNA0S+EJIQXGSGkNjTUWGinokPrAThbbdtO27bOzEHDCGJg5DAw773fOlD7HpnRHKg2xB8QFws+emuVytWyaVXU/s0ZZo1PvnDUwlqLIyrKwOysOTwDNbguCaRkyH3y9RCdX7Dy0zOTaT9z43pdVWj54WOMK1BX3STFLXtTmMzeu8kk1kNO/GXxzNG7++90AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 1&apos; title=&apos;&apos; src=&apos;/static/b6dbdaef82f07dcaa527d29509d6b8da/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_1.png&apos; srcset=&apos;/static/b6dbdaef82f07dcaa527d29509d6b8da/08678/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_1.png 190w,
/static/b6dbdaef82f07dcaa527d29509d6b8da/2edd7/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_1.png 380w,
/static/b6dbdaef82f07dcaa527d29509d6b8da/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_1.png 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;에디터 계의 영원한 스테디 셀러 EditPlus&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;국산 에디터의 자존심이죠. 제가 notepad++을 사용하지 않는 이유도 &lt;a href=&quot;http://editplus.co.kr/&quot;&gt;editplus&lt;/a&gt;가 있기 때문입니다. 주로 전 엄청 큰(몇십메가에서 몇백메가) 텍스트 파일을 작업할 때 이 녀석을 사용하는데요. 정말이지 그렇게 큰 텍스트 파일도 아주 부드럽게 뷰잉해 줍니다. notepad++은 약간 한계를 보이더군요. 거기다 ftp 연동 기능이 아주 편리하게 구성돼 있는것도 장점인 것 같구요. 여튼 정말 강추하고 싶은 텍스트 에디터예요.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; margin-bottom: 16px;&apos; data-url=&apos;./에디터_열전.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ef996bd44919a15eebbbbb055eed1825/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 52.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB6klEQVR42m2RT2/TMBjG85E4cOLAHwHajU+104QQm0pHJyGVgbggIUFBO7QFOjJEBe3asrbbaNLEiR07dv7NTdy01CEdYlTaXv1e6zn4J0uPlc0ay9mqe1v1ZXhcJQ8r44232uYeKNbwkxoqVHPgdiMsqXFJnZRUvn2QlPf0108rCnMNB0FMSOB7LnH4WeQxSqnLOU/T6VSIv4gk/k8ci2nSxTOF4IDSIGReHHERCzERCU/EJBE8vyfms9nvfGdpOptfME3n2WI+MHzFNlITRx964fufvNIJ3x0GlW6UhzftsDXmkEYGjgAJspWRcnkOrVAhlih8W9x4Ju/vynu72d3n2doLufYyu76TrTcWbc2vD7y2weUl+RRNFALEekNe28lulpfcKmd3yvLBK3m7nG2oi5Yefhz4XSu+WrbHojqIH30+K6qTwpeoeMCL+/7+wP16TPsgHAK/M8K6haWUV8iGNs179glkGGLbINDAtuk6kGLkM4ps2zIM7KAVd0U2deGyACFsIwyRAywbANswAUTID8L8CzVNsyx76fxjcS6f5DK2UubS/B0XOxhazjnIBow4gcdMfYRMPQ+X2x45XGkdez2dqR3t+xB2RqSr0R9D2DwCPZ3mHP7CzT5o9q1TxC84gVzHk09H7A/ZVEYCu8723gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 2&apos; title=&apos;&apos; src=&apos;/static/ef996bd44919a15eebbbbb055eed1825/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_2.png&apos; srcset=&apos;/static/ef996bd44919a15eebbbbb055eed1825/08678/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_2.png 190w,
/static/ef996bd44919a15eebbbbb055eed1825/2edd7/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_2.png 380w,
/static/ef996bd44919a15eebbbbb055eed1825/b0db9/%EC%97%90%EB%94%94%ED%84%B0_%EC%97%B4%EC%A0%84.md_2.png 420w&apos; sizes=&apos;(max-width: 420px) 100vw, 420px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;헥사가 필요할 땐, HxD&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이러니 저러니해도 시스템 프로그래머라면 raw data를 처리할 일이 많이 있습니다. 그럴 때 간편하게 사용할 수 있는 헥사 에디터입니다. 크게 특출난 기능은 없지만, 그렇다고 크게 빠지는 부분도 없는 문안함이 장점이랄까요? 물론 무료라는 점은 &lt;a href=&quot;http://mh-nexus.de/en/hxd/&quot;&gt;HxD&lt;/a&gt;를 더욱 돋보이게 만들어 줍니다 ㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 안드로이드 입문]]></title><description><![CDATA[얼마전에 윈도우8로 시스템을 업그레이드 하면서 마이크로소프트가 정신을 차리기 시작하고 있다는 생각이 들었습니다. 가히 저에게는 혁신적인 운영체제라고 할 만큼 만족스러웠거든요. 그런데! 그런데! 윈도우…]]></description><link>https://jiniya.net/wp/archives/9960</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9960</guid><pubDate>Wed, 27 Mar 2013 23:58:48 GMT</pubDate><content:encoded>&lt;p&gt;얼마전에 윈도우8로 시스템을 업그레이드 하면서 마이크로소프트가 정신을 차리기 시작하고 있다는 생각이 들었습니다. 가히 저에게는 혁신적인 운영체제라고 할 만큼 만족스러웠거든요. 그런데! 그런데! 윈도우8 태블릿이나 폰을 사고 싶어도 이건 시장에 물건이 없어도 너무 없더군요. 핡~ MS가 어쩌다가 이런 지경까지…&lt;/p&gt;
&lt;p&gt;그런 찰나에 항상 그렇듯이 남들보다 한 세박자 늦게 모바일 개발에 뛰어들게 되었습니다. 말도 많고 탈도 많다는 바로 그 안드로이드 플랫폼으로 말이죠. 십만년전에 쓰던 구형 갤s 폰이 하나 있었는데 루팅하고 머 하고 해서 개발하려고 세팅 좀 하는데 느려도 너무 느린데다 화면까지 작으니 갑갑해서 태블릿을 하나 사야겠다고 생각을 했습니다. 그나마 넥서스7이 괜찮더군요. 부담없는 가격에 레퍼런스 버프까지. 급한 마음에 지르겠다고 하이마트를 갔는데 16기가는 품절이라 허탕만 쳤습니다. 그러다 우연찮게 점심 먹다 그 이야기가 나오게 됐는데 다음날 제 책상으로 넥서스7이 배달돼 있는 기적이 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;이클레어, 프로요, 진저브레드를 갤s로 경험한 저에게 안드로이드란 그저 음악 끊기는 플랫폼이었습니다. 그런데 이번에 접하게 된 넥서스7, 거기다 안드로이드 젤리빈 4.2.1 쇼킹했습니다. 왜냐구요? 여전히 음악 끊기는 플랫폼이었거든요. ㅋㅋㅋ~ 물론 이건 좀 농담이구요. 음악이 끊긴다는 사실은 진실입니다. 여튼 진짜 놀란건 안드로이드의 진화였습니다. UI부터 시스템까지 때깔벗기고 날아갈 준비가 된 것처럼 보였거든요.&lt;/p&gt;
&lt;p&gt;몇 일 태블릿을 쪼물딱거리면서 드는 생각이 아~ 윈도우 힘들겠는데, … 라는 생각이었습니다. 그 쪼그만한 넥서스7에서 안 되는게 없었거든요. RDP, 삼바, FTP, SSH, 터미널, 토렌트, … 제가 생각하는 그 모든 툴들이 벌써 앱으로 모두 공짜로 제공되고 있었습니다. 거기다 만화책 뷰어는 어찌나 아름다운지… 윈도우가 아쉬운 시점은 글 쓸 때하고 프로그래밍 할 때 말곤 없었습니다. 컨텐츠 소비 플랫폼으로는 슈퍼갑이었지요. 모바일 시장 점유율 75%가 괜한 소리가 아니었습니다.&lt;/p&gt;
&lt;p&gt;Chart: Worldwide Smartphone OS Market Share, 2012Q3Description: IDC’s Worldwide Quarterly Mobile Phone Tracker provides smart phone and feature phone market data in 60 countries and 8 regions by vendor, device type, air interface, operating systems and platforms, and generation. Over 20 additional technical segmentations are provided. The data is provided four times a year and includes historical and forecast trend analysis. For more information, or to subscribe to the research, please contact Kathy Nagamine at 1-650-350-6423 or &lt;a href=&quot;mailto:knagamine@idc.com.Further&quot;&gt;knagamine@idc.com.Further&lt;/a&gt; detail about this tracker can be found at:&lt;a href=&quot;http://www.idc.com/tracker/showproductinfo.jsp?prod%5C_id=37Tags&quot;&gt;http://www.idc.com/tracker/showproductinfo.jsp?prod\_id=37Tags&lt;/a&gt;: Samsung, Apple, Mobile Phone, Smartphone, IDC, tracker, Q3 2012, mobile phones, 3Q 2012, market share, galaxy, iPhone, Android, iOS, BlackBerry, Symbian, Windows Phone, Linux, 2012Q3, AnniversaryAuthor: &lt;a href=&quot;http://www.idc.com/iCharts_Tracker/chartsapp.jsp&quot;&gt;IDC&lt;/a&gt;&lt;a href=&quot;http://www.icharts.net&quot;&gt;charts powered by iCharts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;안드로이드: 모바일은 내가 제일 잘나가~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이렇게 저의 험난한 안드로이드 입문이 시작됐습니다. libcurl 포팅이 골때린다는 인터넷 글들에 쫄았는데 막상 해보니 libcurl 안드로이드 지원이 삼십만년전에 끝났다는 사실에 놀랐고, boost를 어쩌지 이러고 있는데 Boost for Android가 벌써 만들어져 있다는 사실에 감탄했습니다. 그러면서… 아 이래서 세박자 늦게 시작하는게 좋구나라며 꿀빨고 있는데 프로요까지는 wchar_t 타입이 지원되지 않았다는 사실에 급 좌절했고 시스템에서 지원해주는 표준 유니코드 변환 함수가 없다는 사실에 무릎 꿀었습니다. iconv는 GPL 이슈 때문에 쓰기가 지랄맞다는 사실에 가슴 아팠고, ICU를 힘겼게 컴파일 했는데 빌드하니 so 파일 크기가 20메가가 넘어서 포기해야 했습니다. 결국 안드로이드 폴랫폼에 있는 ICU 라이브러리를 써야겠다고 생각했는데 이놈 조차도 안드로이드 버전 별로 다른 ICU가 포함돼 있어서 익스포트된 함수명이 다 다르다는 사실에 피를 토했지요.&lt;/p&gt;
&lt;p&gt;이 모든 기간동안 저를 가장 괴롭혔던 것은 Visual Sutdio가 없다는 점이었습니다. 처음엔 Visual Studio로 작업을 했는데 하도 빨간줄을 그어대는 바람에 짜증나서 Sublime Text 2로 작업을 했습니다. 그럭저럭 쓰긴 편한데 인공위성 쓰다가 나침반들고 작업하려니 기가 막힐 노릇이었습니다. 거기가 학부시절 자바 실험 때부터 저하고는 안 맞았던 이클립스는 여전히 그 철학적 기반이 저와는 180도 다르다는 사실을 새롭게 확인하는 과정을 반복했습니다. 그나마 P가 자바 버프를 제공해서 네이티브 코딩을 제외한 부분에서 걱정할 필요가 없어서 다행이었지요. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;XIGNCODE 클라이언트 코드도 장난 아니었습니다. 몇년된 프로젝트 답게 레거시 코드가 너무 많았고 그 모든 레거시 코드들이 다 윈도우를 가정하고 작성된 것들이라 여기저기 수정할 곳이 장난 아니게 많았습니다. 처음에는 크로스 컴파일 할 수 있도록 소스를 구성하다가 이러다간 죽도 밥도 안될 것 같아서 아예 복사해서 새로 다 고치는 대규모 토목 공사를 해야 했습니다. 이렇게 험난한 크런치 모드 끝에 마침내, 기어이, 우리는 안드로이드 플랫폼에서 알흠답게 동작하는 XIGNCODE 바이너리 파일을 획득할 수 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; margin-bottom: 16px;&apos; data-url=&apos;./안드로이드_입문.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/72add1f39fac8821c58c115b5ef4dbc0/dd4a7/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C_%EC%9E%85%EB%AC%B8.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 177.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAEm0lEQVR42o2W604bRxTHV1DgAxBSiTZQWiUUA6GJUKRyUaGiqpCoxK15or5DH4UvoEgIAYYkwsFgG9/A2AbfvV6vr9hgzPa3MzKQNG34a3R05sycOWfOZXaV7u7ukZHnY2M/K19Ca8ejRwMvukanHw+/au7qbvthUHn69NnzEcvAwMBjga6urq8b+OYTfPukp3+w76dX3/VbnvR93/NsQBmbHPnr7/nffv9lcWFp7o+5+fn5paWlhYWF2dnZ4eHhoU9gsQz+2D9oGRgaHIRXXrwcnluaGB19OTMzM/3r9NTU1OTk5MTExPj4uIWtApYGzMnQkDkEFK/Xd+T0+ny+o6Mjt4CngePjY7/AcQPwvntQarWaqqaz2ezFxYWmaYVCIZPJqKqKJJfLXV5eVqvVdDqNsChg3IOSz+cdDgfHRCIRjAcCAajT6YQGg0F0wuEwXuARljn65uamLgCjcBj7Tk5O4vE49OzsjE0woVAItWQyiX2W4M/PzzkLnTvL5XLZ6/WylX3RaLRSqeB/qVQqC1wISAbK6tXVFReBmspYxknc5mCXy4XbGAkKcFYsFkOOI1CcgnI7NsCbbmOEyYmAVMPP6+tr4wEw3ZZ3xm3o6ekp+eCS9+/2n8pYlsqpVApKtNDHN+L5IGXujI6MtowzeWbtRuB2q+Q/ivatciKR4MKEBE3yiZyoPsCyw4G7CZKJ0WCQeoIGiEIioamqJiounUrFY7EsNUiquZGwr5BQB2UcDCbSaX8goBcKWi4XS6XK1SojXyrpxaKq62ldT2YyTHPFYr3huVKORo/W1/1WaxL7Ozuh9+/De3uVSKRweho/PFQ9nnomY+Ryhq6bQ9OMbNZAkkoZtZpCfblttoDdHvP7occfPiS5gt9/sr/PCBwcMCJud8TjCTudLIVdrrDbXQ0GDVVVSh6Pz+Xy2e1R8uRwZGMxg+orFC7z+ctcrqLrJs1mq7pO08GUVLWoafV43EgmlYtAwP3mjW99Pbm/H9rZybpcCZvt7O3bwNZWxuFAGN7Zibx7F7Rarzk3kTCEmnF2ZpTLSrFcdnq9FHQ8nSZRRO44FEppWlLTYMJExO8vVirVev3qXzWn0Cw8EFS9mk5DY9FoMh7P6TqZi56fkxgyxIhGImTuulYzkyTHbXlSJKRXFialkhX4YnvcVRi1HRKQdS5r++ZjfEaZNpZdhWVZoZzFlNb//966s4zDtDiPgfSc3sYLngoeOUr9s3Vu9jOWUcYglmE4QnY1vHz35DtDFOTDyoN7p8wOtspm0nVdWmMffF4gJ4CEoNJ8t61uvtuI0OQUpEQYiXxZ5RTmugH56F4JmG8YIm5IwDDuFYDZ29vb3t7e3d212WxWqxWKkNfb2wD7saEQUgJmt9sPBQ4ODphubW2trKysra1tbm6urq5ubGwgZOl2D2FCUcH1egP3vwb3c3srvw/zznxQ/xRYXl5eXFyUU3jJvH79elkAHolkJJjeffg7Ozvb29tbWlrktLm5me87n3sYKWlra+vr6+vp6TH/ElpbTflXDbDG17+jowMpU5a7BWCYNjU1cXpvby8Uns0tLS3/APmncGcEzbQaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         md 0&apos; title=&apos;&apos; src=&apos;/static/72add1f39fac8821c58c115b5ef4dbc0/dd4a7/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C_%EC%9E%85%EB%AC%B8.md_0.png&apos; srcset=&apos;/static/72add1f39fac8821c58c115b5ef4dbc0/08678/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C_%EC%9E%85%EB%AC%B8.md_0.png 190w,
/static/72add1f39fac8821c58c115b5ef4dbc0/dd4a7/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C_%EC%9E%85%EB%AC%B8.md_0.png 320w&apos; sizes=&apos;(max-width: 320px) 100vw, 320px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;모바일 게임 보안도 이제 XIGNCODE가 책임지겠습니다 ㅋㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;**그나저나 삼전구글 직원 분들이 참치, 마구로, 약주를 좋아하나 봅니다.**&lt;strong&gt;빌드명이 아스트랄하네요 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;웃을 일이 아닙니다. 겁난다면 루팅하고 리눅스를 공부한 다음에 SSHDroid를 설치하시길 권장해 드립니다~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;작업하는 내내 드는 생각은 안드로이드 플랫폼 참 문제있다라는 생각이었습니다. 안드로이드 플랫폼의 기본적인 보안 정책은 앱들에 별도의 uid, gid를 할당하는 방식을 사용합니다. 이게 좀 욱긴게 사실 백신 앱이 있어도 그놈도 이런 일반 권한으로 동작하는 개별 앱이기 때문에 접근 제한이 엄.청.나.게 심하다는 점입니다. 멀쩡히 백신에 탐지되는 프로그램도 아주 손쉽게 백신은 영원히 탐지하지 못하도록 만들 수 있는 방법이 지천으로 널린 노다지지요. 스파이앱이 활개치는 것을 막을 수가 없습니다. 스파이앱을 막기 위한 유일한 방법은 루팅을 하고 시스템 권한으로 동작하는 보안 소프트웨어를 직접 만드는 방법 밖에는 없습니다. 권한 구성이 신묘하게 돼 있는데 단지 참신하기만 합니다.&lt;/p&gt;
&lt;p&gt;여튼 이제 시작입니다. 아직도 포팅해야 할 코드의 압박이…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 마이너리티 리포트 딜레마 #0]]></title><description><![CDATA[IRIS 
Because these Minority Reports are destroyed the instant they occur. 단독 의견의 리포트는 파괴되거든요.  ANDERTON 
Why? 왜요?  IRIS 
Obviously, for…]]></description><link>https://jiniya.net/wp/archives/9494</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9494</guid><pubDate>Thu, 21 Feb 2013 23:58:47 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_마이너리티_리포트_딜레마_0.md_0.jpg&apos; data-width=&apos;320&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1c52ed50002cae0901f1dc68e5ba9164/d0f75/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 147.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgAB/9oADAMBAAIQAxAAAAGlkXesnJxGqeQ4VpDLlf/EABwQAAICAgMAAAAAAAAAAAAAAAECABEDEhATMf/aAAgBAQABBQJqMRbnWDwQVVBajC2qHIrLlBA8uptP/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAQQDAQAAAAAAAAAAAAAAEQABAhAhMUFh/9oACAEBAAY/Aly8aooxjH1kXixo1//EABsQAQADAAMBAAAAAAAAAAAAAAEAESExQVFh/9oACAEBAAE/IURWV8ibUCeQGOENd5gtGuyV6Iei1UWMxCqJ8Ib9ZTHZjwiW6Wf/2gAMAwEAAgADAAAAEG/azv/EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAEDAQE/EOFeRn//xAAWEQADAAAAAAAAAAAAAAAAAAAAECH/2gAIAQIBAT8QcP/EAB4QAQACAgMAAwAAAAAAAAAAAAEAESFBMWFxUYGh/9oACAEBAAE/EDM3NBhfruPuZ29Q/FlxKCqquIwNjhYU1IvKXs68hP6YsihTqIILnmuINcylPA1f3B4VoBFAqtbgUGPyTrHtT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                    0 md 0&apos; title=&apos;&apos; src=&apos;/static/1c52ed50002cae0901f1dc68e5ba9164/d0f75/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_0.jpg&apos; srcset=&apos;/static/1c52ed50002cae0901f1dc68e5ba9164/8ccab/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_0.jpg 190w,
/static/1c52ed50002cae0901f1dc68e5ba9164/ea4c8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_0.jpg 380w,
/static/1c52ed50002cae0901f1dc68e5ba9164/d0f75/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_0.jpg 750w&apos; sizes=&apos;(max-width: 750px) 100vw, 750px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IRIS&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Because these Minority Reports are destroyed the instant they occur.&lt;br&gt;
단독 의견의 리포트는 파괴되거든요.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ANDERTON&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Why?&lt;br&gt;
왜요?&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IRIS&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Obviously, for Precrime to function, there can’t be any suggestion of fallibility.&lt;br&gt;
After all, what good is a Justice system that instills doubt?&lt;br&gt;
It may be reasonable, but it’s still doubt.&lt;br&gt;
시스템의 완벽성엔 흠집이 없어야 돼요&lt;br&gt;
오류의 여지를 인정하면 효율성에 문제가 생기죠&lt;br&gt;
&lt;br&gt;
– 마이너리티 리포트, 2002&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;역자가 시스템 엔지니어가 아닌지 의심이 들 정도로 원문보다 번역이 아름다운 마이너리티 리포트의 한 장면. 실제로 시스템 상의 오류의 여지를 인정하면 효율성에 문제가 생기는 경우는 수도 없이 찾을 수 있다. 게임 보안 프로그래머들은 속도와 공간의 문제처럼 오류의 여지와 효율성 사이에서 항상 트레이드오프를 강요 받는다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/archives/tag/xigncode&quot;&gt;XIGNCODE&lt;/a&gt; 개발팀에서는 지속적으로 새로운 탐지 루틴을 개발한다. 이때 우리가 개발한 탐지 루틴을 P라고 생각해 보자. 우리는 이 코드 P의 성능을 0에서 1사이의 값으로 표기할 수 있다. 성능이 0이란 말은 과거에 알려진 해킹툴은 차단할 수 있지만 미래에 출현할 해킹툴에 대해서는 하나도 차단할 수 없다는 것을, 반대로 1은 미래에 출현할 모든 해킹툴까지 예측해서 차단할 수 있다는 것을 의미한다. P가 1인 루틴이 하는 일이 마이너리티 리포트에서 나오는 프리크라임 시스템과 동일하다고 생각하면 되겠다.&lt;/p&gt;
&lt;p&gt;여기까지만 살펴보면 당연히 P의 성능이 1인 루틴이 최고인 것처럼 판단된다. 하지만 여기엔 “마이너리티 리포트”에서 지적한 것과 동일한 함정이 숨어있다. 바로 오진이다. 물론 루틴의 구현 방식에 따라서 성능과 오진 사이에 큰 상관 관계가 없는 경우도 있지만 대부분의 경우에 성능 지표가 올라가면 덩달아 오진 지표도 같이 올라간다. 성능이 1이면서 오진 가능성은 0인 ‘현자의 돌’같은 루틴이 있다면 좋겠지만 현실 세계에 그러한 것은 존재하지 않는다. 물론 아직 그런 방법을 우리가 찾지 못한 것일 수도 있다. 어쨌든 이러한 성능과 오진의 관계성 때문에 게임 보안 프로그래머들은 항상 아이리스가 말한 것처럼 reasonable과 doubt 사이에서 갈등한다. 이 정도면 reasonable한 것일까? 이건 너무 doubt 스럽진 않은걸까? 하고 말이다. 그리고 그러한 의문에 따라서 루틴의 성능 지표를 강제로 조금씩 조정한다. 실제 세상에서 봐줄만한 수준으로 돌아가도록 말이다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;그렇다면 왜 굳이 P의 성능을 높이는 방식으로 문제를 해결하려 했던 것일까? P가 0인 루틴을 사용하고 빠르게 과거를 추적한다면 효과를 볼 수 있지도 않을까? 맞다. 영리한 생각이다. 하지만 이런 전략이 실패하는 이유는 크게 세 가지 정도가 있다.&lt;/p&gt;
&lt;p&gt;첫째는 업데이트 속도다. 지난 글에서도 꾸준히 말하고 있지만 엄청나게 많은 사람들이 사용하는 게임과 관련된 코드를 자주 업데이트 하는 일에는 굉장히 많은 검증 작업이 필요할 수 밖에 없고, 또 위험할 수 밖에 없다. 따라서 자연히 업데이트 속도가 빠를 수가 없다. 그러니 덜 업데이트하고 더 효과적인 코드를 만드는 수 밖에는 없다.&lt;/p&gt;
&lt;p&gt;둘째는 해킹툴의 배포 속도다. 일반적으로 해킹툴의 배포 수준을 우리는 실행 대비 해킹툴 검출 비율로 판단한다. 이 오염도가 1%를 넘어서는 게임들에 대해서는 과거를 추적하는 방식으로는 제 아무리 업데이트 속도가 빠르다고 한들 큰 효과를 보기가 힘들다. 해커는 우리가 설날 떡국을 삼키는 그 순간에서 컴파일을 하고 코드를 고치고 릴리즈를 한다. 물론 쪽수는 우리가 상상도 하지 못할 정도로 많다. 그러니 속도전으로 가는 것은 크게 좋은 전략은 아니다. 하지만 아이러니 하게도 속도전이 반드시 필요한 순간도 있긴 하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_마이너리티_리포트_딜레마_0.md_1.png&apos; data-alt=&apos;정말 10명중 한명은 핵을 사용하는 상황. 방마다 핵이 넘쳐 난다는 말이 거짓말은 아니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 401px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/db69e553b0a444990780ff1361e3b45b/25946/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 32.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABKElEQVR42o2MTUsCURSG51eFfSza9gPaFiMhrVq3rYU/J0M0MGRMjaYoDULSQCO8945T92s+7tz5Eqeji9bBw+G8D+85BqPsYzKZTadoTqQQnPH/AFdSeoaUAmGECcYLzCXlggv4sYEKSvnPXxSSs43hgkH0fM/49MaV7v6xVbp8MavDU9Mqla1d4Ki9dfF8Uh1WTGvbtHaAcmfv3D6Ezln/APpjNjCoch7d1h2+7pFGB11ZuNZ3GvbiFmKX1Lu43iNNe9HqOY1756aDan3ShMV2W65CRpB4RbEi4dc7H0zlaO7PolwVRcFjd8Se4P23clfFKlnqIBVv9GHMX0mIwISJZ8SpjrJAZyrOo2SZwAxSqTJ/bbIoybXOlUr9MJWbjl6bTEEhTvUvDc0vNrrgsLcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;정말 10명중 한명은 핵을 사용하는 상황. 방마다 핵이 넘쳐 난다는 말이 거짓말은 아니다.&apos; title=&apos;&apos; src=&apos;/static/db69e553b0a444990780ff1361e3b45b/25946/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_1.png&apos; srcset=&apos;/static/db69e553b0a444990780ff1361e3b45b/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_1.png 190w,
/static/db69e553b0a444990780ff1361e3b45b/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_1.png 380w,
/static/db69e553b0a444990780ff1361e3b45b/25946/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_1.png 401w&apos; sizes=&apos;(max-width: 401px) 100vw, 401px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;정말 10명중 한명은 핵을 사용하는 상황. 방마다 핵이 넘쳐 난다는 말이 거짓말은 아니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;셋째는 추적의 비 효율성이다. 우리가 수집할 수 있는 해킹툴이란 정말 빙산에 일각에 불과하다. 통상적으로 우리는 하루에 1500-2000개 정도의 해킹툴 샘플을 수집한다. 물론 이 수치는 적용되는 게임이 늘어나면 늘어날수록 기하급수적으로 높아진다. 하지만 이것 또한 정말 아주 큰 빙산에 점하나 정도 밖에는 되지 않는다. 세상에는 정말 다양한 게임핵들이 있고, 또 지금 이 순간에도 만들어진다. 그걸 우리가 모두 찾아낸다는 것은 정말이지 불가능에 가깝다.&lt;/p&gt;
&lt;p&gt;이런 다양한 이유 때문에 일정 수준 오진율을 감수하고서라도 P의 성능이 높은 루틴을 사용할 수 밖에 없다. 물론 오진도 낮추면서 성능을 높이는 것이 최고라는 건 두말하면 입아푸다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;그렇다면 어떤 것들이 주로 오진의 범주에 포함될까? 탐지 루틴의 성격에 따라서 천차만별이긴 하지만 대다수 탐지 루틴에서 공통적으로 높은 오진율을 자랑하는 것들이 있다. 바로 악성코드이거나 바이러스다. 일부는 게임 계정을 탈취하는 목적으로 사용되는 것도 있으니 각별한 주의가 필요하다. 종종 이런 심각한 악성 코드나 바이러스에 감염된 사용자들이 문의를 해오곤 한다.&lt;/p&gt;
&lt;p&gt;대부분 원격으로 게임을 할 수 있도록 대응을 해주고 있는데, 가끔씩은 백신으로 아예 치료가 불가능한 것들이 있기도 하고, 더러는 치료를 하고 나면 인터넷이 먹통이 되는 경우도 있다. 이런 경우는 실컷 도와주고도 난감한 상황에 봉착하는 경우가 한두번이 아니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_마이너리티_리포트_딜레마_0.md_2.png&apos; data-alt=&apos;안타깝지만 이런 일이 더 많아 질수록 우리는 더 많은 해킹툴을 놓칠 수 밖에 없다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/48ff904d72efebff70bd912ccb3936a8/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 44.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABG0lEQVR42nWPCW7CMBBFfYOSAFlskziLt8SEhFIIi3r/Y/XHIRUVqvRkvT/SzHiIyhPQ1Lu2pIavC7Yp+QLz/MpbJFqkpmRHp05WdDxkcZDFwW5ilSVhlswSwPN04tWJzBNBNzxaseiDRoES1BRpU6a6YAXbljzCpwQNBV37nrWteO4dkKaitkjRoPNYZZEtKSpOsrbmxtedhCRa4LpYixh1vHBAxoO6Hc211/ejxXs5SMjYqzneB3PQmaupq9lecgDfy6eTSyevg7kNZpqyyLU3j087x3NXYwqKED9XTy29/nIVQf4+O/RDsPZxam6D7U3u/OxlG+/Ua1w2T2vxQ78E7Gvm/tKCioJn9NJ6J+Ny7Xx2p3burf8/fgCSGExVQ6BScAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;안타깝지만 이런 일이 더 많아 질수록 우리는 더 많은 해킹툴을 놓칠 수 밖에 없다.&apos; title=&apos;&apos; src=&apos;/static/48ff904d72efebff70bd912ccb3936a8/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_2.png&apos; srcset=&apos;/static/48ff904d72efebff70bd912ccb3936a8/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_2.png 190w,
/static/48ff904d72efebff70bd912ccb3936a8/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_2.png 380w,
/static/48ff904d72efebff70bd912ccb3936a8/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%A7%88%EC%9D%B4%EB%84%88%EB%A6%AC%ED%8B%B0_%EB%A6%AC%ED%8F%AC%ED%8A%B8_%EB%94%9C%EB%A0%88%EB%A7%88_0.md_2.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;안타깝지만 이런 일이 더 많아 질수록 우리는 더 많은 해킹툴을 놓칠 수 밖에 없다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;많은 게이머들이 공정한 게임을 하고 싶어한다. 정말 공정한 게임을 하고 싶다면 바이러스나 악성코드에 감염되지 말자. 그러면 게이머는 계정탈취나 랙을 겪지 않아서 좋고, 우리는 루틴의 성능 지표를 강제로 조정하지 않아서 좋고, 탐지율은 올라가서 좋고, 게임 운영자는 클레임이 줄어서 좋다. 이렇게 몇 바퀴만 구르면 깨끗한 게임 환경을 만드는 것도 어렵지 않다.&lt;/p&gt;
&lt;p&gt;명심하자. 무리 중에 더러운 녀석을 찾는 가장 쉬운 방법은 모두가 깨끗해지는 것이다. 모두 똥을 묻히고 있으면 누가 더러운지 판단이 잘 서지 않는다. 자 이제 가서 무료 백신을 설치하고 실시간 감시기를 켜도록 하자. 그리고 절.대.로 인터넷에서 받은 이상한 파일은 실행하지 말도록 하자. 설령 백신이 그 파일이 문제없다고 보고할지라도 말이다. 참고로 무료 백신 중에는 광고가 뜨긴 하지만 Avira가 제일 잘 잡는 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[죽기 전에 이런 코드 한 번 쓸 수 있을까?]]></title><description><![CDATA[요즘 별 일 없이 바쁘다는 핑계로 책도 안 읽고, 코드도 너무 안 읽었다. 넥서스…]]></description><link>https://jiniya.net/wp/archives/10329</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10329</guid><pubDate>Tue, 19 Feb 2013 23:58:46 GMT</pubDate><content:encoded>&lt;p&gt;요즘 별 일 없이 바쁘다는 핑계로 책도 안 읽고, 코드도 너무 안 읽었다. 넥서스7로 침대에서 뒹굴거리다 트위터와 뉴스질에 지쳐갈 무렵, 소설책도 읽기 싫은 그 시점, 코드나 읽을까, 라는 생각이 들었다. 잽싸게 요즘 가장 뜨겁다는 깃허브에 들렀다. 어떤 코드가 좋을까를 생각하던 중 막연하게 탐색해 보기로 했다. 그리곤 언어별로 저장소에 있는 소스를 정렬해 봤는데. 헉. C/C++ 없어도 너무 없다. 아래는 깃허브 통계 자료~&lt;/p&gt;
&lt;center&gt;  
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; margin-bottom: 16px;&apos; data-url=&apos;./죽기_전에_이런_코드_한_번_쓸_수_있을까.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c50dc7d1286dc1ffae95626c4efade6e/abf7b/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 39.473684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABTElEQVR42mN4+/bdx/fvv/78M3f/g8a1N1rX32wBIyCjYc31yuXXqlZcA5JN6250bbrVCUPtG25O2nGX4eWLl79+/Xz/5WfW3AvOLUc9Oo65t4OQa+vRiEmnixZfLlh4KXPuhU1nnr368P3h6y+P33wFokdvvj59+43h1YtXf37//vTtV/7CSz5dxwP7TgT0ngjuP+nadnT67nv/////8/fv////wAgdMDx/8vz3r19AzXkLLnp1HvfvAWo+CSSdWo4sOvQQpPnPn3///mIFDO/ffgCa+uHLz9wFF707jwf1nQS63LPz2JLDj4B6/vz5iwcwfP3+HWj8h68/gc726z7h2XG8ed31A9deAXXhshCh+dXL10Bnv//yI2XWebvGI0DLj996CzTu9++/BAHDu7dvP334+Pnbr0WHHjWvu3Ho+mugL37++vOXCAAArsSWQQgf8ToAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                        md 0&apos; title=&apos;&apos; src=&apos;/static/c50dc7d1286dc1ffae95626c4efade6e/abf7b/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_0.png&apos; srcset=&apos;/static/c50dc7d1286dc1ffae95626c4efade6e/08678/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_0.png 190w,
/static/c50dc7d1286dc1ffae95626c4efade6e/2edd7/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_0.png 380w,
/static/c50dc7d1286dc1ffae95626c4efade6e/abf7b/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_0.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;C/C++ 형님께서 아사 직전입니다. 대조적인 자바스크립트의 위용~&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;  
&lt;p&gt;초라한 C++의 저장소 개수를 보면서 그래도 남자라면 C++을 외치면서 클릭을 해봤다. 남자라면 most watched를 외치며 줏대없이 클릭을 했는데 그 중에 단연 돋보이는 소스 코드가 있었으니 카맥옹의 DOOM3 소스였다. 예전에 퀘이크 소스를 보고 충격을 먹었던 기억을 되살리며 그래 한 줄을 읽어도 카맥옹의 소스를 읽어야지, 라며 들어가서는 DOOM3 저장소 탐방을 시작했다. 군더더기 없는 소스 트리하며, 정갈한 소스 코드는 퀘이크 때의 그것과 크게 다르지 않았다. 단지 C에서 C++로 간 느낌? idlib과 sys쪽 코드를 좀 읽었는데 눈물을 감출 길이 없었다. 보는내내 촌스럽고, 안스럽고, 황당하기 그지없는 나 자신을 발견했다. 부끄러웠다. 난 과연 지난 시간 무엇을 한 것인가? 언제 이런 코드 한 번 써보나 하는 생각. 죽기 전에 한 번 써 볼 수 있을까?, 라며 감탄사를 남발하는 그 순간 카맥 옹의 훅 코드에서 나의 멘탈은 초라한 안정을 되찾을 수 있었다. 그래도 훅은 내가 좀 더 아는 것 같다며… 굼벵이도 구르는 재주가 있다고 했던가 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;카맥옹의 단정한 코드는 그 코드를 읽는 것만으로도 한 수 배울 수 있어서 큰 도움이 되지만 그것 외에도 멘탈적으로 큰 힐링이 되는 느낌이다. 그의 단아한 코드는 나에게 전 우주적 자괴감과 초라함, 미칠듯한 열등감을 선사하지만 그 와중에도 코딩을 하고 싶게 만드는 묘한 매력이 있기 때문이다.&lt;/p&gt;
&lt;p&gt;코드를 좀 읽고는 이것 저것 찾다가 &lt;a href=&quot;http://fabiensanglard.net/doom3/index.php&quot;&gt;DOOM3 코드를 분석한 블로그&lt;/a&gt;를 찾았다. 꿈보다 해몽이라고 했던가? 코드보다 이 블로거의 분석이 더 놀라웠다. 퀘이크 소스 분석도 있는데, 드는 생각은 와~ 블로그 저렇게 해야 하는데 라는 생각 … ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;20살 이후로 단 한 번도 훌륭한 프로그래머가 되고 싶다는 생각을 버린 적이 없었다. 토나오게 많은 시간이 지났지만 그 꿈이 이뤄질 기미는 전.혀. 보이질 않는다. 당췌. 이번 생은 아닌건가~ @.@&lt;/p&gt;
&lt;p&gt;덧) 카맥옹하니 중학교 땐가 고등학교 땐가 컴퓨터 잡지에 실렸던 인터뷰 기사가 생각난다. “하루라도 코딩하지 않으면 입에 가시가 돋힌다”라는 내용이었는데 어린 마음에 참 신선한 충격이었다. 송재경님은 아들이 커서 아들이랑 같이 코딩하는게 꿈이라는 인터뷰를 했던 기사가 있었던 것 같다. 근데 안타깝게도 카맥옹이 선수를 친 건 아닌지? ㅎㅎ~ 리틀카맥 뒷모습에서 우월한 유전자의 포스가 뿜어져 나온다~&lt;/p&gt;
&lt;center&gt;  
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; margin-bottom: 16px;&apos; data-url=&apos;./죽기_전에_이런_코드_한_번_쓸_수_있을까.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/644602804e712817dd00d249f777de7c/8980b/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAMEBQH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQP/2gAMAwEAAhADEAAAAchYDSQC1InNBsKA3//EAB4QAAIBAwUAAAAAAAAAAAAAAAECEQADEhAhIjFB/9oACAEBAAEFAiNFEBFzd1wuBtpip5E2TXp7r//EABYRAAMAAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwFw/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGRABAAIDAAAAAAAAAAAAAAAAARAxAAIg/9oACAEBAAY/ApDHWLik4//EABsQAQADAQADAAAAAAAAAAAAAAEAESExEEFR/9oACAEBAAE/Id+wLKojjhMHUXQh3IU89xClQJaeOPJqzbKB5eFst19d8Jps/9oADAMBAAIAAwAAABAQLI//xAAXEQADAQAAAAAAAAAAAAAAAAAAARFR/9oACAEDAQE/EHE4UbpWn//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQIBAT8QFy7Blt//xAAeEAEAAwACAgMAAAAAAAAAAAABABEhUXExQWGBkf/aAAgBAQABPxCq1kv23OLjd1sKjXdg00FBWpeBaK8evi4SDe2FzXBVVXcftRtr+xzTDwHdkWNt0cwBQ5mV1P/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                        md 1&apos; title=&apos;&apos; src=&apos;/static/644602804e712817dd00d249f777de7c/8980b/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_1.jpg&apos; srcset=&apos;/static/644602804e712817dd00d249f777de7c/8ccab/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_1.jpg 190w,
/static/644602804e712817dd00d249f777de7c/8980b/%EC%A3%BD%EA%B8%B0_%EC%A0%84%EC%97%90_%EC%9D%B4%EB%9F%B0_%EC%BD%94%EB%93%9C_%ED%95%9C_%EB%B2%88_%EC%93%B8_%EC%88%98_%EC%9E%88%EC%9D%84%EA%B9%8C.md_1.jpg 320w&apos; sizes=&apos;(max-width: 320px) 100vw, 320px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;리틀카맥! 아빠가 3D를 개척했으니까 전 4D를 개척하겠어요~&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;  </content:encoded></item><item><title><![CDATA[XLGAMES 커버 스토리]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/10295</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10295</guid><pubDate>Wed, 13 Feb 2013 23:58:45 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 510px; margin-bottom: 16px;&apos; data-url=&apos;./XLGAMES_커버_스토리.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/36b41332a9c2eebdec615beafb93b785/1b7d6/XLGAMES_%EC%BB%A4%EB%B2%84_%EC%8A%A4%ED%86%A0%EB%A6%AC.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 49.473684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABvElEQVR42mWRW0/iUBSFz2+AWOQBGEpoC7QBez1Dy6XogC0XDfqgqBEdoiY1ahTQh7kZZzJj1IlOxsub/8Jnf5oLFWN0pV0n2Xt9+5yeEo7jRFFMp9OZTGbsUbIsp1KpuYXFdqeztLKKRxLFsaEQQxgIQIJFVVVK6cehTMvSVeXbyd/bm59HP3YPzy6ormez2ZcAwoqiACQYYxiGaZq5ofL5vKFpX/6c3t9d3159P/h1nM9ZhULhqQVHGAhAIkmSpmmDDYeybTtnmSf/r4/OT3uHX3//u1QV2aAULcuy4DgFDguQJJNJfAl4DIMX7VJ/v9/f3+t2e96mt7Oz3V5ue57X63ZLdhEBSgcxIAAJz/OYgUtSFIxTdV1/2mFra3tjbb3zubOyvFosFMvlMjUMVR2EFFkGApCwbBTX3JxuVt1qpVJu1OpuxSmNj7fmW4vzC1PTzdmZ2U8TE7Vq3Zl0nUm8bs11xZTIsiwJh8OxWCwej/M8xz9KEARuIKFRbziOk0gkBIGH89xzAGEgAEkwGAyFQpFI5MMrRaNRuCSl8U/ftCBUgAAkPp+PYZhAIDD6TqiPMMz7OsJo+f3+BwHdh7pghr3rAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;XLGAMES        md 0&apos; title=&apos;&apos; src=&apos;/static/36b41332a9c2eebdec615beafb93b785/1b7d6/XLGAMES_%EC%BB%A4%EB%B2%84_%EC%8A%A4%ED%86%A0%EB%A6%AC.md_0.png&apos; srcset=&apos;/static/36b41332a9c2eebdec615beafb93b785/08678/XLGAMES_%EC%BB%A4%EB%B2%84_%EC%8A%A4%ED%86%A0%EB%A6%AC.md_0.png 190w,
/static/36b41332a9c2eebdec615beafb93b785/2edd7/XLGAMES_%EC%BB%A4%EB%B2%84_%EC%8A%A4%ED%86%A0%EB%A6%AC.md_0.png 380w,
/static/36b41332a9c2eebdec615beafb93b785/1b7d6/XLGAMES_%EC%BB%A4%EB%B2%84_%EC%8A%A4%ED%86%A0%EB%A6%AC.md_0.png 510w&apos; sizes=&apos;(max-width: 510px) 100vw, 510px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;가끔 프로그래머끼리 술 마실 때 우스갯소리로 전 송재경 선생님 초상화를 걸어 놓고는 아침, 저녁으로 삼배씩 드린다는 농담을 하곤 합니다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/4806&quot;&gt;지난 글&lt;/a&gt;에서도 밝혔듯이 전 우리나라 프로그래머 중에서는 그 분을 제일 존경합니다. 근데 욱긴건 사실 뭐 그 분을 만나본 적도, 강연을 들은 적도, 그렇다고 그 분이 쓴 글을 읽은 적도 그다지 많지는 않습니다. 근데 왜 존경하냐구요? ArcheAge, Lineage, Kingdom of the Winds, Hanterm. 더 말이 필요한가요? 이쯤이면 뭐 게임 끝이죠. 진짜 프로그래머라면 전 작품으로 말해야 한다고 생각합니다. 작품이 없으니 글이 많아지고, 말이 많아진다고 전 생각하거든요.&lt;/p&gt;
&lt;p&gt;어쨌든 사설이 길었습니다. 오늘 이 이야기를 꺼낸 이유는 다름이 아니라 XLGAMES 홈페이지를 들어갔다가 충격을 받아서 였습니다. “모든 개발자는 QA다.”라는 대문에 걸린 저 말을 보는 순간 망치로 머리를 한 대 맞은 느낌이었거든요. 역시 뭔가 다르다는 느낌 ㅋ~ 커버 스토리에 있는 다른 글들도 다 좋은 내용인 것 같아서 과감하게 같이 퍼왔습니다. 눈물은 좀 닦고 배꼽을 바라보면서 묵념 자세로 충분한 반성의 시간을 가지도록 해야 겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl20.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/59a7089016e3013060e1478b7ee7dd9a/f20da/xl20.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdxaAD//xAAVEAEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAQABBQKsf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABwQAAMAAQUAAAAAAAAAAAAAAAABERAhQWFxkf/aAAgBAQABPyGLKa3jHYj2a8Iz/9oADAMBAAIAAwAAABATD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAQACAQUAAAAAAAAAAAAAAAEAEUEhMVHB8f/aAAgBAQABPxB2jfFx06QylpmW8R71AZSk/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl20&apos; title=&apos;&apos; src=&apos;/static/59a7089016e3013060e1478b7ee7dd9a/f20da/xl20.jpg&apos; srcset=&apos;/static/59a7089016e3013060e1478b7ee7dd9a/8ccab/xl20.jpg 190w,
/static/59a7089016e3013060e1478b7ee7dd9a/ea4c8/xl20.jpg 380w,
/static/59a7089016e3013060e1478b7ee7dd9a/f20da/xl20.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl6.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a544ef8f0d1149e01ab85c85e8208d4c/f20da/xl6.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe5NQoP/xAAXEAADAQAAAAAAAAAAAAAAAAAAEBEB/9oACAEBAAEFAjFCL//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABsQAAIBBQAAAAAAAAAAAAAAAAARkQEQQWGB/9oACAEBAAE/IWNm3MGqgVT/2gAMAwEAAgADAAAAENMP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAAIDAQEAAAAAAAAAAAAAAQARIUFhMVH/2gAIAQEAAT8QcPZZlVyWm5Vv64ijTIZSk//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl6&apos; title=&apos;&apos; src=&apos;/static/a544ef8f0d1149e01ab85c85e8208d4c/f20da/xl6.jpg&apos; srcset=&apos;/static/a544ef8f0d1149e01ab85c85e8208d4c/8ccab/xl6.jpg 190w,
/static/a544ef8f0d1149e01ab85c85e8208d4c/ea4c8/xl6.jpg 380w,
/static/a544ef8f0d1149e01ab85c85e8208d4c/f20da/xl6.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl19.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/05b3b8c81564fc18198d68c63f797e15/f20da/xl19.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe5NwA//xAAXEAADAQAAAAAAAAAAAAAAAAAAEBEh/9oACAEBAAEFAqVQ1f/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABwQAAIBBQEAAAAAAAAAAAAAAAABERBBUWFxof/aAAgBAQABPyGGTRqnRFj8IZ//2gAMAwEAAgADAAAAEFMP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBgfH/2gAIAQEAAT8QSaqVuUxtOW9RU7LfEeT7AZSk/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl19&apos; title=&apos;&apos; src=&apos;/static/05b3b8c81564fc18198d68c63f797e15/f20da/xl19.jpg&apos; srcset=&apos;/static/05b3b8c81564fc18198d68c63f797e15/8ccab/xl19.jpg 190w,
/static/05b3b8c81564fc18198d68c63f797e15/ea4c8/xl19.jpg 380w,
/static/05b3b8c81564fc18198d68c63f797e15/f20da/xl19.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl11.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/29cc75d105bd9660f082a868759e79b5/f20da/xl11.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHfPcsVHK//xAAaEAADAAMBAAAAAAAAAAAAAAABAgMQERMS/9oACAEBAAEFAqW836EFDtWmGbimP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABwQAAIBBQEAAAAAAAAAAAAAAAABAhAREiEyYf/aAAgBAQAGPwLHwinLbEXZyqf/xAAaEAADAAMBAAAAAAAAAAAAAAAAAREhUfBx/9oACAEBAAE/Icc0ZYBUqt6FERkr4cEEoj//2gAMAwEAAgADAAAAEHgP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFBYXGB/9oACAEBAAE/EG3wMPbhcVEaEcrfFqD2EbmyJE1RaVx3Fdo6vOHyAAAHU//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl11&apos; title=&apos;&apos; src=&apos;/static/29cc75d105bd9660f082a868759e79b5/f20da/xl11.jpg&apos; srcset=&apos;/static/29cc75d105bd9660f082a868759e79b5/8ccab/xl11.jpg 190w,
/static/29cc75d105bd9660f082a868759e79b5/ea4c8/xl11.jpg 380w,
/static/29cc75d105bd9660f082a868759e79b5/f20da/xl11.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl10.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/aa2c09ba6c71b887773502ad60545af5/f20da/xl10.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe20Io//xAAWEAEBAQAAAAAAAAAAAAAAAAAQEQD/2gAIAQEAAQUCZof/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAaEAADAAMBAAAAAAAAAAAAAAAAARFBYZGB/9oACAEBAAE/IW9leGK5PPCsThHo/9oADAMBAAIAAwAAABAjD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAAICAgMAAAAAAAAAAAAAAAABESExQXGBwf/aAAgBAQABPxBurTcsyQO6vI8NHyNHPgPcUpShvof/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl10&apos; title=&apos;&apos; src=&apos;/static/aa2c09ba6c71b887773502ad60545af5/f20da/xl10.jpg&apos; srcset=&apos;/static/aa2c09ba6c71b887773502ad60545af5/8ccab/xl10.jpg 190w,
/static/aa2c09ba6c71b887773502ad60545af5/ea4c8/xl10.jpg 380w,
/static/aa2c09ba6c71b887773502ad60545af5/f20da/xl10.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl9.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ad9c321e331d25d143d1634d1dbb0df7/f20da/xl9.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHbjYhgH//EABYQAQEBAAAAAAAAAAAAAAAAAAARIf/aAAgBAQABBQKrqIj/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAEBAQAAAAAAAAAAAAAAAAAxACD/2gAIAQEABj8CZz//xAAdEAACAgEFAAAAAAAAAAAAAAAAARExkUFhcYHx/9oACAEBAAE/IWnobUSObJOuDbGBNGh//9oADAMBAAIAAwAAABCQD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAQACAQUAAAAAAAAAAAAAAAEAESExQVFhof/aAAgBAQABPxDQtKekaEJbgWLHEStvhGuzIALhxP/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl9&apos; title=&apos;&apos; src=&apos;/static/ad9c321e331d25d143d1634d1dbb0df7/f20da/xl9.jpg&apos; srcset=&apos;/static/ad9c321e331d25d143d1634d1dbb0df7/8ccab/xl9.jpg 190w,
/static/ad9c321e331d25d143d1634d1dbb0df7/ea4c8/xl9.jpg 380w,
/static/ad9c321e331d25d143d1634d1dbb0df7/f20da/xl9.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl8.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2825c6c7bfab683e6582f2f96c4276c0/f20da/xl8.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAEDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdqLAB//xAAXEAEBAQEAAAAAAAAAAAAAAAARABAB/9oACAEBAAEFAme4Rn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAXEAADAQAAAAAAAAAAAAAAAAAAATEg/9oACAEBAAY/AqirP//EABsQAAIBBQAAAAAAAAAAAAAAAAABERAhQYGR/9oACAEBAAE/IW02BUHXg2wyGf/aAAwDAQACAAMAAAAQQw//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAgIDAAAAAAAAAAAAAAABABEhMXGxwf/aAAgBAQABPxDWgDNubiPC86uWkQwUUIcV0wMpSf/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl8&apos; title=&apos;&apos; src=&apos;/static/2825c6c7bfab683e6582f2f96c4276c0/f20da/xl8.jpg&apos; srcset=&apos;/static/2825c6c7bfab683e6582f2f96c4276c0/8ccab/xl8.jpg 190w,
/static/2825c6c7bfab683e6582f2f96c4276c0/ea4c8/xl8.jpg 380w,
/static/2825c6c7bfab683e6582f2f96c4276c0/f20da/xl8.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl7.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/efeab9a5cb8a791313b61eda0ed139c0/f20da/xl7.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe3NwoP/xAAXEAADAQAAAAAAAAAAAAAAAAAAAREQ/9oACAEBAAEFAmy5CZ//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAcEAABAwUAAAAAAAAAAAAAAAAAARFhECFRkaH/2gAIAQEAAT8hwrcSXR5pi2hlP//aAAwDAQACAAMAAAAQMA//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMUFhgf/aAAgBAQABPxCgQOMupXhD8bhbViUV1nyL6kGUpP/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl7&apos; title=&apos;&apos; src=&apos;/static/efeab9a5cb8a791313b61eda0ed139c0/f20da/xl7.jpg&apos; srcset=&apos;/static/efeab9a5cb8a791313b61eda0ed139c0/8ccab/xl7.jpg 190w,
/static/efeab9a5cb8a791313b61eda0ed139c0/ea4c8/xl7.jpg 380w,
/static/efeab9a5cb8a791313b61eda0ed139c0/f20da/xl7.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl5.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/70cda96d75586d97cac0aafa7d56a411/f20da/xl5.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdtUUV//xAAXEAADAQAAAAAAAAAAAAAAAAAAEBES/9oACAEBAAEFAq8kX//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAQEBAAAAAAAAAAAAAAAAADEAIP/aAAgBAQAGPwJnP//EABkQAQADAQEAAAAAAAAAAAAAAAEAEWEQkf/aAAgBAQABPyFEDjiWZryU5P/aAAwDAQACAAMAAAAQmw//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAgIDAAAAAAAAAAAAAAABABExYSFBUf/aAAgBAQABPxDllBNwbrI+3cVO4kqCuoszMBlLbU//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl5&apos; title=&apos;&apos; src=&apos;/static/70cda96d75586d97cac0aafa7d56a411/f20da/xl5.jpg&apos; srcset=&apos;/static/70cda96d75586d97cac0aafa7d56a411/8ccab/xl5.jpg 190w,
/static/70cda96d75586d97cac0aafa7d56a411/ea4c8/xl5.jpg 380w,
/static/70cda96d75586d97cac0aafa7d56a411/f20da/xl5.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; margin-bottom: 16px;&apos; data-url=&apos;./xl4.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e77b7fb724a90f62103a57c6532bb6fb/f20da/xl4.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 72.10526315789473%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB21AD/8QAFxAAAwEAAAAAAAAAAAAAAAAAABARAf/aAAgBAQABBQKmqEX/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAXEAADAQAAAAAAAAAAAAAAAAAAICEx/9oACAEBAAY/AtIv/8QAHBAAAgICAwAAAAAAAAAAAAAAABEBQRCRUWGB/9oACAEBAAE/IV4DLtePOhqmNCk//9oADAMBAAIAAwAAABCDD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABkQAQEBAQEBAAAAAAAAAAAAAAERAEEhYf/aAAgBAQABPxBFRocuS9n4c+707oW4lZMDIpv/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;xl4&apos; title=&apos;&apos; src=&apos;/static/e77b7fb724a90f62103a57c6532bb6fb/f20da/xl4.jpg&apos; srcset=&apos;/static/e77b7fb724a90f62103a57c6532bb6fb/8ccab/xl4.jpg 190w,
/static/e77b7fb724a90f62103a57c6532bb6fb/ea4c8/xl4.jpg 380w,
/static/e77b7fb724a90f62103a57c6532bb6fb/f20da/xl4.jpg 555w&apos; sizes=&apos;(max-width: 555px) 100vw, 555px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./xl3.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./xl2.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./xl1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[여가부 헌정 동영상]]></title><description><![CDATA[0
 0]]></description><link>https://jiniya.net/wp/archives/10271</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10271</guid><pubDate>Tue, 05 Feb 2013 23:58:44 GMT</pubDate><content:encoded>&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[리눅스 포팅의 기본]]></title><description><![CDATA[예나 지금이나 리눅스의 백미는 여자 연예인 배위에서 코딩하는 그 맛~ 보고있나 Visual Studio !!! 리눅스를 처음 본 게 아마 95년인가 96년인가 그랬던 것 같다. 당시 커널이 1.2였던 시절이었다. 디스켓 2-3…]]></description><link>https://jiniya.net/wp/archives/5589</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5589</guid><pubDate>Mon, 04 Feb 2013 23:58:43 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;http://www.dettus.net/photos/openbsd_icewm_eterm_vim_screenshot.jpg&quot; alt=&quot;&quot;&gt;
&lt;strong&gt;예나 지금이나 리눅스의 백미는 여자 연예인 배위에서 코딩하는 그 맛~ 보고있나 Visual Studio !!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;리눅스를 처음 본 게 아마 95년인가 96년인가 그랬던 것 같다. 당시 커널이 1.2였던 시절이었다. 디스켓 2-30장을 넣어가면서 설치하던 시절은 아니었고 CD를 통해서 설치하던 시절이었다. 물론 그렇다고 지금만큼 편한 시절은 아니었다. 온갖 설정들을 다 해줘야 뭐라도 동작하던 시절이었다. 수많은 밤을 지새면서 X-Window를 처음 띄우고는 그 단순하다 못해 허무한 X 아이콘에 눈물을 흘리기도 했었고, 구형 사블 호환 카드에서 소리가 나오는 것을 보고는 탄성을 지르기도 했었다. 그 당시만 해도 리눅스를 쓴다고 하면 아무도 모를 뿐더러 진정한 괴짜 취급을 받던 시절이었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/07/alinux.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/07/alinux.png&quot; alt=&quot;&quot; title=&quot;alinux&quot;&gt;&lt;/a&gt;
&lt;strong&gt;내가 바로 국내 리눅스 전도사. 알짜 리눅스!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그렇게 세월이 흘렀고 1997년이 도래했다. 이때가 국내 리눅스의 일대 부흥기라 할 수 있다. 알짜 리눅스를 필두로 여기저기 배포판 만드는 사람들이 늘어났다. 마소나 프세같은 잡지에도 종종 리눅스 특집 기사가 실리곤 했었다. 상황이 그렇게 바뀌자 어디가서 리눅스 쓴다고 하면 고수 대접을 받는 웃지 못할 일도 있었다. 그러다 대학교를 들어가면서 부터는 아예 리눅스를 쓰지 않았다. 그때부터 소프트웨어는 너무 구하기 쉬워졌고 더이상 불편한 리눅스를 사용할 필요가 없었기 때문이었다.&lt;/p&gt;
&lt;p&gt;그리고 또 결정적으로 리눅스계를 떠나 사건이 있었다. 병특 자리를 구하던 중에 학교 내에 있는 리눅스 벤처에서 알바를 했었는데, 거기서 내 평생내 정말 쿨~하게 돈을 떼이는 경험을 했기 때문이었다. 그 사장은 어처구니 없게도 리누스 토발즈도 이런걸 만들어서 공짜로 공개하는데 니까짓게 뭐한다고 돈을 받아야 하느냐는 토나오게 말도 안 되는 마인드의 소유자였다. 여튼 그래서 윈도우로 옮겨탔는데 그때나 지금이 그 선택에 후회는 없다.&lt;/p&gt;
&lt;p&gt;그렇게 나의 기억속에서 영원히 잊혀질 것 같았던 리눅스가 최근에 다시 등장했다. 리눅스를 사용하는 게임 서버 프로그램들을 마주하면서 XIGNCODE 코드를 리눅스로 포팅할 필요가 있었기 때문에다. 사실 뭐 포팅 작업 자체는 크게 힘들지 않았는데 엉뚱한 부분들에서 엄청 헤맸다. 아주 사소한 타입 차이를 간과했다거나 UCS2/4의 변환 문제 같은 것들이었다. 포팅을 하고나서 이런 것들을 미리 알았더라면 하는 몇 가지를 여기에다 끄적여 본다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;우선 여러분이 제법 큰 소프트웨어를 만들고 있었다면 당연히 여러분만의 타입시스템을 가지고 있어야 한다. 소프트웨어의 모든 부분을 관통하는 타입시스템이 없다면 좀 곤혹을 치를 수 있다. 그러니 무엇을 만들던지 규모가 좀 있다면 사전에 반드시 먼저 타입시스템을 설계하도로 하자. 뭐 타입시스템 같은건 모르겠다 싶으면 stdint.h같은 호환성 있는 타입시스템을 사용하는 것이 여러분의 포팅을 수월하게 해 줄 것이다. win32 타입시스템이라도 썼다면 그걸 기준으로 리눅스용 헤더를 작성하면 된다. 그런데 그 조차도 없이 진짜 네이티브 타입시스템(int, char, long 따위)을 썼다면 흠~ 생각 좀 해보자. 눈물 좀 닦고.&lt;/p&gt;
&lt;p&gt;타입시스템을 쓰는 가장 큰 이유는 우리가 사용하는 타입의 크기가 시스템마다 다르기 때문이다. 흔한 예로 int는 16비트 시스템에서는 16비트, 32비트 시스템에서는 32비트가 된다. 따라서 시스템이 변경되면 타입의 크기가 달라지면서 많은 문제가 생길 수 밖에 없다. 전 16비트 시스템을 사용하지 않는데염, 따위의 소리를 해도 소용없다. 지금은 64비트가 있다. 너무나 당연한 이야기겠지만 리눅스와 윈도우는 서로 다른 64비트 타입 시스템을 채용하고 있다. 윈도우는 아래 표에 나오는 LLP64 시스템을, 리눅스는 LP64 시스템을 사용한다. 따라서 생각없이 long을 사용했다면 불지옥을 맛볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;주저리 주저리 떠들었는데 타입시스템이 있으면 무엇을 해야 하느냐? 그걸 리눅스에 맞도록 변경해주면 된다. 여러분이 윈도우에서 typedef long mylong;과 같이 사용했다면 64비트 리눅스에서는 typedef int mylong;을 해야 한다는 이야기다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;타입을 넘어가면 다음으로 우리를 괴롭히는 녀석은 유니코드다. 기본적으로 Visual C++은 UCS2를 사용한다. 안타깝지만 너무나 당연하게도 gcc는 UCS4를 사용한다. 이 말이 의미하는 바는 다음과 같다. Visual C++에서 L”Hello”를 하면 6글자를(NULL 포함) 저장하기 위해서 12바이트를 사용하지만, gcc는 UCS4를 사용하기에 24바이트를 사용한다는 의미다. 이건 기본적으로 섬세하게 코딩됐다면 큰 문제를 일으키지는 않는다. 섬세하게 코딩되지 않았다는 말은 sizeof(wchar_t) 따위를 사용하지 않고 2를 하드코딩 하는 것과 같은 것을 의미한다. 그런 기본적인 실수만 없다면 프로그램 동작 상에 발생하는 큰 문제는 없다.&lt;/p&gt;
&lt;p&gt;하지만 진짜 문제는 바이너리 파일을 사용할 때 발생한다. 여러분이 설계한 바이너리 파일이 UCS2의 데이터를 가정하고 있고 그걸 변환없이 Visual C++에서 읽어들이면서 재미를 봤다면 조금 골치가 아파진다. 그런 부분은 전부 별도로 처리를 해야한다. 이게 생각보다 골치아푸다. 괜히 UTF-8같은 걸 사용하는 게 아니다. 어쨌든 이런 부분이 있다면 아주 섬세하게 꼼꼼하게 생각해서 변환 루틴들을 적용시켜 주어야 하겠다.&lt;/p&gt;
&lt;p&gt;윈도우는 MultiByteToWideChar나 WideCharToMultiByte 함수를 사용해서 문자열 변환을 쉽게 할 수 있지만 당연히 리눅스에는 그런 것 따위는 없다. iconv 라이브러리를 사용하면 동일한 버전을 구현할 수 있으니 해당 라이브러리를 사용해서 변환 함수를 구현해주면 되겠다.&lt;/p&gt;
&lt;p&gt;_wfopen 같은 함수를 찾아 헤맬지도 모르겠다. 리눅스에는 애초에 그런 종류의 함수는 없다. 따라서 해당 함수가 필요하다면 직접 구현해야 한다. 윈도우의 A/W 전략과는 반대로 gcc는 대체로 기존 함수에다 UTF-8 문자열 입력 기능을 추가해서 유니코드에 대응하는 방식을 채택하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;여러분이 fopen보다는 CreateFile에 더 익숙하고, fstat보다는 GetFileAttribute에 더 익숙해서 프로그램 전반에 이런 API를 사용하는 부분이 많이 있다면 일일이 API를 사용한 부분을 변경하는 것보다는 CreateFile, GetFileAttribute와 같은 함수의 리눅스 버전을 작성하는 것이 좋다. 이런 작업을 한다면 &lt;a href=&quot;http://www.winehq.org/&quot;&gt;wine&lt;/a&gt;(리눅스에서 윈도우를 구동시켜주는 에뮬레이터 프로젝트) 소스 코드가 큰 도움이 될 것이다. 거의 모든 API가 구현돼 있기 때문에 내부를 살펴보면 어떻게 만들어야 하는지 대충 감을 잡을 수 있다.&lt;/p&gt;
&lt;p&gt;다음으로 호환성 있는 함수라고 생각하고 썼는데도 함수명이 다른 경우도 있다. fstat 같은 함수도 그렇다. gcc에서는 fstat이지만 Visual C++에서는 _fstat이다. 이런 함수들은 당연히 호출 부분마다 전처리기를 사용해서 별도로 처리하기 보다는 mystat 같은 래퍼 함수를 만들거나 매크로를 선언해서 해당 함수를 호출하도록 만들어주는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;문자열에 관한 함정이 또 하나 있다. 바로 포매팅 문자열이다. 윈도우에서는 printf 같은 멀티바이트 함수에서 %s는 멀티바이트 문자열을 %S는 유니코드 문자열을 나타내고, wprintf 같은 유니코드 함수에서는 %s는 유니코드 문자열을, %S는 멀티바이트 문자열을 나타낸다. 근데 gcc에는 이렇지가 않다. printf, wprintf 모두 %s는 멀티바이트, %S는 유니코드를 나타낸다. 따라서 %s, %S 따위를 쓰면 십중팔구 바보가 될 수 있다. 전처리기로 처리하는 것 또한 좋은 생각이 아니다. 가장 좋은 방법은 애초에 %s, %S를 사용하지 않는 것이다. %hs, %hc, %ls, %lc를 사용하는 습관이 도움이 된다. 함수에 관계없이 %hs, %hc는 멀티바이트를, %ls, %lc는 유니코드를 나타낸다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;끝으로 가장 골치 아픈 부분인데 여러분의 코드가 어떻게든 시스템의 도움을 받는 부분들이 있을 것이다. 이 부분이 가장 크리티컬하다. 예를 들면 윈도우 프로그램이라면 별 생각없이 스레드를 사용했을 것이다. 이런 경우에 그런 부분들에 해당하는 함수를 일일이 만드는 행위나 함수 호출 부분을 별도로 코딩하는 일은 실수를 많이 만들어낸다. 자신들과 비슷한 구조를 가진 검증된 라이브러리가 있다면 그걸 사용하는 것이 훨씬 좋다. 우리 같은 경우에는 윈도우 스레드를 자체적으로 추상화 시켜서 사용하고 있었는데 구조가 boost 스레드랑 유사했다. 그래서 해당 부분을 boost 스레드로 교체함으로써 플랫폼 중립적인 코드로 만들 수 있었다.&lt;/p&gt;
&lt;p&gt;또 다른 흔한 예로 GUI가 있다. GUI 관련 코드도 플랫폼에 마다 별도로 직접 만드는 것보다는 QT같은 플랫폼 중립적인 라이브러리를 사용하는 것이 훨씬 정신 건강에 좋다. 그게 포팅 시간도 줄인다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아래 두 글도 더불어 같이 읽어보도록 하자. 분명 큰 도움을 줄 것이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/aix/library/au-porting/&quot;&gt;http://www.ibm.com/developerworks/aix/library/au-porting/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/aix/library/au-porting2/&quot;&gt;http://www.ibm.com/developerworks/aix/library/au-porting2/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[멘.탈.붕.괴.]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/10216</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10216</guid><pubDate>Thu, 31 Jan 2013 23:58:42 GMT</pubDate><content:encoded>&lt;p&gt;바이러스에 난자 당한 컴퓨터,&lt;/p&gt;
&lt;p&gt;전원이 나가버린 새 장난감,&lt;/p&gt;
&lt;p&gt;구현해야 하는 기능 더미,&lt;/p&gt;
&lt;p&gt;써야하는 문서,&lt;/p&gt;
&lt;p&gt;풀리지 않는 문제,&lt;/p&gt;
&lt;p&gt;안드로메다로 가버린 일정,&lt;/p&gt;
&lt;p&gt;심리적 부채가 되버린 계약,&lt;/p&gt;
&lt;p&gt;잡힐 줄 모르는 버그,&lt;/p&gt;
&lt;p&gt;쏟아지는 해킹툴,&lt;/p&gt;
&lt;p&gt;흐트러진 집중력,&lt;/p&gt;
&lt;p&gt;넘쳐나는 사람들,&lt;/p&gt;
&lt;p&gt;하지만 정작 일 할 사람은 없는 아이러니,&lt;/p&gt;
&lt;p&gt;참… 맨정신으로 살기 힘드네.&lt;/p&gt;
&lt;p&gt;지금 한 번 해보자는 거지~&lt;/p&gt;
&lt;p&gt;그래 덤버라!!!&lt;/p&gt;
&lt;p&gt;2013.01.31.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[프로세스 명령줄 정보 삭제하기]]></title><description><![CDATA[cmdline…]]></description><link>https://jiniya.net/wp/archives/10147</link><guid isPermaLink="false">https://jiniya.net/wp/archives/10147</guid><pubDate>Mon, 14 Jan 2013 23:58:41 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2013/01/cmdline.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2013/01/cmdline.png&quot; alt=&quot;cmdline&quot;&gt;&lt;/a&gt;
&lt;strong&gt;커맨드 라인 정보는 어디로??&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;후배 녀석이 자신이 실행시킨 프로그램 명령줄 정보를 못 보게 하는 방법이 없냐고 해서 만들어 본 프로그램입니다. 위에 보이는 것처럼 프로세스 정보를 조회하는 툴에서 명령줄 정보를 볼 수 없도록 삭제해 줍니다. 다.만. 별로 의미없는 이유는 대부분 프로세스 모니터링 프로그램이 프로세스 생성 시점에 바로 정보를 저장해 두었다가 보여주기 때문에 우리가 정보를 지워도 계속 노출된다는 단점이 있습니다. 우리가 정보를 삭제한 다음에 프로세스 모니터링 도구를 띄워서 체크해보면 위에 보이는 것처럼 삭제된 것을 확인할 수 있습니다. 결국 별로 쓰잘때기 없는 코드라는 이야깁니다. ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;윈도우에서 명령줄 정보는 PEB의 RTL_USER_PROCESS_PARAMETERS 구조체의 CommandLine 필드에 저장됩니다. 그곳에 저장된 정보를 제거해 주면 다른 프로그램에서 해당 정보를 참조하지 못하겠지요. 이런 원리로 아래 프로그램은 명령줄 정보를 삭제하는 방법을 보여주고 있습니다. 코드 흐름만 보여주기 위해서 에러 처리 따위는 모두 삭제돼 있습니다. 32비트에서만 동작하는데요. 관심 있으신 분들은 64비트 버전을 만들어보는 것도 실력 향상에 도움이 될 것 같습니다. 난 고수다. 실력 쫌 되는데 하시는 분들은 WoW64 프로세스에서 32비트나 64비트 프로세스 정보를 제거하는데 도전해 보세요. 64비트는 아래 구조체도 일부 포함시켜두었기 때문에 크게 어렵진 않은데, WoW64는 초큼 어렵습니다 ㅋ~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_PEB32&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG reserved&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG param&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; PEB32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PPEB32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_PEB64&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG64 reserved&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG64 param&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; PEB64&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PPEB64&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_UNICODE_STRING32&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	USHORT  Length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	USHORT  MaximumLength&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG  Buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; UNICODE_STRING32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PUNICODE_STRING32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_UNICODE_STRING64&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	USHORT  Length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	USHORT  MaximumLength&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG Pad1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG64  Buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; UNICODE_STRING64&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PUNICODE_STRING64&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_RUPP32&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG reserved1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG reserved2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG reserved3&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG reserved4&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG reserved5&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG reserved6&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	UNICODE_STRING32 path&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	UNICODE_STRING32 image&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	UNICODE_STRING32 cmd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; RUPP32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PRUPP32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_RUPP64&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG reserved1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG reserved2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG reserved3&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG reserved4&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG64 reserved5&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	UNICODE_STRING64 reserved6&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG64 reserved7&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	UNICODE_STRING64 path&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	UNICODE_STRING64 image&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	UNICODE_STRING64 cmd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; RUPP64&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PRUPP64&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__success&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; LONG NTSTATUS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PNTSTATUS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_PROCESS_BASIC_INFORMATION32&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    NTSTATUS ExitStatus&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG PebBaseAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG AffinityMask&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG BasePriority&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HANDLE UniqueProcessId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HANDLE InheritedFromUniqueProcessId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; PROCESS_BASIC_INFORMATION32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PPROCESS_BASIC_INFORMATION32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_PROCESS_BASIC_INFORMATION64&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    NTSTATUS ExitStatus&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ULONG Pad1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID64 PebBaseAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONGLONG AffinityMask&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONGLONG BasePriority&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID64 UniqueProcessId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID64 InheritedFromUniqueProcessId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; PROCESS_BASIC_INFORMATION64&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PPROCESS_BASIC_INFORMATION64&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_WIN64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;PROCESS_BASIC_INFORMATION&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;PROCESS_BASIC_INFORMATION64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;PPROCESS_BASIC_INFORMATION&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;PPROCESS_BASIC_INFORMATION64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;PROCESS_BASIC_INFORMATION&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;PROCESS_BASIC_INFORMATION32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;PPROCESS_BASIC_INFORMATION&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;PPROCESS_BASIC_INFORMATION32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;


&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token function&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;NTSTATUS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;NtQueryInformationProcessT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LONG&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateProcessAndClean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPWSTR cmdline&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	PROCESS_INFORMATION pi&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	STARTUPINFO si &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;si&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;CreateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmdline&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;si&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;pi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;press any key to clean command line information.\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	ULONG req&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	PROCESS_BASIC_INFORMATION pbi&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HANDLE process &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hProcess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	NtQueryInformationProcessT pNtQueryInformationProcess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	HMODULE ntdll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;ntdll.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	pNtQueryInformationProcess 
		&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NtQueryInformationProcessT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
			&lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntdll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NtQueryInformationProcess&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;pNtQueryInformationProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;pbi
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pbi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
									&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	SIZE_T readed&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	PEB32 peb32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	RUPP32 rupp32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;ReadProcessMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; pbi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PebBaseAddress
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;peb32
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;peb32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;readed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;ReadProcessMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; peb32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;param
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;rupp32
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rupp32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;readed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	SIZE_T written&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	WCHAR cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;ReadProcessMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; rupp32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Buffer
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmd
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; rupp32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;readed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%p %ws %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rupp32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dwProcessId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	rupp32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;WriteProcessMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; peb32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;param
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;rupp32
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rupp32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;written&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hProcess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	WCHAR cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;c:\\windows\\system32\\notepad.exe c:\\abc.txt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CreateProcessAndClean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[홀리데이 – 유전무죄 무전유죄]]></title><description><![CDATA[“유전무죄, 무전유죄” 탈주범의 절규 몇 해 전 본 TV 프로그램 중에 “1달러의 삶”이란 다큐가 있어. 세계 각지에서…]]></description><link>https://jiniya.net/wp/archives/4581</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4581</guid><pubDate>Sat, 05 Jan 2013 23:58:38 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.sisapress.com/news/articleView.html?idxno=59324&quot;&gt;“유전무죄, 무전유죄” 탈주범의 절규&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;몇 해 전 본 TV 프로그램 중에 “1달러의 삶”이란 다큐가 있어. 세계 각지에서 1달러로 하루를 해결하는 사람들의 이야기를 담고 있어. 주로 멕시코, 브라질, 인도에 관한 이야긴데, 그 곳 사람들은 단 하나의 기회도 없어. 단지 그곳에서 태어났다는 이유로 8살부터 벽돌을 깨거나, 사람들 앞에서 저글링을 하거나, 맥도날드 앞에서 구걸을 하지. 정말 불쌍하다는 생각을 많이 했어. 진짜 단 1%의 선택권도 없거든. 죽거나 구걸하는 ㅠㅜ 그때 가장 가슴 아팠던 인도 여자 아이에 관한 대사, 일년 삼백육십오일을 맥도날드 앞에서 구걸 하는데 맥도날드 햄버거는 태어나서 한번도 먹어본 적이 없다는 이야기…&lt;/p&gt;
&lt;p&gt;세상이 좀 더 편평했으면 좋겠어. 모든 사람들이 행복하면 우리도 쉽게 행복할 수 있지 않을까?&lt;/p&gt;
&lt;p&gt;영화보는 내내 그런 생각이 들더라.&lt;/p&gt;
&lt;p&gt;– 그 남자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;내일은 아무 생각 안하고… 아무 걱정없이… 정말 행복하게 보냈음 좋겠어.&lt;/p&gt;
&lt;p&gt;영화 보고… 맛난거 먹고… 얘기도 하고… 웃다가… 그렇게 하루가 갔음.&lt;/p&gt;
&lt;p&gt;손에서 계속 땀이나서… 글씨가 잘 안 써져…&lt;/p&gt;
&lt;p&gt;자꾸 삐뚤삐뚤하고… 이상하네…&lt;/p&gt;
&lt;p&gt;그만 쓰고 전화할께…&lt;/p&gt;
&lt;p&gt;“압뿌라쑝”&lt;/p&gt;
&lt;p&gt;“라삘루뚜루뚜”&lt;/p&gt;
&lt;p&gt;– 그 여자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;내가 초등학교 다닐 때는 참 웃긴 설문 조사를 많이 했다. 그 중에 지금 생각해도 제일 웃기다고 생각하는 설문이 대한민국에 태어난 게 자랑스럽냐는 내용이었다. 초등학교 2-3학년이 대한민국에 태어난 게 자랑스러운지 아닌지를 무슨 근거로 판단을 하겠는가? 그나마 부모덕에 외국이라고 한 번 나가본 아이들이라면 비교라고 하겠지만 말이다. 난 그때 초딩이었지만 참 우스꽝스러운 설문이라고 생각했다.&lt;/p&gt;
&lt;p&gt;정말 많은 시간이 흘렀다. 아이러니하게도 지금 난 대한민국에 태어난 게 자랑스럽다고 생각한다. 좀 더 솔직하게 말하자면 단지 다행이라는 생각이 들 때가 많다. 그나마 이곳에 태어나서 그래도 고생은 좀 덜하면서 사는구나, 라는 생각이 들기 때문이다. 언젠가 신문 기사에 난 것 처럼 우리가 벌어들이는 소득은 거의 대부분 우리가 어느 지역에 태어났는지로 결정된다고 생각하기 때문이다. 그나마 중간은 되는 나라에 중간은 되는 지역에 태어나서 나름 기회도 있었고, 굶지 않고 살 수 있었던 것 같다. 나의 의지와는 0.00000001%의 관계도 없는 단순한 그 사실 때문에 말이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;사회주의 역시 돈에 대한 욕구를 완전히 없앨 수는 없었다. 전쟁이 끝난 직후인 1946년에 나는 헝가리 부다페스트에 간 적이 있다. 당시 미국에서는 자본주의 열풍이 뜨거웠고, 사람들이 모이기만 하면 오가는 대화의 주제는 오직 돈이었다. 누가 무슨 직업을 갖고 있느냐가 중요한 것이 아니라 얼마나 돈을 많이 벌 수 있는가가 문제였다. 그런데 나는 부다페스트에서 이와 전혀 다른 현상을 목격했다. 거기서는 누가 무슨 일을 하는지, 어떤 성공을 거두었는지 등에 대해 이야기했다. 어떤 사람이 작곡 분야에서 성공을 했고, 어떤 사람이 베스트셀러 작가가 되었으며, 또 어떤 사람이 인정받는 화학자가 되었는지 등등… 사실 이러한 분위기는 미국의 분위기보다 훨씬 내 마음에 들었다. 그때 한 친구가 이렇게 말했다.&lt;/p&gt;
&lt;p&gt;“어느 누구도 돈에 대해 말하지 않아. 그렇지만 모든 사람들이 그걸 생각하지.”&lt;/p&gt;
&lt;p&gt;그들은 돈을 소유할 수 있다는 희망이 없기 때문에 차라리 말하지 않는 편을 택했던 것이다.&lt;/p&gt;
&lt;p&gt;– 돈, 뜨겁게 사랑하고 차갑게 다루어라, 앙드레 코스톨라니&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;조카들이 내 나이가 됐을 때를 상상해본다. 그때는 나처럼 다행이라는 안도가 아닌 자랑스럽다는 생각을 할 수 있었으면 좋겠다. 편평하고 공정한 그런 세상. 그리고 조금은 누가 얼마를 번다는 이야기 보다는 무슨 일을 한다는 이야기를 더 많이 할 수 있는 세상이 됐으면 좋겠다. 소유의 포기 때문이 아닌 진심으로 하는 이야기로 말이다.&lt;/p&gt;
&lt;p&gt;기회는 평등할 것입니다.&lt;/p&gt;
&lt;p&gt;과정은 공정할 것입니다.&lt;/p&gt;
&lt;p&gt;결과는 정의로울 것입니다.&lt;/p&gt;
&lt;p&gt;문재인 캠프의 슬로건 같은 세상이 올 수 있기를 기도하며 주문을 외워본다.&lt;/p&gt;
&lt;p&gt;압뿌라쑝, 라삘루뚜루뚜~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;기회는 평등할 것입니다. 과정은 공정할 것입니다. 결과는 정의로울 것입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[포맷스트링이 부릅니다. 헬게이트2…]]></title><description><![CDATA[최근에 포맷 스트링과 관련된 문제를 한 번 더 겪어서 여기다 기록을 남겨본다. 문제는 다음과 같은 부분에서 출발했다. 크래시가 났는데 log_writer의 Write…]]></description><link>https://jiniya.net/wp/archives/9392</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9392</guid><pubDate>Thu, 03 Jan 2013 23:58:37 GMT</pubDate><content:encoded>&lt;p&gt;최근에 포맷 스트링과 관련된 문제를 한 번 더 겪어서 여기다 기록을 남겨본다. 문제는 다음과 같은 부분에서 출발했다. 크래시가 났는데 log_writer의 Write 함수를 호출하는 부분에서 났다. 그간 문제없이 잘 사용했던 함수라 증말 증상이 이해가 되질 않았다. 뭔가 buffer 값이 잘못됐는지만 계속 추적했는데 buffer 같은 이상이 없었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 버퍼 계산하는 부분&lt;/span&gt;
log_writer&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;buffer = &apos;%hs&apos;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇게 한참을 시도를 하다 놀라운 사실을 발견했다.&lt;/p&gt;
&lt;p&gt;클래스가 다음과 같이 선언돼 있었던 것이다. 문제를 눈치 챘는가?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogWriter&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ILogWriter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcwstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcwstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; va_arg ap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; va_arg ap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;맞다. 인자가 두개인 함수가 같이 선언된 것이 문제였다. 내가 원했던 링크 경로는 Write(xcwstr fmt, …)이었는데, Write(xcwstr fmt, va_arg ap)로 연결이 됐던 것이다. 흙~ 그래서 클래스를 다음과 같이 바꿨다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogWriter&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ILogWriter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcwstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;WriteV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcwstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; va_arg ap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; XCALL &lt;span class=&quot;token function&quot;&gt;WriteV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; va_arg ap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;가변 인자 함수를 정의할 때에는 각별히 주의해야겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Fighters fight]]></title><description><![CDATA[Fighters fight – Rocky Balboa, 2006 우리는 생각보다 다른 사람의 시선을 더 많이 신경 쓰고 있는 건 아닐까? #0 서울에 괜찮은…]]></description><link>https://jiniya.net/wp/archives/8782</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8782</guid><pubDate>Thu, 03 Jan 2013 23:58:36 GMT</pubDate><content:encoded>&lt;p&gt;Fighters fight – Rocky Balboa, 2006&lt;/p&gt;
&lt;p&gt;우리는 생각보다 다른 사람의 시선을 더 많이 신경 쓰고 있는 건 아닐까?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;서울에 괜찮은 4년제 대학교를 나와서&lt;/p&gt;
&lt;p&gt;나름의 토익 점수라든지 시험점수도 충분히 되고&lt;/p&gt;
&lt;p&gt;자격증도 충분히 따놨는데&lt;/p&gt;
&lt;p&gt;아무도 모르는 중소기업이라든지&lt;/p&gt;
&lt;p&gt;아니면 지방에 있는 그런 작은 회사를&lt;/p&gt;
&lt;p&gt;가고 싶어하는 사람은 없잖아요&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;남들이 ‘요즘 얼마나 먹고 살기 힘든데’&lt;/p&gt;
&lt;p&gt;‘야 죽을 맛이야 너 빨리 아무 데나 잡아라’&lt;/p&gt;
&lt;p&gt;그 말 듣고 가기에는 내 인생이 너무 밑지는 것 같은&lt;/p&gt;
&lt;p&gt;손해 보는 것 같은&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;저는 기업에 가서 하면&lt;/p&gt;
&lt;p&gt;엄청 힘든 일이 있어도&lt;/p&gt;
&lt;p&gt;그냥 제가 원하는 기업이라면&lt;/p&gt;
&lt;p&gt;그 배지나 로고를 보면서&lt;/p&gt;
&lt;p&gt;행복해 할 것 같아요&lt;/p&gt;
&lt;p&gt;그게 맞는 거죠&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;제가 큰 기업에 가고 싶은 이유는&lt;/p&gt;
&lt;p&gt;정말 효도하고 싶어서&lt;/p&gt;
&lt;p&gt;그러는 거예요&lt;/p&gt;
&lt;p&gt;부모님께,&lt;/p&gt;
&lt;p&gt;부모님이 정말 자랑할 수 있게끔&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;서울로 올라가서 일을 한다든지&lt;/p&gt;
&lt;p&gt;본사에서 좋은 조건에서&lt;/p&gt;
&lt;p&gt;돈 많이 받고 일을 하게 되면&lt;/p&gt;
&lt;p&gt;전 제 스스로&lt;/p&gt;
&lt;p&gt;프라이드를 가질 것 같아요&lt;/p&gt;
&lt;p&gt;나 정말 인생 잘 살고 있구나&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;얼마 전, 어려운 취업 현실에 관한 다큐를 한 편 보았다. 단군이례 최고의 스펙임에도 취업이 어려운 요즘 세상에 관한 이야기였다. 공감을 하면서 보다가도 다큐 마지막에 나오는 미취업자들의 인터뷰 내용에는 경악할 수 밖에 없었다. 그 누구도 자신이 뭘 잘 하는지 무엇을 하고 싶은지에 대한 고민은 하지 않았기 때문이다. 모두가 약속이라도 한 것처럼 하나같이 다른 사람이 자신을 어떻게 바라볼지에 대해서만 생각하는 것처럼 보였다.&lt;/p&gt;
&lt;p&gt;평생 직장 내지는 업이라는 것이 사라진 요즘이지만 그래도 한 직장, 내지는 한 업계에 몸을 담으면 상당히 오랜 기간 그 일을 하면서 보낸다. 또한 그렇게 선택한 직업을 가진 동안에는 일과 시간의 대부분을 그 일을 하는데 오롯이 할당할 수 밖에 없다. 그렇게 생활의 대부분을 차지하게 될 업을 선택하는데 자신의 적성, 특기를 고려하기 보다는 일년에 한두 번 만날지도 모르는 주변 사람들 내지는 부모님의 위신만을 고려해서 선택한다면 과연 옳은 것일까? 평생 그 일을 참고 꾸역꾸역 해 나가야 할 자신에게 너무 미안한 선택 아닐까?&lt;/p&gt;
&lt;p&gt;싸움꾼은 싸움을 하고, 가수는 노래를 하고, 화가는 그림을 그리고, 작가는 글을 쓰고, 포토그래퍼는 사진을 찍고, 프로그래머는 프로그래밍을 한다. 주변의 시선 따위는 잠시 쓰레기통에 넣어 두고 먼저 난 어떤 일을 좋아하는지, 내가 잘 할 수 있는 일은 무엇인지를 생각해 보는 시간을 가져보는건 어떨까?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;행복이란 자신이 가치있다고 생각하는 일에 오랫동안 몰두할 수 있는 권리라고도 할 수 있다. 어떤 사람은 아내와 아이들을 돌보는 데서 행복을 찾는다. 어떤 사람은 은행을 터는 데에서 행복을 느낀다. 뚜렷한 성과도 없는 순수한 연구에 매달리며 행복을 느끼는 사람도 있다.&lt;/p&gt;
&lt;p&gt;자신과, 자신을 둘러싸고 있는 환경을 둘러보자. 똑같은 사람은 둘도 없으며 똑같은 사람이 있으리라고 생각하는 것도 얼토당토않은 일이다. 남자든 여자든, 사람은 누구나 오랜 동안 열심히 일하면서 행복을 느낄 수 있는 직업을 찾아야 한다. 거꾸로 말하면, 지금 일을 좀 덜했으면 싶거나 긴 휴가와 퇴직을 바란다면 직업을 잘못 선택했다. 차라리 은행털이를 하거나 한탕할 건수를 찾는 것이 낫다. 아니면 정치를 하거나.&lt;/p&gt;
&lt;p&gt;– 로버트 하인라인의 “해 지는 곳 너머로 돛을 올려서”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[윈도우 8에 관한 10원 짜리 팁들…]]></title><description><![CDATA[지난 주에 Hyper-V 때문에 윈도우8 업그레이드를 단행했습니다. 제가 Hyper-V를 좀 잘못 이해해서 벌어진 해프닝인데 지금은 굉장히 만족하면서 사용하고 있습니다. 사실 사람들이 시작 버튼 없어진 걸 마치 대단한 일인것처럼 말하는데 윈도…]]></description><link>https://jiniya.net/wp/archives/9771</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9771</guid><pubDate>Thu, 27 Dec 2012 23:58:35 GMT</pubDate><content:encoded>&lt;p&gt;지난 주에 Hyper-V 때문에 윈도우8 업그레이드를 단행했습니다. 제가 Hyper-V를 좀 잘못 이해해서 벌어진 해프닝인데 지금은 굉장히 만족하면서 사용하고 있습니다. 사실 사람들이 시작 버튼 없어진 걸 마치 대단한 일인것처럼 말하는데 윈도7에서 작업 표시줄에 PIN 기능 생기고 나서 전 시작 메뉴를 눌러본 적이 거의 없는 것 같습니다. 오히려 없는 게 깔끔하니 좋더군요.&lt;/p&gt;
&lt;p&gt;제가 가장 점수를 많이 주고 싶은 건 live.com 계정을 통해서 모든 것이 자동으로 동기화 된다는 점 입니다. 메일, 일정, SkyDrive로 파일 등을 손쉽게 여러 환경에서 편리하게 쓸 수 있습니다. 데탑에서 앱이 필요없는 기능이라는 의견도 많은데 정작 써보면 단지 뷰가 바꼈을 뿐인데 전혀 새로운 경험을 하게 해주는 경우가 많습니다. 물론 유용하다는 말은 아닙니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;미디어 플레이어 설치&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;N 버전을 사용하시면 미플이 기본적으로 설치되지 않습니다.&lt;/p&gt;
&lt;p&gt;아래 페이지를 방문 하셔서 다운로드 받아서 설치하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://windows.microsoft.com/ko-KR/windows/download-windows-media-player&quot;&gt;미플 다운로드 페이지&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;시작 프로그램 등록하기&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;shell:startup&lt;/strong&gt; 커맨드를 입력하면 시작 프로그램 등록하는 폴더가 나옵니다.&lt;/p&gt;
&lt;p&gt;거기다 바로가기를 추가해 주시면 되겠습니다.&lt;/p&gt;
&lt;p&gt;자세한 설명은 아래 페이지에…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://bbokkun.tistory.com/4&quot;&gt;http://bbokkun.tistory.com/4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;단축키 정리&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;몇 가지 단축키를 알면 정말 쓰기가 편해집니다. 모르면 마우스 동선이 좀 많아서 단축키가 효율적인 것 같아요.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.addictivetips.com/windows-tips/30-new-hotkeys-for-windows-8/&quot;&gt;http://www.addictivetips.com/windows-tips/30-new-hotkeys-for-windows-8/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;W + Q (필수 서치 단축키)&lt;/p&gt;
&lt;p&gt;W + C (참바 나오는 단축키)&lt;/p&gt;
&lt;p&gt;W (시작 화면 표시)&lt;/p&gt;
&lt;p&gt;W + D (데스크톱으로 전환)&lt;/p&gt;
&lt;p&gt;W + T (앱 전환)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;라이브닷컴 계정 만들기&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;한국이면 live.co.kr같은 알흠답지 않은 계정이 생성되는데요. 아래 페이지로 접속해서 계정 생성하면 live.com 계정을 만들 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://signup.live.com/signup.aspx?mkt=en-US&amp;#x26;id=251248&quot;&gt;https://signup.live.com/signup.aspx?mkt=en-US&amp;#x26;id=251248&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;타일 관리 하는 방법&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;뭐 굳이 강좌를 안 봐도 잘 쓸 수 있도록 직관적이지만 그래도 한 번 읽어보면 훨씬 빠르게 적응할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://archwin.net/32&quot;&gt;http://archwin.net/32&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;윈도우 스토어&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아직 한국 앱은 많지 않습니다. 언어에 영어를 추가하면 앱이 갑자기 폭발적으로 늘어납니다. 큰 모니터에 앱을 띄워 놓는게 비효율적이라고 생각들 많이 하는데 27인치 화면에 트위터 앱 띄워놓고 보면 새로운 경험을 하게 됩니다. 그렇게 속이 시원할 수가 없습니다 ㅋㅋ~ 다른 앱들도 데탑 화면에서 써보면 전혀 새로운 경험을 하게 해주는 경우가 더러 있습니다. 단지 뷰가 바꼈을 뿐인데 말이죠. 그렇게 쓸모없지는 않다는 생각입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;정품 인증&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;설치하고 가끔 정품 인증이 안 되는 경우가 있었습니다. 당황하지 말고 윈도키 R 눌러서 실행창 나오면 아래 명령어를 입력하면 제품키를 다시 입력할 수 있는 화면이 출력됩니다. 그 때 제품키 입력하고 인증 받으면 됩니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;slui 3&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;원격 데스크톱 오류&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;윈도우 8에서 윈도우 8로 원격 데스크톱 접속을 하려고 할 때 MicrosoftAccount 오류라고 하면서 접속 안 되는 문제가 발생하는 경우가 있습니다. 아래 방법대로 커스텀 파일을 만들어서 사용하면 문제없이 접속할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://support.microsoft.com/kb/941641&quot;&gt;http://support.microsoft.com/kb/941641&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;키보드 101키 변경&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://answers.microsoft.com/ko-kr/windows/forum/windows%5C_8-hardware/windows-8-%EC%97%90%EC%84%9C-%ED%95%9C%EC%98%81/56039823-78f9-4666-be98-830444eef89c?msgId=432b960d-f2bd-4b4f-9906-b8b4b1e051c3&quot;&gt;http://answers.microsoft.com/ko-kr/windows/forum/windows\_8-hardware/windows-8-%EC%97%90%EC%84%9C-%ED%95%9C%EC%98%81/56039823-78f9-4666-be98-830444eef89c?msgId=432b960d-f2bd-4b4f-9906-b8b4b1e051c3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; 0
 14&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[마이크로소트웨어 29주년 기념식]]></title><description><![CDATA[명함 뽑기에서 상품권을 받는 행운까지 ㅋㅋ~ 수욜날 마소 29주년 기념식이 있었습니다. 마소에서 감사하게도 별로 한 것도 없는 저에게 감사패를 주셨습니다. 10…]]></description><link>https://jiniya.net/wp/archives/9828</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9828</guid><pubDate>Fri, 07 Dec 2012 23:58:34 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./마이크로소트웨어_29주년_기념식.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2092692f3eeeaa539e78be715179dffa/e224a/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%86%8C%ED%8A%B8%EC%9B%A8%EC%96%B4_29%EC%A3%BC%EB%85%84_%EA%B8%B0%EB%85%90%EC%8B%9D.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.73684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQCBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAG+JXG3NL//xAAcEAACAgIDAAAAAAAAAAAAAAABAgADBBESExX/2gAIAQEAAQUCCLxSveX0VyrIDkDTeg0//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8BV//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AUf/xAAbEAACAgMBAAAAAAAAAAAAAAAAASEyERITQf/aAAgBAQAGPwJQPKhIojmjb0of/8QAGxAAAwEAAwEAAAAAAAAAAAAAAAERMVFxgdH/2gAIAQEAAT8hqowUoh2yDd8RQpjeFJW7XJ1PT//aAAwDAQACAAMAAAAQVx//xAAWEQEBAQAAAAAAAAAAAAAAAAAAEQH/2gAIAQMBAT8Quqf/xAAWEQEBAQAAAAAAAAAAAAAAAAAAESH/2gAIAQIBAT8QxD//xAAdEAEAAwABBQAAAAAAAAAAAAABABEhUTFBcYGx/9oACAEBAAE/EE3p6su3mIFmEE1oz3FrW8V+R3Q6MPMES0V7jio4FUY1fZ//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         29       md 0&apos; title=&apos;&apos; src=&apos;/static/2092692f3eeeaa539e78be715179dffa/e224a/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%86%8C%ED%8A%B8%EC%9B%A8%EC%96%B4_29%EC%A3%BC%EB%85%84_%EA%B8%B0%EB%85%90%EC%8B%9D.md_0.jpg&apos; srcset=&apos;/static/2092692f3eeeaa539e78be715179dffa/8ccab/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%86%8C%ED%8A%B8%EC%9B%A8%EC%96%B4_29%EC%A3%BC%EB%85%84_%EA%B8%B0%EB%85%90%EC%8B%9D.md_0.jpg 190w,
/static/2092692f3eeeaa539e78be715179dffa/ea4c8/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%86%8C%ED%8A%B8%EC%9B%A8%EC%96%B4_29%EC%A3%BC%EB%85%84_%EA%B8%B0%EB%85%90%EC%8B%9D.md_0.jpg 380w,
/static/2092692f3eeeaa539e78be715179dffa/e224a/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%86%8C%ED%8A%B8%EC%9B%A8%EC%96%B4_29%EC%A3%BC%EB%85%84_%EA%B8%B0%EB%85%90%EC%8B%9D.md_0.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;명함 뽑기에서 상품권을 받는 행운까지 ㅋㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;수욜날 마소 29주년 기념식이 있었습니다. 마소에서 감사하게도 별로 한 것도 없는 저에게 감사패를 주셨습니다. 100만 정기구독자로 보답하도록 하겠습니닷 ㅋ~ 물론 이게 끝이 아닙니다. 무려 명함 뽑기에서 상품권을 득템하는 행운까지~ 헐 ㅋ~ 네 맞습니다. 이상 자랑질이었습니다…&lt;/p&gt;
&lt;p&gt;마술쇼가 있었는데요. 마술사가 테이블마다 돌아다니면서 자기 마술을 보여주고 있었습니다. 우리 테이블에도 와서는 볼트/너트 푸는 마술을 보여주겠다고 하더군요. 내가 손을 돌리면 너트가 풀리는 걸 보여주겠다고 했습니다. 그래서 시작에 맞춰서 손을 돌리니 마치 모터가 돌리는 것처럼 너트가 풀리더군요. 심심해서는 돌리던 손을 멈추었습니다. 그래도 여전히 돌아가는 너트… 마술사가 초본지 당황해서는 똥씹은 표정이 되더군요. 저도 울고 마술사도 울었습니다. ㅠㅜ~ 프로그래머와 마술사는 그닥 어울리는 조합은 아닌것 같아요 ㅋㅋㅋ&lt;/p&gt;
&lt;p&gt;강의실 옆 운죽정에서 원고를 쓰던 학생이 졸업해서 회사를 다닌지도 몇 해는 지났고, 그 때 학생의 원고를 처음 교정해 주셨던 기자님이 편집장이 된지도 몇 해는 지났습니다. 세월 참 빨라요. 시간이 많이 흘렀지만 처음 원고를 쓰던 그 때의 열정은 잊지 않고 계속 가지고 있었으면 좋겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[이다르크의 위엄…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/9798</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9798</guid><pubDate>Thu, 06 Dec 2012 23:58:33 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;네. 대단히 궁금하신 것 같아서,&lt;/p&gt;
&lt;p&gt;이것만 기억하시면 됩니다.&lt;/p&gt;
&lt;p&gt;박근혜 후보 떨어뜨리기 위한 겁니다.&lt;/p&gt;
&lt;p&gt;저는 박근혜 후보를 반.드.시 떨어뜨릴 겁니다.&lt;/p&gt;
&lt;p&gt;그리고 진보적 정권 교체를 해낼 겁니다.&lt;/p&gt;
&lt;p&gt;– 이정희&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;어제 있었던 대선 티비 토론회를 이제서야 봤는데 이정희 후보 장난 아니네욤. 칼을 갈아도 너&lt;del&gt;무&lt;/del&gt; 잘 갈아서 나온 것 같은 느낌이 들었습니다 ㅋㅋㅋ~ 문재인 후보나 박근혜 후보가 면도칼 들고와서 깨작되고 있는데 혼자 전기톱 들고 와서 제압하는 느낌이랄까? ㅋㅋ~ 보는 내내 어찌나 속이 시원하든지 ㅋ~ 박근혜 떨으뜨리려고 나왔다고 답변할 때에는 레알 소름 돋았습니다. 화이팅이예요. ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;어제 토론회도 그랬지만 정치적 성향을 떠나서 좀 부끄럽습니다. ㅠㅜ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[C++ 개발자를 위한 게임 개발 전략 세미나]]></title><description><![CDATA[마이크로소프트웨어 창간 29주년 기념 세미나를 개최합니다. 우왕 짝짝짝. ㅋㅋ~ 이름도 거창하게 “C…]]></description><link>https://jiniya.net/wp/archives/9651</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9651</guid><pubDate>Fri, 16 Nov 2012 23:58:32 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://new.imaso.co.kr/seminars/cgpc2012/agenda/&quot;&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; margin-bottom: 16px;&apos; data-url=&apos;./C++_개발자를_위한_게임_개발_전략_세미나.md_0.png&apos;&gt;
      &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 53.1578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACp0lEQVR42hWP309SARTH79/RU6uX5ltbrqz5o0xl2ixb5fyxCtl8YBU5apLEpibmDyqdik6NzZwzEVPCDYeIAqJw+SGWCMjPey9wL/cXF0Epe6Dr2Xfn4ez7Od9zgCgMo8mkci8wYvEorAer+k0bCBotuybztmXHumXaVmtWlzVK8HDR5lDtHiwaXMueQ99vj4cFAYLAYyjK+bZVvwReH1fzhGKb1WW2usL+oN/jPzr0G9Y3Bj8L10zCiQV+90jND7vEtf9rz+0OhkIAjmFQHK2ct3P1oVszxt5PUodeZdKptSvz/T3tQ4OdJs38zLT46zpH0N78srt0zt1id7rsTmcEigIYhsXjcfmMXDIo6R3ueS983sbl8OoKqytvFhYVlRdfqX9UzX32kC8tbuHfftVV/mGyxev1e/0+iqYA9JyG/w1X5MeqTmWlo2/K5VKOZporFT0Q8O9O9dW2Nl6rKCloul/bWFPBqyrjNTUj8TiMIDiOAykmnSKTZ1+q8lNPjvvvDAsKFicLNzV83fILg7pxaaykV3CR33D5aW1Z9Y2rjy9daKi7R9LnlclkAIIkSQLPrA3lFt7Sqs5xWadiXPZTqVArFUtzE99npwf6PkrEHe9Eog6RSPxaMDk6wjAMRVHnMAzDSCwGEwxMZWEiTdIpnKQSWDKWQFklEihJUSmGyWSOs9mT3Nnf7Ek2nkDxJMaGA+zpbHaKxBmKYGiCZq0pGkFgCIJi7FIYCYfDkUiEbewkEIzorD4dGADdR39ypwBJEKw7hiCskhjGvhDw++w2awyBdnfMkXDA5QQDAe++2wlFgw77XuuAtq7fMKvayefzAJ3NMqc5nEknaCZKMiE87YEJ0IschGmjLaw3RbX60IYR2jBDVgdqd2AyuaWtS6tdCUe8mf82utmEcvSccgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;C                        md 0&apos; title=&apos;&apos; src=&apos;/static/c014cde5891a166668d81f7d7151373b/5d5ad/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_0.png&apos; srcset=&apos;/static/c014cde5891a166668d81f7d7151373b/08678/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_0.png 190w,
/static/c014cde5891a166668d81f7d7151373b/2edd7/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_0.png 380w,
/static/c014cde5891a166668d81f7d7151373b/5d5ad/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_0.png 610w&apos; sizes=&apos;(max-width: 610px) 100vw, 610px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
    &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://new.imaso.co.kr/seminars/cgpc2012/agenda/&quot;&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 585px; margin-bottom: 16px;&apos; data-url=&apos;./C++_개발자를_위한_게임_개발_전략_세미나.md_1.png&apos;&gt;
      &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 24.210526315789476%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAu0lEQVR42mWOyQ7CIBRF+f8/M6Ym0gEsUylDEbuptdWlN5h040m4OfdBAKLj3LvcDYnZdHN3FR4mzirMwufP5/3Pvu+Hk5qrM+Un2l86eeW67Y32SdhJjulZWNf1yINlWTAhwXuj1aCVs4N3ox0MlrM2xagLSinkWIAYY6SUGKISIQSllDHeAcZQ27Ytyuq6bpoGXlXVb8I5xwE4EheRaZpCwPMemVJCjTEi4c65n2A354yKLfz5Vdi27QtuTwtzhJsqtAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;C                        md 1&apos; title=&apos;&apos; src=&apos;/static/f03b23112fbc9b2d8dfbfa2747d2c380/51d84/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_1.png&apos; srcset=&apos;/static/f03b23112fbc9b2d8dfbfa2747d2c380/08678/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_1.png 190w,
/static/f03b23112fbc9b2d8dfbfa2747d2c380/2edd7/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_1.png 380w,
/static/f03b23112fbc9b2d8dfbfa2747d2c380/51d84/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_1.png 585w&apos; sizes=&apos;(max-width: 585px) 100vw, 585px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
    &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;마이크로소프트웨어 창간 29주년 기념 세미나를 개최합니다. 우왕 짝짝짝. ㅋㅋ~ 이름도 거창하게 “C++ 개발자를 위한 게임 개발 전략 세미나”라는 군요. 게임 개발자를 대상으로 한다니 뉴요커 게임 개발자라면 꼭 참석하도록 합시닷.&lt;/p&gt;
&lt;p&gt;저도 게임 보안으로 한 꼭지를 맡았습니다. 싸인코드 깔때기는 없으니 너무 많이 걱정하실 필요는 없습니다. ㅋㅋㅋ~ 게임 개발자들을 대상으로 하기 때문에 해킹툴 차단 기법같은 내용은 없을 거구요. 게임 개발자들이 신경 써야 하는 보안 요소들에 대해서 좀 다뤄볼까 생각 중입니다. 리소스 핵, 사설 서버, 디지털 서명 같은 주제를 생각만 해보고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; margin-bottom: 16px;&apos; data-url=&apos;./C++_개발자를_위한_게임_개발_전략_세미나.md_2.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f4aeaac359474d44335e86e3c00dcdd3/0cdb7/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 133.68421052631578%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAwABBAL/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQP/2gAMAwEAAhADEAAAAdbWLGSzXF5BLO2WK//EABsQAAMAAwEBAAAAAAAAAAAAAAECEQADIRIy/9oACAEBAAEFAukng1GquXgyxPZGrR8OLiKIgi//xAAYEQACAwAAAAAAAAAAAAAAAAAAEQEQEv/aAAgBAwEBPwFxWRH/xAAYEQEBAAMAAAAAAAAAAAAAAAAAEQESIf/aAAgBAgEBPwGMtuK//8QAHBAAAgICAwAAAAAAAAAAAAAAASEAEAJxEUFC/9oACAEBAAY/Ai7R3HkjWR57g9Tcd//EAB0QAQADAQACAwAAAAAAAAAAAAEAESFBMVFhgbH/2gAIAQEAAT8hC58HMgbdzssLb2XtaA4NlqWGBdQ+TLGmpbGe0Coe72oHeauA+vuAoWHwsLD9n//aAAwDAQACAAMAAAAQk+uC/8QAGREBAQEAAwAAAAAAAAAAAAAAAQAhEUHB/9oACAEDAQE/EAsfY0npHDL/xAAXEQEBAQEAAAAAAAAAAAAAAAABEQAh/9oACAECAQE/ECy7hmA403f/xAAgEAEBAAICAgIDAAAAAAAAAAABEQAhQVExYXGRobHw/9oACAEBAAE/EGZAWDhdY3Exv+GI4oYL1xjDEelttkxZF+sleCT5wpupTxUxXIoBJ9TrJ4iKQHlqcd5v7sme/XGRVi2VL3MJVz4Efhw0XtrU/vP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;C                        md 2&apos; title=&apos;&apos; src=&apos;/static/f4aeaac359474d44335e86e3c00dcdd3/0cdb7/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_2.jpg&apos; srcset=&apos;/static/f4aeaac359474d44335e86e3c00dcdd3/8ccab/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_2.jpg 190w,
/static/f4aeaac359474d44335e86e3c00dcdd3/0cdb7/C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC_%EC%9C%84%ED%95%9C_%EA%B2%8C%EC%9E%84_%EA%B0%9C%EB%B0%9C_%EC%A0%84%EB%9E%B5_%EC%84%B8%EB%AF%B8%EB%82%98.md_2.jpg 300w&apos; sizes=&apos;(max-width: 300px) 100vw, 300px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;내 생애 첫 마소. 뭔 글인지도 모르고 읽고 또 읽던 까까머리 중학생이 …&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;지난 달 마소 인터뷰가 생각나서 본가에 갈 일이 있었을 때 한 컷 찍어 봤습니다. 중학교 때 친구 녀석이 생일 선물로 사 준 마소가 제 인생에 첫 번째 마소였던거 같은데요. 무슨 말인도 모르는 글을 밤새도록 읽고 또 읽었던 기억이 납니다. 그냥 막연하게 내가 하고 싶어하는 일을 하는 사람들은 이런 사람들이구나, 라는 생각을 많이 했었던 것 같습니다.&lt;/p&gt;
&lt;p&gt;고등학교 때는 전 사실 마소보다는 프세를 더 즐겨 봤었는데요. 마소는 좀 덜 실용적인 글들이 많았고 프세는 따라해볼 수 있는 글들이 많았었거든요. 그러다 대학교 때에는 마소를 정기 구독 했었습니다. 신승근씨가 비베 책을 몇 천 권 읽었다는 글을 보면서 연구 도서관에 있는 모든 컴퓨터 책을 다 읽겠다는 어처구니 없는 생각을 했었던 적도 있었고, &lt;a href=&quot;http://www.jiniya.net/wp/archives/1208&quot;&gt;지난 글&lt;/a&gt;에도 언급했었지만 나성언님의 “디지털 메신저”란 칼럼은 기다려가면서 읽을 정도로 재미있게 봤습니다. 연구 도서관에 보관된 오래된 먼지투성이 마이크로소프트웨어 잡지 철 속에서 안철수 선생님이 기고하셨던 글을 찾아보던 때도 생각나네요.&lt;/p&gt;
&lt;p&gt;글 내용을 하나도 몰랐던 까까머리 중학생이 이제는 한 솔루션 개발을 책임지는 프로그래머가 되었고, 선배 개발자들이 그랬던 것처럼 가끔은 신입 개발자를 위한답시고 유치한 글들을 쓰기도 합니다. 그럴 때마다 참 ‘격세지감’이란 단어를 온몸으로 느끼곤 합니다. 이렇게 또 세월의 수레바퀴가 굴러가는 거겠지요? 훗~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[오류의 역사…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/8314</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8314</guid><pubDate>Thu, 01 Nov 2012 23:58:31 GMT</pubDate><content:encoded>&lt;center&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./오류의_역사.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3da5f93c5cffb09c1fc2c779ce97074b/e224a/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAByNZpZHcD/8QAHBAAAgICAwAAAAAAAAAAAAAAAQIRIQADBCIz/9oACAEBAAEFAoaEXqNLgHz4l4DX/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8Bqv/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AYj/xAAbEAACAQUAAAAAAAAAAAAAAAAAATECEYGC0f/aAAgBAQAGPwKSLohs14VYEf/EABwQAQACAwADAAAAAAAAAAAAAAEAESExcVGR0f/aAAgBAQABPyF2OLNyy9qKRzBR2BErXZU9fUwB8whmn//aAAwDAQACAAMAAAAQTw//xAAXEQEAAwAAAAAAAAAAAAAAAAABEBEx/9oACAEDAQE/EAXkP//EABYRAAMAAAAAAAAAAAAAAAAAAAEQIf/aAAgBAgEBPxAyn//EAB0QAAICAwADAAAAAAAAAAAAAAERACExQVGBkaH/2gAIAQEAAT8QXkhQBorkkx7iREZNVqEpXpjxUKE2Dg1cy9wyQsKUXSMP7P/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 0&apos; title=&apos;&apos; src=&apos;/static/3da5f93c5cffb09c1fc2c779ce97074b/e224a/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_0.jpg&apos; srcset=&apos;/static/3da5f93c5cffb09c1fc2c779ce97074b/8ccab/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_0.jpg 190w,
/static/3da5f93c5cffb09c1fc2c779ce97074b/ea4c8/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_0.jpg 380w,
/static/3da5f93c5cffb09c1fc2c779ce97074b/e224a/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_0.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;상식적으로 수술 직후에 나빠진 거니까 수술 부위 확인하자고 말씀 드린…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;뭐 상식? 내가 지금 상식이 없다는 거야? 그럼 내 수술이 잘못됐다는 거야? 뭐야?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;아니… 사고는 누구한테나 생기는 거잖아요.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./오류의_역사.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f3ffa1a400f3605ae570b2c0f1f7a472/e224a/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEEAv/EABYBAQEBAAAAAAAAAAAAAAAAAAABA//aAAwDAQACEAMQAAABo3S80oyv/8QAGhAAAwADAQAAAAAAAAAAAAAAAAECAxESIf/aAAgBAQABBQKey+tRjpxPo0hs/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHhAAAAQHAAAAAAAAAAAAAAAAAAEREgIgISIxQWH/2gAIAQEABj8CNYS5UW50CejpP//EABoQAQADAAMAAAAAAAAAAAAAAAEAEUEhMVH/2gAIAQEAAT8hJqRHhohXh1HADVMIm8lbqIVSz//aAAwDAQACAAMAAAAQB+//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPxAn/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EFywv//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESFBMVFhgcH/2gAIAQEAAT8QVoBh7F6Y1SdzXmr+RZQMbDmKJFSEO0IguMSjCK0z/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;       md 1&apos; title=&apos;&apos; src=&apos;/static/f3ffa1a400f3605ae570b2c0f1f7a472/e224a/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_1.jpg&apos; srcset=&apos;/static/f3ffa1a400f3605ae570b2c0f1f7a472/8ccab/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_1.jpg 190w,
/static/f3ffa1a400f3605ae570b2c0f1f7a472/ea4c8/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_1.jpg 380w,
/static/f3ffa1a400f3605ae570b2c0f1f7a472/e224a/%EC%98%A4%EB%A5%98%EC%9D%98_%EC%97%AD%EC%82%AC.md_1.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;권위의 함점에 빠질 때, 자만에 빠질 때 우리는 상식을 놓친다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;그리고 그렇게 놓쳐버린 상식은 항상 돌이킬 수 없는 사고로 우리를 반겨준다.&lt;/strong&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;요즘 참 재미난 드라마 많이 한다. 특히나 난 의학 드라마를 좋아하는 편인데 골든타임이라는 의학 드라마가 새로 시작했다. 대박~ 원고 때문에 못 보고 있다가 원고 마감을 아슬하게 겨우 넘기고 어제는 홀가분한 마음으로 밀린 드라마 정주행을 시작했다. 굳굳~ 그런데 드라마 보는데 너무 가슴을 후벼파는 장면이 나와서 이 글을 쓰게 되었다. 일단 골든타임의 한 장면을 먼저 바라보고…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;작년에 내가 한 큰 작업 중에 하나는 XIGNCODE 서버 코드를 새로 작성하는 일이었다. 새로 작성하게 된 계기는 여러 가지가 있는데 설계 당시 우리가 생각했던 것보다 서버 쪽 기능이 많아지기도 했고, 서버 적용 난이도를 좀 더 낮출 필요가 있었기 때문이다. 코드를 좀 더 세분화 시키고 싶은 마음도 있었다. 어쨌든 이런 목적으로 작업을 시작했는데 생각보다 이 일은 내가 작년에 한 일 중에 가장 잘한 일이 되었다.&lt;/p&gt;
&lt;p&gt;새로 서버를 작성하면서 난 파이썬에 심취해서 파이썬을 연동해서 사용했다. 많은 잡다한 기능을 파이썬 코드로 작성할 수 있어서 참 매력적인 일이었다. 그런데 문제는 시간이 조금 지난 후에 나타났다. 고객사에서 잘 동작했고, 우리 테스트 PC에서도 잘 동작했는데, 유독 테스트 PC 중에 한 대에서만 바탕 화면에 게임 서버를 설치하는 경우에 시작 시에 크래시가 발생하는 것이었다. 그.것.도. 파이썬 DLL에서.&lt;/p&gt;
&lt;p&gt;난 치기에 불타 올랐다. 후훗. 파이썬 DLL에 숨겨진 버그를 찾아서 파이썬 커뮤니티를 놀라게 해주겠어, 라며 말이다. 크래시는 파이썬 DLL 내의 메모리를 해제하는 지점에서 발생했다. 그래서 난 힙 할당/해제 함수를 후킹해서 모두 추적/기록 하는 엄청난 모듈을 만들었고 파이썬 DLL에서 발생하는 모든 메모리 사용 내역을 뽑아 볼 수 있게 되었다. 그렇게 엄청난 분량의 로그가 출력됐고, 그 엄청난 분량의 로그를 파이썬으로 다시 분석했는데 오류가 없었다. 안타깝게 한 톨의 오류도 없었다. 한 바이트의 힙 오버런도 없었고, 이중 해제도 없었다. 완벽했다.&lt;/p&gt;
&lt;p&gt;멘붕에 빠진 나는 python.org에 들어갔고 2.7.2가 올라왔다는 사실을 알게 되었다. 내가 사용했던 소스는 이전 버전이었다. 그래서 2.7.2 소스를 컴파일해서 넣었다. 그랬더니 마법같이 잘 됐다. 그래서 난 속으로 아 형님들이 그 새 뭘 고쳤구나, 라고 생각하며 변경 로그를 뒤졌지만 그런 수정 사항은 애초에 찾을 수 없었다. 잠수함 패치라도 했나, 라는 생각까지……&lt;/p&gt;
&lt;p&gt;이렇게 하루가 지났다. 난 왜 2.7.1은 안 되고 2.7.2는 되는지에 집요하게 매달렸다. 뭐가 잘못일까? 뭐가 잘못일까? 그러다가 2.7.1 소스를 다시 받아서 컴파일해서 실행하는 짓까지 하게 되었는데… 결과는 정말 참혹스러웠다. 멀쩡하게 잘 실행되는 것이 아닌가? 그 때 깨달았다. 맞아, 내가 뭘 고쳤었지 ㅠㅜ~ 파이썬 소스의 초기화 부분에서 쓸모 없는 부분이라고 내가 일부를 고친 것이 생각났다. 기존에 컴파일했던 소스에서 그걸 다시 원복 시키고 컴파일을 했더니 멀쩡하게 잘 되는 것이 아닌가? ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;사무실에 혼자였지만 너무 얼척이 없어서 한바탕 웃었던 기억이 아직도 생생하다. 이틀간의 개.삽.질…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;자 이제 진짜 좀 임팩트있는 고백을 할 차롄 것 같다. 몇 해전 초여름 나는 내 인생에서 가장 어려운 버그를 마주하고 있었다. 그 이전에도 그 이후에도 나를 그만큼 괴롭혔던 버그는 없었던 것 같다. 심지어 꿈에도 게임 캐릭터가 나타나서 나를 마구 짓누르곤 했다.&lt;/p&gt;
&lt;p&gt;버그는 단순했다. 어느 순간 갑자기 게임이 데드락에 빠지는 문제였다. 그냥 게임을 플레이 할 때에는 잘 발생하지 않았고, 8명이 들어가서 방을 만든 다음에 한 30분쯤 게임을 하면 간헐적으로 데드락이 발생했다. 이 문제를 해결하기 위해서 정말 많은 인원이 같은 게임을 지루하리만큼 많이 플레이를 해야 했다.&lt;/p&gt;
&lt;p&gt;한 달여가 지나서 모두가 그 게임의 고수가 됐을 즈음에 버그의 원인을 찾을 수 있었다. 그 결과는 나를 재차 멘붕에 빠트리기에 충분했고, 다시는 이런 실수를 되풀이하지 않겠다는 마음으로 이 버그에 다음과 같은 거창한 비문을 달았다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*--

여기에 xxx 버그가 있었다.

xxx 캠페인 모드에서 게임이 행이 걸리는 버그가 있었다.
4.18일부터 근 한 달간 해당 문제를 해결하지 못해서 골치가 아팠다.
문제는 다름아닌 이 코드. 0x1234가 하드 코딩된 것이 화근이었다.

xxx 오디오 파일 핸들이 0x1234인 경우에 이 코드가 그 핸들을 닫아버려서,
xxx 특정 스레드가 무한 루프에 빠지게 되었다.

한 달간 엉뚱한 곳만 찾아 헤매었는데...
O 대리가 만든 logsteps.dll이 문제 해결의 단초를 제공했다.
CreateFile/CloseHandle을 훅해서 모니터링한 결과 그 핸들을 우리가 닫고 있었던 것이다.

---
해당 행 현상의 원인은 크리티컬 섹션으로 인한 데드락입니다. 
데드락이 발생하게 된 원인은 파일 핸들이 의도하지 않은 곳에서 먼저 닫혔기 때문으로 판단됩니다. 
데드락은 다음과 갈은 시나리오로 발생한 것으로 추정됩니다.

1. 무슨 스레드인지 모르는 어디선가에서 사운드 파일 핸들이 닫힘
2. ALAudio.dll!FALAudioStreamManager::DestroyStream 스레드가 생성됨
	A. FScopeCriticalSection을 사용해서 크리티컬 섹션 획득
	B. ALAudio.dll!FALAudioStreamOgg::ReadChunks 호출
		i. vorbisfile.dll!ov_read 호출
			1. 상기 닫힌 핸들로 ReadFile 호출함. 
			   닫힌 핸들이기 때문에 정상적이 값을 반환하지 못하고 실패함. 
			   이로 인해서 ReadChunks 함수가 리턴하지 못하고 무한 루프를 돌게 됨.

3. 메인 스레드에서 Engine.dll!ALAudioSubsystem::Update 함수가 호출됨
	A. 상기 DestroyStream이 획득하고 있는 크리티컬 섹션을 획득하려고 시도함. 
	   상기 스레드가 무한 루프에 빠져 있기 때문에 같이 무한 루프에 빠짐. 
	   게임 메인 스레드이기 때문에 다른 모든 작업이 진행되지 않고 멈추게 됨.
---

내가 썼던 보고서의 일부다. 1번 항목 무슨 스레드인지 모르는 어디선가가 바로 여기였다.
모두 꼼꼼하게 체크하지 않은 내 탓이었다. 
이 보고서를 쓰고 나서도 진짜 문제를 찾기까지 2주가 더 걸렸다.
어쨌든 O 대리가 고생한 덕에 찾게 되어서 다행이다.

이 한 줄 때문에 우리는 한 달 동안 200시간 넘게 xxx를 해야만 했다.
정말 토나오는 시간이었다.

--*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇다면 얼마나 대단한 코드가 이 엄청난 버그를 불러온 것일까? 문제의 코드는 정말 어처구니 없을 정도로 간단하다. 아래 코드가 전부다. 간단한 디버그 체크 루틴이다. 내 실수는 다름아닌 핸들 값으로 나와도 전혀 어색하지 않은 0x1234라는 값을 선택한 데 있었다. 생.각.이 없었던 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;__try
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x1234&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EXCEPTION_EXECUTE_HANDLER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// 디버거 탐지&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;마지막 이야기는 우리 이야기는 아니고 다른 업체 이야기다. 최근에 알약 드라이버가 업데이트 되면서 우리 게임과 충돌이 발생하는 문제가 있었다. 2009년 만들 당시를 제외하고는 거의 블루스크린 이슈가 없었는데 그 날 따라 이상하게 블루스크린 클레임이 세 건이나 들어왔다. 그 중에 한 건은 고객이 풀덤프를 메일로 보내주는 수고를 아끼지 않았다. 난 개발팀 팀장과 앉아서 12시가 넘을 때까지 그 덤프를 봤는데 원인이 다소 불분명했다. 메모리의 모든 값들이 모두 제 자리에 우리가 예상했던 대로 들어있었는데 블루스크린이 발생했던 것이다. 우리는 윈도우 소스코드 까지 뒤져가면서 윈도우 내부 함수에서 왜 블루스크린이 발생했을 지를 추적했지만 오리무중이었다.&lt;/p&gt;
&lt;p&gt;시간이 너무 늦었고 덤프만 봐서는 답이 없을 것 같아서 일단 다음날 유저에게 다시 연락을 해보기로 했다. 블소가 OBT를 시작하던 날이었다. 집에 가는데 옆에 회사 다니는 녀석한테 전화가 와서는 PC방에 가서 그 쩐다는 블소 캐릭터를 만들고 무려 7렙까지 키우고는 — 블소 결제는 안했다. — 집으로 돌아왔다. 씻고는 컴퓨터를 켜서는 게임 사이트 모니터링을 잠깐 했는데 난리가 났다는 것을 직감했다. 블루스크린 발생한다는 글이 도배가…… 핡~ 그리고 그 중에 아주 똑똑한 유저가 알약을 끄면 된다는 것까지 알아내서 올려놨다.&lt;/p&gt;
&lt;p&gt;다시 회사로 왔다. 알약을 설치해서 테스트를 했다. 100% 블루스크린이 재현됐다. 알약 드라이버는 전날 빌드된 타임스탬프였다. 알약이 게임 프로세스에 접근하는 것을 차단하면 블루스크린이 발생하는 것처럼 보였다. 그 새벽에 일단 사이트 담당자 분들께 현상을 설명 드리고 수정 작업이 진행된다고 했다. 그리고 드라이버 코드에서 알약을 허용 처리해 준 다음 빌드를 했다.&lt;/p&gt;
&lt;p&gt;다음날 QA팀에서 테스트를하고 수정한 드라이버를 배포했다. 더불어 이스트소프트 측에도 연락을 했는데 내가 놀란 점은 이스트소프트의 대응이었다. 보통 큰 업체들은 이런 종류의 이야기를 하면 니들 잘못이니까 니들이 고치세요~ 이런 반응이 대부분이다. 그런데 이스트소프트는 달랐다. 덤프가 필요하다고 해서 QA팀에서 덤프를 보내 줬는데 바로 자신들의 자체 보호 기능과 충돌이 난 것 같다고 4-5시간 내에 수정해 주겠다는 회신이 온 것이다. 그리고 4-5시간만에 수정된 드라이버를 업데이트해 주었다.&lt;/p&gt;
&lt;p&gt;난 이스트소프트의 이 대응에 정말 진짜 감동을 받았는데 왜냐하면 그 전에는 그 어떤 국내 업체에게서도 그런 반응을 받은 적이 없었기 때문이다. 이스트소프트의 대응은 너무나 상식적이다. 블루스크린이 났으니 덤프가 필요하다는 말. 덤프를 분석했더니 자신의 모듈의 수정 내용에 문제가 있을 수도 있겠다는 말. 그리고 광속으로 수정 업데이트를 진행해 주었다. 난 이 경험이 있고 난 다음 알툴바를 교묘하게 설치하는 것쯤은 눈감아 주기로 했다. ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;주저리 주저리 긴 이야기를 했는데 내가 하고 싶은 이야기는 간단하다. 알약 개발자들은 그렇게 쉽게 찾아낸 오류를 난 왜 이렇게 어렵게 찾아낸 것일까? 왜 그 사소한 버그를 발견하는 데에 터무니없이 오랜 시간이 걸렸을까? 내가 고친 부분은 기억도 못하고 그.렇.게.나 많은 사람들에게 검증 받은 모듈에 문제가 있다고 생각했을까? 소스 코드 한 줄 없는 게임은 디버깅을 해서 데드락의 원인을 완벽하게 찾아내는 동안에 모든 소스 코드를 가지고 있는 우리 제품에서 왜 버그를 발견하지 못했을까?&lt;/p&gt;
&lt;p&gt;답은 간단하다. 바로 문제가 나에게 있지 않고 다른 곳에 있다고 생각했던 나의 오만한 마음이다. 프로세스의 문제도, 스킬의 문제도 아니었다. 지식의 문제가 아닌 마음가짐의 문제였던 것이다. 이런 일련의 사건을 경험하면서 나는 인간의 한계를 뛰어넘는 개발 스킬, 최고의 프로세스, 쩌는 팀을 가지고 있다 해도 오만한 마음가짐으로는 자기 발등에 떨어진 왕방울만한 문제도 제대로 볼 수 없다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;많은 개발자들이 버그로 고생한다. 그리고 버그를 빠르게 찾는 방법을 고민한다. 디버깅 스킬, 개발 지식, 뛰어난 직관, 방법론 등을 찾아 헤맨다. 하지만 진짜 답은 그런 복잡한 도구와 어려운 지식에 있지 않고 문제가 나에게 있다고 생각하는 겸손한 마음가짐 속에 있는 건 아닐까? 그 옛날 맹자 선생님께서 하신 말씀과 다르지 않다. 지난 10년간 내가 프로그래머로 일하면서 배운 가장 중요한 지식은 거의 모든 경우에 자신의 잘못을 먼저 바라보는 사고가 문제 해결에 가장 큰 도움이 된다는 것이었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;인이라는 것은 활 쏘는 것과 같다. 활을 쏠 때는 자세를 바르게 한 후에 쏘는 법이다. 화살이 과녁에 맞지 않으면 자기를 이긴 자를 원망할 것이 아니라 (과녁에 맞지 않은 까닭을) 도리어 자기 자신에게서 찾는다. – 맹자&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 특허와 보고서에 숨겨진 진실]]></title><description><![CDATA[요즘 신규 업체 미팅을 하면 항상 단골 손님으로 특허와 보고서 친구들이 등장합니다. 관련 업체 분들께서 여기에 엄청난 환상을 가지고 계신 것 같아서 오늘은 그 이야기를 좀 해볼까 합니다. #…]]></description><link>https://jiniya.net/wp/archives/9368</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9368</guid><pubDate>Tue, 30 Oct 2012 23:58:30 GMT</pubDate><content:encoded>&lt;p&gt;요즘 신규 업체 미팅을 하면 항상 단골 손님으로 특허와 보고서 친구들이 등장합니다. 관련 업체 분들께서 여기에 엄청난 환상을 가지고 계신 것 같아서 오늘은 그 이야기를 좀 해볼까 합니다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;특허부터 시작해 볼까요? 일단 전 기본적으로 소프트웨어 특허 자체가 좀 코메디라고 생각합니다. 욱기잖아요 이건 ㅋ~ 그래도 어쨌든 고매하신 분들께서 관련 법안을 만드셨으니 특허 시스템은 존재하고 사람들은 자신의 권리 보호를 위해서 특허를 출원합니다. 게임 보안 업체도 너도나도 할 것 없이 특허를 많이 출원하고 있습니다. 물론 큰 업체같은 경우는 특허 지원 시스템이 있어서 — 특허를 출원하는 경우에 포상금이 주어지는 — 더 많은 특허를 내기 위해서 직원들이 매일같이 고민하고 있습니다.&lt;/p&gt;
&lt;p&gt;이렇게 많은 업체들이 경쟁적으로 특허를 출원하는 만큼 특허에 관한 오해도 심각한 수준입니다. 가장 큰 오해는 이런 겁니다. 와 A라는 업체에서 이런 해킹툴을 막는 희깔난 특허를 등록했다는 신문 기사를 보니 해당 업체 솔루션을 사용하면 그런 종류의 해킹툴은 다 차단되겠구나, 라는 정말 순.진.한 생각입니다. 차단 될까요? 전 차단 안 된다에 올인 하겠습니다. 왜냐구요? 현실 세계에 존재하는 초딩이 만드는 해킹툴도 그런 몇 페이지짜리 말장난으로는 절대 차단을 할 수 없기 때문입니다. 하물며 그들이 말하는 그 엄청난 범위의 해킹툴을 그 몇 페이지짜리로 다 차단한다구요. 네. 맞습니다. 어림도 없습니다.&lt;/p&gt;
&lt;p&gt;두 번째 오해는 이런 겁니다. 특허가 등록 됐으니 해당 기능이 솔루션에 탑재됐을 거라는 생각입니다. 뭐 첫 번째 생각도 이 두 번째 생각의 근간에서 출발한다고 볼 수 있습니다. 그런데 말이죠. 소프트웨어 특허란 건 그 사람의 생각에 대한 권리를 인정해 주는 것이지 그 사람이 그걸 만들었는지 안 만들었는지를 검증하는 것이 아닙니다. 즉, 임플멘테이션이 존재하지 않더라도 특허 등록이 가능합니다. 그러니 특허가 등록 됐다고 그 기술이 탑재 됐다고 생각하는 오해는 이제 여기까지만 해주시면 되겠습니다. 특허는 말 그대로 특.허. 일 뿐 아무거도 아닙니다.&lt;/p&gt;
&lt;p&gt;끝으로 게임 보안 솔루션의 특허에 관해서 좀 더 재미난 부분을 살펴보면 이렇습니다. 일반적으로 게임 보안 특허는 연립 방정식과 유사한 구성을 가집니다. 해킹툴을 잡기위한 가설들을 세우고, 그 가설들을 이렇게 저렇게 연결해서 이런 조건을 만족하다면 그 놈은 해킹툴로 간주할 수 있다, 라는 방식을 따르게 됩니다. 결국 따지고보면 여러 개의 방정식을 사용해서 미지수들을 소거해 가면서 해를 구하는 연립 방정식인 셈이죠. 그런데 이 연립 방정식이란게 중학교 정도의 수학 지식을 가지고도 알 수 있겠지만 미지수 개수만큼 방정식이 있어야 해를 구할 수 있습니다. 즉, 미지수가 x, y, z 세 개라면 방정식이 세 개가 있어야 한다는 말이죠. 정수론 따위에서 말하는 브루트포스의 접근을 한다면 방정식이 모자라도 풀 수 있는 경우가 있긴 하지만 어쨌든 일반적이지는 않습니다. 그런데 여러분이 게임 보안 특허에 관심이 많다면 이제부터 그걸 잘 살펴보십시오. 놀라운 발견을 하게 될 겁니다. 상당히 많은 특허에 방정식이 모자라는 경우가 많다는 사실입니다. 어 이렇게 해서는 연립 방정식을 풀수가 없는데, 라는 생각이 드는 경우가 대부분입니다.&lt;/p&gt;
&lt;p&gt;왜 방정식이 모자랄까요? 중요해서 숨겼을 수도 있고, 나머지 방정식을 모르지만 과시용 특허를 등록하기 위해서 출원했을 수도 있습니다. 제가 살펴본 특허 중에 일부는 그 숨겨진 나머지 방정식에 구현이 까다로운 부분이 많이 있었습니다. 어 이걸 구현하려면 뭔가 굉장히 복잡할 텐데 진짜 구현했을까, 라고 생각해서 들춰보면 없는 경우가 많았습니다. 제가 게임 보안 일을 하면서 지난 시간 동안 느낀 것은 거의 모든 경우에 생각이 어려운 부분은 없다는 점입니다. 사실 말로 하면 이 세상에 못 잡을 해킹툴이 없습니다. 어렵지도 않아요. 그거 뭐 게임에 접근 좀 못하게 하고 변조하면 차단하고 그러면 되는 거죠 ㅋ~ 문제는 구현입니다. 제대로 동작하는 코드를 만드는 일은 그 어떤 일보다도 어렵습니다. 특히나 해커를 상대로 싸울 수 있을 만큼 쓸모 있는 코드를 만드는 일은 더욱 어렵습니다. 특허는 특허일 뿐입니다. 그러니 특허가 해킹툴을 차단해 준다는 순진한 생각은 이제 과감하게 버리도록 합시다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;다음으로 보고서를 좀 살펴봅시다. 정말 웃기게도 요즘 보고서를 잘 쓴다는 광고를 하면서 다니는 업체가 있는 것 같습니다. 이 이야기를 들었을 때 전 참 아이돌스러운 광고가 아닐 수 없다는 생각을 했습니다. 가수는 노래를 부르는 게 주업입니다. 당연히 노래를 잘 부른다는 이야기가 먼저 나와야 합니다. 하지만 아이돌들은 그렇지는 않죠 ㅋ~ 전 춤을 잘춰요, 내지는 전 얼굴이 이뻐요, 라는 이야기로 들이 댑니다. 보고서를 잘 쓴다는 게 아이돌의 그것과 별반 다를바가 없는 이야기라는 생각입니다.&lt;/p&gt;
&lt;p&gt;이 바닥에서 6년 정도 일하다 보니 해킹툴을 막을 수 있다는 방법이란 방법은 다 찾아서 해 본 것 같습니다. 절에 가서 기도도 했으니 말이죠 ㅋ~ 당연히 보고서를 만들었던 시절도 있었습니다. 이뿌게 포맷도 정해서 워드 문서로 차곡차곡 정리해서 저장소의 문서 폴더에 하나하나 올렸드랬죠. 나중에 살펴보면서 뿌듯해 하면서 말이죠. 그런데 그런 보고서가 하나 둘 모여감에도 해킹툴 차단은 나날이 구려지는 안습한 시츄에이션이 발생했습니다. 고민했습니다. 우리가 이.렇.게.나 열심히 분석하고 정리하는데 왜 해킹툴은 더 못 막는 걸까, 라는 생각이 저의 뇌를 후벼팠습니다. 결론은 단순했습니다. 보고서 포맷 맞추고, 캡처하고, 코드 붙여넣느라 시간 다 보내고 있으니 정작 차단 코드를 만들 시간이 없었던 겁니다. 해킹툴은 누가 막나요? 패턴이랑 차단 코드가 막습니다. 그걸 업데이트는 안 하고 허구헌날 보고서만 쓰고 있으니 우리는 점점 더 구려졌던 것이죠. 그래서 과감하게 보고서 따위 개나주자. 쓰지 말자는 선택을 했습니다. 그러자 마법처럼 해킹툴이 차곡차곡 막히는 기적을 경험하게 되었습니다. 보고서가 해킹툴을 막아주진 않습니다. 또한 디테일하게 분석할수록 더 원천적으로 차단 억제력이 높은 코드를 만들 수 있다는 것도 진짜 도시전설과 같은 생각입니다. 전혀 그렇지가 않아요. 그 이야기는 다음에 기회가 된다면 자세히 하도록 하겠습니다 ㅋ~&lt;/p&gt;
&lt;p&gt;돌려서 생각해 봅시다. 왜 게임 보안 업체가 보고서를 써야 할까요? 언제 분석 보고서를 쓸까요? 당연합니다. 지독하게 그 해킹툴이 안 막힐 때 쓰는 겁니다. 이게 도저히 안 막히니까 우리가 이렇게 고생해서 분석한 거라도 보여드립니다, 라고는 제품을 구매한 업체에게 전달하는 것이죠. 막히면요? 보고서를 쓸 일도 없습니다. 그러니 다시 생각해보면 보고서를 잘 씁니다. 많이 씁니다, 라고 광고하는 건 우린 해킹툴을 겁나 못 막습니다, 라고 광고하는 것과 다를바가 없는 이야깁니다.&lt;/p&gt;
&lt;p&gt;주간 회의가 있었습니다. 정말 한참만에 보고서를 쓰라는 이야기를 했습니다. 왜 했을까요? 지독하게 안 막히고 계속 꾸역꾸역 업데이트되는 해킹툴이기에 쓰자는 이야기를 한 것이지요. 2개를 이야기 했는데 하나는 벌써 GG를 쳤다는군요. 그래서 하나만 쓰기로 했습니다. 통상 일주일에 4,000개에서 10,000개 정도의 신규 해킹툴이 수집됩니다. 실행해 본다는 게 가능할 것 같나요? 테스트 하는 건요? 보고서는 당.연.히 못 씁니다. 왜냐하면 우리는 패턴 추가하고, 차단 코드 만들고, 취약점 수정하기에도 충분히 바쁘거든요.&lt;/p&gt;
&lt;p&gt;꼭 기억하세요.&lt;/p&gt;
&lt;p&gt;분석 보고서는 지.독.하.게 해킹툴이 안 막힐 때 쓴다는 거.&lt;/p&gt;
&lt;p&gt;그리고 보고서가 해킹툴을 막아주진 않는다는 거.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_특허와_보고서에_숨겨진_진실.md_0.png&apos; data-alt=&apos;특허도 보고서도 해킹툴을 막아주진 않습니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5dc23be4fe0d2e5a5d3b4926d8ca3e72/0eb09/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%8A%B9%ED%97%88%EC%99%80_%EB%B3%B4%EA%B3%A0%EC%84%9C%EC%97%90_%EC%88%A8%EA%B2%A8%EC%A7%84_%EC%A7%84%EC%8B%A4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 31.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABGElEQVR42jVPW26DMBDk/ofoHXqJJvkpDaVAUBNi8zBgY2NsMJhXN4k6Wo1mR1rtjIPOl+QzbPJKVIwXtagbmhGWlX2nlJC67YZeR0HycayTOynyFCGEU0wpnefZqTEhMWqySpSPY4ZL4LZksApCQU/DONnpdDq4rhsEYRRFvu97nocxdjqpRVbJqtn3fVtXzaViYlT9/o91Xa+3wj0XshtGM5gnrLXgO8nXqfy9c1w2mNBbzhAZpB7VYLQShnHdbMucofRwvPrflyD4gdhhGMZxLIRwOEG9VLOZHvF6A7wuy/aE3axdLDy3s204XZ4AHxgKAzujMpp3igoI/BJQgWcVjBFDV6eEvNXlu8xZS1hHeVtQiPZq9AeU8UycLcGSOwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;특허도 보고서도 해킹툴을 막아주진 않습니다.&apos; title=&apos;&apos; src=&apos;/static/5dc23be4fe0d2e5a5d3b4926d8ca3e72/0eb09/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%8A%B9%ED%97%88%EC%99%80_%EB%B3%B4%EA%B3%A0%EC%84%9C%EC%97%90_%EC%88%A8%EA%B2%A8%EC%A7%84_%EC%A7%84%EC%8B%A4.md_0.png&apos; srcset=&apos;/static/5dc23be4fe0d2e5a5d3b4926d8ca3e72/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%8A%B9%ED%97%88%EC%99%80_%EB%B3%B4%EA%B3%A0%EC%84%9C%EC%97%90_%EC%88%A8%EA%B2%A8%EC%A7%84_%EC%A7%84%EC%8B%A4.md_0.png 190w,
/static/5dc23be4fe0d2e5a5d3b4926d8ca3e72/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%8A%B9%ED%97%88%EC%99%80_%EB%B3%B4%EA%B3%A0%EC%84%9C%EC%97%90_%EC%88%A8%EA%B2%A8%EC%A7%84_%EC%A7%84%EC%8B%A4.md_0.png 380w,
/static/5dc23be4fe0d2e5a5d3b4926d8ca3e72/0eb09/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%8A%B9%ED%97%88%EC%99%80_%EB%B3%B4%EA%B3%A0%EC%84%9C%EC%97%90_%EC%88%A8%EA%B2%A8%EC%A7%84_%EC%A7%84%EC%8B%A4.md_0.png 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;특허도 보고서도 해킹툴을 막아주진 않습니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안 솔루션 그놈이 그놈 아닌가요?]]></title><description><![CDATA[게임보안 제품 이거 쓰나 저거 쓰나 그놈이 그놈 아닌가요? 
어차피 100% 막지도 못하잖아요. 업체 분들을 만나면 이런 이야기를 많이 하십니다. 네. 맞습니다. 그 어떤 솔루션도 해킹을 100% 막지는 못합니다. 하지만 10…]]></description><link>https://jiniya.net/wp/archives/9191</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9191</guid><pubDate>Fri, 19 Oct 2012 23:58:29 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;게임보안 제품 이거 쓰나 저거 쓰나 그놈이 그놈 아닌가요?&lt;br&gt;
&lt;br&gt;
어차피 100% 막지도 못하잖아요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;업체 분들을 만나면 이런 이야기를 많이 하십니다. 네. 맞습니다. 그 어떤 솔루션도 해킹을 100% 막지는 못합니다. 하지만 100% 막지 못한다고 해서 다 그놈이 그놈인 건 아니랍니다.&lt;/p&gt;
&lt;p&gt;일반적으로 많은 분들이 게임 보안 솔루션하면 게임 해킹을 100% 차단하기 위한 솔루션이라고 생각을 합니다. 하지만 이건 정말 아주 많이 잘못된 생각입니다. 왜냐하면 어떠한 보안도 100%가 있을 수는 없거든요. 이 세상에 그렇게 많은 경찰과 군인이 있지만 범죄와 테러가 끊임없이 발생하는 것과 똑같은 원리입니다.&lt;/p&gt;
&lt;p&gt;게임 보안 솔루션이 하는 일은 100% 차단하는 것이 아닌 게임 내에서 유통되는 해킹툴의 수치를 관리하는 일에 가깝습니다. 게임 보안 솔루션이 없을 때에는 착한 사용자가 게임 내에서 아주 손쉽게 모든 지역에서 해킹툴을 사용하는 게이머를 만났다면, 게임 보안 솔루션을 적용한 후에는 그 빈도를 좀 낮춰서 가끔 만나도록 만들어 주는 역할을 하는 것이죠.&lt;/p&gt;
&lt;p&gt;일종에 당뇨병 환자의 당 수치를 관리하는 것과 비슷한 일입니다. 당뇨병을 완치할 순 없지만 당 수치를 잘 관리한다면 생존에는 문제가 없습니다. 당 수치를 관리하는 것에는 여러가지 방법이 있죠. 식이요법도 있고, 당뇨약을 시간에 맞춰서 복용하는 방법도 있습니다. 자동으로 인슐린을 투입해주는 인슐린 펌프도 있죠. 모든 방법이 당뇨병을 완치하진 못하지만 심각한 당뇨 환자라면 인슐린 펌프가 제일 편한 방법입니다.&lt;/p&gt;
&lt;p&gt;게임 보안 솔루션도 마찬가지입니다. 많은 솔루션이 존재하지만 100% 모든 해킹툴을 차단하는 솔루션은 단 하나도 없습니다. 하지만 그 솔루션들의 해킹툴 수집 능력, 신규 핵킹툴 출현 억제력, 해킹툴 출현 시 대응 속도에는 식이요법과 인슐린 펌프만큼이나 큰 차이가 있습니다. 이제 게임 보안 솔루션의 기능이 동일하다고 성능도 동일하다는 생각은 과감하게 옆집 멍멍이에게 주도록 합시다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sa.nexon.com/community/free/view.aspx?n4PageNo=1&amp;#x26;emSearchType=Title&amp;#x26;strSearch=%c7%d9&amp;#x26;n4ArticleSN=811427&amp;#x26;n4ArticleCategorySN=1&quot;&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_0.png&apos; data-alt=&apos;반도의 흔한 게이머의 합.성.짤.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &apos;&gt;
      &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 112.63157894736841%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAELUlEQVR42mVUXW/bZBT27+GCO9DuuENITAghLpAQoF1QaRKIDU2q1m1dp7bQdq12sbGOtc062kKF1qofdKPdaLfBurZpSJo0tlMn8bcT+/VXnDi2Y8fhxNbQpD1yjs57fD6e87xWsAu/osvL3pUVp2/ZObdQu7BY719xBlbdbxfsnl+8L6ZrZ6b1r2bUr+83zs57Z+fdbxb8njnn/KI7t0RgosSUuQwvHktyoUSnBSkvVQmazegG1bA5vVYyzYJu5q06Zdu0bZdlM+ValFejEWKwHLV/SGdLqoostWoi2UTI0hRLFQ2NUdgj8oBhCU4ucVKhyB7nqeQBuUWSL0l8nyQyWJY9ojNrydXJmuVYtbpVb1YqMssKIsOI+L9U9pDEcZLATV2z6/U6ZNTqsiLrmsxLCpYn2fT2xb3F74+JslSROp0OLwhZnKyWjoP0ukencjhOs5zjum6rBT/P9VpB2w/bWj3Atnb2/txObj5LJeaXHj7ZXXm4s/V0f+mP7aW1x1N3Evd/3xi/cXf2t/X5xOzsTCJxd+523+DCg0c7u5m/D0vYtR8mx27M/jieGB6bHpm4NzJ+b2QiMTQ6NTw6NTYxc/HqrSuDP/f2/3Tp2uSlgdsDQ3d6+2/2Xr11rvf66M0HmOs22xHCsGtivxMhDEPHC2yn+zSavu22/XZoOp7ecHgZVfUG1nSajuPYdhOWAqfZ7Drha2i3A8/3vVYr9L124PMcJ3AcQ9MqqmKB73fewOvFcHpBo79Sgnew2TaQrOpyFSBrGsJarRbwDILgFfnwzV7xSp1uVqDpuqwoCCH4MjBd17UIiqLIstxoNKBdTL4ZwYkAR+gCxZCtIgTG0FWMYZhcLkeSZLlcpiiKpulisQjB2AFbKpUIguR5Hpbxg8BsNI26XVV1w7IwQRBEUYwtiqBErGAt1J2gqapaq9WAEWzk+YGADF7WKFasajoGvVmWhZkwASzMh7HxcDiCA5FKpQKNYlEkUeRYFh5JFDCW7aYWCoWYs/IKMFOOEGsB0kTX1lY1DXpBuCsYTZehEnbGcTyfz5+cnMQs8hHiOEEQEI9vJNqoAleFkNwthtRyBHBAmHja//vDEdYGByZDPUitInirdIuBA0gVWwAUw7agQiwhxA3DAM6WZYHaLT8wbVerNURoaJhdwSAXiB3lsql0GlaAGkmSOI4DIvGdgQ/1vu9DMV9VabGaPykzvIgNDw18/tmnpz/84J233n7/1KmJiesCz1FUgWXgj0YBbcHhWEYQeLiwsBOCzvB5Q1NR4LD+y32ffPzRl2d6Tr/73uB351fX13TTQloNaaasaAwrsrzEi1Wxgmyn5fltEFmHz8vQKrKCrTz6Z3nj2dLG843HL3cPyc2d5PP9Y3D20tR+hjrIFFPZ8tNU4cmLbPKolMFpqlQkKSqXJ5Lp7H/UBaCjNXYqAAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;반도의 흔한 게이머의 합.성.짤.&apos; title=&apos;&apos; src=&apos;/static/b58304b65e8591793dad0be44fb2dd33/efd7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_0.png&apos; srcset=&apos;/static/b58304b65e8591793dad0be44fb2dd33/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_0.png 190w,
/static/b58304b65e8591793dad0be44fb2dd33/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_0.png 380w,
/static/b58304b65e8591793dad0be44fb2dd33/efd7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_0.png 760w,
/static/b58304b65e8591793dad0be44fb2dd33/24c26/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_0.png 921w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;반도의 흔한 게이머의 합.성.짤.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_1.png&apos; data-alt=&apos;반도의 흔한 게임 보안 솔루션의 네이버 테스트&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e6a9e9b0327cb941c7833b6628c0dabe/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB1UlEQVR42iVRuZLTQBTU/weEEEAE2RZVFCQUGxHgpWyzCz7Kt2TNPaM5pNG5liWLp92uCaZmut973S8wdhtFHyi9M0ZJKQlBVVUOw1Bpfvr3nuzeqtO04nJoLnlO4vijEJ+NSbzPAUFWemuZtTzLUq2d95eyPHg/KZ1WeJGKpVk9uP2mltLWBRN7KU9JkmitR7F1TinJGPe+9n7F+Z3WD4x9V5KXRZO5nP2dhk9Ti1B3G4TUjAGZwYzX6zXgXCMkwjCMY6zU0do/bVt13ZBxkYShB95+4xgd6qrMc5emPhvRti1YC87RD0q+gg2MsTGuvdxut370nKjksHNRVFBqwvCidV3BaL4oiq4fCaM4Qp8QfoNxiDElhICf14/aeLk/p3HcWwOncxbEeZHnaF3iqCvyIc8Cu3uih0eZKGusfkGaZs1zTeMvJPomqXTJI4vftbWAin3fyfXv9c97i869M0EhJIsxIkQIQV7AwW2iwugXJvMYIcoQJtuyhOUUsEW5nR1nk+NyUSkZ2DQ1xnBQCGGthTDcmL8yxidJCndYCcTUNM899O2uejc3h/V5vWqUCMAF+IS0KaUgBjZlDMKDEeCFMyakhFqQ82sW8rDYTCfL+czg+D+NpSAET1QP6AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;반도의 흔한 게임 보안 솔루션의 네이버 테스트&apos; title=&apos;&apos; src=&apos;/static/e6a9e9b0327cb941c7833b6628c0dabe/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_1.png&apos; srcset=&apos;/static/e6a9e9b0327cb941c7833b6628c0dabe/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_1.png 190w,
/static/e6a9e9b0327cb941c7833b6628c0dabe/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_1.png 380w,
/static/e6a9e9b0327cb941c7833b6628c0dabe/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;반도의 흔한 게임 보안 솔루션의 네이버 테스트&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_2.png&apos; data-alt=&apos;반도의 흔한 게임 보안 솔루션 개발자 블로그 검색어 유입 순위&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 238px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5ccefc2eda66240172c4bb2cc8cc3c87/da2e6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 169.4736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAIAAADQyG7qAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADDElEQVR42o1V23KbMBDl/3+pD51OL9PEaZI6tgmFYEAWN4EQQuImIF1ht33oGLwjyxprZJ09Z/fIGKdJtn3bq0K2tGpIWbdqeL8tDDh294pMn9gh3Xrkw08/oBVsTBCrhwcIpaf3adQHxmkcRhgTTLCzGIaQMs6KJGdxzkJSJBlDYZbRMspYznjbLIXBK3F38O4P/stb+GChwzHeO9h08f0rCmLad13TtNfC6PseYAPEGbHGCjNAGlSveji7FEY/DHHBY1qlTOCM47wyT5TL9szZCmG9GnbHeHdM3YjaOHfC4tkjTdvfJBXABrAA9QwbGIZJqRXAF9iVkHaQ2Ch1Q2L58THKd36aUA5715n6Q1glxE8bbR1so8T0Yi/KXxGJsrJdVuksFRTIdK4nXSSjTkF/rZTHpUi6XlmIWChzo8IMCE7LrZukhbiJbbjZT2iQMMJElFdctBkTddtPZzSLYQAxmmOl63gG2w8gQN/p0XUrhJWVuDf9jRk8O/j73rdxdncIHu3T1kvuTCTrJcqNuq5DQiNSFGWVFZxxwXgFLXEiBSasrhfZvtA7j5nsESiEJM4KjIthtJ16dsJnJwKqn5zoGBVf9miH8pvYhj/gsqnqFi6ED5SnaDqmG2PlWn0zZDXnVcu6ht4uuKBlBZmnBedCrphBycW3F/fry/HJxp+3RysAkv1HG3988f2UDWrRDEBnAZfWDWgKa5BY6dENc2Ot6Awt2HSqnROuZFvVXcJkVsqIwlK9vy9XWK82FnqwMLC9sbCfluDBZpB/OqCE18ucGxfjBQDDPw+DA6u+q7tKyjpMKU6LkDAvzMBxwTTdEGpMrKWszUBuTO8BHg0v/mGhN0zeTmTzCyd52XftuTyXrPfiYbONjbOH6V/0Qk264dR161VDkDIYmHAH5yGtgrR0Y4ZzjvLKjWlCxXUzUMNrkIKZnEj565SBTpiUp4w7IbUjtg9IkM3v3jXr/Yv5TPI4u4JW4Y89XIUNZrB38c4ND178aCELpf+38HW2pURxBu+bH+cuJnFetjfHb1Pio2peVF2zAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;반도의 흔한 게임 보안 솔루션 개발자 블로그 검색어 유입 순위&apos; title=&apos;&apos; src=&apos;/static/5ccefc2eda66240172c4bb2cc8cc3c87/da2e6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_2.png&apos; srcset=&apos;/static/5ccefc2eda66240172c4bb2cc8cc3c87/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_2.png 190w,
/static/5ccefc2eda66240172c4bb2cc8cc3c87/da2e6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_2.png 238w&apos; sizes=&apos;(max-width: 238px) 100vw, 238px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;반도의 흔한 게임 보안 솔루션 개발자 블로그 검색어 유입 순위&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_3.png&apos; data-alt=&apos;미디엄과 하드, 사소하지만 굉장히 큰 차이&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 244px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f6ac1f7dfe4793bb46b91b6aefd2e690/d3a2b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 44.21052631578947%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7CAAAOwgEVKEqAAAABT0lEQVR42oVQ21LCMBDtN4jQll4SIL2mLSFpem9BERxlEEfF8f+/xKUo45Oc2WxOstns2VUm02mSJBGljuNQSgPfpzR2yUzX9fE1KI7rFmUpUzlnvGs6wXleVDENNU27nuy6XlEUdVVDfS5EmkoBSGWWZROM/6+vIIQ8z/N9n/zIDqIImqBwaVuW8YvT2wu5JOu6pqojgKapt8PBYHADa9hj1OMcVlX1TP5qUQhxpMwFT2eEMMbruk1FGgRhkjC+4FJmQUjBg5gwjDOZYYwv41B8j7zt2fEl2azw09o9Htj7Ptlt3Ndd9HFgYLut//Um9o/e4Tn6PMRibhuGZfb6Feita4v7u4ovwjAky67YbldtU5T5XKbJclk+rJuuzcqcQahr8q6tyqoihEB9xTRN20Y2wrCPx6ZlIctGwOF7A04Wtu2TIYRR7zGewIzPk/sGBKhQ0lB7OXEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;미디엄과 하드, 사소하지만 굉장히 큰 차이&apos; title=&apos;&apos; src=&apos;/static/f6ac1f7dfe4793bb46b91b6aefd2e690/d3a2b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_3.png&apos; srcset=&apos;/static/f6ac1f7dfe4793bb46b91b6aefd2e690/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_3.png 190w,
/static/f6ac1f7dfe4793bb46b91b6aefd2e690/d3a2b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_3.png 244w&apos; sizes=&apos;(max-width: 244px) 100vw, 244px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;미디엄과 하드, 사소하지만 굉장히 큰 차이&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_4.png&apos; data-alt=&apos;해커들에게 가장 어려운 게임 보안 제품&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 497px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/7204ca97f96a2cb9fba37ac184c69684/c8b0d/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 11.578947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAYklEQVR42j2NXQ6AIAyDuQawISFRkD81GhC8/72cPPilabdkS5n3IaU8lEKIFFprCShBAUykfwBUiEohrSAGzLo1fqScN3omyPc8t2Kf6ltx5Vp69f125+GoiS6NMZxzIcQLKHMSB2SPhRIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;해커들에게 가장 어려운 게임 보안 제품&apos; title=&apos;&apos; src=&apos;/static/7204ca97f96a2cb9fba37ac184c69684/c8b0d/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_4.png&apos; srcset=&apos;/static/7204ca97f96a2cb9fba37ac184c69684/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_4.png 190w,
/static/7204ca97f96a2cb9fba37ac184c69684/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_4.png 380w,
/static/7204ca97f96a2cb9fba37ac184c69684/c8b0d/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_4.png 497w&apos; sizes=&apos;(max-width: 497px) 100vw, 497px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;해커들에게 가장 어려운 게임 보안 제품&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_5.png&apos; data-alt=&apos;해커들에게 가장 골치아픈 게임 보안 제품&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/cd8e03f8dda5114b9730a61d739a7804/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 6.315789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAA7CAAAOwgEVKEqAAAAAPElEQVR42iXJQQ4AEAwFUfc/oX7VhUSVIBEXIOzeZFwfXUUMsBCy9+WhMrcYv435ZgHd20RmSkqkwF7rAEcqNL1I69bmAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;해커들에게 가장 골치아픈 게임 보안 제품&apos; title=&apos;&apos; src=&apos;/static/cd8e03f8dda5114b9730a61d739a7804/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_5.png&apos; srcset=&apos;/static/cd8e03f8dda5114b9730a61d739a7804/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_5.png 190w,
/static/cd8e03f8dda5114b9730a61d739a7804/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_5.png 380w,
/static/cd8e03f8dda5114b9730a61d739a7804/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_5.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;해커들에게 가장 골치아픈 게임 보안 제품&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_6.png&apos; data-alt=&apos;해커들에게 가장 터프한 게임 보안 제품&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 596px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/70fa78790c65c2a653e185654aa75632/fe133/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 11.578947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAA7CAAAOwgEVKEqAAAAAV0lEQVR42h2MUQ6AMAxCPY52QGuNZk69/7VsRgh5fMBC2JFCW3NX7gxHBopdrVIiSIBmRsrdq7cpkct18hscvT03n44JKB4d740jITnnvlxyD9u2+gqPH0PeFjLzkT8ZAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;해커들에게 가장 터프한 게임 보안 제품&apos; title=&apos;&apos; src=&apos;/static/70fa78790c65c2a653e185654aa75632/fe133/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_6.png&apos; srcset=&apos;/static/70fa78790c65c2a653e185654aa75632/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_6.png 190w,
/static/70fa78790c65c2a653e185654aa75632/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_6.png 380w,
/static/70fa78790c65c2a653e185654aa75632/fe133/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_6.png 596w&apos; sizes=&apos;(max-width: 596px) 100vw, 596px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;해커들에게 가장 터프한 게임 보안 제품&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_솔루션_그놈이_그놈_아닌가요.md_7.png&apos; data-alt=&apos;그리고 게이머들이 탑재를 요구하는 게임 보안 제품&lt;br&gt;&lt;br&gt;오늘도 XIGNCODE 개발팀은 그런 제품을 만들기 위해서 최선을 다한다는거, 아시죠? ㅋ~&lt;br&gt;&lt;br&gt;기능이 똑같다고 성능도 똑같다는 편견은 이제 버릴 때가 되었습니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 414px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3015e53f0784ecfd278aaffdb30356a7/c6ea4/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_7.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 27.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABJUlEQVR42hXQy27iQBBAUUt0VXVV9cM2dmOCxsEYjQlPESCQaJIsk0X+/3vCSGd9Fzc7BLtnGtRugz16u/N2EFyiuVuhadHM0AxMS8YOTU+wIJgTrJzNBbM+ly7wn8DzyI+Rp4K1hUQmETQIJZkCYao2MZUEycID/dcFWypl26S7SlalvAj+I9igeUZzhLvRBUaDGZ0RLo6PBFczOoGpyMi9nvMkl2xd67HW1cRtaj0oLhgGgYVAL7i20HpaBl4HHiKvGTrBKOi8LQqtomTzXNpC+1r/Nr5rXBMoeZo6HCs0JZ+Svia9zsI5ud3E38Z6qt25lPfK9ZXLziUfct7ft3m7jbKN/OTsPsrtIX60xXdb/Mzi59i9eXsp9Evp6uiN8ca4KOUXFbocBIvA3IUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그리고 게이머들이 탑재를 요구하는 게임 보안 제품&lt;br&gt;&lt;br&gt;오늘도 XIGNCODE 개발팀은 그런 제품을 만들기 위해서 최선을 다한다는거, 아시죠? ㅋ~&lt;br&gt;&lt;br&gt;기능이 똑같다고 성능도 똑같다는 편견은 이제 버릴 때가 되었습니다.&apos; title=&apos;&apos; src=&apos;/static/3015e53f0784ecfd278aaffdb30356a7/c6ea4/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_7.png&apos; srcset=&apos;/static/3015e53f0784ecfd278aaffdb30356a7/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_7.png 190w,
/static/3015e53f0784ecfd278aaffdb30356a7/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_7.png 380w,
/static/3015e53f0784ecfd278aaffdb30356a7/c6ea4/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%86%94%EB%A3%A8%EC%85%98_%EA%B7%B8%EB%86%88%EC%9D%B4_%EA%B7%B8%EB%86%88_%EC%95%84%EB%8B%8C%EA%B0%80%EC%9A%94.md_7.png 414w&apos; sizes=&apos;(max-width: 414px) 100vw, 414px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그리고 게이머들이 탑재를 요구하는 게임 보안 제품&lt;br&gt;&lt;br&gt;오늘도 XIGNCODE 개발팀은 그런 제품을 만들기 위해서 최선을 다한다는거, 아시죠? ㅋ~&lt;br&gt;&lt;br&gt;기능이 똑같다고 성능도 똑같다는 편견은 이제 버릴 때가 되었습니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[비주얼 스튜디오 2012 테스트 익스플로러 활용]]></title><description><![CDATA[지난…]]></description><link>https://jiniya.net/wp/archives/9157</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9157</guid><pubDate>Mon, 15 Oct 2012 23:58:28 GMT</pubDate><content:encoded>&lt;p&gt;지난 5년간 게임 보안 제품을 개발하면서 보낸 시간은 정말이지 하루도 빠지지 않고 전쟁터 같은 일상이었다. 항상 새로 추가해야 할 기능들이 있었고, 그런 일정을 비웃기라도 하듯 해킹툴은 하루도 거르지 않고 새롭게 나타났다. 이런 연유로 우리는 빌드를 밥 먹듯이 할 수 밖에 없었다.&lt;/p&gt;
&lt;p&gt;빌드 서버 로그 기록을 살펴보니 릴리즈 빌드 서버에서 지난 1년 동안 엔진 빌드를 214번, 차단 코드 빌드를 400번, 패턴을 포함한 전체 릴리즈 빌드를 무려 1078회나 진행했다. 릴리즈 빌드는 거의 매일 3-4회씩은 있었다는 이야기고, 차단 코드를 변경하는 일도 거의 매일 한 번 이상은 있었다는 의미다. &amp;#x3C;화면 1&gt;에 나와 있는 최근 빌드 내역을 살펴보면 정말 매일같이 빌드가 있다는 말이 거짓말이 아님을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 571px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/41dba41421da18e5e01deec22af9d10d/503dd/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 64.21052631578948%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAACuUlEQVR42nWOW0hTcRzHD9GThYhhIS7NICjoqaeeegrqIUFQpMKXiFQaM+qlh4ggiiLbnLo2NBVHKpVuZ2te57xMdzmblnO6rLObbnM7x/O/nHN2cb1ox6CQoh8fPg9fvl/4EXv/3O7uviGHUnFmmwFISO/95whRFBCCGKODIAx8CfcMPbbgM6VcNgzB3wUEBUEgkskQAEGOOwjNcuuJbR8LoktcR+9GJfidSwYgvG8umEwGCZYN83wY4z+EMI6mBY7H0R0M/bhLx8l4PoJwSMRbm7yVBNdYflnAGwwTJBhmf4BQ+BchjGIMpJwbCgYuZhH0QZ2OkWEcgYgWUYrmjeqtE0ns5dFmKiWNuTgS4xDS0hiioIBZlrVNO0s41pNDaR+v7RRlUs6jWAaCkGDoRqXSWPqCZSIEG3WJCSqHRKmRRuwaryfFi8b4qQDuBZkk/tq9NSTLo8yGaGfxWlA0t6VLOBxwZB7OgEcEGmlKkGfmc48BXBdRYkZ40h8vyPSeHgwd+pLriSf67a4CSng2AI5T209RyuaeKxYBPcZVW2LXCWFU8d1y5E2+MguRLX2rhy/vy5YNwHIHVbS4fH40caEtX9iVOTfpJ0Jh5U7YIWqO5djYaqDu8/JNQvikCJFHO3+cTInzw7lL7XyRPltKxmXabLEtUDa3UqHNF+rTZweZwy5wH2x2C7piK75iABX2yG2Cdqkcs1XvEtUfo/WDsWp9pNZE16xa6t5Hqu3eugXnDX2sanCz3jtVZfXWmsI1/pG6vshl+8LVb/ZXhGHp7fOJO8rRRs34PcnqEblqXN4yrVCONSmtCqW1+bWlQTv+4OVUo3JSrpq82zLb3DoqfzHR8MGjI5x+y5BDNUypTZTW4FEbPR1Gqt3k1hjcatLdQbo0Umj26kiP2uTpID3tZkoj2eBuXVgx/wToAFQSlughegAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 0&apos; title=&apos;&apos; src=&apos;/static/41dba41421da18e5e01deec22af9d10d/503dd/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_0.png&apos; srcset=&apos;/static/41dba41421da18e5e01deec22af9d10d/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_0.png 190w,
/static/41dba41421da18e5e01deec22af9d10d/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_0.png 380w,
/static/41dba41421da18e5e01deec22af9d10d/503dd/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_0.png 571w&apos; sizes=&apos;(max-width: 571px) 100vw, 571px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 1 최근 릴리즈 빌드 내역&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이렇게 매일 빌드하고 릴리즈를 하다 보니 해킹툴 만큼이나 버그와의 전쟁을 치러야 하는 처지가 돼 버렸고, 가장 큰 고민 중에 하나가 ‘어떻게 하면 버그 없는 소프트웨어를 개발할 수 있을까?’ 라는 다소 원초적인 문제가 돼 버렸다. 다행스럽게도 이런 문제를 고민했던 수많은 책들이 있었고, 먼저 고민한 선배들은 다양한 실천적인 해법을 제시해 주었다. 그런 다양한 조언과 실천적인 해법을 여기다 조금 옮겨보면 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;똑똑한 프로그래머를 뽑아서 애초에 버그가 없는 코드를 만들도록 해야 한다.&lt;/li&gt;
&lt;li&gt;모니터 한 대를 두고 두 명의 프로그래머가 같이 개발을 한다.&lt;/li&gt;
&lt;li&gt;전문 프로그래머 한 명에게 적어도 한 명 이상의 테스트 프로그래머를 배정해서 전문 프로그래머가 작성한 코드를 집중적으로 테스트 하도록 만들어야 한다.&lt;/li&gt;
&lt;li&gt;코드 리뷰를 철저하게 수행해서 리뷰를 통과하지 않은 코드는 애초에 커밋조차 할 수 없도록 만들어야 한다.&lt;/li&gt;
&lt;li&gt;코드를 작성하기 전에 먼저 테스트 프로그램부터 만들어야 한다.&lt;/li&gt;
&lt;li&gt;컴파일러 경고 레벨을 올리고 정적 분석기를 확실하게 활용해서 그 어떤 경고도 용납하지 않아야 한다.&lt;/li&gt;
&lt;li&gt;코드 커버리지를 철처하게 측정해서 릴리즈 코드는 적어도 일정 수준 이상의 커버리지를 확보하도록 매 순간 확인해야 한다.&lt;/li&gt;
&lt;li&gt;버그가 없도록 만드는 훌륭한 컨벤션을 만들고 모두가 그 방식을 따르도록 강요한다.&lt;/li&gt;
&lt;li&gt;전문 테스터를 고용해서 매 순간 테스터들이 무작위적으로 제품을 테스트할 수 있도록 한다.&lt;/li&gt;
&lt;li&gt;구조화된 체크 리스트를 만들고 제품 릴리즈 시에는 해당 리스트를 모두 만족 시키는지 빼먹지 않고 테스트 하도록 한다.&lt;/li&gt;
&lt;li&gt;같은 제품을 개발하는 프로그램 팀 회식을 매주 한 번씩 한다.&lt;/li&gt;
&lt;li&gt;약수 물을 떠놓고 산신령께 빈다. 우리 제품에 버그가 없기를.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;버그 없는 개발을 위한 이런 수많은 방법들 중에서도 단위 테스트, 코드 커버리지, 정적 분석기와 같은 것들은 투입 대비 효과가 굉장히 높은 편에 속하는 방법들이다. 왜냐하면 이것들을 수행하는 데에는 추가적인 리소스가 많이 필요하지 않기 때문이다. 프로그래머가 조금만 신경 쓴다면 이런 방법을 이용해서 손쉽게 많은 수의 버그를 줄일 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 이런 방법의 중요성을 충분히 깨닫고도 그것들을 충분히 활용하는 데에는 늘 주저했다. 왜일까? 우리가 사용하는 도구가 단위 테스트나 코드 커버리지 측정을 편하게 실행할 수 있도록 만들어주지 않았기 때문이다. 단위 테스트를 한 번 수행하기 위해서는 별도로 복잡한 과정을 거쳐야 하고, 코드 커버리지나 프로파일링 데이터라도 측정할라치면 무슨 화성에 로보트를 보내는 것과 같은 복잡한 과정을 거쳐야 했다. 효과는 있지만 충분히 쉽지 않았던 것이다. 하지만 이번에 출시된 Visual Studio 2012는 다르다. 이 모든 것들을 새롭게 추가된 Test Explorer를 통해서 손쉽게 수행할 수 있도록 만들었다. 클릭 한번으로 단위테스트를 수행할 수 있고, 클릭 한 번으로 코드 커버리지를 실시간으로 확인할 수 있도록 만든 것이다. 물론 결과 데이터도 번잡하지 않다. 우리가 확인하고 싶은 것만 빠르게 확인할 수 있도록 만들어 준다. ‘진화’라는 단어가 전혀 어색하지 않을 만큼 엄청난 이 기능을 사용해서 어떻게 버그 없는 소프트웨어 개발을 할 수 있는지 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;단위 테스트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;최근에 나는 리포팅 클래스에 캐시를 하나 더 추가할 일이 있었다. 이 과정에서 조건문을 잘못 추가하는 사소한 실수 때문에 치명적인 버그를 만들어낸 경험이 있다. 이 클래스를 가지고 단위 테스트와 코드 커버리지를 측정하는 방법을 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;내가 만들어야 했던 클래스 명세를 해보면 다음과 같다. 나는 이 클래스를 &amp;#x3C;리스트 3&gt;과 &amp;#x3C;리스트 4&gt;에 나온 것과 같이 만들었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notifier 클래스는 전달된 메시지를 화면에 출력하는 기능을 한다.&lt;/li&gt;
&lt;li&gt;메시지는 악성(CODE_BLACK), 의심(CODE_SUSPICIOUS), 기타(CODE_EXTRA)로 구분된다.&lt;/li&gt;
&lt;li&gt;Notifier 클래스는 각각의 메시지를 필터링해서 이미 출력한 메시지는 두 번 출력하지 않도록 한다.&lt;/li&gt;
&lt;li&gt;필터링은 악성 메시지와 나머지 메시지를 구분해서 한다. 즉, 의심으로 이미 추가된 메시지가 기타나 의심으로 보고된다면 출력하지 않지만 악성으로 보고되면 출력한다는 의미다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 notifier.hpp 소스 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifndef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;NOTIFIER_HPP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;NOTIFIER_HPP&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;set&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;string&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Notifier&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotifyCode&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        CODE_BLACK &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CODE_SUSPICOUS
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CODE_EXTRA
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;set StrSet&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;set&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;iterator StrSit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

 StrSet b\_cache\_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 StrSet s\_cache\_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

 BOOL &lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NotifyCode code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 BOOL &lt;span class=&quot;token function&quot;&gt;IsCacheItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;StrSet &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 notifier.cpp 소스 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdafx.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;notifier.hpp&quot;&lt;/span&gt;&lt;/span&gt;

BOOL
&lt;span class=&quot;token class-name&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsCacheItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;StrSet &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    StrSit it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

BOOL
&lt;span class=&quot;token class-name&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NotifyCode code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; CODE_BLACK &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IsCacheItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b_cache_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsCacheItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s_cache_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d %ws\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그럼 이제 프로젝트 구성을 해보도록 하자. Visual Studio 2012에서 utest라는 콘솔 프로젝트를 솔루션 구조로 생성한다. 프로젝트를 생성했으면 이 솔루션에 utest-test라는 네이티브 단위 테스트 프로젝트를 추가하자. 이 프로젝트 타입은 &amp;#x3C;화면 2&gt;에 나타난 것과 같이 Test 탭에 포함돼 있다. 프로젝트 생성이 끝나면 utest 프로젝트에 notifier.hpp와 notifier.cpp를 추가한다. 각각의 소스 코드는 &amp;#x3C;리스트 4&gt;와 &amp;#x3C;리스트 6&gt;에 나와 있는 코드대로 입력하도록 하자. 끝으로 notifier.cpp의 설정 항목에 들어가서 미리 컴파일된 헤더를 사용하지 않도록 만들어준다. 여기까지 모든 과정을 정상적으로 수행했다면 &amp;#x3C;화면 3&gt;에 나타난 것과 같은 솔루션 구조를 가지게 되고 탐색기에서 해당 솔루션 폴더를 찾아가보면 &amp;#x3C;화면 4&gt;에 나타난 것과 같이 디렉터리 구조가 생성된 것을 살펴볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/878b4f60c29a92b2fe3fe1b3033f729b/78d47/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABvUlEQVR42mWSC2+bMBSF+f//Z+q2bonSKFOVgHjkCYQY29iGAMbGhqRJJ82Ualo76+j6SubzuT7CmjxOnaXrroLnp+Xs+3z6df7jy3Ty8OQsfHvhL34un2fO2g63brxz49WvbeCEWy/c2+5mNreWy8DzI5AWEJUQV4xxlEIpRNtKpVqtlZDN7fbS9z2l+SlFZd1wLqTuMTlbxxgAgIuirqqmriXC7NvDxHZ2K3tjdIiQF0SeHycJjqNjhqkRIXmRlxmi1imBEOI8L4VQTdPWdQMAwllOSDFUWhJ6JuRcVULK4YNRUmqCcwsCEkagKCpzxrlsW32/382cRsP2ch17rTvO38mGD3CGmJXE6X4fQZiNzqZ2H1Y/VnPpX9vReYDD/XG3CwN/Y14ihDZw/9+6XHql/oHfnHFKjTPIMsbYua6FIaVo+777JAMbZxPnR5hYSZTWJvpWl5XIi1q0ZsbrJ+mu16oz/Pi0cWwMqZUmQEphQqqFQsyEqivRlaIz9cxVyZVp1PU355xSopQaMrxebq+3sqis3XpPMsJoTgnLUIZSBAGEKTSN+VvGhlEGTiA+hMERPW6xfQBrz3Md/w8LmlWuVj5NQgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 1&apos; title=&apos;&apos; src=&apos;/static/878b4f60c29a92b2fe3fe1b3033f729b/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_1.png&apos; srcset=&apos;/static/878b4f60c29a92b2fe3fe1b3033f729b/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_1.png 190w,
/static/878b4f60c29a92b2fe3fe1b3033f729b/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_1.png 380w,
/static/878b4f60c29a92b2fe3fe1b3033f729b/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_1.png 760w,
/static/878b4f60c29a92b2fe3fe1b3033f729b/78d47/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_1.png 800w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 2 네이티브 단위 테스트 프로젝트 선택 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3189bf6dc7a762fdd944d642c187149e/c84e4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 63.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABzElEQVR42nVS626bMBjltVPtvnfZCyxTmj3CfnQ/qk5aA8TYgA02NuArJkBN027Skh0dS8effPxd7AgABGGRJBmEJUIFxvWZlDa0Zquo6o7RjjFaU8YapTTnoq4YYzzKYAFh/ng4QkTyHP8+JClAKMcwx4x3hNT3x+rLD7R/qADCKCcQlSWmhPKyrKMgy7LCmHAmIKkeYpoCBiFtOiOU67UrWntXqF9ECWU7PaxBOza9idM8Oh5BTeumaZx1pcBpYXjZGy6WeXllWM+Yg5zPW2sdpTw6Zlmappxza1zJcUZ6ZaZpnpZXnM//ueEM5wZKRQQACGYppXNr5t7qTlrCxeD98n+8mJMY/ry7D+MhRGRVbkajpKvCVI0Zp8mfptO84pqZRznM4zgRQmhlscBCa1J70ba9Nsp56bwL/mm+nvnxEEMIueDOWtISPsiKC0wqPXjjnLRDaOeybO/HpukihFCSpEqpddoc15001usAN9jBS+v8teZfzEVeHuKUt602rmqbkPDvGz0zlPwPQ9D5MfyEaJmHeZDzqJfZnpy6nM1VTOM4GRndfEs322SzjTdf45tt/HYHLvlxn73bgc/fs/e34NM+e7MDQXy4BU8hTtQTAM4yowAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 2&apos; title=&apos;&apos; src=&apos;/static/3189bf6dc7a762fdd944d642c187149e/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_2.png&apos; srcset=&apos;/static/3189bf6dc7a762fdd944d642c187149e/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_2.png 190w,
/static/3189bf6dc7a762fdd944d642c187149e/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_2.png 380w,
/static/3189bf6dc7a762fdd944d642c187149e/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_2.png 760w,
/static/3189bf6dc7a762fdd944d642c187149e/c84e4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_2.png 1037w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 3 utest와 utest-test 프로젝트가 추가된 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/27d146566e21ae6f703c50a0bbcb3f7f/f843c/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 54.736842105263165%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB50lEQVR42lVRa2/aMBTN//8n01Rt6iY2VvpCUKDtymOgEiBZEuK87PhFQh4OyS4K/bCjo6urYx8fX1v72X2dDeej3uCpO376MXq47t99fbi56t1+uR91J5Obl+fey++7t2Fn3L8eDL4Pf33u3X7rjzv3z5+utMfJZrn6u91a84Wh6/v1u7NcmtPZVt84a93Z7lzLjpDHTAsbhm8YaLfzdoZvOvFshbQAob2HeZJjdnApNaNoF4YWITKrWKqwLFhSiqOSmYIaJ0VAk5ClPsuQh7UwCN51HYchY4xynhVFXp5ZVZWqqiTNhEyUqk6nU5YXparyvACxOtWSCy0KI3AJIUlMBXMPBwn7qg9IKSljQkql1AGQpLAKfd3UlFDNBjgOwQTM2F85tg05LWAfpTQMQ4xJWZacc8Z5XdetmRGm+T4x3SA7plxIRmwPoSzL23CoMEuEcRzHSpWCczjrVJ+TYZXFXENeYO5RnuUA5LqWaRVF8X9yRMg5WQoBt0iSFMwwDouZZlu+5/mCs+PxSEKM3PNBqixbgoHSmDNWFkVyOMTwC1JCn6YJxbGGAzfCyEFYJFnVNFXdqFMDM7U8K61Yn2vLEq7eNPC+2qjfmb4+vrzps/n6wsWlmX7wIrb6Qp//2SyW2/Fo+g/BUFjqAcsyxgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 3&apos; title=&apos;&apos; src=&apos;/static/27d146566e21ae6f703c50a0bbcb3f7f/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_3.png&apos; srcset=&apos;/static/27d146566e21ae6f703c50a0bbcb3f7f/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_3.png 190w,
/static/27d146566e21ae6f703c50a0bbcb3f7f/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_3.png 380w,
/static/27d146566e21ae6f703c50a0bbcb3f7f/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_3.png 760w,
/static/27d146566e21ae6f703c50a0bbcb3f7f/f843c/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_3.png 861w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 4 utest 솔루션 디렉터리 구조&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;프로젝트 구성이 끝났으면 utest-test 단위 테스트 프로젝트에서 utest 프로젝트를 참조할 수 있도록 디렉터리 설정을 변경해 주어야 한다. 아래 순서를 따라서 설정을 변경하도록 하자.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;utest-test 프로젝트 설정 화면에 들어간 다음 C++ 탭의 General 페이지에 있는 Additional Include Directories 항목에 “..\utest”를 추가한다. 이 설정은 단위 테스트 프로젝트에서 utest 프로젝트에 포함된 헤더 파일을 바로 추가할 수 있도록 만들어 주는 기능을 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Link 탭의 General 페이지에 Additional Library Directories 항목에 “..\utest$(Configuration)”을 추가한다. utest에서 빌드한 오브젝트를 참조할 수 있도록 해준다. 이 설정은 단위 테스트 프로젝트에서 utest 오브젝트 파일을 바로 포함할 수 있도록 만들어주는 기능을 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;끝으로 Link 탭의 Input 페이지에 Additional Dependency 부분에 notify.obj 항목을 추가한다. 이 설정은 단위 테스트 프로젝트에서 notifier.cpp의 컴파일된 코드를 사용할 수 있도록 만들어주는 기능을 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;여기까지 마쳤으면 utest-test 단위 테스트 프로젝트에 테스트를 추가할 모든 준비가 끝났다. &amp;#x3C;리스트 5&gt;에 나와 있는 것과 갈이 테스트 케이스를 추가해 보도록 하자. Assert::ArrEqual 함수는 n.Notify(Notifier::CODE_BLACK, L”BITEM”)의 실행 결과가 TRUE와 같은지 체크하는 기능을 한다. TRUE와 같으면 테스트가 성공하고, TRUE가 아닌 다른 값이 반환되면 테스트가 실패했음을 알려준다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 unittest1.cpp 소스 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdafx.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CppUnitTest.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Windows.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;notifier.hpp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; Microsoft&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;VisualStudio&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CppUnitTestFramework&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; utesttest
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;       
    &lt;span class=&quot;token function&quot;&gt;TEST_CLASS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NotifyTester&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        
        &lt;span class=&quot;token function&quot;&gt;TEST_METHOD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;BlackNotifyTest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Notifier n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_BLACK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;BITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;코드 추가가 끝났으면 각 프로젝트를 빌드하고 Visual Studio 2012 메뉴에서 Test, Window, Test Explorer 항목을 선택한다. 그러면 &amp;#x3C;화면 5&gt;에 나타난 것과 같이 테스트 익스플로러가 화면에 표시된다. 우리가 앞으로 진행할 단위 테스트와 코드 커버리지는 모두 이 창을 통해서 손쉽게 제어할 수 있다. BlackNotifyTest를 수행하기 위해서는 해당 테스트 이름에서 오른쪽을 클릭한 다음 메뉴에서 “Run Selected Tests” 항목을 선택하면 된다. 그러면 Visual Studio가 알아서 테스트를 진행한 다음 결과를 우리에게 알려준다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 224px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5f178f45f823a7fb636afac6d7d6d4b0/773ea/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 137.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAIAAADuuAg3AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEq0lEQVR42n2US48UVRSAi4ULly58JkRNxJjgwp0aYmJk6UbDQhf8DsXEjYbHQmBAE1AgMWxUiAaJIMM4PcPAdE/39Lu6a/pR09VdXe/Xrep636qeLk91wQCinny5Offcc869de65RTx3tPHs0caLxxovHW+8cKwJ+lNfVIjPynuOlPd8/ghHymB8+svqM1/V3zpL7T3RfP5og3jn/Nb7F7sHfuh+/NPo4KXewUvd/WeofafbbyxQ+0619p0k73OKfO0k+fopcv9C670L3QMX+m+f7xDrFLfZE8kuvZIvD0WdUy1JMwBB1ZHjOUFk+zjDCeZjGEvGpNrqKKZN0EN5o1SnyNatGzeQZvi2ZyEkC6ImKzgIkp1ZMt3ZZRZPkyQxdUPk+BhjompX614jr65vmqWiXiho+ZJR3ETFslna0At5NQ/GDS1fgDFdzRw2yla5oJeI3PrKL9eubMlqV5JoRenJyraidCWZ5MWBqgx1tSPJjKZuq2pfUUaGBpa2IG/xHCsNiVqlurqcoyW7PkQ1BlFjq7xtMJINY21ojmS7ROs1xmixZm2AKgMD7Ju0QfMGHJ6w/VB3sO24iulaE8sykWq5E8fDge86kzAMIhxEYRDjFBze1yMcghC8aq1tydTYKNIaw0ljXtqgtSqc2LAURfF83/V8798AIaI0iQ8pZ7NZFE9t14vjeLqz4wWh6wWO5/8PRJMkqRa1mS8U11crhbVeu35v9XZ5467AbnNMN9kJkshP4ieY+rPYJ3zHyW8L3yy1Ttzgvv6D/+7u5PifwrGb4rd3zNMrxvel6EkubkbnitGPFUwkcXKVXPrw57Of/JYcvjb79Nfk8O+gJB9dSQ5dTT64nOxdSF49k7wy5+WF5M1zybuXkoOXk0NXZgS0UV+Z/NU3lvt4bRDmaJyjw1U6zPVTZWUbL3bx7d5jLKc++B6DCdf1Qt+fBv40dOMgZRp6KZkeuDvhP5mmPukq4Tiu7Tg+xhPHt13f8UO4ZGQ5rh+6qe7/F+BMsCx7/fr1Qj6/dHsxt7y8uHhrZSVXKhbv3FmtVioBiP+YwHwXwrZtURQFQVBVVdd1TdNkWUaGbhraBOkxDqEF4ijts6zDwkeSEWnuMAhwMBwOR6MRwzCSJMqmR45RfYTarNHlEdDjUWOo06IJumm7WQrC87wYx4AkSSw7BlFVRbF8RrF7gsXq7kh1OqLNag6ne4LhQl5o2Gx7Yoqna4O1wrBgaiacXJ6LqshI1yamIXCsoSmKJCBNlQRe5DlFllwo8Dw8Db7ZublELyEVVWvVwWBAkmStVqNpGnKVSqVGEzqYbLfbYOx0OjAahgFPan5sPz12FEa8wGcFy/YHxbIsx3EQQmAH13AuURQ9LJifPjroFLfVasE+lUoF9qEoqtlsQvHgVUIhYQniobLeXB4Gew8EY5wl3hWYpleR7ZZG+hC3SxoMa3gumV8mWeJsCUZIDXcTZX+SB/+TNJjjBEAQRLgnIJtqGmJZDhiNxqIo6chi5AmvTYayNVZBsQXdRpZNMMyIojq9Hj0YjOp1+Nput9tTFJ3jxFaLarc7na2+ppljDa4ddXizPNApDvVFyzAmfwMD8K/Q8OdiYAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 4&apos; title=&apos;&apos; src=&apos;/static/5f178f45f823a7fb636afac6d7d6d4b0/773ea/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_4.png&apos; srcset=&apos;/static/5f178f45f823a7fb636afac6d7d6d4b0/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_4.png 190w,
/static/5f178f45f823a7fb636afac6d7d6d4b0/773ea/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_4.png 224w&apos; sizes=&apos;(max-width: 224px) 100vw, 224px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 5 Test Explorer 창&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;코드 커버리지&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;코드 커버리지는 테스트를 통해서 코드의 얼마나 많은 부분이 실행되었는지를 나타내는 값이다. 코드 커버리지가 100%라는 의미는 코드의 모든 부분이 테스트를 통해서 실행됐다는 이야기를 나타낸다. 그러면 앞서 우리가 만든 BlackNotifyTest 코드는 Notifier 클래스를 얼만큼 테스트 하는지 측정해 보도록 하자. Test Explorer에서 BlackNotifyTest에 오른쪽 버튼을 누른 다음 표시되는 메뉴에서 “Analyze Code Coverage for Selected Tests” 항목을 선택하면 된다. 그러면 단위 테스트를 수행하는 것과 똑같이 테스트가 진행되고 &amp;#x3C;화면 6&gt;에 나타난 것과 같이 코드 커버리지 측정 결과가 나타난다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 707px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_5.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b15deed96d511f4758f90087785e37e7/e9ffe/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 30.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABR0lEQVR42i2OW2vCMBiG+1c3GHOgwmC4PzS01c3JThcD2cXmWVcZbGrVpLVamyZt0jTxMB0sO8DHx8PDe/FouTuYu52eVUbZsnVcGqVKo5NLK1WyjvSPg8Lg8OI9W55kKjB9DTKV/0tX4OkNPL+3NX8G8XIuaCgoERRLSpIIU7QMXAd5nu/YCUGcBBvOeBjEGImIxNhngb/iTCMz6I7HNhi79iQOEY+Q+lvJdisuGbEnQ8GI4pj4PAr26wTN7RmwlNkIqhXNdb6Jr2pWvr4otKNijxVa2DCFYUq9y/IN33jlP9yhei82+iu9TXQ16Eujx7XmNOnYwrRwtQcf2qA2imoDrGQTCMWPXVi3WAvI5wF+GUZtKJ/evGrfbQHRmMSaCkhogBbzwHO3ku7WyV+nKlzF4cIBW8H2v3Kd0K+NCNHCc4AafMr4G+FVMJSEJGirAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 5&apos; title=&apos;&apos; src=&apos;/static/b15deed96d511f4758f90087785e37e7/e9ffe/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_5.png&apos; srcset=&apos;/static/b15deed96d511f4758f90087785e37e7/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_5.png 190w,
/static/b15deed96d511f4758f90087785e37e7/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_5.png 380w,
/static/b15deed96d511f4758f90087785e37e7/e9ffe/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_5.png 707w&apos; sizes=&apos;(max-width: 707px) 100vw, 707px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 6 코드 커버리지 결과 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;화면 6&gt;의 측정 결과를 살펴보면 우리가 작성한 테스트는 Notifier 클래스의 87.5%를 실행하고 있음을 알 수 있다. 세부적으로는 IsCacheItem 함수를 90%, Notify 함수를 83.33% 커버한다. 여기서 중요한 것은 어떤 부분이 테스트 되지 않았는지 살펴보는 것이다. IsCacheItem 함수 이름이 있는 줄을 더블 클릭하면 &amp;#x3C;화면 7&gt;에 나타난 것과 갈이 실제 코드에서 테스트가 진행된 부분과 진행되지 않은 부분을 명확하게 나누어서 표시해준다. 붉은색으로 표시된 부분이 BlackNotifyTest를 통해서 테스트되지 않은 부분이다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_6.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/68bb7709295fcf64b86b5010a5c4c698/c84e4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 63.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB5klEQVR42o1R227UMBTMb7dAW34GiWeKdvsDPPQRVFh1N4nj2I7jaxLHXjtOsni5iFJRidHo6EjWnBmfkwFQQ4jzvIKQ1Ag3DaMNS5VzyZiglCW2LeeMD0rYXtvRKqlZK4RQWQUxhOhxX0BEYY0fD3lZIVA3EDVC9ZgwhFkyKLF8f1+/+1TsS9RQTpkihGWENIS0TUPTPEDI11yx1mgm9eA6G3obtPFUdBVV96W8L0XbjcZHOdhDgbKyBIwzKaU/+kY3UPfpcZDCWOenmDjP8+kp1nM5Hj3nKgNVVRSFUuroPFG06jQUtsCSaxPnZV5+Yn3K32KdgRIksTHmhzNlvSZE1khMcTm9DO/DWSwYz/eHfuhjCCm2kNi1bRzdef76Cy+IVVbk1cPDjrZcqQFyhE1n/aSN7ZwfrEuLMaML0/xsRAiTEDr7/OXbbrdPBxa8qwXhDPN0JYB0Z/rRDWNaRUhre2YfY1SqzzBCoCydc1MItG8ZhTTP8S7Xqh/9lDz/+edpilL2GUJkv8+l7pz1SDVIS4hU26YDz9bHZV3n9bT8zRQiZeFJfFrDGswax9Oa8ul5mU7/gSXGxZns8mNxcZtf3h4uPhxe3ebX2+pqC94kbv7w5q662oC3d9X19lxfb0BqbrbgO36O0H6L4LtdAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 6&apos; title=&apos;&apos; src=&apos;/static/68bb7709295fcf64b86b5010a5c4c698/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_6.png&apos; srcset=&apos;/static/68bb7709295fcf64b86b5010a5c4c698/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_6.png 190w,
/static/68bb7709295fcf64b86b5010a5c4c698/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_6.png 380w,
/static/68bb7709295fcf64b86b5010a5c4c698/efd7b/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_6.png 760w,
/static/68bb7709295fcf64b86b5010a5c4c698/c84e4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_6.png 1037w&apos; sizes=&apos;(max-width: 760px) 100vw, 760px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 7 코드 커버리지 테스트 결과 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이제 코드의 어떤 부분들이 테스트를 통해서 실행되지 않았는지 알 수 있으니 그 부분들을 실행할 수 있는 테스트 케이스를 추가하도록 해보자. &amp;#x3C;리스트 6&gt;에는 테스트되지 않은 부분을 모두 실행할 수 있도록 만들어진 테스트 케이스가 나와 있다. 이 테스트 케이스를 추가한 후에 빌드하고 다시 코드 커버리지를 측정해보면 &amp;#x3C;화면 8&gt;에 나타난 것과 같이 코드 커버리지가 100%로 출력되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 BlackNotifyTest, SuspNotifyTest 테스트 케이스 소스 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;TEST_METHOD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;BlackNotifyTest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Notifier n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_BLACK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;BITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_BLACK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;BITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;TEST_METHOD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SuspNotifyTest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Notifier n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_SUSPICOUS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;SITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_SUSPICOUS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;SITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 707px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_7.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/23e1e5bd2c77aade3e4ea562fe630b1d/e9ffe/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_7.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 30.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABQ0lEQVR42j2QW0/CQBCF+2ONECMmJgb/EaUQkHh7MJqYKFqKtSZesBfaAq3tdtvudi8FCjGuPphMTs58Mw8zR2qee82z6dHAPOhbta5Z75p7PbvetXbkj11lUpPfG32nMfD2T9zG4L+8w1P/+MKX4rkHo4ChjKGU5ZALRSkCEVjMsjjMAp+mgKRgRRBJkwICMcVJjJOoJFhK597Ctn3XXvhOkQGSA6FrjrclYQh6zueSoqosMIwF3y4pCHzHfFsxtGZY6hjLlgp7Q6v1EMpa3tGxrEHFYIrB209YVoFi0F8/Rm2dKC+lPIJ/kCs6ldQpHfvMsOCN7l1q7tDM7yeJgKrLhL9+nj06ZOSyu0kqWs3jt6/Rle6LBcGlTUkoSkAYJF+LNUebJRXXCiguLIssnE0rXghPRRw4/V5zEYR4sCpJxYsf8LowiKw6FTYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 7&apos; title=&apos;&apos; src=&apos;/static/23e1e5bd2c77aade3e4ea562fe630b1d/e9ffe/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_7.png&apos; srcset=&apos;/static/23e1e5bd2c77aade3e4ea562fe630b1d/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_7.png 190w,
/static/23e1e5bd2c77aade3e4ea562fe630b1d/2edd7/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_7.png 380w,
/static/23e1e5bd2c77aade3e4ea562fe630b1d/e9ffe/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_7.png 707w&apos; sizes=&apos;(max-width: 707px) 100vw, 707px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 8 수정된 테스트 케이스 커버리지 측정 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이제 코드 커버리지 100%를 충족시켰으니 과연 완벽한 테스트 케이스이고 우리가 만든 Notifier 클래스가 우리의 의도를 100% 만족한다고 자신할 수 있을까? 안타깝게도 아니다. 코드 커버리지의 함정은 이 수치가 우리가 만든 테스트가 실제 코드의 어떤 부분을 실행했는지를 나타내는 기계적인 값이란 점에 있다. 즉 이것은 신택스만(syntax) 확인할 수 있을 뿐이지 시맨틱(semantic)은 검증할 수 없다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;앞서 Notifier 클래스 코드 명세에서 이 클래스가 가지고 있는 두 개의 캐시는 독립적으로 동작해야 한다고 했었다. 그렇다면 명세대로 과연 각각의 캐시가 독립적으로 동작하는지 살펴보도록 하자. &amp;#x3C;리스트 7&gt;에는 캐시의 독립성을 검증할 수 있는 테스트 케이스가 나와 있다. 이 테스트를 추가한 다음 Test Explorer를 통해서 테스트를 진행해보면 &amp;#x3C;화면 9&gt;에 나타난 것과 같이 테스트가 실패하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 SBTest 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;TEST_METHOD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SBTest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Notifier n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_SUSPICOUS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;ITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AreEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Notifier&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;CODE_BLACK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;ITEM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 242px; margin-bottom: 16px;&apos; data-url=&apos;./비주얼_스튜디오_2012_테스트_익스플로러_활용.md_8.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b776230100cabede16b4b0204ce9d7c4/9ccb4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_8.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 169.4736842105263%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAIAAADQyG7qAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFK0lEQVR42n1VSY8bVRDuA0ck4EI4ceDfZIYggRCcwiI2AQckhBAXRCSChDhwQZG4IBKSiSCJFE0SkSFjjzPjzOKxPXa8u/e2e19e76+7vVLtnkSzIEpfl17Xe/WqXn3Vr4nnvjs4c/Hxme/rL16sv/TD4+cv1Iiv9omvM5RP4Jlvys9+W33lp8bLPz5+4cIB8fpV8vxfzLs32E9u8+/dZN6+Ti1dpl79g16+Qp79vQ9YupzicLx4ff8me/4G8+Z1mqhSco1RDur10kHdsH0fR8i2LBsFYTg/JbNZqr0Qd0gySkaE2Or3S9XGw81avoAozmV5o0/qvb7NcliUTiOWZZthYU0syYR29675931voxBvbnq53AJ5N5/3c3lnfR3wxJjz1nN+Lmc/AEs+2NhQVu8Q99bXr9y4VdOivaFfU/G+FLb0qCKHO0OfsuM9MThQcV3DVSVs6LiihEXB75gxg0JGFAlZknRVtUxrqBiqagwkXVZN07RkxTANS9VMeNV0U1KMoWzIqqGkFsOyEKwmRNPbpzRyaNQ4UxEFWjRKlKZaLjLV0PdGMR7F4ShaIA6fjmMchiEmYozlcCSEE8PGppvCcELHx16A/TA6Ci+IkHcImA2CkEhmU3pj59LP/3x6f/753ckHq9NzK9Olq9Pla7OlIzh7dXZuZfbxndmHq7O3bs5/3fYHLE9M53Pq4f6lXwpfFOZfPph9dm/yxq35a3/OllemyytHnK/NXl1JPT9anb1ze/5bCRuKSnTb7YMeVax1io92H+3tV+uN4tYWQ1M0RdkIJXEcRzhDFMFBsA8J49i07D7JEa7rGabK8RRN9ocCr6syTZOyJCqS6HvuU89D4DAKgyQOkYV6fZYYJSPDMxRXAbaAHBVosyxd142F4OPieR5CCOyaZqSR4yg2XENBio0gTSul2DrUjuOccPZ9H4ye5xqGRVICAWfRbF22ZNMwJUmCyIoCSgNAhPC4uK67iAyZmRwnEsD1eDwZJWPQcZxgqEsUgREGACDzBLKphcYE7LS5udloNLrdrqLIUN1sPtP/L1BtFzwpiiJJEjaCBICSURyNkmicREmc6vT1CY45Q5LTyQRskpwKz/PIcVnVbQ9RR0Sc6jCqw2lgSQekbB/1JtL8xpMgjgeCwHHcYCBYjkepHqU4pOLJKGwO7b5k07JDK87AcI9FxpOpv5V3KyXNdoAiqKMsSw4yHWQNeFaRxcBzxkkMpxglp9IGZy+/FlR2B5pOQZMNh81Wi+cFwzAZlu2kVVTg5gIiwlM1TNOOJhMf493dXWohLMsKgtBut3u9HpSgXq9XKhWwQC1PuBMZoZ7rFovFnZ2dQqGwtrbWbDb39va2t7eBCDBubW21Wi1ou5NU4UVbQNNWq1VwgEWgISYwNxgMyuUy2Gu1GmxXKpWgC046Z00LiQFVcMJMQ+UyDQJbxws5GRmOkSQJBIdQrXYbQDMMgKQonuOBPKgCfGNRFJ/uOQL2g8MwDAPrYC3cARzLSqIIO8LUKIkn4zFcCNF/tmfmnKVK0iw/lLokQ3MD1w88P7TdQLd9GNtw5Z12hmQgZ6BxPEoUG5dZtM+gKm/vkvoOqVdYs9DRyoy53dddf/HBHD5PImcZPhXYKwhxNk7SufTzgLRBZePsPgMQUAxJgpQ1WVYB6R2gm6qSXgaSJGvws0Au/Bg05MtWqhXLtxy4T6AzfEIQxGaz3e2S/T5drzeBYJrmRVGjaQ5eO52+qlus5vZEuz2067zVHKCB7iL4pSDvXxsGAJnwNMJCAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         2012              md 8&apos; title=&apos;&apos; src=&apos;/static/b776230100cabede16b4b0204ce9d7c4/9ccb4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_8.png&apos; srcset=&apos;/static/b776230100cabede16b4b0204ce9d7c4/08678/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_8.png 190w,
/static/b776230100cabede16b4b0204ce9d7c4/9ccb4/%EB%B9%84%EC%A3%BC%EC%96%BC_%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4_2012_%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EB%9F%AC_%ED%99%9C%EC%9A%A9.md_8.png 242w&apos; sizes=&apos;(max-width: 242px) 100vw, 242px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 9 SBTest 실패 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;문제는 if문장에 숨어 있었다. CODE_BLACK 아이템에 대해서는 else if 줄이 검사되지 않아야 한다. 하지만 &amp;#x3C;리스트 4&gt;에 나타난 코드의 else if 구문에는 ‘code != CODE_BLACK’과 같은 조건이 없었기 때문에 해당 else if 문이 검사되면서 이런 결과가 나타난 것이다. 이런 문제를 미연에 방지하기 위해서는 &amp;#x3C;리스트 8&gt;에 나타난 것과 같이 코드를 명확하게 분리해서 작성하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 수정된 Notify 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL
&lt;span class=&quot;token class-name&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NotifyCode code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCWSTR msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CODE_BLACK&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsCacheItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b_cache_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsCacheItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s_cache_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d %ws\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서도 살펴보았던 것과 같이 코드 커버리지는 보조적인 지표 역할을 해줄 뿐 커버리지가 높다고 테스트 품질이 높다는 것을 의미하지는 않는다. 따라서 테스트 케이스는 명세를 바탕으로 꼼꼼하게 먼저 작성하는 습관을 들이는 것이 중요하다. 코드 커버리지는 작성한 테스트를 통해서 어떤 부분이 실행되지 않는지를 확인하고 추가적으로 어떤 테스트 케이스를 만들어야 하는지를 참고하는 지표 정도로 활용하는 것이 좋겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[포맷 스트링이 부릅니다. 헬게이트~]]></title><description><![CDATA[게임 보안을 하면 참 다양한 이슈를 겪는다. 그 이슈들도 크게 몇 가지 종류로 나뉘는데 종류별로 심각성을 살펴보면 다음과 같다. 서버 크래시 >>>>> 78.2차원문 >>>> 넘사벽 >>> 블랙홀 >> BSOD…]]></description><link>https://jiniya.net/wp/archives/9059</link><guid isPermaLink="false">https://jiniya.net/wp/archives/9059</guid><pubDate>Thu, 11 Oct 2012 23:58:27 GMT</pubDate><content:encoded>&lt;p&gt;게임 보안을 하면 참 다양한 이슈를 겪는다.&lt;/p&gt;
&lt;p&gt;그 이슈들도 크게 몇 가지 종류로 나뉘는데 종류별로 심각성을 살펴보면 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;서버 크래시&lt;/strong&gt; &gt;&gt;&gt;&gt;&gt; 78.2차원문 &gt;&gt;&gt;&gt; 넘사벽 &gt;&gt;&gt; 블랙홀 &gt;&gt; &lt;strong&gt;BSOD&lt;/strong&gt; &gt; 미로 &gt; &lt;strong&gt;클라이언트 크래시&lt;/strong&gt; &gt;= &lt;strong&gt;충돌&lt;/strong&gt; &gt; (퇴근 가능 영역) &lt;strong&gt;오진&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그렇다. 다른 모든 것을 떠나서 서버 크래시는 재앙이다. 대재앙이다. 클라이언트에서 발생한 몇 년 동안의 이슈를 모두 합쳐도 서버 이슈 한 건 보다 못하다고 할만큼 서버 이슈는 심각하다. 서버 이슈는 크리티컬 하고 엄청나며 어렵고, 애매하고, 난감한 그야말로 안드로메다급 문제라고 할 수 있다. 이런 어려움에도 불구하고 고품격 보안 기능을 제공하기 위해서는 복잡하고 난해한 서버 코드를 추가할 수 밖에 읍다. 흙~&lt;/p&gt;
&lt;p&gt;썰이 너무 장황했다. 맞다. 서버가 다운됐다. 큭~ 그 오랜기간 문제없이 동작하던 서버가 다운됐다. 다운됐다. 다운됐다. (에코 메아리)~~&lt;/p&gt;
&lt;p&gt;서버 이슈가 어려운건 한 가지 밖에 없다. 재현이 쉽지 않고 동작하는 서버를 우리가 라이브 단계에서 어떻게 할 수 없다는 점이다. 즉, 서버 문제는 모두가 추측의 영역에서 이루어질 수 밖에 없다. 그나마 이런 어려운 문제를 돕기 위해서 대부분의 게임 서버 프로그램은 고품격 덤프 기능을 가지고 있다. 그런데 그런 고품격 덤프 기능들이 실상은 도움이 별반 되질 않는다. 왜냐하면 진짜 문제가 생겼을 때 제대로된 정보를 우리에게 주는 경우가 드물기 때문이다. 그래도 오늘은 운이 좋았다. 덤프는 없었으나 크래시 로그가 남았고 콜스택이 있었다. 부왘~ 천만다행. 거기다 심볼까지 아름답게 존재해 주시고, 콜스택 로그 또한 아름답게 착착 맞아떨어졌다.&lt;/p&gt;
&lt;p&gt;이쯤되면 뭔가 사소한 버그겠구나 라고 생각할 법 한데, 여기에 반전은 그 콜스택이 가르키는 지점은 다름아닌 StringCchVPrintfW 라는 점, 그리고 그 안의 _woutput_l이라는 함수에서 발생 했다는 점. 그 넓디 넓은 서버 소스 코드 중에 StringCchVPrintfW라는 함수를 얼마나 많이 쓰겠냐는 말. 이쯤되면 해운대 바닷가에서 낚시바늘 찾기만큼 어려워져 버렸다고 생각하는 것이 당연한 진리~ 그런데 왠걸 ㅋㅋㅋ~ 희한하게도 소스 코드에 전부 StringCbVPrintfW를 썼는데 단 한 곳. 단 한 곳만 StringCchVPrintfW를 쓴 것이었다. 럭키가이라고 생각을 하는데. 그 함수가 엄청 많이 호출되는 로그 출력 함수라는 건 또 반전 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;중간 썰도 길었다. IDA로 파일을 열어서 번지를 보니 이렇다. _woutput_l이라는 이 망망대해 함수 속에 우리의 크래시 지점은 저 빨갛게 표시된 좁쌀만한 영역 ㅠㅜ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/10/woutput_l.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/10/woutput_l.png&quot; alt=&quot;&quot; title=&quot;_woutput_l&quot;&gt;&lt;/a&gt;
&lt;strong&gt;인간이 이렇게 긴 함수를 작성하는 것이 가능하단 말인가?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;외계인이 작성한 것이라고 밖에는 생각되지 않는 _woutput_l&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/10/woutput_l2.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/10/woutput_l2.png&quot; alt=&quot;&quot; title=&quot;_woutput_l2&quot;&gt;&lt;/a&gt;
&lt;strong&gt;여기서 난 과연 무엇을 깨달아야 하는가?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;_woutput_l이라는 거대한 함수 속에서 난 어떤 힌트도 찾을 수 없었다. 그저 함수가 굉장히 거대하다는 것 밖에는 느끼지 못했다. 이제는 그저 촉에 맞기는 수 밖에. 딱 떠오르는 첫번째 생각은 그랬다. 그래 %s 따위를 썼는데 뒤에 문자열 포이턴가 먼가 이상했던거야. 아마 종료 NULL이 없었겠지. 그래서 메모리를 계속 읽었겠지. 재수없게 그 종료 널 다음이 딱 커밋되지 않은 메모리 영역이었겠지. 하필 또 난 접근 위반 예외처리를 해놓지 않았지. 그러니까 당연히 크래시가 발생했겠지~ 라고 소설을 써봤다.&lt;/p&gt;
&lt;p&gt;가설을 검증하기 위해서 소설대로 샘플을 만들어서 해봤는데. 너.무.도. 당연하게 깔끔하게 종료됐다. 그 어떤 크래시도 없이 말이지. 그런데 그 샘플이 나를 구원했다. ㅋ~ 크래시가 안나서 _woutput_l 함수 내부로 들어가 볼 수 있었는데, 거기서 디스어셈블 창으로 전환하자 앞으로 내가 10년 더 Visual Studio를 써야 할 것 같은 화면이 출력됐다. 그렇다. 소스코드와 함께 디스어셈블 코드가 출력된 것이다. 장장 2370줄에 이르는 _woutput_l 코드를 에디터에 복사했다. 그리곤 IDA에서 보았던 8b 48 04를 검색했다. 이런 마법이!!! 딱 한 군데 밖에 나오질 않는 기적이 발생하는 것이 아닌가? 거기다 코드가 똑같다. 크래시난 지점과. 빙고~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;                if (pstr == NULL || pstr-&gt;Buffer == NULL) {
00B61D1E 85 C0            test        eax,eax 
00B61D20 74 3A            je          $LN97+224h (0B61D5Ch) 
00B61D22 8B 48 04         mov         ecx,dword ptr [eax+4] 
00B61D25 85 C9            test        ecx,ecx 
00B61D27 74 33            je          $LN97+224h (0B61D5Ch) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;역시 먼가 NULL과 관계된 문제였어. 코드는 나에게 말해주고 있었다. 그런데 진정한 힌트는 바로 그 위에 있었다. 아래와 같은 케이스 문이 있었던 것이다. Z. 그렇다 이 코드는 %Z 따위를 탔을 때 UNICODE_STRING의 Buffer가 NULL인지를 체크하는 코드였던 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 제대로 소설을 갈겨 보자면 이렇다. 포맷 스트링으로 %Z가 넘어왔는데 그놈이 가리키는 UNICODE_STRING 포인터는 있는데 그 안의 Buffer를 접근하려고 하니까 예외가 발생한 것이다. 이쯤되면 이제 내가 %Z를 쓴 곳만 찾으면 되지 않겠는가? 근데 사실 %Z는 드라이버 코드에서나 쓰지 유저 코드에서는 거짐 쓰지도 않는데 라고 하면서 로그 출력 함수를 호출하는 부분을 grep했다. 그리곤 %Z로 검색했는데 역시나 없다. 그래서 로그 출력 함수로 넘어가는 포맷 스트링을 모두 점검하는 와중에 난 놀라운 한 줄을 발견하고야 말았다. 내가 작성한 것이라 믿고 싶지 않은 한 줄이었다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;lb_-&gt;Append(LLV_INFO, buffer);&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;lb_-&gt;Append(LLV_INFO, buffer);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이거슨 무엇인가? 대재앙을 부른다는 바로 그 코드. 악마를 워프시킨다는 바로 그 코드. 핡~ 포맷 스트링으로는 절대로 변수를 넘겨서는 안 된다는 불변의 진리~ 그 망망대해 속에 존재하던 딱 한 줄의 코드가 나에게 말.하.고. 있었다. 이 멍청아~ 꺼져~ ㅠㅜ~&lt;/p&gt;
&lt;p&gt;확인 사살을 위해서 샘플을 만들었다. 당.연.하.게 이 샘플은 한치의 오차도 없이 나의 소설대로 동일한 번지에서 크래시를 발생시켰다. 휴~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;wchar_t&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;%Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PUNICODE_STRING us &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PUNICODE_STRING&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;wprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; us&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 위 샘플보다는 아래 샘플이 원 코드의 심각성을 더 잘 보여준다. 마구 %Z%z%Z%Z%Z%Z 따위를 입력해보자. printf의 포맷스트링으로 변수를 전달하는 것이 얼마나 위험 천만한 짓인지 깨닫게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fgets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아직도 헤매는 독자 여러분을 위해서 어떻게 고치는지 살펴보면 아래와 같이 고쳐야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fgets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/10/vs2012p.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/10/vs2012p.png&quot; alt=&quot;&quot; title=&quot;vs2012p&quot;&gt;&lt;/a&gt;
&lt;strong&gt;이래놓곤 난 다음 주엔 VS2012로 어떻게 우아하게 버그를 잡는지 발표하겠지~ 기가찬다 진짜~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;신이시여, 발표 자료가 뚝 떨어지는 기적을 보여 주옵소서~ 아멘!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;가을가을한 요즘. 깜냥도 안 되면서 너무 많은 걸 약속한 건 아닐까 반성하는 중 ㅠㅜ~&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[아 멘붕. 돌대가리 ㅠㅜ~]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/8832</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8832</guid><pubDate>Fri, 21 Sep 2012 23:58:26 GMT</pubDate><content:encoded>&lt;p&gt;평균 구할 일이 있었다. 가평균으로 구했으면 했다. 그런데 가평균 공식이 잘 생각이 나질 않는 불편한 상황. 여기까진 이해해 줄만 했다. 다 외울 수는 없다고 자위하면서 말이지. ㅠㅜ~ ‘가평균 공식’으로 구글링. 두둥. 잔뜩 나왔다. 몇 페이지 클릭해서 들어갔는데 어랏 공식보고 단박에 이해가 되질 않는 이상한 시츄에이션. 내 머릿속은 이런 상황 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;avg = avg + (i – avg) ? / ?&lt;/p&gt;
&lt;p&gt;그래서 속으로 그래. 이런 건 네이버에서 검색해야지 ㅋㅋ~ 이러면서 네이버에서 똑같은 걸 검색. 한 두 페이지 들어가 봤는데 그래도 이놈에 물음표가 채워지질 않는다. 헉. 약간 멘붕. 어쩌다가 이 지경이. 결국 구글에 ‘average without sum’같은 구차한 검색을 통해서 가평균 코드를 보고서야 물음표를 채울 수 있었다.&lt;/p&gt;
&lt;p&gt;와 어쩌다가 이렇게 됐지. 원래 그닥 좋은 머리는 아니었지만 이렇게 심각하지는 않았는데. 맨날 술만 먹었더니 진짜 돌대가리 다 됐다. 이러다 내년에는 다른 파일에 방금 작성한 클래스 이름이 생각나질 않고, 그 다음 해에는 열줄 위에 있는 지역 변수 이름이 기억나질 않고, 그 다음 해에는 sprintf 함수 원형이 가물가물한 지경이 되는건 아닌지 ㅠㅜ~&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[진정한 여행]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/8750</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8750</guid><pubDate>Fri, 17 Aug 2012 23:58:25 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;가장 훌륭한 시는 아직 씌어지지 않았다.&lt;/p&gt;
&lt;p&gt;가장 아름다운 노래는 아직 불려지지 않았다.&lt;/p&gt;
&lt;p&gt;최고의 날들은 아직 살지 않은 날들.&lt;/p&gt;
&lt;p&gt;가장 넓은 바다는 아직 항해되지 않았고,&lt;/p&gt;
&lt;p&gt;가장 먼 여행은 아직 끝나지 않았다.&lt;/p&gt;
&lt;p&gt;불멸의 춤은 아직 추어지지 않았으며,&lt;/p&gt;
&lt;p&gt;가장 빛나는 별은 아직 발견되지 않은 별.&lt;/p&gt;
&lt;p&gt;무엇을 해야 할지 더 이상 알 수 없을 때&lt;/p&gt;
&lt;p&gt;그때 비로소 진정한 무엇인가를 할 수 있다.&lt;/p&gt;
&lt;p&gt;어느 길로 가야 할지 더 이상 알 수 없을 때&lt;/p&gt;
&lt;p&gt;그때가 비로소 진정한 여행의 시작이다.&lt;/p&gt;
&lt;p&gt;– 진정한 여행, 나짐 히크메트&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;너저분하게 널려있는 쓰레기를 싹 버리고,&lt;/p&gt;
&lt;p&gt;탑처럼 쌓여있는 그릇들을 깨끗하게 씻고,&lt;/p&gt;
&lt;p&gt;마른 오징어가 된 빨랫줄의 옷을 개킨다.&lt;/p&gt;
&lt;p&gt;눅눅해진 빨랫감을 세탁기에 넣어 돌리고,&lt;/p&gt;
&lt;p&gt;청소기로 방에 켜켜이 쌓인 머리카락과 먼지를 모두 쓸어내고,&lt;/p&gt;
&lt;p&gt;침대에 깔깔한 순면 시트를 새로 깐다.&lt;/p&gt;
&lt;p&gt;에어컨을 터보 모드로 켠 다음,&lt;/p&gt;
&lt;p&gt;적당한 온도의 물에 샤워를 한다.&lt;/p&gt;
&lt;p&gt;그리곤, 침대에 쏙!&lt;/p&gt;
&lt;p&gt;반쯤 읽은 신경숙의 소설책을 집어든다.&lt;/p&gt;
&lt;p&gt;하염없이 행복한 이 순간,&lt;/p&gt;
&lt;p&gt;진정한 여행이 시작된다.&lt;/p&gt;
&lt;p&gt;훗~&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[생각만 하는 사람]]></title><link>https://jiniya.net/wp/archives/8656</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8656</guid><pubDate>Thu, 16 Aug 2012 23:58:24 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 489px; margin-bottom: 16px;&apos; data-url=&apos;./생각만_하는_사람.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/931fddad1e95b1a9366386d541d78efb/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.78947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADHklEQVR42mOoaWyPTiuJSc2Lyyh1cfO2tLCxsLDW1TVUV9fV0zNyc3MNCwvbtm3bz58/P378+BkMPn36BCTfvn3LEBIebe1oZWBiYW1voKQsoqTIJyXJIynJLibGIC8LZEtraGhcuHDh////f//+/Q8G//79A5Jfvnxh8PL2d3QRDI8Uz8zhT0kTCo0SCIvgCgzijI5jMDIREBeXlJAQv3z5MlD1jx8/gPYDjUBoDvb29tYTjHERctbl99Tn9dbjDbXgtFNns5BllOdiFRYSYWFhnjFjxv379zdt2jRnzpx9+/b9+fMHpjnA1UyZy1JTxFxTwEqLy1SRw1iRTVeR1UiB1VidUUiIk4GBycvL8/fv30DVz58/B5oC9DxUc1S0k5sXs48/t4c3V1Iqe0AIh18wS2Q0s7c/i38Qq4gwCzMzG9Dlt27dgmhYvHgxJAiAYcYQEOgWEsTq6cETGMAeGsYRGcHp7cURFcXm78dkasIABOzsbCwsLEA9r169WrRo0YYNG75+/Qq12dbWQUGBOShQICaWz8+X09yC0caGwcuLyddb2tPDOjEpMSQkBGhEQkICJMxQQtvZ2YWXl1dCnJuHl0lOTjQ6JnzpktknT+5/+uThp09f7927d/369enTpwcEBACjF6gHGFoIzfb29kCDZWTk8vLyDx06DAySly9fPXz4CMj4+fM70KkzZ87ctWvXgQMHzp49C4ltpKgKDq6qqnr48AHYPSAnff365dLlS93dXXl5eefPn3/z5k1lZeXkyZP37NkDTFXw1ALSDAx6SLoBWnL48OG9e/feuXMHGDHHjh1TVVUFOmrr1q1btmyRl5dPTU3t7+8HphOEzZBIA3pswoQJ9fX1LS0ttbW1y5YtA/qwp6fH2toa6K4rV66Ym5sDDWJlZZ09ezYkzECanzx5cuLECaCeurq6iRMnAo3o6uoqKChYu3Yt0M6Ghob4+HgjIyNgbDGAATc3986dO4H6gaYz7N69G6insLCwsbFx1qxZwATY3NwMjBhg8FZUVPj5+VlZWZmZmZmamlqAga6ublNTE1Dz27dvAXgK5nut1AfSAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;          md 0&apos; title=&apos;&apos; src=&apos;/static/931fddad1e95b1a9366386d541d78efb/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_0.png&apos; srcset=&apos;/static/931fddad1e95b1a9366386d541d78efb/08678/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_0.png 190w,
/static/931fddad1e95b1a9366386d541d78efb/2edd7/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_0.png 380w,
/static/931fddad1e95b1a9366386d541d78efb/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_0.png 489w&apos; sizes=&apos;(max-width: 489px) 100vw, 489px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 489px; margin-bottom: 16px;&apos; data-url=&apos;./생각만_하는_사람.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d75961ebb031925b23db63a31aa76d55/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.78947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADFklEQVR42mNo6+7PLK7NKqwsqGgIi4j08fHx9vZ2dHSys7N3cnIKDQlJSU3duXPnjx8/Pn78+BkMPn36BCTfvXvHEBoZa2jpoGdipaFvJiQiysvDw8PNxc7GysDAwMvLKyUpoaamdvbs2f/////9+/c/GPz79w9IfvnyhcHf389JVSjSSCJIVzhARzRKTyBGmztEnTNSldFdTcBGVVxKSurKlStA1X/+/IFoQ2j28fGVkpJ0UBMzlBSwk+czleS3k+a2l2Q1FGQUYGcTFhZhZWGZP3/+w4cPN2/eDGQcOnQI4gSQZnd3Nx4eflV1MV9fAUsrHidnDicXdlNTdjsHNgcHBnExLgYGJqDrfv78CfTkHTAA+hmq2cXFmZWVQ0qa1zeA1cmFOSyC2dWD0d6JwdmFSVaWlY2NhZWVTVpa+v79+0ANwGBbu3bthQsXgGxgmDF4uHtwcXGKCok7ajr7GvvaqFvYaTi56LhqS2szMjICg42dnZ2FhWXFihWvX79etGjRsmXLIDaDNDs6OrKwskiIS1qqW5kom6uIqioJAz2hoa+sr6en6+/v7+zsDDQiPT0d4lSUAAPK8YIBIxMjFw+Xi5tLS1vzytUrz104//LlywcPHty8ebOtrQ0Y+d++fUMOc5BmB2CwMDCIioomxCds27rt8aPHwIB59fLV50+fgeoeP348Y8YMYAjv3r0b4lVgUCM0e3l5AZ10+fJleBx++PDhzJkz3d3dNTU1d+/effbsWWVl5bx58/bu3QuUQnH29evXIenm/fv3p06dOnbs2NOnT3///r1//34FBQVgaB08eBAYwsrKyoWFhXPmzEFxNjDFAlnA2JsyZUpDQ0Nra2tdXd26deuA4s3Nzdra2hUVFUBvm5iYAH0HTLvLly+HWA7S/OLFi4sXL/b09DQ2Nk6aNGnixIm9vb2lpaW7du0C5gdgUGVmZgJjhIsLmFpAQEREBOg6oH5ghDEAFQFV5+Tk1NbWTp06ddq0aUD7o6OjgcELtNPT09PAwEBdXV1VVVVTU1NLS0tWVhYYFkDNb968AQDV9d7T7Bho2wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;          md 1&apos; title=&apos;&apos; src=&apos;/static/d75961ebb031925b23db63a31aa76d55/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_1.png&apos; srcset=&apos;/static/d75961ebb031925b23db63a31aa76d55/08678/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_1.png 190w,
/static/d75961ebb031925b23db63a31aa76d55/2edd7/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_1.png 380w,
/static/d75961ebb031925b23db63a31aa76d55/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_1.png 489w&apos; sizes=&apos;(max-width: 489px) 100vw, 489px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 489px; margin-bottom: 16px;&apos; data-url=&apos;./생각만_하는_사람.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b069162a2c1bd94375fd50600360c444/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.78947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADIElEQVR42mPomTAlq7gms6Aiv7wpNCzK09MHiOztnWxt7e3tHUNCQpKTk7du3frjx4+PHz9+BoNPnz59+fLl7du3DDEJKVomDnom1sbWZtIyIlKSPCIiXPx8rCzMDAJ8POJiksrKyseOHfv////fv3//g8G/f/+AJFA/Q1RkuKqKsJmZbECAcFCwaEy8gH8At6cXl6sbk4Mjv7KKlIS42NmzZ4Gq//z5A9GG0BwZFWptI+jpKmZjxu/tzBvoyevtymVmwGZvyejmwOJuJ8DOxjxt2vTHjx9v2bJlwYIF+/fv//37N1Szn3+AvBBvioFgki53hhZ7kzFLmBJbuhZrrBpLmhpjpRE7HzuTs5v79+/f3r9/f+fOndu3bwM9D9Xs4+sbr87YZ8dRZMxRa8bWZM5Wbcw83Zap15K52IClxoTFWZ6dR1D01s0bQA2/fv1av379mTNngGxgyDEEBQamaDJ3WnMUG7LmG7Bl6HFUm7J3WLF1WjDHKDNmKjP4ybMzMDIvmD8faPNiMAAyoJp9vL2FOJm1ZYTUJPmlhXjiVRiLNRl0+Rl0pQVczfUyw31CvF0ZGBji4uIgTkUJMF9fX04ubh4+fiZmVj4+Pl9Pt96u9rXr1p05f+np8xd37j+8fvNWT0+Pu7v7hw8fkMMcpNnLywtosKiIcHRU1KaNm+4/eACM/ZcvX3z+9PHvnz/Pnz2bPWvW/gP79+zZA/EqMLYRmoOCgpKSki5evAhJA0CJTx8/nj9/vre3t6qq6saNG69evaqurp49ezZQP9BceGoBab5+/TrEJKCrgGYfPXr0yZMnwJg8cuSImpoaExPTzp07gckTmM7y8vJmzJjx8+dPhM2QSLt///706dMbGhpaW1vr6upWrVoFFO/s7NTR0SksLLx165aNjQ3Qd5ycnPPmzYM4EKT55cuXly9f7uvrA+qcCAZAdmlp6fbt24Hu7OjoyMrKcnZ25ubmZgADfn5+YCID6gdmD4Z9+/b19/fn5ubW1tZOB4OmpiZgxAADsrKy0sfHx9DQUENDA+gFLS0tbW1tOTk5oNFAzW/evAEAHjvpTDU8HwgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;          md 2&apos; title=&apos;&apos; src=&apos;/static/b069162a2c1bd94375fd50600360c444/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_2.png&apos; srcset=&apos;/static/b069162a2c1bd94375fd50600360c444/08678/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_2.png 190w,
/static/b069162a2c1bd94375fd50600360c444/2edd7/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_2.png 380w,
/static/b069162a2c1bd94375fd50600360c444/7f605/%EC%83%9D%EA%B0%81%EB%A7%8C_%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C.md_2.png 489w&apos; sizes=&apos;(max-width: 489px) 100vw, 489px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[하운즈 게릴라 테스트]]></title><description><![CDATA[인트로 동영상 기자 간담회 플레이 영상 넷마블 기대작 하운즈가 8월 17일 게릴라 테스트를 진행합니다. 테스트는 8월 17일 17시부터 24시까지 진행되구욤. 하운즈 게시판에 글을 올리고 등급…]]></description><link>https://jiniya.net/wp/archives/8646</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8646</guid><pubDate>Thu, 16 Aug 2012 23:58:23 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;인트로 동영상&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;기자 간담회 플레이 영상&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;넷마블 기대작 하운즈가 8월 17일 게릴라 테스트를 진행합니다. 테스트는 8월 17일 17시부터 24시까지 진행되구욤. 하운즈 게시판에 글을 올리고 등급 2티어 이상 달성한 사용자를 대상으로 진행됩니다. 하운즈는 RPS라는 흔치않은 장르의 게임입니다. RPS가 뭐냐구욤? 롤플레잉과 총싸움을 결합한 게임이라고 생각하시면 됩니다. 여튼 어서어서 게시판에 가서 글쓰고 테스트에 참여하도록 합시닷. 마격타임이예욥 핡~ ㅋㅋㅋ&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[스레드 동기화 전략]]></title><description><![CDATA[<리스트 1>에 나와 있는 dec_counter라는 간단한 프로그램에서 이야기를 시작해보자. dec_counter 프로그램은 전역 변수 counter를 감소시키는 스레드를 생성하는 프로그램이다. 코드를 살펴보면 각 스레드는 DEC_LOOP_MAX…]]></description><link>https://jiniya.net/wp/archives/8669</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8669</guid><pubDate>Thu, 16 Aug 2012 23:58:22 GMT</pubDate><content:encoded>&lt;p&gt;&amp;#x3C;리스트 1&gt;에 나와 있는 dec_counter라는 간단한 프로그램에서 이야기를 시작해보자. dec_counter 프로그램은 전역 변수 counter를 감소시키는 스레드를 생성하는 프로그램이다. 코드를 살펴보면 각 스레드는 DEC_LOOP_MAX 만큼 루프를 반복하면서 counter 값을 1씩 감소시키고, 주 스레드는 counter 값을 DEC_LOOP_MAX * DEC_THREAD_MAX로 초기화 한 후에, DEC_THREAD_MAX 개수만큼 감소시키는 스레드를 생성시켜서 동시에 실행되도록 만든다. 이렇게 했을 때 이론적으로는 모든 스레드의 실행이 완료되고 나면 counter 값은 0이 되어야 한다. 과연 그런지 dec_counter 프로그램을 컴파일해서 실행시켜 보도록 하자. 실행할 때에 주의해야 할 점은 반드시 컴파일 최적화 옵션을 꺼야 한다는 점이다. 최적화 옵션을 켜두면 컴파일러가 스레드 코드를 우리가 의도했던 것과는 다른 형태로 변형시키기 때문에 결과가 달라진다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 dec_counter 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; DEC_THREAD_MAX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; DEC_LOOP_MAX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; counter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;DecCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DEC_LOOP_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;counter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE thread&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DEC_THREAD_MAX&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        counter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DEC_THREAD_MAX &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; DEC_LOOP_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            thread&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DecCounter
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CREATE_SUSPENDED
                                     &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;ResumeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DTM=%d, DLM=%d, counter=%d\n&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DEC_THREAD_MAX
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DEC_LOOP_MAX
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; counter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;화면 1&gt;, &amp;#x3C;화면 2&gt;, &amp;#x3C;화면 3&gt;에는 DEC_THREAD_MAX와 DEC_LOOP_MAX를 변경해 가면서 프로그램을 실행한 결과가 나와 있다. 결과 화면에서 제일 먼저 눈에 띄는 사실은 우리의 예상과는 달리 counter 결과가 0이 아닌 경우도 있다는 점이다. 게다가 더 재미있는 점은 DEC_THREAD_MAX와 DEC_LOOP_MAX가 각각 1000과 1000일 때에는 프로그램 실행 중에도 그 때 그 때 결과가 달라지기도 한다는 것이다. 물론 이 모든 결과는 필자가 테스트한 컴퓨터에서의 결과일 뿐이고 여러분의 컴퓨터에서는 또 다른 결과가 나올지도 모른다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_동기화_전략.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/73dc7a116b104834d566873a2c00bb3f/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 17.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAi0lEQVR42mOITsrQNzQ2NrM0s7TV0TfWMzLT1jeVU9aQV9GSVdGQV9VSUNWWV9FUVNdRUNMGkkrqukpqWkrq2qUNvQxObp4c7GwCAgLCwkI83Nz8/HycnJwMuAEjIyOQBGpp7uhl8PYL5ObiEhYWERMX5+PjExYW5uXlhSjCCpiYmICy7OxsU2bMBgB+zBLrupgP9wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;           md 0&apos; title=&apos;&apos; src=&apos;/static/73dc7a116b104834d566873a2c00bb3f/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_0.png&apos; srcset=&apos;/static/73dc7a116b104834d566873a2c00bb3f/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_0.png 190w,
/static/73dc7a116b104834d566873a2c00bb3f/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_0.png 380w,
/static/73dc7a116b104834d566873a2c00bb3f/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_0.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 1 100×100 실행 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_동기화_전략.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8daf4fce120f305104de951573aaf772/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 28.947368421052634%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA8ElEQVR42o2OwUrDQBRFJ6Jpk8mkcTIzb96kKrjQn3WTYtVaSi0iKtWCEqXuailBrF3Y/EFdaP/C0ayLXs7iweNwL8lGs2FePEyKwai4fS76+eL65bP/+mW5mS6v8o+jbN64e7ekg7eT+9n54/QyGz91uu2DlCgpk/oWYlLf3omFBG2E0j5lnh+UuFXPrfgVj264VYs91tbd3b394+4FqYVMKSVErAEYY5vRTxzHIStSvhB12myRKKoBgJQSEa0shAiCgKxOKRvE006PxJxLaZsF/DZzzimlf8pJYg7bPQIyBtB2uTEmDEM74Z9yo3X2DZyWP7EJMWWDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;           md 1&apos; title=&apos;&apos; src=&apos;/static/8daf4fce120f305104de951573aaf772/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_1.png&apos; srcset=&apos;/static/8daf4fce120f305104de951573aaf772/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_1.png 190w,
/static/8daf4fce120f305104de951573aaf772/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_1.png 380w,
/static/8daf4fce120f305104de951573aaf772/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_1.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 2 1000×1000 실행 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_동기화_전략.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2cff4edd9adc70aa9ef4f88b5b044568/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 16.842105263157894%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAlElEQVR42mOYPG9V77T5k+eumLxgTc+sFW3Tl7fO3tgxf2vL7I3109Y0TF8LR43T1zbPXNc1e01x44ScjJKmhj4Gn8AwXh5uCQlJFVVVaWlpYWFhcXFxWVlZLi4uBmyAkZERSLKzc9S19TK4e/lxcXKIiIoCNYiJifHx8QkKCkpISHBwcECUogEmJiagOAcbW9+EKQAxrywZVYH1XAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;           md 2&apos; title=&apos;&apos; src=&apos;/static/2cff4edd9adc70aa9ef4f88b5b044568/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_2.png&apos; srcset=&apos;/static/2cff4edd9adc70aa9ef4f88b5b044568/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_2.png 190w,
/static/2cff4edd9adc70aa9ef4f88b5b044568/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_2.png 380w,
/static/2cff4edd9adc70aa9ef4f88b5b044568/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_2.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 3 10×100000 실행 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/08/image003.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/08/image003.png&quot; alt=&quot;&quot; title=&quot;image003&quot;&gt;&lt;/a&gt;
dec_counter 프로그램은 동기화 문제의 가장 큰 특징인 비결정론적인 성질을 잘 보여주고 있다. 비결정론적 성질이란 프로그램이 항상 동일하게 동작하는 것이 아니라 실행 환경에 따라서 동작이 달라지는 것을 말한다. 즉, 진짜로 프로그램이 그 때 그 때 다르게 동작한다는 말이다. 그래서 이런 성격의 동기화 문제는 재현하기도 쉽지 않을뿐더러 관찰하기는 더 어렵다. 이런 점 때문에 동기화 문제는 신입 개발자들에게 거짓말을 시키는 가장 대표적인 버그 중에 하나다.&lt;/p&gt;
&lt;p&gt;동기화 문제가 다루기 어려운 첫 번째 이유는 발생 확률이 낮아서 재현하기가 쉽지 않다는 점에 있다. 만약 여러분의 프로그램이 dec_counter 프로그램의 100×100 정도에 맞먹는 확률로 문제가 발생하는 코드를 가지고 있다면 아마 그 코드는 여러분의 QA팀 테스트 및 사내 테스트를 모두 무사히 통과할 것이다. 하지만 릴리즈하는 순간 고객들에게 프로그램이 정상적으로 동작하지 않는다는 이야기를 듣게 될 것이다. 고객의 클레임을 듣고 문재를 발생시키려고 시도해보아도 쉽지 않다. 왜냐하면 발생 확률이 극히 낮기 때문이다. 이런 어려움 때문에 고객 PC를 직접 디버깅하려고 한들 그것 또한 쉽지 않다. 고객 PC에서도 항상 100% 문제가 동일하게 발생하는 것은 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;동기화 문제가 어려운 두 번째 이유는 동기화 버그를 관찰하려는 시도 자체가 문제를 소멸시키는 성질을 가지고 있다는 점 때문이다. 동기화 문제는 가장 직접적인 디버깅 방법인 코드 트레이싱을 통해서는 문제 원인을 추적할 수 없으며, OutputDebugString 같은 아주 사소한 관찰 기법들이 코드에 추가되더라도 문제가 사라질 수도 있다. 실제로 dec_counter 프로그램의 ResumeThread 다음에 OutputDebugString이나 Sleep과 같은 구문을 넣게 되면 &amp;#x3C;화면 4&gt;에 나타난 것처럼 문제가 사라진 것처럼 보여지게 만들기도 한다. 이런 이유 때문에 신입 개발자들은 곧잘 와서는 “OutputDebugString을 추가하니까 잘 됩니다”, 내지는 “Sleep을 좀 줬더니 버그가 사라졌습니다”같은 이야기를 하는 것이다. 사실 그건 버그를 사라지게 만든 것이 아니라 단순히 재현 확률을 낮췄을 뿐인데도 말이다. 천만 분의 일의 확률로 발생되는 문제를 억만 분의 일로 낮추어 본들 문제가 사라진 것은 아니다. 언젠가 어떤 환경에서 그 문제는 다시 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_동기화_전략.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0e51435cc605216a5e2290ec39e94955/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 18.421052631578945%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoklEQVR42mPYffzy3lM39p6+tfPUnQ2Hrmw6/WTTxY9rz7xGQ+vOvll04P7kdad6VxzuW7xrxrLt6yZPZ5CTk1NWUdXVMzAyNpWWlVdR01DV0BISFcdEgsJivALCfALC/IIiPPxCUrLyDKwszPz8/GJiYhISEpwcHLw8PDzc3Ax4ASMjI5Dk4eZiYGNlFRQUBOqUkpICagSy+fj4iNHMy8MDAI4ANkR9VPhpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;           md 3&apos; title=&apos;&apos; src=&apos;/static/0e51435cc605216a5e2290ec39e94955/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_3.png&apos; srcset=&apos;/static/0e51435cc605216a5e2290ec39e94955/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_3.png 190w,
/static/0e51435cc605216a5e2290ec39e94955/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_3.png 380w,
/static/0e51435cc605216a5e2290ec39e94955/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EC%A0%84%EB%9E%B5.md_3.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 4 Sleep을 적용한 10×100000 실행 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그렇다면 이렇게 다루기 어려운 동기화 문제는 왜 발생하는 것일까? 또 이 문제를 해결하기 위한 방법들에는 어떤 것들이 있을까? 직접 만들지 않은 함수나 라이브러리가 잠재적으로 이런 동기화 문제가 발생할 수 있는지 없는지 사전에 알 수 있는 방법은 없을까? 지금부터 이 질문에 대한 해답을 찾아보도록 하자.&lt;/p&gt;
&lt;p&gt;counter 값이 이상해진 이유&lt;/p&gt;
&lt;p&gt;우리가 사용한 C 코드의 –counter라는 구문은 실제로 CPU 명령어로 번역되면 &amp;#x3C;리스트 2&gt;에 나타난 것과 같이 3개의 명령어로 구성된다. 각 명령어는 counter가 저장된 메모리의 값을 레지스터로 복사하고, 레지스터 값을 1 감소 시키고, 그 감소된 값을 다시 counter가 저장된 메모리에 기록하는 일을 한다. &amp;#x3C;표 1&gt;에는 counter 값이 2인 상황에서 세 개의 명령어를 두 개의 스레드에서 한 번씩 수행할 때에 실행 순서에 따라서 어떤 결과가 나타나는지가 나와 있다. 제일 먼저 나온 실행 순서가 우리가 일반적으로 생각하게 되는 순서다. 이 경우에는 당연히 결과는 우리가 예상한대로 0이 나온다. 반면 두 번째, 세 번째 실행 순서를 보면 실행 순서가 조금 바뀌었을 뿐인데 결과는 우리가 예상하지 않았던 1이 나오는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;counter 값이 이상해진 이유도 바로 여기에 있다. &amp;#x3C;표 1&gt;에 나타난 것과 같이 실행 순서가 일반적인 경우도 있고, 결과가 이상해지는 경우도 있는 것이다. 실행 순서가 모두 우리가 예상한 일반적인 실행 흐름과 100% 똑같다면 정상적인 결과가 나오게 되는 것이고, 조금이라도 달라졌다면 예측하지 못했던 결과가 나오게 되는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 –counter에 대한 어셈블리 명령어&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mov ecx, dword ptr [counter]
sub ecx, 1
mov dword ptr [counter], ecx
mov ecx, dword ptr [counter]
sub ecx, 1
mov dword ptr [counter], ecx	
---
counter = 0

mov ecx, dword ptr [counter]
mov ecx, dword ptr [counter]
sub ecx, 1
sub ecx, 1
mov dword ptr [counter], ecx
mov dword ptr [counter], ecx	
---
counter = 1

mov ecx, dword ptr [counter]
sub ecx, 1
mov ecx, dword ptr [counter]
sub ecx, 1
mov dword ptr [counter], ecx
mov dword ptr [counter], ecx
---
counter = 1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;원자적 연산 (atomic operation)&lt;/p&gt;
&lt;p&gt;앞서 우리는 –counter라는 구문이 실제로 어셈블리어로는 3개의 명령어로 구성돼 있고, 그 명령어의 실행 순서가 엉키면서 값의 상태가 이상해진다는 것을 배웠다. 그렇다면 3개의 명령어가 아닌 하나의 명령어로 만들면 문제가 사라지지 않을까? 이런 관점에서 동기화 문제에 접근하는 방식이 ‘원자적 연산’이다. 번역해 놓으니 단어가 좀 이상한데 ‘원자적 연산’이란 특정 연산이 한번에 수행된다는 의미를 가진다. 즉, 연산 수행 도중에 동일한 연산이 중첩돼서 실행될 수 없다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;그렇다면 앞서 살펴본 3개의 어셈블리 명령어를 하나로 만들면 원자적 연산이 되는 것일까? 우리가 흔히 사용하는 인텔의 x86 CPU에는 –counter를 한번에 수행할 수 있는 dec라는 어셈블리 명령어가 존재한다. dec dword ptr [counter]와 같이 사용하면 위 3개의 명령어가 하는 일과 동일한 기능을 수행할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 –counter를 하나의 인스트럭션으로 변경한 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG CALLBACK &lt;span class=&quot;token function&quot;&gt;DecCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DEC_LOOP_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        __asm dec dword ptr &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;counter&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 3&gt;에는 이렇게 스레드 코드를 하나의 어셈블리 명령어로 고친 것이 나와 있다. 실행을 해보면 여러분의 시스템에 따라서 정상적이기도 하고 정상이 아니기도 한 현상이 발생할 것이다. 이 접근은 반쯤만 원자적인 방법이기 때문이다. 우리가 사용한 이 방법은 시스템이 싱글코어라면 원자성이 보장되지만 멀티코어라면 원자성이 보장되지 않는다. 멀티코어에서는 단일 명령인 dec 명령어 조차도 물리적으로 두 개 이상의 CPU에서 동시에 실행될 수 있기 때문이다. 참고로 멀티코어 환경에서 싱글코어와 동일한 상황의 테스트를 해보고 싶다면 dec_counter 프로그램에서 CreateThread 다음에 SetThreadAffinityMask 함수를 사용해서 모든 스레드가 한 CPU에서만 실행되도록 만들면 된다.&lt;/p&gt;
&lt;p&gt;그렇다면 친화도를 조절하지 않고 멀티코어 환경에서 원자성을 보장할 수 있는 방법은 없을까? 물론 있다. 멀티코어 CPU를 설계한 사람들도 이러한 문제점을 충분히 알고 있었기 때문에 멀티코어 환경에서 원자성을 보장할 방법을 마련해 두었다. x86 CPU에서는 dec 명령어 앞에 lock을 붙여줌으로써 그런 일을 할 수 있다. &amp;#x3C;리스트 3&gt;의 코드에 lock을 붙여서 컴파일하고 실행해보면 코어 개수에 상관 없이 어떠한 환경에서든 정상적으로 실행 결과가 나타나는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;윈도우는 이러한 어셈블리 명령어를 손쉽게 사용할 수 있도록 원자성이 보장되는 API들을 만들어서 제공해 주고 있다. &amp;#x3C;표 2&gt;에는 이러한 Interlocked 함수 중에서 자주 사용되는 함수들의 이름과 그 함수가 어떠한 동작을 한번에 하는지가 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;표 2 자주사용하는 Interlocked 함수들&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LONG __cdecl &lt;span class=&quot;token function&quot;&gt;InterlockedExchange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  __inout  LONG &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  __in     LONG Value
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	

LONG Old &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Old

&lt;span class=&quot;token comment&quot;&gt;///&lt;/span&gt;

LONG __cdecl &lt;span class=&quot;token function&quot;&gt;InterlockedExchangeAdd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  __inout  LONG &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Addend&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  __in     LONG Value
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

LONG Old &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; Value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Old

&lt;span class=&quot;token comment&quot;&gt;///&lt;/span&gt;

LONG __cdecl &lt;span class=&quot;token function&quot;&gt;InterlockedCompareExchange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  __inout  LONG &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Destination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  __in     LONG Exchange&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  __in     LONG Comparand
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	

LONG Old &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; Comparand&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Exchange&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Old&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;///&lt;/span&gt;

LONG __cdecl &lt;span class=&quot;token function&quot;&gt;InterlockedDecrement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  __inout  LONG &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Addend
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	

&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target

&lt;span class=&quot;token comment&quot;&gt;///&lt;/span&gt;

LONG __cdecl &lt;span class=&quot;token function&quot;&gt;InterlockedIncrement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  __inout  LONG &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Addend
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	

&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;Target&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;바쁜 대기 (busy waiting)&lt;/p&gt;
&lt;p&gt;동기화 이슈를 피하기 위한 다른 방법으로는 바쁜 대기가 있다. 바쁜 대기란 자신이 공유 데이터에 접근할 수 있는지를 수시로 체크하는 것을 말한다. &amp;#x3C;리스트 4&gt;에는 DecCounter 스레드를 바쁜 대기를 사용해서 동기화 시킨 코드가 나와 있다. counter 변수 업데이트 전후로 can_update 값을 변경하고, counter 변수에 접근하기 전에 can_update가 접근 가능한 상태로 되어 있는지를 검사하고 있다. 이렇게 할 경우에 이론적으로는 동시에 하나의 스레드만 counter 변수 값을 변경할 수 있기 때문에 counter 값이 이상해지는 문제를 피할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 바쁜 대기를 사용한 동기화&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LONG can_update &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ULONG CALLBACK &lt;span class=&quot;token function&quot;&gt;DecCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DEC_LOOP_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;can_update&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        can_update &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;counter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        can_update &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 4&gt;의 코드는 바쁜 대기의 기본적인 개념을 보여주기 위한 코드다. 실제로 해당 코드를 사용해서 스레드를 돌려보면 여전히 결과가 이상한 것을 볼 수 있는데 이는 바쁜 대기에 사용된 can_update 변수 조작에 원자적 연산이 사용되지 않았기 때문이다. &amp;#x3C;리스트 5&gt;에는 원자적 연산을 이용해서 바쁜 대기를 완전하게 만든 코드가 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 원자적 연산을 사용한 바쁜 대기&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LONG can_update &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ULONG CALLBACK &lt;span class=&quot;token function&quot;&gt;DecCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DEC_LOOP_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;InterlockedCompareExchange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;can_update&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;counter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;InterlockedExchange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;can_update&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;dec_counter 프로그램의 경우에는 공유 자료에 접근하는 코드가 워낙 간단하고(–counter), 해당 연산 자체를 원자적 연산으로 바꾸는 것이 가능해서 바쁜 대기를 사용하는 의도가 불분명하지만 현실세계에서의 복잡한 연산을 단일화 하는 데에는 가장 손쉽고, 금방 떠오르는 방법이기 때문에 바쁜 대기는 의외로 자주 사용되기도 한다. 하지만 바쁜 대기는 멀티코어 환경이든 싱글코어 환경이든 프로그램이 의미 있는 코드를 수행하는데 보내는 시간보다 바쁜 대기를 위한 루프를 반복하는 곳에 CPU 자원을 더 많이 소모하게 된다는 치명적인 단점이 있기 때문에 가급적 사용하지 않는 것이 좋다.&lt;/p&gt;
&lt;p&gt;잠금 (Lock)&lt;/p&gt;
&lt;p&gt;동기화 문제를 해결하는 가장 일반적인 방법은 운영체제에서 지원하는 잠금 장치를 사용하는 것이다. 잠금 장치는 특정 코드 영역이 여러 곳에서 동시에 실행되지 않도록 만드는 일을 한다. 윈도우에서는 이런 목적을 위해서 크리티컬 섹션, 뮤텍스, 세마포와 같은 다양한 방법을 지원해준다. &amp;#x3C;리스트 6&gt;에는 크리티컬 섹션을 사용해서 –counter가 한번에 하나의 스레드만 실행되도록 만든 코드가 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 크리티컬 섹션을 사용한 동기화&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;CRITICAL_SECTION cs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ULONG CALLBACK &lt;span class=&quot;token function&quot;&gt;DecCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DEC_LOOP_MAX&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;EnterCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;counter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;LeaveCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;잠금 장치의 경우에는 운영체제의 스케줄러와 밀접하게 연계되어 있다. 운영체제는 각 잠금 장치의 상태를 추적할 수 있기 때문에 특정 잠금 장치를 사용할 수 없는 상황에서 스레드가 해당 자원을 요청하면 요청한 스레드를 대기 상태로 만든다. 대기 상태로 만든다는 것은 해당 잠금 장치가 사용 가능해질 때까지 해당 스레드가 CPU 자원을 소모하지 않는다는 것을 의미한다. 이런 특징 때문에 바쁜 대기에서 살펴본 것과 같이 자원 획득을 위한 검사 루프에 CPU 자원이 소모하는 일이 없다.&lt;/p&gt;
&lt;p&gt;그렇다면 잠금 장치를 사용하는 것이 모든 동기화 문제를 해결하는 가장 좋은 방법일까? 그렇지는 않다. 우선 잠금 장치는 특정 코드가 동시에 실행되는 것을 제한하는 기법이기 때문에 멀티코어의 성능을 해치는 결과를 초래한다. 즉, 잠금 장치가 많으면 많을수록 CPU 개수가 증가해도 얻을 수 있는 이득이 없다는 말이다.&lt;/p&gt;
&lt;p&gt;윈도우 커널의 경우에도 내부적으로 디스패처 락이라는 전역 락이 존재한다. 커널 내부의 중요한 함수들은 모두 해당 락을 획득한 다음 작업을 진행하도록 되어 있는데 CPU 개수가 몇 개 안될 때는 문제가 되지 않았는데 CPU 개수가 늘어나면 늘어날수록 대부분의 스레드들이 디스패처 락을 획득하기 위해서 대기하는 상태로 노는 문제가 발생했다. Windows 7부터는 이런 문제점을 해결하기 위해서 디스패처 락의 구조를 변경했고, 그런 개선을 통해서 멀티코어에서의 가용성이 상당히 높아졌다고 한다.&lt;/p&gt;
&lt;p&gt;최근에는 CPU 개수가 지속적으로 증가하는 추세이기 때문에 이러한 CPU 규모 가변성에 대응하기 위해서는 잠금 장치보다는 앞서 살펴본 원자적 연산을 사용한 무잠금 알고리즘들이 활발하게 개발되고 있다.&lt;/p&gt;
&lt;p&gt;버퍼 분리&lt;/p&gt;
&lt;p&gt;동기화 문제의 근본적인 원인은 여러 개의 스레드가 동일한 버퍼에 동시에 접근하려는 것에 있다. 지금까지 소개한 해결책은 모두 ‘동시에’라는 부분에 집중한 방법이었다. 반대로 ‘동일한’이란 말에 집중해서 동기화 문제를 해결할 수도 있다. 공유해서 접근하는 버퍼가 정말 공유되어야 하는 성질의 것인지에 대해서 다시 한번 생각해 보자는 것이다. 그리고 정말 공유할 필요가 없는 것이라면 그것을 분리함으로써 동기화 이슈를 완전히 제거할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 7&gt;에는 srand, rand 함수의 일반적인 구현이 나와 있다. 코드를 살펴보면 두 함수 모두 전역 변수인 gseed 값을 갱신하는 것을 볼 수 있다. 따라서 이 구현은 다중 스레드에서 호출될 경우에 문제점이 있다고 할 수 있다. 왜냐하면 앞선 counter 예제와 똑같이 rand 함수 호출에 따라서 gseed 값이 불안정한 상태가 될 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 일반적인 srand, rand 함수의 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; gseed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;srand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; seed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    gseed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; seed&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gseed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gseed &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;214013L&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2531011L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x7fff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 문제점을 해결하기 위해서는 앞서 언급했던 원자적 접근이나 잠금을 사용할 수 있다. 하지만 rand 함수의 구조를 살펴보면 사실 gseed 값은 전혀 스레드 별로 공유해야만 하는 성질의 것이 아님을 알 수 있다. 왜냐하면 완전히 독립적으로 움직이는 변수이기 때문이다.&lt;/p&gt;
&lt;p&gt;따라서 이 경우에는 원자적 접근이나 잠금을 사용하는 것보다는 gseed라는 버퍼를 스레드 별로 분리하는 것이 좋은 방법이다. 그런 방법 중에 하나는 우리가 지난 연재에서 살펴보았던 스레드 지역 저장소가 있다. 스레드 지역 저장소를 사용하면 &amp;#x3C;리스트 7&gt;의 코드를 거의 고치지 않고도 버퍼를 바로 분리할 수 있기 때문이다. 실제로 다양한 컴파일러에 포함된 멀티 스레드용 CRT 코드는 이러한 기법을 사용해서 srand와 rand 함수를 스레드 안전한 함수로 구현하고 있다.&lt;/p&gt;
&lt;p&gt;스레드에 안전한 함수(Thread Safe Function)&lt;/p&gt;
&lt;p&gt;동기화 문제가 점점 더 큰 이슈로 부각되면서 프로그래머 사이에는 동기화 이슈의 발생 가능성에 대해서 사전에 예고할 수 있는 장치가 필요했다. 그래서 나온 말이 ‘스레드에 안전한(Thread Safe)’라는 말이다. 스레드에 안전한 함수란 여러 개의 스레드에서 해당 함수를 무작위적으로 마구 호출해도 전혀 문제가 되지 않는 함수를 말한다. 반대로 스레드에 안전하지 않은 함수란 두 개 이상의 스레드에서 호출하면 부작용이 발생할 수 있는 함수를 의미한다.&lt;/p&gt;
&lt;p&gt;일반적으로 요즘은 멀티 스레드 환경이 일반적이기 때문에 별다른 주의가 없으면 대부분의 함수는 스레드에 안전한 것으로 간주된다. 자신이 작성한 함수가 스레드에 안전하지 않고, 다른 개발자가 사용할 가능성도 있다면 관련 문서에 해당 함수가 스레드에 안전하지 않다는 내용을 표시해 주는 것이 좋겠다.&lt;/p&gt;
&lt;p&gt;새롭게 제작되는 함수라면 가급적 인터페이스를 스레드에 안전하게 만드는 것이 좋다. 앞서 &amp;#x3C;리스트 7&gt;에서 살펴본 rand 함수의 구현은 스레드에 안전하지 않은 함수였다. 그것을 대부분의 CRT에서는 스레드 지역 저장소를 사용해서 스레드에 안전한 함수로 제작한다는 것도 배웠다. CRT에서 스레드 지역 저장소를 사용한 이유는 rand 함수의 프로토타입을 변경할 수 없기 때문이다. 만약 rand 함수의 프로토타입을 변경할 수 있다면 &amp;#x3C;리스트 8&gt;과 같이 전역 변수에 대한 의존성 자체를 제거해서 스레드에 안전한 함수로 만드는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 스레드에 안전한 rand 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;seed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;seed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;seed &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;214013L&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2531011L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;seed &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x7fff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;재진입 가능한 함수(Reentrant Function)&lt;/p&gt;
&lt;p&gt;끝으로 재진입 가능한 함수에 대해서 알아보자. 재진입이라는 말은 말 그대로 함수 내부로 다시 진입하는 것을 의미한다. ‘다시’라는 말이 의미하듯이 함수 코드가 처리되는 와중에도 다시 함수 내부로 진입됨을 의미한다.&lt;/p&gt;
&lt;p&gt;윈도우 프로시저는 흔히 재진입 가능한 함수라고 표현된다. 이 내용을 보통 신입 개발자들은 &amp;#x3C;리스트 9&gt;와 같은 간단한 메시지 처리 루틴에서 WM_PAINT 메시지가 처리되는 동안 Sleep 상태일 때에도 키보드가 눌리면 다시 MyWindowProcedure가 실행되어 WM_KEYDOWN 이벤트가 처리되는 것이라고 생각한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 간단한 메시지 처리 루틴&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;MyWindowProcedure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND Window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT MsgId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM W&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM L&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MsgId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_PAINT&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_KEYDOWN&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OutputDebugStringA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;WM_KEYDOWN&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MsgId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; W&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 이는 잘못된 생각이다. 실제로 테스트해 보면 알겠지만 Sleep 상태인 동안에 키를 아무리 눌러본들 디버그 메시지는 출력되지 않는다. 이유는 무엇일까? 답은 메시지를 처리하는 방법에 있다. 일반적으로 많은 윈도우 개발 입문서에서 메시지 프로시저를 운영체제가 알아서 호출해 주는 것처럼 설명하지만 실제로 운영체제는 메시지 프로시저를 호출하는 일은 하지 않는다. 해당 일은 &amp;#x3C;리스트 10&gt;에 나타난 것과 같은 메시지 처리 루틴에 의해 이뤄진다. DispatchMessage 함수 내부에서 해당 윈도우에 맞는 메시지 프로시저를 찾아서 호출되는 일이 진행된다. 따라서 해당 메시지 처리가 완료되어서 다음 GetMessage가 호출되기 전까지 메시지 프로시저는 새로운 것을 처리하고 싶어도 할 수 없는 상태인 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 메시지 처리 루틴&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Msg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;TranslateMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;DispatchMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;Msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;재진입이란 말이 실제로 하고자 했던 이야기는 윈도우 프로시저는 스레드에 안전하며 병렬적으로 호출이 가능하도록 작성되어야 한다는 것을 나타낸다. &amp;#x3C;리스트 11&gt;과 &amp;#x3C;리스트 12&gt;를 보면 무슨 의미인지가 분명해진다. &amp;#x3C;리스트 11&gt;의 코드는 한 스레드에서 윈도우가 실행될 때와 두 스레드에 윈도우가 실행될 때 동작이 달라진다. 윈도우 의존적으로 처리되어야 하는 데이터가 정적 변수로 되어 있어서 다른 윈도우의 동작에까지 영향을 미치기 때문이다. &amp;#x3C;리스트 12&gt;의 코드는 윈도우 프로시저가 글로벌 크리티컬 섹션에 묶여 있어서 한 스레드의 메시지가 처리되는 동안에 다른 스레드에서 생성한 윈도우는 함수 내부로 진입하지 못하는 문제가 발생한다. 서로 다른 스레드의 윈도우는 상호 동작에 간섭을 받지 않아야 함에도 이 메시지 프로시저는 한 스레드의 메시지 프로시저가 완료되기 전까지는 다른 스레드의 메시지 프로시저가 처리될 수 없게 됨으로써 서로 원활하게 동시 실행이 처리되지 못하는 문제가 있다는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 11 스레드에 안전하지 않은 메시지 프로시저&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;MyWindowProcedure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND Window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT MsgId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM W&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM L&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; Count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MsgId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
　　&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_KEYDOWN&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
　　　　&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;Count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
　　　　&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Count &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
　　　　　　&lt;span class=&quot;token function&quot;&gt;OutputDebugStringA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;“WM_KEYDOWN”&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
　　　　　　&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MsgId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; W&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 12 병렬적으로 호출이 불가능한 메시지 프로시저&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;MyWindowProcedure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND Window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT MsgId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM W&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM L&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;EnterCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;GlobalCs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MsgId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
　　&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_KEYDOWN&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OutputDebugStringA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;“WM_KEYDOWN”&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LeaveSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;GlobalCs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MsgId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; W&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;재진입 가능한 함수란 &amp;#x3C;리스트 11&gt;이나 &amp;#x3C;리스트 12&gt;에 나타난 것과 같은 문제가 없어야 함을 말한다. 결국 이는 스레드에 안전한 함수보다 더 좁은 개념으로 기본적으로 스레드에 안전하면서 멀티 스레드 환경에서 잠금으로 인한 성능상의 이슈도 없어야 한다는 것을 의미한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[큐리오시티]]></title><description><![CDATA[얼마 전 올림픽 뉴스에 가려서 크게 보도되지는 않았지만 NASA…]]></description><link>https://jiniya.net/wp/archives/8604</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8604</guid><pubDate>Mon, 13 Aug 2012 23:58:21 GMT</pubDate><content:encoded>&lt;p&gt;얼마 전 올림픽 뉴스에 가려서 크게 보도되지는 않았지만 NASA의 큐리오시티가 화성에 착륙하는 이벤트가 있었습니다. 뭐 화성에 로보트를 보낸 게 처음은 아니지만 그래도 이렇게 또 보낸다는 건 말로 표현하기 힘들 정도로 대단한 것 같습니다. 이런 과학자들이 있기에 우리가 지금처럼 편리한 생활을 할 수 있는게 아니겠습니까? ㅋㅋ&lt;/p&gt;
&lt;p&gt;큐리오시티 착륙을 지켜보는 NASA 직원들을 보니 참 대단하다는 생각이 듭니다. 저같으면 저걸 차마 눈뜨고는 못 볼 거 같은데 말이죠. ㅋ~ 혹시나 내가 관여한 부분에서 오류가 나서 이 거대한 프로젝트가 실패할까봐서 말이죠 ㅋㅋ~ 우주선이 분리되지 않는다거나, 낙하산이 펼쳐지지 않는다거나, 커버가 떨어지지 않는다거나, 로보트를 연결한 부분이 끊어졌다거나 ㅋㅋㅋ~ 생각만해도 아찔하지 않나요?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://science.dongascience.com/articleviews/special-view?acIdx=11856&amp;#x26;acCode=1&amp;#x26;year=2012&quot;&gt;큐리오시티 관련 과학동아 기사&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://mars.jpl.nasa.gov/&quot;&gt;NASA 화성 탐사 프로젝트&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;직업이 직업인지라 동영상에서 500,000 LINES OF COD3. ZERO MARGIN OF ERROR. 라는 문구만 눈에 확 들어오는 군요. 이런 극도로 미션 크리티컬한 코드를 작성하는 사람들은 어떤 사람들인지 참 궁금합니다. 동영상을 보면서 느낀건데 탐사 로봇을 보내는 것 자체도 대단한 일이지만 일반인에게 자신들이 하는 일을 어필할 수 있는 동영상을 제작해서 발표하는 일도 NASA가 참 잘한다는 생각이 듭니다. 영상이 왠만한 영화보다 더 멋지네요. ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;예전에 어떤 다큐에서 본 것 같은데 화성을 나중에는 &lt;a href=&quot;http://en.wikipedia.org/wiki/Terraforming_of_Mars&quot;&gt;지구형 행성으로 개조하는&lt;/a&gt; 프로젝트를 진행할 수도 있다고 합니다. 테라포밍이라고 하는데요. 작금의 현실을 보니 정말 불가능한 일은 아닐거 같다는 생각도 드는군요. 후훗 2020 원더키디가 생각나는 지점입니다. 그러고보니 2020도 몇 년 남지도 않았네요 헐~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./큐리오시티.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/935ba0bb9d410e075f16c030f856a8ad/e224a/%ED%81%90%EB%A6%AC%EC%98%A4%EC%8B%9C%ED%8B%B0.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.315789473684205%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDAf/EABYBAQEBAAAAAAAAAAAAAAAAAAMBAv/aAAwDAQACEAMQAAABWNJ4qmin/8QAHBAAAQQDAQAAAAAAAAAAAAAAAgABETEDEiEi/9oACAEBAAEFAphHl1TemGj6LV//xAAVEQEBAAAAAAAAAAAAAAAAAAAAAf/aAAgBAwEBPwFX/8QAFREBAQAAAAAAAAAAAAAAAAAAAAH/2gAIAQIBAT8BiP/EABgQAAMBAQAAAAAAAAAAAAAAAAABERAh/9oACAEBAAY/AhcEyiuf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERUSExQWH/2gAIAQEAAT8hcjVMukjuFalUbehImRo8wf/aAAwDAQACAAMAAAAQHz//xAAXEQEBAQEAAAAAAAAAAAAAAAABACEx/9oACAEDAQE/EHELq//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQIBAT8Qwiw4X//EABoQAQACAwEAAAAAAAAAAAAAAAEAESExQVH/2gAIAQEAAT8Qa/2HkSgTvqjHkXmRVZ6+QCks9cwCAHlVMrg2GNAtT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;      md 0&apos; title=&apos;&apos; src=&apos;/static/935ba0bb9d410e075f16c030f856a8ad/e224a/%ED%81%90%EB%A6%AC%EC%98%A4%EC%8B%9C%ED%8B%B0.md_0.jpg&apos; srcset=&apos;/static/935ba0bb9d410e075f16c030f856a8ad/8ccab/%ED%81%90%EB%A6%AC%EC%98%A4%EC%8B%9C%ED%8B%B0.md_0.jpg 190w,
/static/935ba0bb9d410e075f16c030f856a8ad/ea4c8/%ED%81%90%EB%A6%AC%EC%98%A4%EC%8B%9C%ED%8B%B0.md_0.jpg 380w,
/static/935ba0bb9d410e075f16c030f856a8ad/e224a/%ED%81%90%EB%A6%AC%EC%98%A4%EC%8B%9C%ED%8B%B0.md_0.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;진정한 과학자라면 이 정도는 입어줘야 합니다.&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[한류 열풍의 불편한 진실: 애들이나 하는 게임?]]></title><description><![CDATA[약간은 씁쓸한 보통 사람의 게임에 대한 인식 김성주씨보다 카트라이더를 아는 사람이 더 많을지도 모른답니다 ㅠㅜ~ 얼마 전 흥했던 한 트윗입니다. 세대공감 1억 퀴즈쇼의 400…]]></description><link>https://jiniya.net/wp/archives/8297</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8297</guid><pubDate>Mon, 23 Jul 2012 23:58:20 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 445px; margin-bottom: 16px;&apos; data-url=&apos;./한류_열풍의_불편한_진실_애들이나_하는_게임.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a515d2bbd6b9e172aa2067cee2c425f9/a6969/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 80%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADh0lEQVR42mN4++blvXt3X7x4fuvWjWfPnr598/rp00cvXr78TwRgeP36+/PnX1+8+PHwwefnz7+8evn92bMvT558f/Xq/4cP/9+/+//ixf8PH3FofgmUe///7dt/L8CM9+//P38OIoHir17+f/0KhL58Rmj4BwdAzZ8+/v/65f+3byCl377+//79/5tX/z9//v/xE0iQgLMfPnp4+crV23fu3Lp79/qtOzdv3r587frjJ88+v//86eOnN5+/vPv0+dOHj29evgKi58+f37x548a1K7fu3nv48j2Dq4crAwODjIKctraqk4WRs60FKztXY1bBtpnL502eF9cyt2vWuuUTp7XlVE5v6EhKSNGzcZBUUZNW1QnMqWZISYhhYGSwtjD1sTGNdrCM8HQykJbrK6xaXNM/tWWqQ3h9Z8PkRa09nRkly3qnOti5KVk66Tj6S8qrB/h6MZRVlAnLy2soKkZ4eoT5+bm7u9rY2/fXtSyp6VjZP3vNhk0rJs9c0jJhbU1Jb36ajbObgaWll4+3va11fk4Ww7TpE1Jy02OyU5Mz02ID/LSMDXnkFUvjEvZPbNg+ZdbZEwc3L16+o61nW3VOUniwkKy8mKy8i6mRo45GdFgow5wDOyymT1mxakXQrFmKvRM6eycHtXTLdfQsmD8/d+YCuwVL5s5dkjxlZu3kSUmRiSIKKgbmtj62tta6OuGRUQxTdm1hau7qWLDAZNpsht7ptbMXu02az9A3s3nmErsJcxjaJ3VNX6DbM6t00dLqjAItUysnN187K1sVNY2k1DSGpfu2yk2aoDt7msbsmeLTZiktmKs4b77olDn6C2YrzpwrPHmu0YL5sjPnVc6dnxGXaOPg4OXu4WBnr6alHR4dzZCSnS5hom8UGmQaGqzj5qri6ChjY6ft4mrgHaXpGSNp7yrr7KPuFWrk6Obi4KShpm5saBAS5K+rqxsSEsLQ7BoVyiCaxa1TzKlbwaRdw6BVx6DTyqRnLWwmLKTJycopyiPNzy9nwqXQJ+BUzWRaKedS5RaTJGbWbhPFEOHiJsTAIMfMosTAosHAocnAocXAocHAxc7AysDAyMIApJiAqUiQgVWLgUuLgVuNTUBZSFKYgSXQwpGhvKXVNjDYKz7RzD1I29Rd28xL28xdy8zM0NTIxNTU2MzUyMzUxNzcwNxC08JK28Jaz9LRMSjayi8kp6oWAFeY8PQQN42IAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 0&apos; title=&apos;&apos; src=&apos;/static/a515d2bbd6b9e172aa2067cee2c425f9/a6969/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_0.png&apos; srcset=&apos;/static/a515d2bbd6b9e172aa2067cee2c425f9/08678/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_0.png 190w,
/static/a515d2bbd6b9e172aa2067cee2c425f9/2edd7/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_0.png 380w,
/static/a515d2bbd6b9e172aa2067cee2c425f9/a6969/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_0.png 445w&apos; sizes=&apos;(max-width: 445px) 100vw, 445px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;약간은 씁쓸한 보통 사람의 게임에 대한 인식&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;김성주씨보다 카트라이더를 아는 사람이 더 많을지도 모른답니다 ㅠㅜ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;얼마 전 흥했던 한 트윗입니다. 세대공감 1억 퀴즈쇼의 4000천만원이 걸린 문제였는데요. 작년 한 해 컨텐츠 산업에서 수출액이 높은 순서로 네 개를 나열하는 것이었습니다. 당연히 문제를 푼 분은 음악과 영화를 1, 2위로 지목해서 틀리셨지요. 사실 대부분의 분들이 한류하면 K-POP을 떠올리게 됩니다. 워낙 방송에서 K-POP, K-POP하니 그렇게들 생각하는 것이죠. 그리고 일반인들은 보통 게임은 애들이나 하는 거고 돈은 음악이나 영화가 훠얼씬 많이 벌 거라고 생각들을 하시죠. 하지만 이건 정말 말도 안되는 오해랍니다. 여러분의 그런 잘못된 오해를 바로잡기 위해서 데이터를 좀 모아 봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 584px; margin-bottom: 16px;&apos; data-url=&apos;./한류_열풍의_불편한_진실_애들이나_하는_게임.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4bd3efc3468f263b10ee70d4bc375533/f5818/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 52.10526315789474%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABjElEQVR42l1STU/CQBTsz/WgHj2bqMGgFxPjxZh49ORHTPyIEJVYjSKCoGigfHQL7e6228W0dKG01VcaAjKbbCbvvZk321T6ncFACF3XLcvS9S7GBO5uV1fVtmFghJDaVl23D2NRFCXzUhAEowl83xdCDMfwxxBiABgOhlDv9/tQ4ZxTSjWEGGOS67owOpgg0Vl2jxCCMbZJDNic2MEtYj9h//QY55LnebNJEoyCACYhSxCvj8ls1w+jx5Mzo1abFwMB5X+rKZIxzYm2Fjd58XUqThqmaTar1TCceiX1hIRhCBw5UWopzd8LU3Ewbpxmyldr20DCmSxzRiDeXE7zUkFyHce2bU948EBoHJxXjlfWQevH7x25rgNfFDZCImzAwb++aPaCjYVUHFvDVu76Xv36rLfUyuvb4VH2cmdfaymfX7X8U17OvVSe8x/V77vbl4eLbPbspizLGbm4u7pHyiWJ936QiphJLYt1kGZRSgiFPZSaBBMNdaiB4bdBqAO83WwpdaVRrytKgzH2B0frKXeDuK50AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 1&apos; title=&apos;&apos; src=&apos;/static/4bd3efc3468f263b10ee70d4bc375533/f5818/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_1.png&apos; srcset=&apos;/static/4bd3efc3468f263b10ee70d4bc375533/08678/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_1.png 190w,
/static/4bd3efc3468f263b10ee70d4bc375533/2edd7/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_1.png 380w,
/static/4bd3efc3468f263b10ee70d4bc375533/f5818/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_1.png 584w&apos; sizes=&apos;(max-width: 584px) 100vw, 584px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;2011 컨텐츠 산업 수출액 비교 자료&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;컨텐츠 진흥원에서 나온 실제 자료 그래프입니다. 문제의 답에서 출처로 사용된 자료랑 동일한 것인데요. 이렇게 보면 게임이 얼마나 넘사벽 압도적으로 수출액이 많은지 감이 옵니다. 딱 봐도 나머지 모든 분야의 컨텐츠 산업 수출 액수를 다 합쳐도 게임 하나보다 못하다는 사실을 알 수 있죠. 정말 불편한 진실이 아닐 수 없군요.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 606px; margin-bottom: 16px;&apos; data-url=&apos;./한류_열풍의_불편한_진실_애들이나_하는_게임.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/9b772adf9385a88d72e039404adeac5c/cec09/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 43.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABc0lEQVR42nVQSU/CQBTufyeeXEjQuMToSY4kLBqMwYQIxgNRZDNAO21ZugK2tbRDl5n62op60G8yM2/5vnnvDRP9wmq1UlVV1zUNtqrCJcuSDFuSBFHUNI0QQikNgmDjeWEYMp7n+VvYtm1ZFpymZX0ktpHCNA1YpgmctW3r+kKazd4Ng8EYw0upOAjCbxASungDxRVFgbCP8VLX57K8dtau66zxxnVdBjqJ/gGNKEmQOBQcmtj12hNbvfUJYaAaJFJqyvkRJ4gTCUhsU1Bndsv9o+Mwir4qb3mpfuv+0QwFzU62Mji/iMWvPZZ/aSfxuEOYBEZPmY7jLjQNIg4M6Tjwkb7vwZOZ/XL/9CwWH5xUm9ncwjBGQ7bV6hbzpW6jiVi01NXC3XMhd1nMV+qF68da4/6m3ntovnHC3mFpcJUPIspMprPZZDqfSwiJaIy4MeI5QRiziiRNphLPIgGJPMezwxE34vrdfqfd6XV7U1HEGH8CUJPxM92UY8YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 2&apos; title=&apos;&apos; src=&apos;/static/9b772adf9385a88d72e039404adeac5c/cec09/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_2.png&apos; srcset=&apos;/static/9b772adf9385a88d72e039404adeac5c/08678/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_2.png 190w,
/static/9b772adf9385a88d72e039404adeac5c/2edd7/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_2.png 380w,
/static/9b772adf9385a88d72e039404adeac5c/cec09/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_2.png 606w&apos; sizes=&apos;(max-width: 606px) 100vw, 606px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;2011 컨텐츠 산업 매출액 비교 자료&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그건 수출이니까 그렇고 전체 매출로 따지면 그래도 음악이나 영화겠지, 라고 생각하실 겁니다. 하지만 이것 또한 천만의 말씀. 만만의 콩떡입니다. 전체 매출을 보면 출판, 방송, 광고가 압도적으로 높은 것을 볼 수 있습니다. 하지만 여러분이 생각했던 그 음악과 영화는 여전히 힘을 쓰지 못하는 것 같군요. 영화 음악 다 합쳐본들 게임 하나 넘기가 힘들어 보입니다. 이쯤되면 컨텐츠 산업에서 게임이 차지하는 비중을 무시하진 못하겠죠?&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 632px; margin-bottom: 16px;&apos; data-url=&apos;./한류_열풍의_불편한_진실_애들이나_하는_게임.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/38edfb4e47645bca046c3a5f9a4e3d51/afa26/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 33.15789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABiklEQVR42h2O2U/iYBTF+zePT/NodB6cxBcTjDOTNC6JGokiEpjO1DKRUZZSKd2glJamlEKR2vXrAq3ihzf34dzl5HeQG6JOdET8eVBp8YUH6pERsSZbafKkPMXaQkfW7XQtWfHITl6iTPNWUBtBaoTZNEiRHIofoNWve/kvOxdbO+coWt4/vNvO/dn7ge/msOMzPH/17/svIndaw39TJ5dP347uC8XWTxQ7RTEkoqk3ntUqpcH1lVK6HZXvxlg545l3gV0PBIP427vOZyz9xjMZx0CRMvRa4KRiwSwVkfl87ns+1aZqtf+NRlNVVW08tm0nCADsoSTRna7rer4fhGHoeR48JUnCsZyijBDr9RWEgGGZRrNFtklJVmYzc6zrU9OMk0SWZYblAhCGURTFMfT7vp9m6VAeKqq6IcNVt0vXn+rVKtF+7liW5XwW3Pd7AkmSjusCAKDd/qzVaiWK/Q1ZkiTDMOCgaZoxmSwWi+VyGccxBIUAmOZsousw7QYcxdAJyTA2fHMd5wPaxWLK+kdXcAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 3&apos; title=&apos;&apos; src=&apos;/static/38edfb4e47645bca046c3a5f9a4e3d51/afa26/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_3.png&apos; srcset=&apos;/static/38edfb4e47645bca046c3a5f9a4e3d51/08678/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_3.png 190w,
/static/38edfb4e47645bca046c3a5f9a4e3d51/2edd7/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_3.png 380w,
/static/38edfb4e47645bca046c3a5f9a4e3d51/afa26/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_3.png 632w&apos; sizes=&apos;(max-width: 632px) 100vw, 632px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;중국 온라인 게임 순위 자료&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;중국 전체 온라인 게임 순위 자료입니다. 1, 2위에 나란히 국내에서 제작된 게임이 올라 있군요. 1위에 있는 크로스파이어는 중국에서 단일 국가 최다 동시 접속자 수로(350만 명이 넘는 것으로 추정) 기네스북에 오르기도 했습니다. 크로스파이어가 작년 한 해 중국에서 벌어들인 돈은 거의 1조원 가까운 것으로 추정되고 있습니다. 게임 하나가 말이죠. 그것도 한 국가에서. 더 욱긴 사실은 위 순위에서 1, 2위의 점유율을 합하면 50%가 넘는다는 겁니다. 게임을 하는 중국인 두 명 중에 한 명은 저 게임을 하고 있다는 말이죠. 지나가는 중국인 중에 크파나 던파를 아는 사람이 많을까요? 아님 소녀시대나 티아라를 아는 사람이 많을까요? 당연히 전 크파나 던파라고 생각합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_4.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;strong&gt;대륙을 뒤흔은 FPS 게임, 크로스파이어&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;아직도 감이 잘 안오는 분들은 위해서 잠깐 비교를 좀 해보겠습니다. 동방신기, 소녀시대, 보아 등으로 유명한 SM엔터테인먼트의 2011년 매출액은 1430억입니다. 원더걸스로 유명한 JYP는 99억, 2NE1으로 유명한 와이지엔터테인먼트는 781억의 매출을 올렸죠. 눈부신가요? 많아 보이시나요? 그런데 이 세 개 업체가 작년 한 해 동안 벌어들인 돈을 모조리 다 합쳐도 크로스파이어가 중국에서 벌어들인 돈보다 작습니다. 크로스파이어는 2011년 중국에서 1조원 가까운 매출을 올렸다고 했습니다. 국내 개발사와 퍼블리셔인 스마일게이트와 네오위즈는 수출 로열티로 3500억 정도를 벌어들인 것으로 추정됩니다. 중국에 게임 하나 수출해서 벌어들인 돈이 국내에서 가장 유명한 엔터테인먼트 회사 3개가 작년 한 해 동안 모든 지역에서 벌어들인 수입보다 많다는 이야깁니다. 이쯤되면 애들이나 하는 게임이라고 무시하긴 좀 그렇죠?&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 511px; margin-bottom: 16px;&apos; data-url=&apos;./한류_열풍의_불편한_진실_애들이나_하는_게임.md_5.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/524abfd15f9837ad9874face14759fc4/40f84/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 154.73684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAfCAIAAABoLHqZAAAACXBIWXMAAAsSAAALEgHS3X78AAAEtUlEQVR42mVV2Y7cRBT157M8IsEDj4h3nlAkAhKKAhIkUkgmM9MzPe1evFd5qc3lWs0p9yRCwqrRlNx165577jnXWTcOx6psKN1fzofigj0Zh0tT+xDW/z3SrUe5XtTaam2Czoqe7KrLiXaPVbGvi7ytsA5tJeyinGFGK2tmZ7FXVh+FftXy1514Q3cXmWeTVg2fKjb4GLAinnXFwg4LP/Fltt4jbS9FJ6YYsQ/a6pYNGd4OUhz7jgpeT6MPwLv9hYhFBMtpN80Sx6Z5fqLkidZm9Y4SvbtJwS2fctouzs7WuBQVrwtXIPN5oExrH9deyXyojkMxr0Y1tfzwPnPed5ydeoLkxUi1NQAerk8MuPfU0/uuFdazRTzS8317Yk7Vh/b88s9scQ6AZ7Mgj7uGbGXjvwuxYFM+DDtCmUGwPPb1Q1PI4Pp9Wf/8a2ady4fu7fnwsS7umqJLFxmUp51XPpwm9kD727YRRkszA9q+raY1rB/e+W+/yRbvR9K0l7wp8q66lMf9pW0ujHHjtV+xOY9dxXoXHEipp+FIW+FsmCZzOAC2pWw8d3U1kCPpctIe+n7fjzRV4mre77tKWwte1aIvI33qamaN7/vl/j4Fl9NQMbaEKF1gJnAblLXWW2RDq059x/Sc5LXo80By2gjvQk/N7W1iu+GcSqmsYzZI5xdvfSIrgLZOMAQgHjrheq6mwTrr1tUQutzcbJnZuKek5Wz2q4NA4nOr4xrJ1kWowHg32wUX7btauyWv+PnF7xnqgRKGeQYE4xyWD5/aHGOvxGWgR9qhKYCNW6hgSVdPdfXbH5kyC8Cce1zZ1Ntm2XTit2DUvAW3CGazeiINsCDYEpIIQ2ZIWiwarxLQuIb/ZIb4EAyGjbN8Vo9thVb7NaqJN3mRgp9I3bARxUObfnPFdSEa4isGirps8DgAIIAmcbIbxM1dhnaChgNp4R6wisrX+PzAmb3kqHNUAleBDdRotp5396f6pxcZaEA/HrsakSB2UAJvUAXOpVQSsAmQAwiMed+UHRuToT+8C99/lwgDGKgatFHJSzaUU9/yETeSbT20JcpBNqrUri0I5sEaRU34Px8zeBjA4Ec0aY3rFe7n5yoSuZjNzxyWJGLEReX+Uv7yOtPOjvgZGhrpMvYLbdFsn0SS/FxO465rpDEuLoOGli4Np6nmU9u8epNgo+/o5Im2W3kEWJAc8wz2LhnbESLRhWgmzU5DCwq3YFK/fpttM8DjqPXuOm7RIeuDdtB5EDCf8bODCY3zDgpHO5J4PV4saYY1bIIAkRNdBWDtw+wRGRF5GOj78iiX5KpByYe2xgzFno+iyssUDHqv0l98VA6WjMJhg2FggRMtxKhKbEsO8q5jmA+82J9T8KhkMY0V5xgd0uKzEDEGYGagI4KDlOvnQhmNdo5KJW8L3VR9GkPCWGm9chF+1t4ZlJ/UmWYoJA3NoFqwj2ohx+t49RjG45DZuBZjj0EHerYwt0U9T18MmV1TqGXZACZXTVJgSLg3f/uvv8xsWGs23dRFJ8WnMRA+L5gURCL/RpjADAPxW/Bf7qsvMuwwosqxh9fAWTLmszXj9WMiN7emOo2G+LlONfu72/DjD/8C0VXfQD+gPDQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 5&apos; title=&apos;&apos; src=&apos;/static/524abfd15f9837ad9874face14759fc4/40f84/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_5.png&apos; srcset=&apos;/static/524abfd15f9837ad9874face14759fc4/08678/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_5.png 190w,
/static/524abfd15f9837ad9874face14759fc4/2edd7/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_5.png 380w,
/static/524abfd15f9837ad9874face14759fc4/40f84/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_5.png 511w&apos; sizes=&apos;(max-width: 511px) 100vw, 511px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.gameshot.net/common/con_view.php?code=GA4fc77a1d28041&quot;&gt;전세계 게임 업체 매출 순위&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;매출액 기준 전세계 게임 업체 순위입니다. 1위는 스타, 와우, 디아로 유명한 블리자드군요. 2위는 피파로 유명한 EA입니다. 3위에는 크파와 던파를 중국에서 서비스하는 텐센트가 올라있군요. 밑으로 쭉쭉 내려가다보면 반가운 이름이 있습니다. 국내 게임 업체로 유명한 넥슨이 무려 11위에 랭크돼 있군요. 쫌 더 내려가면 낯익은 국내 게임 포털 사이트들도 하나 둘씩 이름이 보이기 시작합니다.&lt;/p&gt;
&lt;p&gt;잘 아시겠지만 국내 재벌 대기업들은 모두 고도성장기에 국가의 엄청난 드라이빙 포스를 받고 지금의 위치에 올라서게 되었습니다. 사실 국가의 전폭적인 지원이 없었다면 당연히 지금의 삼성전자, 현대차, POSCO도 없었을 겁니다. 하지만 게임 업계는 그런 것 하나 없이 맨땅에 헤딩해서 이런 놀라운 성장을 일궈 냈습니다. 그런데 칭찬은 못해줄 망정 국가에서 안티인 정책들을 많이 내놓는 것 같아서 정말 안타깝습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_6.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.dailygame.co.kr/news/read.php?id=58171&quot;&gt;스마일게이트 4년새 매출액 34배&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2011년 삼성전자 매출은 165조였습니다. 영역이익은 16조 2500억이었죠. 영업이익률이 10% 가량됩니다. 반면 넥슨은 1조 2000억의 매출에 5200억의 영업이익을 냈습니다. 영업이익률이 무려 43%에 육박합니다. 매출로 따지자면 160배가 넘는 차이가 나지만 영업이익으로 따지면 31배 가량 차이납니다. 스마일게이트의 매출 신장 그래프를 보니 앞으로 어떻게 될지는 모르겠다는 생각이 드는군요. 게임 산업은 확실한 고부가가치 산업입니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 614px; margin-bottom: 16px;&apos; data-url=&apos;./한류_열풍의_불편한_진실_애들이나_하는_게임.md_7.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a501f6bff990a688ea6690bddc5e6135/c42f5/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_7.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 69.47368421052632%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACT0lEQVR42jVSCXuiMBDl//+htl+3hxwi2qXtKl4oKkIghASQiihF94XtPq7Jm3sGpWmakT0ZfTjO3LUni61P3sdz8+1zutyYo0/PD13Pd+brXRCBH89Wk9lqPHOH7059vijVqTZ/jy3bmbmb0Z85nD+cpWa9L729atrOYgM/19v7IXUW3mK1m7lb+PffxsdTrVDGGWM0YTFNEsZCEoUh4VxQSuOYkkjSYRgFJJIyZR3DYEqTVMHTNzSjb+q6YVnWYGAahjEcDnu9156qjUYjQ9een56NvqHrOtQP9w8Da6BqGompgmjq68vj46Nu6HDQNc227ZeX5/u7O01VreHw6emXqvYgmwPLHAxcd7nqkLBUSXkWR2Tn+4REQRASQvz9vvuSXYeYxkEQgAukOiq/jsUBKFnKFZ6XlOdMHEReJryIWYYjzw6JKEAyXqTZATeY/IAZnctjJe+vSk57tg4/55vJ0l/7seP6H9ONPVl5fjxdBfN14Cx9dxuud9HCCxH3drtdr9fbfyh1XR86FEXxVZaZEHmeAYVEDjbLcvGDjHO5GjAwg6B8f39jC3s0hV0Sst1utjsf7WEKjKXNpTnVdVVVJ/wP9flUVcfj8XSCXINRkP18ufA0xYQQDPGThO79PWTsOeXyiuWyEwioKM+LPM8xMBQlnZE8TZmQ1WQi6wy6N76yVpGlUKNaIZXoub22bfeWzk1zgY4LmeFfc1gP/jDOUU6EIDItF4J3kTKBMhEFh5/MXbWIwDClpJPSlEtIuxyZ0TAs27bL2crcbdv+Ba1O8XcbdOncAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 7&apos; title=&apos;&apos; src=&apos;/static/a501f6bff990a688ea6690bddc5e6135/c42f5/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_7.png&apos; srcset=&apos;/static/a501f6bff990a688ea6690bddc5e6135/08678/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_7.png 190w,
/static/a501f6bff990a688ea6690bddc5e6135/2edd7/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_7.png 380w,
/static/a501f6bff990a688ea6690bddc5e6135/c42f5/%ED%95%9C%EB%A5%98_%EC%97%B4%ED%92%8D%EC%9D%98_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4_%EC%95%A0%EB%93%A4%EC%9D%B4%EB%82%98_%ED%95%98%EB%8A%94_%EA%B2%8C%EC%9E%84.md_7.png 614w&apos; sizes=&apos;(max-width: 614px) 100vw, 614px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;이 모든 사실에 너무 놀라실 필요는 없습니다. 아직 전반전 시작도 안했으니까요.&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[최고령 C++ 개발자는?]]></title><description><![CDATA[채널9을 보는데 재미난 슬라이드가 몇 개 있어서 캡쳐해 봤습니다. 사실 주제는 이게 아닌데 본론보다는 이 부분이 더 재미나더군요 ㅋㅋㅋ~ http://channel9.msdn.com/Events/TechEd/Europe/2012/DEV36…]]></description><link>https://jiniya.net/wp/archives/8185</link><guid isPermaLink="false">https://jiniya.net/wp/archives/8185</guid><pubDate>Wed, 18 Jul 2012 23:58:19 GMT</pubDate><content:encoded>&lt;p&gt;채널9을 보는데 재미난 슬라이드가 몇 개 있어서 캡쳐해 봤습니다.&lt;/p&gt;
&lt;p&gt;사실 주제는 이게 아닌데 본론보다는 이 부분이 더 재미나더군요 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://channel9.msdn.com/Events/TechEd/Europe/2012/DEV368?format=html5&quot;&gt;http://channel9.msdn.com/Events/TechEd/Europe/2012/DEV368?format=html5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./최고령_C++_개발자는.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/81ef9d33d4baf7fa9806fe5ee255d6d5/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 55.78947368421052%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACTklEQVR42mNQ9K/TiWzVjGg2Seg0jO3Uj+nUjmzTjWq1S+s1iuswTeg0TeiySOoGIsvkHiCS9q6W8oIiBlnfauWgBmXvWv/8KcV9y+qnruiavdI9d6JaSKNBTJtORIt6SJNGaJNWeDOQDWTAdYI0S3lVSnlVSbtWFbYuzMlI6ajKWzW7O6JihoBzGdASSc8qoCIJDyAJQjI+1fJ+tTLe1RD7GUA6varFvaqj6+dGhYd21JftXN2X1TJH0LlcMaBO1qdG1rcWqFTOt1bGp0bAqUzIpYLfqVzIuRyqGUhJ+tQE1C5sa6ieOalzx/q52U3ThFwr5P3qZKCaa4BILbihafaakglLExrmehZMlvGugdhcpRzcaJA/L7J1uWfpLMvUPqUAoD3VsiDbgHZWS/tUi3lU2KT0HL+258C2BQf3r1x/YItacBNIM9BjKsGNyhmzxJOmS8ZPlo7skQpolPWplvGqkvUG+hNI1ki4VvoWT5vUU76qq3r1jNbOGZNUgluhmhUC6tUyZ6lmzVXNnqeaM185Y45iwkT58Ha5wCbVwGYV/0Zpz5qw8lllmannD+yd19mUll2oFNIG0xxYr5Y9VzlrnnLaTKW0mQoJk5USJwNJ1diJWrETFcI65ENaVIKa7BL7PQumhZbPdErrBEYBRHO1vH+danSXckS7QkAdMJCB/lTwr1EJrFP0r1X1r1PzrdPwb9Dwr5f3qRb3qOBzKBV0KQfqgoY2CHkCI7xSGhSHoLCV9qpRCqwHxpAUMEphCCgu61OrGtwITC2qwQ0ApebsKkQWCdAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;    C        md 0&apos; title=&apos;&apos; src=&apos;/static/81ef9d33d4baf7fa9806fe5ee255d6d5/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_0.png&apos; srcset=&apos;/static/81ef9d33d4baf7fa9806fe5ee255d6d5/08678/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_0.png 190w,
/static/81ef9d33d4baf7fa9806fe5ee255d6d5/2edd7/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_0.png 380w,
/static/81ef9d33d4baf7fa9806fe5ee255d6d5/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_0.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;네. 92살의 최고령 간달프 느님께서 존재하십니다. 92살이시면 진짜 마법을 쓸 수 있을거 같지 않나요? ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;거의 대부분의 개발자가 2-30대에 포진한 것도 인상적입니다 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./최고령_C++_개발자는.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/724593dd7489b01c9505e71586d56e10/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 55.78947368421052%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABsElEQVR42mOQ862xS++3SukxSeg0S+qyTO7Wj25TD200TewyS+m1TOpS9K+T9KyW8sKCGKS9q7QjWjTDmpUDG1SCGlSDG5UC6kS9alRDmtwT2/Tju2V8aiXdy7FrlvKqEnOvBCJxjyoJjyoZ72pB9yrHiJrD7a1PJneZN22WL18vF9Yh5V4h5V2DRTOEJelVLedbqxrSaBjeurlryb85Pa+ntjl0bDOZeES/d59EeLuURyWafoRmIJLxrhF0KQ2vWL506dX1E3femzjdvGOXZv129/y1tkG94h4V0l64NUt714i4lKVN3LDw8MlF6xasWFCTm9ie7zOz32dCqmurmFeVNC5nA5GsdxWfc2NxZdDDzapbVqvEr4taGmW/yjagxWNykGuLCH7NwJAXca/VDcyZssSgeYeN4YbZ3RWxHwIl1/l4q7vXiXtX49MMRBqhDSohXWbpheGz0sy2bSppzdvno+fjlyjsVSONNaqQ+cBYlfOrEXerE/Wol4ttUomokXYv5/dsRNYp4QlEVUCErhmYmCQ9q6S8q6SADNdKcfdqca9aGVQ1SoENasGNKkGNAEvY4fIKrYGWAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;    C        md 1&apos; title=&apos;&apos; src=&apos;/static/724593dd7489b01c9505e71586d56e10/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_1.png&apos; srcset=&apos;/static/724593dd7489b01c9505e71586d56e10/08678/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_1.png 190w,
/static/724593dd7489b01c9505e71586d56e10/2edd7/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_1.png 380w,
/static/724593dd7489b01c9505e71586d56e10/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_1.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;C++이 가장 많이 사용되는 프로젝트는 다름 아닌 게임이라고 합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./최고령_C++_개발자는.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ebf5393ab70b4a683d27769380b4cc92/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 55.78947368421052%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABy0lEQVR42n2SW0/iYBCG+Q9euIqrKGZdFVyo6EYTNRs1ERAorE0LthVXjdF44VloscXS2haJrjHhEFx3PcXf4L/zLR5QLjZ5M990+s3M0+nYOsKHXk7vZ9SBhOZhdQ973EfneumcK666E9oXSuki5daA2OL/IEQgmz0oOqPZHkrpJOXuWM2JSA5Sgu+MZVG6bTbTHjr8/E6IvCS3BoQWv+DjzTXjIbhZpFJVWrik0pdwEpkrPvsvtl8hOJ1g9UHOko/XXYz6ktwWFJumDpbVe/P6cWzlNLRVwu3oXoXcKZO75chu+cfa7/GV05HFk1q+gTZuRqt3xuGOawRn4GthvSzKm4O8SbCGJc4YWsgj6GI0XMNovlLKe+z0yFJhLlUdWjABDOzk0Q2AZ7eKnnkd+gbL6t6aUKufVmstBSSLn/zCxOoZI/z5nsyD8+d+JbRdQmRy/Xw4mUdz0L6pEdsezPTMKV0RGTzP5X28AUJM3kJtUBzYuddfFRCbZ9LTGxeYtoWdqnLS32XtLrxTQgkMqUFo7qLrna0DML+U29GlQmi7SO6VgQ1+zByjJrj/YuPoCEuwWAZsSGdExsI44JCyMypbj3XhrYTNeU5+Amn/66vdNI8gAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;    C        md 2&apos; title=&apos;&apos; src=&apos;/static/ebf5393ab70b4a683d27769380b4cc92/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_2.png&apos; srcset=&apos;/static/ebf5393ab70b4a683d27769380b4cc92/08678/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_2.png 190w,
/static/ebf5393ab70b4a683d27769380b4cc92/2edd7/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_2.png 380w,
/static/ebf5393ab70b4a683d27769380b4cc92/dface/%EC%B5%9C%EA%B3%A0%EB%A0%B9_C%2B%2B_%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94.md_2.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;정말 이런 이유로 C++을 선택하셨나요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;‘학교에서 배워서…’라는 가장 중요한 이유 하나가 빠진 것 같군요 ㅋㅋ~&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 타이밍 전쟁]]></title><description><![CDATA[A Book On C란 책을 보면 C언어에서의…]]></description><link>https://jiniya.net/wp/archives/6006</link><guid isPermaLink="false">https://jiniya.net/wp/archives/6006</guid><pubDate>Sun, 08 Jul 2012 23:58:18 GMT</pubDate><content:encoded>&lt;p&gt;A Book On C란 책을 보면 C언어에서의 0의 의미에 대해서 설명하면서 시작을 합니다. 배열의 시작 인덱스 번호이기도 하고, 문자열의 끝을 나타내기도 하고, 거짓을 나타내기도 한다… 등등으로 말이죠. 이런 것처럼 게임보안에 있어서도 타이밍이란 참 다양한 의미로 사용되고 또 중요한 개념입니다. 오늘은 이 타이밍에 관한 내용에 대해서 좀 써볼까 합니다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;일단 게임보안 제품이 영원히 한 수 접고 시작할 수 밖에 없는 타이밍이 있습니다. 바로 실행 타이밍입니다. 게임보안 제품의 제1공리가 다름아닌 ‘게임보안 제품은 절대로 해킹툴보다 먼저 실행될 수 없다’이기 때문입니다. 이런 전제를 뒤엎기 위해서 바다 건너 P모 제품은 게임 실행과 상관없이 메모리에 상주하기도 합니다. 하지만 이래봐야 운영체제가 실행된 다음에 실행될 뿐입니다. 운영체제 실행 전에 해킹툴이 실행된다면 어쩔 수 없습니다. 물론 그런 극단적인 — 뭐 사실 크게 극단적이지도 않습니다. — 예를 가정하지 않더라도 P모 제품의 전략이 안통하는 가장 큰 이유가 있습니다. 게임보안의 특수성이 그 이유죠. 일반적인 보안 제품은 사용자가 해커로부터 PC를 보호하기 위해서 보안 제품을 사용합니다. 하지만 게임보안에서는 사용자가 곧 해커가 돼 버립니다. 따라서 상주해 있다고 하더라도 사용자가 해킹툴을 사용할 목적으로 프로세스를 종료해 버리면 끝납니다. 아주 은밀하게 구동하겠다구요. 물론 가능합니다. 하지만 그 은밀함이 지나치다보면 옆동네 백신 친구들하고 싸움이 납니다. 화가난 백신 친구들이 우리를 white rootkit으로 분류하고는 마구 삭제해 버리죠. 어쨌든 백신 친구들하고 싸우면 안됩니다. 친하게 지내야죠 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;이런 이유로 게임 실행 전이란 그 영역은 게임보안 제품에게는 영원한 미지의 영역입니다. 마치 우리에게 빅뱅 시점이 영원히 풀지 못할 것처럼 보이는 미지의 영역인 것처럼 말입니다. XIGNCODE는 이런 제약에 보다 효과적으로 대응하기 위해서 대부분의 기술을 차단(blocking)의 관점보다는 탐지(detection)의 관점에서 개발합니다. 왜냐하면 일단 먼저 시작할 수 없기 때문에 차단은 언제나 결국은 실패할 수 밖에 없는 방법이거든요. 역사적인 관점에서 게임보안을 살펴보면 이것도 약간 트렌드가 있는데요. 아주 초장기는 백신에서 차용한 탐지의 관점에서, 그러다가 후킹이 발전하면서 차단의 관점으로, 그러다 해킹툴 진영의 후킹 기술도 덩달아 발전하면서 다시 탐지의 영역으로 돌아오는 형태가 되고 있습니다. 현재 모든 게임보안 제품에서 말하는 차단의 형태는 바보들을 막기위한 껍데기라고 생각하시면 됩니다. 그렇다고 차단 기술이 완전히 의미없진 않습니다. 해킹툴을 만드려고 하는 사람들의 대다수는 그런 바보들이거든요.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;다음으로 게임보안에서 주로 이야기되는 타이밍은 무한(INFINITE)입니다. 게임 보안에서 INFINITE는 금기시 되어야 하는 것 중에 하나입니다. INFINITE가 뭐냐구요? 특정 이벤트나 메시지가 올 때까지 한없이 대기를 한다는 것을 의미합니다. 프로그래밍을 배울 때 개발자들은 동기화 이슈를 만들지 않기 위해서 INFINITE를 써야 한다고 배웁니다. 하지만 게임보안에서 INFINITE는 구린 제품을 만드는 직행 티켓이죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;게임_보안_타이밍_전쟁.md_0.png&apos; data-alt=&apos;모든 것이 언젠간 응답할 거란 너의 가정이 얼마나 쉽게 부서지는지 보여줄께!!!&lt;br&gt;&lt;br&gt;영원히 응답하지 않는 세계를 한 번 맛보렴.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 450px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/289ba5a5759f85a84128058aa3d8b3d3/31401/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.73684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAADW0lEQVR42nWRa2hbZRzG30lGk7Sr6xwUtB+EOm8oA9mXwQaCfhC/iSLtYt06e1m1lwXXbWYynLdKt7HMTkRowXUUx0CXtE3T7sTGY5o0Mell3U6adrZN1yTnfk5u55z3XJLj2QqCH/zz4+HPw/vw/OEFlW2ItRWpavHWtI4/1e7Ze8K7t82zp2XsMZ6a46O7m11PHnPVfnir/ujNWtsvpsbRnY1uU4PL9P5voOoT/xNt/v3n0DMji0edyPEBtHkAbbrqf6/f907fHdv3oXcvhd66GHGc/wn54qTD3gdskybbxM4jo6YGN6juQi0t3tfPe/3RBPLXA1/0wVRkZWI2MR5cHgtgntCKJ7TqmV0dDyWmY4m+4ek9jSNmm8v0gZEfB7s7EduXP/cPu30z82gs4Y9iKIb/vpydus9PYlkE49EEH1zlwmu5SBz3XnEOnup9rclp9Fc0eUFVh3dwLLiWYpJELs0Ut+jCJiMlWXmdhhu0ofI6BdNZhSpoTFHbIvil+N+HuwbBkYmKYwjY1Tl5J7IsivpDokgwIsNDipf4vMxmIc1LJCPiVJHLQ13Xy+Wyobomv312BNimLB9Ng8puZDRwVyzkKJLCcYIiSEMZmmFZDs9kCIKgadpwUltpQZSMrKrAN3tvgCafuRUF5m7EFVgyXAlCRZGhMZKkKIqqKpIoQQnKj8cwNU17VKzAQyevg2a/+cQMqOjx3Q5gOZ0hWS6T4Sg6S1F8Ok0TJKeoj17/O9tnazI82DMMWgKWj2eB+VP/zT/uGm5ehHkBCpJcEGC2IApQUUslraxvo5bKilZSy7ooCge6roP2oLUrAsy96C0Uy+tsmqRTKYaheaOTprOpFE2SHMvmcJxJpahcXtzuh7J0oPsG6Ahbe2JglyNw7XYgTTNrGWaT4AySOLuBs+tp4/O4TZIzdsPZJPmHJG/s8dW1/R1DOzqjVvs8ePpSvNb+62HHyJ8zYTQY+T/8M+FoNPbVoLu64cfqdrf51JLZvgjqBjZqnMk3hlZ4QWGEEiOo29DF/0DkZaiWh9CNHfa5qnMJy+l7Rh7U/ZB85lry2auJV52Lr1xZfPnywkuXF168uPBC//zz383v+3buuW/m9n0dq78Qrb8Qqfs8XPnZfasjbj2LWU5j/wBak4Frb+8lAgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;모든 것이 언젠간 응답할 거란 너의 가정이 얼마나 쉽게 부서지는지 보여줄께!!!&lt;br&gt;&lt;br&gt;영원히 응답하지 않는 세계를 한 번 맛보렴.&apos; title=&apos;&apos; src=&apos;/static/289ba5a5759f85a84128058aa3d8b3d3/31401/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_0.png&apos; srcset=&apos;/static/289ba5a5759f85a84128058aa3d8b3d3/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_0.png 190w,
/static/289ba5a5759f85a84128058aa3d8b3d3/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_0.png 380w,
/static/289ba5a5759f85a84128058aa3d8b3d3/31401/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_0.png 450w&apos; sizes=&apos;(max-width: 450px) 100vw, 450px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;모든 것이 언젠간 응답할 거란 너의 가정이 얼마나 쉽게 부서지는지 보여줄께!!!&lt;br&gt;&lt;br&gt;영원히 응답하지 않는 세계를 한 번 맛보렴.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;예를 들면 이런 겁니다. 게임보안 제품이 아주 은밀하게 중요한 부분에서 특정 윈도우에 SendMessage를 했다고 생각해 봅시다. 어떤 윈도우인지는 모르겠지만 말입니다. 일반적인 경우라면 메시지가 리턴되겠죠. 해커가 그 사실을 알았다면 어떻게 할까요? 윈도우를 만들어서 SendMessage에 응답을 하지 않도록 만들어버립니다. 당연히 보안 제품은 바보가 돼 버립니다. SendMessage 뿐만 아니라 그 모든 이벤트에 대해서 절대로 무한 대기를 해서는 안됩니다. 이런 것들은 굉장히 쉽게 공격당할 수 있는 포인트거든요. 그래서 게임보안 제품은 대부분의 경우에 타임아웃을 설정합니다. 해당 타임아웃 넘어 응답이 없다면 그 다음 프로시저를 진행할 수 있도록 말이죠.&lt;/p&gt;
&lt;p&gt;똑똑한 신입 게임보안 개발자들은 이런 이야기를 하곤 합니다. “그건 게임보안 제품이 게임과 별개로 동작하니깐 그런거죠. 게임이랑 한몸이 돼서 돌아가면 그렇게 하지는 못할것 같은데요. 그러면 게임도 같이 멈출테니까요?!?!”라고 말입니다. 정말 똑똑한 개발자군요. 우리 회사에 지원했다면 바로 채용했을 겁니다. 게임보안에서 가장 중요하게 생각하는 점을 제대로 짚긴 했습니다만 여기에도 맹점이 있습니다. 렌더링 스레드에 은밀하게 보안 코드가 추가되면 가장 좋긴 합니다. 하지만 다른 100만 가지의 문제를 야기 시키기도 합니다. 바로 랙이죠. 해커가 응답을 지연시키는 행위를 막을 순 있겠지만 정상적인 천만가지 상황에서도 렌더링 스레드가 지연돼서 화면이 프리징되는 문제가 만들어집니다. 그래서 렌더링 스레드에는 아주 섬세하고 조심스럽게 작성된 코드 외에는 추가하지 않는 것이 좋습니다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;음. 다음으로는 또 활성화 타이밍이 있습니다. 해킹툴이 실행된 시점이 아닌 게임 내에서 실제로 활성화되는 시점을 의미하는 말입니다. 요즘 출시되는 대부분의 해킹툴은 실행 시점과 활성화 시점이 같은 경우는 거의 없습니다. 왜냐구요? 보안 제품을 우회하기 위해서입니다. 고전적인 게임보안 제품들은 게임 런칭 시점 외에는 따로 해킹툴 검사를 수행하지 않았습니다. 그래서 해커들은 해당 보안 제품이 스캔한 다음 자신의 해킹툴 코드를 활성화 되도록 만들었습니다. 그러면 스캔이 이미 지나갔기 때문에 예전 방식으로도 손쉽게 보안 제품을 우회할 수 있기 때문이죠.&lt;/p&gt;
&lt;p&gt;게임보안 개발자들도 가만 있진 않았겠죠? 주기적으로 검사를 하도록 만들었습니다. 그랬더니 이번에 해커들은 어떻게 했을까요? 주기적으로 코드를 복원시킵니다. 즉, 초기 회피 타임과 주기를 알고 있다면 자신이 변조한 코드를 그 주기에 맞춰서 원본으로 돌려놓고 보안 제품 스캔이 끝나면 다시 코드를 변조하는 형태로 만들었다는 말입니다. 그 다음은요? 당연히 보안 제품 개발자들은 주기를 랜덤하게 해서 측정할 수 없도록 만들었답니다. 그래도 여전히 이 활성화 타이밍은 굉장히 중요한 부분입니다. 왜냐하면 검사 방식에 따라서는 비용이 너무 높아서 주기적으로 검사 하기는 힘든 것들도 있거든요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;게임_보안_타이밍_전쟁.md_1.png&apos; data-alt=&apos;게이머들은 매뉴얼 방식을 사용해서 인젝션 타이밍을 조절하기도 합니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 599px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2d85dd9677b6354bda06c24443d188c5/1906d/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 77.36842105263158%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACoElEQVR42nVSS08TURSe38WShLjGmGjC0pURjHFlULEFDLjQQKXBsGCD/AMjhlBAkj5pWuy0ZdpOZzov5tV5tNPHlM691zOliTHqyZmTM3fy3fN93xwq8ub1ajQa291d3dhYWFiYmZmZnZ29Pz//7PmLl0tPN548LuayhBCEEPkrqHtzc9F368XDw6/RyINHDzc3N78cHMS2t2NbW5/i8VcrkUQi8V/w0uLi8dnp5crK1fLy+48f1tfWYjs7e/v7n/f24vF4NPI2lUr9BmMyrTjsKHoSnCCopqlrWpPjeIZp5nLcZV7O5NjTM71QJIaJND1MVUOqimxnOrlYKPJ8i2EYQ9c7nY7tOO6Nal6V+nR5JIhWrc7lcsQf4cEAd7u408WeFzZuB9+OqWQy6TiOoii2bQNYliS6UmFF0eZb7jWjXf2snCTIcBgIYtDkEN8KGiw0uG3h0YhKp9OAbDQauq67rqveqJIoGppuwl2DgWpb5Wo11Nzv414PQ+16wGJK++Ligms27ya3223LsoCINQnHdeG8UqmAXdj3yTgg4zEZ3UINXzGmUsmUIiss2+R5HvCGYSiyXK5UuXJZS6bE0zPm+IRIcsDxiOODloAgRSlgm7jXp7LZrKZpdeBdb0iSDHjf94cQg8HI98FFulQiXg+5LrIs7LrYcZDjItDcH1DpTBrYlukywCVJArPDHzkJaOBTCcCTk38sSSaTCU2WZdM0QafneXcrMQZhCJmGAVswBU+TTBsAwwJ1ux2AgTeCIArhI0qybDiu3e0qQBsM+9/kQqEAAmE4KJdlBaqqabqq9gTJawlWvcGcn2O+hdptJCt4OJys5/QiKp/P1+v1arUKlWVZmFyr1ao0fX3+o/DtqHD0XaTLBGGQQIKA/Dn/F5+0FDE+rsznAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;게이머들은 매뉴얼 방식을 사용해서 인젝션 타이밍을 조절하기도 합니다.&apos; title=&apos;&apos; src=&apos;/static/2d85dd9677b6354bda06c24443d188c5/1906d/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_1.png&apos; srcset=&apos;/static/2d85dd9677b6354bda06c24443d188c5/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_1.png 190w,
/static/2d85dd9677b6354bda06c24443d188c5/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_1.png 380w,
/static/2d85dd9677b6354bda06c24443d188c5/1906d/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_1.png 599w&apos; sizes=&apos;(max-width: 599px) 100vw, 599px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;게이머들은 매뉴얼 방식을 사용해서 인젝션 타이밍을 조절하기도 합니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;물론 해커들만 이런 방법을 사용하는 것은 아닙니다. 사용자들도 이런 활성화 타이밍을 사용하는데요. 흔히 인젝션 딜레이라고 말하는 방법들이죠. DLL 인젝션 형태로 구동되는 해킹툴들은 언제 인젝션 하느냐에 따라서 해당 해킹툴이 탐지되기도 하고 안 되기도 합니다. 이런 취약성이 있을 때 쓸 수 있는 방법입니다. 예전에는 매뉴얼 인젝션 기능을 사용해서 게이머가 직접 판단해서 넣는 형태로 조작을 했습니다. 한 해킹툴 사용자가 탐지되지 않는 시점을 찾으면 커뮤니티에 방법을 공유합니다. 언제 게임이 뜨고 머가 나오고 3초 정도 있다가 넣으니까 되더라. 이 추상적인 문구를 토대로 그 글을 본 멍청이들이 모두 따라 해봅니다. 하지만 쉽진 않죠. 이런 백성들을 불쌍히 여긴 해킹툴 제작자가 버전업된 인젝터를 만들기에 이르렀는데요. 바로 인젝션 딜레이를 밀리초 단위로 지정할 수 있게 만든 것이죠. 그 이후로 커뮤니티에는 온갖 추상적인 이야기들은 사라지고 그 밀리초만 공유하게 되었다는 슬픈 이야기가 전해지고 있답니다. 하앍~&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;게임_보안_타이밍_전쟁.md_2.png&apos; data-alt=&apos;내가 바로 그 유명한 알타. 하지만 XIGNCODE는 1000개를 띄워도 한번만 검사할 뿐이고~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3ce1cbed7adc9512e5e579fc18a63543/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 55.263157894736835%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACjklEQVR42l3OSU8TYQCA4Q8vRhPj1Z+hFzU1kpAoSgQ1inhQDgi4JBhQqKHIoshiqylbLUhoQ1gLpcTGpZKGTUwNYe3Q6Uy/2ffpAKVQKBBZBL355vkBLxjz3WrpLKiyXi6vTzK8v1BrSevtyx8cfN7elV1jTTa2XanrTGvpuzPwLb/TnVfSdKqwHmSVJqRkg9RcAKb9FQIfC+HoIWxWFMKaHNGkRVVbXwhg1rrqSoP+taG4zdbk6LLrjadvPgVJ945czACX7gPgD9hhgCUCECIYnPdzhEJj7CFCmZyYelWQ2VCU1VCQ867ihc1iNn94rMsAunSguw0S7yaAUV8zS8v+uQA6T5AoSaI0g6sUJpFBkaOjw97pxtZ+W4+nt/fr3Pis2+PNzD+bmH7s/I2jZ1IB6P9epEoRiEEKsjAQJIMhCmfZkEjjAgklBKF7up2m2remyupua7PT6XK77MNfro94UhyOa8A3Y4ssxjiWxRaCJMZyENI4xZLawT8DJZ5b9Y2OWYx6a5neWlvT0WYb8XxGELN36qQPPQEU6dNadFORZYGXGJrFEYzGMBJFeTrMEQIT4lhhbcr701VSpH+Wl5P7qFz/st1S3+o6Z3IcByHizaIa29hYV1SFwAkqxNKQYQmGI3iWlA/QpLIwg44PODvs7R+t9o62rsF+99DQULVNByi+NBr5HY1GVlfXlpeWJVlhKEhABAYnJFmVJFESeV5bgqRgzGusemiqzC0uf6CvK2wssyQDBH9ChgQtrG1tba1EVkRBJEkKQkJVNUaQ+PByOLoejsYkbQWZZPw+EvmFz/lQOiCXNl0F86FEXvwhcGFVUeIb8e3t7Z2/7e7uxOObO3t7u/v7//yXwZz8B7eu2k9+676GAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;내가 바로 그 유명한 알타. 하지만 XIGNCODE는 1000개를 띄워도 한번만 검사할 뿐이고~&apos; title=&apos;&apos; src=&apos;/static/3ce1cbed7adc9512e5e579fc18a63543/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_2.png&apos; srcset=&apos;/static/3ce1cbed7adc9512e5e579fc18a63543/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_2.png 190w,
/static/3ce1cbed7adc9512e5e579fc18a63543/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_2.png 380w,
/static/3ce1cbed7adc9512e5e579fc18a63543/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_2.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;내가 바로 그 유명한 알타. 하지만 XIGNCODE는 1000개를 띄워도 한번만 검사할 뿐이고~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;또 다른 걸로는 게이머들이 많이 사용하는 용어이긴 한데 ‘알타’라는 말이 있습니다. 알집 타이밍의 준말인데요. 알집을 동시에 여러 개를 실행하는 것을 의미합니다. 알타50, 알타100등이 있는데요. 게임 실행 시점에 알집을 50개, 100개를 동시에 실행 시켜서 게임보안 제품이 알집을 검사하느라 해킹툴을 늦게 발견되도록 만드는 방법입니다. 대단하죠? 이토록 게임 해킹에 대한 사용자들의 욕망은 강렬합니다. 알타랑은 원리가 좀 다르긴 한데 자매품으로 Fraps 타이밍도 있답니다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;XIGNCODE는 이런 방법에 대응하기 위한 다양한 기법들을 사용합니다. 기본적으로 거의 모든 검사 항목에 캐시를 사용합니다. 동일한 오브젝트를 두 번 검사할 필요는 없잖아요. 또 알집과 같이 알려진 프로그램에 대해서는 아주 빠르게 검사할 수 있도록 화이트 목록을 저장해 두는 방법도 사용하죠. 그리고 지능적으로 해킹툴 같아 보이는 것들부터 먼저 검사하도록 만드는 방법을 사용하기도 한답니다. 결국 뭐 알타는 XIGNCODE에게는 무용지물이라는 말이죠.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;해커와 게임보안 개발자 사이의 신경전적인 타이밍도 존재합니다. 바로 릴리즈 타이밍이죠. 새로 제작된 핵툴을 배포하는 시점과 그 핵툴을 차단하는 업데이트를 적용하는 시점을 의미합니다. 이런데 신경전이 있냐구요? 네 엄청나게 있습니다. 그런데 이것도 사실 게임보안 개발자가 천만배는 불리합니다. 왜냐하면 &lt;a href=&quot;http://www.jiniya.net/wp/archives/5657&quot;&gt;지난 글&lt;/a&gt;에서도 보았듯이 게임보안 제품 업데이트는 수많은 인력의 엄청난 시간과 노력을 필요로 하기 때문입니다.&lt;/p&gt;
&lt;p&gt;그런 신경전을 거는 녀석들은 어떤 녀석들인지 알아볼까요? 여러분이 게임보안 개발자라면 언제 해킹툴이 새로 나오면 제일 짜증날까요? 네. 맞습니다. 짝짝짝 ㅋㅋ~ 불금이죠. 불타는 금요일 밤인데 이 녀석들이 업데이트를 하면 참 뷁스럽지 않겠습니까? 더 얄미운 녀석들은 해킹툴 사이트에 보라고 이렇게 공지를 한답니다. 참고로 해외 해킹툴입니다. 우리는 해킹툴을 이미 다 만들었는데, 한국시간으로 금요일 밤에 업데이트 하겠다. 핡~ 혈압이~ ㅠㅜ~ 이 바닥이 이렇습니다.&lt;/p&gt;
&lt;p&gt;멍청하게 당하고만 있을수는 없지요. XIGNCODE 개발팀에서는 진단 루틴을 하나만 만들지 않고 한번에 여러 개를 만든답니다. 그리고 지난 번에 알려준 것처럼 시스템과 시간에 따라서 다르게 액티베이션되도록 만듭니다. 불금이 왔습니다. 해커는 신나게 릴리즈를 하죠. 어떻게 될까요? 네. 사용자들 원성이 자자하군요. 해커는 멘붕 시츄에이션에 봉착합니다. 자기 PC에서는 되는 것도 같거든요. 이런 불일치가 많아지면 많아질수록 해커는 쉽게 포기합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;게임_보안_타이밍_전쟁.md_3.png&apos; data-alt=&apos;XIGNCODE 개발팀 화이트보드에 붙은 그 녀석의 아바타~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 178px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f30ee845b66455ca9b37d75d655f8a06/006cf/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 73.59550561797754%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACb0lEQVR42mN49uzZo0ePHj9+/PDhw+fPn799++bp48cvX70Esh8+ePAYL2AAagbpfPQIqOHgvv0T+yamxCaXF5afOH7i1atXQBMJaAaqePX69cZVa8xMbDkEpXj4xKUEpWwNLDZv2PTmzRs8+hmePHny4uXL4wcPOZjaystr8YjIcPGLiAqIKwhIGCqqHz106CVu+0Gagc6ryivSU9a11zFVllIS4hdTF5O1UtDQFJDMiIh+DdQMDhQsmoHW3rh0ycfOxVbHJMTEMtXa2kpJw0FZU19KUUlI1kRO9eyxoy9evXqEzXKGt+/f792yxVLDAIjCLKzm5cQnOTl66uh56+mK84vLcQtvXr78zbt3WF3O8OHjx/VLl6lKKvuamq8qTuxJiz/UXbysNLnC09VORUWaW+jg5s2vcAQbUPOHzavXakqr57g4nO0tvDa/7fr0siNNGUcb0vy01bSlFa6dPfP85ctHj7BpBkbS+RPHnQ0t022tznRkvdrQf3du7dUJBadbUoykpE0lZC8cOvDi9Wvsfn7+4sWdG9e9rF1cNfUOt2Vcn1l1qjX/YlvWtHhvQXY+F0WVXatWPscVYK9ev7l48oSNobmCmGJbqAfQzTemVq7LC9eRkpRg47eRVtiwYOHL16+x+/n582czOzplxWT5eUUzbMyuTSl4tLCm2MOKgYFFXVBciJG9uarmzdu32DXfvHzZ0dSCgYGBlYE93VT30dziV8tr6l3NxRjYRFk42RkYfIyMH925/fjp00cYSYXh5vmzWWGhzo5uLvZunWmJ99dNfL5r3uLCjIrgkHA371RPr31TO589eYw1iQEA6kRD+Uz8ktAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;XIGNCODE 개발팀 화이트보드에 붙은 그 녀석의 아바타~&apos; title=&apos;&apos; src=&apos;/static/f30ee845b66455ca9b37d75d655f8a06/006cf/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_3.png&apos; srcset=&apos;/static/f30ee845b66455ca9b37d75d655f8a06/006cf/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_3.png 178w&apos; sizes=&apos;(max-width: 178px) 100vw, 178px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;XIGNCODE 개발팀 화이트보드에 붙은 그 녀석의 아바타~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;신경전 이야기를 하니 예전 생각이 나는군요. XIGNCODE 역사상 이름이 가장 많이 거론된 해커가 한 명 있습니다. 얼마나 유명했냐면 개발팀 화이트보드에 그녀석 아바타 사진과 함께 WANTED가 붙기도 했죠. 걔 말고 그런 것이 붙었던 사람은 없었습니다. XIGNCODE 1.0시절 초창기 바이패스를 제작했던 녀석인데, 지금까지 그 녀석이 제작한 바이패스가 이론적으론 가장 완벽한 모델입니다. 그래서 우리는 아주 골치가 아팠죠. 그 녀석을 막기 위해서는 게임 서버에 있는 XIGNCODE 코드를 업데이트해야 했었거든요. XIGNCODE는 게임 서버가 구동 중인 상태에서도 업데이트가 가능하도록 설계는 돼 있지만 게임사에서 그렇게 하는 것을 별로 좋아라하지는 않습니다. 우리가 할 수 있는 업데이트는 일주일에 딱 한 번 정기 점검인 경우가 많았죠. 우리는 그 한 번의 샷을 최대한 활용하기 위해서 월화수목금토일 코드가 다르게 적용되도록 만들었답니다. 9-10개월 정도 지루한 공방이 이어졌지요. 그러다 세번째 버전인 XIGNCODE3가 나오면서 지금은 커뮤니티에서 자취를 감추었답니다. 다소 비극적인 결말이군요. SEH 하이재킹과 후킹을 참 잘하던 친구였는데. 적이었지만 실력은 인정해주고 싶은 친구였답니다. 부디 영원히 착하게 살아가길 ㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;전쟁에서 이기기 위해서 가장 중요한 것은 정보고, 그 다음으로 중요한 것은 타이밍입니다. 게임보안에서도 마찬가지입니다. 정보와 타이밍이 참 중요합니다. 같은 값이면 이런 것들을 잘 이해하고 있는 사람들이 만드는 솔루션을 쓰는 게 좋겠다고 저는 생각하는데 말입니다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;게임_보안_타이밍_전쟁.md_4.png&apos; data-alt=&apos;보안 제품 하나 바꿨을 뿐인데 핵툴 커뮤니티 소문 참 빠르네요. 왜일까요?&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 474px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/30daf1136d70bad5d3a94dd4ffec3b5c/823f8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 37.89473684210527%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABaklEQVR42nXQO0/CUBQH8G4kFIyAJqa0UPp+A5GBGARbXp9AwIQ4uUhIe/uwmDoq4mdkLISBkR3wFmKCif6Gc/733nOWi4yeR7Ztu64HADAt4DhRPh4d2/Z937LMie9vNpv9fr/b7fYnkHQ6g+NEgaIwLJvLkWSePEsmE2giHo+jKHqeSsViMYIg1us1nN5ut7+WLcvyPM+J2DC4rgvgFYiKaZqwj8fjtyCYz+er1SoMw8VRuFgul0itVqvXG43Gna7rsOuG0Ww2W612t9M9BkM32u1OpVKhaZo6gKFAFjiOQ4qRUqlcLhY1RVXhkKZp8EEURZ7nORbiFEUVhQjPCwzNSJIMA8swiCzJHMtLoiTwIkOziqzAjF1heBYniBzxI3cin8/jOM7AZemaVaqCdiOrVUGtisqharcCTmGZ9MXlP+A3YxiGvLyD108n+PL8KfA/wGRqBzPPn5mPT8P+fX/wMPhTr9cbDoff1dGfwmmrBWEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;보안 제품 하나 바꿨을 뿐인데 핵툴 커뮤니티 소문 참 빠르네요. 왜일까요?&apos; title=&apos;&apos; src=&apos;/static/30daf1136d70bad5d3a94dd4ffec3b5c/823f8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_4.png&apos; srcset=&apos;/static/30daf1136d70bad5d3a94dd4ffec3b5c/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_4.png 190w,
/static/30daf1136d70bad5d3a94dd4ffec3b5c/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_4.png 380w,
/static/30daf1136d70bad5d3a94dd4ffec3b5c/823f8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_4.png 474w&apos; sizes=&apos;(max-width: 474px) 100vw, 474px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;보안 제품 하나 바꿨을 뿐인데 핵툴 커뮤니티 소문 참 빠르네요. 왜일까요?&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;게임_보안_타이밍_전쟁.md_5.png&apos; data-alt=&apos;XIGNCODE는 해킹툴 제작자를 집으로 돌려보내는 유일한 솔루션이기 때문이지요.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/6d99b48ed0a2788e5988a9343ae9a7fd/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAA7CAAAOwgEVKEqAAAAC/klEQVR42lVTS08TURSeBRsSbWwbaKXtdPoA+pp22k4LKC0t1RX+CuPCBLAFTY1Ka0kf04f0xSN9mZQNBkMaiCgQFl0YiYkkoAnEuhJ8BBpYsbQPzy2Jid+c+e53TnLPuefcGSwcjkw+vu8Njk88HBsff+B0OkdHR8/OzprNZqPRqNfrIMrlstvt9vv9U1Men8/n8bbg8WCJeDKZmknPxeOJGUAiAUu8WCwuvVoqLi7mcrlSqeR0uthsDo7jIiEuEAgIgujqErDZbEwul6vVGoVCqVQoVUqlSqUGt6e7RyaTcbnc9vZ2Pp8/MnKnr3/AMmixWof6+/qUSiVJkr29CkyvN5hok57Sm2gzTdMgaNpEG40KhaIboQeSORwOPv+6mCDwFlgs1lWEK5haoyE1JBQkNRpUFFyShBWSUhQllcrgnNO+6UKhsNBCNpMFA8pmMhgcEypTOkqro4xGo05HGfQGrVYLBwFXLpPjInxrcxPGVqvVmv8DW1lZgalkWsjn8ygjSpoBhnih8BIiu7u7Jycnx8fHPxB+gri4uICLwA4PD6Elu93uGB6224dtNpvVYm25EHAMDNw0m806nQ5a06C+UFMw4/X1dVR5f39fKpXCMCTAsBAS9EoQQ7yrBaFQCJ0LWxCJRBwOG+4Pbd7b28NxMYTgbqRSiVgshuskCDFoSCLvhkfG4/M7Ojt4PF5nC21tbcvLy2hztVqFSc7NzqeSc8nEbCKeTiSQpVPzlyIeT8dicbBodAYsmUqn0umvlQrafDm3hXzU/fRuIOQKMK5AyBkMT0wHxoADzIQ/5AqFJyHIRB89eXZve/vNv8ljjWbjT632+9f3T5XP2c213LvV3MZqYetNFgnk5jfWwCCY31zLvC29/vC+XPm2cXBQOT9HleuNBvCXoyP5rdtSq01isQn6bxCDVonVRgzZebSZo6U6KAOX0nN1epZKfU1DYvDl5HLY5d8DXD09hc6i4fCLaBQYLBaJxEAyTDgUAmOCQQYEw0Qjkede78ednb/5PIzz2F+bLQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;XIGNCODE는 해킹툴 제작자를 집으로 돌려보내는 유일한 솔루션이기 때문이지요.&apos; title=&apos;&apos; src=&apos;/static/6d99b48ed0a2788e5988a9343ae9a7fd/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_5.png&apos; srcset=&apos;/static/6d99b48ed0a2788e5988a9343ae9a7fd/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_5.png 190w,
/static/6d99b48ed0a2788e5988a9343ae9a7fd/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_5.png 380w,
/static/6d99b48ed0a2788e5988a9343ae9a7fd/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%83%80%EC%9D%B4%EB%B0%8D_%EC%A0%84%EC%9F%81.md_5.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;XIGNCODE는 해킹툴 제작자를 집으로 돌려보내는 유일한 솔루션이기 때문이지요.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 랙에 관한 모든 것]]></title><description><![CDATA[#0 잘나가는 게임에서 가장 민감한 이슈를 하나 꼽으라면 랙이다. 모든 게이머들이 가장 싫어하는 단어 중에 하나고, PC를 업그레이드하는 가장 큰 이유 중에 하나가 랙이다. 그렇다면 도대체 그 랙(lag…]]></description><link>https://jiniya.net/wp/archives/7303</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7303</guid><pubDate>Fri, 06 Jul 2012 23:58:17 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;잘나가는 게임에서 가장 민감한 이슈를 하나 꼽으라면 랙이다. 모든 게이머들이 가장 싫어하는 단어 중에 하나고, PC를 업그레이드하는 가장 큰 이유 중에 하나가 랙이다. 그렇다면 도대체 그 랙(lag)이란 무엇일까? 랙이란 단어 의미 그대로 지연을 나타낸다. 게임상에서 발생하는 그 모든 지연에 대해서 우리는 랙이라고 이야기한다.&lt;/p&gt;
&lt;p&gt;요즘 가장 핫한 게임을 꼽으라면 단연 디아3를 빼놓을 수 없다. 처음 아시아섭이 혼잡해서 접속이 원활하지 않아서 북미섭에서 노멀을 클리어하면서 난 블리자드 장인 정신의 정수 그 자체를 맛보았다. 엔딩을 보고는 이제껏 단 한 차례도 보지 않았던 크레딧을 무려 5분이 넘게 봤다. 그 정도로 감동적인 게임이었고, 그 정도로 누가 만들었는지 궁금했다. 웃긴건 엔딩 크레딧을 5분 넘게 봤는데 안 끝나서 닫았다. 우리 회사의 한 직원은 15분을 봤는데도 끝나지 않아서 닫았다고 한다. 참고로 모든 엔딩 크레딧을 보는데는 대략 18분 정도가 소요된다. 역시 크레딧도 블리자드 스케일 ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_랙에_관한_모든_것.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5647c4e021823acbee1d83d9963251bb/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.89473684210527%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACvElEQVR42gXBSXPSUAAA4Nz1YK0bpBRoWUNIXgIhJCHbewkNSyAhlKVFoKtgbavWUbQuVUenrjMuMx0dHQ8649mDy0HHiz/M78MYyeZhDQclX8oMsvY83+LgsuWMUG1s2JtF72K5uQUrgwV70F3e2N8aDFsbnLWqVPv94Rg7OXUm4J89NR2YngpEfPMwRZWRZ9VXJfcSXd8NzbB4IBOJ6NEgZVKxj3b8ssokCfasP07xJnb8RGDqVOScj5gPMjVRbI0mzWd/UPtGZ+dwcP1llIRAWqo277BAW0bKA0+bNDUX6oDkFOhiZ07PBXzxEJ7mifyoUmzcfrt29Pfuw6f37x08enhYbm1euva85F2J0mVDdQblqquajgbZZEbRG1jYT4RxMhQA0RCPcsVesT668Xxncre/Nu7c+lAa7kNnOyKuzGaHiUwnl3U0sSRnYCwMJNnGwjMgEuLmQnlZrOlwqd5YLzXWGyvXq71tc/N1b/fF4sptt7vnLu0ZrSdq5YAGC2qhQSYlUXYwP87Golo0BgXeyRc8TvESlGF1dy9M3o33Pt88+N4fHa1vHS229xBcUXOLIF6k4iiE5yTFw6zsZiLMg4TJJIuK8yaSHz5Z+7G7+mV549Pl/d/D0Ve7997qvOLFIZ/xMqkSkzRBAiYDWUNzsdcXfphMu0AgnXZluc9Ihq1fW3fe3t/6tb/902u/zKKrGX3MUBYCVYWu0QmDiOvBGU5Wm9jEO/x28x9MWUqqIlIawy5M+8ljJ3DcT5MxwY+nY8FcMlEC8LEi7OhpRyAsLmnEZ2VZ72FE0EDk+XRQmPfFmCiQKBSdKwC6U0G30kKN4ip50DXVSbX3HUlrVBBwESM2B8+eBoJoYyBXz+YqTLaUSJP5vIR4PUNTPOAVoSBIBTmXBSTJEqGi0kCixoK0mncLhS4Jiqjc/g8oksYECmoU1gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                 md 0&apos; title=&apos;&apos; src=&apos;/static/5647c4e021823acbee1d83d9963251bb/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_0.png&apos; srcset=&apos;/static/5647c4e021823acbee1d83d9963251bb/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_0.png 190w,
/static/5647c4e021823acbee1d83d9963251bb/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_0.png 380w,
/static/5647c4e021823acbee1d83d9963251bb/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_0.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;strong&gt;랙으로 이런 화면을 접하게 된다면 모든 게이머는 뚜껑이 열리는 기분을 느낀다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그런 초대작 게임도 랙 이슈는 피해가지 못했다. 디아3는 사실 랙도 블리자드 스케일이다. 주로 서버 랙이라고 불리는 것들인데 이런 상황을 말한다. 내가 기술을 사용하고 2초 정도 있다가 실제로 기술이 발동된다거나, 내가 피통을 보고 적절한 시점에 힐링포션을 먹었음에도 랙 때문에 죽는다던가, 골드 위를 지나가고 2초 있다가 골드가 먹어진다거나 하는 상황을 말한다. 물론 그렇다고 클라이언트 랙이 전혀 없는 것도 아니다. 사양이 충분히 좋지 않은 환경에서는 몹이 대량으로 갑자기 출몰하는 지역이라던가 물리적인 시츄에이션이 겹치는 상황에서는 게임 화면이 프리징되는 경우도 종종있다. 경매장 랙은 말할 필요도 없겠다. 이런 랙은 정말 게임의 재미를 천만분의 일로 반감시키는 효과가 있다. 실제로 집에서 디아를 하다가 이런 연유로 챔피언 몹에게 한 세 번 눕고 나니 할맛이 나질 않아서 이 글을 쓰고 있기도 하다. ㅋㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;이쯤이면 랙이 뭔지는 충분이 이해했을 것 같다. 그렇다면 다음으로 이런 랙의 원인에 대해서 알아보도록 하자. 도대체 이런 빌어먹을 랙은 어디에서 오는 것일까? 도대체!!!&lt;/p&gt;
&lt;p&gt;가장 흔한 원인은 말 그대로 네트워크 지연 때문이다. 온라인 게임은 대부분 네트웍을 전제로 게임이 진행된다. 응당 서버/클라이언트가 있게 되고 이 사이에 통신 속도가 존재한다. 게이머들은 흔히 이를두고 핑(ping)이라 표현한다. 이 핑이 일정 수준 이상으로 높으면 지연이 발생하고 있다는 것을 직접적으로 말해준다. 지연 속도가 특정 수치 이상이 되면 불일치가 발생한다. 게임 클라이언트에서는 공격 모션이 나왔음에도 실제로 공격 대상에는 피해 수치가 적용되지 않는것과 같은 상황이 발생하는 것이다. 이게 점점 심해지면 어느 순간 자신도 모르게 멀미가 나오는 것을 느낄 수 있다.&lt;/p&gt;
&lt;p&gt;이런 온라인 게임의 네트워크 품질은 비단 자신의 인터넷 회선에만 영향을 받는 것은 아니다. P2P 방식으로 게이머들끼리 네트웍을 형성해서 진행되는 게임의 경우에는 다른 게이머의 네트워크 회선 속도에 자신도 같이 영향을 받는다. 빛의 속도에 근접하면 전혀 다른 세상이 펼쳐지는 것처럼, 핑이 일정 수준 이상으로 높아지면 개발자들이 전혀 예측하지 못했던 새로운 문제들이 발생하기도 한다. 이런 버그들을 악용해서 일부 게이머들은 랜선을 뽑았다 다시 연결하는 태핑이나 특정 패킷을 특정 주소로 무한대로 전송하는 누킹, 자신의 PC에 랙을 의도적으로 유발시키는 랙핵과 같은 방법을 사용해서 추가적인 이득을 얻기도 한다.&lt;/p&gt;
&lt;p&gt;랙의 또 다른 요인은 게임 서버에 존재한다. 최근 온라인 게임의 추세는 클라이언트는 뷰어 역할만 하고 게임 서버에서 모든 게임 상태를 모델링하는 방식으로 진화하고 있다. 왜일까? 당연히 해킹을 막기 위함이다. 디아3에서 간단한 조작으로 화면에 표시되는 골드 값을 변경할 수 있을지 몰라도 실제 그 표시되는 데이터로 경매장을 이용할 순 없는 것과 동일한 이치다. 실제 데이터는 서버에 모두 저장돼 있고 그 값을 토대로 계산이 진행되기 때문이다. 이렇게 서버가 복잡해지다보니 서버의 상태 이상이 고스란히 랙으로 전달된다. 내가 속해 있는 게임 서버의 상태 이상으로 모델링 처리 속도가 지연되면 그 모든 영향을 내가 그대로 받는다는 말이다. 최근에 블리자드는 디아3에서 짧은 간격으로 방을 자주 생성하는 것을 막겠다고 공지를 했다. 방을 자주 생성하면 서버에 상태 이상이 발생하게 되고 그게 해당 서버에 속한 다른 게이머들에게 피해를 주기 때문에 그같은 조치를 취했다고 생각할 수 있다. 이런 점들을 본다면 이런 종류의 랙에 대해서 게이머가 할 수 있는 것은 하나도 없다. 그저 손가락 빨면서 게임 개발사에서 서버를 안정화 시키기를 기다리는 수 밖에는 없다. 디아3 랙이 지금 답이 없는 상태와 같은 이치다.&lt;/p&gt;
&lt;p&gt;랙을 유발하는 마지막 이유는 모든 게이머가 잘 알고 있듯이 컴퓨터 사양에 있다. 컴퓨터 사양이 해당 게임을 구동할 수 있을 정도로 충분히 빠르지 않다면 필연적으로 심각한 랙이 발생한다. 이 경우에는 당연히 업그레이드 말고는 답이 없다. 물론 게임의 그래픽 옵션 사양을 낮추고, 해상도를 낮추는 방법을 통해서 어느 정도의 가용성을 확보할 수 있기도 하지만 실질적으로 쾌적한 게임을 즐기기 위해서는 컴퓨터 업그레이드가 유일한 답이다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;그렇다면 이렇게 게임의 재미를 반감시키고, 유저들의 원성을 사며, 동접을 저하시키고, 게임의 수익 창출을 방해하는 랙을 게임사는 도대체 왜 방치하는 것일까? 왜? 모든 게임마다 모든 게이머들은 랙 때문에 불평 불만을 하는 것일까? 원인이 명확하면 그냥 고치면 되는거 아닐까? 하지만 이 문제를 해결하는 일은 생각처럼 쉽진 않다.&lt;/p&gt;
&lt;p&gt;일단 회선 문제. 여기에 대해서 게임사에서 해줄 수 있는 것은 아무것도 없다. 우리 나라의 경우 회선이 아주 좋은 상태지만 해외의 경우에 그렇지 않은 경우도 많다. 정말 희한한 곳들이 많이 있다. 업로드/다운로드 트래픽이 제한된 곳, 인터넷인데 인터넷이 아니라 인트라넷인 경우, 심지어는 업데이트 패치를 제대로 받지 못해 수동패치를 제공해야 하는 경우도 적지 않다. 뭐 국내라고 마냥 좋은 것만은 아니다. 공유기에 공유기에 공유기에 공유기를 쓰는 환경이라던가. 회선 자체가 불량인 경우라던가. 악성 코드에 감염되서 핑이 불안한 경우라던가. 각종 시츄에이션이 다 있다. 하지만 게이머들은 충분한 기술적인 지식이 없기 때문에 자신의 이러한 인터넷 상태에 대해서 잘 알지 못한다. 그저 게임이 되지 않는다고, 핑이 튄다는 이야기를 한다.&lt;/p&gt;
&lt;p&gt;다음으로 서버 랙. 이 경우는 게임 개발사에서 해결을 해야 하는 문제다. 또한 어느 정도 분명한 원인을 가지고 있는 문제이기도 하다. 하지만 이것 또한 정말 쉽지 않다. 왜냐하면 99.98%의 서버랙 이슈는 사용자가 미치도록 몰리고, 게이머가 개발자가 전혀 예측하지 않은 형태로 플레이를 하면서 발생하기 때문이다. 라이브 환경에서만 문제가 발생하기 때문에 해결이 쉽지 않다는 말이다. 더욱이 요즘 게임 서버는 단순히 게임 서버 하나만이 아니라 우리가 상상할 수 없을 정도로 복잡한 구조로 다양한 서버들이 엮여 있기 때문에 랙이 발생해도 도대체 어떤 부분에서 무엇 때문에 지연이 되는지 찾는 일이 백사장에서 바늘 찾기만큼이나 어렵다. 이 문제를 안드로메다로 데려가는 마지막 이유는 게임이 일단 상용화에 들어가고 나면 게임 개발자가 멋대로 변경할 수 있는 것들이 극도로 제한된다는 점이다. 즉, 거의 대부분의 경우에 크리티컬한 이슈가 아니라면 서버 개발자는 이러지도 저러지도 못하는 상황에 처할 수 밖에 없다. 그래서 CBT를 하고 OBT를 하는데, 안타깝게도 요즘에는 그 마저도 아주 짧게 가져가는 추세다. 그래서 이런 이슈가 더 많이 부각되기도 하는 것 같다.&lt;/p&gt;
&lt;p&gt;끝으로 클라이언트 랙을 살펴보자. 이건 기본적으로 클라이언트 리소스가 크기가 정해지는 순간 개발자의 역량으로 할 수 있는 일은 상당히 제한된다. 요즘 게임은 워낙 규모가 크기도 하고, 그런 규모만큼이나 외부 라이브러리를 많이 사용하기 때문이다. 개발자의 열정으로 최적화를 시키던 시대는 쫌 지났다는 말이다. 사실 클라이언트 랙으로 사용자들이 욕을 하는 이유는 다른 곳에 있다. 바로 최소 사양과 권장 사양이다. 대부분의 게임사에서 권장 사양을 최소 사양으로 공지하는 경우가 많다. 그렇다보니 게이머들은 진짜 그게 권장 사양인줄 알고 자기 PC는 권장 사양보다 좋은데 랙이 발생한다고 징징되는 것이다. 사실 거의 대부분의 경우에 권장 사양은 실질적인 의미의 최소 사양이라고 생각하는 편이 정신 건강에 좋다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_랙에_관한_모든_것.md_1.png&apos; data-alt=&apos;디아블로3 권장사양. 귀가 막히고 코가 막힌다.&lt;br&gt;&lt;br&gt;우리집은 저거보다 훨씬 좋음에도 모든 옵션을 최소로 해야 그나마 랙이 들하다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 530px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4664e5b0039a62db06025d059243a7dc/a0177/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 47.368421052631575%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA0ElEQVR42nWRiw5EMBBF/f/P7SKk2Ch90S2+YY82+wpuJpPbeV4jM8bUdV0URVmWbdtWVaW1DhHbti3L8rxGNs+zVsoagzlrk83TNEiZ53nTNJNzp+a9z57e0081NkWPEaL5frs1QsT0CfbNDJBSdl33iOj7nmcfsa4rysM1MgaM40ipUmqI+DQzC04kcQg1XOHbzGZuRhp/Oj5V+zf+NqOekUIIlCMhreXgcOKQJIdz/O78yiZhLcfeoSNsBE/nXCLUnH8zOOr8kOSPPzmE8AK+X+Tgb0M05AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;디아블로3 권장사양. 귀가 막히고 코가 막힌다.&lt;br&gt;&lt;br&gt;우리집은 저거보다 훨씬 좋음에도 모든 옵션을 최소로 해야 그나마 랙이 들하다.&apos; title=&apos;&apos; src=&apos;/static/4664e5b0039a62db06025d059243a7dc/a0177/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_1.png&apos; srcset=&apos;/static/4664e5b0039a62db06025d059243a7dc/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_1.png 190w,
/static/4664e5b0039a62db06025d059243a7dc/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_1.png 380w,
/static/4664e5b0039a62db06025d059243a7dc/a0177/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_1.png 530w&apos; sizes=&apos;(max-width: 530px) 100vw, 530px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;디아블로3 권장사양. 귀가 막히고 코가 막힌다.&lt;br&gt;&lt;br&gt;우리집은 저거보다 훨씬 좋음에도 모든 옵션을 최소로 해야 그나마 랙이 들하다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;클라이언트 랙의 또 다른 이유는 서드파티 제품에 있다. XIGNCODE와 같은 외부 보안 제품도 그런 것들 중에 하나다. 이런 랙 이슈가 게임보안 제품 개발을 어렵게 만드는 이유 중에 하나이기도 하다. 어쨌든 이런 외부 보안 제품도 구동 비용이 0은 아니기 때문에 랙에 영향을 주고 사양에 따라서 미치는 영향이 훨씬 더 커지기도 한다. 안타깝지만 여기에 대해서도 게임 클라이언트 개발자가 해줄 수 있는 일은 사실상 없다. 서드파티 제품 개발자가 할 수 있는 부분이기 때문이다.&lt;/p&gt;
&lt;p&gt;게임 게시판을 모니터링 하다보면 많은 사용자들이 발적화를 운운하며 게임 개발자의 역량을 평가하는 글을 올리는 것을 볼 수 있다. 안타까운 마음에 여기에 몇 글자 덧붙이자면 대부분의 개발자는 거의 비슷한 성능의 코드를 작성한다. 적당히 뛰어난 개발자 A와 그저 그런 개발자 B가 작성한 코드에서 성능 차이는 사실 크지 않다는 말이다. 대부분의 드라마틱한 성능 개선은 개발자의 피땀어린 코딩보다는 문제를 바라보는 시각을 고치는 경우에 만들어진다. 또 그런 문제를 바라보는 시각을 고치는 일은 보통 프로그래머보다는 전산학자들이 하는 일이기도 하다. 그러니 발적화 운운하면서 너무 개발자를 욕하지 말자. 그들은 항상 최선을 다해서 자신이 아는 범위 안에서 가장 빠른 코드를 작성하는 사람들이다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;지금까지 주구장창 어렵다는 이야기만 했는데 사실상 이 문제를 힉스 입자를 발견하는 것과 동급으로 만드는 본질적인 이유는 다른 곳에 있다. 바로 게임 개발자, 운영자, QA, 서드파티 제품 개발자, 운영자, QA 모두 랙을 모른다는 것이다. 거의 대부분의 경우에 그 모든 사람들은 게이머가 말하는 랙을 전혀 이해도 하지 못한다. 왜 그럴까? 서로 체감하는 시간의 기준이 다르기 때문이다. 게이머들은 우리가 상상하는 것보다 훨씬 더 민감하다는 말이다.&lt;/p&gt;
&lt;p&gt;예전에 블리자드의 스타크래프트 개발자가 한국에 와서는 임요환 선수가 마린으로 럴커 잡는 것을 보고는 저런 식으로 플레이를 할줄은 상상도 못했다는 이야기를 했다. 그도 그럴것이 럴커는 마린의 상성 유닛이었기 때문이다. 임요환 선수 정도되면 어떤 것을 느끼냐면 럴커의 촉수가 평소보다 빨리 다가오는지 늦게 다가오는지 스팀팩을 쓴 다음 활성화가 어느 정도에 되는지를 느낀다. 물론 직접 물어본 거는 아니니 이걸로 태클걸진 말도록 하자 ㅋㅋ~ 일반 게이머 중에서도 잘하는 게이머들은 이런 아주 마이크로한 부분에 대해서 굉장히 민감하게 반응한다. FPS 게임이라면 총기를 교환하는 속도, 탄환이 발사되는 속도, 줌 속도, MMO 게임에서는 특정 기술이 발동하는 모션의 속도, 자신이 설치한 구조물들이 활성화되는 속도 등등 전혀 게임을 잘하는 사람이 아니라면 알 수 없는 부분에 대해서 불평을 한다. 이게 어려운 점이다. 왜냐하면 게임을 그 정도로 잘하지 않고서는 백날 죽었다 깨어나도 그 속도의 차이를 알 수 없기 때문이다.&lt;/p&gt;
&lt;p&gt;QA 팀에서 백날 랙 테스트를 해도 문제 없다고 하는 이유가 바로 여기 있다. QA 팀에는 실제 유저가 말하는 랙을 체감할 수 있을만큼 그 게임을 잘하는 플레이어가 없기 때문이다. QA 팀에서 봤을 때는 총기 교체 속도가 원래 만큼이나 충분히 빠르기 때문이다. 안타까운 현실이 아닐 수 없다. 이런 점들을 보완하기 위해서 우리같은 게임관련 서드파티 업체들은 항상 채용할 때 물어보곤 한다. 게임 잘 하세요? 좋아하는 온라인 게임 있으세요? 실제로 우리 회사에는 FPS 게임을 제법 잘하는 QA 직원이 한 명 있는데, 그 직원은 다른 직원보다 해당 분야의 게임에 대한 랙이나 핵을 찾는데 훨씬 더 뛰어난 역량을 보여준다. 실제로 게임사나 서드파티나 랙이란 문제에 대해서 진지한 접근을 하고 싶다면 랙을 이해할 수 있을만큼 뛰어난 게이머를 채용해야 한다. 그렇지 않고서는 백날 테스트 해봐야 도로아미타불이다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;이 글을 쓰던 당시엔 블소가 출시하기 전이었다. 최근에 블소 OBT가 진행됐고, 얼마전에 유료화를 단행했다. 하지만 그런 초핫한 게임인 블소 조차도 랙 이슈는 피해가질 못했다. 게시판을 봐도 블소 하는 사람들 이야기를 들어보아도 랙 이야기는 떠나질 않는다. 어쩌면 랙은 성공한 게임에 따르는 승자의 저주 같은건지도 모르겠다. 일단 사람이 몰려야 발생하니 말이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_랙에_관한_모든_것.md_2.jpg&apos; data-alt=&apos;캐릭터는 슈퍼 갑 블소~ 하앍~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c5dec375a3c9bf6484a6f60b4f2f7045/a3e66/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABQADBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAErqN1hOOj/xAAbEAABBQEBAAAAAAAAAAAAAAABAAIDERITFP/aAAgBAQABBQLmLEDMeaJaK6uoykr/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAcEAABAwUAAAAAAAAAAAAAAAAAARAREjEyQXH/2gAIAQEABj8CuVLJlxo03//EABsQAAIDAAMAAAAAAAAAAAAAAAABESExQVFx/9oACAEBAAE/Ic0tgj2NSwWraH2Vos05LwQVKkf/2gAMAwEAAgADAAAAEAzf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EBLS/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/EHSM/8QAHhABAAICAgMBAAAAAAAAAAAAAQARITFBsVFhgaH/2gAIAQEAAT8QtWEFONeYQ2Kac3fX7GFBmX2O4EHhqCjGG0YH1CL0UF5otn//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;캐릭터는 슈퍼 갑 블소~ 하앍~&apos; title=&apos;&apos; src=&apos;/static/c5dec375a3c9bf6484a6f60b4f2f7045/a3e66/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_2.jpg&apos; srcset=&apos;/static/c5dec375a3c9bf6484a6f60b4f2f7045/8ccab/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_2.jpg 190w,
/static/c5dec375a3c9bf6484a6f60b4f2f7045/ea4c8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_2.jpg 380w,
/static/c5dec375a3c9bf6484a6f60b4f2f7045/a3e66/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EB%9E%99%EC%97%90_%EA%B4%80%ED%95%9C_%EB%AA%A8%EB%93%A0_%EA%B2%83.md_2.jpg 480w&apos; sizes=&apos;(max-width: 480px) 100vw, 480px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;캐릭터는 슈퍼 갑 블소~ 하앍~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[스레드 열거하기]]></title><description><![CDATA[ToolHelp를 사용해서 스레드 열거하기 윈도우 환경에서 시스템에서 수행중인 스레드를 열거하는 가장 손쉬운 방법은 ToolHelp 라이브러리를 사용하는 방법이다. ToolHelp 라이브러리는 kernel32.dll…]]></description><link>https://jiniya.net/wp/archives/7676</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7676</guid><pubDate>Thu, 05 Jul 2012 23:58:16 GMT</pubDate><content:encoded>&lt;p&gt;ToolHelp를 사용해서 스레드 열거하기&lt;/p&gt;
&lt;p&gt;윈도우 환경에서 시스템에서 수행중인 스레드를 열거하는 가장 손쉬운 방법은 ToolHelp 라이브러리를 사용하는 방법이다. ToolHelp 라이브러리는 kernel32.dll에 포함된 프로세스/스레드/모듈 열거 관련 라이브러리를 말한다. kernel32.dll에 포함돼 있기 때문에 별도로 외부 파일을 별도로 설치할 필요 없이 바로 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;ToolHelp 라이브러리에서 스레드 열거에 사용되는 함수 원형이 &amp;#x3C;리스트 1&gt;에 나와 있다. 가장 중요한 함수는 CreateToolhelp32Snapshot 함수다. 이 함수는 호출 시점에 시스템 정보에 대한 스냅샷을 만들어주는 역할을 한다. dwFlags에 TH32CS_SNAPTHREAD를 전달하면 시스템에서 실행되고 있는 스레드 스냅샷을 생성할 수 있다. th32ProcessID는 무시된다. 함수가 성공하면 스냅샷 핸들이 반환된다. 해당 스냅샷 핸들은 사용하고 나서 CloseHandle 함수를 사용해서 닫아주면 된다.&lt;/p&gt;
&lt;p&gt;스냅샷 핸들을 만든 다음에는 해당 스냅샷에 포함된 엔트리 정보를 구할 차례다. 해당 엔트리 정보를 구하는데 Thread32First와 Thread32Next 함수가 사용된다. 각 함수는 첫 번째 엔트리와 다음 엔트리를 반환하는 역할을 한다. 엔트리가 없는 경우에는 함수가 실패한다. 각 함수의 첫 번째 인자에는 스냅샷 핸들을 두 번째 인자에는 정보를 반환 받을 구조체 포인터를 전달하면 된다. 이 때 주의해야 할 점은 구조체의 dwSize 필드를 함수 호출 전에 구조체 크기로 초기화 시켜주어야 한다는 점이다. 스레드 정보를 담고 있는 THREADENTRY32 구조체의 구조와 자주 사용하는 필드의 의미는 &amp;#x3C;리스트 2&gt;에 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 스레드 열거 관련 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HANDLE WINAPI &lt;span class=&quot;token function&quot;&gt;CreateToolhelp32Snapshot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD dwFlags&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD th32ProcessID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;Thread32First&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hSnapshot&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPTHREADENTRY32 lpte&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;Thread32Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hSnapshot&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPTHREADENTRY32 lpte&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 THREADENTRY32 구조체&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;tagTHREADENTRY32&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  DWORD dwSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 구조체 크기&lt;/span&gt;
  DWORD cntUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  DWORD th32ThreadID&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 스레드 아이디&lt;/span&gt;
  DWORD th32OwnerProcessID&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 스레드가 포함된 프로세스 아이디&lt;/span&gt;
  LONG  tpBasePri&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 스레드 우선순위&lt;/span&gt;
  LONG  tpDeltaPri&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  DWORD dwFlags&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; THREADENTRY32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PTHREADENTRY32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ToolHelp 라이브러리를 사용해서 시스템에 수행중인 스레드를 열거하는 프로그램이 &amp;#x3C;리스트 3&gt;에 나와 있다. 각 스레드의 프로세스 아이디와 스레드 아이디를 출력하는 역할을 한다. thread1 프로그램의 실행 결과는 &amp;#x3C;화면 4&gt;에 나와 있다. 화면을 살펴보면 알 수 있겠지만 이 프로그램은 시스템에 수행중인 모든 스레드를 열거하는 역할을 한다. 특정 프로세스에 포함된 스레드 정보를 구하고 싶다면 각 엔트리의 th32OwnerProcessID 필드 값으로 필터링 하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 thread1 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;tlhelp32.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Visitor&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; BOOL &lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; Visitor&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;THREADENTRY32&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ThreadVisitor&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL
&lt;span class=&quot;token function&quot;&gt;EnumThreads&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ThreadVisitor &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;visitor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE snapshot&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    THREADENTRY32 te32&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    snapshot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateToolhelp32Snapshot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TH32CS_SNAPTHREAD&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;snapshot &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; INVALID_HANDLE_VALUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    te32&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dwSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;te32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Thread32First&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;snapshot&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;te32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;snapshot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;visitor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;te32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;snapshot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Thread32Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;snapshot&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;te32&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;snapshot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ThreadPrinter&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ThreadVisitor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; BOOL &lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;THREADENTRY32 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;PID =&gt; %5d, TID =&gt; %5d\n&quot;&lt;/span&gt;
                 &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;th32OwnerProcessID
                 &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;th32ThreadID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ThreadPrinter printer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;EnumThreads&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;printer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_열거하기.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/22203cc16cd21ea10d8ff4234a85b905/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.89473684210527%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABfklEQVR42pWRa0sCQRSGx1u6qyV5WXfm7OrurLsqKpqZ9d8qCCIwMEtYrW3zlmWZFCoEQX+uEUvoQ7CdeTkf5szD+zIHPU5nk/n7w3RujSad4bhhj07N7lmn335e2G8f5tP88OLmqGkdN62TVvdy8NKfzMavi887yz6vo2hkW6E0n88DQEpR2fH6vAGOW2vDH/iR3x/g+GDI4/NRI3M7GKFQkAeQMrouCAImRJIAIeRyudAftRoRQnrDexTkeQKgL+F4LC5I4AgGQroDBnMBEWNNo9FoREgkCMaOYCAdu4fCmyEGZzIGxlhOpmRZcgaDadkovLWJCRh6WhRFBjuNDdBq3yCe4yRZ1qgajbDYLAT+hzP77aSiZA0jLghLZ8lhbGLedlnsLUWluVyWmapUY4tmM7fb43K7v/Wr2MTDHjCPNoNXe6aqEo/FCAEsig73fNW+RrlCsbK3X6nWCqWd3dpBsVSWFVVWqaKl1bTOOiRTay3vaZrIqXKlelpvfAGRXlf2U+PJvQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         md 0&apos; title=&apos;&apos; src=&apos;/static/22203cc16cd21ea10d8ff4234a85b905/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/22203cc16cd21ea10d8ff4234a85b905/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_0.png 190w,
/static/22203cc16cd21ea10d8ff4234a85b905/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_0.png 380w,
/static/22203cc16cd21ea10d8ff4234a85b905/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_0.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 4 ToolHelp 라이브러리를 사용해서 스레드를 열거한 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NtQuerySystemInformation을 사용해서 스레드 열거하기&lt;/p&gt;
&lt;p&gt;NtQuerySystemInformation 함수는 원래 문서화되지 않은 NT 커널 내부 함수였으나 워낙 강력한 기능을 가지고 있고 다양한 곳에서 광범위하게 사용되면서 현재는 MSDN을 통해서 일부 기능이 공개된 상태다. &amp;#x3C;리스트 4&gt;에 함수 원형이 나와 있다. 함수의 구조는 단순해 보이지만 처음 이 함수를 사용하면 생각보다 사용 방법이 만만하진 않다. 우선 파라미터부터 차근차근 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;첫 번째 인자는 어떤 정보를 구하고 싶은지를 나타낸다. SYSTEM_INFORMATION_CLASS는 함수 원형 다음에 나와 있는 것과 같이 선언된 열거형 자료 구조다. 중간 중간 값이 비어있는 부분이 있는데 해당 부분은 외부로 공개되지 않은 기능이라고 생각하면 된다. 실제로는 0번부터 차례로 모든 번호에 해당하는 자료가 구해지도록 되어 있다. 이번 시간에 우리가 사용할 스레드 정보를 구하기 위해서는 5번으로 선언된 SystemProcessInformation을 사용하면 된다. 해당 값을 전달하면 현재 수행 중인 프로세스 목록과 각 프로세스 내에 포함된 스레드 목록에 대한 정보가 반환된다.&lt;/p&gt;
&lt;p&gt;두 번째 인자는 해당 정보를 전달받을 버퍼를 전달한다. 이 버퍼는 우리 쪽에서 할당해서 전달해야 하며 첫 번째 인자인 SystemInformationClass에 따라서 미리 약속된 형태로 자료가 반환된다. 세 번째 인자인 SystemInformationLength는 두 번째 인자로 전달한 버퍼의 크기를 나타낸다. 마지막 인자인 ReturnLength는 해당 정보를 기록하기 위해서 필요한 버퍼의 크기를 전달 받는 곳이다. 만약 전달한 버퍼가 전체 정보를 저장하기에 부족하다면 NtQuerySystemInformation 함수는 에러를 리턴하고 필요한 크기를 ReturnLength에 전달해 준다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 NtQuerySystemInformation 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;NTSTATUS WINAPI &lt;span class=&quot;token function&quot;&gt;NtQuerySystemInformation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    SYSTEM_INFORMATION_CLASS SystemInformationClass&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    PVOID SystemInformation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    ULONG SystemInformationLength&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    PULONG ReturnLength
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_SYSTEM_INFORMATION_CLASS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    SystemBasicInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemPerformanceInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemTimeOfDayInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemProcessInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemProcessorPerformanceInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemInterruptInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemExceptionInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;33&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemRegistryQuotaInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;37&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    SystemLookasideInformation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; SYSTEM_INFORMATION_CLASS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수의 사용법을 어렵게 만드는 요인은 바로 리턴되는 버퍼 구조가 명확하지 않다는 점이다. 함수를 범용적으로 사용할 수 있도록 디자인해서 리턴되는 버퍼 구조가 함수 원형을 통해서 명시화되지 않기 때문이다. 따라서 이 경우에는 개별 항목별로 리턴되는 자료의 형태를 개발자가 일일이 숙지하고 있어야 한다.&lt;/p&gt;
&lt;p&gt;SystemProcessInformation를 전달해서 NtQuerySystemInformation 함수를 호출하면 &amp;#x3C;리스트 5&gt;에 나타나 있는 RSYSTEM_PROCESS_INFORMATION 정보와 &amp;#x3C;리스트 6&gt;에 있는 RSYSTEM_THREAD_INFORMATION 구조체 정보가 리턴된다. 각 구조체에서 자주 사용되는 필드는 설명과 함께 진하게 표시되어 있기 때문에 해당 내용을 참고하도록 하자. &amp;#x3C;그림 1&gt;에는 실제로 버퍼에 어떤 구조로 정보가 리턴 되는지가 나와 있다. 그림에서 SPI는 RSYSTEM_PROCESS_INFORMATION 구조체를 STI는 RSYSTEM_THREAD_INFORMATION 구조체를 나타낸다. SPI 구조체는 현재 실행된 프로세스 개수만큼 존재하며, STI 구조체는 각 프로세스에서 실행된 스레드 개수만큼 SPI 구조체 뒤에 따라 붙어 나온다. 이 구조를 열거하기 위해서는 SPI 구조체에 포함된 두 개의 필드가 중요하다. 첫 번째 필드인 NextEntryOffset은 현재 SPI 구조체 포인터에서 다음 SPI 구조체가 있는 곳까지의 오프셋이 저장돼 있다. 두 번째 필드인 NumberOfThreads에는 해당 프로세스에 몇 개의 스레드가 포함돼 있는지가 나와 있다. 따라서 이 필드에 저장된 개수만큼 STI 구조체가 이어진다고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_열거하기.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/9b36c9c74fcae7d91124a8667fb01f0f/06341/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 20.52631578947369%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAk0lEQVR42j2P2Q6FIBBD+f9P9AkT9MoiCu65KJ5AYp9Kpy0z4l+QUrrvW0rpnIsxGmN+BVrrfd+VUl3XPc+D7fMDsa4r42maruuy1o7jGEKgAuK9h3xPDCjHcdBOip9E3/fLsjDjTYUroKXGUOZ5tgXnecIJo2/b1rataJoGRpIKKnXBMAz4qshe9YScM6fVhSt5AZNH4b59Bc6LAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         md 1&apos; title=&apos;&apos; src=&apos;/static/9b36c9c74fcae7d91124a8667fb01f0f/06341/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_1.png&apos; srcset=&apos;/static/9b36c9c74fcae7d91124a8667fb01f0f/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_1.png 190w,
/static/9b36c9c74fcae7d91124a8667fb01f0f/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_1.png 380w,
/static/9b36c9c74fcae7d91124a8667fb01f0f/06341/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_1.png 512w&apos; sizes=&apos;(max-width: 512px) 100vw, 512px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;그림 1 SystemProcessInformation 버퍼 리턴 구조&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 SYSTEM_PROCESS_INFORMATION 구조체&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_RSYSTEM_PROCESS_INFORMATION&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG NextEntryOffset&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 다음 프로세스 정보 오프셋&lt;/span&gt;
    ULONG NumberOfThreads&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 이 프로세스 포함된 스레드 개수&lt;/span&gt;
    LARGE_INTEGER WorkingSetPrivateSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG HardFaultCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG NumberOfThreadsHighWatermark&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONGLONG CycleTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 프로세스 수행에 소모된 사이클 시간&lt;/span&gt;
    LARGE_INTEGER CreateTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 생성 시간&lt;/span&gt;
    LARGE_INTEGER UserTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 유저 모드에서 수행된 시간&lt;/span&gt;
    LARGE_INTEGER KernelTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 커널 모드에서 수행된 시간&lt;/span&gt;
    UNICODE_STRING ImageName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 프로세스 이미지 이름&lt;/span&gt;
    ULONG BasePriority&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HANDLE UniqueProcessId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 프로세스 아이디&lt;/span&gt;
    HANDLE InheritedFromUniqueProcessId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 부모 프로세스 아이디&lt;/span&gt;
    ULONG HandleCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG SessionId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG_PTR UniqueProcessKey&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T PeakVirtualSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T VirtualSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG PageFaultCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T PeakWorkingSetSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T WorkingSetSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T QuotaPeakPagedPoolUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T QuotaPagedPoolUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T QuotaPeakNonPagedPoolUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T QuotaNonPagedPoolUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T PagefileUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T PeakPagefileUsage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    SIZE_T PrivatePageCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LARGE_INTEGER ReadOperationCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LARGE_INTEGER WriteOperationCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LARGE_INTEGER OtherOperationCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LARGE_INTEGER ReadTransferCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LARGE_INTEGER WriteTransferCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LARGE_INTEGER OtherTransferCount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; RSYSTEM_PROCESS_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PRSYSTEM_PROCESS_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 SYSTEM_THREAD_INFORMATION 구조체&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_CLIENT_ID&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE UniqueProcess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 프로세스 아이디&lt;/span&gt;
    HANDLE UniqueThread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 스레드 아이디&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; CLIENT_ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PCLIENT_ID&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;_RSYSTEM_THREAD_INFORMATION&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    LARGE_INTEGER KernelTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 커널 모드에서 수행된 시간&lt;/span&gt;
    LARGE_INTEGER UserTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 유저 모드에서 수행된 시간&lt;/span&gt;
    LARGE_INTEGER CreateTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 생성 시간&lt;/span&gt;
    ULONG WaitTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID StartAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 시작 주소&lt;/span&gt;
    CLIENT_ID ClientId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 프로세스/스레드 아이디&lt;/span&gt;
    ULONG Priority&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    LONG BasePriority&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG ContextSwitches&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    ULONG ThreadState&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 현재 스레드 수행 상태&lt;/span&gt;
    ULONG WaitReason&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 대기 사유&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; RSYSTEM_THREAD_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;PRSYSTEM_THREAD_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 7&gt;에는 앞서 설명한 내용을 토대로 NtQuerySystemInformation 함수를 사용해서 시스템에서 실행중인 스레드를 열거하는 예제가 나와 있다. 여기서 주의 깊게 살펴볼 점은 NtQuerySystemInformation 함수를 반복적으로 호출하는 부분이다. 통상적으로 NtQuerySystemInformation과 같은 함수는 버퍼 크기를 0으로 해서 필요한 버퍼 크기를 구한 다음 해당 크기만큼 버퍼를 할당하고 다시 호출해서 값을 반환 받는 형태로 사용한다. 그런데 이 때 주의해야 할 점이 이 두 함수를 아주 짧은 시간 간격으로 호출하겠지만 시스템에서는 그 사이에도 스레드가 생성된다는 점이다. 따라서 바로 이어서 호출하는 두 번째 호출이 실패할 수도 있다. &amp;#x3C;리스트 7&gt;의 프로그램은 이런 문제를 해결하기 위해서 반복적으로 성공할 때까지 호출하도록 되어 있다. 또한 NtQuerySystemInformation 함수에서 제공받은 버퍼 보다 NTQSI_BUFFER_MARGIN만큼 더 크게 할당해서 재 호출을 하는데, 이렇게 하는 이유는 NtQuerySystemInformation 함수의 호출 회수를 줄이기 위함이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 thread2 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;winternl.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;STATUS_INFO_LENGTH_MISMATCH&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;0xC0000004&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;XGetPtr&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;base&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;base&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;NTSTATUS&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;NtQuerySystemInformationT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SYSTEM_INFORMATION_CLASS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Visitor&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; BOOL &lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; Visitor&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;RSYSTEM_THREAD_INFORMATION&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ThreadVisitor&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL &lt;span class=&quot;token function&quot;&gt;NtqsiEnumThreads&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ThreadVisitor &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;visitor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HMODULE ntdll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;ntdll.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    NtQuerySystemInformationT pNTQSI&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    pNTQSI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NtQuerySystemInformationT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
             &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntdll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NtQuerySystemInformation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; NTQSI_MAX_TRY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ULONG NTQSI_BUFFER_MARGIN &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ULONG NTQSI_BUFFER_INIT_SIZE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ULONG buffer_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NTQSI_BUFFER_INIT_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PUCHAR buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; UCHAR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;buffer_size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG req_size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    NTSTATUS s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;NTQSI_MAX_TRY&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pNTQSI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SystemProcessInformation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer_size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;req_size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NT_SUCCESS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; STATUS_INFO_LENGTH_MISMATCH&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            buffer_size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req_size &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; NTQSI_BUFFER_MARGIN&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; UCHAR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;buffer_size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    PRSYSTEM_PROCESS_INFORMATION p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PRSYSTEM_PROCESS_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;NextEntryOffset &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        PRSYSTEM_THREAD_INFORMATION t&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        t &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PRSYSTEM_THREAD_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;XGetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;NumberOfThreads&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;visitor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PRSYSTEM_PROCESS_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;XGetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;NextEntryOffset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ThreadPrinter&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ThreadVisitor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; BOOL &lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RSYSTEM_THREAD_INFORMATION &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;PID =&gt; %5d TID =&gt; %5d\n&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClientId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UniqueProcess
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClientId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UniqueThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ThreadPrinter printer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;NtqsiEnumThreads&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;printer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;스레드 시작 주소 구하기&lt;/p&gt;
&lt;p&gt;시스템 프로그래밍, 특히나 보안 프로그래밍을 하면 특정 스레드의 시작 주소를 구하는 일이 자주 있다. 스레드의 시작 주소를 통해서 해당 스레드의 보다 많은 특성에 대해서 알 수 있기 때문이다. 이럼에도 불구하고 안타깝게도 윈도우는 아직까지도 스레드 시작 주소를 구하는 편리한 방법을 제공하지 않는다.&lt;/p&gt;
&lt;p&gt;아마 똑똑한 독자라면 앞서 살펴본 RSYSTEM_THREAD_INFORMATION 구조체의 StartAddress 필드를 기억하고는 NtqsiEnumThreads 함수를 사용해서 &amp;#x3C;리스트 8&gt;에 나온 것과 같은 코드를 만들면 된다고 생각할지도 모르겠다. 하지만 실제로 &amp;#x3C;리스트 8&gt;의 예제 코드를 수행해 보면 &amp;#x3C;화면 5&gt;에 나온 것과 같이 우리가 원하는 스레드 시작 주소가 출력되지 않는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 NtqsiGetThreadStartAddress 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StartAddressFinder&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ThreadVisitor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    HANDLE target_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID address_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;StartAddressFinder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG tid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        target_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; tid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        address_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; BOOL &lt;span class=&quot;token function&quot;&gt;Visit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RSYSTEM_THREAD_INFORMATION &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClientId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UniqueThread &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; target_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            address_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StartAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL &lt;span class=&quot;token function&quot;&gt;NtqsiGetThreadStartAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG tid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    StartAddressFinder &lt;span class=&quot;token function&quot;&gt;finder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;EnumThreads&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;finder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;finder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;address &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; finder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;DummyThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG tid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HANDLE thread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DummyThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;tid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        PVOID address &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetThreadStartAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DummyThread = %p, StartAddress = %p\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DummyThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; WAIT_OBJECT_0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;TerminateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_열거하기.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/98fd03ce28aad43e42aa4a7eb2897123/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 11.052631578947368%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAeUlEQVR42mOYs2TlgmWrFq5YO2Hmgsr26fkNk6OKesPyOkJz28ILumNLJ4TmdQRmtQSkN4QVdDdOXjhp3pLJcxYv6OtbNXMGg49/oIiIiIyMjJCQkISkpKiYmAAYcHNxsbKy8fHysbGxMTAwMMIBExOQy87N09k/EQDVuCQzvFALFwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;         md 2&apos; title=&apos;&apos; src=&apos;/static/98fd03ce28aad43e42aa4a7eb2897123/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_2.png&apos; srcset=&apos;/static/98fd03ce28aad43e42aa4a7eb2897123/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_2.png 190w,
/static/98fd03ce28aad43e42aa4a7eb2897123/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_2.png 380w,
/static/98fd03ce28aad43e42aa4a7eb2897123/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%97%B4%EA%B1%B0%ED%95%98%EA%B8%B0.md_2.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 5 NtqsiGetThreadStartAddress 함수 수행 결과&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;왜 이렇게 엉뚱한 값이 출력된 것일까? 그 이유를 알기 위해서는 윈도우 내부 구조에 대해서 알아야 한다. 윈도우 2000 이후로 모든 윈도우 운영체제는 NT 커널로 되어 있다. 지금은 대부분의 개발자가 NT 커널이 윈도우 커널이라고 생각하지만 사실 NT 커널은 윈도우뿐만 아니라 OS/2, POSIX같은 다른 환경도 수행할 수 있는 별도의 커널이다. 즉, NT 커널에서 윈도우는 하나의 표현 계층에 지나지 않는다. 이번 시간에 살펴본 ToolHelp 라이브러리와 같은 윈도우 API를 Win32 API라고 부르고, 뒤에 살펴본 NtQuerySystemInformation과 같은 함수들은 윈도우 네이티브 API 또는 NT API라고 부른다. 실제로 Win32 API는 이러한 네이티브 API를 조합해서 만든 것이다.&lt;/p&gt;
&lt;p&gt;NT 커널은 내부적으로 스레드를 관리하기 위해서 ETHREAD라는 구조체 리스트를 사용한다. windbg를 통해서 해당 구조체를 덤프해보면 &amp;#x3C;리스트 9&gt;에 나와 있는 것과 같이 구성된 것을 알 수 있다. 구조체를 살펴보면 스레드 시작 주소와 관련해서 두 개의 필드가 존재함을 알 수 있다. 하나는 0x218 오프셋에 위치한 StartAddress이고, 다른 하나는 0x260 오프셋에 위치한 Win32StartAddress다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 ETHREAD 구조체&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;3: kd&gt; dt nt!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   +0x200 CreateTime       : _LARGE_INTEGER
   +0x208 ExitTime         : _LARGE_INTEGER
   +0x208 KeyedWaitChain   : _LIST_ENTRY
   +0x210 ExitStatus       : Int4B
   +0x214 PostBlockList    : _LIST_ENTRY
   +0x214 ForwardLinkShadow : Ptr32 Void
   +0x218 StartAddress     : Ptr32 Void
   +0x21c TerminationPort  : Ptr32 _TERMINATION_PORT
   +0x21c ReaperLink       : Ptr32 _ETHREAD
   +0x21c KeyedWaitValue   : Ptr32 Void
   +0x220 ActiveTimerListLock : Uint4B
   +0x224 ActiveTimerListHead : _LIST_ENTRY
   +0x22c Cid              : _CLIENT_ID
   +0x234 KeyedWaitSemaphore : _KSEMAPHORE
   +0x234 AlpcWaitSemaphore : _KSEMAPHORE
   +0x248 ClientSecurity   : _PS_CLIENT_SECURITY_CONTEXT
   +0x24c IrpList          : _LIST_ENTRY
   +0x254 TopLevelIrp      : Uint4B
   +0x258 DeviceToVerify   : Ptr32 _DEVICE_OBJECT
   +0x25c CpuQuotaApc      : Ptr32 _PSP_CPU_QUOTA_APC
   +0x260 Win32StartAddress : Ptr32 Void
   +0x264 LegacyPowerObject : Ptr32 Void
   +0x268 ThreadListEntry  : _LIST_ENTRY
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 8&gt;의 코드는 이 두 가지 필드 중에서 0x218에 위치한 StartAddress를 출력한 것이다. 그런데 실제로 일반적으로 우리가 필요로 하는 주소는 0x260에 위차한 Win32StartAddress다.&lt;/p&gt;
&lt;p&gt;그렇다면 윈도우는 왜 스레드 시작 주소에 대해서 두 가지 주소를 저장하고 있는 것일까? 이는 앞서 설명한 것과 같이 NT와 Win32의 계층 구조 때문에다. 우리는 스레드를 생성하기 위해서 CreateThread라는 Win32 API를 사용한다. CreateThread는 내부적으로 실제로 스레드를 생성하기 위해서 NtCreateThread라는 네이티브 API를 호출한다. 여기서 우리가 CreateThread로 전달한 시작 주소가 Win32StartAddress가 되고, CreateThread가 내부적으로 NtCreateThread를 호출하면서 전달한 시작 주소가 StartAddress가 된다.&lt;/p&gt;
&lt;p&gt;이런 설명이 윈도우 XP까지는 유효하지만 그 이후의 윈도우부터는 구조가 좀 변경됐다. Vista부터는 CreateThread 함수는 단순히 NtCreateThreadEx 함수의 래퍼 역할만 하고 있으며, 실제로 모든 처리를 NtCreateThreadEx 함수에서 모두 수행한다. NtCreateThreadEx 함수는 이전에 CreateThread가 수행하던 역할을 동일하게 수행한다. 별도의 래퍼함수 주소를 만들어서 NT 커널에 전달하는 것이다. 따라서 이 경우에도 계층이 명확하지는 않지만 Win32StartAddress는 우리가 전달한 함수 주소가 되고 StartAddress는 NtCreateThreadEx 함수가 임의로 생성한 주소가 된다.&lt;/p&gt;
&lt;p&gt;여기까지 설명을 듣고 나면 “왜 윈도우는 내가 전달한 시작함수가 아닌 다른 함수에서 스레드가 시작되도록 만드는 것일까?”라는 의문이 또 생기게 마련이다. 그 이유는 &lt;a href=&quot;http://www.jiniya.net/wp/archives/7194&quot;&gt;5월호에&lt;/a&gt; 잠깐 설명했던 것과 같이 우리가 만든 스레드 함수가 리턴되면 자동으로 ExitThread가 호출되도록 만들기 위해서다.&lt;/p&gt;
&lt;p&gt;복잡하게 설명했는데 결론은 간단하다. 윈도우는 내부적으로 두 개의 스레드 시작 주소를 관리하고 있으며, 우리가 앞서 살펴보았던 NtQuerySystemInformation으로는 우리가 원하는 스레드 시작 주소를 출력할 수 없다는 점이다. 앞서 설명한 것과 같이 이런 목적에 부합하는 Win32 API는 없기 때문에 스레드 시작 주소를 구하기 위해서는 NtQueryInformationThread라는 네이티브 API를 사용해야 한다. &amp;#x3C;리스트 10&gt;에 NtQueryInformationThread 함수를 사용해서 스레드 시작 주소를 구하는 GetThreadStartAddress 함수 코드가 나와 있다. NtQueryInformationThread 함수 사용 방법은 크게 복잡하지 않기 때문에 직접 코드를 실행해 보면서 사용 방법을 알아 보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 GetThreadStartAddress&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;tlhelp32.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;winternl.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;ThreadQuerySetWin32StartAddress&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;NTSTATUS&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WINAPI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;NtQueryInformationThreadT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL
&lt;span class=&quot;token function&quot;&gt;GetThreadStartAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG tid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HMODULE ntdll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;ntdll.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    NtQueryInformationThreadT pNTQIT&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    pNTQIT &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NtQueryInformationThreadT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
             &lt;span class=&quot;token function&quot;&gt;GetProcAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ntdll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NtQueryInformationThread&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;pNTQIT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    HANDLE h &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OpenThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;THREAD_QUERY_INFORMATION&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    PVOID addr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    NTSTATUS s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pNTQIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;h
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ThreadQuerySetWin32StartAddress
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;addr
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NT_SUCCESS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;address &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; addr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[파이썬에서 엑셀 파일 다루기…]]></title><description><![CDATA[XIGNCODE는 간지나는 엑셀 리포트도 제공해 드립니다 ㅋ~ 최근에 고객사의 요청으로 엑셀 리포트를 만드는 기능을 웹 시스템에 추가했다. 일간, 주간으로 월요일…]]></description><link>https://jiniya.net/wp/archives/7692</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7692</guid><pubDate>Wed, 04 Jul 2012 23:58:15 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; margin-bottom: 16px;&apos; data-url=&apos;./파이썬에서_엑셀_파일_다루기.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5b95c17476ce232142d5643bd0a56000/d9f49/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C_%EC%97%91%EC%85%80_%ED%8C%8C%EC%9D%BC_%EB%8B%A4%EB%A3%A8%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAClElEQVR42g1OWW/TQBj0P+YNIVHa/gskQALEqQoqioAWaEkPGuVsEpw0l536WHvX196OHR8p+z2MZuabkUazjJV+09WHvX77qnt9Mug19WHLmA7vlrNRX11z2G1M/p6PO9/Hg8vFeDjXe/NRy5zPvMVSw4QkNMes5LImhCasonJLZM3SbYRLn8qIy4yWQkieVkRsQ1qjOFcxkZead/sgsnaR8YiCXertY2eHgifQeBysHmNnlzr7sb0v0B4Fe4G5I9FuivYk2qfuQ9d4qhHjVQ4PUvfDBh5I5x1dvcHL157+3B09k/b7DHwMpi+r8FMGPvjjF9v4831yWAaH0n4bO6caA5dZ3Oewlce9NOhQr0nANTQaYHEmULsgNxx2KjoSsK3MAg8rOlDJddgOwT+NoHFGTR7NFKZ4ScMphhNv1XOWHRHPC3GXYkMhC6fQusmZuaYGi+YY6j6Ya9Rr5fgfR70sGaXRDfW7CWj75pW3vBRBv+KTnIy36ZSjLlheFEyvxbRgtzLsu6u+xqyjHJ1y90eOfkvvhNo/iPUNzg7B7ScBjqu4sUanW3wuvWO0OKyTP3XSUEnuHEGzoVHraxaccfckQ6ep/4s5x9j67t1+dieq/LNKzvPgzz29Sv3fcPalxhdlclEkV4n51ZqdqdnNHA9E0FWYRn0GO9Rv+cY5WDRE2K24vqH6fTpJox40LyqhZusbPCSg6dsDDSdkvV4zxtbrTHCuZBInAADbthnnRVmqb1VVjFLXdYuiUHyzKfIs82GgqVqe51LKzWaTSqkkoRQh5AFPmSotpajrWggOfViUheLKVGVCmQY86HrQdj3XRwotGzjAN+8cY2UDHwVRgsIkjIkPQ8sBQYQhCu9sa2Fas8XqPwe8q+pkJc4fAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                md 0&apos; title=&apos;&apos; src=&apos;/static/5b95c17476ce232142d5643bd0a56000/d9f49/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C_%EC%97%91%EC%85%80_%ED%8C%8C%EC%9D%BC_%EB%8B%A4%EB%A3%A8%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/5b95c17476ce232142d5643bd0a56000/08678/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C_%EC%97%91%EC%85%80_%ED%8C%8C%EC%9D%BC_%EB%8B%A4%EB%A3%A8%EA%B8%B0.md_0.png 190w,
/static/5b95c17476ce232142d5643bd0a56000/2edd7/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C_%EC%97%91%EC%85%80_%ED%8C%8C%EC%9D%BC_%EB%8B%A4%EB%A3%A8%EA%B8%B0.md_0.png 380w,
/static/5b95c17476ce232142d5643bd0a56000/d9f49/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C_%EC%97%91%EC%85%80_%ED%8C%8C%EC%9D%BC_%EB%8B%A4%EB%A3%A8%EA%B8%B0.md_0.png 400w&apos; sizes=&apos;(max-width: 400px) 100vw, 400px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;XIGNCODE는 간지나는 엑셀 리포트도 제공해 드립니다 ㅋ~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;최근에 고객사의 요청으로 엑셀 리포트를 만드는 기능을 웹 시스템에 추가했다. 일간, 주간으로 월요일 0시에 째깍 째깍 리포트를 자동으로 생성할 뿐만 아니라 영정시킬 수 있는 로그는 별도 색깔로 하이라이팅을 해준다. 여기에 덧붙여 게임 운영자가 아주 손쉽게 쓸 수 있도록 사용자 별로 영정 대상 해킹툴 사용 카운트를 소팅해서 보여준다. 진짜 쏘 쿨한 기능이 아닐 수 없다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;어쨌든 이런 멋진 기능을 만들기 위해서 난 파이썬에서 엑셀 파일을 다루는 라이브러리를 좀 찾아봤다. 배터리가 포함된 파이썬답게 다양한 방법이 있었는데 여기서는 내가 사용해본 3가지 방법에 대해서 이야기 해볼까 한다. 라이브러리를 3가지나 거쳤다는 것은 그만큼 시행 착오를 겪었다는 말이다. 혹시 비슷한 일을 하는 다음 사람은 부디 그런 삽질을 하지 않았으면 한다. 오픈 소스 라이브러리의 경우 문서화가 아주 잘 된 것들도 아니라서 스타일 기능을 쓸 때 마다 라이브러리 소스를 뒤지고, 구글링하는 수고를 거쳐야 했기 때문이다. 몹시 스트레스풀한 작업이었다. ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0. xlwt&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;제일 처음 살펴보았던 녀석이 &lt;a href=&quot;http://pypi.python.org/pypi/xlwt&quot;&gt;xlwt&lt;/a&gt;였다. 이놈은 파이썬 독자적으로 엑셀 파일을 다룰 수 있도록 만든 라이브러리다. 하지만 제일 안습했다. 문제는 간단했다. 우리가 만드는 엑셀 파일은 일간 로그는 많게는 한 시트에 2만건 정도의 데이터가 기록되고, 주간 로그는 많게는 15-20만건 정도의 로그가 기록된다. 근데 이 xlwt는 65536개의 데이터만 기록할 수 있는 한계가 있었다. xls 파일의 한계라 그렇다는데 어쨌든 그런 연유로 다 만들었다 제일 먼저 아웃되었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1. openpyxl&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다음으로 살펴본 녀석은 &lt;a href=&quot;https://bitbucket.org/ericgazoni/openpyxl/wiki/Home&quot;&gt;openpyxl&lt;/a&gt;이다. 이것도 파이썬 독자적으로 엑셀 파일을 다룰 수 있도록 만든 라이브러리다. 활발하게 만들어지고 있는 녀석답게 xlsx 포맷을 지원하고 20만건의 데이터도 저장할 수 있는 위용을 자랑한다. 크게 문제없이 이 녀석으로 구현해 놓고 사용하고 있었는데 이상하게 월요일만 되면 로그가 생성되지 않는 문제가 발생했다. 그래서 살펴봤더니 서버 메모리가 부족해서 처리를 못하는 문제가 있었다. 리포트 생성 스크립트는 서버에서 동시에 실행되도록 되어 있는데 그래서 그런 줄 알고 하나씩 순차적으로 처리하도록 구조를 변경했다. 그래도 메모리가 부족하긴 마찬가지 였다. 그래서 가장 큰 놈을 실행해서 메모리 점유율을 살펴보았는데, 이건 뭐 2기가 바이트를 넘는 메모리가 필요했다. 잘 아다시피 32비트 윈도에서 특별한 옵션없이 부팅하면 애플리케이션은 2기가 이상을 사용하지 못한다. 첨에는 내가 너무 막짜서 그런 줄 알았다. 파이썬은 막 짜는게 간지지 않은가? 그래서 아래와 같은 글까지 살펴보면서 데이터를 일일이 최적화 시켰다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/questions/2211965/python-memory-usage-loading-large-dictionaries-in-memory&quot;&gt;http://stackoverflow.com/questions/2211965/python-memory-usage-loading-large-dictionaries-in-memory&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/questions/2670005/python-large-variable-ram-useage&quot;&gt;http://stackoverflow.com/questions/2670005/python-large-variable-ram-useage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;그런데 결론은? 개뻘짓이었다. 왜냐하면 내가 쓰는 메모리가 많은 게 아니라 openpyxl 안에서 너무 많은 메모리를 사용하고 있었기 때문이다. openpyxl이 사용하는 메모리를 줄이기 위해서는 데이터를 끊어서 저장하고 다시 그 파일을 열어서 추가하고 또 저장하고 하는 식으로 처리를 해야 했다. 그래서 5만건씩 데이터를 나눠서 저장하도록 프로그램을 고쳤는데, 그랬더니 이번에는 스타일이 모두 깨지는 문제가 발생했다. 저장하고 다시 열면 해당 파일의 스타일을 제대로 가져오지 못하는 문제가 있었던 것이다. 흙~ 맞다. 오픈 소스는 아직 갈 길이 멀다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2. COM&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;최종 종착지는 &lt;a href=&quot;http://www.pythonexcels.com/Python_Excel_Mini_Cookbook.html&quot;&gt;여기&lt;/a&gt;다. 엑셀을 다루는 가장 좋은 방법은 엑셀을 사용하는 것 아니겠는가? 우리는 다행이도 윈도우 서버를 운영하고 있었다. 서버에 엑셀을 설치했다. 그리고 COM을 사용해서 접근했다. 결과는 어땠을까? 가장 큰 파일을 저장할 때에도 파이썬은 20메가 안팍의 메모리를, 실행된 엑셀도 30메가를 넘지 않는 점유율을 보였다. 당연히 엑셀에서 사용할 수 있는 모든 기능을 자유자재로 사용할 수 있음은 말할 것도 없다. 근데 메모리 점유율은 확 떨어졌지만 그렇게 빠른 편은 아닌 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3. 결론&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;파이썬에서 엑셀을 다루어야 한다. 파일 크기가 작다면 아무꺼나 쓰든 크게 상관없다. 물론 복잡한 스타일이나 기능을 사용하려면 아무래도 COM이 가장 좋다. 그렇지 않으면 가장 결정적인 순간에 지원되지 않는다거나 아직 구현되지 않았다거나 하는 이유로 결국 다시 COM으로 돌아갈 수 밖에 없기 때문이다. 이런 점을 충분히 고려하고도 독자 라이브러리를 쓰겠다면 openpyxl이 그나마 좀 더 좋은것 같다. 큰 파일을 다루어야 한다. 그러면 걍 COM 쓰자. 그게 편하다. 리눅스 서버다. 그럼 좀 더 고민해보고 ㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 스레드 고급 활용법: 우선순위, 친화도, TLS, APC]]></title><description><![CDATA[스레드 우선 순위(Thread Priority) 윈도우 스케줄러는 상대적인 우선순위에 따라서 스레드를 스케줄링한다. 이러한 우선 순위의 종류가 <표…]]></description><link>https://jiniya.net/wp/archives/7647</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7647</guid><pubDate>Wed, 04 Jul 2012 23:58:14 GMT</pubDate><content:encoded>&lt;h3&gt;스레드 우선 순위(Thread Priority)&lt;/h3&gt;
&lt;p&gt;윈도우 스케줄러는 상대적인 우선순위에 따라서 스레드를 스케줄링한다. 이러한 우선 순위의 종류가 &amp;#x3C;표 1&gt;에 나와 있다. 의미를 살펴보면 마치 말장난같이 적혀 있지만 해당 상수가 의미하는 정확한 내용이다. &amp;#x3C;리스트 1&gt;에는 스레드 우선순위를 조작하는 함수들이 나와 있다. SetThreadPriority 함수는 hThread로 전달된 스레드의 우선 순위를 nPriority로 설정하는 역할을 한다. nPriority로는 &amp;#x3C;표 1&gt;에 나와 있는 상수 값들을 전달할 수 있다. GetThreadPriority 함수를 사용하면 hThread로 전달된 스레드의 우선순위 값을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;표 1 스레드 우선 순위 값&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;상수명                           의미
THREAD_PRIORITY_TIME_CRITICAL   가장 높은 우선 순위보다 더 높은 우선 순위
THREAD_PRIORITY_HIGHEST	        가장 높은 우선 순위
THREAD_PRIORITY_ABOVE_NORMAL    보통 보다 조금 높은 우선 순위
THREAD_PRIORITY_NORMAL          보통
THREAD_PRIORITY_BELOW_NORMAL    보통 보다 조금 낮은 우선 순위
THREAD_PRIORITY_LOWEST          가장 낮은 우선 순위
THREAD_PRIORITY_IDLE            가장 낮은 우선 순위보다 더 낮은 우선 순위&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 스레드 우선순위 조절 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;SetThreadPriority&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; nPriority&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; WINAPI &lt;span class=&quot;token function&quot;&gt;GetThreadPriority&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우 설계자들은 아마도 정말 많은 고민 끝에 다음 이렇게나 다양한 종류의 우선순위를 만들어 두었을 것이다. 하지만 우리에게는 사실상 거의 쓸모 없는 기능이다. 왜일까? 이건 앞서도 말했던 것처럼 상대적이기 때문이다. 이 상대적이라는 말은 THREAD_PRIORITY_IDLE을 지정할 경우에 THREAD_PRIORITY_LOWEST보다는 덜 스케줄링 되지만 THREAD_PRIORITY_LOWEST로 실행할 스레드 조차 없다면 THREAD_PRIORITY_IDLE로 지정한다고 하더라도 모든 CPU 자원을 쓸 수 있다는 의미다. &amp;#x3C;리스트 2&gt;에 그러한 코드가 나와있다. 아무 일도 하지 않는 스레드를 하나 생성한 다음 해당 스레드의 우선 순위를 THREAD_PRIORITY_IDLE로 지정했다. 여러분의 컴퓨터에서 살펴보면 알겠지만 해당 스레드가 한 코어의 모든 자원을 소모하는 것을 볼 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 100% CPU 점유율을 보여주는 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG CALLBACK &lt;span class=&quot;token function&quot;&gt;DummyThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 처리해야 할 작업들&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DummyThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadPriority&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; THREAD_PRIORITY_IDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우가 스케줄러를 잘못 설계한 것일까? 아니다. 당연히 제대로 만들었다. 운영체제 입장에서는 사용할 수 있는 모든 리소스를 사용하는 것이 바람직하기 때문이다. 메모리가 4GB만큼 탑재돼 있다면 필요하다면 4GB를 모두 사용하는 것이, CPU가 3GHz라면 해당 클럭을 모두 빼곡히 실행할 명령어로 채워 넣는 것이 바람직하다는 의미다. 하지만 사용자 입장은 그렇지 않다. 3GHz의 CPU를 사면 좀 더 CPU가 헐렁하기를 바라고, 4GB의 램을 탑재했다면 한 1GB의 여유 공간이 있기를 바라는 게 사람 심리다. 또 그런 심리를 충족시켜야 하는 것이 우리가 만드는 프로그램들이다.&lt;/p&gt;
&lt;p&gt;그래서 현실세계에서 필요한 우선순위는 상대적인 것이 아니다. 절대적인 우선순위가 필요하다. “우리 제품은 2GHz 싱글 코어 CPU에서 초당 2%이상 CPU를 점유하지는 않습니다.”라는 이야기를 할 수 있는 우선순위가 필요하다는 말이다. 안타깝게도 윈도우에서는 그런 것들을 자동으로 해주지 않는다. 우리가 할 수 있는 유일한 방법은 저러한 for 루프마다 CPU 점유율을 계산해서 스레드가 자동으로 쉬도록 만들어주는 것 외에는 없다. 어떻게? Sleep이나 Wait계열의 함수를 호출해서 대기하는 수 밖에는 없다. 내지는 마스터 스레드가 개별 스레드의 동작을 모니터링하면서 Suspend/Resume 시키는 수 밖에는 없다.&lt;/p&gt;
&lt;h3&gt;스레드 친화도 (Thread Affinity Mask)&lt;/h3&gt;
&lt;p&gt;스레드 친화도란 스레드가 어느 CPU에서 스케줄링 될지를 결정하는 값이다. 친화도는 32비트 정수로 표현되며, 개별 비트가 하나의 CPU를 의미한다. 특정 비트가 1이면 해당 CPU에서 스레드가 실행될 수 있음을, 0이면 해당 CPU에서 스레드가 실행될 수 없음을 나타낸다. Process Hacker를 통해서 특정 스레드의 친화도를 설정하는 과정이 &amp;#x3C;화면 1&gt;에 나와 있다. 살펴보면 해당 스레드는 현재 “CPU 1”만 비트가 켜져 있기 때문에 친화도 값은 2가 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./스레드_고급_활용법_우선순위,_친화도,_TLS,_APC.md_0.png&apos; data-alt=&apos;화면 1 작업관리자 프로세스 친화도 설정 화면&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 315px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8434ab9b620ecffb3e310ba102f8db75/3c1ae/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 86.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC2klEQVR42j1TyW7bSBTkh+cywBzyEwEGc5+LDWcRJollWFashXs396W5tbhvEm3kkilSnjw0iNdkV7161Y/C7bfHu/un1Y7cq8HNRrnbmd9pttLiFe2+mC+fjctX67J2p40/bb3Ljv96uP329Oe79fs/Vh/+Eu53a93VVZ/KLnmm0t5WlMgQA+3IygN7ObCLGE9KMunpZPDJyl9JUCqKqavWVnYFmUqO5RBKIxaZhmGapm1ZBjUMQk1Krsu2TNs0KJnzwPf783k8j5oTCxKRDrvDBvG4FUWZsSiKWBwnUZyEYcgY830/CMIgCDzPx5ss433XDW2rO5FALJImqes4vhc0TTMMQ1XXVVX2XT+OYzNHjcD7oe/r5VNV1X3f2X6EylYcx6IoaTpt2xafUQ9cpzzHNk1T3/OCkJVlVZYlikN2xk9gIqj8Qxap4QJsO27XdVVVsSWKokTRJEmQg6KumzzPl0bC0yk/D71kMuFJlOMo0lTNMKxZYlVHSwCALZ6zByyC1KIokADP+QlgEeDHo5SlqSTKuk6XDhuUQoEsy5q2xRNehTMYUSLFli+VDwYTHvYPSZzKkkKocTUH9LCcc44twKC6VkbPMzgM0PN57PeUCev9GmBJkig1m6ZdwHMkSXoF4zS40DNkh8udpRl/Az/st+gKhumENm0DcYsr0Sx7MQzHcQD3V+T5cuFw+3/w+kCTmCmKqunkKhui3xwGOE3DmezNsDkPA/5b9v1OL3KuqpplO+0SuPa55yyDK3VZ8CTmSdK3LagxeSDFlFzGYW9EwnpHxqHr5wnCzLVQ3mG2hqFoWjUuaJzrjFu8MeI8P+X8xIGHbJA+EyZsJOPn6zT0w3kYpst5wtAPw8t5zMr6lmY3kvv39+PKKb/SMPLd5+3m86ePx+ORJ+GehsI/q08a/irPVR37qBPZNGngLysVnVR0M9k/He1E9TLdTYnPTZbrXkr97N+D8x/XSXsmfqOI8AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 1 작업관리자 프로세스 친화도 설정 화면&apos; title=&apos;&apos; src=&apos;/static/8434ab9b620ecffb3e310ba102f8db75/3c1ae/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_0.png&apos; srcset=&apos;/static/8434ab9b620ecffb3e310ba102f8db75/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_0.png 190w,
/static/8434ab9b620ecffb3e310ba102f8db75/3c1ae/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_0.png 315w&apos; sizes=&apos;(max-width: 315px) 100vw, 315px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 1 작업관리자 프로세스 친화도 설정 화면&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;윈도우는 스레드와 프로세스에 대해서 개별적으로 친화도 값을 관리한다. 즉, 스레드 친화도 값과는 독립적으로 프로세스 친화도 값이 존재한다는 의미다. 스레드 친화도는 항상 프로세스 친화도의 서브셋이어야 한다. CPU가 4개인 컴퓨터를 생각해보자. 해당 컴퓨터에서 특정 프로세스의 친화도 값이 3이라면 해당 프로세스는 0, 1번 CPU에서만 수행될 수 있음을 의미한다. 이 때 해당 프로세스에 속한 스레드의 친화도 값은 2, 3번 CPU와 관계된 값을 지정할 수 없다. 해당 값을 지정하려고 하면 운영체제에서 오류를 리턴한다. 만약 스레드의 친화도를 2, 3번 CPU와 관계된 값으로 변경하고 싶다면 프로세스 친화도를 먼저 변경한 다음 스레드 친화도를 변경해야 한다.&lt;/p&gt;
&lt;p&gt;스레드와 프로세스의 친화도 값을 설정하는 함수들이 &amp;#x3C;리스트 3&gt;에 나와 있다. SetThreadAffinityMask 함수의 첫 번째 인자로 친화도를 설정할 스레드를, 두 번째 인자로 친화도 값을 지정하면 해당 스레드의 친화도를 지정된 값으로 변경한다. 리턴 값은 이전 친화도 값이다. 실패하면 0이 리턴된다. SetProcessAffinityMask 함수도 사용 방법은 동일하다. 단지 스레드가 아닌 프로세스에 대한 친화도를 설정한다는 차이만 있다. GetProcessAffinityMask 함수는 특정 프로세스의 친화도 값을 구하는 역할을 한다. hProcess로 친화도를 구할 프로세스 핸들을 전달하면 lpProcessAffinityMask로 해당 프로세스의 친화도 값이, lpSystemAffinityMask로는 시스템 친화도 값이 리턴된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 스레드 친화도 설정 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD_PTR WINAPI &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    HANDLE hThread
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD_PTR dwThreadAffinityMask
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;SetProcessAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    HANDLE hProcess
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD_PTR dwProcessAffinityMask
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;GetProcessAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    HANDLE hProcess
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PDWORD_PTR lpProcessAffinityMask
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PDWORD_PTR lpSystemAffinityMask
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 4&gt;에는 친화도를 설정하는 간단한 프로그램이 나와 있다. 듀얼코어 이상인 시스템에서 해당 프로그램을 실행하면 &amp;#x3C;화면 2&gt;에 나타난 것과 같은 출력을 볼 수 있다. 친화도를 설정하기 전에는 해당 스레드가 여러 CPU에서 번갈아 가면서 실행되지만, 친화도를 2로 고정한 다음부터는 1번 CPU에서만 실행되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 스레드 친화도 변경 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;ThreadProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentProcessorNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;스레드 친화도 변경\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentProcessorNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ThreadProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./스레드_고급_활용법_우선순위,_친화도,_TLS,_APC.md_1.png&apos; data-alt=&apos;화면 2 스레드 친화도 프로그램 실행 결과&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/9e464e8f99ab0ed0880a7e35786a5f43/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.89473684210527%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABBUlEQVR42mNYs/3w+j0nVu04tmjT4QUbD83YcGLS2pOT12Gg9Senrj85e/OZxVuOLl2/e8fseXP7JjEAAQcnFysrGysbGwsLKzMhxMrGwcjMIq+kPHn2IpBmJiYmBqIBIyMjkJSUlJizYClEMzOpmqWkJBcuWw3iMzMzM4IB8ZqlpSRnL1rFwMbKLCQkxMPDw8vDQ4x+FM1gm1mItRdTMxkBRiXNnFxcbOzswHgGMoAkIyMTIxNOxMQMihppaelZC1eCNXNysrOxsbGycnJwAEmibJaWmrd0DYOcsrqKpp6skpqMgoq0goqMvDKQAeQCxeVVNBRUNNGQoqqWjIKqkbl1W990APEiS6eNJW8CAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 2 스레드 친화도 프로그램 실행 결과&apos; title=&apos;&apos; src=&apos;/static/9e464e8f99ab0ed0880a7e35786a5f43/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_1.png&apos; srcset=&apos;/static/9e464e8f99ab0ed0880a7e35786a5f43/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_1.png 190w,
/static/9e464e8f99ab0ed0880a7e35786a5f43/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_1.png 380w,
/static/9e464e8f99ab0ed0880a7e35786a5f43/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_1.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 2 스레드 친화도 프로그램 실행 결과&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그렇다면 이러한 친화도 값은 언제 사용할까? 윈도우 사용자들은 최적화를 위해서 친화도 값을 많이 사용한다. 방송을 하는 게이머들은 게임을 특정 CPU에 바인딩 시키고, 분리된 CPU에 방송 프로그램을 할당하는 방법을 사용한다. 일부 게임 최적화 유틸리티는 이러한 작업들을 자동으로 해주기도 한다. 물론 이 경우에 진짜 최적화가 될지는 조금 생각을 해보아야 한다.&lt;/p&gt;
&lt;p&gt;프로그래머가 친화도를 설정하는 경우도 크게 다르지는 않다. 프로그래머의 경우 자신이 작성한 프로그램의 스레드 구조를 완벽하게 알 수 있기 때문에, 병렬적으로 수행되어야 하는 스레드들에 대해서는 독립된 CPU를 설정함으로써 상호 컨텍스트 스위칭을 줄일 수 있다. IOCP도 그러한 식으로 최적화를 수행한 예로 생각할 수 있다.&lt;/p&gt;
&lt;p&gt;스레드 친화도 값은 최적화 작업 외에도 CPU와 관련된 특수한 작업을 하기 위해서 사용하는 경우도 있다. QueryPerformanceCounter 함수가 대표적이다. 해당 함수는 윈도우의 고해상도 타이머 값을 가져오는 역할을 한다. 이 함수는 CPU의 클럭과 밀접한 관련이 있는데 일반적인 경우에는 멀티 프로세서 환경에서 어떤 프로세서에서 호출되는지에 관계없이 정상적으로 동작하지만 BIOS에 버그가 있는 경우에는 호출되는 프로세서에 따라서 다른 값이 리턴되는 경우가 있다. 이러한 버그를 보정하기 위해서 SetThreadAffinityMask가 사용되기도 한다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 5&gt;에 특정 코드의 수행 시간을 구하기 위한 전형적인 QueryPerformanceCounter 호출 구조가 나와 있다. 보통의 경우에 이 코드는 전혀 문제가 없지만 BIOS 등에서 처리가 잘못된 경우에는 1번 코드가 실행되는 프로세서와 2번 코드가 실행되는 프로세서가 다를 경우에 전혀 엉뚱한 두 값이 리턴되기도 한다. 이러한 부작용을 보정하기 위해서는 &amp;#x3C;리스트 6&gt;에 나타난 것과 같이 SetThreadAffinityMask 함수를 사용해서 QueryPerformanceCounter 함수가 하나의 프로세서에서만 호출되도록 만들어주어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 QueryPeroformanceCounter 호출 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;QueryPerformanceCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// … 1&lt;/span&gt;
특정 작업들
&lt;span class=&quot;token function&quot;&gt;QueryPerformanceCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// … 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 QueryPerformanceCounter 함수가 특정 프로세서에서 호출되도록 지정한 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;QueryPerformanceCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// … 1&lt;/span&gt;
특정 작업들
&lt;span class=&quot;token function&quot;&gt;QueryPerformanceCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// … 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서 스레드와는 별개로 프로세스 친화도 값이 있고, 스레드 친화도는 프로세스 친화도의 서브셋이 되어야 한다고 이야기했다. 이런 관점에서 살펴보면 &amp;#x3C;리스트 6&gt;와 같은 코드는 문제가 있다. 상수 1을 지정해서 0번 CPU에서만 실행하겠다고 지정했지만, 현재 실행되는 프로세스가 0번 CPU에서 실행되지 않도록 설정됐을 수 있기 때문이다. 이런 경우를 좀 더 유연하게 처리하기 위해서는 현재 프로세스의 친화도 값을 구해서 비교하는 약간 복잡한 과정을 거쳐야 한다. &amp;#x3C;리스트 7&gt;에는 이런 경우에 사용할 수 있는 간단한 헬퍼 클래스가 나와있다. 해당 객체를 생성하면 생성된 블록은 싱글 코어로 동작하게 만들어준다. &amp;#x3C;리스트 8&gt;에는 SingleCore 클래스를 사용해서 QueryPerformanceCounter의 동작을 보정하는 방법이 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 SingleCore 스레드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SingleCore&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SingleCoreError&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ULONG_PTR oam_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;SingleCore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        ULONG_PTR pam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sam&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetProcessAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;pam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SingleCoreError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        ULONG_PTR am &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; bits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CHAR_BIT &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;am&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;bits&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;am &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; pam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                oam_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; am&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;oam_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SingleCoreError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            am &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SingleCore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;SetThreadAffinityMask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; oam_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 SingleCore 클래스를 사용해서 QueryPerformanceCounter 동작을 보정한 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;SingleCore s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;QueryPerformanceCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// … 1&lt;/span&gt;
특정 작업들
&lt;span class=&quot;token function&quot;&gt;QueryPerformanceCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// … 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;스레드 지역 저장소(Thread Local Sotrage)&lt;/h3&gt;
&lt;p&gt;GetLastError는 SetLastError로 설정된 오류 코드를 리턴해 주는 기능을 하는 윈도우 함수다. 신입 개발자에게 해당 함수를 직접 구현해 보라고 시키면 &amp;#x3C;리스트 9&gt;에 있는 코드와 같이 구현하는 경우가 많다. 이 코드는 기본적인 Set/GetLastError의 기능을 구현했지만 Set/GetLastError 함수가 스레드별로 독립적으로 오류코드를 관리되는 특징은 구현하지 않았다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 Set/GetLastError 구현 1&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG error_code &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MySetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    error_code &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG &lt;span class=&quot;token function&quot;&gt;MyGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; error_code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;원본 함수와의 차이점을 살펴보기 위해서 &amp;#x3C;리스트 10&gt;과 같은 프로그램을 만들어볼 수 있다. 두 개의 스레드를 만들어서 교차로 SetLastError, GetLastError를 호출하는 것이다. 이렇게 호출하면 원본 윈도우 함수와 우리가 구현한 버전의 차이를 발견할 수 있다. &amp;#x3C;리스트 10&gt;의 코드에서 MySetLastError, MyGetLastError 호출 부분을 우리가 작성한 버전과 윈도우 표준 함수로 변경해 가면서 결과를 관찰해 보도록 하자. &amp;#x3C;화면 3&gt;에는 윈도우 버전을 호출해서 결과를 출력한 화면이, &amp;#x3C;화면 4&gt;에는 우리가 구현한 버전을 호출해서 결과를 출력한 화면이 나와있다. 살펴보면 윈도우 버전을 호출했을 때에는 스레드별로 독립적으로 오류코드가 관리되고 있는 것을 볼 수 있다. 반면 MySetLastError, MyGetLastError를 호출했을 때에는 GetLastError를 호출 했을 때 다른 스레드가 덮어쓴 값이 반환되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 MySet/GetLastError 테스트 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG CALLBACK &lt;span class=&quot;token function&quot;&gt;GleTestThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        code &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetTickCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d] SetLastError %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;MySetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d] GetLastError %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MyGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; GleTestThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;WaitForMultipleObjects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; threads&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./스레드_고급_활용법_우선순위,_친화도,_TLS,_APC.md_2.png&apos; data-alt=&apos;화면 3 Set/GetLastError 출력 결과&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8c4f6ab77573d87d1f2eca1178c82cd6/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 65.26315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABNklEQVR42mOYt3rH4o271u4+sXzL8UWbjyzefnr+7mvzd1/Hihbvu7Fiz4WlWw5tnLd40/wlDLHJGfLycurqmhoaWopKypJS0iysbGzsHDgRBycrGwePgFDv1NkMiWlZsjLSSkpKysrKcnKy4mJiDAwMjIyMDDgARIqNlWXS1JkMCSkZMtJS6urqGhoa8vLy4uLixGhmZWWdOWc+Q1hsioS4GFCziooKULO0tDQjGBCymXXyjHkM5vZuQA4XNzcbGHBwcDAzMxOr2cjSAchhYmJiIA6gaXYEaWZmJk8zRTZToNnYygnIYWZmYWRkAiEmHIgRipgYgR5kZGdnmzxzPszPJNrMzsY2YcoMBr/IVDkVbTVdE1UdY3U9U20jSx1jKyRkDUZWGvpmQDXqYARk6Jlad0yaDQDQNF7BScIK1QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 3 Set/GetLastError 출력 결과&apos; title=&apos;&apos; src=&apos;/static/8c4f6ab77573d87d1f2eca1178c82cd6/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_2.png&apos; srcset=&apos;/static/8c4f6ab77573d87d1f2eca1178c82cd6/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_2.png 190w,
/static/8c4f6ab77573d87d1f2eca1178c82cd6/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_2.png 380w,
/static/8c4f6ab77573d87d1f2eca1178c82cd6/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_2.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 3 Set/GetLastError 출력 결과&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./스레드_고급_활용법_우선순위,_친화도,_TLS,_APC.md_3.png&apos; data-alt=&apos;화면 4 MySet/GetLastError 출력 결과&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/cbd42ce4c92d0a58ec07bc82664ffbe5/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 65.26315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABdklEQVR42mPIqp9R2jm/uHPhtCVbZ6/cMWnJtr4VhyesOd636mjfysNT1p8q6V3uEVvul1zvk1Dlm1CZVtrR2DNzQc+ERX2TGJy8guXl5ZRV1dTUNRQVFcUlJJmYWVjZ2IGIhRWEmFnYgHwgAgozMjEDZYEkNx9/x4SpDF4B4fKyMsrKSirKyrKysmJiYgwMDIyMjAw4AESKjZVl4tQZDF5BkbIyUurq6hoaGioqKhISEsRpZp0xex6DqaOvjJQE0NHKQNuVlKSlpYnSzMY6cdpsBnFVI2ZGBk4uLjYw4ODgYGZmJsbmSTPnMQgp6YOFmBiIA0g2z2EQUzEACTGRrnn6HAZhJV3ybJ40fS6DuApZzgb6ecY8BiUtYyAHGPVMMAA0COgLZIQMgMEJNICdnX3yzPkMwqqG5Dl7MtBmDZdwfkUdEQ0TLSMLAzNrPRNLHQNTbT1jHUMTHQMLXSNzTT0jPTNbAws7CDK0tNc2sjCytJsyfyUAm0xSQFbtiEAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;화면 4 MySet/GetLastError 출력 결과&apos; title=&apos;&apos; src=&apos;/static/cbd42ce4c92d0a58ec07bc82664ffbe5/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_3.png&apos; srcset=&apos;/static/cbd42ce4c92d0a58ec07bc82664ffbe5/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_3.png 190w,
/static/cbd42ce4c92d0a58ec07bc82664ffbe5/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_3.png 380w,
/static/cbd42ce4c92d0a58ec07bc82664ffbe5/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_3.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;화면 4 MySet/GetLastError 출력 결과&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이러한 Set/GetLastError 함수의 특성을 이야기해 주면 똑똑한 신입 개발자들은 &amp;#x3C;리스트 11&gt;과 같은 코드를 작성한다. 스레드와 오류코드를 연결하는 맵을 만들어서 관리하는 것이다. 물론 이 코드는 멸티스레드 환경에서 사용하기에는 조금 부적절한 버전이다. 더 똑똑한 개발자는 여기에 동기화 처리를 덧붙여서 &amp;#x3C;리스트 12&gt;에 나와 있는 것처럼 실제로 써먹을 수 있는 코드를 만든다. 이쯤 되면 이제 기능적으로는 Set/GetLastError와 동일하다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 11 Map을 사용한 Set/GetLastError 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;map&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;map ErrorCodeMap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;map&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;iterator ErrorCodeMit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ErrorCodeMap error \_codes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;MyThreadSetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG tid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ErrorCodeMit it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error \_codes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; error \_codes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		error \_codes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;make\&lt;span class=&quot;token function&quot;&gt;_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		it&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;second &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG
&lt;span class=&quot;token function&quot;&gt;MyThreadGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ULONG tid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ErrorCodeMit it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error \_codes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; error \_codes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; it&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;second&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 12 동기화 처리를 추가한 Set/GetLastError 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;CRITICAL_SECTION gle_cs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;InitSystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;InitializeCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gle_cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CleanupSystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;DeleteCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gle_cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SyncMyThreadSetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;EnterCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gle_cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;MyThreadSetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LeaveCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gle_cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG &lt;span class=&quot;token function&quot;&gt;SyncMyThreadGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG ge&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;EnterCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gle_cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MyThreadGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LeaveCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;gle_cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ge&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 모든 구현을 마치고 나면 한가지 의문이 떠오른다. 과연 이 방법뿐일까? 스레드별로 다른 저장소를 구현하기 위해서 우리는 매번 스레드와 자료를 연결하는 맵을 만들고 또 그 맵에 접근하기 위한 동기화 객체를 만들어야 할까? 구현의 번잡함을 차치하고서도 이 코드의 더 큰 문제점은 성능에 있다. 우리가 사용하려는 데이터의 논리적 특성은 전혀 공유적인 속성이 아니다. 하지만 우리는 구현상의 이유로 동기화 객체를 사용해서 직렬화를 시켰다. 이 말은 다시 표현하면 멀티 코어의 장점을 하나도 살리지 못한다는 의미가 된다.&lt;/p&gt;
&lt;p&gt;윈도우는 앞서 제기된 문제를 해결하기 위해서 스레드 지역 저장소(Thread Local Storage)라는 것을 제공해 준다. 이름에서 알 수 있듯이 지금까지 우리가 논의했던 모든 문제들을 한번에 해결해주는 기능이라고 생각하면 되겠다. 스레드 지역 저장소를 통해서 우리는 스레드별로 별도의 데이터를 동기화 객체 없이 저장하고 읽어올 수 있다.&lt;/p&gt;
&lt;p&gt;우선 스레드 지역 저장소를 조작하는 함수들을 살펴보자. &amp;#x3C;리스트 13&gt;에 TLS 조작 함수들의 원형이 나와 있다. TlsAlloc 함수는 스레드 별로 관리할 데이터의 인덱스를 할당하는 역할을 하는 함수다. 해당 함수를 호출하면 사용할 수 있는 TLS 인덱스를 반환해 준다. TlsFree 함수는 dwTlsIndex로 지정된 인덱스를 해제하는 역할을 한다. TlsGetValue 함수는 dwTlsIndex로 전달된 인덱스에 해당하는 값을 반환하는 역할을 한다. TlsSetValue 함수는 dwTlsIndex로 전달된 인덱스에 해당하는 값을 lpTlsValue로 설정하는 역할을 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 13 TLS 조작 함수&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD WINAPI &lt;span class=&quot;token function&quot;&gt;TlsAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;TlsFree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD dwTlsIndex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
LPVOID WINAPI &lt;span class=&quot;token function&quot;&gt;TlsGetValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD dwTlsIndex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;TlsSetValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD dwTlsIndex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID lpTlsValue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지 설명만 듣고는 어떻게 TLS가 우리가 제기했던 문제를 해결하는지 감이 잘 잡히지 않는다. 감을 잡기 위해서는 TLS의 구조에 대해서 알아야 한다. TLS가 동작하는 기본 원리는 운영체제가 스레드를 생성할 때에 스레드 스택을 만드는 것과 동일하게 TLS를 저장할 배열도 같이 만든다는데 있다. 물론 그 크기는 고정적이다. TLS로 할당할 수 있는 인덱스 개수는 그 배열의 개수만큼으로 한정된다. 이렇게 생성된 배열은 스레드의 컨텍스트 정보를 저장하는 곳에 기록돼서 스레드가 변경될 때마다 스레드가 생성될 때 같이 만들어진 TLS 배열을 가리키도록 설정된다. 따라서 우리는 표면적으로는 동일한 2번 인덱스의 값을 참조하지만 그걸 저장하고 있는 배열이 활성되는 스레드 컨텍스트에 따라서 변경되기 때문에 최종적으로는 다른 장조를 참조하게 되는 것이다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 14&gt;에는 이렇게 TLS 함수를 사용해서 Set/GetLastError를 구현한 버전이 나와있다. 앞서 작성한 것보다 코드도 훨씬 적지만 동기화 객체가 없기 때문에 멀티 코어의 장점도 십분 활용할 수 있다는 특징이 있다. 이렇게 직접 TLS 함수를 호출하지 않고도 __declspec(thread) 지시어를 사용하면 &amp;#x3C;리스트 15&gt;에 나타난 것처럼 간단하게 TLS를 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 14 동적 TLS를 사용한 Set/GetLastError 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG gle_index&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;InitSystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    gle_index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;TlsAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CleanupSystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;TlsFree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gle_index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MyTlsSetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;TlsSetValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gle_index&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG &lt;span class=&quot;token function&quot;&gt;MyTlsGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;TlsGetValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gle_index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;리스트 15 정적 TLS를 사용한 Set/GetLastError 구현&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;__declspec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ULONG error_code &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MySetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    error_code &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG &lt;span class=&quot;token function&quot;&gt;MyGetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; error_code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;유저모드 APC&lt;/h3&gt;
&lt;p&gt;APC란 Asynchronous Procedure Calls의 약자로 우리말로 하면 비동기 프로시저 호출 정도로 번역할 수 있다. 여기서 가장 중요한 말은 제일 앞에 있는 비동기란 말이다. 우리가 일반적으로 호출하는 함수 구조를 동기 방식이라고 한다. 그렇다면 비동기 방식은 무엇일까? 바로 함수 호출이 즉시 일어나지 않고 지연돼 있다가 특정 시점에 호출된다는 의미다.&lt;/p&gt;
&lt;p&gt;세부적인 내용을 살펴보기에 앞서 관련 함수들의 사용법에 대해서 먼저 알아보도록 하자. &amp;#x3C;리스트 16&gt;에 유저모드 APC와 관련된 함수 원형들이 나와있다. 제일먼저 보이는 QueueUserAPC 함수가 APC 큐에 함수를 추가하는 역할을 한다. pfnAPC로는 수행될 APC 함수를, hThread로는 해당 APC 함수가 추가될 스레드 핸들을, dwData로는 pfnAPC 함수로 전달될 컨텍스트 변수를 지정하면 된다. APCProc은 실제로 수행될 APC 함수 원형이다. 리턴 값은 없으며, dwParam은 QueueUserAPC 함수에서 설정한 컨텍스트 변수가 전달된다. 그 다음으로는 SleepEx라는 함수가 있다. 해당 함수는 Sleep과 동일한 기능을 하는데 추가적인 기능은 두 번째 파라미터인 bAlertable 값을 통해서 스레드를 통지 가능 상태로 만들 수 있다는 점이 특징적이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 16 유저모드 APC 관련 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD WINAPI &lt;span class=&quot;token function&quot;&gt;QueueUserAPC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PAPCFUNC pfnAPC&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG_PTR dwData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
VOID CALLBACK &lt;span class=&quot;token function&quot;&gt;APCProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR dwParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
DWORD WINAPI &lt;span class=&quot;token function&quot;&gt;SleepEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD dwMilliseconds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BOOL bAlertable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 APC가 동작하는 세부 구조에 대해서 좀 살펴보자. 윈도우 스레드는 모두 APC 큐라는 것을 가지고 있다. 해당 큐에 값을 추가하는 함수가 QueueUserAPC 함수가 하는 역할이다. APC 큐에 추가된 함수들은 스레드가 통지 가능 상태(Alertable State)가 될 때에 일괄 수행된다. 스레드를 통지 가능 상태로 만드는 함수로는 SleepEx부터 WaitForSingleObjectEx, WaitForMultipleObjectsEx 등의 함수가 있다. 보통 스레드를 대기 상태로 만드는 함수의 Ex버전에 포함돼 있다고 생각하면 되겠다. 이렇게 스레드가 통지 가능 상태에 진입하면 윈도우는 APC 큐에 뭔가 추가된 것이 있거나 대기 중에 뭔가가 추가되면 해당 APC 루틴을 호출하고 대기를 종료한다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 17&gt;에는 이렇게 유저모드 APC루틴을 사용한 예가 나와 있다. 실행 결과에서도 볼 수 있지만 동기 호출과 다르게 APC 루틴의 가장 큰 장점은 APC 루틴이 추가된 스레드 컨텍스트에서 호출된다는 점이다. 따라서 특정 스레드 컨텍스트에서 특정 함수가 호출되도록 만들어야 하는 경우라면 유용하게 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 17 유저모드 APC 사용 예제&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;ApcThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;통지 상태 시작\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;SleepEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;통지 상태 끝\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;작업중...\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
CALLBACK
&lt;span class=&quot;token function&quot;&gt;ApcProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ApcProc %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;ApcProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


    HANDLE thread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ApcThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;QueueUserAPC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ApcProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 677px; margin-bottom: 16px;&apos; data-url=&apos;./스레드_고급_활용법_우선순위,_친화도,_TLS,_APC.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0b4bc3dfdb78f6aae3d4c970eb91939e/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 65.26315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABb0lEQVR42mPIqJpc0jKrsHl2YtmkkOxut6Q2RY8qWbcqeY9qec8aea8aee9aEPKpU/Fv0Alr88mdlN8yZ35V+dyqcgZHzyAFBXklZRU+fgEGJhYmZlZG3AioAEQysnDy8pU1dTPYOXtLS0nw8PIwMTExEAEYGRmBJDsba1f/ZAZHdz9ZGWkuLm4WFhbiNbOxsk6bOYfBwNpTTlZKRUWVh4eHFJvZeiZOZzBz9FNSkNXS1ubm5iZJc/eE6Qw6Fq7ystLCwiIkOZuDnb21s59Bw8RJUV6WhZUVIkq85vbuCQy6Vh4yUuKysnIkOpu1b9pMBlPnQEU5GU1NLVL93DttBoOOtaeigiy/gADQ5RA5RiYQYAQjNAASZGYGKuNk5wBp1jCxlxQVAoYW0EQmRkZmQkkFbnP/9BkMqvZhSnoWNs6eJtaOZjbOlg5uhhb2BuZ2usZWQKRnYg3k6hhb6RhbGlqCGUaWuiZWptZOXdPnAgCwwElwUCrAdgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                      TLS  APC md 4&apos; title=&apos;&apos; src=&apos;/static/0b4bc3dfdb78f6aae3d4c970eb91939e/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_4.png&apos; srcset=&apos;/static/0b4bc3dfdb78f6aae3d4c970eb91939e/08678/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_4.png 190w,
/static/0b4bc3dfdb78f6aae3d4c970eb91939e/2edd7/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_4.png 380w,
/static/0b4bc3dfdb78f6aae3d4c970eb91939e/3c503/%EC%8A%A4%EB%A0%88%EB%93%9C_%EA%B3%A0%EA%B8%89_%ED%99%9C%EC%9A%A9%EB%B2%95_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%2C_%EC%B9%9C%ED%99%94%EB%8F%84%2C_TLS%2C_APC.md_4.png 677w&apos; sizes=&apos;(max-width: 677px) 100vw, 677px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;화면 5 유저모드 APC 사용 예제 실행 결과&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[xfav 0.9.8: 탐색기에 즐겨찾기를 달아보아요~~]]></title><description><![CDATA[xfav 프로그램이 업데이트 되었습니다. 다음 사항이 변경되었습니다. 크래시 버그 수정. x키로 이어지는 연속기를 쓰실 수 있습니다. 탐색기 창 전부 닫기 (esc → x → k) 탐색기 창 전부 최소화 (esc → x → x…]]></description><link>https://jiniya.net/wp/archives/7599</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7599</guid><pubDate>Wed, 04 Jul 2012 23:58:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://jiniya.net/wp/archives/2821&quot;&gt;xfav 프로그램&lt;/a&gt;이 업데이트 되었습니다. 다음 사항이 변경되었습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;크래시 버그 수정.&lt;/li&gt;
&lt;li&gt;x키로 이어지는 연속기를 쓰실 수 있습니다.
&lt;ul&gt;
&lt;li&gt;탐색기 창 전부 닫기 (&lt;strong&gt;esc → x → k&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;탐색기 창 전부 최소화 (&lt;strong&gt;esc → x → x&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;탐색기 창 전부 팝업 (&lt;strong&gt;esc → x → z&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;현재 창 항상 위 토글 (&lt;strong&gt;esc → x → t&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;아래 경로에서 다운로드 받으실 수 있습니다. 그럼 모두 모두 즐탐하세욥 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/bins/xfav/xfav32.0.9.8.zip&quot;&gt;xfav 0.9.8 32비트 버전&lt;/a&gt;&lt;a href=&quot;http://www.jiniya.net/bins/xfav/xfav64.0.9.8.zip&quot;&gt;xfav 0.9.8 64비트 버전&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; 1
 1&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[boost와 ABI, 그리고 ELF…]]></title><description><![CDATA[최근에 XIGNCODE…]]></description><link>https://jiniya.net/wp/archives/7543</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7543</guid><pubDate>Tue, 03 Jul 2012 23:58:12 GMT</pubDate><content:encoded>&lt;p&gt;최근에 XIGNCODE3를 리눅스 게임 서버에 적용한 적이 있다. 뭐 리눅스 게임 서버야 여러 군데 적용을 했었는데 그 곳이 조금 특별했던 건 자바를 사용한다는 점이었다. 학부 때 자바 실험한 기억을 떠올리며 회사에 비치된 자바 책을 참고하여 난 뚝딱뚝딱 자바 인터페이스를 만들었다. 뭐 별로 어렵진 않았다. 그리고 적용도 잘 됐다. 적용하고 나서 한 가지 문제가 발생했다. 해당 게임 서버에 XIGNCODE3 기능을 ON/OFF 시키는 걸 만들면서 시작된 문제였는데 XIGNCODE3를 OFF 상태로 시작했다가 ON을 시키면 크래시가 난다고 했다. 자바 크래시 로그를 같이 보내 왔는데 XIGNCODE3 so 파일에서 다른 boost 공유 라이브러리에 있는 심벌에 바인딩되면서 오류가 발생했다.&lt;/p&gt;
&lt;p&gt;한동안 이 문제는 나를 굉장히 골치 아프게 만들었다. 그도 그럴것이 해당 게임 서버에서만 발생하는 문제이기 때문에 우리 쪽에서 재현하기가 쉽지 않았다. 모든 것을 동일하게 구축하고 해당 boost so 파일을 먼저 로드하고 고갱님 환경과 동일해 보이도록 만들고는 테스트를 해도 우리 쪽에서는 재현되지 않았다. 그래서 빌드할 때마다 고갱님께 테스트를 부탁 드려야 했기에 참 쉽지 않았다. 나와 같은 문제로 고통받는 개발자가 분명히 있을거란 생각에 내가 멘붕을 탈출했던 경로를 여기에다 조금 끄적여 본다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0. ABI가 뭔가요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ABI라고 하면 뭔가 거창하고 있어보이는데 전산 약어들이 다 그렇듯이 아무거도 아닌 용어다. application binary interface의 약자로 바이너리 단계에서의 인터페이스를 의미한다고 보면 되겠다. 구조체가 메모라상에 실제로 어떻게 존재하는지 호출 규약이 어떻게 되는지를 나타내는 말이라고 생각하면 된다. 이렇게 말해도 참 어려운데 윈도우 프로그래머들이 더 쉽게 이해할 수 있게 말하자면 dll 버전 업이 되었을 때, 해당 dll을 사용하는 프로그램을 새로 컴파일할 필요없이 dll만 교체해서 실행이 되면 ABI 호환성을 지원한다고 하고, 재컴파일이 필요하다면 ABI 호환성을 지원하지 않는다고 말한다.&lt;/p&gt;
&lt;p&gt;어쨌든 장황하게 설명했는데 boost는 ABI 호환성을 제공하지 않는다. 버전 업이 되면 새로 컴파일을 해야 한다. 이건 여담이지만 여러분이 API 세트를 디자인해보면 알겠지만 ABI 호환성을 제공하는 것이 생각처럼 녹록한 일은 아니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1. ELF는 또 뭐죠?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ELF는 리눅스의 실행 파일 포맷이다. 난 이 포맷에 대해서 자세한 정보를 알진 못하는데 이번 사례를 통해서 아주 심각한 한가지 문제에 대해서 알게 되었다. 윈도우 dll은 export 시킨 심볼에 대해서만 외부로 노출시킨다. 근데 이 망할 ELF는 별도 설정을 하지 않으면 내가 가진 모든 심벌이 외부로 그대로 노출된다. 도대체 왜 이런지 모르겠다. 더 욱긴건 난 우리 so 파일에 boost를 정적으로 링크 시켰음에도 이 망할 시스템은 고객님의 게임 서버에 있는 다른 boost so 파일에 있는 심벌로 바인딩을 시도한다는 점이었다. 물론 그 다른 boost so 파일이 올라오기 전에 우리가 먼저 로딩되면 우리꺼를 쓴다. 근데 OFF로 시작해서 그 다른 버전의 boost so파일이 올라오고 우리 so 파일을 로딩하면 우리 so 파일 안에 정적으로 링크된 boost 심벌을 쓰는 것이 아니라 다른 버전의 boost so 파일에 있는 동일한 이름의 심벌에 바인딩을 한다는 점이었다. 그러니 크래시가 났다. ABI가 다르기 때문이다.&lt;/p&gt;
&lt;p&gt;ELF에 심벌 노출 정책을 설정하는 컴파일러 플래그들이 있는데 그걸 통해서 해당 심벌이 노출되지 않도록 설정해도 제대로 적용이 되질 않았다. 그 망할 문제가 생기는 심벌은 항상 공유됐다. 희한했다. 궁극의 ms-compatible 따위의 기능이 gcc 있었는데, 우리가 사용하는 버전에서는 지원되지 않았다. 그래서 더 골치 아팠다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2. 똑같은 boost를 쓴다면?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;온갖 컴파일 플래그 설정으로 문제를 해결하려 했지만 제대로 되지 않았기에 난 멘붕에 빠졌다. 그러다 결국 비굴하게 그냥 고객님께서 사용하시는 boost 최신 버전으로 우리 꺼를 컴파일하기로 했다. 그러면 ABI가 호환되니까 크래시는 발생하지 않을 것이라 생각한 것이다. 그렇게 온갖 것들을 다 바꿔서 새로 컴파일을 해서 테스트를 했는데 고객님께서 크래시가 발생하지 않는다고 했다. 근데 더 이상한 알 수 없는 온갖 문제들이 발생했다. 흙~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3. 심벌 이름 변경하기&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 단계에서 이제 내가 선택할 수 있는 방법은 많은 선지자들이 갔던 길을 따르는 수 밖에는 없다. 심벌 이름이 바뀌도록 boost 소스 코드를 고치는 방법이었다. C++의 경우 이름 장식에 namespace가 포함되기 때문에 이 경우에 boost 네임스페이스 명을 boost2와 같이 변경하기만해도 심벌 이름이 모두 바뀌는 효과를 얻을 수 있다. 당연히 난 처음에 boost 라이브러리에서 ABI 호환성을 제공하지 않으니 이런 기능은 아주 자연스럽게 config.hpp 따위의 #define BOOST_NAMESPACE 값만 변경하면 싹 바뀌어서 컴파일이 될 줄 알았는데 그리 간단한 문제가 아니었다.&lt;/p&gt;
&lt;p&gt;똑똑한 우리 선배 개발자들은 파이썬 스크립트를 사용해서 네임스페이스를 변경하는 기능을 이미 만들어 두었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://lists.boost.org/boost-build/2009/05/21911.php&quot;&gt;http://lists.boost.org/boost-build/2009/05/21911.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;나는 그냥 그걸 다운받아서 쓰기만 하면 되는 줄 알았다. 하지만 세상일이 모두 그리 간단하지만은 않다. 스크립트로 모든 네임스페이스를 변경하고는 boost를 컴파일 시키는데 당연한 이야기겠지만 제대로 동작하지 않았다. 멘붕, 멘붕, 멘붕… 난 어뜩하지?… 고객님 환경의 특성상 우리 라이브러리를 제일 처음 일단 로드만 시켜주세요. 이럴수는 없지 않겠는가? 핡~&lt;/p&gt;
&lt;p&gt;이제 난 어떡해야 하는가? boost 그 많은 파일들을 찾아서 모든 네임스페이스를 일일이 손으로 고쳐야 할까? 그 작업만 하는데도 올해가 다 지날지도 모른다. 그 전에 그 지겨운 일을 하다 내가 개발자를 그만둘지도 모른다. 그 때 생각났다. 그래 #define boost boost2 따위로는 안될까? 근데 config.hpp 처럼 모든 boost 파일이 공통으로 참고하는 헤더 따위를 알 수가 없었다. 그 때 떠올랐다. 그럼 gcc에 시키지 머. 그렇다. 이런 마법 같은 커맨드가 존재했던 것이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;bjam cxxflags=-Dboost=boost2&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;bjam cxxflags=-Dboost=boost2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;저렇게 할 경우에 include 경로도 모두 변경되기 때문에 boost 폴더에 있는 것을 boost2 폴더로 모두 복사한 다음에 컴파일을 시켜야 한다. 그렇게 하면 우리의 boost는 네임스페이스가 boost2로 변경돼서 멋지게 빌드된다. 당연한 이야기겠지만 이 경우에 boost를 사용하는 우리 모듈의 makefile에도 -Dboost=boost2를 넣어서 빌드를 해야한다.&lt;/p&gt;
&lt;p&gt;두둥 이렇게 네임스페이스를 변경했다. 그리고 고갱님께 한땀한땀 빌드한 so 파일을 제공하고는 테스트를 부탁한다. 그랬더뉘 마법같이 된단다. 살았다. boost 산을 넘었다.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[링크드 리스트를 추억하며…]]></title><description><![CDATA[중학교 2학년 때였다. 그 때까지 베이직만 배웠던 나에겐 실행 파일을 만들어보고 싶은 열망이 있었다. 그리고 실행 파일을 만들기 위해서는 컴파일러 언어라는 것을 배워야 한다는 것도 알게 되었다. 서점에 C…]]></description><link>https://jiniya.net/wp/archives/5610</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5610</guid><pubDate>Wed, 27 Jun 2012 23:58:11 GMT</pubDate><content:encoded>&lt;p&gt;중학교 2학년 때였다. 그 때까지 베이직만 배웠던 나에겐 실행 파일을 만들어보고 싶은 열망이 있었다. 그리고 실행 파일을 만들기 위해서는 컴파일러 언어라는 것을 배워야 한다는 것도 알게 되었다. 서점에 C언어 책이 많았던 시절이었다. 그 중에 내가 살 수 있는 책은 딱 두 종류 밖에 없었다. 무료 컴파일러가 번들로 끼워져 있던 책이 두 가지 밖에 없었기 때문이었다. 하나가 맥가이버 C언어였던가 그랬고, 다른 하나는 제목은 생각나지 않는데 PCC인가 하는 컴파일러가 들어있던 책이었다. 난 PCC가 들어있던 책을 샀다. 사실 맥가이버 C언어는 서점을 들락날락 하면서 거의 다 봐버렸고 좀 더 비싸기도 했기 때문이었다.&lt;/p&gt;
&lt;p&gt;PCC가 들어있던 그 책은 자료형에 대한 설명으로 시작하는 책이었다. 잠수함 게임을 만드는데 뭐 미사일의 공격력은 정수여야 하니깐 int를 써야 하고, 잠수함 이름은 문자라서 char를 쓴다는 식의 비유로 시작하는 책이었던 것 같다. 나중에 느낀 사실이지만 입문서 치고는 참 괜찮았던 책이었다.&lt;/p&gt;
&lt;p&gt;그 책으로 C언어를 좀 배우고는 만들고 싶은 게 하나 생겼는데 MDIR 같은 프로그램이었다. MDIR은 도스 시절 거의 국민 유틸리티로 통했던 파일 관리자였다. “C로 하드웨어 주무르기”라는 책을 통해서 나름 시스템 프로그래밍에 대해서도 눈을 떴던 나는 금방이라도 MDIR을 만들 수 있을 것 같은 느낌이었다. 그래서 거침없이 코딩을 시작했다. 하지만 안타깝게도 500줄을 타이핑 하기도 전에 코딩을 멈출 수 밖에 없었다.&lt;/p&gt;
&lt;p&gt;MDIR 짝퉁을 만들면서 한 가지 궁금한 게 생겼던 것이다. 디렉터리마다 파일 개수가 다 다른데 그걸 어떻게 저장할까, 라는 질문이었다. 그 당시 배열만 알고 있던 나에게는 무척 궁금한 질문이었다. 내가 3000개를 지정했는데 파일이 4000개가 있으면 어떡하지, 라는 생각이었다. 물론 malloc같은 동적 할당을 사용해서 복사를 하면 되는데 그건 또 답이 아닌 것 같은 느낌이었다. 난 그 질문을 한참을 가지고 있었다. 그리곤 500줄에서 진도는 더 나가지도 못했다.&lt;/p&gt;
&lt;p&gt;그 질문에 답을 찾기 위해서 대형 서점의 컴퓨터 코너에 있는 책은 정말 거의 다 읽다시피 했다. 그런데 그 어느 책에도 답이 나와 있질 않았다. 물론 사실 답은 지천으로 널려 있었지만 단지 내가 찾지 못했을 뿐이었다. 그 답을 중학생도 이해할 수 있게 써 놓은 책은 그리 많지 않았던 것이다. 그러다 한날 “PC Tools 따라하기”라는 책을 통해서 그 마법 같은 방법을 배웠다. 링크드 리스트였다. 충격과도 같은 방법이었다. 동시에 난 왜 이 방법을 생각하지 못했을까라는 자괴감이 들었다.&lt;/p&gt;
&lt;p&gt;링크드 리스트를 배우고 나서도 난 MDIR을 만들지 않았다. “PC Tools 따라하기”라는 책에 그 모든 것이 나와 있어서 재미가 없어졌기 때문이었다. 책의 예제 코드만 따라해도 반쪽짜리 MDIR은 만들 수 있을 정도로 굉장한 책이었다. 그러다 djgpp의 allegro라는 게임 라이브러리에 빠져서 한동안 게임 프로그래밍을 했었던 것 같다.&lt;/p&gt;
&lt;p&gt;난 여기서 반쯤은 위안을 얻기도 하고 반쯤은 좌절하기도 한다. 위안을 얻는 부분은 내가 배열이 정답은 아니라는 사실을 본능적으로 알았다는 점이다. 그럼에도 좌절하는 부분은 링크드 리스트를 절대로 내 머리로는 생각해 낼 수 없었다는 사실이다. 알고 나면 그렇게 어려운 내용이 아니기에 더 좌절감이 큰 것 같기도 하다.&lt;/p&gt;
&lt;p&gt;그 이후로도 난 상당히 오랜 시간 프로그래밍을 했는데 내가 가지는 장점과 단점은 그 일화에 거의 모두 다 들어있다는 느낌이 든다. 난 프로그래밍적인 문제에 대한 직관은 뛰어난 편이다. 답을 알진 못하더라도 답이 있을지 없을지, 내지는 이 방법이 옳은지 틀린지를 판단하는 능력은 좀 좋다는 말이다. 반면 역시 그리 똑똑한 편은 아니다.&lt;/p&gt;
&lt;p&gt;우습게도 나중에 알게 된 사실이지만 초창기 MDIR은 배열을 사용해서 디렉터리 목록을 관리했다고 한다. 그래서 지정된 배열의 원소 개수를 초과하면 해당 파일이 조회되지 않는 문제가 실제로 있었다는 이야기를 들은 적이 있다. 그 이야기를 듣고 난 큰 교훈 하나를 깨닳았는데, 바로 분야에 따라서는 오덕스런 꼼꼼함과 집요함보다는 느슨한 실용성이 더 중요할 수도 있다는 점이었다.&lt;/p&gt;
&lt;p&gt;덧) 가끔 뜨문뜨문 아빠 생각이 날 때가 있다. 중학교 때 이야기를 쓰고 나니 그 때 생각이 난다. 중학교 때 난 난생처음 내 컴퓨터를 가지고는 신나서 밤새 컴퓨터를 하곤 했었다. 종종 아빠는 내 방에서 같이 잠을 잤는데, 그런 날도 난 아랑곳하지 않고는 컴퓨터를 늦게까지 했다. 그러던 어느 날이었다. 새벽에 컴퓨터가 고장나서 디스크를 고치는 중이었다. 지금 생각해보면 진짜 욱긴데 scan disk같은걸로 치료를 하는데 백업을 디스켓에 하겠냐고해서 난 멍청하게 하겠다고 한 것이었다. 새벽 늦게까지 컴퓨터는 미친듯이 디스켓을 갈아 끼우라고 시켰고, 난 또 그걸 꼬박꼬박 했다. 컴퓨터가 새벽에 디스켓에 뭔가를 쓰는 소리는 분명 잠을 자는 아빠한테는 엄청 거슬리는 소리였을텐데 아빠는 나에게 아무 말도 하지 않았다. 내가 컴퓨터 프로그래머가 되는데 가장 큰 사건이 무엇이었냐고 물으면 난 이 이야기를 하곤 한다. 웃기지만 아마 그 때 아빠가 머라고 했다면 난 프로그래머가 안됐을 수도 있었을 것 같기 때문이다. ㅋㅋㅋ&lt;/p&gt;
&lt;p&gt;나이가 들어서도 그랬다. 엄마는 항상 말한다. 치대가라. 약대가라. 졸업할 때는 공무원 해라. 대기업 가라. 그래도 아빠는 항상 나의 편이었다. 내가 하는 일을 잘 아시진 않았지만 언제나 아들이 하는 일이 멋있어 보인다며 말이다. 글을 써놓고 보니 그런 아버지가 유난히 생각난다. 무에 그리 급하셨는지… ㅠㅜ~ 아버지, 좋은 곳에 잘 계시죠?&lt;/p&gt;
&lt;p&gt; 1
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[해킹툴 박멸 퀘스트에 참여하실 프로그래머/리버서 모집합니닷!!!]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/7276</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7276</guid><pubDate>Mon, 04 Jun 2012 23:58:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;이 글은 온니 구인광고 목적으로 올린 글입니다. 몇 분께서 오픈 프로젝냐고 물어보셨는데요, 안타깝게도 오픈프로젝트는 아닙니다. 제가 대부분 다 별도로 회신을 드렸는데 부득이하게 회사 메일이 지메일에는 블록이 돼 있어서, 해당 메일로 보내주신 분들께는 회신을 못드렸습니다. 다음에 오픈 프로젝트로 뭔가를 진행하게 된다면 메일을 드리도록 하겠습니다. 개발자는 계속 채용 중이니까요. 관심 있으신 분들은 많이 지원해 주세요!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.wellbia.com&quot;&gt;(주)웰비아닷컴&lt;/a&gt;에서 해킹툴 박멸 퀘스트를 함께 진행할 참신한 엔지니어 분들을 모집합니다. 지구의 평화를 위협하며 개인의 의지를 무참히 짓밟는 해킹툴 세력에 맞서서 버티기가 가능하다, 라고 생각하시는 분들은 지원을 자제해 주시구요. 싸워서 이길 의지가 있으신 분들의 많은 지원부탁드립니다. 뭐 사실 장비는 그리 중요하지 않습니다. 이기겠다는 의지와 열정이 중요하죠. 물론 그래도 기본 장비는 좀 갖춰져야 싸움을 시작이라도 할 수 있다는 건 아시죠? 지원 방법은 어떻게 되냐구요? 간단한 이력서와 자기소개서를 codewiz at wellbia dot com으로 보내주시면 됩니다. 별도 양식은 없습니다. &lt;a href=&quot;http://jiniya.net/tt/694&quot;&gt;4년 만에&lt;/a&gt; 이런 글을 올리니 참 감회가 새롭네요. 내용을 새로 썼는데 찾아보니 그 때나 지금이나 별반 달라지진 않았군요. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;프로그래머&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;윈도우 시스템 프로그래밍 경력 2-3년 이상&lt;/p&gt;
&lt;p&gt;C/C++을 잘한다.&lt;/p&gt;
&lt;p&gt;Python도 할 줄 안다.&lt;/p&gt;
&lt;p&gt;Windows의 내부 구조를 쫌 안다.&lt;/p&gt;
&lt;p&gt;Visual C++을 다년간 사용해 봤다.&lt;/p&gt;
&lt;p&gt;프로그래머란 직업을 사랑한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;테스트 프로그래머&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;신입&lt;/p&gt;
&lt;p&gt;C/C++을 배웠다.&lt;/p&gt;
&lt;p&gt;Python도 배워볼 생각이 있다.&lt;/p&gt;
&lt;p&gt;Windows 프로그래밍 책을 몇 권 쯤은 읽었다.&lt;/p&gt;
&lt;p&gt;시스템 프로그래밍에 관심이 많다.&lt;/p&gt;
&lt;p&gt;프로그래밍이 정말 재밌어 죽겠다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;해킹툴 분석가&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;신입/경력&lt;/p&gt;
&lt;p&gt;진짜 리버싱을 할 줄 안다.&lt;/p&gt;
&lt;p&gt;C/C++을 할 줄 안다.&lt;/p&gt;
&lt;p&gt;Windows API도 쫌 안다.&lt;/p&gt;
&lt;p&gt;PoC 정도는 직접 구현할 수 있다.&lt;/p&gt;
&lt;p&gt;세상 모든 것들을 리버싱하고 싶은 욕구가 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;아래 사항에 부합하면 더욱 좋습니다. ^^;;&lt;/strong&gt;&lt;/p&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;
&lt;p&gt;블로거다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;미친듯이 해 본 온라인 게임이 하나 이상은 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;연애 경험이 좀 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;좋아하는 작가가 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[상수를 왼쪽에 쓰는 이유…]]></title><description><![CDATA[흔한 C언어 비교 구문입니다. C언어 코딩 컨벤션 중에 위와 같은 구문에서 if…]]></description><link>https://jiniya.net/wp/archives/7328</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7328</guid><pubDate>Wed, 30 May 2012 23:58:09 GMT</pubDate><content:encoded>&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 뭔가 멋진 동작&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;흔한 C언어 비교 구문입니다. C언어 코딩 컨벤션 중에 위와 같은 구문에서 if문의 상수 위치를 변경해서 사용하는 것이 있습니다. 아래와 같이 말이죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 뭔가 멋진 동작&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 것을 강제하는 회사도 있는데, 전 개인적으로 이 표기법을 굉장히 증오합니다. 잘못 알려진 헝가리언 표기법 만큼이나 싫어합니다. 그런데 중요한 것은 위와 같은 방식에는 그 나름의 논리적인 이유가 있어서 저렇게 한다는 겁니다. 그런데 맥락도 모르고 그냥 상수를 왼쪽에다 쓰는 건줄 알고 사용하는 개발자들이 있습니다. 아래처럼 말이죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 뭔가 멋진 동작&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;정말 이건 아닙니다. 이건 아니예요. 우선 왜 if문의 상수를 왼쪽에다 쓰는지 그 이유를 알아봅시다. C언어의 경우 대입 연산자도 표현식으로 if문에 사용할 수 있습니다. 대입 연산자의 경우에 대입된 값이 if문 평가에 사용되죠. 즉, 아래 코드가 완전 합법적인 C 코드라는 말이죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 뭔가 멋진 동작&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;개발자가 의도한건 저런건 아니었겠죠. 왜냐하면 저건 사실 아래와 동일한 코드이기 때문에 if문을 쓸 필요가 없습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;A &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 뭔가 멋진 동작&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 개발자가 한 실수는 사소한 타이핑 실수입니다. ‘==’ 를 써야 할 자리에 ‘=’를 쓴거죠. 그러면서 구문 자체가 완전 엉뚱해져 버린 겁니다. 엄청난 코드 더미에서 이런 실수가 하나 있다면 잡는게 쉽진 않겠죠. 그래서 앞서 말한 상수를 왼쪽에다 적는 컨벤션이 나온 겁니다. if(10 = A) 이렇게 실수로라도 쓰면 컴파일 오류가 나거든요. 이런 사소한 타이핑 실수를 방지하기 위해서 상수를 왼쪽에다 쓰는 겁니다.&lt;/p&gt;
&lt;p&gt;자 그럼 이제 if(10 &gt;= A)를 살펴봅시다. 이건 정말 의미 없는 짓입니다. if(10 &gt;= A)를 타이핑하려고 했던 개발자가 실수로 if(10 = A)로 타이핑을 할까요? 별로 가능성이 없습니다. 그러니 이런 표현식에는 애초에 굳이 상수를 왼쪽에다 쓸 필요가 없는거죠.&lt;/p&gt;
&lt;p&gt;끝으로 제가 이 표현식을 왜 증오하는지를 조금 설명드리겠습니다. 코드는 컴퓨터가 읽는게 아니라 사람이 읽는 겁니다. if(10 == A)라는 구문을 만난다고 생각해봅시다. 10은 A와 같다라고 보통은 읽힐 겁니다. 눈에 10이 먼저 들어오니까요. 그런데 우리가 원래 하려고 했던 생각은 대체로 A는 10과 같다일겁니다. 즉, 한번 꼬여서 머릿속에 들어온다는 거죠. if(10 &gt;= A)가 되면 좀 더 심해집니다. 당연히 원래 의도는 A는 10보다 작거나 같다를 의도했겠지만 실제 식은 10은 A보다 크거나 같다가 되었습니다. 머리에서 한번 더 생각해야하고 번역 작업이 들어간다는 거죠. 그래서 전 이런 표현식을 싫어합니다. 아주 많이.&lt;/p&gt;
&lt;p&gt;진짜 끝으로 한 가지 이야기만 더 하겠습니다. 이건 C언어 이야깁니다. 파이썬 코드를 if 10 == A:와 같이 작성할 필요는 정말 전혀 없습니다. 왜냐하면 파이썬에서는 if A = 10: 자체가 오류가 나는 구문이기 때문입니다. 그러니 머릿속에서 생각나는대로 구현하면 됩니다. 젭알 그걸 한번 더 꼬아서 쓸 필요는 없어요.&lt;/p&gt;
&lt;p&gt;진짜 진짜 끝으로 사족을 하나 더 달자면 요즘 컴파일러는 정말 기똥차게 좋습니다. if(A = 10) 같은 구문은 경고 레벨만 올려도 잡을 수 있고, 정적 분석 도구를 사용한다면 지나치다 싶을 정도로 친절한 설명을 들을 수 있습니다. 그러니 우리가 고생하면서 꼬아서 쓸 필요가 없습니다. 선조들이 돌도끼로 사냥했다고 우리도 돌도끼로 사냥할 필요는 없잖아요.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/1337995436-22.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/1337995436-22.png&quot; alt=&quot;&quot; title=&quot;1337995436-22&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;좋은 도구를 사용해야 레벨업이 편합니다. 현실 세계에서도 말이죠.&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[스레드 다루기 (기초편)]]></title><description><![CDATA[윈도우는 스레드를 관리하기 위해서 다양한 함수들을 제공해 준다. 그러한 함수들을 살펴보기에 앞서서 윈도우는 스레드를 위해서 어떠한 속성들을 저장하고 관리하는지를 먼저 살펴보도록 하자. <화면 1>에는 Process Hacker…]]></description><link>https://jiniya.net/wp/archives/7194</link><guid isPermaLink="false">https://jiniya.net/wp/archives/7194</guid><pubDate>Fri, 04 May 2012 23:58:08 GMT</pubDate><content:encoded>&lt;p&gt;윈도우는 스레드를 관리하기 위해서 다양한 함수들을 제공해 준다. 그러한 함수들을 살펴보기에 앞서서 윈도우는 스레드를 위해서 어떠한 속성들을 저장하고 관리하는지를 먼저 살펴보도록 하자. &amp;#x3C;화면 1&gt;에는 Process Hacker라는 유틸리티를 사용해서 특정 프로세스에서 생성한 스레드 목록을 살펴보고 있다. 이 화면에는 윈도우에서 저장하고 있는 스레드의 속성의 거의 대부분이 포함되어 있다. 각각의 항목이 어떤 의미를 나타내는지 먼저 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image001.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image001.png&quot; alt=&quot;&quot; title=&quot;image001&quot;&gt;&lt;/a&gt;
&lt;strong&gt;화면 1 스레드 속성들&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;화면에서 제일 먼저 보이는 것은 TID라는 것이다. 이는 Thread Identifier의 약자로 스레드 아이디를 의미한다. 윈도우에서 동작하는 모든 스레드는 이 아이디를 통해서 다른 스레드와 구분된다. 다음으로는 Start Address가 보인다. 이는 스레드의 시작 주소가 된다. 스레드는 이 주소에서 시작해서 이 함수가 ExitThread를 호출할 때까지 수행을 이어나간다. 다음으로는 Priority가 있다. 이는 우선순위를 나타내는 것으로 해당 스레드가 얼마나 높은 빈도로 스케줄링 될 것인지를 나타낸다. 아래에 있는 Started라고 표시된 항목은 스레드의 시작 시간을 나타낸다. State는 현재 스레드의 상태를 나타낸다. Kernel Time은 스레드가 수행한 커널 코드의 시간을 나타내며, User Time이란 스레드가 수행한 유저 코드의 시간을 나타낸다. Context Switches는 컨텍스트 전환 횟수를 Cycles는 이 스레드가 사용한 CPU 클럭을 나타낸다.&lt;/p&gt;
&lt;p&gt;그러면 이제부터 스레드를 어떻게 생성하고 종료시키는지부터 개별 스레드의 이러한 속성들을 어떻게 프로그램 내에서 조작할 수 있는지에 대해서 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스레드의 탄생&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CreateThread와 CreateRemoteThread는 윈도우에서 스레드의 탄생을 책임지고 있는 함수다. 이 두 함수는 동일하게 스레드를 생성하는 역할을 한다. 단지 차이가 있다면 CreateThread는 호출한 프로세스에서 동작하는 스레드를 생성하는 역할을 하며, CreateRemoteThread는 파라미터로 넘어온 프로세스에서 수행되는 스레드를 생성하는 역할을 한다. 실제로 윈도우 내부에서 CreateThread는 GetCurrentThread를 사용해서 CreateRemoteThread를 호출하는 것으로 구현되기 때문에 CreateThread는 CreateRemoteThread의 서브셋이라고 보면 되겠다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 1&gt;에는 이 두 함수의 원형이 나와 있다. CreateThread의 함수 원형을 살펴보면 6개의 파라미터를 받는 복잡한 함수라는 것을 알 수 있다. 하지만 주로 사용하는 파라미터는 몇 개 되지 않기 때문에 차근차근 사용 방법을 살펴보면 크게 어렵지는 않다. 첫 번째 파라미터는 스레드의 보안 속성이다. 보통은 NULL을 전달하면 된다. 두 번째 파라미터로는 스레드 스택 크기를 지정한다. 0을 넘겨주면 기본 스택 크기로 스레드가 생성된다. 세 번째 파라미터인 lpStartAddress로는 실제 스레드가 수행될 함수 포인터를, 네 번째 파라미터인 lpParameter로는 lpStartAddress로 전달될 파라미터를 넘겨주면 된다. dwCreationFlags는 생성 플래그를 지정한다. 0을 지정하면 기본 상태로 생성한다. 스레드를 정지된 상태로 생성하고 싶으면 이 플래그에 CREATE_SUSPENDED를 지정하면 된다. 끝으로 lpThreadId에는 스레드 아이디를 전달 받을 포인터를 넘겨주면 된다. 스레드 아이디가 필요 없다면 NULL을 지정하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 1 CreateThread, CreateRemoteThread 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DWORD&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__stdcall &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;LPTHREAD_START_ROUTINE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPVOID lpThreadParameter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

HANDLE WINAPI &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    LPSECURITY_ATTRIBUTES lpThreadAttributes
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T dwStackSize
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPTHREAD_START_ROUTINE lpStartAddress
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID lpParameter
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD dwCreationFlags
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPDWORD lpThreadId
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

HANDLE WINAPI &lt;span class=&quot;token function&quot;&gt;CreateRemoteThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    HANDLE hProcess
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPSECURITY_ATTRIBUTES lpThreadAttributes
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T dwStackSize
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPTHREAD_START_ROUTINE lpStartAddress
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPVOID lpParameter
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD dwCreationFlags
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPDWORD lpThreadId
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우에서 동일한 실행 파일을 가진 프로세스를 여러 개 동시에 실행할 수 있는 것처럼 스레드 또한 동일한 lpStartAddress를 가지는 것을 동시에 여러 개 만들 수 있다. 이렇게 만들어진 스레드 인스턴스를 구분하기 위해서는 스레드 아이디라는 것이 사용된다. 스레드 내에서 현재 자신의 스레드 아이디를 구하기 위해서는 GetCurrentThreadId라는 함수를 사용하면 된다. 파라미터는 없으며, 리턴 값은 현재 실행되고 있는 스레드의 아이디를 반환해 준다. 마찬가지로 GetCurrentThread를 사용하면 현재 실행되는 스레드의 의사 핸들을 반환 받을 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 2&gt;에는 이러한 스레드 함수를 사용해서 실제로 스레드를 생성하는 예제가 나와 있다. 프로그램은 PrintThread 함수를 시작 주소로 하는 스레드를 세 개 생성해서 해당 스레드가 종료될 때까지 기다리는 역할을 한다. 세 개의 스레드가 모두 종료되면 프로그램도 같이 종료된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 2 PrintThread 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

DWORD
CALLBACK
&lt;span class=&quot;token function&quot;&gt;PrintThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG_PTR id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; param&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[TID = %8d] [PARAM = %d] Running...\n&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentThreadId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        threads&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PrintThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;WaitForMultipleObjects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threads&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; threads&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Complete\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;화면 2&gt;에는 PrintThread 프로그램의 실행 화면이 나와 있다. &amp;#x3C;화면 2&gt;를 살펴보면 스레드가 생성 순서를 기준으로 0, 2, 1, 1, 2, 0, 0, 2, 1 순서대로 실행된 것을 볼 수 있다. 직접 입력해서 프로그램을 실행해보면 아마 화면의 순서와는 또 다른 실행 흐름을 볼 수 있을 것이다. 이렇게 스레드 프로그래밍은 운영체제 스케줄링 순서에 따라서 매번 실행 흐름이 바뀐다는 특징이 있다. 이런 비결정적인 특성 때문에 멀티 스레드 관련 버그들은 항상 재연이 쉽지 않고 재연이 된다 하더라도 그것을 관찰하려고 하면 버그가 사라지는 하이젠버그 같은 것들이 자주 만들어진다. 이런 특수한 성질이 있기 때문에 멀티스레드 프로그래밍에 있어서는 항상 머릿속으로 모든 실행 흐름을 염두에 두고 꼼꼼하게 따져보는 습관을 가지는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image002.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image002.png&quot; alt=&quot;&quot; title=&quot;image002&quot;&gt;&lt;/a&gt;
&lt;strong&gt;화면 2 PrintThread 실행 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스레드 종료&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;스레드 생성 부분을 살펴보았으니 이번에는 스레드를 종료 시키는 방법에 대해서 살펴보도록 하자. 스레드 종료에는 ExitThread, TerminateThread, FreeLibraryAndExitThread등의 함수가 사용된다. &amp;#x3C;리스트 3&gt;에는 각 함수의 원형이 나와 있다. ExitThread는 가장 기본적인 함수로 해당 함수를 호출한 스레드를 종료하는 역할을 한다. 파라미터로는 스레드 종료 코드가 넘어간다. TerminateThread는 특정 스레드를 강제로 종료 시키는 역할을 한다. TerminateThread의 파라미터로는 종료시킬 스레드 핸들과 종료 코드가 넘어간다. 끝으로 FreeLibraryAndExitThread 함수는 스레드를 종료함과 동시에 특정 모듈을 FreeLibrary 시키는 역할을 한다. DLL 내에서 생성된 스레드에서 해당 스레드 종료와 동시에 모듈을 언로드 시키고 싶을 때 사용하기에 적합한 함수다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 3 스레드 종료 관련 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;VOID WINAPI &lt;span class=&quot;token function&quot;&gt;ExitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD dwExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;TerminateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD dwExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
VOID WINAPI &lt;span class=&quot;token function&quot;&gt;FreeLibraryAndExitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE hModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DWORD dwExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;GetExitCodeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPDWORD lpExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우 환경에서 프로그래밍을 해본 독자라면 사실 이렇게 복잡한 함수를 직접 호출하지 않고도 그냥 스레드 함수가 리턴 함으로써 스레드가 종료된다는 사실을 알고 있을 것이다. 앞서 작성해본 &amp;#x3C;리스트 2&gt;의 프로그램도 그렇게 스레드를 종료했다. 또한 대부분의 책에서 그렇게 종료하는 것이 가장 좋은 방법이라고 강조하고 있다. 그렇다면 어떻게 스레드 함수가 리턴하는 것만으로도 스레드가 종료될 수 있을까? 그 마법의 비밀은 다름아닌 윈도우의 CreateThread 구현에 있다. CreateThread 함수는 사실 lpStartAddress를 시작으로 하는 스레드를 생성하지 않는다. 대신 &amp;#x3C;리스트 4&gt;에 나타난 것과 같이 BaseThreadStart라고 명명된 래퍼 함수를 시작 주소로 하는 스레드를 생성한다. 해당 래퍼 함수는 &amp;#x3C;리스트 4&gt;에 나와있는 것과 같이 개발자가 실제로 생성하려고 넘겨 주었던 lpStartAddress를 호출하고 해당 함수가 리턴하면 자동으로 ExitThread를 호출하도록 되어 있다. 이런 이유로 우리가 만든 스레드 시작 함수가 리턴 하는 것만으로도 자연스럽게 스레드가 종료될 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 4 BaseThreadStart 함수 의사 코드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;VOID
&lt;span class=&quot;token function&quot;&gt;BaseThreadStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    LPTHREAD_START_ROUTINE lpStartAddress&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    LPVOID lpParameter
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;ExitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lpStartAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lpParameter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;한 가지 더 살펴볼만한 내용은 TerminateThread 함수에 관한 오해다. 많은 책에서 TerminateThread를 사용하면 리소스 반환이 정상적으로 되지 않고 마치 큰 일이 생기는 것처럼 언급하고 있지만 이는 사실 잘못된 내용이다. TerminateThread를 호출한다고 해서 리소스 반환이 되지 않고 ExitThread를 호출한다고 해서 리소스 반환이 되는 것은 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 5&gt;와 같은 스레드를 살펴보자. 이 스레드는 스레드 함수 내에서 메모리를 할당한 다음 리턴한다. 이 스레드 함수가 정상적으로 종료된다면 결국 궁극에는 ExitThread에 의해서 종료된다. 그렇다면 ExitThread 함수는 할당된 buffer를 자동으로 소거해 줄까? 당연히 하지 않는다. 이 스레드의 경우에는 ExitThread로 종료하던, TerminateThread로 종료하던 스레드가 종료되면 메모리 릭이 발생한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 5 메모리 할당 작업을 하는 스레드&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD
CALLBACK
&lt;span class=&quot;token function&quot;&gt;Thread1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우는 프로그램에서 사용하는 리소스와 관련해서 스레드 별로 할당 내용을 추적하지 않는다. 따라서 ExitThread나 TerminateThread 모두 리소스를 소거해 주는 역할을 가지고 있지는 않다. TerminateThread와 ExitThread 사이의 차이는 단지 누가 언제 스레드를 종료 시키느냐의 차이 밖에는 없다. &amp;#x3C;리스트 6&gt;를 살펴보면 그러한 차이를 알 수 있다. &amp;#x3C;리스트 6&gt;의 스레드 루틴은 buffer를 할당한 다음 작업을 하고 buffer를 삭제한 다음 종료한다. 이 경우에 있어서 ExitThread에 의해서 종료된다는 것은 항상 자신이 생성한 buffer 리소스에 대해서 해제 작업이 완료된 다음에 종료된다는 것을 알 수 있다. 하지만 외부에서 TerminateThread로 종료 시키는 경우에는 스레드 실행 시점에 따라서 buffer가 해제된 다음일 수도 있고, buffer가 사용 중인 도중일 수도 있다. 따라서 이 경우에는 실행 시점에 따라서 리소스 릭이 발생할 수도 있고, 아닐 수도 있게 되는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 6 리소스 해제가 추가된 스레드 루틴&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD
CALLBACK
&lt;span class=&quot;token function&quot;&gt;Thread2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// buffer 관련 작업&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국은 ExitThread나 TermianteThread나 운영체제 내부적으로 리소스 해제와 관련된 작업을 해주는 것은 없다. 스레드 내에서 생성된 리소스에 대한 책임은 해당 리소스를 생성한 스레드 루틴에 있다. TerminateThread라고 무턱대고 사용하지 말아야 하는 함수라고 생각하기보다는 이러한 내부적인 차이점을 정확하게 이해하고 상황에 맞는 함수를 선택해서 사용하는 습관을 가지는 것이 좋겠다.&lt;/p&gt;
&lt;p&gt;끝으로 스레드의 종료 상태를 알아내는 방법에 대해서 살펴보자. 스레드의 종료 상태를 알아내기 위해서는 GetExitCodeThread 함수가 사용된다(&amp;#x3C;리스트 3&gt; 참고). hThread로 종료 상태를 알고 싶은 스레드를 전달하면 lpExitCode로 종료 상태가 넘어온다. 종료되지 않고 스레드가 실행중인 상태라면 lpExitCode로 STILL_ACTIVE가 전달되며, 종료된 상태라면 스레드 종료 코드가 넘어온다.&lt;/p&gt;
&lt;p&gt;실전에서는 GetExitCodeThread 함수보다는 WaitForSingleObject가 훨씬 더 많이 사용된다. 스레드 객체는 윈도우 운영체제에 의해서 종료 시에 시그널 상태로 설정된다. 따라서 WaitForSingleObject로 스레드 핸들을 전달해서 WAIT_OBJECT_0이 반환된다면 해당 스레드는 종료된 것이며, 다른 값이 반환된다면 여전히 실행 중인 상태로 판단할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스레드 일시 정지와 재개&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;스레드는 언제든지 SuspendThread 함수를 통해서 일시 정지 시킬 수 있고, 또 ResumeThread를 통해서 실행을 재개할 수 있다. 각 함수의 원형은 &amp;#x3C;리스트 7&gt;에 나와 있다. 파라미터로 전달되는 hThread는 실행을 중지 하거나 재개시킬 스레드 핸들이며, 반환 값은 이전에 실행이 중지된 횟수를 반환한다. 중지된 횟수를 반환한다는 의미는 SuspendThread를 두 번 호출했다면 ResumeThread를 두 번 호출해야 스레드가 실제로 다시 수행된다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 7 SuspendThread/ResumeThread 함수 원형&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD WINAPI &lt;span class=&quot;token function&quot;&gt;SuspendThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
DWORD WINAPI &lt;span class=&quot;token function&quot;&gt;ResumeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 8&gt;에는 SuspendThread와 ResumeThread를 사용해서 스레드를 정지 시키고 다시 재개시키는 프로그램이 나와 있다. 프로그램의 코드를 바꿔가면서 SuspendThread와 ResumeThread의 반환 값이 어떤 식으로 동작하는지 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 8 SuspendResumeThread 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE thread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ThreadFunc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SuspendThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;suspend count = %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SuspendThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;suspend count = %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ResumeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;suspend count = %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ResumeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;suspend count = %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;스레드 컨텍스트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;하나의 CPU 상에서도 스레드를 동시에 실행시키기 위해서는 스레드를 중지시킨 이후에 다시 실행을 재개 시키기 위해서는 어디서부터 실행을 재개할지 저장해 두어야 한다. 이렇게 다시 실행 시킬 위치를 저장해 두는 것을 컨텍스트라고 표현한다. x86/x64 환경에서는 이러한 컨텍스트로 CPU 레지스터를 저장해둔다. 해당 레지스터만 있으면 언제든지 다시 실행을 재개할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;윈도우에서는 특정 스레드의 컨텍스트를 구하기 위해서 GetThreadContext를 반대로 특정 스레드의 컨텍스트를 설정하기 위해서는 SetThreadContext라는 함수를 사용한다. &amp;#x3C;리스트 9&gt;에는 해당 함수의 원형이 나와 있다. GetThreadContext 함수는 hThread로 지정된 스레드의 컨텍스트를 lpContext에 저장하는 역할을 한다. 이 함수를 사용할 때 한 가지 주의해야 할 점은 lpContext의 ContextFlags는 함수 호출 전에 미리 설정해 두어야 한다는 점이다. GetThreadContext가 lpContext의 ContextFlags에서 지정한 것과 관계된 레지스터 값만 반환하기 때문이다. SetThreadContext 함수는 hThread로 지정된 스레드의 컨텍스트를 lpContext로 대체시키는 역할을 한다. 이 두 함수 모두 현재 스레드나 실행 중인 스레드에 대해서 함수 호출을 할 경우에는 정상적인 컨텍스트를 구할 수 없다. 따라서 이 함수를 호출하기 위해서는 항상 대상 스레드를 일단 SuspendThread로 중지 시킨 다음에 작업해야 한다는 점을 명심하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 9 스레드 컨텍스트 관련 함수들&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;GetThreadContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCONTEXT lpContext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;SetThreadContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HANDLE hThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CONTEXT &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;lpContext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 10&gt;에는 GetThraedContext/SetThreadContext 함수를 사용해서 실행중인 스레드의 컨텍스트를 런타임에 변경하는 작업을 보여준다. SetThreadContext로 지정하기 전에 Eip를 Bypass로 바꾸었기 때문에 ResumeThread가 수행되면 스레드는 Bypass 함수부터 스레드 수행을 재개한다. &amp;#x3C;화면 3&gt;에는 DebugView를 통해서 프로그램 실행 중에 디버그 출력을 캡쳐한 화면이 나와 있다. 화면에 나타난 것을 살펴보면 정상적이라면 실행되지 않았을 Bypass 함수가 실행된 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 10 Bypass 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

ULONG
&lt;span class=&quot;token function&quot;&gt;Bypass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;OutputDebugStringA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bypass\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;ExitThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ULONG
CALLBACK
&lt;span class=&quot;token function&quot;&gt;MyThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG ntick &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetTickCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;OutputDebugStringA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetTickCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ntick&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        ntick &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetTickCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE thread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MyThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;SuspendThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    CONTEXT ctx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ctx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ContextFlags &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CONTEXT_FULL&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;GetThreadContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ctx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ctx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Eip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Bypass&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;SetThreadContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ctx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;ResumeThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image003.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image003.png&quot; alt=&quot;&quot; title=&quot;image003&quot;&gt;&lt;/a&gt;
&lt;strong&gt;화면 3 Bypass 프로그램 실행 화면&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 10&gt;의 프로그램에서는 Bypass 함수에서 ExitThread를 호출해서 스레드를 강제로 종료시킨다. 이렇게 하지 않고 Bypass 함수를 수행한 다음 원래 스레드 컨텍스트로 돌아가서 MyThread의 남은 코드를 마저 실행 시키도록 만들 방법은 없는지 생각해보자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스레드 실행 시간&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;스레드 실행 시간을 구하는 데에는 GetThreadTimes 함수가 사용된다. 함수 원형은 아래 나와 있는 것과 같다. hThread로는 실행 시간을 구하고 싶은 스레드의 핸들을 전달해 주면, lpCreationTime에는 해당 스레드가 생성된 시간이, lpExitTime에는 해당 스레드가 종료된 시간이, lpKernelTime에는 해당 스레드가 사용한 커널 영역 코드의 시간이, lpUserTime은 해당 스레드가 사용한 유저 영역 코드의 시간이 넘어온다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;GetThreadTimes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    HANDLE hThread
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPFILETIME lpCreationTime
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPFILETIME lpExitTime
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPFILETIME lpKernelTime
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPFILETIME lpUserTime
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수를 사용하면 특정 스레드의 CPU 점유율을 계산할 수 있다. CPU 점유율이란 “사용한 CPU 시간 / 전체 CPU 시간”으로 계산할 수 있고, 사용한 CPU 시간은 앞서 살펴본 GetThreadTimes 함수의 lpKernelTime과 lpUserTime을 합한 값으로 계산할 수 있다. &amp;#x3C;리스트 11&gt;에는 이러한 기본적인 원칙을 바탕으로 작성한 현재 스레드의 CPU 점유율을 출력해주는 CpuUsagePrinter 클래스 코드가 나와 있다. CpuUsagePrinter의 순간 점유율은 Reset 이후부터 Dump를 수행할 때까지의 점유율을 최근 1분은 최근 1분간 스레드의 CPU 점유율을 보여준다.&lt;/p&gt;
&lt;p&gt;CpuUsagePrinter에서 출력되는 CPU 점유율은 싱글 코어를 기준으로 한 점유율을 말한다. 멀티코어라면 이 점유율이 코어 개수에 대한 비율만큼 줄어들어야 한다. 예를 들어 CpuUsagePrinter가 100%의 점유율을 출력했는데 듀얼코어라면 실제로 듀얼코어 상의 점유율은 50%가 된다는 의미다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 11 CpuUsagePrinter&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; LPCWSTR xcwstr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; UINT64 xuint64&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CpuUsagePrinter&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    FILETIME fkt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fft_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILETIME skt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sft_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FILETIME ekt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eft_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    T &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;printer_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    xcwstr tag_&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;CpuUsagePrinter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcwstr tag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; T &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;printer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printer_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;printer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tag_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;GetSystemTimeAsFileTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        FILETIME ct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; et&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;GetThreadTimes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;et&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;skt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fft_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sft_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fkt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;skt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fkt_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    xuint64 &lt;span class=&quot;token function&quot;&gt;ToUInt64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FILETIME &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        ULARGE_INTEGER u&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HighPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dwHighDateTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LowPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dwLowDateTime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;QuadPart&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    xuint64 &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FILETIME &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FILETIME &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ToUInt64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ToUInt64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;GetSystemTimeAsFileTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        FILETIME ct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; et&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;GetThreadTimes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;et&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fkt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;fut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Dump&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xcwstr tag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        xuint64 lusage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        xuint64 iusage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


        FILETIME ct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; et&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;GetThreadTimes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;et&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ekt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;eut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;GetSystemTimeAsFileTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;eft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        xuint64 ltime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sft_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ltime &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        xuint64 lcpu &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;skt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ekt_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lcpu &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ltime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            lusage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lcpu &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; ltime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            lusage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        xuint64 itime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fft_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itime &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        xuint64 icpu &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fkt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ekt_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDiff64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;icpu &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; itime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            iusage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; icpu &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; itime&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            iusage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        printer_&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%ls 순간: %3llu.%02llu%%    최근 1분: %3llu.%02llu%%\n&quot;&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tag &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; tag &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; tag_
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; iusage &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; iusage &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lusage &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lusage &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ltime &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;skt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ekt_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;skt_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;eut_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sut_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sft_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;eft_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sft_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CpuUsagePrinter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Dump&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tag_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 12&gt;에는 CpuUsagePrinter를 사용해서 간단한 스레드의 CPU 점유율을 측정하는 예제가 나와 있다. CalcThread를 실행하면 &amp;#x3C;화면 4&gt;에 나와 있는 것과 같이 스레드 동작 과정에서 CPU 점유율이 지속적으로 표시된다. CalcThread 코드를 바꿔가면서 CPU 점유율이 어떻게 변화하는지 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;리스트 12 CalcThread 프로그램&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;windows.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;printer&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lpcstr fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        va_list ap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;va_start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ap&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fmt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;vprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;va_end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

DWORD
CALLBACK
&lt;span class=&quot;token function&quot;&gt;CalcThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    CpuUsagePrinter&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Printer&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;token string&quot;&gt;&quot;CalcThread&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Printer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ULONG_PTR id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; param&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cpu&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; k &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            k &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; k &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        cpu&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Dump&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HANDLE thread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CalcThread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image004.png&quot;&gt;&lt;img src=&quot;http://www.jiniya.net/wp/wp-content/uploads/2012/05/image004.png&quot; alt=&quot;&quot; title=&quot;image004&quot;&gt;&lt;/a&gt;
&lt;strong&gt;화면 4 CalcThread 실행 화면&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[내가 생각하는 장인, 그리고 장인이 되는 길…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/6917</link><guid isPermaLink="false">https://jiniya.net/wp/archives/6917</guid><pubDate>Wed, 02 May 2012 23:58:07 GMT</pubDate><content:encoded>&lt;p&gt;아는 녀석 중에 고기 굽기 달인이 한 명 있다. 우리끼리 만나면 항상 고기 굽는 일은 녀석이 전담하는데, 굽는 솜씨가 정말 일품이다. 토욜에도 만나서 고기를 먹었다. 셋이서 먹는데 당연히 고기 굽는 일은 녀석이 했다. 대충 다 굽고는 이제 먹어라, 하는데 나랑 옆에 있던 형이랑 둘이서 그냥 감동의 눈물을 흘렸다. 평소에도 고기를 잘 굽는다는 것은 알고 있었지만 그 날 따라 유달리 더 잘 구운 것 같아 보였기 때문이었다. 그래서 옆에 형이랑 둘이서 호들갑을 떨면서 인증샷을 찍었다. 맛은? 당연히 일품이었다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./내가_생각하는_장인,_그리고_장인이_되는_길.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d1d558b6db9be60027a4a50936ea708c/e224a/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.73684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAID/9oADAMBAAIQAxAAAAHPq4RqyQj/AP/EABoQAAIDAQEAAAAAAAAAAAAAAAECAAMTISL/2gAIAQEAAQUCCM0ZeDIT1S9+hfRhP//EABcRAQEBAQAAAAAAAAAAAAAAAAEAEUH/2gAIAQMBAT8BXlpf/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAgEBPwFWmn//xAAdEAACAgEFAAAAAAAAAAAAAAAAAREhUSMxQXGB/9oACAEBAAY/Aq4M5LTY46NTcil4f//EABsQAQADAQADAAAAAAAAAAAAAAEAESFBMZHw/9oACAEBAAE/IWNYK2IksPABKHpmN2b6LlNgp4IAAgfOT//aAAwDAQACAAMAAAAQND//xAAXEQEAAwAAAAAAAAAAAAAAAAAAESFB/9oACAEDAQE/EKCDH//EABgRAAMBAQAAAAAAAAAAAAAAAAARQQGh/9oACAECAQE/EGtBavT/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFhcYGh/9oACAEBAAE/EDEgAioG+YtQWqHySX7cMaju2D10/cBD3InfE5g3VGMSeLNYAOIEK+7j/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 0&apos; title=&apos;&apos; src=&apos;/static/d1d558b6db9be60027a4a50936ea708c/e224a/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_0.jpg&apos; srcset=&apos;/static/d1d558b6db9be60027a4a50936ea708c/8ccab/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_0.jpg 190w,
/static/d1d558b6db9be60027a4a50936ea708c/ea4c8/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_0.jpg 380w,
/static/d1d558b6db9be60027a4a50936ea708c/e224a/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_0.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;고기굽기 만렙의 위용. 어떤 분야든 우리는 장인의 작품을 대하면 감탄하게 된다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;사진을 찍어놓고는 집에와서 면면히 들여다보니 과연 녀석은 고기 굽기에 있어서는 장인이란 생각이 들었다. ㅋㅋ~ 그 크기의 균일성하며 절단면의 일관성. 섬세하게 발라낸 오도독뼈. 적당한 강도로 굽힌 고기 덩어리들. 그리고 완벽한 배치. 더 심각한건 녀석은 어느 정도는 자신의 고기 굽기에 대해서 철학을 가지고 있다는 점이다. 녀석이 제일 싫어하는 행위는 다 굽지 않았는데 먼저 먹는 것이다. 자신이 판단했을 때 익지 않았는데 손대면 심하게 혼난다 ㅋ~&lt;/p&gt;
&lt;p&gt;사진을 보면서 감탄하다가 문득 장인에 관한 이야기를 좀 해보고 싶다는 생각이 들었다. 장인이란 어떤 사람일까? 또 장인이 되려면 어떻게 해야 할까? 난 프로그래밍도 하나의 예술 행위로 간주하기 때문에 장인정신이 무척 중요하다고 생각한다. 그래서 이런 질문들은 나에게는 다소 엄숙하기도 하고 근엄하기도 한 질문들이다. 이 질문들이 정답이 있는 것도 또 정답을 찾는 것이 쉬운 문제들도 아니지만 편하게 요즘 내가 생각하는 장인에 대한 이야기를 좀 해볼까 한다. 맞다. 모두 다 개똥 철학이다. ㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;XIGNCODE 로그 파일을 설계할 때였다. 로그 파일을 만드는 일이 뭐 대단한 일이냐고 생각할 수 있다. 사실 뭐 정말 아무것도 아닌 일이다. 숙련된 개발자라면 한두 시간 코딩하면 쓸만한 로그 파일 구조를 만들어 낼 수 있다. 더욱이 난 많은 업체에서 다양한 형태의 로그 파일을 수도없이 만들어 보았다. 그렇게 늘 반복적으로 했던 일임에도 XIGNCODE 로그 파일을 설계할 때는 정말 많은 생각을 했다. 그리고 그 생각들은 그 전까지는 내가 전혀 해보지 않은 것들이었다.&lt;/p&gt;
&lt;p&gt;가장 고민을 많이 한 생각은 이거였다. 과연 로그 파일의 크기는 얼마여야 하는가? 어느 정도 크기면 사용자들이 부담없이 로그 파일을 전송할 수 있을까? 압축이란 과정을 통하지 않고도 보내기에 적당한 크기는 얼마일까? 또 어느 정도 크기여야 우리가 그 로그 파일로부터 의미있는 정보들을 충분히 얻을 수 있을까? 사용자의 심리적 바운더리와 우리가 체험하게 될 유용성의 바운더리 사이에서 최대 값을 찾고 싶었던 것이다. 난 로그 파일을 설계하는 것보다 이 아무것도 아닌 문제에 대해서 더 오랜 시간 고민했다.&lt;/p&gt;
&lt;p&gt;그렇게 많이 고민했음에도 로그 파일에는 빈틈은 많다. 난 틈만나면 로그 파일을 새롭게 설계하고 싶은 욕망에 휩싸이곤 하지만 다른 바쁘고 중요한 일들에 치여 로그 파일은 늘 제자리다. 그런 실수들 중에서도 명백하게 내가 가장 제일 잘못했다고 생각하는 한 가지 실수가 있다. 명백히 잘못했지만 아마 영원히 바로 잡긴 힘들것 같은 실수다. 뭘까? 바로 확장자다. 난 로그 파일이라 별 생각없이(&amp;#x3C;= 장인이 되기엔 아직 한 십만년 더 멀었다는 사실에 대한 고백) log라는 확장자를 채택했다. 그런데 이게 왜 문제일까?&lt;/p&gt;
&lt;p&gt;윈도우 정책과 결합하면 놀라운 문제가 된다. 확장자가 숨겨지기 때문이다. 윈도우 탐색기 기본 옵션은 알려진 확장자 숨김이기 때문이다. 따라서 그 옵션을 끄기 전까지 사용자들은 xigncode.log 파일을 보내 주세요, 라고 말해도 그 파일이 없어요, 라고 대답하게 되는 것이다. 치명적이다. 근데 그 확장자가 더 치명적인 두 번째 사실은 윈도우 기본 옵션이 log 파일을 노트패드에다 연결해 놨다는 점이다. 당연히 우리 파일은 암호화된 바이너리 파일이다. 흙~ 노트패드로 열었다. 실수로라도 고쳐서 저장하는 경우에는 말짱 황이다. 유저들이 그런 로그를 보내는 경우도 종종있다.&lt;/p&gt;
&lt;p&gt;로그 파일 설계에 대한 이야기를 하고 싶었던 건 아니다. 내가 이야기하고 싶었던 것은 이전에 다른 제품을 만들 때에는 전혀 신경 쓰지도 않았던 것들에 대해서 많은 부분 신경을 쓰게 됐다는 점이다. 또 이전에 만든 제품들이라면 전혀 문제라고 생각지도 않았을 것들에 대해서도 문제라고 인식한다는 점이다. 누구도 말하지 않았고, 누구도 신경쓰지 않는데도 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 333px; margin-bottom: 16px;&apos; data-url=&apos;./내가_생각하는_장인,_그리고_장인이_되는_길.md_1.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3130569c8142bdca4adc705c532f2e41/7bf32/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_1.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEBQb/xAAXAQADAQAAAAAAAAAAAAAAAAAAAgMB/9oADAMBAAIQAxAAAAGyeZ9JPM81UaNrlpzJ0Yx//8QAHRAAAgICAwEAAAAAAAAAAAAAAQIDEgAhBBETFP/aAAgBAQABBQJ3WaOOsbHlAFH23VbWyFbt89hlAhA15Jn/xAAXEQEBAQEAAAAAAAAAAAAAAAAAARES/9oACAEDAQE/AW1kcv/EABgRAQADAQAAAAAAAAAAAAAAAAABAhES/9oACAECAQE/AWJs7f/EAB8QAAIBBAIDAAAAAAAAAAAAAAABEQIQEiExMkFhcf/aAAgBAQAGPwJpSZJ+DoYzr0bqX2CbOXbVNJwjqf/EAB4QAQACAgEFAAAAAAAAAAAAAAEAESExQVFxgZHh/9oACAEBAAE/IRLptUg4qioJ9yiwUcK3L2EK21lVzvxB7UALgxncTPyCITriAhlddif/2gAMAwEAAgADAAAAEKTZgP/EABsRAQACAgMAAAAAAAAAAAAAAAEAERAxIYHw/9oACAEDAQE/EN8u4i1Z7qDNuH//xAAZEQADAAMAAAAAAAAAAAAAAAAAAREhQVH/2gAIAQIBAT8QkxoStWMbIieH/8QAHxABAAMAAgIDAQAAAAAAAAAAAQARITFRQWFxgaHB/9oACAEBAAE/EA/2HQ3xHSOhQu/H5EiD3n+S2qi3AuvGRUUBqGmzh9MskdHFM42CC2jbSfUdoWmx1WZ8z3BMfaWrp4Vs8x3bl4QUhqq1Zs//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 1&apos; title=&apos;&apos; src=&apos;/static/3130569c8142bdca4adc705c532f2e41/7bf32/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_1.jpg&apos; srcset=&apos;/static/3130569c8142bdca4adc705c532f2e41/8ccab/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_1.jpg 190w,
/static/3130569c8142bdca4adc705c532f2e41/7bf32/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_1.jpg 333w&apos; sizes=&apos;(max-width: 333px) 100vw, 333px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;XIGNCODE의 기반 구조를 변경시킨 드라마, 브레인&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;언젠가 브레인이란 드라마에 심취해서 본방 사수하면서 보던 때가 있었다. 히로인으로 나온 최정원씨도 이뻤지만 신하균씨의 연기가 정말 일품인 드라마였다. 발연기 하는 장면을 연기하는 모습이 얼마가 간지던지 ㅋㅋ~ 여튼 그 드라마를 다 보고는 그런 생각이 들었다. 어쩌면 내가 만드려고 하는 시스템이 뇌랑 비슷한 건 아니었을까, 라는 생각. 소프트웨어로 구성된 독립적인 시스템은 모두 그렇지만 게임보안도 하나의 완성된 계를 이룬다. 각각의 기능들이 있고, 그 기능들은 서로 협력해서 하나의 큰 기능을 만들어 낸다. 그래서 그런 생각을 했다. 아, 뇌를 만들어야겠다. 마치 뇌의 뉴런들이 신경 전달 물질을 통해서 정보를 주고 받는 그것처럼 말이다.&lt;/p&gt;
&lt;p&gt;브레인이 끝나던 밤에 난 우리 코드에 IBrain이란 객체를 추가했다. 또 INeuron을 추가했다. 그리곤 일부 핵심 기능들을 그 INeuron으로 대체했고 IBrain에 추가했다. 그랬더니 놀라운 일이 벌어졌다. 그 300줄로 안되는 코드로 이전에는 아주 복잡하고 지저분하게 구현했던 것들이 깔끔해지는 놀라운 현상을 목격한 것이다. 뉴런 간 크로스 체크를 더욱 은밀하게 할 수 있었고, 동일한 기능을 하는 뉴런이 여러 개 있다면 가장 우수한 뉴런을 선택해서 기능을 수행할 수도 있게 되었다.&lt;/p&gt;
&lt;p&gt;300줄도 안되는 객체를 만든 것을 두고 호들갑을 떨려던 것은 아니다. 내게 이 사건이 놀라웠던 이유는 드라마를 보면서 내가 그런 생각을 했다는 점이다. 단지 그게 신기했다. 어쩌면 난 드라마를 보는 동안에도 우리 제품을 어떻게하면 더 좋게 만들지를 고민하고 있었는지도 모른다. 무의식이 의식을 지배하는 그것처럼 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;미켈란젤로에 관한 일화 중에 이런 이야기가 있다. 그가 천장 벽화 작업을 하고 있을 때 였다. 아래에서는 보이지도 않는 구석까지 그가 신경써서 다듬는 것을 보고는 조수가 그에게 잘 보이지도 않는 부분까지 왜 그렇게 신경을 쓰냐고 물었다. 미켈란젤로가 말한다. 내가 보잖아.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./내가_생각하는_장인,_그리고_장인이_되는_길.md_2.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e08f48a6c558297ae440fb90fcebc56e/e224a/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_2.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABy6ReVkRv/8QAGRAAAgMBAAAAAAAAAAAAAAAAAQIQESES/9oACAEBAAEFAkGutQGzuP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABoQAAIDAQEAAAAAAAAAAAAAAAABESExQVH/2gAIAQEAAT8hpxpvfUJJaRoNH6TNn//aAAwDAQACAAMAAAAQuM//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxBX/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEh/9oACAECAQE/ENR//8QAGhABAAMAAwAAAAAAAAAAAAAAAQARITFBUf/aAAgBAQABPxBGqawZeHMLr2GaJrBscWO7bEB6Zfmn/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                         md 2&apos; title=&apos;&apos; src=&apos;/static/e08f48a6c558297ae440fb90fcebc56e/e224a/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_2.jpg&apos; srcset=&apos;/static/e08f48a6c558297ae440fb90fcebc56e/8ccab/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_2.jpg 190w,
/static/e08f48a6c558297ae440fb90fcebc56e/ea4c8/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_2.jpg 380w,
/static/e08f48a6c558297ae440fb90fcebc56e/e224a/%EB%82%B4%EA%B0%80_%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94_%EC%9E%A5%EC%9D%B8%2C_%EA%B7%B8%EB%A6%AC%EA%B3%A0_%EC%9E%A5%EC%9D%B8%EC%9D%B4_%EB%90%98%EB%8A%94_%EA%B8%B8.md_2.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;strong&gt;미켈란젤로의 서명이 있는 유일한 작품이자 그의 처녀작, 피에타&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;지금까지 이야기하려던 장인의 모습이 바로 미켈란젤로다. 난 어떤 기능의 숙련됨의 정도가 장인을 나타내는 지표는 아니라고 생각한다. 진정한 장인이냐 아니냐는 어떤 행위를 얼마냐 잘하느냐가 아닌 그 행위를 하는 그의 태도에 달려 있다고 생각한다. 어떤 창조물이 사람들을 감동시키는 것 또한 그것이 얼마나 잘 만들어졌냐 아니냐를 떠나서 그걸 만드는 동안에 그걸 만든 사람의 태도가 어땠느냐에 따른다고 생각한다. 모든 창조물에는 반드시 창작자의 애티튜드가 반영될 수 밖에 없다고 믿기 때문이다. 사람들이 말하는 혼이 담긴 작품이란 말도 그런 맥락일 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;프로그래머를 시작하던 그 시절 난 장인은 아니었다. 그 때 난 지금보다 훨씬 더 유명한 제품을 만들기도 했었고, 훨씬 더 돈을 많이 버는 제품을 만들기도 했었고, 훨씬 더 기술력이 뛰어난 제품을 만들기도 했었다. 하지만 난 장인은 아니었다. 그저 한 명의 회사원이었고, 프리랜서였다. 그랬던 내가 지금은 장인이라고 떳떳하게 말하고 다닌다. 어떻게 그럴 수 있는 것일까? 단지 경력이 좀 됐기 때문일까? 절대 아니다. 그렇게 말할 수 있는 이유는 바로 지금 만드는 제품이 제품이 아닌 작품이 돼 버렸기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://jiniya.net/tt/164&quot;&gt;세상이 좀 더 편평하고 공정해져야 한다&lt;/a&gt;고 생각한다. 하지만 오프라인 세계에서 그런 세상을 만들기 위해서 내가 할 수 있는 일은 솔직히 거의 없다. 거대한 권력을 가진 것고, 큰 힘을 가진 것도, 많은 부를 축적한 것도 아니기 때문이다. 하지만 온라인 게임 세상에서는 다르다. 난 온라인 게임 세계에서 공정성을 해치는 많은 장애물들을 제거할 수 있고, 또 온라인 게임 세계를 경험하는 많은 이들에게 오프라인 세상보다는 공정한 세상을 보여줄 수 있는 힘이 있다. 그래서 난 이 일이 재미있고, 또 더 잘하고 싶다. 좋은 게임보안 제품을 만들고 싶고, 당당하게 그 제품에 내 크레딧을 달고 싶다. 부끄럽지 않은 제품을 만들고 싶다. 그러니 당연히 남들이 신경쓰지 않는 부분도 내가 본다는 생각으로 만들 수 밖에는 없다. 이건 내 꿈이고, 내 작품이기 때문이다. 이게 바로 내가 스스로 장인이라 떳떳하게 말할 수 있는 이유다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;좋아하는 학교 선배가 한 명 있다. 마계촌 온라인을 개발하면서 이제는 너무 &lt;a href=&quot;http://www.bloter.net/archives/99093&quot;&gt;유명해져 버린&lt;/a&gt; 형이다. &lt;a href=&quot;http://www.jiniya.net/wp/archives/5451&quot;&gt;지난 마계촌 글&lt;/a&gt;에도 썼었지만 그 형은 내가 아는 사람들 중에 몇 안되는 진짜 장인이다. 왜냐하면 그 글에도 나타난 것처럼 형은 자신이 만드는 작품을 학교 수업시간에도 들고와서 진지하게 고민했기 때문이다. 장인이 아니라면 절대 그렇게 할 수 없다. 선우 형이 몇 해 전 쓴 글 중에 &lt;a href=&quot;http://megarex.tistory.com/19&quot;&gt;내가 참 좋아하는 글이 있다.&lt;/a&gt; 아래 글은 그 글에서 발췌한 것인데 다시 읽어도 정말 멋있는 문장이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;다시 돌아와서 간단히 말하자면&lt;br&gt;
&lt;br&gt;
회사에서의 자기 업무가 곧 자신의 작품이자 자신의 꿈이라면&lt;br&gt;
&lt;br&gt;
업무시간이라는 것은 아무 의미가 없습니다.&lt;br&gt;
&lt;br&gt;
저의 인생 모든 시간이 곧 제 작품을 만들기 위한 시간이니까요.
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;저의 팀원 모두가 같은 생각이었으면 좋겠습니다.&lt;br&gt;
&lt;br&gt;
게임 개발자도 creator 입니다.
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– 마계촌 온라인 개발자 황선우&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;우리는 태어날 때 모두 장인이었는지도 모른다. 단지 사는 동안 하루 살이에 치여 모두가 장인이었다는 사실을 잊어버린 것이다. 그러니 우리가 장인이 되는 법은 복잡하거나 어렵지 않다. 단지 그 잊어버렸던 꿈을 다시 찾기만 하면 된다. 자신의 꿈을 향해 가는 동안 우리 모두는 저절로 장인이 될 수 밖에는 없기 때문이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 허들 넘기…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/6414</link><guid isPermaLink="false">https://jiniya.net/wp/archives/6414</guid><pubDate>Fri, 27 Apr 2012 23:58:06 GMT</pubDate><content:encoded>&lt;p&gt;사용자들은 언제 게임보안 제품을 느낄까? 해킹툴을 잘 잡아서 게임 내 해킹이 줄었을 때? 아니다. 사실 일반 게이머들은 게임보안 제품이 해킹툴을 잡는다는 사실을 모르는 경우가 대부분이다. 그들이 게임보안 제품을 느끼는 대표적인 순간은 바로 잘되던 게임이 안되기 시작하는 순간이다. 게임보안 제품이 게임 구동을 방해하는 허들이 되는 그 지점인 것이다. 이 순간이 되면 모든 게이머들이 안티치트 솔루션 이름에 대해서 알게된다. 더불어 그 게임이 진짜 인기있는 게임이라면 네이버 실시간 검색어 1위에서 10위까지 휩쓰는 기염을 토하기도 한다. 이 모든 일들과 함께 안티치트 솔루션에 대한 욕과 비방이 범람한다. 한마디로 아찔한 순간이다.&lt;/p&gt;
&lt;p&gt;XIGNCODE라는 제품을 처음 만들 때 사실 별 생각이 없었다. ㅋㅋ~ 후에 제품의 틀을 잡으면서는 크게 두 가지 다짐을 했다. 하나는 아이러니하게도 진짜 해킹툴을 잡는 제대로 된 솔루션을 만들자는 생각이었고, 다른 하나는 절대로 게임의 허들이 되는 제품을 만들지는 말자는 생각이었다. 하지만 시간이 흘렀고, 우리 제품도 게임에 속속 탑재되기 시작했고, 해킹툴과 전쟁도 뻘짓나게 많이 하면서 자연스럽게 허들이 되는 순간도 생기게 됐다. 그렇게 장애물은 되지 말자고 했는데 애물단지가 되는 순간이 발생한 것이다. 그럴때면 나 또한 똑같은 한명의 게이머로서 한없이 죄송함을 느끼곤 한다. 그리곤 또 다짐한다. 정신차리고 똑바로 만들자고 말이다.&lt;/p&gt;
&lt;p&gt;그렇다면 왜 그렇게 모든 게임보안 제품은 하나같이 다 허들이 되는 것일까? 또 그 허들은 왜 생기는 것일까? 피할 순 없는 것일까? 또 반대로 게이머 입장에서는 조금이라도 허들을 피하기 위해서는 어떤 점들에 주의해야 할까? 역설적이게도 게임보안 제품이 허들이 되는 이유는 그들에게 봉착한 허들을 제대로 넘지 못했기 때문이다. 여기서는 게임보안 제품 개발을 하면서 겪게 되는 허들에 대해서 살펴보고 작게나마 앞선 질문들에 대한 해답을 찾아보는 시간을 가져보도록 하자.&lt;/p&gt;
&lt;h3&gt;#0 운영체제 허들&lt;/h3&gt;
&lt;p&gt;일단 게임보안 제품에게는 운영체제 하나가 거대한 산맥으로 다가온다. 왜 그럴까? 게임도 똑같이 다양한 운영체제 위에서 구동되는 프로그램이고 게임보안 프로그램도 그럴 뿐인데 왜 게임보안 제품에게는 운영체제 자체가 허들이 되는 것일까? 그 이유는 게임보안 제품의 특성상 운영체제에서 공개하지 않은 다양한 기능들을 사용하기 때문이다. 왜? 도대체 왜? 많은 이유가 있는데 주된 이유만 들어보자면 하나는 해킹툴이 그런 기능을 사용하기 때문에 탐지하기 위해서 부득이하게 사용하는 경우고, 다른 하나는 해킹툴로부터 자신을 보호하기 위한 목적으로 사용한다. 이렇게 공개되지 않은 부분들을 사용하는 것이 호환성을 떨어뜨리는 대표적인 요인이다. 여러분이 생각하는 그 모든 호환성 이슈는 다 이 하나의 사실에 기인한다고 할 수 있다. 그렇다면 이건 어떻게 해결해야 할까? 테스트만 열심히 한다고 해결될까? 물론 문제가 그렇게 쉽진 않다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_허들_넘기.md_0.png&apos; data-alt=&apos;우리가 생각하는 것 이상으로 게임이 실행되는 운영체제는 게임 종류와 국가에 따라 천차만별이다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/95d9694335b7b2a8f7b90ff151864aea/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 31.578947368421055%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABc0lEQVR42j2RO0/CUBiGuxgH/R+OLv4SNxMnf4OLt8TFwWjUSRkgDiZumjiog8b7BYzEGAEDonJtCy1NLZTWlvJ4KMRvOZfvzfN+7zkS3QC6XcLq7UXpqX2UQhq9YeL7fr9HZ7CG2sBpZLtK5gRVMzGMxr9O6vUDrulUlkG+Dy+Vr0Wy6QsKRSUU931aFI0TPPk81DT1Kz5eVvj81jDNBp1OMADKl/iZYbxHwY6MgPFGLBchkbmjUqjwkc9j264wneI0J2FtS5DaIvPzwuHbJnr1h6pcRlVVApFUIr4AMQFLzRPsCHF6g6WjMvfJFHqtSqlcw21+EZQl7Pok/sEEHI5xmS2xehynqdUolkq4rjuYsHoG0SGICOjuqMjyxN76N6+JHHVdwW45QiYmvB2H3eG+6dM0yQeL6FqSipxHq+u4jhu+oxRie9DnOVDvwqNdb+OImJ7n/X8UxjvczAjYLHgajhmg5Q1a7SZtu41lWWLKX/4AVtqppcO6PdsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;우리가 생각하는 것 이상으로 게임이 실행되는 운영체제는 게임 종류와 국가에 따라 천차만별이다.&apos; title=&apos;&apos; src=&apos;/static/95d9694335b7b2a8f7b90ff151864aea/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/95d9694335b7b2a8f7b90ff151864aea/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_0.png 190w,
/static/95d9694335b7b2a8f7b90ff151864aea/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_0.png 380w,
/static/95d9694335b7b2a8f7b90ff151864aea/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_0.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;우리가 생각하는 것 이상으로 게임이 실행되는 운영체제는 게임 종류와 국가에 따라 천차만별이다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;XIGNCODE는 기본적으로 Windows 2000 SP4, Windows XP SP2, Windows XP SP3, Windows Vista SP1, Windows Vista SP2, Windows 7 RTM, Windows 7 SP1, Windows 8 CP에서 게임 구동 테스트를 거친다. 우와 장난 아니다. 그런데 여기서 놀라면 안된다. 저 모든 운영체제를 한중일영으로 테스트 한다. 보면 알겠지만 서팩별로도 많이 사용되는 것들은 분리해서 테스트 한다. 그 이유가 서팩별로도 많은 차이를 가지기 때문이다. 이런 복잡한 테스트를 몇 시간씩 하고, 일주일 내내하고, 또 하고, 또 하고, 제품 릴리즈를 함에도 문제는 발생한다. 왜 그럴까?&lt;/p&gt;
&lt;p&gt;그 이유는 바로 우리가 기대고 있는 언덕이 그만큼 부실하기 때문이다. 공개되지 않은 부분이라는 그 사소하지만 절대 사소하지 않은 사실 때문이다. 즉, 오전까지는 잘되다가 오후에는 안되도 전혀 이상할 이유가 없는 단서들에 제품이 기반하고 있기 때문이다. 우리가 이 사실에 대해서 어떤 불평을 한다면 운영체제를 만든 MS에서는 이렇게 대답할 것이다. “야, 그건 우리가 그래서 공개안한거야. 니네들 쓰라고 만든건 아니거든.” 이라고 말이다. 어쨌든 그래서 테스트 만으로는 이 허들을 넘기가 쉽지 않다. 우리가 관찰한 100시간 동안은 운영체제가 A라는 방식으로 동작했겠지만 그건 단지 우리가 관찰한 100시간 동안만 그랬기 때문일 수도 있기 때문이다.&lt;/p&gt;
&lt;p&gt;이 허들을 넘기 위해서는 테스트 보다는 운영체제에 대해서 보다 더 정확하게 알 수 있는 방법이 필요하다. 즉, 100시간의 관찰보다는 실제로 그렇게 돼 있는지 안 돼 있는지를 판단할 수 있어야 한다는 말이다. 그래서 운영체제를 직접 리버싱 하는 것이 더 도움이 된다. 맞다. 그런데 리버싱도 한계가 있다. 그래서 이 허들을 넘는 궁극의 도구는 MS 소스 코드 라이선싱 프로그램이다. 바로 그 놈이 답지고 그 놈이 갑이기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_허들_넘기.md_1.png&apos; data-alt=&apos;내가 곧 진리요. 답이고, 갑이다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a58de23b943e20cdd9965207a4b9f240/d9f49/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.73684210526315%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAERUlEQVR42h2Pa0yTBxSGm+yH2Z/NReemiBBRBuJlOoegE5niBJFMiYKRxSnO6cxQbi2gIFOoMK61tJWLoVYugihUQNhADAjaYkWQAN7m5mVMp3yoFIFCy7Mv+/Hm5D3Jec77SiaMpVjvVGHtvizOOia66hjvrMNyuwaL6C29ou+tZeJuDeN9tYx1XmS0vZzRFh3vfstjuPYU7xq0jLWUMdF2Fsl4+wUmOvSMmy4xaqjgXVspZkM55lsXGO6uYrhHL6oac2cF5vYSRq5qGb6kYrAsjYESOW8rs7HUKKBBhaU2DclIaxmjRhFkOM+bazoGmgt5ea2QF61a/rlexLPWUvqbCum/ouNBvQ69sZ4jT/7gRl059xuqeaRLp7dSR1vjVRTZeUiGmkt43XyGF2L8x3olD8WPdysy6L2kpEd/kt5qNddaL6P6+zmHhkaQjY2z3wY/DY5xZcTKxZ5nJDW/5XgXnK+oRPKiSsWj0gx6tHI6Tx+jo/A4Rl0yXUWJGOoL0HTfI+SOwO5hK8esE0RZLARN2tgkgjMf/0vriI1MwwClxTUMFicjeViQTG9+Ih2qOG4oZbRrYriuiOB0QjhByVo2GF7y7Z03/Gy2sMVqw3cSttomCWaS0Fdm9MIoTbf7uKs8yqtiOZI+dQJdOTG0K6Npy46kKlPKD3EJLM9twLP5KV9qGnGWX8DruRlfK2wctbFZBAeO2/A224h/8BpjXQPdBWk81qYi6ciKwaSQYsqNw5D6IwnFOtYOQrB4uOYvmLrtBB8GyHHV9uBuHMTrCXw9IEKHrOw1g0/bEOeyNbQoUuhSn0BiUhzhpghsTA7jonQHOfF78NK341bfz6L6VzjFFjE3y8RHB7Q4pN7Eo3WSLffG2NsPAU0DhOS1clahoTEnk47cX5E0JkVR/8sBauJ3UyYLIj/UE5+QvcxIrGV2lA6nrBu4lv3JJ4drWJzexPaHsEo/gEdaI36bAkmPiOBcloJ6pQJjjlj5qjyCuqM7KY/YjHrXGlICP2dfgCcfLNjE9KAE5uX34ZBuYNqhM8zLuMUKpQmPwH34LXPhe4/5ZMXFUJKWwe+qk5gKFEiK9m8m97tVKLctJzVgIYl+rsi85/CZvSPvb4/FPruOKQHhfLzUj7W7ZPh/5Y6/4xRCFk/j4PqFqGMOUqnIoilPze1CDZIUXzfS/F3/V7KvM7HejkjXzGHrMjves3NnqsMXrHBxYOui6ex0n8melbM5tN6FyHXORHk7kRW6haqUY7SosunOy0RyxGMmSWsdSP5mPsc3OJPg40TkSjvCPGcRvHgWe5bNQCruov3ckPouIM5/CYf9lohNFpG0wY38XRtpkEfTlZ/G0+IMJDL3T4XDq+2FmFV2gnSlvRAtKnK1oxDuNVeQ+bgIUetchDCveUKkt6sgXb9UkO/YKJwKCxXOhocKJQeDherYnUJbukzoVMcL9zVxwn+vmTDbEWt/yAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;내가 곧 진리요. 답이고, 갑이다.&apos; title=&apos;&apos; src=&apos;/static/a58de23b943e20cdd9965207a4b9f240/d9f49/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_1.png&apos; srcset=&apos;/static/a58de23b943e20cdd9965207a4b9f240/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_1.png 190w,
/static/a58de23b943e20cdd9965207a4b9f240/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_1.png 380w,
/static/a58de23b943e20cdd9965207a4b9f240/d9f49/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_1.png 400w&apos; sizes=&apos;(max-width: 400px) 100vw, 400px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;내가 곧 진리요. 답이고, 갑이다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이 허들과 관련해서 사용자가 겪게 되는 또 다른 불편 중에 하나는 다양한 환경에서 게임을 즐기지 못한다는 요소다. 우리 제품도 종종 불만사항으로 올라오는 내용 중에 하나가 와인에서 실행되지 않는다는 것들이다. 이럴때면 늘 우리는 갈등한다. 사실 와인에서 실행되도록 만들어주는 것은 전혀 어려울 게 없다. (&amp;#x3C;== 어려울 수도 있다 ㅋㅋ) 그런데 문제는 와인을 통해서 해킹을 한다면 문제가 복잡해지기 시작한다. 물론 나는 선량한 리눅서가 와인을 통해서 게임을 즐기기 위함이지 절대 해킹을하기 위해서 리눅스를 깔고 와인을 올려서 게임을 구동하리라곤 생각하지 않는다. 그래도 만에 하나의 경우 그래 버린다면 문제가 될 수도 있다는 것이다. 어쨌든 우리는 이 옵션에 대해서 심각하게 고민하고 있다. 벤더 정책에 따라서 옵션으로 와인 호환성을 제공할까도 고려중이다.&lt;/p&gt;
&lt;h3&gt;#1 시스템 허들&lt;/h3&gt;
&lt;p&gt;다음으로 우리가 넘어야 할 허들은 게임 시스템이다. 이 또한 정말 다양한 시스템들이 있다. 이제는 우리가 시중에서 구하기도 힘든 시스템으로 게임을 하는 유저들이 적지 않다. 특히 오래된 게임들은 더 그렇다. 이 부분은 사실 테스트도 어렵다. 우리는 다양한 환경이라고 테스트 시스템 수십대를 구비해 놓지만 정작 유저들이 사용하는 시스템에 비한다면 그 수십대는 샘플 수량조차 되지 못한다. 그만큼 다양한 환경이 존재한다. 그리고 그 다양한 시스템을 게이머들은 우리가 상상도 못한 방식으로 변형시켜 사용한다.&lt;/p&gt;
&lt;p&gt;여튼 이런 다양한 시스템이 문제가 되는 주된 요소들은 시스템 버그에 대한 패치를 사용자가 하지 않는다는 점이다. 대표적인 예를 들어보자면 AMD CPU의 Cool’n Quiet 기능 버그가 있다. 해당 기능을 사용하면 특정 운영체제에서는 시간을 측정하는 함수가 비정상적으로 동작하는 문제가 있다. 이건 패치를 해야 하는데 사용자들이 그러한 패치를 알리가 만무하고 또 그 패치를 하지 않더라도 일반 프로그램 사용에는 문제가 없기 때문에 하지 않는 경우가 많다.&lt;/p&gt;
&lt;p&gt;하지만 우리에게는 그러한 것들이 굉장히 크리티컬하게 다가온다. 게이머가 해킹툴을 설치해서 시간이 이상한지 아니면 패치를 안해서 이상한지를 구분해야 하기 때문이다. 그래서 온갖 꼼수들이 동원된다. 당연히 그 꼼수들로 인해서 프로그램의 호환성은 더 떨어지고, 테스트는 더 힘들어지고, 제품은 더 쉽게 부서진다.&lt;/p&gt;
&lt;h3&gt;#2 오진 허들&lt;/h3&gt;
&lt;p&gt;여기부터는 이제 우리가 우리 발목을 잡기 시작하는 허들이다. 해킹툴 차단 방식은 크게 나누자면 패턴 방식과 로직 방식으로 나눌 수 있다. 패턴 방식은 사람 지문으로 누군가를 구분하는 것처럼 해킹툴의 특정 시그니처로 해당 해킹툴을 차단하는 방식을 말한다. 지문이 데이터베이스에 없다면 인식이 안되는 것처럼 이 경우도 수집이 안 된 해킹툴에 대해서는 차단을 하지 못한다는 문제가 있다. 그래서 도입된 개념이 로직 방식이다. 이건 이렇게 행동하는 사람은 A 밖에는 없다고 우리가 추론하는 것과 똑같은 원리로 해킹툴을 진단한다. 즉, 어떤 프로그램이 a, b, c라는 동작을 하면 해킹툴로 간주하는 것이다. 당연히 우리가 인식하는 세계처럼 여기에는 맹점이 생길 수 밖에 없다. 그 사람이 아닌데, 내지는 해킹툴이 아닌데도 a, b, c라고 동작을 하는 경우가 있기 때문이다. 이게 우리 발목을 잡는다. 물론 대놓고 난 정상 프로그램이라고 말하면 문제는 한결 가벼워 지는데 그 정상 프로그램이 각종 꼼수 꼼수에 꼼수를 사용해서 마치 해킹툴처럼 판단하기 어렵게 만든 경우에는 허용 처리가 안드로메다로 가버린다.&lt;/p&gt;
&lt;p&gt;그럼 어떤 프로그램이 주로 오진 케이스에 말려들까? 가장 대표적인 프로그램들은 아이러니하게도 게임 유틸리티다. 게임 동영상 촬영 도구라던지, 게임 내에서 채팅 기능을 구현한 메신저 프로그램이 대표적이다. 이들 프로그램은 게임과 동시에 동작한다는 것이 특징인 것들이지만 내부 구현 방식은 해킹툴의 그것과 상당히 유사하기 때문이다. 또 이 프로그램들이 진화하면서 이 프로그램들 나름대로 탐지를 회피하기 위해서 각종 테크닉을 사용하기 때문에 요즘은 허용 처리도 참 쉽지 않은 경우가 많다.&lt;/p&gt;
&lt;p&gt;그 다음 대표적인 유틸리티 들로는 가상화 유틸리티들 SandBox, Vmware, Virtual PC부터 네트워크 프록시 도구들이 있다. 이런 프로그램들은 해킹툴과 동작 방식이 유사히진 않지만 벤더 요청으로 차단하는 경우가 있다. 그렇게 차단된 것임에도 사용자 입장에서는 정상 프로그램을 오진한다고 생각하기도 한다.&lt;/p&gt;
&lt;p&gt;벤더 정책으로 누명을 쓰는 또 하나의 대표적인 프로그램으로는 또 JoyToKey가 있다. 이름에서 볼 수 있듯이 조이스틱을 컴퓨터에서 매핑해서 사용할 수 있게 해주고, 또는 매크로 기능을 사용할 수 있게 해주는 프로그램이다. 그런데 이게 왜 문제인고 하면 게임 벤더에 따라서 어떤 쪽은 이 프로그램을 허용처리하고 어떤 곳은 차단 처리를 하기 때문이다. 유저들의 반응은 딱 갈리게 된다. 저걸 해킹툴로 많이 사용하는 게임인데 벤더에서 허용을 해주면 어떤 반응이냐면 우와 XIGNCODE는 쓰레기다. JoyToKey도 차단이 안된다. 이런 반응들이 올라온다. 사실 우리가 못 막아서 안 막는 경우는 아님에도 말이다. 또 반대로 이 프로그램을 별로 해킹툴로 사용하지도 않는 게임인데 벤더 정책상 차단하게 되면 와 이런 정상 프로그램을 왜 차단하냐. 미친거 아니냐. 라는 반응들이 올라온다. 마찬가지로 우리가 차단하고 싶어서 차단한건 아님에도 말이다. 즉, 가끔은 중간에 끼여서 욕을 먹는 경우에는 조금 억울한 생각이 들 때도 있다.&lt;/p&gt;
&lt;h3&gt;#3 충돌 허들&lt;/h3&gt;
&lt;p&gt;충돌은 정말 장난아닌 문제다. 게임보안 제품은 그 모든 것들과 충돌을 일으키지만 특히 안티바이러스 이슈가 많다. 가장 최근에 겪었던 충돌 문제를 한 번 살펴보자. 이 문제는 안티바이러스의 코드 에뮬레이션 기능과의 충돌이었다. 처음 보고가 들어온 제품은 AVAST였다. 이런 문제의 99.8971234%는 서로 같은 포인트를 후킹하거나 후킹하려고 하는 것이 문제이기 때문에 그 체크를 먼저 했다. 어라? 근데 깨끗하다. 아무 문제가 없어 보였다. 근데 게임이 크래시가 난다. 그래서 AVAST의 이 옵션, 저 옵션 조정하면서 왜 크래시가 나는지를 관찰했다. 그랬더니 아니나 다를까 AVAST의 코드 에뮬레이션 기능을 켜면 크래시가 발생하는 것이었다. 게임이!!! 도대체 왜? 아마 우리의 코드가 그 코드 에뮬레이터가 이해하기는 힘들었는지도 모르겠다. 여튼 QA팀에게 AVAST에 충돌 보고를 하라고 했다. 내가 보기에는 AVAST에서 봐야 할 문제였기 때문이었다. 그러고 끝일까? 당연히 아니다. 게이머한테 이건 AVAST 버그니 코드 에뮬레이션 끄고 게임하세요. 이렇게 말할수는 없기 때문이다. 그래서 우리는 그 코드를 AVAST가 켜진 경우에는 AVAST가 딱 이해할만한 수준으로 낮춰서 동작시키도록 했다.&lt;/p&gt;
&lt;p&gt;이 문제가 억울한 이유는 사실 이런 경우는 우리쪽 버그가 아니다. AVAST 코드 에뮬레이터 버그지 않겠는가? 결국 AVAST에서 해당 기능을 고쳤다는 보고를 해왔다. 하지만 게임사나 유저들은 우리 잘못으로 오인하는 경우가 많다. 안타까운 현실이다. AVAST만 거론해서 그렇는데 동일한 이슈를 겪은 다른 3종의 백신이 더 있었다. MS SE, ESET Smart Security, McAfee였다. 물론 다른 벤더엔 귀찮아서 오류 보고도 하지 않았다.&lt;/p&gt;
&lt;p&gt;그렇다면 우리는 왜 AVAST 코드 에뮬레이터도 이해하지 못하는 그런 코드를 써야 했을까? 첨부터 그냥 다 평이한 걸 사용했으면 문제가 없지 않을까라고 생각할 수도 있겠다. 근데 이게 딜레마다. 우리 제품은 해커로부터 우리 코드를 보호해야 한다. 또 해커가 우리 코드를 이해하는 것을 막아야 한다. 그러니 당연히 복잡하게 꼬아 놓을 수 밖에는 없는 것이다. 그게 경쟁력이니 포기할 수가 없는 것이다. 충돌을 감수하더라도 그 코드를 계속 써야만 하는 이유다.&lt;/p&gt;
&lt;p&gt;그리고 이런 충돌 이슈는 충돌을 넘어서 좀 더 복잡한 문제들을 야기 시킨다. 충돌때문에 작성한 특수 코드가 우리 발목을 잡는 경우가 생기는 것이다. 해커가 만약 백신 때문에 작성한 특수한 코드에 대한 사실을 눈치채면 그걸 이용해 먹을 수 있다는 말이다. 그런 방법을 공유한다고 사용자들이 백신을 설치할까라고 생각할 수 있다. 근데 뻥안치고 방법만 있다면 게임핵을 사용하고 싶은 모든 사용자는 어디서 구하든 다 구해서 그 백신을 설치한다. 그 정도로 게임핵의 유혹은 강하기 때문이다. 실제로 예전에 중국에서 KAV를 이용해서 해킹 시도를 하는 사례가 있었다. 그래서 귀찮더라도 보고하고 무조건 백신을 고쳐야 한다.&lt;/p&gt;
&lt;p&gt;여기까지 생각하면 이제 게임보안 1-2년 정도 해본 사람이라고 할 수 있겠다. 좀 더 해보면 알겠지만 저거 고쳤다고 원래 코드를 쓸 순 없다. 세상이 그렇게 순수하진 않은 탓이다. 백신 업체가 고쳤다고 그걸 업데이트하는 유저도 있지만 하지 않는 유저도 부지기수기 때문이다. 우리가 백신 업체가 고쳤다는 소리만 듣고 순진하게 원래 코드로 원복시켰다가는 다시 똑같은 문제가 생긴다는 소리만 듣는다. 모든 사용자는 업데이트를 하지 않는다고 생각하는게 속편하다. 그래서 그 특수 코드를 이용하는 놈들이 나타나면 다시 그 특수 코드에 대한 특수 코드를 만들어야 한다. 이렇게 소스 코드는 걸레가 되고 로직은 38.7차원 어딘가에 위치하게 된다.&lt;/p&gt;
&lt;h3&gt;#4 버그 허들&lt;/h3&gt;
&lt;p&gt;이거야말로 우리가 피해야 할 허들이다. 그런데 가장 많으면서 제일 피하기 힘든 허들이다. 누구 말처럼 이건 명백히 프로그래머의 실수다. 그런데 버그라는 말을 만들어서 책임 회피를 하는 것처럼 보일 수 있다. 어쨌든 맞다. 명백한 우리 실수, 잘못이다. 인정한다.&lt;/p&gt;
&lt;p&gt;그럼에도 변명을 좀 대보자면 이렇다. 우선 게임보안 제품은 생각보다 빌드가 굉장히 많이 있다. 왜냐하면 해킹툴이 자주 나오기 때문에 그 취약점도 고쳐야 하고 새로운 방식에 대응도 해야 하기 때문이다. 심한 시기에는 풀빌드가 일주일에 두세 번씩 되기도 한다. 이런 경우에는 머 QA팀은 초죽음이 된다고 보면 된다. 또한 이러한 풀빌드가 전혀 계획되지 않은 상황에서 발생하기도 한다. 왜? 해킹툴을 막아야 하기 때문이다. 자잘한 빌드는 말도 못 할 정도로 많다. 하루 밤에 24번 모듈을 빌드하고 업데이트 한 적도 있었다. 당연히 그 해킹툴 제작자는 그 다음주에 학교로 돌아갔다. 그래서 때로는 이런 어처구니 없는 실수들도 자주 발생한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_허들_넘기.md_2.png&apos; data-alt=&apos;이렇게 아무 문제도 없어 보이는 배열 속에…&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4219a15013e725feb5aa16d0f9c7b004/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 65.78947368421053%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAByElEQVR42m2S627jIBCF8yrdxkls4ytg7mAMvidV3/9pdtxspd1spWEEP47mO4c5pXVLlaFSN0xUlFWkqzv+vBSYFC2pCCsxuRUoQUWSlxdUJnlxTrNft+z0dr314zSu+/rxOe+PuO7L42OY12l/hHmxIcT1PsyT0KKmNK+btGquZZXkX2I4zDgVIu8HNUTuPO99Zx01llmHJS/wIbjk6P2WvV3T7/oWI0IbZVooY2ul4VJy8exQFROoxReUv3+h/l2HuOWCaSudVzBTGeUGKjQ3jkrVSSWt50aXLVjNfxBDVEAunNdD6LSBS6cd5gILqfqBG4uaIsn+oL6KmbE2jGHZbJzidvfzAoH5adZ+cHHSvqeSFUCev5IfYiB04ww5+3EO6z5u935cph36ZEMM62a8xZymVX3J/xVDhkRIMAxjZQ/kESiAFqrTGrIwx9NjRrKqSrL/Jle0o0qD7aNrCwVr0zIBto/9UQaCaBlHTfk6GY6wzk8LYMd1A+cAbIYI8GBb9f3hf16kEaguz9kPXyXBtvIBsIXr5ZG21T50SoMj7SPTCtUIVvIl8NM5y0tCiVCw3lBEalDCz0MnUgEtFgrz53oXL5N/A0mnoUZtWpPFAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;이렇게 아무 문제도 없어 보이는 배열 속에…&apos; title=&apos;&apos; src=&apos;/static/4219a15013e725feb5aa16d0f9c7b004/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_2.png&apos; srcset=&apos;/static/4219a15013e725feb5aa16d0f9c7b004/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_2.png 190w,
/static/4219a15013e725feb5aa16d0f9c7b004/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_2.png 380w,
/static/4219a15013e725feb5aa16d0f9c7b004/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_2.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;이렇게 아무 문제도 없어 보이는 배열 속에…&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_허들_넘기.md_3.png&apos; data-alt=&apos;NULL이 하나 빠진 이런 말도 안 되는 버그가 숨어있는 상황. 때로는 깔맞춤이 필요한 이유.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2a2208ca8aaa47d90a3b186141782656/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 58.42105263157894%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB8ElEQVR42lWSWZbaMBBFWUm6A3jUZM22bHkETAMh6aRP9r+UPPOXHx1JVa/q1pN2pmlVHcpKYi2EpMoo3zBtE8IyxitX4xJ7rFybyvqcV8eSZpQcS7IzTeiXM0o8/3zpOgyny3p/4ngoCTdufTx106aU1TFOl/V8e6D0oaDSkJzRHdXGxIFZ1y4nZr3pIrdun5fvaV5KLVElJzgK520cAHLIy+9ZQSqWELpDhqgDNS4sZ269DJ2LAzghzivZTEvBK4i586qNth9BsYkl38RMG1U3TJnxvNZxcG3s5iVj4i3JidLCOEDui1L5GtH+dOHaoi6TJCXkJfYBK6YV1tf9GMYpJRwZMM+GDvZALL1v+rGbllJIdGaSbmKUxK309f3zN6qOl+v91yep1Ldjilo/v/7CMGC/DLs+thwDKGlYRukOlsJb4J0+7lTqMM7z+oEjBETq4cWJvW7CFrreXm4TrsgmJlKhA1W6m+aUcttG1/UYL+cqDrQfyFtSIFsYa9vOI9QPGKcUJAG2sM6GCP3l/gPhMMwbggJbpry5Pe/S1ehs27abTsv1hvz3tBCabp3/E4euGSZg4z9BTKWd1xseYp8XNoR22iYCKbwU6iXGx0QfZAMYm82C0OVcwFI8GC7LSqEz5sLfRKgQFUIFI0lJ/gFJQ5Hdi8sfUwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;NULL이 하나 빠진 이런 말도 안 되는 버그가 숨어있는 상황. 때로는 깔맞춤이 필요한 이유.&apos; title=&apos;&apos; src=&apos;/static/2a2208ca8aaa47d90a3b186141782656/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_3.png&apos; srcset=&apos;/static/2a2208ca8aaa47d90a3b186141782656/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_3.png 190w,
/static/2a2208ca8aaa47d90a3b186141782656/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_3.png 380w,
/static/2a2208ca8aaa47d90a3b186141782656/dface/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_3.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;NULL이 하나 빠진 이런 말도 안 되는 버그가 숨어있는 상황. 때로는 깔맞춤이 필요한 이유.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;물론 당연하다. 똑똑하다면, 진짜 실력이 있다면 빨리 만들면서도 잘 만들어야 하고, 또 문제가 없어야 한다. 우리가 항상 이런 버그 앞에서 한없이 초라해지고 숙연해지는 이유이기도 하다. 그럼 우린 어떻게 해야 하는가? 프랙티스, 프랙티스, 프랙티스… practice makes perfect를 외치며 항상 연습하는 수 밖에는 없다. 빨리 고치고, 급하게 고치고, 막 바꾸면서도 실수하지 않도록 말이다. 라이브는 말 그대로 전쟁터다.&lt;/p&gt;
&lt;h3&gt;#5 필요악???&lt;/h3&gt;
&lt;p&gt;문제가 한두 가지가 아니다. 한 게임보안 프로그램은 국내 대형 MMORPG에 탑재됐다가 북미에서는 유저들 원성으로 제거되는 굴욕을 겪기도 했었다. 사람들은 늘 말한다. 100% 막지도 못하고, 그렇다고 문제가 0%인 것도 아닌데 왜 필요한가라고 말이다.&lt;/p&gt;
&lt;p&gt;하지만 정작 실제 내용을 살펴보면 그런 이야기를 하기는 힘들다. 왜냐하면 게임보안 솔루션을 사용해서 유통되는 유료핵툴 한두 개만 차단하더라도 연간 구독료 값어치는 하고도 남기 때문이다. 특히 MMORPG같이 컨텐츠가 생명인 게임은 더 그렇다. 아래는 한 게임에 오토 유료핵이 나온 경우의 상황을 보여주고 있다. 여러분이 보는 그대로 전체 게이머의 60%가 그 핵툴을 사용하는 시간대도 있다. 이 정도로 말도 안 되게 온라인 게임의 핵은 심하고, 또 게임보안 제품은 여러분이 생각하는 것보다 훨씬 더 쓸모있다. 저 오토들이 컨텐츠 소모에 들어갔다면 어땠을까? 단순히 유저들이 느끼는 불균형의 문제가 아니다. 비싼 돈주고 개발한 컨텐츠가 유저가 아닌 기계에 의해서 순식간에 소모되는 말도 안 되는 일이 벌어질 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_허들_넘기.md_4.png&apos; data-alt=&apos;가로축은 시간이고, 세로축은 해킹툴 유저 비율(%)이다. 유료핵의 파괴력은 생각보다 훨씬 심하다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 467px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e1c1196cae62eb6480b029ea4d1cfa6e/128f7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABpklEQVR42kVPy27TQBTNX7JBQlBSKvWxJpsKVQRaqMSOH2DBgiWrSiwRTRM/EI9YSuNHCiqx41dsjx9zZzwcGwFXozN3zpxz58yAMZamafu3ZCukFF0jZX/EJrlIQXZ9T/6rQZ5ltm0LAY8Ugjo3EVoiUCDbhtLv0fGGfVKt4lRDI/rqzGVZup5H0EIqREXrmhLoegazlJe+mazvLJJXUsLG4flvLorCcV3qXms5FV/D0ZdwhBF4FyOS+vNsfd/cHJjBkRWPV9u3UTWFkpARZvzZcRxODaQ323eavzNd37st3iupENiKn2n+0AgOdH9PDx5d/bo7j56ILjoiyM7seR7ixZWp+btmcAi0ojGnch6NZ/4DOI1gX/f3cWX4iHDImp8YjfgDVlTW8nIen5jhnr55aIS7xmZohEMreQo0cexw+Af7ZudbPLKz1371YaCUWvy4mCyPNed85pzp3our5XNjdX55faK7L2fOKZbmnk2ux3qP0Ezt04+Lx6vwojPnOSPeMlZjcXw0LaRQ27Tgjci2LM/LuqYoSkmoMEyamvKM5VnVSvUbT9zY7j/2qEsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;가로축은 시간이고, 세로축은 해킹툴 유저 비율(%)이다. 유료핵의 파괴력은 생각보다 훨씬 심하다.&apos; title=&apos;&apos; src=&apos;/static/e1c1196cae62eb6480b029ea4d1cfa6e/128f7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_4.png&apos; srcset=&apos;/static/e1c1196cae62eb6480b029ea4d1cfa6e/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_4.png 190w,
/static/e1c1196cae62eb6480b029ea4d1cfa6e/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_4.png 380w,
/static/e1c1196cae62eb6480b029ea4d1cfa6e/128f7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_4.png 467w&apos; sizes=&apos;(max-width: 467px) 100vw, 467px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;가로축은 시간이고, 세로축은 해킹툴 유저 비율(%)이다. 유료핵의 파괴력은 생각보다 훨씬 심하다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;해킹툴로 서비스되는 게임을 내려본 게임사는 게임보안 솔루션의 필요성에 대해서 절절하게 실감한다. 몇 백억이 투입된 게임도 해킹으로 난장돼서 서비스가 불가능할 수도 있기 때문이다. 여러분이 생각하는 것 이상으로 반드시 필요하고, 또 좋은 솔루션이 필요하다. 그래야 문제는 낮추고, 탐지율은 높아지기 때문이다.&lt;/p&gt;
&lt;h3&gt;#6 허들을 넘어서&lt;/h3&gt;
&lt;p&gt;참 문제도 많고 탈도 많다. 프로그래머는 어떨까? 이런 수많은 허들을 마주하면 게임보안 프로그래머는 위축될 수 밖에 없다. 공격적인 탐지 방식보다는 느슨한 탐지 방식을 사용할 수 밖에 없다. 좀 더 복잡한 숨김 방식보다는 노멀한 방식을 사용할 수 밖에 없다. 자신감이 없어지기 때문이다. 하지만 이런 것들에 위축돼서 쪼는 순간 게임보안 프로그래머로써의 생명은 끝이고, 그 제품 생명도 끝이다. 왜냐하면 그런 자신감이 없어지는 순간 제품과 코드의 경쟁력은 순식간에 사라지기 때문이다. 진짜 프로라면 이 모든 허들을 웃으면서 사뿐히 뛰어넘으면서도 위험한 방법을 과감하게 선택하는 강단이 필요하다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;게이머에게 유쾌한 느낌을 주는 게임보안 솔루션이고 싶다. 물론 쉽진 않다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;적어도 XIGNCODE를 사용하는 게임에게 짐이고 싶진 않다. 또 적어도 XIGNCODE가 탑재된 게임을 하는 게이머들에겐 공정하다는 느낌을 주고 싶다. XIGNCODE 팀은 매 순간 그 시소의 양 극단에서 갈등하고 고민한다. 지금까지 우리는 항상 가장 위험한 방법에 과감하게 도전했고, 그걸 제일 안전하게 구현했다. 또 실수를 최소화하기 위해서 매일 연습했다. 그것만이 우리 제품을 사용하는 모든 이들에게 신뢰를 줄 수 있는 방법이고, 또 우리가 이 수많은 허들을 뛰어넘은 방법이기 때문이다.&lt;/p&gt;
&lt;p&gt;새로운 기능이 잔뜩 준비됐다. QA팀은 긴장한다. 그 쏘 쿨한 기능들은 늘 그랬듯이 허들을 하나씩 넘을 것이고, 그걸 다 넘으면 게임에 탑재돼서 새로운 핵들에 대한 대응력을 강화해 나갈 것이다. 이렇게 우리는 매일 조금씩 전진한다. 제품도, 팀도, 회사도 말이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_허들_넘기.md_5.png&apos; data-alt=&apos;가장 공격적인 방법을 선택하되 가장 안전하게 구현해야 한다. 왜? 우리는 프로니까.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/dc41bc1baab2d05dd6d4c60e540054d6/984b6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_5.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 5.7894736842105265%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAO0lEQVR42h3GOxYAEAwFUfvfFhryEnJ0QsU+fO6ZYpxqBaiIUCZ8zAx6X1OWEOD9jWM01dna6N2+tfYBvz0w2mII1KIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;가장 공격적인 방법을 선택하되 가장 안전하게 구현해야 한다. 왜? 우리는 프로니까.&apos; title=&apos;&apos; src=&apos;/static/dc41bc1baab2d05dd6d4c60e540054d6/984b6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_5.png&apos; srcset=&apos;/static/dc41bc1baab2d05dd6d4c60e540054d6/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_5.png 190w,
/static/dc41bc1baab2d05dd6d4c60e540054d6/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_5.png 380w,
/static/dc41bc1baab2d05dd6d4c60e540054d6/984b6/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%ED%97%88%EB%93%A4_%EB%84%98%EA%B8%B0.md_5.png 630w&apos; sizes=&apos;(max-width: 630px) 100vw, 630px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;가장 공격적인 방법을 선택하되 가장 안전하게 구현해야 한다. 왜? 우리는 프로니까.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 커플링에 관한 오해들…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5823</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5823</guid><pubDate>Tue, 24 Apr 2012 23:58:05 GMT</pubDate><content:encoded>&lt;p&gt;게임사 미팅을 해보면 흔하게 겪는 일 중에 하나가 커플링에 관한 오해들입니다.&lt;/p&gt;
&lt;p&gt;반지는 아니구요. ㅋㅋ 게임과의 결합도가 높은 보안 코드에 대한 이야깁니다.&lt;/p&gt;
&lt;p&gt;소프트웨어 공학에서는 모듈간의 의존도 내지는 결합도를 나타내는 척도로 커플링이란 단어를 쓰거든요. 결합도가 낮으면 느슨한 결합이라고 하고 결합도가 높으면 강한 결합이라고 한답니다. 어떤게 좋을까요? 당연히 소프트웨어 공학에서는 커플링이 낮은 수준이 닥치고 갑입니다. 결합도가 높다는 건 덜 모듈화 됐고, 고치기 쉽지 않으며, 수정할 때 오류가 발생하기 쉽고, 유지보수 하기가 까다롭다는 그 모든 것을 의미합니다. 그래서 커플링을 피해야 할 그것으로 간주하죠.&lt;/p&gt;
&lt;p&gt;하지만 요사이 많은 부분에서 게임보안 제품과 게임은 커플링이 높아지는 것이 필연적일 수 밖에 없다는 주장이 제기되는 것 같아서 몇 가지 사례별로 생각을 정리해 보았습니다. 자 그럼 과연 커플링이 높아야 해킹툴을 잘 잡는다는 말이 진실인지 아닌지 한 번 살펴볼까요? ㅎㅎ~&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;언제부턴가 게임보안 업체들 사이에서 서버에 게임보안 코드를 탑재하는 것이 일반화 됐습니다. 저희가 XIGNCODE라는 제품을 개발하던 초기만 해도 서버 쪽에 코드를 탑재하는 것을 두고 게임 서버 개발자들 사이에서 반감이 굉장히 많았습니다. 그랬던 것이 요즘은 대부분 다 기본적으로 코드를 탑재해야 된다고 생각하시니 감사할 따름입니다. 격세지감도 좀 느끼고 그래요. 여튼 이러한 서버 코드 탑재와 함께 따라온 잘못된 관습(?!) 중에 하나가 클라이언트가 빌드될 때마다 서버에 클라이언트 해시 데이터를 업로드하는 것입니다. 보안 코드에서는 서버 쪽과 클라이언트를 비교해서 다른 경우에 끊겠다는 것을 목표로 개발된 기능인 것 같습니다. 매우 강한 결합 중에 하나죠.&lt;/p&gt;
&lt;p&gt;이 경우에 실수가 발생할 소지는 굉장히 다분합니다. 관리자가 서버 쪽에 해시 데이터를 업로드 하는 것을 빼먹거나, 서버에 올린 해시 데이터와 다른 클라이언트가 패치 된다거나 하는 등의 실수 개입 요지가 많습니다. 근데 뭐 실수는 안한다고 차치하더라도 이 방법이 그다지 좋지 않은 이유는 대부분의 게임에서는 이런 조치가 전혀 필요하지 않기 때문입니다. 도둑이 모두 창문으로 넘나드는데 창문은 지키지 않고 정문을 유지보수 한다는 느낌일까요? 이런 이야기를 하면 꼭 그럼 정문은 안지켜도 되는거냐? 라고 물으시는 분들이 계신데 현실 세계에서 리소스는 항상 제한적입니다. 따라서 그 정문 지키는 리소스로 도둑이 드나드는 다른 곳을 지키는 것이 백배 더 현명하다는 이야기입니다.&lt;/p&gt;
&lt;p&gt;그렇다면 게임 서버에 탑재되는 코드에서 해야 하는 일은 무엇일까요? 바로 실행 보장입니다. 게임보안 제품은 외부 라이브러리 형태로 제공되기 때문에 인터페이스가 노출되면 손쉽게 바이패스될 수 있습니다. 이런 경우를 검증하기 위함입니다. 즉, 모든 것들이 다 제거되고 우회되고 변경되더라도 단 하나 이거는 그래도 실행된다고 보장할 것이 필요하다는 것이죠. 그게 바로 서버에 적용된 코드가 해야 하는 일입니다. 실행 보장만 되면 변경된 지점을 찾아내는 것은 언제든지 할 수 있거든요. 하지만 실행 보장이 되지 않으면 백날 변경 지점을 찾는 코드를 넣어봐야 효과도 없습니다. 변경 지점을 찾는 그 코드가 변경될꺼거든요.&lt;/p&gt;
&lt;p&gt;그리고 뭔가를 변경한다는 자체가 굉장히 오래된 발상입니다. 요즘 트렌드는 노모디피케이션입니다. 즉 아무것도 바꾸지 않고 바꾼 것과 동일한 효과를 내는 방법들이라는 것이죠. 왜냐면 해커들도 이제는 다들 알거든요. 뭔가를 바꿔서는 너무 쉽게 탐지된다는 사실을요.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;오토, 매크로 프로그램과 특정 기술을 무한대로 사용하게 하는 핵들은 게임 내 특정 함수를 불법적으로 호출하는 기능을 통해서 많이 구현됩니다. 예를 들어서 레이싱 게임이라면 부스터 가속을 시키는 함수를 들 수 있습니다. 외부 해킹툴은 그런 함수를 불법적으로 계속 호출합니다. 이렇게 만들어진 것이 무한 부스터 핵입니다. 이런 기법이 게임 개발자들 사이에도 많이 퍼져서 요즘 흔하게 나오는 질문 중에 하나가 보안 프로그램이 특정 함수를 보호할 수 있는 기능을 제공하는가 물어보십니다. 이 기능이 제공되면 게임 개발자가 생각하기에 위험하다고 생각하는 함수 주소를 전달해서 불법 호출을 막겠다는 생각인거죠.&lt;/p&gt;
&lt;p&gt;과연 효과적인 전략일까요? 솔직히 무용지물입니다. 게임 내 랙만 증가시킨다고 보시면 됩니다.&lt;/p&gt;
&lt;p&gt;일단 기본적으로 반환 주소 체크 기법은 return address morphing이란 테크닉에 의해서 너무 쉽게 무력화됩니다. 그런 기법을 방어하기 위해서는 코드를 트레이싱해서 추적해야 하는데 해당 게임 함수 런타임에 이런 체크를 깊이 하게 되면 부하가 증가됩니다. 따라서 일정 범위 밖에 체크를 못하죠. 즉 우리가 N Depth를 추척하는데 상대가 N+1 Depth를 사용하면 그냥 우회된다는 겁니다. 참고로 이런 것들을 인식하고 N Depth를 검사하도록 넣은 보안제품도 잘 없답니다. 안타까운 현실이죠.&lt;/p&gt;
&lt;p&gt;근데 더 안타까운 사실은 이러한 체크 기법이 후킹이란 방식에 의존하는데 제작자 입장에서는 해당 후킹 포인트를 지나서 함수를 호출하는 것 또한 너무 쉽다는 겁니다. 물론 이것도 방어하기 위해서 동적 코드 분석을 한 다음에 애매한 위치에 알박기를 할 수도 있지만 소프트웨어의 견고성만 떨어질 뿐 크게 효과적이진 못합니다.&lt;/p&gt;
&lt;p&gt;진짜 최고로 안습한 사실은 해당 함수 주소를 차단하면 해커는 다른 함수를 찾아낸다는 겁니다. 100% 말이죠. 그래서 효과적이지 않습니다. 여러분이 해커와 같은 속도 내지는 해커보다 빠른 속도로 해커가 다시 찾아낸 그 함수를 찾아낸다 해도 효과는 없습니다. 그냥 하나의 경쟁 루프를 만들어낼 뿐이거든요. 상호 패치 공방 밖에는 벌어질 수 없는 방식이란 거죠.&lt;/p&gt;
&lt;p&gt;저희도 중국 유료 해킹툴에 이 기법을 몇 차례 적용했었는데 별 재미를 못 봤습니다. 왜 재미를 못봤냐구요? 우리는 일주일이 걸려 겨우 그 함수를 찾았습니다. 그래서 이제 막으면 원천 차단이 되겠다 생각했죠. 근데 넣고 하루만에 다른 함수를 호출하더군요. 다시 일주일을 분석하느니 그냥 그런 방법은 개나 주는 편이 낫겠다고 생각했습니다. 저희는 다른 방법을 선택했고 그 해킹툴은 3월 2일부로 영원한 수면에 들어가셨습니다. ㅋㅋ~ 이 사례를 통해서 전 교과서에 나오는 방법들이 생각보다 훨씬 더 실전에서 쓸모가 없다는 저의 생각을 좀 더 굳히게 됐습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_커플링에_관한_오해들.md_0.png&apos; data-alt=&apos;XINGCODE로 인하여 3월 2일부로 영면하신 그 비운의 해킹툴…&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 507px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1ca6771485881f6e9380392d33c89636/f03ec/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 36.31578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABDUlEQVR42m2Qy07DMBBF/cP8BOInYIXEmg17BAvEAqmiKqFKW1LivOzYjh+x3UTYaTBFgrZwNBpdjebOjAZcPVbn9/npzfphycdxdH4IbHcMw6/+F3BxC8+u45PL6O6VBfOwHY86QvEnH5uFMklBrTXdRhtjGWNqh9ZaStW2bRDW2lDp+z4c4vcAOVWTFRKtkbwxWpMaKyk456FbSiEDQnQbizEO5vEQwCiFMF1CvCoI5jJKcU54gcoFLOYZwY1AQq4rYo2WX+MOAMZoShAijGNqUM1gqUqkYMaT9waWuiZtXinCwtruD8C7jtO0KKuPLPeLxD+/uGnkotg9Tf1s7uM3N5kNuN5+PyzkvfgErJWJn6T98KIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;XINGCODE로 인하여 3월 2일부로 영면하신 그 비운의 해킹툴…&apos; title=&apos;&apos; src=&apos;/static/1ca6771485881f6e9380392d33c89636/f03ec/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_0.png&apos; srcset=&apos;/static/1ca6771485881f6e9380392d33c89636/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_0.png 190w,
/static/1ca6771485881f6e9380392d33c89636/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_0.png 380w,
/static/1ca6771485881f6e9380392d33c89636/f03ec/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_0.png 507w&apos; sizes=&apos;(max-width: 507px) 100vw, 507px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;XINGCODE로 인하여 3월 2일부로 영면하신 그 비운의 해킹툴…&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;저희가 커플링 높은 인터페이스를 게임 개발자들에게 권하지 않는 이유는 이런 겁니다. 첫째는 게임 개발자가 스터디를 해야하는 보안 제품을 만들어서는 안 된다고 생각하기 때문입니다. 여려분이 자동차를 사는데 그 엔진 구조를 모르고는 시동도 걸 수 없는 차라면 사시겠습니까? 저같으면 그런 건 개나 줄 것 같거든요. 다른 하나는 이러한 테크닉의 경우 자칫 남용되거나 내부 구현을 모르고 사용했다가는 게임 내 부하만 증대 시키고 해킹툴을 막는대는 하나도 보탬이 되지 않기 때문입니다. 결국 출혈을 감수해 가면서까지 가져간 높은 커플링으로 볼 수 있는 재미는 하나도 없다는 이야기입니다.&lt;/p&gt;
&lt;p&gt;물론 잘 아시겠지만 여러분이 모르는 그런 곳에 이 반환 주소 체크 기법을 사용해서 재미를 볼 수 있는 곳은 많이 있습니다. 당연히 그런 건 여기다 적진 않겠죠? 단물 좀 더 빼먹고 누구나 알게 될 즈음에 마치 제가 처음 발견한 마냥 교과서에다 공개하겠습니다. ㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;끝으로 요즘 가장 핫한 데이터 중에 하나인 DirectX 인터페이스 주소를 좀 살펴보겠습니다. DirectX 가상 함수 변조를 체크하기 위해서 해당 인터페이스의 포인터를 전달 받는 것이 이 커플링 높은 방식의 골격같습니다. 하지만 이 또한 안타깝게도 큰 의미는 없습니다. 우선 전달받지 않고도 주소를 획득할 수 있고, 무조건 전달을 받아야만 막을 수 있는 방식이 한가지 있긴 한데 그 방식은 속도 상의 이유로 실전에서 거의 사용되지 않습니다. 또한 사용한다 하더라도 다른 루트를 통해서 검출할 수 있습니다.&lt;/p&gt;
&lt;p&gt;전 이런 방식을 사용해 본 업체들에게 페르미의 역설처럼 한 번 여쭤보고 싶습니다. 달라고 하는 DirectX 인터페이스 주소를 가르쳐 주셔서 재미 좀 보셨습니까? 라구요. 아마 그닥 재미를 못 보셨을 겁니다. 인터페이스를 조작하는 해킹 방식은 제가 지난 번에 썼던 것처럼 Visual C++ 일주일 배우고 게임 커뮤니티에서 DirectX Hook Toolkit을 받아서 월핵 샘플따라 코딩하는 경우 외에는 잘 없거든요. 참 올드 패션드한 테크닉이란 이야기죠. 요즘은 저런 방식 자체가 전문 해커들에게는 거의 사용되지 않습니다. 물론 사용하는 해커가 있다면 그건 B급 해커겠죠. 그리고 그런 B급 해커가 조작하는 것들은 인터페이스를 받지 않아도 다 차단할 수 있답니다. 그러라고 비싼 돈주고 솔루션 사서 쓰는 것 아니겠습니까?&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;게임보안 제품을 왜 사용하는 걸까요? 해킹툴을 막기 위함일겁니다. 그런데 요 근래에 몇몇 게임 업체와 미팅을 하면서 느낀 점은 보안 제품을 해킹툴을 막는 본연의 목적이 아니라 보안 제품한테서 컨설팅을 받고 계시더군요. 그것도 잘못된 보안 컨설팅을요. 그럴 때 마다 정말 안스러움을 느낀답니다.&lt;/p&gt;
&lt;p&gt;해킹툴을 막는 데에는 여러 수천가지 방법이 있습니다. 제가 생각하는 가장 상책은 개발사나 운영사 모두가 전혀 신경 쓸 필요가 없는 방법입니다. 중책은 개발사에서 뭔가 정보를 알려줘야 하는 방법이고, 가장 하책은 게임 업데이트를 보안 업체에 신고해야 하는 방법입니다. 왠만하면 상책을 사용하는 업체와 일을 하세요. 그게 여러분에게도 보안 업체에게도 정신 건강에 이롭습니다. 물론 저희도 과거에 ‘나는 보안이다’라면서 하책을 남발했던 경험이 있습니다. 결과는요? 상호 멘붕상태가 오더군요. 그 때 깨달았습니다. ‘아 진짜 이거 없이는 답이 없겠다 하는 경우를 제외하고는 절대로 하책을 써서는 안되겠다’라고 말이죠.&lt;/p&gt;
&lt;p&gt;다시 한 번 기억하세요. 여러분이 사용하는 솔루션은 해킹툴을 차단하기 위한 솔루션입니다. 게임의 보안 결함을 찾아서 나열해 주는 솔루션이 아니라는 이야기죠. 더 나아가서는 해킹툴 분석 보고서를 그럴듯하게 쓰는 솔루션도, 특허를 나열하는 솔루션도 아닙니다. 단지 여러분의 그 지긋지긋하게 골치아픈 해킹툴들을 알아서 잘 차단해 줄 솔루션을 선택하세요. 그럼 게임 내 보안 결함을 찾을 필요도, 해킹툴 분석 보고서를 쓸 필요도, 특허를 나열할 필요도 없거든요. 맞습니다. 카드를 쥐고 있는 한 여러분이 갑입니다. 이제는 갑의 권리를 다시 찾아 올 때 입니다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_커플링에_관한_오해들.md_1.png&apos; data-alt=&apos;right now는 빼도 된다는 거 아시죵? ㅎㅎ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 612px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/725058a7a4527f814c8db6c709a82b67/dbf98/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 13.684210526315791%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAkklEQVR42qWLORbCMAxEcw9IghfJduKKJpsbCMHH5QZU1NwIBmGOQDHvz/sjVV3XIcaIPvb49n8SQkDlnYcx5kHEzxA8rKW3NQRrGEweZH2h1hZGk3QnjuWOhU5+CSTu5x0qZkZd725KqTuzw3FsX/PWYFpbpKyxXDWSZDjvMZzq4ubtgOnSyqYwrk1hygpLVvgAU9VY0j5RKk0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;right now는 빼도 된다는 거 아시죵? ㅎㅎ~&apos; title=&apos;&apos; src=&apos;/static/725058a7a4527f814c8db6c709a82b67/dbf98/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_1.png&apos; srcset=&apos;/static/725058a7a4527f814c8db6c709a82b67/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_1.png 190w,
/static/725058a7a4527f814c8db6c709a82b67/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_1.png 380w,
/static/725058a7a4527f814c8db6c709a82b67/dbf98/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%BB%A4%ED%94%8C%EB%A7%81%EC%97%90_%EA%B4%80%ED%95%9C_%EC%98%A4%ED%95%B4%EB%93%A4.md_1.png 612w&apos; sizes=&apos;(max-width: 612px) 100vw, 612px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;right now는 빼도 된다는 거 아시죵? ㅎㅎ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 인력에 관한 불편한 진실…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/6174</link><guid isPermaLink="false">https://jiniya.net/wp/archives/6174</guid><pubDate>Mon, 23 Apr 2012 23:58:04 GMT</pubDate><content:encoded>&lt;p&gt;국내 게임보안 업체 중에서 &lt;a href=&quot;http://wellbia.com/&quot;&gt;우리 회사&lt;/a&gt;가 가장 영세하다. 가장 후발 주자다. 그러다보니 업체 미팅을 하다보면 으례 듣는 이야기가 있다. 그 인력을 가지고 지원이 되겠냐는 이야기다. 그런데 아이러니한 사실은 그렇게 이야기 했던 많은 업체들이 사용하고 난 다음에는 지원이 참 좋다는 이야기를 한다. 해킹툴을 잘 잡는다는 이야기도 한다. 왜 그럴까?&lt;/p&gt;
&lt;p&gt;여기에는 게임 업체에서는 전혀 생각하지 못하는 정말 불편한 진실이 숨어있기 때문이다. 바로 MPS다. MPS가 뭐냐고? Man Per Site다. 사이트당 몇 명의 인력이 대응하는지를 나타내는 수치라고 생각하면 되겠다. 과연 이 수치가 얼마일까? 1정도는 될까? 당연히 안된다. 1이면 게임보안 업체는 아마 한 십년 전에 모두 망했을 것이다. 그렇다면 어느 정도일까? 여러분이 생각하는 것보다 훨씬 낮다. 0.1이 되는 업체가 잘 없다. 즉, 게임 10개 사이트에 한 명이 채 되지 않는다는 말이다. 반대로 말하면 한 사람이 열 개 이상의 사이트를 커버해야 한다는 말이다. 이러니 무슨 보안이되고 무슨 해킹툴 컨트롤이 되겠는가? 당연히 되지 않을 수 밖에 없다. 메이저 업체들이 그렇게 해킹툴을 못막는 이유가 바로 여기 있는 것이다. 관심이 없어서가 아니다. 사람이 없는데 무슨 수로 해킹툴을 막겠는가? 당연히 우리는 0.1은 넘는다. 아직까지는. 그러니 다른 업체보다는 잘 할 수 밖에 없는 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 이 MPS 수치가 어느 정도면 해킹툴 제어가 가능할까? 내가 생각하는 최소 수치는 0.57이다. 무슨 근거로 그런 이야기를 하느냐고? 바로 4명이서 7개 사이트를 커버하는 수준이다. 그렇다면 그 4명과 7개 사이트는 어디서 나왔을까? 우선 해킹툴이 출몰하는 정도로 인기있는 온라인 게임의 경우 통상 수출하면 7개국 정도는 깔고 가는 경우가 많다. 따라서 7개 사이트라는 말은 하나의 게임을 4명이서 컨트롤 한다는 말과 동일하다. 그렇다면 4명은 어떤 사람일까? 검색 한명, 분석 한명, 개발 한명, QA 한명이다. 이걸로 될까? 뻥안치고 저정도 인력 투입하면 거의 모든 해킹툴 사이트를 다 다운시킬 수 있다. 물론 기반 시스템은 모두 갖추어져 있다는 전제 하에서다. 기반 시스템 없이 4명이서 무얼 하겠는가? 또 물론 그 4명이 겁나 똑똑하다는 전제하에서다.&lt;/p&gt;
&lt;p&gt;그런데 정말 안타까운 현실은 많은 게임 업체들이 해킹툴 차단에 관심은 많다고 하지만 MPS 0.57에 대한 투자 조차도 인색한 경우가 많다. 국내 게임보안 업체들은 모두 연간 구독(annual subscription) 형태로 제품을 판매한다. 그런데 이 구독료가 십년 전이나 지금이나 별반 차이가 없기 때문이다. 지금 시세로 따져보면 그 일년 구독료가 통상 MPS 0.1에서 0.2 사이다. 그러니 회사 입장에서 차떼고 포떼고 하면 MPS 0.1 이상 투입하기가 힘든 것이다. 흙. 상황이 이러면 메이저 게임보안 업체에서라도 인식을 바꾸도록 테이블을 새로 구성해야 함에도 현실은 그렇지가 못하다. 같이 치킨 게임을 하는 경우가 다반사다. 이러니 게임보안 제품이 좋아지고 싶어도 좋아질 수가 없는 환경인 것이다.&lt;/p&gt;
&lt;p&gt;자자. 여기저기서 웅성 거리는 소리가 들려오는 것 같다. 맞다. 규모의 경제가 있다. 일정 규모를 넘어서면 깔고가는 인력이 당연히 생기게 마련이다. 하지만 그 깔고가는 수많은 인력 중에서 여러분의 게임 게시판 내지는 해킹툴 포럼을 모니터링해주는 인력이 있다고 생각하면 정말 큰 오산이다. 안한다. 왜냐고? 그 깔고가는 수많은 인력은 말 그대로 공유인력이기 때문이다. 그들은 그런 일외에도 할 일이 너무도 많기 때문이다. 그러면 스스로 알아서 한 번은 하지 않을까? 라고 생각할 수도 있는데. 뻥안치고 안한다. 사람이기 때문이다. 잠깐 짬나면 나가서 담배펴야지 그거 모니터링 하겠는가? 난 다른 일도 많이 했는데, 라고 생각하면서 신나게 나가서 담배피게 돼 있다. 그러니 공유인력을 계산에 넣는다는 자체가 넌센스다.&lt;/p&gt;
&lt;p&gt;그러면 다음으로 나오는 이야기들이 있다. 기술을 개발해서 원천 차단을 하면 되지 않겠냐는 것이다. 근데 이게 진짜 정말 골때리는 이야기다. 아니면 게임 업체들이 하는 오해일 수도 있겠다. 그런 오해를 하는 많은 분들을 위해서 조금 원천차단이라는 말의 실제 의미를 풀이해보자면 이렇다. 모든 게임보안 업체에서 말하는 원천차단이라는 말은 Visual C++을 일주일 배우고 나서 해킹툴 커뮤니티에서 소스를 퍼다가 변수 오프셋을 조금 수정해서 해킹툴을 만드는 경우에 대한 대응을 자동으로 할 수 있는 기술이라고 이해하면 되겠다. 물론 어러분도 잘 알고 있는 것처럼 안타깝지만 이것 조차도 잘 안되는 경우도 많이 있긴 하다. 그러니 어떤 업체와 미팅을 하는데 원천차단에 대해서 이야기를 한다면 ‘아 이건 코흘리게들을 막는 기술인데 다른 업체는 이것도 안되나 보구나’라고 이해하면 되겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_인력에_관한_불편한_진실.md_0.png&apos; data-alt=&apos;저 수많은 초록색 Undetected!!! 현기증이 ㅠㅜ~&lt;br&gt;&lt;br&gt;하지만 MPS 0.57에 좋은 게임보안 제품을 사용한다면 저 목록에서 빠지는 것도 불가능 한 일은 아니다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 516px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1eef6f027671f48dedadc1efbde41bc2/fbb32/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 48.42105263157895%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABz0lEQVR42kWLa2+bMBSG+TipkbYFGIECxjaXJMXcCbmAwU4w6XVat2qTpqr//18Msk6TXj1+z3OOpe8v7d1Lc3zt+t9MvLXd10eEA2BpCBge1F3HGMuNp3twHA3sGI6t+2j0+jqAUpi7fuUB6sN6iWgQbHcksFb2hxDOUvdq7VytwZSVM1vaM4JmS3Dl27PR74kiadj8Etjy0lF9rKygTQobuJb2GZuqZylAU01NxWCkYi0UbCj2QgULFepK5FmSBpHmYx0G12g1BkXVrl6RzacwXiSlVp7mVS3vHblkSlHqOZVJJVcnJW3meW1KBvDHPyZeW15kudGybJ++Jc3Dx/3BFPfX57f5w7P8Y63c/lLOt6D/OaeP8t2rzJ/n7MmUaMu6jrFj3zHe8Z73gzgPYuiFOA1jEcfzMIjjaZS9OAohhn+r04lLbVNUe9J25XYX12122Ke7OqZ1PklabHaEtkWxiS6r5NCkzSHdHuKW5ml1IxUJDIm/Kdww9MoCR8TPczdL/Dj1yswNI29TumQ6wHHsl8W0yjK3zDySYAkACyOEEUQIYuhMvHQE34MnMwrnL9FEONFxJEop55wxziayqfwne++cd5enmyZ+Ae869gfuT22dhUcVlgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;저 수많은 초록색 Undetected!!! 현기증이 ㅠㅜ~&lt;br&gt;&lt;br&gt;하지만 MPS 0.57에 좋은 게임보안 제품을 사용한다면 저 목록에서 빠지는 것도 불가능 한 일은 아니다.&apos; title=&apos;&apos; src=&apos;/static/1eef6f027671f48dedadc1efbde41bc2/fbb32/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_0.png&apos; srcset=&apos;/static/1eef6f027671f48dedadc1efbde41bc2/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_0.png 190w,
/static/1eef6f027671f48dedadc1efbde41bc2/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_0.png 380w,
/static/1eef6f027671f48dedadc1efbde41bc2/fbb32/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_0.png 516w&apos; sizes=&apos;(max-width: 516px) 100vw, 516px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;저 수많은 초록색 Undetected!!! 현기증이 ㅠㅜ~&lt;br&gt;&lt;br&gt;하지만 MPS 0.57에 좋은 게임보안 제품을 사용한다면 저 목록에서 빠지는 것도 불가능 한 일은 아니다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그럼 게임 업체들을 고민에 빠뜨리는 진짜 해킹툴들은 어떤 것들일까? 저런 꼬맹이들이 코흘리면서 만드는 장난감일까? 당연히 아니다. 게임 업체를 고민에 빠뜨리고, 게임 서비스 자체를 종료시키게 만드는 유료핵들은 수년간 Visual C++을 갈고 닦았고 (&amp;#x3C;== 해킹툴 소스가 더럽다고 생각하면 오산이다.) 어셈블리에도 능통하면서, 리버싱도 잘하는 그런 애들이 알바해서 돈을 벌려고 만드는 것들이다. 물론 심한 경우에는 기업에서 하는 경우도 있다. 심지어는 보안회사, 게임회사보다 그 기업이 더 클 수도 있다. 여기에다 원천 차단이란 말을 쓴다는 건 내년까지 단 한번도 비가 오지 않을 거라는 걸 보장하는 것과 주식이 5000까지 쭉 갈거라는 걸 보장하는 것과 똑같은 의미다. 미래에 일어날 일에 대한 보장이란 것이다. 당연히 말도 안되는 소리라는 것을 알 수 있다. 여기엔 원천 차단이란 있을 수도 없고, 그런 말을 쓰는 것도 넌센스다.&lt;/p&gt;
&lt;p&gt;그렇다면 무슨 차이가 있는가? 단지 해킹툴이 나왔을 때 얼마나 신속하고 정확하게 대응하느냐의 차이 밖에는 없다. 당연히 여기서 대응한다는 말은 그 지겹도록 매일 올라와 있는 초록색 Undetected라는 말을 적어도 이틀 이상은 빨간색 Detected라는 말로 바꾸는 경우를 말한다. 이 정도 억제력을 우습게 생각할 수 있다. 그렇다면 여러분이 사용하는 보안 제품 업데이트 이후에 해킹툴 페이지를 꼭 방문해 보길 바란다. 그러면 이 이틀이란 시간이 얼마나 영겁의 시간인지를 금방 알 수 있을 것이다. 물론 여러분이 선택한 보안 제품이 진짜 탁월하다면 그 목록에서 여러분의 게임이 영원히 제거되는 기적을 경험케 해 줄 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_인력에_관한_불편한_진실.md_1.png&apos; data-alt=&apos;누구나 공정한 게임을 하고 싶어한다. 그래야 재미있기 때문이다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 418px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/980d3ee10e7cc499c7a2c22254cf750f/2bbac/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 26.31578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAArklEQVR42n2PzQqDMBCE8/4P5qW9iFSsgtGDRARR87tmE+020lNpv8MwDMMsy/w4urqGrvNCAOf28dD3mykKXNag9YF4Jo4vKGRxWVye+77HYYC2hbI0WeabJiodrT1COH/DfAiAaAB270OMDkA7p6y1jizsCWOM1lopRUpeJRCRzfPccc7blnSaJtJnVQkhtk0qKa0xV1tKua7rRmkyBI2ya5guUSM130fw8+p/Xp4LHlG71S0LAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;누구나 공정한 게임을 하고 싶어한다. 그래야 재미있기 때문이다.&apos; title=&apos;&apos; src=&apos;/static/980d3ee10e7cc499c7a2c22254cf750f/2bbac/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_1.png&apos; srcset=&apos;/static/980d3ee10e7cc499c7a2c22254cf750f/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_1.png 190w,
/static/980d3ee10e7cc499c7a2c22254cf750f/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_1.png 380w,
/static/980d3ee10e7cc499c7a2c22254cf750f/2bbac/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_1.png 418w&apos; sizes=&apos;(max-width: 418px) 100vw, 418px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;누구나 공정한 게임을 하고 싶어한다. 그래야 재미있기 때문이다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;게임 시장은 점점 더 커져가고 있다. 당연히 이러한 블랙마켓도 점점 커지고 있다. 더불어 요즘 온라인 게임의 출시에는 항상 이런 질문이 따라 다닌다. 안티 치트 솔루션은 무엇을 사용하는가? 치트 대책은 무엇인가? 이런 것들이 이제는 일반화 됐다는 이야기고 또 온라인 게임에 있어서는 굉장히 중요한 이슈라는 의미일 것이다. 자 이제 결론을 내려보자. 그렇다. 회사에 직원이 많다는 이야기가 여러분의 게임에 관심을 가지는 사람이 많다는 것을 의미하는 건 아니다. 또 해킹툴을 더 잘 막고 관리하기 위해서는 MPS 0.57이라는 최소한의 투자는 이루어져야 한다. 이런 것들이 이루어진다면 클린한 온라인 게임 환경을 만드는 일이 결코 불가능한 일은 아니다.&lt;/p&gt;
&lt;p&gt;아직 이 모든 이야기의 맥락을 눈치채지 못한 분들을 위해서 딱 한 마디만 더 하자면, ㅋㅋ~&lt;/p&gt;
&lt;p&gt;게임보안 하면 &lt;a href=&quot;http://wellbia.com&quot;&gt;XIGNCODE, XIGNCODE&lt;/a&gt;하면 게임보안이라는 거. 답 딱 나온다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 569px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_인력에_관한_불편한_진실.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f1a1d39632ad98f8e1568aa605ea97e5/7ca0c/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 20.52631578947369%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAnklEQVR42iWPCw7DIAxDe46qUiFh4w9pKLv/0eZSC0WQWH5hI+KcS4oJJy7lnFFLKajee0wLDAntmpdCCLlUsnYLIY4lEVEdrXWRa96ztaaX6vVo6N17H+PGFE/YYkzmPLev97XWF4gLCDFEJIIJ4AMBpTbvw7sCtGzpOI6H/JsTcSJ9KDaYfcUjy1pLRM45fM0xG2OImYk/aDHv+/4Hdw8oAITqu48AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                    md 2&apos; title=&apos;&apos; src=&apos;/static/f1a1d39632ad98f8e1568aa605ea97e5/7ca0c/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_2.png&apos; srcset=&apos;/static/f1a1d39632ad98f8e1568aa605ea97e5/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_2.png 190w,
/static/f1a1d39632ad98f8e1568aa605ea97e5/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_2.png 380w,
/static/f1a1d39632ad98f8e1568aa605ea97e5/7ca0c/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_2.png 569w&apos; sizes=&apos;(max-width: 569px) 100vw, 569px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 562px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_인력에_관한_불편한_진실.md_3.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a54dc3484f0f7f9bebb83bfcb31aebfd/a4f00/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 6.315789473684211%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAANUlEQVR42mMwN7ewsrLS1dXV09XRhQF9PX0dHV0DAwM9PT1dPT0DfRBDSxsEIFLGJibq6uoAVFYK55RK46IAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                    md 3&apos; title=&apos;&apos; src=&apos;/static/a54dc3484f0f7f9bebb83bfcb31aebfd/a4f00/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_3.png&apos; srcset=&apos;/static/a54dc3484f0f7f9bebb83bfcb31aebfd/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_3.png 190w,
/static/a54dc3484f0f7f9bebb83bfcb31aebfd/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_3.png 380w,
/static/a54dc3484f0f7f9bebb83bfcb31aebfd/a4f00/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_3.png 562w&apos; sizes=&apos;(max-width: 562px) 100vw, 562px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_인력에_관한_불편한_진실.md_4.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2533ab7b4ef612cd6c6379b0d64a2bab/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 5.263157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAMklEQVR42g2KQQoAMAzC9v9nNrb2tH1hoiiEHIGk9WZbnU6SlyhshwAhHndP9AhU3fs+Y9s1tm5BT34AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                    md 4&apos; title=&apos;&apos; src=&apos;/static/2533ab7b4ef612cd6c6379b0d64a2bab/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_4.png&apos; srcset=&apos;/static/2533ab7b4ef612cd6c6379b0d64a2bab/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_4.png 190w,
/static/2533ab7b4ef612cd6c6379b0d64a2bab/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_4.png 380w,
/static/2533ab7b4ef612cd6c6379b0d64a2bab/abf7b/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_4.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_인력에_관한_불편한_진실.md_5.jpg&apos; data-alt=&apos;고기도 먹어 본 놈이 잘 먹고, 연애도 해 본 놈이 잘 하고, 해킹툴도 막아 본 놈이 잘 막는다.&lt;br&gt;&lt;br&gt;우리는 최고의 팀을 가지고 있다. 그게 바로 우리가 이런 이야기를 들을 수 있는 이유다.&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/88ccc10b29aff0e767354c74152c9904/e28f5/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_5.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHRSjS3JCf/xAAZEAEBAQEBAQAAAAAAAAAAAAACAQMRAAT/2gAIAQEAAQUC2XdvoqEF6NYUoTr7Fyj/xAAVEQEBAAAAAAAAAAAAAAAAAAAQIf/aAAgBAwEBPwGH/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHRAAAgIBBQAAAAAAAAAAAAAAAAECESEiUmGBof/aAAgBAQAGPwKEOxO82JnhJtcFbdJ//8QAHBABAAMBAAMBAAAAAAAAAAAAAQARITFBUWFx/9oACAEBAAE/If0PUMABh8sa6uy4EXEdfYSn2t9lGPds9T//2gAMAwEAAgADAAAAEA//AP/EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxARjN//xAAWEQEBAQAAAAAAAAAAAAAAAAABADH/2gAIAQIBAT8QRYy//8QAHRABAAMAAgMBAAAAAAAAAAAAAQARITFBcZGhwf/aAAgBAQABPxCn8KtKaXX7kdpQJwec6Ir7DTMGAzbtvzZdLWSqAOSvKxZfVQQL29VP/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;고기도 먹어 본 놈이 잘 먹고, 연애도 해 본 놈이 잘 하고, 해킹툴도 막아 본 놈이 잘 막는다.&lt;br&gt;&lt;br&gt;우리는 최고의 팀을 가지고 있다. 그게 바로 우리가 이런 이야기를 들을 수 있는 이유다.&apos; title=&apos;&apos; src=&apos;/static/88ccc10b29aff0e767354c74152c9904/e28f5/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_5.jpg&apos; srcset=&apos;/static/88ccc10b29aff0e767354c74152c9904/8ccab/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_5.jpg 190w,
/static/88ccc10b29aff0e767354c74152c9904/ea4c8/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_5.jpg 380w,
/static/88ccc10b29aff0e767354c74152c9904/e28f5/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EC%9D%B8%EB%A0%A5%EC%97%90_%EA%B4%80%ED%95%9C_%EB%B6%88%ED%8E%B8%ED%95%9C_%EC%A7%84%EC%8B%A4.md_5.jpg 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;고기도 먹어 본 놈이 잘 먹고, 연애도 해 본 놈이 잘 하고, 해킹툴도 막아 본 놈이 잘 막는다.&lt;br&gt;&lt;br&gt;우리는 최고의 팀을 가지고 있다. 그게 바로 우리가 이런 이야기를 들을 수 있는 이유다.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[클라우드 서비스!!! 과연 저렴할까?]]></title><description><![CDATA[CBT가 시작하던 날이었다. 날씨도 꿉꿉하던 그 날. 기어이 사고가 터졌다. 회사 홈페이지와 메일 서버를 운영하는 서버에 이상이 생긴 것이다. 멀쩡하다가 접속이 안돼서 IDC…]]></description><link>https://jiniya.net/wp/archives/6103</link><guid isPermaLink="false">https://jiniya.net/wp/archives/6103</guid><pubDate>Sat, 21 Apr 2012 23:58:03 GMT</pubDate><content:encoded>&lt;p&gt;CBT가 시작하던 날이었다. 날씨도 꿉꿉하던 그 날. 기어이 사고가 터졌다. 회사 홈페이지와 메일 서버를 운영하는 서버에 이상이 생긴 것이다. 멀쩡하다가 접속이 안돼서 IDC에 전화해서 재부팅을 요청했다. 소식이 없길래 재차 전화했더니 하드가 나갔다는 것이었다. 물론 그 사이에 IDC에서 무슨 일이 있었는지는 아무도 모른다. 단지 하드가 노후해서 맛이 갔다는 이야기. IDC를 찾아갔다. 겉은 멀쩡해 보이는 SATA 하드디스크를 가져오면서도 내심 우리 PC에 연결하면 잘 될 거란 생각을 했다. 하드디스크가 고장 난다니 설마? 설마? 했다. 그랬는데 그 하드는 진짜 맛탱이가 갔다. 부팅을 시키려고 하자 끼릭끼릭 거리며 고주파 음을 울리며 우리를 나락으로 보냈다. 남자라면 백업을 하지 않는다는 토발즈의 말을 철썩 같이 믿었기에 우리에겐 어떠한 데이터도 없었다. 운영중인 서비스는 회사 홈페이지에 FAQ 페이지뿐이라 천만 다행이었다. IDC 직원이 그랬다. 서버도 하드웨어에 신경을 써야 한다고. 멀쩡하다고 하더라도 3-4년에 한번씩 서버 업그레이드도 하고 아니면 하드는 반드시 교체해 주는 것이 좋다고 말이다. 그렇겠지.&lt;/p&gt;
&lt;p&gt;그날의 일을 교훈 삼아서 클라우드 서비스를 찾아보기 시작했다. 서버 관리할 사람도 없는데 서버 하드웨어까지 신경 쓸 필요는 없지 않을까라는 생각에서였다. 예전부터 구글 앱엔진 이야기를 많이 들어서 살펴봤는데 우리 목적에 쓸만한 서비스는 아니었다. 거기다 앱엔진 홈페이지는 온통 불투명한 사항뿐이었다. 뭔가 고객들에게 제품을 파는 사이트가 아니라 개발자 놀이터를 만들어 놓은 느낌이었다. 그래서 접었다. 그리고 이후 가장 많은 클라우드 서비스를 운영한다는 아마존을 찾았다. AWS 계정을 만들고 접속했다. 이거다. 무엇이 어떻게 진행되는지 명확했고 내가 무엇을 사용할 수 있고 돈은 얼마가 지불되는지 확실했다. 직관적이었고 쓰기 편했다.&lt;/p&gt;
&lt;p&gt;그러면서 나는 막연하게 서버를 직접 운영하는 것보단 아마존이 응당 쌀것이라 생각했다.&lt;/p&gt;
&lt;p&gt;그런데 그건 정말 오해였다. 진짜로.&lt;/p&gt;
&lt;p&gt;우선 기존 서버를 살펴보자. 서버를 임대하는 비용은 얼마일까? 공짜다. 요즘은 회선 비용만 주면 공짜로 주는 서버도 많기 때문이다. 우리가 사용하는 서비스에는 공짜 서버를 써도 전혀 지장이 없었다. 지출하는 비용은 IDC 회선 비용. 10Mbps에 대한 10만원이 전부다. 10Mbps 회선이면 얼마를 전송할 수 있을까? 초당 1.25메가 바이트, 분당 75메가바이트, 시간당 4.5기가바이트, 하루당 108기가 바이트를 전송할 수 있다. 그닥 나쁘진 않다.&lt;/p&gt;
&lt;p&gt;그럼 이제 아마존 클라우드 서비스를 생각해보자. 난 처음에 멋모르고 서비스할 지역이 싱가폴이랑 가까워 싱가폴에 서버를 만들었다. 기존에 우리가 가진 공짜 물리 하드웨어와 유사한 성능을 가진 인스턴스는 m1.xlarge였다. 그거보다 낮은 단계의 인스턴스는 모두 서비스가 불가능할 정도로 성능이 나빴다. 그 인스턴스는 시간당 무려 0.45달러가 들어간다. 이게 참 웃긴데 이렇게 보면 굉장히 싸 보이는데 곱하기를 하면 장난이 아니다. 해볼까? 0.45*24*30 = 324달러가 나온다. 한 달에 서버 비용으로만 33만원 가량을 지출해야 한다는 의미다. 물론 m1.xlarge가 기존의 공짜 서버 보다는 좋을 것이다. 그러리라 굳게 믿는다. 하지만 가격은 여기서 끝이 아니다. 데이터 요금이 추가되기 때문이다. 아마존 클라우드 서비스는 밴드 기준이 아니라 트래픽 기준으로 과금을 한다. 싱가폴 지역의 데이터 요금은 10TB까지 기가바이트당 0.19달러다. 역시 싸 보인다. 그런데 우리는 어제 하루 서비스를 오픈했는데 벌써 30기가 바이트를 사용했다. 0.19*30=5.7달러, 6-7천원 가량을 썼다는 의미다. 30을 곱하면 재미있어진다. 171달러가 된다. 자 이제 우리가 한 달에 아마존에 상납해야 하는 비용을 계산해보면 인스턴스 비용과 데이터 비용만 합해도 무려 495달러가 나온다. 50만원 가량이다. 기존 서버보다 5배나 많은 돈을 지불해야 한다는 의미다. 그런데 이게 끝이 아니다. IP비용, 하드디스크 비용, 무슨 비용, 무슨 비용… 서비스를 신청하면 당연한 이야기겠지만 모두 비용이다. 딱 보고 드는 느낌은 한솥도시락이다. 계란 후라이도 팔아먹는 그 느낌? ㅋㅋ~&lt;/p&gt;
&lt;p&gt;과연 싼 걸까? 우리가 아마존에서 서버를 운영하면서 누릴 수 있는 프리미엄은 두개 뿐이다. 하나는 250Mbps의 회선, 다른 하나는 하드웨어는 신경 꺼도 된다는 거. 물론 서버를 복사해서 바로 생성할 수 있는 이점도 있지만 직접 세팅하나 복사하나 별 차이는 없다. 단지 하드웨어에 신경을 쓰지 않기 위해서 한대당 40만원 가까운 추가 비용을 지출해야 하는 것이다. 과연 싼가? 글쎄다. 한대는 40만원, 두 대는 80만원, 세 대면 120만원 벌써 이쯤 되면 하드웨어 관리자를 고용하는 게 더 싸지 않을 까란 생각이 들기 시작한다. 클라우드 서비스는 결코 싸지 않다. 더욱이 우리처럼 밴드는 전혀 중요하지 않은 서비스는 더더욱 그렇다. 밴드가 중요한 서비스라면 다시 고려해볼 필요가 있다. 왜냐하면 글로벌 100Mbps 밴드가 가비아의 경우 월 800만원 정도 하기 때문이다. 250Mbps면 장난 아닌 밴드다. 물론 가비아는 데디 방식이라 아마존 보다는 좀 더 좋을 수도 있다.&lt;/p&gt;
&lt;p&gt;이런 모든 사항에도 불구하고 난 아마존을 쓰겠다. 난 아마존의 모든 클라우드 서비스가 필요하다는 사람들에게 하고 싶은 몇 가지 팁을 써보면 이렇다. 일단 절대 32비트 운영체제는 설치하지 말지어다. 확장이 불가능하다. 큰 걸 쓰던 작은 걸 쓰던 64비트를 써라. 그래야 나중에 쉽게 큰 걸로 바꿀 수 있다. 또한 윈도우도 절대 쓰지 말아야 한다. 훨씬 비싸다. 곱하기 하면 추가 비용이 장난이 아니다. 다른 한 가지는 절대 지역을 선택하지 마라. 가깝다고 일본, 동남아 서비스한다고 싱가폴 이랬다간 망한다. 왜냐하면 해당 지역이 결코 싸지 않기 때문이다. 가격 테이블보고 제일 싼 지역을 선택하는 것이 좋다. 내가 멋모르고 싱가폴에 서버를 세팅했다고 했는데 미쿡에 세팅했을 때와 비교하면 데이터 요금이 한 달에 7-8만원 차이 난다. 장난 아니다. 트래픽이 더 많으면 더 커진다. 그리고 진짜로 쓸 생각이 있다면 무조건 약정해야 한다. 그것만이 살 길이다.&lt;/p&gt;
&lt;p&gt;난 비용은 하나도 중요하지 않은데 서비스는 괜찮냐고 물어본다면 절대 그냥 아마존 쓰라고 강추해주고 싶다. 진짜 편하고 잘 돼 있다. 그 모든 것이. 국내 업체들이 아마존보다 속도도 빠르고 더 저렴한 서비스들을 내놓겠다고 한다. KT의 유클라우드도 그랬고, SKT도 상품을 준비한다고 한다. 나름 써 본 입장에서 비교해 보자면 비싸도 아마존이다. 안정성 및 검증은 둘째 치고라도 웹 인터페이스만 봐도 진짜 애와 어른이 아니라 세포 덩어리와 사람을 비교하는 수준으로 차이 난다. 나도 개발자지만 아마존 웹서비스를 사용하면서 느낀 건 진짜 토나올 정도로 잘만들어 놨다는 거다. 저런거 만든 개발자 한 명만 데려와도 울 웹 서비스도 진짜 뽀대날 거 같은 느낌. 근데 이랬든 저랬든 그 모든 게 다 결코 싸진 않다. 우리가 신경 쓰지 않아도 되고 편한 만큼 그 비용을 지불하고 있다는 거다. 세상에 절대로 네버 공짜 점심은 없다. 진짜 이 글은 한 30만원 짜리는 되는것 같다. 왜냐하면 나는 이 모든 사실을 아마존에 한 30만원은 상납하고 배웠기 때문이다. 큭~&lt;/p&gt;
&lt;p&gt;멋도 모르고 로그 서버 주소를 죄다 변경했는데 월요일 다시 모두 롤백 업데이트를 해야 할 것 같다. 애꿎은 지원팀 식구들만 고생하게 생겼다. 헤드가 멍청하면 직원들이 고생한다는 말이 괜한 말이 아니다. 흙~&lt;/p&gt;
&lt;p&gt;끝으로 사족을 하나만 더 달자면 국내 서버 임대는 가비아가 좋다. 예전에 싸다고 닷네임코리아를 쓴 적이 있었는데 완전 왓더헬이었다. 전화도 안받고, 관리도 안되고 싼 게 비지떡이란 교훈을 그 때 깨달았다. 가비아는 항상 전화도 받았고, 우리 하드디스크가 맛탱이가 간 그 순간에도 우리가 가장 빠르게 서비스를 복구 할 수 있도록 도와 주었다. 괜히 코스닥 상장 업체가 아니다. 가비아를 안쓰더라도 절대로 닷네임코리아는 쓰지 말길 바란다. 이건 뭐. 헬이다. 헬게이트 ㅋ~&lt;/p&gt;
&lt;p&gt; 10
 34&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[스레드 개념과 원리]]></title><description><![CDATA[컴퓨터에서 무엇인가를 동시에 실행시킨다는 개념은 초창기부터 있었다. 실제로 1970년대 유닉스 구현에는 이미 멀티태스킹이라는 개념이 포함되어 있었다. 하지만 이런 방식이 범용적으로 사용되기 까지는 오랜 시간이 걸렸다. 1995년 Windows 9…]]></description><link>https://jiniya.net/wp/archives/5856</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5856</guid><pubDate>Tue, 20 Mar 2012 23:58:02 GMT</pubDate><content:encoded>&lt;p&gt;컴퓨터에서 무엇인가를 동시에 실행시킨다는 개념은 초창기부터 있었다. 실제로 1970년대 유닉스 구현에는 이미 멀티태스킹이라는 개념이 포함되어 있었다. 하지만 이런 방식이 범용적으로 사용되기 까지는 오랜 시간이 걸렸다. 1995년 Windows 95가 나오기까지 PC 운영체제를 거의 독점했던 DOS 시절에는 한번에 하나의 프로그램이 실행되는 것이 상식이었고, 다른 프로그램과 동시에 실행되는 프로그램을 만드는 것이 대단한 테크닉으로 취급 받았다. Windows 3.1의 등장과 함께 멀티태스킹이란 개념이 일반인들에게 본격적으로 소개되었다. Windows 3.1은 DOS 위에서 구동되는 프로그램이었지만 여러모로 현재 Windows의 기틀을 다진 운영체제였다. 비선점형 멀티태스킹 방식을 지원했고 현재 사용되는 GUI의 기본 개념을 소개한 운영체제였다. 이런 시기를 거쳐 Windows 95가 등장하면서 DOS 시절에 굳어졌던 일반인들의 상식은 완전히 뒤집혔다. 이제 프로그램은 원래 당연히 동시에 실행되는 것이고, 운영체제에서 멀티태스킹이란 당연히 지원해야 되는 기능이 돼버렸다. Windows 95의 선점형 멀티태스킹은 일반인들에게 그런 인식을 심어주기에 충분했다.&lt;/p&gt;
&lt;p&gt;하지만 모든 일이 항상 좋은 점만 있는 것은 아니다. 일반인들에게 당연한 기능 내지는 축복이 시선을 달리해서 개발자의 입장으로 바라보면 재앙과도 같기 때문이다. 단순히 동시에 실행된다는 사실 만으로는 그렇게 많은 문제가 발생하진 않지만 동시 상황에서 무엇인가를 공유하기 시작하면 지옥 문을 여는 것과 동일한 효과를 가져온다. 단순히 하나만 공유해도 이런데 프로세스 내에서 모든 자원을 공유하는 스레드는 문제 발생의 정도가 더 심각하다. 이런 환경은 개발자에게 엄청나게 많은 문제들을 안겨주었고, 더불어 기존에는 고민할 필요도 없었던 문제들에 대해서 고려하도록 만들었다. 그리고 이 시점부터 더 이상 프로그램은 결정론적으로 동작하지 않게 되었다. 이는 달리 표현하면 재현 불가능한 무수한 버그들이 스레드라는 판도라의 상자를 통해서 세상으로 출현했다는 것이다.&lt;/p&gt;
&lt;p&gt;이런 여러 이유로 멀티 스레드 프로그래밍은 윈도우 프로그래밍 중에서도 매우 어려운 부분에 속한다. 그럼에도 점점 더 PC의 코어 수는 늘어가고 멀티 스레드 프로그래밍은 점점 더 당연한 일이 되어가고 있다. 왜 멀티 스레드 프로그래밍이 어려운 것일까? 아마도 우리의 생각 자체가 병렬적으로 동시 처리하는 것에 익숙하지 않은 점에 그 근본적인 원인이 있을 것 같다. 이번 시간에는 컴퓨터에서 멀티태스킹을 구현하는 기본적인 구조와 멀티태스킹이 가져오는 동기화 문제에 대해서 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;시분할&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;요즘은 CPU가 여러 개 달린 컴퓨터가 일반적이다. 스마트폰에도 듀얼 코어가 탑재되는 세상이니 PC는 두 말하면 잔소리다. 이렇게 CPU가 여러 개 달린 컴퓨터에서는 동시에 실행하는 것이 하나도 이상하지 않다. 장치 개수만큼 동시에 실행할 수 있는 것은 누가 봐도 당연한 일이기 때문이다. 하지만 Windows가 인기를 끌듯 말듯했던 Windows 3.1 시절부터 Windows XP가 등장하던 시점까지는 이러한 멀티 코어가 일반적인 PC 환경은 아니었다. 그 당시 컴퓨터에는 CPU가 하나라는 것이 거의 고정적이었던 시절이었다. 그렇다면 어떻게 이 CPU가 하나인 환경에서 여러 개의 프로그램을 동시에 실행할 수 있었던 것일까? 여기에는 약간의 눈속임이 있다.&lt;/p&gt;
&lt;p&gt;눈속임을 쉽게 이해하기 위해서 우리가 공부를 하는 과정에 비유를 들어서 먼저 살펴보도록 하자. 텅 빈 책상이 있고, 책상 앞 의자에 우리가 앉아 있는 상황이다. 책상에는 국어, 영어, 수학 문제집이 놓여 있다. 이 문제집을 다 푸는 것이 오늘 우리의 할 일이다. 이 미션을 달성하는 방법에는 크게 두 가지 전략이 존재한다고 볼 수 있다. 하나는 국어 문제집을 다 풀고, 영어 문제집을 다 풀고, 수학 문제집을 다 푸는 형태로 순차적으로 하나씩 작업을 완료해 나가는 방식이고, 다른 하나는 국어, 영어, 수학 문제집을 번갈아 가면서 조금씩 풀어 나가는 방식이다. 멀티태스킹의 비밀은 바로 두 번째 방법에 있다. 문제집을 번갈아 가면서 푸는 상황에서 문제집을 교체하는 시간을 단축시키다 보면 어느 순간부터는 마치 우리가 세 개의 문제집을 동시에 풀고 있는 것처럼 느껴진다는 사실을 이용한 것이다.&lt;/p&gt;
&lt;p&gt;운영체제는 여러 개의 프로그램을 동시에 실행하기 위해서 우리가 문제집을 풀었던 것과 동일한 방식으로 CPU에 프로그램 코드를 할당한다. 탐색기, 계산기, 그림판이 실행되어 있다면 Windows는 탐색기 코드를 조금 실행하고 계산기 코드를 또 조금 실행하고 이어서 그림판 코드를 실행하고는 다시 탐색기 코드를 실행하는 식으로 동시에 실행된 프로그램의 코드들을 잘게 나누어서 반복적으로 실행함으로써 마치 우리 눈에는 여러 개의 프로그램이 동시에 실행되는 것처럼 보이도록 만든다.&lt;/p&gt;
&lt;p&gt;문제집을 번갈아 가면서 풀려면 문제집을 바꿀 때에 자신이 마지막으로 풀었던 문제가 어디인지를 기록해 두어야 한다. 그래야 나중에 다시 그 문제집을 풀 때에 어디서부터 풀어나가야 할지 기억할 수 있기 때문이다. 이렇게 마지막으로 풀었던 문제가 어떤 것이었는지를 기억하는 것과 마찬가지로 멀티태스킹에서도 이러한 것들이 필요하다. 작업을 이어가기 위해서는 중지했던 작업을 어디서부터 이어가야 할지를 알아야 하기 때문이다. 이렇게 작업을 이어가기 위해서 중단했던 시점의 기록을 “컨텍스트”, 작업들을 전환하는 것을 두고는 “컨텍스트 스위칭”이라고 표현한다.&lt;/p&gt;
&lt;p&gt;문제집을 번갈아 가면서 푼다는 이 방법을 좀 더 살펴보면 재미있는 현상이 있다. 문제집을 너무 띄엄띄엄 번갈아 풀 경우에는 세 개를 동시에 푼다는 느낌이 없어지고, 문제집을 자주 번갈아 풀다 보면 특정 시점 이상부터는 문제집을 푸는 시간보다 문제집을 바꾸는 시간이 더 많아진다는 점이다. 이는 시분할을 사용한 멀티태스킹 시스템에서는 모두 발생하는 문제로 컨텍스트 교체 비용이 공짜가 아니라는 점을 보여준다. 따라서 운영체제는 멀티태스킹의 품질과 교체 비용을 고려해서 작업 교체 빈도를 적절하게 결정할 필요가 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;협력형 vs 선점형&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;앞선 국영수 문제집 풀이 예를 다시 생각해 보자. 여기서 우리가 문제집을 번갈아 푼다고 생각했을 때 이를 통제하는 방식 또한 크게 두 가지 형태로 나뉠 수 있다. 문제집을 푸는 당사자가 자유롭게 일정시간 한 문제집을 풀다가 다음 문제집을 푸는 형태로 번갈아 가면서 푸는 방식이 있을 수 있고, 다른 하나는 선생님이 일정시간마다 들어와서 다음 문제집을 풀도록 지시하는 방법이 있을 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 이 두 방식에는 각각 어떤 장단점들이 있을까? 우선 스스로 관리하는 방법을 생각해 보자. 이 방법의 장점은 효율성의 극대화에 있다. 문제를 푸는 당사자가 스스로 문제집을 교체하기 때문에 언제 교체하는 것이 가장 유리한지를 알 수 있다는 점이다. 다른 부가적인 장점으로는 선생님이라는 외부 존재가 필요하지 않다는 점을 들 수 있겠다. 이는 다시 말하면 비용이 절감된다는 말이다. 이에 반해서 두 번째 방법은 선생님이라는 추가 비용이 발생하지만 문제집 교체가 일정시간마다 반드시 발생하기 때문에 문제집 세 개에 할당되는 시간이 비슷해 진다. 멀티태스킹의 관점에서 보자면 일정 수준 이상으로 멀티태스킹 품질을 유지할 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;이게 바로 협력형과 선점형 멀티태스킹의 차이다. 협력형 멀티태스킹이란 멀티태스킹 작업들이 협력해서 동시에 실행되는 구조를 말한다. 프로그램 실행 중간에 스스로 컨텍스트 전환을 해도 되는 시점이라고 판단이 된다면 다음 작업에게 CPU를 양보해주는 형태로 멀티태스킹이 진행된다. Windows 3.1이 이러한 방식을 채택했었다. 하지만 앞서도 언급했듯이 이 방식의 단점은 특정 작업이 지나치게 오래 CPU를 독점할 경우 전체 멀티태스킹의 품질이 떨어질 수 있다는 점에 있다. 더욱 치명적인 문제는 특정 작업의 버그로 인해서 CPU 자원을 다른 작업에게 양보하지 않을 경구 운영체제 자체가 다운될 수 있다는 점이다.&lt;/p&gt;
&lt;p&gt;선점형 멀티태스킹이란 협력형과는 반대로 작업 제어 권한을 커널이 가지는 구조를 말한다. 이는 모든 작업이 임의의 시점에 커널에 의해서 선점될 수 있음을 의미한다. 선점된다는 말은 CPU 자원이 커널에게로 다시 넘어간다는 것이다. 여기에선 특정 작업이 CPU를 독점할 수도 없으며, CPU를 독점하려 한다고 해도 커널이 원하면 언제든지 CPU 제어권을 뺏어올 수 있다. 즉, 커널이 선생님의 역할을 한다고 할 수 있다. 이 방식의 장점은 앞에서도 설명한 것과 같이 안정적으로 멀티태스킹을 수행할 수 있으며, 작업들의 버그로 시스템다운이라는 치명적인 결과가 나타나진 않는다는 점이 있다. Windows 95 이후의 모든 Windows 운영체제는 이러한 선점형 멀티태스킹 방식으로 멀티태스킹을 구현하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스레드&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;전통적으로 운영체제에서 작업이란 프로세스란 개념으로 표현된다. 따라서 운영체제는 앞서 설명한 것처럼 이런 프로세스를 동시에 여러 개 실행할 수 있도록 만들기 위해서 프로세스의 코드를 번갈아 가면서 수행한다. 이렇게 멀티태스킹 운영체제를 만들어놓고 보니 만들어진 프로세스들 중에는 다른 프로세스와 대규모의 자료를 공유해야 하는 것들이 있었다. 이런 프로세스들은 단순히 자료를 공유하기 위해서 운영체제의 IPC라는 복잡하고 비싼 메커니즘을 사용하고 있었다. 여기에서 이런 의문을 품은 사람들이 생겨난다. 왜 이렇게 멍청하게 하고 있지? 처음부터 모든 것을 자동으로 공유하도록 해준다면 어떨까? 이런 생각이 스레드라는 개념의 초기 발상이다. 많은 유닉스 운영체제는 이 개념의 생각대로 스레드를 특수한 형태의 프로세스로 처리한다. 실제로 리눅스의 경우에는 스레드라는 별도의 커널 객체를 두기 보다는 단순히 동일한 커널 구조체를 참조하는 특수한 프로세스로 구현했다.&lt;/p&gt;
&lt;p&gt;하지만 Windows는 이러한 방식이 아닌 좀 다른 방식으로 스레드와 프로세스의 관계를 정리했다. 일단 기존의 스케줄링 단위를 프로세스에서 스레드로 바꾸어 버렸고, 프로세스는 스레드가 수행될 때 참조하는 컨테이너 역할로 만들어버렸다. 이렇게 만들어버리자 Windows에서는 스레드가 없는 프로세스란 아무런 의미가 없어졌다. 그래서 Windows에서 모든 스레드 종료란 프로세스의 종료를 의미한다.&lt;/p&gt;
&lt;p&gt;다시 정리하면 이렇다. Windows 환경에서 프로세스란 실행 환경을 제공해주기 위한 컨테이너 역할을 한다. 여기에는 주소 공간과 접근 권한 같은 것들이 포함된다. 프로세스 자체로는 수행 가능한 객체가 아니며 내부에서 하나 이상의 스레드를 수행시킬 수 있는 환경에 불과하다. 스레드는 스케줄링의 기본 단위이며 하나의 실행 흐름을 나타낸다. 스레드는 수행되기 위해서는 해당 스레드가 수행될 프로세스 정보가 있어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;동기화&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;스레드가 이야기가 나오면 기본 안주로 함께 등장하는 메뉴가 동기화 문제다. 왜 그럴까? 그 답을 알기 위해서는 “동기화란 무엇인가?” 라는 질문에 대한 답을 먼저 찾아야 한다. 동기화란 바로 코드가 실행되는 순서를 정하는 일을 말한다. 어떤 코드를 먼저 실행할지 어떤 코드를 나중에 실행할지 순서를 정하는 일이다. “프로그램은 항상 프로그래머가 정해둔 순서대로 실행되는 것 아닌가요?”라는 의문을 가질 수 있다. 맞다. 프로그램은 항상 프로그래머가 정해둔 순서대로 실행된다. 하나만 실행될 때에는 말이다. 하지만 동시에 실행되기 시작하면 문제가 달라진다. 개별 실행 흐름들은 기존과 마찬가지로 순차적으로 수행되지만 그 흐름들이 섞이면 전혀 생각지도 못한 문제를 발생시킨다. 이를 방지하기 위해서 섞여서 실행되는 코드들 사이에 순서를 정하는 일이 필요해진 것이다. 그래서 동기화 문제란 항상 동시성과 같이 나올 수 밖에 없다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;동시성 vs 병렬성&lt;/p&gt;
&lt;p&gt;비슷해 보이는 이 두 말은 큰 차이를 가지고 있다. 우선 동시성이란 우리에게 동시에 실행되는 것처럼 보이는 것들을 모두 나타내는 말이다. 따라서 단일 CPU 상에서 시분할 기법을 사용해서 여러 개의 프로그램을 수행하는 것도 동시성에는 포함된다. 반면 병렬성이란 복수의 CPU를 통해서 코드가 진짜 동시에 실행되는 상황을 나타낸다. 이런 의미에서 병렬성이란 물리적인 동시성을 나타낸다고 생각하면 되겠다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#x3C;리스트 1&gt;에는 동기화 문제를 보여주는 간단한 코드가 나와 있다. PinGame 함수는 핀을 서로 하나씩 가져가면서 마지막 핀을 가져가는 사람이 이기는 게임을 묘사한 코드다. 이제 이 함수가 스레드로 여러 개가 동시에 실행된다고 가정해보자. 그러면 개별 스레드는 이 하나의 코드를 순차적으로 실행하겠지만 운영체제 관점에서 보자면 이 코드들이 섞여서 동시에 실행되는 셈이 된다. 이렇게 동시에 실행되면 하나만 실행될 때에는 전혀 생각지도 못했던 문제가 발생하는데 이렇게 동시에 실행되면서 발생하는 문제를 동기화 문제라고 말한다.&lt;/p&gt;
&lt;p&gt;우선 동기화 문제를 보다 효과적으로 설명하기 위해서 간단한 표현식을 정의하자. “(숫자)”는 숫자에 해당하는 스레드로 컨텍스트가 변경됐음을 나타낸다. a, b와 같은 기호는 코드 상의 주석에 나타나 있는 지점이 실행됐음을 의미한다. 따라서 “(1)ab”라는 것은 1번 스레드가 a, b라는 코드를 실행했음을 나타낸다. 마찬가지로 “(1)ab(2)a”라는 것은 1번 스레드가 a, b를 수행하고 2번 스레드로 컨텍스트 전환돼서 a라는 코드가 실행됐음을 나타낸다.&lt;/p&gt;
&lt;p&gt;리스트 1 동기화 문제를 가진 코드&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PrintWinner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;                                 &lt;span class=&quot;token comment&quot;&gt;// ... a&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pin &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;// ... b&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token comment&quot;&gt;// ... c&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;you win\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// ... d&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token comment&quot;&gt;// ... e&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;자 그렇다면 앞서 정의한 표현식을 토대로 &amp;#x3C;리스트 1&gt;의 코드에서 동기화 문제가 발생하는 흐름을 찾아보도록 하자. 바로 “(1)abea(2)ab(1)bcd(2)cd”가 그것이다. 문제는 결국 “you win”이라는 문자열이 화면에 두 번 출력된다는 것이다. 이런 코드들을 보여주고 여기까지 설명하면 대부분의 학생들은 &amp;#x3C;리스트 1&gt;의 코드를 고침으로써 문제를 해결할 수 있다고 생각한다. 그리고는 거의 대부분 코드를 &amp;#x3C;리스트 2&gt;와 같이 고친다.&lt;/p&gt;
&lt;p&gt;리스트 2 동기화 문제를 가진 코드&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PrintWinner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pin &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;token comment&quot;&gt;// … a&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pin &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// … b&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;you win\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇다면 과연 &amp;#x3C;리스트 2&gt;의 코드는 문제가 없을까? 언뜻 보기에는 뭔가 좀 더 명확해 보여서 문제가 없어 보이지만 좀 깊이 생각해보면 &amp;#x3C;리스트 2&gt;의 코드도 문제가 생기는 흐름을 찾아낼 수 있다. “(1)a(2)abc(1)bc”가 그것이다. 이 코드는 동기화 문제가 어디에서 비롯되는지 보다 명확하게 보여준다. 바로 값의 변경과 비교 사이에 발생하는 컨텍스트 전환이다. 이 말은 pin의 값 변경과 0과 비교하는 부분이 하나의 덩어리로 뭉쳐서 연산이 되지 않고서는 절대로 이 문제를 해결할 수 없다는 걸 의미한다.&lt;/p&gt;
&lt;p&gt;여기까지 이야기하면 “if(--pin == 0)”과 같은 코드를 쓰면 된다고 생각하는 사람들이 있다. 하지만 “if(--pin == 0)”과 같은 표현식도 C언어 상으로는 한 줄로 표기되기 때문에 한번에 실행된다고 생각하기 쉽지만 컴파일러가 생성해낸 기계어는 &amp;#x3C;리스트 2&gt;의 코드와 마찬가지로 여러 개의 기계어로 구성되어 있기 때문에 실행하는 사이에 컨텍스트 스위칭이 발생할 수 있고, 최종 프로그램에서는 동일한 문제가 발생한다.&lt;/p&gt;
&lt;p&gt;이를 해결하기 위해서는 앞에서 우리가 내린 결론, 값의 변경과 비교가 한 덩어리가 되어서 실행되도록 만들어줄 어떤 도구가 필요하다. 이런 기능을 제공해주는 도구가 바로 운영체제에서 지원해주는 동기화 객체다. &amp;#x3C;리스트 3&gt;에는 이러한 도구 중 하나인 크리티컬 섹션을 사용해서 문제를 해결한 코드가 나와있다.&lt;/p&gt;
&lt;p&gt;리스트 3 크리티컬 섹션을 통한 동기화 문제 해결&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;CRITICAL_SECTION cs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;EnterCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                   &lt;span class=&quot;token comment&quot;&gt;// … a&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                                       &lt;span class=&quot;token comment&quot;&gt;// … b&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pin &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;                                 &lt;span class=&quot;token comment&quot;&gt;// … c&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;LeaveCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;// … d&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;you win\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                      &lt;span class=&quot;token comment&quot;&gt;// … e&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;LeaveCriticalSection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                   &lt;span class=&quot;token comment&quot;&gt;// … f&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;크리티컬 섹션은 해당 객체를 진입한 상태에서 다른 스레드가 다시 진입하지 못하도록 만드는 기능을 한다. “(1)a(2)”는 가능하지만 “(1)a(2)a”는 불가능하다는 말이다. “(1)a(2)(1)b(2)(1)c(2)”와 같이 1번 스레드가 a를 수행하고 나면 1번 스레드가 d를 수행하기 전까지 다른 스레드로의 컨텍스트 스위칭은 발생할 수 있지만 해당 스레드가 a를 수행 시키는 것은 불가능하다. 결국 실행 흐름의 입장에서는 중간 중간 잡음이 섞이긴 하지만 결과론적으로 b와 c가 항상 한번에 수행되는 것과 동일한 효과를 나타낸다.&lt;/p&gt;
&lt;p&gt;그렇다면 운영체제는 어떻게 이런 것들을 만들 수 있었을까? 운영체제가 만든 코드라고 하더라도 결국 CPU 상에서 동작하기는 우리가 만든 코드와 다를 수 없기 때문이다. EnterCriticalSection 내부에서도 언제든지 컨텍스트 전환이 발생할 수 있지 않을까? 당연한 이야기다. 이 문제를 해결하기 위해서는 크게 두 가지 종류의 해법이 있다. 하나는 운영체제 스케줄러를 특수하게 만들어서 EnterCriticalSection과 같은 함수의 수행 도중에는 절대로 컨텍스트 전환이 발생하지 않도록 만드는 것이다. 다른 하나는 보다 낮은 단계에서 값의 변경과 비교를 한번에 수행하는 연산을 사용하는 것이다. x86/64 계열의 CPU에는 이러한 목적을 위해서 cmpxchg라는 명령어를 제공한다. 비교와 변경을 한번에 수행하는 명령어다. Windows는 결국에는 이러한 명령어를 사용해서 동기화 객체를 구현한다. 이런 맥락에서 우리가 처음에 만든 프로그램도 cmpxchg라는 명령어를 사용하도록 만든다면 동기화 객체를 사용하지 않고도 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;지금까지의 논의는 단일 CPU 상에서 동시에 실행되는 코드들에 대한 것이었다. 멀티코어가 되면 문제가 좀 더 복잡해진다. 멀티코어란 CPU가 두 개 이상인 시스템을 말한다. 이런 시스템에서는 진짜 동시 실행이 가능해진다. 이 말은 지금까지 논의했던 방식으로는 멀티코어 환경에서 문제를 해결할 수 없다는 것을 의미한다. 앞서 동기화 문제를 해결하는데 일등 공신이었던 cmpxchg라는 명령어를 생각해보자. n개의 CPU가 있다고 가정한다면 n개의 CPU에서 동시에 cmpxchg가 실행될 수 있다. 결국 문제를 해결하기 위해서는 cmpxchg라는 명령어가 n개의 CPU가 아닌 한번에 하나의 CPU에서만 실행될 수 있도록 만들어주는 메커니즘이 필요하다. x86/64 계열의 CPU에서는 lock이라는 접두어가 이런 역할을 한다. lock cmpxchg를 하면 해당 시점에는 한 녀석만 메모리에 접근하도록 만들어준다. 재미있는 사실은 동시성에서 비롯된 동기화 문제를 해결하기 위해서는 결국 동시에 실행되지 않는 무엇인가가 필요하다는 점이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;컨텍스트, 컨텍스트, 또 컨텍스트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;스레드 이야기에는 필연적으로 다양한 종류의 컨텍스트라는 말이 등장한다. 의미는 다른데 이를 표현하는 말은 모두 컨텍스트이기 때문에 처음 접하는 개발자는 상당히 혼란스러울 수 있다. 여기에서 잠깐 이런 컨텍스트라는 말의 정체에 대해서 알아보고 넘어가도록 하자. 컨텍스트를 우리 말로 번역하면 문맥이라는 말이 된다. 문맥이란 무엇인가? 우리가 일상생활에서 접하게 되는 문맥이라는 말의 의미는 다음과 같은 간단한 대화 속에서 쉽게 파악할 수 있다.&lt;/p&gt;
&lt;p&gt;영희: 너 밥 먹었니?&lt;/p&gt;
&lt;p&gt;철수: 응. 먹었어.&lt;/p&gt;
&lt;p&gt;일반적으로 구두 표현은 상황을 통해 유추할 수 있는 정보는 대부분 삭제된다. 우리는 철수의 대답에는 포함되지 않았지만 상황을 통해 ‘먹었어’라는 말을 철수가 밥을 먹었다라는 사실로 자연스럽게 확장시킬 수 있다. 이렇게 유추의 근거를 제공하는 말이 놓인 상황을 우리는 문맥이라고 부른다. 프로그래밍에서 말하는 것 또한 이와 별반 다르지 않다. 일반적인 프로그래밍 환경에서 말하는 컨텍스트라는 말은 해당 코드가 바인딩되어 실행되는 환경을 일컫는다. 물론 이렇게 이야기를 하더라도 바인딩되어 실행되는 환경이라는 것이 무엇인지 감이 잡히지 않는다. 이를 좀 더 구체적으로 살펴보기 위해서 &amp;#x3C;리스트 4&gt;의 코드를 살펴보자.&lt;/p&gt;
&lt;p&gt;리스트 4 콜백 함수를 사용한 프로그램&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;list GlobalList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    GlobalList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetTickCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;RegisterCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;GlobalList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
           cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; GlobalList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;front&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
           GlobalList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop_front&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;리스트 4&gt;의 코드에서 RegisterCallback 함수는 입력으로 들어간 콜백 함수가 랜덤 주기로 호출되도록 등록하는 함수다. 만약 RegisterCallback 함수 설명에 ‘입력으로 들어온 콜백 함수는 등록한 스레드 컨텍스트에서 호출된다’라는 말이 있다면 위 코드는 아무런 문제 없이 동작한다. 하지만 이와는 다르게 ‘입력으로 들어온 콜백 함수는 시스템 스레드 컨텍스트에서 호출된다’는 말이 있다면 위 코드는 잘못 동작한다. 이유는 Callback이 호출되는 스레드와 main이 실행되는 스레드가 다르기 때문이다. 서로 다른 스레드가 GlobalList를 동시에 접근함에도 동기화 처리가 되어 있지 않기 때문에 최악의 경우에는 프로그램 크래시가 발생한다. 이와 같이 Callback이라는 코드가 바인딩되어 실행되는 스레드를 우리는 컨텍스트라는 말로 표현한다.&lt;/p&gt;
&lt;p&gt;여기서 더불어 살펴보아야 할 표현이 하나 있다. 바로 “임의의 스레드 컨텍스트”라는 표현이다. 대부분의 콜백 함수 설명에는 등록한 콜백 함수는 임의의 스레드 컨텍스트에서 호출된다라는 말이 있기 때문이다. 여기서 “임의의”라는 말은 정해지지 않았음을 나타내는 말이다. 그러니 “임의의 스레드 컨텍스트”라는 말은 달리 표현하면 “정해지지 않은 스레드 컨텍스트”가 된다. 그렇다면 도대체 정해지지 않은 스레드 컨텍스트라는 표현이 개발자에게 해주고 싶은 속내는 무엇이었을까? “정해지지 않았음”이 프로그래머에게 해주고 싶은 진짜 이야기는 이 말이다. “네 멋대로 특정 스레드 컨텍스트에서 호출된다고 생각하지 말아라. 이 코드는 네가 생각지도 못한 스레드 컨텍스트에서도 호출될 수 있다.”&lt;/p&gt;
&lt;p&gt;“해당 콜백 함수는 임의의 스레드 컨텍스트에서 호출된다”는 문장을 보는 순간 여러분이 베스트 개발자라면 다음과 같은 생각을 반드시 해야 한다. “아, 이 함수가 실행되는 스레드는 정해지지 않았구나. 콜백 함수가 전역 데이터에 접근하는 경우에는 반드시 동기화 처리를 해줘야 하겠구나.” 반대로 “해당 콜백 함수는 콜백을 등록한 스레드와 같은 컨텍스트에서 호출된다”는 문장을 보게 되면 역으로 콜백과 등록한 스레드에서만 사용하는 공유 데이터가 있다면 동기화 처리를 생략해서 최적화 작업을 할 수 있겠다라는 생각을 하는 것이 정석이다.&lt;/p&gt;
&lt;p&gt;지금까지 특정 함수가 수행되는 컨텍스트에 대해서 알아보았다. 이와 마찬가지로 특정 스레드도 해당 스레드가 수행되는 컨텍스트가 존재한다. 바로 프로세스다. 앞서 Windows에서 스레드의 개념을 설명할 때 특정 프로세스 내에서 수행되는 실행 흐름이라고 표현했다. 따라서 스레드가 동작하기 위해서는 반드시 어떤 프로세스 컨텍스트에서 동작할지를 알아야 한다는 말이다. 일반적으로 프로그램에서 생성하는 모든 스레드는 그 코드를 수행하는 스레드가 참조하는 프로세스 컨텍스트로 생성된다. 하지만 커널 모드 코드들의 경우에는 이 참조하는 프로세스 컨텍스트를 임의의 변경할 수 있다. 따라서 코드가 호출되는 스레드 컨텍스트와 마찬가지로 스레드가 수행되는 프로세스 컨텍스트도 변경될 수 있음을 알아야겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: 광클릭 개론]]></title><description><![CDATA[광클릭이란 말 그대로 빛 광자에 클릭을 붙인 말로 빛처럼 빠르게 클릭을 한다는 의미입니다. 그렇다면 게임에서 빛처럼 빠르게 클릭해서 어떤 이득이 있는 것일까요? 이득이 있으니까 그런 일들을 하는 거겠죠. 바로 FPS…]]></description><link>https://jiniya.net/wp/archives/5740</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5740</guid><pubDate>Mon, 12 Mar 2012 23:58:01 GMT</pubDate><content:encoded>&lt;p&gt;광클릭이란 말 그대로 빛 광자에 클릭을 붙인 말로 빛처럼 빠르게 클릭을 한다는 의미입니다. 그렇다면 게임에서 빛처럼 빠르게 클릭해서 어떤 이득이 있는 것일까요? 이득이 있으니까 그런 일들을 하는 거겠죠. 바로 FPS 게임에서 이득을 볼 수 있습니다. 모든 FPS 게임에 통용되는 것은 아니지만 일부 FPS 게임의 경우 클릭 속도가 일정 간격 아래로 떨어질 경우 총기 반동이 왜곡되는 구간이 생깁니다. 동일한 지점에 클릭을 두 번 할 때에는 첫 번째 샷과 두 번째 샷이 총기 반동으로 인해서 다른 곳에 각각 발사됩니다. 하지만 광클릭을 사용해서 굉장히 빠르게 같은 지점에 두 번 클릭을 하게되면 두 샷 모두 동일한 지점에 발사되는 놀라운 현상을 경험할 수 있죠. 이말은 즉, 헤드샷이 아니더라도 한 방에 보내는 것이 가능해 진다는 겁니다. 속도 조절에 따라서 한 지점에 세 방, 네 방 등등을 한 큐에 발사할 수 있습니다. 굉장하죠? 조준이 아예 되지 않는 초보 게이머의 경우에는 별 효과가 없지만 중수 정도만 되더라도 광클릭을 사용하면 굉장한 실력 상승의 효과를 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;다음으론 이 광클릭의 진화 역사를 좀 살펴보겠습니다. 초창기 광클릭은 대부분 소프트웨어 매크로 형태였습니다. 매크로를 이용해서 특정 키나 마우스의 특정 버튼에 더블 클릭 내지는 특수한 빠른 입력의 매크로를 작성해서 사용하는 형태였죠. 하지만 아시겠지만 이런 소프트웨어 매크로 방식의 경우에는 한계가 있습니다. 탐지하기 쉽고 무력화 되기는 더 쉽죠. 이후 등장한 광클릭은 마우스 자체를 개조한 형태였습니다. 기계적으로 사용자들이 개조한 것도 있고 중국 등지에서 만든 개조 마우스가 유행했죠. 기계적인 방식의 경우에는 만들어진 형태를 소프트웨어 적으로 가공하는 것이 불가능한 경우가 대부분입니다. 하지만 소프트웨어 방식이 아니라 이 시기부터 사실상 광클릭 탐지가 불가능해지기 시작했습니다. 이후에 거대한 변화가 닥쳐옵니다. 게이밍 마우스라는 이름으로 메이저 벤더들에서 매크로 기능이 탑재된 마우스를 내놓기 시작한 것이죠. 로지텍이 대표적입니다. 로지텍도 초창기 게이밍 마우스의 경우 소프트웨어 방식으로 에뮬레이션하는 형태였으나 최근에 나오는 시리즈 상위 버전의 경우 놀라운 기능이 탑재됩니다. 바로 마우스 하드웨어 내부에 별도 메모리를 두고 해당 메모리에 매크로를 입력했다가 사용하는 기능이죠. 로지텍 소프트웨어를 사용해서 매크로를 마우스 내부 메모리에 입력 시킨 다음에 다른 컴퓨터에 들고가도 바로 사용이 가능하다는 이야깁니다. 추가적인 드라이버나 소프트웨어 설치 없이 말이죠. 기계식 개조의 조악함을 넘어섬과 동시에 소프트웨어 방식의 손쉬운 탐지를 회피한 것이죠. 이 때 부터 게이머들 사이에서는 이러한 마우스의 사용이 우후죽순 늘어납니다.&lt;/p&gt;
&lt;p&gt;이 문제가 심각한 사실은 분명한 부정행위 임에도 메이저 벤더들이 게이밍 마우스라는 이름으로 제품을 출시하고 해당 제품들이 게임에서 차단되지 않기 때문에 해킹이라는 사실을 별로 인식하지 않는 문제가 발생했다는 점 입니다. 일부 사용자의 경우 매크로 게이밍 마우스를 사용해서 게임 대회에 참가하는 것 또한 문제될 것이 없다고 생각한다는 점에서 이러한 상황의 심각성을 엿볼 수 있습니다. 더 안타까운 사실은 게이머들 사이에서 실력으로 게임을 하는 시대는 지나갔다. 이제는 돈으로 게임을 하는 시대라는 인식이 퍼지고 있다는 사실입니다(로지텍 게이밍 마우스 상위 기종은 상당히 고가입니다). 뭔가 현실 세계의 불균형이 온라인 세계로까지 이어지는 것 같지 않습니까? 이러한 공정하지 못한 현실을 바로잡기 위해서 최근 몇 달 동안 저희 XIGNCODE(라고 쓰고 싸인코드라고 읽습니다) 개발팀에서는 광클릭에 대한 연구를 진행했습니다. 그 결과 이 이슈가 제기되었던 게임 내에서 상당 수의 광클릭 유저를 몰아냄과 동시에 광클릭 사용이 부정행위라는 인식을 심어주고 있습니다. 물론 아직 끝은 아니죠. 이 이슈를 발본색원하기 위해서 지금도 새로운 아이디어, 알고리즘, 그리고 대안을 연구하고 있습니다. 이어지는 내용은 그간 저희가 겪은 시행 착오와 생각들을 정리해본 내용입니다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;우리의 초기 접근은 하드웨어에 대한 탐지였습니다. 사용자들이 주로 사용하는 메이저 벤더의 게이밍 마우스가 한정적이기 때문에 해당 벤더의 마우스 내부에 탑재된 메모리의 내용물을 읽어서 차단할 수 있지 않을까란 생각이었죠. 참 재기 발랄한 생각이 아닐 수 없습니다. 그래서 저희는 불철주야 게이밍 마우스를 분석했습니다. 당연히 로지텍 마우스가 일순위였죠. 그런데 안타까운 사실이 벌어졌습니다. 저희 예상과는 달리 로지텍 마우스 소프트웨어 자체에서도 게이밍 마우스에 담겨진 매크로 내용을 읽어오는 부분이 없었기 때문이었죠. 로지텍 전용 소프트웨어 조차도 마우스에 쓰는 기능은 있어도 읽는 기능은 없다는 이야기입니다.&lt;/p&gt;
&lt;p&gt;어쨌든 그래도 아쉬운대로 저희는 해당 소프트웨어의 기록하는 부분만 리버싱을 한 다음 샘플 프로그램을 만들어서 똑같이 기록해 봤습니다. 그랬더니 놀라운 일이 발생했습니다. 해당 로지텍 마우스는 영원히 매크로를 기록할 수 없는 불능 상태가 돼버렸지요. ㅋㅋ 개발팀에서는 이 세상 모든 게이밍 마우스를 매크로 불능으로 만드는 것도 나쁘지 않겠다고 생각했지만 광클릭 외의 목적으로 그 비싼 마우스를 구매하신 분들에게는 큰일날 소리라는 생각과 함께 이 방식에 대한 연구를 중단했습니다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;이후 저희는 속도에 집착했습니다. 광클릭이란 말에서도 알 수 있듯이 이 문제의 핵심 쟁점은 속도에 있다고 생각한 것이죠. 당연히 매크로 마우스의 클릭 속도는 인간이 범접할 수 없는 영역의 속도로 설정할 것이란 생각이었습니다. 사람이 할 수 있는 속도라면 그 속도로 설정하진 않을 것이란 생각이었죠. 하지만 이런 생각을 토대로 속도를 측정하는 것 또한 쉽지는 않습니다. 매크로 설정을 통한 자동 입력되는 마우스 클릭도 있지만 거기에 더불어 사용자가 해당 매크로나 일반 버튼을 통해서 입력 시키는 이벤트도 존재하기 때문입니다. 즉, 우리가 구하려고 하는 매크로 입력의 속도만 차용할 수는 없다는 점이죠. 노이즈가 섞여 있다는 이야기 입니다. 더불어 이 문제를 좀 더 어렵게 만드는 또 한 가지 요인은 FPS 게임의 경우에 항상 클릭 이벤트를 강요하지는 않는다는 점입니다. 대부분의 시간을 적을 찾는데에 보내고 실제로 전투 중 발발하는 클릭 이벤트는 그렇게 많지 않습니다. 이렇게 적을 서치하는 시간 또한 같이 계산해버리면 엄청난 노이즈가 됩니다.&lt;/p&gt;
&lt;p&gt;이렇게나 복잡하고 어려운 문제를 똑똑한 XIGNCODE 개발 팀에서 아주 심플하게 모델링 해서 놀랍게도 노이즈를 상당수 줄이는데 성공했습니다. 그리곤 그 결과를 측정해 보았죠. 참고로 XIGNCODE 개발팀에는 정말 똑똑한 사람들이 많습니다. 진짜로요 ㅋㅋ~~&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 619px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_광클릭_개론.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/eb15879c06badfc741df34a111049d97/80833/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAp0AAAKdAGYYj8ZAAABf0lEQVR42mNgAIKcnBxFZ2dnYSCTw1hSkktGRoaTVCwuLs4N1M8OMo8hNzdX2d7eXqK+vp6lfv9+FiDNBsMzZ85kBWEYG5d4aGgo2GCwgcVAF9p4eIj+d3Xl/qKhIbnq/3/mM2fOgDWAaGQME0OW+///P0t8fDwH3ECQl419fET+a2gIf5OUlFuF5AJi8H6grzAMtHR1FfsvJSX8QUtL6J2xMX8o0JVkG5iWlibn5Osr/hFo4F2gYU/V1ETsgYquIIXlKjz4DNBQFAOTsrOlpunqKv2XkREC8f8rKYntByqo//+fCRSeIAwMJyZkPkwMihlBlsIN9K+vF5ippKS7lptbDBjl7NPk5AT3SkjIr5KQEAVaJNgvLy8AYs9WVBRfpaICoYH8RUCLQfRaIG0PVANNOgwMoOTiGhPDbWxszBUdHS3pCoztNHd3ycmGhlKlLi5SJcAk1WdsLNlnY6PUoq8vXW9vrzJBR0e8ycVFda6BgWiTl5emh5kZX2xsrBwAyYfurbmQWfIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;             md 0&apos; title=&apos;&apos; src=&apos;/static/eb15879c06badfc741df34a111049d97/80833/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_0.png&apos; srcset=&apos;/static/eb15879c06badfc741df34a111049d97/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_0.png 190w,
/static/eb15879c06badfc741df34a111049d97/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_0.png 380w,
/static/eb15879c06badfc741df34a111049d97/80833/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_0.png 619w&apos; sizes=&apos;(max-width: 619px) 100vw, 619px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
이 그래프는 사용자들의 평균 입력 속도를 나타냅니다. 앞에서 설명한 것처럼 복잡한 연산 후에 노이즈를 제거하고 뭔가 의미있는 값들로 구한 평균입니다. 가로축은 속도를 ms단위로 세로는 해당 구간에 포함된 사용자 숫자를 의미합니다. 알흠답게도 200ms를 기점으로 정규 분포를 보여주고 있습니다. 저희 내부 테스트에 의하면 보통 사람이 생각없이 더블 클릭을 하면 100-200ms 정도가 나오는 것으로 나타났습니다. 저희는 이 데이터 구간에서 100ms 아래에 있는 사용자들이 광클릭을 사용하고 있는 것이 아닌가라는 추론을 하기 시작했습니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 621px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_광클릭_개론.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f196fee2ce687148b5b7aa2c47532452/41b39/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAApNAAAKTQG1k+TGAAABoUlEQVR42pWSMWvCQBTHz2g1RqO1MSZnrQEbEJyEIDgUDnQwQ3ETIg6Cg4oQKF0KLhm6dO0o/QYZSunULV+gn6DQsUPbobX9ANf3grYObWkDP97LvXf/XP7vCIFnPB7nLcvKQioaAMQ4ssr/CyGu66qNRkPxPC+G3Fcq2TtdV89tO7Fe+wuapqVCwclksttutxW/14tySvOv5XLu4fBQ4oah3y4WWz7nUQ4EQRBbx+8EKaVSKDidTgtHlkWXsqy8GMY24TyCPDKWfjNN1eNcQJFNfhW0PS9zpeu1J0mi+B5AEUHRZbGoPFerMua45vt+9Cc+BQeum5mXy5TXanHcCF8T1gSMxd5TKQ0j1tCWTTZ7QSr5NRTwEPwR+MqvDQQ+HIq8UNC458Xx99dgLTwd9CGfJ5zNZumDel3FsTebzWSpVEoahhHmGAlj4khR5BtR3PNVVb8Er324BReZzM4J3IizXC47RjFVTYeCPTh6t9uVIRX6/X6ewTBQbDAYoKeRkeMUe2AH9sxbrV2fkPSpbe9fEyIddTr0mLG8bZoJx3G0D0et2ZCFeK15AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;             md 1&apos; title=&apos;&apos; src=&apos;/static/f196fee2ce687148b5b7aa2c47532452/41b39/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_1.png&apos; srcset=&apos;/static/f196fee2ce687148b5b7aa2c47532452/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_1.png 190w,
/static/f196fee2ce687148b5b7aa2c47532452/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_1.png 380w,
/static/f196fee2ce687148b5b7aa2c47532452/41b39/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_1.png 621w&apos; sizes=&apos;(max-width: 621px) 100vw, 621px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
평균만으론 뭔가 심심해서 표준 편차를 구해봤습니다. 매크로 입력을 사용한다면 당연히 표준 편차가 낮을 거라는 생각이었죠. 이 그래프도 앞선 그래프와 마찬가지로 x축은 속도를 y축은 사용자 숫자를 나타냅니다. 저희는 앞쪽 데이터 0-20ms 정도의 편차를 가지는 사용자들을 광클릭 사용자라고 판단하고 있습니다. 사람이 클릭 이벤트를 발생 시켰다면 이렇게 편차가 낮기는 쉽지 않을테니까 말입니다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 619px; margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_광클릭_개론.md_2.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f7038487ccd5a8e4cd0da1aa6005bed5/80833/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAzDAAAMwwFTdG0jAAAB4UlEQVR42nWSv24TQRDG5/bOd/5zviQ2lmVhdDKyFHGNi1Miy80iRTZU7q7AMqIJjf0ASKa4B6CDNBFtinCiiBSJlhdImSpNJDqUiAIlghCH5ZvlzmBEik87Ozv725mdoTiOrcFgUCGiHGRDTqrbbMcnyt8akySJ2el0VgEWSimheM3sKDK1pLSWxD4kopXdUcogfijCoWQgkdBQ7I/CMMc69f3851rNzXReqXhn1Wr5U7NZ4DOO+YgHkt8PCA2cTqdVBu6i5Ax00m47X9bWVi6KxcY3x2l9t+3gq20/gN1mH58xlGPTbHUyGjiZTPwMqFOv10u4eP+HZcm5EE+UENtYp1dCjODrXRYKdzlTFQT237AFcDabNcIwXMHGQCbrP4V4fmMYb26I3kGH0B6AL69N8xFgTYXSk39AS0Ducntz07si2gbo/dwwDgDZh17PiV5cE21xVlzi/0Dcg2UguvR0Y6OKiw+VaW6pcnld5fP3lOvWVKNRPI4iW2V/hYnQXUVHF1PxxzbS8SF6hj98RVT6QOS9bbXqiedVdojcOAzvxIAGmLF+v19KZy3X6/XKmT0cDhe2lHJVA2Nk8Rh0SWRFUrr4Ux5yE+W4HBigAaPRyO92u4XMn8ZYKVDb4/G49AtKw9unmeCoXgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;             md 2&apos; title=&apos;&apos; src=&apos;/static/f7038487ccd5a8e4cd0da1aa6005bed5/80833/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_2.png&apos; srcset=&apos;/static/f7038487ccd5a8e4cd0da1aa6005bed5/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_2.png 190w,
/static/f7038487ccd5a8e4cd0da1aa6005bed5/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_2.png 380w,
/static/f7038487ccd5a8e4cd0da1aa6005bed5/80833/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_2.png 619w&apos; sizes=&apos;(max-width: 619px) 100vw, 619px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
두 데이터에 대한 상관 관계입니다. 가로축이 평균, 세로 축이 표준편차입니다. 뭔가 소행성같은 느낌이 나죠. 저희는 이 소행성에서 떨어져 나온 분진들 중에서도 y축값이 낮고 x축의 값도 낮은 데이터에 집중하고 있습니다. 평균 50ms, 표준 편차 50ms를 설정할 경우에 전체 사용자의 1% 정도가 나왔습니다. 그리고 더욱 놀라운 사실은 그 데이터에 포함된 사용자들이 기존 매크로 검출률이 높은 사용자였다는 점이죠. 이쯤되면 감 잡으셨죠.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;물론 광클릭외에도 게이밍 마우스를 통해서 얻을 수 있는 이득은 무궁무진합니다. 인간의 입력을 기계가 대체한다는 점만을 놓고 볼 때 게임 상에서 허용되지 않는 방식을 통한 모든 종류의 매크로 입력은 사실상 부정행위입니다. XIGNCODE 개발팀에서는 이러한 다양한 매크로 방식에 대해서도 자동적으로 식별할 수 있는 새로운 방법을 연구하고 있습니다.&lt;/p&gt;
&lt;p&gt;지금은 일정 구간의 모든 입력을 레코딩한 다음 해당 구간에서 공통적으로 반복되는 가장 긴 부분 집합을 찾는 작업을 하고 있습니다. 물론 이 방법의 가장 큰 취약점은 타이밍 오차인데 그 부분만 근사할 수 있게 만든다면 굉장히 강력한 방법이 될 거라고 생각합니다. 하지만 이 작업의 가장 큰 걸림돌은 잘 아시겠지만 이 내용이 말로하면 쉽지만 동작하는 코드로 만들어 내기에는 그렇게 녹록한 작업이 아니라는 점이죠. 어쨌든 XIGNCODE 개발팀은 이 세상 모든 하드웨어 입력 방식의 매크로를 원천 차단하겠다는 신념 하나로 오늘도 불철주야 불꽃 코딩을 하고 있습니다. ㅋㅋㅋ~&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;어때요? 잘 보셨죠. XIGNCODE 개발팀은 단순히 해킹툴을 잡은 일만 하는 건 아니라는 거, 게임에 대한 모든 부정 행위에 대해서 깊이 있는 생각을 하고 그 대안을 찾아준다는거 꼭 기억하세요. 뉴요커 게임 개발자라면 당연히 보안 제품은 XIGNCODE를 선택한다는 것도 잊지 마시구욥 흐흐~~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_광클릭_개론.md_3.png&apos; data-alt=&apos;probably는 빼도 된다는거, 까먹지 마세요!!! ㅋ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 636px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/53c726b9d892cee99c11f60af88bb9dc/44bb2/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 16.315789473684212%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAtUlEQVR42gXBuw6CMBQAUH7IwahAvFLsLS1QhSYFLGkkPmJ8YNTFn3HSQeOgi3/oOY5LPeA+SQGnEOTReK3ppsJtLVqbnOasXbDDkm1n0WGRXlbiuGT7hrcWbN2BidMjroe+h0OIIZwSkkdEJYHKaKmELYqdUWuT2kw2KmkMmooZjVWOWnbDxHHDPkSDkXBD6RMJLA+EHgsd8wL31/Pz+3u8P7f7q1yVvJJxrWQ94UWKitOM/gFzzTheOPmtOAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;probably는 빼도 된다는거, 까먹지 마세요!!! ㅋ~&apos; title=&apos;&apos; src=&apos;/static/53c726b9d892cee99c11f60af88bb9dc/44bb2/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_3.png&apos; srcset=&apos;/static/53c726b9d892cee99c11f60af88bb9dc/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_3.png 190w,
/static/53c726b9d892cee99c11f60af88bb9dc/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_3.png 380w,
/static/53c726b9d892cee99c11f60af88bb9dc/44bb2/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_%EA%B4%91%ED%81%B4%EB%A6%AD_%EA%B0%9C%EB%A1%A0.md_3.png 636w&apos; sizes=&apos;(max-width: 636px) 100vw, 636px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;probably는 빼도 된다는거, 까먹지 마세요!!! ㅋ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[개발자에게 독이되는 말, 말, 말, …]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5735</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5735</guid><pubDate>Fri, 09 Mar 2012 23:58:00 GMT</pubDate><content:encoded>&lt;p&gt;인간은 말을 통해서 의사 소통을 한다. 서로 의견을 교환하고, 자신의 생각을 표현하고, 설득을 하고. 사랑을 표현한다. 그래서 회사 생활에도 말은 참 중요하다. 오죽하면 말 잘하는 사람이 성공한다는 이야기도 있겠는가? 그런 말 중에도 신입 개발자들에게 참 독이 되는 말이 있다. 독이 되는 말임에도 하나같이 신기하게도 신입 개발자들은 이 말을 입에 달고 사는 것 같다. 새해에는 이런 말을 하지 않는 신입 개발자들이 좀 늘었으면 하는 바램이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0. 안 됩니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;무슨 이야기만 하면 찾아보지도 않고 안 된다는 답변을 먼저 해버리는 개발자들이 있다. 사실 좀 어처구니 없는 대답이긴 하다. 왜냐하면 회사에서 높은 비용을 지불해가면서 똑똑한 개발자를 쓰는 유일한 이유는 남들이 못하는 것을 하기 위해서지, 남들도 다하는걸 하기 위해서는 아니기 때문이다. 사사건건 하는 것마다 안 된다는 이야기를 한다면 과연 어떤 회사가 당신에게 높은 비용을 지불하겠는가?&lt;/p&gt;
&lt;p&gt;더 안타까운 사실은 개발자에게 주어지는 요구 사항 중에 안 되는 것은 사실 거의 없다는 점이다. 나도 사회 초년생 시절에는 회사에서나 커뮤니티에서 답변을 달 때에 ‘안 된다’라는 이야기를 자주 했다. 하지만 지나고 보니 안 된다고 생각했던 건 그 당시 지식이 부족했거나 아이디어가 없었던 경우가 대부분이었다. 논리적으로 안 되는 이유를 증명할 수 있는 이야기가 아니라면 가급적 안 된다라는 말을 하는 것은 피하는 것이 좋다. 차라리 정직하게 자신이 아는 한도 내에서는 방법이 없는 것 같다고 말하고, 긍정적으로 방법을 찾아 보자고 이야기 하는 것이 좋은 방법이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1. 팀장님이 작성한 코드예요.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;대다수 신입 개발자들이 회사에서 처음 맡아서 하게 되는 일은 기존 코드의 유지 보수 작업이다. 선임들의 코드 뭉치를 한 덩이 받아 들고는 시작하는 경우가 태반이라는 말이다. 상황이 이렇다 보니 자신이 만든 코드가 아니라는 알량한 생각에 문제가 생기거나 기존 코드에 잘못을 지적 받으면 자연스럽게 방어기제가 발동한다. 책임 회피가 나오는 것이다. “팀장님이 작성한 코드예요”, “그 부분은 원래 이렇게 돼 있었습니다”라는 말들은 이러한 방어기제의 대표적인 형태다. 하지만 안타깝게도 이 답변은 질문에 대한 0점짜리 대답이다. 왜냐하면 이 답변은 지적 받은 문제가 제대로 된 지적인지 아닌지에 대한 생각도 없고, 또 그것을 어떻게 고쳐야 하는지에 대한 생각은 더더욱 없으며, 일말의 책임감이라고는 하나도 찾아볼 수 없는 아주 비겁한 답변이기 때문이다.&lt;/p&gt;
&lt;p&gt;여러분이 어떤 코드 뭉치를 받았건 그것을 받아 들고 해당 코드를 관리하는 순간부터 그 코드는 여러분의 것이고, 직접 책임져야 하는 것들이다. 그 코드를 누가 만들었는지, 기존 코드가 처음부터 문제가 있었는지 없었는지는 하나도 중요하지 않다. 여러분이 알아야 할 것은 지금 문제가 있는지, 문제가 있다면 그것을 고칠 수 있는지 없는지가 중요하다.&lt;/p&gt;
&lt;p&gt;많은 신입 개발자들이 선임의 코드를 받으면서 그 코드는 완전 무결할 것이라는 막연한 환상을 가진다. 하지만 그걸 만든 선임 개발자도 나름의 사정이 있었고, 일정에 쫓겼고, 더욱이 신은 아니다. 그는 자신의 아내가 출산을 하는 날에도 야근을 하면서 해당 코드를 작성해야 했을 수도 있고, 어처구니 없는 일정에 쫓겨가면서 급하게 코드를 만들었을지도 모른다. 상황이 이런데도 신입 개발자들은 코드가 돌아간다면 가급적 고치지 않으려는 습성이 있다. 일종의 관성이라고 할 수도 있는 이 문제는 고치다가 문제가 발생할지도 모른다는 두려움이 그 원인이다. 하지만 반드시 기억해야 할 사실은 항상 새로운 것들은 기존의 것들을 파괴하는 데서 출발한다는 점이다. 기존의 것을 변경하지 않고는 절대로 새로운 것이 탄생할 수 없다. 맡은 코드에 대해서 잘 돌아가는 것 이상을 생각할 필요가 있다. 그게 처음부터 만들지 않은 사람이 해야 할 일이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2. 잘되는데요.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;신입 개발자들의 코드를 보다가 문제를 지적하면 흔히 듣게 되는 대답이다. 물론 똑똑한 개발자라면 기초적인 실수는 하지 않았을 것이기 때문에 이런 실수는 아주 드물게 나타나는 현상에 대한 것이거나 이론적으로는 가능하지만 현실 세계에서 재현은 되지 않는 문제인 경우가 많다. 특히 이번 시간에 언급할 멀티 스레드 문제들도 이 범주에 속한다. 재현이 쉽지 않기 때문에 자신의 코드가 잘 동작한다는 착각에 빠지는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 코드가 잘 돌아간다고 모두 제대로 동작하는 것은 아니다. 완전한 논리로 설명할 수 없다면 불충분한 코드다. 언제든지 안될 수 있다는 말이다. 잘못을 정확하게 판단하기 위해서는 지금까지 잘됐는지 안됐는지가 아니라 그 코드의 논리가 제대로 된 논리인지 아닌지를 해명하는 것이 우선이다.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 게임 보안: VIP 해킹툴 대처 방안 A to Z…]]></title><description><![CDATA[블로그가 진짜 말그대로 거의 개점 휴업 상태였네요. 바쁘다는 말을 별로 좋아하진 않는데 정말 바빴습니다. 제 머릿속에서 날 것 그대로 방출된 무수한 버그들, 겹겹이 겹친 CBT 일정, 그리고 각종 요구 사항, 이슈 사항, 거기에다 VIP…]]></description><link>https://jiniya.net/wp/archives/5657</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5657</guid><pubDate>Wed, 29 Feb 2012 23:57:59 GMT</pubDate><content:encoded>&lt;p&gt;블로그가 진짜 말그대로 거의 개점 휴업 상태였네요. 바쁘다는 말을 별로 좋아하진 않는데 정말 바빴습니다. 제 머릿속에서 날 것 그대로 방출된 무수한 버그들, 겹겹이 겹친 CBT 일정, 그리고 각종 요구 사항, 이슈 사항, 거기에다 VIP 핵툴까지… 헉. 이런 것들에 파묻혀서 정말 숨도 못쉬다가 이제 조금 호흡을 가다듬고 있습니다. 후훗~ 간만에 XIGNCODE(라고 쓰고 싸인코드라고 읽습니다) 깔때기나 좀 댈겸 VIP 핵툴에 대한 이야기를 좀 해볼까 합니다. ㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./게임_보안_VIP_해킹툴_대처_방안_A_to_Z.md_0.png&apos; data-alt=&apos;가장 최근에 등장한 모 해킹툴 그룹의 GG 제스쳐.&lt;br&gt;&lt;br&gt;해킹툴 제작자만 이런 사실을 안다는게 안타깝습니다 ㅋ~&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 584px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1e4ad12424a94ff748fb79d5d30c32e7/f5818/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_VIP_%ED%95%B4%ED%82%B9%ED%88%B4_%EB%8C%80%EC%B2%98_%EB%B0%A9%EC%95%88_A_to_Z.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 26.31578947368421%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABDUlEQVR42hWNW3KCMAAAOYyKaKSAESU8FBIS3hKCpmKpWh9t73+B0pmdnf1bJREFbS65vJXdq+5/q/4nk/eqe1TnZ3l6YP5JxBU3V0gOVlgDN5ttqGYTFYZjM1B2+T4sT5T3rL3E/IPwMxV9kEmHtl4qvfSIqHCYQMkRscPcSTQ7nsJoYm3Hhq8EaR0W0sZ70091l5lBBneV7uUzZ5iwgakdT2A0tkJ1Rf57OTy3I8Mf6a6Cy4NLa8ujqrVTVzFAubZmwC2sUCzczPArI6iAk8zXZG6HYEMWDgVrrC23kzekREUUlxJnTXPiXy9+/25vz3rw+6XmkjYyFl3WdolPmYGoiTD0qYUi3Q4A9P4AdsNPBpMDCagAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;가장 최근에 등장한 모 해킹툴 그룹의 GG 제스쳐.&lt;br&gt;&lt;br&gt;해킹툴 제작자만 이런 사실을 안다는게 안타깝습니다 ㅋ~&apos; title=&apos;&apos; src=&apos;/static/1e4ad12424a94ff748fb79d5d30c32e7/f5818/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_VIP_%ED%95%B4%ED%82%B9%ED%88%B4_%EB%8C%80%EC%B2%98_%EB%B0%A9%EC%95%88_A_to_Z.md_0.png&apos; srcset=&apos;/static/1e4ad12424a94ff748fb79d5d30c32e7/08678/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_VIP_%ED%95%B4%ED%82%B9%ED%88%B4_%EB%8C%80%EC%B2%98_%EB%B0%A9%EC%95%88_A_to_Z.md_0.png 190w,
/static/1e4ad12424a94ff748fb79d5d30c32e7/2edd7/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_VIP_%ED%95%B4%ED%82%B9%ED%88%B4_%EB%8C%80%EC%B2%98_%EB%B0%A9%EC%95%88_A_to_Z.md_0.png 380w,
/static/1e4ad12424a94ff748fb79d5d30c32e7/f5818/%EA%B2%8C%EC%9E%84_%EB%B3%B4%EC%95%88_VIP_%ED%95%B4%ED%82%B9%ED%88%B4_%EB%8C%80%EC%B2%98_%EB%B0%A9%EC%95%88_A_to_Z.md_0.png 584w&apos; sizes=&apos;(max-width: 584px) 100vw, 584px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;가장 최근에 등장한 모 해킹툴 그룹의 GG 제스쳐.&lt;br&gt;&lt;br&gt;해킹툴 제작자만 이런 사실을 안다는게 안타깝습니다 ㅋ~&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;VIP 핵툴이란 유료 핵툴이라고 생각하면 됩니다. 근데 그냥 유료 핵툴은 아니고 해킹툴 제작 그룹에서 퀄리티를 보장하는 해킹툴이라는 게 특징이죠. 즉 비싼 돈을 받는 대신에 QA를 해주는 핵툴이라고 생각하면 되겠습니다. 그래서 흔히들 보안 업체가 계약을 할 때에 최대 몇 시간 내에 대응을 해줄 것인지에 대한 보장을 하는데 이런 VIP 해킹툴도 사용자들에게 그런 조항을 달아 줍니다. 예를들면 72시간 동안 해킹툴이 다운될 경우에는 보너스 기간을 준다거나 하는 식이죠. 즉, 쉽게 생각하면 목숨걸로 핵툴 만드는 애들이 판매하는 핵툴이 VIP라고 생각하면 됩니다.&lt;/p&gt;
&lt;p&gt;그러다보니 자연스럽게 VIP 핵툴의 경우 대응이 까다로운 점이 있습니다. 사실 대응이라고 하기도 좀 힘든 실정입니다. 대부분의 경우 VIP 핵툴은 게임 패치와 동시에 업데이트 돼서 거의 항상 오픈된 상태를 유지하기 때문입니다. 어쨌든 요번 글에서는 이런 VIP 해킹툴을 대응하면서 느꼈던 점, 팁(?!)들을 몇 가지 써볼까 합니다.&lt;/p&gt;
&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;테크닉, 기술. 사실 가장 중요한 요소입니다. 이게 안되면 이후에 진행하는 모든 것들이 애초에 불가능하기 때문입니다. 따라서 게임 보안 제품을 만든다면 반드시 해커보다는 똑똑한 개발자와 분석가를 뽑아야 합니다. 그게 안되면 싸움 자체가 성립이 안되기 때문입니다.&lt;/p&gt;
&lt;p&gt;이 말이 의미하는 바는 이런 겁니다. 커널 모드 핵툴이 나왔는데 우리는 유저 모드 기술 밖에는 없을 때. 같은 레벨에서 싸우지 않고서는 답이 없는 경우가 존재합니다. DirectX 후킹만 알고 있는데 핵툴 제작자는 WDDM 후킹을 하고 있을 때, 함수 진입 부분 훅 체크만 하는데 함수 중간 부분을 후킹하는 기법일 때, 코드 오버라이트 방식의 훅만 생각하는데 예외 처리기를 통한 후킹 방식일 때, 등등… 즉, 일부 영역에서는 해당 테크닉을 모르고는 영원히 대응이 불가능한 지점이 생깁니다. 따라서 일정 수준 이상의 기술력을 갖추는 것은 필수 사항입니다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;도구. 두 번째로 중요합니다. 보안 제품에 반드시 특정 싸움에 대해서는 종결 시킬 수 있는 이론적 근간이 있는 코드들이 있어야 한다는 것을 의미합니다. 논클라이언트 봇이나 바이패스 툴이 나왔을 때 해당 툴들을 사전에 차단은 하지 못하더라도 사후 대응은 가능한 이론적 근간은 있어야 한다는 겁니다. 그런 게 없으면 싸움을 이어 나갈 수가 없습니다. 이런게 없으면 그냥 단순하게 바이패스 등장, 끝이기 때문입니다.&lt;/p&gt;
&lt;p&gt;더불어서 알려진 범용 핵툴 기법에 대해서는 해당 접근 루트를 완전히 차단할 정도로 완전한 도구가 필요합니다. 특정 API를 후킹할 때 우리가 해당 API를 체크하면 더 이상 해당 API를 후킹하면서 우리 코드를 우회할 방법은 없어야 한다는 것, 특정 게임 함수를 불법 호출할 때 해당 게임 함수를 보호하면 더 이상 불법 호출을 하면서 우리 코드를 우회할 방법은 없어야 한다는 것을 의미합니다. 그런데 이 정도로 완성도 높은 코드들을 만들기는 쉽지 않습니다. 하지만 이런 코드들 없이는 절대로 싸움을 끝낼 수가 없습니다. 반드시 어느 지점까지 몰아갔을 때에는 해커들을 막다른 골목으로 인도할 수 있는 도구가 있어야 싸움을 끝낼 수 있습니다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;이런 기본기가 갖추어진 다음 진짜 중요한 것은 업데이트 입니다. 핵툴은 제작이 끝나는 순간 바로 배포합니다. 몇몇 운영체제에서 크래시가 나는 것은 중요하지도 않습니다. 선배포 후에 테스트를 진행한다고 보면 되겠습니다. 이렇게만 해도 일부 핵툴이 동작하는 사용자들은 환호하면서 그들에게 돈을 지불하고도 칭찬을 아끼지도 않죠.&lt;/p&gt;
&lt;p&gt;하지만 보안 제품은 상황이 다릅니다. 모든 PC에서 정상 동작을 해야 하며, 다른 제품들과 충돌 테스트도 거쳐야 하고, 내부 QA에서 게임사 QA, 또는 게임사에 따라서는 게임사의 자체 보안팀의 QA를 거쳐야 합니다. 이러한 복잡한 단계를 거치더라도 최소한 해킹툴과 속도전을 할 수 있을 정도의 업데이트 속도는 갖추어야 합니다. 보안 제품 한 번 업데이트로 해킹툴을 하루 다운(down) 시킨다면 적어도 매일 업데이트가 이루어져야 한다는 겁니다. 대응을 해보면 알겠지만 사실 추가 업데이트 없이 하루를 다운시키는 것도 거의 불가능할 정도로 긴 시간입니다.&lt;/p&gt;
&lt;p&gt;물론 이런 업데이트 주기를 가지기 위해서는 보안 제품을 개발하는 쪽에서도 많은 부분을 신경 써야 합니다. 우선은 코드가 아닌 데이터만 교체함으로써 핵툴을 차단할 수 있는 구조를 많이 만들어 두어야 합니다. 데이터 교체는 빌드를 새로 하는 것보다는 훨씬 문제가 덜 발생하기 때문이죠. 또한 검증할 것도 적어지기 때문에 QA 시간도 단축됩니다. 더불어 절대로 핵툴이 새로 나왔다고 그걸 분석하고 있어서는 안됩니다. 나오는 즉시 일단 막고 봐야 합니다. 그 후에 분석해도 늦지 않습니다. QA 시간을 고려해서 최대한 빨리 대응할 수 있도록 해주어야 한다는 의미입니다.&lt;/p&gt;
&lt;p&gt;속도전입니다. 핵툴이 새롭게 업데이트 되자 마자 바로 문제가 발생한다는 인식을 해킹툴 사용자와 해킹툴 제작 그룹에 인지시켜 주어야 합니다. 이런 인식이 없으면 마치 깨진 유리창 이론처럼 우후죽순 유사 해킹툴들이 등장합니다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;시스템 가변성. 이 싸움을 잘 살펴보면 해킹툴 그룹은 아주 소수이며 그것을 사용하는 사람은 절대 다수라는 점을 알 수 있습니다. 따라서 이 싸움에서 이기기 위한 영리한 생각 중에 하나는 시스템 가변성을 두는 것입니다. 즉 우리가 만든 보안 제품이 해킹툴 제작자의 PC와 다른 사람들의 PC에서 다르게 동작한다면 해킹툴 제작자 입장에서는 굉장히 골치 아픈 문제가 될 수 있다는 겁니다. 해커가 자기 PC에서 되는 것 같아서 배포했는데 사용자들은 모두 동작하지 않는다고 아우성을 치는 상황을 만들 수 있다는 것이죠. 이런 상황이 몇 번 연출되면 해킹툴 제작자 입장에서는 클레임에 골치 아파서라도 그냥 GG치게 됩니다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;p&gt;느린 탐지. 아주 간단하지만 의외로 굉장히 효과적인 방법입니다. 해킹툴 배포 시간을 늦추고 싶다면 해당 해킹툴 탐지 시간을 늦추는 단순한 행위로도 효과를 볼 수 있다는 말입니다. 물론 아무리 길어지더라도 해킹툴 사용자 입장에서는 핵툴을 이용한 효용이 없는 시간 정도여야겠지요. 예를 들어 FPS 게임이라면 핵툴을 가동하고 게임을 실행하고 방을 찾아 들어가서 이제 한 번 시작해볼까 할 때에 탐지하는 것을 말합니다. 그런데 보통은 빠른 탐지가 좋은 줄 알고 게임 구동 시에 알려진 핵툴에 대해서는 바로 탐지해 버립니다. 이게 문제입니다.&lt;/p&gt;
&lt;p&gt;이 방법이 효과적인 이유는 해킹툴 제작자의 테스트 시간을 늘린다는 점과 굉장히 피로하게 만든다는 점입니다. 게임을 구동해서 방에까지 들어가야 뭔가 결과를 알 수 있기 때문이죠. 즉, 자신이 수정한 것이 우회됐는지를 확인하기까지 시간이 늘어난다는 점입니다. 더불어 탐지 시간이 가변적이라면 더 효과적입니다. 해킹툴 제작자 입장에서는 얼마 정도를 테스트해야 하는지를 알기가 힘들어지기 때문입니다.&lt;/p&gt;
&lt;h3&gt;#5&lt;/h3&gt;
&lt;p&gt;복잡한 내부 IPC 구조. 여러분이 반드시 숨겨야 하는 것은 어떤 기준으로 해킹툴을 탐지 했냐는 겁니다. 따라서 탐지하는 부분과 사용자에게 핵툴이 탐지 됐다고 보고하는 부분 사이에는 거리가 있어야 합니다. 절대로 탐지 했다고 바로 그것을 보고하는 멍청한 짓을 해서는 안됩니다. 왜냐하면 해커들은 당연히 탐지 지점부터 우리를 추적해 오기 때문입니다. 그 사이에 엄청 복잡한 단계의 IPC 통로를 만들어 두세요. 그 IPC 메커니즘이 일정 수준 이상 복잡해지면 어느 순간부터는 해커들이 우리 코드를 분석해 패치하기 보다는 그냥 자기 코드를 고치는 것이 빠르다는 생각을 하게 됩니다.&lt;/p&gt;
&lt;h3&gt;#6&lt;/h3&gt;
&lt;p&gt;VIP 핵툴의 경우 절대로 진단 루틴이 제너레이터를 통해서 우회할 수 있는 수준이어서는 안됩니다. 해킹툴 개발자가 코드를 보고 어디를 고쳐야 할지 생각하고 다시 컴파일을 강요할 수준은 되어야 합니다. 이런 게 되지 않으면 업데이트 한 트럭이 주어져도 전혀 효과가 없습니다. 무조건 우리가 업데이트를 한 번 할 때에는 해킹툴 개발자도 적어도 컴파일을 새로할 정도는 되는 진단 루틴을 추가해야 합니다. 물론 해커가 고민을 많이 해야 알 수 있는 루틴이라면 더 좋습니다.&lt;/p&gt;
&lt;h3&gt;#7&lt;/h3&gt;
&lt;p&gt;구구절절 설명했지만 솔직히 정말 복잡하고 골치 아프고 신경쓰기 싫은 문제들입니다. 그럴 땐 그냥 &lt;a href=&quot;http://www.wellbia.com&quot;&gt;웰비아닷컴의 XIGNCODE를&lt;/a&gt; 사용하시면 됩니다. 합리적인 가격에 우수한 게임 보안 서비스를 제공한답니다. 어쨌든 게임 보안하면 XIGNCODE, XIGNCODE하면 게임 보안 딱 답 나오잖아요 ㅋㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[키보드 눌렀는지 비동기 방식으로 검사하기]]></title><description><![CDATA[프로그래밍을 하다보면 동기/비동기라는 말이 자주 등장합니다. 동기 방식이란 해당 I/O…]]></description><link>https://jiniya.net/wp/archives/5598</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5598</guid><pubDate>Tue, 03 Jan 2012 23:57:58 GMT</pubDate><content:encoded>&lt;p&gt;프로그래밍을 하다보면 동기/비동기라는 말이 자주 등장합니다. 동기 방식이란 해당 I/O 작업이 완료될 때까지 프로그램이 블록된다는 것을 의미합니다. 소켓 통신에서 수신을 한다면 데이터가 올 때까지 프로그램이 정지한다는 말이죠. 키보드 입력을 받는다면 사용자가 키보드에서 데이터를 입력할 때까지 프로그램이 정지하는 겁니다. 그렇다면 비동기는 어떻게 동작하는 것일까요? 동기 방식과 정반대로 동작하는 것을 말합니다. I/O가 완료되지 않아도 바로 리턴하며, I/O가 완료됐을 때 이벤트를 받는 형태로 동작하는 방식입니다. 따라서 프로그램은 계속 다른 작업을 할 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;p&gt;… 작성 중 (나용 추가 필요) …&lt;/p&gt;
&lt;p&gt;아래 프로그램은 지속적으로 “Happy New Year!!!”을 출력하다가 사용자가 q를 누르면 종료하는 프로그램입니다. _kbhit 함수는 사용자가 키보드를 입력했는지 하지 않았는지를 검사하는 함수 입니다. 키보드를 입력했으면 0이 아닌 값을, 입력하지 않았다면 0을 리턴하죠. getch는 키보드 입력 버퍼에서 한 글자를 입력 받아서 해당 키 값을 리턴해 주는 함수입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;tchar.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;conio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_kbhit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;q&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Happy New Year!!!\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아래 프로그램과 동작을 비교해 보시면 어떤 차이가 있는지 금방 알 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;tchar.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;conio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_tmain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _TCHAR&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;q&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Happy New Year!!!\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[여러분의 DllMain이 예외를 발생시키면 어떻게 될까요?]]></title><description><![CDATA[#0. 이 내용은 최문혁 MVP 햄님께서 친히 제보해 주신 xfav…]]></description><link>https://jiniya.net/wp/archives/5253</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5253</guid><pubDate>Wed, 21 Dec 2011 23:57:57 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#0.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 내용은 &lt;a href=&quot;http://dotnetpower.kr/&quot;&gt;최문혁 MVP 햄님&lt;/a&gt;께서 친히 제보해 주신 xfav 프로그램 버그를 찾다가 알게 된 사실입니다. 이 자리를 빌어서 다시한번 감사의 마음을 전합니다. 여러차례 덤프를 떠서 전달해 주시는 수고를 마다하지 않으셨습니다. 흙~ 눈물날라 그러는군요. 좀 오래된 이야긴데 바빠서 그간 정리를 못하고 있다가 인제서야 올리게 되는군요. 수정된 프로그램은 다음에 시간날 때 빌드해서 올리도록 하겠습니다. ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;증상은 간단했습니다. xfav.exe에서 인젝션하는 DLL이 explorer.exe에 주입되면서 explorer.exe가 크래시가 발생하는 현상이었습니다. 덤프는 explorer.exe가 종료되려고 하는데 엉뚱하게도 언로드된 xfav.exe의 _freefls를 가리키고 있더군요. 뭐 그런 상황이었습니다. 원인이 무엇이었는지는 제목이 암시하고 있는 거겠죠. 애니웨이, 시작해 봅시다!!!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;제일 먼저 DllMain에 대해서 운영체제가 어떤 정책을 취하고 있는지 알아보아야 합니다. 우리가 아무리 잘 만들어본들 우리는 그저 O/S 위에서 돌아가는 일개 프로그램일 뿐이잖아요. ㅋ~ MSDN을 찾아보면 아래와 같이 설명이 나와있습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If the DLL’s entry-point function returns FALSE following a DLL_PROCESS_ATTACH notification, it receives a DLL_PROCESS_DETACH notification and the DLL is unloaded immediately. However, if the DLL_PROCESS_ATTACH code throws an exception, the entry-point function will not receive the DLL_PROCESS_DETACH notification.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;영어를 잘하는 제가(ㅋㅋ) 짧게 요약을 해보면 이렇습니다. DLL_PROCESS_ATTACH에서 FALSE를 리턴하면 DLL_PROCESS_DETACH 호출을 받을 것이고, DLL_PROCESS_ATTACH에서 예외가 발생했다면 DLL_PROCESS_DETACH를 받을 생각 따위는 아예 하지도 말아라. 헉. 그렇습니다. 기본적으로 예외가 발생하면 DLL_PROCESS_DETACH 호출을 받지 못합니다. 우리가 운영체제를 만든다고 하더라도 그러겠지요? 생성자에서 예외가 발생하면 소멸자가 호출되지 않는 것과 동일한 원리 아니겠습니까? ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다음으로 우리는 그 지긋지긋한 CRT에 대해서 다시 살펴보는 시간을 가져야 겠습니다. CRT는 멀티스레드 환경을 지원하기 위해서 FLS(Fiber Local Storage)라는 것을 사용합니다. CRT 초기화 루틴에서 FlsAlloc(_freefls)를 호출해서 등록하죠. 이는 다시 CRT가 종료될 때 회수됩니다. 일반적인 DLL을 만들면 우리의 DLlMain이 호출되기 전에 FlsALloc으로 flsindex를 할당 받고, DLL_PROCESS_DETACH가 호출되면 CRT가 그것을 정리하는 원리로 돌아갑니다.&lt;/p&gt;
&lt;p&gt;즉, 코드로 살펴보면 다음과 같은 구조가 되는 겁니다. OurDllMain이 우리가 작성한 것이고, 실제 DLL의 엔트리는 CrtDllMain이 되는 구조입니다. 머 심플하죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL CALLBACK &lt;span class=&quot;token function&quot;&gt;CrtDllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HINSTANCE instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ULONG reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; DLL_PROCESS_ATTACH&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        flsindex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FlsAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_freefls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OurDllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reason &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; DLL_PROCESS_DETACH&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        BOOL r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OurDllMain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reason&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reserved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;FlsFree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flsindex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;#3.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그런데 이 CRT가 싸지른 FlsCallback이 문제입니다. 앞선 코드에서 _freefls가 되겠죠. 이 FlsCallback은 운영체제에서 필요한 경우, 스레드 종료, 파이버 종료, fls 해제와 같은 상황이 되면 호출을 합니다. 이런 복잡한 처리를 하기 위해서 운영체제는 이놈을 운영체제의 테이블, 리스트같은 곳에 등록을 해놓습니다. 뭐 PEB같은 곳에 말이죠. 그리고는 필요한 때에 그 루틴을 불러서 호출한답니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;자 이제 다왔습니다. 그렇다면 우리가 만든 DllMain의 DLL_PROCESS_ATTACH에서 예외가 발생하면 어떻게 될까요? DLL_PROCESS_ATTACH가 실패했으니 일단 DLL은 로드되지 않겠죠. 여기까지는 문제가 없습니다. 그냥 DLL이 로드되지 않고 기능이 동작하지 않을 뿐이죠. 문제는 프로세스가 종료할 때 발생합니다. FLS를 정리하기 위해서 운영체제는 우리 DLL의 CRT 코드가 싸지른 FlsCallback을 호출하려고 시도합니다. 비극은 여기서 시작됩니다. DLL은 로드에 실패했기 때문에 메모리에 존재하지 않고, 운영체제는 그 바운더리에 있는 FlsCallback을 호출하려고 하는 겁니다. 결과는 머 당연하죠. 크래시가 발생합니다.&lt;/p&gt;
&lt;p&gt;이유는 우리가 예외를 발생시켰고, 예외가 발생한 경우에 운영체제는 DLL_PROCESS_DETACH를 호출하지 않고, 그러니 CRT는 자신이 싸지른 FlsCallback을 회수할 기회가 없었던 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;결론을 요약하면 이렇습니다. DllMain에서는 절대로 예외를 발생시켜서는 안됩니다. 왜냐하면 그 예외가 CRT의 코드에 영향을 미칠 수 있기 때문입니다. 모든 예외를 봉쇄하고 발생한 경우에는 그냥 FALSE를 리턴하는 것이 현명합니다. 그러면 적어도 다른 프로그램에 민폐는 안끼칠 수 있겠죠. 그렇지 않다면 민폐를 끼치고 엉뚱한 프로그램이 크래시가 발생하는 문제가 생길 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다시 처음으로 돌아와서 그렇다면 xfav.exe에서 주입했던 DLL의 DllMain은 왜 크래시가 발생했던 걸까요? 궁금하시죠? 이유는 제가 예전에 썼던 글들에 답이 있습니다. DllMain과 관련된 글을 두 개를 썼더랬습니다. 하나는 &lt;a href=&quot;http://jiniya.net/tt/788&quot;&gt;DllMain에서는 절대로 하지 말아야 할 것&lt;/a&gt;이고, 다른 하나는  &lt;a href=&quot;http://www.jiniya.net/wp/archives/4457&quot;&gt;DLL_PROCESS_DETACH 시점에서 주의해야 할 점&lt;/a&gt;이었습니다. 그런데 제가 그 DllMain에서는 절대로 하지 말아야 할 것을 해버린 것이었죠. user32.dll의 함수를 DLL_PROCESS_ATTACH에서 호출한 겁니다. user32.dll이 아직 초기화가 되어있지 않아서 예외가 발생해버린 겁니다. 하지 말라는데에는 다 이유가 있는 거겠죠. 흙~~&lt;/p&gt;
&lt;p&gt;그래서 어떻게 했냐구요? 초기화를 지연 시켰습니다. DLL_PROCESS_ATTACH에서 하지 않고 말이죠.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[마계촌 온라인 클베 두둥~]]></title><description><![CDATA[이 게임의 역사를 말하자면 좀 유서가 깊은데요. 한 6-…]]></description><link>https://jiniya.net/wp/archives/5451</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5451</guid><pubDate>Wed, 14 Dec 2011 23:57:56 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./마계촌_온라인_클베_두둥~.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/0411bbcc601dd6d68d1eedd8ff7f280e/e224a/%EB%A7%88%EA%B3%84%EC%B4%8C_%EC%98%A8%EB%9D%BC%EC%9D%B8_%ED%81%B4%EB%B2%A0_%EB%91%90%EB%91%A5~.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 62.63157894736842%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwX/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAcdoMqhyv//EABkQAAIDAQAAAAAAAAAAAAAAAAABAhASEf/aAAgBAQABBQKmjbQ5Gun/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAADAQEAAAAAAAAAAAAAAAAAATEQQf/aAAgBAQAGPwKEzhERH//EABsQAQADAAMBAAAAAAAAAAAAAAEAESExUXGB/9oACAEBAAE/ITAdRpoqeRB4nQfpNSFt0fJ//9oADAMBAAIAAwAAABDDD//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EEf/xAAWEQADAAAAAAAAAAAAAAAAAAAAARH/2gAIAQIBAT8QjKz/xAAcEAEAAwEAAwEAAAAAAAAAAAABABEhMUFRceH/2gAIAQEAAT8QIKAd+1sdMp5TsQgsgkvJFxsjxWRY+io/U//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;               md 0&apos; title=&apos;&apos; src=&apos;/static/0411bbcc601dd6d68d1eedd8ff7f280e/e224a/%EB%A7%88%EA%B3%84%EC%B4%8C_%EC%98%A8%EB%9D%BC%EC%9D%B8_%ED%81%B4%EB%B2%A0_%EB%91%90%EB%91%A5~.md_0.jpg&apos; srcset=&apos;/static/0411bbcc601dd6d68d1eedd8ff7f280e/8ccab/%EB%A7%88%EA%B3%84%EC%B4%8C_%EC%98%A8%EB%9D%BC%EC%9D%B8_%ED%81%B4%EB%B2%A0_%EB%91%90%EB%91%A5~.md_0.jpg 190w,
/static/0411bbcc601dd6d68d1eedd8ff7f280e/ea4c8/%EB%A7%88%EA%B3%84%EC%B4%8C_%EC%98%A8%EB%9D%BC%EC%9D%B8_%ED%81%B4%EB%B2%A0_%EB%91%90%EB%91%A5~.md_0.jpg 380w,
/static/0411bbcc601dd6d68d1eedd8ff7f280e/e224a/%EB%A7%88%EA%B3%84%EC%B4%8C_%EC%98%A8%EB%9D%BC%EC%9D%B8_%ED%81%B4%EB%B2%A0_%EB%91%90%EB%91%A5~.md_0.jpg 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이 게임의 역사를 말하자면 좀 유서가 깊은데요. 한 6-7년은 된 이야기 같습니다. 대학교 수업 시간이었죠. 수업 시간에 형이 연습장에 막 뭔가를 끄적이면서 고민을 하고 있었습니다. 그 때 셋이서 수업을 같이 들었던 것 같은데 저랑 다른 형은 어떻게 하면 출석 부르고 나가서 스타나 할까라는 생각을 하고 있었죠. 밖으로 나가기는 애매한 분위기가 되서 무슨 고민을 그리도 하냐고 물어 봤습니다. 그 때 형이 그러더군요. 마계촌이란 게임을 온라인으로 만드는데 횡스크롤을 3D로 어떻게 매핑을 해야 할지를 모르겠다고 말이죠. Z축이 생기면 여러모로 원작 마계촌의 횡스크롤 느낌을 살리기는 힘드니까요. 그런 심도 있는 고민을 연습장에 맵을 그려가면서 막 했답니다. 다른 날은 또 와서는 월드 클래스를 어떻게 만들어야 좋을지를 고민하기도 했었죠. 그렇게 시간이 흘러 흘러 우리는 졸업을 했고, 열심히 고민을 했던 형은 졸업을 하고도 계속 마계촌 온라인을 만들었고, 저는 어찌 흘러 흘러 게임 보안 제품을 만들게 되었답니다.&lt;/p&gt;
&lt;p&gt;우왕 사설이 너무 길었네요. 새벽에 감상에 젖어서 그만… ㅋㅋ 각설하구요. 어쨌든 그랬던 마계촌 온라인이 지난 주 목요일부터 일요일까지 장장 4일에 거쳐서 클로즈 베타 테스트라는 엄청한 테스트를 진행했습니다. 지난 시간 옆에서 들은 이야기가 있어서 그런 걸까요? 게임을 보는데 제가 다 뿌듯하더군요. 물론 형이 고맙게도 보안 제품으로 우리 회사 제품인 XIGNCODE3를 전격 기용하는 용단을 발휘했기 때문에 그런건 절대 아닙니다. 아니고요. ㅋ~&lt;/p&gt;
&lt;p&gt;클베 이야기를 좀 해야겠네요. 이번 클베는 26렙까지 컨텐츠를 오픈했다고 하는데 전 그마저도 모두 즐기지를 못했습니다. 시간만 있었어도 만렙을 찍는 기염을 토하려고 했으나 진행하는 과제 완료 발표가 이번주로 잡혀서 주말 내도록 발표 자료 만드느라 제대로 게임을 즐기질 못했습니다. 뭐 핑계죠 ㅋㅋ~ 어쨌든 그래도 조금은 즐겨 봤는데요. 기사 6렙, 아처 3렙, 기사 11렙 이렇게 했봤습니다. 첨에 하던 기사가 클베 시작하니 삭제되고 없드라고요. 흙~&lt;/p&gt;
&lt;p&gt;마계촌을 처음 마주한 느낌은 딱 두 가지였습니다. 배경 음악, 마계촌 고유의 배경음악을 듣는데 왠지 오싹하더군요. 저도 어렸을 때 마계촌을 했었거든요. 난이도 탓에 늘 초반에 죽곤 했었지만 말입니다. 그리고 다른 한 가지 느낌은 그래픽이 뭔가 요즘 게임같지 않게 후지다는 느낌이었습니다. ㅋㅋ~ 근데 클베 마지막 날 알게된 사실인데 그래픽이 그랬던건 해상도 탓이더군요. 제 모니터 해상도가 1680×1050인데 디폴트로 1280x???로 잡혀서 그랬더라고요. 해상도 맞추고 게임을 하니 몰입도가 100배 증가 부왘. 마치 해골 분쇄기가 모니터에서 튀어나오는듯한 느낌이었습니다. 그래픽 좋습니다.&lt;/p&gt;
&lt;p&gt;앞서 기사와 궁수를 해봤다고 했는데 전 여러모로 기사가 재밌었습니다. 타격감도 좋고, 써는 맛도 있고, 뭔가 내가 하려는 의지대로 캐릭터가 움직인다고 할까요? 손에 착착 감기는 ㅋㅋ~ 반면 궁수는 허구헌날 그 놈에 언덕 때문에 화살이 언덕에 박히는 몹쓸 장면이 많이 연출되더군요. 물론 제가 발컨이라 그렇기도 합니다. 같이 테스트 했던 직원도 기사가 재밌다고 하는걸로 봐서는 확실히 기사가 대세인것 같아요 ㅋㅋ~&lt;/p&gt;
&lt;p&gt;초반에는 x키로 닥썰만 하면 돼서 사실 좀 심심한데요. 제가 재밌다고 느낀 건 그 불타는 농장인가 거기를 가면서부터였습니다. 막 바퀴 날라오고 불덩이 날라오고 하는데 뭔가 이제는 약간 컨트롤 아닌 컨트롤이 필요한 듯한 느낌, 또 해골 분쇄기 앞에 이상한 놈 두 놈 나오는 데 왠지 그것들을 처리하고 나면 뿌듯하더군요. 발컨이라 해골 분쇄기는 죽지 않곤 못잡겠드라고요. 후반 컨텐츠가 더 재밌을 것 같은데 해보질 않아서 논하기가 곤난하네요. 2차 클베때는 반드시 만렙을 찍겠습니다. 그리고 해보면서 느낀 건데 기사는 진짜 타격감이 좋습니다. 특히 초반에 그 무덤 나오는 데서 해골 때릴 때 그 독특한 타격감은 잊을 수가 없네요.&lt;/p&gt;
&lt;p&gt;한 가지 건의 사항이 있다면 물약을 단축키로 지정했을 때, 물약 다 먹고 나면 단축키에서 사라져서 다시 물약 주으면 또 끌어다 놔야 하는 불편함이 있는데요. 한번 물약 단축키는 영원한 물약 단축키가 됐으면 좋겠다는 소소한 바램이 ㅋ~ 저희 같은 발컨은 물약이 생명이거든요. 흙~&lt;/p&gt;
&lt;p&gt;어쨌든 구구절절 느낌점을 풀어봤는데요, 총평을 하자면 재밌습니다. 게임이 재밌으면 그만이죠. 특히 자투리 시간 킬링 타임용으로는 정말 괜찮을것 같다는 생각이 팍팍 들었습니다. 뭔가 지금도 불타는 농장을 들어가서 다시 해골 분쇄기와 맞짱을 뜨고 싶은데 서버와 연결이 되지 않아 많이 안타깝네요. 스샷을 좀 찍어둔다는게 정신이 없어서 못찍었네요. 그나마도 클베 끝나고 드가서 시작 화면 하나 찍었습니다. ㅠㅜ~ 클베 끝날 때 GM이랑 애들이랑 막 밖에서 댄스타임하길래 그 때 나중에 글 올리려고 스샷을 찍어 둔다고 찍었는데 Print Screen 누른다는게 그만 Pause를 계속 연타해서 하나도 못건졌습니다.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[아버지와 나…]]></title><description><![CDATA[#0 일요일 저녁. 술을 한 잔 하고는 집으로 들어왔다. 11시쯤 됐던가? 이른 시간이었지만 피곤했는지 집에 와서는 그 길로 잠들어 버렸다. 일어나니 새벽 3시. 한참을 고민했다. 이상하게 안가던 떼목욕이 가고 싶었기 때문이다.…]]></description><link>https://jiniya.net/wp/archives/5518</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5518</guid><pubDate>Tue, 13 Dec 2011 23:57:55 GMT</pubDate><content:encoded>&lt;h3&gt;#0&lt;/h3&gt;
&lt;p&gt;일요일 저녁. 술을 한 잔 하고는 집으로 들어왔다. 11시쯤 됐던가? 이른 시간이었지만 피곤했는지 집에 와서는 그 길로 잠들어 버렸다. 일어나니 새벽 3시. 한참을 고민했다. 이상하게 안가던 떼목욕이 가고 싶었기 때문이다. 4시쯤이 돼서는 기어코 목욕 가방을 챙기고 길을 나섰다. 4시부터 5시까지 탕을 청소한다는 말에도 아랑곳하지 않고 들어가서는 신나게 목욕을 했다. 간만에 탕에 몸을 담그고 떼를 밀고나니 한 결 머리가 가벼워진 느낌이었다.&lt;/p&gt;
&lt;p&gt;어린 시절 아빠는 목욕을 끝내곤 곧잘 삼육두유를 마셨다. 나도 그런 그의 취향을 물려받아 떼목욕을 하고 나면 으레 삼육두유를 하나씩 먹곤 했다. 그날도 냉장고를 뚫어져라 뒤졌다. 하지만 삼육두유는 없었다. 순두유를 마셨다.&lt;/p&gt;
&lt;p&gt;백팩을 가지러 회사에 들렸다 집으로 돌아왔다. 내일은 과제 완료 발표가 있었고, 다음주 토요일에는 엄마 CT 촬영이 있었다. 보고서도 써야 했고 집 청소도 해야 했다. 귀찮은 생각이 들어서 그냥 다 잊고 침대에 몸을 뉘였다. 그때 핸드폰 벨이 울렸다. 엄마다. 전화를 받고는 엄마, 하는데 반대편에서 “느그 아버지가…”하는 광란에 빠진 한 마리 짐승의 절규만 들리고는 전화가 끊어졌다. 다시 전화를 하려는데 작은 누나에게 전화가 먼저 왔다. 울고불고 정신 없는 상태에서 누나는 나에게 재차 아버지 부고를 전했다.&lt;/p&gt;
&lt;p&gt;멍했다. 처음에는 마치 이 모든 사실이 농담처럼 느껴졌다. 그것도 잠시 주섬주섬 아무 옷이나 챙겨 입고는 뒤도 돌아보지 않고 집을 나왔다. 택시를 타고는 공항으로 향했다. 눈물이 났다. 너무 슬프면 눈물도 나지 않는다고 했는데 내 평생에 그렇게 구슬프게 모르는 사람 앞에서 처절하게 울었던 적은 처음이었다. 이상한 듯 쳐다보는 택시 아저씨의 시선도 무시한 채 엉엉 울었다. 너무 슬펐다. 뭔지 모를 감정이 내 머릿속을 헤집고 다녔고, 내 심장에서는 뭔가 대단한 덩어리가 빠져나간 느낌이었다.&lt;/p&gt;
&lt;p&gt;그의 죽음은 나에게 이렇게 어처구니 없이 갑작스럽게 차가운 바람처럼 다가왔다.&lt;/p&gt;
&lt;h3&gt;#1&lt;/h3&gt;
&lt;p&gt;부산에서 친구 결혼식이 있던 날이었다. 역시나 난 늦잠을 잤고 늘 그렇듯이 부리나케 서울역으로 가서는 아무 기차나 올라탔다. 입석이었다. 11월임에도 날씨가 무던 덥던 날이었다. 부산 양정에서 결혼식이 있었는데 양정에 도착하자 정말 애매모호한 시간만 남았다. 집에 가서 정장을 갈아입고 오기엔 시간이 너무 촉박해 그냥 근처 커피숍을 찾아 들어갔다. 부산 날씨는 그야말로 7월 장마철 날씨였다. 습하고, 더웠고, 불쾌지수는 상상을 초월했다.&lt;/p&gt;
&lt;p&gt;결혼식이 끝나고 친구들과 술을 한 잔 하고는 저녁쯤 본가 기습을 단행했다. 동래부터 온천천을 호기롭게 걸어가며 엄마한테 전화를 건다. 별 일 없냐는 나의 질문. 엄마는 대뜸 아빠가 입원했다가 어제 퇴원했다는 이야기를 한다. 종합 검진을 받았는데 장기들 기능이 떨어져서 그렇지 관리만 잘하면 큰 문제는 없다는 이야기를 의사가 했다고 전해준다. 그러다 배터리가 다돼서 전화가 끊겼다.&lt;/p&gt;
&lt;p&gt;집에 도착했다. 1302호. 내가 고등학교를 다니던 무렵부터 이 곳에 살았다. 이제는 익숙하지 않은 비밀번호를 누르고는 들어가면서 신나게 소리친다. 사랑하는 아들이 왔노라고. 쇼파에 앉아서 TV를 보고 있던 아빠는 늘 그랬듯이, “영지~ 왔나?”라는 말을 하며 아주 반갑게 맞아 주셨다.&lt;/p&gt;
&lt;p&gt;다음날 아침. 아빠는 목욕을 가고 싶어 했다. 그렇게 엄마가 가라고 할 때는 가지 않다가 교통사고가 난 불편한 발을 이끌고 기어코 목욕을 가겠다고 고집을 부리신 것이었다. 고집을 이기지 못한 엄마가 나에게 같이 가라고 했다. 그러겠다고. 그렇게 집을 나와서는 거의 20년 만에 처음으로 목욕탕 가는 길을 함께 걸었다. 하필 옆 상가에 목욕탕이 없어져서 먼 길을 걸어서 가야 했다. 비는 여전히 추적추적 내리고 있었다. 5m를 가다가 잠시 앉아 쉬고, 또 열 걸음을 가다 쉬곤 했다. 그러기를 5-6회 기어코 아빠는 다리 한 가운데서 주저 앉았다. 저혈당이 온 것이다. 평소 가지고 다니시던 사탕이 없어 부리나케 근처 구멍가게에서 사탕을 사왔다. 그러고도 수습이 되질 않았다. 결국 엄마를 불러서 차에 태워서 집으로 다시 돌아갈 수 밖에 없었다.&lt;/p&gt;
&lt;p&gt;집에 와서는 한참 동안 아빠를 타박한다. “왜 엄마 말을 듣지 않느냐?”부터 시작해서 갖은 타박을 다했다. 아픈 것도 야속한데 하나 있는 아들이 그랬으니 그 심정이 오죽했을까? 그런데도 아빠는 싫은 내색 한 번 하지 않고 아들이 자신을 살렸다는 이야기를 하시며 해맑게 웃으셨다.&lt;/p&gt;
&lt;p&gt;이 장면이 내가 기억하는 그의 마지막 모습이다. 물론 이렇게 되리란 걸 상상도 못했지만 그렇게 돼 버렸다. 야속하게도 말이다. 물론 내가 그의 마음을 야속하게 한 것에 비하면 이 일은 아무 것도 아닌지도 모르겠다. 그럼에도 너무 슬프고, 애통하고, 비통하고, 원통하다. 또 그가 너무 원망스럽다. 그는 평생 자신을 이해해 주지 않았던 나를 한번도 원망하지 않았지만, 난 단 한 차례 그가 나의 바램을 꺾었다는 이유만으로 그를 원망한다는 사실이 비겁하다는 생각이 들었지만, 마음은 어쩔 수가 없었다. 이제는 그의 모습을 볼 수 없다. 목소리도 들을 수 없으며, 체취를 느낄 수도 없다. ‘영원’이란 단어가 허용된다면 단 한 곳, 바로 이 상황에 쓸 수 있다는 생각이 들었다. 그는 영원히 우리 곁을 떠났다.&lt;/p&gt;
&lt;h3&gt;#2&lt;/h3&gt;
&lt;p&gt;2년 전 크리스마스였다. 여자친구와 파르나서스 박사의 상상극장이라는 내 생애 최악의 영화로 꼽을 만한 영화를 이브 날에 보고는 술을 마시며 밤을 보냈다. 그리곤 크리스마스 날 오후에 눈을 떴을 때 엄마에게 전화가 왔다. 아빠가 쓰러져서 대학병원에 입원했다는 전화였다. 부리나케 비행기를 예약하고는 전화 받고 한 시간도 안되어서 공항에서 비행기를 탔다. 참 시트콤같은 크리스마스였다.&lt;/p&gt;
&lt;p&gt;택시를 타고 도착한 대학병원. 엄마와 작은 누나가 있었고, 머지 않아서 큰 누나도 왔다. 아빠는 의식이 없었다. 우리는 의식이 없는 아빠를 쳐다보면서 황당하게 크리스마스 당일에 가족이 다 모인 게 정말 얼마 만인지 모르겠다는 이야기를 했다. 실로 큰 누나가 20살이 된 이후로는 단 한 차례도 없었던 것 같았기 때문이다. 아마 올해도 아빠가 스러지지 않았다면 우리는 모두 따로 각자의 크리스마스를 보냈을 것이다.&lt;/p&gt;
&lt;p&gt;병원에서는 아버지께서 돌아가실 수도 있다는 말을 하면서 마음의 준비를 하라는 이야기를 했다. 하지만 아빠는 우리의 바램을 저버리지 않고 다시 일어났다. 그가 깨어났을 때 난 정말 우리 아빠라는 생각을 했다. 그가 깨어나고 처음 한 말이 저기 간호사가 이쁘다면서 나보고 꼬셔보라는 농이었기 때문이었다. 난 아빠가 농을 하는 걸 보니 다 나은 것 같다고 너스레를 떨었다.&lt;/p&gt;
&lt;p&gt;그렇게 우리는 그 해 크리스마스를 병원에서 함께 보냈다. 작은 누나는 다음 해 아빠가 퇴원하기가 무섭게 그때 병문안을 왔던 남자와 결혼을 했다. 돌이켜보니 누나 나이도 있겠지만 아빠의 건강 때문에 결혼식이 더 빨리 진행됐던 것 같다.&lt;/p&gt;
&lt;h3&gt;#3&lt;/h3&gt;
&lt;p&gt;장례식장, 상주 자리에 앉아서 그의 영정 사진을 멍하니 쳐다보고 있다. 지난 2년여의 시간이 스펙트럼처럼 머릿속을 뒤지고 돌아다닌다. 신성태라는 아빠 이름 앞에 붙은 ‘고’라는 한자를 볼 때면 이상하게 눈물이 났다. 그 한 글자가 아빠의 영면을 부인하는 나에게 그의 죽음을 계속 강요하는 느낌이 들었기 때문이었다.&lt;/p&gt;
&lt;p&gt;당연한 이야기겠지만 이 모든 슬픔과 아픔에도 시간은 하염없이 흘러갔고 장례식도 끝이 났다. 한 평생을 싸웠던 엄마는 장례식이 끝나고 그래도 그는 따뜻한 사람이었다는 이야기를 생전 처음으로 자식들에게 들려줬다. 엄마의 타박도 그는 항상 묵묵히 받아 줬으며, 야망을 가진 한 평생을 살지는 않았지만 적어도 그는 살아생전 누구에게도 피해를 주지 않으려는 착한 사람이었다고 말했다. 우리 모두는 눈물을 훔쳤다.&lt;/p&gt;
&lt;h3&gt;#4&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;세상은 요지경 속이다.&lt;/p&gt;
&lt;p&gt;이 다음에 무슨 일이 닥쳐올지 알 수 있다면&lt;/p&gt;
&lt;p&gt;물이 막혀 넘치는 주방, 옻이 올라 가려운 피부&lt;/p&gt;
&lt;p&gt;그리고 죽일 듯이 싸우던 순간들이&lt;/p&gt;
&lt;p&gt;앞으로 다가올 일에 비하면&lt;/p&gt;
&lt;p&gt;우리 생애 최고의 순간이라는 것을 깨닫게 도와줄 수 있을까?&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;– Grey’s Anatomy S08E09&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;사람들은 늘 어리석다. 많은 사람들이 자신은 예외라고 생각하지만 큰 착각이다. 나 또한 예외는 아니었다. 화장실이 고장 난 통에 물바다가 된 주방에서 밤새 고생했던 날, 보일러가 갑작스레 고장 난 월요일 아침, 코딩할 게 너무 많다고 투덜거렸던 새벽, 쓰기 싫은 보고서에 치여서 한숨 쉬던 날들을 돌아 본다. 힘들다고 생각했던 그 순간들 조차도 지금 생각해보니 정말 아름다운 시간이 아니었나 하는 느낌이 들었다. 단지 그와 내가 같은 하늘 아래에서 함께 숨쉬고 있다는 그 사실, 아주 사소하게 생각했지만 전혀 사소하지 않았던 그 사실 하나만으로 말이다.&lt;/p&gt;
&lt;p&gt;우리는 소중한 것들을 잃어버린 후에야 그것이 얼마나 소중했는지를 깨닫는다.&lt;/p&gt;
&lt;p&gt;똑같은 실수를 두 번 하지는 말자.&lt;/p&gt;
&lt;p&gt;절대로!!!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Unicode Windows Internals]]></title><description><![CDATA[There are many developers in Windows environment who are well aware of the Unicode function but not specifically with the Unicode Windows…]]></description><link>https://jiniya.net/wp/archives/5532</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5532</guid><pubDate>Mon, 12 Dec 2011 23:57:54 GMT</pubDate><content:encoded>&lt;p&gt;There are many developers in Windows environment who are well aware of the Unicode function but not specifically with the Unicode Windows. One could argue that this is because the majority of books do not directly demonstrate it as the first reason, and secondly because it’s concealed by Windows API. This post explores the principles of Unicode Windows for those rookie developers who are not yet familiar with this system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to understand the Unicode Windows, we need the full understanding of activity structure of Unicode function that Windows support. The Windows provides two primary versions of Unicode for most functions that handle the string. Multi-byte version with A is attached to, and the Unicode version which W is attached to. In other words, there’s ‘GetWindowTextA’ and ‘GetWindowTextW’. The performance of the two functions are equal, with the difference that A function gets char pointer as the parameter, while W gets ‘wchar-t’ as the parameter.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_UNICODE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;GetWindowText&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;GetWindowTextW&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;GetWindowText&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;GetWindowTextA&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In other words, if our build environment is under Unicode, GetWindowText becomes GetWindowTextW, while GetWindowTextA is resulted when it’s under multi-byte. This allows us to use the T typed neutral character with the system, with the neutral API which is redefined with the Macro without A and W. Moreover, the T typed neutral function on character string handling gets redefined by the macro, which allows us to generate the code regardless of the multi-byte build.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;TCHAR buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;GetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;_tcscat_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;$&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Although development process is done with no such issues with programs adequately compiling according to the build due to the well-structured Window Subsystem, it is difficult to know the root of the issue if the conversion problem breaks out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We will now cover our main subject, the Unicode Window. One can define the Unicode Window as the Window that uses the Unicode when processing a message, which makes sense to have the ’ansi window’ on the other hand, which processes the message via multi-byte message.&lt;/p&gt;
&lt;p&gt;If you were a developer with a little more insights, you could question what exactly it means to proceed by ‘unicode’. Here is a simple example with WM_GETTEXT message. Its WParam appoints the number of letters, while IParam appoints the buffer pointer that can save the letters. The question in this case is, Should one deliver the Unicode buffer via Iparam? Or multi-byte buffer? In other words, in the identical code as mentioned, is it right to use StringCchCopyW? Or StringCchCopyA?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;MyWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwnd
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT msg
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM w
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; WM_GETTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;token comment&quot;&gt;// StringCchCopyW((LPWSTR) l, w, L&quot;MyWindowText&quot;);&lt;/span&gt;
         &lt;span class=&quot;token comment&quot;&gt;// or&lt;/span&gt;
         &lt;span class=&quot;token comment&quot;&gt;// StringCchCopyA((LPSTR) l, w, &quot;MyWindowText&quot;);&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Most of the developers wouldn’t have wondered such issue, as Window subsystem does an excellent job of hiding it. Ultimately, we should handle ‘ansi window’ by multi-byte buffer, and Unicode window by Unicode buffer in dealing with ‘WM-GETTEXT’. In other words, you will result having an abnormally functioning window if you have multi-byte pointer handling Unicode Window, and vice versa with ansi-window.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now, we’re going to cover how Unicode Window is created. Developing the Unicode Window involves the ‘RegisterClass’ function. Although no parameter of this function has the function of categorizing the new Window into the Unicode or not, it is decided automatically depending on the type of function it’s calling out. A window becomes a Unicode window when one uses the Unicode class is&lt;/p&gt;
&lt;p&gt;We can also identify if a particular Window is Unicode window or not by ‘Spy++ utility’. When we search through the Window and its property using Spy++, it shows ‘Unicode’ on Window Proc section. If it doesn’t have it, we can understand that it’s the ansi window.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 458px; margin-bottom: 16px;&apos; data-url=&apos;./Unicode_Windows_Internals.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5a51fcbc4aa4a4b538ccce81a702e55e/e5e51/Unicode_Windows_Internals.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 61.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACDUlEQVR42m1Sa4+aQBTl//+EfmjSJk2atummxqRttnHXXdRVHgLyFBAY3iAvEVwDSi/YL5t0cnKZOeHcOXNmMJwUcFrqKyUsJftFzZ7kdCICsokEyB+V4kHOH6V0tk2XWkrtUgaVvB7++PAR2wiKpuuapvOCSK8Zes0tXlYsJ1A0w3I8RbMEScmK6gWh5wc3uJ6fpMliSWKqbu7jOIpj23F4XoiiyDDReiMiL0RuYPvRDjleuM/LOj1UWVkDkqJ8bVqa2WCaYZqmoes6fCRJapomzfI1wziu2zZt13XX67WvXXergPZygTnNcJis7kzDkGVF07Qsy4CN45gkSUVRtoDtNvD98/lcHY9VXQ8dussgJtcbTNzqjm2zLKuq6uFwABYqKC3L4nkevIAj6AteoNFbMYdJqhEEPvwHzouiADbPc1mWYYkQAoFt29ACmPrtzgTNYbykWpapDA6hgsMkSWazmSiKbdvCgS/DuJ38P2Lfc0EIF1ZVFbAgxnEctroO46a8DPgXWNsHuQLbG0n1XLePfLdL9zGwp/oIl5cXRX06lUcIqoIJpAW4LWEC+iXF9oE153NxKPW04py9HOZ6dgqT1EbIMk24dtd10TAcx4EHEQQBBLSPIwJ2vp/ORUmhOeE7Ib//Q7z7Nf+6VKYLYjT++e1u9ITPH6bPd6MxAJjZYjWZPn/6/KUnx7//AoHOfq9En977AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Unicode Windows Internals md 0&apos; title=&apos;&apos; src=&apos;/static/5a51fcbc4aa4a4b538ccce81a702e55e/e5e51/Unicode_Windows_Internals.md_0.png&apos; srcset=&apos;/static/5a51fcbc4aa4a4b538ccce81a702e55e/08678/Unicode_Windows_Internals.md_0.png 190w,
/static/5a51fcbc4aa4a4b538ccce81a702e55e/2edd7/Unicode_Windows_Internals.md_0.png 380w,
/static/5a51fcbc4aa4a4b538ccce81a702e55e/e5e51/Unicode_Windows_Internals.md_0.png 458w&apos; sizes=&apos;(max-width: 458px) 100vw, 458px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;However, one could wonder, why is it so important to know whether it’s a Unicode window or not? First of all, it’s because there could be an error with the handler if we didn’t know about it. As seen below, Window class registration is left under Unicode window and the particular window message procedure: for eg; ‘WM_GETTEX’ is processes via multi-byte, which will obviously cause an error.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;WNDCLASSEXW wcex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
wcex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lpfnWndProc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; WndProc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RegisterClassExW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;wcex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;WndProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND wnd
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT message
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM w
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; WM_GETTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;StringCchCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lstrlenA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProcW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Secondly, this is one of the most important effect for any action related to the Window, which can complicate the system if you’re not fully aware of the system. Say for example, we are sub-classing a particular window. In this case also, we neede to use ‘SetWindowLongW’ for a Unicode, and ‘SetWindowLongA’ for multi-byte. If it were done in an opposite way, the original window message will be dealt with by the Unicode, with the procedure which sub-classes it using multi-byte system. Moreover, even when the original window is the Unicode window, it will turn into the ansi-window once the sub-classing is done via ‘SetWindowLongA’. Using the sub-classing function without the internal mechanisms as noted could cause a complicated conversion issues.&lt;/p&gt;
&lt;p&gt;Here is another example. Most message procedure consists of creating only the critical parts, leaving the rest upto the ‘DefWindowProc’ function, which could either be ‘DefWindowProcA’ or DefWindowProcW, which is where the problem could occur with the system not responding as expected in some cases. The window below shows the similar case. The case below refers to the similar case, when ‘defWindowProcW’ is called for after creating the ANSI window using ‘RegisterClass’ A function. If it were processed correctly, it would show Hello on the title bar, but you can notice something else instead below.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 337px; margin-bottom: 16px;&apos; data-url=&apos;./Unicode_Windows_Internals.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/501c1c5256bcfaa44ff76af6cbe0ca80/f57f1/Unicode_Windows_Internals.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 50.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABVElEQVR42mPonLZw2oKVHd29nb0TSqvq2rv7qxuaU7MLHLyDtczsdMwdrJx9XP3CcooqOnsntfZOntLaujorfntFbnd6EsPMhStXrd+xat2WhUtWzV+6euGyNbMWLOvsn5Zf3piaX5FWUJldXFtc3dLYMbFn8uyJMxZMn7UAiFfOX9je1sWwcevuS5fv33nw5tDhcw+efnjx9ufz19+B5Ov3v998+ANGv4Hsl29/vnjzA0S+/fnk9Y8P3/5v2LaP4dSZc//////9+/e/f//+IoE/qABZ4tevn0Athw4fZdi1dz+QBZT8TzQAmgUkN2/bwbB91144nyTNm7ZsZ9i0bQd5mtdu2Mywet1GIOvXr19/iQZAxUAty1etZVixZj2pNv8GK166YjVDRV3z1h27Vq3bAHTG+k1bN2zehoaAgus2bVmzYdPq9ZvWgNHKtRuAWkqrGwDot/b+W6nK/wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Unicode Windows Internals md 1&apos; title=&apos;&apos; src=&apos;/static/501c1c5256bcfaa44ff76af6cbe0ca80/f57f1/Unicode_Windows_Internals.md_1.png&apos; srcset=&apos;/static/501c1c5256bcfaa44ff76af6cbe0ca80/08678/Unicode_Windows_Internals.md_1.png 190w,
/static/501c1c5256bcfaa44ff76af6cbe0ca80/f57f1/Unicode_Windows_Internals.md_1.png 337w&apos; sizes=&apos;(max-width: 337px) 100vw, 337px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To avoid the mistakes mentioned previously, all we need is to have the understanding of the existence of Unicode and its procedure. Its procedure is that it uses W function for Windows, and A type for the multi-byte window. And lastly, that the related windows deal with messages by either Unicode or multi-byte.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Knowing the existence of Unicode window and being aware of what kind of disasters you might face, one could probably wonder how we could find out whether the window we are working on is a Unicode or not. There is a very simple function for it, called “IsWindowUnicode”. If you receive a false message after you type in “IsWindowUnicdoe(hwnd), it means that you’re working on an ansi-window, while if you have other answers instead of FALSE, your Window turns out to be a Unicode.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lastly, I would like to cover a few things. For those developers who have already tested the codes, you will notice that you end up getting ‘WM_GETTEXT’ no matter which one you type in out of ‘DefWindowProcA’ or ‘DefWindowProcW’ out of the Unicode or ansi. The reason for this is simple. If its coded as protectively as shown, it can solve the character string no matter the type of window that’s used.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_GETTEXT&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsWindowUnicode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hWnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;StringCchCopyW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPWSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lstrlenW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPWSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;StringCchCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lstrlenA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some of those who are reading this post might think that one should stick to ‘SendMessageW’ for Unicode, and ‘SendMessageA’ for ansi even when sending the message in a particular window. It is smart, but the reality is not as inconvenient as it seems. Through the test, you would notice the system delivering the correct answer no matter whether if you’ve used ‘SendMessageA’ or ‘SendMessageW’, as long as you have delivered the adequate buffer. In other words, ‘SendMessage’ function does all the hard work of appointing the adequate buffer or conversing the ‘IsWindowUnicode’ into ‘WideeCharToMultibyte’ etc. Moreover, other than WM_GETTEXT, ‘sendMessage’ functions as to adequately change the messages that we need the conversion on. All we need to remember is to use ‘SendMessage A’ for ansi, and ‘SendessageW ‘for the Unicode.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[저장소 업적 놀이… ㅋㅋ~]]></title><description><![CDATA[어제는 또 사고를 쳤습니다. 뭐냐구요? 버그죠 ㅋㅋ~ 반성하는 마음으로 디버깅을 밤새 하고는 이전 글에 적었던 충돌 문제도 해결했습니다. QA…]]></description><link>https://jiniya.net/wp/archives/5361</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5361</guid><pubDate>Fri, 25 Nov 2011 23:57:53 GMT</pubDate><content:encoded>&lt;p&gt;어제는 또 사고를 쳤습니다. 뭐냐구요? 버그죠 ㅋㅋ~ 반성하는 마음으로 디버깅을 밤새 하고는 &lt;a href=&quot;http://www.jiniya.net/wp/archives/5339&quot;&gt;이전 글에 적었던 충돌 문제&lt;/a&gt;도 해결했습니다. QA팀이 출근할 때에 맞춰서 따끈따끈한 빌드를 만들어 놔야겠다는 생각에 빌드를 돌려 놓고는 기다리다 심심해서 간만에 저장소 통계를 돌려 봤습니다. 예전에는 재미삼아 한 달마다 돌려서 개발팀끼리 업적 놀이도 하곤 했었는데 말이죠… ㅋㅋ~ 먹고 사는게 바쁘다보니 그런 것도 해본지가 한 백만년은 된 듯 하네욤. 절대로 우리 회사는 이런 걸로 개발자를 압박하거나 그러진 않습니다. ㅋㅋㅋ~ 여튼 랭킹 한 번 볼까요?&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 540px; margin-bottom: 16px;&apos; data-url=&apos;./저장소_업적_놀이_ㅋㅋ~.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/7ad7824300d29fc11a2cf55d5e163957/03ec9/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 40.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABf0lEQVR42hWQ6W7bMBCE9f6PUiB2LFEUKR46HOiKLYu6r8hJkKAtULQJGqB/OwYIYrHkzHy71rfjJTCrLKdD0p/GbZ/0OOI8PfZrWi+pmfP2KWsWL87uuAoLkzdr1q6pWfJpsMQoH97S6BrLWWffc7FoFOFTFG4Ra5malByl6H0xCN4xr/bUpNUo1azzH4XFe65m/BCs8eLnWAzc7zjvOOq7dMcadl/svcZzK0IqisI+H3b5Pn45Nn8bi3VMLVovtwQI4CJn5fciukZO6SDcH3wo7bONghoabdHp17n8XVYfxsKzXgNoXEPj5yO8XOOy1iOlvct2vOWkJE5JQL4v7knpYEA0k7fEQIyc4+tDfI2CNUjeUzVJvQTBEoAFGj0rWlE5KczMOp6+J8XPovlqhn8Dbgs5N84OCQ4fBK1dDEZrGm7h4WRjQ0ClxkW+W7nUEN77lz+X6rMCuSWn26jYKviBHaxaTLdlRltILgR9sMAaFmIUvGVAMJ91+9WaD/Mf9Vl1UGxoWR0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;              md 0&apos; title=&apos;&apos; src=&apos;/static/7ad7824300d29fc11a2cf55d5e163957/03ec9/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_0.png&apos; srcset=&apos;/static/7ad7824300d29fc11a2cf55d5e163957/08678/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_0.png 190w,
/static/7ad7824300d29fc11a2cf55d5e163957/2edd7/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_0.png 380w,
/static/7ad7824300d29fc11a2cf55d5e163957/03ec9/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_0.png 540w&apos; sizes=&apos;(max-width: 540px) 100vw, 540px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
역시 codewiz라는 감탄사가 절로 나오죠? 이건 어느 나라 깔때긴지? ㅋㅋ 무려 7개월 동안 연속 1등을 놓치지 않는 기염을 토했습니다. 4월에 zippolook에게 습격 받지만 않았어도 좀 더 장기간 집권할 수 있었는데 아쉽군요. 물론 이거보다 더 기가막힌 통계 자료가 있긴 하지만 그건 너무 심한 깔때긴것 같아서 자체 검열했습니다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;저장소 업적을 좀 살펴볼까요? 돈 좀 벌자는 우리의 염원을 담아서 GoldRush라 지었답니다. 실제로 캘리포니아로 골드러시를 갔던 분들의 말로가 어떻게 됐는지는 미처 고려하지 못했습니다. 흠흠. 작년 1월 22일에 저장소를 만들었네요. 무려 672일이나 됐군요. 하루 평균 3.6개를 커밋했습니다. 장난 아니죠? 우리 회사 개발자들이 참 열심히 합니다. 개발자가 13명이라고 나와있는데 실제로 이 저장소를 거쳐간 개발자는 6명입니다. zippolook이 어찌나 줏대 없이 아무 아이디나 막 쓰는지 혼자 4-5개를 썼더군요 헐~ ㅋㅋㅋ~&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Project name: GoldRush&lt;br&gt;
&lt;br&gt;
Generated: 2011-11-25 08:37:59 (in 227 seconds)&lt;br&gt;
&lt;br&gt;
Generator: GitStats (version d2b5b32)&lt;br&gt;
&lt;br&gt;
Report Period: 2010-01-22 17:02:59 to 2011-11-25 08:25:23&lt;br&gt;
&lt;br&gt;
Age: 672 days, 382 active days (56.85%)&lt;br&gt;
&lt;br&gt;
Total Files: 3482&lt;br&gt;
&lt;br&gt;
Total Lines of Code: 1220952 (1678694 added, 457742 removed)&lt;br&gt;
&lt;br&gt;
Total Commits: 2397 (average 6.3 commits per active day, 3.6 per all days)&lt;br&gt;
&lt;br&gt;
Authors: 13&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; margin-bottom: 16px;&apos; data-url=&apos;./저장소_업적_놀이_ㅋㅋ~.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/67c0f6ba68fb5907f2fbca7330605536/abf7b/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 45.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABeElEQVR42o2RzWrCQBDH168mmmhTo6WplkDryYMXIXjbi8qCQb0siogLHlQUUQ895zk895aXyAv02JOXglBKn2I7E1ooQUgXfkwmM/vf+SAEjhDCmM1mFfjUARXI/hP1giVkt9sZ4/H4vtVqZaWUSd/3U3F4kCcZU2SzmZO2rUrOr0i1iqIksV6v9clkYjchGCZ7XjqOz0ZDe6vX9dfFIoME8K+KgqvV6na5XFZA8NGGl+IEOcTP0Mk7pSqP5FqWlSOHw6Gy3++t0Wj0gIJxLWM1X1DZpVgoOJ/P85vNxsQZQvsKzgBEE1ECStOnWk35gEswtwwkJaCq5F9+FkMIVghbfqrBBXk8Zs6cZ6UQash2q0jXzYWAfwLflzIVBEE6SlghHlwKF+Juoeull2Kx8GyaecQrl3W0LiTiYwiOBYePNgpIaeT3TKdTjTNW7vV6N5RSgw4GhsNYYTgcmp1OR2u329cY63a7RbToI67rlhjkOY5T6Pf7+W9eQNi/0Atr/AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;              md 1&apos; title=&apos;&apos; src=&apos;/static/67c0f6ba68fb5907f2fbca7330605536/abf7b/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_1.png&apos; srcset=&apos;/static/67c0f6ba68fb5907f2fbca7330605536/08678/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_1.png 190w,
/static/67c0f6ba68fb5907f2fbca7330605536/2edd7/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_1.png 380w,
/static/67c0f6ba68fb5907f2fbca7330605536/abf7b/%EC%A0%80%EC%9E%A5%EC%86%8C_%EC%97%85%EC%A0%81_%EB%86%80%EC%9D%B4_%E3%85%8B%E3%85%8B~.md_1.png 620w&apos; sizes=&apos;(max-width: 620px) 100vw, 620px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
LOC 그래프입니다. 뭔가 좀 경이롭지 않나요? 도대체 5-8월에 무슨 일이 있었던 걸까요? 사실 저 시기가 거의 죽음의 시기이긴 했습니다. 진짜 밥만먹고 코딩했던 것 같네요. 밥도 안먹고 코딩했었나? ㅋㅋ 그래도 거품이 좀 심하죠. 사실 저 기간에 늘어난 LOC 중에 거의 대부분은 IP 지역을 저장하고 있는 SQL 파일이 주범입니다. 500k나 되더군요. 헐. 네 맞습니다. 전체 LOC 거의 절반이 그겁니다. 그래도 이전 버전에서 가져온 코드가 180k 정도니 그 사이에 정말 많이 늘긴 했네요.&lt;/p&gt;
&lt;p&gt;프로그래머라는 명함을 판지 한 10년 돼 가는것 같은데, XIGNCODE를 5년 동안 개발했으니 제 경력의 절반은 XIGNCODE와 함께 했다고 해도 과언이 아니네요. 당연히 이리 오래 걸린다는 걸 알았다면 시작도 안했을 겁니다. 겁나서요 ㅋ~ 그래도 오랜 기간 한 제품을 만들어 본다는 건 정말 무엇과도 바꿀 수 없는 멋진 경험인 것 같습니다. 누가 알아주지 않더라도 말이죠. ㅋㅋ~ 5년간 저의 세계는 XIGNCODE였습니다. 내년에도 그랬으면 좋겠네요. 세상의 모든 해킹툴을 잡아내는 현자의 알고리즘(?!)을 찾는 그날까지 달리고 또 달려야죠. 빌드가 끝났네요. 테스트하러 가야겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] Collision Hell…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5339</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5339</guid><pubDate>Fri, 25 Nov 2011 23:57:52 GMT</pubDate><content:encoded>&lt;p&gt;프로그래머로 밥 벌어 먹고 살면서 제일 싫어하는 단어가 생겼다. ‘크래시’, 밥 먹다가도 이 말만 들으면 먹던 내용물이 올라오는 느낌이 든다. 그만큼 듣기 싫은 말이고 짜증나는 말이며, 피하고 싶은 대상이다. 보안이라는 전문 분야를 정하고 나서는 싫어하는 단어가 하나 더 생겼는데 바로 ‘충돌’이다. 좋은 보안 프로그램을 만든다는 것은 달리 말하면 얼마나 많은 충돌을 피했는가로 귀결된다고 할 수 있다. 많은 보안 업체에서 자사 제품의 장점으로 내세우는 게 바로 다름아닌 충돌이 얼마나 없는가라는 사실도 이를 반증해 준다고 할 수 있겠다. 진짜 우습지 않은가? 보안 제품의 성능을 첫 번째 장점으로 말하는 것이 아니라 충돌이 없다는 것을 장점으로 말한다는 것이, 그런데 더 웃긴 건 고객들이 그걸 더 우선시한다는 점이다. 그만큼 실전에서 충돌은 아주 굉장히 중요한 요소다.&lt;/p&gt;
&lt;p&gt;5년간 게임 보안 제품을 만들면서 정말 온갖 충돌이란 충돌은 다 겪어 봤다고 생각했다. 유사 게임 보안 제품과의 충돌은 기본 안주고, 각종 타사 보안 제품들과의 충돌들이 있었다. 심지어는 게임 핵툴과의 충돌도 있었다. 커널 모드 게임 핵툴이 있었는데 그놈이 어설프게 작성하는 바람에 게임을 실행한 다음 그 핵툴을 실행하고, 그 상태에서 게임을 종료하면 블루스크린이 발생하는 문제가 있었다. 우습게도 우리는 충돌이 없다는 장점을 부각시키기 위해서 그 핵툴을 위해서 전체 훅 코드를 죄다 변경했다. 물론 지금 생각해보면 굉장한 오버 센스인데, 그 때는 그래야 하는 줄 알았다. 대단한 작업이었다. 훅코드를 죄다 변경했더니 이번에는 중국 방화벽 제품과 충돌이 발생했다. 그래서 해당 방화벽 제품을 위한 특수한 코드를 추가했다. 이런 식이다. 이 곳에는 신호등도 없고, 교통 법규도 없다. 그냥 무법 천지 세상에서 온갖 충돌을 피해야 한다. 그래서 이 세상에서는 경험이 닥치고 갑이며, 충돌을 피한다는 아무것도 아닌 사실이 우리의 가장 든든한 진입 장벽이 되어준다. 참 우스운 사실이다.&lt;/p&gt;
&lt;p&gt;이렇게 온갖 충돌을 겪었고, 그 온갖 충돌을 피하는 코드를 추가하다 보니 나름 이 바닥에서는 산전수전 다 겪었다고 생각을 했었다. 그랬는데. 오늘 진짜 핵폭탄 같은 충돌을 목격하고 말았다. 우리가 만드는 제품은 다름아닌 게임 보안 제품이다. 게임 프로그램이 동작하는 동안 부정 행위를 막아주는 그런 제품이다. 그런데 이런 게임 보안 제품이 게임 그 자체와 충돌이 발생하는 것이 아닌가? 좀 더 정확하게 말하자면 게임에 포함된 자체 보안 코드와 충돌이 발생하는 것이었다. 핡~ 게임 내 보안 코드가 게임 보안 제품을 잡는 우스운 상황. 정말 보고 어처구니가 없었다. 이렇게 말하고 보니 그 게임이 아주 큰 잘못을 한 것 같은데 사실은 전혀 그렇지 않다. 요즘은 워낙 해킹 이슈가 부각되다 보니 큰 게임 업체에서는 다들 자체 보안팀을 가지고 있고, 해당 보안팀에서도 게임의 보안을 향상 시키기 위한 모듈을 개발하기도 한다. 매우 바람직한 현상이며, 외부 보안 업체에게도 큰 힘이 되어준다. 왜냐하면 외부 보안 제품의 경우 게임과의 결합도가 일정 수준 이상으로 높아지기 힘들다는 단점이 있고 게임 개발팀과의 이야기를 하는데 한계가 있을 수 밖에 없는데 내부 보안팀은 그런 것들이 가능하기 때문이다. 어쨌든 해당 보안 코드는 자신의 의무를 다했다. 단지 우리는 다른 필요한 기능을 수행하기 위해서 그 코드의 사각 지대를 찾아야 할 뿐이다.&lt;/p&gt;
&lt;p&gt;여기까지만 딱 읽으면 우리가 항상 충돌을 당하는 입장처럼 보인다. 하지만 사실은 우리가 더 많은 충돌을 야기시키는 주범이기도 하다. 그런 불이익을 당하는 대부분의 프로그램은 게임 유틸리티다. 그런 유틸리티 중에 유명한 프로그램으로 반디캠이 있다. 게임 동영상을 촬영하는 유틸리티인데, 나도 한 때 와우 동영상을 찍기 위해서 애용하던 제품이었다. 프랩스보다 훨씬 강력한 유틸리티다. 그런 반디캠도 게임 보안 제품과 충돌이 잦은 편이다. 물론 우리 제품과도 다소 충돌이 있었다. 그래서 허용 처리를 해주었다. 이런 허용 처리를 하다 보면 반디캠의 신묘한 후킹 코드에 놀라곤 한다. 왜 당췌 이런 정상적인 유틸리티가 이리도 복잡한 방식으로 후킹을 하는 것일까, 라는 생각이 들었던 적이 한두 번이 아니었다. 대놓고 나는 반디캠 후킹 코드요, 라고 우리한테 말해 준다면 우리가 한결 허용 처리 하기가 쉬웠을 것이기 때문이다. 하지만 실상은 반디캠 개발자 분도 똑같은 고민이 있었음에 틀림이 없다. 보안 제품과의 충돌을 피하는 것이 그 제품에는 하나의 장점이 될 수도 있었을 것이기 때문이다. 그래서 보안 제품에 탐지되면 그걸 피하기 위한 보다 복잡한 방식을 생각해내다 보니 거기까지 가신 것이 아닐까?&lt;/p&gt;
&lt;p&gt;어쨌든 이쯤되면 한 가지 생각이 들 것이다. 사실 이 모든 게 정말 바보 같다는 사실이다. 충돌을 당하는 입장에는 그 충돌을 피하기 위해서 더 복잡한 코드를 작성하고, 충돌을 야기시킨 입장에서는 그 복잡해진 코드를 허용하기 위해서 더 복잡한 코드를 작성한다는 점이다. 즉, 여기엔 기본적으로 엔트로피를 증가시키는 악순환의 피드백 루프가 내장되어 있는 것이다. 이런 맥락에서 오늘밤 내가 작성할 코드도 언젠가는 그 게임에 내장된 자체 보안 코드를 작성한 분에겐 애물단지가 될 것이다. 내가 충돌을 피하기 위해서 작성한 복잡한 코드가 그걸 작성한 사람에게 다시 충돌이 되어 돌아가는 정말 요지경 같은 구조, 보고 있으면 그저 웃음 밖에는 나오질 않는다.&lt;/p&gt;
&lt;p&gt;예전에 어떤 TCP/IP 책인지 모르겠는데 CSMA/CD 설명이 나와 있는 책을 읽었던 적이 있었다. CSMA/CD 설명을 읽고는 참 심플하면서 신묘한 방법이라는 생각이 들었다. 오늘 밤, 또다시 충돌을 피하기 위한 코드를 작성하보니 CSMA/CD의 Collision Detect라는 말이 생각난다. 우리에겐 이 악순환의 피드백 루프를 끊고 자동으로 충돌을 탐지할 수 있는 방법이란 없을까?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[디버깅 0교시: 절차대로]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/3997</link><guid isPermaLink="false">https://jiniya.net/wp/archives/3997</guid><pubDate>Fri, 04 Nov 2011 23:57:51 GMT</pubDate><content:encoded>&lt;p&gt;요즘 여기 저기 다른 일들로 불려 다니는 경우가 많다 보니 회사에서 진득하게 앉아서 코딩을 해 본 적이 거의 없는 것 같다. 난 개발이 좋고, 개발 일을 할 때가 가장 행복하고, 가장 잘하는 것도 개발이지만, 그렇다고 개발만하고 살수는 없는 거니까. 현실 세계에서 살아남으려면 결국 손에 물을 묻히기도 해야 하는 법이다. 어쨌든. 그러다 어제 조금 한 숨 돌릴 짬이 났다. 신규 업체에 SDK 파일들을 전달해 주기에 앞서서 이번에 새로 추가된 기능도 있고, 매뉴얼도 업데이트된 부분이 있어서 개발팀 막내에게 숙제를 하나 내주게 되었다. TCP/IP로 간단한 소켓 통신 프로그램을 만들고, 거기다 매뉴얼보고 그대로 적용을 해보라는 것이었다. 개밥 먹기라고 했던가? 우리가 만든 것들이 제대로 되는지 확인해보고자 하는 심산이었다.&lt;/p&gt;
&lt;p&gt;뭐 어쨌든 돌아가는 놈들이니 다소 우여곡절이 있었지만 적용은 되었고 테스트가 진행이 되었다. 그런데 이상한 문제가 하나 발생했다. 이상하게 먼가가 정상적으로 돌아가지 않는 것이었다. 딱 2시간 걸린 것 같다. 막내가 매뉴얼에 적혀 있는 초기화 함수를 호출하지 않았던 것이었다. 로그 파일만 봐도 알법한 이 문제를 찾는데 2시간이나 걸리다니. 하지만 이건 복선에 불과했다.&lt;/p&gt;
&lt;p&gt;그 아주 가벼운 문제를 해결하고 심층 테스트로 넘어가려고 하는 순간 정말 요상한 문제가 발생했다. 이상하게 새로 만든 클라이언트와 서버 사이의 통신이 안되는 것이었다. 그것도 아주 통신이 안되는 것이 아닌 우리가 전달하려고 하는 일부 패킷만 이상해지는 문제였다. 이 문제가 좀 더 심오하게 보이는 이유는 새로운 서버에 기존 클라이언트로 접속하면 잘 되었고, 기존 서버에 새로운 클라이언트로 접속하면 잘되기 때문이었다. 정말 희한하게 새로운 서버와 새로운 클라이언트만 통신을 하면 이상해지는 문제였다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; margin-bottom: 16px;&apos; data-url=&apos;./디버깅_0교시_절차대로.md_0.jpg&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c07e2711441dcf43aaed37ca9bc5408a/56d4e/%EB%94%94%EB%B2%84%EA%B9%85_0%EA%B5%90%EC%8B%9C_%EC%A0%88%EC%B0%A8%EB%8C%80%EB%A1%9C.md_0.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 75.26315789473684%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB0bVJjIoJ/8QAGhAAAgMBAQAAAAAAAAAAAAAAABIBAhETIf/aAAgBAQABBQL0aTR648HWp//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABcQAQEBAQAAAAAAAAAAAAAAAAAxECH/2gAIAQEABj8C5tVX/8QAGxABAAICAwAAAAAAAAAAAAAAAQARECFBcdH/2gAIAQEAAT8hUhrgQsqHLqFMNvif/9oADAMBAAIAAwAAABBXH//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/EKf/xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxCH/8QAHBABAAMBAAMBAAAAAAAAAAAAAQARITFBUbHR/9oACAEBAAE/EFJq014HuXaNm0eWXZ7AigAFW/IzDa3jDU+k/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;    0        md 0&apos; title=&apos;&apos; src=&apos;/static/c07e2711441dcf43aaed37ca9bc5408a/56d4e/%EB%94%94%EB%B2%84%EA%B9%85_0%EA%B5%90%EC%8B%9C_%EC%A0%88%EC%B0%A8%EB%8C%80%EB%A1%9C.md_0.jpg&apos; srcset=&apos;/static/c07e2711441dcf43aaed37ca9bc5408a/8ccab/%EB%94%94%EB%B2%84%EA%B9%85_0%EA%B5%90%EC%8B%9C_%EC%A0%88%EC%B0%A8%EB%8C%80%EB%A1%9C.md_0.jpg 190w,
/static/c07e2711441dcf43aaed37ca9bc5408a/ea4c8/%EB%94%94%EB%B2%84%EA%B9%85_0%EA%B5%90%EC%8B%9C_%EC%A0%88%EC%B0%A8%EB%8C%80%EB%A1%9C.md_0.jpg 380w,
/static/c07e2711441dcf43aaed37ca9bc5408a/56d4e/%EB%94%94%EB%B2%84%EA%B9%85_0%EA%B5%90%EC%8B%9C_%EC%A0%88%EC%B0%A8%EB%8C%80%EB%A1%9C.md_0.jpg 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
새벽 4시였던가? 우리는 김밥천국에 앉아서 이 요상한 문제에 대해서 이야기를 했다. 김밥천국 주문서 쪽지에 그림을 그려가며, 떡볶이 국물을 튀겨가며, 이 이해할 수 없는 문제의 원인에 대해서 토론을 했다. 그 때가 디버깅하고 한 6시간은 지났던 시간이었던 것 같다. 그리곤 김밥을 먹고는 올라가서 디버깅을 이어갔다. 이 알 수 없는 문제를 해결하기 위해서 한 10가지 프로젝트를 열었고, 여기저기 단서를 추적하기 위한 내용들을 추가했다. 그리곤 결국 10시간 정도 지나서 문제를 찾았는데 다름 아닌 새로 만든 서버가 엉뚱한 내용을 클라이언트에 전달하고, 그 클라이언트가 그 내용을 우리 SDK에 바로 전달해서 발생한 문제였다. 로그 파일에 선명하게 남아있는 PacketError, 사실 로그 파일만 열어봤어도 이렇게 오랜 시간 디버깅을 할 필요가 없었을 텐데. 그 절차를 아무도 따르지 않았던 것이었다.&lt;/p&gt;
&lt;p&gt;디버깅을 할 때면 ‘말렸다’는 표현을 쓸 때가 있다. 엉뚱한 곳에 휘말려서 정작 중요한 부분을 보지 못하고 헤매는 경우에 쓰는 말이다. 이렇게 ‘말리는’ 상황을 미연에 방지하기 위해서는 항상 침착하게 절차대로 디버깅을 진행해야 한다. 더불어 자신이 가진 모든 증거를 차근차근 나열해서 꼼꼼하게 생각하는 습관을 들여야 한다. 절대로 증거가 아닌 현상에 휩싸여서는 안된다. 그럼 지는 거다.&lt;/p&gt;
&lt;p&gt;힘겨웠던 디버깅 세션을 마치고 집으로 돌아가는 길. WoW에 미쳤던 시절이 떠올랐다. 공대에서 불타는 성전의 거의 마지막 던전인 검은 사원을 트라이 하고 있었던 때였다. 나는 주말 공대였지만 평일에 다른 레이드 던전을 재미 삼아 다니다 보면 으레 지쳐서 5인 던전은 엄두도 못 낼 때가 많았다. 이런 상황임에도 우리 공대에는 하루도 거르지 않고 5인 영던을 꼬박꼬박 다니는 두 놈이 있었다. 한 날 그 녀석들과 영던 나들이를 갔다가 궁금해서 물었다. 지치지도 않냐고, 무슨 재미도 없는 영던을 그리 맨날 다니냐, 라는 질문. 대답이 가관이었다. 감각을 잃지 않으려면 매일 수련을 해야 한다는 것이었다. 레이드 던전을 매일 갈수는 없으니 영던에서 수련을 한다는 대답이었다. 게임 훼인스런 대답이긴 하지만 여기서 우리가 배울 점이 하나도 없는 것은 아니다. 녀석들의 말은 사실 게임을 떠나서 어떤 분야에든 적용될 수 있는 말이기 때문이다.&lt;/p&gt;
&lt;p&gt;“숙련됨은 연습을 중단하는 그 시점부터 퇴보하기 시작한다.” 당신이 프로그램을 짜지않는 하루하루마다 숙련공으로 가는 길은 점점 더 멀어져 간다. – 프로그래머의 길, 멘토에게 묻다.&lt;/p&gt;
&lt;p&gt;수련을 게을리하는 순간 우리는 퇴보한다. 그런 수련을 게을리한 나에게 일침을 놓는 디버깅 세션이었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[05. 무한 루프를 다스려라, 2001]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5333</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5333</guid><pubDate>Tue, 01 Nov 2011 23:57:50 GMT</pubDate><content:encoded>&lt;p&gt;안녕하세요~ 요즘 몇일동안 강좌 올리는 플그램을 만드느라 강좌를 못 올렸음당. 지금은 거의 반쯤 완성된 단계라서, 일케 편하게 강좌를 올릴 수 있게 되었네요. 앞으로는 틈틈히 남는 시간을 이용해서 이렇게 강좌를 올리도록 하겠습니다. 그럼 오늘은 while을 이용한 무한루프의 세계로 한번 가 보도록 합시다~&lt;/p&gt;
&lt;p&gt;우선 간단하게 while문의 문법을 알아보도록 하겠습니다. 지난 시간에 배운 for문은 그 구조가 상당히 복잡한 반면에 while문은 문장 구조 자체가 단순하므로 배우기가 수월 하실겁니다. 그럼 아래 소스를 보도록 하죠~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token comment&quot;&gt;// 위에것과 같은 for문 루틴 &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예제를 보면 금방 이해가 가실 겁니다. 지난 시간에 배운 for문에 대해서 확실하게 숙지하고 계시는 분들은 훨씬 더 이해하기가 쉽겠죠~ 그럼 while문을 잠시 살펴보도록 합시다. while다음에 오는 괄호에 인자로 들어가는 것은 조건문 입니다. 그 조건문인 참인 동안 아래있는 반복할 문장을 실행 시키는 거죠. 아주 쉽죠?! 그럼 오늘 배울 무한루프의 세계로 한번 날아가 봅시다~&lt;/p&gt;
&lt;p&gt;A Book On C라는 책의 첫머리에 이런 말들이 나옵니다. C언어에서 0은 매우 다양하고 특이한 의미들로 사용된다. 0은 모든 숫자의 시작이며, 문자열 배열의 끝을 알리는 기호이며, 또한 메모리 가비지 값을 초기화 시키는 값으로 사용된다. 뿐만 아니라 모든 배열의 시작또한 0에서 한다. 그리고 0은 거짓을 의미하는 기호이기도 하다. 제가 대충 생각나는대로 적었는데, 아마도 말은 틀리지만 의미는 비슷한 글이었을 것 입니다. 그렇습니다. C언어에서 0그렇게 다양한 의미로 사용되고, 그 중에 오늘 배울 의미중의 하나가, 바로 거짓을 나타내는 기호입니다. 그럼 다음 문장을 보도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 거짓이다... &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 참이다... &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 무엇일까? &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 무엇일까? &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위에서 서술한 것을 보면 0은 거짓으로 나와있고 1은 참이라고 나와있다. 다른 것은 무엇일까?! 여러분은 어떻게 생각하나요?! 위의 글을 충분히 읽었다면 당연하게 상상을 해 낼 수 있을 겁니다. 0은 특별한 의미의 기호로 사용되고 있다는 것을 여러분들은 아실 수 있을 겁니다. 그러니 당연히 거짓의 0도 특별한 의미겠죠. 그럼 0이외의 다른 값들은 바로 다 참인 것 입니다. 그럼 아래있는 구문은 어떻게 될까요?!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;이건 볼 수 없습니다...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위에 있는 소스는 한줄도 실행되지 않습니다. 왜 일까요?! 바로 whlie안의 조건문이 처음부터 거짓이기 때문입니다. 반면에 다음 예제는 어떤가요?!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;이건 계속 볼 겁니다...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 프로그램을 실행하면 여러분들은 끝없는 문장을 보게 될 겁니다. 헤헤. 이런 프로그램을 어디다 써 먹을려고 작성을 하냐구요~ 그럼 다음 프로그램을 한 번 봅시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;yes&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예는 끝없이 yes를 출력하는 프로그램입니다. 이것두 쓸모없어 보이나요?! 하지만 매우 가치있는 프로그램임을 여러분들은 곧 알게 될 겁니다. 실제로 Unix에는 yes라는 프로그램이 있습니다. 바로 위와 같은 기능을 하는 프로그램이죠~ 어디다 써먹냐 하면, 몇몇 성가신 명령어들 | yes 이렇게 하면 계속 반복된 질문을 하는 프로그램들에게 yes라고 타이핑 할 필요없이 자동으로 넘어가게 되는 것 입니다. 아마도 유닉스를 사용해 보신 분들은 알겠지만 사용해 보지 않으신 분들은 그냥 그런게 있다 하는 정도로 넘어 가도록 하죠~&lt;/p&gt;
&lt;p&gt;그럼 이제 그 무한 루프를 제어하는 두가지 비밀병기를 알아보도록 하겠습니다. 하나는 break라는 넘이고 또 하나는 continue라는 넘입니다. 이제 설명할 내용들은 while문을 중심으로 설명하지만, for문에서도 똑같이 적용된다는 사실을 알았으면 합니다. 그럼 그 두 넘이 무슨 일을 하는지 알아보기 위해서 간단한 소스코드를 보면서 이해해 보도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ............. 1번 &lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// ............ 2번 &lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;번 

   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;번 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;츨력 결과가 어떻게 될까요?! 다들 지금 한번 실행시켜 보십시요. 아마도 화면에는 이렇게 출력이 될 겁니다. 1, 3만 출력 될 겁니다. 왜 그렇게 될까요?! 궁금하죠?! 위에서 continue라는 키워드를 만나게 되면 루프의 조건문 i에게로 다시 돌아갑니다. 그러니 뒤에 있는 것들은 무시가 되는 것이죠~ 반면에 break를 만나면 루프를 탈출해 버리는 겁니다. 실제로 위에 있는 예제는 무한루프입니다. 왜 그럴까요? i가 1부터 계속 증가하기때문에 영원히 거짓은 될수가 없는 겁니다.(추신 : 하지만 실제 시스템 상에서는 종료 될수도 있습니다. 정수의 한계를 넘어서서 오버플로우 되어 다시 0이 되는 경우에 그런 가능성이 있습니다). 그러면 어떤 순서로 수행되었는지 한번 알아봅시다.&lt;/p&gt;
&lt;p&gt;처음에 1번이 실행될 겁니다. 그러면 i값이 1이 되니까 참이 되겠죠. 여기서 여러분들이 한가지 상기하셔야 할 것은 ++이라는 연산자 입니다. 이 ++이라는 넘은 단순하게 변수를 1 증가 시키는 역할을 하지만, 변수의 앞에 쓰이는 것과 뒤에 쓰이는 것은 천지 차이가 있습니다. 위의 while(++i)는 참이 되지만. while(i++)은 거짓이 됩니다. 왜 그런가 하면 을 앞에서 쓰게 되면 변수의 값을 먼저 증가시킨 다음에 식에 반영을 합니다. 하지만 뒤에 쓰게 되면 식을 해석하고 난 다음에 나중에 변수값을 증가시키는 거죠. 하여튼 그래서 i는 1이 되고 1번은 참이므로 블록안에 있는 것들이 실행됩니다. 그러면 조건문을 만나게 되는데, i % 2 == 0는 무엇을 의미하는 조건문 입니까?! i를 2로 나누어서 나머지가 0과 같으냐를 묻는 조건문 입니다. 당연히 실행이 안 되겠죠. 그 다음것도 실행이 안됩니다. 그래서 4번이 실행되고 다시 1번으로 돌아가서 i값은 2가 됩니다. 역시 참이죠. 그래서 또 블록안의 것이 실행이 되고, i % 2가 참이 되게 됩니다. 그러면 continue를 만나게 되고. 그렇게 되면 다시 바로 1번으로 돌아가는 겁니다. 지금까지의 순서를 한번 정리 해 볼까요?!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1번 — 4번(1출력) — 2번 — 1번 — 4번(3출력) — 1번 — 2번 — 1번 — 3번 — 종료&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;위의 순서대로 되는 겁니다. break는 이해가 가죠. 바로 루프를 타출하는 기능입니다. 그러면 오늘 강좌는 여기까지 하도록 하겠습니다. 다들 충분히 이해하셨죠. 처음 배우는 분들은 continue의 개념을 잘 이해하지 못하는데. 그 부분을 집중적으로 한번 살펴보세요~ 그럼 다들 좋은 하루 되세요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;숙제!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;뭐물래?! 를 출력해서 사용자가 먹고 싶은 것을 입력 받는다. 사용자가 99를 입력하면 프로그램이 종료되도록 하여라. 99를 입력하기 전까지는 무한대로 입력받을 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[유니코드 윈도우의 정체]]></title><description><![CDATA[윈도우 환경에서 개발 경험이 있는 많은 개발자들이 유니코드(Unicode…]]></description><link>https://jiniya.net/wp/archives/4760</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4760</guid><pubDate>Tue, 01 Nov 2011 23:57:49 GMT</pubDate><content:encoded>&lt;p&gt;윈도우 환경에서 개발 경험이 있는 많은 개발자들이 유니코드(Unicode) 함수에 대해서는 잘 알고 있는데, 정작 유니코드 윈도우에 대해서는 잘 모르는 경향이 있다. 왜 그럴까? 대다수 책에서 이를 직접적으로 설명하지 않기 때문이 그 첫 번째 이유고, 이 내용이 윈도우 API에 의해서 잘 감춰져 있기 때문이 그 두 번째 이유다. 이런 내용을 모르고 고통 받는 많은 루키 개발자들을 위해서 유니코드 윈도우에 대해서 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;유니코드 윈도우를 이해하기 위해서는 기본적으로 윈도우에서 제공하는 유니코드 함수들의 동작 구조에 대해서 잘 이해하고 있어야 한다. 윈도우는 문자열을 취급하는 대부분의 함수에 대해서 A가 붙은 멀티바이트(multi-byte) 버전과 W가 붙은 유니코드 버전을 제공한다. GetWindowTextA가 있다면 GetWindowTextW가 있는 셈이다. 물론 각 함수의 기능은 동일하며 A 함수는 파라미터로 char 포인터를, W 함수는 파라미터로 wchar_t 포인터를 전달받는 차이점이 있다. 그렇다면 GetWindowText는 무엇인가? 그건 아래와 같이 매크로로 재정의된 함수다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifdef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;_UNICODE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;GetWindowText&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;GetWindowTextW&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;GetWindowText&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;GetWindowTextA&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 우리의 빌드 환경이 유니코드라면 GetWindowText는 GetWindowTextW가 되고, 멀티바이트라면 GetWindowTextA가 되는 것이다. 그래서 이 시스템에서는 다음에 나오는 코드와 같이 T형 중립(neutral) 문자형을 사용하고, A, W가 없는 매크로로 재정의된 중립 API를 사용하고, 문자열 처리에도 매크로로 재정의된 T계열 중립 함수를 사용하면 유니코드, 멀티바이트 빌드에 상관 없는 코드를 만들 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;TCHAR buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_PATH&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;GetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;_tcscat_s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ARRAYSIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;$&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우 하부 시스템이(window subsystem) 모든 것을 잘 포장하고 있기 때문에 유니코드, 멀티바이트에 대한 고려 없이 프로그램을 작성해도 빌드에 따라서 적절하게 컴파일되고 잘 동작하지만, 정작 변환(conversion) 문제가 발생하면 내부 구조를 모르고는 어디서, 왜 문제가 발생했는지를 알 수 없는 구조라 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이제 본론으로 들어가서 유니코드 윈도우에 대해서 알아보자. 유니코드 윈도우란 무엇인가? 메시지(message) 처리에 유니코드를 사용하는 윈도우를 말한다. 그러니 당연히 안시(ansi) 윈도우도 있고, 그건 멀티바이트로 메시지를 처리하는 윈도우를 말한다.&lt;/p&gt;
&lt;p&gt;똑똑한 개발자라면 메시지를 멀티바이트, 유니코드로 처리한다는 것은 무엇을 의미하는 거지, 라는 새로운 의문이 들 것이다. 간단한 예를 통해서 살펴보도록 하자. WM_GETTEXT라는 메시지를 보자. 이 메시지의 wParam은 글자 개수를, lParam은 글자를 저장할 수 있는 버퍼의 포인터를 지정한다. 문제는 여기서 시작된다. 그렇다면 lParam으로는 유니코드 버퍼를 전달해야 할까? 아니면 멀티바이트 버퍼를 전달해야 할까? 다음과 같은 코드에서 StringCchCopyW를 쓰는 것이 옳은지, StringCchCopyA를 쓰는지가 옳은지를 묻는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;MyWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND hwnd
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT msg
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM w
                              &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; WM_GETTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;token comment&quot;&gt;// StringCchCopyW((LPWSTR) l, w, L&quot;MyWindowText&quot;);&lt;/span&gt;
         &lt;span class=&quot;token comment&quot;&gt;// or&lt;/span&gt;
         &lt;span class=&quot;token comment&quot;&gt;// StringCchCopyA((LPSTR) l, w, &quot;MyWindowText&quot;);&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hwnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아마 대부분의 개발자가 이런 것에는 신경 써 본 적이 없을 것이다. 윈도우 하부 시스템이 이를 굉장히 잘 감추고 있기 때문이다. 결론부터 말하면 WM_GETTEXT의 버퍼를 유니코드 윈도우는 유니코드 버퍼로, 안시 윈도우는 멀티바이트 버퍼로 취급해야 한다. 유니코드 윈도우가 멀티바이트 포인터로 이를 처리하고, 반대로 안시 윈도우가 유니코드 문자열로 처리하면 이상하게 동작하는 윈도우가 만들어진다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그럼 이제 유니코드 윈도우는 어떻게 생성되는지에(created) 대해서 알아보자. 유니코드 윈도우의 생성에는 RegisterClass라는 윈도우 클래스(class) 등록 함수가 개입한다. 물론 이 함수의 어떤 파라미터도 생성될 윈도우가 유니코드인지 아닌지를 결정하는 것은 없다. 그렇다면 어떻게 결정되는 것일까? 바로 호출하는 함수의 종류에 따라서 자동으로 결정한다. RegisterClassW 함수를 사용해서 윈도우 클래스를 등록하면 해당 클래스로 생성되는 윈도우는 유니코드 윈도우가 된다. 반대로 RegisterClassA 함수를 사용해서 윈도우 클래스를 등록하면 해당 윈도우는 멀티바이트 윈도우가 되는 것이다. 이렇게 생성 과정이 감추어져 있기 때문에 많은 개발자가 윈도우가 유니코드인지 아닌지에 대해서 잘 모르고 지나치게 된다.&lt;/p&gt;
&lt;p&gt;화면에 존재하는 특정 윈도우가 유니코드 윈도우인지 아닌지는 Spy++ 유틸리티를 통해서 살펴볼 수 있다. Spy++을 사용해서 해당 윈도우의 속성을 살펴보았을 때 다음 그림에 나타난 것처럼 Window Proc 부분에 Unicode라는 말이 있다면 해당 윈도우는 유니코드 윈도우인 것이고, 이런 표시가 없다면 안시 윈도우라고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 458px; margin-bottom: 16px;&apos; data-url=&apos;유니코드_윈도우의_정체.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5a51fcbc4aa4a4b538ccce81a702e55e/e5e51/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 61.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACDUlEQVR42m1Sa4+aQBTl//+EfmjSJk2atummxqRttnHXXdRVHgLyFBAY3iAvEVwDSi/YL5t0cnKZOeHcOXNmMJwUcFrqKyUsJftFzZ7kdCICsokEyB+V4kHOH6V0tk2XWkrtUgaVvB7++PAR2wiKpuuapvOCSK8Zes0tXlYsJ1A0w3I8RbMEScmK6gWh5wc3uJ6fpMliSWKqbu7jOIpj23F4XoiiyDDReiMiL0RuYPvRDjleuM/LOj1UWVkDkqJ8bVqa2WCaYZqmoes6fCRJapomzfI1wziu2zZt13XX67WvXXergPZygTnNcJis7kzDkGVF07Qsy4CN45gkSUVRtoDtNvD98/lcHY9VXQ8dussgJtcbTNzqjm2zLKuq6uFwABYqKC3L4nkevIAj6AteoNFbMYdJqhEEPvwHzouiADbPc1mWYYkQAoFt29ACmPrtzgTNYbykWpapDA6hgsMkSWazmSiKbdvCgS/DuJ38P2Lfc0EIF1ZVFbAgxnEctroO46a8DPgXWNsHuQLbG0n1XLePfLdL9zGwp/oIl5cXRX06lUcIqoIJpAW4LWEC+iXF9oE153NxKPW04py9HOZ6dgqT1EbIMk24dtd10TAcx4EHEQQBBLSPIwJ2vp/ORUmhOeE7Ib//Q7z7Nf+6VKYLYjT++e1u9ITPH6bPd6MxAJjZYjWZPn/6/KUnx7//AoHOfq9En977AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;             md 0&apos; title=&apos;&apos; src=&apos;/static/5a51fcbc4aa4a4b538ccce81a702e55e/e5e51/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_0.png&apos; srcset=&apos;/static/5a51fcbc4aa4a4b538ccce81a702e55e/08678/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_0.png 190w,
/static/5a51fcbc4aa4a4b538ccce81a702e55e/2edd7/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_0.png 380w,
/static/5a51fcbc4aa4a4b538ccce81a702e55e/e5e51/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_0.png 458w&apos; sizes=&apos;(max-width: 458px) 100vw, 458px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그렇다면 왜 그렇게 윈도우가 유니코드인지 아닌지가 중요할까? 첫째는 이를 모르는 경우에는 메시지 핸들러를 잘못 작성할 수 있기 때문이다. 다음 코드와 같이 윈도우 클래스 등록은 유니코드 윈도우로 해두고 해당 윈도우의 메시지 프로시저의 WM_GETTEXT같은 것은 멀티바이트로 처리해 버리는 것이다. 이러면 당연히 오류가 발생한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;WNDCLASSEXW wcex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
wcex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lpfnWndProc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; WndProc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RegisterClassExW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;wcex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

LRESULT CALLBACK &lt;span class=&quot;token function&quot;&gt;WndProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HWND wnd
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UINT message
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM w
                        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; WM_GETTEXT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;StringCchCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lstrlenA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DefWindowProcW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;둘째는 윈도우와 관련된 모든 행동을 할 때에 이것은 굉장히 중요하게 작용하기 때문이다. 이를 모르면 엉뚱하게 시스템을 헝클어 버리는 경우가 발생할 수 있다. 특정 윈도우를 서브클래싱을 한다고 해보자. 이 경우에도 유니코드 윈도우라면 SetWindowLongW를, 멀티바이트 윈도우라면 SetWindowLongA를 사용해야 한다. 만약 반대로 호출했다면 원본 윈도우는 유니코드로 메시지를 처리하고, 그걸 서브클래싱한 윈도우 프로시저는 멀티바이트로 처리하는 등의 혼선이 발생한다. 또한 원본 윈도우는 유니코드 윈도우였음에도 SetWindowLongA를 사용해서 서브클래싱하는 순간 해당 윈도우는 안시 윈도우로 변경된다. 이러한 내부 메커니즘을 모르고 서브클래싱을 하면 복잡한 변환 문제에 봉착할 수 있다.&lt;/p&gt;
&lt;p&gt;한가지 예를 더 들어보자면 이런 경우도 있다. 보통 메시지 프로시저는 필요한 부분만 작성하고 나머지 부분은 DefWindowProc 함수에 위임한다. 그런데 이 DefWindowProc함수도 DefWindowProcA가 있고, DefWindowProcW가 있다. 여기서 문제가 발생한다. 윈도우는 유니코드로 생성해놓고 DefWindowProcA를 호출한다거나, 윈도우는 멀티바이트로 생성해놓고 DefWindowProcW를 호출하는 것이다. 물론 이렇게 호출하면 대부분의 함수에 대해서 정상 동작하지만 일부 메시지에 대해서는 우리가 기대한대로 동작하지 않는 문제가 발생한다. 아래 윈도우는 그런 경우를 보여주고 있다. RegisterClassA 함수를 사용해서 ANSI 윈도우를 만들고 DefWindowProcW를 호출할 경우다. 정상적으로 처리됐다면 타이틀바에 Hello가 출력돼야 하지만 이상한 글자가 출력되고 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 337px; margin-bottom: 16px;&apos; data-url=&apos;유니코드_윈도우의_정체.md_1.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/501c1c5256bcfaa44ff76af6cbe0ca80/f57f1/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 50.526315789473685%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABVElEQVR42mPonLZw2oKVHd29nb0TSqvq2rv7qxuaU7MLHLyDtczsdMwdrJx9XP3CcooqOnsntfZOntLaujorfntFbnd6EsPMhStXrd+xat2WhUtWzV+6euGyNbMWLOvsn5Zf3piaX5FWUJldXFtc3dLYMbFn8uyJMxZMn7UAiFfOX9je1sWwcevuS5fv33nw5tDhcw+efnjx9ufz19+B5Ov3v998+ANGv4Hsl29/vnjzA0S+/fnk9Y8P3/5v2LaP4dSZc//////9+/e/f//+IoE/qABZ4tevn0Athw4fZdi1dz+QBZT8TzQAmgUkN2/bwbB91144nyTNm7ZsZ9i0bQd5mtdu2Mywet1GIOvXr19/iQZAxUAty1etZVixZj2pNv8GK166YjVDRV3z1h27Vq3bAHTG+k1bN2zehoaAgus2bVmzYdPq9ZvWgNHKtRuAWkqrGwDot/b+W6nK/wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;             md 1&apos; title=&apos;&apos; src=&apos;/static/501c1c5256bcfaa44ff76af6cbe0ca80/f57f1/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_1.png&apos; srcset=&apos;/static/501c1c5256bcfaa44ff76af6cbe0ca80/08678/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_1.png 190w,
/static/501c1c5256bcfaa44ff76af6cbe0ca80/f57f1/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98_%EC%A0%95%EC%B2%B4.md_1.png 337w&apos; sizes=&apos;(max-width: 337px) 100vw, 337px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;앞서 언급한 실수를 방지하기 위해서는 그저 유니코드 윈도우의 존재와 그것이 처리되는 방식에 대해서만 이해하고 있으면 된다. 여기서 그것이 처리되는 방식이란 유니코드 윈도우는 윈도우 관련 함수에 W계통의 함수를 사용하고, 멀티바이트 윈도우는 A계통의 함수를 사용해야 한다는 것. 그리고 해당 윈도우들은 메시지를 유니코드나 멀티바이트로 처리한다는 점이다. 이것만 기억한다면 바보 같은 실수를 하지 않을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;유니코드 윈도우라는 것이 있고, 그것을 잘못 다룰 때 어떤 재앙이 발생하는지에 대해서 살펴봤으니 이제는 당연히 우리가 작업을 하려고 하는 대상 윈도우가 유니코드 윈도우인지 아닌지가 궁금해질 것이다. 어떻게 대상 윈도우가 유니코드인지 아닌지 알 수 있는지 말이다. 이런 용도로 사용하기 위한 아주 간단한 함수가 하나 존재한다. 바로 IsWindowUnicode다. IsWindowUnicode(hwnd)를 호출해서 FALSE가 리턴되면 해당 윈도우는 안시 윈도우고, FALSE가 아닌 값이 반환되면 유니코드 윈도우라는 것을 나타낸다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;끝으로 몇 가지 추가적인 사항에 대해서 좀 더 알아보도록 하자. 앞선 코드를 실제로 테스트해본 개발자라면 윈도우가 유니코드인지 안시인지에 상관 없이 DefWindowProcA나 DefWindowProcW나 아무거나 호출해도 WM_GETTEXT의 메시지의 결과는 정상적으로 나온다는 것을 볼 수 있었을 것이다. 어떻게 이런 것일까? 답은 간단하다. 다음처럼 방어적인 코딩을 했다면 해당 메시지 프로시저는 윈도우의 종류에 관계없이 문자열을 적절하게 처리할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; WM_GETTEXT&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsWindowUnicode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hWnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;StringCchCopyW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPWSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lstrlenW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPWSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;StringCchCopyA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lstrlenA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPSTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; lParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;끝으로 이 글을 읽고는 아마도 특정 윈도우에 메시지를 보낼 때에도 해당 윈도우가 유니코드 윈도우라면 SendMessageW를, 안시 윈도우라면 SendMessageA를 써야겠다는 생각을 한 개발자도 있을 것이다. 똑똑한 생각이다. 하지만 현실은 그렇게 불편하지는 않다. 테스트를 해보면 SendMessageA든 SendMessageW든 적절한 버퍼를 전달했다면 제대로 된 값을 반환해 주는 것을 볼 수 있을 것이다. 놀랄 필요는 없다. IsWindowUnicode를 호출해서 해당 윈도우로 적절한 버퍼를 전송하고 그 결과를 다시 우리 입맛에 맞게 WideCharToMultiByte, MultiByteToWideChar를 호출해서 변환하는 그 귀찮은 작업들을 SendMessage가 대신해 주고 있을 뿐이다. 물론 WM_GETTEXT외에도 이렇게 변환이 필요한 모든 메시지에 대해서 SendMessage는 내부적으로 적절하게 변환해주도록 되어 있다. 단지 우리는 SendMessageA를 사용했다면 안시 버퍼를, SendMessageW를 사용했다면 유니코드 버퍼를 전달해야 한다는 사실만 기억하면 된다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[04. 구구단을 만들어 보자, 2001]]></title><description><![CDATA[안녕하세요~ 오늘은 지난번에 배웠던 if…]]></description><link>https://jiniya.net/wp/archives/5231</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5231</guid><pubDate>Wed, 26 Oct 2011 23:57:48 GMT</pubDate><content:encoded>&lt;p&gt;안녕하세요~ 오늘은 지난번에 배웠던 if문과 함께 반복문에 대해서 익혀보도록 하겠습니다~ 지난번 숙제는 다 하셨나요..?! 이번 강좌부터는 숙제는 계속 나가지만 해답은 올리지 않도록 하겠습니다. 왜냐하면 해답을 그냥 자꾸 올리니까 어려분의 상상력을 억제하는 듯한 느낌이 드네요. 풀어보고 모르시겠으면 Q&amp;#x26;A란에 질문하시면 제가 아는 한도 내에서 답글을 올리도록 하겠습니다~ 그럼 오늘도 시작하도록 하죠~~!!…&lt;/p&gt;
&lt;p&gt;오늘 배울것은 for라는 놈입니다~ 이놈은 아마도 C++언어에서 가장 많이 접하는 놈이 아닐까 생각합니다. 그럼 한번 for문의 문법부터 살펴보고 가도록 합시다~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;초기문&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 종료조건&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 반복할것&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   실행문&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;조금 난해해 보일수도 있겠지만 저게 for문의 모든 요소입니다. 그럼 지금부터 설명하도록 하죠~ 우선 한가지 저 for문에 걸리는 실행문이 두개 이상이면 어떻게 해야한다구요?!… 예… 바로 {}로 묶어줘야 겠죠~~ 항상 C++에서는 한 구문에 걸리는 문장이 두개이상이면 {}로 묶어야 합니다. 그것을 블록을 만든다라구 표현하죠~ for문의 요소를 보면 세가지가 있습니다. 초기문, 종료조건, 반복할것인데. 하나씩 뜯어보도록 하죠. 제일 처음 저 구문이 실행되면 제일 처음 초기문이 실행되고 실행문이 실행되고, 다음으로 반복할 것이 실행됩니다. 그 다음 종료조건을 검사하고 종료조건이 참이면 다시 실행문을 실행하고 반복할 것을 실행한다음 종료조건을 검사합니다. 그렇게 종료조건이 거짓일때까지, 계속 반복하는 것이죠. 말로 적으니까 조금 난해해 보이는데. 하나씩 적으면서 따져보면 금방 이해가 가실 겁니다. 그럼 아래 예를 보도록 하죠!!!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 소스를 실행하면 결과가 어떻게 나올까요? 아마도 0부터 9까지 출력이 될 겁니다. 아시겠죠. 그럼 아래 문장은 어떻게 될까요?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;똑같은 결과가 출력될 겁니다. 조금만 생각해 보면 금방 알수가 있겠죠~ 다음에를 보도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위에 것도 똑같은 예 입니다. 이제 저것과 똑같은 예를 남아있는데로 한번에 열거해 보도록 하죠~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;대충 이정도 보셨으면 마치 말장난 처럼, 똑같은 문법을 여러방법으로 돌려가면서 사용하는 것을 보셨을 겁니다. 처음 보시는 분들은 저런걸 왜 저렇게 머리아프게 다양한 방법으로 사용하는가 궁금해 하실텐데, 나중에 되면 저걸 알고 모르고가 얼마나 큰 차이인지 아실 겁니다. 가까운 예로 문자열을 입력받는 함수를 C로 한번 작성한다고 생각을 해 봅시다. 보통사람은 아래와 같이 작성합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      temp&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

      ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

   &lt;span class=&quot;token function&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;보통 사람의 소스였습니다.. 조금 C언어를 공부한 사람들은 다음과 같이 작성하죠~~~!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      temp&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token function&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;어때요… 훨씬 깔끔해 졌죠… 하지만… 완벽하게 for문을 이해한 사람은 아래와 같이 작성합니다~~~~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      temp&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token function&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 연유로 for문을 여러방향으로 사용할 수 있어야 합니다. 아시겠죠?! 이 정도 겅부하셨으면 아마 이제는 어떠한 for 문장이 나와도 두렵지 않을 겁니다. 그럼 오늘의 본론 구구단 프로그램을 작성 해 볼까요?!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2 * &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; = &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;구구단 이단을 출력하는 프로그램입니다. 이제 몸에 금방 아!. 하고 느낌이 오죠~ 그럼 오늘 강좌는 여기서 마치도록 하겠습니다. 다음시간에는 while구문에 대해서 설명하도록 하죠!!!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;숙제!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;구구단을 2단부터 9단까지 출력하는 프로그램을 작성해보세요!! 단,. 각 단 사이에는 구분줄이 하나씩 들어가야 합니다. 아래 출력처럼 출력이 되도록작성해 보세요!!&lt;/p&gt;
&lt;p&gt;[Hint: C++에서의 산술연산자에는 다음이 있다… 곱하기(*), 나누기(/), 더하기(+), 빼기(-), 나머지(%) 이걸 이용하면, 금방 답을 찾으실 수 있얼거예엽~~~]&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; 2\*1 = 2  
&gt; 
&gt; 2\*2 = 4  
&gt; 
&gt; …  
&gt; 
&gt; …  
&gt; 
&gt; 2\*9 = 18  
&gt; 
&gt; ============== &amp;lt;== 이넘이 출력되도록…  
&gt; 
&gt; 3\*1 = 3  
&gt; 
&gt; ….
&gt; 
&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;조금만 고민해 보면 금방 답이 보이실 겁니다~~~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[치프가 된다는 건…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4629</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4629</guid><pubDate>Tue, 25 Oct 2011 23:57:47 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;치프 생활을 즐기는 것 같더군&lt;/p&gt;
&lt;p&gt;힘 있는 자리야&lt;/p&gt;
&lt;p&gt;이보다 더 사람들에 둘러싸여 본 적도&lt;/p&gt;
&lt;p&gt;이보다 더 외로웠던 적도 없을거야&lt;/p&gt;
&lt;p&gt;모든 이의 아버지이자 상사지만 친구는 없을거네&lt;/p&gt;
&lt;p&gt;깔끔한 절개, 정돈된 봉합 다 자네의 결정이지&lt;/p&gt;
&lt;p&gt;감정도 타협도 사생활도 없는 자릴세&lt;/p&gt;
&lt;p&gt;리처드&lt;/p&gt;
&lt;p&gt;난 뇌 수술을 받았네&lt;/p&gt;
&lt;p&gt;과일 바구니에 둘러싸여 있어&lt;/p&gt;
&lt;p&gt;찾아오는 사람마다 내 비위를 맞추려 안달이더군&lt;/p&gt;
&lt;p&gt;나는 이유가 있어서 자네를 선택했네&lt;/p&gt;
&lt;p&gt;우린 똑같아&lt;/p&gt;
&lt;p&gt;일이 우선이지&lt;/p&gt;
&lt;p&gt;I know you’re enjoying yourself, Preston&lt;/p&gt;
&lt;p&gt;It’s a power kick to be the chief.&lt;/p&gt;
&lt;p&gt;You’re never more surrounded.&lt;/p&gt;
&lt;p&gt;Never more alone.&lt;/p&gt;
&lt;p&gt;You’re everyone’s father, everyone’s boss, and no one’s friend.&lt;/p&gt;
&lt;p&gt;Choices you make.&lt;/p&gt;
&lt;p&gt;Clean slices and neat stitches.&lt;/p&gt;
&lt;p&gt;No emotions, no compromise, no personal life.&lt;/p&gt;
&lt;p&gt;But, Richard…&lt;/p&gt;
&lt;p&gt;I just had brain surgery.&lt;/p&gt;
&lt;p&gt;I’m surrounded by fruit baskets.&lt;/p&gt;
&lt;p&gt;The only people who’ve been in this room come and kiss my ass.&lt;/p&gt;
&lt;p&gt;I gave you a shot for a reason, Preston.&lt;/p&gt;
&lt;p&gt;You and I, we’re the same.&lt;/p&gt;
&lt;p&gt;We put the job first.&lt;/p&gt;
&lt;p&gt;from &lt;strong&gt;Grey’s Anatomy S02E01&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;모두를 이해해야 하지만, 정작 본인은 제일 이해받기 힘든 자리.&lt;/p&gt;
&lt;p&gt;모든 걸 자기 뜻대로 결정할 수 있지만, 동시에 하나도 자기 멋대로 할 수 없는 자리.&lt;/p&gt;
&lt;p&gt;모든 걸 책임져야 하지만 자기 힘으론 아무 것도 책임질 수 없는 자리.&lt;/p&gt;
&lt;p&gt;모두가 자기편인 척 하지만 진짜 자기편은 아무도 없는 자리.&lt;/p&gt;
&lt;p&gt;많은 사람들에 둘러싸여 있지만 가장 외로운 자리.&lt;/p&gt;
&lt;p&gt;치프가 된다는 건 그래서 힘든 것.&lt;/p&gt;
&lt;p&gt;그런 세상의 모든 치프들이 한없이 존경스럽게 느껴지는 밤.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[03. 급여 관리를 만들어 보자, 2001]]></title><description><![CDATA[이제 완연한 여름이 오는것 같네요~ 햇살도 아주 따스하고, 날씨도 맑고. 쿠쿠. 이런때일수록 나른하고 피곤해지기 쉬우니 모두들 건강관리에 신경을 써야할 것 같습니다. 오늘은 간단한 if…]]></description><link>https://jiniya.net/wp/archives/5194</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5194</guid><pubDate>Tue, 25 Oct 2011 23:57:46 GMT</pubDate><content:encoded>&lt;p&gt;이제 완연한 여름이 오는것 같네요~ 햇살도 아주 따스하고, 날씨도 맑고. 쿠쿠. 이런때일수록 나른하고 피곤해지기 쉬우니 모두들 건강관리에 신경을 써야할 것 같습니다. 오늘은 간단한 if문을 배워서 급여를 관리하는 시스템을 만들어 볼 생각입니다. 모두들 재미있게 읽고, 오늘 배우는 if문 만은 마스터한다는 생각으로 강좌를 읽어 주시면 되겠네요~ 자, 그럼 시작하겠습니다.&lt;/p&gt;
&lt;p&gt;if, 영어에서 가정문을 사용할때 쓰이는 단어입니다. 마찬가지로 플밍에서도 조건을 검사할때 사용합니다. “만약 이것이 참이면 이런행동을 하고, 이것이 거짓이면 저런 행동을 해라.” 따위의 조건을 판단하는 문장을 말하는 거죠~ 그럼 간단하게 사용되는 if문을 살펴보도록 할까요.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; 검사할 조건 &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      실행문&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예가 간단한 if문을 사용한 예입니다. 검사할 조건이 참이면 실행문이 실행이 되겠죠. 거짓이면 실행이 되지 않을 겁니다. 그리고 만약 실행문 두개 이상이 한 if문에 걸릴때는 항상 브레이스( { } )로 묶어 주어야 합니다. 그럼 다음으로 완전한 if문을 한번 살펴 보도록 합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;조건 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;조건 &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;조건 &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;예~, 길죠. 위의 예가 모든 if문의 구성요소를 보여주는 예입니다. 구성요소별로 살펴보면 처음의 키워드 if는 본체입니다. 그리고 생략이 안되고 반복도 안되죠. 그리고 나머지 else if와 else는 옵션입니다. 옵션은 생략을 해도 되고, 붙여도 되는 겁니다. 끝으로 옵션중에 else if는 반복사용이 가능합니다. 휴~ 그럼 위 구문을 해독해 보도록 합시다. 조건1이 참이면 실행1이 실행이 되고, 조건2가 참이면 실행2. 이런식으로 실행이 될 겁니다. 그런데 위에서 중요한 것은 위의 나열된 조건들은 서로 배타적이라는 겁니다. 배타적이라는 의미가 뭐냐면 만약 조건1과 조건3이 동시에 만족할 경우에는 실행1만 실행되고, 나머지 조건은 무시되는 겁니다. 그럼 그걸 잘 생각해 본 다음에 아래있는 if문 예제를 보세요~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;조건&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;조건&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      실행&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 if문에서 조건 1과 2는 서로 배타적인 관계이며, 조건 3과는 서로 독립적인 관계입니다. 그러니까 만약 조건 1과 2가 참이면. 실행 1만 실행이 될 겁니다. 반면에 조건 1과 3이 참이면 실행1과 실행3이 순차적으로 실행이 되는 겁니다. 아시겠죠 자알~ 생각해 보시면 금방 원리를 알 수 있을 겁니다.&lt;/p&gt;
&lt;p&gt;아! 그리고 조건에 사용할 수 있는 관계연산자에는 ==(같다), &gt;=(크거나같다), &amp;#x3C;=(작거나같다), &gt;, &amp;#x3C;, !=(같지않다)가 있습니다. 그리고 주의할것은 =은 항상 모든 기호 오른쪽에 사용한다는 것입니다. 왼쪽에쓰면 구문오류가 발생합니다. 주의하세요!!!&lt;/p&gt;
&lt;p&gt;그럼 오늘의 본론으로 들어가서, 회사의 급여관리 시스템을 만들텐데. 우선 구체적인 스펙을 정하도록 하죠. 쉬운 예제니까 아주 제한을 많이 가하도록 하겠습니다. 우리가 관리하려는 회사의 직원은 5명이며, 회사의 순수익은 수익의 45%입니다. 그 중에 10%를 회사에 재투자하고, 나머지 남은 금액을 5명이 아주 공평하게 분배하는 것을 원칙으로 하겠습니다. 그런 회사가 어딨냐구요?! 여기있습니다. 쿠쿠. 그럼 만들어 볼까요? 변수 정리부터 하도록 하죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; sun_suik&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; jae_tu_ja&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pay_per_man&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; suik&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; max_man &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위에 있는 변수들이 우리가 사용할 변수의 전부입니다. sun_suik은 순수익을, suik은 수익을, jae_tu_ja는 재투자비용을, 그리고 pay_per_man은 일인당 급여를 그리고 max_man은 전체 사원수를 저장하는 변수입니다. 그런데 사원수 앞에 붙어있는 const가 궁금하죠. 그건 상수라는 건데, 그 값은 한번 초기화 되면, 프로그램이 실행되는 동안 변하지 않는 값을 의미합니다. 다음에 한번 자세하게 설명하도록 하죠~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;수익을 입력해 주세요!!!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   cin &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; suik&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   sun_suik &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; suik &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   jae_tu_ja &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sun_suik &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   pay_per_man &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sun_suik &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; jae_tu_ja&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; max_man&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;순수익은 &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; sun_suik &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; 입니다...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;재투자 비용은  \&quot; &amp;lt;&amp;lt; jae_tu_ja &amp;lt;&amp;lt; \&quot; 입니다...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;사원은 총 &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; max_man &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; 이며 , 일인당 급여는 &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; pay_per_man &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; 입니다...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;소스를 다 짰는데 정작 중요한 오늘의 if문은 없는 것 같네요~ 그래서 그부분을 숙제로 내도록 하겠습니다~ ㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;숙제!!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;5명의 직원이 사장, 부장, 대리, 사원 2명으로 구성되어 있으며,. 각각의 급여는 35%, 20%, 15%, 20% * 2라고 합시당… 그래서 사용자가 각각의 직원 코드와 총수익을 입력하면… 그 사원의 급여를 상황에 맞게 출력하는 겁니다… 별로 어렵진 않죠…! [Hint : 아래 코드를 참조하세요!!!]&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

cin &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   xxx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
   yyy&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[02. 변수, 2001]]></title><description><![CDATA[오늘은 초보C++강좌…]]></description><link>https://jiniya.net/wp/archives/5181</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5181</guid><pubDate>Mon, 24 Oct 2011 23:57:45 GMT</pubDate><content:encoded>&lt;p&gt;오늘은 초보C++강좌 2탄으로 변수에 대해서 준비했습니다. 앞으로 강좌를 계속 올릴 예정이니 차근차근 읽고 숙제를 풀다보면 어느새 발전된 자신을 발견할 수 있을 겁니다. 그럼 그날을 위해서 오늘도 힘차게 한번 출발 해보도록 하죠~&lt;/p&gt;
&lt;p&gt;지난번 숙제부터 한번 푸러 볼까요?! 자신의 이름과 생을 화면에 출력하는 예제였죠~ 전 이렇게 했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt;  &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
 cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;이름 : 신영진&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
 cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;생일 : 6월 10일&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;간단하죠~ 다들 잘 하셨으리라 생각합니다. 그럼 오늘 강좌의 본론인 변수에 대해서 알아보도록 합시다. 변수는 무엇일까요?! 변수는 말그대로, 변(변하는) 수(숫자) 이런 뜻이 아닐까요?! 제 생각이었습니다. 프로그래밍에서 말하는 변수는 프로그램의 실행도중에 변하는 값을 말합니다. 그렇게 변하는 값들을 메모리에 저장시키기 위해서 변수라는 것을 사용하는 것이죠~ 그럼 간단한 예를 한번 보도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt;  &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
 &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

 cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;숫자를 한번 입력해 보세요&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
 cin &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

 cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;당신이 입력한 숫자는 &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;입니다...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예제는 간단하게 사용자로 부터 숫자를 하나 입력받고 출력하는 예제입니다. 그럼 사용자에게 숫자를 하나를 입력 받아야 하는데, 사용자가 무엇을 입력할 지 알 수 있을까요? 물론 알 수 없겠죠. 사용자가 1을 입력할 수도 있고, 12를 입력할 수도 있고. 이런 식으로 다른 값이 프로그램 실행 도중에 입력되기 때문에 그런것들을 저장시키기 위해서 변수가 필요한 겁니다. 그럼 분석을 한번 해 보도록 할까요?!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;int형 변수로 num이라는 놈을 만든다는 것 입니다. int는 뭐죠?! 바로 정수형 변수 입니다. 위의 문장이 딱 실행이 되면, 메모리에 정수한넘을 저장할 공간을 만들어서 이름표를 다는데, 뭐라고 다냐면 바로 num이라고 다는 겁니다. 아시겠죠. 그렇게 여러개를 만들고 싶으면, int num1, num2, num3; 이렇게 선언해 줄 수 있습니다. 일종의 우리가 건물을 짓고 각각의 방을 만드러서 방번호를 붙이는 것과 같다고 생각하시면 되겠네요~ 그리고 꼭 변수는 선언과 동시에 초기화 시키는 게 중요합니다. 예를 들면 이렇게 하는 거죠~ int num = 0; 이렇게 하면 0으로 초기화가 되겠죠~ 그런데 여기서 여러분이 유의하셔야 할 개념이 하나 있습니다. 바로 초기화와 대입연산입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// int num(5); 이렇게 써도 됨. &lt;/span&gt;
num &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예에서 보면 첫번째 문장, int num = 0; 은 num을 0으로 초기화 시킨다는 의미이고, 밑에 있는 문장은 num에다가 5라는 값을 넣는다는 걸 의미하는 겁니다. 그리고 첫번째 문장의 //이후의 글들은 주석이라고 도움말이라고 생각하면 되겠네요. 그러면 초기화와 대입을 왜 구분하냐고 의문을 가지시는 분들이 계실겁니다. 이 부분은 조금 더 배운 후에 설명을 해 주도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;그럼 다음줄을 분석해 보도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;cin &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 문장은 num이라는 변수에 키보드로부터 숫자하나를 입력받으라는 문장입니다. 모양새를 잘 보면 &quot;&gt;&gt;&quot; 사용되서 cin을 num으로 보내느 것처럼 보이죠. 맞습니다. 그리고 여기서, cin은 표준입력(키보드)가 되는 거죠~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;당신이 입력한 숫자는 &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;입니다...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 문장은 당신이 입력한 숫자는 xx입니다를 출력하겠죠. 사용자가 입력한게 num에 저장되어 있으니 그걸 모니터로 보내 버리면 출력이 되는 겁니다.&lt;/p&gt;
&lt;p&gt;그럼 오늘 끝으로 변수의 종류에 대해서 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;int 정수형 변수입니다.&lt;/p&gt;
&lt;p&gt;long 좀 더 큰 정수를 저장할 수 있는 변수입니다..&lt;/p&gt;
&lt;p&gt;float 실수를 저장하는 변수입니다.&lt;/p&gt;
&lt;p&gt;double 소수점이하 자리가 좀 더 정확한 변수입니다.&lt;/p&gt;
&lt;p&gt;char 문자형 변수입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;숙제!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이름과 전화번호를 입력받아서 출력시키는 프로그램을 작성해 보세요~~~!! 그럼 다들 좋은 하루되세요~~~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[임의의 수를 뽑는 랜덤 함수 사용법, 2001]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4969</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4969</guid><pubDate>Sat, 22 Oct 2011 23:57:44 GMT</pubDate><content:encoded>&lt;p&gt;일반적으로 랜덤함수는 임의의 수를 뽑기 위해서 많이 사용합니다. 이러한 원리가 가장 많이 적용되는 부분이 아마도 게임일 겁니다. 게임에서 매번 같은 경로를 통해서 나타나지 않는 것이 바로 랜덤함수를 이용했기 때문입니다. 이러한 랜덤함수는 다음과 같은 형태로 사용할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;rand()함수는 임의의 정수를 리턴하게 됩니다. 하지만 이러한 식으로 뽑는 임의의 정수는 별로 큰 효용이 없습니다. 대부분의 경우는 정해진 범위 사이의 숫자를 뽑기 위해서 사용하는 일이 많습니다. 1에서 10 사이의 랜덤 숫자를 뽑기 위해서는 다음과 같이 하면 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;보면 알겠지만 간단한 공식을 적용한 것입니다. n으로 나눈 나머지는 0에서 n-1까지 범위라는 점을 이용한 것이죠.. 따라서 다음과 같은 일반적인 식이 성립됩니다.&lt;/p&gt;
&lt;p&gt;난수 = rand() % 범위 + 최소값;&lt;/p&gt;
&lt;p&gt;그럼 실제로 이러한 랜덤함수를 어떤식으로 써먹는지 알아보도록 하겠습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Sam&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Linda&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;token function&quot;&gt;srand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;실행시킬때마다 다른 사람의 이름이 적히게 되는 소스입니다.&lt;/p&gt;
&lt;p&gt;srand란 난수를 초기화 하는 함수입니다. 항상 rand를 하기 전에 한번쯤 해줘야하는 걸로 기억해 두시면 됩니다 [1]. 위의 식은 말그대로 현재 시간을 기준으로 난수를 뽑겠다는 말입니다. srand를 제비통을 섞는 함수 정도로 이해해 두시면 됩니다.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;[1] srand는 위에 언급한대로 제비통을 섞는 일을 합니다. 따라서 전체 난수 세트를 리프레시할 필요가 있는 시점에만 사용해 주시면 됩니다. 참고로 시간을 기준으로 srand를 사용했고, 그 시점이 알려진다면 취약점이 될수도 있습니다. 왜냐하면 rand는 의사 난수를 발 생시키는 함수라 시드가 똑같으면 동일한 난수열을 생성하기 때문입니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[프레임워크를 넘어서…]]></title><description><![CDATA[개발을 처음 시작할 때에 누구나 한번쯤 특정 라이브러리를 사용해서 MP…]]></description><link>https://jiniya.net/wp/archives/5152</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5152</guid><pubDate>Fri, 21 Oct 2011 23:57:43 GMT</pubDate><content:encoded>&lt;p&gt;개발을 처음 시작할 때에 누구나 한번쯤 특정 라이브러리를 사용해서 MP3 플레이어나 게임 같은 것을 만들곤 우쭐해 하던 기억이 있을 것이다. 그러면서 우리는 잘 만든 라이브러리에 대한 환상에 빠진다.&lt;/p&gt;
&lt;p&gt;라이브러리를 넘어서 프레임워크라는 말이 대세가 된 요즘이다. 신기술이라 하면 프레임워크란 말 정도는 달아줘야 그나마 개발자들이 한 번이라도 쳐다보게 마련이다. 그렇다면 라이브러리나 프레임워크 같은 것들이 개발자에게 가지는 의미는 무엇일까?&lt;/p&gt;
&lt;p&gt;나는 개발자 게시판에서 벌어지는 도구에 관한 종교적인 논쟁에서 그러한 것들을 느껴보곤 한다. 그 중에 대표적인 논쟁이 언어에 관한 것이다. 자바 vs C++, C++ vs C#이런 류의 것들이다. 그런 논쟁의 중간을 잘라서 살펴보면 신입 개발자들이 프레임워크나 라이브러리에 대해서 가지는 환상을 쉽게 볼 수 있다. C#으로는 10줄이면 되는 것을 C++로는 1000줄을 작성해야 한다는 사실로부터 사용처나 목적을 떠나서 C#이 더 좋다고 하는 주장이 그 대표적인 예다. C#에서 10줄이 되기 위해서 뒤에서 다른 개발자들이 작성한 10만 줄의 코드를 보지 못하는 것이다.&lt;/p&gt;
&lt;p&gt;프레임워크의 대중화는 생산성을 극적으로 끌어올리는데 일조했다. 너도나도 레고 블록 같은 프레임워크의 구조만 익히면 이것저것 조합해서 근사한 것을 만들 수 있는 세상이 온 것이다. 하지만 다른 한편으로 프레임워크는 약골 개발자들을 대량으로 양산하는 첨병 역할 또한 같이 했다. 많은 신입 개발자들이 프레임워크에서 지원하지 않으면 만들 수 없는 기능이고 다음 버전의 프레임워크에 해당 기능이 포함되기를 기다려야 한다고 생각한다. 그들은 프레임워크는 완벽하다고 생각한다. 말 그대로 프레임워크라는 우물 안에 갇힌 개구리인 셈이다.&lt;/p&gt;
&lt;p&gt;하지만 좋은 개발자가 되기 위해서는 프레임워크에 한정되지 않은 강한 개발자가 되어야 한다. 더 넓게는 도구에 종속되지 않는 자유로는 개발자가 될 필요가 있다. 그렇다면 어떻게 강한 개발자가 될 수 있을까? 방법은 간단하다. 프로그래밍의 기초 체력이라 할 수 있는 논리력을 향상 시키는 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 논리력은 어디서 나오는 것일까? 그것은 여러분의 논리력을 향상 시켜주는 문제를 지속적으로 해결하는 것에서부터 길러진다. 처음부터 거창한 문제를 해결할 필요는 없다. 프레임워크나 운영체제에서 지원해 주는 기능을 사용해서 해결하고 있는 문제를 해당 기능 없이 구현해 보거나 프레임워크나 운영체제의 접근 방법과는 다른 좀 더 좋은 방법을 생각해 보는 것만으로도 충분하다.&lt;/p&gt;
&lt;p&gt;42.195 킬로미터를 달리는 마라톤을 하는데 가장 중요한 한 가지 요소는 기본적인 심폐 능력이다. 마찬가지로 프로그램을 작성하는데 있어서 가장 중요한 기본 요소는 논리력이다. 얼만큼 새로운 API를 아는지, 라이브러리 구조를 아는지, 프레임워크의 세부 기능을 암기하고 있는지가 아니라는 이야기다. 그러한 것들은 모두 시간이 지남에 따라 쉽게 습득할 수 있는 기술들이다. 특히나 요즘같이 인터넷이 대중화된 시대에는 더더욱 그런 것들은 가치가 없다. 하지만 논리력은 쉽게 습득하기도 힘들뿐더러 그 능력의 차이는 극복하기가 쉽지 않다. 바퀴를 새로 만들 필요는 없다. 하지만 그 바퀴를 만들 수 있는 사람과 그렇지 않는 사람과의 차이는 분명히 존재한다는 사실을 명심해야 한다.&lt;/p&gt;
&lt;p&gt; 12
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[스티브 잡스 타계]]></title><description><![CDATA[Steve Jobs, 1955 – 2011 IT 업계의 살아있는 신화에서, 이제는 전설이 되어버린 스티브 잡스 아저씨. “Stay Hungry. Stay Foolish…]]></description><link>https://jiniya.net/wp/archives/5143</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5143</guid><pubDate>Fri, 21 Oct 2011 23:57:42 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.apple.com/&quot;&gt;Steve Jobs&lt;/a&gt;, 1955 – 2011&lt;/p&gt;
&lt;p&gt;IT 업계의 살아있는 신화에서, 이제는 전설이 되어버린 스티브 잡스 아저씨.&lt;/p&gt;
&lt;p&gt;“Stay Hungry. Stay Foolish.”란 그의 말이 오늘 따라 더 가슴에 와 닿습니다.&lt;/p&gt;
&lt;p&gt;이제는 동영상에서 밖에 추억할 수 없는 분이 되었네요.&lt;/p&gt;
&lt;p&gt;삼가 고인의 명복을 빕니다.&lt;/p&gt;
&lt;p&gt;2011.10.06&lt;/p&gt;</content:encoded></item><item><title><![CDATA[01. Hello World를 만들어 보자, 2001]]></title><description><![CDATA[모든 플밍언어를 접하면 처음 해보는 게 있다. 바로 만국 공용, 첫단계 샘플 프로그램 Hello World…]]></description><link>https://jiniya.net/wp/archives/5132</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5132</guid><pubDate>Fri, 21 Oct 2011 23:57:41 GMT</pubDate><content:encoded>&lt;p&gt;모든 플밍언어를 접하면 처음 해보는 게 있다. 바로 만국 공용, 첫단계 샘플 프로그램 Hello World를 만드는 것이죠. 그럼 우선 간단한 소스를 보면서 시작해 봅시다. 두눈 크게 뜨고 자알 살펴보세용~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&gt;&lt;/span&gt; &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;간단하죠~ 위의 프로그램을 컴파일해서 실행시키면 화면에 헬로, 월드!라고 찍힙니다. 그럼 지금부터 차근 차근 소스를 분석해 볼까요?!.. 너무 쉽다구요. 그래도 기초부터 튼튼히 해야 나중에 두려울게 없겠죠~&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C++ 헤더 파일중에 iostream이라는 헤더 파일을 포함시키는 겁니다. 헤더 파일이 뭐냐구요?! 움… 그건.. 일종의 플밍을 쉽게 하도록 도와주는 유틸리티 같은 겁니다. 위에 있는 iostream을 포함시키면 화면에 출력과 입력을 할 수 있는 클래스인 cin, cout을 사용하게 해 줍니다. 그러니 저건 필수적으로 포함시켜야 겠죠~ 처음에는 그냥 꼭 포함시켜야 하는 것 정도로 이해하고 계세요~ 그리고 가끔 C++책들을 보면, #include &amp;#x3C;iostream.h&gt;라고 된것도 있는데 두개는 똑같은 겁니다. 반면에 .h를 쓰는 건 C언어식 표현 방법이죠. 그러니 간단하게 생략하고 표현하도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이건 프로그램의 핵심이라고 할수 있는 본체 입니다. 프로그램에는 꼭 이 함수가 하나씩 드러가야 하죠. 쿄쿄. 안드러가면 아마도 링크가 되지 않을 겁니다. main이라는 함수가 프로그램의 시작위치를 지정하고 있는 함수라고 생각하면 되죠~ 그리고 main 앞에 붙어있는 int는 뭐냐구요. 그건 우리 프로그램이 종료되고 운영체제에게 int형으로 된 뭔가를 반환한다는 겁니다. 그러면 int가 뭐냐구요..?! 하하… int는 정수형을 말하는 겁니다. 따라서 우리의 메인은 정수를 반환하는 함수가 되겠죠~ 그리고 함수는 항상 {로 시작해서 }로 끝나야 합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 문장은 화면에 헬로 월드를 출력하는 실행문입니다. 그런데 잘 보면, &amp;#x3C;&amp;#x3C;게 있는 걸 알수 있는데 모양새를 잘 보세요. cout이라는 데로 헬로월드와 endl이라는 걸 집어넣는 것 처럼 보이죠. cout은 뭐냐구요. 바로 표준 출력(모니터)입니다. 그러니 모니터에다 헬로 월드와 endl를 집어넣는게 되죠. 그런데 헬로월드는 알겠는데 endl은 뭐냐구요. 그건 end of line의 약자로 다음줄로 가는 캐릭터 코드 입니다. 아래아한글에서 엔터를 치면 다음줄로 넘어가는 것 처럼 endl을 cout으로 넣으면 한줄 넘어가게 되죠~~~~!!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;운영체제에게 우리가 프로그램을 잘 실행했다고, 정수로 0을 반환하는 부분입니다. 리턴 다음에 반환할 값을 적으면 되죠. return 255이렇게 하면 255가 반환되는 겁니다. 반면에 return 12.5이렇게 하면 안되겠죠. 왜냐면 우리는 위에서 리턴값으로 정수형을 보낸다고 약속했기때문에 정수만 보내야 합니다. 일반적으로 관례상 정상종료시에는 0을 반환합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;숙제!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;오늘 강좌를 다 읽으신 분들은 자신의 실력도 점검해 볼겸 화면에 자신의 이름과 생일을 출력하는 프로그램을 작성해 보세요. 다음 강좌 때 답을 갈켜 드리도록 하죠!!! 그럼 다들 수거하세요!!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[링버퍼, 2002]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5127</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5127</guid><pubDate>Fri, 21 Oct 2011 23:57:40 GMT</pubDate><content:encoded>&lt;p&gt;링버퍼란 원형큐의 또다른 이름이라 생각할 수 있다. 뒤로 삽입이 이루어지고, 앞으로 삭제가 이루어지며 최대 갯수를 넘어설 경우 앞에 있는 것이 자동적으로 삭제되고 뒤에 추가가 이루어 진다. 요즘 흔히 사용하는 휴대전화기의 문자 메시지의 원리를 생각하면 된다. 최대 저장갯수가 초과하게 되면 가장 오래된 메시지가 삭제되고 새로운 메시지가 보관되는 원리아다. 물론 그렇게 처리가 되지 않은 구식 전화기도 종종있다.&lt;/p&gt;
&lt;p&gt;이러한 큐를 구현하는데 가장 많이 사용되는 방법중에 하나가 읽기, 쓰기 포인터를 이용한 방법이다. 각각은 MAXDATA가 되게 되면 다시 0으로 초기화 되어야 하므로 주로 나머지 연산자를 이용해서 많이들 구현하게 된다. 일반적으로 사용되는 수식은 대부분 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;MAXDATA&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; nPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nPos &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; MAXDATA&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;흔히들 사용하는 진부한 식이다. 물론 이러한 수식을 처음 보는 분들께서는 위의 식에서 nPos가 움직이는 값을 관찰하면 금방 0~MAXDATA-1을 반복하면서 변화하게 되리란 것을 알수 있을것이다.&lt;/p&gt;
&lt;p&gt;몇일전 필자는 위와 같은 형태의 자료구조를 가진 것을 한번 만들 일이 있어서 프로그램을 작성한 일이 있었다. 하지만 작성도중 정말 어처구니 없는 일을 당하고 말았다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;MAXDATA&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;3600&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; nPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nPos &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; MAXDATA&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아무래도 이상한 결과가 출력되어 추적해 본 결과 nPos값이 0에서 200으로 변하는 것이 아닌가… ㅋㅋ… 이쯤 되었으면 아! 하는 분들이 많이 계시리라는 생각이 든다. 괄호가 빠져서 그런 결과가 나왔던 것이다. 하지만 실제로 선언과 참조가 한참이 분리된 코드에서는 그렇게 쉽게 생각나는 내용이 아니어서 한번 적어 보았다. 참고로 위 코드의 제대로 된 버전은 아래와 같이 되어야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;MAXDATA&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3600&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; nPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nPos &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; MAXDATA&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[사소한 차이가 정답과 오답을 가른다, 2004]]></title><description><![CDATA[요즘 acm icpc 문제 풀이에 재미를 붙여 하루에 한두개씩 풀곤하는데 오늘 어이없는 것으로 한 20여 차례의 wrong answer를 만나야 했다. 문제는 너무나 간단해서 정답이 아닐리가 없고… 다 확인을 해 보았는데두 계속 wrong answer…]]></description><link>https://jiniya.net/wp/archives/5019</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5019</guid><pubDate>Fri, 21 Oct 2011 23:57:39 GMT</pubDate><content:encoded>&lt;p&gt;요즘 acm icpc 문제 풀이에 재미를 붙여 하루에 한두개씩 풀곤하는데 오늘 어이없는 것으로 한 20여 차례의 wrong answer를 만나야 했다. 문제는 너무나 간단해서 정답이 아닐리가 없고… 다 확인을 해 보았는데두 계속 wrong answer만 나오는 것이었다. 그 정답과 오답의 차이는 아래 루프에 있었다. 참고로 아래와 같은 루프는 주로 출력할것의 갯수를 잘라서 출력하는데 많이 사용되는 구조이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 루프1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%3d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;putchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;\n&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 루프2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;putchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;\n&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%3d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;원 문제의 요구는 15개씩 끊어서 출력하는 것이었다. 내가 작성한 루프는 1번구조였고 2번 구조가 정답의 루프 구조이다. 둘간의 차이를 금방 알수 있는 분은 충분히 코드를 머릿속으로 그릴수 있는 사람들이다. 나 또한 둘간의 차이를 구분하지 못해서 수십번의 오류를 가진 답을 제출해야 했다. 눈에 들어오지않는 사람들은 한번 쯤 곰곰히 생각해 보길 바란다. 둘간의 차이가 무엇일까??&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;15개씩 끊어주는 건 둘 다 같은데…&lt;/p&gt;
&lt;p&gt;한 가지 다르다면 15n-1의 경우 첫번째는 리턴값이 포함된다는 것 정도?&lt;/p&gt;
&lt;p&gt;by &lt;strong&gt;인터넷 논객&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[setjmp/longjmp, 2002]]></title><description><![CDATA[C언어를 가끔 사용하다 보면 이런 것들을 하고 싶을때가 있습니다. 이 함수를 넘어 저 함수로 이동하거나 함수의 경계를 넘나드는 어떤 처리를 하고 싶을때가 있죠. 처음 딱 생각하기에는 goto로 될 것 같지만, C언어의 goto…]]></description><link>https://jiniya.net/wp/archives/5030</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5030</guid><pubDate>Fri, 21 Oct 2011 23:57:38 GMT</pubDate><content:encoded>&lt;p&gt;C언어를 가끔 사용하다 보면 이런 것들을 하고 싶을때가 있습니다. 이 함수를 넘어 저 함수로 이동하거나 함수의 경계를 넘나드는 어떤 처리를 하고 싶을때가 있죠. 처음 딱 생각하기에는 goto로 될 것 같지만, C언어의 goto에는 함수의 범위를 넘지 못하는 제약이 있습니다. 대신 목적을 위해 만들어진 함수 두개가 있습니다. 바로 setjmp, longjmp입니다. 이름 그대로 아주 먼 거리를 점프하는 함수죠. 그럼 실제 소스 코드를 볼까요??&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;/span&gt;

jmp_buf pos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
       &lt;span class=&quot;token function&quot;&gt;longjmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pos&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setjmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pos&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token function&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결과는 각자 감상하시면서 한번씩 생각해 보시길 바랍니다. 참고로 jmp_buf는 상태를 저장하는 버퍼 구조체 입니다. 기본 원리는 setjmp는 현재 상태를 저장하고 longjmp이전 상태로 이동하는 역할을 하게 됩니다. 각자 한번 실행해 보시면 금방 아! 하시게 될겁니다.&lt;/p&gt;
&lt;p&gt;그럼 다들 좋은 하루 되세요.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[iostream에서 지원하는 텍스트 포맷팅 함수들, 2001]]></title><description><![CDATA[C언어를 배우고 난 뒤 처음 C++ 책을 접하게 되면 iostream…]]></description><link>https://jiniya.net/wp/archives/4952</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4952</guid><pubDate>Thu, 20 Oct 2011 23:57:37 GMT</pubDate><content:encoded>&lt;p&gt;C언어를 배우고 난 뒤 처음 C++ 책을 접하게 되면 iostream이라는 것을 배우게 됩니다. 모두 단순히 출력또는 입력을 연산자 오버로딩을 통해 간단하게 해주는 정도의 기능을 알고 넘어가게 되는데 사실 그정도만 알면 되죠. 하지만 가끔 그 이상의 iostream기능이 궁금할때가 있습니다. 그것을 잘 몰라서 고생하는 경우가 계신것 같아서 옵션으로 쓸수 있는 것들을 한번 추려서 올려봅니다.&lt;/p&gt;
&lt;p&gt;이 자료는 모두 Practical C++ Programming에서 발췌된 것입니다. 참고로 책에서도 C++의 입,출력 포맷 방식이 아주 불편한 방식이라구 [1]. sprintf등을 통한 포맷된 문자열을 화면으로 출력하기를 권하고 있습니다. 하지만 때로는 이런것들을 알고 있는 것이 도움이 될때도 있기에 올려봅니다. 그럼 다들 즐프하세염.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;입출력 변환 플래그&lt;/p&gt;
&lt;p&gt;ios::skipws 입력에서 공백 문자를 건너뛴다.&lt;/p&gt;
&lt;p&gt;ios::left 출력 왼쪽 정렬&lt;/p&gt;
&lt;p&gt;ios::right 출력 오른쪽 정렬&lt;/p&gt;
&lt;p&gt;ios::internal 숫자 출력은 부호나 기조 문자와 숫자 사이에 채우기 문자 삽입&lt;/p&gt;
&lt;p&gt;ios::dec 10진수&lt;/p&gt;
&lt;p&gt;ios::oct 8진수&lt;/p&gt;
&lt;p&gt;ios::hex 16진수&lt;/p&gt;
&lt;p&gt;ios::showbase 각 숫자의 서두에 기저를 표시한다. 예를들어 16진수이면 0x가 앞에출력된다.&lt;/p&gt;
&lt;p&gt;ios::showpoint 모든 부동 소수에 대해 10진수로 표시한다.&lt;/p&gt;
&lt;p&gt;ios::uppercas 16진수 변환시 대문자로 출력&lt;/p&gt;
&lt;p&gt;ios::showpos 모든 양수 앞에 + 기호 붙임&lt;/p&gt;
&lt;p&gt;ios::scientific 출력 시에 모든 부동 소수를 지수 형식으로 변환&lt;/p&gt;
&lt;p&gt;ios::fixed 출력시에 모든 부동 소수를 고정 소수로 변환&lt;/p&gt;
&lt;p&gt;ios::unitbuf 버퍼 출력&lt;/p&gt;
&lt;p&gt;ios::studio 출력 후에 스트립 플러시&lt;/p&gt;
&lt;p&gt;입출력 조정자&lt;/p&gt;
&lt;p&gt;setiosflags(long flags) 지정 변환 플래그 설정&lt;/p&gt;
&lt;p&gt;resetiosflags(long flags) 지정 플래그로 복원&lt;/p&gt;
&lt;p&gt;dec 10진수&lt;/p&gt;
&lt;p&gt;hex 16진수&lt;/p&gt;
&lt;p&gt;oct 8진수&lt;/p&gt;
&lt;p&gt;setbase(int base) 기저를 8,10,16으로 변환&lt;/p&gt;
&lt;p&gt;setw(int width) 출력 너비 설정&lt;/p&gt;
&lt;p&gt;setprecision(int precision) 부동 소수 출력의 정확도 설정&lt;/p&gt;
&lt;p&gt;setfill(char ch) 채우기 문자 설정&lt;/p&gt;
&lt;p&gt;ws 입력시에 공백 문자 건너뜀&lt;/p&gt;
&lt;p&gt;endl 라인끝 출력&lt;/p&gt;
&lt;p&gt;ends 문자열 끝 출력&lt;/p&gt;
&lt;p&gt;flush 버퍼에 있는 내용을 출력&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;[1] boost::format을 사용하면 C++에서도 printf같이 편리하게 자료를 출력하실 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.boost.org/doc/libs/1_47_0/libs/format/&quot;&gt;http://www.boost.org/doc/libs/1_47_0/libs/format/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; 1
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[printf 가변 공백 삽입하기, 2001]]></title><description><![CDATA[오늘 방금 책을보다 깨닫게 된 것이 있어 올려봅니다. printf를 사용하다보면 공백을 적당하게 넣어야 하는 경우가 생기는데 그럴때 유용하게 사용할 수 있는 방법입니다. 위와같이 하면 6칸을 띄우고 Hello…]]></description><link>https://jiniya.net/wp/archives/4961</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4961</guid><pubDate>Thu, 20 Oct 2011 23:57:36 GMT</pubDate><content:encoded>&lt;p&gt;오늘 방금 책을보다 깨닫게 된 것이 있어 올려봅니다. printf를 사용하다보면 공백을 적당하게 넣어야 하는 경우가 생기는데 그럴때 유용하게 사용할 수 있는 방법입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%*sHello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와같이 하면 6칸을 띄우고 Hello가 출력이 됩니다. &lt;strong&gt;아직 확인해보지는 못했지만 책에서 봤으니까 맞는것 같네염 [1].&lt;/strong&gt; 다들 한번해보세염. 괜찮은 것 같은데. 그럼 좋은하루되세요!!!&lt;/p&gt;
&lt;p&gt;[1] 세상에서 제일 멍청한 생각이죠. 여러분은 절대로 이런 생각을 하지 말기를 바랍니다. ㅋㅋ~&lt;/p&gt;</content:encoded></item><item><title><![CDATA[비트 연산 몇 가지, 2002]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/5025</link><guid isPermaLink="false">https://jiniya.net/wp/archives/5025</guid><pubDate>Thu, 20 Oct 2011 23:57:35 GMT</pubDate><content:encoded>&lt;p&gt;요즘은 실제로 윈도우나 리눅스쪽에서 프로그래밍을 한일이 별로 없어서 그쪽으로 적을만한 것이 없네염. 드뎌 몇달간 당당히 오늘의 코드를 지키고 있던 진수 변환기를 재치고 새로운 코드를 올려 놓으려 합니다.&lt;/p&gt;
&lt;p&gt;요즘 원칩 플밍을 하면서 비트 연산이 자주 필요해서 만들어 본 함수입니다. 함수라고 하기보다는 매크로 입니당. 그럼 코드 내려 갑니당.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;CHKBIT&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;var&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;var&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x01&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;CLRBIT&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;var&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;var&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x01&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;SETBIT&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;var&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;var&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0x01&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위에서 부터 설명 드리겠습니다.&lt;/p&gt;
&lt;p&gt;CHKBIT(숫자, 비트번호) 하면 해당 숫자에 비트번호가 세팅되어 있는지 되어 있지 않은지를 판단합니다. CLRBIT는 해당 숫자의 비트를 제거하는 것이며 SETBIT은 해당 숫자의 비트를 설정하는 것 입니다. 모든 기준은 8비트 자료형에 맞추어져 있습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[소수 판별하기, 2002]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4982</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4982</guid><pubDate>Thu, 20 Oct 2011 23:57:34 GMT</pubDate><content:encoded>&lt;p&gt;일반적으로 소수를 판별하는 다항식은 존재하지 않는다고 많이 알려져 있습니다. 그래서 소수를 판별하는 것 또한 컴퓨터로 하기 힘든 일 중에 하나죠. 최근 그 문제에 대한 해답이 나왔나 봅니다. 소수를 판별하는 다항식에 대한 자세한 설명과 알고리즘이 나와 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.cse.iitk.ac.in/news/primality.pdf&quot;&gt;http://www.cse.iitk.ac.in/news/primality.pdf&lt;/a&gt; [1]&lt;/p&gt;
&lt;p&gt;기럼, 전 구시대적 방법으로 판별하는 함수를 하나 올리도록 할께염… ㅎㅎ&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IsPrime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 소스는 위의 함수를 이용하여서 1000이하의 소스를 출력하는 소스 입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsPrime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%d &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;[1] 링크가 깨졌네요. 글에서 언급한 소수 판별 다항 알고리즘은 “AKS 소수 판별법”입니다. 다음 위키 페이지에 설명이 나와 있습니다. &lt;a href=&quot;http://en.wikipedia.org/wiki/AKS_primality_test&quot;&gt;http://en.wikipedia.org/wiki/AKS_primality_test&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;소수라고 함은..정수로 하는 것인데..쓸대 없이 루프가 더 도네요….정수는 자신의 1/2 이상의 수로는 절대 나눌수 가 없죠….. for(i = 2; i &amp;#x3C; n/2 ; ++1) 라고 해야…효율적일듯&lt;/p&gt;
&lt;p&gt;by &lt;strong&gt;까칠한 인터넷 논객&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;n/2라뇨. 수학을 배웠으면 루트죠. 이게 더 효율적일듯…&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;MyRoot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;IsPrime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MyRoot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;by &lt;strong&gt;까칠한 인터넷 논객 제압자&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;안녕하세요,&lt;/p&gt;
&lt;p&gt;ICPC 자료들 구하다가 찾아들어왔습니다.&lt;/p&gt;
&lt;p&gt;좋은 자료 잘 받아갑니다.^^;&lt;/p&gt;
&lt;p&gt;마지막으로 올라온 코드에서 한가지 더 추가드리자면..&lt;/p&gt;
&lt;p&gt;n이 짝수일때는 소수일리가 없으므로..&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;IsPrime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MyRoot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// increment i by 2&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 위의 함수는 아래의 매크로로 사용될수 있습니다. (단 n이 홀수일때만).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;isprime&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//works when n is odd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;글구…&lt;/p&gt;
&lt;p&gt;위에 예제처럼 primality testing을 여러번 해야 할 시에는 sieve라는 알고리즘을 많이 사용합니다. 테이블을 0부터 n까지 잡고, 각 숫자마다 2부터 sqrt(n) 까지만 테스팅을 해주는 방식인데요, 그걸 해주자면 배열에서 루프를 돌려서 각 인덱스마다 인덱스의 배수에 해당하는 엘리먼트들을 죄다 날려주는 겁니다. 이런식으로 날려(?)주다보면 나중엔 안날라(?) 간 아이들만 소수가 되는것이지요.. 간단한 코드 올려 봅니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;MAX&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;20000000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gen_sieve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/*sieve: 0 means prime, 1 means composite*/&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ulimit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sieve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20000001&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MAX&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MAX&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ulimit&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ulimit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;j&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;j&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MAX&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;j&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;j&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        sieve&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 알고리즘의 시간복잡도는 O(n log log n )입니다.&lt;/p&gt;
&lt;p&gt;시간 복잡도 계산을 위해선 다음과 같이 생긴 harmonic series를 구해야 합니다.&lt;/p&gt;
&lt;p&gt;Sigma n/i, i=3..sqrt(n), where i=prime number&lt;/p&gt;
&lt;p&gt;ie) n/3 + n/5 + n/7 + n/11 + n/13 + …&lt;/p&gt;
&lt;p&gt;그리구 저 시리즈의 값은 다음 주소에 나와있네요.^^;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://mathworld.wolfram.com/MertensSecondTheorem.html&quot;&gt;http://mathworld.wolfram.com/MertensSecondTheorem.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;by &lt;strong&gt;인터넷 지존&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[How to wake up a PC using waitable timer.]]></title><description><![CDATA[I used to love listening to the pop-song radio program that aired early in the morning when I was a teenager. However, waking up in the…]]></description><link>https://jiniya.net/wp/archives/4910</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4910</guid><pubDate>Thu, 13 Oct 2011 23:57:33 GMT</pubDate><content:encoded>&lt;p&gt;I used to love listening to the pop-song radio program that aired early in the morning when I was a teenager. However, waking up in the early morning was almost impossible for me, then I couldn’t help wondering how convenient and wonderful it would be if the radio could automatically be turned on and wakes me up. (There was no such thing back then). However, I am guessing that some students nowadays might want the similar function from their PCs, so we are going to cover the method to do so today.&lt;/p&gt;
&lt;p&gt;The power status of the Windows are divided into five main categories. Please refer to the link below for further information.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/aa373229(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/windows/desktop/aa373229(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we were to categorize the five different power status, we have Operating mode (S0), Sleep mode (S1, S2, S3) and Hibernation (S4), soft off (s5) and Off(G3). The only categories we can wake up the computer via the software is when it’s on Sleep mode S1,S2,S3 and S4 mode while hibernation (S4) mode is the most frequently used to turn on the computer automatically as it consumes the lowest amount of power.&lt;/p&gt;
&lt;p&gt;Now we will look at the specific way we can turn the computer back on at a certain time. The most common technique for this would be to turn it off to the hibernation and wake it up at a certain time. Turning off the computer via hibernation mode is extremely simple. All it requires is the code as you see below.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;SetSystemPowerState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, it will not work as well as you expect, as we do not have the authority to turn off the power. Thus, we will need to gain the authority through the code SeShutdownPrivilege. This code allows the authority to turn your computer off via the code “SetSystemPowerState” successfully.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; BOOL WINAPI
&lt;span class=&quot;token function&quot;&gt;_EnableShutDownPriv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	BOOL ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	HANDLE process &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	HANDLE token&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenProcessToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TOKEN_ADJUST_PRIVILEGES &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; TOKEN_QUERY
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	LUID luid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;LookupPrivilegeValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SeShutdownPrivilege&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;luid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	TOKEN_PRIVILEGES priv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	priv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PrivilegeCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	priv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Privileges&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Attributes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SE_PRIVILEGE_ENABLED&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	priv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Privileges&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Luid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; luid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AdjustTokenPrivileges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;priv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I am going to cover the method to wake the computer up. In order to get the computer back on from the hibernation mode, we need what we call ‘waitable timer’, which operates when your PC is in the hibernation mode. Its primary function is as same is the timer, which triggers the event we appointed at the designated time. In other words, the event set in prior is triggered automatically as the code prepared starts its progress. The next code shows us how to use the pre-arranged timer. The only fact you need to be aware in this process is that the unit of time is based on 100 nano seconds. If you appoint the positive number, it becomes an absolute time, while using appointing negative becomes a relative time. The absolute time is recognized same as FILETIME on Windows. Therefore, as we appoint the negative number as per below, the timer will initiate itself after certain seconds from the moment we set the timer.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HANDLE timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyWaitableTimer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

__int64 nanoSecs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
LARGE_INTEGER due&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

nanoSecs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;secs &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LowPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HighPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last thing you need to remember is that you need to notify the Windows that certain power is required if you need to turn on the monitor separately once the computer is turned on from the Hibernation mode. All you need is the code as per below, which will trigger the notification and automatically turn on the monitor.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SetThreadExecutionState(ES_DISPLAY_REQUIRED);&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;SetThreadExecutionState(ES_DISPLAY_REQUIRED);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Overall, first you gain the authority, then set the waitable timer and initiate hibernation. When the waitable timer starts its procedure, it notifies the system that we want the power on. This is all done as per the code below.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD CALLBACK
&lt;span class=&quot;token function&quot;&gt;ShutDownProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPVOID p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	PHANDLE timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PHANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;SetThreadExecutionState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ES_DISPLAY_REQUIRED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

PWRMGMT_API BOOL WINAPI
&lt;span class=&quot;token function&quot;&gt;HibernateAndReboot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; secs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_EnableShutDownPriv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HANDLE timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyWaitableTimer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	__int64 nanoSecs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	LARGE_INTEGER due&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	nanoSecs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;secs &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LowPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HighPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; ERROR_NOT_SUPPORTED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HANDLE thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ShutDownProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;SetSystemPowerState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once your PC is turned on, it will be ready for you to do whatever you would like to do.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[학부 수업 명장면, 베스트 3]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4806</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4806</guid><pubDate>Thu, 06 Oct 2011 23:57:32 GMT</pubDate><content:encoded>&lt;p&gt;자주 오시는 분들께서는 아시겠지만 개천절을 기해서 블로그를 리뉴얼 했습니다. 원래 제가 호스팅 받던 곳이 워드프레스 최신 버전을 지원하지 않아서 새로운 호스팅 업체로 옮기고 홈페이지에 있던 자료들도 정리했습니다. 블로깅 하기 이전의 사이트에 있던 자료들을 옮기려고 살펴보다 보니 예전 생각이 새록새록 나더군요. 풋풋한 시절에 제가 작성한 글들에서 묻어나는 풋내랄까요? ㅋㅋ~ 어쨌든 대학 시절에 쓴 글들을 읽고 있으니 자연스럽게 그 시절을 회상하게 되었습니다. 그러다 떠오른 세 가지 장면. 캡쳐해 보았습니다. 학부 4년의 수업 시간 중에서 가장 감동적이었던 장면, 베스트 3입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;처음으로 놀랐던 수업은 다름아닌 유명한 권혁철 교수님의 C언어 수업 시간이었습니다. 1학년 과목 중에 유일한 A+이있습니다. — 그거 말고는 전부 D, F였다죠 ㅠㅜ — 수업을 듣기 전부터 C언어를 알고 있었던 지라 수업은 그다지 새로울 것이 없을 거라고 생각하고 들었습니다. 그런데 아이러니한 사실은 대학 4년 동안 프로그래밍이란 관점에서 내지는 제가 프로그래머로 생활하는데 있어서 가장 큰 교훈을 준 수업은 바로 그 시간에 있었습니다. 그 후에도, 그 전에도 대학교 프로그래밍 수업에서 그런 감동을 느꼈던 적은 없었던 것 같네요.&lt;/p&gt;
&lt;p&gt;사설이 길었습니다. 어떤 내용이었는지 궁금하실 것 같네요. 바로 다름아닌 배열에 관한 내용이었습니다. 간단하게 학생 번호와 학점을 입력 받아 평균을 계산하는 프로그램이 예제였습니다. 너무 쉽죠. 그런데 그전까지 저는 매번 그런 프로그램을 작성할 때마다 항상 배열 오프셋에 -1을 하는 코드를 추가해서 계산을 했었습니다. 왜냐하면 C언어는 특성상 배열 인덱스가 0에서 시작하고 학생 번호는 1에서 시작하기 때문이었죠. 그 때 교수님께서 그러시더군요. 이렇게 멍청하게 하지 않는 방법은 없을까? 조용했습니다.&lt;/p&gt;
&lt;p&gt;교수님 설명이 이어졌습니다. “그럴 필요 뭐 있어. 그냥 배열을 1크게 잡으면 되는 거지.” 학생이 20명이면 21개를 배열로 잡으면 되는 거고, 30명이면 31개를 배열로 잡으면 되는 거라는 말씀이었습니다. 그게 컴퓨터 공학에 있어서의 숙명, 공간과 속도 사이의 트레이드오프라는 설명을 같이 해주셨습니다. 저에게는 샥(shock)이었습니다. 뭔가 번갯불이 머리를 스쳐 지나가는 느낌이었죠.&lt;/p&gt;
&lt;p&gt;여기서 끝이 아니었습니다. 교수님께서 말씀하십니다. “컴퓨터 공학에서 속도와 공간이라는 문제는 흔히 두 마리 토끼에 비유된다. 하나를 잡으면 다른 하나는 놓칠 수 밖에 없는 것이란 말이다. 하지만 이 조차도 때로는 고정관념에 불과하다. 이런 관점에서 앞선 문제를 좀 더 똑똑하게 해결할 수 있는 방법을 아는 사람?” 다시 조용해 졌습니다. 그리곤 포인터를 오프셋만큼 옮기는 테크닉을 설명해 주셨습니다. 배열을 정해진 크기만큼 할당하고 배열의 시작 위치에서 -1한 지점을 가리키는 방법이었죠. 아래와 같이 코딩한 다음 pscore를 배열로 사용한다는 의미입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; score&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pscore &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; score &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;설명을 다 듣고 울었습니다. 물론 가슴속으로 말입니다. 그리곤 아주 잠깐 동안 이래서 엄마가 대학을 가라고 했던 거구나, 라는 생각을 뼈저리게 했었답니다. 지금도 무엇인가를 설계할 때, 프로그래밍을 할 때 가끔 그 수업 시간을 떠올리곤 합니다. ‘더 좋은 방법은 없을까? 내가 진리라고 믿고 있는 것 조차도 고정 관념이 아닐까? 내 틀에 갇혀 있는 것은 아닐까?’ 라는 생각을 하면서 말입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;두 번째 수업은 3번씩 재수강을 하고도 한번도 패스하지 못했던 일반물리학 수업 시간이었습니다. 변명을 좀 하자면 사실 전 물리를 제법 잘합니다. 고교 이과 선택과목도 물리 II였고, 수학능력시험에서 하나도 틀리지 않는 기염을 토했으며, 물리경시대회에 참가하기도 했었죠. 특별한 사유(?!)가 있었습니다. 너무 치명적인 사유였죠. ㅠㅜ&lt;/p&gt;
&lt;p&gt;계절학기 첫 수업 시간이었던 것 같습니다. 교수님께서 들어오시더니 본인의 인생사 이야기를 잠시 하셨습니다. 이어서 일반 물리학 책을 펼치면서 말씀하십니다.&lt;/p&gt;
&lt;p&gt;“여기 뉴턴이 이해한 물리학이 있다. 난 그걸 내가 해석한대로 가르칠 생각이다. 여러분은 여러분의 버전으로 그 내용을 이해하면 된다. 여기에 정답이란 없다. 뉴턴이 잘못된 생각을 했을 수도 있고, 우리 모두가 엉뚱한 착각에 빠졌을 수도 있다. 의문이 있다면 가지는 것이 당연한 일이다. 권위 앞에 주눅들 필요 없다. 그래야 우리 후배들은 더 정확한 물리학을 배울 수 있게 된다.”&lt;/p&gt;
&lt;p&gt;교수님의 짧았던 이 이야기는 저에게 자신감을 주는 동시에, 겸손함을 가르쳐 주었습니다. 정답은 없다는 사실. 누구나 의문을 제기할 수 있다는 사실. 저에게는 세상을 살아 나가는데 무엇과도 바꿀 수 없는 정말 값진 교훈이었습니다. 이 평범한 사실이 말입니다. 그 전에도 그 후에도 누구도 저에게 이런 이야기를 해주진 않았거든요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;학부 마지막 감동 수업은 복학하고 들었던 컴퓨터 구조 수업 시간이었습니다. 지루하던 찰나, 교수님께서 굴곡진 인생을 살았다는 학부인지 대학원인지 동기에 관한 이야기를 하셨습니다. 처음에는 무슨 이야긴가 싶었습니다. 누구지라는 의문이 잠시 들다가 이야기가 중반을 넘어서면서 바로 알겠더군요. 그 친구가 누구인지 말이죠. 한국 프로그래머의 살아있는 전설로 불리는 바로 그 분, 송재경씨였습니다. 신선한 충격이었습니다. 우리 학교에 그 분과 친구였던 교수님이 있다는 사실이 말이죠. 교수님이 그 이야기를 하시는 10분 사이에 완전 새로워 보이는 기적을 경험했다고나 할까요. ㅋㅋ~ 아마 교수님께서 어렵겠지만 송재경씨를 한 번 수업시간에 초빙해 주셨다면 저는 그 교수님을 ‘신’이라 여겼을지도 모르겠습니다. 어쨌든 그런 기회는 저에겐 없었지만 단지 송재경씨와 친구 사이인 교수님께서 계시다는 사실만으로도 전 제법 감동을 받았습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[특정 시간에 컴퓨터를 깨우는 방법]]></title><description><![CDATA[중학교 때 가끔 굿모닝 팝스를 들었습니다. 그런데 잘 아시겠지만 그 때나 지금이나(?!) 굿모닝 팝스는 굉장히 아침 일찍 합니다. 아침잠 많은 제가 듣기에는 제법 벅찬 방송이었죠. 그 시절 뭐 지금처럼 mp…]]></description><link>https://jiniya.net/wp/archives/4511</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4511</guid><pubDate>Tue, 04 Oct 2011 23:57:31 GMT</pubDate><content:encoded>&lt;p&gt;중학교 때 가끔 굿모닝 팝스를 들었습니다. 그런데 잘 아시겠지만 그 때나 지금이나(?!) 굿모닝 팝스는 굉장히 아침 일찍 합니다. 아침잠 많은 제가 듣기에는 제법 벅찬 방송이었죠. 그 시절 뭐 지금처럼 mp3나 인터넷 스트리밍이 흔한 시절도 아니었으니 방송을 놓치면 그냥 그날은 공치는 셈이었습니다. 그래서 전 가끔 내 라디오가 그 시간에 나를 깨워주면 참 좋겠다는 생각을 많이 했었습니다. 제가 그 때 사용하던 구형 라디오는 정말 6.25 때나 쓰던 것처럼 생겼던 것이었지요. 당연히 알람 기능 따위는 없었습니다. 그래서 저는 알람 시계에 연결을 해서 그 녀석이 알람 시계가 울릴 때 켜지도록 하는 기능을 만들었었죠. 한동안 그렇게 잘 썼는데 알람시계를 라디오 내부에 연결을 해두니 미관상 별로 좋지가 않았습니다. 그래서 선을 깔끔하게 한다는 명분아래 시계를 밖으로 빼서 220볼트에 물렸죠. 그리곤 전원을 꽂았습니다. ㅋㅋ~ 미친 짓이었죠. 콘덴서가 펑하고 터지더니 안에서 휴지 같은 것들이 튀어 나오더군요. 그 때 이후로 그런 장난은 다시는 치지 않습니다.&lt;/p&gt;
&lt;p&gt;요즘은 머 라디오는 잘 쓰지도 않으니 종종 컴퓨터로 이런 짓들을 하고 있을 학생들이 있을지도 모르겠다는 생각을 해봅니다. 알람 시계를 컴퓨터에다 연결하는 학생들 말이죠. 컴퓨터가 아침에 자동으로 일어나서는 나에게 정보를 알려주는 일은 상상만으로도 즐겁잖아요. 뭐 일어나서 오늘의 날씨를 알려준다던지, 뉴스를 읽어준다든지 말이죠. 어쨌든 그런 니즈가 많이 있습니다. 물론 똑똑한 학생이라면 알람 시계를 연결하기 전에 웹서핑을 해볼 것이고, 그러면 자신이 사용할 수 있는 프로그램이 제법 많이 있다는 사실에 놀랄지도 모르겠군요. ㅋㅋ~ 오늘은 그런 프로그램들이 어떻게 해당 기능을 구현하는지에 대해서 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;윈도우의 전원 상태는 크게 5가지 상태가 있습니다. 전원 상태에 대한 세부 설명은 아래 페이지에 자세하게 나와 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/aa373229(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/windows/desktop/aa373229(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;크게 구분을 지어 보자면 동작 상태(S0), 수면 상태(S1, S2, S3), 하이버네이션 상태(S4), 소프트 오프 상태(S5), 그리고 완전 오프 상태로(G3) 나뉩니다. 여기서 소프트웨어 적으로 깨어날 수 있는 상태는 동작, 수면, 하이버네이션 상태가 전부입니다. 소프트 오프와 완전 오프 상태에서는 소프트웨어 적으로 깨어날 수가 없습니다. 그 중에서도 컴퓨터를 특정 시간에 깨워주는 소프트웨어들이 자주 애용하는 상태는 다름아닌 하이버네이션입니다. 소프트웨어적으로 깨어날 수 있는 상태 중에서 가장 적은 에너지를 소모하기 때문입니다. 사실 뭐 거의 오프 상태나 다름 없습니다.&lt;/p&gt;
&lt;p&gt;자 그럼 이제 구체적으로 컴퓨터를 특정 시간에 어떻게 깨우는지에 대해서 방법을 알아보도록 하겠습니다. 여기에 사용되는 가장 기본적인 테크닉은 컴퓨터를 하이버네이션으로 끄고, 특정 시간 이후에 다시 깨우는 것입니다. 그렇담 당연히 하이버네이션으로 끄는 것을 먼저 알아야겠죠. 하이버네이션을 시키는 방법은 정말 간단합니다. 아래와 같은 단 한줄의 코드면 충분합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SetSystemPowerState(FALSE, FALSE);&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;SetSystemPowerState(FALSE, FALSE);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 세상 일이란게 그리 쉽진 않죠. 생각처럼 잘 동작하지 않을 겁니다. 왜냐하면 우리에겐 권한이 없거든요. 전원을 꺼버릴 권한이요. 그렇다면 당연히 해당 권한을 획득해야겠죠. SeShutdownPrivilege가 그런 역할을 하는 권한입니다. 아래 코드는 그런 권한을 획득하는 역할을 합니다. 아래 코드를 통해서 권한을 획득하고 SetSystemPowerState를 하면 정상적으로 꺼지는 것을 확인하실 수 있을 겁니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; BOOL WINAPI
&lt;span class=&quot;token function&quot;&gt;_EnableShutDownPriv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	BOOL ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	HANDLE process &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	HANDLE token&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenProcessToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TOKEN_ADJUST_PRIVILEGES &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; TOKEN_QUERY
						&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	LUID luid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;LookupPrivilegeValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SeShutdownPrivilege&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;luid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	TOKEN_PRIVILEGES priv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	priv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PrivilegeCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	priv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Privileges&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Attributes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SE_PRIVILEGE_ENABLED&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	priv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Privileges&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Luid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; luid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AdjustTokenPrivileges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;priv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제는 다시 깨우기 위한 준비를 배워봅시다. 하이버네이션 상태에서 깨어나기 위해서는 윈도우에서 제공해주는 대기 타이머라는 것을 사용합니다. 웨이터블 타이머(waitable timer)가 정식 명친인데요, 이 녀석은 하이버네이션 상태가 되더라도 동작한다는 끈질긴 특징이 있습니다. 기본적인 기능은 타이머와 동일하다고 생각하면 되겠습니다. 즉, 우리가 지정한 시점이되면 이벤트가 트리거되고 타이머를 대기하던 코드가 깨어나서 수행되는 겁니다. 다음 코드는 대기 타이머를 사용하는 방법을 보여주고 있습니다. 여려운 건 없죠. 단지 시간이 100나노초 단위라는 것에 주의하면 되겠습니다. 양수를 지정하면 절대 시간을, 음수를 지정하면 상대 시간이 됩니다. 절대 시간은 윈도우에서 사용하는 FILETIME과 동일한 값을 가집니다. 아래 코드에서는 음수를 지정했으니 타이머를 대기하는 순간부터 secs초 이후에 해당 타이머가 발동하는 구조가 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HANDLE timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyWaitableTimer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

__int64 nanoSecs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
LARGE_INTEGER due&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

nanoSecs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;secs &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LowPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HighPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;끝으로 한 가지 더 기억해야 할 것이 있습니다. 하이버네이션 상태에서 깨어난 다음에 모니터 전원이 필요하다면 윈도우에 해당 전원이 필요하다는 사실을 알려주어야 합니다. 어떻게 요청하냐구요? SetThreadExecutionState(ES_DISPLAY_REQUIRED); 이 한 줄이면 충분합니다. 해당 함수를 호출하면 윈도우는 모니터 전원이 필요하다는 것을 눈치채고 모니터에도 전원을 공급해 줍니다. 즉, 모두 다 종합해보면 이렇습니다. 권한을 얻고, 웨이터블 타이머를 설정하고, 하이버네이션을 시킵니다. 웨이터블 타이머가 동작하면 시스템에 우리가 모니터 전원이 필요로 하다는 의사를 알려주고는 하고 싶은 나머지 작업을 진행하면 됩니다. 아래 코드에 모두 다 들어 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD CALLBACK
&lt;span class=&quot;token function&quot;&gt;ShutDownProc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPVOID p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	PHANDLE timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PHANDLE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;WaitForSingleObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INFINITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;SetThreadExecutionState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ES_DISPLAY_REQUIRED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

PWRMGMT_API BOOL WINAPI
&lt;span class=&quot;token function&quot;&gt;HibernateAndReboot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; secs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_EnableShutDownPriv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HANDLE timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyWaitableTimer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	__int64 nanoSecs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	LARGE_INTEGER due&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	nanoSecs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;secs &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LowPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HighPart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LONG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nanoSecs &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetWaitableTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetLastError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; ERROR_NOT_SUPPORTED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	HANDLE thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ShutDownProc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;CloseHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;SetSystemPowerState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;깨우고 난 다음 무엇을 할지는 전적으로 여러분의 몫입니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[지식 근로자 관리의 어려움…]]></title><description><![CDATA[#…]]></description><link>https://jiniya.net/wp/archives/3803</link><guid isPermaLink="false">https://jiniya.net/wp/archives/3803</guid><pubDate>Mon, 26 Sep 2011 23:57:30 GMT</pubDate><content:encoded>&lt;p&gt;#0.&lt;/p&gt;
&lt;p&gt;예전에 회사 생활을 하다가 울었던 적이 딱 한 번 있었다. 그 시절 나는 제법 열심히 일하는 프로그래머였는데, 한 날은 같은 팀원들끼리 게임을 하고 있었다. 그런데 같이 게임을 하다가 유독 나만 혼이 난 것이었다. 웃긴 것은 내가 혼날 만한 하등의 상황이 아니었다는 점이었다. 사실 혼난게 뭣같아서 울었다기 보다는 억울해서 울었다. 누가봐도 그건 아닌 상황이었기 때문이었다.&lt;/p&gt;
&lt;p&gt;그 때 느꼈다. 아 이거 x빠지게 열심히 일해봤자 하나도 소용없구나. 그 날로 그냥 쉬엄쉬엄 회사를 다녔다. 할 줄 아는 것도 남들이 못하면 못한다고 했고, 금방 할 수 있는 것도 개발팀에서 제일 못하는 사람 바로 위 정도로 일정을 맞췄다. 당연히 남들이 못잡는 버그는 나도 잡지 않았다. 그리고는 이해 관계가 끝나기가 무섭게 회사를 그만뒀다. 그런 회사에서 일하고 싶지는 않았기 때문이다. 마음이 그랬다.&lt;/p&gt;
&lt;p&gt;#1.&lt;/p&gt;
&lt;p&gt;뛰어난 개발자의 딜레마라는 이야기가 있다. 뛰어난 개발자 A와 그저 그런 B가 있을 때 아주 어려운 과제 P가 주어진 상황이다. A는 2달을 놀다가 2주만에 P를 깔끔하게 해결했고, B는 3달 동안 x빠지게 밤새고 야근하고 다녔지만 결국 해결하지 못했다. 이 때 보통 관리자는 A는 농땡이를 쳤다고 생각하고, B는 최선을 다했음에도 과제가 너무 어려웠다고 판단한다는 것이다. 결국 승진은 B가 한다는 서글픈 스토리다. 사실 내가 봐도 세상은 좀 그렇다. 특히 대기업 다니는 형들이 그런 이야기를 많이 한다.&lt;/p&gt;
&lt;p&gt;#2.&lt;/p&gt;
&lt;p&gt;우리 회사에도 뛰어난 개발자들이 많이(?!) 있다. 난 그런 개발자들이 나와 같은 감정을 회사에 느끼지 않기를 바란다. 사실 그런 감정을 느끼면 우리는 최고의 개발자가 아니라 그냥 타이핑 하는 기계 하나를 더 가진 것이나 다름 없기 때문이다. 그만큼 지식 근로자에게 감정은 중요하고, 어렵지만 공정한 보상은 중요하다. 그런데 6살 어린 아이도 똑바로 할 것 같은 이 단순한 “공정한 보상”이라는 것이 실상은 굉장히 어렵다.&lt;/p&gt;
&lt;p&gt;가장 큰 어려움은 바로 성과를 공정하게 판단한다는 그 자체가 불가능에 가까울 정도로 어려운 문제라는 점이다. 성과를 공정하게 판단하기 위해서는 과제의 난이도 x와 개인의 역량 y를 정확하게 측정하는 것이 가능해야 하는데, 이걸 측정한다는 것이 사실상 거의 불가능하기 때문이다. 과제의 난이도가 일정 수준 이상이 되면 누구도 그 문제가 얼마나 해결하기 어려운지 판단할 수 없다. 마찬가지로 개인의 역랑 y도 일정 수준을 넘어서면 그 사람이 얼마나 가능성이 있는지를 가늠하는 일 자체가 쉽지 않다. 즉, 지식 근로자의 성과를 측정한다는 자체가 애초에 넌센스라는 이야기다.&lt;/p&gt;
&lt;p&gt;물론 이러한 개념적인 어려움 외에도 이 문제를 힘들게 만드는 점이 있다. 바로 감정이다. 평가라는 것이 주관을 넘어서는 이루어질 수 없기 때문이다. 열손가락 깨물어서 안아픈 손가락이 없다고 하지만 무던 더 아픈 손가락이 있기 마련이다. 기계가 아닌 사람이 평가하면서 이러한 감정을 배제하기란 불가능에 가깝다. 이런 연유로 그렇게도 많은 직장인들이 처세에 몰두하는지도 모르겠다.&lt;/p&gt;
&lt;p&gt;끝으로 이 문제를 NP 컴플리트로 만드는 일등 공신은 다름아닌 간신들이다. 능력 없는 사람들은 보통 처세에 능하다. 그도 그럴 것이 먹고 살 방법이 그 길 밖에는 없기에 그 쪽 분야에 퍽이나 신경을 쓴다. 그러면서 열심히 일하는 사람들의 사생활부터 시작해서 아주 사소한 것들까지 들먹이면서 흠집을 낸다. 안타깝게도 아래 직원이 하고 있는 일을 정확하게 평가할 수 있는 능력의 관리자가 아니라면 이 흠집은 아주 그럴싸해 보인다. 그리고는 다음날 거위의 배는 갈라진다. 그렇게 어처구니 없는 말 한마디에 황금알을 낳는 거위가 사라지는 것이다. 애처로운 현실이다.&lt;/p&gt;
&lt;p&gt;#3.&lt;/p&gt;
&lt;p&gt;그렇다면 거위의 배를 가르지 않기 위해서는 어떻게 해야 할까? 핵심 가치에 집중해야 한다. 세상에 영구 기관은 없고 만병통치약도 없다. 사람은 누구나 장점도 있고, 몇 가지 정도는 단점도 가지고 있게 마련이다. 그 단점이라는 것이 회사에서 그 사람에게 요구해야 하는 핵심 가치가 아니라면 어느 정도는 신경쓰지 않을 필요가 있다는 것이다. 싱거워 보이는 이 사소한 일이 얼마나 어려운지는 두말하면 잔소리다.&lt;/p&gt;
&lt;p&gt;뛰어난 인력으로 넘쳐나는 대기업은 이런 고민이 필요 없을지도 모르겠다. 거기에는 아주 중요한 나사 하나쯤 빠져도 그 자리를 메워줄려고 대기하는 수많은 부품들이 있을테니깐 말이다. 하지만 작은 기업들에게는 사람이 전부다. 특히나 근속 횟수가 많고 히스토리를 아는 직원들의 가치란 상상을 초월한다. 그래서 더욱 그들을 보호해야 하고, 그들이 공정한 보상을 받을 수 있도록 해줘야 한다. 그들이 공정한 보상을 받지 못해 단순 타이핑 기계로 전락하거나 조금이라도 더 나은 보상을 받기 위해 능력 개발보다 처세에 집중할 때 회사 발전은 그날로 끝난 거나 다름 없는 셈이기 때문이다.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[광식이 동생 광태]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4543</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4543</guid><pubDate>Thu, 25 Aug 2011 23:57:29 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;그 장면… 기억나지?? 윤경이랑 광태랑 삼겹살 집 같은데서 대화하는 장면…&lt;/p&gt;
&lt;p&gt;광태가 윤경이한테 묻잖아- “우리 형이 윤경씨 어떻게 생각하는지 알았죠?”&lt;/p&gt;
&lt;p&gt;그러면 윤경이가 그러잖아- “바보가 아닌 이상 나도 짐작은 하죠. 근데, 여자들은 짐작만으로는 움직이지 않아요.”&lt;/p&gt;
&lt;p&gt;여자들은 정말 그래- 짐작만으론 움직이지 않고, 남자의 마음을 알면서도 확인하고 싶어하거든.&lt;/p&gt;
&lt;p&gt;– 그 여자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;영화에 공감가는 대사, 장면들이 무지 많았는데, 특히나 인상 깊었던 장면은 광태가 여자 친구한테 차이는 장면. 여자 친구가 그러자나 “너랑 나랑 추억이 있냐?” 그리곤 광태의 독백이 이어지잖아, “그녀와 난 추억이 정말 없다. 모텔, 차, 집 … 모텔, 차, 집… ” 이상하게 그 장면이 인상 깊더라공.&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;p&gt;언젠가 49-1번을 타려고 버스 정류장으로 가던 날이었어. 하나로 카드가 바닥나서 그 앞 편의점엘 들어갔는데 갑자기 당신 얼굴이 떠올랐어. 저쪽 라면대 위에 네가 올라가 있는거 같았거든. 그래서 나도 모르게 아이스크림을 사가지고는 그 쪽으로 가서 먹었지. 그 장소, 그 시간, 그 물건엔 네 생각이 베어 있었나 봐. 추억이란 그런 거 아닐까? 한참 후에, 시간이 엄청 많이 지난 후에도, 당신에게 가끔은 내 생각이 나는 어떤 장소, 어떤 시간, 어떤 물건들이 있었으면 좋겠다.&lt;/p&gt;
&lt;p&gt;– 그 남자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[조엘 온 소프트웨어]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4497</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4497</guid><pubDate>Mon, 01 Aug 2011 23:57:28 GMT</pubDate><content:encoded>&lt;p&gt;음… 많은 사람들이 너무나도 마니 극찬을 했기에 나까지 칭찬할 필요가 있을까 하는 생각이 들지만… ㅎㅎㅎ~ 눈물없이 볼 수 없었던 책이었기에 칭찬을 좀 붙여볼까?? 한다.. 몇일전 강컴에서 구매한 책의 하나로 조엘 아저씨가 블로그에 기고한 글들을 묶어서 책으로 출간한 것이다. 나온지는 꽤(?!) 되었다. 나름대로 이전에 조엘씨 블로그를 조금 봤었으나 그다지 큰 감흥은 없었다. 오늘 느낀 점은 아무래도 어려운 영어 때문이 아니었나 하는 점이었다. 한글로 다시 만나보니 감동 백배였다.&lt;/p&gt;
&lt;p&gt;책을 어제 읽기 시작해서 조금 보다가 오늘 레폿하다 심심해서 마저 읽어버렸다. 음음… 그런데 단숨에 읽게하는 소설같은 마력이 있다. ㅎㅎㅎ~ 글이 워낙 재밌기도 하고 기지가 넘치다 보니 그런것 같다. 그게 아마도 이 책의 가장 큰 장점이 아닐까 하는 생각이 든다. 그의 다양한 경험에서 나오는 뛰어난 통찰력들을 종종 볼 수 있다.&lt;/p&gt;
&lt;p&gt;cvs를 써야 한다는 점. 일일빌드를 해야 한다는 점. 사용자에게 자동화된 버그 보고를 받아야 한다는 점. 모든것을 새로 개발하는 것은 좋지 않지만, 적어도 가져다 쓰되 지나친 의존성은 가지지 말아야 한다는 점등은 기존의 내가 가지고 있는 생각과 일치했다.&lt;/p&gt;
&lt;p&gt;버그 패치를 비용 관점에서 볼 수 있다는 점. 대형 벤더의 오픈 소스 지지를 미시 경제학적인 관점에서 분석해본 점. 닭이 먼저냐 달걀이 먼저냐의 문제를 호환성 측면에서 바라본 점등은 다소 신선한 아이디어로 보였다.&lt;/p&gt;
&lt;p&gt;다소 차이가 났었던 부분으로는 블로트웨어가 있었다. 그는 대부분의 사용자가 사용하는 기능이 전체 기능의 20% 밖에 되지 않는 건 맞지만 대부분의 사용자가 서로 다른 20%를 주로 사용한다는 점에서 블로트웨어를 당연하다고 피력했다. 음… 난 기존에 simply the best란 오래된 유닉스 격언 추종자로 당연히 사라져야할 악으로 생각했으나… 그의 관점이 맞을 수 있을것도 같다는 느낌이 들었다. 얼마전 워드를 쓰는 나에게 수식 편집이 불편하지 않냐고 물어본 한글 애용자 처럼 사람들이 쓰는 20%는 제각각이란 생각이든다~&lt;/p&gt;
&lt;p&gt;내가 XP를 가지고 설계를 안하는데 정당한 방패로 삼은 것에 대해서 그의 지적을 들을 수 있었던 점은 좋았다. 앞으론 설계를 열심히 해야 겠다는 생각을 가졌다. ㅋㅋㅋ 역쉬 귀가 얇은… 소심남… ^^ 그리고 msdn에 대한 의견은 정말 나와같았다. 정말 몇해전 msdn을 봐도 볼 수 있는 챕터라곤 한두개 밖에 없다. win32 q&amp;#x26;a 정도… ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;에릭 레이먼드의 TAOUP(The art of unix programming)에 대한 다소 비난적인 부분도 그리 썩 맘에 들지 만은 않았다. 그런데 사실 레이먼드 아저씨가 완전 유닉스맨인건 사실이다. 하지만 그의 책을 읽으면서 느낀건 조엘씨도 완전 윈도우맨이란 사실이다. 서로 피장파장 정도였다. 그러나 그가 TAOUP의 전부를 무시 하지 않은 점은 정말 다행이었다. ㅋㅋㅋ~ TAOUP도 눈물 흘리며 읽었기에… ㅋㅋㅋ~&lt;/p&gt;
&lt;p&gt;음~ 읽다가 생각난건 나도 미시 경제학을 한번 들어봐야 겠다는 점이었다… 그리고 또 하나는 우리학교가 일학년들에게 C에서 VB를 가르치기로 바꾼건 좀 실수가 아니었나 하는 생각… 조엘씨가 마이크로소프트에 굉장히 우호적인 감정을 가지고 있으며, 그가 MS에서 한일에 대해서 프라이드를 마니 가지고 있다는 점… @.@&lt;/p&gt;
&lt;p&gt;그리고 챕터가 끝으로 갈수록 묘해지는 그의 리치 클라이언트에 대한 생각들은 지금 현재 그러한 것들을 개발하는 나로써는 다소 받아들이기 힘들었다. 웹이 대세란 말인가? ㅎㅎ~&lt;/p&gt;
&lt;p&gt;꽤나 다양한 생각을 할 수 있게 해준 좋은 책이었던거 같다. 올만에 진국을 만난듯한 느낌??? ㅎㅎㅎ~ 오랜만에 독서를 한거겠지. ㅋㅋ 개발과 관련된 분야에 있다면 꼭 일독하기를 권하고 싶다. 특히나 관리자라면… 더더욱~ ^^&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[비스타 테마 리스트 컨트롤 만들기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4479</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4479</guid><pubDate>Sun, 31 Jul 2011 23:57:27 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; margin-bottom: 16px;&apos; data-url=&apos;./비스타_테마_리스트_컨트롤_만들기.md_0.png&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/756500c45a45efb88c866ee78ed69aeb/dface/%EB%B9%84%EC%8A%A4%ED%83%80_%ED%85%8C%EB%A7%88_%EB%A6%AC%EC%8A%A4%ED%8A%B8_%EC%BB%A8%ED%8A%B8%EB%A1%A4_%EB%A7%8C%EB%93%A4%EA%B8%B0.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 67.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAADKklEQVR42lWT6VPbVhTF9Xf3Uz/3S0rbEAJt2qRDm5BQhmBinMYmGDBgYzYveNNmW4steZVjW1749UmknemdOSPp3XfPPefdJ2kr2SCW0YhdGkQyNhsxjbVYnWdRjSc7JZ7t13hz1mM73efNqcvzA531mM7mcZu9yy6f831S+RbXZ3l2tv9G+ubXGGvv4zx5G+eX6BmrOwk29o5Z2U3y/c4hP0WOeZG44mXyVuCG1dgF321/YiWS5MdoiqexFGufzvk5ecXKQRpp6/CCzXiG10dZIhc5dlPXrEcSPBWb18X6RiLL2seUaPiBjYMjNpNpnu/H+f3onD9PM/yWOOHVUYq3ZxlW9+JIY3/BYzx8fS7wejUG/R7/hj8Z45hNXNtkMhph6Br9bvex6uEhRBCp6wKS3PLwZ3OBWficzaeYjVtct8NisWA+nzMYDJBlhZpAq+1QKpVoGhaL5QNTfxZiuVwST98g9b0xs5kfFs7nC6bTiSC8w7SscFPQ3fM8VFVFEeh2OlQqFSzLDlUFdTMhJoh3H5NI5aZJ07RE4rHLZDKibeVwHCckW/6PUKErrFYrZexW6z/CAEG8/pAQlg2NarUa2gqi7bgcHl+jKqpQYQnrLq4g174qDL5luUZF1ATHFDQNmoyGA/aPM0iqXAjtBV2W4syG3ojLq2J4To1Gk16vL9BD0zRUgY6wXK/r3Iu8bdvhMAM3vW6Hg1QWyTQN0a0slDkh6dT3Me0WSi2YdD9U/UVY1jUVXUw3KNR1lftiAVWWBd9SOGiLqXeInl4iTb/Y1Kp5jKYl5C8Zj8fkikXKsk5/7DMWt8rpe5RqgkTWMJyOeFfI5goooibIN+w2bXEroifC8mLmUinf0WjaobrA8l2pwm2xSqvnMfSX2N0B+YpCrqqgGC2KgjhXkTE7wzCv2Q5m22X38znSX3/8gGqKTYpOXXS3+kNKdYNyw0B3u9ijMb3FA63xnKY3Qxv4yD2fcsen6PjcWhPSdY+sMWEtKn69Fy9XyTcdCgL3Vpdco01WbnKpGiFuxPqt4XKhWqR1h5OaTeSqyvtsje2LCltn5RDv0grfvoryD0B47Yl6qWKPAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;                   md 0&apos; title=&apos;&apos; src=&apos;/static/756500c45a45efb88c866ee78ed69aeb/dface/%EB%B9%84%EC%8A%A4%ED%83%80_%ED%85%8C%EB%A7%88_%EB%A6%AC%EC%8A%A4%ED%8A%B8_%EC%BB%A8%ED%8A%B8%EB%A1%A4_%EB%A7%8C%EB%93%A4%EA%B8%B0.md_0.png&apos; srcset=&apos;/static/756500c45a45efb88c866ee78ed69aeb/08678/%EB%B9%84%EC%8A%A4%ED%83%80_%ED%85%8C%EB%A7%88_%EB%A6%AC%EC%8A%A4%ED%8A%B8_%EC%BB%A8%ED%8A%B8%EB%A1%A4_%EB%A7%8C%EB%93%A4%EA%B8%B0.md_0.png 190w,
/static/756500c45a45efb88c866ee78ed69aeb/2edd7/%EB%B9%84%EC%8A%A4%ED%83%80_%ED%85%8C%EB%A7%88_%EB%A6%AC%EC%8A%A4%ED%8A%B8_%EC%BB%A8%ED%8A%B8%EB%A1%A4_%EB%A7%8C%EB%93%A4%EA%B8%B0.md_0.png 380w,
/static/756500c45a45efb88c866ee78ed69aeb/dface/%EB%B9%84%EC%8A%A4%ED%83%80_%ED%85%8C%EB%A7%88_%EB%A6%AC%EC%8A%A4%ED%8A%B8_%EC%BB%A8%ED%8A%B8%EB%A1%A4_%EB%A7%8C%EB%93%A4%EA%B8%B0.md_0.png 600w&apos; sizes=&apos;(max-width: 600px) 100vw, 600px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;비스타에서 리스트 뷰는 상당히 고급 스런 디자인을 하고 있습니다. 특히나 선택 영역은 과거의 그것과는 비교가 불가할만큼 고급스럽죠. ㅎ 저런데서 그냥 푸른색 칠해진 리스트 뷰를 보면 정말 싼티나 보입니다. 대부분의 개발자가 저도 그랬고, 리스트 뷰가 비스타에 가면 그냥 자연스럽게 저렇게 그려질거라 생각합니다. 커먼 컨트롤이 업그레이드 되면서 그렇게 됐겠지 하는 생각을 하죠. 그런데 천만에 말씀, 만만에 콩떡입니다. 매니페스트를 적용한 프로그램의 리스트도 저렇게 고급스럽게 그려지지 않죠. 그렇다면 도대체 이 마법 같이 아름다운 리스트 컨트롤은 어떻게 해야 만들 수 있는 걸까요?&lt;/p&gt;
&lt;p&gt;물론 그렇게 어렵지는 않습니다. ㅋㅋ~ 바로 마법 같은 함수가 있기 때문이죠. &lt;strong&gt;SetWindowTheme&lt;/strong&gt;라는 함순데요. 여러분이 사용하는 리스트 컨트롤에 대고, &lt;strong&gt;SetWindowTheme(리스트 컨트롤 핸들, _T(“explorer”), NULL);&lt;/strong&gt; 하는 순간 싼티나던 리스트 컨트롤이 탐색기의 그것과 똑같아지는 기적을 경험하게 될겁니다. 안된다구요? 네. 아마 커스텀 드로나 오너 드로를 사용하고 계신가 보군요. 그렇다면 좀 더 복잡하지만 &lt;strong&gt;DrawThemeBackground&lt;/strong&gt;라는 함수를 사용하셔서 배경을 그리면 되겠습니다. 참고로 이 두 함수를 사용하기 위해서는 uxtheme.h 파일과 uxtheme.lib 파일이 필요합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[DLL_PROCESS_DETACH의 비밀]]></title><description><![CDATA[예전 글에서 DllMain이 얼마나 위험한 곳인지, 로더락이란 것이 얼마나 무서운 놈인지에 대해서 소개했었습니다. 그 때 주로 로더락 관점에서 DllMain에서 하지 말아야 할 것들을 소개 했는데요. 이 로더락을 배제하고도 DLL_PROCESS…]]></description><link>https://jiniya.net/wp/archives/4457</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4457</guid><pubDate>Sun, 31 Jul 2011 23:57:26 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.jiniya.net/tt/788&quot;&gt;예전 글에서 DllMain이 얼마나 위험한 곳인지, 로더락이란 것이 얼마나 무서운 놈인지에 대해서 소개했었습니다.&lt;/a&gt; 그 때 주로 로더락 관점에서 DllMain에서 하지 말아야 할 것들을 소개 했는데요. 이 로더락을 배제하고도 DLL_PROCESS_DETACH가 호출되는 시점에는 주의해야 할 것이 있습니다. 바로 이 놈이 호출되는 시점입니다. 보통 여러분이 알고 있는 것처럼 DLL_PROCESS_DETACH로 DllMain이 호출되는 시점은 DLL이 프로세스로부터 떨어져 나가는 시점. 즉, FreeLibrary가 호출되서 해당 DLL의 레퍼런스 카운트가 0이 되는 시점에 호출됩니다. 하지만 이 경우 외에도 다른 한 가지 경우가 더 있습니다. 바로 프로세스가 종료되는 시점에도 호출되죠.&lt;/p&gt;
&lt;p&gt;이런 특성 때문에 DLL_PROCESS_DETACH에 대해서 가지는 흔한 오해가 있는데요. 바로 TerminateProcess에 의해서 종료될 때에도 DLL_PROCESS_DETACH가 실행된다는 것과, DLL_PROCESS_DETACH에서 종료 작업을 하는 것이 좋다라는 생각입니다. 물론 이 두 가지 생각 모두 제대로 잘못된 생각들입니다.&lt;/p&gt;
&lt;p&gt;우선 프로세스의 종료를 만들어내는 두 가지 API, ExitProcess와 TerminateProcess의 구현을 살펴보면 아래와 같이 되어 있습니다. 보이는 것처럼 둘 다 NtTerminateProcess를 사용합니다. 둘의 차이라면 ExitProcess는 이 NtTerminateProcess 이후에 shutdown process라는 작업을 진행하는 것이라고 보면 되겠습니다. 이 shutdown process의 진행 과정의 일환으로 호출되는 것이 DLL_PROCESS_DETACH입니다. 따라서 TerminateProcess로 프로세스가 종료될 때에는 이 shutdown process라는 것이 존재하지 않기 때문에 당연히 DLL_PROCESS_DETACH의 호출 또한 받을 수 없습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ExitProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;NtTerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// shutdown process&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;NtTerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;TerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;NtTerminateProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Process&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ExitCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리가 ExitProcess의 구현에서 눈치채야할 다른 중요한 시사점은 바로 NtTerminateProcess를 호출한 다음 shutdown process를 진행한다는 점입니다. 여기에는 굉장히 중요한 점이 내포되어 있는데요. 바로 여러분의 DLL_PROCESS_DETACH가 호출되는 시점에는 그 어떠한 스레드도 살아 있지 않다는 점입니다. NtTerminateProcess(NULL, ExitCode)를 거치는 순간 해당 프로세스의 모든 스레드는 강제로 터미네이트(Terminate)되기 때문입니다.&lt;/p&gt;
&lt;p&gt;요약하면 이렇습니다. &lt;strong&gt;DLL_PROCESS_DETACH가 호출되는 시점에는 스레드가 다 죽고 없는 시점이다. 따라서 DLL_PROCESS_DETACH에서 복잡한 클린업 작업을 하는 것은 **짓이나 다름 없다.&lt;/strong&gt; 여기서 복잡하다는 것은 적어도 스레드를 하나 이상 생성해서 종료 작업에 해당 스레드가 필요한 녀석으로 이해하면 되겠습니다. 물론 이런 작업 외에 간단한 작업도 하지 않는 것이 정신 건강에는 무척 유익합니다.&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[리소스 풀어 헤치기]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4366</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4366</guid><pubDate>Sun, 31 Jul 2011 23:57:25 GMT</pubDate><content:encoded>&lt;p&gt;디버그뷰나 프로세스 익스플로러같은 프로그램을 보면 실행 파일 하나로 구성되어 있는데 프로그램을 실행하면 드라이버를 로딩하는 것을 볼 수 있습니다. 어떻게 하는 걸까요? 답은 간단한데요. 해당 드라이버 파일을 리소스에 포함시켜 놓고 런타임에 풀어서 사용하는 방식입니다. 리소스에 추가하는 방법은 간단합니다. Visual Studio 리소스 뷰에서 오른쪽 클릭하시고 임포트 하시면 됩니다. sys 파일 같은건 안보이시죠. *.*로 필터링한다음 추가하시면 됩니다. 그러면 어떤 타입을 추가할지 물어볼텐데요. 아무렇게나 이름을 지어 주시면 됩니다. Binary 이런 식으로요. 자 그렇다면 이제 이렇게 추가된 리소스 파일을 런타임에 어떻게 조작하는지를 알아보도록 합시다.&lt;/p&gt;
&lt;p&gt;조작하는 API는 소 심플합니다. FindResource, LoadResource, SizeOfResource, LockResource라는 API가 사용됩니다. 각각의 함수 사용 방법을 알아보도록 합시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HRSRC &lt;span class=&quot;token function&quot;&gt;FindResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE hModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR lpName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR lpType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;FindResource 함수입니다. 이 함수는 우리가 분리해 내려고 하는 리소스를 찾는데 사용됩니다. hModule에는 리소스를 찾을 DLL의 모듈 핸들을 넣어주면 됩니다. NULL을 전달하면 현재 프로세스의 실행 파일 모듈에서 찾습니다. lpName에는 리소스 이름을 전달합니다. MAKEINTRESOURCE를 사용해서 리소스 ID를 문자열로 변환한 것을 대입해 주면 됩니다. 리소스 ID가 IDR_BINARY1이라면 MAKEINTRESOURCE(IDR_BINARY1)을 전달하면 되겠죠. lpType에는 리소스 타입을 넣어줍니다. 리소스 타입이 Binary라면 “Binary”를 전달하면 됩니다. 이렇게 넣어주면 리소스를 찾아서 해당 리소스의 핸들을 넘겨줍니다. 실패하면 NULL이 리턴되겠죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;DWORD &lt;span class=&quot;token function&quot;&gt;SizeofResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE hModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HRSRC hResInfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;러소스의 크기를 구할 때 사용하는 함수입니다. hModule에는 모듈 핸들을 hResInfo에는 FindResource를 통해서 찾은 리소스 핸들을 넣어줍니다. 성공한 경우에는 리소스 크기를, 실패한 경우에는 0을 리턴합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;HGLOBAL &lt;span class=&quot;token function&quot;&gt;LoadResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE hModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HRSRC hResInfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;리소스를 로드하는 함수입니다. hModule에는 모듈 핸들을 hResInfo에는 FindResource로 찾은 리소스 핸들을 전달하면 되겠습니다. 해당 리소스의 포인터가 리턴됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LPVOID &lt;span class=&quot;token function&quot;&gt;LockResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HGLOBAL hResData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;마지막 함수입니다. LoadResource 한 메모리의 실제 포인터를 반환합니다. hResData에는 LoadResource에서 반환한 포인터를 넣어줍니다. 그럼 실제 포인터가 리턴됩니다.&lt;/p&gt;
&lt;p&gt;종합해서 함수 하나로 만들어 봅시다. GetResourceInfo라는 함수입니다. module에서 type, name의 리소스를 찾아서 해당 리소스의 포인터를 data에 크기를 rsize에 있는지 없는지를 리턴 값으로 리턴해 주는 함수입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;BOOL WINAPI &lt;span class=&quot;token function&quot;&gt;GetResourceInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HMODULE &lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR type
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPCTSTR name
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PVOID &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;rsize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    DWORD size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HGLOBAL mem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    PVOID ptr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    HRSRC src&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindResourceW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SizeofResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    mem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;mem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LockResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ptr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    __try
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ptr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rsize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;rsize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EXCEPTION_EXECUTE_HANDLER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지만 설명하고 마칠까 하는데 아마 똑똑한 분들이라면 먼가 찜찜한 기분이 드실 거예요. 화장실가서 볼 일 보고 뭔가 정리하지 않고 나온 느낌이겠죠. 실컷 로딩하고 락하고 했는데 그것들을 해제하는 작업에 대해서는 하나도 설명하지 않았으니 말입니다. UnlockResource, FreeResource와 같은 함수들이 있긴 한데, 그것들은 사용하지 않아도 됩니다. 왜냐하면 여기서 사용하는 리소스 핸들을 구하고 하는 함수들은 로드된 모듈에서 포인터를 참조해 오는 일이거든요. 여러분이 획득한 모든 포인터 내지는 리소스는 hModule이 FreeLibrary 되는 시점에 같이 사라집니다. 따라서 별도로 해제할 필요가 없는 셈이죠. 참고로 그래도 나는 해제하겠다고 UnlockResource, FreeResource를 호출한들 실제 해당 함수에서 하는 일은 return 밖에는 없답니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Visual Studio로 드라이버 개발하기]]></title><description><![CDATA[빌 조이는 vi로 vi를 개발하고, 리차드 스톨만 아저씨는 emacs를 emacs…]]></description><link>https://jiniya.net/wp/archives/4195</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4195</guid><pubDate>Sun, 31 Jul 2011 23:57:24 GMT</pubDate><content:encoded>&lt;p&gt;빌 조이는 vi로 vi를 개발하고, 리차드 스톨만 아저씨는 emacs를 emacs로 개발한다는 전설같은 무용담들이 있지만, 우리같은 쪼렙 개발자들에게는 에디터보다는 편리한 툴들이 필요합니다. 전 그간 드라이버를 개발할 때에는 소스 인사이트라는 프로그램을 사용했는데, 혼자 개발할 때에는 그럭 저럭 편했는데 여러 명이 개발하게 되니깐 좀 불편하더군요. 그래서 여차저차해서 Visual Studio로 개발 환경을 모두 통합하게 되었습니다. 물론 이제는 &lt;a href=&quot;http://zpacket.blogspot.com/2011/06/visual-studio.html&quot;&gt;Visual Studio에 드라이버 개발 프로젝트&lt;/a&gt;가 빌트인된 시대지만 아직까지 구시대적인 개발 방법도 필요한지라 정리해놓습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#0.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;제일 먼저 필요한 도구는 ddkbuild입니다. ddkbuild.bat 파일만 있으면 끝입니다. 해당 파일을 Visual Studio 프로젝트 파일이 있는 폴더에 같이 복사해 둡니다. 깔았냐, 머 설치해라 이런말 안해도 되서 여러모로 편합니다. 근데 ddkbuild를 어디서 다운 받냐구요? &lt;a href=&quot;http://www.hollistech.com/Resources/ddkbuild/ddkbuild.htm&quot;&gt;여기서&lt;/a&gt; 받으시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ddkbuild 설명서를 보면서 sources 파일을 수정하면 한 군데서 막힐 텐데요. 브라우저 정보를 생성하는 부분이죠. 아래와 같이 브라우저 정보를 생성하도록 source 파일을 수정하면 오류가 발생할 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;sources&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;BROWSER_INFO=1&lt;/p&gt;
&lt;p&gt;BSCMAKE_FLAGS=$(BSCMAKE_FLAGS) -n&lt;/p&gt;
&lt;p&gt;BROWSERFILE=$(TARGETNAME).bsc&lt;/p&gt;
&lt;p&gt;오류가 생기는 원인은 ddk 때문에 그런 건데요. ddk 설치 폴더를 간 다음 verify.src 파일의 아래 줄들을 주석 처리해 주시면 해당 오류가 발생하지 않도록 만들 수 있습니다. 브라우저 정보는 왜 생성하냐구요? 여러분이 F12를 눌렀을 때 정의된 곳으로 이동시켜 주기 위해서 생성한답니다. 그 기능을 사용하고 싶으시다면 이 작업을 하시고, 필요 없다면 안하셔도 됩니다. 하지만 하시는게 좋을 거예요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C:\WinDDK\7600.16385.1\bin\verify.src&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;#!if defined(BROWSER_INFO) &amp;#x26;&amp;#x26; !defined(USER_ENV_BROWSER_INFO)&lt;/p&gt;
&lt;p&gt;#!error BLD1007 : BROWSER_INFO defined in sources file – this is a user environment setting ($(MAKEDIR))&lt;/p&gt;
&lt;p&gt;#!endif&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;요즘은 64비트를 지원하는게 필수기 때문에 대부분 한 드라이버 프로젝트에서 32, 64 빌드가 모두 나옵니다. 그런데 이 때 32, 64 구성 파일이 모두 동일하다면 상관 없는데 아마도, 종종, 제법 심하게 자주 구성 파일 한 두개가 서로 다른 시츄에이션이 발생할 겁니다. 현란한 전처리기를 사용해서 그것들을 처리하는 것도 한 방법이긴 하지만 별로 추천해 드리고 싶지는 않군요. 제가 추천해 드리고 싶은 방법은 속편하게 sources 파일을 두 개 만들라는 겁니다. sources_x86, source_x64 이렇게 두 개를 만들어 두세요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#3.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이제 빌드 배치 파일을 만들어 봅시다. 이 배치 파일들이 하는 일은 32, 64 빌드에 따른 sources 파일 교체 및 인증서 서명, 그리고 최종적으로 빌드된 파일을 Dist 폴더로 복사해주는 역할을 합니다. 이 마법같은 배치 파일은 다음과 같이 작성하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;build_x64_release.bat&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;set name=%1&lt;/p&gt;
&lt;p&gt;copy sources_x64 sources&lt;/p&gt;
&lt;p&gt;call ddkbuild.bat -WIN7A64 -oacr free .  -cZg&lt;/p&gt;
&lt;p&gt;call sign.bat objfre_win7_amd64\amd64%name%64.sys&lt;/p&gt;
&lt;p&gt;mkdir Dist&lt;/p&gt;
&lt;p&gt;copy objfre_win7_amd64\amd64%name%64.sys Dist&lt;/p&gt;
&lt;p&gt;copy objfre_win7_amd64\amd64%name%64.pdb Dist&lt;/p&gt;
&lt;p&gt;del sources&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;build_x86_release.bat&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;set name=%1&lt;/p&gt;
&lt;p&gt;copy sources_x86 sources&lt;/p&gt;
&lt;p&gt;call ddkbuild.bat -WIN7 -oacr free .  -cZg&lt;/p&gt;
&lt;p&gt;call sign.bat objfre_win7_\i386%name%32.sys&lt;/p&gt;
&lt;p&gt;mkdir Dist&lt;/p&gt;
&lt;p&gt;copy objfre_win7_x86\i386%name%32.sys Dist&lt;/p&gt;
&lt;p&gt;copy objfre_win7_x86\i386%name%32.pdb Dist&lt;/p&gt;
&lt;p&gt;del sources&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;sign.bat&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;signtool sign /a /v /ac MSCV-VSClass3.cer /s my /n “인증서이름” /t “&lt;a href=&quot;http://timestamp.verisign.com/scripts/timestamp.dll%E2%80%9D&quot;&gt;http://timestamp.verisign.com/scripts/timestamp.dll”&lt;/a&gt; %1&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#4.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다시 정리하면 이렇습니다. 드라이버 프로젝트 폴더에는 ddkbuild.bat, sources_x86, sources_x64, build_x64_release.bat, build_x86_release.bat, sign.bat 파일이 있는 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#5.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이제 Visual Studio에서는 make 프로젝트로 프로젝트를 생성하시고 프로젝트 빌드 커맨드로는 build_x86_release.bat 드라이버명, build_x64_release.bat 드라이버명 이렇게 만드시면 됩니다.&lt;/p&gt;
&lt;p&gt; 4
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[[소고] 끝나지 않은 전쟁: 논클라이언트 봇]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/4372</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4372</guid><pubDate>Sun, 31 Jul 2011 23:57:23 GMT</pubDate><content:encoded>&lt;h3&gt;요약&lt;/h3&gt;
&lt;p&gt;영겁의 세월을 두고 진화하는 우주처럼 보안에서의 창과 방패의 싸움도 영원히 이어질 수 밖에 없는 구조로 되어 있다. 여기서는 그런 이슈 중에 하나인 논클라이언트 봇과의 전쟁에 대해서 살펴본다. 논클라이언트 봇의 정의 및 구조적 특징과 함께 그간 논클라이언트 봇에 대응하기 위해서 논의되었던 전략들에 대해서 알아보도록 하자.&lt;/p&gt;
&lt;h3&gt;필자 메모&lt;/h3&gt;
&lt;p&gt;“보안 프로그래밍”이라는 주제로 글을 부탁 받고는 어떤 내용을 담을지를 한참 고민했다. 정수 연산의 위험성 이라든지, 포맷 스트링 버그 라든지, 버퍼 오버플로우와 같은 보안 프로그래밍을 생각했을 때 누구나 떠올리는 다소 식상한 내용은 담고 싶지 않았다. 달리 생각하면 PC 클라이언트 보안을 하는 업체에서 10년 가까운 세월을 일했지만 감히 “보안”이라는 주제로 글을 쓰기가 두려웠는지도 모르겠다. “보안”이라는 것은 너무도 넓고 너무도 방대한 내용들을 포함하고 있기 때문이다.&lt;/p&gt;
&lt;p&gt;식상한 주제는 피하고 싶고, 모르는 것에 대해서 글을 쓰는 것만큼 멍청한 일도 없으니 결국은 내가 그간 했던 고민 중에서 한 꼭지를 끄집어 내 보기로 결정했다. 여기서 설명할 논클라이언트 봇은 과거에도 심각한 문제였고, 현재에도 계속 문제가 되고 있다. 그럼에도 글을 쓰고 있는 지금 이 시점에도 완벽한 대응 전략은 부재중인 상태다. 이 글을 읽고 여러분이 다소 자극을 받아서 혁신적인 새로운 대응 방법을 생각해 낸다면 그 또한 엄청나게 의미 있는 일이 아닐까라는 생각을 하면서 글을 시작해 보려고 한다.&lt;/p&gt;
&lt;p&gt;혹시 앞서 언급했던 일반적인 “보안 프로그래밍”이라는 주제에 대해서 공부하고 싶은 독자라면 이 세 권의 책을 꼭 일독하기를 권한다. Writing Secure Code 2/e, 윈도우 비스타 보안 프로그래밍, Secure Coding in C and C++이 그 세 권의 책이다. 그 어떤 책보다도 여러분에게 일반적인 보안 프로그래밍의 관점에 대해서는 가장 많은 영감을 줄 수 있는 책이라고 감히 자부한다.&lt;/p&gt;
&lt;h3&gt;개요&lt;/h3&gt;
&lt;p&gt;이 문제는 여러분이 잘 알고 있는 튜링 테스트와 유사하다. 여러분의 여자친구 내지는 남자친구를 생각해 보자. 없다면 부모님을 생각해도 되겠다. 벽이 하나 있고, 반대편에 여러분의 사랑스런 그 사람이 앉아 있는 것이다. 여러분은 상대에게 질문을 할 수 있고, 상대는 여러분에게 대답을 할 수 있다. 이 질문과 답변 과정은 대리인을 통해서 이루어지며 그 사람은 벽 반대편 사람이 여러분이 알고 있는 사람인 것처럼 보이게 하기 위해서 질문과 답변 내용을 조작할 수 있다. 과연 이런 상황에서 여러분은 벽 반대편에 있는 상대가 여러분이 알고 있는 그 사람인지 아닌지를 구분할 수 있을까라는 것이 문제다. 물론 질문은 여러분이 확신이 들 때까지 계속 할 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 이야기를 하면 대다수 사람들은 제일 먼저 하고 싶은 질문으로 상대와 나만 알고 있는 은밀한 내용을 꼽는다. 처음 데이트 했던 장소 라던지, 상대의 신체적 특징, 기호 등을 묻는 것이다. 하지만 이는 벽 반대편에 어떤 엉뚱한 존재가 우리의 사랑스런 사람을 인질로 잡고 있다면 전혀 의미가 없다. 협박을 해서 답을 얻어낼 수도 있기 때문이다. 이런 극단적인 상황까지 고려한다면 우리는 이 문제를 풀기 위해서 상대에게 어떤 질문을 던져야 할까? 또 과연 그러한 질문을 통해서 벽 반대편에 있는 보이지 않는 대상의 정체를 판별할 수 있을까?&lt;/p&gt;
&lt;p&gt;가볍게 설명한 이 문제가 오랫동안 보안 업계에서 이슈가 되고 있는 원격 클라이언트의 인증 문제다. 인증이라는 말만 듣고 반사적으로 아이디와 비밀번호를 생각했다면 번지수를 잘못 짚었다. 여기서는 원격 사용자에 대한 인증이 아니라 원격에서 실행되고 있는 클라이언트 프로그램 그 자체에 대한 인증이기 때문이다. 그렇다면 원격 사용자도 아닌 원격지 클라이언트의 인증이 왜 그토록 중요할까?&lt;/p&gt;
&lt;p&gt;이 문제가 주요 이슈로 부각된 분야는 다름아닌 게임이다. 게임의 경우에는 게임 플레이를 사람이 할 수도 있지만 기계가 할 수도 있기 때문이다. 생각해 보자. 여러분이 온라인으로 철수와 바둑을 두고 있는데 사실은 알고 봤더니 철수가 둔 것이 아니라 철수 컴퓨터가 뒀다면 어떨까? 물론 여러분은 졌다고 가정했을 때 말이다. 별 느낌이 들지 않는다면 다른 사례를 생각해보자. 요즘 유행하는 MMORPG 게임은 해당 가상 세계 속에서의 행위를 통해서 캐릭터를 육성하는 방식으로 진행되는 게임이다. 이러한 캐릭터 육성 과정에는 필연적으로 시간과 노력이 들어간다. 그런데 여러분은 그런 것들을 실제 여러분의 시간과 노력을 투입해서 얻은 반면에 철수는 철수 컴퓨터가 대신 게임을 해서 그런 것들을 자동으로 얻었다고 한다면 어떤 느낌이 들까?&lt;/p&gt;
&lt;p&gt;물론 두 가지 사례 모두 여러분이 게임을 하지 않는다면 단지 기분 나쁜 사건 정도로 생각할 수 있는 문제다. 자본주의 세상답게 진짜 문제는 머니(money)가 개입했을 때 발생한다. MMORPG같은 온라인 게임의 경우에는 해당 가상 세계에서 통용되는 화폐가 실제 화폐와 교환 가지를 가진다. 즉, 가상 세계의 1골드가 실제 세계에서 100원에 팔릴 수 있다는 말이다. 실제로 소위 유명한 게임들의 경우에는 이를 환율과 같은 시세로 표기하는 사례도 있다. 이러한 가상 세계에서 골드를 획득하는 방법은 보통의 경우 사냥을 통해서인데, 이는 상당히 단순한 반복 작업을 필요로 한다. 이러한 반복 작업을 기계가 대신하고 그것을 운영한 사람이 부가적인 수익을 얻는다면 그것은 과연 공정한 일일까? 더욱이 이런 기계 때문에 가상 세계 속에서 사람이 획득할 수 있는 리소스가 줄어든다면 말이다.&lt;/p&gt;
&lt;p&gt;여기에는 두 가지 중요한 이슈가 내포되어 있는데 하나는 이러한 부정 게임 방식이 게임 운영에 나쁜 영향을 미친다는 점이다. 생각해 보자. 누구나 부정 행위를 통해서 게임을 한다면 과연 그 게임을 누가 멍청하게 자신의 힘으로 하려고 하겠는가? 아마 아무도 하지 않고 전부 기계들만 게임을 하다가 결국 그 게임은 아무도 하지 않는 게임이 되고 말 것이다. 다른 한 가지는 이런 프로그램들이 아이템 거래 시장을 왜곡 시킨다는 점이다. 아이템 거래 시장이란 앞서 말했던 게임 머니를 실제 머니와 교환하는 시장을 말한다. 일반적인 경우라면 그 시장을 통해서 통용될 수 있는 게임 리소스는 제한적일 수 밖에 없다. 하지만 봇 프로그램의 등장으로 그 속에서 획득할 수 있는 게임 리소스가 폭발적으로 증가했고, 그것들은 별 노력 없이 획득한 것이기 때문에 아이템 거래 시장에서 낮은 가격에 팔릴 수 있다. 이는 결과적으로 정직하게 노력해서 해당 리소스를 획득한 사용자들에게는 자신이 획득한 리소스에 대한 가치를 불법적으로 하락 시키는 행위가 되는 셈이고 결국 시장은 공정하지 않은 상태가 되고 만다.&lt;/p&gt;
&lt;p&gt;앞서 언급한 여러 가지 이유로 부정 클라이언트 프로그램이 자동으로 게임을 하는 행위는 좁게는 게임 업체에게 그리고 넓게는 게임 사용자들에게 다시 피해가 가기도 하는 것이다. 따라서 이런 부정 클라이언트 프로그램을 막는 것은 게임 업체에게는 굉장히 중요한 당면 과제라고 할 수 있다.&lt;/p&gt;
&lt;h3&gt;논클라이언트 봇&lt;/h3&gt;
&lt;p&gt;게임 업계에서는 앞서 설명한 것과 같이 벽 반대 편에 앉아서 마치 우리가 알고 있는 사람인척 하는 나쁜 프로그램을 두고 논클라이언트 봇(Non-client Bot)이라고 부른다. 좀더 엄밀히 말하자면 논클라이언트 봇이란 게임 프로토콜을 모방해 게임 클라이언트가 아닌 별도의 클라이언트가 게임 서버에 접속해서 플레이어와 같은 행위를 하는 것을 말한다. 즉, 논클라이언트라는 말은 클라이언트가 없다는 것을 봇이라는 말은 자동으로 게임 플레이를 한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;이렇게 복잡하게 프로토콜을 모방해서 논클라이언트 봇을 제작하는 이유는 게임 클라이언트에서 로딩하는 복잡한 그래픽 리소스 등이 필요하지 않아서 한 PC에서도 여러 개의 논클라이언트 봇 프로그램을 띄워서 동시 작업을 원활하게 할 수 있기 때문이다. 동시 실행이 원활하다는 말은 달리 표현하면 단위 시간당 더 많은 게임 리소스를 획득할 수 있음을 의미한다. 이러한 이유로 논클라이언트 봇은 주로 작업장이라고 불리는 곳에서 은밀하게 제작되기 때문에 실제로 구동이 되는 프로그램을 구하기는 쉽지 않다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 1&gt;에는 정상적인 게임 클라이언트와 서버의 통신 구조가 나와 있다. C는 게임 클라이언트를 S는 게임 서버를 의미한다. 이 그림이 나타내는 의미는 서버가 Q라는 패킷을 전달하면 클라이언트가 R이라는 응답을 하는 구조로 통신이 이루어진다는 것이다. &amp;#x3C;그림 2&gt;에는 이 구조를 도용한 논클라이언트 프로그램의 구조가 나와있다. 클라이언트는 변조되거나 새롭게 만든 NC이지만 통신 구조를 그대로 모방했기 때문에 게임 서버 입장에서는 이 클라이언트가 정상적인 게임 클라이언트 프로그램인지 아닌지를 판별할 방법이 없다. 논클라이언트 봇을 구현하는 핵심 기술은 이러한 게임 서버와 클라이언트의 통신 구조를 도용하는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_0.png&apos; data-alt=&apos;그림 1 정상 클라이언트 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 217px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/2ca9046713f0ac1495769e0079a748bf/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_0.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 101.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABwklEQVR42mP4//9/3YsXL47u3r17B5B99M+fP+EMQABkMzMQAYDqEo4dO9Z05cqVZiA7AiSw9tevX/8vXrz4E8j+DzSwHKqQhYBBjFD6yPnz5/9fu3YNpH0bSEDr3bt3PjNnzswDsp2BWA5ZAxEu1FmzZk3yxo0bE4BsDZg4NxA7MJAOYJZqAbE6XNTFxYUfCJyANjCBMLqu+vp6plWrVsHClAmKGWEGiouLa4Mwsh5cLmRE0owPWAOxBrIAF5KBTOhe2rNnjzQwFehCxUSBWAqIVYDYEIhVgdgD3UB0F4K8xyQpKSkCpAW6uromA8F9qLeU2dnZFYG0IFQdCGijhCEQsAJxAhAbQW3XBGI9Pj4+kCuElixZ4g90YStS+DKi0broLgRJNEENNQdiJWgwsGIJLyaYD5AM1MHmZXuoIl4glgQpYmVl1QfScsHBweUtLS37pkyZwgPks2BJNjrYIsUZ3SmwpAKMlLKlS5euADJloJYYQH0hDsQc0KBSxxcp+JILyIXsQCwBjWGQ4b3QWGcgJacwoiUpZC8bEHIhsdmOBVeyoTQv6xBK2BQbCIplO6qVNrRwISgZ6FFgoDwojYJYAOzHnoVNYriDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 1 정상 클라이언트 통신 구조&apos; title=&apos;&apos; src=&apos;/static/2ca9046713f0ac1495769e0079a748bf/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_0.png&apos; srcset=&apos;/static/2ca9046713f0ac1495769e0079a748bf/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_0.png 190w,
/static/2ca9046713f0ac1495769e0079a748bf/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_0.png 217w&apos; sizes=&apos;(max-width: 217px) 100vw, 217px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 1 정상 클라이언트 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_1.png&apos; data-alt=&apos;그림 2 논클라이언트 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 217px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/245ac8a828127f2fd8c4d881af063ad2/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_1.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 101.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABvUlEQVR42mP4//9/3Zo1a47Onj17x/Pnz48C+eEMQACkmRmIAEB1CceOHWu6cuVKM5AdARJYe/bs2f8bNmz4+R8CyqEKWQgYxAilj5w/f/7/tWvXQHq3gQS0gNhnyZIleUDaGYjlkDUQ4UIdoA+TN27cmABka8DEuYHYgYF0ALNUC4jV4aIuLi78QOAEtIEJhNF11dfXM61atQoWpkxQzAgzUFxcXBuEkfXgciEjkmZ8wBqINZAFuJAMZEL30p49e6R3796tCxUTBWIpIFYBYkMgVgViD3QD0V0I8h6TpKSkCJAW6OrqmgwE96HeUmZnZ1cE0oJQdSCgjRKGQMAKxAlAbAS1XROI9fj4+ECuEAKmAH+gC1uRwpcRjdZFdyFIoglqqDkQK0GDgRVLeDHBfIBkoA42L9tDFfECsSRIESsrqz6QlgsODi5vaWnZN2XKFB4gnwVLstHBFinO6E6BJRVgpJQtXbp0BZApA7XEAOoLcSDmgAaVOr5IwZdcQC5kB2IJaAyDDO+FxjoDKTmFES1JIXvZgJALic12LLiSDaV5WYdQwqbYQFAs21GttKGFC0HJQI8CA+VBaRTEAgAv25ylyv9QKgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 2 논클라이언트 통신 구조&apos; title=&apos;&apos; src=&apos;/static/245ac8a828127f2fd8c4d881af063ad2/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_1.png&apos; srcset=&apos;/static/245ac8a828127f2fd8c4d881af063ad2/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_1.png 190w,
/static/245ac8a828127f2fd8c4d881af063ad2/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_1.png 217w&apos; sizes=&apos;(max-width: 217px) 100vw, 217px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 2 논클라이언트 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;프로토콜 변형&lt;/h3&gt;
&lt;p&gt;이러한 논클라이언트 봇의 등장을 맞이한 게임 개발자들이 취한 그 첫 번째 대응은 프로토콜 변형이었다. &amp;#x3C;그림 3&gt;에는 이렇게 통신 방법이 변경된 그림이 나와 있다. 기존의 Q와 R이 Qa, Ra라는 새로운 값들로 변경되었다. 따라서 기존 논클라이언트 봇은 이 서버와는 통신을 할 수가 없다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_2.png&apos; data-alt=&apos;그림 3 프로토콜 변조 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 217px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e3acc49f706cb8faa168f5e352397427/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_2.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 101.05263157894737%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB4klEQVR42rVUv0tCURR+Pi3zhUYgWBkFmVRqYTU0BBnl0FDkVm1Co9TalmDgIDQ4NPgXSGKDiwQ6mjglioh/gINLzibC6ztyjNfD0n4d+LiH8879znfuufcJsixfNxqNp0wm8wj/qdPpnAgw+FphCEOeP5/PhyqVyg38Uwo8tNttuVQqvcKXQXjFiboBRBpec8ViUa5Wq7Q9TQFHs9k8jMVil/D3gTnlhiEUupLJ5HkqlfLDX+7Fx4Fd4fvWK+oAlt6jXq93AraHCiJBvSuRSGjpCFg1QeS1S2ixWJwE5Z7PFPY2D7JtYFkZkBSEouqMtOVyeaFerx/VajUzQpMGg8GKdRFYB+zAgZpQrVDr8Xhoykafz7cZjUYb6XRajkQiF4hNmUwmGxFTHuc7P5whbATwAxvADLACrAELdrvdigneZbPZaKvV6qoIBoOiaiiraoX0IcSkW0TExzDCbUuKXJGViQpCV7+WPZxkBKY5qVs5EAg8Q+VLoVA45gJqha5+Q9nv9xLQnjmXy93H4/FmOBw+Q8gmSdIGd2EBxviolr4aikbVEhUYZWU0LD0NhyfsBm556sKwL0XT70op4u5BCod9drrPrs1v37Jr0MX+NSFNeefP/jb/oVDPT+2nhPPALHlvye7DNQGSoy0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 3 프로토콜 변조 통신 구조&apos; title=&apos;&apos; src=&apos;/static/e3acc49f706cb8faa168f5e352397427/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_2.png&apos; srcset=&apos;/static/e3acc49f706cb8faa168f5e352397427/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_2.png 190w,
/static/e3acc49f706cb8faa168f5e352397427/58178/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_2.png 217w&apos; sizes=&apos;(max-width: 217px) 100vw, 217px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 3 프로토콜 변조 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이 방식은 일견 기존의 논클라이언트 봇을 일망타진하면서 동시에 논클라이언트 봇 제작자들에게 새롭게 프로토콜을 분석해야 한다는 짐까지 던져주는 셈이기 때문에 굉장히 효과적인 대응으로 생각되기 쉽다. 하지만 이는 큰 착각이다. 그 사실이 잘못된 가장 큰 이유는 기존의 서비스되고 있는 서버, 클라이언트의 프로토콜 구조 전체를 새롭게 설계하는 작업은 전혀 소프트하지 않기 때문이다. 사실상 이러한 작업을 한다는 것은 거의 미친 짓이나 다름 없다. 보통의 경우에 서비스되고 있는 프로그램에서 선택할 수 있는 방법의 최대치는 새로운 패킷 추가나 기존 패킷의 상수 값을 변경하는 정도가 전부다. 하지만 이러한 것들은 이미 프로토콜 전체가 분석된 논클라이언트 봇 제작자 입장에서는 전혀 어렵지 않은 과제다. 단순히 변경된 부분만 추적하면 되기 때문이다. 결과론적으로 이 방법은 막는 입장에서는 굉장한 노력이 필요하지만 공격하는 입장에서는 그렇게 많은 노력이 필요하지 않다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;여기까지 이야기를 듣고 보통 나오는 첫 번째 반응은 그러면 패킷을 암호화하면 되지 않냐는 질문이다. 그런데 이 말은 지금까지의 논의를 전혀 이해하지 못해서 나오는 반응이다. 논클라이언트 봇 제작자가 날패킷(raw packet)을 살펴보지 않는 것은 아니지만 어차피 그들은 게임의 거의 모든 코드를 꿰고 있으므로 암호화는 그들에게 큰 장애물이 되지 못한다. 필연적으로 해독하는 코드가 클라이언트에 같이 존재할 수 밖에 없기 때문이다. 즉, 아주 뛰어난 해커를 가정했을 때 패킷 암호화라는 것은 그 효과가 0이라고 할 수 있다. 물론 현실세계에 존재하는 수많은 어중이떠중이 해커를 고려한다면 하지 않는 것 보다는 하는 것이 효과가 있지만 실제로 논클라이언트 봇을 제작할 수 있는 수준의 실력자들에게는 큰 효과를 보기는 힘들다.&lt;/p&gt;
&lt;h3&gt;키인증&lt;/h3&gt;
&lt;p&gt;본격적으로 보안 업체가 관여하면서 나온 첫 번째 생각은 키인증이다. 키인증이란 클라이언트와 서버만이 알고 있는 비밀스런 질문과 답변을 주고 받자는 것이었다. 이 방법은 서버에서 클라이언트로 특정 키를 전송하고 클라이언트에서는 그 키에 대해서 아주 특수한 연산을 한 다음 그 값을 서버로 전송한다. &amp;#x3C;그림 4&gt;에 이러한 방식의 통신 구조가 나와 있다. 서버와 클라이언트는 사전에 약속된 아주 비밀스러운 연산 E를 각자 가지고 있다. 이 상태에서 서버는 클라이언트에게 Q를 보내고 클라이언트는 그것을 자신이 가진 연산 E의 인자로 전달해서 나온 결과, R을 서버로 전송한다. 서버에서는 다시 동일한 연산을 수행해서 클라이언트가 응답한 R이 자신이 계산한 답과 맞는지를 비교해서 정상 클라이언트인지 아닌지를 판단한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_3.png&apos; data-alt=&apos;그림 4 키인증 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 298px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c34433053f6b79bc81032a754ac496c4/c9fe3/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_3.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 73.68421052631578%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+UlEQVR42o1TvWsaYRh/vY+otSeYq41xSWns0nx2k0LrlK1dEiQhdHTL1A/p4GDHrlIcnEUEBddgbBDFv8DaXh1E0cEMKmbMZH/P5T24vvWkP/j5PD7ve797vo4xGxaLhcztea/X+z0ajX7A/8JjEhNgxWCPm81mYTabfWUOgif9fr/d7XY78D+vELTuXzQajZvJZHLJlsBFP36/fx3muT1GiMfjcjqdlmwx0/p8vn0YjTlB0zRdVdU9/ldmK0AvURTlla7rmmOGkUgkGAgEdnlM4lmxYrH4JpPJvKR3ut3uJ7DPwBD4GnzISqWSXK/XFSIeUnK5nGor+YV5ibHHHo9nC3YjlUp9g+AH+N5oNOq1ZX+wtGQ02MywUCi8TSQSJbib4CPwAT9XhAFZvTw0Ba+AdrvdGw6HvyqVilGtVo1arfZzOp3ezefzMS6p4mC47xLi9xkahpEfDAbN8Xj8vdVqXWOfroErCN5C8EYQJEqCuPRfJUP8fT6fp73SwTWbsAj5r5JpCJ1OZ42IoZikHoXDYZ3voR/cxkSfUi+TyeRHTPqUFGKxmPJPyU5rEwqFgljWHStGG0BOuVz+lM1m39EVbMI2LL0oCB7RfjsKAvYvRRb6ZoFa4eWCZ9x3FKSSd4TGmz3mfXYJZ4crPz1+uLVkZZwSiFCGfwA4DcryBTLw0wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 4 키인증 통신 구조&apos; title=&apos;&apos; src=&apos;/static/c34433053f6b79bc81032a754ac496c4/c9fe3/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_3.png&apos; srcset=&apos;/static/c34433053f6b79bc81032a754ac496c4/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_3.png 190w,
/static/c34433053f6b79bc81032a754ac496c4/c9fe3/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_3.png 298w&apos; sizes=&apos;(max-width: 298px) 100vw, 298px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 4 키인증 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;은행에서 사용하는 보안카드를 게임 클라이언트에 적용했다고 생각하면 쉽게 이해할 수 있다. 서버가 보내는 Q는 보안 카드의 인덱스를 의미하고 E는 보안 카드에서 인덱스에 대응하는 값을 찾는 과정을 R은 해당 보안 카드에 기록된 보안 코드 4자리 숫자를 의미하는 것이다. 상당히 유사한 만큼 이 방식은 은행 보안카드와 동일한 맹점을 가지고 있다. 보안카드 자체를 분실하면 무용지물이라는 점이다. 즉, 우리가 아주 은밀하다고 앞서 언급했던 연산 E가 도용되면 해킹툴도 얼마든지 정상 클라이언트로 둔갑할 수 있는 것이다. &amp;#x3C;그림 5&gt;에는 이러한 연산 함수 E 코드를 도용한 논클라이언트 봇의 통신 구조가 나와있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_4.png&apos; data-alt=&apos;그림 5 키인증 함수를 도용한 논클라이언트 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 298px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e7c702dc3f24491129e291d552e577ca/c9fe3/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_4.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 73.68421052631578%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACEUlEQVR42o1TO4wSURSdGWYWEIaEnUWRZo2Ljetnt0PjSmWnjQnRwpLOyg+xoGBLW2IoqAkhgYTWsLgSPsViqACdyoSQAFsAwdIKzx3fS/DtzMabnNybd++c+x1JgqzXaxfTj8rl8qDZbH6bTqfddrttDgaDY/JlMhlFEgTxCtPPW61WcblcfrQcIOGED0By1uv1voKw3e12zclk8uESQv7daxRxPp/PP0s2QTIzt/1+/21m8zcpkUi4GLm86fP5fPeg9AuEvBJd1w1N0+6yZ5d0iVASVVWPDMPQ7fxWxmg0GgoGg3fYm8ITlUqlp9ls9iHldLvdN6BvAWHgMeC35tdoNFQCPlLz+bxGHwYCgW2oQytIkq56PJ5d6GvpdPoTCN/C9sZiMe9G9fdtW+YzLBaLz5LJZBnmdWAHuML8Kt+uMN8Di/AE0u/3f47H4x/VatWs1WpmvV7/vlgsfq9WqxmCNHExzJaF978VmqZZGI1Grdls9qXT6Zzink4hJyD8BcJzgZCgCOTKf7UM8jeFQoHuygC2NohFcf3TMi1hOBxuEbAUCzSjSCRCRHSHAWAPG71Js0ylUu+w6RfEEI/H1QstO51NOBwO4Vj3+RtdABmVSuV9Lpd7RSG4hD1oShQCntB9OxLSn8Iq5G3JNrE0Ci8jfMlsR0JqeV8YvDVjNmdZ8B04tcyFnLs2J+NUQJQq/AMUoNX51Z6DUgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 5 키인증 함수를 도용한 논클라이언트 통신 구조&apos; title=&apos;&apos; src=&apos;/static/e7c702dc3f24491129e291d552e577ca/c9fe3/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_4.png&apos; srcset=&apos;/static/e7c702dc3f24491129e291d552e577ca/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_4.png 190w,
/static/e7c702dc3f24491129e291d552e577ca/c9fe3/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_4.png 298w&apos; sizes=&apos;(max-width: 298px) 100vw, 298px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 5 키인증 함수를 도용한 논클라이언트 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;연산을 도용한다는 것은 무엇을 의미할까? 컴퓨터에서 말하는 연산은 결과론적으로는 수행되는 코드의 집합. 즉, 함수가 된다. 앞서 &amp;#x3C;그림 4&gt;에서 살펴본 연산 E가 아주 단순하게는 XOR이라고 생각할 수 있다. Q, R이 4바이트 정수이고 E는 XOR인 것이다. 그 규칙을 모르면 통신 구조가 어려워 보이지만 규칙을 알면 쉽게 도용할 수 있다. 물론 논클라이언트 봇 제작자들이 이렇게 날패킷(raw packet)을 보고 규칙을 추론해 내는 것은 아니다. 그들은 클라이언트 게임 코드를 보고 그 코드를 직접 가져다 사용한다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;리스트 1&gt;에는 원본 클라이언트에서 사용했다고 생각할 수 있는 SomeFantasticFunction이라는 연산이 나와 있다. 여기서는 간단하게 산술 연산을 수행한 후에 결과 값을 돌려준다. 이 코드를 컴파일해서 실행 코드를 생성하면 해당 코드에 대한 어셈블리어 코드가 어딘가에는 존재한다. 논클라이언트 봇 제작자들은 그 코드를 찾는 것이다.&lt;/p&gt;
&lt;p&gt;리스트 1 원본 연산 함수&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG &lt;span class=&quot;token function&quot;&gt;SomeFantasticFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG Q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ULONG R&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    R &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Q &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;34&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1573&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; R&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;#x3C;그림 6&gt;에는 IDA와 같은 정적 분석 툴을 사용해서 해당 코드를 찾아본 화면이 나와 있다. 코드를 보면 오른쪽에는 어셈블리어 코드가 나와 있고 왼쪽에는 바이트 코드가 나와있다. 뛰어난 논클라이언트 봇 제작자라면 함수 자체의 기능도 이해하겠지만, 사실은 그럴 필요도 없다. 이 함수가 특정 시점에 수행된다는 사실만 확인하고 나면 그냥 바이트 코드를 그대로 긁어다 사용하면 되기 때문이다. &amp;#x3C;리스트 2&gt;에는 이렇게 도용한 함수 코드가 나와 있다. 보면 알겠지만 함수는 바이트 코드를 저장해놓고 실행 시점에 가상 메모리에 복사한 다음 해당 함수를 다시 호출하는 구조로 되어 있다. 여기서는 간단하게 컨셉만 보여주기 위해서 이렇게 코드로 만들었지만 실제로는 이렇게 복잡하게 코드로 구성하지 않고도 손쉽게 도용할 수 있는 다양한 방법이 존재한다. 어쨌든 이 이야기의 결론은 특정 코드가 무엇을 하는지, 내지는 어느 시점에 수행되는 지만 판단하고 나면 그 코드를 훔치는 것은 식은 죽 먹기라는 사실이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_5.jpg&apos; data-alt=&apos;그림 6 IDA로 살펴본 SomeFantasticFunction&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 601px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/ffbbad40b222830985fb1878de2ee8c8/9a33a/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_5.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.31578947368422%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB70ua0GR//8QAGBAAAwEBAAAAAAAAAAAAAAAAARAxAAL/2gAIAQEAAQUCuCg5X//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABkQAAIDAQAAAAAAAAAAAAAAAAABEBEhUf/aAAgBAQABPyFZK8KQsDcf/9oADAMBAAIAAwAAABAwD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABURAQEAAAAAAAAAAAAAAAAAABBx/9oACAECAQE/EIf/xAAaEAEAAwEBAQAAAAAAAAAAAAABABExIRBx/9oACAEBAAE/EGCpzcgaiLe5AMJSsRCWu/fP/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 6 IDA로 살펴본 SomeFantasticFunction&apos; title=&apos;&apos; src=&apos;/static/ffbbad40b222830985fb1878de2ee8c8/9a33a/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_5.jpg&apos; srcset=&apos;/static/ffbbad40b222830985fb1878de2ee8c8/8ccab/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_5.jpg 190w,
/static/ffbbad40b222830985fb1878de2ee8c8/ea4c8/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_5.jpg 380w,
/static/ffbbad40b222830985fb1878de2ee8c8/9a33a/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_5.jpg 601w&apos; sizes=&apos;(max-width: 601px) 100vw, 601px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 6 IDA로 살펴본 SomeFantasticFunction&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;리스트 2 도용한 함수 코드&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ULONG&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;SFFT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG Q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ULONG &lt;span class=&quot;token function&quot;&gt;SomeFantasticFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ULONG Q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    UCHAR code&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;\x55\x8b\xec\x81\xec\xcc\x00\x00\x00&quot;&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;\x53\x56\x57\x8d\x8d\x34\xff\xff\xff&quot;&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;\xb9\x33\x00\x00\x00\xb8\xcc\xcc\xcc\xcc&quot;&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;\xf3\xab\x8b\x45\x08\xc1\xe8\x0d\x6b\xc0\x22&quot;&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;\x05\x25\x06\x00\x00\x89\x45\xf8\x8b\x45\xf8&quot;&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;\x5f\x5e\x5b\x8b\xe5\x5d\xc3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    PVOID cptr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;VirtualAlloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_COMMIT &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; MEM_RESERVE
                                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_EXECUTE_READWRITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cptr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        SFFT sfft &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SFFT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; cptr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ULONG R &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sfft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;VirtualFree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cptr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MEM_FREE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; R&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;무결성 검사&lt;/h3&gt;
&lt;p&gt;E를 도용 당한 보안 업계의 반격은 무결성 검사로 이어졌다. 이는 말 그대로 클라이언트의 내용물을 검사해서 진짜인지 아닌지, 변조가 있었는지 없었는지를 판별하겠다는 말이다. 앞선 키 인증이 사랑하는 사람과 둘만 알고 있는 기억에 대한 질문이었다면, 이는 사랑하는 사람이 가진 고유한 신체적인 특징을 묻는 것이라고 할 수 있겠다.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;그림 7&gt;에는 이러한 경우의 통신 구조가 나와 있다. 서버는 Q라는 랜덤한 값을 보내고 클라이언트는 그 값과 클라이언트 프로그램 자체를 해시 함수 H에 입력으로 넣는다. 그러면 H 함수는 클라이언트에서 Q로 표기된 부분의 해시 값을 구해서 R에 저장한다. 서버에서는 구해진 해시 함수를 가지고 변조된 클라이언트인지 아닌지를 판단하는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_6.png&apos; data-alt=&apos;그림 7 클라이언트 무결성 검사 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 319px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/1349ad5b7d3f8aecc19c1c6ea1bc4f02/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_6.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 68.42105263157895%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzElEQVR42o2TS0sCURTHZ3TK6WllYU1Wo4kvkgp3QQWFidDGhdE+RFr7AfwMQiIEtmzdQhEiXwsDRQhx4RMyRBDRb1BM58gI023MDvw4Zy6X/z2voSjCBEFgRH9Tr9c/+v1+A+Jr8UxJ3FWI3pnP55+63e4dJSOoFP1lpVJJtlqtZ4jPpQIygu5cLvfWbrcfqTFGi54DeOJsFNPEuRlY/lOQ5/kdjuNMMoIjw/bM2Gy2ebBTk8m0SqXTaQb7hmCMFIvFKbxtNBp1Wq12mKHX68VWMH6/fz8cDt/jY/C9BaBfAg6AlUkl6wAnlq5SqQzgtR6PZy8ajd4GAoE5onTLUDAWi530ej13o9FwZbNZF0zL1el0XPF4/KxaraYSicQL3g4Gg8yYh5U/BGE67yAglMvlLyhXyGQyQrPZFED4E0wYDAZJyfRxqkoQn5aIKn4IwkUDYAHMSKlUGvparWaAPXwtFAopuZWRydA6sYdqtVrPsuwxhOvALrBmt9t1oVDoQvLArwxpEihJQe6hw+HAyat8Pt9RJBJ5gHhbnPIGMAscTtxDUVBP7qEkOxbQ4PSBK2BxkuAmIUgTqyIt2fqfPdSI/Rv3p9ASQWzBwjc01N1Cx+0a1gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 7 클라이언트 무결성 검사 통신 구조&apos; title=&apos;&apos; src=&apos;/static/1349ad5b7d3f8aecc19c1c6ea1bc4f02/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_6.png&apos; srcset=&apos;/static/1349ad5b7d3f8aecc19c1c6ea1bc4f02/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_6.png 190w,
/static/1349ad5b7d3f8aecc19c1c6ea1bc4f02/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_6.png 319w&apos; sizes=&apos;(max-width: 319px) 100vw, 319px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 7 클라이언트 무결성 검사 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이 방식의 가장 큰 특징은 연산 H의 입력으로 클라이언트 프로그램 그 자체를 넣도록 만들었다는 점이다. 따라서 클라이언트에 가해진 사소한 수정 사항도 모두 검사할 수 있다. 하지만 과연 이 방법으로 논클라이언트 봇을 막을 수 있었을까? 안타깝게도 아니다. 앞선 키 인증과 마찬가지로 논클라이언트 봇이 클라이언트 프로그램 자체를 도용한다면 여전히 무용지물이 되기 때문이다. &amp;#x3C;그림 8&gt;에는 이러한 방식으로 게임 클라이언트 프로그램 C와 해시 함수 H를 도용한 논클라이언트 봇의 통신 구조가 나와 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_7.png&apos; data-alt=&apos;그림 8 클라이언트 및 해시 함수를 도용한 논클라이언트 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 319px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c27e0affc4ae05e36c859144a606be10/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_7.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 68.42105263157895%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACDElEQVR42o2TzYsScRjHZ9Rt7NVqC82sdU3cXUkqvAUVBJvs0YNdO4l09tLNv6CDkIiBnWQPXooY8VKjHgwUIW1QfIMUEXy9ePBUTN/fMAO//eW2PfDheUYevr/nTY6DKYrCa15otVqfM5lMfzgcyu12W242m/JgMPhRLBZHq9XqDcnLZrNGLd+g+cNKpfJpMpm84xjBrel0+laSpI/z+fyYiNfrdXGxWGQgLq7X61eMkO6PyuXy99FodMxtMv0BmB04tZinUnjqW/d74NomMWMqldoisc1m27Hb7R4Sk9+oh3QzgfNer/cS7JnH47nBFQoFExJVSEyo1WqqoNvtdlitVrXCUChE5maKRCIPEonEe6fTuYPvO4D4q+AhuM6dYnolDnBIWhcEwQVvDQaD99Pp9OtoNHqRaX1fFRRF8elsNjvq9XqBUqkUwLYC4/E4kMvlnmMRUj6f/0KyY7GY6ZSHjScEsZ2fEFBkWf6NdhWch9Lv9xUI/4Ipy+Xyqz5bOLJVI8TPUaKGE4JIdIF9sEdoNBqq73Q6rm63+61arUr0ifyjwoMzZ2ixWHbNZvMTsnBwD9z0+XyOeDz+gnrgrwp5FrRkYO/Q7/eTzQvhcPhxMpn8gPiutuVb4AJ4tPEOmS0TwV32sKnqzGCbbB+8BFfOErzNCPLMqdAtH/zPHW5r82P/enSeLkhGcPkPtO0Hw4g+pKEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 8 클라이언트 및 해시 함수를 도용한 논클라이언트 통신 구조&apos; title=&apos;&apos; src=&apos;/static/c27e0affc4ae05e36c859144a606be10/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_7.png&apos; srcset=&apos;/static/c27e0affc4ae05e36c859144a606be10/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_7.png 190w,
/static/c27e0affc4ae05e36c859144a606be10/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_7.png 319w&apos; sizes=&apos;(max-width: 319px) 100vw, 319px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 8 클라이언트 및 해시 함수를 도용한 논클라이언트 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;앞서 함수를 도용하는 것에 대해서는 설명했다. 그렇다면 게임 클라이언트를 도용한다는 것은 무슨 의미일까? 그 말에 대한 해답이 &amp;#x3C;리스트 3&gt;과 &amp;#x3C;리스트 4&gt;에 나와 있다. &amp;#x3C;리스트 3&gt;은 정상 게임 클라이언트의 응답 함수가, &amp;#x3C;리스트 4&gt;에는 논클라이언트 봇의 응답 함수가 나와 있다. 이 둘의 차이를 보면 알겠지만 정상 클라이언트는 H 함수에 현재 실행되고 있는 프로그램을 입력으로, 논클라이언트 봇은 자신이 도용한 클라이언트 프로그램을 입력으로 넣는 차이를 가지고 있다. 즉, 이 경우에는 앞선 함수 도용처럼 Reply 함수를 통째로 도용하는 경우에는 동작을 하지 않겠지만 &amp;#x3C;리스트 4&gt;에 나와 있는 것처럼 약간의 수정을 가한 후에 사용한다면 서버와 통신이 가능하다.&lt;/p&gt;
&lt;p&gt;리스트 3 원본 응답 함수 코드&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ULONG &lt;span class=&quot;token function&quot;&gt;Reply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pvoid received_data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    R &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetModuleHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;R&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;리스트 4 논클라이언트 봇 응답 함수 코드&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;GameClient &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadGameToMemory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ULONG &lt;span class=&quot;token function&quot;&gt;Reply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pvoid received_data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    R &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GameClient&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;R&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 방법을 우회하는 논클라이언트 봇의 핵심은 &amp;#x3C;리스트 4&gt;에 나와 있는 LoadGameToMemory 함수다. 이 함수는 게임 클라이언트를 로딩하는 역할을 한다. Windows 실행 포맷인 PE 파일의 구조는 이미 분석이 많이 되었기 때문에 이러한 별도의 실행 파일을 메모리에 올리는 작업은 무척이나 간단하다. 물론 실행 파일 자체에 자가 수정 코드나 폴리모픽, 메타모픽 등의 기법을 적용해서 단순히 로딩 만으로는 실제 구동되는 단계의 클라이언트와 다르도록 만들 수 있다. 하지만 이 또한 VM 환경을 사용하면 간단하게 해결할 수 있다. VM 환경이란 실제 CPU를 사용해서 구동하는 것이 아닌 가상의 메모리 공간과 가상의 CPU를 사용해서 게임 클라이언트 코드를 에뮬레이팅해서 푸는 작업을 말한다.&lt;/p&gt;
&lt;h3&gt;타이밍 체크&lt;/h3&gt;
&lt;p&gt;이 방법은 실상 필드에서는 큰 효과가 없는 방법이나 논문에서는 흔히 등장하는 해법 중에 하나다. &amp;#x3C;그림 9&gt;에 나온 것처럼 해당 연산을 수행하는데 소요된 시간을 같이 보낸다는 것이 핵심 개념이다. 그림에서는 t가 E라는 연산을 수행하는데 소요된 시간을 나타낸다. 물론 t 값은 R안에 은밀하게 포장될 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_8.png&apos; data-alt=&apos;그림 9 타이밍 체크를 사용하는 통신 구조&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 319px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/15d4a9fec44869a5daeccc62e9c1db58/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_8.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 68.42105263157895%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3klEQVR42o1Sv0tCURRWn6X2y3oJL9RKRdQkqP6ACgoRoUXIaG+QhiZXwa2/IAcDB5cGpwZdxKc4GOhg6iLaoKKDg+CPKSR5nfN4ht6e2YGP797L4TvnfPdIJERwHCcX+K5WqzW73e4HnG+FN4rIlQnsyOVyr51O50kiIkgJfFWpVNhGo5GA8+W0gIigK5vNvrdarRfJnJAKrAUYiLfJWUq8WwFbfwoaDIZ9rVZrERGcBNqjstvtaxDnFotFw3uWTqflE0aEQqElzDabzXqGYfgOPR4PWiH3er1HwWDwGYvBfReAvAk4BtCLRtYDHDi6QqEwATNut/swHA7f+3y+VWJ0Gy84Go3Oksmkq9/vO4vFojORSDgzmYyz1+tdVKvVVDweT2J2IBCQzylMzQiOx+N6qVTi6vX6GJllWS4Wi3HD4fALbOBgbdip35fC6MvRaFQFBSY/LpsRhEQTwAawIgaDgbXdblubzaYJ9vAtn8+nxFZGpMODhR6q1WqjUqk8heMOeGhG8/1+/3W5XH4AMIIVvzqUkphK+tlDHBW7iUQij4VC4RM/BveOpmkd8ArgZOEeCoJGcg+hqAqABRQADf4+4AawsUhQJyJIEUsu+7eHENvon0iHvDWE4B5g/RtSXvJBL3TfKQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 9 타이밍 체크를 사용하는 통신 구조&apos; title=&apos;&apos; src=&apos;/static/15d4a9fec44869a5daeccc62e9c1db58/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_8.png&apos; srcset=&apos;/static/15d4a9fec44869a5daeccc62e9c1db58/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_8.png 190w,
/static/15d4a9fec44869a5daeccc62e9c1db58/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_8.png 319w&apos; sizes=&apos;(max-width: 319px) 100vw, 319px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 9 타이밍 체크를 사용하는 통신 구조&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;우선 이 방법의 가장 큰 문제점은 범용 OS가 보통은 RTOS가 아니라는 점이다. 이는 시간 측정이 정확할 수 없다는 이야기다. 모든 스레드나 프로세스는 다른 스레드나 프로세스에 의해서 선점될 수 있고, 이는 곧 정상 환경에서도 실제 동작 시간이 지연될 수 있음을 의미한다. 또한 클라이언트가 구동되는 실행 환경은 천차만별이라는 점도 문제점이다. 같은 게임을 셀러론 CPU에서 실행하는 사용자도 있고, i7 쿼드 코어 컴퓨터에서 실행하는 사용자도 있다. 이 둘의 실행 시간은 아주 당연하게 전혀 같지 않다.&lt;/p&gt;
&lt;p&gt;그리고 결정적으로 앞선 무결성 검사에서 살펴보았던 것처럼 연산 E는 도용뿐만 아니라 변조도 당할 수가 있다. 따라서 이 경우에는 정상의 경우 t가 일정한 값으로 나올 것이기 때문에 조작을 해서 실행 시간에 상관 없이 같은 시간을 보내도록 하면 손쉽게 우회할 수 있다.&lt;/p&gt;
&lt;p&gt;물론 이렇게 여러모로 실전에서 사용하기에는 다소 부족한 점이 많은 방법이지만 이 방법을 소개한 이유는 이 방법의 경우 기존 방법과 달리 직접적인 값 보다는 간접적인 값을 통해서 논클라이언트 봇을 진단하려고 했다는 점이다. 즉, 기존 방식들이 예, 아니오의 답을 원하는 닫힌 질문이라면 이 방법은 주관식으로 답할 수 밖에 없는 열린 질문이라는 점이다. 즉, 시간이라는 변수 외에도 이러한 열린 질문을 통해서 정상 클라이언트를 판단을 할 수 있는 방법이 존재한다면 이 테크닉은 논클라이언트 봇에 대한 좋은 대응 방법이 될 수도 있다.&lt;/p&gt;
&lt;h3&gt;CAPTCHA&lt;/h3&gt;
&lt;p&gt;지금까지 우리는 이 문제를 논클라이언트와 정상 클라이언트를 판단하는 것으로 파악했다. 하지만 이것들 전혀 새로운 관점에서 기계와 인간을 구분하는 관점에서 바라본 해법이 CAPTCHA다. CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart)는 흔히 인터넷에서 자동 가입 방지용으로 사용되는 사람인지 기계인지를 테스트하는 방법을 말한다. &amp;#x3C;그림 10&gt;와 같이 아주 이상하게 생긴 문자열을 보여주고는 그대로 다시 입력하라고 하는 방법이 대표적이다. 사실 사람도 이해하기가 쉽지 않다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_9.jpg&apos; data-alt=&apos;그림 10 사람도 이해하기 힘든 인증&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 387px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/09dffa7113f8a2c1fc8f2359ee5a7e7a/e1e87/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_9.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 27.89473684210526%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAGABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHWmJcF/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERAgP/2gAIAQEAAQUCnQS3T//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAAIDAAAAAAAAAAAAAAAAAAABEDEy/9oACAEBAAY/AtItR//EABoQAAEFAQAAAAAAAAAAAAAAABEAARAhUfH/2gAIAQEAAT8h5CuXBgj/2gAMAwEAAgADAAAAEI/P/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHRAAAgEEAwAAAAAAAAAAAAAAAREhABAxQVGhsf/aAAgBAQABPxAZ3ngw8oES8WCald2//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 10 사람도 이해하기 힘든 인증&apos; title=&apos;&apos; src=&apos;/static/09dffa7113f8a2c1fc8f2359ee5a7e7a/e1e87/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_9.jpg&apos; srcset=&apos;/static/09dffa7113f8a2c1fc8f2359ee5a7e7a/8ccab/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_9.jpg 190w,
/static/09dffa7113f8a2c1fc8f2359ee5a7e7a/ea4c8/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_9.jpg 380w,
/static/09dffa7113f8a2c1fc8f2359ee5a7e7a/e1e87/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_9.jpg 387w&apos; sizes=&apos;(max-width: 387px) 100vw, 387px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 10 사람도 이해하기 힘든 인증&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이 방식을 논클라이언트 봇 문제에 적용하는 것은 간단하다. 위와 같은 이미지 코드가 Q가 되고 사용자가 입력한 문자열이 R이 되는 것이다. 물론 입력 받는 함수가 연산 E가 되겠다. 이 경우에는 CAPTCHA라는 방식 자체가 기계가 자동으로 답을 판단할 수 없도록 고안되었기 때문에 이론적으로는 사람이 개입할 수 밖에 없다. 즉, 자동으로 입력하는 것이 불가능해진다는 의미이고, 그렇다면 논클라이언트 봇은 자연스럽게 의미가 없어진다.&lt;/p&gt;
&lt;p&gt;물론 이 방법도 논클라이언트 봇이 작정하고 자동화를 하겠다고 다짐을 한다면 할 수 있는 방법이 전혀 없는 것은 아니다. 서버가 가지고 있는 모든 이미지 코드에 대한 결과 값을 수집한 다음 해당 값들에 대한 매핑 함수를 제작하는 것이다. &amp;#x3C;그림 11&gt;에 이러한 방법이 나와 있다. 모든 가능한 Q들에 대한 R을 구한 다음 그것 사이를 매핑하는 M 함수를 제작해서 자동으로 대답하는 방법이다. 하지만 이 경우에는 앞선 프로토콜 변경과 마찬가지로 논클라이언트 봇 제작자 입장에서는 무척 힘든 작업이지만 서버 쪽에서 요청의 내용을 교체하는 것은 쉽다는 특징이 있다. 즉, 서버 쪽에서는 데이터만 교체하면 순식간에 모든 논클라이언트 봇이 무력화되고, 논클라이언트 봇 제작자는 모든 요청과 결과에 대한 내용을 다시 수집해야 한다는 말이다. 더욱이 이런 교체 작업은 자동화 시킬 수 있기 때문에 논클라이언트 봇 제작자 입장에서는 이러한 M을 만들어서 대응하는 것은 사실상 의미가 없다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos; data-url=&apos;./끝나지_않은_전쟁_논클라이언트_봇.md_10.png&apos; data-alt=&apos;그림 11 매핑 함수를 사용한 논클라이언트 봇&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 319px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/5a66c27dd1efb28f642df27a8a05f473/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_10.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 76.84210526315789%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACOUlEQVR42o2Tz4tSURTH/TGNpvks5zU2FRPMGE4GEy2FZhdRf4BBbgLpHwiiyI2I0FpCIXCVCxPBnagLFU0XLtwokjxwoSiUItY8eYE/8Pa9znvweo02Bz7cc8+793vPOfc+FSFEq4ItFotX8H+Ab4CjpFIprtlscuPxmJNi4vfvwE/3YdSo5CYJYnxL6A6Om3e7XdJut0mtViPVapXU63UCYTKZTMhsNpuTM/sk7lPzPM9WKhU7/Jtywdd0Az6c5nI5IZ/PCxAWyuXybwgKpVJJ6PV6lFMYFfwoS+pDo9EggiBkVyfQIBbtwL8P6En3gC2dTj+Kx+OP4R+IsSOR4+FwuCcTZEOh0PNWq2VXrTG1OFrBgSK2bu0x0K2aKrIFLlESicQ2XeF0Ou84HA6bvPnJZHI3Go0+hWsCNMtDvV6/D05sNpvuIhnSky/DblMBt9v9LBwOx6xW6y7mDNhSZmgEZsDIoHNdNpt9FwgEvmCh2WKx0M0al8ul3VjydDrNFwqFeafT+YUb5WOxGJ/JZHjc8M/lcklGo9FX5Xvz+XwamdA/PXwJMR8e73vcnBdPxFssFr39fv8N5h2MJYWgWoHmL8FNPfT7/Sco0UN7aTKZdmjP7Ha7KRKJWM8p+YGUoVYJSlo12mAw3JCejdFopCJmj8fzJBgMfoZ/HVwDVy+cIcuyewzDHIqxVWmDweAKDr0FVyseSG/7Lnix4a2e+7A1azZIsYf/zVAsa18eo7+q9LsqLuUIbP8B4OSIKD9cMQ0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그림 11 매핑 함수를 사용한 논클라이언트 봇&apos; title=&apos;&apos; src=&apos;/static/5a66c27dd1efb28f642df27a8a05f473/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_10.png&apos; srcset=&apos;/static/5a66c27dd1efb28f642df27a8a05f473/08678/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_10.png 190w,
/static/5a66c27dd1efb28f642df27a8a05f473/759af/%EB%81%9D%EB%82%98%EC%A7%80_%EC%95%8A%EC%9D%80_%EC%A0%84%EC%9F%81_%EB%85%BC%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8_%EB%B4%87.md_10.png 319w&apos; sizes=&apos;(max-width: 319px) 100vw, 319px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;&lt;p&gt;그림 11 매핑 함수를 사용한 논클라이언트 봇&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;CAPTCHA 방식이 가지는 문제점은 이러한 논클라이언트 봇에 대한 대응력이 아닌 다른 곳에 있다. 바로 저 문자열을 입력하라는 귀찮은 과정을 게임 플레이 중간 중간에 하게 한다면 과연 어떤 사용자가 그 게임을 하고 있겠냐는 점이다. 사실 인터넷 사이트도 CAPTCHA가 적용된 곳은 진짜 필요한 곳이 아니면 가입이 꺼려지는 것이 사실이다. 더 중요한 사실은 이런 입력의 경우 기계뿐만 아니라 사람도 이해하기 힘들며 종종 틀린다는 점이다. 따라서 실제로 이를 게임이나 특정 클라이언트 프로그램에 적용하는 것은 실용적인 관점에서의 한계가 존재한다.&lt;/p&gt;
&lt;p&gt;그렇다면 사람이 귀찮아 하지 않는 CAPTCHA 방식을 사용하면 괜찮을까? 그런 것들 중에 하나가 게임 상에서 GM(Game Master)들이 하는 말걸기가 있다. GM들이 필드에서 이상 행위를 반복하는 사람들을 보면 말을 걸어보고 제대로 된 대답을 하지 않는다면 자동 플레이로 간주하고 해당 사용자를 퇴장 시키는 방법이다. 그럴듯해 보이지만 요즘 나오는 논클라이언트 봇은 GM의 질문에 대한 몇 가지 대답들을 미리 준비해 놓거나 주변에 GM이 오면 자동으로 다른 곳으로 움직이는 기능을 추가하고 있는 경우도 있다. 따라서 이러한 비강제성 CAPTCHA 방식은 효과를 가지기가 쉽지 않다.&lt;/p&gt;
&lt;p&gt;그럼에도 이 방식이 의미가 있는 것은 새로운 CAPTCHA 방식이 강제성을 가지지만 사람은 전혀 귀찮음을 느끼지 않고, 오히려 흥미를 느끼며, 사람이라면 거의 99.9%의 확률로 틀리지 않는 방식이라면 논클라이언트 봇을 손쉽게 무력화 시킬 수 있는 가장 강력한 방법이라는 특징 때문이다.&lt;/p&gt;
&lt;h3&gt;데이터 마이닝&lt;/h3&gt;
&lt;p&gt;끝으로 소개할 방법은 데이터 마이닝이다. 이 방법은 논클라이언트 봇 문제를 정상 플레이어와 비정상 플레이어의 문제로 바라본 해결책이다. 간단하게 소개하자면 서버 쪽에서 개별 플레이어의 행위를 모두 파악한 다음 그것을 토대로 데이터 마이닝을 해서 해당 플레이어가 정상의 범주에 속하는지 비정상의 범주에 속하는지를 판별한다는 것이다.&lt;/p&gt;
&lt;p&gt;이론적으로는 굉장히 깔끔해 보이지만 실상 이 방법은 많은 단점을 가지고 있다. 우선 플레이어의 모든 행위를 기록내지는 실시간으로 판별해야 한다는 점이다. 이를 위해서는 추가적인 많은 리소스가 투입될 수 밖에는 없다. 그리고 그것을 자동적으로 판별하는 함수를 제작하는 것도 쉬운 일은 아니다. 논클라이언트 봇이 문제가 되는 MMORPG 류의 게임에서 정상의 플레이어 임에도 논클라이언트 봇처럼 플레이를 하는 사용자들도 많기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 그런 모든 단점을 극복했다고 하더라도 정말 이 방법이 효과가 없을 수 밖에 없는 마지막 약점이 있다. 논클라이언트 봇이 정상의 범주와 같이 플레이를 한다면 이 방법으로는 절대로 논클라이언트 봇을 잡을 수 없다는 점 때문이다. 물론 그것이 문제가 되지 않을 수 있다고 생각할 수 있겠지만 기계가 사람을 대신하여 게임을 자동으로 플레이한다는 관점에서는 여전히 공평하지 않다.&lt;/p&gt;
&lt;p&gt;결론적으로 다시 설명하자면 이렇다. 이 방법에서 생각하는 정상과 비정상을 구분하는 방법을 담고 있는 함수를 P라고 가정하자. 이 P라는 함수가 정상의 범주를 좁히면 좁힐수록 정상 플레이어도 차단되는 경우가 생기는 문제가 발생한다. 반면에 이 P라는 함수가 정상의 범주를 넓히면 넓힐수록 비정상 플레이어가 차단되지 않는 경우도 생긴다. 결정적으로 논클라이언트 봇 제작자는 이 P의 범주를 파악해서 딱 그 범주의 최대치만큼만 부정적인 방법으로 플레이를 한다면 이 방법은 무용지물이 된다. 즉, 이 P의 판단 범주를 어떤 범위에 두더라도 논클라이언트 봇은 항상 그것을 통과할 수 있다는 점에서 이 방법은 좋은 대안이 되기는 힘들다.&lt;/p&gt;
&lt;h3&gt;끝은 없다&lt;/h3&gt;
&lt;p&gt;여기까지가 그간 논클라이언트 봇에 대응하는 게임 업계, 보안 업계, 그리고 학계의 생각들이다. 하지만 개별 항목에서 설명한 것처럼 하나같이 단점 없는 방법이 없으며, 완전하게 논클라이언트 봇을 탐지할 수 있는 방법은 더더욱 없다. 그래서 이 문제가 더욱 매력적인지도 모르겠다.&lt;/p&gt;
&lt;p&gt;다시 제일 앞 소개 글에서 했던 질문을 해보자. 과연 여러분은 질문을 통해서 벽 반대편에 있는 사람의 정체를 판단할 수 있을까? 결론은 불가능하다. 왜냐하면 질문과 답변이라는 메커니즘 자체가 이미 결정돼 있는 것들이기 때문이다. 여러분이 질문을 던지는 순간 그 해답은 이미 나와 있는 것이라는 말이다. 이는 결국 그 질문들을 미리 다 알고 있는 상대라면 얼마든지 여러분의 판단을 흐리게 만들 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;하지만 이러한 이론적인 결론 때문에 기죽을 필요는 없다. 실제 현실 세계에 존재하는 논클라이언트 봇 제작자가 우리가 가정한 신적인 존재는 아니라는 점 때문이다. 그들도 결국 사람이기 때문에 모든 코드들을 한번에 다 파악할 수는 없다. 문제는 얼마나 적은 리소스를 사용해서 효과적으로 그들을 괴롭히는가에 달려있다.&lt;/p&gt;
&lt;p&gt;이런 이야기가 끝날 즈음엔 사람들은 항상 왜 보안 업체가 완벽하게 막을 수 없는지를 궁금해 한다. 그러면서 잘 생각해 내면 뭔가 마법 같은 방법으로 이 모든 것을 해결해 낼 은탄환(silver bullet)이 있지 않을까라는 생각도 덧붙인다. 이 싸움이 원숭이나 개나 고양이와의 싸움이었다면 그런 은탄환이 존재했을지도 모른다. 하지만 이 싸움은 적어도 우리와 동등한 내지는 우리보다 더 나은 지능을 가진 사람들과의 싸움이다. 우리가 완벽하게 막을 방법을 생각해 낸다는 건 그들이 완벽하게 우회할 방법을 생각해 낼 수 있다는 말과 같은 의미다. 결국 이 싸움은 뫼비우스의 띠처럼 끝없이 반복될 수 밖에 없는 구조로 되어 있는 것이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[cpp] 안티 덤프]]></title><description><![CDATA[덤프(dump…]]></description><link>https://jiniya.net/wp/archives/4369</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4369</guid><pubDate>Sat, 30 Jul 2011 15:00:01 GMT</pubDate><content:encoded>&lt;p&gt;덤프(dump)란 메모리 상의 내용을 그대로 파일에 기록하는 것을 말한다. 이 또한 공격자들이 실행 파일을 분석하기 위해서 사용하는 한 가지 방법이다. 알려지지 않은 실행 압축 프로그램을 사용한 실행 파일도 덤프 기법을 사용하면 쉽게 압축이 해제된 원본 코드를 저장할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;공격 기법이 있으면 응당 그에 대한 방어 기법이 있기 마련이다. 어떤 형태로 덤프를 막을 수 있을지 한번 생각해보자. 여러 가지 방법이 있지만 그 중에 가장 간단한 방법은 덤프에 사용되는 정보를 삭제하는 방법이다. &amp;#x3C;리스트 2&gt;에 이 방법을 구현한 소스 코드가 나와 있다. 코드를 살펴보면 NT 헤더의 OptionalHeader 부분의 SizeOfImage와 AddressOfEntryPoint 부분을 제거하여 덤프 프로그램이 이미지 크기와 실행 파일의 시작 코드를 추척하기 힘들도록 만들고 있다.&lt;/p&gt;
&lt;p&gt;리스트 2 안티덤프 소스&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;windows.h&quot;&lt;/span&gt;  &lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tchar.h&quot;&lt;/span&gt;  &lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stdio.h&quot;&lt;/span&gt;  &lt;/span&gt;
  
PVOID &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LPCVOID addr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SIZE_T offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PVOID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DWORD_PTR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; addr &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
  
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    HANDLE &lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetModuleHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
    MEMORY_BASIC_INFORMATION mbi&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    &lt;span class=&quot;token function&quot;&gt;VirtualQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;mbi&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mbi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    DWORD old&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    BOOL b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;VirtualProtect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;  
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mbi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RegionSize  
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PAGE_READWRITE  
                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;old&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
    PIMAGE_DOS_HEADER dos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    PIMAGE_NT_HEADERS nt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    PIMAGE_SECTION_HEADER sec&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
    dos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_DOS_HEADER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    nt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_NT_HEADERS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dos&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;e_lfanew&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    sec &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PIMAGE_SECTION_HEADER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetPtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;nt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
    nt&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OptionalHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SizeOfImage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    nt&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;OptionalHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AddressOfEntryPoint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
        &lt;span class=&quot;token function&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
  
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;em&gt;2015-06-26&lt;/em&gt;&lt;br&gt;
&lt;br&gt;
사실 실질적으로 덤프를 방지하기 위해서는 위와 같은 코드가 크게 도움이 되지 않는다.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SizeOfImage 필드는 진짜 거의 의미가 없는데 왜냐하면 EXE이 DLL이 매핑된 섹션 영역을 구해서 덤프를 뜨는 경우가 많기 때문이다. 따라서 실질적으로 덤프 프로그램이 SizeOfImage를 참조하는 일은 잘 없다고 보는게 옳다.&lt;/li&gt;
&lt;li&gt;AddressOfEntryPoint는 효과는 있겠지만 그 효과가 제한적이다. 왜냐하면 대부분 CRT 코드에 연결해서 사용하기 때문에 패턴 검색을 통해서 진입점을 추론할 수 있는 경우가 많기 때문이다. 그리고 DLL 같은 경우에는 로딩/언로딩에 엔트리가 계속 호출되기 때문에 위와 같이 제거해 버리면 문제가 발생할 소지가 있기도 하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;덤프 대응력을 높이는 실질적인 방법으로는 ASLR을 사용하고 재배치 정보를 숨기는 것이 있다. 이렇게 할 경우 덤프를 뜬 대상체도 원본이 있었던 주소에서만 정상적으로 실행할 수 있기 때문에 덤프를 뜬 것을 재사용하기 위해서는 제약이 따른다. 다른 방법으로는 이미지 밖의 다른 주소 영역을 참조하는 포인트를 만드는 방법이 있을 수 있다. 이 경우에는 덤프를 원본 이미지 영역만 추출하게 되면 같이 딸려 있는 메모리가 추출되지 않았기 때문에 참조 포인터를 추론하기가 쉽지 않아서 효과적이다. 물론 이 두가지 방법다 이미지 로딩 전처리기 단계에서 뭔가를 프로세싱 해야 하기 때문에 위에 있는 것보다는 훨씬 더 복잡한 내용이다.&lt;br&gt;
&lt;br&gt;
끝으로 사족을 하나 더 달자면 원론적인 관점에서 덤프를 방지할 수 있는 방법은 사실상 없다. 덤프 뜬 걸 분석, 재활용 하는 작업을 얼마나 더 어렵게 만들 것인가의 관점에서 접근하는 것이 옳다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[키보드 훅, IME 메시지, 그 복잡함 속에 숨겨진 진실들]]></title><description><![CDATA[URL 하이재커를 만드는 한 가지 방법으로 키보드 후킹을 사용하는 방법이 있습니다. 키보드 후킹을 해서 엔터 키를 누르는 메시지를 감시하고 있는 것이죠. 아래 코드는 IE…]]></description><link>https://jiniya.net/wp/archives/4310</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4310</guid><pubDate>Tue, 19 Jul 2011 23:57:22 GMT</pubDate><content:encoded>&lt;p&gt;URL 하이재커를 만드는 한 가지 방법으로 키보드 후킹을 사용하는 방법이 있습니다. 키보드 후킹을 해서 엔터 키를 누르는 메시지를 감시하고 있는 것이죠. 아래 코드는 IE 주소창의 내용을 변경시키는 전형적인 키보드 후킹 프로시저 입니다. 야후라고 입력하고 엔터를 누르면 그 내용을 &lt;a href=&quot;http://www.devpia.com%EC%9C%BC%EB%A1%9C&quot;&gt;http://www.devpia.com으로&lt;/a&gt; 변경 시키는 것이죠.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK
&lt;span class=&quot;token function&quot;&gt;KeyHookMsg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; HC_ACTION
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x80000000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; VK_RETURN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        HWND g_HwndServer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;IEFrame&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g_HwndServer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;WorkerW&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND rebar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ReBarWindow32&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND combo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rebar&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ComboBoxEx32&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND box &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;combo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ComboBox&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND edit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;box&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Edit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetFocus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; edit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   
            TCHAR str&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;GetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_tcscmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;야후&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;SetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://www.devpia.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CallNextHookEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그런데 위 코드에는 사소하지 않은 한 가지 문제가 있습니다. 바로 IME 조합 과정에서 내용이 엉뚱하게 바뀌는 문제죠. 아래 그림을 봅시다. 첫번째 그림은 야후라는 글자에 후가 조합 중인 상태입니다. 이 상태에서 엔터키를 누르면 오른쪽에 있는 것처럼 “후ttp://&lt;a href=&quot;http://www.devpia.com%E2%80%9D%EC%9C%BC%EB%A1%9C&quot;&gt;www.devpia.com”으로&lt;/a&gt; 주소창이 변경됩니다. 반면 두번째 그림처럼 조합이 완료된 상태에서 엔터 키를 누르면 정상적으로 변환이 돼죠. 왜 이런 일이 벌어지는 것일까요?&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;사용자 삽입 이미지&lt;/td&gt;
&lt;td&gt;사용자 삽입 이미지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;사용자 삽입 이미지&lt;/td&gt;
&lt;td&gt;사용자 삽입 이미지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;답은 IE의 메시지 처리 순서를 살펴보면 금방 알 수 있습니다. 물론 이는 단순히 IE에만 국한되는 내용은 아닙니다. IME를 사용하는 모든 에디터가 보통 이런 방식을 사용하기 때문이죠. 아래 그림은 SPY++을 사용해서 IE의 메시지를 캡쳐한 화면입니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.jiniya.net/tt/attach/1/1688651044.png&quot; alt=&quot;사용자 삽입 이미지&quot;&gt;&lt;/p&gt;
&lt;p&gt;포커스가 있는 부분이 B를 누른 시점이죠. 참고로 세벌식에서 B가 후의 ㅜ글자가 됩니다. 그 다음으로 엔터를 눌렀습니다. WM_KEYDOWN 전에 생소해 보이는 메시지 하나가 있죠. WM_IME_COMPOSITION 메시지 입니다. 보통 한글을 지원하는 에디터는 이 메시지에서 조합 중인 글자를 변경합니다. 이 메시지의 플래그가 GCS_COMPSTR이면 조합중이라는 의미를 나타내고, GCS_RESULTSTR이면 완료되었다는 메시지를 나타냅니다.&lt;/p&gt;
&lt;p&gt;이 과정을 보면 딱 두 가지 의문이 듭니다. VK_PROCESSKEY는 무엇인가? WM_IME_COMPOSITION 따위의 메시지는 도대체 누가 언제 어떻게 발생 시키는가? 라는 것 입니다. VK_PROCESSKEY는 GetMessage나 PeekMessage를 통해서 키보드 메시지를 꺼낼 때 생성되는 놈 입니다. 하드웨어 입력 메시지를 꺼내는 깊숙한 곳에서 IME에게 이 키보드가 처리할 때 필요하냐고 묻는 부분이 있습니다. 그 때 IME가 이 키가 필요하다고 리턴하면 GetMessage는 크 키 값을 VK_PROCESSKEY로 변경한 다음 리턴합니다. 그리고 그 과정에서 IME 핸들러가 각종 IME 메시지들을 생성해서 메시지 큐에 집어넣습니다. 종종 TranslateMessage에서 IME 메시지가 생성된다는 이야기를 하시는 분들이 있는데 그렇지 않습니다. TranslateMessage는 WM_KEYDOWN, WM_SYSKEYDOWN등의 메시지에서 WH_CHAR, WM_SYSCHAR등의 메시지를 생성해내는 역할만 합니다.&lt;/p&gt;
&lt;p&gt;끝으로 한가지 더 이해해야 하는 부분은 WM_IME_COMPOSITION 메시지 입니다. 대부분의 한글 에디터들은 이 메시지를 별도로 특별하게 처리해 줍니다. 이 메시지의 역할은 현재 조합중인 글자가 변경되었음을 나타냅니다. 따라서 보통 에디터들은 이 메시지가 날라오면 현재 카렛이 있는 위치의 글자를 GetCompositionString의 결과 값으로 변경시킵니다. ‘아’라는 글자에서 ‘ㄴ’을 눌러서 ‘안’이 되는 과정을 생각해 봅시다. ‘ㄴ’을 누른 순간 WM_IME_COMPOSITION이 발생해고 에디터는 현재 위치의 ‘아’를 지우고 그 자리를 ‘안’으로 변경하는 겁니다. 워낙 순식간에 일어나기 때문에 우리는 그것이 지웠다가 다시 그려진다는 것을 모를 뿐이죠.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.jiniya.net/tt/attach/1/1281720214.png&quot; alt=&quot;사용자 삽입 이미지&quot;&gt;&lt;/p&gt;
&lt;p&gt;설명이 너무 길었습니다. 이제 훅 프로시저가 적용되면 어떻게 되는지 살펴보도록 합시다. 위 그림은 훅 프로시저가 적용된 경우의 메시지 순서를 캡쳐한 화면입니다. B키를 누르고 엔터를 친 상황이죠. WM_SETTEXT로 &lt;a href=&quot;http://www.devpia.com%EC%9C%BC%EB%A1%9C&quot;&gt;http://www.devpia.com으로&lt;/a&gt; 변경하는 부분이 우리의 훅 프로시저가 호출된 시점입니다. 값을 변경했기 때문에 카렛은 h앞에 위치하고 있을 겁니다. 그 다음으로 WM_IME_COMPOSITION이 호출되죠. 그럼 에디터 프로시저는 현재 위치에 있는 h란 글자를 지우고 그 자리에 GetCompositionString의 리턴 값을 넣습니다. ‘후’란 글자가 그 자리에 추가되겠죠. 그리고 WM_KEYDOWN 프로시저가 시작됩니다.&lt;/p&gt;
&lt;p&gt;여기서 가장 먼저 드는 의문은 왜 VK_RETURN을 꺼내는 시점이 아닌 VK_PROCESSKEY 앞에서 우리 루틴이 호출되냐 하는 것입니다. VK_RETURN 앞에서 훅 루틴이 호출된다면 이런 일이 없기 때문이죠. 그건 윈도우의 IME 처리와 관련이 있습니다. 이 과정을 간단하게 코드로 살펴보는 것이 좋을 것 같습니다. 코드를 보고 나면 왜 이런 일이 벌어졌는지 모두 이해할 수 있습니다. 아래 코드에 나타난 것처럼 GetMessage API에서 키 값을 VK_PROCESSKEY로 변경하기 전에 키보드 훅 프로시저를 호출하기 때문에 그렇습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;GetMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 키보드 메시지인가?&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsKeyboardMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// IME가 처리하는 키인가?&lt;/span&gt;
        ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IsIMEWantThisKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 등록된 키보드 훅 프로시저 호출&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;CallHookFunctions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// IME가 처리하는 키인 경우 키 값을 VK_PROCESSKEY로 변경&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ret&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wParam &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VK_PROCESSKEY&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그럼 키보드 훅 프로시저에서는 방법이 없는 건가요?&lt;/p&gt;
&lt;p&gt;물론 모두 사람이 만든 것들인데 방법이 없을 순 없겠죠. 단지 호출되는 시점이 앞서 소개한 것과 같기 때문에 키보드 훅 프로시저에서 에디터 값을 변경하는 것은 좋은 생각은 아닙니다.&lt;/p&gt;
&lt;p&gt;그럼 답을 찾아 봅시다. 가장 큰 원인은 WM_IME_COMPOSITION 메시지에서 글자를 지우고 그 위치에 마지막에 조합 중이던 글자가 추가된다는 점 이었습니다. 마지막에 조합 중이던 글자는 ImmGetCompositionString으로 구한다고 앞서 소개했습니다. 그렇다면 방법은 이제 나왔죠. ImmGetCompositionString이 조합 중이던 값이 아닌 다른 값을 리턴 하도록 만들면 됩니다.&lt;/p&gt;
&lt;p&gt;ImmSetCompositionString이라는 함수를 사용하면 간단하게 ImmGetCompositionString의 값을 변경할 수 있습니다. &lt;a href=&quot;http://www.devpia.com%EC%9C%BC%EB%A1%9C&quot;&gt;http://www.devpia.com으로&lt;/a&gt; 바꾸어야 한다면 ImmSetCompositionString으로 조합 중인 문자를 h로 지정해 주면 됩니다. 그러면 WM_IME_COMPOSITION에서 h를 지우고 다시 h를 추가하는 겪이 되기 때문에 원래 의도했던 URL로 이동하겠죠. 한 가지 주의할 점은 IME 상태를 조사해서 한글 모드인 경우만 이런 일을 해야합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;LRESULT CALLBACK
&lt;span class=&quot;token function&quot;&gt;KeyHookMsg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPARAM w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LPARAM l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; HC_ACTION
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x80000000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; VK_RETURN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        HWND g_HwndServer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;IEFrame&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g_HwndServer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;WorkerW&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND rebar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ReBarWindow32&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND combo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rebar&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ComboBoxEx32&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND box &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;combo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ComboBox&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        HWND edit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FindWindowEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;box&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Edit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetFocus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; edit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   
            TCHAR str&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;GetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            TCHAR &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://www.devpia.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_tcscmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;야후&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                HIMC imc&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ImmGetContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                DWORD conv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;ImmGetConversionStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;imc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;conv&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;sent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;conv &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; IME_CMODE_ALPHANUMERIC&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; 
                    &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ImmGetVirtualKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; VK_RETURN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

                    &lt;span class=&quot;token function&quot;&gt;ImmSetCompositionString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;imc
                                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SCS_SETSTR
                                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url
                                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TCHAR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
                                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;
                                            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                    &lt;span class=&quot;token function&quot;&gt;SetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;SendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EM_SETSEL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;SetWindowText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;token function&quot;&gt;ImmReleaseContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; imc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CallNextHookEx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[헷갈리는 유니코드 출력: %s vs %S]]></title><description><![CDATA[유니코드는 참 사람을 헷갈리게 만듭니다. 유니 코드가 아니라 문자열이란 자체가 사람을 헷갈리게 만드는 것 같아요. 오늘은 그 중에서도 특히나 우리를 더 헷갈리게 만드는 포맷 문자열 변환 지시자 %s와 %S에 대해서 살펴보겠습니다. 우선 %s와 %S…]]></description><link>https://jiniya.net/wp/archives/4299</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4299</guid><pubDate>Tue, 19 Jul 2011 23:57:21 GMT</pubDate><content:encoded>&lt;p&gt;유니코드는 참 사람을 헷갈리게 만듭니다. 유니 코드가 아니라 문자열이란 자체가 사람을 헷갈리게 만드는 것 같아요. 오늘은 그 중에서도 특히나 우리를 더 헷갈리게 만드는 포맷 문자열 변환 지시자 %s와 %S에 대해서 살펴보겠습니다. 우선 %s와 %S가 먼지에 대해서 알아볼까요. 일단 아래 코드를 봅시다.&lt;/p&gt;
&lt;p&gt;printf(“%s”, str);&lt;/p&gt;
&lt;p&gt;C언어 처음 배우는 학생도 다 알법한 코드죠. str이라는 문자열을 출력하는 코드입니다. 그러면 다음은요?&lt;/p&gt;
&lt;p&gt;printf(“%S”, str);&lt;/p&gt;
&lt;p&gt;네. 이건 C언어만 배워서는 알긴 힘들지만 어쨌는 앞서 설명한 것과 비슷하게 문자열을 출력하는 역할을 합니다.&lt;/p&gt;
&lt;p&gt;그렇다면 대문자 %S와 소문자 %s는 무엇이 다른 걸까요? 바로 변환 방식입니다. 설명하려면 조금 어려운데요. %s는 사용되는 함수와 동일한 문자열 타입으로 출력을 하는 것이고, %S는 사용되는 함수의 반대되는 문자열 타입으로 출력을 하는 지시자입니다. 듣고도 모르겠죠. 당연합니다. ㅋㅋ~ 예를들어 보겠습니다. wprintf에 %s를 사용했다. 그러면 뒤에 str은 wchar_t *로 인식하겠다는 말입니다. %S를 사용했다. 그러면 뒤에 str은 char *로 인식하겠다는 거죠. printf는 어떨까요? %s를 사용하면 char *, %S를 사용하면 wchar_t *로 변환해서 출력합니다. 이해되시나용?&lt;/p&gt;
&lt;p&gt;헷갈리지만 자동으로 변환을해서 출력해주니 편리한 기능이긴 합니다. 하지만 사실 대문자 %S 옵션은 사용하지 않는 편이 좋습니다. 왜냐구요? 헷갈리잖아요.&lt;/p&gt;
&lt;p&gt;다음 코드를 봅시다.&lt;/p&gt;
&lt;p&gt;TCHAR *str;&lt;/p&gt;
&lt;p&gt;_tprintf(_T(“%s”), str);&lt;/p&gt;
&lt;p&gt;위의 구문은 전형적으로 MBCS빌드와 유니코드 빌드에서 다 안전한 코드입니다. 코드에서 향기가 느껴지지 않으신가요? ㅎㅎ~&lt;/p&gt;
&lt;p&gt;wchar_t *str;&lt;/p&gt;
&lt;p&gt;_tprintf(_T(“%S”), str);&lt;/p&gt;
&lt;p&gt;자 이 코드는 어떻습니까? 먼가 우스꽝 스럽죠. 맞습니다. 이 코드는 유니코드 빌드에서 실패하는 코드입니다.&lt;/p&gt;
&lt;p&gt;wchar_t *str;&lt;/p&gt;
&lt;p&gt;printf(“%S”, str);&lt;/p&gt;
&lt;p&gt;%S 옵션이 유일하게 힘들 얻는 순간입니다. 하지만 이 순간에서 조차도 편리하긴 하지만 헷갈리는건 어쩔 수 없습니다. 왜냐구요? %S만 보고는 이게 어떻게 변환되는 건지 추론을 할 수 없기 때문이죠. printf까지 봤을 때, 아 이게 wchar_t *로 변환되는 거구나라고 판단할 수 있기 때문입니다. 뇌에 부담을 준다고 생각할 수 있겠습니다.&lt;/p&gt;
&lt;p&gt;이런 헷갈리는 문제 때문에 다른 변환 지시자들이 존재합니다. 바로 %hs, %ws(=%ls)가 그것이죠. %hs는 대상을 함수에 상관없이 char *로 변환해서 출력해 주는 역할을 합니다. 반대로 %ls, %ws는 wchar_t *로 변환해서 출력하는 역할을 하죠. 따라서 마지막에 쓴 코드는 다음과 같이 사용하는게 덜 헷갈리는 코드라고 할 수 있겠습니다.&lt;/p&gt;
&lt;p&gt;wchar_t *str;&lt;/p&gt;
&lt;p&gt;printf(“%ws”, str);&lt;/p&gt;
&lt;p&gt; 15
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[디지털 서명은 반드시 마지막에…]]></title><description><![CDATA[…]]></description><link>https://jiniya.net/wp/archives/307</link><guid isPermaLink="false">https://jiniya.net/wp/archives/307</guid><pubDate>Tue, 19 Jul 2011 23:57:20 GMT</pubDate><content:encoded>&lt;p&gt;디지털 서명과 실행파일 프로텍트를 같이 하면서 흔히들 저지르는 실수가 하나 있습니다. 디지털 서명을 처음 적용하시는 분들이 많이들 하는 실수 같은데요. 실행 파일을 빌드한 다음 디지털 서명을 적용하고, 해당 파일을 실행 파일 프로텍터로 보호하는 겁니다. 그런데 웃기게도 이렇게 해버리는 경우는 실행 파일 프로텍터가 실행 파일 내용을 바꾸면서 자연스럽게 해시 값이 변경되서 디지털 서명으로 인한 인증효과가 전혀 없어진다는 겁니다. 그러니 이렇게 백날 디지털 서명을 해봤자 백신 프로그램이나 다른 여타 보안 프로그램에서는 허구헌날 그 프로그램을 잡게 됩니다. 왜냐하면 디지털 서명이 되어 있지만 변조된 파일이거든요.&lt;/p&gt;
&lt;p&gt;그렇다면 제대로 하려면 어떻게 하면 되느냐? 바로 순서를 반대로 하면 됩니다. 프로텍터로 보호하고, 디지털 서명을 하는 거죠. 그러면 디지털 서명이 최종적으로 적용되었기 때문에 실행 파일 해시는 디지털 서명의 그것과 일치하고 백신등이 검사했을 때 변경되지 않았기 때문에 안전하게 예외처리가 될 겁니다. 물론 디지털 서명을 제대로 해도 잡는 백신도 많습니다.&lt;/p&gt;
&lt;p&gt;결론은 “디지털 서명을 제대로 적용하기 위해서는 반드시 실행 파일에 최종 수정을 가하는 것이 인증서 프로그램이 되도록 만들어야 한다”로 요약할 수 있겠습니다.&lt;/p&gt;
&lt;p&gt;아래는 참고로 프로그램에서 디지털 서명을 체크하는 코드가 나와 있는 사이트입니다. 프로그램에 디지털 서명 체크 기능을 추가해야 한다면 유용하게 카피앤페이스트해서 사용하실 수 있습니다. ㅋㅋ~&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa382384(VS.85).aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/aa382384(VS.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://support.microsoft.com/kb/323809/ko&quot;&gt;http://support.microsoft.com/kb/323809/ko&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; 0
 0&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[PE 헤더 사이즈 필드 믿을 수 있을까?]]></title><description><![CDATA[PE 포맷의 NT 헤더에 보면 OptionalHeader에 SizeOfHeaders란 필드가 있습니다. 이 필드는 보통 파일 기반의 헤더 크기로 정의 됩니다. SizeOfImage…]]></description><link>https://jiniya.net/wp/archives/4250</link><guid isPermaLink="false">https://jiniya.net/wp/archives/4250</guid><pubDate>Tue, 19 Jul 2011 23:57:19 GMT</pubDate><content:encoded>&lt;p&gt;PE 포맷의 NT 헤더에 보면 OptionalHeader에 SizeOfHeaders란 필드가 있습니다. 이 필드는 보통 파일 기반의 헤더 크기로 정의 됩니다. SizeOfImage는 반대로 파일을 로딩하기 위해서 메모리에 확보해야할 공간을 의미하죠. 그래서 SizeOfHeaders는 FileAlignment 단위로 정렬되고, SizeOfImage는 SectionAlignment 단위로 정렬됩니다.&lt;/p&gt;
&lt;p&gt;보통의 경우 이 SizeOfHeaders 필드가 정상적입니다. 파일일 때의 크기와 일치한다는 것이죠. 그런데 얼마전에 정말 어처구니 없는 상황을 알게 되었습니다. 이 SizeOfHeaders 필드가 upx 압축이 되면 잘못될 수 있다는 것이죠. upx의 경우 소스를 보지 않아서 정확하게 왜 그러는지는 알 수 없지만 실행 파일의 SizeOfHeaders 필드를 4K로 만들어 버립니다. 더 재