<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://bridgetownrb.com/" version="1.3.1">Bridgetown</generator><link href="https://kodingwarrior.github.io/rss.xml" rel="self" type="application/atom+xml" /><link href="https://kodingwarrior.github.io/" rel="alternate" type="text/html" /><updated>2025-10-21T07:22:33+00:00</updated><id>https://kodingwarrior.github.io/rss.xml</id><title type="html">KODINGWARRIOR QUEST</title><subtitle>고생을 사서 하는 개발자의 여정은 앞으로도 계속됩니다.</subtitle><entry><title type="html">기본을 잘하는 것이 힙한 것이다.</title><link href="https://kodingwarrior.github.io/post/2024/11/01/about-hype" rel="alternate" type="text/html" title="기본을 잘하는 것이 힙한 것이다." /><published>2024-11-01T00:00:00+00:00</published><updated>2024-11-01T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2024-11-01-about-hype.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2024/11/01/about-hype">&lt;blockquote&gt;
  &lt;p&gt;나 또한 Boring Technology에 굉장히 찬성하는 입장이기 때문에, 편파적인 관점이 있다. Boring Technology 자체를 엄청 싫어하는 성향이라면 그냥 지나가도 좋을 것 같다. Boring Technology를 찬성하는 입장일 뿐, 업계의 최근 동향을 반영하는 것이 무조건 나쁘다고 생각하진 않는다. 다만, 불필요한 복잡성을 추가하는 것이 아닌지는 고려할 필요가 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;사람이라면 누구나 인정욕구라는 것이 있다. 내가 이 정도는 해낼 수 있다는 역량을 드러내기 위함이라던가 인터뷰에서 걸러지지 않기 위해서 지금 당장 실감이 나지 않는 것이라 할지라도 새로운 개념을 공부해야 겠다는 강박이 생기는 것은 어쩔 수가 없다. 그저 저마다의 생존방식이기 때문에 그러는 것일 뿐이다. 그게 자의에 의한 것이든 타의에 의한 것이든.&lt;/p&gt;

&lt;p&gt;학원가라던가 일부 교육 업체에서는 특히 빅테크에서 일하려면 마이크로서비스 아키텍쳐를 알아야 하며, 대규모 트래픽을 감당할 수 있는 실력을 가져야 하는 것처럼 마케팅을 하고, 그런 경험이 없는 사람들에게 FOMO를 안겨주는 것이 마치 당연한 것처럼 관행이 이어져오고 있다. 업계에서 그런 사람들을 원하는 요구사항이 있다면, 교육업계도 그걸 반영하는 것이 어떻게 보면 당연한 일이다.&lt;/p&gt;

&lt;h2 id=&quot;우리는-정말로-이게-필요한걸까&quot;&gt;우리는 정말로 이게 필요한걸까?&lt;/h2&gt;

&lt;p&gt;한편으로는 의문이 드는 지점이 있다. &lt;strong&gt;우리는 정말 필요해서 이것을 하고 있냐&lt;/strong&gt;는 점이다. 기술스택을 결정하는데 있어서는 저마다의 사정이 있고, 비즈니스의 관점에서 보았을 때 나름 합리적인 의사결정 과정이 있었을 수 있다. 하지만, 여러 사례들을 관찰해본 관점에서 봤을때, 개인으로서는? 그렇지 않은 경우가 많은 것 같다.&lt;/p&gt;

&lt;h3 id=&quot;숨겨져-있는-복잡성&quot;&gt;숨겨져 있는 복잡성&lt;/h3&gt;

&lt;p&gt;가령, 사이드 프로젝트 혹은 포트폴리오를 만들기 위해서 간단한 Todo 앱을 만든다고 가정하자. Todo 앱을 만든다고 하더라도, 웹 개발자로서는 백엔드 쪽으로 역량이 있다는 것을 어필할 수도 있고, 프론트엔드 쪽으로 역량이 있다는 것을 어필할 수도 있다. 혹은 기술을 가리지 않고 프로덕트를 완성하는데 의미를 두는 풀스택 엔지니어(좋게 말하면, Product Engineer)로서 어필할 수도 있을 것이다. 여기에서도 선택과 집중이 필요하다. 누군가는 Github Actions를 끼얹어서 클라우드 서비스를 통해 배포할 수도 있고, 누군가는 EC2에 SSH 접근해서 배포하는 식으로 접근할 수도 있다. 혹은, 리포지토리에 푸시만 넣으면 바로 배포가 되는 PaaS를 이용할 수도 있다.&lt;/p&gt;

&lt;h4 id=&quot;배포-방식-혹은-인프라&quot;&gt;배포 방식 (혹은 인프라)&lt;/h4&gt;

&lt;p&gt;먼저, &lt;strong&gt;배포방식&lt;/strong&gt;에 대해 살펴보자. PaaS가 장사가 잘 되는 이유가 무엇일지에 대해 생각해보자. 그것은 배포를 하는데 드는 인지부하와 불필요한 시간을 줄이고, 핵심적인 비즈니스 로직에 더 집중할 수 있게 보조하는 것에 의의가 있다. 어떤 인프라를 유지보수하고 있다면, 유지보수하는 주체가 조직 내부 구성원이 되거나 혹은 PaaS 업체에 맡기거나로 관점이 나뉠 수 있다. 퍼포먼스를 최대한 쥐어짜내고 인프라 비용을 줄이기 위해서 인프라가 주력이 아닌 조직 내부 구성원이 인프라를 유지보수한다면, 인프라를 AWS EC2에다가 바로 배포하는 방식으로 접근할 수도 있다. 데이터베이스 및 인메모리 캐시까지 같은 서버에서 배포한다면 월 20~40달러 안쪽으로 나올 수도 있을 것이다. 하지만, 비즈니스 로직을 빠르게 개발해서 출시하는 것이 중요하고, 인프라를 관리하는데 드는 시간적 비용을 줄이고 싶다면 PaaS 업체에 인프라 관리를 맡기는 편이 시간도 아낄 수 있기 때문에 더 나을 수 있다.&lt;/p&gt;

&lt;h4 id=&quot;아키텍쳐&quot;&gt;아키텍쳐&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;아키텍쳐&lt;/strong&gt;에 대해서도 알아보자. 빅테크 경험이 없는 입장에서 아키텍쳐를 논하는게 우스울 수도 있겠다. 프레임워크에서 강제하는 아키텍쳐는 제쳐두더라도, 프레임워크에서 강제하지 않는 아키텍쳐로 개발을 한다고 가정했을때 여기서도 트레이드오프가 필요하다.  예를 들어, 소스 코드 파일을 어떻게 구성하고 조직할지, 팀원들의 이해 수준이나 소스 코드의 복잡도가 가져올 인지부하까지 고려해야 한다. 만약 빠른 출시가 최우선이라면, 복잡한 구조보다는 팀이 쉽게 이해하고 작업할 수 있는 단순한 아키텍처가 오히려 더 효과적일 때가 많다. 결국, 중요한 것은 프로젝트의 요구사항에 맞고, 팀이 지속적으로 관리 가능한 구조를 선택하는 것이다.&lt;/p&gt;

&lt;p&gt;안하면 안된다고 얘기가 나오고 있는 마이크로서비스 아키텍쳐는 또 어떤가? DAU가 300명이 안되고 트래픽 분산이라는게 필요가 없는 규모에서는 모놀리스 아키텍쳐로 운영하는 것이 적당할 수도 있는데, Single Point of Failure 혹은 서비스의 확장성 내지는 Fault Tolerance의 사유를 들 수도 있다. 근데, 그게 마이크로서비스 아키텍쳐 만으로 가능하냐면 모르겠다. 정말 도입을 하는게 필연적인 요구사항이라면 맞을 수도 있을 것 같다.&lt;/p&gt;

&lt;h4 id=&quot;도입하는-기술-스택&quot;&gt;도입하는 기술 스택&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;기술 스택&lt;/strong&gt;에 대해서도 생각해보자. 시간이든 시간안에 쳐낼 수 있는 일의 양이든 모든 자원은 한정되어 있다. 이런 한정된 자원을 적제적소에 스케쥴링하는 것도 엔지니어로서의 역량이다. 핵심적으로 어필해야 하는 것을 제쳐두고, 불필요한 복잡도를 늘리면서 불필요한 곳에 시간을 잡아먹는 것은 지양할 필요가 있다. 요즘은 해석이 다르긴 하지만, “섣부른 최적화는 만악의 근원”이라는 말도 있다. 당장은 내놓은 제품이 느리거나 아키텍쳐적으로 좋지는 않을 수 있다. 근데 빠른 출시를 위해서 어쩔 수 없이 트레이드오프를 한 것이라면 이것도 분명 옳은 선택일 수 있다. 완벽함을 추구하기보다 현재의 요구사항과 리소스에 맞춰 최선의 결정을 내리는 것이 중요하다.&lt;/p&gt;

&lt;p&gt;채용공고에서 명시했고, 그에 맞게 과제를 하는 것이라면 분명 실제로 사용되는 규모에 비해 오버엔지니어링이라 할 지라도 좋은 접근 방식일 수 있다. 다만, 제품을 만들때는 일부 기술스택은 우선순위가 그렇게 높지 않을 수도 있다.&lt;/p&gt;

&lt;h2 id=&quot;우리는-본연에-충실할-필요가-있다&quot;&gt;우리는 본연에 충실할 필요가 있다&lt;/h2&gt;

&lt;p&gt;회사에서 제품을 만들든, 남들이 이용하기를 바라는 사이드 프로젝트를 만들든, 어느 정도 경험을 쌓았다면 다들 알게 되는 것이 있다. 기술적인 관점에서 접근하는 것이 전부는 아니라는 것이다. 우리 딴에는 “필요할 것 같은데?” 라고 생각을 하더라도, 고객 입장에서는 그렇지 않은 경우를 숱하게 보곤 한다. 엔지니어로서 우리는 그냥 미션을 해결하면 되는 것인데, 어떤 도구를 사용하고 있는지는 고객에게 그렇게 중요하지 않을 수도 있다.&lt;/p&gt;

&lt;p&gt;문제를 해결하는 사람의 관점에서 생각해보자. 우리가 가장 먼저 해결해야 하는 것은 무엇인가? 그것은 바로 눈 앞에 있는 과제를 해결하는 것이다. 고객이 있다면 고객과 충분히 대화하고 고객이 원하는 것을 충족시키는 핵심적인 기능을 만들고 가다듬는 것이다. 문제를 해결하기 위해 사용하는 기술이나 방법론은 단순히 수단일 뿐이지, 그것이 과시하는 것을 드러내거나 혹은 인정을 받기 위한 것이나 다른 목적이 끼여있으면 안 된다. 필요한 지점이 오면 그 때 하는 것이 최선의 방법이다.&lt;/p&gt;

&lt;p&gt;엔지니어의 관점에서도 엄청 핫한 기술을 쓰지 않고서도 주어진 미션을 해결하기 위해 엔지니어의 인지부하를 최소한으로 만드는 솔루션도 나오곤 한다. 예시를 두개 정도 들어보고 싶다. 먼저, ssh로 직접 접근해서 배포하는 방식 + 컨테이너를 사용하는 배포방식을 교묘하게 잘 섞은 &lt;a href=&quot;https://kamal-deploy.org/&quot;&gt;kamal&lt;/a&gt;이라는 솔루션이 있다. PaaS를 쓰는 듯한 경험을 할 수 있으면서도, 누가 인프라를 복잡하게 세팅하지 않고도 서비스를 어렵지 않게 배포할 수 있고, 서버의 자원을 최소화하면서도 격리된 환경으로서의 장점을 동시에 누릴 수 있다.&lt;/p&gt;

&lt;p&gt;또 하나의 예시로는 데이터베이스를 메시지 큐로 쓰는 관점이 있다. Postgres의 예시를 들자면 LISTEN/NOTIFY를 활용해서 이벤트를 구독하고, 일정 간격으로 폴링하거나 즉시 알림을 받아 필요한 작업을 트리거하는 것이다. Rails에서는 &lt;a href=&quot;https://github.com/rails/solid_queue/&quot;&gt;Solid Queue&lt;/a&gt;/&lt;a href=&quot;https://github.com/bensheldon/good_job&quot;&gt;Good Job&lt;/a&gt;, Django 에서는 &lt;a href=&quot;https://django-q.readthedocs.io/en/latest/index.html&quot;&gt;Django Q&lt;/a&gt;가 대표적인 예시다. 의외로 빠른 출시를 위해서 사용하긴 괜찮은 솔루션이다. Redis/Kafka/RabbitMQ 등 추가적인 인프라를 세팅하지 않고서도 데이터베이스를 세팅하는 것 하나만으로 문제를 해결할 수 있기 때문이다. 심지어, 데이터베이스를 캐시로 쓰는 관점도 있다. 이에 대해서는 &lt;a href=&quot;https://github.com/rails/solid_cache&quot;&gt;Solid Cache&lt;/a&gt;를 살펴보면 될 것 같다. 인프라의 가짓수를 줄여서 인프라 관리의 복잡도를 최소화하는 것에 중점을 두는 것이라면 제법 괜찮은 접근이라고 본다.&lt;/p&gt;

&lt;p&gt;기본에 충실한 것, 본연에 충실한 것이 무엇인지도 고민해볼 필요가 있다. &lt;strong&gt;기본에 충실하다는 것은 단순히 어디에도 휘둘리지 않고 문제의 본질을 꿰뚫는 통찰력을 갖추는 것&lt;/strong&gt;이다. 문제를 본질적으로 해결할 수 있는 능력을 키우는 것, 즉, 문제의 핵심을 파악하고 다각도로 깊이 있게 바라보는 능력을 기르는 것이 중요하다. 어떤 지인의 말을 빌리자면, 공부한다는 것은 현상을 바라보는 해상도를 늘리는 것이다. LLM의 도움을 받는다하더라도 아는 만큼 보이기 때문에, 더더욱 중요해졌다. 우리는 그저, 엔지니어의 관점에서 문제를 해결하는 것에 집중하기만 하면 된다.&lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;다시 돌아가자면, &lt;strong&gt;기본을 잘하는 것이 힙한 것이다&lt;/strong&gt;. &lt;strong&gt;미션을 잘 수행한다&lt;/strong&gt;라는 기본을 잘하는 것에 우선순위를 가장 높게 둬야 한다. 스스로에게 복잡성이라는 핸디캡을 주면서 도전적인 일을 할 수는 있겠지만, 미션을 수행하지 못하면 인정받는건 물론이고 신용을 가지기도 어렵다. 최신 기술이나 트렌드에 너무 빠지기보다는, 본질적인 문제 해결에 집중하고, 고객에게 필요한 가치를 제공하는 것이야말로 진정한 의미에서의 &lt;strong&gt;“잘하는 것”&lt;/strong&gt;이고 정말로 &lt;strong&gt;“힙한 것”&lt;/strong&gt;이다. 당사자성이 있는 사람으로서 말하지만, 학습을 하는 입장에서도 마찬가지로 적용할 수 있을 것 같다. 뉴스레터를 접하면서 여러가지 트릭이나 라이브러리 및 도구를 알아보는 것도 분명 좋은 접근이지만, 문제를 본질적으로 파악할 수 있는 시야를 가지는 것이 중요하다. 때로는 고전으로 여겨지는 이론서가 오히려 장기적으로 더 큰 이득을 가져다줄 수 있다.&lt;/p&gt;

&lt;p&gt;이런 글을 쓰기로 마음 먹게 된 계기를 말하자면, 의외로 타임라인에서 떠도는 얘기들을 관찰하면서 트리거가 된 것은 아니다. 일상에서 접하는 것들을 마주하면서 문득 떠오른 생각이었다. 요즘은 머신러닝/LLM이 핫하다고는 하지만, 그런 것이 아예 없으면서도 장사가 잘 되는 제품들도 있고, 그런 제품들을 만드는 사람들의 관점들을 보자면 자주 감탄하게 되곤 한다. 언제였는지 기억이 나지는 않는데, 프로덕트헌트에 올라왔던 것 중에 jQuery + php 기반의 스택에다가 구조화가 잘 되어있지 않았음에도 10k 정도의 star가 찍혔던 오픈소스 프로젝트가 있었다.(제대로 기억하는 사람이 있다면 알려주면 좋을 것 같다. 어렴풋이 기억은 하고 있다.) 사진 편집기 어플리케이션이었던 것으로 기억한다. 어떤 스택을 쓰는지는 그렇게 중요하지는 않았고, 프로덕트헌트에서 상위권에 올라갔을 정도면 제품의 퀄리티만으로 인정을 받은 것이다. 이외에도 &lt;strong&gt;좋은 프로덕트들을 많이 접하긴 했는데, 좋은 프로덕트를 만드는 것에는 어떤 기술 스택을 선택하는지는 크게 중요하지 않았다는 사실을 깨달았다&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;이전에 &lt;a href=&quot;/post/2024/08/02/do-not-try-unncecessary-hard-things&quot;&gt;잘해야 한다는 강박이 얼마나 해로울 수 있는지&lt;/a&gt; 개인적인 사례를 들면서 앞서 언급한 적이 있다. 적절하지 않은 비유와 그닥 와닿지 않는 경험이 들어가있을 수도 있겠지만, 요즘 들어서 일관적으로 드는 생각이다. 기술적인 역량으로 인정받고자 하는 것은 엔지니어로서는 당연히 가질 수 밖에 없는 것이겠지만, 정말 적절한 기술인지를 결정하는 것도 엔지니어의 역량 중 하나이며 어떻게 보면 가장 중요한 영역이라고 생각한다.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;2024년 11월 19일 &lt;a href=&quot;https://neovimconf.live&quot;&gt;NeovimConf.live 2024&lt;/a&gt; 에서도 위에서 언급한 주제와 비슷한 주제로(You don’t need plugin, Long live command lines) 발표할 예정이다. 좋아보인다고 플러그인을 덕지덕지 붙여서 불필요한 복잡성을 늘리거나, 바퀴를 재발명할 바에는 터미널에서 Vim 에디터를 사용하는 입장에서 커맨드라인을 잘 사용하는 방법을 익히는 것이 도움이 될 수 있다는 관점으로 발표할 예정이다.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">어려운 것을 해야겠다는 강박</title><link href="https://kodingwarrior.github.io/post/2024/08/02/do-not-try-unncecessary-hard-things" rel="alternate" type="text/html" title="어려운 것을 해야겠다는 강박" /><published>2024-08-02T00:00:00+00:00</published><updated>2024-08-02T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2024-08-02-do-not-try-unncecessary-hard-things.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2024/08/02/do-not-try-unncecessary-hard-things">&lt;p&gt;본론부터 읽고 싶다면 &lt;a href=&quot;#s-1&quot;&gt;여기서부터&lt;/a&gt; 읽으면 된다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“어려운 것을 해야 겠다”&lt;/strong&gt;라는 강박은 인정욕이 있는 사람이면 누구나 가지게 된다. 나도 그 중 하나이기도 했고, 여전히 그런 경향을 가지고 있다. 
지금 와서 생각해보면 미숙한 결정을 내렸다고 생각할 때가 굉장히 많은데, 가령 이런 것들이 있었다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;학부생 시절의 실수&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;엄청나게 멋진 동아리 홈페이지를 만들겠다는 강박
    &lt;ul&gt;
      &lt;li&gt;2017년 기준으로, 내가 다니던 학교에서는 동아리 홈페이지가 있는 IT 동아리가 없다시피 했었다. 다른 학교는 있는데, 우리학교는 왜 없지? 라는 생각이 들어서 다른 학교에 있는 개발 동아리가 어떻게 운영되어 왔는지 최대한 찾아보기도 했다. 그 중에는 동아리 위키, 동아리 전용 이슈트래커 등등 멋있어 보이는 것들이 있었다.&lt;/li&gt;
      &lt;li&gt;내가 다른 학교의 동아리 생태계를 부러워했던 만큼, 나도 역시 다른 학교에서 부러워할 수준의 생태계를 만들고 싶었다. 그 중 대외적으로 어필하기 쉬운 수단 중 하나가 IT 동아리로서의 인프라 구축이었다. 그래서 미디어위키 기반의 위키를 도입하고, 레드마인도 직접 설치해보고, 그 외에도 다양한 도구들을 도입해보기도 했다. 당연히 도입은 실패로 끝났다.&lt;/li&gt;
      &lt;li&gt;어떤 인프라를 도입하는 것의 당위성이 충분히 설득되기 힘들기도 했고, 정말 필요하게 되는 순간도 없었기 때문이다. 단순히 구글 드라이브로 해결이 되는 것들인데 굳이 미디어위키로 지식 관리 시스템을 도입을 해야 했냐면 지금은 굉장히 후회되는 결정이기도 했다. 그 과정에서 불신의 씨앗이 피어나기도 했다.&lt;/li&gt;
      &lt;li&gt;홈페이지를 만들려는 시도도 여러번 했지만, &lt;strong&gt;만든다는 것 그 자체에만 의미를 두고, 정말로 필요한걸 만들려고는 하지 않았다.&lt;/strong&gt; 후술할 기술스택 이슈도 있어서 몇번을 갈아엎기도 하고, 이 과정에서도 마찰이 있었다. 결국에는 Github Page에 동아리 소개 페이지를 만드는 것 정도로만 끝냈다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;타 학교와 견줄 수 있는 수준으로 높은 수준의 알고리즘 스터디를 하겠다는 강박
    &lt;ul&gt;
      &lt;li&gt;알고리즘 동아리를 대표하고 직접 발품파는 사람이었다보니, &lt;strong&gt;다른 학교에서도 부러워하는 스터디&lt;/strong&gt;, &lt;strong&gt;혼자 공부하는 것과는 다르게 배워갈 수 있는 스터디&lt;/strong&gt;를 운영해야 겠다는 강박이 있었다.&lt;/li&gt;
      &lt;li&gt;가령, 예를 들자면… Brute Force/DP/Greedy/이분탐색/DFS/BFS/다익스트라/Minimum Spanning Tree 등 기본적인 알고리즘을 공부하는 것이 일반적이지만, 여기다 고급 알고리즘 트랙을 개설해서 확률론적 알고리즘/병렬 이분 탐색/아호-코라식/sqrt decomposition 등 난이도가 비교적 높은 것 위주로 강의자료를 준비했다. &lt;strong&gt;물론, 이렇게 해놓고 대회에서 좋은 성적을 얻진 못했다.&lt;/strong&gt; &lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
      &lt;li&gt;사실 나 말고도 비슷한 접근을 했던 사람들도 있었던 모양이다. 그런 사태를 보면서 누군가는 이런 평가를 했었다. &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;A + B 덧셈문제도 포드-풀커슨 알고리즘으로 푸시겠어요&quot;&lt;/code&gt; &lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;사회로 진출하고 나서의 실수&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;남들이 시도하지 않는 힙한 기술스택으로 셀프 브랜딩을 해야겠다는 강박&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Rails라던가 Django라던가 기술스택 베이스는 이미 있었지만, 이력서에 적을 프로젝트 만큼은 &lt;a href=&quot;&quot;&gt;Elixir&lt;/a&gt; 기반의 웹 프레임워크인 &lt;a href=&quot;&quot;&gt;Phoenix&lt;/a&gt;로 만들어야겠다는 강박이 있었다. 동아리 홈페이지도 마이너한 스택으로 혼자 개발하려고 했고, 포트폴리오용 프로젝트도 그렇게 접근했다. 실무에서는 혼자 일하는 것이 아니고, 다른 사람들과 같이 일하는 것이기 때문에 &lt;strong&gt;같이 참여하는 사람을 고려하는 것이 중요하다는걸 뒤늦게 깨달았다.&lt;/strong&gt; 마이너한 스택은 필연적으로 리소스가 충분하지 않기 때문에 삽질하는 시간이 심각하게 병목이 되었고, 진행속도는 더디게 되어 완성되는게 없다시피 했다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;결과적으로는 제대로 된 프로젝트를 하나 만든게 없는 사람&lt;/strong&gt;이 되었고, 이미 알고 있는 기술 스택의 숙련도는 말할 것도 없다. 제품을 잘 만드는 것에는 관심이 없었다. 실전으로 개발할때도 아웃풋이 그닥 좋게 나오지도 못했다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;기술적인 역량을 어필해야겠다는 강박&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;마이크로서비스 아키텍쳐, 디자인 패턴 도입, 테스트 커버리지 100%, kubernetes 기반의 클러스터 구축 등등 맥락에 적절하지 않은 것들을 내 역량을 증명하기 위해서 도입하려고 했던 적이 있다. 물론, 거기에 충분한 대화가 들어가지 않았고, 고집도 있었다. 흔히들 &lt;strong&gt;이력서 주도 개발&lt;/strong&gt;이라고 표현하는 것인데, 비즈니스적인 임팩트가 없는 것은 물론이고 프로젝트에서 그렇게 필요한 것도 아니었다. 단순히, 나를 위한 것 그 이상 그 이하도 아니었다.&lt;/li&gt;
      &lt;li&gt;한 때는 이러한 시도 조차 하려고 하지 않는 것을 게으른 것으로 취급하기는 했었다. 지금 생각하면 어리석은 생각이었다. &lt;strong&gt;시도하는 것으로 인해 이후에 유지보수 하는 사람들이 기술 부채로 어떻게 고생을 할 것인지, 시도하는 것으로 인해 독보적으로 얻을 수 있는 장점이 무엇인지 신중하게 생각하지 않는 것이 문제&lt;/strong&gt;라는 것을 뒤늦게 깨달았다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이런 실수들을 반복하다보니, &lt;strong&gt;어려운 것을 해야겠다는 강박&lt;/strong&gt;이라는 것이 여러모로 해로운 것이라는 사실을 깨달았다.
뭐 이미 지난 세월은 지난 세월이고, 앞으로 그런 실수를 반복하지 않으면 된다. 그러기 위해서는 의식적으로 노력하면 된다.&lt;/p&gt;

&lt;hr id=&quot;s-1&quot; /&gt;

