<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>MoonCha&apos;s Notepad</title>
    <description>See how MoonCha lives his life.</description>
    <link>https://mooncha.github.io/</link>
    <atom:link href="https://mooncha.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 26 Apr 2026 14:21:09 +0000</pubDate>
    <lastBuildDate>Sun, 26 Apr 2026 14:21:09 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Goodbye, 2025</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/images/mooncha-and-hasuk.jpg&quot; alt=&quot;&quot; width=&quot;40%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;벌써 2025년의 마지막 날이다.
&lt;a href=&quot;/misc/2024/12/29/looking-back-my-life-2024.html&quot;&gt;체크포인트 2024년 - 뒤돌아 보다&lt;/a&gt;와 함께 2024년을 마무리 했었는데,
2025년도 이처럼 보내볼까 한다. 딱히 정갈하게 다듬어 내놓을 글은 아니고, 2025년을 가볍게 돌아보며 쉽게 쓰는 작별 인사의 느낌으로 쓰기로 한다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;30대-숙련된-개발자&quot;&gt;30대, 숙련된 개발자&lt;/h2&gt;
&lt;p&gt;이제는 만 나이도 30이 되면서 통계상으로도 30대에 진입했다.
막 시니어로 가는 관문에 놓인 느낌이다. 
요구사항이 주어지면 이제는 어느 정도 어느 코드를 고치고 어떤 팀과 커뮤니케이션이 필요할지 대략적으로 감이 온다.
특별히 신경 쓰면서 공부한 것은 아니라서, 이제 꽤나 현 조직의 도메인에 경험과 숙련도가 꽤나 쌓인 느낌이다.
올해는 멘티도 한 명 생겨서, 누군가를 가이드 하는 책임까지 생겼다!&lt;/p&gt;

&lt;p&gt;물론 흔히 말하는 JSON 상하차… 를 넘어서는 경쟁력을 갖추기 위한 공부는 계속되어야 할 것 같은데, 잘 실천되지는 않았다.
오는 2026년에는 도메인 숙련도 보다는 경쟁력을 갖추는 쪽에서 성과가 있으면 기분은 좋을 듯 하다!
앞으로 오래 살아남기 위해서라도 ^^7&lt;/p&gt;

&lt;h2 id=&quot;격동의-시대가-주는-과제&quot;&gt;격동의 시대가 주는 과제&lt;/h2&gt;
&lt;p&gt;AI 도구 기반의 경쟁력을 갖추면 좋을 것으로 생각하고 있다.
이제 그 내부 동작을 파악하는 것은 나의 이해 범주를 넘어선 것 같고, 내가 휴대폰이 어떻게 만들어 졌는지는 모르지만 활용할 수는 있듯 이와 같은 방식으로 접근할 차례인 것 같다.
아직까지 기존에 존재하는 대규모 BE 코드를 수정 할 때 사용하기는 무리가 있는 것으로 판단하고 있다.
다만 처음부터 시작하는 프로젝트의 프로토타이핑이나 툴, 서드파티 프로그램 제작에는 기존과 비교할 수 없을 정도로 효과적이라고 느끼고 있다.
이 부분에 초점을 맞춰서 뭘 재미있게 할 수 있을지 찾아보려고 한다.&lt;/p&gt;

&lt;p&gt;2025년에는 Bithumb 에서 USDT 마켓이 열렸었는데, 소소하게 Arbitrage를 수행하는 봇을 빠르게 프로토타이핑 해볼 수 있었다.
안타깝게도 수익은 몇 천원 정도라서 서버비도 안나왔다. 😢&lt;/p&gt;

&lt;h2 id=&quot;커리어를-넘어---화폐-가치-하락과-재테크&quot;&gt;커리어를 넘어 - 화폐 가치 하락과 재테크&lt;/h2&gt;
&lt;p&gt;2023년 ~ 2025년에 가장 아쉬운 점을 하나 뽑자면, 액티브하게 자산을 관리하지 않은 것이다.
위 기간 동안 자산 거의 대부분(아마 95% 이상)을 원화 현금으로 보유했고, 되돌아보면 근 3년간의 재테크 최대 실책으로 남았다.
원화 화폐 가치가 하락하면서 거의 모든 자산 가치가 오르는 랠리가 일어났고, 적어도 원화만 가지고 있지 않았어도 재테크 모범 답안에 근접했을 것이라 본다.&lt;/p&gt;

&lt;p&gt;자산 총량이 숫자 상으로는 줄어들지 않아도, 화폐 가치가 하락하면서 실질 근로 소득도 감소하고 있는 실정이다.
FOMO에 시달리다가 마음의 안정을 위해 미장에 살짝 담군 것은 비과세는 무슨 마이너스가 되었다. 물론 비중은 크게 두지 않았다.
근로의 가치가 날이 갈수록 떨어져가는 참 희망이 없는 시대이지만 어떻게든 이겨나가야겠지…&lt;/p&gt;

&lt;h2 id=&quot;일상의-포인트-생활-습관과-지금의-나&quot;&gt;일상의 포인트: 생활 습관과 지금의 나&lt;/h2&gt;
&lt;p&gt;2024에는 이제까지 변화한 점에 대해 썼었는데, 이번에도 한 번 간단하게 정리해보려고 한다.&lt;/p&gt;

&lt;h3 id=&quot;여전히&quot;&gt;여전히&lt;/h3&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;약 6권의 책과 2권의 기술서적을 읽었다. (그러나) 하반기에는 소홀했다.&lt;/li&gt;
  &lt;li&gt;회사 기술 프로그램의 소소한 그룹을 운영했다. (그러나) 짧게하고 끝냈다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;이제는-바란다&quot;&gt;이제는 바란다&lt;/h3&gt;
&lt;p&gt;유감스럽게도 추가로 변화한 것은 생각나는게 없다. 2025년에 바라는 모습을 써보기로 한다.&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;/ul&gt;

&lt;p&gt;그리고 없는 후회없는 시간 보내길.&lt;/p&gt;

&lt;h2 id=&quot;살아간다는-것&quot;&gt;살아간다는 것&lt;/h2&gt;
&lt;h3 id=&quot;가족&quot;&gt;가족&lt;/h3&gt;
&lt;p&gt;올해는 조카가 생겼다. 내가 삼촌이라니…
그렇게 형은 이제 한 아이의 부모님이 되었고, 부모님은 할아버지/할머니가 되셨다.
새삼스럽게 시간이 많이 흘렀다는 것이 느껴진다.&lt;/p&gt;

&lt;h3 id=&quot;함께하는-것&quot;&gt;함께하는 것&lt;/h3&gt;
&lt;p&gt;나는 평생 혼자 살아갈 수 없다.
그리고 올해는 나와 많은 시간을 함께한 이가 있었다.
모두, 또한 특별한 사람께 감사하며 2025년을 마무리한다.&lt;/p&gt;
</description>
        <pubDate>Wed, 31 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2025/12/31/goodbye-2025.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2025/12/31/goodbye-2025.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>프로그래밍 토막 지식 (1)</title>
        <description>&lt;p&gt;실무에서 겪은 작은 시행착오들을 짧게 기록해 둡니다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-배포-중-febe-하위호환성&quot;&gt;1. 배포 중 FE/BE 하위호환성&lt;/h2&gt;

&lt;p&gt;BE 배포에서만 하위 호환성을 보통 고려하고 있었으나, FE에서도 동일한 문제가 생길 수 있습니다.
SPA처럼 하나의 번들만 로드하면 괜찮겠으나, 외부 라이브러리를 script로 따로 불러오는 경우 배포 중 구버전과 신버전이 섞여 로드될 수 있습니다.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;SPA FE도 배포 시 하위호환성 고려가 필요하다.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-mysql-auto-increment-채번-규칙&quot;&gt;2. MySQL Auto Increment 채번 규칙&lt;/h2&gt;

&lt;p&gt;MySQL은 DB 재시작 시 다음 ID를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX(id) + 1&lt;/code&gt;로 정합니다.
문제는 가장 큰 ID가 삭제된 상태라면 재시작 후 그 값이 다시 ID로 채번될 수 있습니다.
비즈니스 로직에 따라서 삭제된 것이 다시 부활하거나 정합성을 헤치는 포인트가 됩니다.&lt;/p&gt;

&lt;p&gt;(*) 지금 일하는 팀에서는 Oracle DB를 쓰고, sequence 기반 채번을 하기 때문에 해당사항이 없었습니다.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;MySQL Auto Increment ID는 재사용될 수 있다.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-jpa-onetoone과-lazy-loading&quot;&gt;3. JPA OneToOne과 Lazy Loading&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@OneToOne(fetch = FetchType.LAZY)&lt;/code&gt;라 해도 항상 지연 로딩이 되지 않습니다.
Proxy는 null을 값으로 가질 수 없으므로, 외래키를 알 수 없는 상황(연관관계 주인이 아니면서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;optional = true&lt;/code&gt;)에서는 Eager로 동작합니다.&lt;/p&gt;

&lt;p&gt;(*) Lazy Load 메커니즘으로 Bytecode Enhancement를 쓰면 해결되는 것으로 알고 있습니다.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;@OneToOne(fetch = FetchType.LAZY)도 조건에 따라 Eager로 바뀔 수 있다.&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 29 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2025/08/29/misc-programming-knowledge-1.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2025/08/29/misc-programming-knowledge-1.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>개발자 커리어를 시작할 때 알았으면 좋았을만한 점</title>
        <description>&lt;p&gt;이번에 처음으로 멘토 역할을 맡게 된 기념으로 개발자 커리어를 시작할 때 알았으면 꽤 괜찮았을 만한 부분들을 글로 남겨보려고 한다.&lt;/p&gt;

&lt;h3 id=&quot;자취를-할거면-온전한-1년을-다니기-전에-구하는-것이-낫다&quot;&gt;자취를 할거면 온전한 1년을 다니기 전에 구하는 것이 낫다.&lt;/h3&gt;
&lt;p&gt;입사 첫 년차에는 보통 1월부터 일을 시작하지 않는 경우가 많기 때문에, 소득이 실제 연봉보다 적게 잡힌다. 그리고 연봉이 7000만원을 넘어서는 시점 부터는 거의 모든 세제 혜택의 대상에서 제외되고, 각종 국가지원 사업의 대상이 되지 않는다. 그러나 첫 년차에는 앞서 말한 이유로 실제보다 적게 잡히기 때문에 소득 제한이 있는 것들을 해보기에 적기이다. 대표적으로 디딤돌대출, 행복주택 등이 있다. 특히 이 두 가지는 지출의 큰 부분을 차지하는 주거 비용과 연관되어 있기 때문에 빠르게 생각해보면 좋다. 주거와 관련된 대출과 주택은 이후에 소득조건이 만족되지 않더라도 연장 가능한 것으로 알고 있어 더 중요하다.&lt;/p&gt;

&lt;h3 id=&quot;공부한파악한-내용을-정리한-노트-만들기&quot;&gt;공부한/파악한 내용을 정리한 노트 만들기&lt;/h3&gt;
&lt;p&gt;앞서 작성한 글에서 이어지는 부분인데, 처음부터 배운 내용을 정리해서 남겨 놓으면 추후에 참고하면서 기억하기 좋았겠다. 그리고 기록하다보면 회의 같은 내용도 기록하면서 듣기 때문에 업무에 있어 빈틈이 없어지는 효과도 있다.&lt;/p&gt;

&lt;h3 id=&quot;모니터링-로그-및-유틸-페이지의-중요성&quot;&gt;모니터링, 로그 및 유틸 페이지의 중요성&lt;/h3&gt;
&lt;p&gt;백엔드 서비스 개발의 중요한 포인트 중 하나는 운영중에 발생하는 이슈 대응에 있다. 처음 입사한 시점에는 문제가 발생했을 때 무엇을 해야하는지 알지 못한다. 이 때 가장 먼저 살펴보게 되는 것들은 모니터링 툴 및 로그를 살펴보게 되는데, 이것들에 대한 접근성이 얼마나 확보되어 있느냐가 빠르게 대응할 수 있는가를 크게 가른다. 조직에서 사용하고 있는 이런 툴들에 대한 링크를 잘 모아두고 각각에서 어떤 것들을 살펴볼 수 있는지 파악해두면 대단히 유용하다. 처음에는 문제가 발생했을 때 선배들이 어떻게 하는지 살펴보고, 어떤 페이지들을 살펴보고 그 페이지 내에서더 어떤 정보들을 깊게 살펴보는지 살펴보면 좋은 것 같다.&lt;/p&gt;

&lt;h3 id=&quot;작은-변경이라도-반드시-테스트할-것&quot;&gt;작은 변경이라도 반드시 테스트할 것&lt;/h3&gt;
&lt;p&gt;개발에서 테스트의 중요성은 아무리 강조해도 지나치치 않다. 그런데 처음에는 코드 수정을 하고 나서 적절한 테스트 방법을 어느 정도 시간이 지나도 어려운 영역들이 존재한다. 신입 때의 나는 이런 부분들을 묻는 것에 어려움이 있었고, 근거없는 자신감으로 잘 돌아가겠지… 하고 서비스로 코드가 나간적이 있다. 그 결과 서비스는 로그인이 안되는 커다란 문제가 있었다. 그 이후 나는 조그마한 변경이라도 반드시 테스트 해보는 개인적인 원칙을 가져가고 있고, 매 번 이 정도면 당연히 생각대로 돌아가겠지 싶은 것에서 버그를 찾아내곤 한다.&lt;/p&gt;

&lt;h3 id=&quot;기획이-원하는-것은-기획서의-내용이-아닐-수-있다&quot;&gt;기획이 원하는 것은 기획서의 내용이 아닐 수 있다&lt;/h3&gt;
&lt;p&gt;기획 내용을 보다보면 설명상 간단한 것에 비해 대단히 어려운 변경이 있다던지, 굳이 왜이렇게 해야 하는가 싶은 부분을 마주할 때가 있다. 대부분의 경우 기획서의 내용에는 달성하려는 목표가 있으며 그것을 만족하는 한 협의의 여지가 있다. 이 경우 숨은 목표에 대해 이야기 하고, 개발 공수를 크게 줄이면서도 더 나은 방향이 제시될 수도 있다.. 그 만큼 커뮤니케이션을 능동적으로 할 필요가 있다는 말이기도 하다. (e.g. 세세한 정렬 로직, ADMIN 툴의 기능 등…)&lt;/p&gt;

&lt;h3 id=&quot;서비스-특성과-기술적-퀄리티-그-간극-사이&quot;&gt;서비스 특성과 기술적 퀄리티, 그 간극 사이&lt;/h3&gt;
&lt;p&gt;자기들의 기술을 갈고 닦고, 높은 기술적 수준의 결과물을 만들어내는 것을 싫어할 개발자는 거의 없을 것이다. 좋아하지 않는다 해도, 그러길 바랄 것이다. 연구 조직은 모르겠지만, 서비스 조직의 경우 빠른 개발 또한 회사의 이익 측면에서 중요한 요소이기 때문에 둘 간의 밸런스를 잘 잡는게 중요하다. 급하다고 해서 너무 중구난방으로 할 수 없고, 급한데 길고 깊은 고민을 담기도 쉽지 않다. 일을 하다 보면서 자신만의 적절한 선을 찾아가는 것도 중요한 포인트다. 개인적으로는 쉽게 변경하기 어려운 인터페이스 레벨의 설계에서는 시간을 들이는 편이다.&lt;/p&gt;
</description>
        <pubDate>Wed, 30 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2025/07/30/good-things-to-know-starting-developer-career.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2025/07/30/good-things-to-know-starting-developer-career.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>일하면서 일찍 했으면 좋았을 점 (1) - Cheat Sheet 만들기</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/images/working-man-with-tools.png&quot; alt=&quot;&quot; width=&quot;40%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;어느덧 일한 지도 만 7년이 다 되어 간다. 이쯤 되니 종종 ‘그때 이걸 더 일찍 했더라면 어땠을까’ 하는 생각이 들곤 한다. 최근 들어 특히 많이 느끼는 것은 &lt;strong&gt;업무 Cheat Sheet의 중요성&lt;/strong&gt;이다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;빠르게-대응하는-사람들의-공통점을-보다&quot;&gt;빠르게 대응하는 사람들의 공통점을 보다&lt;/h2&gt;

&lt;p&gt;서버 개발을 하다 보면 긴급히 대응해야 하는 장애 상황을 종종 맞이한다. 그런 상황에서 유독 빠르게 대응하는 사람들이 눈에 띄는데, 그들은 모두 자신만의 Cheat Sheet를 갖고 있었다.&lt;/p&gt;

