<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>thomas-min.log</title>
        <link>https://velog.io/</link>
        <description>I build stuff.</description>
        <lastBuildDate>Fri, 29 Sep 2023 04:16:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>thomas-min.log</title>
            <url>https://images.velog.io/images/mgm-dev/profile/76927dd7-398c-4f09-baee-29391748b697/circle-cropped.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. thomas-min.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/mgm-dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[토스뱅크 FE 합격기]]></title>
            <link>https://velog.io/@mgm-dev/%ED%86%A0%EC%8A%A4%EB%B1%85%ED%81%AC-FE-%ED%95%A9%EA%B2%A9%EA%B8%B0</link>
            <guid>https://velog.io/@mgm-dev/%ED%86%A0%EC%8A%A4%EB%B1%85%ED%81%AC-FE-%ED%95%A9%EA%B2%A9%EA%B8%B0</guid>
            <pubDate>Fri, 29 Sep 2023 04:16:00 GMT</pubDate>
            <description><![CDATA[<h1 id="머리말">머리말</h1>
<p>먼저 토스팀에 먼저 합류하시고, 합격/이직 수기를 공유 해주신 분들에게 감사의 인사를 전한다. 글쓴이의 합격에 크게 기여했다. 이 글 또한 미래의 지원자들에게 도움이 될지는 모르겠지만, 최종합격 까지 과정에 대한 기억이 휘발되기 전에 글을 써본다.</p>
<h1 id="서류제출">서류제출</h1>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/d5a6e5ec-1911-41d4-8bc3-02a7a13a88ed/image.png" alt=""></p>
<p>창밖으로 비가 추적추적 내린다. 열심히 정리한 이력서와 급하게 써내려간 포트폴리오 파일을 몇번이고 다시 확인했다. 토스로의 첫 지원이다. 기회를 낭비하기는 싫었다. 고민하고 고민하다 보니 서류제출 마감일. 하필 마감일이 낀 주말에 부모님을 뵈러 고향에 내려갔다.</p>
<p>포트폴리오가 문제였다. 어떤 내용을 포함할지 몇번이고 바꿨지만 도통 마음에 들지 않았다. 여러번 고쳐쓰다보니 마음은 더 급해졌다. 마지막으로 모집요강의 내용을 다시 확인하고, 불필요하다고 생각되는 정보를 모조리 쳐냈다. 이쁘게 꾸미고 싶은 욕구와 줄글을 쓰고 싶은 욕구를 참아냈다. </p>
<p>결국 서울로 올라오는 버스 안에서 제출하기 버튼을 눌렀다.</p>
<h1 id="사전과제">사전과제</h1>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/6412cb67-2d6b-453f-bfc1-b7010aa73048/image.png" alt=""></p>
<p>서류가 통과 되었다. 이틀만에 유선으로 합격 연락이 온다음, 이메일로 사전과제 관련 안내가 날라왔다. 이때부터 토스팀의 빠른 일처리가 느껴졌다. 알 수 없는 오기로, 나도 최대한 빠르게 과정에 임하고 싶은 욕구에 타올랐다. 오는 일요일에 바로 과제를 진행해서 제출하겠다고 했다.</p>
<p>아뿔사, 그주 주말에 친구들과 양양에 가기로 약속이 잡혀있었고, 금요일 연차도 사용한 상태였다. 막무가내로 양양에 랩탑을 들고 내려갔다. 친구들은 이해해주는 한편 이상하게 쳐다봤다. 서핑샵에 붙어있는 카페에서 예상 문제를 상상하면서 코드를 끄적거렸다.</p>
<p>두가지 목표를 설정했다. 첫째, 토스팀에 합류하면 빠르게 적응 할 수 있다는 점을 코드로 어필 하기. 둘째, 같이 일하기 편해보이는 코드를 작성하기.</p>
<p>예전에 봤던 slash 컨퍼런스의 프론트엔드 발표 영상을 복기하고, slash 라이브러리의 코드들을 훑어 보았다. 토스뱅크의 프론트엔드 챕터에서 사용하고 있는 기술스택을 어떻게 과제에 녹여낼지 고민했다. 특히 emotion은 제대로 사용 해본적이 없어서 best practice 위주로 documentation을 속독했다.</p>
<p>휴가가 끝나고 서울로 돌아왔다. 일요일 점심이 다가왔고 과제의 상세 안내 사항을 안내 받았다. 주어진 시간은 8h. 요구조건들을 보자마자 만만치 않겠다 생각이 들었다. 어느 순서로 작업을 진행할지 결정하고, 1시간의 버퍼를 설정한 뒤 요구조건 별로 시간을 어떻게 배분 할지 결정했다.</p>
<p>버퍼를 설정한게 천만 다행이었다. 시간배분 실패로 마지막 일분 일초까지 사용했다. 시간 부족으로 넘어간 부분에는 주석으로 문제점과 개선 방향성을 남겼다. 나름 만족스러운 결과물을 제출했다.</p>
<h1 id="직무-인터뷰">직무 인터뷰</h1>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/1ae8037e-4a1f-4148-b23b-621a3a14e29d/image.png" alt=""></p>
<p>떨어졌구나, 생각이 들때 쯤에 과제전형 합격 연락이 왔다. 어찌나 기쁘던지! </p>
<p>직무 인터뷰는 제출한 사전과제 결과물과 이력서를 기반으로 진행한다고 안내를 받았다. 제출한 과제를 톺아보았다. 예상 질문 리스트를 만들고, 과제를 리팩토링하는 라이브 코딩을 연습했다. 이력서의 경우 항목별로 꼬리질문을 2 depths로 준비했다.</p>
<p>면접이 시작됬다. 다행히 내가 어필하고 싶은 부분을 콕찝어서 질문 해주셔서 마음껏 내생각을 전달 할 수 있었다. 답을 모르거나, 면접관의 의도를 잘못 파악해서 엉뚱한 대답을 몇번 했다. 그때마다 선문답을 하듯이 정답을 향해 대화를 이끌어 주셨다.</p>
<p>면접과정에서 내가 제대로 활용하고 있지 않았던 react-query의 기능과, compound component pattern의 장단점에 대해 알게되었다. 다음날 출근해서 새로 배운것을 바로 사용하는 방식으로 프로젝트의 코드를 리팩토링 했다. 기분이 아주 좋았다.</p>
<h1 id="문화-인터뷰">문화 인터뷰</h1>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/744496d1-0e28-4717-822b-d13f1b982809/image.png" alt=""></p>
<p>다음주에 직무 인터뷰 합격 연락이 왔고, 문화 인터뷰 일정이 잡혔다. </p>
<p>우선 채용담당자님이 보내주신 토스커뮤니티 더 알아보기 자료들을 살펴봤다. &lt;유난한 도전&gt;도 구매 해서 읽기 시작했다. 마지막으로 이력서를 살펴보면서 나의 경험을 기반으로, 내가 어떻게 토스팀에서 시너지를 낼 수 있을지 정리했다.</p>
<p>면접이 시작되었다. 매우 직설적인 질문들을 받았다. 나도 최대한 핵심만 전달하기 위해 노력했다. 미처 생각치도 못한 질문들도 다수 받았다. 그때마다 잠시 생각을 해보겠다 한뒤, 생각이 정리되면 솔직하게 대답을 드렸다.</p>
<p>인터뷰가 끝나고, 저녁을 때우면서 집으로 돌아갔다. 집으로 돌아가는 길에 바로 내가 말한 내용들을 복기했다. 다소 횡설수설 했지만, 정합성이 있는 대답을 드렸다는 생각이 들었다.</p>
<h1 id="결과">결과</h1>
<p>문화 인터뷰도 합격이었다. 만만세. 레퍼런스 체크와 처우 협의는 과정은 무탈하게 진행 되었다. 온보딩이 기대된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(번역) 궁극의 가비지 컬렉션]]></title>
            <link>https://velog.io/@mgm-dev/%EB%B2%88%EC%97%AD-%EA%B6%81%EA%B7%B9%EC%9D%98-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98</link>
            <guid>https://velog.io/@mgm-dev/%EB%B2%88%EC%97%AD-%EA%B6%81%EA%B7%B9%EC%9D%98-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98</guid>
            <pubDate>Tue, 05 Sep 2023 12:51:36 GMT</pubDate>
            <description><![CDATA[<h1 id="번역">번역</h1>
<p>제목: 메모리가 누수되나요?
날짜: 1995/03/31</p>
<p>Norman H. Cohen (<a href="mailto:nco...@watson.ibm.com">nco...@watson.ibm.com</a>)가 썼습니다.
: 고의적으로 메모리 누수가 있는 프로그램은 실행 시간이 충분히 짧고,
: 타겟 머신의 가상 메모리 공간이 충분하여 메모리 부족이 걱정되지 않는 경우로
: 한정 됩니다. (이러한 프로그램에는 많은 학생 프로그래밍 연습 문제와
: 몇몇 간단한 애플릿과 유틸리티가 포함됩니다; 내장형 또는 안전 중심의 프로그램은
: 거의 없거나 전혀 해당하지 않습니다.)</p>
<p>위글은 제가 가진 흥미로운 기억 중 하나를 상기 시켰습니다. 
한때 저는, 미사일을 위한 온보드 소프트웨어를 제작하고 있는 고객과 일하고 있었습니다. 
코드 분석 중에 저장소 누수와 관련된 여러 문제점을 지적했습니다. 
고객의 최고 소프트웨어 엔지니어가 &quot;물론 누수되죠&quot;라고 말했을 때 제가 얼마나 놀랐는지요. 
그는 미사일의 전체 가능 비행 시간 동안 애플리케이션이 누출할 메모리의 양을 계산하고, 그 숫자를 두 배로 늘렸다고 설명했습니다. 
그들은 이만큼의 추가 메모리를 하드웨어에 추가하여 누수를 &quot;지원&quot;했습니다. 
미사일이 목표물에 부딪히거나 비행이 끝날 때 폭발하기 때문에, 프로그래머의 개입 없이도 궁극의 가비지 컬렉션이 수행되는 것입니다.</p>
<p>--
Kent Mitchell | 일이 계획대로 진행되지 않는 
기술 컨설턴트 | 이유 일 수 있는 것 중 하나는 .....
Rational Software Corporation | 애초에 계획이 없었기 때문입니다!</p>
<h1 id="원문">원문</h1>
<p>From: <a href="mailto:k...@rational.com">k...@rational.com</a> (Kent Mitchell)
Subject: Re: Does memory leak?
Date: 1995/03/31</p>
<p>Norman H. Cohen (<a href="mailto:nco...@watson.ibm.com">nco...@watson.ibm.com</a>) wrote:
: The only programs I know of with deliberate memory leaks are those whose
: executions are short enough, and whose target machines have enough
: virtual memory space, that running out of memory is not a concern.
: (This class of programs includes many student programming exercises and
: some simple applets and utilities; it includes few if any embedded or
: safety-critical programs.)</p>
<p>This sparked an interesting memory for me.  I was once working with a
customer who was producing on-board software for a missile.  In my analysis
of the code, I pointed out that they had a number of problems with storage
leaks.  Imagine my surprise when the customers chief software engineer said
&quot;Of course it leaks&quot;.  He went on to point out that they had calculated the
amount of memory the application would leak in the total possible flight time
for the missile and then doubled that number.  They added this much
additional memory to the hardware to &quot;support&quot; the leaks.  Since the missile
will explode when it hits its target or at the end of its flight, the
ultimate in garbage collection is performed without programmer intervention.</p>
<p>--
Kent Mitchell                   | One possible reason that things aren&#39;t
Technical Consultant            | going according to plan is .....
Rational Software Corporation   | that there never <em>was</em> a plan!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[새 단장한 React 다큐멘테이션 훑어보기]]></title>
            <link>https://velog.io/@mgm-dev/%EC%83%88-%EB%8B%A8%EC%9E%A5%ED%95%9C-React-%EB%8B%A4%ED%81%90%EB%A9%98%ED%85%8C%EC%9D%B4%EC%85%98-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@mgm-dev/%EC%83%88-%EB%8B%A8%EC%9E%A5%ED%95%9C-React-%EB%8B%A4%ED%81%90%EB%A9%98%ED%85%8C%EC%9D%B4%EC%85%98-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sat, 18 Mar 2023 15:07:15 GMT</pubDate>
            <description><![CDATA[<h2 id="react-홈페이지-새-단장-완료">React 홈페이지 새 단장 완료!</h2>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/de4a3c5e-e498-43eb-885a-69a7e09a066f/image.png" alt=""></p>
<p>3월 16일 부로 기존의 <a href="https://legacy.reactjs.org">reactjs.org</a>가 사라지고 새로운 <a href="https://react.dev">react.dev</a> 사이트가 오픈 되었다. 여전 부터 beta 상태로 최신 다큐멘테이션을 읽어 볼 수 있었지만, 이제 기존 다큐멘테이션은 완전히 레거시로 넘어가게 되었다. 모던한 React 개발을 매우 친절하게 설명하고 있기에, FE 개발자라면 한번 톺아보는 것을 추천한다. 이 게시글에서 글쓴이 기준으로 React에 대해 어느정도 알고 있는 개발자도 리마인드 하거나 새로 익히면 좋을 정보들만 정리 했다.</p>
<h2 id="다큐멘테이션-웹사이트에서-fe-트렌드가-보인다">다큐멘테이션 웹사이트에서 FE 트렌드가 보인다</h2>
<h3 id="nextjs--tailwind의-채택">Next.js &amp; Tailwind의 채택</h3>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/4c6277a1-171f-422c-a953-e3d833fd0b72/image.png" alt=""></p>
<p><a href="https://www.wappalyzer.com/">wappalyzer</a>라는 툴로 확인 해본 결과 새로 작성된 React 다큐멘테이션은 <a href="https://nextjs.org/">Next.js</a>로 만들어 졌고, 배포 환경에는 <a href="https://vercel.com/">Vercel</a>이 사용되었다. 메타 프레임워크, 서버리스(엣지) 환경 트렌드가 떠올려진다.</p>
<p>또한 살펴볼점은 <a href="https://tailwindcss.com/">Tailwind CSS</a>의 채택이다. Tailwind CSS는 Utility-first CSS 프레임워크의 대표 주자이다. SSR의 가장 중요한 목표중의 하나는 성능이다. 이에 CSS-in-JS의 런타임 오버헤드를 피할 수 있는 Tailwind CSS 또한 최근 채택이 증가되고 있다.</p>
<p>글쓴이가 말한 내용이 흥미롭다면, 다음 아티클들을 추가로 읽어보는 것을 추천한다.
<a href="https://www.robinwieruch.de/web-development-trends/">10 Web Development Trends in 2023</a>
<a href="https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b">Why We&#39;re Breaking Up with CSS-in-JS</a></p>
<h3 id="cra는-공사진행-중">CRA는 공사진행 중</h3>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/d20a98ba-7ce8-4542-ba91-f6dd796f81fb/image.png" alt=""></p>
<p>공식문서에서 <a href="https://create-react-app.dev/">create-react-app</a>에 대한 추천이 사라졌다. 이제 새로운 프로젝트를 시작하는 경우 <a href="https://nextjs.org/">Next.js</a>, <a href="https://remix.run/">Remix.js</a> 등 React 기반 메타 프레임 워크를 추천하고, React를 라이브러리로 사용하려는 경우 <a href="https://vitejs-kr.github.io/">Vite</a>를 번들러로 추천한다. React Core팀은 create-react-app라는 커맨드는 유지하되, 프레임워크를 추천 해주는 launcher로 수정하는 방향을 잡았다고 한다. 궁금하다면 <a href="https://github.com/reactjs/reactjs.org/pull/5487#issuecomment-1409720741">Dan Abramov의 설명</a>을 읽어보자. </p>
<hr>
<h2 id="quick-start-섹션을-먼저-살펴보자">&quot;Quick Start&quot; 섹션을 먼저 살펴보자</h2>
<h3 id="function-component-first">Function Component First!</h3>
<p><img src="https://velog.velcdn.com/images/mgm-dev/post/6dcf6430-107f-4738-9b55-71915d92e73c/image.png" alt=""></p>
<p>기존의 React 튜토리얼은 틱택토 게임을 Class Component로 작성했다. Function Component 또한 사용했지만, 상태를 가지고 있지 않은 소위 Dumb(Presentational) Component로 사용되었다. hooks API가 존재하기 전 <a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0">Presentational and Container Component Pattern</a>의 잔재 였으리라. 업데이트 된 튜토리얼에서는 Function Component와 useState가 사용된다.  </p>
<h3 id="thinking-in-react가-강조-되었다">&quot;Thinking in React&quot;가 강조 되었다!</h3>
<p>Thinking in React라는 파트가 Quick Start 섹션으로 이동 되었다. 디자인 목업과 JSON API가 정의 되어있다고 가정하고, React를 사용하는 개발자가 작업하는 프로레스를 권장/설명 해주는 섹션이다. </p>
<h4 id="1-ui를-컴포넌트-계층-만들기">1. UI를 컴포넌트 계층 만들기</h4>
<p>UI 목업을 보고, 필요한 컴포넌트와 하위 컴포넌트를 정의한다. 이상적으로 <a href="https://en.wikipedia.org/wiki/Single-responsibility_principle">단일 책임 원칙</a>에 따라 하나의 컴포넌트를 분해하여 여러개의 하위 컴포넌트로 이루어진 계층을 만든다.</p>
<h4 id="2-react로-정적인-버전-만들기">2. React로 정적인 버전 만들기</h4>
<p>유저 상호작용을 생각하지 않고, UI의 마크업을 진행한다. 이때 재사용 가능한 컴포넌트를 실제로 작성한다. 컴포넌트를 정의하면서 화면을 그리는데 필요한 prop 또한 정의한다. 간단한 컴포넌트 계층의 경우 top down으로 복잡한 계층의 경우 down up으로 작업하는 것이 추천된다.</p>
<h4 id="3-ui-상태의-최소이지만-완전한-표현-찾기">3. UI 상태의 최소이지만 완전한 표현 찾기</h4>
<p>상호작용을 구현하기 위한 state를 정의한다. 가장 중요한 점은 <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY 원칙</a>에 따라 최소한의 state만 선언하는 것이다. 다른 state나 prop으로 부터 파생된 값은 render시 on-demand로 계산한다. </p>
<h4 id="4-state가-어디에-위치-해야할지-결정하기">4. state가 어디에 위치 해야할지 결정하기</h4>
<p>어느 컴포넌트에 어떤 state를 둘지 결정한다. 다음과 일반적으로 같은 과정을 통해 결정한다.</p>
<pre><code>1. 특정 State에 따라 re-render 되어야하는 컴포넌트를 모두 찾는다.
2. 해당 컴포넌트들로 부터 가장 가까운 부모 컴포넌트에 state를 정의 한다.
3. State를 두는 것이 자연스러운 컴포넌트가 존재하지 않는다면 새로운 컴포넌트를 정의한다.</code></pre><h4 id="5-역방향-데이터-흐름-추가하기">5. 역방향 데이터 흐름 추가하기</h4>
<pre><code class="language-jsx">import { useState } from &#39;react&#39;;

function FilterableProductTable({ products }) {
  const [filterText, setFilterText] = useState(&#39;&#39;);
  const [inStockOnly, setInStockOnly] = useState(false);

  return (
    &lt;div&gt;
      &lt;SearchBar 
        filterText={filterText} 
        inStockOnly={inStockOnly} 
        onFilterTextChange={setFilterText} 
        onInStockOnlyChange={setInStockOnly} /&gt;
      &lt;ProductTable 
        products={products} 
        filterText={filterText}
        inStockOnly={inStockOnly} /&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p>React에서 데이터 흐름은 단방향이다. 필요에 따라 부모의 state를 변경 시키는 setState 함수를 자식 컴포넌트에게 전달한다.</p>
<hr>
<h2 id="learn-react-섹션이-새로-생겼다">&quot;Learn React&quot; 섹션이 새로 생겼다!</h2>
<p><a href="https://legacy.reactjs.org/docs/hello-world.html">Main Concepts</a> 섹션이 <a href="https://react.dev/learn/describing-the-ui">Learn React</a> 섹션으로 변경 되었다. 가장 많은 변화가 생긴 섹션이다. 유저편의를 위해 샘플 코드가 <a href="https://codesandbox.io/">codesandbox</a>에 연동되었고, 이해를 돕기 위한 비유와 일러스트레이션이 추가되었다.</p>
<p>특수한 상황이 아니면 이제 권장되지 않는 <a href="https://legacy.reactjs.org/docs/higher-order-components.html">High-Order Component</a>, <a href="https://legacy.reactjs.org/docs/typechecking-with-proptypes.html">PropTypes</a>에 대한 설명이 삭제 되었다. </p>
<p>4가지 파트로 나누어져있는데 기존 다큐멘테이션에 비해서 매우 유기적으로 설명을 진행한다.</p>
<blockquote>
<p>Describing the UI : jsx, property, list/conditional rendering
Adding Interactivity : event, state, render &amp; commit
Managing State : declarative UI, state structure, context &amp; reducer
Escape Hatches : ref, effect, custom hooks</p>
</blockquote>
<p>Escape Hatches에서 다루는 주제는 고급 개념이다.  useEffect 잘 쓰기 위해서 가장 중요한 규칙은, <a href="https://www.youtube.com/shorts/-RoKGk5Lju0">최대한 useEffect의 사용을 피하는 것</a>이라는 말도 있는데 <a href="https://react.dev/learn/you-might-not-need-an-effect">다큐멘테이션도 이를 알려주려한다</a>. 또한 <a href="https://react.dev/learn/referencing-values-with-refs#how-does-use-ref-work-inside">useRef에 대한 자세한 설명</a>과 <a href="https://react.dev/learn/manipulating-the-dom-with-refs">DOM Manipulation</a>으로 분리 되었다.</p>
<h3 id="pure-function--strict-mode">Pure Function &amp; Strict Mode</h3>
<pre><code class="language-jsx">let guest = 0;

function Cup() {
  // Bad: changing a preexisting variable!
  guest = guest + 1;
  return &lt;h2&gt;Tea cup for guest #{guest}&lt;/h2&gt;;
}</code></pre>
<p>함수가 컴포넌트를 작성하는 기본 방법으로 권장되면서, <a href="https://en.wikipedia.org/wiki/Pure_function">순수함수</a>와 컴포넌트가 순수함수이여야 하는 이유에 대한 설명이 추가되었다. 컴포넌트가 순수하지 않으면 render 될때마다 부수효과를 야기 하기 때문이다. 이를 반쯤 강제하기 위한 <a href="https://react.dev/reference/react/StrictMode">StrictMode</a>가 존재하긴 했지만 이제 다큐멘테이션에서 순수하지 않은 컴포넌트의 위험성을 자세히 설명 해준다. </p>
<h3 id="필요하면-immer를-사용하자">필요하면 Immer를 사용하자</h3>
<pre><code class="language-js">// useState
const [person, setPerson] = useState({
  name: &#39;Niki de Saint Phalle&#39;,
    artwork: {
      title: &#39;Blue Nana&#39;,
      city: &#39;Hamburg&#39;,
      image: &#39;https://i.imgur.com/Sd1AgUOm.jpg&#39;,
    }
});

function handleTitleChange(e) {
  setPerson({
    ...person,
    artwork: {
      ...person.artwork,
      title: e.target.value
    }
  });
}

// useImmer
const [person, updatePerson] = useImmer({
    name: &#39;Niki de Saint Phalle&#39;,
    artwork: {
      title: &#39;Blue Nana&#39;,
      city: &#39;Hamburg&#39;,
      image: &#39;https://i.imgur.com/Sd1AgUOm.jpg&#39;,
    }
  });

function handleTitleChange(e) {
  updatePerson(draft =&gt; {
    draft.artwork.title = e.target.value;
  });
}</code></pre>
<p>필요하면 <a href="https://immerjs.github.io/immer/">Immer</a>를 사용하자. 일일히 spread 하지 않고 state의 불변성을 지킬 수 있게 도와준다.</p>
<h3 id="batching-state-update">Batching state Update</h3>
<pre><code class="language-jsx">function App() {
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);

  function handleClick() {
    fetchSomething().then(() =&gt; {
      // React 17 and earlier does NOT batch these because
      // they run *after* the event in a callback, not *during* it
      setCount(c =&gt; c + 1); // Causes a re-render
      setFlag(f =&gt; !f); // Causes a re-render
    });
  }

  return (
    &lt;div&gt;
      &lt;button onClick={handleClick}&gt;Next&lt;/button&gt;
      &lt;h1 style={{ color: flag ? &quot;blue&quot; : &quot;black&quot; }}&gt;{count}&lt;/h1&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p>setState에 함수를 인자로 전달하면, state 업데이트가 batching 된다. React v18의 업데이트로 <a href="https://github.com/reactwg/react-18/discussions/21">eventHandler 밖에서도 batching이 기본으로 적용된다</a>. </p>
<h3 id="state를-설계하는-규칙">state를 설계하는 규칙</h3>
<h4 id="관계가-있는-state는-묶어라">관계가 있는 state는 묶어라</h4>
<pre><code class="language-js">// 비추천
const [x, setX] = useState(0)
const [y, setY] = useState(0)

// 추천
const [position, setPosition] = useState({position})</code></pre>
<h4 id="모순된-state를-피해라">모순된 state를 피해라</h4>
<pre><code class="language-jsx">// 비추천
const [isSending, setIsSending] = useState(false);
const [isSent, setIsSent] = useState(false);

async function handleSubmit(e) {
  e.preventDefault();
  setIsSending(true);
  await sendMessage(text);
  setIsSending(false);
  setIsSent(true);
}

// 추천
const [status, setStatus] = useState(&#39;typing&#39;);

async function handleSubmit(e) {
  e.preventDefault();
  setStatus(&#39;sending&#39;);
  await sendMessage(text);
  setStatus(&#39;sent&#39;);
}</code></pre>
<h4 id="불필요한-state를-피해라">불필요한 state를 피해라</h4>
<pre><code class="language-js">// 비추천
const [firstName, setFirstName] = useState(&#39;&#39;);
const [lastName, setLastName] = useState(&#39;&#39;);
const [fullName, setFullName] = useState(&#39;&#39;);

//추천
const [firstName, setFirstName] = useState(&#39;&#39;);
const [lastName, setLastName] = useState(&#39;&#39;);

const fullName = firstName + &#39; &#39; + lastName;</code></pre>
<h4 id="state-복사를-피해라">state 복사를 피해라</h4>
<pre><code class="language-jsx">// color가 업데이트 되지 않는다
import { useState } from &#39;react&#39;;

export default function Clock(props) {
  const [color, setColor] = useState(props.color);
  return (
    &lt;h1 style={{ color: color }}&gt;
      {props.time}
    &lt;/h1&gt;
  );
}

// 가능하면 state 복사를 피해라
export default function Clock({color, time}) {
  return (
    &lt;h1 style={{ color }}&gt;
      {time}
    &lt;/h1&gt;
  );
}</code></pre>
<h4 id="깊게-nesting-된-state를-피해라">깊게 nesting 된 state를 피해라</h4>
<pre><code class="language-js">// 비추천
export const initialTravelPlan = {
  id: 0,
  title: &#39;(Root)&#39;,
  childPlaces: [{
    id: 1,
    title: &#39;Earth&#39;,
    childPlaces: [{
      id: 2,
      title: &#39;Africa&#39;,
      childPlaces: [{
        id: 3,
        title: &#39;Botswana&#39;,
        childPlaces: []
      }, {
        id: 4,
        title: &#39;Egypt&#39;,
        childPlaces: []
      }, ...                 </code></pre>
<pre><code class="language-js">// 추천
export const initialTravelPlan = {
  0: {
    id: 0,
    title: &#39;(Root)&#39;,
    childIds: [1, 43, 47],
  },
  1: {
    id: 1,
    title: &#39;Earth&#39;,
    childIds: [2, 10, 19, 27, 35]
  },
  2: {
    id: 2,
    title: &#39;Africa&#39;,
    childIds: [3, 4, 5, 6 , 7, 8, 9]
  }, ...</code></pre>
<h3 id="useeffect-사용이-필요한-경우들">useEffect 사용이 필요한 경우들</h3>
<h4 id="non-react-widget를-제어-할때">non-React widget를 제어 할때</h4>
<pre><code class="language-js">useEffect(() =&gt; {
  const map = mapRef.current;
  map.setZoomLevel(zoomLevel);
}, [zoomLevel]);</code></pre>
<h4 id="event에-구독-할때">event에 구독 할때</h4>
<pre><code class="language-js">useEffect(() =&gt; {
  function handleScroll(e) {
    console.log(window.scrollX, window.scrollY);
  }
  window.addEventListener(&#39;scroll&#39;, handleScroll);
  return () =&gt; window.removeEventListener(&#39;scroll&#39;, handleScroll);
}, []);</code></pre>
<h4 id="애니메이션을-트리거-할때">애니메이션을 트리거 할때</h4>
<pre><code class="language-js">useEffect(() =&gt; {
  const node = ref.current;
  node.style.opacity = 1; // Trigger the animation
  return () =&gt; {
    node.style.opacity = 0; // Reset to the initial value
  };
}, []);</code></pre>
<h4 id="분석-정보를-로깅할-때">분석 정보를 로깅할 때</h4>
<pre><code class="language-js">useEffect(() =&gt; {
  logVisit(url); // Sends a POST request
}, [url]);</code></pre>
<h3 id="useeffect-사용이-불필요한-경우들">useEffect 사용이 불필요한 경우들</h3>
<h4 id="prop의-변경으로-state를-일괄-초기화-할때">Prop의 변경으로 state를 일괄 초기화 할때</h4>
<pre><code class="language-jsx">export default function ProfilePage({ userId }) {
  const [comment, setComment] = useState(&#39;&#39;);

  // 🔴 Avoid: Resetting state on prop change in an Effect
  useEffect(() =&gt; {
    setComment(&#39;&#39;);
  }, [userId]);
  // ...
}</code></pre>
<pre><code class="language-jsx">export default function ProfilePage({ userId }) {
  return (
    &lt;Profile
      userId={userId}
      key={userId}
    /&gt;
  );
}

function Profile({ userId }) {
  // ✅ This and any other state below will reset on key change automatically
  const [comment, setComment] = useState(&#39;&#39;);
  // ...
}</code></pre>
<h4 id="post-requst-전송">Post requst 전송</h4>
<pre><code class="language-jsx">function Form() {
  const [firstName, setFirstName] = useState(&#39;&#39;);
  const [lastName, setLastName] = useState(&#39;&#39;);

  // ✅ Good: This logic should run because the component was displayed
  useEffect(() =&gt; {
    post(&#39;/analytics/event&#39;, { eventName: &#39;visit_form&#39; });
  }, []);

  // 🔴 Avoid: Event-specific logic inside an Effect
  const [jsonToSubmit, setJsonToSubmit] = useState(null);
  useEffect(() =&gt; {
    if (jsonToSubmit !== null) {
      post(&#39;/api/register&#39;, jsonToSubmit);
    }
  }, [jsonToSubmit]);

  function handleSubmit(e) {
    e.preventDefault();
    setJsonToSubmit({ firstName, lastName });
  }
  // ...
}</code></pre>
<pre><code class="language-jsx">function Form() {
  const [firstName, setFirstName] = useState(&#39;&#39;);
  const [lastName, setLastName] = useState(&#39;&#39;);

  // ✅ Good: This logic runs because the component was displayed
  useEffect(() =&gt; {
    post(&#39;/analytics/event&#39;, { eventName: &#39;visit_form&#39; });
  }, []);

  function handleSubmit(e) {
    e.preventDefault();
    // ✅ Good: Event-specific logic is in the event handler
    post(&#39;/api/register&#39;, { firstName, lastName });
  }
  // ...
}</code></pre>
<h4 id="data-fetching">Data Fetching</h4>
<pre><code class="language-jsx">function SearchResults({ query }) {
  const [results, setResults] = useState([]);
  const [page, setPage] = useState(1);

  useEffect(() =&gt; {
    // 🔴 Avoid: Fetching without cleanup logic
    fetchResults(query, page).then(json =&gt; {
      setResults(json);
    });
  }, [query, page]);

  function handleNextPageClick() {
    setPage(page + 1);
  }
  // ...
}</code></pre>
<pre><code class="language-jsx">function SearchResults({ query }) {
  const [results, setResults] = useState([]);
  const [page, setPage] = useState(1);
  useEffect(() =&gt; {
    let ignore = false; // ! avoid race condition
    fetchResults(query, page).then(json =&gt; {
      if (!ignore) {
        setResults(json);
      }
    });
    return () =&gt; {
      ignore = true;
    };
  }, [query, page]);

  function handleNextPageClick() {
    setPage(page + 1);
  }
  // ...
}</code></pre>
<h4 id="외부-저장소에-구독">외부 저장소에 구독</h4>
<pre><code class="language-jsx">function useOnlineStatus() {
  // Not ideal: Manual store subscription in an Effect
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() =&gt; {
    function updateState() {
      setIsOnline(navigator.onLine);
    }

    updateState();

    window.addEventListener(&#39;online&#39;, updateState);
    window.addEventListener(&#39;offline&#39;, updateState);
    return () =&gt; {
      window.removeEventListener(&#39;online&#39;, updateState);
      window.removeEventListener(&#39;offline&#39;, updateState);
    };
  }, []);
  return isOnline;
}

function ChatIndicator() {
  const isOnline = useOnlineStatus();
  // ...
}</code></pre>
<pre><code class="language-jsx">function subscribe(callback) {
  window.addEventListener(&#39;online&#39;, callback);
  window.addEventListener(&#39;offline&#39;, callback);
  return () =&gt; {
    window.removeEventListener(&#39;online&#39;, callback);
    window.removeEventListener(&#39;offline&#39;, callback);
  };
}

function useOnlineStatus() {
  // ✅ Good: Subscribing to an external store with a built-in Hook
  return useSyncExternalStore(
    subscribe, // React won&#39;t resubscribe for as long as you pass the same function
    () =&gt; navigator.onLine, // How to get the value on the client
    () =&gt; true // How to get the value on the server
  );
}

function ChatIndicator() {
  const isOnline = useOnlineStatus();
  // ...
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[번역] 아토믹 웹 디자인 (Atomic Web Design)]]></title>
            <link>https://velog.io/@mgm-dev/%EB%B2%88%EC%97%AD-%EC%95%84%ED%86%A0%EB%AF%B9-%EC%9B%B9-%EB%94%94%EC%9E%90%EC%9D%B8-Atomic-Web-Design</link>
            <guid>https://velog.io/@mgm-dev/%EB%B2%88%EC%97%AD-%EC%95%84%ED%86%A0%EB%AF%B9-%EC%9B%B9-%EB%94%94%EC%9E%90%EC%9D%B8-Atomic-Web-Design</guid>
            <pubDate>Sat, 03 Jul 2021 05:07:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>우리는 페이지를 디자인 하는 것이 아니라, 컴포넌트로 이루어진 시스템을 디자인한다.
<strong>Stephen Hay</strong></p>
</blockquote>
<p>&amp;nbsp 웹디자인이라는 기술이 진화함에따라, 단순한 웹페이지의 집합이 아니라, 제대로 정의된 디자인 시스템 개발의 필요가 대두 되고있다.</p>
<p>&amp;nbsp 디자인 시스템을 만드는 것에 대해서는 많은 논의가 이루어졌다. 이 논의의 대부분은 색상, 타이포그래피, 그리드, 텍스처 등을 확립하는데 집중한다. 이러한 생각도 매우 중요하다, 하지만 나는 앞서 언급한 요소에 대한 흥미가 상대적으로 적다. 앞서 언급한 요소는 주관적이고 앞으로도 주관적일 것이기 때문이다. 최근, 나는 우리가 사용하는 인터페이스가 어떻게 구성되어있고, 디자인 시스템을 질서있게 만들 방법에 대해 관심을 가지고 있다.</p>
<p>&amp;nbsp 나는 적합한 비유를 위해 화학을 사용한다. 고체, 액체, 기체, 등 모든 물체는 원자(atom)으로 이루어져있다. 이러한 원자가 모여 분자(molecule)가 된다. 분자는 모여 유기체(organism)이 되고 결국 우주의 모든 물질을 구성한다.</p>
<p>&amp;nbsp 이와 유사하게, 우리가 만든 인터페이스는 하위 컴포넌트들로 이루어져있다. 인터페이스를 기초적인 구성 요소로 해체하여 거기서 부터 작업할 수 있다는 것을 의미한다. 이것이 아토믹 디자인(atomic design)의 요점이다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/2e56fe13-f2c6-44c7-9a1f-f0514e7073f6/image.png" alt=""></p>
<h2 id="아토믹-디자인이란-무엇인가">아토믹 디자인이란 무엇인가?</h2>
<p>아토믹 디자인이란 디자인 시스템을 만드는 방법론이다. 아토믹 디자인에는 다섯가지 수준이 존재한다.</p>
<ol>
<li>Atoms</li>
<li>Molecules</li>
<li>Organisms</li>
<li>Templates</li>
<li>Pages</li>
</ol>
<p><img src="https://images.velog.io/images/mgm-dev/post/9047684d-11d8-4dcd-80df-d7f7f0ae8022/image.png" alt=""></p>
<h3 id="atoms">atoms</h3>
<p>&amp;nbsp atom는 물질의 기본 구성요소(basic building block) 이다. 웹 인터페이스에 이를 적용하면, atom이란 label, input, button 같은 HTML 태그라 할 수 있다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/b1d3e9ef-ba47-4a4b-840f-d6b1ef8ba3e2/image.png" alt=""></p>
<p>&amp;nbsp 또한 atom은 색상 팔레트, 폰트 같은 추상적인 요소일 수 있고, 애니메이션 같은 인터페이스의 양상일 수도 있다.</p>
<p>&amp;nbsp 현실과 같이 atom은 추상적이고, 독립적으론 크게 유용하지 않다. 하지만 패턴 라이브러라는 문맥에서 본다면, 글로벌한 스타일을 한번에 볼 수 있게 해주는 레퍼런스로써 훌륭하다.</p>
<h3 id="molecules">molecules</h3>
<p>&amp;nbsp atom을 조합하기 시작하면 일이 훨씬 흥미롭고 명백 해지기 시작한다. molecule은 접합 된 atom의 모음이고 화합물의 주요한 단위이다. molecule은 각자의 속성을 지니고 디자인 시스템의 뼈대로 쓰인다.</p>
<p>&amp;nbsp 예를 들어, form label, input, button의 따로따로 크게 유용하지 않다. 하지만 3개를 form으로 합친다면 실제로 기능을 담당할 수 있다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/02009d90-5aaf-47a8-a4cb-da4117ec9f9a/image.png" alt=""></p>
<p>&amp;nbsp atom으로 부터 molecule를 만드는 것은 &quot;하나의 일을 하고 그 일을 제대로 해라&quot;라는 모토를 장려한다. molecule은 복잡 할수도 있지만, 투박한 정의를 하자면 다음과 같다. molecule이란 재사용을 위해 만들어진, 상대적으로 심플한 atom의 조합이다.</p>
<h3 id="organisms">organisms</h3>
<p>&amp;nbsp molecule은 우리가 작업할 수있는 기본 구성요소이다. 이제 우리는 molecule을 조합하여 organism을 만들 수 있다. organism은 상대적으로 복잡하며, 웹 인터페이스의 분명한 구역을 담당한다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/242b1c65-4881-42fa-8a64-5272d3c4c068/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/mgm-dev/post/45a94b75-5b61-418b-aaff-9c1c78ea432d/image.png" alt=""></p>
<p>&amp;nbsp 우리는 점점 더 구체적인 부분을 다루고 있다. 클라이언트는 디자인 시스템의 atom에 대해 흥미가 없을 수 있다. 하지만 organism을 다루기 시작하면 최종적인 웹 인터페이스의 형태가 잡히는 것을 볼 수 있다. 내가 협업하고 있는 Dan Mall은 element collage를 사용한다. element collage는 주요한 organism의 아이디어를 명료하게 표현하여 클라이언트와의 의사소통을 용이하게 하고 디자인의 방향성을 미리 정할 수 있게 해준다.</p>
<p>&amp;nbsp organism은 유사하거나 상이한 molecule로 구성 될 수 있다. 예를 들어, masthead(페이지 헤더) organism은 logo, primary navigation, search form 등 상이한 molecule로 이루어 질 수 있다. 반면 product grid(상품 리스트) organism은 동일한 molecule의 반복으로 이루어질 수 있다.</p>
<p>&amp;nbsp molecule로 organism을 만드는 것은 독립적이고 재사용 가능한 컴포넌트를 작성을 장려한다.</p>
<h3 id="templates">templates</h3>
<p>&amp;nbsp template의 레벨에서 화학을 통한 비유가 끝나고, 클라이언트가 이해하기 쉽고 실제 결과 물과 밀접한 언어가 사용된다. template은 oragnism을 묶어 만들어 놓은 페이지이다. 여기서 우리는 디자인이 완성되고 레이아웃의 실체를 볼 수 있게 된다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/473418f2-e7ab-4707-9d72-faf3b85a7b4d/image.png" alt=""></p>
<p>&amp;nbsp template은 매우 구체적이며 상대적으로 추상적인 molecule과 organism에게 문맥을 제공한다. 또한 클라이언트는 template을 통해 디자인의 완성을 보기 시작한다. 나는 아토믹 디자인이라는 방법론을 사용하면서, template은 HTML 와이어 프레임으로 시작하여 최종적으로 정확도(fidelity) 증가하며 최종 결과물이 된다. Pittsburgh의 Bearded Studio는 유사한 방법을 사용한다. 디자인은 흑백톤의 레이아웃리스로 시작하여 최종 디자인으로 발전한다.</p>
<h3 id="pages">pages</h3>
<p>&amp;nbsp page는 template의 특정한 인스턴스이다. 플레스홀더는 실제 콘텐츠로 대체되며, 최종적으로 유저가 보게 될 화면이 묘사 된다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/b8cbbdf0-a3c8-4e1a-b4d2-6391612bfb00/image.png" alt=""></p>
<p>&amp;nbsp page는 가장 구체적이기 때문에 가장 정확도가(fidelity) 높은 레벨이다. 일반적으로 대다수의 유저가 사용하고, 많은 리뷰의 대상이다.</p>
<p>&amp;nbsp page는 디자인 시스템의 효율성을 테스트하는 곳이다. 실제 문맥(웹페이지)에서 molecule, organism, template이 필요한 일을 하는지 확인 후, 컴포넌트를 리팩토링 할 수 있다는 것이다.</p>
<p>&amp;nbsp 또한 page는 template의 여러가지 사례를 테스트 할 수 있는 곳이다. 예를 들어 헤드라인은 40자가 될 수 있고, 340자가 될 수도 있다. 장바구니에 상품이 하나가 있을 수 있고, 상품이 10개 있을 수도 있다. 할인 코드가 적용된 상태일 수 있고, 아닐 수도 있다. 거듭이 말하자면, 이러한 실제 사례는 어떻게 디자인 시스템을 만들지에 영향을 미친다.</p>
<h3 id="왜-아토믹-디자인을-사용하나">왜 아토믹 디자인을 사용하나</h3>
<p>&amp;nbsp 여러가지 의미로, 우리는 앞서 언급한 방법들을 사용하고 있었다. 무의식적으로 했던 의식적으로 했던간에 말이다.</p>
<p>&amp;nbsp 아토믹 디자인은 디자인 시스템을 만들기 위한 명확한 방법론을 제공한다. 클라이언트와 팀 멤버들 또한 디자인 시스템을 눈앞에서 보는 것을 통해 디자인 시스템의 개념과 중요함을 제대로 인지 할 수 있다.</p>
<p>&amp;nbsp 아토믹 디자인은 추상적인 개념과 구체적인 개념을 모두 들여다볼수 있게 해준다. 이 덕분에 우리는 일관적이고 확장 가능한 디자인 시스템을 만듦과 동시에 최종 결과물을 동시에 보여줄 수 있다. 또한 해체(deconstructing)으로 부터 시작하는 것이 아니라 조립(assembling)의 방법을 사용하기 때문에, 뒤늦게 패턴을 선택하는 것이 아니라, 시작 부터 디자인 시스템 설계를 시작 할 수 있다.</p>
<blockquote>
<p>원문 :  <a href="https://bradfrost.com/blog/post/atomic-web-design/">atomic-web-design</a>
*가독성을 위해 의역한 부분이 존재합니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬, 미리 알았으면 좋았을 것들]]></title>
            <link>https://velog.io/@mgm-dev/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90-%EB%8C%80%ED%95%B4-%EB%AF%B8%EB%A6%AC-%EC%95%8C%EC%95%98%EC%9C%BC%EB%A9%B4-%EC%A2%8B%EC%95%98%EC%9D%84-%EA%B2%83%EB%93%A4</link>
            <guid>https://velog.io/@mgm-dev/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90-%EB%8C%80%ED%95%B4-%EB%AF%B8%EB%A6%AC-%EC%95%8C%EC%95%98%EC%9C%BC%EB%A9%B4-%EC%A2%8B%EC%95%98%EC%9D%84-%EA%B2%83%EB%93%A4</guid>
            <pubDate>Sun, 13 Jun 2021 08:13:21 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/mgm-dev/post/47644796-ee72-4f48-ab72-bc7debb64f12/image.png" alt=""></p>
<h2 id="📚누구를-위한-포스트인가">📚누구를 위한 포스트인가?</h2>
<blockquote>
<ol>
<li>변수, 함수, 객체 등 프로그래밍에 대한 기초 지식이 있는 사람</li>
<li>파이썬을 사용 해본적 있지만 자세히 모르는 사람</li>
<li>흥미 위주로 파이썬에 대해 읽을 거리가 필요한 사람</li>
</ol>
</blockquote>
<p>&amp;nbsp 본 포스팅은 프로그래밍에 대한 기본 개념이 있는 아는 사람이, 파이썬을 사용하면서/사용하기전 미리 알고 있으면 좋을 개념들을 간략하게 정리하기 위해 작성 되었습니다. 모든 부분을 상세히 설명하는 것보다, 새로운 개념을 소개하고 읽을 거리를 추천하는 형식으로 작성했습니다. </p>
<hr>
<h2 id="🚧-작업중인-포스트-입니다">🚧 작업중인 포스트 입니다</h2>
<p>&amp;nbsp 내용이 수정되거나 추가 될 수 있습니다 :)</p>
<hr>
<h1 id="1-빅픽처">1. 빅픽처</h1>
<h2 id="🙆♂️-파이썬은-객체지향-언어이다">🙆‍♂️ 파이썬은 객체지향 언어이다</h2>
<p>&amp;nbsp 파이썬이 프로그래밍을 처음 접하는 사람에게 추천 되어서 망각되는 부분이다. 파이썬은 명령적 성격을 지닌 객체지향 언어이다. 파이썬에서 모든 것은 객체이다.</p>
<blockquote>
<p><strong>잠시만요~ 파이썬에는 클로저도 있고, 고차함수도 있고, 익명함수도 있고 함수지향 적인 부분이 많지 않나요?</strong></p>
</blockquote>
<p>&amp;nbsp 맞는 말이다. 파이썬의 함수는 일급함수이다. 파이썬을 사용하면서 순수함수를 사용하고 선언적으로 프로그래밍 할 수 있다. 파이썬의 기능이 확장 되면서 <strong>lambda</strong>, <strong>map</strong>, <strong>filter</strong> 같은 함수지향 파라다임에 영향을 받은 기능이 추가 되었다. 하지만 파이썬 개발자들은 <strong>list comprehension</strong>을 선호하고 귀도 반 로섬도 파이썬을 함수지향 언어로 보지 않았다고 한다.</p>
<h3 id="읽을-거리">읽을 거리</h3>
<p><a href="http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html">Origins of Python&#39;s &quot;Functional&quot; Features</a>
<a href="https://stackabuse.com/functional-programming-in-python">Functional Programming in Python</a></p>
<hr>
<h2 id="🤔-파이썬은-컴파일-절차를-거치고-인터프리트-된다">🤔 파이썬은 컴파일 절차를 거치고 인터프리트 된다</h2>
<blockquote>
<p><strong>파이썬은 인터프리터 언어로 한줄 읽어지면서 실행 되요~</strong></p>
</blockquote>
<p>&amp;nbsp 맞는말이다. 그런데 의문이 들지 않는가? 파이썬 코드를 작성 해놓으면 윈도우에서도 동작하고 맥에서도 동작하고 리눅스에서도 동작한다. 어떻게 그런 걸까. Java의 &quot;Write once, run anywhere(WORA)&quot;이 생각이 난다면 정답이다. JVM 처럼 <strong>PVM</strong>이 존재한다. 무슨 말인지 모르겠다고요? 최대한 간략하게 설명을 해보겠다.</p>
<p>&amp;nbsp 우리는 <code>.py</code> 확장자로 파이썬 <strong>소스코드</strong>를 작성한다. 이 코드는 컴퓨터에 의해서 바로 실행 되지 않고 <strong>바이트코드</strong>라는 플랫폼 독립적인 저차원 코드로 컴파일 된다. 이 <strong>바이트코드</strong>는 <strong>Python Virtual Machine(PVM)</strong>이라는 플랫폼 종속적인 프로그램에 의해 실행 된다. </p>
<p>&amp;nbsp 파이썬의 컴파일과 실행을 담당하는 대표적인 프로그램이 <strong>Cpython</strong>이다. <strong>Cpython</strong>은 이름 그대로 C언어로 구현되어 있다. <strong>Cpython</strong> 이외에 <strong>Jpython</strong>, <strong>pypy</strong> 같은 임플리멘테이션이 있다.</p>
<h3 id="읽을-거리-1">읽을 거리</h3>
<p><a href="https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d">Understaing Python Bytecode</a>
<a href="https://towardsdatascience.com/how-does-python-work-6f21fd197888">How Does Python Work</a></p>
<hr>
<h2 id="🌪️-파이썬-34-부터-공식적으로-비동기-프로그래밍이-지원-된다">🌪️ 파이썬 3.4 부터 공식적으로 비동기 프로그래밍이 지원 된다</h2>
<p>&amp;nbsp 자바스크립트 개발자에게 특히 유의미한 부분일 수 있다. 파이썬 버전 2 까지는 언어 레벨에서 비동기 프로그래밍을 지원하지 않았다. <strong>Twisted</strong> 같은 이벤트 기반 엔진이나 <strong>Tornado</strong> 같은 비동기 웹프레임 워크가 존재하긴 했다. 하지만 버전 3.4 부터 <strong>asyncio</strong>라는 공식 라이브러리가 추가 되었고, <code>async</code> <code>await</code> 문법을 통해서 비동기 프로그램을 할수 있게 되었다.</p>
<blockquote>
<p>asyncio는 상대적으로 새로운 파이썬 모듈이다. 파이썬 버전 마다 api가 자주 바뀌고 이미 deprecated 된 부분도 존재하니, 기왕이면 공식문서를 참고 하자</p>
</blockquote>
<h3 id="읽을-거리-2">읽을 거리</h3>
<p><a href="https://realpython.com/async-io-python/">Asyncio Python</a>
<a href="https://docs.python.org/3/library/asyncio.html">Asyncio Docs</a></p>
<hr>
<h1 id="2-디테일">2. 디테일</h1>
<h2 id="🔍-스코프를-구현하기-위한-네임스페이스">🔍 스코프를 구현하기 위한 네임스페이스</h2>
<p>&amp;nbsp 파이썬의 <code>globals()</code>나 <code>locals()</code> 키워드가 무엇인지 궁금하지 않았는가? 해당 키워드는 파이썬의 특정 <strong>네임스페이스</strong>를 접근하기 위해서 사용된다. 파이썬에서 <strong>네임스페이스</strong>는 <strong>스코프</strong>를 구현하기 위한 구현 방법이다. <strong>네임스페이스</strong>는 파이썬의 자료형의 하나인 <strong>dictionary</strong>로 구현 되어있다. 파이썬의 <strong>네임스페이스</strong>에는 네가지 종류가 있다.</p>
<blockquote>
<ol>
<li>Built-In</li>
<li>Global</li>
<li>Enclosing</li>
<li>Local</li>
</ol>
</blockquote>
<p>변수의 참조는 <code>4 &gt; 3 &gt; 2 &gt; 1</code>의 순서로 간다. 함수안에서 글로벌 네임스페이스에 접근하기 위해선 <code>global</code>이라는 키워드를 명시 해야한다.</p>
<h3 id="읽을-거리-3">읽을 거리</h3>
<p><a href="https://realpython.com/python-namespaces-scope/">Python Namespace Scope</a></p>
<hr>
<h2 id="🪄-init-같은-메소드는-magic-method라고-불린다">🪄 <strong>init</strong> 같은 메소드는 magic method라고 불린다</h2>
<p>&amp;nbsp 파이썬 소스코드를 보면서 언더바 두개로 감싸진 함수를 본적이 있을 것이다. 대표적으로 <code>__init__</code> 이 있겠다. 이러한 메소드는 <strong>magic method</strong> 또는 <strong>special method</strong>라고 불린다.</p>
<blockquote>
<p>왜 하필 <strong>magic method</strong> 이냐고? 사용자가 정의한 클래스에 마법 같은 기능을 부여하기 때문이다</p>
</blockquote>
<p>말이냐 방구냐고? 풀어서 설명 해보겠다. 매직 메소드를 클래스에 추가하면, 사용자가 생성한 커스텀 클래스가, 파이썬의 빌트인 타입과 동일한 동작을 할수 있게 하는 것이 가능하다.</p>
<p>매우매우 간략한 예시를 들자면 <code>__eq__</code>라는 메소드를 정의하면 <code>==</code> 연산자를 오브젝트에 사용할 시 어떻게 동작 할지 정의 할 수있다.</p>
<h3 id="읽을거리">읽을거리</h3>
<p><a href="https://rszalski.github.io/magicmethods/">magicmethods</a></p>
<hr>
<h2 id="mutable-vs-immutable">Mutable vs Immutable</h2>
<p><img src="https://images.velog.io/images/mgm-dev/post/5d3916fc-2975-42c4-905e-48bd33793a7f/image.png" alt="">
&amp;nbsp 파이썬의 모든 것은 객체이다. 어떤 객체는 <strong>mutable</strong>이고 어떤 객체는 <strong>immutable</strong>인지 알면 좋다. 아래의 그래프도 한번 훑어보자. 빨간색 박스에서 시작해서 화살표 방향으로 읽으면 된다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/a1b29e83-b4cc-4b1e-acbc-23da63f47621/image.png" alt=""></p>
<blockquote>
<ol>
<li>List are Mutable.</li>
<li>List are the most popular type of Collections</li>
<li>List are orderd group of Elements which are actually Pointers.</li>
</ol>
</blockquote>
<h3 id="읽을거리-1">읽을거리</h3>
<p><a href="https://medium.com/@meghamohan/mutable-and-immutable-side-of-python-c2145cf7274">Mutable and Immutable Side of Python</a></p>
<hr>
<h2 id="✨-class-attributes">✨ Class Attributes</h2>
<p>🚧 추가 예정</p>
<h3 id="읽을거리-2">읽을거리</h3>
<p><a href="https://www.toptal.com/python/python-class-attributes-an-overly-thorough-guide">Python Class Attributes an Overly Thorough Guide</a></p>
<hr>
<h1 id="3-기타">3. 기타</h1>
<h2 id="포멧팅은-어떻게-하면-좋을까">포멧팅은 어떻게 하면 좋을까?</h2>
<p>javascript에는 prettier가 있고 golang에는 gofmt가 있는데 파이썬은? 삼대장이 있다. <code>autopep8</code>, <code>yapf</code>, <code>black</code>에서 취향껏 선택하면 된다. 글쓴이는 black을 사용 중이다. </p>
<h3 id="읽을거리-3">읽을거리</h3>
<p><a href="https://www.kevinpeters.net/auto-formatters-for-python">Auto formmatters for Python</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[하노이의 탑과 연역적 사고법]]></title>
            <link>https://velog.io/@mgm-dev/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B3%B5%EB%B6%80%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1-feat.%EC%9E%AC%EA%B7%80</link>
            <guid>https://velog.io/@mgm-dev/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B3%B5%EB%B6%80%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1-feat.%EC%9E%AC%EA%B7%80</guid>
            <pubDate>Wed, 21 Apr 2021 14:40:11 GMT</pubDate>
            <description><![CDATA[<h2 id="📚tldr">📚TL;DR</h2>
<blockquote>
<p>알고리즘을 공부 안한다고 코딩을 못하는 것은 아니다. 하지만, 알고리즘을 공부하면 컴퓨터에게 더 똑똑하게 일을 시킬 수 있다.</p>
</blockquote>
<p>&amp;nbsp 프로그래밍 입문자를 위한 포스팅입니다. 알고리즘과 재귀의 정의, 하노이의 탑 게임의 룰을 알고있다면 더 재미있게 읽으실 것이라고 생각합니다 😊</p>
<hr>
<p><img src="https://images.velog.io/images/mgm-dev/post/4e6ef87c-acf2-4841-a25e-b17201378375/image.png" alt=""></p>
<h2 id="알고리즘-알고리즘-알고리즘">알고리즘, 알고리즘, 알고리즘</h2>
<p>&amp;nbsp 글쓴이는 프로그래밍을 처음 입문 할 당시, 알고리즘 알레르기가 있었다. 물론 기능을 구현하는데 필요한 자료구조와 알고리즘은 제외. 아무튼 글쓴이는 알고리즘은 당장 취업할때나 필요하고, 이후엔 매우 어려운 문제에 봉착하는 경우, 특수한 케이스를 해결하기 위해서 공부하면 될 것이라고 생각했다. 그런데 얼마전에 이를 바꿀만한 경험을 했고, 그 경험을 공유하고자 포스팅을 한다.</p>
<hr>
<p><img src="https://images.velog.io/images/mgm-dev/post/df1a1a21-533a-4064-8879-081ab078861b/image.png" alt=""></p>
<h2 id="프로그래밍-감각과-재귀법">프로그래밍 감각과 재귀법</h2>
<p>&amp;nbsp 사수님과 점심을 같이 먹고 있었다. 갑자기 질문을 받았다.</p>
<blockquote>
<p>사수님 : 입문자가 프로그래밍 감각이 있는지 판단하기 가장 쉬운 방법이 뭔지 아세요?
글쓴이 : 음... 잘모르겠네요
사수님 : 재귀 알고리즘 문제를 풀어보라고 하면 되요
글쓴이 : 어째서죠???
사수님 : 재귀함수를 잘 짜면 연역적으로 사고 할 수 있다는 뜻이거든요 ㅎㅎ </p>
</blockquote>
<hr>
<p><img src="https://images.velog.io/images/mgm-dev/post/44372ce7-43d5-4e15-be86-de46422ac836/image.png" alt=""></p>
<h2 id="하노이의-탑">하노이의 탑</h2>
<p>&amp;nbsp 사수님에게 설명을 부탁드렸다. 백문이불여일견이라고 알고리즘 문제를 직접 풀어보는게 빠르다고 말하셨다. 여러분도 직접 풀어볼 수 있도록 문제를 내보겠다. 제약 사항을 집중해서 보자.</p>
<blockquote>
<p><strong>하노이의 탑</strong>
n개의 꽂힌 원판들을 그 순서 그대로 다른 기둥으로 옮겨서 다시 쌓아야 한다.</p>
</blockquote>
<ol>
<li>한 번에 하나의 원판만 옮길 수 있다.</li>
<li>큰 원판이 작은 원판 위에 있어서는 안 된다.</li>
</ol>
<blockquote>
<p><strong>문제</strong>
n개의 원판을 모두 옮기는데 필요한 시행 회수를 도출하는 함수를 구현하라.
예시) 3개의 원판을 모두 옮기려면 7번의 시행 회수가 필요하다면 <code>hanoi(3) = 7</code></p>
</blockquote>
<ol>
<li>재귀함수로 구현 할 것.</li>
<li>귀납법을 사용하면 안된다.</li>
</ol>
<p>&amp;nbsp <strong>귀납법</strong>은 사례나 현상에서 부터 일반적인 결론을 이끌어내는 추론 방법이다. 즉 하노이의 탑을 귀납적으로 해결한다고 하면, 직접 게임을 수행 한후, 일련의 과정에서 통용 되는 법칙을 찾을 것이다. 독자들이 글쓴이와 유사하다면, 다음과 같은 과정을 거칠 것이다.</p>
<hr>
<h2 id="귀납적으로-푼다면">귀납적으로 푼다면</h2>
<blockquote>
<ol>
<li>우선 원판 직접 게임을 시행 해볼까?</li>
</ol>
</blockquote>
<ol>
<li><code>hanoi(1) = 1</code> 일 것이고 <code>hanoi(2) = 3</code>이고 <code>hanoi(3)</code>은 몇이지?</li>
<li>머리속에서 하기 어렵군 그림을 한번 그려보자.</li>
</ol>
<p><img src="https://images.velog.io/images/mgm-dev/post/18a5eb6e-b4f6-465b-90b2-8595ddcc1224/image.png" alt=""> </p>
<blockquote>
<ol start="4">
<li><code>hanoi(3) = 7</code>이군. 이제 통용되는 로직을 생각해보자. 우선 맨 위에 있는 원판을 c로 이동시키고, 그 다음에는...</li>
</ol>
</blockquote>
<p><img src="https://images.velog.io/images/mgm-dev/post/e7b9d33e-2c43-404e-9ee0-1f2ed3433d8a/image.png" alt=""></p>
<hr>
<h2 id="귀납-멈춰✋">귀납 멈춰!!!✋</h2>
<blockquote>
<p><strong>재귀법의 문제 해결 방법</strong></p>
</blockquote>
<ol>
<li>일정 조건이 만족 되면 자기 자신을 호출하지 않는다. (종료조건)</li>
<li>자기 자신을 호출하면 할 수록 1번의 조건에 가까워져야한다. (종료조건으로 수렴)</li>
<li>1번에 부합하지 않는다면, 2를 이행하는 행동을 하고 자기자신을 호출한다. (재귀)</li>
</ol>
<p>&amp;nbsp 정신이 멍해져버렸다. 정신을 가다듬고 다시 생각 해보자. 문제에 재귀법을 사용하라 했으니 당연히 재귀함수를 짜야할 것이다. 재귀함수에는 종료조건이 필요하다. 머리를 식힐겸 함수를 한번 짜보자.</p>
<pre><code class="language-python">def hanoi(n):
    # 원판이 1개라면 1회의 시행으로 게임이 끝난다
    if n == 1:
        return 1</code></pre>
<p>오케이 이건 금방 생각 할 수 있다. 그러면 어떻게 종료조건으로 수렴 시키면 좋을까? </p>
<hr>
<h2 id="연역적으로-푼다면">연역적으로 푼다면</h2>
<p>&amp;nbsp <strong>연역법</strong>은 일반적으로 알려진 이론을 어떠한 현상에 대입시켜 이에 대한 결론을 도출해내는 방법이다. 사전적 개념은 &#39;어떤 명제로부터 추론 규칙에 따라 결론을 이끌어 내는 것&#39;을 말한다. 글쓴이와 같이 문제를 다시 살펴보자. </p>
<blockquote>
<ol>
<li>당연하지만, 사람이 풀라고 만든 문제일 것이다.</li>
</ol>
</blockquote>
<ol>
<li>재귀법을 사용하라고 했다, 따라서 재귀법으로 풀 수 있는 문제일 것이다.</li>
<li>재귀함수는 자기자신을 호출한다, 반복적으로 함수가 실행된다는 것이다.</li>
<li>즉 하노이의 탑 게임은, <strong>반복적으로 같은 행동을 수행</strong>하면 클리어 가능한 게임이다.</li>
</ol>
<p>사실 연습문제 였다. 축하합니다. 하지만 덕분에 당신은 연역법을 마스터했습니다. 이제 하노이의 탑 게임의 룰을 생각해보자</p>
<blockquote>
<ol>
<li>작은 원판 위에 큰 원판이 있을 수 없다.</li>
</ol>
</blockquote>
<ol>
<li><p>따라서, 목적지 기둥에는 가장 큰 원판 부터 순서대로 원판이 쌓여야한다.</p>
</li>
<li><p>즉, 목적지 기둥에 가장 큰 원판을 먼저 옮겨야한다.</p>
</li>
<li><p>그러기 위해서는 <strong>가장 큰 원판을 제외한 모든 원판을 중간 기둥으로 옮겨</strong>야한다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/7193945a-fbf8-4099-9edb-dea21ad9f6c0/image.png" alt=""></p>
</li>
</ol>
<blockquote>
<p>띠띠용!💡 가장 큰 원판을 제외한 원판을 중간 기둥으로 옮기는 것은 
<strong>1개 적은 원판 개수로, 하노이의 탑 게임을 하는 것과 동일</strong>하다!!! 반복작업을 찾았다!!!</p>
</blockquote>
<p>수식으로 표현하면 다음과 같다. 이걸 그대로 함수에 적용하면 된다.</p>
<pre><code>hanoi(n) = 2 * hanoi(n-1) + 1</code></pre><hr>
<h2 id="빨리-정답-알려주세요">빨리 정답 알려주세요</h2>
<p><img src="https://images.velog.io/images/mgm-dev/post/d450e993-4c05-40f4-bc1b-18f7f41267d1/image.png" alt=""></p>
<pre><code class="language-python">def hanoi(n):
    # 원판이 1개라면 1회의 시행으로 게임이 끝난다
    if n == 1:
        return 1
    # 수식을 그대로 집어 넣자
    return 2 * hanoi(n-1) + 1</code></pre>
<p>&amp;nbsp 뭔가 엄청 간단해 보인다. 게임 클리어에 필요한 시행 회수를 계산하는 함수를 만들긴 했는데, 어떻게 가장 짧은 회수로 게임을 클리어하는 방법 자체는 모르겠다. 하노이의 탑 그게 뭔데? 그거 어떻게 하는 건데? </p>
<hr>
<h2 id="모르는게-정상이다">모르는게 정상이다</h2>
<p><img src="https://images.velog.io/images/mgm-dev/post/e8d1a3e3-6eab-4ce1-bb54-0e08d1b431dc/image.png" alt=""></p>
<p>&amp;nbsp 극단적인 예시를 들어보자. 물리엔진을 만든 개발자가 있다. 당신은 그 개발자에게 다음과 같은 질문을 했다.</p>
<blockquote>
<p>님이 만드신 물리엔진에서 젠가를 쌓아놓고 거기다가 공을 차면 어떻게 되나요?</p>
</blockquote>
<p>다음 중 어느 대답이 더 신빙성이 있는가?</p>
<blockquote>
<ol>
<li>그러한 경우 제가 이렇게 저렇게 동작하게 만들어 놓았기 때문에 다음과 같은 결과가 나올 것입니다...</li>
<li>시뮬레이션을 돌려봐야 알 것 같은데요. 해당 케이스에 적용 되는 법칙은 다음과 같습니다...</li>
</ol>
</blockquote>
<p>글쓴이 같으면 2번 대답이 더 신빙성이 있을 것 같다. 물론 글쓴이가 물리엔진을 잘안다는 것은 아니고. 물리엔진 처럼 복잡한 프로그램을 만들면서, 모든 케이스를 일일히 직접 생각해가면서 만드는게 편할까. 통용이 가능한 공식의 모음으로 생각하면서 만드는게 편할까? 전자와 후자 중 어느 경우가 에러가 더 많을까?</p>
<hr>
<h2 id="컴퓨터에게-생각을-이양하자">컴퓨터에게 생각을 이양하자</h2>
<p><img src="https://images.velog.io/images/mgm-dev/post/20bfbaff-c275-46dc-9e00-601c0746cf8e/image.png" alt=""></p>
<p>&amp;nbsp 컴퓨터는 똑똑하다. 계산을 실수하는 일도 없고. 기억력도 사람보다 좋다. 하지만 컴퓨터는 멍청하기도 하다. 당연하지만, 시킨일 밖에 못한다. 컴퓨터에게 명령하기 위해서는 명확한 룰을 정해서 프로그래밍 언어로 실수 없이 정리 해줘야한다. 효율적으로 프로그램을 짜기 위해서는 컴퓨터에게 현명한 명령을 내려야한다. 말은 쉽지 현명하게 명령을 내리는 것은 겁나 어렵다. 그래서 알고리즘이 어렵다.</p>
<p>&amp;nbsp 하지만 현명하게 명령을 내릴 수 있다면 어려운 문제를 해결 할 수 있다. 애초에 사람이 쉽고 빠르게 해결할 수 있는 문제였으면 프로그램을 작성할 필요가 희박하다고, 글쓴이는 생각한다. 뭔가 하노이의 탑 알고리즘을 이야기하다가, 왜 프로그래밍을 하는지에 대해 까지 급발진 한 것 같다. 정리 하자면 다음과 같다.</p>
<p><img src="https://images.velog.io/images/mgm-dev/post/5a62285f-fd39-4ae4-9d51-fba93f250756/image.png" alt=""></p>
<p>&amp;nbsp 알고리즘이란 어떠한 문제를 해결하기 위해 정해진 일련의 절차나 방법을 공식화한 형태로 표현한 것 또는 계산을 실행하기 위한 단계적 절차를 의미한다. <strong>알고리즘 문제를 푸는 것은 컴퓨터에게 생각 또는 작업을 이양하는 것의 연습이다.</strong> </p>
]]></description>
        </item>
    </channel>
</rss>