<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>genieDocs</title>
    <link>https://geniee.tistory.com/</link>
    <description>웹 개발하는 마라토너. 기술 이면의 인간다운 기록들을 남깁니다.</description>
    <language>ko</language>
    <pubDate>Tue, 11 Aug 2026 15:25:45 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>realhee</managingEditor>
    <image>
      <title>genieDocs</title>
      <url>https://tistory1.daumcdn.net/tistory/3738730/attach/e4289304f7c84e57a5b8a9082e624fd8</url>
      <link>https://geniee.tistory.com</link>
    </image>
    <item>
      <title>테크 리더들이 생각하는 &amp;quot;개발자 원칙&amp;quot;</title>
      <link>https://geniee.tistory.com/entry/%ED%85%8C%ED%81%AC-%EB%A6%AC%EB%8D%94%EB%93%A4%EC%9D%B4-%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9B%90%EC%B9%99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;service-leadership-rules-header.webp&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXpN52/btsAUmnjnum/kiyvPpcjlomeCqGL0VGLX1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXpN52/btsAUmnjnum/kiyvPpcjlomeCqGL0VGLX1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXpN52/btsAUmnjnum/kiyvPpcjlomeCqGL0VGLX1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXpN52%2FbtsAUmnjnum%2FkiyvPpcjlomeCqGL0VGLX1%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;302&quot; data-filename=&quot;service-leadership-rules-header.webp&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 학습 루틴이 느슨해지거나, 나태해질 때 쯤 우아한 테크 Youtube 채널을 들어가 신입 개발자 분들의 10분 테코톡을 보면서 요새 궁금해하는 키워드들이 무엇인지 탐색해보곤 한다. (이와 동시에 공부하기도 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중에서도 주기적으로 진행하는 컨텐츠,&lt;b&gt; 우아한 테크 세미나&lt;/b&gt;는 현업 개발자 분들의 스피치 및 인터뷰로 짧은 시간 안에 양질의 테크 트렌드와 이직 시장 분위기를 파악할 수 있어 애청하는 편이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 3월, 우아한 형제들에서 진행하는 우아한 테크 세미나 라이브 스트리밍을 시청한 적이 있는데 요즘의 무기력한 자신을 돌이켜 보며 당시 메모했던 내용을 복기하며 포스팅을 올려본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 자주 접하던 네임드 개발자 분들의 질의응답 인터뷰가 인상적이었는데, 7개월이 지난 지금 내용을 곱씹어 보니 그때와 지금의 내 마음가짐과 현업에 대한 나의 인식이 어떻게 다른지 생각해보게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제어할 수 없는 것에 의존하지 않기 - 인프랩 이동욱&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래머에게 요구되는 것은 100점이 아닌 80~90점짜리 프로그램을 기한 내에 완성하는 일이다.&lt;br /&gt;- 나카지마 사토시, [오늘, 또 일을 미루고 말았다]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연구원이 아닌 &lt;b&gt;프로덕트 엔지니어&lt;/b&gt;의 일은 &lt;b&gt;고객이 원하는 기능&lt;/b&gt;을 &lt;b&gt;고객이 원하는 시점&lt;/b&gt;에 전달하는 것&lt;/li&gt;