&lt;p&gt;예를 들면,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;사내 managed Kubernetes 환경에서 load balancer에서 제거하려면 어떤 label을 제거해야 하고, 이를 제거하는 명령어는 무엇인가?&lt;/li&gt;
  &lt;li&gt;Elasticsearch에서 특정 조건의 document를 찾아야 할 때, 쿼리를 얼마나 빠르게 짤 수 있는가?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이런 상황에서 필요한 건 대부분 익숙한 명령어나 이것의 약간의 변형이다. 이를 미리 정리해둔 사람과 그렇지 않은 사람 사이에는 큰 차이가 난다.&lt;/p&gt;

&lt;h2 id=&quot;단순-스케쥴링-기록으로는-부족하다&quot;&gt;단순 스케쥴링 기록으로는 부족하다&lt;/h2&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;/ul&gt;

&lt;p&gt;나는 보통 위처럼 일들을 관리하는데, 이 정도로는 직장인으로서 평범하게 일을 진행하게 될 뿐 시간이 흐를수록 팀에서의 내 경쟁력이 강해지지는 않는다고 느꼈다.퍼포먼스가 좋은 사람들은 어떤 특징이 있나 관찰하기도 하고 직접 묻기도 하면서 발견한 것은 여러 팁들을 써놓은 메모가 존재한다는 것이었다.&lt;/p&gt;

&lt;h2 id=&quot;어떤-내용을-cheat-sheet에-담아야-하나&quot;&gt;어떤 내용을 Cheat Sheet에 담아야 하나?&lt;/h2&gt;

&lt;p&gt;내가 직접 써보거나, 동료들이 잘 활용하는 내용을 기준으로 정리하면 다음과 같다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;업무 도메인 내용 정리
    &lt;ul&gt;
      &lt;li&gt;자주 쓰는 용어나 개념&lt;/li&gt;
      &lt;li&gt;내부 시스템 흐름&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;중요 회의 내용 요약
    &lt;ul&gt;
      &lt;li&gt;결정된 사항&lt;/li&gt;
      &lt;li&gt;TODO&lt;/li&gt;
      &lt;li&gt;이슈&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자주 사용하는 명령어
    &lt;ul&gt;
      &lt;li&gt;Kubernetes에서 pod shell 접속&lt;/li&gt;
      &lt;li&gt;사내 저장소 업로드 명령어&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;로 API 수동 호출&lt;/li&gt;
      &lt;li&gt;BOM 제거용 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; 명령어&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;사내용 도구 정리
    &lt;ul&gt;
      &lt;li&gt;모니터링 툴 링크&lt;/li&gt;
      &lt;li&gt;테스트용 계정 정보&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이런 정보들은 급할 때 빠르게 꺼내 쓸 수 있고, 이슈 대응도 상당히 반복되는 패턴인 경우가 많은데 이 때의 생산성을 높여준다.&lt;/p&gt;

&lt;p&gt;이렇게 만들어진 Cheat Sheet는 퍼포먼스를 좋게도 만들지만, 다른 곳에 가더라도 다시 꺼내볼 수 있는 자료가 될거라고 생각이 든다. 그리고 내용을 글로 정리하는 과정에서 이해의 깊이가 더해진다.&lt;/p&gt;

&lt;p&gt;일을 시작하면서 처음부터 이런 습관을 들였다면, 지금보다 더 많은 자료를 축적하고 훨씬 퍼포먼스 있게 일할 수 있었을 것 같다.&lt;/p&gt;

&lt;h2 id=&quot;번외-어떤걸-써서-메모해야-하나&quot;&gt;번외: 어떤걸 써서 메모해야 하나?&lt;/h2&gt;

&lt;p&gt;요즘은 Obsidian을 사용하는 사람이 많이 보인다. 마크다운 기반이라 개발자에게 친숙해서 그런 것 같다. 나는 개인적으로 OneNote를 쓰고 있는데, 블로그 글을 정리할 때도 연계하기 좋아 보여서 Obsidian도 써볼까 싶다. 이 외에도 Bear 같은 마크다운 편집기를 쓰는 사람도 있었다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;⚠️ 회사마다 보안 정책이 다르기 때문에 클라우드 동기화가 제한되는 경우도 있다. 이 경우 OneNote는 적절하지 않고, 로컬 디스크 기반으로 동작하는 도구가 필요하겠다.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 27 May 2025 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2025/05/27/the-things-that-i-should-have-done-early-1.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2025/05/27/the-things-that-i-should-have-done-early-1.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>체크포인트 2024년 - 되돌아 보다</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/images/worrying-developer.webp&quot; alt=&quot;&quot; width=&quot;40%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;지나오다&quot;&gt;지나오다&lt;/h2&gt;
&lt;p&gt;2024년이 되며 한국식 나이로 30이 되고, 이제는 멀지 않은 미래에 만 나이도 30이 되면서 통계상으로도 30대가 된다.
이제는 친구들도 스스로를 젊다고 할 지언정, 어리다고는 말하지 않는다.&lt;/p&gt;

&lt;p&gt;병역 특례로 베이글코드에서 2년, 졸업 후 네이버에서 4년 6개월.
개발자로서의 커리어도 이제는 7년차로 접어들었고, 이제 주니어라고 칭하기에는 민망하다.
그렇다고 시니어는 아닌데. 흔히 중니어라고 부르는 시점인 것 같다.&lt;/p&gt;

&lt;h2 id=&quot;뒤돌아보다&quot;&gt;뒤돌아보다&lt;/h2&gt;
&lt;p&gt;Github의 풀밭은 사막이 된지 오래다. Resume 정리도 되어있지 않다.
돈을 악착같이 번 것도 아니라서, 몇 년 전 수준에서 딱히 변한 것도 없다.
공부를 그렇게 열심히 한 것도 아니라서, 그저 시간이 흐르면 자연스럽게 생기는 숙련도만 남았다.
나는 무엇을 바라 대학생 시절에는 그렇게 열심히 공부한 것일까?
녹슬어 무뎌질 거라면 딱히 열심히 안해도 됐을 것 같다는 생각이 든다.&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;h2 id=&quot;발자취를-살펴보다&quot;&gt;발자취를 살펴보다&lt;/h2&gt;
&lt;p&gt;연말이 되면 업무 평가가 진행된다. 나를 PR하는 셀프 리뷰에 “적당히 시키는거 잘했습니다.”라고 쓸 수는 없다.
그래도 한 해 간 뛰어난 역량을 보여줬다고, 발전하는 모습을 보여줄 수 있다고 직장인의 페르소나를 만들어야 한다.
이제껏 한 것들을 끌어 모아서 어떻게든 셀프 리뷰를 써내려간다.&lt;/p&gt;

&lt;p&gt;이렇게 리뷰를 쓰기 위해 행적을 자세히 살펴보니, 발전이 아주 없지는 않았다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;약 10권의 책과 2-3권의 기술서적을 살펴봤다.&lt;/li&gt;
  &lt;li&gt;기술 뉴스를 자주 살펴보게 되었다.&lt;/li&gt;
  &lt;li&gt;ES 그룹 스터디를 운영했다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;완전히 만족스러운 정도는 아니지만, 그래도 희망적인 편이다.&lt;/p&gt;

&lt;p&gt;의외로 큰 변화는 커리어 외적인 부분에서 볼 수 있었다. &lt;br /&gt;
커리어와는 무관한 만큼 리뷰에 쓰지는 못하지만, 행적을 짚고 넘어가지 않을 수 없다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;표준 체중을 유지하고 있다. (* 2023년에 7개월에 걸쳐 90+kg 에서 76kg으로 감량했다.)&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;h2 id=&quot;나를-바꾸는-힘&quot;&gt;나를 바꾸는 힘&lt;/h2&gt;
&lt;p&gt;대학교에서 좋은 교육을 받고,
좋은 기업에 취직을 하고,
재테크를 하며 자산을 늘려가고. &lt;br /&gt;
이정도면 괜찮지라고 생각했던 것 같다. 아주 나태한 생각이었던 것 같지만.&lt;/p&gt;

&lt;p&gt;변화는 내 부족함을 인정하는 것에서 시작됐다. &lt;br /&gt;
시장에 내놓았을 때 나의 경쟁력이 부족함을 인정하자. &lt;br /&gt;
사람으로서든, 기술자로서든 어느 쪽이든.&lt;/p&gt;

&lt;h2 id=&quot;앞으로도-시간은-흐른다&quot;&gt;앞으로도 시간은 흐른다&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;“어제보다 나은 내가 될 수 있다는 희망이 있다.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;이번 셀프 리뷰에 쓴 말이다. 시간이 더 흐르기 전에 앞으로도 움직일 것이다. &lt;br /&gt;
그간 말라왔던 Github에 2024년 마지막 날에 흔적을 남기며, 2025년도 파이팅.&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2024/12/29/looking-back-my-life-2024.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2024/12/29/looking-back-my-life-2024.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>유럽에서 자동 이체를 사용할 때 주의할 점</title>
        <description>&lt;p&gt;&lt;strong&gt;선요약&lt;/strong&gt;: 자동 이체가 잔액 부족으로 실패하게 하면 많은 수수료가 청구된다. + Educom sucks&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;최근, 유럽 교환학생으로 있는 동안 사용한 유럽 통신사 Educom으로부터 10 유로를 추가로 청구 받았다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/educom-bank-charge.png&quot; alt=&quot;10 euros charge from Educom&quot; width=&quot;75%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이 모든 문제는 2020년 2월 13일에 귀국하고, 한참의 시간이 흘러 3월 27일에 뜬금 없이 1.03유로가 청구되면서 문제가 발생했다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/educom-1.03-euro-charge.png&quot; alt=&quot;10 euros charge from Educom&quot; width=&quot;75%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이미 2월 분은 한국으로 돌아오기 전에 미리 요금에 해당하는 9.99유로를 이체하고 왔기 때문에 문제가 없을 것이라 생각했는데, 뜬금없이 4일분의 1.03 유로가 청구되었다. 사용하지도 않은 나머지 2월달의 요금이 청구 되는 것 까지는 이해하더라도, 갑자기 2월 요금을 뜬금 없이 3월 27일에 청구 되어서 화가 난다.&lt;/p&gt;

&lt;p&gt;마침 유럽에서 사용했던 N26 계좌의 금액은 모두 출국하고 한국으로 돌아왔기에, 1.03 유로를 지불할 수 없었다. 그래서 잠시 Educom Customer Service와 실랑이를 벌이는 동안 자동 이체로 1.03유로가 이체 시도 되었다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/n26-account-transactions.jpg&quot; alt=&quot;N26 account transactions&quot; style=&quot;max-height:700px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;그 시점에서 알게된 사실은 유럽 은행에서는 자동 이체가 실패하면 패널티 금액이 부과된다는 것이다. N26에서는 자동 이체가 실패했기 때문에 3유로를 가져갔고, 은행 잔고는 마이너스가 되었다. 한국에도 통장 잔고를 충분히 넣어놓지 않아서 통신 요금 자동 이체가 실패한 적이 있는데, 그 때는 돈이 정상적으로 지불이 되지 않을 뿐 전산 처리 비용으로 추가 수수료를 물지는 않았다. 한국과 유럽의 은행 시스템은 많은 차이가 있지만, 다시 한 번 체감하게 된다.&lt;/p&gt;

&lt;p&gt;잔고가 마이너스가 되는 경우 이자가 청구되고 추후에 문제가 될 소지가 있으니 급하게 이번에 교환 학생을 간 사람들에게 유로를 약간 구매해 1.03 유로를 수동으로 지불했다. 그렇게 3유로의 수업 비용(?)을 치루고 모든 일이 마무리 되었다고 생각했다.&lt;/p&gt;

&lt;p&gt;그런데 다시 한 번 4월 27일, 위의 10유로 청구가 온 것이다. 독일어를 잘 몰라서 해석은 못하겠지만, Bank Charge 정도로 구글 번역되는 것으로 보아 이체 실패에 대한 수수료인 것으로 보인다. 정확한 청구 이유를 알고 싶어서 Educom Customer Service에 다시 한 번 메일을 보냈다. 로밍, 탈퇴, 요금 청구까지 수십 통의 메일을 보내게 만드는 Educom은 정말 최악의 경험을 선사해준다. 
1.03 유로 수동 결제 문제로 문의 했을 때 이런 요금 부과가 있을 거라고 알려주기라도 하던가 아니면 즉시 청구 되기라도 하던지. Educom Customer Service는 고객에게 충분한 설명을 제공하지 않는 것 같다.&lt;/p&gt;

&lt;p&gt;아무튼, 갑자기 또 돈 청구해서 짜증나게 하는 Educom에 대한 인상은 최악으로 떨어졌다. 만약 유럽에서 소액만 유로화 판매해줄 사람이 없었더라면 괜히 수수료도 많이 들고 최소 금액 제한도 있는 해외 송금을 해야됐을 수도 있는데, 얼마나 짜증 나는 일이었을지.&lt;/p&gt;

&lt;p&gt;혹시 유럽에서 자동 이체(Direct Debit)을 사용하는 사람이 있다면 괜히 저처럼 1.03유로 때문에 13유로를 추가로 지불하는 일은 없길 바랍니다.&lt;/p&gt;
</description>
        <pubDate>Mon, 27 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2020/04/27/be-careful-when-you-use-direct-debit-in-europe.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2020/04/27/be-careful-when-you-use-direct-debit-in-europe.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>당신이 C integer에 대해 몰랐을 만한 것들</title>
        <description>&lt;p&gt;당신이 C언어의 Integer에 관해 몰랐을 만한 내용들을 소개합니다.&lt;/p&gt;

&lt;p&gt;알고 있었다면 어쩔수 없구요.&lt;/p&gt;

&lt;h2 id=&quot;1-integer-overflow-standard-behavior&quot;&gt;&lt;strong&gt;1. Integer overflow standard behavior&lt;/strong&gt;&lt;/h2&gt;

&lt;h3 id=&quot;--signed-int의-overflow-동작은-undefined-behavior이다&quot;&gt;- &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed int&lt;/code&gt;의 overflow 동작은 undefined behavior이다.&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. - &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf&quot;&gt;5/4&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;위 처럼 C++ Standard에 따르면 계산 결과가 데이터 표현 범위를 벗어나는 경우의 동작은 정의되어 있지 않다.&lt;/p&gt;

&lt;h3 id=&quot;--unsigned-int의-overflow-동작은-standard로-명시되어-있다&quot;&gt;- &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsigned int&lt;/code&gt;의 overflow 동작은 standard로 명시되어 있다.&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Unsigned integers shall obey the laws of arithmetic modulo 2
n where n is the number of bits in the value
representation of that particular size of integer. - &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf&quot;&gt;3.9.1/4&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting
unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the
resulting unsigned integer type. - &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf&quot;&gt;3.9.1/4 - annotation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;그러나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsigned int&lt;/code&gt;의 경우 계산 후 $\mod 2^{n}$를 취하는 것이 standard로 정의되어 있어 일반적으로 기대하는 동작을 한다.&lt;/p&gt;

&lt;h3 id=&quot;일반적인-가정&quot;&gt;일반적인 가정&lt;/h3&gt;

&lt;p&gt;많은 경우 C 프로그램들은 int가 overflow하면 2의 보수하의 연산 후 $\mod 2^{n}$를 취하는 동작을 한다고 가정하고 작성되어 있다. &lt;a href=&quot;https://www.gnu.org/software/autoconf/manual/autoconf-2.64/html_node/Integer-Overflow-Basics.html&quot;&gt;ref&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;2-integer-overflow-by-negation&quot;&gt;&lt;strong&gt;2. Integer overflow by negation&lt;/strong&gt;&lt;/h2&gt;

&lt;h3 id=&quot;---negation에-의해서도-integer-overflow가-발생한다&quot;&gt;- &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;(negation)에 의해서도 integer overflow가 발생한다.&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-INT_MIN&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt; 표현 범위를 벗어난다. (일반적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-INT_MIN == INT_MIN&lt;/code&gt;이 된다.)&lt;/p&gt;

&lt;h3 id=&quot;--division에-의해서도-integer-overflow가-발생한다&quot;&gt;- &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;(division)에 의해서도 integer overflow가 발생한다.&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/ -1&lt;/code&gt;은 negation과 동일하다. 따라서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INT_MIN / -1&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt; 표현 범위를 벗어난다.&lt;/p&gt;

&lt;h2 id=&quot;3-how-to-effectively-check-overflow&quot;&gt;&lt;strong&gt;3. How to effectively check overflow&lt;/strong&gt;&lt;/h2&gt;