&lt;p&gt;소프트웨어 업계에서는 YAGNI 라는 격언이 있다. &lt;strong&gt;You Ain’t Gonna Need It.&lt;/strong&gt; 즉, 당장 필요하지 않은 기능을 구현하지 말라는 것이다. 이것은 개발자들이 코딩을 할 때, 불필요한 기능을 구현하지 않도록 하기 위한 원칙이다. 여기서 더 나아가서, &lt;strong&gt;어려운 것을 해야겠다는 강박&lt;/strong&gt;도 마찬가지로 적용할 수 있다. &lt;strong&gt;당장 필요한 것도 아닌데, 어려운 것을 해야겠다는 강박으로 인해 불필요한 시간과 에너지를 낭비해서는 안된다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;시간은 한정되어 있고, 그 시간에 사용할 수 있는 리소스도 한정되어 있다. &lt;strong&gt;그 시간 안에 할 수 있는 노력과 의지력의 총량도 당연히 제한되어 있다.&lt;/strong&gt; 쉬운 것들 위주로 해내더라도, 어려운 것들을 해내는 것보다 &lt;strong&gt;더 적은 노력으로 더 많은 임팩트를 낼 수 있다.&lt;/strong&gt; 거기다가 어떻게 리소스를 투입해왔고, 어떤 결과가 나왔는지에 따라 &lt;strong&gt;나에 대한 신뢰도가 달라질 수 있다.&lt;/strong&gt; 어려운 것도 해내는 나의 가치를 애써 증명하기 위해, 어려운 것을 해야겠다는 강박은 버릴 필요가 있다. &lt;strong&gt;당장 필요한 순간에 내가 할 수 있는 것을 잘하고, 단순하게 해결하는 것만으로도 애쓰지 않아도 내 가치는 증명이 된다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;위에서 언급한 실수들이 꼭 나쁜 영향을 준 것은 아니었다. 결과적으로 실패한 경험들이긴 했지만, 그 경험들을 통해 배운 것들이 있었기 때문이다. 함수형 프로그래밍을 일찍이 접하면서 가독성있고 예측이 가능한 코드를 짜는 버릇이 생겼고, 어려운 알고리즘을 공부하면서 어지간한 알고리즘 문제는 쉽게 보이게 되었고, 기술 스택 도입에 실패한 여러 경험을 통해 &lt;strong&gt;기본을 집중해서 잘해야 한다&lt;/strong&gt;는 결론에 도달했기 때문이다.&lt;/p&gt;

&lt;p&gt;실패하는 과정에서 잃은 사람들도 있었지만, &lt;strong&gt;그 과정에서 얻은 사람들도 많았다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;어려운 것을 시도하는 행위 자체는 나의 성장에 도움이 될 수 있기 때문에 분명 가치가 있다. 어려운 것을 시도하다가 실패할 수도 있다. 실패하는 것이 꼭 나쁜 것만은 아니다. 하지만, &lt;strong&gt;어려운 것을 해내는 나의 가치를 증명하기 위해 나만의 리소스가 아닌 것을 희생하는 행위은 지양&lt;/strong&gt;해야 한다.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;이렇게 공부해놓고도 ACM-ICPC 본선에는 진출하지 못했다. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm&quot;&gt;Ford-Fulkerson algorithm&lt;/a&gt; - 간선에 capacity가 있는 그래프에서 최대 유량을 찾는 알고리즘이다. 이분 매칭에 사용되기도 하고, 네트워크 플로우 문제를 푸는데 사용된다. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://blog.naver.com/pasdfq/222217957003&quot;&gt;어려운 알고리즘을 권하는 사회&lt;/a&gt; - 이 글도 읽을만한 가치가 있다. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name></name></author></entry><entry><title type="html">이메일 클라이언트 구매 후기 (with hey.com)</title><link href="https://kodingwarrior.github.io/post/2024/03/08/hey-as-productivity-tool" rel="alternate" type="text/html" title="이메일 클라이언트 구매 후기 (with hey.com)" /><published>2024-03-08T00:00:00+00:00</published><updated>2024-03-08T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2024-03-08-hey-as-productivity-tool.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2024/03/08/hey-as-productivity-tool">&lt;p&gt;&lt;a href=&quot;/wiki/quarterly/2023-Q4&quot;&gt;2023년도 4/4분기 결산&lt;/a&gt; 에서 쓸까말까하다가 이걸 다 담기에는 4/4분기 결산 퇴고하는걸 미루게 될 것만 같아서 블로그 포스트로 따로 분리하기로 했다. 2023년 9월 쯤부터 유료 이메일 서비스를 구매하면서부터 뉴스레터를 구독하기 시작했던 특이점이 있었는데, 이에 대해서 설명하기에는 분량이 상당히 길어질 수도 있고 커피챗에서도 1시간 이상을 떠들어댈 수 있는 소재이기도 했기 때문이다.&lt;/p&gt;

&lt;p&gt;내가 사랑하는 여러가지 것들을 커피챗마다 가서 전도하고 싶은 마음은 굴뚝같지만, 만나고 싶어도 시간이 부족해서 못 만나는 사람, 꼭 만나서 전도해보고 싶은 마음은 굴뚝같지만 만날 시간이 없는 사람 등등을 고려해서 내가 사용하고 있는 유료 이메일 서비스에 대한 간증과 그리고 내가 왜 뉴스레터를 구독하고 있는지에 대해서 두 개의 아티클로 나눠서 설명하게 될 것 같다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.hey.com/&quot;&gt;Hey.com&lt;/a&gt; 라는 이메일 서비스가 있다.
Hey.com 에서 내세우는 기능 중에 &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;내 계정 핸들&amp;gt;@hey.com&lt;/code&gt; 로 이메일을 보내면 블로그 포스트처럼 글을 발행할 수 있는 기능이 있다.
여러 가지의 서비스를 사용해보고 케이스스터디를 해야하는 관점에서 통크게 이 기능을 시험삼아 적용해보고 싶었다.
하지만, &lt;strong&gt;유료결제를 해야만 이용할 수 있는 서비스&lt;/strong&gt;였고 글을 발행하기 위한 목적으로 쓰기에는 &lt;code class=&quot;highlighter-rouge&quot;&gt;$99/year&lt;/code&gt; 를 쓰는건 개인적으론 부담이었다.&lt;/p&gt;

&lt;p&gt;vim.kr&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; 관련해서도 이메일 업무를 해야하는 일이 많아지게 된 입장으로서 이메일 업무를 도와주는 생산성 도구를 찾아보긴 해야하는 입장이기도 했다.
이메일은 계속해서 쌓여만 가고 있었고, 구독 신청만 누르고 있었던 뉴스레터는 읽을 일도 없이 계속해서 스킵하고만 있었고, 쌓인 이메일만 네자릿수가 넘어갔다.
당시, 주변에서 &lt;a href=&quot;https://www.superhuman.com&quot;&gt;SuperHuman&lt;/a&gt;을 썼더니 “내 인생이 달라졌더라” 내지는 “삶의 질이 달라졌더라” 같은 간증이 들려오긴 했지만, &lt;code class=&quot;highlighter-rouge&quot;&gt;$300/year&lt;/code&gt;는 너무 부담스러운 가격이었다.
아까 설명했던 hey.com에 비하면 &lt;code class=&quot;highlighter-rouge&quot;&gt;$99/year&lt;/code&gt;와 &lt;code class=&quot;highlighter-rouge&quot;&gt;$300/year&lt;/code&gt;는 너무나도 차이가 나는 것이기도 했고, 내가 그나마 &lt;strong&gt;매력적으로 느껴졌던 기능들이 hey.com도 충분히 충족하고 있었기 때문에&lt;/strong&gt; hey.com를 구매해서 쓰는 결정을 하게 되었다.&lt;/p&gt;

&lt;h1 id=&quot;heycom을-쓰고나서-일어난-변화&quot;&gt;Hey.com을 쓰고나서 일어난 변화&lt;/h1&gt;

&lt;p&gt;hey.com을 쓰고 나서부터는 이메일을 처리하는 방식이 많이 달라졌다.&lt;/p&gt;

&lt;p&gt;적어도, 내가 확인해야 함에도 불구하고 매일마다 쌓이는 이메일이 줄고 있다는 점에선 확실히 달라졌다. 언젠가는 봐야지하고 미루는 것들도, 바로바로 처리하거나 혹은 시간이 지나고 난 뒤 유효하지 않다고 판단되면 과감하게 지울 수도 있게 되었다. 뉴스레터가 특히 그렇다.&lt;/p&gt;

&lt;h2 id=&quot;이메일을-kanban-board-처럼-활용하기&quot;&gt;이메일을 Kanban Board 처럼 활용하기&lt;/h2&gt;

&lt;p&gt;이메일 업무를 단순히 게시판 마냥 여러개의 게시글이 있으면 그 게시글을 일일이 확인하고, 거기다가 코멘트를 다는 접근 방식으로 바라볼 수 밖에 없었다.
왜냐면, 이메일 클라이언트의 생김새가 우리가 통상적으로 생각하는 게시판의 UI처럼 생겨먹었기 때문이다.
UX만으로도 사람의 생각을 바꿀 수 있다는 표현을 지나가다 주워들은 적이 있는데, 이런 것이 바로 적절한 예시가 아닐까 싶다.&lt;/p&gt;

&lt;p&gt;hey.com에는 workflow라는 기능이 있는데, 이는 이메일을 칸반보드처럼 활용할 수 있게 해준다.
엄밀하게는 각각의 이메일 쓰레드가 어떤 단계에 있는지를 표시해주고 각각의 단계에 맞게 lane에 배치핼 수 있게 해주는 기능이다.
국내 B2B 업무관리 도구 중에 Dooray! 라는 SaaS 도구가 이런 기능을 제공해주긴 하지만, 개인 이메일 클라이언트 단에서 이런 기능을 제공해주는 것은 신선한 경험이기도 했다.&lt;/p&gt;

&lt;center&gt;
    &lt;iframe src=&quot;https://social.silicon.moe/@kodingwarrior/112064159434723326/embed&quot; class=&quot;mastodon-embed&quot; style=&quot;max-width: 100%; border: 0&quot; width=&quot;400&quot; allowfullscreen=&quot;allowfullscreen&quot;&gt;&lt;/iframe&gt;&lt;script src=&quot;https://social.silicon.moe/embed.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
&lt;/center&gt;

&lt;p&gt;(추후에 뉴스레터를 읽는 노하우를 소개할 때도 다룰 내용이긴 하지만) 이와 비슷한 방식으로, 언젠가는 읽을 이메일은 reply later로 분류하고 회신을 위해서 계속해서 Follow-up 해야 하는 이메일은 Set Aside로 분류를 해서 처리를 할 수 있다.&lt;/p&gt;

&lt;p&gt;분류를 하는 행위에 대한 인지부하가 줄어들었기 때문에, 이메일을 처리하는데 드는 시간이 전반적으로 많이 줄었다.&lt;/p&gt;

&lt;h2 id=&quot;이메일을-자동으로-분류해준다고&quot;&gt;이메일을… 자동으로… 분류해준다고…?&lt;/h2&gt;

&lt;p&gt;내가 이메일 서비스를 적극적으로 이용하지는 않았기 때문에 이메일 서비스에 이런 기능이 있는지는 모르겠지만, hey.com에는 이메일이 들어오는 출처를 보고 그 이메일이 어떤 유형의 이메일인지를 자동으로 분류해주는 기능이 있다.&lt;/p&gt;

&lt;p&gt;스팸 메일이라고 판단되면 Spam,
뉴스레터라고 판단되면 The Feed,
영수증 청구 이메일이라고 판단되면 Paper Trail,
그 외에는 메인 화면 상에서 표시되는 Imbox,
이런 식으로 분류해주는데 어떤 목적으로 이메일 클라이언트를 들여보느냐에 따라 초점을 맞춰야 하는 부분을 UX 상에서 완전히 다른 영역으로서 분리를 해준다.&lt;/p&gt;

&lt;p&gt;그때그때 신경써야 하는 영역을 확실하게 분리를 해주다보니, 이메일을 읽거나 혹은 읽지도 않고 바로 휴지통에 버리는 행위에 대한 부담이 확실히 줄어들었다.&lt;/p&gt;

&lt;center&gt;
&lt;iframe src=&quot;https://social.silicon.moe/@kodingwarrior/112064270089350146/embed&quot; class=&quot;mastodon-embed&quot; style=&quot;max-width: 100%; border: 0&quot; width=&quot;400&quot; allowfullscreen=&quot;allowfullscreen&quot;&gt;&lt;/iframe&gt;&lt;script src=&quot;https://social.silicon.moe/embed.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;my-2&quot;&gt;
&lt;i class=&quot;my-2&quot;&gt;뉴스레터 처리하기&lt;/i&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;/center&gt;

&lt;center&gt;
&lt;iframe src=&quot;https://social.silicon.moe/@kodingwarrior/112064279573261015/embed&quot; class=&quot;mastodon-embed&quot; style=&quot;max-width: 100%; border: 0&quot; width=&quot;400&quot; allowfullscreen=&quot;allowfullscreen&quot;&gt;&lt;/iframe&gt;&lt;script src=&quot;https://social.silicon.moe/embed.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;my-2&quot;&gt;
&lt;i class=&quot;my-2&quot;&gt;영수증 청구 이메일 처리하기&lt;/i&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;/center&gt;

&lt;h1 id=&quot;결론&quot;&gt;결론&lt;/h1&gt;

&lt;p&gt;확실한 것은, 사람들이 돈을 쓰고 사용하는 소프트웨어들은 다들 그럴만한 가치가 있다. 돈이 달달이 나갈때마다 통장이 좀 아프긴 하지만, 이런 도구라도 사용해야 내가 감당하는 인지부하가 줄어드는 것은 자명한 사실이고, &lt;strong&gt;달달이 나가는 구독료는 인지부하를 줄이기 위한 비용이라 생각하면 그렇게 비싸지는 않다&lt;/strong&gt;. 생산성 도구를 사용하는 것이 다 그런 것이라 생각한다.&lt;/p&gt;

&lt;p&gt;어떤 생산성 도구는 가격이 부담스럽다고 한들, 막상 계산기를 두들겨보면 그럴만한 가치가 있는 물건이라는 생각이 들 때가 많다. 앞에서 설명한 것처럼, hey.com을 사용하면서 이메일을 처리하는데 드는 시간이 줄어들었는데, 이걸 시급이라는 기준으로 환산해보면 &lt;code class=&quot;highlighter-rouge&quot;&gt;$99 / 12개월&lt;/code&gt; ~= &lt;code class=&quot;highlighter-rouge&quot;&gt;$8.25 / 30일&lt;/code&gt; = &lt;code class=&quot;highlighter-rouge&quot;&gt;$0.275 / 1일&lt;/code&gt; 이라는 계산이 나온다. 하루에 500원씩 아낀다고 생각해보면, 그렇게 비싼 금액은 아니다.&lt;/p&gt;

&lt;p&gt;Todoist도 그런 의미에서 다시 결제하기 시작했는데, Todo 앱에서 단축키를 지원하고 커스텀 쿼리를 조합해서 사용할 수 있는 것이 얼마나 매력적인 기능인지를 지금와서야 처음 알았다. 어딘가에다가 할일 목록을 작성하고, 그것을 온라인/오프라인 가리지 않고 언제 어디서든 기록할 수 있어야 하며, 심지어 UX가 간편한 것이라면 당연히 돈을 쓰는 것이 안 아까울 수 밖에 없다. 단축키 지원으로 워크플로우가 최적화될 수 있다는 점은 이미 Vim을 1년 넘게 체화하고 현재도 사용하고 있는 지금의 시점에서 많이 체감하고 있다.&lt;/p&gt;

&lt;p&gt;언젠가는 언급할 주제이긴 하지만, 당연히 &lt;strong&gt;사용하는 생산성 도구의 가짓수를 늘리는 것은 굉장히 위험&lt;/strong&gt;하다. 생산성 도구는 가능하면 적게 사용하는 것이 좋지만, &lt;strong&gt;내 워크플로우에 잘 맞는 도구이며 내 워크플로우를 최적화할 수 있다면 결제하는 것 정도야 그렇게 아깝지 않은 비용&lt;/strong&gt;이라는 것을 말하고 싶었다.&lt;/p&gt;

&lt;p&gt;생산성 도구를 구매할까 말까 고민하고 있다면, 특히, 이메일 클라이언트를 구매하는 쪽으로 고민이 들고 있다면 충분히 참고자료가 되었으면 좋겠다.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;실제로 &lt;a href=&quot;https://au-vimenter.github.io/post/2023-12-23-au-vimenter&quot;&gt;VimEnter 2023&lt;/a&gt; 행사를 진행할때, 후원사와 이메일을 주고뱓으면서 큰 도움을 받을 수 있었다. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name></name></author></entry><entry><title type="html">2027년 낙장불입 해피엔딩 3개년 계획</title><link href="https://kodingwarrior.github.io/post/2023/12/29/farewell-for-future" rel="alternate" type="text/html" title="2027년 낙장불입 해피엔딩 3개년 계획" /><published>2023-12-29T10:05:00+00:00</published><updated>2023-12-29T10:05:00+00:00</updated><id>repo://posts.collection/_posts/2023-12-29-farewell-for-future.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2023/12/29/farewell-for-future">&lt;p&gt;2027년 쯤에는 아마 종적을 감추고 있을지도 모른다. &lt;br /&gt;
삶을 지속하는 것에 회의감을 느끼던 2020년 쯤부터 결심했던 일이다. &lt;br /&gt;
꾸준히 언급은 해왔기 때문에, 오래 알고 지낸 지인들도 충분히 예상이 가능한 결말이다.&lt;/p&gt;

&lt;p&gt;나를 위한 해피엔딩이고 다른 주변 사람들을 위한 해피엔딩을 위한 선택이다.&lt;/p&gt;

&lt;p&gt;극단적 선택이라기 보다는 중대한 결정에 가깝다.&lt;br /&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;strong&gt;스스로의 감정에 대한 통제가 되지 않는다.&lt;/strong&gt;
올해 2월 쯤에는 병원에 5일 정도 입원했던 적이 있었다.
책을 반입하지 못한 나머지 심심해서 뛰쳐나오긴 했지만, 10개월 째 계속해서 같은 병원에서 치료받는 중이다. 계속해서 증량해서 처방받고 있다지만, 나아질 기미가 보이지도 않는다. 사람이 나이가 들면 들 수록 변하기 어렵다는 통념을 자주 접하고 있는데, 지금 상태에서 더 나아지지 않는다면 불행한 상황을 만들어낼 것 같은 미래가 너무 선하다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;내 목숨의 값 어치를 싸게 여기는 마인드셋은 변하지 않는다.&lt;/strong&gt;
내 목숨의 값 어치를 싸게 여기는 건, 단순히 내가 나를 그렇게 생각하기 때문이다. 살 사람은 살아야겠지만, 나는 그저 아닌 것일 뿐이다. 내가 내 목숨의 값 어치를 낮게 평가하는 것이 간접적으로는 다른 사람 목숨의 값 어치를 낮게 여기는 것으로도 비춰질 수 있다는 것 역시 알고 있다. &lt;br /&gt;
그럼에도 불구하고 나에 대한 가치 평가는 변하지 않는다. 이로 인해서 주변 사람들이 힘들어 하게 될 바에는 아무도 남지 않게 정리하는 게 나은 것 같다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;삶을 살아가는 것 자체가 귀찮아졌다.&lt;/strong&gt; 긍정적인 미래에 대한 생각도 없어졌다. 잠을 자는 것도 사실상 도피성 수면이라서 눈 뜨고 몸뚱이를 움직여야한다는 것 자체가 받아들이기 싫을 때가 많다. 내가 원하는 것을 쟁취하기 위해 도박을 하거나 경쟁이라는 것도 해볼 필요가 있다는 건 머리론 이해하지만, 그냥 지쳐서 시도하기도 싫을 때가 많다. 앞으로도 모든 것이 더 귀찮아질 것이고, 계속 불만족스러운 현 상황을 한탄하면서 악순환을 반복할 것 같다. 난 앞으로도 스스로에게 무책임한 사람일 것이다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;이젠 기쁜 일이 있어도 크게 감흥이 와닿지가 않는다.&lt;/strong&gt;
최근 들어서 기쁜 감정을 느꼈던 일이나, 좋은 일이 있었는데도 불구하고 그런 감정에 불감증이 생긴 것 같다. 정확히는 공허한 감정이 더 강하다.
사실, 그 원인이 무엇인지도 안다.
쓰잘데기없는 동물적인 본능에 기인한 것이라는 확신이 들어서 더욱 회의감이 든다.&lt;/p&gt;

&lt;h2 id=&quot;존재론적인-질문&quot;&gt;존재론적인 질문&lt;/h2&gt;

&lt;p&gt;스스로에게 질문을 많이 던진다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;나는 무해한 사람이었는가?&lt;/strong&gt; 전혀 그렇지 않다.&lt;br /&gt;
무해한 것처럼 보이는 속성을 드러내면서 은근슬쩍 유해한 사람이진 않았는가?&lt;br /&gt;
인권활동을 지지하는 것처럼 행동하지만, 한편으로는 내가 지지하는 사람들에게 해를 끼치는 행동을 하지는 않았는가?&lt;br /&gt;
내가 지지하고 연대하는 사람들에게 무해한 사람이었냐면 아니었던 것 같다. 없느니만 못한게 아니었을까&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;나는 내가 정한 원칙을 잘 지키는가?&lt;/strong&gt; 아직까지는 잘 지키는 편이다.&lt;br /&gt;
내가 독한 놈이라고 욕을 먹는 한이 있어도, 내가 정한 원칙은 무조건 지키는게 철칙이고 원칙을 어겨야 한다면 차라리 죽는 것이 낫다고 생각하는 입장이다.
하지만, 이게 앞으로도 계속될 지 확신이 생기지 않는다.&lt;br /&gt;
내가 존경해왔던 여러 인물들, 여러 유명 인사들이 부도덕한 행위를 저질렀다거나 권력관계를 이용한 범죄를 저질렀다는 소식을 볼 때마다 늘상 들었던 생각이다.
신념을 가지고 도덕적인 행동을 하는 사람들이라고 생각했는데도 그런다면, 나이가 들면 결국에는 자제력을 잃어버리는게 아닐까라는 생각이 드는 것이다.&lt;br /&gt;
언제 폭발할 지 모르는 시한폭탄을 사람들 있는데서 터트릴 바에는 아무도 없는데서 터트리는게 낫다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;나는 이전보다 더 나아질 수 있는 사람인가?&lt;/strong&gt;
내 생각엔 절대 아니다.
내가 이전보다 더 나아질 수 있는 사람이었으면 진작에 이런 계획을 세우지도 않았을 것이다.
미래에 더 추하게 늙지 않기 위해서, 적당한 타이밍에 결말을 내고 싶을 뿐이다.
수많은 사람들을 케이스 스터디 해왔기 때문에, 건강한 상태의 나라면 어떻게 지금보다 더 나아질 수 있는지 정도는 알고 있다. &lt;br /&gt;
다만, 인간으로서 가진 한계 그리고 나라는 사람이 가진 한계 때문에 앞으로도 내가 의도하는대로 되지 않을 것을 잘 알고 있다.&lt;/p&gt;

&lt;h2 id=&quot;정상성&quot;&gt;정상성&lt;/h2&gt;

&lt;p&gt;나는 정상성과는 굉장히 거리가 멀다면 멀 수도 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;난 가족이 없다.&lt;/strong&gt;
정확히는 일시적으로나마 여러가지 혜택을 누릴 수 있음에도 불구하고, 내 의지로 의절했다.
계속해서 끈질기게 연락오는 것이 괴롭기도 했었고, 친구관계에 대한 간섭/진로 방향성에 대한 간섭/가스라이팅이 지속되었기 때문에 나에게는 해롭다는 판단이 들어서 의절했다.
더불어, 내가 사랑하는 사람에게도 해로울 것이라는 판단이 들어서 더욱 확신이 생긴 것이기도 했다.
그에 대한 대가로, 명분상으로 가족이 필요한 상황이 온다 하더라도 가족이 없기 때문에 인생 전반적으로 선택할 수 있는 선택지가 더욱 줄어들게 된 셈이다.
가족이 없는 사람을 기피하는 시선이라는 것도 무시할 수 없다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;다른 동년배와는 거리가 먼 삶을 살고 있다.&lt;/strong&gt;
주식 투자는 미국 빅테크 위주로 꾸준히 적금넣듯이 하고 있지만, 적극적으로 공부하고 있지도 않는다.
내일이라는게 없는 삶을 살다시피 하고 있기 때문에 투자/재테크 같은 것들이 눈에 들어오지도 않는다.
차를 사는 것에도 딱히 관심이 없고, 앞으로도 사지 않을 것 같다. 번거롭고 귀찮은 것을 싫어하기 때문이다. 내가 사랑하는 사람의 낭만을 위해서라도 사는게 불가피하겠지만, 어차피 일어나지도 않을 상황이기 때문에 뜬구름이나 잡는 꼴이라고 생각하고 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;추억이라고 할만한 것이 없다.&lt;/strong&gt;
그러다보니, 인류에 대한 애정이라는 정서에 공감하지 못할 때가 많고, 내 주변 사람들을 챙기는 것이 아닌 이상에야 대부분의 경우에는 인간 혐오라는 정서를 깔고 있다.
매매혼을 권유받을 정도로 지겹도록 외모 차별을 당해온 경험이 있기 때문에, 외모로 인한 열등감도 병적으로 심한 편이다.
통상적인 사람에 대한 기대치도 낮아졌기 때문에, 신뢰를 주는 것도 어렵다.&lt;/p&gt;

&lt;p&gt;정상성과 거리가 먼 삶은 내가 함께하는 사람들을 더욱 힘들게 할 뿐이라는 사실을 알고 있다.&lt;br /&gt;
정상성과 거리가 먼 삶은 내가 사랑하는 사람들을 더욱 병들게 할 뿐이라는 사실을 알고 있다.&lt;br /&gt;
정상성과 거리가 먼 삶은 내가 누군가를 사랑해도 되는지 회의감이 들게 한다.&lt;br /&gt;
사랑하기 때문에, 떠나야 할 때도 있다는 것을 알고 있다. 사실은 진작에 떠나야 했겠지만 말이다.&lt;/p&gt;