&lt;li&gt;즉, 일정 &amp;gt; 퀄리티? &amp;rArr; 아무리 급해도 항상 80~90점짜리 소프트웨어를 일정 내 개발할 수 있는 방법&lt;/li&gt;
&lt;li&gt;일정을 항상 잘 지키는 분들의 공통점
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;u&gt;본인만의 기준과 원칙으로 빠르게 결정 (경험)&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;선택의 순간마다 고민하는 사람 vs &lt;u&gt;원칙에 따라 빠르게 결정하고 중요한 것만 고민하는 사람&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;좋은 코드를 결정하는 방법이 최신의 영감에 따라 움직이지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;힘든 개발자 시장에서 회사 입장에서 제어할 수 있는 것 : 개발문화/프로세스에 대한 변화&lt;/li&gt;
&lt;li&gt;제어할 수 없는 것에 거리두기 + &lt;u&gt;제어할 수 있는 것에 집중하기&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나의 생각&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용에 적극적으로 동감한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6년 차 개발자로 일하면서 때로는 내가 이직을 하거나 환경을 바꾸지 않는 이상 바꿀 수 없는 요소들이 더러 있다. 예를 들어, 사업 카테고리라던가, 조직의 의사결정 흐름 등 개인의 노력만으로는 바꾸기 쉽지 않은 부분들은 아무리 수평적인 관계인 조직이더라도 어디에나 있기 마련이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자로 일하면서 문제를 발견하고 즉각적으로 개선해나갈 수 있는 것들이 무엇인지 고민하는 것. 이 요소는 앞으로 개발자 생태계를 살아감에 있어서 현명하게 커리어를 결정하고 나아갈 수 있는 큰 원동력이 될 것이라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 이런 방향성을 개발자들과 공유하면서 고리타분한 생각은 걷어내고, 도움이 될 만한 방향으로 성장하는 것이 중요할 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Q&amp;amp;A&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q. 유연성 있게 성장할 수 있는 개발 방법이나 습관&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;박미정 : 내가 작성했던 코드를 다시 작성하는 것 (확장성, 시스템 설계 등)&lt;/li&gt;
&lt;li&gt;이동욱 : 주니어 때부터 연습해야하는 부분인데 내가 틀렸다고 인정 하는 것&lt;/li&gt;
&lt;li&gt;박성철 : 소프트웨어 개발자로 성장하는 과정을 즐기는 것. 어느정도 수준에 다달아야 하고, 그 부분을 즐기는 것.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q. 좋은 리더십과 좋은 피드백을 주고받는 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;박미정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;팀원 한 명 한 명에 맞는 피드백을 주려고 함&lt;/li&gt;
&lt;li&gt;팀원 한 명 한 명을 깊게 관찰하고 염탐(?)한다&lt;/li&gt;
&lt;li&gt;어떻게 일을 하는 사람이고, 문제에 어떻게 행동을 보이는 사람인지 계속 트랙킹
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 성향의 사람인지 알고싶어서&lt;/li&gt;
&lt;li&gt;슬랙에서 메시지를 주고받는 뉘앙스까지 관찰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이동욱
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일기를 쓴다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가 이런걸 했다, 회의 때 이런 걸 했다&lt;/li&gt;
&lt;li&gt;피드백을 줘야되는 것이 생겼을 때, 조금 빠르게 주는 편
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내가 생각하는 게 맞나? 생각하고 금주 내에 피드백 주는 편&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전사적으로 하는데 회의를 모두 녹음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;녹음을 듣고, 셀프 피드백을 하도록 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;박성철
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각자의 특징을 수용하고, 각자가 잘하는 일을 할 수 있는 상황을 만드는 데 노력&lt;/li&gt;
&lt;li&gt;교정 피드백(고치는 것)을 하지 않고, 잘 하는 부분을 더 잘하게끔 상황을 만드는 노력을 함&lt;/li&gt;
&lt;li&gt;하지만 이 부분이 한계를 넘어서는 경우, 미안하지 않으려 노력&lt;/li&gt;
&lt;li&gt;그저 안 맞는 것일 뿐 그 사람의 잘못이 아님&lt;/li&gt;
&lt;li&gt;회사 안에서 맞는 조직을 찾아 제안해준다던가, 안 맞는 부분에 대해 그 사람을 바꾸려고 노력하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나의 생각&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 분의 답변 모두 내 뇌리를 관통하는 답변이어서 많은 생각을 하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자도 부사수가 고민스러워하는 부분을 물어오거나 코드 리뷰를 진행할 때마다 적절한 피드백이 무엇일지 고민한다. (이 부분은 앞으로도 항상 고민스러울 것 같다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;박미정 리더님의 방법은 긴 시간동안 팀원들을 지켜봐야 하는 동시에 긴 시간이 필요하므로 피드백을 주기에 가장 정통적 방법이지만 가장 쉽지 않은 방법일거라 생각한다. 조직에서의 시간은 돈이다. 물론 단시간에 사람을 꿰뚫어 볼 줄 아는 혜안을 가진 리더들은 충분히 좋은 방법이라 생각하지만 그 누구에게나 통용하는 방법은 아니라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혼자만이 아닌 여러 사람들의 시간을 덜어주기 위해서는 즉각적인 피드백. 이보다 더 지혜로운 방법은 없다. 혹여 그 피드백이 옳은 방식이 아니더라도 이 부분이 노출되는 것 자체에서 개선의 여지가 있다. 팀원간의 잦은 의사소통은 업무 효율에 도움이 될 수 밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q. 팀원들이 성장에 대한 니즈가 많이 없어 보이면 어떻게 불어넣을까?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;박성철&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;일이 재밌으면 성장하고 싶어진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;근본적으로 자기 실현에 대한 욕구가 없는 사람은 한 명도 없다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;그것을 발현하지 못하게 봉인한 것이 문제, 이것을 열어주는 것이 좋다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;u&gt;성취할 수 있는 경험&lt;/u&gt;을 조금씩 해 나가면 좋지 않을까?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나의 생각&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, 업무가 일정에 치여 바쁘게 흘러갈 때 개발자들이 무기력감에 휩싸일 때가 있다. 자발적으로 분석하고, 설계하고 개선해나가는 분위기라기보다 위에서 정해진 틀에 맞추기 위해 수동적으로 개발을 하게 되는 경우 특히 그렇다. 일이 항상 재밌을 수는 없을 것이다. 리더가 개발자들에게 동기 부여를 줄 수 있도록 고민하는 것도 좋지만, 개발자들이 자발적으로 작은 성취라도 이룰 수 있도록 의사 표현을 하는 것도 중요하다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올 해 팀장님과 그룹장님과 함께 조직에서 성장의 환경을 만드는 방법에 대해 고민을 나눴던 경험이 있다. 성장 의지가 없는 후배를 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;적절한 타이밍에 &lt;/span&gt;이끄는 방법에 대한 것도 고민하는 주제였다. 성과에 대한 칭찬과, 더 잘하고 싶어지는 환경을 만들기. 올 한 해를 솔선수범으로 채우고자 했던 초심을 떠올릴 수 있었다. 경험주의자의 시간은 헛되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q. 실패와 번아웃, 무기력함을 경험한 적이 있는지?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;박성철&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;스트레스 관리 - 심리학에서 스트레스를 기피해야 하는 것으로 여겨서 심리학을 싫어한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;디스트레스와 유스트레스를 구분&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;유스트레스 : 활력을 얻고, 더 잘하고 싶어지게 만드는 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;디스트레스 : 과해서 견딜 수 없게 되는 상태 &amp;rArr; 정도를 넘어가면 번아웃으로 직결&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;내가 자신감이 넘치면 유스트레스의 범위가 넓어진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;자신감이 없으면, 조금만 스트레스가 쌓여도 디스트레스가 되어버린다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;자신감을 회복하고, 도전하고 해낼 수 있다는 생각을 스스로 만들 수 있게 만드는 게 중요&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;내가 하는 건, 이불을 개는 것. 즉, 아주 작은 성취를 하고 이를 통해 뿌듯해 하는 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;이로 인해 더 많은 일을 도전하고, 재밌게 할 수 있게 된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나의 생각&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자를 떠나서 모든 직장인들이 공감할 수 있는 내용. 스트레스는 직장 생활에서 뗄 래야 뗄 수 없다. 그 스트레스 상황을 어떻게 해석하고 나아가는지에 대한 아주 좋은 인사이트라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적당한 긴장감과 스트레스는 성장의 재료가 된다. 작은 성취를 습관적으로 해 온 사람이라면 스트레스는 긍정적인 선순환으로 이어질 수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Ref.&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=DJCmvzhFVOI&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[우아한테크세미나] 테크 리더 3인이 말하는 &quot;개발자 원칙&quot;&lt;/a&gt;&lt;/p&gt;</description>
      <category>Insight</category>
      <category>개발자</category>
      <category>리더십</category>
      <category>배달의민족</category>
      <category>번아웃</category>
      <category>우아한테크세미나</category>
      <category>우아한형제들</category>
      <category>우테코</category>
      <category>인사이트</category>
      <category>컨퍼런스</category>
      <category>프론트엔드</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/52</guid>
      <comments>https://geniee.tistory.com/entry/%ED%85%8C%ED%81%AC-%EB%A6%AC%EB%8D%94%EB%93%A4%EC%9D%B4-%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9B%90%EC%B9%99#entry52comment</comments>
      <pubDate>Mon, 27 Nov 2023 22:34:44 +0900</pubDate>
    </item>
    <item>
      <title>Emotion으로 React 컴포넌트 디자인하기</title>
      <link>https://geniee.tistory.com/entry/Emotion-%EC%98%A8%EB%B3%B4%EB%94%A9</link>
      <description>&lt;h1&gt;&lt;b&gt;Emotion?&lt;/b&gt;&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5JMCZ/btrNX83KQw3/SrvCRpnF2EEfmYfPkY7Rw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5JMCZ/btrNX83KQw3/SrvCRpnF2EEfmYfPkY7Rw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5JMCZ/btrNX83KQw3/SrvCRpnF2EEfmYfPkY7Rw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5JMCZ%2FbtrNX83KQw3%2FSrvCRpnF2EEfmYfPkY7Rw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;520&quot; height=&quot;260&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML 요소 혹은 React 컴포넌트에 CSS를 적용하기 위한 라이브러리&lt;/li&gt;
&lt;li&gt;CSS-in-JS 라이브러리 중에서는 Styled Component 라이브러리가 가장 대두 되었으나, &lt;a href=&quot;https://mui.com/&quot;&gt;MUI(Material UI)&lt;/a&gt;가 스타일링 엔진을 Emotion으로 채택하면서 이목이 집중되고 있음&lt;/li&gt;
&lt;li&gt;(Emotion에서도 styled component의 장점을 차용해서 활용하려는 흔적이 돋보임)&lt;/li&gt;
&lt;li&gt;css() 함수를 통해 간편한 React 컴포넌트 스타일링이 가능&lt;/li&gt;
&lt;li&gt;공식 문서가 굉장히 친절하므로 &lt;a href=&quot;https://emotion.sh/docs/introduction&quot;&gt;Getting Started&lt;/a&gt; 항목을 읽어보는 것이 가장 명시적&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;패키지 설치 (react)&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vanilla 환경은&amp;nbsp;@emotion/css 패키지로 설치&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;$ yarn add @emotion/react
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;emotion에서도 styled component처럼 styled 사용이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;# assuming you already have @emotion/react installed
$ yarn add @emotion/styled
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;기본 문법&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;css() 함수&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;css() 함수의 반환 결과로 해당 스타일을 적용하고 싶은 HTML 요소나 React 컴포넌트의 css라는 prop에 넘겨줌&lt;/li&gt;
&lt;li&gt;인자를 객체형 또는 문자형으로 넘길 수 있는데, Emotion 공식문서에서는 가급적 스타일을 &lt;b&gt;객체로 선언 권장&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;css() 함수 호출 생략하고 요소 혹은 컴포넌트 css prop에 바로 객체를 넘길 수 있음&lt;/li&gt;
&lt;li&gt;TS 사용 시 type checking 을 통해 오타 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;예시 (객체형 인자, 문자형 인자)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;/** @jsxImportSource @emotion/react */
// JSX pragma : React의 jsx() 함수를 사용하지 말고, Emotion의 jsx() 함수를 대신 사용하라고 알려주기 위함
// css prop에 넘어간 스타일이 제대로 반영이 되지 않을테니 주의
import { css } from &quot;@emotion/react&quot;;

function MyComponent() {
  return (
    &amp;lt;div
      css={css({
        backgroundColor: &quot;yellow&quot;,
      })}
    &amp;gt;
      노란색 영역
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;/** @jsxImportSource @emotion/react */
import { css } from &quot;@emotion/react&quot;;

function MyComponent() {
  return (
    &amp;lt;div
      css={css`
        background-color: yellow;
      `}
    &amp;gt;
      노란색 영역
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a href=&quot;https://emotion.sh/docs/styled&quot;&gt;Styled Components&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lscEO/btrNYo6belM/e2FxmyuOcFkLhpMHBoTLh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lscEO/btrNYo6belM/e2FxmyuOcFkLhpMHBoTLh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lscEO/btrNYo6belM/e2FxmyuOcFkLhpMHBoTLh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlscEO%2FbtrNYo6belM%2Fe2FxmyuOcFkLhpMHBoTLh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;857&quot; height=&quot;563&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;withComponent&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;StyledComponent 에 적용된 style을 다른 tag 혹은 요소에 동일한 style을 적용하기 위해 사용&lt;/li&gt;
&lt;li&gt;아래는 Section 태그의 style을 aside 태그에 withComponent로 동일하게 적용한 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;${} : 부모, 자식 간의 targeting이 가능하다&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;593&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNKicW/btrNYfBFUyK/v8ipWWEkCdQUM18DMItKM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNKicW/btrNYfBFUyK/v8ipWWEkCdQUM18DMItKM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNKicW/btrNYfBFUyK/v8ipWWEkCdQUM18DMItKM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNKicW%2FbtrNYfBFUyK%2Fv8ipWWEkCdQUM18DMItKM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;856&quot; height=&quot;593&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eLhelE/btrNVliQojY/GizdnY6kvSKBZ1SZxw5EkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eLhelE/btrNVliQojY/GizdnY6kvSKBZ1SZxw5EkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eLhelE/btrNVliQojY/GizdnY6kvSKBZ1SZxw5EkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeLhelE%2FbtrNVliQojY%2FGizdnY6kvSKBZ1SZxw5EkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;852&quot; height=&quot;519&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;amp; : nest selector를 사용할 수 있다&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZsHZm/btrNY0Rz3wd/XUcQvzlTnr8JpdUefeoVYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZsHZm/btrNY0Rz3wd/XUcQvzlTnr8JpdUefeoVYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZsHZm/btrNY0Rz3wd/XUcQvzlTnr8JpdUefeoVYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZsHZm%2FbtrNY0Rz3wd%2FXUcQvzlTnr8JpdUefeoVYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;857&quot; height=&quot;460&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;https://emotion.sh/docs/composition&quot;&gt;Composition&lt;/a&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Emotion의 가장 강력하고 유용한 패턴 중 하나&lt;/li&gt;
&lt;li&gt;일반 CSS를 사용하면 여러 클래스 이름을 사용하여 style을 함께 구성할 수 있지만 정의되는 순서가 적용되는 순서이기 때문에 매우 제한적&lt;/li&gt;
&lt;li&gt;Composition을 사용하면 style이 사용되는 순서대로 merge 된다&lt;/li&gt;
&lt;li&gt;&amp;rArr; style이 생성된 순서에 대해 생각할 필요가 없음!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bffWcO/btrNVkYymlQ/C4NRN09hKc4S61qTHh1390/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bffWcO/btrNVkYymlQ/C4NRN09hKc4S61qTHh1390/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bffWcO/btrNVkYymlQ/C4NRN09hKc4S61qTHh1390/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbffWcO%2FbtrNVkYymlQ%2FC4NRN09hKc4S61qTHh1390%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;861&quot; height=&quot;551&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;React로 Button 컴포넌트 작성해보기&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고정 스타일링
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt;button&amp;gt;요소의&amp;nbsp;cssprop을 통해 다양한 CSS 속성 정의를 객체로 정의&lt;/li&gt;
&lt;li&gt;브라우저에서 소스 보기를 해보면 아래와 같이 &amp;lt;button&amp;gt; 요소에 Emotion이 자동으로 생성해준 클래스 이름이 붙어있음 (랜덤으로 생성됨)&lt;/li&gt;
&lt;li&gt;내부 스타일 시트는 class selector로 적용된 스타일이 Emotion으로 삽입한 CSS 선언 내용과 동일하게 적용되어 있음&lt;/li&gt;
&lt;li&gt;Emotion의 vendor prefixing 기능 : Emotion이 자동으로 브라우저 별로 필요한 CSS 속성을 추가. 소위 이러한 작업을 &lt;b&gt;vendor prefixing&lt;/b&gt;이라고 칭하는데, Emotion을 사용할 때 얻을 수 있는 이점 중 하나!&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;가변 스타일링&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React 컴포넌트에 넘어온 props에 따라 다른 스타일을 쉽게 적용 가능&lt;/li&gt;
&lt;li&gt;바꾸고 싶은 CSS 속성 값에 상수 대신에 prop에 따라 변하는 변수를 할당
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import Button from &quot;./Button&quot;;

function App() {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;Button variant=&quot;default&quot;&amp;gt;Default&amp;lt;/Button&amp;gt;
      &amp;lt;Button variant=&quot;danger&quot;&amp;gt;Danger&amp;lt;/Button&amp;gt;
      &amp;lt;Button variant=&quot;outline&quot;&amp;gt;Outline&amp;lt;/Button&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;prop에 따라 바꾸고 싶은 CSS 속성이 위와 같이 하나가 아니라 여러 개일 경우 CSS 속성 이름과 값을 동시에 객체화&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;Ref&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://emotion.sh/docs/introduction&quot;&gt;&lt;b&gt;Emotion 공식문서&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.daleseo.com/emotion/&quot;&gt;&lt;b&gt;Emotion으로 React 컴포넌트 스타일하기&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End</category>
      <category>css</category>
      <category>cssinjs</category>
      <category>Emotion</category>
      <category>frontend</category>
      <category>JavaScript</category>
      <category>React</category>
      <category>react컴포넌트</category>
      <category>React컴포넌트스타일</category>
      <category>VanillaJS</category>
      <category>컴포넌트디자인</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/51</guid>
      <comments>https://geniee.tistory.com/entry/Emotion-%EC%98%A8%EB%B3%B4%EB%94%A9#entry51comment</comments>
      <pubDate>Thu, 6 Oct 2022 17:41:14 +0900</pubDate>
    </item>
    <item>
      <title>React  공식문서 톺아보기 (feat.코어 자바스크립트)</title>
      <link>https://geniee.tistory.com/entry/React%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-%ED%86%BA%EC%95%84%EB%B3%B4%EA%B8%B0-feat%EC%BD%94%EC%96%B4-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 개발자들은 공부를 시작한 순간, 심화 기술에 대한 레퍼런스 참고 시, 새로운 버전이 출시되면 어김없이 공식문서를 찾게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수 많은 테크 블로그들의 정보와 비교해 가장 심플하고 가장 직관적이며 가장 정확한 정보를 가지고 있기에 뗄레야 뗄 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 최근 한 동안 코어 자바스크립트 공부에 빠져 &lt;b&gt;실행 컨텍스트, 스코프, 비동기&lt;/b&gt;에 대한 기본기를 다졌다. (이에 대한 내용은 느낀 바가 많아 정리 후 포스팅 할 예정이다) 자바스크립트 엔진이 동작하는 방식을 이해하고 다시 읽는 공식문서는 좀 색달랐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 그저 페이스북이 정한 법칙대로. 로마에 왔으면 로마의 법을 따르라는 것 마냥 &quot;그냥 그렇게 써야 돼&quot;로 문서를 받아들였다면, 지금은 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&quot;로컬 state를 적용하기 위해서 왜 function 컴포넌트가 아닌 class 컴포넌트를 써야할까?&quot;&lt;/span&gt;&lt;/b&gt;가 궁금해졌다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;br /&gt;클래스형 컴포넌트는 자유롭게 state에 접근할 수 있지만, 함수형 컴포넌트는 state를 직접 사용하진 못하고 다른 메소드를 통해서 사용&lt;br /&gt;&lt;br /&gt;&lt;b&gt;클래스형 컴포넌트 :&lt;/b&gt;&lt;br /&gt;state기능 및 라이프사이클 기능 사용 가능&lt;br /&gt;임의 메서드 정의 가능&lt;br /&gt;render 함수 정의 필수&lt;br /&gt;jsx 반환 필수&lt;br /&gt;&lt;br /&gt;&lt;b&gt;함수형 컴포넌트 :&lt;/b&gt;&lt;br /&gt;선언하기 간편&lt;br /&gt;메모리도 클래스형 컴포넌트보다 덜 사용&lt;br /&gt;빌드 후 배포할 때 파일 크기가 더 작음 (사실상 별 차이 없음)&lt;br /&gt;state와 라이프사이클 API의 사용이 불가능&lt;br /&gt;-&amp;gt; 리액트 v16.8업데이트 후 Hooks 도입 후 해결&lt;br /&gt;(완전히 클래스형 컴포넌트와 같지는 않지만 조금 다른 방식으로 비슷한 작업 가능)&lt;br /&gt;(리액트 공식 권장: 함수형 컴포넌트 + Hook )&lt;br /&gt;&lt;br /&gt;&lt;b&gt;결론 :&lt;/b&gt; &lt;br /&gt;리액트 공식 문서에서는 가능하면 함수형 컴포넌트와 React Hooks를 사용할 것을 권장하고있다. 따라서 함수형 컴포넌트와 함께 useState를 사용하자!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(결국 리액트도 자바스크립트로 만들어진 라이브러리이기 때문에 기본적으로 vanillaJS에 대한 이해가 있다면, 모든 것이 자연스럽게 받아들여질 수 있다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 읽어보는 공식문서는 궁금증과 나름대로의 해답을 내려가는 과정이 흥미로웠고, 이 과정을 기억하고자 포스팅 해 본다 ✍ &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/react-api.html&quot;&gt;React 최상위 API 불러오기&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;//ES6
import React from 'react&amp;rsquo;
//ES5
var React = require('react')
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React 엘리먼트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불변객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성 이후에는 자식이나 속성 변경 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI를 업데이트하는 유일한 방법 &amp;rarr; &lt;b&gt;새 엘리먼트를 생성하고 ReactDOM.render()로 전달&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React 컴포넌트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI를 독립적이고 재사용할 수 있는 부분으로 분리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/react-api.html#reactcomponent&quot;&gt;React.Component&lt;/a&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class Greeting extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;Hello, {this.props.name}&amp;lt;/h1&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;ES6 class 사용&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/react-api.html#reactpurecomponent&quot;&gt;React.PureComponent&lt;/a&gt;컴포넌트에 대하여 얕은 비교만 수행해 성능 향상 가능자식 컴포넌트들이 &amp;ldquo;순수&amp;rdquo;한지 확인 필요&lt;/li&gt;
&lt;li&gt;props와 state의 구조가 간단할 것으로 예상될 때에만 사용&lt;/li&gt;
&lt;li&gt;shouldComponentUpdate() 구현 X&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/react-api.html#reactmemo&quot;&gt;React.memo()&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;const MyComponent = React.memo(function MyComponent(props) {
  /* props를 사용하여 렌더링 */
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고차 컴포넌트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 동일한 props로 동일한 결과를 렌더링 시 memo 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 메모이징(Memoizing)하도록 래핑&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 렌더링하지 않고 마지막 렌더링 결과를 재사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; &lt;b&gt;불필요 렌더링 줄여 성능 최적화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props변화에만 영향을 줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props가 갖는 복잡한 객체에 대하여 얕은 비교만을 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 래핑 함수컴포넌트에 useState, useReducer, useContext hook을 사용하면 여전히 state, context 변화 시 재렌더링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 다른 비교 동작을 원한다면, 두 번째 인자로 별도의 비교 함수를 제공&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;function MyComponent(props) {
  /* props를 사용하여 렌더링 */
}
function areEqual(prevProps, nextProps) {
  /*
  nextProps가 prevProps와 동일한 값을 가지면 true를 반환하
	현재 state 또는 props의 변화 시 true를  반환하는 shouldComponentUpdate() 메서드와 반대!
  */
}
export default React.memo(MyComponent, areEqual);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.createElement()&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React.createElement(type, [props],[...children])&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인자로 주어지는 타입에 따라 새로운 React 엘리먼트를 생성 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인자로 JSX 사용 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 React 컴포넌트를 만들 땐 createElement(), createFactory() 대신&amp;nbsp;&lt;a href=&quot;https://ko.reactjs.org/docs/introducing-jsx.html&quot;&gt;JSX를 사용할 것&lt;/a&gt;을 권장!&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/react-dom.html#render&quot;&gt;render()&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;ReactDOM.render(element, container[, callback])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 엘리먼트를&amp;nbsp;container&amp;nbsp;DOM에 렌더링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트에 대한&amp;nbsp;&lt;a href=&quot;https://ko.reactjs.org/docs/more-about-refs.html&quot;&gt;참조&lt;/a&gt;를 반환 (&lt;a href=&quot;https://ko.reactjs.org/docs/components-and-props.html#function-and-class-components&quot;&gt;무상태 컴포넌트&lt;/a&gt;는&amp;nbsp;null을 반환)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;container&amp;nbsp;하위에 렌더링 이력이 있다면 업데이트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경된 React 엘리먼트 DOM만 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 콜백 제공 시 컴포넌트가 렌더링되거나 업데이트된 후 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  &lt;b&gt;참고&lt;/b&gt;&lt;br /&gt;- 처음 호출할 때 기존의 DOM 엘리먼트를 교체하며 이후의 호출은 React의 DOM diffing 알고리즘을 사용&lt;br /&gt;- 컨테이너 노드를 수정하지 않고 컨테이너의 하위 노드만 수정&lt;br /&gt;- 자식 노드를 덮어쓰지 않고 기존 DOM 노드에 컴포넌트를 추가 가능&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const element = &amp;lt;h1&amp;gt;Hello, world&amp;lt;/h1&amp;gt;;
ReactDOM.render(element, document.getElementById('root'));
// root 객체에 render하는 다른 방법
// const root = ReactDOM.createRoot(document.getElementById('root'));
// root.render(element);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;// React.createElement(type, [props],[...children])
// 명세 : 인자로 주어지는 타입에 따라 새로운 React 엘리먼트를 생성하여 반환
class Hello extends React.Component {
  render() {
    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
  }
}

ReactDOM.render(
  React.createElement(Hello, {toWhat: 'World'}, null),
  document.getElementById('root')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.Children&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불투명(opaque) 자료구조 this.props.children을 다루는 유틸리티 함수들을 제공&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.Children.toArray&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 자식에 key가 할당된 배열을 불투명 자료구조로 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;render()메서드에서&amp;nbsp;children의 집합을 다루고 싶을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this.props.children을 하부로 전달하기 전 재정렬하거나 일부만 잘라내고 싶을 때에 유용&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.Fragment&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;render() 메서드 내에서 추가 DOM 엘리먼트를 생성하지 않아도 여러 엘리먼트를 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;축약형인&amp;nbsp;&amp;lt;&amp;gt;&amp;lt;/&amp;gt;문법으로도 동일&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;render() {
  return (
    &amp;lt;React.Fragment&amp;gt;
      Some text.
      &amp;lt;h2&amp;gt;A heading&amp;lt;/h2&amp;gt;
    &amp;lt;/React.Fragment&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.Suspense&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리 상 아직 렌더링이 준비되지 않은 컴포넌트가 있을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로딩 지시자를 나타낼 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React.lazy와 Suspense는 아직 서버 사이드 렌더링 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에서 렌더링 된 앱에서 코드 분할을 하기 원한다면&amp;nbsp;&lt;a href=&quot;https://github.com/gregberge/loadable-components&quot;&gt;Loadable Components&lt;/a&gt; 추천&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 이 컴포넌트는 동적으로 불러옵니다
const OtherComponent = React.lazy(() =&amp;gt; import('./OtherComponent'));

function MyComponent() {
  return (
    // Displays &amp;lt;Spinner&amp;gt; until OtherComponent loads
    &amp;lt;React.Suspense fallback={&amp;lt;Spinner /&amp;gt;}&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;OtherComponent /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/React.Suspense&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Hooks&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class를 사용하지 않아도 state와 React 기능들을 사용&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/components-and-props.html&quot;&gt;주요개념&amp;gt;4.Component와 Props&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX attributes와 child를 해당 컴포넌트에 단일 객체로 전달 &amp;rarr; 이 객체가 &amp;ldquo;props&amp;rdquo;!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props의 이름은 사용될 context가 아닌 컴포넌트 자체의 관점에서 짓는 것을 권장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props는 readonly!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 순수함수 : 입력값을 바꾸려 하지 않고 항상 동일한 입력값에 대해 동일한 결과를 반환&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;// 순수함수 O
function sum(a, b) {
  return a + b;
}

//  순수함수 X
function withdraw(account, amount) {
  account.total -= amount;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt; 모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야 합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 순수함수 규칙을 위반하지 않기 위해 state를 사용!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(사용자 액션, 네트워크 응답 및 다른 요소에 대한 응답으로 시간에 따라 자신의 출력값을 변경)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/state-and-lifecycle.html&quot;&gt;주요개념&amp;gt;5.State와 생명주기&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clock컴포넌트에 setInterval()로 타이머를 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매초 UI를 업데이트하는 것을 외부가 아닌 컴포넌트Clock의 내부로 옮기고 싶을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상적으로 한 번만 코드를 작성하고&amp;nbsp;Clock이 스스로 업데이트하도록 만들려면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;rarr; State 사용!!!&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Clock 컴포넌트코드 상세 정리&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const root = ReactDOM.createRoot(document.getElementById('root'));

// function Clock(props) {
//   return (
//     &amp;lt;div&amp;gt;
//       &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
//       &amp;lt;h2&amp;gt;It is {props.date.toLocaleTimeString()}.&amp;lt;/h2&amp;gt;
//     &amp;lt;/div&amp;gt;
//   );
// }

// function tick() {
//   root.render(&amp;lt;Clock date={new Date()} /&amp;gt;);
// }

// setInterval(tick, 1000);

// function 컴포넌트에 state  적용하기
// 1. 함수에서 클래스로 변환하기
// 2. 클래스에 로컬 State 추가하기
// 3. 생명주기 메서드를 클래스에 추가하기 =&amp;gt; 마운팅 / 언마운팅
// 4. 컴포넌트 로컬 state 업데이트 =&amp;gt; tick() 메서드 구현
class Clock extends React.Component {
  // 2. this.state를 지정하는 constructor 추가
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  componentDidMount() {
    // 3. 컴포넌트 출력물이 DOM에 렌더링 된 후에 실행
    this.timerID = setInterval(
      () =&amp;gt; this.tick(),
      1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
  // 4.로컬 state 업데이트하기
  tick() {
    this.setState({date: new Date()});
  }
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
         {/*
         1. render() 내용 안에 있는 props를 this.props로 변경 
        &amp;lt;h2&amp;gt;It is {this.props.date.toLocaleTimeString()}.&amp;lt;/h2&amp;gt;
         2. this.state로 변경
         */}
        &amp;lt;h2&amp;gt;It is {this.state.date.toLocaleTimeString()}.&amp;lt;/h2&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
ReactDOM.render(
  &amp;lt;Clock/&amp;gt;,
  document.getElementById(&quot;root&quot;)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;setState()에 대한 3가지&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;직접 State 수정하지 말 것&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;this.state를 지정하는 유일한 공간은 contstructor&lt;/li&gt;
&lt;li&gt;this.state를 불변적(Immutable)인 데이터로 취급해라! &amp;rarr; setState() 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;State 업데이트는 비동기적일 수 있음&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1656212788344&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

// Correct 1  - 화살표 함수 형태
// 객체보다는 콜백함수를 인자로 사용!!
// state : 이전 state, props  : 변경할 값
this.setState((state, props) =&amp;gt; ({
  counter: state.counter + props.increment
}));

// Correct 2 - 일반  함수 형태
this.setState(function(state, props) {
  return {
    counter: state.counter + props.increment
  };
});&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;State 업데이트는 병합된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;별도의 호출로 변수를 독립적으로 업데이트&lt;/li&gt;
&lt;li&gt;병합은 얕게 이루어짐&lt;/li&gt;
&lt;li&gt;this.setState({comments})는&amp;nbsp;this.state.posts에 영향을 주진 않지만&amp;nbsp;this.state.comments는 완전히 대체&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1656212815597&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;componentDidMount() { 
	fetchPosts().then(
    	response =&amp;gt; { 
        	this.setState({
            	posts: response.posts 
             });
         });
fetchComments().then(
response =&amp;gt; { 
	this.setState({
    	comments: response.comments 
    });
 }); 
 }&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병합은 얕게 이루어짐&lt;/li&gt;
&lt;li&gt;제공한 객체를 현재 state로 병합&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;State&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props와 유사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비공개이며 컴포넌트에 의해 완전히 제어&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터는 아래로 흐른다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state = 로컬 = 캡슐화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트는 자신의 state를 자식 컴포넌트에 props로 전달할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;하향식(top-down)&amp;rdquo; 또는 &amp;ldquo;단방향식&amp;rdquo; 데이터 흐름&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;&amp;lt;FormattedDate date={this.state.date} /&amp;gt;
/*
FormattedDate 컴포넌트는 date를 자신의 props로 받을 것이고
이것이 Clock의 state로부터 왔는지,
Clock의 props에서 왔는지,
수동으로 입력한 것인지 알지 못합니다.
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/react-component.html&quot;&gt;API참고서&amp;gt;React&amp;gt;React.Component&lt;/a&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마운트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트의 인스턴스가 생성되어 DOM 상에 삽입될 때 순서대로 호출&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;constructor()&lt;/b&gt;&amp;nbsp;: 메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 생략 가능&lt;/li&gt;
&lt;li&gt;static getDerivedStateFromProps() : &amp;nbsp;render메서드를 호출하기 직전에 호출&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;render()&lt;/b&gt;&lt;/b&gt;&amp;nbsp;: 클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;componentDidMount() &lt;/b&gt;&lt;/b&gt;: 컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props 또는 state가 변경되면 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 메서드들은 컴포넌트가 다시 렌더링될 때 순서대로 호출&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;static getDerivedStateFromProps()&lt;/li&gt;
&lt;li&gt;shouldComponentUpdate()&amp;nbsp;: 현재 state 또는 props의 변화가 컴포넌트의 출력 결과에 영향을 미치는지 여부를 확인. 기본 동작은 매 state 변화마다 다시 렌더링을 수행하는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render()&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;getSnapshotBeforeUpdate()&amp;nbsp;: 가장 마지막으로 렌더링된 결과가 DOM 등에 반영되기 전에 호출. 이 생명주기 메서드가 반환하는 값은 componentDidUpdate()에 인자로 전달&lt;/li&gt;
&lt;li&gt;&lt;b&gt;componentDidUpdate()&lt;/b&gt;&amp;nbsp;: 갱신이 일어난 직후에 호출. 최초 렌더링에서는 호출되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마운트 해제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &lt;b&gt;componentWillUnmount()&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오류 처리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;static getDerivedStateFromError()&lt;/li&gt;
&lt;li&gt;componentDidCatch()&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;class 프로퍼티&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;defaultProps&amp;nbsp;: null이 아닌 아직 정의되지 않은 undefined 인 props를 다룰 때 사용&lt;/li&gt;
&lt;li&gt;displayName&amp;nbsp;: 디버깅 메시지 표시에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Ref&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@thyoondev/React-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-state-vs-%ED%95%A8%EC%88%98%ED%98%95-state&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[React] 클래스형 state vs 함수형 state&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>Props</category>
      <category>React</category>
      <category>react컴포넌트</category>
      <category>render</category>
      <category>State</category>
      <category>공식문서</category>
      <category>리액트</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/50</guid>
      <comments>https://geniee.tistory.com/entry/React%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-%ED%86%BA%EC%95%84%EB%B3%B4%EA%B8%B0-feat%EC%BD%94%EC%96%B4-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8#entry50comment</comments>
      <pubDate>Sun, 26 Jun 2022 12:02:47 +0900</pubDate>
    </item>
    <item>
      <title>구글 스프린트 7기 FTOOS, 뒤늦은 회고</title>
      <link>https://geniee.tistory.com/entry/%EA%B5%AC%EA%B8%80-%EC%8A%A4%ED%94%84%EB%A6%B0%ED%8A%B8-7%EA%B8%B0-FTOOS-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;프롤로그&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 3월, 한창 VanillaJS로 lotto 프로젝트의 코드 리뷰를 진행하던 시점에 있던 일이다. 처음에 function으로 구현되어 있던 객체들을 class형으로 &lt;span&gt;리팩토링 해보면서 ES6부터 class 개념이 도입되고, 이로 인해 절차 지향형 언어 JavaScript가 OOP 패러다임을 따르고 있는 것이 기존 스크립트 언어의 정체성을 반하는 행위가 아닐까 싶은 의문이 들었다. &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;function 객체와 class 객체의 차이점이 궁금해지면서 관련 기술 포스팅을 서치하던 중&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;우연히 현 카카오 엔터프라이즈에서 시니어 프론트엔드 개발자로 일하고 있는 &lt;/span&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://velog.io/@teo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;teo&lt;/b&gt;&lt;/a&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;의 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;글 &lt;b&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;&lt;a style=&quot;color: #7e98b1;&quot; href=&quot;https://velog.io/@teo/oop&quot;&gt;객체지향 프로그래밍과 javascript (약간의 역사를 곁들인...)&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;을 접하게 됐다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팩트만 나열한 기술 포스팅이 아닌 인사이트를 경험하고 그로 인한 성찰을 고스란히 녹여낸 필력이 너무나도 인상깊었다. 결국 집단 지성과 엔지니어들이 모여 기존 언어의 본질을 넘어 하나의 패러다임으로 변해가는 과정이 흥미롭기도 하면서 한 편으로는 충격적으로 다가오기도 했다. (결국 언어는 어떻게 쓰냐에 따라 끊임 없이 변화한다!) 다른 글들을 이어 읽어보면서 teo의 주도 하에 이뤄지는 &lt;b&gt;구글 스프린트&lt;/b&gt;라는 게 있다는 것을 알게 됐다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;*구글 스프린트란, 처음으로 만난 각 분야의 &lt;b&gt;&lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://github.com/FTOOOS&quot;&gt;사람들&lt;/a&gt;&lt;/b&gt;과 5일간 타이트하게 진행하는 협업 프로젝트다. 개발자와 디자이너, 기획자까지 다양한 분야의 사람들이 모여 자유로운 주제와 범위가 정해지지 않은 형식으로 아이디어 회의를 진행하고, 배포까지 진행하게 된다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소 활용해보고 싶었던 figma(피그마)를 통해 아이데이션을 진행하고, 게더타운을 통해 협업을 경험하면서 직접 배포도 할 수 있다는 것이 큰 장점으로 다가왔고, teo의 아카이빙 디스코드를 통해 일정을 눈여겨보며 7기 멤버로 참여하게 되었다.   짧은 기간동안 열중해서 작업결과물을 내야 한다는 생각 때문에 부담이 되기도 했지만 (퇴근 후 6일동안 매일 밤 11시부터 평균 3시간 정도 이루어졌다) 그래서 어떤 아이디어와 결과물이 나올지 더 궁금해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프린트가 진행되기 전 메일을 통해 준비해야 할 아이디어 스케치 양식과 스프린트의 목적에 대한 공지를 전달 받고는 취지가 마음에 들어 더 설레이는 마음으로 첫 스프린트를 기다렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아이디어의 범위는 없다.&lt;br /&gt;스프린트의 아이디어는 구체화하지 않는다.&lt;br /&gt;스프린트의 목적은&amp;nbsp;완성이 아닌 검증이다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구글 스프린트 1일차 : 팀 캔버스 활동 &amp;amp; 아이디어 선정&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_7671.PNG&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxNm1X/btrEvMuMafb/b4s3KkpzYEn1cg3Eo0msm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxNm1X/btrEvMuMafb/b4s3KkpzYEn1cg3Eo0msm1/img.png&quot; data-alt=&quot;구글 스프린트 7기 첫 만남 (어색)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxNm1X/btrEvMuMafb/b4s3KkpzYEn1cg3Eo0msm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxNm1X%2FbtrEvMuMafb%2Fb4s3KkpzYEn1cg3Eo0msm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;608&quot; height=&quot;521&quot; data-filename=&quot;IMG_7671.PNG&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구글 스프린트 7기 첫 만남 (어색)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3460&quot; data-origin-height=&quot;2514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ejlOzD/btrEvNULF4M/HP83scfVmwo3eGGyHK2Eo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ejlOzD/btrEvNULF4M/HP83scfVmwo3eGGyHK2Eo0/img.png&quot; data-alt=&quot;팀 캔버스 활동을 통해서 서로가 누군인지 알아보고 우리의 목표를 다짐하는 시간을 가졌다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ejlOzD/btrEvNULF4M/HP83scfVmwo3eGGyHK2Eo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FejlOzD%2FbtrEvNULF4M%2FHP83scfVmwo3eGGyHK2Eo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3460&quot; height=&quot;2514&quot; data-origin-width=&quot;3460&quot; data-origin-height=&quot;2514&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;팀 캔버스 활동을 통해서 서로가 누군인지 알아보고 우리의 목표를 다짐하는 시간을 가졌다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각자의 꿈,&amp;nbsp;&lt;span&gt;팀메이트가 알면 좋을만한&lt;span&gt; &lt;/span&gt;&lt;/span&gt;각자의 강점, 약점 등을 공유하며 팀 캔버스를 꾸몄다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스티커와 밑줄, 그림 등으로 리액션하는 과정에서 비언어적 소통을 하면서 피그잼의 유려한 UX에 또 한번 감탄했다..   스프린트를 진행하면서 가져가고 싶은 마음가짐에 대한 내용도 알아보면서 아이스 브레이킹만을 위함이 아닌 서로 알아가는 과정이 나중에 협조적인 분위기를 형성해나가는 데 큰 도움이 되는 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3910&quot; data-origin-height=&quot;2112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u8dKK/btrEulSK1Gt/1nFmzjOlRq4hL8kXcjNafK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u8dKK/btrEulSK1Gt/1nFmzjOlRq4hL8kXcjNafK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u8dKK/btrEulSK1Gt/1nFmzjOlRq4hL8kXcjNafK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu8dKK%2FbtrEulSK1Gt%2F1nFmzjOlRq4hL8kXcjNafK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3910&quot; height=&quot;2112&quot; data-origin-width=&quot;3910&quot; data-origin-height=&quot;2112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3836&quot; data-origin-height=&quot;1704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l0bJw/btrEtMiGdZg/kDi7l0yQ4EEPHy7ADgM0FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l0bJw/btrEtMiGdZg/kDi7l0yQ4EEPHy7ADgM0FK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l0bJw/btrEtMiGdZg/kDi7l0yQ4EEPHy7ADgM0FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl0bJw%2FbtrEtMiGdZg%2FkDi7l0yQ4EEPHy7ADgM0FK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3836&quot; height=&quot;1704&quot; data-origin-width=&quot;3836&quot; data-origin-height=&quot;1704&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3494&quot; data-origin-height=&quot;2216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c81MZe/btrEup1ECjj/EJfK1aKW4h42Ruk48jSDjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c81MZe/btrEup1ECjj/EJfK1aKW4h42Ruk48jSDjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c81MZe/btrEup1ECjj/EJfK1aKW4h42Ruk48jSDjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc81MZe%2FbtrEup1ECjj%2FEJfK1aKW4h42Ruk48jSDjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3494&quot; height=&quot;2216&quot; data-origin-width=&quot;3494&quot; data-origin-height=&quot;2216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 연 초부터 frontend 관련 기술 서적들에 꽂혀 한창 읽던 중이였는데, 알음알음 지인들의 추천을 받아 읽다보니 하나의 로드맵처럼 전체적인 기술 스택을 익히는 데 있어서 시퀀스를 가져갈만한 가이드가 있다면 취업 준비생이나 주니어 개발자들에게 좋을 것 같다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당시 흥미롭게 느꼈던 유려한 스크롤 효과와 3D 애니메이션을 적용한 인터랙티브 스크롤 페이지가 떠올랐고, 이를 토대로 영감을 받아 소프트웨어 장인 로드맵이라는 아이템이 떠올려 마인드맵을 그려봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_7670.PNG&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NRpnm/btrEumc1m6c/AiGTqOPMRO6eZtWHUE3F3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NRpnm/btrEumc1m6c/AiGTqOPMRO6eZtWHUE3F3k/img.png&quot; data-alt=&quot;랜덤 아이디어 투표 진행 중&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NRpnm/btrEumc1m6c/AiGTqOPMRO6eZtWHUE3F3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNRpnm%2FbtrEumc1m6c%2FAiGTqOPMRO6eZtWHUE3F3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;402&quot; height=&quot;522&quot; data-filename=&quot;IMG_7670.PNG&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;랜덤 아이디어 투표 진행 중&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;다 같이 아이디어를 나누고 또 발표하고 소규모 토론을 통해서 1시간이 넘게 토론하며 하나의 의견으로 합의하는 과정을 가졌다. 최종적으로 3가지 아이디어를 후보로 결정했는데 득표를 동일하게 가져 각자 발전 시킬만한 레퍼런스를 찾아 다음 스프린트까지 선택을 결정지어 오기로 했다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;다음 스프린트 과제로는 아이데이션을 위한 스케치, 레퍼런스 스크랩이 주어졌다. 스프린트 공지대로 아이디어를 너무 구체화하지 않음에 유의하며 레퍼런스를 목록을 꾸려 2일차 스프린트를 준비했다.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구글 스프린트 2일차 : 아이데이션 &amp;amp; 지도 그리기&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;936&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ9HZ3/btrEuQdEbMH/4dDChnqM7x4BOJ3ZSxG5F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ9HZ3/btrEuQdEbMH/4dDChnqM7x4BOJ3ZSxG5F1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ9HZ3/btrEuQdEbMH/4dDChnqM7x4BOJ3ZSxG5F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ9HZ3%2FbtrEuQdEbMH%2F4dDChnqM7x4BOJ3ZSxG5F1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;595&quot; height=&quot;359&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;936&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;둘째날에는 우리가 정한 아이디어를 하나로 결정하고, 청사진을 그려보는 시간을 가졌다. &lt;/span&gt;&lt;span&gt;우리가 만들어야 할 목적을 분명히 하고 우리가 만들어야 할 방향성의 싱크를 맞출 수 있게끔 지도를 작성했다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아이데이션은 모두 다 같이 동등하고 적극적이게 발표하고 공유하는 게 가장 중요&lt;/li&gt;
&lt;li&gt;목소리가 큰 사람이나, 마지막 언급자의 의견으로 결정되는 것은 바람직하지 못하다.&lt;/li&gt;
&lt;li&gt;그래서 실제 협업이 어려움&lt;/li&gt;
&lt;li&gt;팀원 간 변동 사항에 대한 빠른 피드백이 중요&lt;/li&gt;
&lt;li&gt;어떤 사람이 이 서비스를 찾을까? &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;페르소나&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;떠올리기&lt;/li&gt;
&lt;li&gt;무언가를 제공 &amp;rarr; 서비스 수단? &amp;rarr; 서비스 목적?(공부에 도움이 되는) + 재미!&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;이미 첫째날부터 아이디어에 대해 글과 말로써 이야기를 충분히 나누었기 때문에 사진과 이미지, 그림 등을 눈으로 확인할 수 있는 레퍼런스들이 요구됐다.&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KqIFY/btrEt2TpRYW/FDinjgjvJOoKDpJJZPQfwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KqIFY/btrEt2TpRYW/FDinjgjvJOoKDpJJZPQfwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KqIFY/btrEt2TpRYW/FDinjgjvJOoKDpJJZPQfwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKqIFY%2FbtrEt2TpRYW%2FFDinjgjvJOoKDpJJZPQfwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;774&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;942&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dB6pgM/btrEtupm3Sj/a3IABwFysS0pPbiOL4mCM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dB6pgM/btrEtupm3Sj/a3IABwFysS0pPbiOL4mCM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dB6pgM/btrEtupm3Sj/a3IABwFysS0pPbiOL4mCM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdB6pgM%2FbtrEtupm3Sj%2Fa3IABwFysS0pPbiOL4mCM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1112&quot; height=&quot;942&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;942&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp7LT6/btrEt2eQuvh/9TlYeI5iOTRT42WJUTSNb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp7LT6/btrEt2eQuvh/9TlYeI5iOTRT42WJUTSNb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp7LT6/btrEt2eQuvh/9TlYeI5iOTRT42WJUTSNb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp7LT6%2FbtrEt2eQuvh%2F9TlYeI5iOTRT42WJUTSNb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;604&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;감사하게도 6명의 팀원들 중 4명의 공감을 얻어 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;스프린트&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;의 주제는&lt;span&gt;&amp;nbsp;내가 제안했던&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&quot;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&lt;b&gt;소프트웨어 장인 로드맵&quot; &lt;/b&gt;으로 선정이 되었다! ✨ 팀원들의 추가 레퍼런스 자료들을 갈무리하고, 서비스의 궁극적인 목적은 무엇이 될지 얘기하는 시간을 가졌다. 나 혼자만 상상했던 심플한 아이디어에 여러 사람들의 의견으로 풍성해지는 과정에서 단순히 data를 뿌려주는 정적 페이지를 넘어 유익한 컨텐츠 서비스가 될 수 있겠다는 흥미가 솟아났다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;기존 아이디어에서 하마의 레퍼런스를 참조해 3D 애니메이션을 적용하고, 책 커버 이미지에 마우스를 hover 했을 때 사용자가 재미를 느낄만한 애니메이션을&amp;nbsp; 추가하기로 했다. &lt;span&gt;특히&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;후라이가 준비해 온 3D 책 레퍼런스를 보면서 어떻게 이런 걸 찾았지? 싶을만큼 정보의 질이 좋아서 구글링도 실력이라는 것을 체감했다..!&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;s&gt;구글링 능력을 전수받고 싶어요 후라이..&amp;nbsp;&lt;/s&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BBC 인터랙티브 페이지&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.bbc.com/korean/resources/idt-48d3c9a7-4063-4289-9726-611b5ea9d7b5&quot;&gt;https://www.bbc.com/korean/resources/idt-48d3c9a7-4063-4289-9726-611b5ea9d7b5&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1618&quot; data-origin-height=&quot;1582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMQNTj/btrEtI12wBj/kv1G79sIKk5ZMNbO96XNj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMQNTj/btrEtI12wBj/kv1G79sIKk5ZMNbO96XNj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMQNTj/btrEtI12wBj/kv1G79sIKk5ZMNbO96XNj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMQNTj%2FbtrEtI12wBj%2Fkv1G79sIKk5ZMNbO96XNj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1618&quot; height=&quot;1582&quot; data-origin-width=&quot;1618&quot; data-origin-height=&quot;1582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;여기서 중요한 것은 텍스트로 만들어진 결과물이 아니라 지금까지 논의를 하고 만들어오는 과정에서 각자 머리속에 쌓여진 구성과 그것들의 컨텍스트가 모두에게 공유되고 목표와 방향성이 동일해지는 과정이였다는 점이었다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;지도 그리기의 목적은 결과물을 만들어내느게 아니라 &quot;&lt;b&gt;모든 멤버의 생각의 주파수를 맞추는 과정&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;이라는 점이라며 강조하던 테오의 말이 뇌리에 꽂혔는데 실무에서 협업을 할 때 가장 중요한 것이 &lt;b&gt;팀원 간 합의된 확실한 목적&lt;/b&gt;임을 알기에 스프린트 과정의 참된 의미를 스프린트의 참된 의미를 느낄 수 있었다.  &lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구글 스프린트 3일차 : 스케치&lt;/b&gt;&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIeTGW/btrEvmXrj3A/qXSV5r8jNJkI1jYM75avg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIeTGW/btrEvmXrj3A/qXSV5r8jNJkI1jYM75avg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIeTGW/btrEvmXrj3A/qXSV5r8jNJkI1jYM75avg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIeTGW%2FbtrEvmXrj3A%2FqXSV5r8jNJkI1jYM75avg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1004&quot; height=&quot;916&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd7DPu/btrEtvIAbOW/FzbtnrJGnLjj8ZL6NE0WN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd7DPu/btrEtvIAbOW/FzbtnrJGnLjj8ZL6NE0WN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd7DPu/btrEtvIAbOW/FzbtnrJGnLjj8ZL6NE0WN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd7DPu%2FbtrEtvIAbOW%2FFzbtnrJGnLjj8ZL6NE0WN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2050&quot; height=&quot;624&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 만들어야 할 페이지들을 주제로 스케치를 해봤다. 페이지는 크게&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;대문 페이지(메인) / 책 카테고리 페이지 / 책 상세 페이지 / 프로필&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 나뉘어졌고, 각 스케치에 대해서 본인의 마음에 드는 곳에 투표를 해서 전체적인 의견 공유 시간을 가졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1174&quot; data-origin-height=&quot;868&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sS4aD/btrEulZynhW/YdVKTsYsvlpUCPINicP3B0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sS4aD/btrEulZynhW/YdVKTsYsvlpUCPINicP3B0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sS4aD/btrEulZynhW/YdVKTsYsvlpUCPINicP3B0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsS4aD%2FbtrEulZynhW%2FYdVKTsYsvlpUCPINicP3B0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1174&quot; height=&quot;868&quot; data-origin-width=&quot;1174&quot; data-origin-height=&quot;868&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bg3Ow/btrEvHG1wdB/SFtwmLWS7iqrkI3KJIZSIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bg3Ow/btrEvHG1wdB/SFtwmLWS7iqrkI3KJIZSIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bg3Ow/btrEvHG1wdB/SFtwmLWS7iqrkI3KJIZSIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBg3Ow%2FbtrEvHG1wdB%2FSFtwmLWS7iqrkI3KJIZSIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1030&quot; height=&quot;924&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;또한 짧은 시간동안 구현할 수 있는 가성비 좋은 항목들부터 페이지들을 간추리고 우리가 만들어야 할 요소들을 가치와 시간으로 만들어 보는 시간을 가졌다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;또 하나 인상 깊었던 것이 테오가 스프린트 작업 방식을 조언하면서 작업물을&lt;b&gt; &quot;스노우볼&quot;&lt;/b&gt;에 비유했는데, &lt;b&gt;항시 배포할 수 있는 형태로 구현&lt;/b&gt;해야 하는 것이 예상치 못한 변경사항에 대해 적절하게 대응할 수 있고, 전체적인 작업물의 완성도와 도메인 기능에 대한 집중도를 유지하는 데 있어 중요하다는 것을 깨달았다. &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이렇게 많은 것들을 늘어놨지만 이것을 다 만들어 보는 것이 아니라 일단 이 서비스가 가치가 있는지, 그리고 사용자로 부터 검증을 받아서 방향을 계속 바꿔보는 피봇팅을 하기 위해서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;일단 만들어서 외부로 보여줘야 합니다. 그리고 반응을 보고 계속할지 수정할지 개선책을 없을지 판단을 해야 합니다. 완성도&lt;span&gt;&amp;nbsp;&lt;/span&gt;중요하지만 다 완성하는 것이 아니라 첫째날 정했던 이 서비스의 궁극적인 목적을 이 서비스가 해결할 수 있는지 검증해볼 수 있는 최소한의 것을 만드는 것이 우리의 과제입니다. - teo&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;개발 설계하기&lt;span&gt;&amp;nbsp;&lt;/span&gt;(개념도)&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;페어프로그래밍을 하기전에 여럿이서 협업을 할 경우에는 아무리 애자일해도 다같이 미리 맞춰두면 좋은 것들이 있다. 기획서를 어떻게 하면 개발로 쪼개기 쉬운지에 대해 방법을 공유했다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3506&quot; data-origin-height=&quot;2074&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u2ona/btrEtm5T9Yo/id1lQE7g82R0cACnv62jY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u2ona/btrEtm5T9Yo/id1lQE7g82R0cACnv62jY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u2ona/btrEtm5T9Yo/id1lQE7g82R0cACnv62jY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu2ona%2FbtrEtm5T9Yo%2Fid1lQE7g82R0cACnv62jY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3506&quot; height=&quot;2074&quot; data-origin-width=&quot;3506&quot; data-origin-height=&quot;2074&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;View&lt;/b&gt;
&lt;div&gt;- 스케치로 그렸던 요소들을 페이지 / 컴포넌트 단위로 분리한다.&lt;/div&gt;
&lt;div&gt;- 이름을 미리 다같이 영어로 지어준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;BDD (&lt;span&gt;Behavior Driven Develop)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;- 페이지 별로 사용자가 일단 할 수 있는 모든 행동들을 찾는다.&lt;/div&gt;
&lt;div&gt;- 행동을 중심으로 given - when - then의 형식으로 전(조건) 후(변화) 를 작성한다.&lt;/div&gt;
&lt;div&gt;- 해당 Task를 통해서 사용자의 목적와&amp;nbsp;원하는 바를 적어 1개의 User Stroy를 만든다.&lt;/div&gt;
&lt;div&gt;- 이후 반복하며 1개의 User Stroy안에 여러개의 Task들이 포함되어 있는 구조를 만든다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;실제 UX에서는 스토리 -&amp;gt; 태스크 등으로 작업을 하는 것이나 일반적인 기획서는 그렇게 되어 있지 않기 떄문에 개발입장에서는 기획서를 이렇게 Bottom-up 방식으로 풀어가며 해석을 하며 정리하면 쉽습니다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;DDD (&lt;span&gt;Data Driven Develop)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;(사실은 없는 말)&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;- Data 스킴을 찾기 위해서 여정&lt;/div&gt;
&lt;div&gt;- View에 있는 요소중 모든 변하는 값을 찾아냅니다. (변화해야지만 Data)&lt;/div&gt;
&lt;div&gt;- 값에 이름을 붙입니다.&lt;/div&gt;
&lt;div&gt;- 영어 이름을 붙여봅니다. (변수명으로)&lt;/div&gt;
&lt;div&gt;- 구조화 하여 위계를 만들어 냅니다. (1depth)&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;이렇게 대략적으로 Task를 찾아내고 분배하는 방식에 대해 알게 되었는데 기획을 개발로 쪼개기에 유용한 구조여서 &lt;span&gt;스프린트&lt;/span&gt;를 넘어 실무에서도 도움이 될 것 같다. 실제 포스팅을 하고 있는 현재, DDD 아키텍처링 업무를 진행하면서 해당 내용을 복기했던 경험이 큰 도움이 되었다.  
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구글 스프린트 4-5일차 : 디자인 &amp;amp; 개발&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평일동안 진행한 아이데이션과 구체화된 명세들을 토대로 &lt;span&gt;각자의 역할과 담당 페이지를 나눠&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;주말 이틀동안 디자인 및 개발을 진행했다. 개발은 페어 프로그래밍 형태로 진행됐다. 게더타운과 단톡방을 통해 논의와 진행 상황을 공유했는데 밤낮 없이 새벽까지 게더타운에 남아 구현하는 팀원들을 보면서 자극을 받기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2450&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b27sLd/btrEwkro3bx/UCuQ401csC9Gl7IKNhi5LK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b27sLd/btrEwkro3bx/UCuQ401csC9Gl7IKNhi5LK/img.png&quot; data-alt=&quot;three.js live example&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b27sLd/btrEwkro3bx/UCuQ401csC9Gl7IKNhi5LK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb27sLd%2FbtrEwkro3bx%2FUCuQ401csC9Gl7IKNhi5LK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2450&quot; height=&quot;1260&quot; data-origin-width=&quot;2450&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;three.js live example&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 3D 애니메이션을 구현해보고 싶은 욕심이 있었는데, 팀원들이 이를 알고 배려해줘서 우선적으로 내게 우선권을 배정해주었다. (감사합니다 프투스.. ✨) 구현 당시 WebGL, js 기반 3D library인 three.js에 대한 관심이 엄청났기에 &lt;a href=&quot;https://jsfiddle.net/fxurzeb4/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;관련 레퍼런스&lt;/a&gt;들을 찾아 구현해보고자 했으나 러닝 커브가 높아 내가 원하는 형태의 애니메이션을 구현하기에는 2일이라는 구현 기간이 너무나도 짧았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토요일 새벽까지 레라와 함께 협업하면서 three.js를 적용해보고자 했으나.. 테오의 &lt;b&gt;&quot;스노우 볼&quot;&lt;/b&gt; 비유가 떠오르면서, 아쉽지만 선택과 집중을 위해 라이브러리를 활용해 애니메이션을 구현하기로 결정했다. 앞으로도 디자인 부분은 얼마든지 빌드 업 할 수 있는 영역이기에 팀원들도 흔쾌히 동의해주었고, 작업이 지체된 만큼 일요일 아침부터 본격적인 구현을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 JSON으로 만든 mockup data의 포맷을 맞추는 작업, React에서 사용자가 일반적인 도서 웹사이트와 차별점을 느낄 수 있도록 구현자들이 직접 읽은 책들의 추천사들을 figma로 수집해 상세 페이지에 추가했다. 이 외에도 반응형 레이아웃의 포지셔닝이나 template literal을 통한 3D image 파일 매핑과 같은 디테일적인 부분을 구현하며 작업물을 완성해갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구글 스프린트 6일차 : 배포 및 피드백&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3786&quot; data-origin-height=&quot;2786&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ImzNc/btrEt2zebHI/XIPSYflNRZGcl69A0r503K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ImzNc/btrEt2zebHI/XIPSYflNRZGcl69A0r503K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ImzNc/btrEt2zebHI/XIPSYflNRZGcl69A0r503K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FImzNc%2FbtrEt2zebHI%2FXIPSYflNRZGcl69A0r503K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3786&quot; height=&quot;2786&quot; data-origin-width=&quot;3786&quot; data-origin-height=&quot;2786&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업물을 Vercel을 통해 배포하고 테오가 오픈카톡방에 작업물을 공유하기 전 직접 테스터가 되어 전체적인 좋은 점과 아쉬운 점들을 피드백 해주고 수정해보는 시간을 가졌다. 개인 작업물로만 남기지 않고 외부에도 직접 공개하면서 많은 의견들을 받을 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;좋은 스프린트는 결과물이 아니라 짧은 주기의 개발과 함께 항상 회고를 통해서 좋았던 점과 개선할 점을 찾아 다음 스프린트에 반영해서 계속 개선해나가는 것입니다. 이렇게 진행해본 회고를 통해서 두번째, 세번째 스프린트에서는 지금 느꼈던 것들을 보강하면서 발전할 수 있었으면 좋겠습니다. - teo&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;배포 한 달이 지나고&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OyU00/btrEu8d8VWi/4Fek3jfVVZKD08dJBFEZ00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OyU00/btrEu8d8VWi/4Fek3jfVVZKD08dJBFEZ00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OyU00/btrEu8d8VWi/4Fek3jfVVZKD08dJBFEZ00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOyU00%2FbtrEu8d8VWi%2F4Fek3jfVVZKD08dJBFEZ00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;548&quot; height=&quot;419&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;1038&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LVMse/btrEuk7wKSG/PCRApkFBMJkpInMxjX8Irk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LVMse/btrEuk7wKSG/PCRApkFBMJkpInMxjX8Irk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LVMse/btrEuk7wKSG/PCRApkFBMJkpInMxjX8Irk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLVMse%2FbtrEuk7wKSG%2FPCRApkFBMJkpInMxjX8Irk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;545&quot; height=&quot;418&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;1038&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;904&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mcxSR/btrEwkdSc7R/6LbRUlLmNMYvrk9WcPFjkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mcxSR/btrEwkdSc7R/6LbRUlLmNMYvrk9WcPFjkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mcxSR/btrEwkdSc7R/6LbRUlLmNMYvrk9WcPFjkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmcxSR%2FbtrEwkdSc7R%2F6LbRUlLmNMYvrk9WcPFjkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;477&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;904&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱 배포 이후 구글 애널리틱스를 통해 MAU 및 유의미한 데이터를 확인해 볼 수 있도록 하였다. 간간히 주변에서 기능적인 피드백이나 책 정보 관련된 질문이 들어오기도 했다. 두 달 차가 지나가는 지금 활성 사용자가 적어진 만큼 추후 빌드업을 진행해보고 싶다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;에필로그&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프린트 경험은 내가 느껴왔던 개발과 협업에 대한 인식이 정말 정형화되어 있었다는 생각이 들게 해줬다. 이를 토대로 실무에도 적극적으로 의견을 취합하는 과정에 적극적으로 도입하려고 조금씩 노력해보고 있다. (특히 팀원 간 아이디어의 싱크를 맞추는 방법들이 실무에 요긴하게 쓰여지고 있다 ⚡️)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이드 프로젝트를 진행하면서 개인으로 진행하는 것보다 다른 사람들과 같이 의견을 공유하고 같은 목표를 가지고 협업한다는 것이 굉장한 동기부여가 된다는 것을 실감했다. 역시 진정한 학습은 이론보다는 실전으로 경험해보는 것이 훨씬 더 중요한 것 같다. 특히 6일동안 늦은 밤까지 주인 정신을 가지고 열심히 협력해 준 프투스교육 팀원들과 스프린트라는 좋은 경험을 선사해주고 아이데이션의 방향성을 이끌어 준 teo에게 감사한 마음이 컸다   이런 좋은 경험을 많은 사람들도 시도해봤으면 좋겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로&amp;nbsp; &lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #000000; background-color: #f6e199;&quot; href=&quot;https://github.com/FTOOOS/frontend-master-library&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Repository&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&amp;nbsp; 를 공유하며 회고를 마무리 해 본다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;구글 스프린트 7기 'FTOOS' repository&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://github.com/FTOOOS/frontend-master-library&quot;&gt;https://github.com/FTOOOS/frontend-master-library&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1654947417779&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - FTOOOS/frontend-master-library:   프론트엔드 장인의 서재  &quot; data-og-description=&quot;  프론트엔드 장인의 서재  . Contribute to FTOOOS/frontend-master-library development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/FTOOOS/frontend-master-library&quot; data-og-url=&quot;https://github.com/FTOOOS/frontend-master-library&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Lmrkb/hyOIg1a9ev/YkUJ4wknfDsGCW2OUMbX2k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/FTOOOS/frontend-master-library&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/FTOOOS/frontend-master-library&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Lmrkb/hyOIg1a9ev/YkUJ4wknfDsGCW2OUMbX2k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - FTOOOS/frontend-master-library:   프론트엔드 장인의 서재  &lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  프론트엔드 장인의 서재  . Contribute to FTOOOS/frontend-master-library development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SfcZo/btrEuQSl23Y/FkVQ0XcZ40SfpcGnFWDnCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SfcZo/btrEuQSl23Y/FkVQ0XcZ40SfpcGnFWDnCK/img.png&quot; data-alt=&quot;두둑히 쌓여가는 star !&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SfcZo/btrEuQSl23Y/FkVQ0XcZ40SfpcGnFWDnCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSfcZo%2FbtrEuQSl23Y%2FFkVQ0XcZ40SfpcGnFWDnCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;407&quot; height=&quot;357&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;두둑히 쌓여가는 star !&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Ref&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://press.stripe.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;3D 애니메이션 레퍼런스&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.bbc.com/korean/resources/idt-48d3c9a7-4063-4289-9726-611b5ea9d7b5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BBC 인터랙티브 페이지&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://threejs.org/docs/#manual/ko/introduction/Creating-a-scene&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;three.js 한글 매뉴얼&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=b3vP6wfpqWE&amp;amp;ab_channel=FEConfKorea&quot;&gt;생각보다 쉬운 webGL (feat.three.js) - 전기환&amp;nbsp;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cdnjs.com/libraries/three.js&quot;&gt;three.js : 3D 자바스크립트 라이브러리&amp;nbsp;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/PqjmF2qJd8U&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;React에서의 Three.js - Codestates 수료생 박성현&lt;/a&gt;&lt;/p&gt;</description>
      <category>Insight</category>
      <category>figjam</category>
      <category>figma</category>
      <category>three.js</category>
      <category>WebGL</category>
      <category>구글스프린트</category>
      <category>스프린트</category>
      <category>피그마</category>
      <category>협업</category>
      <category>협업프로젝트</category>
      <category>회고</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/49</guid>
      <comments>https://geniee.tistory.com/entry/%EA%B5%AC%EA%B8%80-%EC%8A%A4%ED%94%84%EB%A6%B0%ED%8A%B8-7%EA%B8%B0-FTOOS-%ED%9A%8C%EA%B3%A0#entry49comment</comments>
      <pubDate>Sat, 11 Jun 2022 01:41:30 +0900</pubDate>
    </item>
    <item>
      <title>2022 GDG Korea 이력서 멘토링 후기</title>
      <link>https://geniee.tistory.com/entry/2022-GDG-Korea-%EC%9D%B4%EB%A0%A5%EC%84%9C-%EB%A9%98%ED%86%A0%EB%A7%81-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #4a4a4a;&quot;&gt;대다수의 직장인에게 이력서란 단순히 이직을 위한 &quot;수단&quot;이 아니게 됐다. 이력서를 주기적으로 갱신하고, 커리어를 회고하는 일은 다양화된 커리어의 방향성을 정립할 수 있는 주춧돌이 된다.이를 토대로 원하는 분야의 기업에서 오퍼를 받거나 JD를 검토해보면서 현 IT 시장에서 공통적으로 요구하는 역량이 무엇인지 파악할 수도 있다. 이처럼 이력서 관리는 소프트웨어 엔지니어에게 빠질 수 없는 필수 역량(?) 중 하나가 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #4a4a4a;&quot;&gt;지난 4월 23일, GDG Korea WebTech에서 진행한 이력서 멘토링 관련 세션을 참여했다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;단순 호기심에 신청한 행사였는데 굉장히 만족스러웠기에 뒤늦게나마 후기를 적어본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2094&quot; data-origin-height=&quot;1174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9awDG/btrEns5Z4Sc/Bk8fpvNKpk5Gw9wYaLofaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9awDG/btrEns5Z4Sc/Bk8fpvNKpk5Gw9wYaLofaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9awDG/btrEns5Z4Sc/Bk8fpvNKpk5Gw9wYaLofaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9awDG%2FbtrEns5Z4Sc%2FBk8fpvNKpk5Gw9wYaLofaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2094&quot; height=&quot;1174&quot; data-origin-width=&quot;2094&quot; data-origin-height=&quot;1174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://festa.io/events/2164&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;페스타&lt;/a&gt;&lt;/b&gt;를 통해 신청했고&amp;nbsp;&lt;b&gt;개발자 이력서&lt;/b&gt; 키워드로 구글링하면 최 상단에 위치한 이력서 작성법 포스팅으로 유명한 워니님의 발표 세션이 있어 더욱 기대가 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;현업에서 일하고 있는 프론트엔드 개발자들이 [ 그때는 몰랐지만 지나고나서 알게된 것, 몰라서 못챙기는 사소한 것 ] 들에 대해서 작성하신 이력서를 바탕으로 참가자분의 매력발산 포인트를 잡아드립니다. 없는 한줄을 만들어 내는 것이 아니라, 있는 한줄이 더 매력적으로 보일 수 있도록.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;1240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bts8zS/btrEjMvnJ8o/6TRRK6DImZpezWyhEakw7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bts8zS/btrEjMvnJ8o/6TRRK6DImZpezWyhEakw7k/img.png&quot; data-alt=&quot;1교시 - 이력서 작성 팁을 공유하는 발표 세션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bts8zS/btrEjMvnJ8o/6TRRK6DImZpezWyhEakw7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbts8zS%2FbtrEjMvnJ8o%2F6TRRK6DImZpezWyhEakw7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;482&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;1240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1교시 - 이력서 작성 팁을 공유하는 발표 세션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이력서 작성 팁을 공유하는 발표 세션과 소그룹으로 나뉘어 발표자와 웹테크 오거나이저가 참가자의 이력서에 피드백을 나누는 세션 순서로 진행됐다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;웹테크 오거나이저이자 두나무, 토스페이먼츠 등 여러 기업의 실무진 분들이 도맡아 진행해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;#1교시 #발표세션&lt;/b&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;발표1. 함께일하고싶은개발자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;요약&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;채용은 기업에 나를 판매하는 일&lt;/li&gt;
&lt;li&gt;어떻게 이 조직에 기여할 수 있는지, 뭘 할 수 있는지 어필하는 과정&lt;/li&gt;
&lt;li&gt;나를 어떻게 어필할지에 대한 전략이 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나는 누구인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;나는 역량을 설명하기 전 나라는 사람을 먼저 설명할 수 있는 것이 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;더 나아가 내가 어떤 개발자인지 어필하는 것이 키 포인트.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;나는 무엇을 좋아하고 어떤 가치관을 가지고 있는가?&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;내가 생각하는 좋은 코드란 무엇인가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;내가 요즘 흥미롭게 공부하는 것은 무엇인가??&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;내가 원하는 조직은 어떤 조직인가?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나를 설명하는 핵심 키워드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구구절절 장황하게 쓰지 말고 나를 표현하는 핵심적인 키워드를 중점적으로 설명하는 것이 좋다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;저는  &lt;s&gt;유지보수와 역할, 위임을 분리를 잘하는&lt;/s&gt; 사람입니다&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;저는 한 가지에 깊게 고민하고 깨우친 내용을 기록하고, 글을 써서 공유하는 것을 잘하는 사람입니다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;저는 지식을 공유하고 신뢰하는 동료들과 후배들을 이끄는 것을 잘 하는 사람입니다.&quot;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;발표2. 10초컷당하지않는이력서작성법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;면접관이 궁금한 껀덕지가 없는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무슨 역량이 있는지 알 수 없는 경우&lt;/li&gt;
&lt;li&gt;구체적으로 어떤 일을 어떻게 해왔는지 알 수 없는 경우&lt;/li&gt;
&lt;li&gt;어떤 성과를 내왔는지 알 수 없는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 지원자가 이 회사에서 이런 기여를 해줄 수 있겠구나.. 하는 기대감을 유발해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 성능과 개선했을 때의 성능을 비교 분석하고 수치화 하기 위해 측정하는 것도 업무 능력이다.&lt;br /&gt;실제로 이정도 좋아졌어. 하는 경험까지 추가하면 굉장히 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2교시. 멘토링&lt;/b&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2교시 멘토링의 경우, 소그룹으로 나뉘어져 멘토와 이력서 참가자의 이력서에 대해 코멘트해주는 방식으로 진행되었다. 내가 세션을 신청했을 당시 첨부했던 notion 이력서와 최신 이력서의 내용이 조금 달라져 멘토님에게 양해를 구하고 최신 자료로 검토를 부탁드렸다. 감사하게 도 멘토님께서 흔쾌히 바로 화면에 공유하여 소개 구문부터 경력 사항까지 면밀히 검토해주셨다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;피드백 받은 내용에 대해서는 개인적인 사항들이 많기에 되도록 전체적인 감상에 대한 내용으로 대체하였다.&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/i&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주도적으로 일하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 회사에서 일을 할 때 resume를 변경할 목적을 가지고 임하는 것이 중요하다. (1년, 2년짜리 목표로)&amp;nbsp;자신이 나아가려는 커리어 방향성을 가지고 프로젝트와 업무를 주도적으로 가져오는 것이 좋다. 이로 인해 업무에도 주인 의식을 가지고 임할 수 있을 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 되면 이직이 굉장히 쉬워진다. &lt;s&gt;엔지니어의 장점!&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;resume 분량이 적절한가?&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필요한 정보만 있는가? (A4 1장 수준 분량)&lt;/li&gt;
&lt;li&gt;포트폴리오가 있는가?&lt;/li&gt;
&lt;li&gt;문구가 임팩트있는 수치로 잘 표현되어 있는가?&lt;/li&gt;
&lt;li&gt;내가 해왔던 이력에서 나의 역할이 명확하게 드러나는가?&lt;/li&gt;
&lt;li&gt;업무의 동기, 목표 달성에 대한 키워드가 있는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분 면접관은 면접자의 깃헙, 블로그 링크 스키밍으로 평가를 하지는 않고, 서브의 영역으로생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 resume로 판가름이 끝났고, 포스팅을 직접 들어가보진 않을 것이다.&amp;nbsp;최신 트렌드에 관심이 있구나 정도의 임팩트를 주면 충분하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여건이 된다면 나를 표현할 수 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;이력서는 2가지&lt;/b&gt;로 만들면 좋다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회사 제출용으로 쓰이는 resume&lt;/li&gt;
&lt;li&gt;나를 표현하는 자유 경험 이력 (동아리, 스터디..)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체적으로 돈이 하나도 아깝지 않은 구성과 만족도였다! 사실 이런 모 컨퍼런스 플랫폼을 통한 행사나 강의들을 접하다 보면 시간 채우기용의 불필요한 구성으로 돈이 아깝게 느껴지는 경우가 있는데, 소수 정예로 진행됐다는 점이 멘토링을 받기에 더욱 수월했던 이유같다. 이력서를&amp;nbsp; 작성하고 나서 첨삭을 받고싶다거나 내가 지원을 희망하는 회사에서 근무하는 WebTech 오거나이저들의 따끈따끈한 현업 소식과 인사이트를 얻고 싶다면 주변인에게 적극 추천하고싶은 세션이다.  &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;부록&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 내가 5년차 경력을 쌓아오면서 항상 딜레마로 겪는 부분들을 직접 멘토들에게 물어보고 피드백 받은 내용으로 후기를 마무리 해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;일반적인 2-3년차 기준으로 이직을 하지 않았다면.. 어떤 인식인지&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경력직에 대한 기대치는 절대적인 게 없다고 생각한다. 이 분이 가지고 있는 역량이 비즈니스에 도움이 될 것인가가 더 중요하다. 자신이 면접관이라면&amp;nbsp;5년차 개발자에겐 &lt;span&gt;작은 팀에서 리드를 할 수 있을 정도의 능력치를 기대할 것 같다. &lt;/span&gt;한 직장에서 오래 있었던 나름의 이유가 확실하다면 된다. 즉, 나의 비전과 목표가 더 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객관적인 역량에 대한 지표를 알기 위한 레퍼런스로 &lt;a href=&quot;https://dropbox.github.io/dbx-career-framework/ic1_software_engineer.html&quot;&gt;Dropbox Engineering Career Framework&lt;/a&gt;도 추천 받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blILWq/btrEnwz7jhA/Ecr1OlKFku6ZdUW1cK44VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blILWq/btrEnwz7jhA/Ecr1OlKFku6ZdUW1cK44VK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blILWq/btrEnwz7jhA/Ecr1OlKFku6ZdUW1cK44VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblILWq%2FbtrEnwz7jhA%2FEcr1OlKFku6ZdUW1cK44VK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1628&quot; height=&quot;370&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDeHGu/btrEntX3Ht3/sGh3NcppddjJpQfg0jORT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDeHGu/btrEntX3Ht3/sGh3NcppddjJpQfg0jORT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDeHGu/btrEntX3Ht3/sGh3NcppddjJpQfg0jORT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDeHGu%2FbtrEntX3Ht3%2FsGh3NcppddjJpQfg0jORT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1612&quot; height=&quot;396&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;그리고, 워니님에게 받은 깨알 후기 피드백&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blfNhX/btrEhYRp1r1/YZd830tXXKxkxKKLjTeSoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blfNhX/btrEhYRp1r1/YZd830tXXKxkxKKLjTeSoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blfNhX/btrEhYRp1r1/YZd830tXXKxkxKKLjTeSoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblfNhX%2FbtrEhYRp1r1%2FYZd830tXXKxkxKKLjTeSoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;938&quot; height=&quot;348&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4QF0e/btrEhXSdl5w/5kd4kQtAVk4EykBHcJ5sMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4QF0e/btrEhXSdl5w/5kd4kQtAVk4EykBHcJ5sMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4QF0e/btrEhXSdl5w/5kd4kQtAVk4EykBHcJ5sMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4QF0e%2FbtrEhXSdl5w%2F5kd4kQtAVk4EykBHcJ5sMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;302&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자들의 연예인을 만나 성덕이 된 기분이였다..  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Insight</category>
      <category>festa</category>
      <category>frontend</category>
      <category>gdg</category>
      <category>GDGKorea</category>
      <category>webtech</category>
      <category>개발자</category>
      <category>이력서멘토링</category>
      <category>이력서작성법</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/48</guid>
      <comments>https://geniee.tistory.com/entry/2022-GDG-Korea-%EC%9D%B4%EB%A0%A5%EC%84%9C-%EB%A9%98%ED%86%A0%EB%A7%81-%ED%9B%84%EA%B8%B0#entry48comment</comments>
      <pubDate>Fri, 10 Jun 2022 00:03:50 +0900</pubDate>
    </item>
    <item>
      <title>3월 회고, 코드 리뷰 스터디와 멘탈 케어의 흔적들</title>
      <link>https://geniee.tistory.com/entry/3%EC%9B%94-%ED%9A%8C%EA%B3%A0-%EC%BD%94%EB%93%9C-%EB%A6%AC%EB%B7%B0-%EC%8A%A4%ED%84%B0%EB%94%94%EC%99%80-%EB%A9%98%ED%83%88-%EC%BC%80%EC%96%B4%EC%9D%98-%ED%9D%94%EC%A0%81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어느덧 3월이 끝나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오미크론 확진으로 3월 &amp;nbsp;첫 주는 회복에만 힘쓰느라 일주일을 약에 취해 살았다.. (누가 경미한 감기 증세라 했나요.. 목에 칼춤을 추는 기분이였다..!)&amp;nbsp;그렇게 일상에 복귀한 지 보름 째.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 커밋 잔디를 심지못해 부채감을 느끼며 VanillaJS 코드 리뷰 스터디와 Next.js 프로젝트 등 계획했던 일정들이 부메랑처럼 돌아와 매우 바쁜 일상을 보내게 되었다. 맘 같아서는 일주일에 한 번씩 회고록을 작성하려 했으나..   각 잡고 포스팅을 쓸 여유가 나지 않아 개인 notion에만 조금씩 정리했던 내용들과 개인적인 멘탈이 흔들렸을 때 극복했던 방법들을 톺아보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  3월에 진행한 것들&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 출근 전 10분 TIL 저널 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. React 공식문서 정독&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. VanillaJS 클린 코드 리뷰 스터디 활동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Github, 디스코드, 개더타운 활용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- &lt;span&gt;OOP 구현 (함수형 컴포넌트 vs 클래스형 컴포넌트)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;- MV* 패턴과 flux 패턴 정리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 함수형 프로그래밍 개념 정리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;- 1급 객체와 고차함수 개념 정리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;- 코딩 컨벤션 정리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;- TDD cypress 문법 개선 항목 공유&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 격리 후유증 극복을 위한 주 3회 러닝 30분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. [코드 스피츠 ES6+ 함수와 OOP] 재수강&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. Next.js 트위터 클론코딩 프로젝트 FE 완성 (40%)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 기술 서적 읽기 : 클린 코드(100%) , You Don't Know JS(60%), 딥다이브 정독(30%), 프로그래밍은 상상이다 (30%)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. 효율적 TDD를 위한 고민, Cypress DSL 적용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. 설계 산출물을 위한 Figma 입문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. [테오의 프론트엔드] 디스코드 참여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kOs4j/btrxHw0C9Ok/gC0PsKVa8PnkbHNlq6o8G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kOs4j/btrxHw0C9Ok/gC0PsKVa8PnkbHNlq6o8G1/img.png&quot; data-alt=&quot;책을 읽고 오래 기억하기 위해 모아둔 구절들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kOs4j/btrxHw0C9Ok/gC0PsKVa8PnkbHNlq6o8G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkOs4j%2FbtrxHw0C9Ok%2FgC0PsKVa8PnkbHNlq6o8G1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;676&quot; height=&quot;676&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;책을 읽고 오래 기억하기 위해 모아둔 구절들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;/b&gt;3월에 느낀 것들&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. React 공식문서 정독&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 요즘의 추세가 hook을 사용하기 위해 function구문을 애용하는 것일 뿐 패러다임에 집착할 필요는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론은,, 적재적소에 클래스와 함수를 적용하는 것이 가장 좋다.. 특정 패러다임에 매몰되지 말자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;3. VanillaJS 클린 코드 리뷰 스터디 활동&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1~8주차동안 매 주 새로운 미니 프로젝트 일정이었으나 팀원들과 논의하던 중 시간에 치여 코드를 작성하고 있지 않나 돌아보게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인풋(지식)과 아웃풋(코딩)의 적절한 밸런스가 중요한데, 아웃풋 일정에 급급해 인풋 적용이 부족했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 유의미한 코드 리뷰와 리팩토링을 진행했는가에 대해서는 계속 의문이였고 스터디원 분들도 공감하는 부분이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;매번 30개 가량 달려있는 PR comment들을 Todo-list 하나하나를 지워가듯이 수정해나가는 게 정말 의미가 있나?&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;내 코드에서 이게 정말 필요한 수정일까? 등&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고민하는 시간이 부족하다고 느껴졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 4주차에 이른 지금, 여태 작성한 코드를 기반으로 리팩터링에 초점을 맞춰 학습하도록 일정을 변경했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&amp;nbsp;- 매 주 코드리뷰 전, 계획한 분량의 [리팩터링 2판]을 읽는다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&amp;nbsp;- 각자 읽으면서 적용해보고싶었던 부분이 뭐였는지 중간 공유&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&amp;nbsp;- 정식 세션에서 디스코드 스크린 쉐어를 통해 각자의 리팩토링한 코드를 설명 (*단 한줄도 무의미한 코드가 없게끔 한다)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 일정이 기대되기도 하고, 이로서 얻어지는 아웃풋이 굉장히 궁금하다!&amp;nbsp;  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;vanillaJS class 구조에서의 상태 관리는 새로운 인스턴스 생성보다는 재렌더링이 알맞지 않을까?&lt;br /&gt;어떻게 효율적으로 재렌더링을 구현할 수 있을까? 반복적 객체 재생성이 불가피한걸까?&lt;br /&gt;불필요한 메모리 할당을 줄이고 싶은데, 리액트처럼 부분 재렌더링 하는 방법이 어떤 것이 있을까?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cypress 테스트 코드 작성도 유지보수 생산성을 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;실제 코드만큼이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;시간을 들여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 완벽한 커버리지에 집착하면 재사용성이 떨어진다. 이 중간점을 잘 조절해봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. Next.js 트위터 클린코딩 프로젝트 진행 (40%)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 프로젝트를 진행하면서 함수형 컴포넌트를 추구하는 리액트와 vanillaJS와의 구조적 차이점에 자꾸 의문점을 가졌던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스와 함수의 차이가 궁금하다보니 모던JS, MDN, You Don't Know JS(특히 좋았다!)에서 필요한 부분을 파고들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원론적인 개념을 이해하면 모든 것이 자연스럽게 받아들여진다. 외워야 할 부분과 외우지 말아야 할 부분을 구분하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; ️&amp;zwj;♀️ VanillaJS 코드 리뷰 스터디 회고&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHDtvg/btrxLSauD34/G0sCyfTeAJ9bIRy61DmIe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHDtvg/btrxLSauD34/G0sCyfTeAJ9bIRy61DmIe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHDtvg/btrxLSauD34/G0sCyfTeAJ9bIRy61DmIe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHDtvg%2FbtrxLSauD34%2FG0sCyfTeAJ9bIRy61DmIe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1864&quot; height=&quot;696&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작성한 코드를 Pull Request하면 merge하기 전 코멘트 리뷰를 진행한다. 이 과정을 통해 매 주 새로운 부분들을 깨닫는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 질문하면서 더 좋은 방안을 떠올리기도 하고, 어떤 코드가 조금 더 &lt;b&gt;성능적으로&amp;nbsp;효율적인 코드&lt;/b&gt;인지, 조금 더 &lt;b&gt;클린&lt;/b&gt;한지, 조금 더 &lt;b&gt;유지보수가 용이&lt;/b&gt;한지 느끼게 된다. 다른 분들의 코드를 보면서 같은 주제를 기반으로 한 VanillaJS 코드여도 그 자유도에 따라 형태와 성능이 천차만별로 달라진다는 것을 알게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oKoFi/btrxHZ2lB9C/Vj6p8Sk7K4t16tqvxl8340/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oKoFi/btrxHZ2lB9C/Vj6p8Sk7K4t16tqvxl8340/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oKoFi/btrxHZ2lB9C/Vj6p8Sk7K4t16tqvxl8340/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoKoFi%2FbtrxHZ2lB9C%2FVj6p8Sk7K4t16tqvxl8340%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1646&quot; height=&quot;790&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;1262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwAkll/btrxLl4RVPd/sK8gG9h3mWyDe6C3tEzo90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwAkll/btrxLl4RVPd/sK8gG9h3mWyDe6C3tEzo90/img.png&quot; data-alt=&quot;cypress 테스트 코드도 실제 코드만큼이나 시간을 들여야 한다. Commands, 모듈화를 통해 중복 코드를 줄여보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwAkll/btrxLl4RVPd/sK8gG9h3mWyDe6C3tEzo90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwAkll%2FbtrxLl4RVPd%2FsK8gG9h3mWyDe6C3tEzo90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1640&quot; height=&quot;1262&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;1262&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;cypress 테스트 코드도 실제 코드만큼이나 시간을 들여야 한다. Commands, 모듈화를 통해 중복 코드를 줄여보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/loAkC/btrxGcuzqAI/V4EFI5NPKoJkL1KwY3twpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/loAkC/btrxGcuzqAI/V4EFI5NPKoJkL1KwY3twpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/loAkC/btrxGcuzqAI/V4EFI5NPKoJkL1KwY3twpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FloAkC%2FbtrxGcuzqAI%2FV4EFI5NPKoJkL1KwY3twpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1110&quot; height=&quot;920&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;318&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m3Dvh/btrxHxFcsMx/iPrClkonIFkocB0MUymodk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m3Dvh/btrxHxFcsMx/iPrClkonIFkocB0MUymodk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m3Dvh/btrxHxFcsMx/iPrClkonIFkocB0MUymodk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm3Dvh%2FbtrxHxFcsMx%2FiPrClkonIFkocB0MUymodk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1720&quot; height=&quot;318&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;318&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰어님으로부터 변수명이 명시적이고 코드가 읽기 편하다는 칭찬을 들었는데, 매 주 미션을 진행하면서 새로운 패러다임을 적용하는 데 수동적으로 했기 때문에 읽기 좋은 것이 아닐까 하는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1644&quot; data-origin-height=&quot;1162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvD9Ba/btrxILCX8xc/y3TB9rAk5zRkCnlk34RafK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvD9Ba/btrxILCX8xc/y3TB9rAk5zRkCnlk34RafK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvD9Ba/btrxILCX8xc/y3TB9rAk5zRkCnlk34RafK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvD9Ba%2FbtrxILCX8xc%2Fy3TB9rAk5zRkCnlk34RafK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1644&quot; height=&quot;1162&quot; data-origin-width=&quot;1644&quot; data-origin-height=&quot;1162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지적해주신 대로 일주일 내내 &lt;b&gt;MV* 패턴과 도메인, UI 분리&lt;/b&gt;에 대해 고민했지만 실제 코드에 반영하기가 여간 쉽지 않았다. 그게 오롯이 코드에 나타났나보다   세션을 통해 서로의 구조화 과정을 설명해보면서 내가 발전하지 않는 기존 코드 구조에 고여있었던 것은 아닌지 생각해보게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복적으로 instance를 생성해야 하는 객체는 클래스로 생성하고, 나머지는 함수로 바꾸는 리팩토링을 진행하려 했으나 OOP 개념이 부족한 탓일까.. 구현 전 설계 단계에서 도메인 영역과 UI 영역을 완벽하게 분리하고 MV*를 고려한 디렉토리 구조를 짜는 것이 너무 어렵다. 어떤 이유일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;주 1회 세션을 진행하며 느낀 점&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모던 JS에서의 클래스는 함수의 method.prototype.func 형태를 간단하게 나타낸것일 뿐 동일하다. 클래스는 이를 간단하게 나타낸 구조형태라고 생각.. 하지만 constructor나 불필요한 메서드를 모두 적어줘야하는 단점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스형 컴포넌트를 작성하면 extends를 통한 부모 객체 메소드 접근이 매우 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 요즘의 추세가 hook을 사용하기 위해 function구문을 애용하는 것일 뿐 패러다임에 집착할 필요는 없다.결론은, 적재적소에 클래스와 함수를 적용하는 것이 가장 좋다! 특정 패러다임에 매몰되지 말자. (개인적으로는 절차지향적 언어인 JS에서 클래스를 사용하는 건 다른 클래스 지향적 언어들을 쓰던 사람들의 마지막 집착?이 아닐까..싶었다ㅎㅎ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현은 항상 기능 구현에 초점을 맞춰 시작한다. 모듈화는 리팩토링 시 고려한다. 처음부터 완벽한 코드는 없다. TDD를 활용해 점진적인 개선에 집중하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;방향성 정립&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클린코드의 목적은 결국 유지보수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인이 복잡한 미션은 View(그리는 부분)와 Domain(연산하는 부분) 의 변화율이 다르기 때문에 정확한 구분이 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 계속 틀리고, 두려워하는 부분에 집중하고 익숙해지자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하루종일 모든 시간을 할애하지 말고 시간을 정해서 집중적으로 몰입하자. 코딩도 공부도 데드라인을 정해 하는 연습&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함께 자라기 책에 나온 그레이 존(Grey-zone)&lt;/b&gt;을 항상 생각하자. 알 듯 말듯한 개념을 파고들어 직접 활용해보는 경험은 기억에 오래 남는다. 개발 지식을 쌓는 일은 쉽게 느껴져선 안된다. 내 견문에서 조금씩 어려운 부분들을 적용하고 개념을 확장시켜나가야 의미있게 점진적으로 발전할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  4월에 해보고싶은 것들&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 트위터 클론코딩 프로젝트 BE 파트 완성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템에 대한 이해와 Storybook 입문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;functional CSS의 이해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 스프린트 협업 진행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩터링-2판, You Don't Know JS, 딥다이브, 프로그래밍은 상상이다 완독&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React boilerplate 만들기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 Cypress로 구현했던 프로젝트 Jest 적용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React-query 리팩토링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;♻️ 인사이드 아웃 방식 학습법&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가끔 하루종일 책상에 앉아 있었는데도 온전히 집중이 안되고 돌이켜 생각해보면 어느 하나 몰입한 순간이 없는 날이 있다   공부를 진행하면서 때때로 지금 양질의 공부를 하고 있는가? 의문이 들고는 한다. 그 전에는 기능 구현이 기대되고 재밌었는데, 갑자기 부담감으로 크게 다가온다던가.. 도메인과 UI, MV* 패턴.. 무언가 정답이 있을것만 같은 이 형식을 자꾸 완벽하게 이해하려고 하다 보니까 내가 구현해온 것이 오답이라는 생각에 자괴감이 들었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이번 달은 코드를 짜면서 나름 클린 코드 인사이트를 적용하고, 가독성에 신경을 많이 썼기에 자신감이 있었다. 다른 분들 코드를 읽으면서 느낀 것은 그저 기본에 충실할 것. 코드는 각자 나름의 스타일이 있고 정답은 없기 때문에 흔들리지 않고 나만의 페이스로 가야 한다는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;...아웃사이드 인 방식으로 학습하지 말아야 합니다. 이는 주변에서 TDD가 좋다, OOP가 좋다, 디자인 패턴 알아야 한다, 누구 누구는 스터디를 한다더라하면서 남들에 의해 공부를 하게 되는 것을 말합니다. 이것은 자칫하면 &lt;b&gt;번아웃으로 가는 지름길&lt;/b&gt;이 될 수 있습니다. 왜냐하면, 현재 자기 자신보다 잘하는 사람들과 비교하게 되어 금방 지칠 수 있기 때문이죠. &lt;br /&gt;&lt;br /&gt;따라서, 반란군 기질을 가짐으로써 남들의 의견을 &lt;b&gt;어느 정도 무시&lt;/b&gt;할 줄 알아야 합니다. 즉, &lt;b&gt;본인만의 기준을 세우고 묵묵하게 학습을 하라는 것&lt;/b&gt;이죠. 그리고 이것을 &lt;b&gt;인사이드 아웃 방식&lt;/b&gt;이라고 합니다. 인사이드 아웃 방식을 잘하기 위해서는 &lt;b&gt;개인 회고나 학습 로그를 작성&lt;/b&gt;한 뒤, &lt;b&gt;한 가지에 일에 집중하는 습관&lt;/b&gt;을 만들어서 &lt;b&gt;작은 성공의 맛&lt;/b&gt;을 보아야 합니다. 또한, 한 번에 여러 가지를 하는 것이 아니라 &lt;b&gt;한 가지 일에 집중을 하는 것이 중요&lt;/b&gt;합니다.&lt;br /&gt;&lt;br /&gt;- 우아한 테크코스 [포비]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;아티클에서 얻은 멘탈 솔루션&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제 개발 쪽에서 일하시는 분들 중 **&amp;lsquo;임포스터 신드롬(imposter syndrome)&amp;rsquo;**이라는 가면 증후군(스스로를 과소평가하는 경향)이 있는데, 저도 초반에 많이 겪었던 부분이에요. 특히 엔지니어 직군 중에서도 여성분들이 더 많이 겪는다고 하더라고요. 지속적으로 성장하기 위해서 마인드 컨트롤이 정말 중요하다고 생각합니다.&lt;br /&gt;&lt;br /&gt;- 원티드+ 아티클 중&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 개인적으로 조금 필요 이상으로 나에게 혹독한 면이 있다. 세바시 강연에서 '임포스터 증후군'이라는 가면 증후군을 알게 된 적이 있다. 증상이 나와 꽤나 비슷해서 관심있게 강연을 들었는데, 이러한 가면 증후군을 극복하기 위해선 소속감을 되찾기,&amp;nbsp;&lt;u&gt;자신의 성취를 시각적으로 정리하기(포스팅)&lt;/u&gt;, 목표를 위해 끝없이 도전하고 노력하기 등이 해결법으로 조언된다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 겸손하되 당당하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;비교 대상을 &amp;lsquo;나&amp;rsquo;에 둘 것.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;공부를 하면서 겸손함과 자만함 두 사이에서 균형을 맞추는 게 너무 어렵다고 생각한다. 스스로 누구와 비교하는가에 따라 엄청 자신감이 생기기도 하고, 떨어지기도 한다. &lt;b&gt;특히 개발 쪽은 실력/나이/연차에 비례하지 않기 때문에, 주위의 영향을 받기 쉽다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나보다 좋은 실력을 가진 분을 볼 때는 &amp;lsquo;좌절하지 말고 그냥&amp;nbsp;&lt;b&gt;저분처럼 되어야겠다&lt;/b&gt;&amp;rsquo;고 생각하자. 다른 사람으로 인해 내가 스트레스 받으려 하기보다는 어떤 점을 배우고,&amp;nbsp;&lt;b&gt;공유해 줄 수 있는지&lt;/b&gt;&lt;span&gt;를 생각하자. 이 둘 사이에 균형을 잘 맞추면서 나의 실력을 쌓는 방향으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;의식적으로 마인드 셋을 정립해 보는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국, 스스로의 기준을 세워서 남들과 비교하지 않고 꾸준히 자기가 할 일을 지속하는 사람이 프로그래밍 뿐만 아니라 인생을 살아가는 데 있어서 좋은 태도라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 어제 FE 단톡방에서 받은 구문 중 기억에 남는 구문을 적으며 포스팅을 마무리해본다 ✍  4월도 화이팅..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;작성한 결과물은 어떠한 방식으로는 꼭 외부에 주위에 공유를 하세요. 남들에게 보여주겠다는 생각으로 하셔야 퀄리티를 적당히 타협하지 않는 습관이 만들어집니다!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- teo&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Insight</category>
      <category>fontend</category>
      <category>JavaScript</category>
      <category>MV*패턴</category>
      <category>VanillaJS</category>
      <category>자바스크립트</category>
      <category>코드리뷰스터디</category>
      <category>프론트엔드</category>
      <category>함수형프로그래밍</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/46</guid>
      <comments>https://geniee.tistory.com/entry/3%EC%9B%94-%ED%9A%8C%EA%B3%A0-%EC%BD%94%EB%93%9C-%EB%A6%AC%EB%B7%B0-%EC%8A%A4%ED%84%B0%EB%94%94%EC%99%80-%EB%A9%98%ED%83%88-%EC%BC%80%EC%96%B4%EC%9D%98-%ED%9D%94%EC%A0%81#entry46comment</comments>
      <pubDate>Mon, 28 Mar 2022 20:50:24 +0900</pubDate>
    </item>
    <item>
      <title>React #4. Lifecycle Hook vs useEffect</title>
      <link>https://geniee.tistory.com/entry/React-4-Lifecycle-Hook-vs-useEffect</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNREA4/btrvUBJB1Av/KvWd817d9tUEQwl44qvXdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNREA4/btrvUBJB1Av/KvWd817d9tUEQwl44qvXdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNREA4/btrvUBJB1Av/KvWd817d9tUEQwl44qvXdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNREA4%2FbtrvUBJB1Av%2FKvWd817d9tUEQwl44qvXdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;671&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;React의 Lifecycle이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 컴포넌트 기반으로 설계된 라이브러리이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에서 우리가 만드는 컴포넌트는 React에서 각각의 컴포넌트는 생명주기(Lifecycle)를 가진다. 즉, 컴포넌트도 인생이 있다는 것이다. 컴포넌트의 수명은 보통 페이지에서 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝이 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lifecycle은 크게 세 가지 유형으로 나눌 수 있는데,&amp;nbsp;특히 업데이트가 되는 시점에 props, state를 통한 상태 관리가 필요하므로 주목하길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;생성(mount)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM이 생성되고 웹 브라우저 상에서 나타날 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;업데이트(update)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props가 바뀔 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state가 바뀔 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트가 리렌더링 될 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this.forceUpdate로 강제 렌더링을 트리거할 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;제거(unmount)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM에서 제거될 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Lifecycle Hook&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 컴포넌트의 Lifecycle 중간중간 Hook을 걸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 Lifecycle Hook이라고 하는데, 사전적 의미 그대로 컴포넌트 수명 안에서 갈고리를 걸 수 있다는 뜻이다. 우리는 Hook를 통해 Lifecycle 특정 시점에 코드를 동작시키게끔 제어할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 설명한 Hook들은 원래 class로 만든 컴포넌트에서만 사용이 가능했다.&lt;/p&gt;
&lt;pre id=&quot;code_1647233668208&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Detail2 extends React.Component {
  componentDidMount(){
    //Detail2 컴포넌트가 Mount 되고나서 실행할 코드
  }
  componentWillUnmount(){
    //Detail2 컴포넌트가 Unmount 되기전에 실행할 코드
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class 컴포넌트의 가장 유용한 Hook 두개는 아래와 같다. (이러한 메서드들은 &quot;생명주기 메서드&quot;라고 불린다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. componentDidMount() : 컴포넌트 첫 등장 후 실행할 코드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. componentWillUnmount() : 다른페이지로 넘어간다든지 등의 사유로 컴포넌트가 사라지기 전 실행할 코드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;componentDidMount()&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드는 컴포넌트 출력물이 DOM에 렌더링 된 후에 실행되므로 이 장소가 타이머를 설정하기에 좋은 장소이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647234415750&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; componentDidMount() {
    this.timerID = setInterval(
      () =&amp;gt; this.tick(),
      1000
    );
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 언마운트 될 때는 생성된 타이머를 삭제해주는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647234649593&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;componentWillUnmount() {
    clearInterval(this.timerID);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;function 컴포넌트에서 사용하는 useEffect HOOK&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 리액트개발에선 짧고 더 간편한 useEffect를 많이 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useEffect Hook은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;function &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 안에서 사용된다. (return 구문 나오기 전까지)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React state와 생명주기 기능(lifecycle features)을 &amp;ldquo;연동(hook into)&amp;ldquo;할 수 있게 해주는 함수이며 class 안에서는 동작하지 않음에 주의하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 미리 페이지 상단에서 useEffect를 import&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. useEffect() 를 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. useEffect() 안에 콜백함수를 삽입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 콜백함수 안에는&lt;span&gt; &lt;/span&gt;&lt;b&gt;컴포넌트가 첫 등장하고나서 실행하고싶은 코드&lt;/b&gt;를 집어 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;useEffect() 코드의 실행조건&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컴포넌트가 첫 등장해서 로딩이 끝난 후에 (전문용어로 mount 끝났을 때)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컴포넌트가 재렌더링 되고난 후 때 (전문용어로 update 되고난 후에)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 로드 시나 업데이트 시 뭔가 코드실행하고 싶은게 있으면 useEffect 함수 안에 적으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컴포넌트가 사라질 때 코드를 실행하고 싶으면&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useEffect() 안에는 return이라는걸 넣을 수 있다. &lt;b&gt;여기 넣은 함수는 컴포넌트가 사라질 때 실행된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;b&gt;여러개를 사용하고 싶다면&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useEffect는 여러개 사용 가능하며 적은 순서대로 순차적으로 실행이 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 개발시 활용하시면 되고 그럼 이제 숙제나 해보도록 합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;함수에서 클래스로 변환하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯 단계로&lt;span&gt;&amp;nbsp;&lt;/span&gt;Clock과 같은 함수 컴포넌트를 클래스로 변환할 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React.Component를 확장하는 동일한 이름의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes&quot;&gt;ES6 class&lt;/a&gt;를 생성&lt;/li&gt;
&lt;li&gt;render()라고 불리는 빈 메서드를 추가&lt;/li&gt;
&lt;li&gt;함수의 내용을&lt;span&gt;&amp;nbsp;&lt;/span&gt;render()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드 안으로 이동&lt;/li&gt;
&lt;li&gt;render()&lt;span&gt;&amp;nbsp;&lt;/span&gt;내용 안에 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;props를&lt;span&gt;&amp;nbsp;&lt;/span&gt;this.props로 변경&lt;/li&gt;
&lt;li&gt;남아있는 빈 함수 선언을 삭제&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1647232894821&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Clock extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
        &amp;lt;h2&amp;gt;It is {this.props.date.toLocaleTimeString()}.&amp;lt;/h2&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clock은 이제 함수가 아닌 클래스로 정의된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;render&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드는 업데이트가 발생할 때마다 호출되지만, 같은 DOM 노드로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Clock /&amp;gt;을 렌더링하는 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;Clock&lt;span&gt;&amp;nbsp;&lt;/span&gt;클래스의 단일 인스턴스만 사용된다. 이것은 로컬 state와 생명주기 메서드와 같은 부가적인 기능을 사용할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 컴포넌트는&amp;nbsp;this를 가질 수 없기 때문에&amp;nbsp;this.state 를 할당하거나 읽을 수 없음&lt;/li&gt;
&lt;li&gt;Hook은 state 그 자체가 아니라,&amp;nbsp;상태 관련 로직을 재사용하는 방법&lt;/li&gt;
&lt;li&gt;Hook은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;함수&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 &amp;ldquo;연동(hook into)&amp;ldquo;할 수 있게 해주는 함수. Hook은 class 안에서는 동작하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 점차 리액트가 함수형 컴포넌트를 추구하는 느낌이다. VanillaJS에서도 함수형에 익숙해져있으니 클래스형도 경험해보도록 노력해야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Ref&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/state-and-lifecycle.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN 공식문서 - 5.State and Lifecycle&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>frontend</category>
      <category>hook이란</category>
      <category>lifecyclehook</category>
      <category>lifecycle이란</category>
      <category>React</category>
      <category>react생명주기</category>
      <category>useEffect</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <category>프론트엔드</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/45</guid>
      <comments>https://geniee.tistory.com/entry/React-4-Lifecycle-Hook-vs-useEffect#entry45comment</comments>
      <pubDate>Mon, 14 Mar 2022 14:22:03 +0900</pubDate>
    </item>
    <item>
      <title>ES6+ 함수와 자바스크립트 OOP의 원리</title>
      <link>https://geniee.tistory.com/entry/ES6-%ED%95%A8%EC%88%98%EC%99%80-OOP</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;코드스피츠 강의를 듣고 복습하기 위해 포스팅을 정리해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;사실 자바스크립트 엔진과 OOP는 다소 궁합이 안 맞는다.&amp;nbsp;그래서 개발자가 더욱 신경을 써야 하는 영역이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;객체 지향적인 설계는 프로젝트 확장성에 큰 기여를 하기 때문에 초반 설계에 많은 시간을 들여야 하는 고된 작업이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;코드 스피츠 수업은 두번째 수강인데&amp;nbsp;기초적인 개념을 넘어서 실무에 적용할 수 있을만한 견문을 넓힐 수 있는 좋은 강의였다.&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;1회차&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sub routine flow는 상대주의적 관점을 가진다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 플로우, 서브루틴 중 누구를 기준으로 보냐에 따라 달라진다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 플로우는 서브루틴이 시작하고 돌아와야 할 point 위치를 가진다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브루틴이 중첩될수록 중첩된 서브루틴들의 point를 메모리에 모두 keep 한다 =&lt;span&gt;&amp;nbsp;&lt;/span&gt;call stack&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LIFO 구조이기 때문에 stack memory를 사용하여 call stack이라 부르는 것&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ES6+에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수가 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;루틴이 흐른다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스의 메소드에 정의하기 때문에 this(function)의 의미가 없다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;value vs reference&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;value에 의한 할당은 복사본이기 때문에 의존성이 떨어진다. 즉, 사이드 이펙트가 없다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;state safe&lt;span&gt;&amp;nbsp;&lt;/span&gt;!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브루틴에서 return하는게 ref 값이면 메인 플로우 안에있는 원본 데이터를 변경시킬 가능성이 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 되도록 서브루틴의 리턴값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;readonly로 반환하거나&lt;span&gt;&amp;nbsp;&lt;/span&gt;새 객체로 만들어 반환한다&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// ref 값 참조로 원본 데이터 변경시키는 예제
const routine = ref =&amp;gt; ['a', 'b'].reduce((p,c)=&amp;gt;{
	delete p[c];
	return p; // a,b를 제거하여 return
}, ref);
const ref = {a:3, b:4, c:5, d:6};
const a = routine(ref);
ref === a; // true

// 원본을 유지하기 위해 readonly로 변경! state safe! (side effect 제거)
const routine = ({a, b, ...rest}) =&amp;gt; rest; // destructuring
const ref = {a:3, b:4, c:5, d:6};
const a = routine(ref);
ref !== a // true
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// ref 값 참조로 원본 데이터 변경시키는 예제
const routine = ref =&amp;gt; {
	const local = ref;
	local.e = 7;
	return local;
};
const ref = {a:3, b:4, c:5, d:6};
const a = routine(ref);
ref === a; // true

// 원본을 유지하기 위해 new object로 변경! state safe! (side effect 제거)
const routine = ref =&amp;gt; ({...ref, e:7}); // 순서 중요
const ref = {a:3, b:4, c:5, d:6};
const a = routine(ref);
ref !== a // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;래리 콘스탄틴 : Structured Design (구조적 설계)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  아래로 갈수록 좋은 설계 구조&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;낮은 결합도(coupling)&lt;span&gt;&amp;nbsp;&lt;/span&gt;높은 응집도(Cohesion)&lt;span&gt;&amp;nbsp;&lt;/span&gt;를 추구해야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결합도와 응집도는 대체로 정비례하므로 더욱 어렵다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 프로그래밍 설계 시 그 둘의 합치 최상을 구현해야한다 &amp;rarr; 이것이 전문가의 영역과 역할&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;결합도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;content(-)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;common(-)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;external(-)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;control(-)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;stamp(-)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;data(+)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;응집도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;coinciental(-)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logical(/)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;temporal(/)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;procedural(/)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;communicational(/)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sequential(/)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;functional(+)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Coupling (for 낮은 결합도)&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 1. Content 강결합은 안좋다(-)
// A클래스 속성v가 변경되면 즉시 B클래스가 깨짐
const A = class{
	constructor(v) {
		this.v = v;
	}
};
const B = class{
	constructor(a){
		this.v = a.v;
	}
};
const b = new B(new A(3));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 2. Common 강결합도 안좋다(-)
// Common클래스 변경 시 즉시 A,B 클래스가 깨짐
const Common = class{ // 전역 객체
	constructor(v){
	this.v = v;
	}
};
const A = class{
	constructor(c){
		this.v = c.v;
	}
};
const B = class{
	constructor(c){
		this.v = c.v;
	}
};
const a = new A(new Common(3));
const b = new B(new Common(5));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 3. External 강결합은 그나마 낫다(-) 실무에서 불가피하기때문에 극복의 영역이다..
// A, B클래스는 외부의 정의에 의존함. member의 json 구조가 변경되면 깨
const A = class{
	constructor(member){this.v = member.name;}
};
const B = class{
	constructor(member){this.v = member.age;}
}
fetch('/member').then(res=&amp;gt;res.json()).then(member =&amp;gt; {
	const a = new A(member);
	const b = new B(member);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 4. Control 강결합은 코드를 고쳐야 한다(-) **(factory pattern)**
// A 클래스 내부의 변화는 B클래스의 오작동을 유발
const A = class{
	process(flag, v){
		switch(flag){
		case 1:return this.run1(v);
		case 2:return this.run2(v);
		case 3:return this.run3(v);
		}
	}
};
const B = class{
	constructor(a){
		this.a = a;
	}
	noop(){this.a.process(1);}
	echo(data){
		this.a.process(2, data);
	}
};
const b = new B(new A());
b.noop();
b.echo();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 5. Stamp 강결합 or 유사약결합(-)
// A와 B는 ref(count)로 통신함. ref에 의한 모든 문제가 발생할 수 있음
// 되도록 필요한 값만 넘겨야 한다
const A = class{
	add(data){
		data.count++;
	}
};
const B = class{
	constructor(counter){
		this.counter = counter;
		this.data = {a:1, count:0};
	}
	count(){
		this.counter.add(this.data);
		}
};
const b = new B(5);
b.count();
b.count();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 6. Data 약결합은 좋다(+)
// A와 B는 value로 통신함. 모든 결합문제에서는 자유로워짐
const A = class{
	add(count){
		return count + 1;
	}
};
const B = class{
	constructor(counter){
		this.counter = counter;
		this.data = {a:1, count:0};
	}
	count(){
		// 참조 형태를 value(값)으로 변경하면 결합도를 낮출 수 있다!	
		this.data.count = 
			this.counter.add(this.data.count);
	}
};
const b = new B(5);
b.count();
b.count();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Cohesion (for 높은 응집도)&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;// 1. Coincidental(-)
// 아무런 관계가 없음. 다양한 이유로 수정됨
const Util = class{
	static isConnect(){}
	static log(){}
	static isLogin(){}
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;// 2. Logical(/)
// 사람이 인지할 수 있는 논리적 집합. 언제나 일부만 사용됨
const Math = class{
	static sin(r){}
	static cos(r){}
	static random(){}
	static sqrt(v){}
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 3. Temporal(/) - 시간의 순서
// 시점을 기준으로 관계없는 로직을 묶음. 관계가 아니라 코드의 순서가 실행을 결정
// 역할에 맞는 함수에게 위임해야 함
const App = class{
	init(){
		this.db.init();
		this.net.init();
		this.asset.init();
		this.ui.start();
	}
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 4. Procedural(/)
// 외부에 반복되는 흐름을 대체하는 경우. 순서 정책 변화에 대응 불가
const Account = class{
	login(){
		p = this.ptoken();
		s = this.stoken(p);
		if(!s) this.newLogin();
		else this.auth(s);
	}
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;// 5. Communicational(/)
// 하나의 구조에 대해 다양한 작업이 모여있음. 권한과 역할들
const Array = class{
	push(v){}
	pop(){}
	shift(){}
	unshift(v){}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 6. Sequential(/)
// 실행순서가 밀접하게 관계되며 같은 자료를 공유하거나 출력결과가 연계됨
const Account = class{
	ptoken(){
		return this.pk || (this.pk = IO.cookie.get(&quot;ptoken&quot;));
	}
	stoken(){
		if(this.sk) return this.sk;
		if(this.pk){
		const sk = Net.getSesstionFromPtoken(this.pk);
		sk.then(v =&amp;gt; this.sk);
		}
	}
	auth(){
		if(this.isLogin) return;
		Net.auth(this.sk).then(v =&amp;gt; this.isLogin)
	}
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;// 7. Functional(+)  **&amp;mdash;&amp;gt; 우리의 `달성 목표`!**
// **역할모델에 충실하게 단일한 기능이 의존성 없이 생성된 경우**
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;2회차&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Spread Ref&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조 관계는 계속 전파되므로 상호 참조가 계속될수록 어디서 오염되는지 파악하기 어려워진다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Sub Routine Chain&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call stack&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 서브루틴의 메모리는 데이터를 return하지 않고 keep 하고 있다 (execution context)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tail Recursion (꼬리물기 최적화)  &lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;return point&lt;span&gt;&amp;nbsp;&lt;/span&gt;아래에서는 메모리가 필요없어지므로 우리는 서브루틴을 최적화할 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 더 이상 call stack 이 없어지게 된다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 효율적인 재귀 함수 구현 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 함수의&lt;span&gt;&amp;nbsp;&lt;/span&gt;return point를 바꿔주는 것은&lt;span&gt;&amp;nbsp;&lt;/span&gt;언어 수준으로만 구현할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어문은 제어문을 통해서 Stack Clear 기능(ex. for문)&lt;/li&gt;
&lt;li&gt;Safari 지원 (call stack 무한대 가능) / Chrome, Edge 미지원&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;const sum = v =&amp;gt; v + (v &amp;gt; 1 ? sum(v -1) : 0);
sum(3);

sum(v:3)
return 3 + sum(2)

sum(v:2)
return 2 :+ sum(1)

sum(v:1)
return 1+0모든 연산자는 스택 메모리를 유발하여 꼬리물기 최적화를 방해한다.

// 해당 재귀함수는 꼬리물기 최적화를 할 수 없다
// return point로 돌아와서 값을 더해주고 return해야 하기때문
// return과 함수 call만 남아야 tail recursion 가능
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// JS에서 stack 메모리를 쓰지 않아 꼬리물기 최적화를 지원해주는 함수
// : 삼항 연산자,&amp;nbsp; OR 연산자, AND 연산자
// 즉, tail recursion을 위해 연산을 인자로 넘긴다!
const sum = (v, prev = 0) =&amp;gt; {
	prev += v;
	return (v &amp;gt; 1 ? sum(v-1, prev) : prev);
};
sum();

sum(v:3, prev:0)
return sum(2,3)

sum(v:2, prev:3)
return sum(1,5)

sum(v:1, prev:5)
return 6
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tail Recursion To Loop&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼬리물기 최적화만 잘 짜놓으면, 재귀함수는 기계적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;루프로 무조건 바꿀 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼬리물기 최적화가 불가능한 언어의 경우, 굉장히 큰 재귀함수가 stack overflow로 죽어버리니까 우리는 기계적으로 루프문으로 바꿀 줄 알아야한다&lt;/p&gt;
&lt;pre class=&quot;q&quot;&gt;&lt;code&gt;// before(tail recursion)
const sum = (v, prev = 0) =&amp;gt; {
	prev += v;
	return (v &amp;gt; 1 ? sum(v-1, prev) : prev);
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// to loop!
const sum = (v) =&amp;gt; {
	let prev = 0;
	while(v&amp;gt;1){
		prev += v;
		v--;
	}
	return prev;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Closure  
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static State : 루틴(함수)를 정적인 문으로 만드는 언어들의 특징&lt;/li&gt;
&lt;li&gt;Runtime State : 런타임 실행 중간에 루틴(함수) 생성Global &amp;gt; Main Flow &amp;gt; Routine
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;루틴을 만들면 내부 지역변수는 어디서 만들어진건지 같이 기록하는데 이것이&lt;span&gt;&amp;nbsp;&lt;/span&gt;scope&lt;/li&gt;
&lt;li&gt;내가 어떤&lt;span&gt;&amp;nbsp;&lt;/span&gt;flow&lt;span&gt;&amp;nbsp;&lt;/span&gt;상에서 만들어진건지&lt;span&gt;&amp;nbsp;&lt;/span&gt;루틴이 알고있다&lt;/li&gt;
&lt;li&gt;노란 박스에는 없는데 바깥에 있고 루틴이 인식하는 변수는 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;자유변수&lt;/li&gt;
&lt;li&gt;루틴에서 접근하는 바깥 스코프의 변수는 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;free variables(자유변수)&lt;/li&gt;
&lt;li&gt;루틴이 물고있기 때문에 자유변수는 수정이&lt;span&gt;&amp;nbsp;&lt;/span&gt;불가능하다&lt;/li&gt;
&lt;li&gt;루틴 안에서 자유변수를 다뤄서 자유변수가 변하지 못하게끔 갇히게 된다.&lt;/li&gt;
&lt;li&gt;Free variables가&lt;span&gt;&amp;nbsp;&lt;/span&gt;close됐다 &amp;mdash;&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;closure&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ltlg8/btrt7r8DDae/efWQvg1RotarmYalOv3I5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ltlg8/btrt7r8DDae/efWQvg1RotarmYalOv3I5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ltlg8/btrt7r8DDae/efWQvg1RotarmYalOv3I5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fltlg8%2Fbtrt7r8DDae%2FefWQvg1RotarmYalOv3I5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;542&quot; height=&quot;473&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1117&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;rarr; 오직&lt;span&gt;&amp;nbsp;&lt;/span&gt;런타임&lt;span&gt;&amp;nbsp;&lt;/span&gt;중에&lt;span&gt;&amp;nbsp;&lt;/span&gt;루틴을 만들 수 있는 언어에서만 발생한다&lt;/li&gt;
&lt;li&gt;Nested Closure(중첩된 클로저)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// closure chain
window.a = 3;
if(a == 3){
	const b = 5;
	const f1 = v =&amp;gt; {
		const c = 7;
		if(a + b &amp;gt; c) {
			return p =&amp;gt; v + p + a + b + c;
		} else {
			return p =&amp;gt; v + p + a + b;
		}
	};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Shadowing
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상위 변수명과 현재 루틴&lt;span&gt;&amp;nbsp;&lt;/span&gt;변수명이 겹치면&lt;span&gt;&amp;nbsp;&lt;/span&gt;가장&lt;span&gt;&amp;nbsp;&lt;/span&gt;가까운 변수를 closure로 사용 =&lt;span&gt;&amp;nbsp;&lt;/span&gt;shadowing&lt;/li&gt;
&lt;li&gt;중첩된 클로저에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;서브 루틴으로부터&lt;span&gt;&amp;nbsp;&lt;/span&gt;자유 변수를&lt;span&gt;&amp;nbsp;&lt;/span&gt;보호하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유일한&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;방법&lt;/li&gt;
&lt;li&gt;namespace를 정의할 때 써야한다! (자유변수의 권한을 보호하기 위해)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;const a = 3; // block
if(a == 3){
		const a = 5; // block
	const f1 = v =&amp;gt; {
		const a = 7;
		console.log(a);
	};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Co Routine
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;const generator = function*(a){
	a++;
	yield a;
	a++;
	yield a;
	a++;
	yield a;
};
const coroutine = generator(3);

let result = 0;
result += coroutine.next().value; // coroutine().value;
console.log(result); // 4
result += coroutine.next().value;
console.log(result); // 9
result += coroutine.next().value;
console.log(result); // 15
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서브루틴에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;yield&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용해서&lt;span&gt;&amp;nbsp;&lt;/span&gt;suspesion(일시정지) 발생&lt;/li&gt;
&lt;li&gt;yield&lt;span&gt;&amp;nbsp;&lt;/span&gt;지나고 난 뒤&lt;span&gt;&amp;nbsp;&lt;/span&gt;coroutine.next()&lt;span&gt;&amp;nbsp;&lt;/span&gt;형태로 다음 루틴 접근 가능&lt;/li&gt;
&lt;li&gt;점점 공유해야 할 변수가 많아지면 여러 함수를 만들어야 하는데, yield를 쓰면 같은 함수 내에서 지역 변수 메모리가 해지되지 않은 채&lt;span&gt;&amp;nbsp;&lt;/span&gt;변수 공유,&lt;span&gt;&amp;nbsp;&lt;/span&gt;상태 유지하며 사용할 수 있다&lt;/li&gt;
&lt;li&gt;우리가 짠 코드의 이해도 상승&lt;/li&gt;
&lt;li&gt;루프 함수(재귀 함수)를 원하는 만큼만 동작시킬 수 있도록 제어 가능&lt;/li&gt;
&lt;li&gt;즉, 꼬리물기 최적화를 통해 루프로 만들면 이를 제어할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>JavaScript</category>
      <category>es6</category>
      <category>OOP</category>
      <category>VanillaJS</category>
      <category>객체지향</category>
      <category>객체지향프로그래밍</category>
      <category>자바스크립트</category>
      <category>자바스크립트oop</category>
      <category>자바스크립트객체지향</category>
      <category>코드스피츠</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/44</guid>
      <comments>https://geniee.tistory.com/entry/ES6-%ED%95%A8%EC%88%98%EC%99%80-OOP#entry44comment</comments>
      <pubDate>Wed, 23 Feb 2022 00:44:01 +0900</pubDate>
    </item>
    <item>
      <title>컴파일러는 두 번 공격한다 #호이스팅</title>
      <link>https://geniee.tistory.com/entry/%EB%8B%B9%EC%8B%A0%EC%9D%80-JS%EB%A5%BC-%EB%AA%A8%EB%A5%B8%EB%8B%A4-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxUSr/btrtIUrooq0/P6CDFsZwz7LFFbLpfFMLv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kxUSr/btrtIUrooq0/P6CDFsZwz7LFFbLpfFMLv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kxUSr/btrtIUrooq0/P6CDFsZwz7LFFbLpfFMLv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxUSr%2FbtrtIUrooq0%2FP6CDFsZwz7LFFbLpfFMLv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;394&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 호이스팅&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4.1 컴파일러는 두 번 공격한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 스코프 안에서 선언된 변수는 바로 그 스코프에 속한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 프로그램은 1장의 컴파일러 이론에 따라 실행된다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;자바스크립트 엔진이 코드를 인터프리팅 하기 전에 컴파일한다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴파일레이션 단계 중에는 모든 선언문을 찾아 적절한 스코프에 연결해주는 과정이 있었다. 이게 바로 2장 렉시컬 스코프의 핵심이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수와 함수 선언문은 모두 코드가 실제 실행되기 전에 먼저 처리된다고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;var a = 2;&amp;rdquo;는 하나의 구문이라 생각할 수 있지만 자바스크립트는 두 개의 구문으로 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;var a; // 선언문 (컴파일레이션 단계)
a = 2; // 대입문 (실행 단계)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 변수와 함수 선언문은 선언된 위치에서 코드의 꼭대기로 끌어올려진다. 이렇게 선언문을 끌어올리는 동작을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;호이스팅&lt;/b&gt;이라고 한다.(호이스팅은 스코프 별로 작동한다.) 즉,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;선언문&lt;/b&gt;이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;대입문&lt;/b&gt;보다 먼저다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의할 점은 선언문만 끌어올려지고 다른 대입문이나 실행 로직 부분은 제자리에 그대로 있기 때문에 호이스팅 코드 실행 로직 부분이 재배치된다면 유심히 살펴봐야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;foo();

function foo() {
	console.log(a); // undefined
	var a = 2;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 foo의 선언문은 끌어올려졌으므로 foo를 첫째 줄에서도 호출할 수 있다. 호이스팅이 스코프 별로 작동한다는 점도 중요하다. 함수 foo() 내에서도 변수 a가 foo()의 꼭대기로 끌어올려진다. 즉 아래와 같이 동작한다고 볼 수 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;foo();

function foo() {
	var a;
	console.log(a); // undefined
	a = 2;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 기억할 것은 함수 표현식이 이름을 가져도 그 이름 변수는 해당 스코프에서 찾을 수 없다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;foo(); // TypeError
bar(); // RefereneceError
var foo = function bar() { // bar() 접근 불가
	// ...
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에 호이스팅을 적용하면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;var foo;

foo(); // TypeError
bar(); // RefereneceError

foo = function() {
	var bar = ...self...
	// ...
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4.2 함수가 먼저다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수와 변수 선언문은 모두 끌어올려지는 와중에 함수가 먼저 끌어올려지고 다음으로 변수가 올려진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;foo(); // 1
var foo;

function foo() {
	console.log(1);
}

foo = function() {
	console.log(2);
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결괏값으로 2가 아니라 1이 출력된다. 엔진은 다음과 같이 해석한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function foo() {
	console.log(1);
}
foo(); // 1
foo = function() {
	console.log(2);
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;var foo가 중복 선언문이라는 점을 보자. var foo는 function foo() 선언문보다 앞서 선언됐지만 함수 선언문이 일반 변수 위로 끌어올려졌다. 많은 중복 변수 선언문이 사실상 무시됐지만 중복 함수 선언문은 앞선 것들을 겹쳐 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 블록에서 보이는 함수 선언문은 보통 둘러싼 스코프로 끌어올려지지만 따르지 않을 수도 있다. 자바스크립트 차후 버전에서는 바뀔 수 있는 부분이며 맹신하지 말아야 한다. 즉, 블록 내 함수 선언은 지양하는 것이 가장 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;foo(); // 3

function foo() {
	console.log(1);
}

var foo = function() {
	console.log(2);
};

function foo() {
	console.log(3);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;var a = 2;&amp;rdquo;는 하나의 구문처럼 보이지만 자바스크립트 엔진은 그렇게 보지 않는다. 엔진은 이를 &amp;ldquo;var a&amp;rdquo;와 &amp;ldquo;a = 2&amp;rdquo;라는 두 개의 독립된 구문으로 보고 첫째 구문은 컴파일러 단계에서, 둘째 구문은 실행 단계에서 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 의미하는 바는 스코프의 모든 선언문은 어디서 나타나든 실행 전에 먼저 처리된다는 점이다. &amp;lsquo;호이스팅'이라 불리는 이 과정은 선언문이 각각이 속한 스코프의 꼭대기로 &amp;lsquo;끌어올려' 지는 작업이라고 생각할 수 있다. 그 과정에서 선언문 자체는 옮겨지지만 함수 표현식의 대입문을 포함한 모든 대입문은 끌어올려 지지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복 선언을 조심하자. 일반 변수 선언과 함수 선언을 섞어 사용하면 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ref&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;[도서] 카일 심슨, ⌜YOU DON'T KNOW JS - 타입과 문법, 스코프와 클로저⌟, 한빛미디어, 2017&lt;/span&gt;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>렉시컬스코프</category>
      <category>스코프</category>
      <category>자바스크립트</category>
      <category>자바스크립트엔진</category>
      <category>자바스크립트컴파일러</category>
      <category>프론트엔드</category>
      <category>프론트엔드공부</category>
      <category>호이스팅</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/43</guid>
      <comments>https://geniee.tistory.com/entry/%EB%8B%B9%EC%8B%A0%EC%9D%80-JS%EB%A5%BC-%EB%AA%A8%EB%A5%B8%EB%8B%A4-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85#entry43comment</comments>
      <pubDate>Tue, 22 Feb 2022 00:17:44 +0900</pubDate>
    </item>
    <item>
      <title>변수를 찾기 위해 정의된 규칙  #스코프</title>
      <link>https://geniee.tistory.com/entry/%EB%8B%B9%EC%8B%A0%EC%9D%80-JS%EB%A5%BC-%EB%AA%A8%EB%A5%B8%EB%8B%A4-%EC%8A%A4%EC%BD%94%ED%94%84%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5vsdl/btrtJC47zho/zF1qXGj7psJkmWxS9zOI1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5vsdl/btrtJC47zho/zF1qXGj7psJkmWxS9zOI1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5vsdl/btrtJC47zho/zF1qXGj7psJkmWxS9zOI1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5vsdl%2FbtrtJC47zho%2FzF1qXGj7psJkmWxS9zOI1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;1. 스코프란 무엇인가&lt;/h1&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍 언어는 변수에 값을 저장하고 &amp;rarr; 저장된 값을 가져다 쓰고 &amp;rarr; 수정하는 패러다임을 가진다. 이 기능은 프로그램에서 상태(state)를 나타낼 수 있게 해준다. 그렇다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✔️&amp;nbsp;변수는 어디에 저장되는가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✔️&amp;nbsp;필요할 때 프로그램은 어떻게 변수를 찾는가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 장소에 변수를 저장하고 그 변수를 찾는 데는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;잘 정의된 규칙&lt;/b&gt;이 필요한데 이를 스코프라고 부른다. 그렇다면 스코프 규칙은 어디서 어떻게 정의되는걸까? 스코프 규칙에 대한 컴파일러 이론을 확인해 보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.1. 컴파일러 이론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 자바스크립트는 &amp;lsquo;동적' 또는 &amp;lsquo;인터프리터'언어로 분류하나 사실은 &amp;lsquo;컴파일러 언어'다. 어떤 자바스크립트 조각이라도 실행되려면 먼저(보통 바로 직전에) &amp;lsquo;컴파일&amp;rsquo;되어야한다. 자바스크립트 컴파일러는 프로그램을 받아 컴파일하여 바로 실행될 수 있게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적인 컴파일러 언어의 처리 과정에서는 프로그램을 이루는 소스 코드가 실행되기 전에 보통 3단계를 거치는데, 이를 &amp;lsquo;컴파일레이션'이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;토크나이징 &amp;amp; 렉싱&lt;/li&gt;
&lt;li&gt;파싱 : 토근 배열을 프로그램 문법 구조를 반영해 중첩 원소를 갖는 트리(AST) 형태로 바꾸는 과정&lt;/li&gt;
&lt;li&gt;코드 생성 : AST를 컴퓨터에서 실행 코드로 바꾸는 과정&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은 이 세 가지 단계 뿐 아니라 많은 부분에서 다른 프로그래밍 언어의 컴파일러보다 훨씬 복잡하다. 자바스크립트 엔진은 파싱과 코드 생성 과정에서 불필요한 요소를 삭제하는 과정을 거쳐 실행 시 성능을 최적화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 컴파일레이션은 보통 코드가 실행되기 겨우 수백만 분의 일초 전에 수행한다. 자바스크립트 엔진은 가능한 한 가장 빠른 성능을 내려 한다. 간단히 말하자면, 어떤 자바스크립트 조각이라도 실행되려면 보통 바로 직전에 컴파일되어야 한다는 말이다. 자바스크립트 컴파일러는 프로그램 &amp;ldquo;var a = 2;&amp;rdquo;를 받아 컴파일하여 바로 실행될 수 있게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.2 스코프 이해하기&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔진 : 컴파일레이션의 시작부터 끝까지 전 과정과 자바스크립트 프로그램 실행을 책임진다&lt;/li&gt;
&lt;li&gt;컴파일러 : 토크나이징과 렉싱 &amp;amp; 파싱 &amp;amp; 코드 생성의 모든 잡일을 도맡아 한다&lt;/li&gt;
&lt;li&gt;스코프 : 선언된 모든 변수 검색 목록을 작성하고 유지한다. 또한 엄격한 규칙을 강제하여 현재 실행 코드에서 변수의 적용 방식을 정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✔️&amp;nbsp;컴파일러 관련 용어, 컴파일러체 (Compiler Speak)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LHS(Left-Hand Side) 검색 : 변수가 대입 연산자의 왼쪽에 있을 때 수행. 값을 넣어야 하므로 변수 컨테이저 자체를 찾는다.&lt;/li&gt;
&lt;li&gt;RHS(Right-Hand SIde) 검색 : 변수가 대입 연산자의 &amp;lsquo;왼편이 아닌 쪽&amp;rsquo;에 있을 때 수행. 단순히 특정 변수의 값을 찾는 것과 다름 없다. &amp;rarr; &amp;ldquo;Retrieve(가져오라) his/her (그의/그녀의) source(소스) !&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;// a에 대한 참조는 RHS 참조(대입한 값)
// a에 아무것도 대입하지 않기 때문이다.
// 대신 a의 값을 가져와 console.log()에 넘겨준다
console.log( a ); 

// a에 대한 참조는 LHS 참조 (대입할 대상)
// 현재 a 값을 신경 쓸 필요 없이 &amp;lsquo;= 2&amp;rsquo; 대입 연산을 수행할 대상 변수를 찾기 때문이다. 
a = 2;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dis36I/btrtQoK26WY/ydkx7YO5OYmIVRSZFHSy11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dis36I/btrtQoK26WY/ydkx7YO5OYmIVRSZFHSy11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dis36I/btrtQoK26WY/ydkx7YO5OYmIVRSZFHSy11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdis36I%2FbtrtQoK26WY%2Fydkx7YO5OYmIVRSZFHSy11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;518&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFEOAk/btrtJEhwVVs/ZDUjCfIlkMfel9liySAw2k/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFEOAk/btrtJEhwVVs/ZDUjCfIlkMfel9liySAw2k/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFEOAk/btrtJEhwVVs/ZDUjCfIlkMfel9liySAw2k/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dFEOAk/btrtJEhwVVs/ZDUjCfIlkMfel9liySAw2k/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;405&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9oU4f/btrtO82KiAB/JuLtLcxVokf1yCdi5xph11/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9oU4f/btrtO82KiAB/JuLtLcxVokf1yCdi5xph11/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9oU4f/btrtO82KiAB/JuLtLcxVokf1yCdi5xph11/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/c9oU4f/btrtO82KiAB/JuLtLcxVokf1yCdi5xph11/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;405&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.3 중첩 스코프 (Nested Scope)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 블록이나 함수는 다른 블록이나 함수 안에 중첩될 수 있으므로 스코프도 다른 스코프 안에 중첩될 수 있다. 따라서 대상 변수를 현재 스코프에서 발견하지 못하면 엔진은 다음 바깥의 스코프로 넘어가는 식으로 변수를 찾거나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;글로벌 스코프라 부르는 가장 바깥 스코프에 도달할 때까지&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;계속한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.4 오류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LHS와 RHS를 구분하는 것이 왜 중요할까? 이 두 종류의 검색 방식은 변수가 아직 선언되지 않았을 때 (검색한 모든 스코프에서 찾지 못했을 때) 서로 다르게 동작하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 검색 실패 시&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LHS : 자동적, 암시적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;글로벌 스코프&lt;/b&gt;에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;같은 이름의 새로운 변수가 생성&lt;/b&gt;된다. (Strict Mode 동작이라면 ReferenceError&amp;rsquo;가 발생)&lt;/li&gt;
&lt;li&gt;RHS : 다시는 변수를 찾을 수 없다. 스코프에서 찾지 못한 변수는 &amp;lsquo;선언되지 않은 변수&amp;rsquo;라 부르며 엔진이 **&amp;lsquo;ReferenceError&amp;rsquo;**를 발생시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;ReferenceError&lt;/b&gt;는 스코프에서 대상을 찾았는지와 관계가 있다. 반면에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;TypeError&lt;/b&gt;는 스코프 검색은 성공했으나 결괏값을 가지고 적합하지 않거나 불가능한 시도를 한 경우를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프는 어디서 어떻게 변수(확인자)를 찾는가를 결정하는 규칙의 집합이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 검색하는 이유는 변수에 값을 대입하거나(LHS 참조) 변수의 값을 얻어오기 위해서다(RHS 참조)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LHS 참조는 대입 연산 과정에서 일어난다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스코프와 관련된 대입 연산 : &amp;lsquo;=&amp;rsquo; 연산자, 인자를 함수의 인자로 넘겨줄 때(암시적 인자 대입)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은 코드를 실행하기 전에 먼저 컴파일하는데, 이 과정에서 엔진은 &amp;ldquo;var = 2;&amp;rdquo;와 같은 구문을 독립된 두 단계로 나눈다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;var a는 변수 a를 해당 스코프에 선언한다. 이 단계는 코드 실행 전에 처음부터 수행된다.&lt;/li&gt;
&lt;li&gt;a=2는 변수 a를 찾아 값을 대입한다. (LHS 참조)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LHS, RHS 참조 검색은 모두 현재 실행 중인 스코프에서 시작한다. 그리고 변수를 찾지 못했을 경우 한 스코프씩 중첩 스코프의 상위 스코프로 넘어가며 변수를 찾느다. 이 작업은 최상위 층 글로벌 스코프에 이를 때까지 계속하고 대상을 찾았든, 못 찾았든 작업을 중단한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LHS, RHS 참조 방식은 변수가 아직 선언되지 않았을 때 서로 다르게 동작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RHS 참조가 대상을 찾지 못하면 ReferenceError가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LHS 참조가 대상을 찾지 못하면 자동적, 암시적으로 글로벌 스코프에 같은 이름의 새로운 변수가 생성된다. (Strict Mode의 경우 ReferenceError 발생)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;2. 렉시컬 스코프&lt;/h1&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자가 코드를 작성할 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;함수&lt;/b&gt;를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;어디에 선언하는지에 따라&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;정의되는 스코프를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.1 렉스타임&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 언어의 컴파일러는 첫 단계를 전통적으로 토크나이징 또는 렉싱이라 불리는 작업으로 시작한다. 렉싱 처리 과정에서는 소스 코드 문자열을 분석하여 상태 유지 파싱의 결과로 생성된 토큰에 의미를 부여한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약간 순환적인 정의를 하면 렉시컬 스코프는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;렉싱 타임(Lexing Time)에 정의되는 스코프&lt;/b&gt;다. 즉, 렉시컬 스코프는 개발자가 코드를 짤 때 변수와 스코프 블록을 어디서 작성하는가에 기초해서 렉서가 코드를 처리할 때 확정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 코드의 스코프를 분석할 때 스코프를 겹쳐진 &amp;lsquo;버블&amp;rsquo;이라고 가정하면 이해하기 쉽다. 스코프 버블은 스코프 블록이 쓰이는 곳에 따라 결정되는데, 스코프 블록은 서로 중첩될 수 있다. 각각의 함수가 새로운 스코플 버블을 생성한다고 생각해도 좋다. 어떤 함수의 버블도 동시에 다른 두 스코프 버블 안에 존재할 수 없다. 어떤 함수도 두 개의 부모 함수 안에 존재할 수 없는 것처럼 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1.1 검색&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프는 목표와 일치하는 대상을 찾는 즉시 검색을 중단한다. 여러 중첩 스코프 층에 걸쳐 같은 변수 이름을 정의할 수 있는데 이를 **섀도잉(shadowing)**이라 한다. 더 안쪽의 변수가 더 바깥쪽의 변수를 숨기는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;✔️&amp;nbsp;숨겨져 있어서 접근할 수 없는 글로벌 변수에는 어떻게 접근할 수 있을까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;window&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체를 통해서 접근할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글로벌 변수는 자동으로 웹 브라우저의 window 같은 글로벌 객체에 속한다. 따라서 글로벌 변수를 직접 렉시컬 이름으로 참조하는 것뿐만 아니라 글로벌 객체의 속성을 참조해 간접적으로 참조할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;// 하지만 글로벌이 아닌 섀도잉 변수는 접근할 수 없다
window.a
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.2 렉시컬 속이기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런타임에 스코프를 수정하거나 새로운 렉시컬 스코프를 만드는 방법은 **eval()**과 **with()**가 있다. eval 은 하나 이상의 선언문을 포함하는 코드 문자열을 해석하여 렉시컬 스코프가 있다면 런타임에 이를 수정한다. with 는 객체 참조를 하나의 스코프로, 속성을 확인자로 간주하여 런타임에 완전히 새로운 렉시컬 스코프를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 방식의 단점은 엔진이 컴파일 단계에서 수행한 스코프 검색과 관련된&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;최적화 작업을 무산시킨다&lt;/b&gt;는 점이다. 따라서 둘 중 하나라도 사용하면 코드는 더 느리게 동작하므로 되도록 이 방식을 사용하지 말자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;3. 함수 vs 블록 스코프&lt;/h1&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.1 함수 기반 스코프&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 어떤 것이 새로운 버블을 만들까? 함수만 버블을 만들까? 자바스크립트의 다른 자료 구조는 스코프 버블을 생성하지 못할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수는 자바스크립트에서 스코프를 이루는 가장 &amp;lsquo;흔한' 단위다. (함수는 자바스크립트의 &amp;lsquo;유일한&amp;rsquo; 스코프 단위가 아니다! 예시로는 아래에서 설명할 블록 스코프가 있다.) 다른 함수 안에서 선언된 변수와 함수는 본질적으로 다른 &amp;lsquo;스코프'로부터 &amp;lsquo;숨겨진' 것이다. 이는 좋은 소프트웨어를 위해 적용해야 할 디자인 원칙이다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;function foo(a) {
	var b = 2;
	// some code..
	function bar() {
		// ...
	}
	// more code..
	var c = 3;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 코드에서 foo()의 스코프 버블은 변수 a, b, c와 bar를 포함한다. bar() 는 자체 스코프 버블이 있고 글로벌 스코프도 마찬가지다. 글로벌 스코프에는 하나의 변수가 있는데 바로 &amp;lsquo;foo&amp;rsquo; 다. a, b, c, bar 모두 foo()의 스코프 버블에 속한다. foo() 바깥에서는 이들에게 접근할 수 없다.&amp;nbsp;다음 코드는 호출된 변수가 글로벌 스코프에는 없기 때문에 ReferenceError 오류를 발생시킨다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;bar(); // fails
console.log( a, b, c ); // all 3 fails
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 모든 확인자 (a, b, c, foo, bar)는 foo() 안에서 접근할 수 있고 bar() 안에서도 이용할 수 있다. (bar 내부에서 섀도 확인자가 선언되지 않았을 때)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.2 일반 스코프에 숨기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수에 대한 전통적인 개념은 이렇다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수를 선언하고 그 안에 코드를 넣는다. 바꿔 생각해보는 것도 꽤 유용하다.&lt;/li&gt;
&lt;li&gt;작성한 코드에서 임의 부분을 함수 선언문으로 감싼다. 이는 해당 코드를 &amp;lsquo;숨기는' 효과를 낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;달리 말하면, 함수의 스코프로 둘러싸서 변수와 함수를 숨길 수 있다는 말이다. 이 원칙은 모듈/객체의 API와 같은 소프트웨어를 설계할 때 필요한 것만 최소한으로 남기고 나머지는 &amp;lsquo;숨겨야'한다는 것이다. 이것이 더 나은 코드를 만들기 위한 조건 중 하나다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.2.1 충돌 회피&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수와 함수를 스코프 안에 숨기는 것의 또 다른 장점은 같은 이름을 가졌지만 다른 용도를 가진 두 변수가 충돌하는 것을 피할 수 있다는 것이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;글로벌 네임스페이스&lt;/b&gt;나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;모듈 관리&lt;/b&gt;를 위해서라도 스코프를 염두해 함수를 숨겨가며 작성해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.3 스코프 역할을 하는 함수&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수 선언문&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;함수 표현식&lt;/b&gt;의 중요한 차이는 함수 이름이 어디의 변수로 묶이느냐와 관련이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 1. 함수 선언문
var a = 2;
function foo() {
	var a = 3;
	console.log(a); // 3
}
foo();

console.log(a); // 2

// 2. 함수 표현식
var a = 2;
(function foo() {
	var a = 3;
	console.log(a); // 3
})();
foo();

console.log(a); // 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 코드에서 함수 이름 foo는 함수를 둘러싼 스코프에 묶이고, foo()라는 이름을 통해 직접 호출했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째 코드에서 함수 이름 foo는 함수를 둘러싼 스코프에 묶이는 대신 함수 자신의 내부 스코프에 묶였다. 즉, &amp;ldquo;(function foo() {...})&amp;rdquo; 라는 표현식에서 확인자 foo는 오직 &amp;lsquo;...&amp;rsquo;가 가리키는 스코프에서만 찾을 수 있고 바깥 스코프에서는 발견되지 않는다. 함수 이름 foo를 자기 내부에 숨기면 함수를 둘러싼 스코프(예를 들면 글로벌 스코프)를 불필요하게 오염시키지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.3.1 익명 vs 기명&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;setTimeout( function() {
	console.log(&quot;I waited 1 second!&quot;);
}, 1000 );
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 함수 표현식을 콜백 인자로 사용하는 사례에 익숙할 것이다. 이런 방식을 &amp;lsquo;&lt;b&gt;익명 함수 표현식&lt;/b&gt;'이라 부르는데, 이는 함수에 확인자 이름이 없기 때문이다**. 함수 표현식**은 이름 없이 사용할 수 있지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;함수 선언문&lt;/b&gt;에는 이름이 빠져서는 안된다. 이름 없는 함수 선언문은 자바스크립트 문법에 맞지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익명 함수 표현식은 편리하지만, 함수 표현식을 사용할 땐 몇 가지 기억할 단점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;익명 함수는 스택 추적 시 표시할 이름이 없어서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;디버깅&lt;/b&gt;이 더 어려울 수 있다.&lt;/li&gt;
&lt;li&gt;이름 없이 함수 스스로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;재귀 호출을 하려면&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;폐기 예정인 arguments.callee 참조가 필요하다. 자기 참조가 필요한 또 다른 예로는 한 번 실행하면 해제되는 이벤트 처리 함수가 있다.&lt;/li&gt;
&lt;li&gt;이름은 보통 쉽게 이해하고 읽을 수 있는 코드 작성에 도움이 되는데, 익명 함수는 이런 이름을 생략한다. 기능을 잘 나타내는 이름은 해당 코드를 그 자체로 설명하는 데 도움이 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 표현식에 이름을 사용하면 특별한 부작용 없이 상당히 효과적으로 앞의 단점을 해결할 수 있다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;따라서 함수 표현식을 사용할 때 이름을 항상 쓰는 것이 가장 좋다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.3.2 함수 표현식 즉시 호출하기&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;var a = 2;
(function foo() { // () : 함수를 표현식으로 변경
	var a = 3;
	console.log(a);
})(); // () : 함수 실행
foo();

console.log(a);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;()로 함수를 감싸면 함수를 표현식으로 바꾸는데, 마지막에 ()를 덧붙이면 함수를 실행할 수 있다. 함수를 둘러싼 첫 번째 ()는 함수를 표현식으로 바꾸고, 두 번째 ()는 함수를 실행시킨다. 이를 **즉시 호출 함수 표현식(IIFE)**라고도 부르는데 이는 가장 흔하게 사용된다. Immediately (즉시), Invoked (호출), Function (함수), Expression (표현식) 3.3.1에서 설명한 이유대로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;기명 IIFE&lt;/b&gt;를 사용하는 것이 더 좋은 습관이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.4 스코프 역할을 하는 블록&lt;/h2&gt;
&lt;pre class=&quot;matlab&quot;&gt;&lt;code&gt;for (var i=0; i&amp;lt;10; i++){
	console.log(i);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 i를 for 반복문의 시작부에 선언하는 이유가 뭘까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 i를 오직 for 반복문과 관련해서 사용하려 하기 때문이다. 그러고는 변수 i가 실제로는 둘러싼(함수 또는 글로벌) 스코프에 포함되는 사실을 무시한다. 즉, 블록 스코프의 목적대로 바로 변수를 최대한 사용처 가까이에서 최대한 작은 유효 범위를 갖도록 선언하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;with&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지양해야 할 구조이긴 하지만 블록 스코프의 형태를 보여주는 예시로 with 문 안에서 생성된 객체는 바깥 스코프에 영향 주는 일 없이 with 문이 끝날 때까지만 존재한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;try/catch&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;try/catch 구문 중 catch 부분에서 선언된 변수는 catch 블록 스코프에 속한다. 즉, catch 구문 안에서 정의된 변수는 다른 스코프 내에서 참조하면 ReferenceError 오류가 발생한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;let&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ES6부터 사용되는 키워드 let은 선언된 변수를 둘러싼 아무 블록 {}의 스코프에 붙인다. 즉 let 선언문은 둘러싼 함수(또는 글로벌) 스코프가 아니라 가장 가까운 임의의 블록에 변수를 붙인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 let을 사용한 선언문은 속하는 스코프에서 호이스팅(끌어올리기) 효과를 받지 않는다. 즉 let으로 선언된 변수는 실제 선언문 전에는 명백하게 &amp;lsquo;존재'하지 않는다.&lt;/p&gt;
&lt;pre class=&quot;clojure&quot;&gt;&lt;code&gt;{
	console.log(bar); // ReferenceError
	let bar = 2;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가비지 콜렉션 (Garbage Collection)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function process(data) {
	// ...
}
var someReallyBigData = { ... };

process( someReallyBigData );

var btn = document.getElementById(&quot;my_button&quot;);
btn.addEventListener(&quot;click&quot;, function click(evt) {
	console.log(&quot;button clicked&quot;);
}, /*capturingPhase=*/false);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;click 함수가 해당 스코프 전체의 클로저를 가지고 있기 때문에 자바스크립트 엔진은 데이터를 남겨둘 것이다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function process(data) {
	// ...
}

// anything declared inside this block can go away after.!
{
	let someReallyBigData = { ... };
	process( someReallyBigData );
}

var btn = document.getElementById(&quot;my_button&quot;);
btn.addEventListener(&quot;click&quot;, function click(evt) {
	console.log(&quot;button clicked&quot;);
}, /*capturingPhase=*/false);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드와 같이 명시적으로 블록을 선언하여 변수의 영역을 한정하는 것은 효과적인 코딩 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;const&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let과 같이 블록 스코프를 생성하지만 선언된 값은 고정된다. (상수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수는 결코 &amp;lsquo;유일한&amp;rsquo; 스코프 단위가 아니다. 블록 스코프는 함수만이 아니라 (일반적으로 { } 같은) 임의의 코드 블록에 변수와 함수가 속하는 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ES3부터 시작해서 try/catch 구조의 catch 부분은 블록 스코프를 가진다. ES6에서는 키워드 let이 추가되어 임의의 코드 블록 안에 변수를 선언할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 착각하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;블록 스코프는 var 함수 스코프를 완전히 대체할 수 없다&lt;/b&gt;. 두 기능은 공존하며 개발자들은 함수 스코프와 블록 스코프 기술을 같이 사용해야 한다. 적절하게 읽히고 유지 보수가 쉬운 코드를 작성하기 위해 상황에 따라 적절한 곳에 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ref&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;[도서] 카일 심슨, ⌜YOU DON'T KNOW JS - 타입과 문법, 스코프와 클로저⌟, 한빛미디어, 2017&lt;/span&gt;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>렉시컬스코프</category>
      <category>블록스코프</category>
      <category>스코프</category>
      <category>중첩스코프</category>
      <category>함수스코프</category>
      <author>realhee</author>
      <guid isPermaLink="true">https://geniee.tistory.com/42</guid>
      <comments>https://geniee.tistory.com/entry/%EB%8B%B9%EC%8B%A0%EC%9D%80-JS%EB%A5%BC-%EB%AA%A8%EB%A5%B8%EB%8B%A4-%EC%8A%A4%EC%BD%94%ED%94%84%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80#entry42comment</comments>
      <pubDate>Mon, 21 Feb 2022 00:13:01 +0900</pubDate>
    </item>
  </channel>
</rss>