&lt;h3 id=&quot;--diy-overflow-check&quot;&gt;- DIY overflow check&lt;/h3&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;secure_calculate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strcmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* Check for overflow */&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* n1 * n2 &amp;gt; LONG_MAX */&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG_MAX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* Check for overflow */&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* n1 * n2 &amp;gt; LONG_MAX */&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* Bringing a negative n2 to the rhs inverts the inequation */&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG_MAX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* Check for underflow */&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* n1 * n2 &amp;lt; LONG_MIN */&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG_MIN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* Check for underflow */&lt;/span&gt;
      &lt;span class=&quot;cm&quot;&gt;/* n1 * n2 &amp;lt; LONG_MIN */&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG_MIN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;고려할 것도 많고 실수할 것도 많다. 하지 말자.&lt;/p&gt;

&lt;h3 id=&quot;--compiler-built-in-overflow-check-functions&quot;&gt;- Compiler built-in overflow check functions&lt;/h3&gt;

&lt;p&gt;컴파일러에서는 계산시 Overflow가 발생했는지 알려주는 built-in functions가 존재한다.&lt;/p&gt;

&lt;p&gt;이를 활용해보자.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GCC&lt;/strong&gt;: https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;secure_calculate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strcmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__builtin_smull_overflow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4-implicit-conversion-between-signed-and-unsigned-integers&quot;&gt;&lt;strong&gt;4. implicit conversion between signed and unsigned integers&lt;/strong&gt;&lt;/h2&gt;

&lt;h3 id=&quot;--signed--unsgined-계산시-항상-signed가-unsigned로-conversion-되지는-않는다&quot;&gt;- signed &amp;lt;&amp;gt; unsgined 계산시 항상 signed가 unsigned로 conversion 되지는 않는다.&lt;/h3&gt;

&lt;p&gt;C를 배울 때 unsigned와 signed 타입 int간의 연산이 발생하면 signed integer가 unsigned로 전환된다고 배우는 것 같다. 많은 경우 그렇게 계산 되기 때문에 그렇게 생각할 수도 있지만, 이것은 사실이 아니다.&lt;/p&gt;

&lt;h3 id=&quot;--signed로-전환되는-경우&quot;&gt;- signed로 전환되는 경우&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;… Otherwise (the signedness is different, and the unsigned type has conversion rank less than the signed type): If the signed type can represent all values of the unsigned type, then the operand with the unsigned type is implicitly &lt;strong&gt;converted to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed&lt;/code&gt; type&lt;/strong&gt;.
Otherwise: Both operands undergo implicit conversion to the unsigned type counterpart of the signed operand’s type. - &lt;a href=&quot;https://en.cppreference.com/w/c/language/conversion&quot;&gt;cppreference&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;위 글에서 글에서 알 수 있듯, signed &amp;lt;&amp;gt; unsigned implicit conversion은 표현 범위에 의해 결정되며, signed 타입이 unsigned 타입의 표현 범위를 모두 포함하는 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed&lt;/code&gt;로 implicit conversion이 발생한다.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;signed&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;signed&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;signed&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;실행 결과는 아래와 같다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;4294967294
-2
18446744073709551614
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Mon, 23 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/development/2020/03/23/the-things-you-might-not-know-about-integer.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/development/2020/03/23/the-things-you-might-not-know-about-integer.html</guid>
        
        
        <category>DEVELOPMENT</category>
        
      </item>
    
      <item>
        <title>단기 유학동안 수강한 보안 과목의 CTF 과제 문제 리뷰</title>
        <description>&lt;h2 id=&quot;2019-winter-sasd&quot;&gt;2019 Winter: SASD&lt;/h2&gt;

&lt;p&gt;2019년 2학기, TU Graz로 단기유학을 가서 Security Aspects in Software Development(이하 SASD)라는 과목을 들었다.&lt;/p&gt;

&lt;p&gt;SASD는 보안의 여러 분야 중 시스템 해킹을 중점적으로 다루는 석사 과정 과목이다.&lt;/p&gt;

&lt;p&gt;보안 과목 답게, 과제 중 하나는 CTF 형식으로 나왔으며 총 21문제가 출제되었다.&lt;/p&gt;

&lt;p&gt;전체적으로 PLUS 101이라는 느낌을 많이 받는다. 소스 코드가 주어지기 때문에 PLUS에서 입부 후 한 두번의 방학 스터디를 거치면 큰 어려움 없이 모두 풀어낼 수 있으리라 생각한다. 창피한 일이지만, 당시 CTF를 안한지 너무 오래되어 다 푸는데 꽤나 오래 걸렸다.&lt;/p&gt;