&lt;p&gt;부정당할 수 밖에 없는 삶이라면 무덤덤하게 받아들이는 것이 내 선택이다. 선택지가 사실상 없지만 말이다.&lt;/p&gt;

&lt;h2 id=&quot;앞으로의-계획&quot;&gt;앞으로의 계획&lt;/h2&gt;

&lt;p&gt;삶에 욕심이 아예 없는 것은 아니다. 내가 어디가서 무시당할만한 실력의 사람이 아니었다는 기록 정도는 남기고 싶다. 2024년 연말에는 온라인으로 진행되는 해외 컨퍼런스에 라이트닝 토크 지원해서 꼭 발표하고자 하는 계획이 있고, 2025년에도 100명 이상 규모의 컨퍼런스에서 발표할 계획이 있고, 2026년 쯤에는 해외 컨퍼런스에서도 발표하고 싶은 의지가 있다.&lt;/p&gt;

&lt;p&gt;그 외에는, 계획이 없다. 내 삶의 행복을 위한 계획을 세운다는 것 자체가 행동으로 옮겨질 가능성도 없거니와 내가 원하는 것이 충족되지 않다는 것을 스스로도 잘 알고 있다.&lt;/p&gt;

&lt;p&gt;혹여나, 갑자기 앞으로의 계획에 변동이 생길 만한 이벤트는 언제든지 있을 수는 있다고 생각한다.&lt;br /&gt;
지금까지 경험해 본 바로는 이런 것들도 결국에는 착시 현상에 가까울 뿐이었다. 안정감이란 내 삶과는 거리가 멀 뿐이었다. &lt;br /&gt;
계획에 변동이 생길 만한 유혹이 든다 한들, 내가 바라는 목표를 위해 스스로를 몰아붙일 것이다.&lt;br /&gt;
계획이 바뀌었다고 가정해도, 2027년에 맞이할 해피엔딩을 전제하고 달려왔던 삶을 후회하느라 불필요하게 시간을 낭비하고 싶지 않다.
그러다가 다시 잃을 것도 없는 원래 상태로 돌아와서 악순환을 반복할 바에는 일직선으로 직진하는 것이 차라리 낫다.&lt;/p&gt;

&lt;p&gt;이 글이 기록물로 남게 되는 것으로 인해서 어떤 파급력을 가지고 있을지도 충분히 예상하고 있다.
제목에서도 언급했듯이, 낙장불입. 앞으로도 돌이킬 수 없도록 해피엔딩을 맞이하기 위해서 스스로에게 하는 맹세이기도 하다.
헛된 희망을 가지면서 스스로를 희망고문하고 불필요하게 피해를 주고 다닐 바에는 확실하게 깔끔한 엔딩을 향해 나아가는 것이 낫다.&lt;/p&gt;

&lt;p&gt;비록, 앞으로 3년 밖에 남지 않는 시한부 같은 삶을 살아간다지만, 나는 내가 지향하는 방향대로 살아갈 것이고, 나만의 원칙은 절대로 어길 생각이 없다. 3년 정도는 내가 목표하는대로 화끈하게 살다가, 때가 되면 적당히 정리하고 박수칠 때 떠나는 엔딩을 맞이하고 싶다.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">『업무 시각화』 리뷰</title><link href="https://kodingwarrior.github.io/post/2022/05/27/review-of-making-work-visible" rel="alternate" type="text/html" title="『업무 시각화』 리뷰" /><published>2022-05-27T23:59:59+00:00</published><updated>2022-05-27T23:59:59+00:00</updated><id>repo://posts.collection/_posts/2022-05-27-review-of-making-work-visible.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2022/05/27/review-of-making-work-visible">&lt;p class=&quot;flex justify-center&quot;&gt;&lt;img src=&quot;https://image.aladin.co.kr/product/22896/26/cover500/k602636940_1.jpg&quot; alt=&quot;업무 시각화 표지&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;text-center py-3&quot;&gt;&lt;a href=&quot;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=228962643&quot;&gt;『업무 시각화』 구매 URL&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5월 31일 기준으로, 지금 소속된 회사에 일을 하게 된 지 곧 4개월이 되어갑니다.&lt;/p&gt;

&lt;p&gt;서비스 출시 초기부터 개발과 관련된 일은 내가 온전히 다 책임지는 상황이다보니 프로젝트 관리에 좀 더 신경을 써야겠다는 걸 피부로 뼈저리게 느끼기 시작했어요.&lt;/p&gt;

&lt;p&gt;이 글에서 리뷰할 &lt;strong&gt;『업무 시각화』&lt;/strong&gt;라는 책 자체는 트위터 타임라인에서 영업글을 발견한 2021년 2월 쯤부터 시작해서 자기전에 읽는 것을 반복하다가 중간에 읽다 말긴 했었는데요. 현재 소속된 회사 프로젝트의 일정을 직접적으로 관리를 해야하는 입장 상 읽는 것을 미룰 수가 없었어요. 그래서, 2022년 3월 쯤에 들어서서 다시 읽기 시작했어요.&lt;/p&gt;

&lt;h1 id=&quot;i-이-책에서는-어떤-내용을-다루나요&quot;&gt;I. 이 책에서는 어떤 내용을 다루나요?&lt;/h1&gt;

&lt;p&gt;이 책은 크게 보자면, 5가지 업무 흐름 시스템을 설계하고 사용하는 것을 권장하고 있어요.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;업무 시각화&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;진행 중 업무 제한&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;업무 흐름 측정 및 관리&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;효과적인 우선순위 선정&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;피드백과 측정 항목을 통해 배운 것을 기반으로 조정&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;볼드 처리한 부분 위주로 소개해볼게요.&lt;/p&gt;

&lt;h2 id=&quot;업무-시각화&quot;&gt;업무 시각화&lt;/h2&gt;

&lt;p&gt;이 책에서는 업무를 시각화하는 방법 중 하나로 &lt;code class=&quot;highlighter-rouge&quot;&gt;칸반 보드&lt;/code&gt;를 이용하는 것을 권장하고 있습니다. &lt;code class=&quot;highlighter-rouge&quot;&gt;칸반 보드&lt;/code&gt;를 사용하는 방법 자체는 간단하지만, 이를 이용해서 업무의 진행을 가로막는 &lt;strong&gt;‘시간 도둑’&lt;/strong&gt;들을 드러내고,  최종적으로는 업무 생산성을 극대화시키기 위한 시스템을 만들 수 있도록 돕고 있습니다.&lt;/p&gt;

&lt;p&gt;업무가 어떻게 진행되고 있는지를 시각화하면서 어떤 업무를 놓치고 있는지, 어떤 사람에게 과중한 업무가 부과되어 있는지, 어떤 업무가 서로 얽혀있는지를 조직의 구성원들이 한눈에 파악할 수 있게 됩니다. 이는, 곧, 부서간의 정보 공유를 원활하게 해주고 의사소통 비용 감소로도 이어질 수 있다고 강조합니다.&lt;/p&gt;

&lt;p&gt;업무를 시각화하는게 왜 좋은지 충분한 근거를 들면서 설명하고 있습니다.&lt;/p&gt;

&lt;h2 id=&quot;진행-중-업무-제한&quot;&gt;진행 중 업무 제한&lt;/h2&gt;

&lt;p&gt;어떻게 보면 당연한 얘기기도 하겠지만, 한 번에 여러 개를 동시에 하려고 하면 생산성이 떨어질 수 밖에 없습니다. 한 업무에서 다른 업무로 왔다갔다 하다보면 다른 업무를 하기 위해서 생각하는 시간을 가지고, 다른 업무를 하기 위해 준비하는 시간이 포함되기 마련입니다. 한정된 시간 자원이라는 맥락 안에서 보면, 이것도 역시 불필요한 비용 중 하나이기도 합니다. 한정된 시간 자원 내에서 불필요한 비용이 비중을 차지하면, 제 시간에 해내야 하는 업무를 제 시간에 끝낼 수 없게 될 수도 있습니다.&lt;/p&gt;

&lt;p&gt;컴퓨터 과학 분야에서는 &lt;code class=&quot;highlighter-rouge&quot;&gt;컨텍스트 스위칭(문맥 전환)&lt;/code&gt;이라는 용어가 있습니다. 이 책에서도 위에서 언급한 문제를 &lt;code class=&quot;highlighter-rouge&quot;&gt;컨텍스트 스위칭&lt;/code&gt;이라는 용어를 언급하면서 비유하고 있는데요. &lt;code class=&quot;highlighter-rouge&quot;&gt;컨텍스트 스위칭&lt;/code&gt; 비용을 줄이기 위해서라도 너무 많은 진행 중 업무를 줄일 수 있도록 강조하고 있습니다.&lt;/p&gt;

&lt;p&gt;이 책에서는 다음과 같이 해결책을 제시합니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;진행 중 업무 갯수에 최대 할당량을 두자.&lt;/li&gt;
  &lt;li&gt;잦은 &lt;code class=&quot;highlighter-rouge&quot;&gt;컨텍스트 스위칭&lt;/code&gt;을 줄이고자 한다면, &lt;code class=&quot;highlighter-rouge&quot;&gt;Pomodoro&lt;/code&gt; 기법을 사용해보자.&lt;/li&gt;
  &lt;li&gt;일정이 꽉 차있다면, 추가 업무 요청에 ‘아니요’라고 말할 수 있도록 하자.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;효과적인-우선순위-선정&quot;&gt;효과적인 우선순위 선정&lt;/h2&gt;

&lt;p&gt;개발팀의 우선순위와 운영팀의 우선순위와 경영진의 우선순위는 각자 다를 수 있습니다. 서로 다른 개발팀이라도 사정이 크게 다르지 않을 것입니다. 우선순위는 어떻게든 충돌하기 때문이죠.&lt;/p&gt;

&lt;p&gt;우선순위를 명확하게 정하지 않으면, 모든 우선순위가 1순위가 되는 모순되는 상황이 발생할 수도 있으며, 너무 많은 진행 중 업무를 가지게 되는 문제로 이어질 수 있습니다.&lt;/p&gt;

&lt;p&gt;이 책에서는 &lt;code class=&quot;highlighter-rouge&quot;&gt;A3 씽킹&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;지연비용률&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;HiPPO&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;약속선&lt;/code&gt; 등의 용어를 언급하면서 우선순위를 어떻게 효과적으로 선정할지 소개하는 한편, &lt;strong&gt;의사소통의 중요성&lt;/strong&gt;도 역시 강조하고 있습니다.&lt;/p&gt;

&lt;h1 id=&quot;ii-개인적인-경험&quot;&gt;II. 개인적인 경험&lt;/h1&gt;

&lt;h2 id=&quot;프로젝트-일정이-산으로-가는-까닭은&quot;&gt;프로젝트 일정이 산으로 가는 까닭은…&lt;/h2&gt;

&lt;p&gt;감각으로 어림잡아서 프로젝트 일정을 보고했던 적이 많았습니다. 당연히, 어림잡았던 것과는 다르게 생각보다 시간을 많이 잡아먹던 경우가 많았구요.&lt;/p&gt;

&lt;p&gt;이를테면, A라는 태스크가 ‘7일이면 다 끝날 수 있겠지’하고 어렴풋하게 추정해보기도 합니다. 하지만, 클라이언트로부터 클레임이 들어오거나 엄청나게 치명적인 버그를 발견해서 급하게 버그픽스를 하느라 시간이 다 가기도 했습니다. 혹은, 경험해보지 못했던 문제를 마주했거나, 기술부채를 뒤늦게 갚느라 많은 시간을 보내게 되기도 했었습니다. 책에서는 &lt;strong&gt;‘알려지지 않은 의존성’&lt;/strong&gt;이라 표현하고 있습니다.&lt;/p&gt;

&lt;p&gt;약속했던 일정보다 과업이 늦게 끝났다면 왜 늦었는지에 대한 알리바이를 증명하면 됩니다. 하지만, 일정을 약속해놓고 빈번하게 약속한 일정보다 늦는 일이 상습적이면 안 된다고 생각합니다. 프로 개발자가 되고자 한다면 ‘그럴 수도 있지’하고 넘기는 것이 아니라, &lt;strong&gt;예정된 일정에 늦지 않을 수 있는 방법&lt;/strong&gt;을 고민해야 하거나 불확실한 변수를 고려하더라도 &lt;strong&gt;좀 더 정확하게 일정을 추정할 수 있는 방법&lt;/strong&gt;을 고민해야 할 것이라고 생각합니다.&lt;/p&gt;

&lt;p&gt;사실, 이런 문제는 &lt;strong&gt;마땅한 해결방법을 찾지는 못했습니다&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;다만, 의도적으로 꾸준히 시간대별로 무슨 일을 했는지 일일보고를 작성하고 있습니다. 회고를 작성하는 단계까지 가지는 못했지만요. &lt;code class=&quot;highlighter-rouge&quot;&gt;Pomodoro&lt;/code&gt; 앱을 사용하면서 어떤 종류의 과업을 하는데 얼마 만큼의 시간을 들였는지 정량적인 기록도 남기고 있어요. 꾸준히 기록을 남겨 측정 데이터를 쌓으면서, 비슷한 업무를 받았을때 어느 정도 시간이 걸릴 것인지 예측할 수 있도록 하거나 이를 좀 더 최적화할 수 있도록 하고, 불확실한 변수가 껴있는 일이라면 어떻게 하면 덜 헤맬 수 있을지 방안을 찾아보고는 있어요.&lt;/p&gt;

&lt;h2 id=&quot;내-생산성이-바닥을-기었던-이유에-대한-근본적인-의문&quot;&gt;내 생산성이 바닥을 기었던 이유에 대한 근본적인 의문&lt;/h2&gt;

&lt;p&gt;개인적으로는 스터디/사이드 프로젝트/커뮤니티 등등 벌려놓은 일들이 많았습니다. 본업 이외에도 벌려놓은 일들에 파묻혀서 정신이 여기저기 분산되어 하나에 집중하기가 어려웠었고, 거기다가 주의력 결핍 증상에 시달리고 있었습니다.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;es&quot; dir=&quot;ltr&quot;&gt;RescueTime &lt;a href=&quot;https://t.co/VjcoUTXSOU&quot;&gt;https://t.co/VjcoUTXSOU&lt;/a&gt; &lt;a href=&quot;https://t.co/nFd2fRuYBi&quot;&gt;pic.twitter.com/nFd2fRuYBi&lt;/a&gt;&lt;/p&gt;&amp;mdash; Lee Jae-yeol (@kodingwarrior) &lt;a href=&quot;https://twitter.com/kodingwarrior/status/1531065420832067584?ref_src=twsrc%5Etfw&quot;&gt;May 30, 2022&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;생산성이 저하되는 것을 손 놓고 지켜만 보고 있을 수는 없었기 때문에, 내가 과연 어디어디에 시간을 쓰고 있었는지 정량적으로 파악하기 위해 &lt;a href=&quot;https://www.rescuetime.com/&quot;&gt;RescueTime&lt;/a&gt;을 써보기도 했습니다. SNS에 시간을 불필요하게 써왔던 감이 없지 않았고, 정작 내가 필요한 곳에 선택과 집중을 하고 있는 것 같지도 않았습니다. 그래도 다행이었던 점이 있다면, &lt;strong&gt;생산적인 활동에 일주일에 몇시간까지는 써야겠다&lt;/strong&gt;라는 목표가 생겼습니다. 어떻게 보면, &lt;strong&gt;측정과 피드백&lt;/strong&gt;의 산물이라고 볼 수 있겠죠.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;ko&quot; dir=&quot;ltr&quot;&gt;Toggl로 타이머 돌리면 내가 어디에 시간썼는지 차트 뽑아볼 수 있는데, 만족하면서 잘 쓰고 있음 &lt;a href=&quot;https://t.co/cISpXPbHU6&quot;&gt;pic.twitter.com/cISpXPbHU6&lt;/a&gt;&lt;/p&gt;&amp;mdash; Lee Jae-yeol (@kodingwarrior) &lt;a href=&quot;https://twitter.com/kodingwarrior/status/1531061223013244928?ref_src=twsrc%5Etfw&quot;&gt;May 29, 2022&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;당연히, 생산성은 절대적인 시간의 투입량에 비례하는 것도 아닙니다. &lt;strong&gt;너무 많은 진행 중 업무&lt;/strong&gt;도 &lt;code class=&quot;highlighter-rouge&quot;&gt;컨텍스트 스위칭&lt;/code&gt; 비용이 발생하기 때문에, &lt;strong&gt;너무 많은 진행 중 업무&lt;/strong&gt;를 줄여야 합니다. 생산적인 활동에 투입할 수 있는 절대적인 시간의 양은 한정되어 있고, 이를 어떻게 분배할 지 전략을 세워야 합니다. ‘자기계발은 해야겠고, 내가 이루고 싶은 것 때문에 사이드프로젝트는 해야겠고, 본업에는 충실해야겠고, …’ 그래도 어느 쪽이든 진척은 어떻게든 나가야 합니다.&lt;/p&gt;

&lt;p&gt;이에 대한 해결책으로, 카테고리 별로 시간할당제를 두기로 했습니다. 예를 들면, 개인 공부에는 주당 8시간 ~ 14시간, 사이드 프로젝트에는 주당 10시간 ~ 20시간 정도로 두는 겁니다. 그렇다면, 이렇게 정해둔 시간할당제를 어떻게 정확하게 맞출 수 있을까요? 개인적으로 내놓은 답은 &lt;code class=&quot;highlighter-rouge&quot;&gt;Pomodoro&lt;/code&gt; 타이머였습니다.&lt;/p&gt;

&lt;p&gt;어떤 도구를 사용하든 상관없긴 하지만, 진행 중 업무에 시간 자원을 어떻게 사용할 지 의도적으로 제한함으로써 생산성 향상을 시도하고 있습니다.&lt;/p&gt;

&lt;h2 id=&quot;best-practice라도-case-by-case&quot;&gt;Best Practice라도 Case by Case&lt;/h2&gt;

&lt;p&gt;과거의 나 자신에 대해 반성하자면, 모범 사례(Best Practice)를 도입하면 무조건 좋다고 생각하는 쪽에 가까웠어요. 최상의 결과를 이끌어내려면 최고의 툴셋을 써야한다고 봐왔던, 어떻게 보면 빌런에 가까운 사람이었다고 해도 과언이 아니었을 겁니다.&lt;/p&gt;

&lt;p&gt;책의 후반부에서는 &lt;strong&gt;모범 사례를 무작정 도입하는 것의 위험성&lt;/strong&gt;을 강조했습니다. 개인적으로도 많이 와닿았던 구절이기도 했어서, 페이지의 일부를 카메라로 찍어서 트윗으로 공유하기도 했습니다.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;ko&quot; dir=&quot;ltr&quot;&gt;베스트프랙티스는 전후관계를 알고 있을때만 😂😂😂 &lt;a href=&quot;https://t.co/LGUTArwmkG&quot;&gt;pic.twitter.com/LGUTArwmkG&lt;/a&gt;&lt;/p&gt;&amp;mdash; Lee Jae-yeol (@kodingwarrior) &lt;a href=&quot;https://twitter.com/kodingwarrior/status/1513508437204008964?ref_src=twsrc%5Etfw&quot;&gt;April 11, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;모범 사례(Best Practice)를 도입하려면 How(어떻게)를 고민하기 전에 Why(왜)를 고민하는 것이 필요합니다. 협업하고 커뮤니케이션을 하면서 만들어가는 시스템은 조직을 이루는 구성원이 어떻게 일하는지에 대한 이해가 선행되지 않으면 실패할 확률이 큽니다.&lt;/p&gt;

&lt;p&gt;개인적인 경험에 미루어 보았을때도 어디서나 통하는 모범 사례라는 건 절대로 존재하지 않았습니다. 흔히들 쓰는 표현이 있습니다. &lt;code class=&quot;highlighter-rouge&quot;&gt;은탄환은 존재하지 않는다.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;시스템이 없는 상황이고 어떻게라도 시스템을 잡는게 목적이라면 참고자료로 활용하기에는 모범 사례가 더할 나위 없이 좋았습니다. 다만, &lt;strong&gt;‘상황에 맞게 도입할 만 한가?’&lt;/strong&gt; 같은 비판적인 사고가 필요한 것 같습니다.&lt;/p&gt;

&lt;h1 id=&quot;iii-결론&quot;&gt;III. 결론&lt;/h1&gt;

&lt;h2 id=&quot;️-주의할-것&quot;&gt;⚠️ &lt;strong&gt;주의할 것&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;이 책은 &lt;strong&gt;소프트웨어 개발 경험이 있거나, CS를 전공한 사람이라면&lt;/strong&gt; 재밌게 읽을 수 있을지도 모릅니다.&lt;/p&gt;

&lt;p&gt;과연 이렇게 하는게 베스트였나 싶었는데요, 앞서 언급했듯이 &lt;code class=&quot;highlighter-rouge&quot;&gt;컨텍스트 스위칭&lt;/code&gt;이라던가 &lt;code class=&quot;highlighter-rouge&quot;&gt;대기열 이론&lt;/code&gt; 같은 &lt;strong&gt;SW 개발자나 이해할 법한 비유&lt;/strong&gt;가 종종 들어가기 때문에 SW 개발 경험이 있는게 아닌 사람에게는 진입장벽이 느껴질 수도 있습니다.&lt;/p&gt;

&lt;p&gt;하지만, &lt;strong&gt;‘프로젝트 관리’&lt;/strong&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;del&gt;즉, 프로젝트를 하는 사람이라면 반드시 봐야하는 책이라도 봐도 됩니다.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;개인적인 경험을 거론하면서 언급했듯이, 이 책은 저에게 괜찮은 책이었습니다. 프로젝트를 매니징하는 사람을 타겟으로 쓰여진 책이긴 하지만, 스스로를 매니징을 하고자 하는 사람에게도 더할 나위없이 추천할 만한 책입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;꼭 보세요. 두번 보세요.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;이 책을 리뷰하면서, 생산성 도구에 적극적으로 관심을 두었던 얘기를 주저리주저리 읊었는데요. 추후에 생산성을 관리하기 위한 도구들을 추천하는 아티클 시리즈를 발행할 수 있도록 하겠습니다.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">만우절에 해야 했을 블로그 컴백 선언을 하루 늦게 뒷북치게 된 놀랍도록 경악스럽고 충격적인 사건에 대하여</title><link href="https://kodingwarrior.github.io/post/2022/04/02/i-am-back" rel="alternate" type="text/html" title="만우절에 해야 했을 블로그 컴백 선언을 하루 늦게 뒷북치게 된 놀랍도록 경악스럽고 충격적인 사건에 대하여" /><published>2022-04-02T00:00:00+00:00</published><updated>2022-04-02T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2022-04-02-i-am-back.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2022/04/02/i-am-back">&lt;p&gt;안녕하세요. 이재열 개발자 a.k.a. KODING WARRIOR 입니다. 오랜만에 글을 남깁니다. &lt;code class=&quot;highlighter-rouge&quot;&gt;본격적으로 블로그에 글을 남겨야지.. 이번에는 진짜 블로그 써야지...&lt;/code&gt;하다가 이제서야 글을 남기게 되네요.&lt;/p&gt;

&lt;h2 id=&quot;변경된-점&quot;&gt;변경된 점&lt;/h2&gt;

&lt;p&gt;어느새 다시 돌아와보니 블로그가 바뀌어져 있는 점에 놀랄 분도 계실 것이에요. 크게 3가지 정도 바뀌었다고 보면 될 것 같아요.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;블로그의 엔진을 바꿨습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;블로그 엔진을 &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; 기반에서 &lt;a href=&quot;https://www.bridgetownrb.com/&quot;&gt;Bridgetown&lt;/a&gt; 기반으로 바꿨습니다. 딱히, 큰 이유는 없었어요. 볼르그는 새로운 시작을 하고 싶었고, Bridgetown이라는 블로그 엔진이 최근에 1.0.0 메이저 버전으로 공식 릴리즈되어서 한번 써보자는 마인드였거든요.&lt;/p&gt;

&lt;p&gt;근데, 쓰다보니 생각보다 괜찮은 것 같아요. 레퍼런스가 없어보이는건 아쉽지만, 직접 몸을 던지고 있는 입장에서 보면 사용성이 정말 괜찮다고 확신이 들 정도거든요. 어떤 장점이 있었는지는 상반기 중에 블로그로 공유해볼까 싶어요.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;About 페이지도 싹 바꿨습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;구글 독스 기반으로만 레쥬메를 관리해왔었는데요. 개인 홈페이지의 About 페이지가 초라한걸 인지하고는 있었지만 너무 지나치게 방치하고 있었던 것 같았어요.&lt;/p&gt;

&lt;p&gt;블로그를 개편하는 김에, About 페이지도 내용 좀 제대로 채워보자는 마음을 먹게 되었죠. 급하게 채워넣었다보니 R&amp;amp;R이라던가 몇몇 중요한 것들을 채워넣지는 않았어요. 이것도 역시 단계적으로 채워나갈 계획이에요.&lt;/p&gt;

&lt;p&gt;지금의 디자인도 최선의 디자인이 아니라고 생각하고 있어요.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;약간의 CSS도 첨가했습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;풀스택 개발자로서 살아온 경력이 그나마 빛을 발하기라도 했는지, 블로그의 글에 좀 더 가독성이 좋은 방향으로 스타일을 입힐 수 있게 되었어요.&lt;/p&gt;

&lt;p&gt;다만, 프론트엔드 주력도 아니거니와 디자인이라고는 감으로 해왔기 때문에 Bridgetown 엔진의 테마를 직접 제작하는 것까지는 무리가 있을 것 같아요. 개인적인 취향으로는 싸이버 펑크 내지는 칩튠 감성을 좋아하지만… 제 역량으로는 무리라는 걸 알아요.&lt;/p&gt;

&lt;p&gt;지금 당장에는, 가독성을 좀 더 좋게 유지하는 방향으로 디자인을 개선하는데 집중하려고 해요.&lt;/p&gt;

&lt;h2 id=&quot;블로그의-운영-방식에-대해&quot;&gt;블로그의 운영 방식에 대해…&lt;/h2&gt;

&lt;p&gt;사실 저도 어떻게 해야할지는 크게 방향성을 잡지는 않았어요. 다만, &lt;strong&gt;어떤 형태로든 글을 꾸준히 남기는 루틴&lt;/strong&gt;을 만들어야겠다는 자각이 언제부턴가 들기 시작했어요. 어떻게든 방법을 찾아서 &lt;strong&gt;나에게 맞는 방식을 조금씩 만들어가려고 합니다&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;개발자로서 일을 하다 보면, 여러가지 일들을 마주히게 됩니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;이직하게 될 회사에 스스로를 어필하기 위해서 이력서를 다듬는다던가&lt;/li&gt;
  &lt;li&gt;내가 &lt;del&gt;싸지른 똥&lt;/del&gt; 작성한 코드를 유지보수하게 될 개발자를 위해서 인수인계 가이드 문서를 작성하게 된다던가&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;내가 지금까지 해왔던 일들, 내가 지금까지 해왔던 공부들, 내가 지금까지 배워왔던 것들. 이 모든 것들을 기록의 형태로 남기지 않고 방치했다가 나중에 업보로 되돌아오는 순간들을 여러번 경험했었던 것 같아요.&lt;/p&gt;

&lt;p&gt;프로그래밍 실력 뿐만이 아니라 문서화 능력과 커뮤니케이션 능력도 역시 내가 필수적으로 단련해야 하는 영역이라는걸 세월이 지나면서 실감하게 됩니다.&lt;/p&gt;

&lt;p&gt;최근 들어, 어떤 회사에서 개발팀장으로 일을 하기 시작했는데, &lt;strong&gt;cross-functional&lt;/strong&gt;한 개발자가 되는 것을 지향하는 저로서는 당장에라도 스스로를 디버깅하지 않으면 안되겠다는 생각이 들었구요.&lt;/p&gt;

&lt;p&gt;현재의 내가 가진 문제점, 현재의 내가 가진 한계점을 인지하고, 지금 당장의 내 모습이 시원치 않아도 상관없으니 어떻게든 메트릭을 많이 만들어서 개선할 부분은 빨리 개선하는 방향으로 노선을 틀었어요. 병도 숨기고 다니고 있어봐야 나중에 더 큰 병으로 돌아오듯이, 내가 가진 단점도 숨기고 다녀봐야 스노우볼처럼 커질테니까요.&lt;/p&gt;

&lt;h2 id=&quot;글-잘쓰기-금지&quot;&gt;글 잘쓰기 금지&lt;/h2&gt;

&lt;p&gt;얼마 전에, 제가 존경하는 모 개발자님으로부터 어떤 책을 추천받은 적이 있는데요. 아직 중간까지 밖에 읽지는 못했지만, 저에게 유익하고 너무나 필요했던 책이었어요. 일러스트레이터 및 만화가를 위한 책으로 보이겠지만, 프로덕트를 창작하는 개발자한테도 도움되는 책이니 꼭 읽어보시는 것을 권장합니다.&lt;/p&gt;

&lt;div class=&quot;flex justify-center&quot;&gt;
    &lt;img width=&quot;250&quot; src=&quot;{{ &apos;/images/dont-draw-well.jpg&apos; | relative_url }}&quot; /&gt;
&lt;/div&gt;

&lt;p class=&quot;text-center&quot;&gt;잘 그리기 금지 - 사이토 나오키&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;알라딘 : &lt;a href=&quot;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=284106373&quot;&gt;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=284106373&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;책의 요지는 이거였어요. &lt;code class=&quot;highlighter-rouge&quot;&gt;처음부터 완벽하려고 하면 스스로에게 독이 된다. 작은 것이라도 꾸준히 제대로 하면서 성취감을 쌓는 것이 중요하다.&lt;/code&gt; 하루에 한 포스트 씩 쓰지는 못하더라도, &lt;strong&gt;어느 정도 주기를 가지고 글을 발행&lt;/strong&gt;하는 버릇은 들여보려고 합니다.&lt;/p&gt;

&lt;p&gt;딱히 성취감이 목적인 것은 아니지만, 빠른 이터레이션을 돌면서 기능을 개발하고 버그 픽스하는 개발자들의 습관처럼, 글쓰는 내 모습도 역시 점진적으로 디버깅하고 싶어요.&lt;/p&gt;

&lt;h2 id=&quot;혼란을-틈탄-디스코드-홍보&quot;&gt;혼란을 틈탄 디스코드 홍보&lt;/h2&gt;

&lt;p&gt;전 언제든지 조금씩이라도 스스로 디버깅을 해나갈거에요. 다만, 나 혼자서는 스스로 디버깅하는 것에 한계가 있다고 생각해요. 저에게 적극적으로 피드백 주는 것에 관심있으신 분이라면, 저의 개인 디스코드에 조인해주시면 정말 감사할 것 같아요.&lt;/p&gt;

&lt;div class=&quot;flex justify-center&quot;&gt;
&lt;iframe src=&quot;https://discord.com/widget?id=848681351750483988&amp;amp;theme=dark&quot; width=&quot;250&quot; height=&quot;500&quot; allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; sandbox=&quot;allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
저의 개인 디스코드에 대해 설명하자면, 다음과 같아요.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;신원이 확인되신 분만 이용할 수 있어요.&lt;/strong&gt; 처음에 들어가면 공지밖에 안보이실텐데요, 신원확인이 되는 사람만 이용할 수 있도록 수동으로 권한을 드리고 있어요.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;영감을 얻기 위한 자료들을 아카이빙해요.&lt;/strong&gt; 구독하고 있는 여러 곳의 채널에서 감명깊게 읽었던 아티클들, 감명깊게 읽었던 트윗, 신기하다는 생각이 드는 프로젝트들을 공유해요. 개인적으로는 유튜브 채널을 운영하는데도 관심이 있어서, 블로그에 올릴 내용이나 유튜브에 올릴 강의자료를 사전 리뷰하는 목적으로도 사용하려고 해요.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;다른 커뮤니티에 정보를 공유하기 전에, Cache의 역할로 사용해요.&lt;/strong&gt; 정보무역상을 자처하는 입장으로서, 다른 커뮤니티에 적절한 정보를 공유하는걸 좋아하는데요. 커뮤니티에 공유하기 전에 적법성의 여부를 떠나서 가장 먼저 공유하는 채널의 역할을 하게 될 것 같아요.&lt;/li&gt;
  &lt;li&gt;개발자가 참여하면 좋을 행사의 정보도 간간히 올라갈 수도 있어요.&lt;/li&gt;
  &lt;li&gt;개인적으로 강하게 친분이 있는 분들은 친목하는 채널이 따로 있지만, 디폴트로는 음지로 남기고 있어요.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;끝내며&quot;&gt;끝내며&lt;/h2&gt;

&lt;p&gt;아무튼 복귀한 김에 이런저런 얘기를 하느라 말이 길어졌네요. 앞으로 문체를 구어체로 갈 지 평어체로 갈 지는 알 수 없겠지만, 일단 어떻게든 꾸준히 글을 써내려가려고 합니다.&lt;/p&gt;

&lt;p&gt;떠벌림 주도 개발이라는 용어가 있듯이, 떠벌림 주도 블로깅도 어쩌면 가능하지 않을까요?&lt;/p&gt;
&lt;hr /&gt;

&lt;p class=&quot;text-center&quot;&gt;앞으로 잘 부탁드리겠습니다.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">「고양이도 할 수 있는 Vue.js」 리뷰</title><link href="https://kodingwarrior.github.io/post/2019/10/02/review-of-cat-vue-js-book" rel="alternate" type="text/html" title="「고양이도 할 수 있는 Vue.js」 리뷰" /><published>2019-10-02T02:27:00+00:00</published><updated>2019-10-02T02:27:00+00:00</updated><id>repo://posts.collection/_posts/2019-10-02-review-of-cat-vue-js-book.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2019/10/02/review-of-cat-vue-js-book">&lt;p&gt;필자는 회사에서 프론트엔드 프레임워크 &lt;strong&gt;Vue.js&lt;/strong&gt;를 이용하여 프론트엔드 개발을 하고 있으며, 개발 언어는 &lt;strong&gt;Typescript&lt;/strong&gt;를 쓰고 있다. 제이펍 출판사의 이벤트에 당첨되어, “고양이도 할 수 있는 Vue.js”라는 책을 받았으며 아래와 같이 후기를 남긴다.&lt;/p&gt;

&lt;h1 id=&quot;i-선행-지식&quot;&gt;I. 선행 지식&lt;/h1&gt;

&lt;p&gt;이 책을 읽으려면 약간의 선행지식이 필요하다.&lt;/p&gt;

&lt;p&gt;초보자도 이해할 수 있는 책인건 분명하지만, 어느 정도 배경지식은 갖추고 있어야 이해할 수 있음을 밝혀둔다. 이 중에 하나라도 모르는 것이 있다면, 이 책만으로는 공부하는데 어려움이 있을 것이다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;HTML/CSS 기본 지식&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 책을 구매하려고 고민중인 사람들이 &lt;strong&gt;Vue.js&lt;/strong&gt;를 어떤 목적으로 배우려고 하는지는 모르겠다. 하지만, &lt;strong&gt;Vue.js&lt;/strong&gt;로 개발하려면 &lt;strong&gt;HTML/CSS&lt;/strong&gt;로 페이지를 윤곽잡는 것부터 시작하기 때문에 &lt;strong&gt;HTML/CSS&lt;/strong&gt;에 대한 배경지식은 필수적으로 요구된다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;자바스크립트 기본 지식&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vue.js는 이름만 봐도 알 수 있듯이 자바스크립트로 짜여진 프레임워크이다. 자바스크립트로 짜여진 프레임워크를 이용하려면 당연히 자바스크립트에 대한 지식은 필수라고 할 수 있다.&lt;/p&gt;

&lt;p&gt;그럼 자바스크립트 문법만 대충 알고 가도 되냐? 그렇지도 않다. 자바스크립트 문법을 아는 것 만으로는 충분하지 않다. &lt;strong&gt;Vue.js&lt;/strong&gt;의 주된 용도는 자바스크립트로 UI를 구성하는 것이기 때문에, 자바스크립트를 이용해서 DOM 요소를 어떻게 조작하는지는 알고 있어야 할 것이다.&lt;/p&gt;

&lt;p&gt;여기까지도 이해하고 있다면, 책을 펼치고 공부하는데 어려움이 없을 것이다.&lt;/p&gt;

&lt;p&gt;아직 준비가 되어 있지 않았음에도 지금 당장 뛰어들어보고 싶다면, W3School(&lt;a href=&quot;https://www.w3schools.com/&quot;&gt;https://www.w3schools.com/&lt;/a&gt;)과 함께하기를 권장한다.&lt;/p&gt;

&lt;h1 id=&quot;ii-책의-구성&quot;&gt;II. 책의 구성&lt;/h1&gt;

&lt;p&gt;어떤 책인지 알 수 있는 방법은 뭐니뭐니해도 목차를 살펴보는 방법이라 할 수 있다. 책의 구성을 살펴보자. 책은 9개의 장(Chapter)과 55개의 절(Section)로 구성되어 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;전반부에서는 Vue.js의 기본적인 기능을 설명하고 있다.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;1장&lt;/strong&gt; Vue.js 프레임워크의 기초&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;2장&lt;/strong&gt; 데이터 등록과 변경&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;3장&lt;/strong&gt; 이벤트와 입력 양식&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;4장&lt;/strong&gt; 데이터 감시하고 가공하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;5장&lt;/strong&gt; 컴포넌트로 UI 부품 만들기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;6장&lt;/strong&gt; 트랜지션과 애니메이션&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;후반부에서는 자바스크립트, Vue.js 생태계를 활용해서 본격적으로 개발하는 방법을 설명하고 있다.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;7장&lt;/strong&gt; 큰 규모의 애플리케이션 개발하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;8장&lt;/strong&gt; Vuex로 애플리케이션 상태 관리하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;9장&lt;/strong&gt; Vue Router로 SPA 만들기&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;목차만 봐도 알 수 있듯이 이 책은 A-Z까지 친절하게 설명해주고 있다. Vue.js의 키 컨셉을 설명하는 것부터 시작해서, 컴포넌트를 조합해서 어플리케이션의 기능을 구현하는 방법을 살펴보고, Vue.js 생태계를 활용해서 큰 규모의 어플리케이션을 만들 수 있도록 안내해준다.&lt;/p&gt;

&lt;p&gt;완전히 초보자를 위한 책은 아니지만, Vue.js를 처음 접하는 사람들에게는 꽤 권장할 만하다.&lt;/p&gt;

&lt;h3 id=&quot;직관적인-이해를-돕는-일러스트&quot;&gt;직관적인 이해를 돕는 일러스트&lt;/h3&gt;

&lt;p&gt;입문서로서 이 책이 무엇보다 좋은 점은 중간중간에 동작원리를 설명하는 삽화가 잘 삽입되어있다는 점이다. 책의 원 저자가 엔지니어 겸 디자이너이다보니 삽화의 퀄리티도 제법 괜찮은 편이었다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/4cTk9gJ93qWp7PdKrWau0n7I2b8mxN1jQECbL3fPmWhqc1KcSVBIwKCZ1osMVHAfnsoah3X4HEfOZO7Hm5LTWO4_cqTckofJpiBEkZv3NfizGU-6H-Q6jo38Za-CLqwR9he97TBJtq9YrdmrOY-D57ef_w9TBQ7W_nLymyruoLuep8qK6cCcrR1db3XkDVEXNGAtWBmjrl_mmLMldBM42e0uN4kF6JI5kRPVDlQCv6XW99cnyMpN538CyAOGpK4MksXvYrKf-oGhW2op9-eipe_A_MIlA4M7rA1La2CbiElSzoYNuVQbJgI_y0_VsEzomYjJamTZUfqIDutG30sJbcsYpOaRmAgGp0WHLvPzZclQgwvMjHwueuMy3RWvjatPbCv-hQJmhuuRxJXgqZSvtiTFA1L_NxX0X6acd2UwxeP8MLSmJG96wzwNwz8PlTxhwyohFf9RY9o5EMqvk6JKYKnvA_t1iqjMC2a1saktAlLL_VVw5N-LeAA3CygASqtDY-nLhyE8chiSvK8KRy4TL9JBmeMHEhcKN8YXWy6EylTaTIKOHFG8p1bx3U_5p56Fk-GqfaXaQGnSr7kim-OWnGiLKkSDHY-HXQriS9qkC8okyw0cMhH1u2fIbkIE4EeSLlS-OOGhhd4-4X5Vn2K8zeop2SFvdWW2JGeDYSbE67AjlD0zkinoU-M=w947-h411-no&quot; alt=&quot;컴포넌트를 조합해서 복잡한 구성의 페이지를 간단하게 만들 수 있다는 것을 의미내는 삽화&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;컴포넌트를 조합해서 복잡한 구성의 페이지를 간단하게 만들 수 있다는 것을 의미내는 삽화&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/zYuBZoP6d-VnxkyrjqNoGG_HXCYFiHHSbsL2c0wmeTtkaVAp9aODH7F3M0CNziHaCFKTaOVnS8BTmb2Zfj0S26WA25vQA-KhH6t_27upGeU1DOlKRcR0gIUvCItRa6NYxIo0pPmr_yOPMXZAtAak4maW_drUHJD4WMH7fbHjBjOizeysCXxfmOBTZEVBDKzN5ArH07KwAH5uyqSS5DBcJcWKW1W-MI7qoNpM0X9ld4aZzMcNVJIpj3Ns5TQIhsrQ6HmlH0sKFwqW30LkyJzr3xygKpWymqP7DgITdlaEYmcqwFUhJoy0NkIv7JxzuUAt2BddYSw-WjDKdmTolpYt22E0KzINmkmviYdlGBDXj_0fzat31LiHQuQZsKaNFLkO-KWxhHMiL3giTs_9amTq0KpqFXm5NsgNYbRRrfKAzgeOvmGcRxJxjGUxXXZ9jRDujWqKEcRicp_Xl-AJ-56clqkHuVt_p5n_EFzvcXsCRSUvulHfet2qub180Xp2WmD9g1_vryQqxYZvU7Mr98ZZt5Ay1VWfTT1_ZWyj2F5j8ZYsqe7A8eLq_FKKVBkwvCUfl4vvH9Rfrj_MT1mT75cYETdZQ3GxPBS6_RSClXjPlev72GG0jZqN28bBSRAo9l6wAdauBNNV_VYmnvt5CnFZzNP2NeGmeMYBtz-zhi-RI_y6_Q8oPm99qCE=w884-h354-no&quot; alt=&quot;재사용가능한 컴포넌트를 활용해서 동일한 모양의 UI 요소를 간단하게 만들어냄을 의미하는 삽화&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;재사용가능한 컴포넌트를 활용해서 동일한 모양의 UI 요소를 간단하게 만들어냄을 의미하는 삽화&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/bKE22lskhWZnnzd-E3bXKhy9pECMZa5m8mzz9uP38NyW5QyJrNKOFFwYr9LSXhqF8-GAvezxhNGEgVIzCx1t2NjrV1hr3BAHF-ub_opySSf6IbIuu6i9Eh1xlJaN6cuEW5Kt8BJESuvRnWjs_DUHb2uieEYgtMbkHaqf8O19F8EUIlOnON--rwmdhm5_MB8Yc-JFkdCD4gNVhK9jagWoSmyJVQHPRGYJ5EVtt-0CqjN4JsDs7d4CecCxLEudMYLmIhnirIPaV-gCGyhmAGoHwYQt4xYjjvsEc7gYX0CcGdirZlWZJVHT3kdOEvT9W7rOM4yt2WI_Ur5xSpZL2nbaybmh3C2m-7IhCcFpBdtICBkRp8HjXxi6p-OSvPxqg0KLvkXJvO9EHHvGEUvkj4LJy_H5pVXPOQlr15Aa6g9udiPypRI2PEVJ2pLagsqb3pY4ycVzdu7B-SzeCqcUCNkvpexNSQYl4Mo80GnSJghC2YZRn_sWismelAC-7vvr8fZQK7RjJSXYWxiIMIAtxapNKawfO5twTvXmNqvadfK9Y3iVxnbJmRQ5DBUP7OuXXSWcm66lz3ZYfGe-Kyb54phSVZkUuRo3XNLoh_OdjP5vXS41aQceVqHCtQxsxQ38NdYibJ4ogWvvkIVIZxm7Ut2wL4D4xZLKzCyJ6UP7iRFxWWv1hpJKGyRtX8kj6YAmKz0vGL3_uXnOuPc5snzQE5-JwLp2i0p88-3X3XFH12wrvfadwnvv=w884-h354-no&quot; alt=&quot;트랜지션 태그가 동작하는 모습을 설명하는 삽화&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;트랜지션 태그가 동작하는 모습을 설명하는 삽화&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;책-못지-않게-완성도-있는-보조-자료&quot;&gt;책 못지 않게 완성도 있는 보조 자료&lt;/h3&gt;

&lt;p&gt;책의 이해를 돕기 위해 배포된 메뉴얼 페이지도 인상적으로 와닿았다. 원본은 일본어로 되어 있지만, 한글 버전으로 옮겨진 버전이 있다. 원서 못지 않은 정성을 발휘해서 번역하신 번역가분께 리스펙을 표현하고 싶다. &lt;a href=&quot;https://rintiantta.github.io/jpub-vue&quot;&gt;https://rintiantta.github.io/jpub-vue&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/4XO0sIGQrKQNEJBrz-IJjhJamjRUYfDtUCCdJ6yt7h390-mVcE8Uu-tp-vc6bmkFo079TEJCqh8Ri7s1xqGaJCfW-4rk22lTq4YWSyetJfRr8-O0yVbeF2MGaPbglg-sMqp8vHBE1DlWYPCSFid-XwKHLampPxFugnVGlFsJUAa2Unk7oTXltT66eq4Ce0GJFxH2PLvldD8na3qEUFICi2UEMYTQvRLuuA9jllsSs7wwz5AK7E9Ye-98QHBF5rX-URCH4fx0GS9h_FBXyXQl4r64zTcedIw47FbPlo-U9C3VViMMdBwDoVrQxkWrgAeCTQqFTelIPfZpDa9mq6K4Zw51ObZFb1wzNImBLoV-MF7wJGot_1KmYpBWtwykrXda0GzJDKcs_rMqc2W-zieQ1zMsPvcDOC5CKqQSfqzYVZwygWeHBDsPmnmSH7I8OYvIS31kF1a6Jw7yDBGWyeVv9uHvg6s2X1jG-0jeL4lq2i_5A-C81ei2vuyAwmnP8IC-nPOcFfwEbqyercKXQiptDGBBDOnUEKLgq7NRsLFK9w0cCu0GeiZYhOcJYkh6eTiK9asw-l2TWClLUG9SF1qVjfc65uHIJkfCcognm6W4kdnyHWqLZsm-5dINZzGxwUWoOgCj9RSNUZ_2g1P2WiHmJQ_w-92XGu_GNKkZZrzoG6MGYlq-sqI6KxI=w1365-h759-no&quot; alt=&quot;메뉴얼 탭에서는 책에서 설명했던 소스코드들이 나열되어 있으며, 소스코드를 실행한 결과를 눈으로 직접 확인해볼 수 있다.&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;메뉴얼 탭에서는 책에서 설명했던 소스코드들이 나열되어 있으며, 소스코드를 실행한 결과를 눈으로 직접 확인해볼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/G-p-cpaYl_JNzpecQs1Rro5jj3J490ZxXg7gFbQJ9h2XxC1xvUln1p62STRoC2-AU4IwnoI1rHMoTykGiaLI1vRB-QLT3ss5pkVvpQIhDPNcDrTq-xGZTsl9uY0iDy5xAN3FsfaOJLViGVq4Mx4oYR2cd1EQS2aA18vizvWLMMq2qFu7jbTnqMsr5LJKWw22lZf7MqtuFgzvqVDR511riIufxIGOL3sj2zEPMc1G51VrH8QGjjKOvwfVlU4PBN0oHaECpyBL9GwH6BLCNc-ricfSYnpDkyUh9p5hft0CYH46xacitf_it2aaXcVixh5bKZHuB15ExHDSfNmNGx4XvlAXdp1cIMHmeMKsmX9T_o3XVihUdX9ckUh5IwisyIsNnNSfvkQ4C0SWs5XhyvNWeFMoxZ7HrzhojyAFYHpQKfibF-v0R04kQDb6CIk7Vk-tEoeLVTYufVXmcF8uzRN2FHPQoGVtQmRoPnu5wLCpg1PZd4dHzkNh-rxfDqQEXxqAgDQXAR7xjwNh_0XgV-xFyuvcTH2rNDjdgt8j17y_ECJwJkSKkzGWqH0qgrJuPnuyBlMLIEHuOxxW-T2cSq6cRw4xJMl4ZtqxgbRebF_80322e_f5P93-hUDcXndWwSUXZPqsO1Gg8AHAl86kT0gZ4uOwcJqJPs8bFo1SLov85pl59Ucq0Wz4QTY=w1365-h803-no&quot; alt=&quot;메뉴얼 페이지는 Vue.js를 이용한 소스코드를 직접 돌려볼 수 있도록 개발되어 있다.&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;메뉴얼 페이지는 Vue.js를 이용한 소스코드를 직접 돌려볼 수 있도록 개발되어 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;iii-결론&quot;&gt;III. 결론&lt;/h1&gt;

&lt;p&gt;이 책은 초보자도 이해할 수 있는 수준으로 설명이 잘 되어 있다. &lt;strong&gt;Vue.js&lt;/strong&gt;는 공식 가이드만 봐도 사용법을 한번에 이해할 수 있을 정도로 문서화가 잘 되어 있는 것으로 잘 알려져 있으나, 본 교재는 &lt;strong&gt;Vue.js&lt;/strong&gt; 가이드를 보고도 이해가 되지 않는 점들을 삽화까지 첨부하면서 이해시키려고 노력하고 있다. &lt;strong&gt;Vue.js&lt;/strong&gt; 가이드가 어렵게 느껴진다면, 한번쯤은 구매를 생각해볼만 하다.&lt;/p&gt;

&lt;p&gt;이미 &lt;strong&gt;Vue.js&lt;/strong&gt; 사용법을 알고 있는 시점에서 이 책을 읽긴 했지만, 애매하게 알고 있었던 부분을 제대로 이해하는데 도움을 얻을 수 있었다. 주어진 시간이 얼마 없는 개발자라면, 쓱 훑어보면서 대략적인 컨셉을 이해하고, 필요할 때마다 관련된 챕터를 공부해보는 방법도 괜찮을 것이라 감히 권장해본다.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">Kotlin으로 C++의 lower_bound, upper_bound 함수 구현하기</title><link href="https://kodingwarrior.github.io/post/2019/04/13/implementing-lower-bound-using-kotlin" rel="alternate" type="text/html" title="Kotlin으로 C++의 lower_bound, upper_bound 함수 구현하기" /><published>2019-04-13T16:31:00+00:00</published><updated>2019-04-13T16:31:00+00:00</updated><id>repo://posts.collection/_posts/2019-04-13-Implementing-Lower-Bound-Using-Kotlin.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2019/04/13/implementing-lower-bound-using-kotlin">&lt;blockquote&gt;
  &lt;p&gt;TL;DR&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt;를 구현할 때 반열린 구간 Notation을 지키는 것이 좋다.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt; 구현하기
      &lt;ol&gt;
        &lt;li&gt;이분탐색을 수행하듯이 lo, mid, hi 파라미터를 반복문 돌려가면서 적당히 조정한다.(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;while(lo &amp;lt; hi)&lt;/code&gt;&lt;/strong&gt;)&lt;/li&gt;
        &lt;li&gt;mid가 가리키는 값이 &lt;strong&gt;value보다 작으면(&lt;code class=&quot;highlighter-rouge&quot;&gt;elements[mid] &amp;lt; value&lt;/code&gt;)&lt;/strong&gt;, 탐색해야 하는 범위가 뒤쪽에 있다고 가정한다. → &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lo = mid + 1&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
        &lt;li&gt;mid가 가리키는 값이 &lt;strong&gt;value보다 크거나 같으면&lt;/strong&gt;(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;elements[mid] ≥ value&lt;/code&gt;&lt;/strong&gt;),  탐색해야 하는 범위는 좁혀진다.(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;high = mid&lt;/code&gt;&lt;/strong&gt;)&lt;/li&gt;
        &lt;li&gt;탐색에 성공하여 value 이상의 값이 처음 나타나는 위치를 발견하게 된다면, 탐색 범위가 좁혀진 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lo&lt;/code&gt;&lt;/strong&gt;(==&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;hi&lt;/code&gt;&lt;/strong&gt;)를 반환한다.&lt;/li&gt;
        &lt;li&gt;탐색에 실패하여 mid가 포함되지 않는 구간인 high에 도달하게 된다면, 없다고 가정하고 high를 반환한다.&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt; 구현하기
      &lt;ol&gt;
        &lt;li&gt;이분탐색을 수행하듯이 lo, mid, hi 파라미터를 반복문 돌려가면서 적당히 조정한다.(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;while(lo &amp;lt; hi)&lt;/code&gt;&lt;/strong&gt;)&lt;/li&gt;
        &lt;li&gt;mid가 가리키는 값이 &lt;strong&gt;value보다 작거나 같으면(&lt;code class=&quot;highlighter-rouge&quot;&gt;elements[mid] &amp;lt;= value&lt;/code&gt;&lt;/strong&gt;), 탐색해야 하는 범위가 뒤쪽에 있다고 가정한다. → &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lo = mid + 1&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
        &lt;li&gt;mid가 가리키는 값이 &lt;strong&gt;value보다 크면&lt;/strong&gt;(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;elements[mid] &amp;gt; value&lt;/code&gt;&lt;/strong&gt;), 탐색해야 하는 범위는 좁혀진다.(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;high = mid&lt;/code&gt;&lt;/strong&gt;)&lt;/li&gt;
        &lt;li&gt;탐색에 성공하여 value를 넘는 값이 처음 나타나는 위치를 발견하게 된다면, 탐색 범위가 좁혀진 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lo&lt;/code&gt;&lt;/strong&gt;(==&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;hi&lt;/code&gt;&lt;/strong&gt;)를 반환한다.&lt;/li&gt;
        &lt;li&gt;mid가 포함되지 않는 구간인 high에 도달하게 된다면, 없다고 가정하고 high를 반환한다.&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Kotlin&lt;/strong&gt; 믿고 잡숴보시라&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;이 글에서는 &lt;strong&gt;Kotlin&lt;/strong&gt;을 이용해서, &lt;strong&gt;C++&lt;/strong&gt;의 STL에서 제공되는 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt; 함수를 어떻게 구현하게 되었는지 공유하고자 한다.&lt;/p&gt;

&lt;p&gt;프로그래밍 대회 준비/학회 내부 알고리즘 교육 때문에 &lt;strong&gt;C++&lt;/strong&gt;로 알고리즘 문제를 풀어왔었지만, 학부 생활을 벗어나니 &lt;strong&gt;C++&lt;/strong&gt;를 쓸 일도 없어졌다. &lt;strong&gt;웹 개발자&lt;/strong&gt;로서 주로 접하게 되는 언어는 &lt;strong&gt;Java&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;Ruby&lt;/strong&gt;, &lt;strong&gt;Javascript&lt;/strong&gt; 정도 밖에 되지 않는다. 그 중에서도 &lt;a href=&quot;https://acmicpc.net&quot;&gt;Baekjoon Online Judge&lt;/a&gt;에서 대부분의 알고리즘 문제를 풀 수 있으려면 가장 무난한 언어가 &lt;strong&gt;Java&lt;/strong&gt;였다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Java로 알고리즘 문제 푸는 걸 연습해야겠다&lt;/code&gt;&lt;/strong&gt;고 결심이 들던 와중 &lt;a href=&quot;https://www.acmicpc.net/blog/view/71&quot;&gt;이런 글&lt;/a&gt;을 발견했다. &lt;strong&gt;Kotlin&lt;/strong&gt;을 이용해서 알고리즘 문제를 푸는 방법을 기초적인 수준에서 설명하는 글이다. 뒤에서 설명하겠지만, &lt;strong&gt;Java&lt;/strong&gt;로 알고리즘 문제를 푸는 행위에 회의감을 느끼던 나에게는 상당히 흥미롭게 느껴졌고, &lt;a href=&quot;https://shiftpsh.com/&quot;&gt;저자 분&lt;/a&gt;에게 직접 이것저것 물어보면서 &lt;strong&gt;Kotlin&lt;/strong&gt;으로 알고리즘 문제를 푸는 방법을 연마하는 중이다.&lt;/p&gt;

&lt;h2 id=&quot;kotlin으로-ps를-하면서-느낀-점&quot;&gt;Kotlin으로 PS를 하면서 느낀 점&lt;/h2&gt;

&lt;p&gt;대략 &lt;strong&gt;4월 초&lt;/strong&gt;부터 &lt;strong&gt;Kotlin&lt;/strong&gt;으로 알고리즘 문제를 풀기 시작했다. &lt;strong&gt;C++&lt;/strong&gt;가 아닌 언어로 알고리즘 문제를 풀어놓은 흔적을 남겨놓은 &lt;a href=&quot;https://github.com/malkoG/polyglot-cp&quot;&gt;리포지토리&lt;/a&gt;를 한달 전부터 유지하고 있는데, &lt;code class=&quot;highlighter-rouge&quot;&gt;.kt&lt;/code&gt; 확장자가 보인다면 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;이게 Kotlin으로 풀이한거구나&lt;/code&gt;&lt;/strong&gt;하고 이해하면 된다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt;&lt;/strong&gt;으로 알고리즘 문제를 풀게 된 건 그렇게 오래되지는 않았지만, 1주~2주의 짧은 기간 동안 건드리면서 느꼈던 점들을 간단하게 아래에서 정리했다.&lt;/p&gt;

&lt;h3 id=&quot;좋았던-점&quot;&gt;&lt;strong&gt;좋았던 점&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Java&lt;/strong&gt;와 100% 호환되기 때문에, &lt;strong&gt;Java&lt;/strong&gt;에서 제공하는 클래스를 그대로 끌어다 쓸 수 있다. (컨테이너 클래스는 &lt;strong&gt;C++&lt;/strong&gt; 못지 않다)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Java&lt;/strong&gt;로 코딩하는 방식에 비해, 불편한 점이 상당히 줄었다.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Pair&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Triple&lt;/code&gt;&lt;/strong&gt; 자료구조를 지원한다.  (&lt;strong&gt;Java&lt;/strong&gt;에서는 이런 자료구조까지 클래스와 생성자로 직접 정의해야 했고, 정렬할 때도 정렬 함수를 따로 정의해줘야 하는 불편함이 있다. 하지만 코틀린에서는? 그런거 없다. 이미 만들어져 있고, 생성자도 잘 정의되어 있고, 정렬 함수도 납득할만한 수준으로 잘 정의되어 있다. &lt;strong&gt;C++&lt;/strong&gt;에서 옮겨와도 크게 불편함이 없을 수준이다.)&lt;/li&gt;
      &lt;li&gt;디폴트 파라미터를 지원한다.&lt;/li&gt;
      &lt;li&gt;연산자 오버로딩을 지원한다. (&lt;strong&gt;Java&lt;/strong&gt;에서는 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt;&lt;/strong&gt; 컬렉션에 random access를 할 때, &lt;code class=&quot;highlighter-rouge&quot;&gt;.at(idx)&lt;/code&gt; 노테이션을 이용해서 접근해야 하는 불편함이 있었지만, &lt;strong&gt;Kotlin&lt;/strong&gt;에서는 random access를 할 때 &lt;code class=&quot;highlighter-rouge&quot;&gt;[idx]&lt;/code&gt; 노테이션으로 접근하기만 하면 된다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt;&lt;/strong&gt;도 마찬가지로 적용된다.)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;typealias&lt;/code&gt;&lt;/strong&gt;를 지원한다. (&lt;strong&gt;Java&lt;/strong&gt;는 상속으로 흉내내야 한다.)&lt;/li&gt;
      &lt;li&gt;불필요한 OOP 문법을 적용하지 않아도 된다.(&lt;strong&gt;Kotlin&lt;/strong&gt;으로 문제 풀면서 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;public static class&lt;/code&gt;&lt;/strong&gt; 이런걸 거의 보지 않았던 것 같다.)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;C++&lt;/strong&gt; 최신 표준 못지 않게 현대적인 문법이 많이 제공된다. (destructuring, 메서드 연쇄 중 어딘가에서 null이 튀어나오면 null을 리턴하는 등 Optional type에 대한 우아한 처리)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;아쉬웠던-점&quot;&gt;&lt;strong&gt;아쉬웠던 점&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;C++&lt;/strong&gt;에 비해 제공되는 함수가 적다. 정확히는, 필요한데 제공되지 않는 함수들이 있어서 빈자리가 느껴진다.(&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound/upper_bound&lt;/code&gt;&lt;/strong&gt; 등 이분 탐색을 응용한 함수, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;next_permutation/prev_permutation&lt;/code&gt;&lt;/strong&gt; 등 순열을 다루는 함수)&lt;/li&gt;
  &lt;li&gt;컴파일 속도가 좀 느리다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Java&lt;/strong&gt;와 100% 호환이 되는 건 좋지만, 공식 문서가 모자란 것 같다는 느낌이 든다. (&lt;strong&gt;Java&lt;/strong&gt; 공식 문서를 더 많이 봤던 것 같다.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;없으면-직접-만들어야지-뭐&quot;&gt;없으면 직접 만들어야지, 뭐…&lt;/h2&gt;

&lt;p&gt;알고리즘 문제 중에는 이분탐색으로 분류된 여러가지 문제가 있는데, 이분탐색으로 분류된 문제 중에는 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt; 함수를 이용해야만 편리하게 풀 수 있는 문제들이 있다. 하지만, 위에서 언급했다시피 &lt;strong&gt;Kotlin에서는 이런 함수를 가져다 쓸 수가 없다&lt;/strong&gt;. 그러면 뭐다? 직접 만들어야지.&lt;/p&gt;

&lt;h3 id=&quot;lower_bound&quot;&gt;&lt;strong&gt;lower_bound&lt;/strong&gt;&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;C++에서 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt; 함수를 어떻게 활용하는지는 &lt;a href=&quot;https://en.cppreference.com/w/cpp/algorithm/lower_bound&quot;&gt;여기&lt;/a&gt;에서 볼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;는 정렬된 리스트 내에서 특정 값 이상의 값이 처음 나타나는 위치를 반환하는 함수로 구현되어야 한다. 일단, 구현되는 원리는 이분탐색에서 기반한 거라고 주워들은 게 있었기 때문에, &lt;strong&gt;Parametric Search&lt;/strong&gt;를 적용하던 방식을 떠올리기 시작했다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parametric Search&lt;/strong&gt;는 어떤 값이 정답일 지 알 수 없지만, &lt;strong&gt;결과값 y&lt;/strong&gt;가 결정되어 있을 때 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x) = y&lt;/code&gt;&lt;/strong&gt; 식을 만족하도록 이분탐색으로 solution이 될 수 있는 범위를 좁혀가면서 solution x의 최솟값/최댓값을 구하는데 쓰이는 알고리즘이다. &lt;strong&gt;Parametric Search&lt;/strong&gt;를 적용할 수 있으려면, 적용되는 함수가 &lt;strong&gt;단조증가함수&lt;/strong&gt;이거나 &lt;strong&gt;단조감소함수&lt;/strong&gt;여야 한다는 제약이 있다.&lt;/p&gt;

&lt;p&gt;함수 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x)&lt;/code&gt;&lt;/strong&gt;가 &lt;strong&gt;단조증가함수&lt;/strong&gt;라고 가정해보자. &lt;strong&gt;Parametric Search&lt;/strong&gt;는 이런 조건에서 아래와 같이 구현할 수 있다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;i) &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x1) &amp;lt; y&lt;/code&gt;&lt;/strong&gt;일 경우, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x)&lt;/code&gt;&lt;/strong&gt;는 &lt;strong&gt;단조증가함수&lt;/strong&gt;이기 때문에 &lt;strong&gt;해답이 되는 x는 x1보다 뒤에 있다&lt;/strong&gt;고 생각할 수 있다.
ii) &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x1) &amp;gt; y&lt;/code&gt;&lt;/strong&gt;일 경우, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x)&lt;/code&gt;&lt;/strong&gt;는 &lt;strong&gt;단조증가함수&lt;/strong&gt;이기 때문에 &lt;strong&gt;해답이 되는 x는 x1보다 앞에 있다&lt;/strong&gt;고 생각할 수 있다.
iii) 특정구간에서 계단함수로 나타날 가능성이 있기 때문에, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f(x1) = y&lt;/code&gt;&lt;/strong&gt;일 때, 탐색범위가 하나로 좁혀질때까지 탐색범위를 줄여나간다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;도 어떻게 보면 &lt;strong&gt;Parametric Search&lt;/strong&gt;의 응용이라고 볼 수 있는데, 해의 범위는 조사를 시작하는 인덱스 low와 조사를 끝내는 인덱스 high 사이이며, 적용되는 함수는 인자로 넘겨진 배열 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;elements&lt;/code&gt;&lt;/strong&gt;에 random access한 값이다. 이분탐색을 적용할 수 있으려면, &lt;strong&gt;“&lt;code class=&quot;highlighter-rouge&quot;&gt;elements&lt;/code&gt;는 오름차순으로 정렬되어 있어야 한다”&lt;/strong&gt;라는 전제조건이 있기 때문에, &lt;strong&gt;단조증가&lt;/strong&gt;일 수 밖에 없다. 따라서, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;도 &lt;strong&gt;Parametric Search&lt;/strong&gt;처럼 구현이 가능하다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parametric Search&lt;/strong&gt;의 구현원리를 이용하여 &lt;strong&gt;Kotlin&lt;/strong&gt;으로 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt; 함수를 구현한 코드는 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;language-kotlin 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;typealias&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lower_bound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&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;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&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;mid&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;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shr&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&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;mid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&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;high&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;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;// value보다 작은 값을 만난 경우&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&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;c1&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;c1&quot;&gt;// value보다 크거나 같은 값을 만난 경우&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;                &lt;span class=&quot;c1&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;n&quot;&gt;lo&lt;/span&gt;                     &lt;span class=&quot;c1&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;upper_bound&quot;&gt;&lt;strong&gt;upper_bound&lt;/strong&gt;&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;C++에서 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt; 함수를 어떻게 활용하는지는 &lt;a href=&quot;https://en.cppreference.com/w/cpp/algorithm/upper_bound&quot;&gt;여기&lt;/a&gt;에서 볼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt;는 정렬된 리스트 내에서 특정 값을 넘는 값이 처음 나타나는 위치를 반환하는 함수로 구현되어야 한다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt;는 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;와 비슷하게 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Parametric Search&lt;/code&gt;&lt;/strong&gt;처럼 구현 가능하다.. 다만, 특정 원소보다 크거나 같은 값이 처음으로 나타나는 위치가 아닌 특정 원소보다 큰 값이 처음으로 나타나는 위치를 반환해야 하기 때문에, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;elements&lt;/code&gt;&lt;/strong&gt;에 random access한 값이 찾고자 하는 값보다 작거나 같다면, 탐색해야 하는 범위는 뒤쪽에 있다고 가정해야 한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Parametric Search&lt;/code&gt;&lt;/strong&gt;의 구현원리를 이용하여 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt;&lt;/strong&gt;으로 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt; 함수를 구현한 코드는 아래와 같다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;와 비슷하지만, 등호 부분만 바꿔주면 된다.&lt;/p&gt;