&lt;p&gt;문제는&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;String (Null Terminator 처리 등)&lt;/li&gt;
  &lt;li&gt;Environment (Library Hook, PATH, TOCTOU 등)&lt;/li&gt;
  &lt;li&gt;Buffer (ROP 등)&lt;/li&gt;
  &lt;li&gt;Heap (UAF와 variable overwite 외 다른 힙 기법은 다루지 않는다)&lt;/li&gt;
  &lt;li&gt;Format String Bug&lt;/li&gt;
  &lt;li&gt;Bonus (= Reversing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;항목으로 나누어져 있다.&lt;/p&gt;

&lt;p&gt;모두 쉬운 문제여서 소개하기 민망하지만 풀었던 21개의 문제 중 그래도 어느 정도 평소 잊고 살았을 수 있거나 환기해보면 괜찮을 문제들을 소개하려고 한다.&lt;/p&gt;

&lt;h2 id=&quot;문제-소개&quot;&gt;문제 소개&lt;/h2&gt;

&lt;h3 id=&quot;environmentfast_math&quot;&gt;&lt;a href=&quot;https://github.com/MoonCha/sasd2019g11/tree/master/01_environment/fast_math&quot;&gt;&lt;strong&gt;Environment/fast_math&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;이 문제는 한 프로그램에서 계산을 위해 작성된 별도의 프로그램을 실행시키고, 그 프로그램의 실행 결과값을 받아온 후 보여주는 프로그램이다. 이 처럼 한 프로그램이 다른 프로그램을 실행시킬 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setuid&lt;/code&gt;같은 것이 걸려 있다면 특히 주의할 필요가 있는데, 실행되는 별도의 프로그램 또한 같은 권한으로 실행되기 때문이다.&lt;/p&gt;

&lt;p&gt;이 문제는 권한 체크를 통해 익스플로잇을 막으려 했지만, &lt;a href=&quot;https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use&quot;&gt;&lt;strong&gt;TOCTOU&lt;/strong&gt;&lt;/a&gt;취약점이 있는 문제이다.&lt;/p&gt;

&lt;p&gt;아래는 fast_math 문제의 일부분으로, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setgid&lt;/code&gt;가 걸려 있는 바이너리에서 아래와 같이 특정 바이너리를 실행하려고 할때, 자신의 파일인지 권한 체크 후 실행한다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/MoonCha/sasd2019g11/blob/master/01_environment/fast_math/fast_math.c&quot;&gt;Full Source Code&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;// check file ownership is equal&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main.elf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;info_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_uid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_uid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;executable owner is wrong&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Do Something&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;execv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 경우, 처음에는 Symbolic Link로 파일 오너 체크를 통과한 후, &lt;em&gt;// Do Something&lt;/em&gt; 부분이 실행되는 동안 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argv[1]&lt;/code&gt;으로 전달된 파일을 자신의 파일로 바꿔치는 공격을 할 수 있다.&lt;/p&gt;

&lt;p&gt;[+] 보자마자 눈치챈 사람도 있겠지만, 굳이 TOCTOU를 이용하지 않아도 원하는 파일을 실행할 수 있다. 하지만 과제 문제이기 때문에 Intended Solution으로 풀었다.&lt;/p&gt;

&lt;h3 id=&quot;integercard_game&quot;&gt;&lt;a href=&quot;https://github.com/MoonCha/sasd2019g11/tree/master/03_integer/card_game&quot;&gt;&lt;strong&gt;integer/card_game&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;다음 코드에서, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a == -a&lt;/code&gt;가 참인 ???는 몇 가지일까?&lt;/p&gt;

&lt;p&gt;별 고민 없이 생각한다면 아마 1개라고 대답할지 모르겠다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;???&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// OK!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;하지만, 위 조건을 만족하는 숫자는 &lt;strong&gt;2&lt;/strong&gt;개이며 나머지 하나는 $-2^{31}$, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INT32_MIN&lt;/code&gt;이다. (gcc 기준. 엄밀하게 말하면, signed integer overflow는 undefined behavior이다.)&lt;/p&gt;

&lt;p&gt;이처럼 사칙연산 외에도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;(negate)에서도 Overflow가 발생할 수 있다는 점을 명심하며, 숫자의 표현 범위가 정해져 있는 언어의 경우 항상 Overflow를 고려해서 로직을 짜야한다.&lt;/p&gt;

&lt;p&gt;그러면 이 사실을 명심하며, 직소와의 카드 게임에서 이겨보면 된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/jigsaw-head.png&quot; alt=&quot;Jigsaw&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Let&apos;s play a game:
There are 3 piles of cards.
In each turn you may pick any positive number of cards from one pile only.
If you take the last card you win.
Round 1
piles[0] = 7
piles[1] = 11
piles[2] = 12
Pick a pile: 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;bonusturing_completeness&quot;&gt;&lt;a href=&quot;https://github.com/MoonCha/sasd2019g11/tree/master/06_bonus/turing_completeness&quot;&gt;&lt;strong&gt;bonus/turing_completeness&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;전형적인 리버싱 문제이다. 바이너리에서 요구하는 알맞은 인풋을 찾아서 입력하면 Flag가 나오게 되어있다.&lt;/p&gt;

&lt;p&gt;일차적으로 바이너리가 굉장히 커서 겁을 먹게 되고, 열면 일반적인 바이너리와 달리 첫 부분에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sigaction&lt;/code&gt;과 함께 특이하게도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov&lt;/code&gt;들로 도배되어 있는 것을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;이 문제는 프로그램이 어떤 난독화 툴로 난독화 되었는지 알아내는 것에서 부터 시작한다. 난독화된 상태로 그대로 리버싱을 진행하는 방법도 있지만, 프로그램의 flow가 어떻게 이루어지는지 파악하기가 굉장히 어렵기 때문에 쉽지 않다. 기본적으로 난독화된 상태에서는 Flow Graph가 그려지지 않는다. 그와 동시에 동적 디버깅을 실행해보면 flow가 어떻게 이어지는지 매우 혼란스럽다. 물론 짱해커들은 어떻게든 잘 해내겠지만.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/obfuscated-turing_completeness.png&quot; alt=&quot;Obfuscated turing_completeness&quot; width=&quot;80%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;아무튼, 이러한 난독화에 대응할 방법을 찾기 위해 구글링을 하다보면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov&lt;/code&gt; instruction이 turing complete하다는 점을 이용하여 만들어진 &lt;a href=&quot;https://github.com/xoreaxeaxeax/movfuscator&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;movfuscator&lt;/code&gt;&lt;/a&gt;로 난독화 되어 있음을 알게된다.&lt;/p&gt;

&lt;p&gt;그리고 머지 않아 &lt;a href=&quot;https://github.com/kirschju/demovfuscator&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;demovfuscator&lt;/code&gt;&lt;/a&gt;라는 툴이 있다는 것을 알게될 것이다.&lt;/p&gt;

&lt;p&gt;다만, 패키지 관리자를 통해 편리하게 내려받을 수 없는 dependency들이 존재하기 때문에 설치 자체에 상당한 귀찮음이 있을 것이다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;demovfuscator&lt;/code&gt;를 이용하고 나면 아래와 같이 Flow Graph를 볼 수 있게 되며, 평소에 하던대로 로직 분석을 통해 알맞은 인풋을 찾아내면 된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/demovfuscated-turing_completeness.png&quot; alt=&quot;Demovfuscated turing_completeness&quot; width=&quot;80%&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 22 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/hacking/2020/03/22/review-2019-winter-sasd-ctf.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/hacking/2020/03/22/review-2019-winter-sasd-ctf.html</guid>
        
        
        <category>HACKING</category>
        
      </item>
    
      <item>
        <title>왜 node_modules를 커밋해야 하는가?</title>
        <description>&lt;h3 id=&quot;일반적인-개발-상식과-달랐던-것들&quot;&gt;일반적인 개발 상식과 달랐던 것들&lt;/h3&gt;

&lt;p&gt;실제로 개발을 하다보면 일반적인 개발 상식이나 컴퓨터 공학적 지식에 반대되는 방향으로 처리되는 것들이 있었다.&lt;/p&gt;

&lt;p&gt;대표적으로 Relational DB 디자인이 있을 수 있는데, DB 수업때는 Consistency 등의 이유로 Normalization을 해야 하는 것으로 배우지만,&lt;/p&gt;

&lt;p&gt;실제로는 퍼포먼스를 이유로 Join을 피하기 위해 중복 저장을 허용한다던지, 한 Column에 많은 정보를 뭉텅이로 넣는다던지 그런 것들이 있을 수 있을 것 같다.&lt;/p&gt;

&lt;p&gt;이제 보니 이런 사용 경향이 No SQL DB가 나온 이유중 하나던가? 아무튼.&lt;/p&gt;

&lt;h3 id=&quot;node_modules의-경우&quot;&gt;node_modules의 경우&lt;/h3&gt;

&lt;p&gt;마찬가지로 일반적으로는 Node JS에서 코드를 작성할 때, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 repo에 커밋하지 않는 것이 일반적인 상식인 것으로 보인다.&lt;/p&gt;

&lt;p&gt;하지만, 내가 다녔던 회사에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; 전체를 repo에 커밋하여 사용했다.&lt;/p&gt;

&lt;p&gt;처음 막 들어 왔을때는 그닥 신경쓰지 않았고, 일을 하면서 경험을 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 커밋해야 하는 이유에 대해서 알게 되긴 했지만 굳이 그 이유에 대해 설명할 상황은 없었기에 머릿속에 제대로 정리가 되어 있지는 않았다.&lt;/p&gt;

&lt;p&gt;그런데, 회사가 합쳐지면서 기존의 코드를 포크하여 다른 팀에서 사용하는 일이 있었는데, 그 때 왜 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 커밋해놓았냐는 질문을 받았던 것으로 기억한다.&lt;/p&gt;

&lt;p&gt;그 당시에는 인식하고 있던대로 어떻게든 대답했는데, 지금 생각해보니 정리해두어도 나쁘지 않은 내용인 것 같다.&lt;/p&gt;

&lt;p&gt;먼저, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 커밋하지 않아야 하는 이유를 간단히 말하면&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;package.json 및 package-lock.json에 명시된 dependencies들을 다시 다운받아 node_modules를 재구성할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;라는 이유 때문이라고 생각한다. 이 근거를 바탕으로 &lt;strong&gt;“따라서 node_modules를 커밋하는 것은 불필요한 파일을 커밋하는 것이으로, 해서는 안된다.”&lt;/strong&gt; 라고 주장할 수 있겠다.&lt;/p&gt;

&lt;p&gt;하지만, 실제로 일을 하다보니 위 근거에는 숨은 가정이 있다는 것을 알게 된다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;NPM 서버가 정상 작동중일 것&lt;/li&gt;
  &lt;li&gt;Dependencies에 명시된 패키지들이 서버에 올바르게 남아있을 것&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이러한 이유로, 위 가정중 하나라도 깨지면 정상적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 받아올 수 없게 되고, 서버 디플로이가 불가능해지거나 기존에 작성해 둔 툴을 실행시킬 수 없어 다른 사람에게 해당 툴의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 복사해 달라고 요청해야 하는 상황이 발생할 수 있다. 물론 이런 예를 드는 이유는 실제로 있었던 일이기 때문이다.&lt;/p&gt;

&lt;p&gt;디플로이가 불가능해지는 것은 직접 경험하지는 못했지만, 기존에 작성된 툴의 Dependencies 중 하나가 npm 에서 삭제되면서 사용할 수 없게 되는 불상사는 당황스러운 경험이었다.&lt;/p&gt;

&lt;p&gt;전해들은 바로는 기존에 업로드 된 package의 내용도 버전 변경 없이 새로 퍼블리시 되면서 내용이 바뀌어 버리는 상황도 있을 수 있다고 들었던 것 같다. 조금 조사해보니 지금은 unpublish후 다시 publish하면 발생할 수 있는 듯하고, 과거에는 force 옵션을 통해 가능했던 것 같다. &lt;a href=&quot;https://stackoverflow.com/questions/27873515/is-there-a-workaround-for-npm-publish-f&quot;&gt;참고링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;정리하자면,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;package.json 및 package-lock.json에 명시된 dependencies들을 다시 다운받아&lt;strong&gt;야만&lt;/strong&gt; node_modules를 재구성할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;현재 이용하고 있는 node_modules 데이터가 npm 서버에 그대로 남아있다는 보장이 없다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;라고 할 수 있겠다.&lt;/p&gt;

&lt;p&gt;다만, 모든 방식에는 장단점이 있듯 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 커밋해서 사용하는 경우 편의를 위해 임시로 일부 코드를 커스터마이징 해서 커밋해 쓰는 등의 향후 알기 어려운 문제로 이어질 수 있는 행동도 허용하게 되는 문제가 있다고 생각이 든다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;other-posts&quot;&gt;Other Posts&lt;/h3&gt;

&lt;p&gt;작성하고보니 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commiting node_modules&lt;/code&gt;를 키워드로 구글 검색을 하면 나오는 포스트 들이 있었고, 이미 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;를 커밋하는 것에 대한 장/단점이 잘 작성되어 있었다.&lt;/p&gt;

&lt;p&gt;참고: https://flaviocopes.com/should-commit-node-modules-git/&lt;/p&gt;
</description>
        <pubDate>Wed, 18 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/development/2020/03/18/why-we-had-to-commit-node_modules.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/development/2020/03/18/why-we-had-to-commit-node_modules.html</guid>
        
        
        <category>DEVELOPMENT</category>
        
      </item>
    
      <item>
        <title>TU Graz에서 수강한 과목에 대한 리뷰</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/images/tu-graz-alte-campus.jpg&quot; alt=&quot;TU Graz Alte Campus&quot; width=&quot;55%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;tu-graz-과목들의-특징&quot;&gt;TU Graz 과목들의 특징&lt;/h2&gt;
&lt;p&gt;Graz University of Technology (TU Graz)의 보안랩은 &lt;a href=&quot;https://meltdownattack.com/&quot;&gt;Meltdown&lt;/a&gt; 취약점 발견 당시 해당 취약점을 리포트한 팀 중 하나였다. 그 이후로도 &lt;a href=&quot;https://zombieloadattack.com/&quot;&gt;ZombieLoad&lt;/a&gt;와 같은 Side Channel 취약점들을 보고해온 것으로 보인다. 이런 이유때문인지 TU Graz에서는 컴퓨터 보안과 관련된 과목이 세분화되어 다양하게 열렸고, 전체적으로 Side Channel 취약점을 집중적으로 연구하는 편이었던 것 같다.&lt;/p&gt;

&lt;p&gt;학부생을 위해서는 Information Security 과목을 통해 컴퓨터 보안과 관련된 전반적인 지식을 배우고, 대학원 과목으로 Embedded Security (주로 Side Channel 취약점을 다루는 듯), Applied Cryptography, Security Aspects in Software Development등의 보안의 세부적인 영역을 다루는 과목이 열렸다. 우리 학교에서는 커리큘럼상 학부생을 위한 보안 과목은 없고, 대학원에서 조차 컴퓨터 보안에 대해 다루는 과목은 거의 없었던 것 같은데 상당히 대조적인 모습이었다. 최근 우리 학교 컴퓨터공학과 과목에서 AI와 관련된 과목이 많아졌는데, 이처럼 과목 구성을 통해서도 최근 학교에서 집중적으로 연구하는 토픽이 무엇인지 알 수 있는 듯하다.&lt;/p&gt;

&lt;p&gt;TU Graz에서는 Lecture 과목과 Practice 과목이 분리되어 있어서 원한다면 한 쪽만을 수강할 수도 있었다. Lecture 과목에서는 이론적인 정보 전달만을 목적으로 하기 때문에 보통 과제가 나오지 않았고, Practice 과목에서는 실제 구현 및 적용을 목표로 하기 때문에 과제와 실습으로 구성되어 있다.&lt;/p&gt;

&lt;h2 id=&quot;수강한-과목들&quot;&gt;수강한 과목들&lt;/h2&gt;

&lt;p&gt;TU Graz에 있는 동안 나는 아래 세 과목을 수강했다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Information Security (Lecture)&lt;/li&gt;
  &lt;li&gt;Security Aspects in Software Development (Lecture + Practice)&lt;/li&gt;
  &lt;li&gt;Applied Cryptography (Lecture + Practice)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;각-과목에-대한-리뷰&quot;&gt;각 과목에 대한 리뷰&lt;/h2&gt;

&lt;h3 id=&quot;information-security&quot;&gt;Information Security&lt;/h3&gt;

&lt;p&gt;학부생이 듣는 과목으로, Cryptography(암호학)-System Security(BOF, UAF 등)-Network Security(주로 웹) 세 파트로 나누어서 각 파트가 서로 다른 강사에 의해 진행된다. 실습 과목은 듣지 않아서 잘 모르겠지만, Cryptography와 System Security의 경우 CTF 식으로 문제를 풀고 Network Security의 경우 웹 프록시 구현이 과제로 나온 것같다. 들으면 컴퓨터 보안에 대해 어느정도 지식을 얻을 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;security-aspects-in-software-development&quot;&gt;Security Aspects in Software Development&lt;/h3&gt;

&lt;p&gt;석사 대학원생이 듣는 과목으로, System Security에 대해서 집중적으로 다룬다. 학교에서 Side Channel 취약점에 대해 집중적으로 연구하기 때문인지, Meltdown이나 Spectre같은 취약점에 대해서도 어느정도 언급된다. Applied Cryptography에 비해 강의 과목과 연습 과목 간에 싱크가 잘 되지 않는 과목이다. 연습 과목에서 풀어야 하는 문제는 후반부 강의에 나오는 지식을 요구하는데, 과제의 데드라인이 해당 강의 이전 이라거나 하는 부분들이 있었다. 그리고 보안 분야의 특성인지는 모르겠으나 가르쳐 주는 것에 비해서 스스로 공부해야 하는 부분이 훨씬 많다. 과제는 총 2개이며, 첫 번째 과제에서는 CTF 형식으로 21가지 문제를 푸는 것이었고 두 번째 과제는 ELF 파일을 읽어서 Section / Segment를 수정하는 라이브러리를 작성하는 것이었다. 첫 번째 과제의 경우 보안 동아리 PLUS 활동을 성실하게 했다면 어렵지 않은 과제가 될 것이지만, 오랜만에 하는지라 어느 정도 애를 먹었다. 보안 관련 지식이 전무한 상태라면 상당히 어려움이 예상된다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: 수강생 중 Top 3 안에 들게 되면 트로피 느낌의 작은 기념품을 받는다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/tu-graz-sasd-awards.jpg&quot; alt=&quot;SASD Awards Slides&quot; width=&quot;48%&quot; /&gt;
&lt;img src=&quot;/assets/images/tu-graz-iron-ducky.jpg&quot; alt=&quot;Iron Ducky&quot; width=&quot;48%&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;applied-cryptography&quot;&gt;Applied Cryptography&lt;/h3&gt;

&lt;p&gt;컴퓨터 보안의 석사 과정 과목으로, Cryptography 파트를 조금 더 자세하게 배운다. 과목 이름에 맞게 전반적인 Cryptography 지식을 늘릴 수 있고 개인적으로 수업에서 배운 내용을 연습 과목에서 문제를 풀어보면서 이해도를 높이는 구성이 잘 되어 있어 추천하는 과목이다. 수강하게 되면 어느 정도 암호학의 기본 지식을 쌓을 수 있다.&lt;/p&gt;
</description>
        <pubDate>Thu, 12 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2020/03/12/tu-graz-courses-review.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2020/03/12/tu-graz-courses-review.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>Memo] JS Promise resolve 결과로 Promise를 주는 경우 동작</title>
        <description>&lt;p&gt;&lt;strong&gt;요약:&lt;/strong&gt; Promise의 resolve parameter로 새로운 Promise를 주면 기존 Promise가 resolve의 parameter로 전달된 Promise로 갈아 치워진다.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))));&lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`hi, &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; 
   &lt;span class=&quot;nx&quot;&gt;Domain&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;nl&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;_events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;debugDomainError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;_eventsCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;_maxListeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;members&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 다음 콘솔에 찍히는 것은&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; hi, string
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이다. 이와 관련하여 타입 스크립트에서 type notation을 적었을 때&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;와&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;중 올바른 것은 두 번째 것이다.&lt;/p&gt;

&lt;p&gt;이런 패턴으로 Promise를 안쓰다보니 몰랐는데, 오늘 코드 리뷰 하면서 동작이 기대한 것과 다른 부분이 있어서 테스트해 본 결과 알게 되었다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/then/promise#user-content-new-promiseresolver&quot;&gt;then/promise github의 README.md&lt;/a&gt;에 따르면 resolve의 결과로 Promise가 오면 기존 Promise가 파라미터로 전달 된 Promise로 갈아치워 지는 듯 하다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h3 id=&quot;new-promiseresolver&quot;&gt;new Promise(resolver)&lt;/h3&gt;

  &lt;p&gt;This creates and returns a new promise. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolver&lt;/code&gt; must be a function. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolver&lt;/code&gt; function is passed two arguments:&lt;/p&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolve&lt;/code&gt; should be called with a single argument. If it is called with a non-promise value then the promise is fulfilled with that value. If it is called with a promise (A) then the returned promise takes on the state of that new promise (A).&lt;/p&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reject&lt;/code&gt; should be called with a single argument. The returned promise will be rejected with that argument.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 16 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/javascript/2019/07/16/what-if-promise-resolve-with-new-promise.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/javascript/2019/07/16/what-if-promise-resolve-with-new-promise.html</guid>
        
        
        <category>JAVASCRIPT</category>
        
      </item>
    
      <item>
        <title>Today I Suffered From (1) - Unity LPWStr(wchar_t*) marshalling causes memory violation</title>
        <description>&lt;h3 id=&quot;today-i-suffered-from&quot;&gt;Today I Suffered From&lt;/h3&gt;

&lt;p&gt;최근 Windows Store 출시를 위해 Unity WSA로 빌드를 하게 되었고, IL2CPP를 이용한 결과물이 프로젝트로 나온다. 그리고 이를 기반으로 C++ Plugin을 작성하여 결제를 지원하도록 수정중이다.&lt;/p&gt;

&lt;p&gt;Unity에서는 C# 을 사용하는 반면, Plugin에서는 C++을 사용하므로 Plugin의 함수를 호출하거나 return value를 받을 때 C#에서 필연적으로 &lt;a href=&quot;https://en.wikipedia.org/wiki/Marshalling_(computer_science)&quot;&gt;Marshalling&lt;/a&gt;을 하게 되는데, 주로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;(C#) &amp;lt;–&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t *&lt;/code&gt;(C++) 사이의 Marshalling이 빈번하게 일어났다.&lt;/p&gt;

&lt;p&gt;그러던 중, 3336길이를 가지는(= &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t&lt;/code&gt;가 2byte이고, null이 포함되므로 총 1667글자) today-i-suffered-from-1을 C++ Plugin에서 반환하고, C# 코드에서 Marshalling된 string을 사용하려 했더니, Memory Access Violation 에러들이 났다. 그런데 매 번 동일한 패턴이 아니고 여러 군데에서 터지는 문제가 발생했다.&lt;/p&gt;

&lt;p&gt;이상한 것이 기존에도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t *&lt;/code&gt; –&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; 변환은 이미 작성한 다른 코드들에서 문제 없이 동작하고 있었는데, 이 곳에서 문제가 매 번 발생하는 것으로 보아 길이가 특정 길이 이상이면 메모리 관리가 이상해지는 것으로 추정했다.&lt;/p&gt;

&lt;p&gt;일단은 이를 빠르게 수정할 방법은 찾을 수가 없어서, 다른 방법을 찾아보기로 했다. 다른 C++ Plugin에서 아주 긴 문자열도 보낸 기억이 있는데, Unity의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SendMessage&lt;/code&gt;를 이용해 Callback을 부를 때, parameter로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t *&lt;/code&gt;를 Marshalling하는 경우는 문제가 없는 것이 생각나서 일단 그런 식으로 우회해 두었다.&lt;/p&gt;

&lt;p&gt;그래도 일단은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t *&lt;/code&gt;를 return value로 주는 경우가 문제를 일으키는지 확인해보기 위해 이를 테스트 하기 위한 Minimal Unity Project를 만들었다.&lt;/p&gt;

&lt;h3 id=&quot;unity-project-테스트&quot;&gt;Unity Project 테스트&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;실험 환경:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Unity 2018.3.8f1&lt;/li&gt;
  &lt;li&gt;x64&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;먼저, 테스트를 위해 아래와 같이 빈 프로젝트를 만들고 Text UI하나를 놓았다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unity-project-scene-for-marshalling-test.png&quot; alt=&quot;Sample Project Scene for Marshalling Test&quot; title=&quot;Sample Project Scene for Marshalling Test&quot; /&gt;&lt;/p&gt;

&lt;p&gt;그 다음, C++ Plugin에서 받아온 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;을 화면에 보여주도록 만들었다.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Collections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Collections.Generic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;UnityEngine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Runtime.InteropServices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MarshalledStringTester&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MonoBehaviour&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#if UNITY_WSA &amp;amp;&amp;amp; !UNITY_EDITOR
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DllImport&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;__Internal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MarshalAs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UnmanagedType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LPWStr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getMarshalledString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Start is called before the first frame update&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Update is called once per frame&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#if UNITY_WSA &amp;amp;&amp;amp; !UNITY_EDITOR
&lt;/span&gt;        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marshalledString&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getMarshalledString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;GetComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UnityEngine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marshalledString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;C++ Plugin으로는 아래와 같이 길이를 늘려가면서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t *&lt;/code&gt;를 반환하게 만들었다.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;Windows.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toUnityString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srcData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;ULONG&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;ulSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wcsnlen_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;srcData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pwszReturn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CoTaskMemAlloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ulSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// Copy the contents.&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;wcscpy_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pwszReturn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ulSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srcData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pwszReturn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wstring&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;astr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;L&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_stdcall&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMarshalledString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;astr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;astr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;L&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wcout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wcsnlen_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toUnityString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;실행-결과&quot;&gt;실행 결과&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/memory-violation-after-marshalled-string-return-1.png&quot; alt=&quot;Memory Violation After Marshalled String Return 1&quot; title=&quot;Memory Violation After Marshalled String Return 1&quot; /&gt;
&lt;img src=&quot;/assets/images/memory-violation-after-marshalled-string-return-2.png&quot; alt=&quot;Memory Violation After Marshalled String Return 2&quot; title=&quot;Memory Violation After Marshalled String Return 2&quot; /&gt;
&lt;img src=&quot;/assets/images/memory-violation-after-marshalled-string-return-3.png&quot; alt=&quot;Memory Violation After Marshalled String Return 3&quot; title=&quot;Memory Violation After Marshalled String Return 3&quot; /&gt;
&lt;img src=&quot;/assets/images/memory-violation-after-marshalled-string-return-4.png&quot; alt=&quot;Memory Violation After Marshalled String Return 4&quot; title=&quot;Memory Violation After Marshalled String Return 4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;뭔가 실행할 때 마다 다른 곳에서 다양하게 죽는 것을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;정확한 원인은 모르겠지만 Marshaling된 string을 이용할 때 아무튼 메모리가 개판이 되는 것은 확실하다.&lt;/p&gt;

&lt;p&gt;이미 Windows Store 관련 개발로 너무 많은 시간을 끌어 버려서 일단은 되는 방법으로 조치해두고, 시간을 더 투자해서 해결법이나 원인을 제대로 찾지는 못해서 Today I Suffered From(TISF)로 제목을 지었다.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;2019.07.17&lt;/p&gt;

&lt;h3 id=&quot;추가-실험&quot;&gt;추가 실험&lt;/h3&gt;

&lt;p&gt;위 실험을 진행하면서 정확히 어떤 크기의 Input이 Memory Violation을 일으키는지 테스트 해보지 않았다. 그래서 이를 알아내기 위해 아래와 같이 고정된 길이의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t *&lt;/code&gt; 값을 변경해가면서 실행한 후 시간이 지나도 Memory Violation을 일으키지 않는지 확인해 보았다.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;Windows.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toUnityString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srcData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;ULONG&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;ulSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wcsnlen_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;srcData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pwszReturn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CoTaskMemAlloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ulSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// Copy the contents.&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;wcscpy_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pwszReturn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ulSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srcData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pwszReturn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;wchar_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_stdcall&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMarshalledString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toUnityString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;L&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;테스트 결과는 다음과 같다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a - OK&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaa - OK&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - OK&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - OK&lt;/li&gt;
  &lt;li&gt;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - NO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;위 결과 중 마지막 두 개에서 어떤 길이 이상의 문자열이 문제를 일으키는지 확인할 수 있다. 37글자의 a의 경우 OK 38글자의 a의 경우 Memory Violation이 발생했다.&lt;/p&gt;

&lt;p&gt;따라서 이로 부터 추측해볼 때, 37글자를 초과하는 경우 Memory Violation이 발생하는 것으로 보인다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codeblog.jonskeet.uk/2011/04/05/of-memory-and-strings/&quot;&gt;string의 in-memory size에 관한 글&lt;/a&gt;에 따르면 37글자의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;은 x64 환경에서 26 + length * 2 = 100 byte 인 것으로 보인다.&lt;/p&gt;

&lt;p&gt;처음에는 문자열의 길이에 따라 C#에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;이 어느 heap bin에 할당되는지에 따라 문제가 있지 않을까? 라고 의심을 했는데&lt;/p&gt;

&lt;p&gt;100은 대단히 수상한 숫자여서 Unity의 Marshalling 로직에 오류가 있지는 않은지 킹리적 갓심을 해본다.&lt;/p&gt;
</description>
        <pubDate>Mon, 15 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/unity/c++/2019/07/15/today-i-suffered-from-1.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/unity/c++/2019/07/15/today-i-suffered-from-1.html</guid>
        
        
        <category>UNITY</category>
        
        <category>C++</category>
        
      </item>
    
      <item>
        <title>Lessons from confusing between Microsoft Account(MSA) and Office 365 account</title>
        <description>&lt;h3 id=&quot;two-different-types-of-microsoft-accounts&quot;&gt;Two Different Types of Microsoft Accounts&lt;/h3&gt;

&lt;p&gt;Microsoft has two different account types. Microsoft Account(MSA) and Office 365 account.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://tellus-consulting.com/microsoft-account-msa-compared-to-office-365-account/&quot;&gt;this article&lt;/a&gt; explains differences between Microsoft Accounts(MSAs) and Office 365 accounts well.&lt;/p&gt;

&lt;p&gt;In short, there exist two different types of Microsoft accounts: MSA and Office 365, and each account has access to some unique services.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/microsoft-login-with-different-account-types.png&quot; alt=&quot;Login Page of Microsoft&quot; title=&quot;Login Page of Microsoft&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can login with different type of accounts as shwon in the picture above. One with name tag is Office 365 account, and the other one is MSA.&lt;/p&gt;

&lt;p&gt;However, I didn’t know that each account type has own access to different services when I was working on Windows Store payments. To implement payments functionality, I should handle stuffs related to &lt;strong&gt;Partner Center&lt;/strong&gt;(for app submission) and &lt;strong&gt;Azure AD&lt;/strong&gt;(for validating purchase for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows.Services.Store&lt;/code&gt; namespace payments). After I worked on implementing payments functionality, I could draw a brief diagram for Microsoft accounts like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph TD
subgraph MSA
  OneDriveP[OneDrive Personal]
  Outlook[Outlook Email]
  PartnerCenter[Partner Center]
end
subgraph Office365
  OneDriveB[OneDrive Business]
  AzureAD[Azure AD]
  PartnerCenterManager[Partner Center Manager]
end
PartnerCenter--&amp;gt;|grant access|PartnerCenterManager
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Followings are little lessons I learned while working:&lt;/p&gt;

&lt;h3 id=&quot;1-msa-cant-use-azure-ad&quot;&gt;(1) MSA can’t use Azure AD&lt;/h3&gt;

&lt;p&gt;You can’t manage Azuare AD settings if your account is MSA.&lt;/p&gt;

&lt;p&gt;For example, you will see pages with error messages like below if you go to Azure portal with MSA:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/azure-ad-error-message-1-when-account-is-msa.png&quot; alt=&quot;Azure AD Error Message (1)&quot; title=&quot;Azure AD Error Message (1)&quot; /&gt;
&lt;img src=&quot;/assets/images/azure-ad-error-message-2-when-account-is-msa.png&quot; alt=&quot;Azure AD Error Message (2)&quot; title=&quot;Azure AD Error Message (2)&quot; /&gt;
&lt;img src=&quot;/assets/images/azure-ad-error-message-3-when-account-is-msa.png&quot; alt=&quot;Azure AD Error Message (3)&quot; title=&quot;Azure AD Error Message (3)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, the error messages are not descriptive enough. They just show messages like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Unable to complete due to service connection error, please try again later.&lt;/li&gt;
  &lt;li&gt;Unable to get the list of domains. Please try again later.&lt;/li&gt;
  &lt;li&gt;Unable to complete due to service connection error, please try again later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;not something like “Permission Denied”. Even the messages seems to indicate as if it is a temporary problem.&lt;/p&gt;

&lt;p&gt;Fortunately, I also found an error message showing the adequate reason why I can’t use Azure AD:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Access denied&lt;/p&gt;

  &lt;p&gt;You do not have access&lt;/p&gt;

  &lt;p&gt;Looks like you don’t have access to this content. To get access, please contact the owner.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/azure-ad-error-message-4-when-account-is-msa.png&quot; alt=&quot;Azure AD Error Message (4)&quot; title=&quot;Azure AD Error Message (4)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Thanks to the message, finally I could find out that MSA account can’t use Azure AD.&lt;/p&gt;

&lt;h3 id=&quot;2-office-365-account-cant-manage-microsoft-store-app-at-partner-center-by-itself&quot;&gt;(2) Office 365 Account can’t manage Microsoft Store App at Partner Center by itself&lt;/h3&gt;

&lt;p&gt;MSA can’t use Azure AD, but MSA can submit app to Windows Store using Partner Center.&lt;/p&gt;

&lt;p&gt;On the contrary, Office 365 account can’t submit app to Windows Store using Partner Center by itself.&lt;/p&gt;

&lt;p&gt;If you click &lt;em&gt;Get started&lt;/em&gt; at &lt;em&gt;Developer programs &amp;gt; Windows&lt;/em&gt;,&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/developer-program-windows-product.png&quot; alt=&quot;Developer programs &amp;gt; Windows&quot; title=&quot;Developer programs &amp;gt; Windows&quot; /&gt;&lt;/p&gt;

&lt;p&gt;you will see error messages like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/partner-center-error-for-office-365-account.png&quot; alt=&quot;Partner Center Error for Office 365 Account&quot; title=&quot;Partner Center Error for Office 365 Account&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We should notice the first line of the error messages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Sign in with an Azure AD user account that is already associated with a Partner Center account&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Sign in with a Microsoft account that is already associated with a Partner Center account&lt;/li&gt;
  &lt;li&gt;Sign in with a Microsoft account that you’d like to register for a new Partner Center account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inferencing from the first error message, we can expect that the way to associate Azure AD account with Partner Center exists.&lt;/p&gt;

&lt;p&gt;It’s true, see following:&lt;/p&gt;

&lt;h3 id=&quot;3-office-365-account-get-control-to-partner-center-by-msa-account&quot;&gt;(3) Office 365 Account get control to Partner Center by MSA account&lt;/h3&gt;

&lt;p&gt;MSA can allow Office 365 account to manage Partner Center by placing an Office 365 account as manager.&lt;/p&gt;

&lt;p&gt;You can follow &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/publish/associate-azure-ad-with-partner-center&quot;&gt;this document&lt;/a&gt; to achieve this.&lt;/p&gt;

&lt;p&gt;If you complete granting access to Office 365 account, you will see page like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/after-enroll-azure-ad-tenant.png&quot; alt=&quot;Partner Center Tenants Setting Result&quot; title=&quot;Partner Center Tenants Setting Result&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By doing this, you can use Office 365 account instead to manage Partner Center page.&lt;/p&gt;
</description>
        <pubDate>Wed, 03 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/uwp/microsoft/development/2019/07/03/uwp-lessons-from-msa-and-office-365-accounts.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/uwp/microsoft/development/2019/07/03/uwp-lessons-from-msa-and-office-365-accounts.html</guid>
        
        
        <category>UWP</category>
        
        <category>MICROSOFT</category>
        
        <category>DEVELOPMENT</category>
        
      </item>
    
      <item>
        <title>How to add onestore.microsoft.com to Azure AD app manifest identifierUris</title>
        <description>&lt;p&gt;I found many people having difficulty in following &lt;strong&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/monetize/view-and-grant-products-from-a-service&quot;&gt;Manage product entitlements from a service&lt;/a&gt;&lt;/strong&gt; document’s Step 1. 5th instruction to implement uwp payments with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows.Services.Store&lt;/code&gt; namespace, and I was also one of those suffering people.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Add several required audience URIs to your &lt;em&gt;application manifest&lt;/em&gt;. In the left pane, click &lt;strong&gt;Manifest&lt;/strong&gt;. Click &lt;strong&gt;Edit&lt;/strong&gt;, replace the “identifierUris” section with the following text, and then click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;

  &lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;&quot;identifierUris&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://onestore.microsoft.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://onestore.microsoft.com/b2b/keys/create/collections&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://onestore.microsoft.com/b2b/keys/create/purchase&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;problem&quot;&gt;Problem&lt;/h3&gt;

&lt;p&gt;The problem is that every time I replace manifest’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;identifierUris&lt;/code&gt; with the value above, we get an error like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Failed to update WindowsTestApp application. Error detail: The Application ID URI must be from a verified domain within your organisation’s directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The error instructs me to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onestore.microsoft.com&lt;/code&gt; to our verified domain, but adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onestore.microsoft.com&lt;/code&gt; is obviously impossible as I don’t own the domain.&lt;/p&gt;

&lt;p&gt;I found other people submitted the same issues like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;https://github.com/MicrosoftDocs/windows-uwp/issues/1717&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;https://social.msdn.microsoft.com/Forums/en-US/ab849235-e9a0-4676-b810-f58e35248a1f/can-not-save-application-manifest-when-adding-httpsonestoremicrosoftcom-to-identifieruris?forum=windowsstore&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I read replies in the links and searched more but I couldn’t find any working solution.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;Yes, I know the domain should be inside verified domain, but what’s the point is that I cannot!! Stop saying to check domain.&lt;/del&gt;&lt;/p&gt;

&lt;h3 id=&quot;solution&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;After wasting a lot of time, I found a working but strange solution.&lt;/p&gt;

&lt;p&gt;The solution is to &lt;strong&gt;modify manifest using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App registrations (Legacy)&lt;/code&gt; tab&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/app-registrations-tab.png&quot; alt=&quot;App Registrations (Legacy) Tab Image&quot; title=&quot;App Registrations (Legacy) Tab&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you go to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App registrations (Legacy)&lt;/code&gt; tab, you will see a warning message like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;App registrations (Legacy) will be replaced and no longer available starting May 2019. Go to the new and improved App registrations (now Generally Available).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;identifierUris&lt;/code&gt; to the value above, you will see an error message like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Failed to save manifest. Error details: Request_BadRequest&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; It was 2 July 2019, but I could use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App registrations (Legacy)&lt;/code&gt; tab to create or modify app registrations.&lt;/p&gt;

&lt;p&gt;I have no idea why I had to use the already deprecated legacy, but it successfully modified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;identifierUris&lt;/code&gt; to the values involving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://onestore.microsoft.com/b2b/keys/create/collections&lt;/code&gt; eventhough it showed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Request_BadRequest&lt;/code&gt; error message.&lt;/p&gt;

&lt;p&gt;As I had no way to put &lt;strong&gt;https://onestore.microsoft.com/b2b/keys/create/collections&lt;/strong&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;identifierUris&lt;/code&gt;, I couldn’t get Azure AD access token for &lt;strong&gt;https://onestore.microsoft.com/b2b/keys/create/collections&lt;/strong&gt; audience URI. It just showed an error message like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;AADSTS500011: The resource principal named https://onestore.microsoft.com/b2b/keys/create/collections was not found in the tenant named (…). This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, I could get access token for the audience URI after I use the solution above.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;another-solution&quot;&gt;Another Solution&lt;/h3&gt;

&lt;p&gt;https://github.com/MicrosoftDocs/windows-uwp/issues/1717#issuecomment-507577676 suggests another way to solve this problem.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have solve this problem:
Changing following fields to following value in your manifest.&lt;/p&gt;

  &lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;&quot;accessTokenAcceptedVersion&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;identifierUris&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://onestore.microsoft.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://onestore.microsoft.com/b2b/keys/create/collections&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://onestore.microsoft.com/b2b/keys/create/purchase&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;signInAudience&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AzureADMyOrg&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;The “signInAudience” part can solve this problem, and the “accessTokenAcceptedVersion” part can solve the “getCustomerCollectionsIdAsync” return empty problem.
https://stackoverflow.com/a/56848128/1586797&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve not tested the solution above, but there exists another important point to notice.&lt;/p&gt;

&lt;p&gt;After I solved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;identifierUris&lt;/code&gt; problem, I also met &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;getCustomerCollectionsIdAsync&quot; return empty&lt;/code&gt; problem.&lt;/p&gt;

&lt;p&gt;I had no idea to solve the problem, but changing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accessTokenAcceptedVersion&lt;/code&gt; to 1 resolved the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return empty&lt;/code&gt; problem. (previously &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Many people seems to suffer from the same problems, but why don’t Microsoft update documents handling those stuffs?&lt;/p&gt;

&lt;p&gt;I thought Microsoft is one of the best companies that manage documents well, so it is quite disappointing…&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/uwp/microsoft/azure/development/2019/07/02/uwp-how-to-add-onestore-to-identifier-uris.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/uwp/microsoft/azure/development/2019/07/02/uwp-how-to-add-onestore-to-identifier-uris.html</guid>
        
        
        <category>UWP</category>
        
        <category>MICROSOFT</category>
        
        <category>AZURE</category>
        
        <category>DEVELOPMENT</category>
        
      </item>
    
      <item>
        <title>How to build Unity UWP project and bundle into .appxbundle or .appxupload</title>
        <description>&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;

&lt;p&gt;1) Build Unity Project with UWP as build target&lt;/p&gt;

&lt;p&gt;2) Execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget restore &quot;${product_name}.sln&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;3) Repeat &lt;a href=&quot;https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild?view=vs-2017&quot;&gt;MSBuild&lt;/a&gt; for each TARGET_ARCHITECTURE(e.g. x86, x64, ARM) you want to bundle.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Git Bash Command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;/C/Program Files (x86)/Microsoft Visual Studio/2017/Community/MSBuild/15.0/Bin/msbuild.exe&quot; &quot;${product_name}.sln&quot; -p:Platform=&quot;${TARGET_ARCHITECTURE}&quot; -p:Configuration=Master -p:AppxBundle=Never -p:AppxBundlePlatforms=&quot;${TARGET_ARCHITECTURE}&quot; -p:UapAppxPackageBuildMode=&quot;SideloadOnly&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;bundle-into-appxbundle&quot;&gt;Bundle into .appxbundle&lt;/h3&gt;

&lt;p&gt;4) Copy built *.appx into an empty directory.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Git Bash Command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/bin/find &quot;./AppPackages/${product_name}&quot; -maxdepth 2 -name &apos;*.appx&apos; -exec cp -f {} ./${PACKAGE_DIR}/ \\;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;5) Bundle *.appx using &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/appxpkg/make-appx-package--makeappx-exe-&quot;&gt;makeappx.exe&lt;/a&gt;  (&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/packaging/create-app-package-with-makeappx-tool#create-an-app-package&quot;&gt;reference&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Git Bash Command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;/C/Program Files (x86)/Windows Kits/10/bin/x64/makeappx.exe&quot; bundle -d &quot;${PACKAGE_DIR}&quot; -p result.appxbundle&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;6) Sign result.appxbundle using &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe&quot;&gt;signtool.exe&lt;/a&gt; with your keyfile (&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/packaging/sign-app-package-using-signtool&quot;&gt;reference&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Git Bash Command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;/C/Program Files (x86)/Windows Kits/10/bin/x64/signtool.exe&quot; sign -fd SHA256 -a -f &quot;./Your_StoreKey.pfx&quot; result.appxbundle&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;bundle-into-appxupload&quot;&gt;Bundle into .appxupload&lt;/h3&gt;

&lt;p&gt;4) Copy built *.appx and *.appxsym.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Git Bash Command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;/usr/bin/find &quot;./AppPackages/${product_name}&quot; -maxdepth 2 \( -name &apos;*.appx&apos; -o -name &apos;*.appxsym&apos; \) -exec cp -f {} ./ \;&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;5) Zip files into .appxupload file (&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/packaging/packaging-uwp-apps#create-your-app-package-upload-file-manually&quot;&gt;reference&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Git Bash Command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zip result.appxupload *.appx *.appxsym&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;

&lt;p&gt;I recently worked on building Unity UWP project using Jenkins CI. Some functionalities only accessable through GUI are not available options for CI build. Thus, I should build Unity UWP project only by command-line.&lt;/p&gt;

&lt;h3 id=&quot;main-obstacles&quot;&gt;Main Obstacles&lt;/h3&gt;

&lt;p&gt;While I was working on building Unity UWP project, I met some problems that took pretty much time to solve:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Build fails due to dependencies on NuGet Packages&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild?view=vs-2017&quot;&gt;MSBuild&lt;/a&gt; does not support bundling multiple platforms (However, Pacakge Wizard in Visual Studio bundle multiple platforms at once)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First problem occurs due to Unity UWP project’s characteristics.&lt;/p&gt;

&lt;h3 id=&quot;unity-uwp-project-build-process&quot;&gt;Unity UWP project build process&lt;/h3&gt;

&lt;p&gt;Seeing &lt;a href=&quot;https://docs.unity3d.com/Manual/windowsstore-generatedproject-il2cpp.html&quot;&gt;Unity document about UWP build result&lt;/a&gt;, we can modify build result’s main project.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The main project (it name matches your Unity project name). This is the project that will be built into an application package, which may be deployed to a device or uploaded to the Windows Store. Unity will not overwrite this project when built on top of it, so it can be modified freely without the fear of changes becoming lost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Due to the behavior, we can add some native functions and 3rd-party packages like Facebook SDK. Thus I copied the pristine build result and added &lt;a href=&quot;https://github.com/microsoft/winsdkfb&quot;&gt;winsdkfb&lt;/a&gt;(one of NuGet packasges), and native implemenation for push notifications, image load and so on. I put them to source control, and I filtered some unnecessary files like downloaded NuGet packages after reading a &lt;a href=&quot;https://docs.microsoft.com/en-us/nuget/consume-packages/packages-and-source-control&quot;&gt;document&lt;/a&gt;. Then I modified CI system to copy them before build start. Unity will preserve modified project and we can proceed building our custom UWP project.&lt;/p&gt;

&lt;h3 id=&quot;build-failure-by-missing-nuget-package&quot;&gt;Build failure by missing NuGet package&lt;/h3&gt;

&lt;p&gt;However, my custom UWP project failed building project with error message that it cannot find winsdkfb package.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-plain&quot;&gt;Error	C2653	&apos;winsdkfb&apos;: is not a class or namespace name ${project_name}	c:\users\user\desktop\native_project\...
Error	C2871	&apos;winsdkfb&apos;: a namespace with this name does not exist	${project_name}	c:\users\user\desktop\native_project\...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I didn’t think that NuGet dependency error because I turned “Package Restore” option on following &lt;a href=&quot;https://docs.microsoft.com/en-us/nuget/consume-packages/package-restore#migrating-to-automatic-restore&quot;&gt;this document&lt;/a&gt;. Anyway it happened, so I tried to research how to manually restore them. I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msbuild.exe -t:restore&lt;/code&gt;, but It had no effect. I found from the document above that msbuild’s restore only works for packcages managed by PackageReference, but my project used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;packages.config&lt;/code&gt; for packcages management.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;MSBuild&lt;/strong&gt;: use the msbuild -t:restore command, which restores packages packages listed in the project file (PackageReference only). Available only in NuGet 4.x+ and MSBuild 15.1+, which are included with Visual Studio 2017. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget restore&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dotnet restore&lt;/code&gt; both use this command for applicable projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unlike the description that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget restore&lt;/code&gt; uses msbuild restore, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget restore&lt;/code&gt; just worked fine. Build successfuly finished after I execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget restore &quot;${product_name}.sln&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget&lt;/code&gt; is involved in Visual Studio, but not in .exe form, so you need to download it separately. see &lt;a href=&quot;https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools#cli-tools&quot;&gt;this&lt;/a&gt; to install.&lt;/p&gt;

&lt;h3 id=&quot;bundle-multiple-architectures-appx-file&quot;&gt;Bundle multiple architectures’ appx file&lt;/h3&gt;

&lt;p&gt;I wanted build to result in ‘&lt;em&gt;.appxbundle’ or ‘&lt;/em&gt;.appxupload’ file, which involves several appx files like Visual Studio’s Packcage Wizard results in. Thus I executed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;/C/Program Files (x86)/Microsoft Visual Studio/2017/Community/MSBuild/15.0/Bin/msbuild.exe&quot; &quot;${product_name}.sln&quot; -p:Configuration=Debug -p:AppxBundle=Always -p:AppxBundlePlatforms=&quot;x86|x64&quot; -p:UapAppxPackageBuildMode=&quot;SideloadOnly&quot;&lt;/code&gt; with Git, but it failed with error messages:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  LINK : fatal error LNK1104: cannot open file &apos;C:\Users\user\Desktop\NATIVE_PROJECT\build\bin\ARM\Debug\x86\${product_name}\GameAssembly.lib&apos; [C:\Users\user\Desktop\NATIVE_PROJECT\${product_name}\${product_name}.vcxproj]
    20 Warning(s)
    1 Error(s)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I searched something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msbuild bundle multiple platforms&lt;/code&gt; and tried some solutions, but no solution could bundle multiple platforms’ appx only by single execution of msbuild. I ended up concluding no solution for bundling appx with single command exists. Thus I planned to build each appx file and bundle them manually.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Wanted, but impossible
[ MSBuild -&amp;gt; .appxbundle, .appxupload ] ---&amp;gt; DONE!

Changed process
[ MSBuild -&amp;gt; .appx ] * n ---&amp;gt; [ Bundle Manually -&amp;gt; .appxbundle, .appxupload ] ---&amp;gt; DONE!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I executed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msbuild&lt;/code&gt; multiple times to create .appx file for each platforms (x86, x64, ARM). Then I followed &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/packaging/packaging-uwp-apps#create-your-app-package-upload-file-manually&quot;&gt;this document&lt;/a&gt; to create .appxupload file manually. Just copy *.appx and *.appxsym file into the directory, and zip all *.appx and *.appxsym file with result file name ‘something.appxupload’. That was an easy stuff.&lt;/p&gt;

&lt;p&gt;Creating .appxbundle was a little bit harder than .appxupload. After searching internet more, I also found the way to bundle .appx files into .appxbundle file. First, copy all *.appx file into an empty directory. Second, create .appxbundle file using &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/appxpkg/make-appx-package--makeappx-exe-&quot;&gt;makeappx.exe&lt;/a&gt; executable. I executed a command in Git Bash:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/C/Program Files (x86)/Windows Kits/10/bin/x64/makeappx.exe&quot;&lt;/span&gt; bundle &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PACKAGE_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; result.appxbundle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MakeAppx.exe&lt;/code&gt; is bundled with Windows SDK. see &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/packaging/create-app-package-with-makeappx-tool#create-an-app-package&quot;&gt;reference&lt;/a&gt; for detailed instruction.&lt;/p&gt;

&lt;p&gt;Third, sign the .appxbundle with &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe&quot;&gt;signtool.exe&lt;/a&gt;. You should use SHA256 for sign algorithm by this reason:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When using &lt;strong&gt;SignTool&lt;/strong&gt; to sign your app package or bundle, the hash algorithm used in &lt;strong&gt;SignTool&lt;/strong&gt; must be the same algorithm you used to package your app. For example, if you used &lt;strong&gt;MakeAppx.exe&lt;/strong&gt; to create your app package with the default settings, you must specify SHA256 when using &lt;strong&gt;SignTool&lt;/strong&gt; since that’s the default algorithm used by &lt;strong&gt;MakeAppx.exe&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With your certificate file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Your_StoreKey.pfx&lt;/code&gt; specified in project’s .appmanifest file for code signing, you may run command in Git Bash like:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/C/Program Files (x86)/Windows Kits/10/bin/x64/signtool.exe&quot;&lt;/span&gt; sign &lt;span class=&quot;nt&quot;&gt;-fd&lt;/span&gt; SHA256 &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./Your_StoreKey.pfx&quot;&lt;/span&gt; result.appxbundle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SignTool.exe&lt;/code&gt; is also bundled with Windows SDK. see &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/uwp/packaging/sign-app-package-using-signtool&quot;&gt;reference&lt;/a&gt; for detailed instruction.&lt;/p&gt;
</description>
        <pubDate>Sun, 23 Jun 2019 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/uwp/microsoft/windows/development/ci/cd/2019/06/23/how-to-build-unity-uwp-using-command-line.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/uwp/microsoft/windows/development/ci/cd/2019/06/23/how-to-build-unity-uwp-using-command-line.html</guid>
        
        
        <category>UWP</category>
        
        <category>MICROSOFT</category>
        
        <category>WINDOWS</category>
        
        <category>DEVELOPMENT</category>
        
        <category>CI/CD</category>
        
      </item>
    
      <item>
        <title>내가 Typescript의 Enum을 쓰지 않는 이유</title>
        <description>&lt;p&gt;회사에서 기존 자바스크립트던 코드를 타입스크립트로 포팅한 이후로, 꾸준히 타입을 써가면서 타입 시스템의 혜택을 보기 위해 바꾸어 나가고 있다.&lt;/p&gt;

&lt;p&gt;기존 코드에는 아래와 같이 오브젝트의 Key-Value로 enum을 시뮬레이션 해서 사용하고 있었다.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고 이를 이제 Typescript 형태로 바꾸자면, 이를 다음과 같이 enum으로 바꿀 수 있겠지만 나는 이를 두 가지 이유로 선호하지 않는다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;COIN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;GEM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;SWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;1-typescript의-enum은-number-타입과-서로-assignable한-관계에-있다&quot;&gt;(1) Typescript의 enum은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; 타입과 서로 assignable한 관계에 있다&lt;/h3&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;FIFI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;FOFO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;aa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FIFI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FIFI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드는 컴파일 에러를 일으키지 않는다. 따라서 임의의 숫자를 넣는 등 valid한 enum값이 아니어도 타입 에러로 처리되지 않는다. 이러한 동작이 굉장히 의아할 수 있는데, 그래서 그 만큼 &lt;a href=&quot;https://github.com/microsoft/TypeScript/issues/26362&quot;&gt;Typescript Github Issue&lt;/a&gt;에서도 여러 중복 이슈가 올라올 만큼 꽤나 핫한 주제였던 것 같다. 결론만 말하자면 Flag Enum(bit operator를 이용해서 여러 enum을 동시에 표현. 예를 들면 3은 위 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fire&lt;/code&gt; enum에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fire.FIFO | Fire.FOFO&lt;/code&gt;가 된다.)을 지원하기 위해 어쩔수 없이 허용된 동작인듯 하다. 개인적으로는 굉장히 마음에 들지 않는다.&lt;/p&gt;

&lt;p&gt;다만 그렇다고 해서 enum이 number와 차이점을 가지지 않는 것은 아니다. enum과 number 사이에는 assignable한 관계가 있지만, 서로 다른 종류의 enum 사이에서는 assignable하지 않다. 예를 들면 아래와 같은 코드는 타입 에러를 일으킨다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;FIFI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;FOFO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Water&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;WIWI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;WOWO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;aa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Water&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;WIWI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error!&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FIFI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Water&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;WIWI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;물론 누군가는 이러한 flag적 특성을 장점으로 볼 수도 있겠지만, 기존의 js코드에서 number를 bit operator를 이용한 flag로서 활용하는 형태를 전혀 사용하지 않았고 기본적으로 floating point number와 integer간의 구분이 없는 js의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; 타입에 이와 같은 패턴을 사용하는게 무슨 의미인가 싶다. 대부분의 경우 여러 옵션들의 여부를 표기하기 위해서 아래와 같이 object를 이용해서 사용하지, bit flag를 이용해서 활용할까?&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;IRequestOption&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;encrypted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;concurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;따라서 개인적으로 이러한 Typescript enum의 특성은 명백히 &lt;strong&gt;단점&lt;/strong&gt;이라고 생각한다.&lt;/p&gt;

&lt;h3 id=&quot;2-number-enum은-reverse-map을-가진다&quot;&gt;(2) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; enum은 reverse map을 가진다&lt;/h3&gt;

&lt;p&gt;reverse map이 있으면 더 좋은 것 아니냐고 할 수 있지만, 원래 코드에서 아래와 같은 패턴이 자주 사용되고 있었기 때문에 기존 enum 시뮬레이션들을 Typescript enum으로 바꾸는데 장애가 있었다.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Fire&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;FIFI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;FOFO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 경우&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-plain&quot;&gt;FIFI
FOFO
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;라는 결과가 나오게 될 것이다.&lt;/p&gt;

&lt;p&gt;하지만 위의 Fire를 앞선 enum으로 바꾸는 경우, 아래 와 같은 결과가 나타난다.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-plain&quot;&gt;1
2
FIFI
FOFO
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;그래서 오브젝트에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for ... in&lt;/code&gt; 구문을 써서 key iteration 하는 패턴으로 코드를 작성해온 팀에서 enum을 사용한다면 의도치 않게 버그를 발생 시킬 위험이 농후해 보였고, 그래서 기존의 enum 시뮬레이션을 Typescript의 enum으로 전환하지 않았다.&lt;/p&gt;

&lt;p&gt;또한, 앞서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; enum이 reverse map을 가진다고 했는데 이는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; enum의 경우 reverse map을 가지지 않기 때문이다.&lt;/p&gt;

&lt;p&gt;즉, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;을 value로 가지는 enum의 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for .. in&lt;/code&gt; 패턴을 그대로 활용 할 수 있다.&lt;/p&gt;

&lt;p&gt;하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; enum이냐 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; enum이냐에 따라 달라지는 일관성 없는 동작은 오히려 실수를 일으키기 쉽게 하며, 결국 의도치 않은 버그로 이어지게 만드는 나쁜 특성이라고 생각한다.&lt;/p&gt;

&lt;p&gt;또한 web page처럼 human readable한 표현을 위해 key를 이용하는 것이 중요한 경우를 제외하면 logic 구현 및 DB 저장에 value를 활용하지, key를 이용하는 경우는 드물다. 때문에 reverse map의 활용도는 더더욱 떨어진다.&lt;/p&gt;

&lt;h3 id=&quot;enum의-장점은-살리고-단점을-최소화-하는-대안&quot;&gt;enum의 장점은 살리고, 단점을 최소화 하는 대안&lt;/h3&gt;

&lt;p&gt;하지만 기존의 enum 시뮬레이션을 그대로 사용하는 경우, 서로 다른 enum간에 assignable하지 않은 특성을 가지지 못한다. 그래서 우리는 &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/enums.html#const-enums&quot;&gt;&lt;strong&gt;const enum&lt;/strong&gt;&lt;/a&gt; 사용을 고려해 보았다. const enum으로 생성된 enum은 오브젝트가 아니기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for .. in&lt;/code&gt; 구문에 활용할 수 없어 잘못된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for .. in&lt;/code&gt; 사용을 방지할 수 있다. 또한 기존 enum과 동일하게 서로 다른 enum type에 대해 assignable하지 않은 장점을 동일하게 지닌다. 따라서 key iteration이 필요 없는 경우에는 const enum을 이용해 작성하고, key iteration이 필요한 경우는 기존의 enum 시뮬레이션의 형태로 코드를 작성하기로 했다.&lt;/p&gt;

&lt;p&gt;하지만 const enum을 사용한다는 것은 결국 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for .. in&lt;/code&gt;의 잘못된 사용을 방지한다는 의미로 볼 수 있지만 결국 이는 key iteration의 &lt;strong&gt;불가능&lt;/strong&gt;을 나타낸다고 볼 수도 있고, 기존 enum의 문제점인 number와 서로 assignable한 관계에 있다는 그대로 가진다.&lt;/p&gt;

&lt;h3 id=&quot;개선된-enum-시뮬레이션-활용법&quot;&gt;개선된 enum 시뮬레이션 활용법&lt;/h3&gt;

&lt;p&gt;누군가는 아래처럼 enum을 표현하여 사용하면 결국 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for .. in&lt;/code&gt; 패턴을 이용한 key iteration 사용에 제약이 없는 것을 제외하고 어떤 이득이 있냐고 생각할 수도 있겠다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;또한 어떤 사람은 discriminated union에 이용하기위해 enum이 필요하지 않냐고 주장할 수 있지만, 기존의 javascript식 enum에서도 적절히 타입을 써주면 discriminated union을 위한 enum처럼 활용할 수도 있다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위와 같이 기존 값을 복사하여 그대로 type notation으로 활용하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_TYPE.COIN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_TYPE.GEM&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_TYPE.SWORD&lt;/code&gt; 각각이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt;가 아니라 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt; 타입으로 취급되면서 discriminated union에 사용할 수 있다.&lt;/p&gt;

&lt;p&gt;하지만 위의 notation이 굉장히 이상하게 보일 수 있다. 그리고 이러한 형식으로 타입을 표기하는 경우가 꽤나 있었는지 Typescript 3.4부터 &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const assertion&lt;/code&gt;&lt;/a&gt;이라는 기능이 생겼다. 그래서 이제 아래와 같이 훨씬 간결하게 위와 동일하게 타입을 작성할 수 있다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;as const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TValues&amp;lt;T&amp;gt;&lt;/code&gt; 같은 타입을 선언해서 사용하면 적어도 enum 시뮬레이션의 범위를 벗어나는 숫자는 대입할 수 없게 방지할 수 있다. 또한, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; 타입은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TValues&amp;lt;T&amp;gt;&lt;/code&gt;를 이용해 시뮬레이션한 enum 타입에 대입할 수 없게 된다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;as const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error!&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;즉, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for .. in&lt;/code&gt; 패턴을 이용한 key iteration의 용이성 외에도 기존 enum이 가지던 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; 타입의 값을 대입할 수 있다는 문제점을 해소할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;개선된-enum-시뮬레이션-활용의-한계&quot;&gt;개선된 enum 시뮬레이션 활용의 한계&lt;/h3&gt;

&lt;p&gt;물론, 개선된 enum 시뮬레이션에도 한계는 분명히 존재하며, 결국 이는 Typescript enum이 아니기 때문에 Typescript enum이 가지는 장점을 가지지 못했다.&lt;/p&gt;

&lt;h4 id=&quot;서로-다른-enum간의-대입-관계가-성립할-수-있다&quot;&gt;서로 다른 enum간의 대입 관계가 성립할 수 있다.&lt;/h4&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;as const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CURRENCY_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;BTC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ETH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;XRP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;as const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currencyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CURRENCY_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CURRENCY_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BTC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;currencyType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;currencyType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이렇게 시뮬레이션 한 enum은 결국 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_TYPE.COIN&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CURRENCY_TYPE.BTC&lt;/code&gt;모두 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; 이라는 타입을 가지게 되고, 타입 시스템은 이 둘을 동일한 타입으로 인식하게 되므로 서로 assignable한 관계를 가지게 된다. 즉, typescript enum이 가지는 “&lt;em&gt;서로 다른 enum간의 assignable 관계가 성립하지 않음&lt;/em&gt;“이라는 특징을 여전히 가지지 못한다.&lt;/p&gt;

&lt;h4 id=&quot;type-notation-작성시-가독성이-떨어짐&quot;&gt;Type notation 작성시 가독성이 떨어짐&lt;/h4&gt;

&lt;p&gt;enum을 시뮬레이션하게 되는 경우, 기존 js object를 그대로 활용하는 것이 되므로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typeof&lt;/code&gt; 사용이 불가피하며, enum의 값들에 대한 타입 표현으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TValues&amp;lt;T&amp;gt;&lt;/code&gt;와 같은 것을 사용해야 한다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;COIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;GEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;SWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;as const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ITEM_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ItemType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;COIN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;GEM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;SWROD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itemType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ItemType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위처럼, const enum을 활용한 쪽이 훨씬 간결하게 표현이 가능하다.&lt;/p&gt;

&lt;p&gt;이렇듯 Typescript enum을 활용하는 것과 enum을 시뮬레이션 하는 것은 각각의 장단점이 있으며, 코드 스타일에 따라 취사 선택하면 될 것 같다.&lt;/p&gt;
</description>
        <pubDate>Wed, 24 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/javascript/typescript/programming/2019/04/24/why-I-avoid-typescript-enum.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/javascript/typescript/programming/2019/04/24/why-I-avoid-typescript-enum.html</guid>
        
        
        <category>JAVASCRIPT</category>
        
        <category>TYPESCRIPT</category>
        
        <category>PROGRAMMING</category>
        
      </item>
    
      <item>
        <title>Video Poker RTP 계산기 구현에 대한 기록</title>
        <description>&lt;p&gt;회사에서 주어진 일 중 하나로 비디오 포커에 대한 Return To Player(이하 RTP)계산을 맡은적이 있다.&lt;/p&gt;

&lt;p&gt;RTP는 유저가 한 게임에 1의 금액을 투입했을 때 얻을 수 있는 평균 기대 보상량이라고 보면 된다.&lt;/p&gt;

&lt;p&gt;일반적인 슬롯 머신의 경우 유저가 할 수 있는 동작은 그저 배팅 금액을 정하고 스핀을 돌리는 것 뿐이기에 고정된 RTP값을 가진다.&lt;/p&gt;

&lt;p&gt;하지만 비디오 포커의 경우 유저의 선택에 따라서 달라지기 때문에, 유저가 RTP를 최대화시키는 플레이를 한다고 가정하고 계산하기로 결정했다.&lt;/p&gt;

&lt;p&gt;처음에는 기본적인 포커 룰도 알지 못해서 일의 시작은 포커 룰을 알아가는 것부터 시작되었다.&lt;/p&gt;

&lt;p&gt;물론 포커룰을 익히는 것은 그리 오래 걸리지 않았지만, 이 일의 가장 큰 문제는 유저가 RTP를 최대화시키는 플레이를 어떻게 아냐는 것이었다.&lt;/p&gt;

&lt;p&gt;처음에는 아무 생각없이 brute force를 통해 이상적인 카드 교환을 구현했지만, 너무 느려서 곧장 폐기 되었다.&lt;/p&gt;

&lt;p&gt;여러 문서를 봐가면서 최종적으로는 &lt;a href=&quot;https://wizardofodds.com/games/video-poker/methodology/&quot;&gt;Wizard of Odds - My Methodology for Video Poker Analysis&lt;/a&gt;의 글에서 소개하는 구현 알고리즘을 그대로 구현했다.&lt;/p&gt;

&lt;p&gt;구현 조건 중에는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;임의의 족보(ex: 4 Spade Aces)를 포함하여 계산 가능해야 함&lt;/code&gt;도 있었기 때문에, &lt;a href=&quot;https://arxiv.org/pdf/1602.04171.pdf&quot;&gt;문양의 구분이 없는 족보만 존재하는 경우 컴퓨팅 타임을 약 95% 줄이는 방법&lt;/a&gt;은 적용하지 않았다. &lt;a href=&quot;https://wizardofodds.com/games/video-poker/methodology/&quot;&gt;Wizard of Odds - My Methodology for Video Poker Analysis&lt;/a&gt;에서도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;To cut down the running time to a few days you can avoid analyzing similar hands on the deal.  ... the number of different kinds of starting hands can be cut from 2,598,960 to 134,459.&lt;/code&gt; 라고 소개하고 있다.&lt;/p&gt;

&lt;p&gt;결과물을 보고 싶은 사람이 있을지는 잘모르겠지만, 위 과정을 거쳐서 만든 Video Poker RTP Calculator는 &lt;a href=&quot;https://github.com/MoonCha/video-poker-calculator&quot;&gt;GitHub Repository&lt;/a&gt;에 올려두었다. 코드가 뒤죽박죽 섞여 어지러운 상태지만, 시간이 나면 정리해두려고 한다.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;참고한 페이지의 설명이 생각보다 자세하게는 안되어 있어서(카드 패를 버린 후 나올 수 있는 경우를 계산하는 부분, Step 5 ~ Step 9) 고민하다가 생각을 수식으로 표현하면 나오는 부분을 노트해 두었는데, 아마 맞을 것 같긴 하지만 다음에 할 일이 없으면 증명해 봐야 할 것 같다.&lt;/p&gt;

\[\binom{m}{n} = \sum_{k=0}^{n} (-1)^k \binom{n}{k} \binom{m+n-k}{n-k}\]

&lt;blockquote&gt;
  &lt;p&gt;for this case, m = 47, n = discarded card amount, which means hand result should have case_count of combination(47, discardedCardAmount)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://www.wolframalpha.com/input/?i=summation+of+(((-1)%5Ek)+*+(n+choose+k)+*+((m%2Bn-k)+choose+m))+from+k+%3D+0+to+n&quot;&gt;위 식을 Wolfram Alpha에 넣어본 결과&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;식이 나온 논리의 흐름은 다음과 같다.&lt;/p&gt;

&lt;p&gt;52장의 덱에서 5장을 뽑은 후 이 중 $n$장의 특정 카드를 다시 뽑은 카드와 교환하는 경우의 수는 $\binom{47}{n}$이다. 그리고 이는 교환하지 않는 $5-n$장을 제외하고 남은 $52-(5-n) = 47+n$장에서 $n$장을 다시 뽑을 때 나올 수 있는 경우에서 $n$장의 특정 카드가 한 장이라도 포함된 경우를 제외한 것과 동일하므로, 그 경우의 수도 동일하다. 이 경우 $47+n$장에서 $n$장을 다시 뽑는 경우 나올 수 있는 결과를 집합 $S$로 표현하고, 교환되는 카드($x_{1}, x_{2}, …, x_{n}$)가 포함된 경우를 집합 $X_{1}, X_{2}, …, X_{n}$으로 나타내면, $S - (X_{1} \cup X_{2} \cup … \cup X_{n})$이 된다. 그리고 $S \supset (X_{1} \cup X_{2} \cup … \cup X_{n})$ 이므로 $\mid S - (X_{1} \cup X_{2} \cup … \cup X_{n})\mid = \mid S \mid -\mid X_{1} \cup X_{2} \cup … \cup X_{n}\mid$ 그리고 &lt;a href=&quot;https://math.stackexchange.com/questions/2038147/equation-for-cardinality-of-the-union-of-n-sets&quot;&gt;합집합의 cardinality를 교집합들의 cardinality를 이용하여 표현하고&lt;/a&gt;, 47을 m으로 바꾸면 대충 위와 같은 식이 나온다.&lt;/p&gt;

&lt;p&gt;이것이 적용된 것은 아래 코드에 해당하는 부분이다.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;nf&quot;&gt;getPossibleOutcomeOfHoldingCards&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;origCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TCard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;holdingCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TCard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;IExpectedOutcome&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* \binom{m}{n} = \sum_{k=0}^{n} (-1)^k \binom{n}{k} \binom{m+n-k}{n-k} */&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// for this case, m = 47, n = discarded card amount, which means hand result should have case_count of combination(47, discardedCardAmount)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// WARNING: formula above &amp;amp; this logic is not proved yet!&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expectedOutcome&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getExpectedOutcomeFromDiscardValueArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;holdingCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expectedOutcomeWithDiscard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;IExpectedOutcome&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;case_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expectedOutcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;case_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expectedOutcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;discardedCardList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;origCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;function &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;card&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;holdingCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;card&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;discardedCardListSubset&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;subsetsWithoutEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;discardedCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;impossibleHand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;holdingCardList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;discardedCardListSubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;impossibleHandResult&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getExpectedOutcomeFromDiscardValueArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;impossibleHand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;discardedCardListSubset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;mergeBySubtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;expectedOutcomeWithDiscard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;impossibleHandResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;mergeByAdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;expectedOutcomeWithDiscard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;impossibleHandResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expectedOutcomeWithDiscard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 23 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/math/video_poker/2018/11/23/poker-rtp-calculation.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/math/video_poker/2018/11/23/poker-rtp-calculation.html</guid>
        
        
        <category>MISC</category>
        
        <category>MATH</category>
        
        <category>VIDEO_POKER</category>
        
      </item>
    
      <item>
        <title>갑자기 생각난, 쉬워 보이지만, 내겐 너무 어려웠던 그런 수학 문제</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;주사위를 6이 한 번 나올때 까지 던지면 평균적으로 몇 번을 던져야 할까?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;아마 나를 포함한 많은 사람들이 ‘6번 던지면 한 번 꼴로 나오니까 6번이겠다.’ 라고 말하리라 생각한다.&lt;/p&gt;

&lt;p&gt;그렇다면 다음은 어떨까?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;주사위를 6이 두 번 나올떄 까지 던지면 평균적으로 몇 번을 던져야 할까?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;그렇다면 마찬가지로 12번이겠다.&lt;/p&gt;

&lt;p&gt;하지만, 안타깝게도 이 문제를 처음 마주했을 때는 이러한 사고의 흐름이 이루어지지 않았다.
중학교 영재원 시험인지 뭐인지는 정확히 기억하지 못하지만 어린 시절의 시험 문제였던 이를 제대로 풀어내지 못해 좋지 않은 기억으로 남아있다.&lt;/p&gt;

&lt;p&gt;일단 먼저 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6번 던지면 한 번 꼴로 나오니까 6번이다.&lt;/code&gt; 같은 직관에 의존하지 않고고 한 번 나올때까지 던지면 평균적으로 몇 번 던져야 하는지를 생각해보자.&lt;/p&gt;

&lt;p&gt;$k$번째 던졌을 때 6이 나오고, 그 전까지는 모두 6이 아닌 것이 나올 확률이 $(1 - \frac{1}{6})^{k-1}(\frac{1}{6})$이고, 1번 부터 $n$회 까지 시도할 수 있고 $n$은 무한히 커질 수 있으므로&lt;/p&gt;

\[\lim_{n\rightarrow \infty}{\sum_{k=1}^{n}{k(1 - \frac{1}{6})^{k-1}(\frac{1}{6})}}\]

&lt;p&gt;고등학교 수학에서 멱급수를 처음 배우면 나오는 기본적인 문제로, 고등학교 수학을 적당히 이수했다면 풀 수 있다.&lt;/p&gt;

&lt;p&gt;그리고 이어서 두 번 나올때 까지 던지는 문제를 같은 방법으로 풀어보면, 아래와 같은 과정을 거친다.&lt;/p&gt;

&lt;p&gt;먼저, 주사위를 한 번 더져서 6이 나올 확률은 $\frac{1}{6}$이다. 그리고 주사위 던지기를 $k$회 시도했을 때, 마지막을 시도를 제외하고 1번 성공하고 $k-2$번 실패하는 경우는 $(\frac{1}{6})^{1}(1 - \frac{1}{6})^{k-2}$이고, $\binom{k-1}{1}$가지 존재하므로 그 확률은 $(\frac{1}{6})^{1}(1 - \frac{1}{6})^{k-2}\binom{k-1}{1}$이다. 그리고 마지막이 성공일 확률은 $\frac{1}{6}$이다. 즉, $k$번 째 시도에서 6이 2번째로 나올 확률은 $(\frac{1}{6})^{1}(1 - \frac{1}{6})^{k-2}\binom{k-1}{1}(\frac{1}{6})$이다.&lt;/p&gt;

&lt;p&gt;그리고 우리가 시도해야 하는 횟수는 최소 2회부터 $n$회까지이고, 이때 $n$은 무한히 커질 수 있으므로 평균적으로 던져야 하는 횟수를 구하려면 아래 급수를 풀어내야 한다.&lt;/p&gt;

\[\lim_{n\rightarrow \infty}{\sum_{k=2}^{n}{k(\frac{1}{6})^{1}(1 - \frac{1}{6})^{k-2}\binom{k-1}{1}(\frac{1}{6})}}\]

&lt;p&gt;그래도 여기 까지는 고등학교 수학을 잘 익혔다면 풀 수 있는 멱급수 문제이다. 물론 다소 높은 난이도로 등장하기는 한다. 그리고 이를 풀면 예상처럼 12가 나온다.&lt;/p&gt;

&lt;p&gt;그런데 알다시피 두 번이 아니라 세 번만 되어도 깡으로 풀기에는 답이 없는 문제가 되어간다.&lt;/p&gt;

&lt;p&gt;이 문제를 일반화 시키면&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;어떤 시도를 해서 성공할 확률이 $a$일 때, $b$ 번 성공할 때까지 시도를 하면 평균적으로 몇 번을 시도해야할까?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;가 되고, 앞서 푼 것과 마찬가지로 식을 세우면 아래와 같다.&lt;/p&gt;

\[\lim_{n\rightarrow \infty}{\sum_{k=b}^{n}{k(a)^{b-1}(1 - a)^{k-b}\binom{k-1}{b-1}(a)}}\]

&lt;p&gt;그리고 이를 모든 공대생의 희망인 &lt;a href=&quot;https://www.wolframalpha.com/input/?i=Sum%5Bk+a%5E(b+-+1)+(1+-+a)%5E(k+-+b)+Binomial%5Bk+-+1,+b+-+1%5D+a,+%7Bk,+b,+Infinity%7D%5D&quot;&gt;울프람 알파님의 힘&lt;/a&gt;을 빌려풀면 직관적으로 생각했을 때 나오는 간단한 결과($\frac{b}{a}$)로 바뀐다. (어떻게 푸는지는 대학 수학을 제대로 공부 안해서 모르겠다)&lt;/p&gt;

&lt;p&gt;여기서 의문점은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;주사위를 6이 2번 나올때 까지 던지면, 평균적으로 몇 번 던져야 할까?&lt;/code&gt;라는 문제의 정석 풀이가 위와 같다면 아직 고등학교 수학을 제대로 않았을 어린 나에게 지나치게 어려운 문제가 아니었나 하는 것이다. 사실 멍청한 내겐 지금도 버겁다.&lt;/p&gt;

&lt;p&gt;그래서 생각한 것은, 분명히 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6번 던지면 한 번 꼴로 나오니까, 12번이다.&lt;/code&gt; 같은 직관에 의존하지도 않고 다소 복잡한 계산을 하지 않아도 되는 쉬운 풀이가 있을거라는 생각이 든다.&lt;/p&gt;

&lt;p&gt;$\frac{b}{a}$로 이어지는 간단한 결과를 구하기 위해 저정도까지 해야하는걸까?&lt;/p&gt;

&lt;p&gt;그러니까 다른 풀이를 누군가 좀 알려줬으면 좋겠다.&lt;/p&gt;

&lt;p&gt;나의 멍청함을 구제해 주었으면 좋겠다.&lt;/p&gt;

&lt;p&gt;누군가 이 글을 봤다면 도와주세요.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;20181122-추가&quot;&gt;2018.11.22 추가&lt;/h2&gt;

&lt;p&gt;며칠 전 같은 병특 회사에서 근무하고 있는 대학 친구에게 물어본 결과, 새로운 관점의 풀이를 얻어 막힌게 조금은 뚫린 기분이 들었다.&lt;/p&gt;

&lt;p&gt;한편으로는 생각해보면 통계를 배운 사람으로서 당연히 연상할 수 있어야 하는 내용인데, 이를 떠올릴 수 없었던 것을 보면 대학에 들어와서는 수학이나 통계를 너무나 챙기지 않았다는게 실감난다. 고등학교 때까지는 수학을 가장 잘하는 학문이라고 생각했는데, 언제 이렇게 됐을까 갑자기 한심함을 느낀다.&lt;/p&gt;

&lt;p&gt;아무튼 이 문제를 이산 확률 분포와 연관지어 생각하면, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;이항 분포(Binomial Distribution)&lt;/code&gt;에 대한 문제로 접근할 수 있다. 이야기 도중에는 푸아송 분포(Poisson Distribution)나 이항 분포의 일반화 형태인 다항 분포(Multinomial Distribution)가 언급됐지만, 굳이 여기까지는 갈 필요가 없는 듯 하다.&lt;/p&gt;

&lt;p&gt;이항 분포는 성공할 확률이 $p$인 일의 $n$번의 시도 중 $k$번 성공할 확률($\binom{n}{k}p^k(1-p)^{n-k}$)에 대한 분포이고, 그 기댓값은 $n$번의 시도를 하면 평균 $k$번 성공한다는 의미가 된다. 따라서 이항 분포의 기댓값($\mu = np$)에서 $\mu = 횟수, p = \frac{1}{6}$을 만족하는 $n$을 찾으면 된다. 기댓값 식에 대한 &lt;a href=&quot;https://en.wikipedia.org/wiki/Binomial_distribution#Mean&quot;&gt;증명&lt;/a&gt;을 포함하더라도 처음 시도한 접근 방식 보다는 훨씬 간단한 접근인 듯 하다.&lt;/p&gt;

</description>
        <pubDate>Tue, 16 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/math/2018/10/16/hard-math-problem-when-young.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/math/2018/10/16/hard-math-problem-when-young.html</guid>
        
        
        <category>MISC</category>
        
        <category>MATH</category>
        
      </item>
    
      <item>
        <title>웹 커뮤니티 자동 출석기 개발 일지 (1)</title>
        <description>&lt;p&gt;최근 남는 시간에 프로그래밍 연습도 하는 겸, 평소에 어느 정도 필요했던 것을 만들어 보기로 했다.
연습을 위해 별로 필요도 없는걸 만드는건 흥미가 살지 않아서 오래 가지 않았기 때문에, 실제로 사용할 만한 것을 생각해보았다.&lt;/p&gt;

&lt;p&gt;평소에 들어가는 사이트로 &lt;a href=&quot;https://coinpan.com&quot;&gt;코인판&lt;/a&gt;이 있는데, 최근에는 암호화폐 가격확인과 핫이슈 확인 정도를 위해 종종 방문하고 있다.&lt;/p&gt;

&lt;p&gt;그리고 방문하면 매일 출석 도장을 찍을 수 있는데, 레벨업에 필요한 포인트를 준다.&lt;/p&gt;

&lt;p&gt;레벨업을 하면 뭐가 좋으냐? 일단 겉으로 드러나는 혜택은 높아지면 VIP게시판에 접근할 수 있다고 한다. 혹은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ㅉㅉ 렙도 낮은 코린이가&lt;/code&gt;라는 말을 시전할 수 있을지도 모르겠다.&lt;/p&gt;

&lt;p&gt;그런데 뭐 사실 결국 큰 의미는 없다.&lt;/p&gt;

&lt;p&gt;그래도 이것보다 의미 있는 것은 더더욱 없는 듯하여 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;코인판 자동 출석기&lt;/code&gt;로 주제를 정했다.&lt;/p&gt;

&lt;p&gt;그리고 &lt;a href=&quot;https://github.com/GoogleChrome/puppeteer&quot;&gt;puppeteer&lt;/a&gt;라는 쓰기 편한 headless chrome을 쓰기로 하고, 이에 따라 Typescript로 개발했다.&lt;/p&gt;

&lt;p&gt;지금 생각해보니 최근 회사에서 Typescript만 써서 Python쓸 일이 잘 없는데, Python도 연습하는 겸 Python-Selenium으로 할 걸 그랬나 싶기도 하다.&lt;/p&gt;

&lt;p&gt;뭐 어찌 되었든 코인판을 짜고 나니, 나는 인벤도 자주 접속한다는 사실을 발견했고, 인벤에서 매일 출석하고 이니 모아서 경품 응모하는게 훨씬 유용해 보였다.&lt;/p&gt;

&lt;p&gt;그래서 프로젝트 이름을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;자동 출석기&lt;/code&gt;로 변경하고 인벤 자동 로그인 + 출석 + 주간 게임 투표를 하는 기능도 추가했다.&lt;/p&gt;

&lt;p&gt;이렇게 된 김에 다른 유용한 여러 사이트 자동 출석도 넣고, 코인 랜딩봇처럼 웹 페이지로 잘 돌아가고 있는지 로그 확인할 수 있게 만드는 것도 괜찮을 것 같다.&lt;/p&gt;

&lt;p&gt;라고 생각하던 도중, Ubuntu에서 테스트 해 본 결과 여러가지 depencency가 상당히 많다는 점을 발견했고, 초기 환경 세팅이 복잡하므로 dockerize 해야겠다는 계획을 세웠다.&lt;/p&gt;

&lt;p&gt;Ubuntu 테스트는 개인 AWS EC2 인스턴스에서 진행했는데, 이상하게 coinpan에서 nginx 403 forbidden 페이지가 나오는 것을 발견했다. (개발은 Windows에서 해서 몰랐었다.)&lt;/p&gt;

&lt;p&gt;처음에는 Linux버전과 Windows버전의 Chromium구현 차이로 Coinpan에 있는 headless blocker가 작동한게 아닐까 싶었는데, Windows에서 Ubuntu EC2 인스턴스로 SSH 터널링을 하고 코인판에 접속해 본 결과 마찬가지로 403 Forbidden이 발생했다.&lt;/p&gt;

&lt;p&gt;아마 AWS쪽 IP를 차단한 것으로 추측된다. Chrome Extension의 Proxy를 써서 접속해도 잘 접속되던 사이트가 왜 하필 AWS일까? 싶지만 뭐 어쩌겠는가.&lt;/p&gt;

&lt;p&gt;개발은 Windows에서 했지만 컴퓨터를 항상 안정적으로 켜두기는 힘들어서 AWS EC2 인스턴스에서 돌릴 계획이었는데, 큰 문제가 발생했다.&lt;/p&gt;

&lt;p&gt;이로서 IP 차단 우회 기능도 넣어야 하게 되버렸다. 외부 서버 depencency없이 만들고 싶은데, 외부 Proxy server만드는 것 정도를 제외하고는 방법이 잘 떠오르지 않는다.&lt;/p&gt;

&lt;p&gt;(갑자기) 글을 쓰다보니 생각난 건데, gmarket같은 사이트 출석도 자동화 하면 포인트 한 10원 정도씩 쌓이니까 그것도 나쁘지 않을 듯하다.&lt;/p&gt;

&lt;p&gt;하지만 당장은 아래처럼 TODO LIST를 만들고 순서대로 진행해볼 생각이다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Coinpan AWS ip block bypass&lt;/li&gt;
  &lt;li&gt;Dockerize&lt;/li&gt;
  &lt;li&gt;Web Log Viewer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;아직 설명도 제대로 안되어 있는 것에 관심있는 사람이 있을지는 모르겠지만, &lt;a href=&quot;https://github.com/MoonCha/auto-attendance-checker&quot;&gt;Git repo Link&lt;/a&gt;에서 볼 수 있다.&lt;/p&gt;
</description>
        <pubDate>Sun, 14 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/development/project/2018/10/14/auto-attendance-checker-develop-note-1.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/development/project/2018/10/14/auto-attendance-checker-develop-note-1.html</guid>
        
        
        <category>DEVELOPMENT</category>
        
        <category>PROJECT</category>
        
      </item>
    
      <item>
        <title>네임드 개발자 - 블로깅을 시작하며</title>
        <description>&lt;p&gt;개발자들의 블로그는 상당히 흥미롭다.&lt;/p&gt;

&lt;p&gt;이 사람이 어떤 프로젝트를 진행해 보았고, 어떤 언어들을 써보았는지 등을 알게되며 그 깊이에 대해서도 얼핏 짐작할 수 있다.&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-Blog-Resume로 이루어진 경우 더욱 완벽하다)&lt;/p&gt;

&lt;p&gt;이러한 이유로 이미 대학교 1-2학년때 블로깅을 시작하려 했었다.&lt;/p&gt;

&lt;p&gt;다른 사람도 그런지는 모르겠지만, 접게되는 이유중 하나로 소재 부족이 크다고 생각한다.&lt;/p&gt;

&lt;p&gt;지금은 조금은 다르지 않을까.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;image right&quot;&gt;&lt;img src=&quot;/assets/images/wolves.jpg&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 03 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/misc/2018/10/03/starting-blog-to-be-named-developer.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/misc/2018/10/03/starting-blog-to-be-named-developer.html</guid>
        
        
        <category>MISC</category>
        
      </item>
    
      <item>
        <title>어느 날 일하면서 알게된 Promise 동작의 일부</title>
        <description>&lt;p&gt;나는 보통 새 프로그래밍 언어를 입문할 때 튜토리얼 페이지를 보면서 기초부터 쌓아올리는 방식을 쓰지 않는다. 이미 작성된 코드나 예시 코드만 보고 대충 추측하고, 언어 syntax나 기능 사용에 문제가 부딪치면 그 때서야 찾아보는 편이다.
그리고 이 방식은 새로운 library를 사용할 때도 적용되는데 이번에 이러한 방식 때문에 잠깐 혼란에 빠졌다.&lt;/p&gt;

&lt;p&gt;knex라는 Javscript query builder를 사용할 때였다.
기존에 작성되어 있던 코드는 대충 이런 구조로 되어 있었다.&lt;/p&gt;
&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;knex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;knex&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;knex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mysql2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* ... omitted ... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TABLE_NAME&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getRowListById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TABLE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getAllRowList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TABLE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고 이 함수들을 db라는 변수로 import했다고 가정하면, 이렇게 사용하고 있다.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rowList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getRowListById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gameId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;allRowList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getAllRowList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;내 머리속의 await은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await (something: Promise&amp;lt;any&amp;gt; | string | number | boolean ...)&lt;/code&gt;과 같은 모호한 형태로 그 사용법이 정해져 있었다.
현재 await을 통해서 값을 받아오고 있고, knex가 db로 쿼리를 날리고 row를 받아오는 과정은 async하게 일어날 것이므로 getRowListById와 getAllRowList는 모두 Promise를 반환하리라 생각했다.
그런데 이 함수들이 Promise를 반환한다고 가정하면, knex의 구현에 의문이 생긴다.&lt;/p&gt;

&lt;p&gt;knex는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client.select().from(TABLE_NAME)&lt;/code&gt;의 호출 만으로 Promise 반환과 함께 query &amp;amp; fetch를 수행하는데, 동일한 구문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.where({id: id})&lt;/code&gt;가 하나 더 붙은 것은 어느 타이밍에 query를 시도하냐는 것이다.
orm처럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.execQuery()&lt;/code&gt;가 마지막에 호출되면 모를까, 쿼리 빌드를 수행하고 쿼리를 DB에 날리는 시점이 불분명하다.&lt;/p&gt;

&lt;p&gt;그래서 처음에 생각한 가설은 아래 정도였다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WHERE&lt;/code&gt;을 쿼리에 넣지 않고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client.select().from(TABLE_NAME)&lt;/code&gt;의 결과에서 JS 로직으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; filter를 한다.&lt;/li&gt;
  &lt;li&gt;call chain 사이에는 그리 크지 않은 시간차가 있을 것이므로, 각 call이 들어올 때마다 다음 쿼리 빌드 호출을 일정시간 기다린다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.&lt;/code&gt;의 방법은 query builder라고 칭할 수 없는 멍청한 동작이고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.&lt;/code&gt;는 불안정하고 퍼포먼스도 구린, 차마 입에 담을수 없는 동작이다.
그래서 이 의문은 잠시 미궁에 빠졌다. 하지만 곧 이들 함수는 Promise를 반환하는 것이 아니라는 것을 알게됐다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/getRowListByIdReturnType.png&quot; alt=&quot;Return type of getRowListById&quot; width=&quot;70%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Knex.QueryBuilder라는 유사 Promise를 반환한다. 그러면 마지막으로 추정할 수 있는 것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await (something: Knex.QueryBuilder)&lt;/code&gt;가 어떤 동작을 하냐는 것이다.
await이 Knex.QueryBuilder의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt; property를 호출한다고 하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.execQuery()&lt;/code&gt;와 같은 역할을 수행할 수 있다고 생각한다.&lt;/p&gt;

&lt;p&gt;아래는 knex documentation중 then에 대한 항목이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/knexThenDocument.png&quot; alt=&quot;Knex Then Document&quot; width=&quot;70%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;빙고. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;이 호출되면 그 때 쿼리 빌드를 끝내고 내부적으로 Promise와 동일하게 동작을 수행하는 듯 하다.&lt;/p&gt;

&lt;p&gt;즉, await이 하는 일은 operand의 then proeprty가 함수인 경우 이를 호출하고, then에 넘겨준 함수가 호출 되기를 기다리는 것이 되겠다.&lt;/p&gt;

&lt;p&gt;따라서 다음 코드는 HI를 콘솔에 호출하고, a는 1이 된다.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HI&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onrejected&lt;/code&gt;의 경우는 어떤 동작을 할지 생각을 안해봤는데, async/await + Promise 구현이 어떻게 되어있는지 보는 것이 정확할 것 같다.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;JS에는 마법같은 동작이 많다.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* a becomes empty list */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;같은 것이나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.defineProperties&lt;/code&gt;로 getter나 valueOf property에 side effect 있는 함수를 넣는 것도 한 예라고 할 수 있겠다.&lt;/p&gt;

&lt;p&gt;다만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]+[]&lt;/code&gt;나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]+{}&lt;/code&gt;같은 형태의 해괴한 동작을 하는 코드는 한 눈에 보기에도 이상하고, 사용하지 않을 코드이고, 타입 스크립트에서는 사용하지도 못할 코드라서 괜찮다.&lt;/p&gt;

&lt;p&gt;물론 알아 두면 개발자끼리 장난칠 때는 좋다.&lt;/p&gt;

&lt;p&gt;이러한 동작을 배울 만한 사이트로 &lt;a href=&quot;https://alf.nu/ReturnTrue&quot;&gt;return true to win&lt;/a&gt;이라는 JS 퀴즈 문제 사이트가 있다.&lt;/p&gt;

&lt;p&gt;앞의 몇 문제만 풀고, 그 이후에는 안했었는데 시간 날 때 풀어보면 JS 마법 세계를 이해하는데 도움이 될 듯하다.&lt;/p&gt;
</description>
        <pubDate>Wed, 03 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://mooncha.github.io/javascript/programming/2018/10/03/async-await-internal-operation.html</link>
        <guid isPermaLink="true">https://mooncha.github.io/javascript/programming/2018/10/03/async-await-internal-operation.html</guid>
        
        
        <category>JAVASCRIPT</category>
        
        <category>PROGRAMMING</category>
        
      </item>
    
  </channel>
</rss>