&lt;div class=&quot;language-kotlin 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;typealias&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;upper_bound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&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;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&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;mid&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;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shr&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&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;mid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&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;high&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;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;// value보다 작거나 같은 값을 만난 경우&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&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;c1&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;c1&quot;&gt;// value보다 큰 값을 만난 경우&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;                  &lt;span class=&quot;c1&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;n&quot;&gt;lo&lt;/span&gt;                       &lt;span class=&quot;c1&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;equal_range&quot;&gt;&lt;strong&gt;equal_range&lt;/strong&gt;&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;C++에서 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;equal_range&lt;/code&gt;&lt;/strong&gt; 함수를 어떻게 활용하는지는 &lt;a href=&quot;https://en.cppreference.com/w/cpp/algorithm/equal_range&quot;&gt;여기&lt;/a&gt;에서 볼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;equal_range&lt;/code&gt;&lt;/strong&gt;는 정렬된 리스트 내에서 특정 값이 나타나는 구간을 반열린 구간으로 반환하는 함수로 구현되어야 한다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;equal_range&lt;/code&gt;&lt;/strong&gt;를 구현하는 건 그렇게 어렵지 않다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lower_bound&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;upper_bound&lt;/code&gt;&lt;/strong&gt;로 구성된 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Pair&lt;/code&gt;&lt;/strong&gt;를 반환하면 그만이다.&lt;/p&gt;

&lt;div class=&quot;language-kotlin 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;typealias&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// equal_range는 정렬된 리스트의 [low, high) 구간 사이에서 특정 값이 나타나는 구간을 Pair로 반환한다.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// lower_bound == upper_bound일 경우, value가 나타나는 구간은 없다고 가정한다.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// low : 조사를 시작하는 구간(닫힌 구간) - 포함&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// high : 조사를 끝내는 구간(열린 구간) - 미포함&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// value : 조사할 값&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equal_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&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;nc&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;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;nc&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lower_bound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;upper_bound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;upper&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;equal_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&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;nc&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&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;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kotlin&lt;/strong&gt;을 개발한 JetBrain에서 ACM-ICPC(세계 대학생 프로그래밍 대회)를 후원하고 있다. &lt;a href=&quot;https://blog.jetbrains.com/kr/2017/06/jetbrains-acm-icpc-%EA%B3%B5%EC%8B%9D-%ED%9B%84%EC%9B%90/&quot;&gt;ACM-ICPC 공식 페이지에서도 Kotlin을 지원하게 될 것&lt;/a&gt;이라고 밝혔기 때문에, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Kotlin을 이용한 알고리즘 문제 풀이&lt;/code&gt;&lt;/strong&gt;에 대한 수요는 계속해서 증가할 것이라 본다.&lt;/p&gt;

&lt;p&gt;하지만, 아직까지는 국내에 &lt;strong&gt;Kotlin&lt;/strong&gt;을 이용해서 알고리즘 문제를 풀이하는 방법을 소개하는 리소스가 많지 않다. &lt;strong&gt;Kotlin&lt;/strong&gt;이라는 언어가 아직까지는 &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Java에 대한 배경지식을 요구한다는 인식&lt;/code&gt;&lt;/strong&gt;이 지배적이며, &lt;strong&gt;Kotlin&lt;/strong&gt;이 정규 교과과정에 들어가는 언어도 아니다보니 따로 공부하는 사람만 알고 있는 편이다.&lt;/p&gt;

&lt;p&gt;국내에서 출판된 &lt;strong&gt;Kotlin&lt;/strong&gt; 도서도 &lt;strong&gt;Java&lt;/strong&gt;에 대한 배경지식이 있다고 가정하고 쓰여진 책이 여럿 있다보니, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;Kotlin을 하려면 Java를 알아야 한다&quot;&lt;/code&gt;&lt;/strong&gt;가 통념이 되어버리는 것 같다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;C++를 알기 위해서, C를 알고 있어야 한다&lt;/code&gt;&lt;/strong&gt;는 논리처럼 보여지기도 하지만, 나도 역시 &lt;strong&gt;Java&lt;/strong&gt;를 어느 정도 공부하고 나서 &lt;strong&gt;Kotlin&lt;/strong&gt;을 영접한 케이스이고, 개인차가 있는 것 같으니 확실히 답하기는 어렵다.&lt;/p&gt;

&lt;p&gt;그럼에도, &lt;strong&gt;Kotlin&lt;/strong&gt;은 정말 배우기 쉬운 편이며, 문법이 다른 언어 못지 않게 간결하며, 배울만한 가치가 있다. 지금 당장은 암흑기라고 판단되지만, 조만간 대중적인 언어로서 주가가 크게 상승할 것이라고 강하게 촉이 오는 언어는 &lt;strong&gt;Kotlin&lt;/strong&gt;이 처음이었다. 대중적으로 쓰이는 &lt;strong&gt;Java&lt;/strong&gt;와 100% 호환이 되며, &lt;strong&gt;Java&lt;/strong&gt;와 비슷하면서도 &lt;strong&gt;Java&lt;/strong&gt;보다 문법이 훨씬 간결하고 편의 문법이 여럿 제공되는데 &lt;strong&gt;Kotlin&lt;/strong&gt;을 선택하지 않을 이유가 무엇이란 말인가?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kotlin&lt;/strong&gt;, 한번 믿고 잡숴보시라.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">2018년 회고</title><link href="https://kodingwarrior.github.io/post/2018/12/31/postmortem-2018" rel="alternate" type="text/html" title="2018년 회고" /><published>2018-12-31T00:00:00+00:00</published><updated>2018-12-31T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2018-12-31-postmortem-2018.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2018/12/31/postmortem-2018">&lt;h1 id=&quot;i-고민&quot;&gt;I. 고민&lt;/h1&gt;

&lt;p&gt;알고리즘 학회장으로서의 나는 2017년에 이뤄낸 일이 있긴 했지만, 개발자로서의 나는 성장하기는 커녕 이뤄낸 것이 아무것도 없었다. 지인분의 제안을 덥석물고 Rails로 외주를 시작하긴 했지만, 학회/연구실 관련 일때문에 빠져나오게 되면서 그대로 성장이 멈춰버린채로 2017년을 그냥 보냈다. 올해만큼은 그렇게 보내고 싶지 않았다.&lt;/p&gt;

&lt;h2 id=&quot;벌써-2018년이-지나간다&quot;&gt;벌써 2018년이 지나간다.&lt;/h2&gt;

&lt;p&gt;올해만큼은 &lt;code class=&quot;highlighter-rouge&quot;&gt;아무것도 안했는데 벌써 2018년이 끝나가는구나&lt;/code&gt; 라는 생각을 하면서 의미없이 보내고 싶지는 않았다. 2017년에는 무기력에 빠진 나 자신과의 싸움을 하면서 정체된 상태를 이어가다가, 2018년 초에 들어서서 다시 제정신을 부여잡고 앞으로 나아가기로 했다. 작년에도 약까지 먹어가면서 무기력증에서 벗어나고자 했으나 실패한 경험이 있었는데, 올해는 그렇게 되고 싶지 않았다. 올해만큼은 절대로 작심삼일로 끝나지 않고, 작년의 무기력에 빠져서 아무것도 하지 못하던 나와 달라지고 싶었다.&lt;/p&gt;

&lt;h2 id=&quot;나는-어쩌다가-인생이-이렇게-꼬였던가&quot;&gt;나는 어쩌다가 인생이 이렇게 꼬였던가?&lt;/h2&gt;

&lt;p&gt;나는 대학에 들어가서야 프로그래밍을 공부하기 시작했다. 좋은 선배를 만나서 급성장을 하는 경우를 많이 봤는데, 나는 좋은 선배를 만나지 못했다. 공부하고 싶은 욕심은 엄청 났는데, 내가 모르는 정보를 알려주는 선배도 만나보지 못했고, 오히려 응원해주는 선배를 만나보지도 못했고, 오히려 앞길을 막으려는 선배나 자존심을 깎으려는 선배들만 만나와서인지 학교에 대해 그다지 애정을 가지지 못했다.&lt;/p&gt;

&lt;p&gt;학교에 애정을 가질 일도 없었고, 이렇다 할 추억을 가지지 못했던 암울한 나날을 지내오다보니 &lt;code class=&quot;highlighter-rouge&quot;&gt;이 놈의 학교 빨리 탈출하던가 해야지...&lt;/code&gt; 라는 생각을 쭉 유지하면서 살아왔다. 2년의 휴학기간 동안 Project Euler, CodeWars, BOJ를 알게 되면서, PS에 재미를 붙이기 시작했는데 모여서 이런 재밌는 것을 하는 사람들이 학교마다 있다는 것을 처음 알았다. 그래서, 구글이나 네이버에 열심히 검색해보기까지 했다. 아쉽게도 없었지만. 좋은 선배를 만나보지도 못했는데, 있었을리도 없을 것이다. 어느새부턴가 &lt;code class=&quot;highlighter-rouge&quot;&gt;좋은 선배란 무엇인가&lt;/code&gt; 라는 고민을 하게 되었고, 어쩌다가 알게된 친한 후배들이 내가 겪어왔던 것처럼 좋은 선배를 만나지 못해서 손해보는 일이 없었으면 좋겠다는 생각이 들게 되었다. &lt;code class=&quot;highlighter-rouge&quot;&gt;나만 당할 수 없지&lt;/code&gt;보다는 &lt;code class=&quot;highlighter-rouge&quot;&gt;다음 세대는 나처럼 고생 안 했으면 좋겠다&lt;/code&gt; 라는 생각으로 동아리를 처음부터 키우는 일에 손을 대게 되었다. 지금 생각해보면 돌이킬 수 없는 일이었다. 복수전공을 고려하고 있었고, 학문에 한참 관심을 가지던 시기였으니 말이다. 그냥 나 혼자만의 길을 걸어서 토이 프로젝트를 여러개 찍어낼 수도 있었을 것이다.&lt;/p&gt;

&lt;p&gt;동아리의 운영을 2016년까지 어떻게 잘 이어가다가, 고학년들이 한꺼번에 졸업하면서 실질적으로 이어갈 수 있는 사람이 나밖에 없는 상황이 되어버렸다. 동아리가 폐지될 위기를 민석이형이 어떻게 모면해주긴 했지만, 어디까지나 이름을 빌려주는 것 정도만 가능할 정도로 많이 바쁜 처지였다. 그러다보니, 미안한 마음이 들어서 내가 학회장 자리를 이어받았는데, 남아있는 인원들은 전부 고학년이고, 이끌어가려는 의지를 가진 사람도 거의 없다시피했기 때문에, 저학년 인원을 모집하는 것이나, 어색하지 않게 분위기를 만들어가는 것이나, 내부 교육을 하는 것이나 모든 것들을 내가 떠맡아야 했다.&lt;/p&gt;

&lt;p&gt;동아리를 운영하는 과정에서 발생하는 모든 일들이 나에게는 스트레스였고, 동아리의 존폐에 위협을 느낀 경험을 여러번 겪기도 했기 때문에 일상생활을 하기에도 어려울 지경이었다. 번아웃이 심해지고, 무기력한 상태가 계속 이어져서 2017년을 거의 공백의 기간으로 보내기까지 했다. 억지로나마 내부 교육 컨텐츠를 만들기 위해서 일주일마다 슬라이드를 여러장 찍어내긴 했었다. 2017년 2학기에는 정신 바로 잡고 열심히 달리기로 했지만, 지루한 수업을 듣고 싶지 않다는 듯한 경멸적인 시선, 다른 학회 활동에 눈치를 주는 듯한 이상한 문화, 모르는데서 퍼져가는 학회와 관련된 악성 소문들을 마주하면서 약 없이는 제 정신을 유지하기가 어려운 세월을 보냈다.&lt;/p&gt;

&lt;p&gt;그나마 좋았던 점은, 개발 커뮤니티를 통해 알게된 지인을 통해 Rails로 프로덕션 환경에서 웹 개발을 할 수 있는 기회를 얻을 수 있었다는 것이다. 0년차 콤플렉스가 있었던 나에게는 절호의 기회였다. 2017년 겨울방학 후반쯤부터 풀타임으로 개발에 참여했다. 개발을 하면서 돈을 버는 과정이 너무 황홀할 지경이었다. 하지만, 학기를 시작하면서 외주를 이어가기 어렵게 되었다. 시간을 낭비하는 수준의 과제/시험때문에 잠깐잠깐 시간내서 참여하기도 어려운 수준이었다. 여름방학 연구실에 들어가기로 하면서부터, 외주를 하기도 어렵게 되었다.&lt;/p&gt;

&lt;p&gt;한 분을 제외하고는 사수가 없었던, 경력이 없었던 콤플렉스를 작년까지는 계속 달고 다녀야만 했다. 정말, 내 인생은 어디서부터 잘못된 것이었을까?&lt;/p&gt;

&lt;h2 id=&quot;나는-좀-더-거칠게-날뛰고-싶었다&quot;&gt;나는 좀 더 거칠게 날뛰고 싶었다.&lt;/h2&gt;

&lt;p&gt;2018년 5월까지는 계속해서 학부연구생 신분이었다. 학회 창설 멤버이자 학회장이라는 책임감을 가지고 학회 활동을 하는 것이나, 학부연구생으로서 연구실에서 프로젝트하느라 학교라는 범주에서 갇혀서 생활한다는 것은 나에게 족쇄나 마찬가지였다. 학교 안에서만 갇혀있고 싶지 않아서, 대외활동 여기저기 지원해보기도 했지만, 몇군데는 &lt;code class=&quot;highlighter-rouge&quot;&gt;시간을 내기 어려우실 것 같다.&lt;/code&gt;라는 이유로 떨어지기도 했다. 밖으로 나오기 위해서, 무엇인가를 포기해야 겠다는 결심이 생겼다.&lt;/p&gt;

&lt;p&gt;연구실 활동도 사실 대학원/연구활동에 관심있어서 시작한 것도 아니었다. 2017년 여름방학 때 쯤 비어있는 기간 동안 무기력에서 벗어날겸 개발활동을 여기서라도 해야겠다는 단순한 생각에서 시작한 것이었다. 연구실에서 배운 것도 많았지만, 폭넓은 경험의 개발자가 되고 싶은 나의 욕구를 충족시키지는 못했다. 몇년 쯤 뒤쳐져 있는 테크스택을 계속해서 제자리 걸음으로 두고 싶지도 않았다. 이상하게 꼬여서 0년차인 것도 서러운데, 외부에 공유하면 안되는 보안 수준의 코드를 작성하면서 속으로 끙끙 앓는 시간을 보내고 싶지도 않았다. 내 실력이 이렇게 정체되어 있어도 되는건지 회의감이 드는데, 자극받을 만한 사람들과 같이 협업해서 성장하고 싶기도 했다.&lt;/p&gt;

&lt;h1 id=&quot;ii-달라진-점&quot;&gt;II. 달라진 점&lt;/h1&gt;

&lt;p&gt;나는 어떻게든 작년과는 달라지려고 발버둥쳤다. 무기력한 과거의 나를 극복하기 위해서이기도 했지만, 계속해서 나를 무기력하게 만드는 원인도 하나 둘씩 걷어내고 싶었다.&lt;/p&gt;

&lt;h2 id=&quot;대외활동을-하기-시작했다&quot;&gt;대외활동을 하기 시작했다.&lt;/h2&gt;

&lt;p&gt;재작년에는 전역한지 얼마 안 되기도 했고, 전역하자마자 이것저것 하고 싶은 것들이 많았기 때문에 스터디에 여러번 참여하기도 하고, 컨퍼런스에 여러번 참여하기도 했지만, 작년에는 무기력해서 거의 아무것도 못하던 상태였기 때문에 항상 가던 행사들을 제외하면 대외활동할 기력도 거의 없었다. 올해는 작년의 정체된 상태에서 벗어나고 싶기도 했고, 무기력하게 보내서 잃은 것들이 많았던 세월을 올해에는 만회해보고 싶었다. 컨퍼런스/밋업에 대한 기록을 적자니, &lt;code class=&quot;highlighter-rouge&quot;&gt;어딜가나 항상 참관인으로 보이는 사람&lt;/code&gt;이었다보니, 참관인이었던 경험을 제외하고 대외활동을 했던 썰을 간단하게 풀어보려고 한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/tXsrzK7bc0yJrbwofkz6M_1_ZIJaZvzgPDK1t0Of7UuHAB8xrFxXG3tU85POapx8gX4tY_4s57HvVrnitfLO7w_KxmW1JZsetl_xXwsrYhRmV6gGL4wzG78eEQq5leGj7RO_RG_r6zHSwNJX5_zE1XPPnFjZS35NW2cJT_rDC7oLHkMby5r93h083mTkMOnIKMBGVMHtlk2VzhaVnaf7oKqwupE8y9wZlMLuLB5i6R3Cy1x-eQ--okK5Jh1Cq0dN1Rlt3rKQY7reDLqYO4LPg67CjUKK8lz2CVhchY8wXpTj_tGXR4GY_nWBVSW2qpBz6ISGpjAbWhR-CH0KkcA0T1xpXOHvhUprKmmjfkYjcCULm25LSRUvJbk-6zr_UQh2qJH-0GMexS6_v5Tu2IPUzzaZDJwg_C3L9tsKHGxsnR6H-jd-A2SdMFjN-Y2GEe7DFJk9RtRTk0vh07SZb-DcM4DOiHSy6RhR9LOhFDmAFw75C3WVVnn8zsEYCUob7y3FhnJEoBM7c2dxlNRItADbCmptgRzR3ZbhZq1tyeXFUr_5i4u2gI-ztcaUZVpp85N2q6z2nr2EdccrPtIiPCyobPdxR6V7oOUIXcHyB820wenD5aeS85Rs6WND1rAL8PsWnL1wcZXUzVFA5LeULydtBFlk=w1680-h1120-no&quot; alt=&quot;쟝고걸스 쟝쟝걸&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1월 13일 : Microsoft 광화문 사옥에서 열린 &lt;code class=&quot;highlighter-rouge&quot;&gt;DevOps Korea Meetup&lt;/code&gt;에서 자원 봉사자로 활동했다. 입장하는 시간대에는 티셔츠를 나눠주는 역할을 하다가, 중간중간에 강연을 듣기도 했었는데 DC/OS, Kubernetes, Marathon 등을 비롯한 프레임워크를 현업에서 다루는 얘기들을 보고 들었다. 연구실에서도 이와 비슷한 일을 하긴 했었는데, 현업에서 어떻게 다루는지를 직접 보게 되면서 DevOps 엔지니어가 되고 싶다는 생각을 가지게 되었다.&lt;/li&gt;
  &lt;li&gt;7월 20일~7월 21일 : 공덕의 서울창업허브에서 열린 &lt;code class=&quot;highlighter-rouge&quot;&gt;Django Girls 워크숍&lt;/code&gt;에서 Coach로 활동하게 되었다. 같은 조였던 분들이 Django를 이용하여 그럴싸한 웹사이트를 만들 수 있도록 옆에서 도와주는 역할을 했다. 같은 조원 분들이 알고보니 일부분을 이미 알고 오신 분들이라서 진도가 너무 빠르게 나가다시피 했는데, 설명을 이것저것 덧붙이고, 좀 더 어려운 도전과제를 내주려고 고민했던 것 같다. Django Grils 워크숍의 인연을 통해 다양한 분들을 알게 되었고, 꾸준히 모여서 코딩하는 스프린트 모임인 PyJog 운영권한을 받았다(!!?). 어떻게 보면, 최저점을 달리던 내 삶의 한 전환점이라고 봐도 될 것 같다.&lt;/li&gt;
  &lt;li&gt;12월 29일 : 10월 31일부터 파이콘 한국 준비위원회에 합류하자마자, 12월에 열릴 예정이었던 파이썬 격월 세미나를 준비하기 시작했다. 처음 행사를 준비하는 것이다보니, 행사 준비 회의도 서툴다시피했고, 인턴과 관련된 일로 바빠서 슬랙을 확인할 시간도 거의 없다보니, 업무의 흐름도 파악이 잘 안되기도 해서 어려움이 있었다. 처음이라 행사 준비에 미숙하긴 했지만, 기존에 같은 업무를 해왔던 다른 분들의 도움이 있었기에, 구글 드라이브와 슬랙 로그를 비롯한 과거의 기록이 있었기에 큰 실수 없이 해낼 수 있었다. 그리고 12월이 되어서야 한빛미디어 리더스홀에서 열린 &lt;code class=&quot;highlighter-rouge&quot;&gt;파이썬 연말 미니 컨퍼런스&lt;/code&gt; 에서 데스크를 지키는 역할을 했으며, 문자통역사분들과 연락을 주고 받는 역할을 했다. 데스크를 지키면서 파이콘에서 뵈었던 분들을 다시 한번 뵐 수 있어서 흐뭇하기도 했다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;나에게도-드디어-경력이라는게-생겼다&quot;&gt;나에게도 드디어 경력이라는게 생겼다.&lt;/h2&gt;

&lt;p&gt;2018년 10월, ‘&lt;strong&gt;이번엔 진짜 0년차에서 벗어나서 인턴을 해보자’&lt;/strong&gt;라는 생각이 들어서 프로그래머스에서 주관하는 스타트업 겨울 인턴십 프로그램인 ‘윈터코딩’에 지원했다. 10월 27일에 있었던 코딩테스트는 너무 간단한 문제였기 때문에 빠르게 All Solve하고, 11월 초에는 개발과제에 내 시간과 노력을 쏟아부었다. 프로젝트를 여러번 찍어내본 경험이 있었다면 빠르게 뚝딱하고 해치울 수 있었을텐데, 주요 테크스택을 Rails에서 Django로 갈아타는 단계이기도 했고, 익숙해지려는 단계이다보니 버벅이면서 코딩하다보니 시간이 오래 걸려서야 마감기한에 곁다리로 걸쳐서 끝냈다. 아래의 글에서 윈터코딩에 참여한 후기를 올린 바가 있다. DRF, React의 조합으로 프로젝트를 했는데, TDD, JWT, Redux를 아직도 제대로 이해하지 못하고 있는 내가 싫었다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://kodingwarrior.github.io/post/2018/11/06/Participating-In-Winter-Coding.html&quot;&gt;https://kodingwarrior.github.io/post/2018/11/06/Participating-In-Winter-Coding.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;개발과제를 제출하고, 0년차 경험이긴 하지만 어떻게든 이력서에 이것저것 내용을 채워넣고 며칠을 기다렸다. 그리고, 여러 스타트업에서 서류합격메일을 받으면서 3주에 가까운 시간을 면접으로 달려왔다. 스무스하게 면접을 본 회사가 있는가하면, 내가 생각하지도 못한 질문에 압도되기도 했던 회사가 있었고, 내가 모르는 것이 무엇인가를 깨닫게 해주는 회사도 있었다. 10개가 넘는 회사에 지원했는데, 역시나 좌절감은 지원한 회사의 갯수만큼 몰려왔다. 10개의 불합격통보 메일이 연달아왔을때, 작년의 무기력한 모습으로 되돌아가게 될 것만 같았다.&lt;/p&gt;

&lt;p&gt;우울감을 유발하는 불합격통보 메일이 오가는 와중에, 아직 통보 메일이 오지 않았던 한 회사에서 전화가 왔다.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;안녕하세요. XXX입니다. 혹시 합격 통보 메일이 왔던 회사가 있나요?&quot;
&quot;어... 아직 없는데요..?&quot;
&quot;혹시 저희 회사에서 인턴으로 근무하실 의사가 있으신가요?&quot;
&quot;네!!! 감사합니다!!!!&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고, 나는 인턴에 합격했다. 그토록 바라고 바라던 실무 경험이었다. 현재 인턴으로 근무하고 있는 회사는 근무하고 싶은 회사 중 하나이기도 했다.&lt;/p&gt;

&lt;h2 id=&quot;스스로의-변화를-위해-투자를-늘리기-시작했다&quot;&gt;스스로의 변화를 위해 투자를 늘리기 시작했다.&lt;/h2&gt;

&lt;p&gt;왠지 모를 불안감과 우울에서 벗어나기 위해, 소비를 조금씩 늘리기 시작했다. 작년에도 느껴왔지만, 나 스스로를 위해 돈을 소비할 때 만큼 행복한게 없었다. 시간이 갈수록 속물이 되어가는 것 같은 느낌이 들기도 하지만, 자본주의의 유혹은 좀처럼 뿌리치기 어려웠다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/-CQomtetZnMfjEnSrktWGT2_W6URJiK0VmE7IfYS_t9EAx7YbKa9EsEvQRjSLXAIlDTwN1S_a73oJniRtLmFKemEtATpxVjuxDLrThWg8VED_JdZyqSvB1ZHkZv32C4qwvr_ELcNa42RjXnRiTFNAb7yyS1CKl6u_id4LuG4aNtjK2VPRcDoRM70g-NparuOGPUCFtv0FM5OuK7Q6N05AqMX-w2lDvTjKqFkGXUs1WsgspiMkMI-a5EIBcSCC8shlWiUk-GvIyiihqBHzdSi_C2hoAsGtdIOEkDdNXDWzYkQ0owCIhOUcj4Rj7kO1ftmPxxVil9e6bNfYe6f2GBAgw2bJHMDjtGUc9XGStt2XnmFC6FLCQMp3jCCeflcV6_dy82GujYfDu4aRBx1gL4SuAWsh4XVYz1P4Omx1WSMZnXtAJLP6B9h75w-TeWxuuOXjTUos25_xbgBxZRhlazgh7GVmiyLdYzL9CRJfyXcW7OjPg1aO6FsV4b4Ce9Z92h4wliQJ6Ou_gDvqXKxLE5FLtMjx8IjjrkPin67JNAmoYJoL0n0iW6_dWjZGAUVCwCtCe5C9BKiNkJ_9gJnMYfq5dXFy0oOPG1Av7CkVwHHjWMl2E69LQeFU1Qa1Inwc0EOnyTTk_I314t8sT4iM2rRlhxboK2IaUOApSnDz_ctSKGNZgRK5Q3Pgynb5ArMuWvcmvgk4eQlw7n_NYIwSQ=w1316-h740-no&quot; alt=&quot;Notion 쓰세요. Notion&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;타임라인에서 그렇게 유명하던 &lt;strong&gt;Notion을 구매했다.&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Notion을 구매했던 계기를 말하자면, 학습기록을 어떻게 남길지 고민하던 나에 대한 얘기를 하지 않을 수가 없다. 얼마전까지만 해도, 나만의 Private Wiki 를 어떻게 구축해야할까 꾸준히 고민을 해왔다. 몇달 전까지만 해도 라즈베리파이에 OpenNAMU라는 위키엔진을 설치하고 외부에서 접근할 수 있게 공유기 포트 포워딩하면서 이용해왔는데, Mediawiki처럼 UX가 훌륭하지 못한게 불만이었다.&lt;/li&gt;
      &lt;li&gt;다시 원점으로 돌아가서 Jekyll 블로그에다가 공부기록을 남기자니, 개인적으로는 TIL 만으로 공부기록을 유지하기에는 회의감이 들기도 했었고, 블로그에는 왠만하면 정리된 글 중심으로 남기고 싶었다. 시험기간에는 시험공부하기가 싫으니까 블로그라도 살린다는 각오로 기록을 남기긴 했었지만, 책의 내용을 그대로 번역해서 기록으로 남기려니, 공부 양에 비해서 시간 효율성이 떨어진다는 생각이 강하게 들었다. 책의 내용을 그대로 옮겨쓰는 것 자체에 대해서 개인적으로 불편한 생각이 들기도 했고, 내 방식대로 좀 더 잘 정리된 글로만 블로그를 채우고 싶었다.&lt;/li&gt;
      &lt;li&gt;하지만, 블로그에 올릴 글들의 Draft를 계속 쌓아두기만 할 수는 없고, Github에 TIL 저장소를 따로 만들자니 위키방식으로 편하게 내부링크를 이어주는 방식으로 이용하고 싶었다. @johngrib님처럼 Jekyll Wiki를 만들자니 그러기에는 검증할만한 시간은 없고, 개인서버를 파서 Mediawiki를 굴리자니 설치하는데만 시간을 엄청 들일 것 같고, 이런저런 후보를 생각하던 중 타임라인에서 보이던 것이 Notion이었다. UI는 당연히 훌륭하지만, Private Wiki로 접근했을 때 UX는 어떨까하는 생각에 3주째 쓰고 있는데 제법 괜찮다. 앞으로도 계속 쓰게 될 것 같다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;한 달에 책 사는데 드는 비용을 늘리고 있다.
    &lt;ul&gt;
      &lt;li&gt;작년부터 학습속도가 느려지고 있다는 것을 자각하고 위기감을 느껴왔다. 어떤 방법이든 효율성을 가리지 않고 시도하던 대학 새내기 때는 시험기간만 되면 아무 생각없이 깜지수련을 하거나, 시간 물량 공세를 했던 것 같은데, 복학하면서 이것저것 일을 벌리다보니 시간을 적절히 분배해야하고, 공부하는데에도 효율을 따지게 되어버렸다. 아무 고민도 없이 공부만 했다면, 그나마 걱정하는 시간을 줄였을 수도 있지만, 아무 생각없이 비효율적인 방식을 고집하다가 다른 생산적인 활동을 하지 못하게 될 수도 있다는 점이 걱정되기도 했다. 개발에 발을 들이면서 필요한만큼만 골라서 공부하는 방식에 익숙하다보니, 동기부여가 되지 않은 부분까지 공부하는 것만큼은 집중력이 확 떨어지기까지 했다. ‘&lt;strong&gt;나의 학습방식에는 분명히 문제가 있다’&lt;/strong&gt;라는 문제의식을 가지고 학습방법에 대한 책을 이것저것 사들이면서 읽고 있다. 그러던 와중에 알게 된 책이 &lt;code class=&quot;highlighter-rouge&quot;&gt;삼색볼펜 공부법&lt;/code&gt;이었는데, 2주간 이 방법을 적용해보니 학습속도가 어느정도 개선되긴 했다. 뒤늦게 알게 되서 여러모로 아쉬운 책이지만.&lt;/li&gt;
      &lt;li&gt;전자책 독서량을 늘리고 있다. 몇 달 전까지만해도, 넷플릭스보느라 시간가는줄도 몰랐고, 인정을 받고 싶은 욕구, 불안감 때문에 SNS 중독이 날이 갈수록 심해지고 있었다. 지하철 타고 오고 가는데만 편도 30분~50분인데, 이 시간을 SNS 확인에 들이는 것이 아깝다는 생각이 들기 시작했었다. 넷플릭스 구독도 해제하고, 과감하게 리디북스 Select를 결제했다. 출퇴근길에 개발관련 도서를 구매하려고, 프로그래밍 대회 은상으로 받았던 15만원짜리 상품권들을 리디북스에 올인했다. 얼마전부터 관심가지고 보던 인권문제 관련 도서도 구매하고 있고, 출퇴근시간을 이용해서 전자책으로나마 독서의 스펙트럼을 늘리고 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;생활 패턴을 바로 잡기 위해, 수면 측정 어플리케이션(Sleep as android, SleepTown), 생산성 측정 어플리케이션(Forest)들을 구매해서 쓰고 있다. 수면패턴이 망가져서 시험을 응시하지 못하고 졸업이 꼬인 적이 한두번이 아니었는데, 이제는 달라져야겠다는 마음가짐으로 생활패턴을 조절하는 방법을 닥치는대로 알아보고 있고, 수면패턴 조절을 보조해주는 유료앱도 이것저것 구매했다. 작업하는 동안 블랙리스트 사이트 지정해서 차단해주면서 백색소음을 깔아주는 Forest라는 앱도 한달째 꾸준히 애용하고 있다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;iii-압도적-감사&quot;&gt;III. 압도적 감사&lt;/h1&gt;

&lt;p&gt;정신적으로 힘든 나날을 보내면서, 알게 모르게 주변의 여럿 사람들에게 신세를 지게 되기도 했다. 내가 그나마 예전보다 나아질 수 있었던 것도, 앞으로 나아갈 수 있었던 것도 주변 사람들의 도움이 있었기 때문이 아닐까 싶다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;D님&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;재작년 Lisp 세미나에서 알게 되었고, 작년 Clojure Bridge를 시작으로 친해지게 되었는데 2017년 중반까지는 Clojure 커뮤니티 관련 일을 거들어주다가 개인적인 사정으로 이어나가지 못하게 되어 아쉽기도 했다. 개인적으로 죄송한 감정이 남아있기도 했는데, 어느날 갑자기 결혼식에 초청되는 영광을 누리기도 했었다. 항상 좋은 분이라는 인상을 가지고 있었기 때문에, 굳이 일 때문이 아니더라도 연락을 계속 꾸준히 이어나가고 싶다. 한번은 직장 근처로 놀러가서 밥도 얻어먹고 진지하게 고민을 털어놓은 적도 있었는데, 이제는 내가 보답할 차례다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;17년도 하반기부터 지금까지 함께 해준 학회 친구들&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;17년도 하반기 초까지는 사실 나에게 꿈도 희망도 느껴지지 않던 암흑기처럼 느껴졌었다. 내가 무슨 신념을 가지고 좋은 기회를 뿌려쳤는지 회의감이 들기도 했고, 신입생이 거의 없었기 때문에 다음해에도, 다다음해에도 일을 내가 다 짊어져야 할 것 같은 불길한 예감까지 들기도 했다. 그나마 다행인 것은 2학년 멤버 중에서 일을 거들어주겠다는 인원이 하나 둘씩 보이면서, 학회장 1인 독재체제가 아닌 소수의 운영진이 협업하는 체제로 조금씩 변화하기 시작했다. 소수의 핵심인원만 활동의 중심이 되는 것도 아니었고, 17년도부터 지금까지 꾸준히 남아있던 14~16학번 멤버들이 운영진들이 학회의 운영에 어려움을 겪지않게 뒤에서 잘 보조해주기도 했다.&lt;/p&gt;

&lt;p&gt;18년도 초에는 처음으로 신입생을 많이 모집하던 시기였어서, 신입생을 이끄는 것이나, 신입생 대상으로 스터디를 여는 것이나 모든 것이 서툴러서 개인적으로 느끼기에도 운영이 많이 미숙하다시피했는데, 지금까지도 잘 남아있는 18학번 친구들한테도 고마움을 느끼고 있다.  지금 운영진으로 인수인계 받은 친구들도 대부분이 18학번 신입생인 친구들인데, 다들 내가 인정하는 실력파&amp;amp;노력파인 친구들이라서 걱정하지 않고 은퇴할 수 있다는 생각에 홀가분하다.&lt;/p&gt;

&lt;p&gt;18년도 하반기부터는 학회장 자리를 다른 친구에게 넘겨주고, 왠만하면 개입을 안하는 방향으로 일관했다. 내가 해결하지 못한 문제를 해결해나가는 모습들을 보고 뿌듯했다. 올해 들어, 사상 처음으로 술자리(라기보다는 회식)를 가져보기도 하고, 자발적으로 스터디장을 하려는 친구들도 하나 둘 씩 생기기 시작했고, 편입생 여러명이 입부를 하면서 규모도 상당히 커지다시피했다. 억지로 학술적인 분위기를 만드려고 했던 과거에 비해, 이제는 문화적으로 정착되기 시작했다. 나 혼자로는 절대로 하기 어려웠던 것들을, 후발주자들이 잘 해결해주고 있다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;H&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;사실 SNS에서 알게 된 동생인데, 홍대 구경 좀 시켜주다가 친해지게 되었다. 내가 봐온 친구들 중에 제일 멋있는 동생이기도 하고, 인생을 정말 재밌게 사는 친구이기도 해서 생각날때마다 계속 연락하고 싶다. 사람 만나면서 휴식을 취하고 싶을때 한번 만나서 드라이브를 해보기도 하고, 인생 사는 얘기도 진지하게 나눠보기도 하고, 남양주시 근처 카페에서 인생샷도 찍어준 친구인데 또 보고 싶다…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;W님&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;군에 입대하기 한 달 전, 레일스 커뮤니티에서의 인연으로 알게 되었는데, 작년이나 지금이나 여전히 내 인생의 멘토되시는 분이다. 프로덕션에 투입된 경험이 없던 나에게 도구 사용법을 제대로 익혀두라는 참교육을 주셨던 분이기도 하고, 처음으로 나에게 일을 제안해주셨던 분이기도 하고, 일로 엮일 일이 없음에도 불구하고 적극적으로 연락을 하시려던 분이기도 했고, 인턴 이력서를 넣을때도 첫 직장을 잘 고르라면서 상담을 해주시던 분이기 때문에 이 분에게 항상 감사함을 느끼고 있다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;U님&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;개발자로서의 삶을 살아가는데 있어서 롤모델이신 분 중 한 분. 트위터를 시작하시기 전부터 우러러보던 분이기도 했고, 평소에 근면성실하시고 꾸준히 정진하시는 모습이 부럽기도 했다. 언제 한 번 강연다닌다고 하셨을때 기회를 덥석물어서 모시긴 했었는데, 흔쾌히 받아들이시는 열린 마인드에 아직도 감사함을 느낀다. 학교에 강연하러 오시고 돌아가시는 길 배웅하지 못해서 아쉽기도 한데, 언제 한번 밥이라도 사드려야겠다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;C님&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;예전이나 지금이나 느끼는 인상은 그냥 동네 친한 개발자 아저씨 정도인데, 만나서 얘기하면 얘기할 수록 배울 점이 많은 아저씨. 진지한 얘기는 그렇게 많이 해보지는 않았던 것 같은데, 심심할때 만나서 밥 같이 먹고, 위워크 한번 놀러가고, 모여서 코딩했던 기억이 소소하게 남는다. 쓸쓸한 인생 덜 외롭게 해줘서 고마운 아저씨&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;B님&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;내 생일에 젠틀맨 라이언 인형을 선물해줬다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;그 외 SNS 친구들&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SNS 친구들의 응원이 없었으면 살아가는거 완전 막막하지 않았을까….. 사실 적고 싶은 사람들 다 많긴 한데, 너무 길어질 것 같아서 이 정도로만 그쳐야겠다.&lt;/p&gt;

&lt;h1 id=&quot;iv-앞으로의-다짐&quot;&gt;IV. 앞으로의 다짐&lt;/h1&gt;

&lt;p&gt;무기력한 나 자신을 극복했겠다. 이번에는 다시 딛고 일어서서 SWAG 넘치는 개발자가 되기 위한 여정을 다시 이어나가려고 한다. 대외활동도 많이 해보고, 오픈소스 생태계에 많이 기여도 해보고, 발표도 여기저기해보고, 번역도 해보고, 해보고 싶은 것들은 많다. 작년에는 초라함 그 자체였다면, 올해는 다시 딛고 일어서는 단계를 겪고 있고, 내년에는 멋진 개발자로 한 발짝 나아갈 것이다!&lt;/p&gt;

&lt;h2 id=&quot;애증을-가진-학교는-이제-안녕이다&quot;&gt;애증을 가진 학교는 이제 안녕이다.&lt;/h2&gt;

&lt;p&gt;나는 이제 학교 생태계에 내가 할 수 있는 것들은 다 했다. 이제, 학교에 내 삶이 매몰되는 일은 없도록 하고 싶다. 나는 이제 OB 회원이다. 충분히 잘하고 있는데, 필요 이상으로 개입해서 내가 그토록 싫어하던 &lt;code class=&quot;highlighter-rouge&quot;&gt;진상 선배&lt;/code&gt;가 되고 싶지도 않고, 가끔씩 홈커밍데이나 방학 중에 깜짝 등장해서 통 크게 쏴주는 선배 포지션 정도로만 유지하고 싶다.&lt;/p&gt;

&lt;h2 id=&quot;기본기에-더욱-충실해지기로-했다&quot;&gt;기본기에 더욱 충실해지기로 했다.&lt;/h2&gt;

&lt;p&gt;비록 일부 수업이 그렇게 훌륭하지 못해서 정보를 흡수하는데 어려움이 있었지만, 학교에서 배우는 것들은 나에게 피가 되고 살이 되는 것들이 많았다. 웹 백엔드 개발자를 꿈꿔왔던 나에게는 특히, 네트워크 쪽 지식을 깊이 아는 것이 필수적이라 볼 수 있는데, 학교에서 시키는 대로만 공부하고, 학교에서 요구하는 공부방식에 맞춰서 공부하기만 했다. 학교 수업에서 다루는 교재 자체는 훌륭하지만, 진도 나간 대로만 공부하다보니, 진도 안나간 부분을 대충 짚고 넘어가기도 했었다. 그러다보니, 제대로 배운 게 있었나 싶을 정도로 피상적인 지식만 머릿속에 남아있다. 다시 복습을 해야한다.&lt;/p&gt;

&lt;p&gt;운영체제/시스템 분야는 비록 성적을 잘 받긴 했지만, 난 좀 더 내가 만족스러운 수준까지 공부하고 싶다. 나는 여기에 &lt;strong&gt;투머치토커(Too Much Talker) 공부법&lt;/strong&gt;으로 접근해보려고 한다. 누군가가 이 분야에 대해 질문을 할 때, 질문을 한 사람이 부담스러워 할 수준으로 내가 아는 모든 것들을 막힘없이 설명할 수 있을 수준으로 올라가고 싶다. 책까지 쓸 수 있으면 더 좋을 것이다. 운영체제/네트워크 분야를 어느 정도 아는척 할 수 있는 수준으로 공부하게 되면, 잘 알려진 웹 서버들의 내부 동작원리를 SWAG 넘치게 바닥에서부터 설명해보고 싶다.&lt;/p&gt;

&lt;p&gt;학교 커리큘럼의 한게로 배우지 못했던 것들도 차근차근 공부하기로 했다. 신입생때는 컴파일러가 교과과정에 들어가있었지만, 수강생이 적어서 일부 교과과정이 폐지되고 있는 지금, 컴파일러를 포함한 여러과목이 폐지되고 있다. 관심이 있었는데, 학교 커리큘럼에 없었다는 이유를 핑계로 들어서 공부하지 않는 것은 지양하고 싶다.&lt;/p&gt;

&lt;p&gt;교육방식의 문제 때문에 학교 수업이 쓸데없다고 할 수 있을지는 몰라도, 학교에서 배우는 것 자체로는 피가 되고 살이 된다는 것을 항상 느껴오곤 했다. 탄탄한 기초지식을 기반으로, 오픈소스에 기여하는 분들을 보면 그렇게 멋져보이지 않을 수가 없었다. 뜯어볼 줄도 알고, 튜닝할 줄도 알고, 직접 기여할 줄도 알고, 직접 만들어서 씬을 주도할 수 있는 수준까지 올라가고 싶다.&lt;/p&gt;

&lt;h2 id=&quot;내가-가진-한계를-이제는-인정하기로-했다&quot;&gt;내가 가진 한계를, 이제는 인정하기로 했다.&lt;/h2&gt;

&lt;p&gt;도전을 하지 않겠다는 의미가 아니다. 일을 여기저기 벌리는 특성을 주체할 수는 없기 때문에, 현재의 내가 어느까지만 할 수 있는지 객관적으로 인지하고, 가능한 선까지만 일을 벌리겠다는 의미다. 감당하지 못할 수준으로 일을 벌리다가 감당하지 못해서 좌절을 겪는 실수를 다시 범하고 싶지 않다. 한계를 인정하지 않고, 무작정 자존심을 내세우고 다니다가 신뢰를 얼마나 많이 잃었을까 싶다. 사실, 자존심 세울 일도 없어지다보니 자연스럽게 이렇게 된 것 같기도 하다.&lt;/p&gt;

&lt;h2 id=&quot;경험을-좀-더-늘리기로-했다&quot;&gt;경험을 좀 더 늘리기로 했다.&lt;/h2&gt;

&lt;p&gt;지금까지의 내 삶을 돌이켜보면, 토이 프로젝트를 제대로 만들어서 배포한 적도 없었다. PoC 프로젝트는 커녕 TDD를 연습하는 프로젝트를 제대로 만들어보지도 않았고, 지금 당장 과제로 주어진 일을 제외하면, 바쁘다는 핑계를 대면서 손을 거의 대지 않다 시피 했다. 프로젝트를 평소에 많이 연습하지 않다보니, 빨리 걸릴 수 있는 작업을 다른 사람들보다 오래 걸리기도 했었다.&lt;/p&gt;

&lt;p&gt;빠르게 프로젝트를 만드는 연습을 해보거나, 기획적인 고민을 많이 해보지도 않았다. 예전에는 이 바닥에서 살아남기 위해 내가 가진 Skill set을 늘리는게 중요하다는 생각을 했었는데, 이제는 Skill set보다는 숙련도에 더 신경을 써야한다. 나에게는 지식의 깊이 뿐만이 아니라, 주어진 마감기한 안에 얼마나 빠르게 찍어낼 수 있는지가 중요하고, 제한된 시간안에 빠르게 취사선택을 할 수 있는지, 소통의 비용을 최소화시킬 수 있을만큼 감각을 키우는 것이 중요하다. 내가 가진 한계를 고려하면서, 짧은 주기를 가지고 한 해 동안 다양한 시도를 해보고 싶다.&lt;/p&gt;

&lt;h2 id=&quot;한-우물만-파기로-했다&quot;&gt;한 우물만 파기로 했다.&lt;/h2&gt;

&lt;p&gt;고용 불안 때문에, 여기저기 헤메던 생활도 이제 그만이다. 이제서야 겨우 정착할 기회가 생겼다. 나에게 주어진 일에 맞게 내 역량을 키우면서도, 내가 원하는 분야로 전문성을 강화하여 앞으로도 이 바닥에서 현역으로 살아남고 싶다. 여기저기 발 걸쳤다가 아무것도 잘하는게 없었던 과거에서는 벗어나고 싶다.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;학점 관리를 실패했지만, 이력 관리도 제대로 하지 못했고, 학회 운영도 잘하지 못했던 것 같지만, 좋은 사람들을 만날 수 있었고, 해피엔딩으로 끝나게 된 한 해였다. 내년에는 올해의 해피엔딩이 지루해보이게끔 SWAG 넘치는 삶을 살고 싶다.&lt;/p&gt;</content><author><name></name></author></entry><entry><title type="html">프로그래머스의 윈터코딩에 참여하다</title><link href="https://kodingwarrior.github.io/post/2018/11/06/participating-in-winter-coding" rel="alternate" type="text/html" title="프로그래머스의 윈터코딩에 참여하다" /><published>2018-11-06T00:00:00+00:00</published><updated>2018-11-06T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2018-11-06-Participating-In-Winter-Coding.md</id><content type="html" xml:base="https://kodingwarrior.github.io/post/2018/11/06/participating-in-winter-coding">&lt;h1 id=&quot;프로그래머스의-윈터코딩에-참여하다&quot;&gt;프로그래머스의 윈터코딩에 참여하다&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/4rCkjWbJ4CPCZyGZTRJ4uRJDVAW2DFCbvtGVBt5bHocPc6kRvNyx_TgM8B6pWo-xjn0D5alar1suBUcNxK3ICxmLwLrNYZOVxPdOFnzUEryAnGpgU5RsT6E_6zefPm0WLu7N_ypfhIzFOb2xxtAraJOTuqf9loyjW2tNv2iBAMaWBei5dqMpk72i-_p5NYuJ3NtmxkRGmF4YSRe8U0Fh458xXcnhuOMXO7BN5WP8nwCinZUI_Xi4V0MrYqah9VF4icXRKLl19Y4qJyF8bV4EJaRyewLz_K_1JWI6Bc6EEVQP8pyxefBmaTA3SDABtfjFibaRqWSgln4evHocA4LrVgo-mj8HDaqyjyVcKQ9CM5SHqR49yeRFV5dGJNdXirLqQtjREKpJWjCWuL2akMUctPPuk07D3POBEXGOLisYd2Hij5GzVOdvdOQjj8_2Jo2z79GrSi_aQeCKZSGdgOUJzsVFLH3iU5wVGC4QZHm2QgnrdFOeezP9YFPTizau8veFdGdQ1Bf-U0DkNj1EVklBKV1eV2lKAegzUBuSy5zSCrpiDVDnSpR1J9jXuJcIogDYJejxlQPd6thJ1S0oIIWUchpt6J91aqJqiP8rrzdE-xErRMXUojXO1x4SGJC0zRzZaTXm5Tk2BP2AR-Over5-u-pYB26hjOYkjIvkkV8Lcwjp-eS7DK9W3D6U1wgv_iqGFO_Wk3dff8BFot12hg=w546-h728-no&quot; alt=&quot;윈터코딩 포스터&quot; /&gt;&lt;/p&gt;

&lt;p&gt;나는 평소처럼 넋놓고 학교 게시판을 보고 있던 와중, 눈길을 끄는 어떤 포스터를 보게 되었다. 스타트업 겨울 인턴십 공고 포스터였다. 역시나 &lt;code class=&quot;highlighter-rouge&quot;&gt;작년에 봤던 것처럼 프로그래머스를 통한 인턴십 채용과 관련된 공고 포스터겠구나&lt;/code&gt;하는 생각이 들었는데, 참여 기업 명단에 지그재그의 &lt;code class=&quot;highlighter-rouge&quot;&gt;Croquis&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;코인원&lt;/code&gt;이 내 눈을 이끌었다. 스타트업을 가게 된다면 이 회사에서 일해보고 싶은 생각이 들었던 회사였는데, 이 때가 아니면 언제 여기서 일해볼 수 있을까라는 생각이 들어 망설일 틈이 없이 바로 지원을 하게 되었다. 굳이 인턴이 아니더라도, 혹시나 계속해서 일하게 된다면 졸업을 앞두고 휴학을 길게 잡을 생각할 정도로 간절했다.&lt;/p&gt;

&lt;p&gt;지원서를 쓰기 전에 앞서, 윈터코딩 일정을 자세히 알아보았는데 윈터코딩은 크게 다음과 같이 일정이 되어있는 모양이었다.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;1차 선발 코딩테스트 : 흔히 말하는 알고리즘 문제를 빠른 시간안에 풀어야 하는 테스트&lt;/li&gt;
  &lt;li&gt;2차 선발 개발과제 : 요구사항을 주면, 그 요구사항에 맞게 각자 원하는 프레임워크, 각자 원하는 방식대로 구현해서 코드를 제출하는 것&lt;/li&gt;
  &lt;li&gt;스타트업 인터뷰 : 스타트업 돌아다니면서 인터뷰를 하는 것 같다. 개인적으로는 원하는 회사 찾아가서 인터뷰하고 싶은 생각이 들기도 하는데, 다양한 경험도 나쁘지는 않다.&lt;/li&gt;
  &lt;li&gt;교육 프로그램 : 12월 초부터 12일 정도 기간 잡고 빡세게 OJT 하는 모양이다. 근데 기말고사 기간이다(….)&lt;/li&gt;
  &lt;li&gt;인턴 근무 : 12월 중순부터 실무에 투입하는 것 같다. 사실 이게 제일 기대된다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/5eeGyxnhugf85NoJCszQeQx_QsEo6kfBXJnK82L5PrF3k1aHgKPXCoipg-DpZsVYAx9IgSTeqiUcvvakm1vGjKeI4sgh2XWusA7SZuDFBAswjeewbgyX_0bzJ2E0W3y4oedQ76n8mB6HQgxJe1d8Ht0RljafEYir4U8TvG5nqoUJipLR9Pkve-j9V3QfVbpVtr6Qv-gcIEx_q1H4daCmwmB7uwHReYQ6oOf_wGEaHlsO_iKbCLGS-dDBMN0yYB6SMjnlONpWl3DIiv6QGh9sM6y7T5NWe6I3oTPefrvCJOQYKdU_KGJJYGAqUzrBJKA9GajAMSePj5bWLpl4vPcXTQ-Oq2fLM1eS59-92SPWW824M4vwP8rLtdKiHYb53EniMHnatuTOgfIGMLN8DRb425O1gLYTbXiXnCxMhpxttERbqxja6NDmrp6KTvlpz_hg23PmF9jtFcepW5Vthx4PNHos-Fu9DX0-2c7dpJ0XKSsPE3yOPSs4WUtQQCwyThCLIgJoPJR1KePLlslUhiYaTZq5ds5nMR2Y75FdeWrBYqpFZPFzfPocT8gDU9i6VPpgX2hlYo3uxm_q6k9IC_irakLiiSQEEqVRT7CmvfwPAF244co74KnqHTQtjn0wr3ErhJ9mZjQZcrMWDUJfQf6XkrWL0ySi7ub8hKIB2XxSjcMQRR2vtXTgh3QDop39MqzblCLqa4PX_9P9PlerMg=w228-h220-no&quot; alt=&quot;CPU 3000% 풀가동&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이렇게 부푼 기대를 가슴에 안고 이력서를 쓰게 되었는데, 음…. 정말 적을 게 없었다. 이력서 양식에는 &lt;code class=&quot;highlighter-rouge&quot;&gt;회사에 속해서 개발자로서 얼마나/어떻게 일했는지를 적는 직무경험&lt;/code&gt;을 적는 란이 있고, 개인적으로 만들어본 &lt;code class=&quot;highlighter-rouge&quot;&gt;토이 프로젝트&lt;/code&gt;를 적는 란이 있었지만, 번역을 했던 경험이라던가 학술동아리에서 활동한 경험을 적을 수 있는 란도 없었고, &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;오로지 개발 경험만&lt;/code&gt;&lt;/strong&gt; 적어야 했다. 사실 프로젝트 엄청 옛날에 몇개 깔짝깔짝 만들어본 적이 있긴 했지만, &lt;code class=&quot;highlighter-rouge&quot;&gt;굳이 이런걸 써야하나?&lt;/code&gt; 혹은 &lt;code class=&quot;highlighter-rouge&quot;&gt;이런걸 써도 되나?&lt;/code&gt; 싶은 생각이 드는 프로젝트가 많았어서 일부러 이력서에 적지 않았다. 오로지, 학력 기재사항에만 밑에 짤막하게 &lt;code class=&quot;highlighter-rouge&quot;&gt;알고리즘 학회 창설멤버 및 학회장, 학회 위키 구축 및 운영 경험, 1년 반에 걸친 알고리즘 교육 경험&lt;/code&gt; 정도만 적었다. 이런걸 예상하고는 있었지만, 스스로를 돌 볼 시간이 없었다는 점에 회의감이 들기도 했다.&lt;/p&gt;

&lt;p&gt;지금까지의 인생을 되돌아보면, 개발경험이라기보다는 커뮤니티 활동 경험만 많은 편이었다. 2016년에 제대하자마자 Elixir School 이라는 Elixir 튜토리얼 문서를 번역하면서 함수뽕이 차오르기도 했고, 번역하다보니 재밌어서 7~8월 쯤에 ROR 커뮤니티에서 주관하는 레일스 워크숍을 하면서 프로젝트 결과물을 뽑으면서도 레일스 공식 문서 번역을 리뷰하기도 했었다. 군인이라는 신분 때문에 참여하고 싶어도 참여하지 못했던 Lisp 세미나를 가게 되면서부터 시작된 인연으로 그 다음해 3월에 Clojure Bridge 워크숍에서 코치로 활동하기도 했다. 2017년도 하반기부터는 알고리즘 동아리 회장을 자진해서 맡고 학부연구생으로 들어가면서부터 외부와의 연락을 거의 단절하면서 살아왔다. 학교라는 제한된 범위에서 활동하다보니 학교 밖에서 놀던 자유롭던 시절이 그립기도 했고 답답한 1년을 보내왔다. 그렇게 1년의 공백기간을 살다가, 2018년 7월에 열린 Django Girls 워크숍에서 코치로 활동하게 되었고, Django Grils에서의 인연으로 원래 단골로 갔던 정기 꾸준 코딩 모임 &lt;code class=&quot;highlighter-rouge&quot;&gt;PyJog&lt;/code&gt;를 공동 운영하게 되면서 밖으로 나갈 준비를 하고 있는 상황이다. 이런 자잘한 TMI를 얘기하는 걸 좋아하는데, 이력서에는 그런 얘기를 적기에는 양식이 모자란 느낌이 없지 않았다. 그런데 어떻게 생각해보면, 실력으로 승부해야한다면 이런 양식을 쓰는게 오히려 맞을 수도 있긴 할 것 같다. 내가 스스로 생각하기에도 밖으로 나가기에는 그 동안 준비가 너무 소홀하기도 했기 때문이다.&lt;/p&gt;

&lt;p&gt;경력이라 할 것도 없으니, 정말로 내가 가진 실력으로만 승부해야겠다는 생각이 들었다. 결국 이력서에는 학력사항만 기재하고, 알고리즘 학회의 학회장이었다는 사실만 짤막하게 적었다.&lt;/p&gt;

&lt;h2 id=&quot;코딩-테스트&quot;&gt;코딩 테스트&lt;/h2&gt;

&lt;p&gt;코딩 테스트는 중간고사가 끝난 직후에 시작되었는데, 코딩 테스트는 그냥 간단하게 언급만 하려고 한다. 코딩 테스트에는 꼭 합격하기 위해서 최근 2년 간의 기출문제를 쉬지않고 풀었다. 단순히 코딩테스트가 어느 정도 난이도인지 가늠하기 위해서였다. 문제 세트가 대부분 한 문제 빼고는 쉽게 풀 수 있는 수준이었다. 내가 풀지 못했던 그 한 문제는 다이나믹 프로그래밍 유형의 문제였기 때문에, &lt;code class=&quot;highlighter-rouge&quot;&gt;이번 코딩 테스트에는 DP 안 나오게 해주세요&lt;/code&gt;하고 속으로 빌었다.&lt;/p&gt;

&lt;p&gt;그리고, 10월 27일 온라인 코딩테스트를 2시간 동안 치게 되었는데, 2시간에 3문제 정도 밖에 안 주길래 속으로 &lt;code class=&quot;highlighter-rouge&quot;&gt;띠용&lt;/code&gt;하는 생각이 머릿속을 스쳤다. 처음 2문제는 BOJ의 &lt;code class=&quot;highlighter-rouge&quot;&gt;구현&lt;/code&gt; 카테고리 문제만 풀 줄 알면 어느 정도 풀 수 있는 수준의 난이도였고, 마지막 문제는 이분탐색으로 슥삭할 수 있는 문제였다. 머리가 좀 빠릿빠릿하게 돌아갔으면, 40분 안에는 풀 수 있었을 것 같기도 한데, 엉뚱하게 접근한 것도 있었고 이상한 삽질을 많이 하다보니 1시간이 지나서야 겨우 올솔브했다. 난이도가 너무 낮아서 타임어택으로 떨어지는게 아닌가하고 속으로 걱정하기도 했고, &lt;code class=&quot;highlighter-rouge&quot;&gt;코딩 테스트 합격하더라도 최종 합격 여부는 개발 과제에서 결정나겠구나&lt;/code&gt;라는 생각이 들기도 했다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/rulgIdr6MriSe-FGO1hKsq0sO8aZP6GDcSx8K8ofR8Fcb9CypTpshhH2cN5OcLXC1jiIFkISJp7_G9y1OzC-k4dp-mlJ33kge_bzJ9EJOVlP4CawcgBJ9gwSsNxhfRC399KRTKfnZr2auV8y1QUBAq-5pSTb7fYdVfkYy7TIyN5o7ZYMLgW1_zX6f37BGGqoK8qkA2eM5zcwyIqDVK1mZXPntC_Px50LXV8Z-D44DIXUcE7Yu8HgjXEKLD0Tc_3jm1bIMqMV8EhIbLAZOS-maVbXszpG1aMrpBqij0vaCeKZrn0kZ-YRRT_Wki7h2xXfMZ5uX0vmR0m3a3bN6KfYIGyMUXTKLcdrBi6EdFNyu55n_9ZJSVqLHLoBRcvVQdFCjtkX3Y3sxyhxAq4FNn_zW2n0sbzrGpBFaWb4a34C0xD7dfggc5kpsnSma-SPKPcBqL_dvILbmeZmKx8aNM57uzcLkGrJGd_b0xzWuJBVG9-mchc4icBGASP_dWHK2OPfTpduI5U6pxtPFRWvedBVZQBAmvQBN3OqxpmGK3sphVm_CNepSmW9Fev2tTl0_XIk9TFNNETVDMftn2PJa6akRqS83HaALHv-8jvcjl3qcp2Yx2EvYrkFvOFrzjiv8ewrErU3TLRhKY8F5mH3RCCZowi-X5N5XPFAjMHqI2DKxuF47yCID7z-S4-_E4WMUB90r_aFYyxOIVHsuJ5Vbg=w1896-h1052-no&quot; alt=&quot;합격 통보 메일&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이렇게 2일 동안 이런저런 생각을 하던 사이, 10월 29일 프로그래머스에서 윈터코딩 코딩테스트 합격 통보 메일을 받았다.&lt;/p&gt;

&lt;h2 id=&quot;개발-과제&quot;&gt;개발 과제&lt;/h2&gt;

&lt;p&gt;코딩테스트 합격 통보 메일을 받으면서, 한편으로는 흐뭇한 생각이 들기도 했지만, 역시나 본 게임은 여기서 시작이었다. 메일에는 코딩테스트 합격 결과와 함께 웹/모바일/머신러닝 분야별로 과제가 주어졌고, 나는 그나마 자신이 있는 웹 분야 과제를 하기로 했다. 웹 분야의 과제는 다음과 같이 요구사항이 주어져 있었다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;새로운 TODO(제목 + 내용)를 작성한다&lt;/li&gt;
  &lt;li&gt;사용자의 선택에 의해 TODO에는 마감 기한을 넣을 수 있다.&lt;/li&gt;
  &lt;li&gt;우선순위를 조절할 수 있다.&lt;/li&gt;
  &lt;li&gt;완료 처리를 할 수 있다.&lt;/li&gt;
  &lt;li&gt;마감기한이 지난 TODO에 대해 알림을 노출한다.&lt;/li&gt;
  &lt;li&gt;TODO 목록을 볼 수 있다.&lt;/li&gt;
  &lt;li&gt;TODO 내용을 수정할 수 있다.&lt;/li&gt;
  &lt;li&gt;TODO 항목을 삭제할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;요구사항은 그렇게 어렵지는 않아 보였다. 전형적인 Todo 앱이었다. 어느 정도 개발에 기본기가 충분한 사람이라면 빠르게 만들 수도 있을 것이다. 나는 개발에 그렇게 능숙한 사람도 아니기 때문에, 설계는 둘째치더라도 구현을 오래할 것 같은 예감이 들었다. 주 개발스택을 Ruby/Rails에서 Python/Django로 갈아타는데서 진통을 겪고 있는 입장이기도 했고, 학회 홈페이지를 Django 기반으로 구축하겠다고 해놓고, 사용자 인증에서 매번 막히고, Redux도 제대로 익히지 못할 정도로 상당히 미숙했기 때문이었다. 교양 레포트 과제 제출 마감기한도 끼어있었는데, 나한테는 개발과제가 더 중요했기 때문에 어쩔 수 없이 교양은 드랍하고 개발과제에 몰빵하기로 했다.&lt;/p&gt;

&lt;p&gt;그래도 이왕이면 오랜만에 실서비스를 가정하고 개발하는 것이기 때문에, 쓰고 싶은 스택대로 시도해보면서, 지금까지 해본 적도 없는 모험적인 방법으로 구현을 해보기로 했다. 어쨌거나 구현해야하는 결과물은 Todo List 어플리케이션이기 때문에, 평소에 자주 사용하고 있는 Todoist를 참고하면서 개발하기로 했다. 왠만하면 RESTful API 서버를 개발하는 쪽으로 가는게 트렌드이기 때문에, Django REST Framework를 이용하여 RESTful API 서버를 개발하는 방향으로 가면서도, 프론트엔드가 없으면 아주 아주 섭하기 때문에 프론트엔드는 잠깐잠깐 깔짝거리던 React를 쓰는 방향으로 가게 되었다.&lt;/p&gt;

&lt;h3 id=&quot;개발과제를-하면서-알게된-자잘한-것들&quot;&gt;개발과제를 하면서 알게된 자잘한 것들&lt;/h3&gt;

&lt;p&gt;내가 가진 모든 시간을 개발과제에 투자했다. 어쩌다 엄청난 우연으로 진지한 만남을 고려하게 된 사람이 있게 되긴 했지만, 양해를 구하고 오로지 개발과제에만 투자했다. 오랜만에 하는 웹개발인 만큼, 최대한 퀄리티를 높여서 개발하는 방식으로 진지하게 개발에 임했다. 프론트엔드는 내가 주력으로 하고자 하는 분야가 아니다보니 React 코드가 들어간 부분은 연구실에서 프로젝트할때 썼던 코드 일부를 재활용하긴 했지만, 백엔드에 들어가는 코드는 왠만하면 예전 코드 재탕없이 레퍼런스 문서를 참고하면서 작성했다. Todoist를 참고하면서 개발했기 때문에, UI로 얼추 흉내낼 수 있는 수준으로 코드를 짰다.&lt;/p&gt;

&lt;p&gt;파이썬으로 실서비스로 웹개발을 해본 것은 Flask로 해본 게 처음이었고, Django를 이용해서 직접 개발에 투입해본 적은 거의 없다시피 했는데, 한번 집중해서 개발해보니 이만큼 좋은 것은 없겠다는 생각이 들기도 했다. 책보며 독학하는 것보다는 요구사항이 명확하게 주어진 상황에서 이를 구현하기 위해 발악하는 과정 자체가 정말 나에게 큰 도움이 되었다. 개발을 하게 되면서 Django에 애정을 가지는 수준까지 가게 되어버렸다. Django를 이용해서 개발하면서 어떤 점에서 애정을 가지게 되었는지 몇가지만 찝어서 얘기해보고자 한다.&lt;/p&gt;

&lt;h4 id=&quot;django에-내장된-db-모듈의-기능&quot;&gt;Django에 내장된 DB 모듈의 기능&lt;/h4&gt;

&lt;p&gt;Django에는 모델을 다루는데 굉장히 쓸만한 여러가지 유틸리티 함수, 클래스가 내장되어 있었다. Django에는 자체적으로 ORM이 내장되어 있으며, ORM에는 데이터베이스에 있는 여러개의 레코드를 다루기 위한 &lt;code class=&quot;highlighter-rouge&quot;&gt;QuerySet&lt;/code&gt;이라는 클래스가 있다. 데이터베이스의 &lt;code class=&quot;highlighter-rouge&quot;&gt;TodoEntry&lt;/code&gt; 테이블에 있는 모든 레코드를 불러오고 싶다면 &lt;code class=&quot;highlighter-rouge&quot;&gt;TodoEntry.objects.all()&lt;/code&gt; 코드를 실행하여 &lt;code class=&quot;highlighter-rouge&quot;&gt;TodoEntry&lt;/code&gt; 테이블의 모든 레코드의 정보를 담고있는 &lt;code class=&quot;highlighter-rouge&quot;&gt;QuerySet&lt;/code&gt; 인스턴스를 얻을 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/jqBByjyfGug1RhHCW12RfJquePXkT0nG_ikkTCWOpdiUGMQ3vkGT0nOjZcZ6R-5Y5PqrnEYRvM2jQKMzb4H5XGFKDFTn6TuoRcXl_ebk4DsTE0E2MUudlBzDn1C83uvcL_S6uSPVpu309mlkayj0uLTgDHbCRLxr1E__hbU_vmyGhCGXTVgicTWh769bH1cMv-XxvrJYjKvnRX1iq4evHTOa_SOUMhXn3l5v5x1D3qraef0ObR16dTqAiq9R7bWew9nsb16R9mwBXvjYp_3FMWFYWFPHdyQmII6XxOGNcaumgp7usE9wMds-L1MBMVIgGEHwi_AWU9dwvcMrQZLHfud46ZqVfSFV69nmJiTVD7Ja-mVMI98Tw91yfCZHmqyytgSJvJ4t-vqhidP1mMK-AXQhghXx46SoYueSKcEzSNVuR8hPTplrfoepuYErFuE-lXPfImMzgGw-yFr5-Tuw9XpsNbTZ-PT4yQ5puiLq-KC3gjB9u7Uo6B5gyt2BroOw5BcOQkVSWbSgPmQ4c2ed_A4o389ZNkqCd4SMVzUfiekClS0NfaNMcibwm28CbRU9HQ6lezKRL5gkP6h_9n9PK1sZhE7zxYxLAig5hDxl7qrpauWAER3lb0RUkyW0kHiIfT5nxA7SoNPpvuXINOLCxZluQAkoMEDHquegMmeJNdLy-TJH-RGNC3LEEuGDcROPWmh36N1qT5wO172JAQ=w894-h576-no&quot; alt=&quot;Todoist 홈 화면&quot; /&gt;&lt;/p&gt;

&lt;p&gt;앞에서 Todo 앱을 구현할 때, Todoist를 많이 참고했다고 언급했었다. Todoist의 홈 화면에는 기한이 지난 할 일 목록과 앞으로 처리해야할 할 일 목록을 따로 보여주는 방식으로 구현이 되어 있었는데, 이를 구현하려면 당연히 두 개의 리스트로 따로 나눠서 구현해 한다. 두 개의 리스트를 이용해서 React 같은 걸로 동적으로 렌더링해야할 것이다. 각 할일마다 마감기한이 있을 수도 있고, 마감기한이 없을 수도 있기 때문에(NULL을 허용하는 방식으로 구현할 수 있다) 다소 복잡한 로직이 들어갈 수도 있을 것이다. 마감기한은 기한이 지났는지 여부는 매시간마다 태스크를 수행하는 방식으로 구현하거나 칼럼을 따로 추가하는 방식으로 구현하기에는 너무 비효율적이라는 판단이 들었기 때문에, SQL 문을 실행하듯이 레코드의 모든 정보를 긁어오면서도 출력된 결과물의 각 레코드마다 추가적인 칼럼을 추가하는 방식으로 구현하기로 했다.&lt;/p&gt;

&lt;p&gt;하지만, 한 가지 의문점이 있었다. 홈 화면을 불러올때 실행되는 View의 코드에서 매번 복잡하게 쿼리를 수행해야 하는가? 쿼리를 좀 더 깔끔하게 수행하기 위해서 모델 수준에서 해결할 수 있는 방법은 없는 것일까? 그렇게 Django 공식 문서를 찾아보다가 &lt;code class=&quot;highlighter-rouge&quot;&gt;Manager&lt;/code&gt; 클래스라는 것을 알게 되었다. &lt;code class=&quot;highlighter-rouge&quot;&gt;TodoEntry.objects.all()&lt;/code&gt;에서 &lt;code class=&quot;highlighter-rouge&quot;&gt;objects&lt;/code&gt;는 사실 &lt;code class=&quot;highlighter-rouge&quot;&gt;Manager&lt;/code&gt; 클래스의 인스턴스였고, 모델 클래스에서 다른 &lt;code class=&quot;highlighter-rouge&quot;&gt;Manager&lt;/code&gt; 클래스의 인스턴스인 멤버변수를 정의하면 내가 원하는 &lt;code class=&quot;highlighter-rouge&quot;&gt;QuerySet&lt;/code&gt;을 반환하는 쪽으로 구현이 가능할 것만 같았다. &lt;code class=&quot;highlighter-rouge&quot;&gt;objects&lt;/code&gt;가 &lt;code class=&quot;highlighter-rouge&quot;&gt;QuerySet&lt;/code&gt;을 반환하는 방식을 유지하면서도, 내가 원하는 &lt;code class=&quot;highlighter-rouge&quot;&gt;QuerySet&lt;/code&gt;을 가져올 수 있도록 &lt;code class=&quot;highlighter-rouge&quot;&gt;RemainingTodoManager&lt;/code&gt; 클래스를 정의했다. 기존의 쿼리셋은 완료한 작업에 대한 레코드도 같이 가져오는 반면, 내가 정의한 방식대로 가져오게 되는 쿼리셋은 완료하지 않은 작업에 대한 레코드 만을 가져오면서도 기한이 지났는지 여부를 추가적인 칼럼을 붙이는 방식으로 구현되어야 한다. 마감기한은 현재 시간을 기준으로 대소비교를 할 수도 있지만, 마감기한 칼럼에는 NULL을 허용하도록 조건을 추가했기 때문에 NULL 검사도 따로 해줄 필요가 있었다. 이런 귀찮고 번거로운 작업을 모델에서 질의를 수행하는 시점에서 해결할 수 있도록 하는게 이상적이다.&lt;/p&gt;

&lt;p&gt;그래서, 이 문제를 어떻게 해결할 수 있을까하고 공식문서를 찾던 와중 &lt;code class=&quot;highlighter-rouge&quot;&gt;QuerySet&lt;/code&gt; 클래스에 &lt;code class=&quot;highlighter-rouge&quot;&gt;annotate&lt;/code&gt; 메서드가 있다는 것을 알게 되었다. &lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;annotate&lt;/code&gt;&lt;/strong&gt;의 사전적 의미만 보아도 알 수 있듯이, &lt;code class=&quot;highlighter-rouge&quot;&gt;주석 달다&lt;/code&gt;라는 뜻이다. 즉, 각 레코드마다 조건 검사를 수행하여, 각 레코드의 조건을 보았더니 &lt;code class=&quot;highlighter-rouge&quot;&gt;이게 어떤 유형의 레코드였더라&lt;/code&gt; 하는 정보를 쿼리셋 내부에서 추가적인 칼럼을 만들 수 있다. 조건검사를 어떻게 하고, 칼럼에다가 어떻게 값을 대입하는지 공식문서를 찾아보면서 &lt;code class=&quot;highlighter-rouge&quot;&gt;Q&lt;/code&gt; 객체를 알게 되기도 했고, &lt;code class=&quot;highlighter-rouge&quot;&gt;Case&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Value&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;When&lt;/code&gt;과 같은 괜찮은 유틸리티 함수를 알게 되었으며, 아래와 같이 코드를 짤 수 있었다.&lt;/p&gt;

&lt;div class=&quot;language-python 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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.db&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.db.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;When&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.db.models.functions&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Now&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.utils.timezone&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;PRIORITIES&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;긴급&apos;&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;s&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;중요한 일&apos;&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;s&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;평범한 일&apos;&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;s&quot;&gt;&apos;4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;사소한 일&apos;&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;# 완료한 작업을 제외한 모든 Todo Entry에 대한 질의를 수행
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RemainingTodoManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Manager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_queryset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&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;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RemainingTodoManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&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;get_queryset&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;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;completed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&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;annotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;outdated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;# deadline 필드가 NULL이 아니면서, 
&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;# 현재 시간보다 적으면 기한이 지났다고 표시
&lt;/span&gt;                &lt;span class=&quot;n&quot;&gt;When&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deadline__isnull&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                    &lt;span class=&quot;n&quot;&gt;deadline__lte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; 
                    &lt;span class=&quot;n&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;output_field&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BooleanField&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;c1&quot;&gt;# Create your models here.
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TodoEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    TodoEntry Model
    할 일 목록의 각 엔트리가 가지는 속성을 정의한다.
    * title : TodoEntry에서 제목을 의미한다.
    * description : TodoEntry에서 구체적으로 어떤 일을 할 것인지를 의미한다.
    * priority : TodoEntry에서 할 일의 우선순위를 의미한다.
    * completed : TodoEntry에서 할 일의 완료 여부를 의미한다.
    * deadline : TodoEntry에서 마감기한을 의미한다.
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;completed&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BooleanField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;priority&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CharField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_length&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;n&quot;&gt;choices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PRIORITIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;deadline&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTimeField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTimeField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;updated_at&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTimeField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Query Set 정의
&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;entries&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Manager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remaining&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RemainingTodoManager&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;h4 id=&quot;db-설정의-간편함&quot;&gt;DB 설정의 간편함&lt;/h4&gt;

&lt;p&gt;개발과제로 제출한 서비스는 깃헙에 커밋이 올라가자마자 CircleCI를 거쳐서, Heroku 서버로 배포되는 과정을 거친다. Heroku는 DB로 Postgres를 쓰게 되는 경우가 많은데, Django에서 쓰는 Postgres 커넥터 라이브러리인 psycopg가 계속해서 말썽을 부리는 것이다. &lt;code class=&quot;highlighter-rouge&quot;&gt;symbol __res_maybe_init, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference&lt;/code&gt; 이런 메시지가 뜨는 에러였는데, &lt;strong&gt;제출 마감기한 4시간을 앞두고&lt;/strong&gt; 이 에러를 고치느라 사경을 헤메는 것 같은 생각이 들었다. 스택오버플로우를 참고하면서 가능한 온갖 트러블슈팅 방법을 다 시도해보았지만, 이건 Heroku 서버 문제이면서 Postgres에 문제가 있는거구나라는 결론을 내리게 되었다. 그래서, 배포 문제를 어떻게 해결해야하나 고민하던 와중, Heroku에서 MongoDB 애드온을 지원한다는 사실을 알게 되었다.&lt;/p&gt;

&lt;p&gt;그래서 코드를 급하게 수정했다. 사용하는 라이브러리만 바꾸었을 뿐인데 성공적이었다.(!!!!) 아래의 코드는 환경설정에 해당되는 &lt;code class=&quot;highlighter-rouge&quot;&gt;settings.py&lt;/code&gt; 파일의 소스코드 일부분인데, DB 백엔드를 Postgres에서 MongoDB로만 바꿔서 쓰겠다하고 한줄을 수정했을 뿐이었는데, 그냥 돌아갔다. 모델 부분의 코드를 일괄적으로 뜯어고칠 필요가 없었던 것이다.&lt;/p&gt;

&lt;div class=&quot;language-python 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;n&quot;&gt;DATABASES&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;s&quot;&gt;&apos;default&apos;&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;s&quot;&gt;&apos;ENGINE&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;djongo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;s&quot;&gt;&apos;NAME&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;NAME&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;	
		&lt;span class=&quot;s&quot;&gt;&apos;HOST&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;HOST&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
		&lt;span class=&quot;s&quot;&gt;&apos;USER&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;USER&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
		&lt;span class=&quot;s&quot;&gt;&apos;PASSWORD&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;PASSWORD&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
		&lt;span class=&quot;s&quot;&gt;&apos;PORT&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;PORT&apos;&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;내가 왜 이런거에 감동을 느끼게 되었는지에 대해 설명하자면, 과거의 경험을 설명하지 않을 수 없다. Rails로 개발할 당시에는 모델과 관련된 코드를 짤 때 RDBMS 기반으로 코드를 짜느냐, MongoDB 기반으로 코드를 짜느냐에 따라 코드를 짜는 방법이 달랐는데, RDBMS 기반으로 코드를 짜게 되면 모델 클래스가 ActiveRecord 클래스를 상속하는 방식으로 코드를 짜야 했고, MongoDB 기반으로 코드를 짜게 되면 &lt;code class=&quot;highlighter-rouge&quot;&gt;Mongoid&lt;/code&gt;의 Document 모듈을 모델 클래스 안에서 mixin을 해야 했다. 사용하는 DB를 바꾸게 되면, DB 때문에 모든 모델의 코드를 뜯어고쳐야 할 수도 있는 위험성이 보였다. Flask도 역시 예외는 아니었는데, Flask도 어떤 DB를 쓰느냐에 따라 SQLAlchemy 기반으로 코드를 짜야 할 수도 있고, MongoEngine 기반으로 코드를 짜야 할 수도 있다. 그런데 Django는? 그런거 없다. 그냥 DB 백엔드를 뭐로 쓰는지 바꿔주기만 하면 된다. 당연히 엄청 추상화가 잘 되어 있어서 그런 탓도 있겠지만, DB 백엔드 설정만 한 줄 바꿔줬을 뿐인데 삶의 질이 확 올라가는 것이 느껴졌다.&lt;/p&gt;

&lt;h3 id=&quot;이런건-정말-아쉬웠다&quot;&gt;이런건 정말 아쉬웠다&lt;/h3&gt;

&lt;p&gt;윈터코딩 개발과제까지 하면서 한 편으로는 괜찮게 느껴진 것들이 많았지만, 다른 한 편으로는 아쉽게 느껴진 것들이 많았다. 시스템에 아쉽게 느껴진 것이라기보다는 스스로에게 아쉽게 느껴진 것들이라 할 수 있을 것이다.&lt;/p&gt;

&lt;p&gt;첫번째로는 &lt;strong&gt;TDD에 너무 미숙했다&lt;/strong&gt;는 점이다. 가산점을 얻기 위해 어떻게든 TDD를 끼얹어보려고 노력하긴 했으나, 연습장처럼 쓸 목적으로 TDD 쓰기만 하다보니 Unit Test, Integration Test를 고려하면서 TDD 코드를 제대로 작성해본 적이 거의 없었고, 심지어 RESTful API 서버를 개발하면서 TDD 코드를 작성해본 적도 없다. 언젠가는 하겠지, 언젠가는 하겠지하고 미루고 미루다보니, 막상 때가 다가오니 아무 손도 쓰지 못하게 되었다는 점에서 보면 너무 아쉽게 느껴진다.&lt;/p&gt;

&lt;p&gt;두번째로는 &lt;strong&gt;사용자 인증 기능을 구현하지 못했다&lt;/strong&gt;는 점이다. 개발 과제에서의 요구사항은 실 서비스에서 사용할 수 있는 수준의 퀄리티를 원하는 것일텐데, 사용자 인증은 Rails를 이용해서 웹서비스를 개발했을때도 라이브러리를 그냥 갖다쓰기만 해서 개발해오기만 했지 혼자 힘으로 구현을 못하는 경우가 대부분이었다. 심지어, RESTful API 서버를 개발할때는 더 막막했다. 주워들은 바로는 JWT(Json Web Token)을 이용한 사용자 인증이 있는 모양이다. 하지만, 아직까지 그럴만한 역량이 충분하지 못했다는 것이 너무 아쉬웠다.&lt;/p&gt;

&lt;p&gt;세번째로는 &lt;strong&gt;나는 아직도 상태관리 라이브러리에 익숙하지 못했다&lt;/strong&gt;는 점이다. 연구실 관련 일때문에 자진해서 React 중심으로 만져오긴 했었지만, 상태관리 라이브러리를 다루는데 그렇게 익숙하지 못했다. 연구실을 도중에 나오기 전까지도 나는 여전히 Redux가 있다는 것만 알고 있지, Redux를 제대로 쓸 줄 몰랐으며 지금도 제자리 걸음이다. 주변에서는 MobX를 쓰는게 어떠냐는 권유를 하긴 했지만, Redux도 이해를 제대로 못하고 있는데, MobX는 그 나름대로 난해하게 느껴지는 구조였기 때문에 결국 쓰지는 못하고 React + axios만 써서 프론트엔드 작업을 해왔던 것 같다. 물론, 내가 프론트엔드 중심으로 가려는건 아니지만, JWT를 이용한 사용자 인증과 관련해서도 장벽이 느껴지는 부분이었기 때문에 항상 아쉬움이 남아있다.&lt;/p&gt;

&lt;p&gt;네번째로는 &lt;strong&gt;시간에 쫓겨서 작업하느라 문서화가 미비했던 점&lt;/strong&gt;이다. 오랜만에 실서비스를 가정한 개발이라는 것에 손을 대었던 만큼, 개발을 하면서도, 배포를 하면서도 흔히 말하는 &lt;code class=&quot;highlighter-rouge&quot;&gt;맞왜틀!!!&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;맞는데 왜 틀리지!!!&lt;/code&gt; 를 외치며 분노의 수정작업을 하느라 시간을 엄청 잡아먹게 되었다. 문서화를 하고 나서 코드를 짜자니, 내가 짠 코드도 믿을 수 없는 수준이라서 일단 돌아가는 코드를 짜는데만 집중했다. Django로는 실서비스를 개발한 경험이 많이 없다보니 시행착오를 엄청 많이 겪었고, 그렇게 잘 다루지는 못하는 React로 온갖 런타임에러를 뗌질하는데 대부분의 시간을 보냈다. 마감기한까지 2시간을 앞두고 돌아가는 코드를 제출하기는 했는데, 설치 방법에 대한 문서화, API에 대한 문서화, 웹 UI의 사용법에 대한 문서화를 놓고 보더라도 너무 아쉬운 것들 투성이였다. 이번 개발과제를 통해, 오랜만에 본격적인 개발을 접해보는 것이기도 하고, 이 때가 아니면 언제 온갖 새로운 방법을 다 써먹을 수 있을까 싶은 생각도 들었는데, 마감기한이 지나고나서 생각해보면, RESTful API 서버를 만들었음에도 Swagger API 문서 생성기를 올리지 못한게 너무 아쉽게 느껴졌다.&lt;/p&gt;

&lt;p&gt;사실 이것 외에도 아쉬운 점은 정말 많지만, 가장 걱정되는건 &lt;code class=&quot;highlighter-rouge&quot;&gt;너무 최소한으로 구현했던건 아닐까&lt;/code&gt;하는 것이다. 나도 역시 내 딴에는 퀄리티를 높이려고 노력을 했다고 생각하긴 하지만, 결과물만 보면 그렇게 성의가 들어간 작품으로 보이지는 않는다. 오히려 다듬고 더 다듬어야 하는 미완성작에 가깝다. 웹개발 과제로 제출한 코드는 어차피 만들기 시작한거 구데기인 상태로 방치는 할 수 없으니 단계적으로 개선해나갈 생각이다.&lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;윈터코딩은 어쩌면 올해의 내 운을 건 최후의 도박일지도 모른다. 학점을 챙겼을때 생길 수 있는 이점(졸업을 그나마 일찍하고 탈홍한다), 개발과제에 몰빵했을때 생길 수 있는 이점(인턴을 하게 될 확률이 높아진다)의 선택지 중에서 하나를 포기해야 했고, 나는 개발과제를 충실히 하는 쪽을 선택했다. &lt;code class=&quot;highlighter-rouge&quot;&gt;High Risk, High Return&lt;/code&gt; 이라는 말이 있듯이, 졸업도 못하고 인턴도 못하게 되어서 먹고 살기 힘들어지는 최악의 가능성도 생각하지 않을 수는 없다.&lt;/p&gt;

&lt;p&gt;레일스로 스택오버플로우 비슷한거 만들어본 적도 있었고, 게임개발동아리 임원이었을 당시 커맨드 패턴을 이용해서 쯔꾸르와 같은 플레이 방식을 구현한 적도 있었고, 라즈베리파이에 Vue.js를 올려보는 이상한 실험을 하긴 했었지만, 나 자신의 역량을 드러내는 프로젝트는 아니라는 생각이 강하게 들었다. 근데, 개발을 너무 쉬었던 탓에 토이프로젝트로 뭔가를 만들었다하면 이런거 밖에 없었다. 어떻게든 합격을 해야겠다는 심정으로, 이런걸 굳이 이력서에 써야하나 싶었던 프로젝트까지도 이력서에 한 3개 정도 적었다. 오히려 감점 요인이 될 수도 있지 않을까 싶어서 불안하기도 하다.&lt;/p&gt;

&lt;p&gt;비록 리스크를 감수하고 개발과제에 내가 가진 모든 시간을 쏟아붓긴 했지만, 실패해도 후회는 없을 것 같다. 개발과제를 하면서 조금은 해커톤을 하는 것 같은 느낌이 들기도 했었고, 오랜만에 머리를 쓰면서 개발하는 것 같은 느낌이 들어서 좋았고, 내가 어느 부분에서 한계를 느끼게 되는지 인지하게 되었으며, 앞으로 어떤 부분을 개선해야 할 지 되돌아볼 수 있게 되었다. 개발과제를 하는 것 자체는 정말 좋은 경험이다. 비록, 멘탈이 털릴 수도 있겠지만 그만큼 개발과제에 임하면서 배우게 되는 것들도 많고, 직무를 수행하기 위해서 최소한 어떤 것이 요구되는지 알 수 있고, 모자란 점을 개선하면서 성공에 한발짝 두발짝 다가갈 수 있기 때문이다.&lt;/p&gt;

&lt;p&gt;개발과제에 제출한 코드는 &lt;a href=&quot;https://github.com/malkoG/TodoQuest&quot;&gt;여기&lt;/a&gt;에 올렸으며, 추후에 포트폴리오에도 써먹을 수 있도록 단계적으로 개선하여 재활용할 계획이다.&lt;/p&gt;

&lt;p&gt;이제 11월 8일에 있을 합격자 발표를 기다려야겠다.&lt;/p&gt;</content><author><name></name></author></entry></feed>