<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Your Site's RSS Feed]]></title><description><![CDATA[열심히 기록하려고 합니다.]]></description><link>https://donghoon-song.github.io</link><generator>GatsbyJS</generator><lastBuildDate>Sun, 24 May 2026 14:17:35 GMT</lastBuildDate><item><title><![CDATA[<에이전트 시대의 AI 시스템 설계> AI 실습 문제 생성은 프롬프트만 잘 쓰면 충분할까?]]></title><description><![CDATA[“한빛미디어 <나는 리뷰어다> 활동을 위해 도서를 제공받아 작성된 서평입니다.” 제품을 만들 때 AI…]]></description><link>https://donghoon-song.github.io/books/에이전트-시대의-ai-시스템-설계-리뷰(한빛미디어)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/에이전트-시대의-ai-시스템-설계-리뷰(한빛미디어)/</guid><pubDate>Sun, 24 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/8d41c069-ad2a-4742-a452-1dfa4a21c185.png&quot; alt=&quot;에이전트 시대의 AI 시스템 설계 책 표지&quot; width=&quot;300&quot;&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해 도서를 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;제품을 만들 때 AI로 실습 문제를 생성하는 기능을 붙인 적이 있다. 사용자의 직무, 개선하고 싶은 업무, 지금 하고 있는 일을 입력으로 받아서 그 사람의 상황에 맞는 실습 문제를 만들어주는 흐름이었다. 처음에는 프롬프트에 규칙을 잘 적어두면 어느 정도 안정적인 결과가 나올 거라고 생각했다.&lt;/p&gt;
&lt;p&gt;그런데 실제로 만들어보니 생각보다 쉽지 않았다. 결과물이 겉으로는 문제 형식을 갖추고 있었지만, 실제 업무 상황처럼 느껴지지 않는 경우가 많았다. 실습 데이터도 부실해서 사용자가 “이걸 내 업무에서 어떻게 쓰지?”라고 느낄 만한 결과가 나왔다. 직무와 상황을 입력으로 넣었는데도, 결과물은 그 맥락을 깊게 반영하지 못했다.&lt;/p&gt;
&lt;p&gt;그래서 계속 규칙을 고쳤다. “이런 상황을 더 구체적으로 반영해라”처럼 규칙을 자세히 쓰기도 했고, 반복해서 안 좋은 결과가 나오는 경우에는 “이런 식으로 만들면 안 된다”는 금지 규칙을 추가하기도 했다. 이 과정을 반복하면서 AI 기능은 프롬프트 한 번으로 완성되는 게 아니라, 실패 사례를 보고 규칙과 검증 기준을 계속 보강하는 운영 루프에 가깝다는 생각을 하게 됐다.&lt;/p&gt;
&lt;p&gt;이 책 &amp;#x3C;에이전트 시대의 AI 시스템 설계&gt;는 생성형 AI를 실제 서비스로 운영할 때 마주치는 환각, 비결정적 응답, 지식 공백, 도구 호출 실패, 비용과 지연시간, 안전장치 문제를 32가지 설계 패턴으로 다루는 책이다. 내가 겪었던 “AI가 문제는 만들지만 좋은 실습 문제는 못 만든다”는 문제도 결국 프롬프트 문장력보다 시스템 설계에 가까웠다.&lt;/p&gt;
&lt;h2 id=&quot;인사이트-1-좋은-문제를-만들려면-좋은-맥락이-먼저-필요하다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-1-%EC%A2%8B%EC%9D%80-%EB%AC%B8%EC%A0%9C%EB%A5%BC-%EB%A7%8C%EB%93%A4%EB%A0%A4%EB%A9%B4-%EC%A2%8B%EC%9D%80-%EB%A7%A5%EB%9D%BD%EC%9D%B4-%EB%A8%BC%EC%A0%80-%ED%95%84%EC%9A%94%ED%95%98%EB%8B%A4&quot; aria-label=&quot;인사이트 1 좋은 문제를 만들려면 좋은 맥락이 먼저 필요하다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인사이트 1: 좋은 문제를 만들려면 좋은 맥락이 먼저 필요하다&lt;/h2&gt;
&lt;p&gt;AI에게 직무와 상황을 넣었다고 해서 곧바로 실제 업무 같은 문제가 나오지는 않았다. “프론트엔드 개발자”, “업무 자동화를 개선하고 싶다”, “현재 이런 일을 하고 있다” 같은 정보를 줘도 결과물은 종종 일반적인 예시 문제에 머물렀다. 입력값은 구체적인데 출력은 뭉뚱그려지는 느낌이었다.&lt;/p&gt;
&lt;p&gt;이때 아쉬웠던 건 실습 데이터였다. 실제 업무에서 다룰 법한 데이터, 제약 조건, 예외 상황, 의사결정 맥락이 있어야 문제가 살아나는데, AI가 만든 데이터는 너무 얇았다. 테이블이나 예시 값은 있지만 현업에서 마주치는 복잡함이 없었다. 그래서 학습자는 문제를 풀 수는 있어도, 그 문제가 자기 업무와 연결된다는 느낌을 받기 어려웠다.&lt;/p&gt;
&lt;p&gt;책을 읽으면서 가장 먼저 연결된 부분도 RAG와 지식 추가였다. 기본 RAG, 의미 기반 색인화, 대규모 색인화, 신뢰할 수 있는 생성 같은 주제를 따로 다루는데, 여기서 좋았던 건 RAG를 단순히 “문서 검색 붙이기”로 설명하지 않는다는 점이었다. 내가 만들던 기능에 대입해보면, 사용자 입력 몇 개를 프롬프트에 넣는 것만으로는 부족하고, 직무별 업무 사례나 좋은 실습 데이터의 기준을 어떻게 공급할지까지 설계해야 한다는 이야기로 읽혔다.&lt;/p&gt;
&lt;p&gt;결국 맥락은 “문장으로 설명하는 것”만으로 충분하지 않다. 좋은 실습 문제를 만들려면 사용자의 직무와 상황을 해석할 수 있는 참고 데이터, 예시, 제약 조건이 같이 들어가야 한다. 책을 읽고 나서는 내가 부족하다고 느꼈던 “실습 데이터의 부실함”도 단순 데이터 양의 문제가 아니라, 어떤 지식을 어떻게 가져오고 생성 과정에 연결할지의 문제였다는 생각이 들었다.&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/3JVEZf1.png&quot; alt=&quot;RAG와 지식 추가 관련 내용을 읽은 화면&quot; style=&quot;max-width: 400px;&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;인사이트-2-금지-규칙도-시스템의-일부다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-2-%EA%B8%88%EC%A7%80-%EA%B7%9C%EC%B9%99%EB%8F%84-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EC%9D%BC%EB%B6%80%EB%8B%A4&quot; aria-label=&quot;인사이트 2 금지 규칙도 시스템의 일부다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인사이트 2: 금지 규칙도 시스템의 일부다&lt;/h2&gt;
&lt;p&gt;실습 문제 생성에서 규칙을 추가하다 보면 자연스럽게 금지 규칙이 늘어난다. 처음에는 “직무와 레벨을 반영해라”처럼 원하는 방향을 적는다. 그런데 결과를 보다 보면 “이런 식으로 만들면 안 된다”는 조건이 더 중요해지는 순간이 생긴다. 실제 업무 상황 같지 않은 문제, 데이터가 너무 단순한 문제, 정답이 뻔한 문제, 맥락 없이 용어만 바꾼 문제 같은 것들이다.&lt;/p&gt;
&lt;p&gt;이런 금지 규칙을 넣으면 당장은 나아진다. 하지만 금지 규칙만 계속 늘어나는 방식은 한계가 있다. 프롬프트가 길어지고, 규칙 사이의 우선순위가 애매해지고, 새로운 실패 유형이 나오면 또 규칙을 추가해야 한다. 결국 “규칙을 얼마나 많이 쓰느냐”보다 “어떤 실패를 막아야 하고, 그 실패를 어떻게 감지할 것인가”가 더 중요한 문제가 된다.&lt;/p&gt;
&lt;p&gt;책의 후반부에는 템플릿 생성, 조립 후 재구성, 자체점검, 가드레일 같은 안전장치 패턴이 나온다. 이 부분을 읽으면서 내가 프롬프트에 계속 추가하던 금지 규칙을 조금 다르게 보게 됐다. AI가 부실한 실습 문제를 만들지 않게 하려면 단순히 “잘 만들어줘”라고 하는 게 아니라, 나쁜 결과의 유형을 정의하고 막는 장치가 필요하다.&lt;/p&gt;
&lt;p&gt;내가 추가했던 금지 규칙은 일종의 작은 가드레일이었다. 다만 그때는 그것을 시스템 설계라고까지 생각하지 못했다. 책을 읽고 나니 금지 규칙을 프롬프트 안에 계속 쌓아두는 것보다, 템플릿, 자체점검, 평가 기준으로 분리하는 편이 더 운영 가능한 방식이라는 생각이 들었다.&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/uejrDtG.png&quot; alt=&quot;가드레일과 자체점검 관련 내용을 읽은 화면&quot; style=&quot;max-width: 400px;&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;인사이트-3-퀄리티-컨트롤은-생성-이후에-더-중요해진다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-3-%ED%80%84%EB%A6%AC%ED%8B%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EC%9D%80-%EC%83%9D%EC%84%B1-%EC%9D%B4%ED%9B%84%EC%97%90-%EB%8D%94-%EC%A4%91%EC%9A%94%ED%95%B4%EC%A7%84%EB%8B%A4&quot; aria-label=&quot;인사이트 3 퀄리티 컨트롤은 생성 이후에 더 중요해진다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인사이트 3: 퀄리티 컨트롤은 생성 이후에 더 중요해진다&lt;/h2&gt;
&lt;p&gt;실습 문제 생성에서 가장 어려웠던 건 퀄리티 컨트롤이었다. 문제를 하나 생성하는 것 자체는 어렵지 않았다. 어려운 건 그 문제가 정말 사용자의 직무와 상황에 맞는지, 실습 데이터가 충분한지, 실제 업무 상황처럼 느껴지는지 판단하는 일이었다.&lt;/p&gt;
&lt;p&gt;처음에는 결과가 마음에 들지 않으면 프롬프트를 고쳤다. 규칙을 더 구체화하거나 금지 규칙을 추가했다. 하지만 시간이 지날수록 프롬프트를 수정하는 것만으로는 충분하지 않다는 생각이 들었다. 어떤 결과가 좋은 문제인지, 어떤 결과가 나쁜 문제인지 판단하는 기준이 더 중요했다. 기준이 없으면 매번 사람이 감으로 보고 고쳐야 한다.&lt;/p&gt;
&lt;p&gt;이 책은 신뢰성 개선 파트에서 심판형 LLM, 성찰, 의존성 주입, 프롬프트 최적화 같은 패턴을 다룬다. 제약 조건 해결 파트에는 성능 저하 테스트도 있다. 이 부분을 읽으면서 이 책이 “생성”만이 아니라 “생성된 결과를 어떻게 믿을 것인가”를 꽤 중요하게 다룬다는 느낌을 받았다.&lt;/p&gt;
&lt;p&gt;내 경험에 대입하면, AI가 만든 실습 문제를 다시 평가하는 단계가 필요했다. 예를 들어 “실제 업무 상황이 드러나는가”, “사용자의 입력이 문제에 반영됐는가”, “실습 데이터가 충분한가”, “금지한 유형의 문제가 나오지 않았는가” 같은 기준이다. 이 기준을 사람이 매번 감으로 보는 게 아니라, 시스템 안에 넣을 수 있어야 제품으로 안정화될 수 있다. 책에서 말하는 신뢰성 개선 패턴은 이 지점을 정리하는 데 도움이 됐다.&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/CGnkdv5.png&quot; alt=&quot;신뢰성 개선과 성능 저하 테스트 관련 내용을 읽은 화면&quot; style=&quot;max-width: 400px;&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h2&gt;
&lt;p&gt;책을 다 읽고 나니, 이 책은 단순한 AI 입문서나 프롬프트 작성법 책과는 거리가 있었다. 생성형 AI를 실제 서비스로 운영할 때 생기는 문제를 패턴 단위로 다루는 책에 가깝다. 그래서 처음부터 끝까지 순서대로 읽는 것도 가능하지만, 지금 만들고 있는 AI 기능에서 막히는 지점을 기준으로 필요한 패턴을 찾아 읽는 방식도 잘 맞아 보였다.&lt;/p&gt;
&lt;p&gt;내가 AI 실습 문제 생성 기능을 만들면서 겪었던 문제도 결국 같은 방향이었다. 좋은 결과가 나오지 않을 때마다 프롬프트를 고치고 규칙을 추가했지만, 더 근본적으로는 맥락 공급, 금지 규칙, 품질 평가, 검증 루프가 필요했다. 이 책을 읽으면서 그 경험을 RAG, 신뢰성 개선, 가드레일, 성능 저하 테스트 같은 패턴으로 다시 정리할 수 있었다.&lt;/p&gt;
&lt;p&gt;AI 기능을 빠르게 만드는 단계에서는 프롬프트와 데모가 중요하다. 하지만 오래 버티는 AI 시스템을 만들려면 그 뒤의 설계가 필요하다. 특히 AI로 무언가를 생성하는 제품을 만들고 있고, “결과는 나오는데 품질이 안정적이지 않다”는 고민을 해본 사람이라면 이 책에서 연결해볼 지점이 많을 것 같다.&lt;/p&gt;
&lt;p&gt;#한빛미디어 #나는리뷰어다 #에이전트시대의AI시스템설계 #AI시스템설계 #RAG #가드레일 #AI에이전트&lt;/p&gt;</content:encoded></item><item><title><![CDATA[더 줄일 수 있는건 없을까? <미니멀리즘 프로그래머>]]></title><description><![CDATA[“한빛미디어 <나는 리뷰어다> 활동을 위해 도서를 제공받아 작성된 서평입니다.” 인사이트 1: 비동기적인 삶 많은 팀이 이벤트 주도 시스템처럼 일한다는데 공감한다. 요즘에 B2B…]]></description><link>https://donghoon-song.github.io/books/더-줄일-수-있는건-없을까-미니멀리즘-프로그래머/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/더-줄일-수-있는건-없을까-미니멀리즘-프로그래머/</guid><pubDate>Sun, 05 Apr 2026 09:04:21 GMT</pubDate><content:encoded>&lt;!-- 사진 1: 책 표지 직접 촬영 사진으로 교체해주세요 --&gt;
&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/23bd2fd9-83a8-4bbe-a140-07f73111a97b.png&quot; alt=&quot;미니멀리즘 프로그래머 책 표지&quot; width=&quot;300&quot;&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해 도서를 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;인사이트-1-비동기적인-삶&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-1-%EB%B9%84%EB%8F%99%EA%B8%B0%EC%A0%81%EC%9D%B8-%EC%82%B6&quot; aria-label=&quot;인사이트 1 비동기적인 삶 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인사이트 1: 비동기적인 삶&lt;/h2&gt;
&lt;p&gt;많은 팀이 이벤트 주도 시스템처럼 일한다는데 공감한다. 요즘에 B2B로 제품이 나가면서 이슈 해결을 빠르게 하려다 보니까 새로운 일이 터지면 온 신경이 거기다 쏠린다. 하지만 그 중에는 우선순위, 긴급도가 낮은 경우도 분명 있었을 것이다. 하지만 셀에서 비동기로 처리할 수 있는 일을 남겨놓는 프로세스가 부족하다는 생각이 들었다.&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/3tR208y.jpeg&quot; alt=&quot;인사이트 1&quot; style=&quot;max-width: 400px;&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;인사이트-2-회의도-복잡함을-줄일-수-있다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-2-%ED%9A%8C%EC%9D%98%EB%8F%84-%EB%B3%B5%EC%9E%A1%ED%95%A8%EC%9D%84-%EC%A4%84%EC%9D%BC-%EC%88%98-%EC%9E%88%EB%8B%A4&quot; aria-label=&quot;인사이트 2 회의도 복잡함을 줄일 수 있다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인사이트 2: 회의도 “복잡함”을 줄일 수 있다&lt;/h2&gt;
&lt;p&gt;코드 바깥에서 가장 인상 깊었던 부분이 여기였다. 책은 회의를 단순히 “시간 낭비”로 뭉뚱그리지 않는다. 회의는 여러 사람의 시간을 동시에 소모하는, 비용이 굉장히 큰 행위라는 시각으로 접근한다. 실제로 드는 비용을 계산해봤을 때 꽤나 컸다.&lt;/p&gt;
&lt;p&gt;실무에서 회의 시간이 길어지는 경우가 많았다. 하지만 길어진다고 해서 회의를 마쳤을 때 상쾌한 기분이 들지도 않았다. 아무래도 셀에서 챙겨야 할 것들이 많았어서 이런저런 이야기를 하다가 흩어지는 회의들이 대부분이었다. 책을 읽고 나서는 회의 전에 “이 회의가 끝났을 때 무엇이 결정되어야 하는가”를 먼저 정의하고, 끝난 후에 실제로 그게 이뤄졌는지 확인해봐야겠다는 다짐을 하게 됐다. 코드를 단순하게 만드는 것처럼, 회의도 목적이 뚜렷할수록 비용 대비 가치가 올라간다.&lt;/p&gt;
&lt;p&gt;또 한 가지 와닿은 포인트는, 회의는 강의 시간이 아니라는 것이다. 정보 전달을 회의 시간 안에 하려고 하면 그만큼 의사결정에 쓸 시간이 줄어든다. 읽어야 할 자료를 미리 공유하고, 회의 자리에서는 이미 자료를 읽은 사람들이 논의하고 결정하는 구조가 훨씬 효율적이다. 회의를 하기 전에 필요한 자료를 읽어보자는 요청을 해야겠다. 정보는 회의 밖에서도 자유롭게 흐를 수 있어야 한다.&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/SWQ0QOE.jpeg&quot; alt=&quot;인사이트 2&quot; style=&quot;max-width: 400px;&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;인사이트-3-주석도-관리-대상이다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-3-%EC%A3%BC%EC%84%9D%EB%8F%84-%EA%B4%80%EB%A6%AC-%EB%8C%80%EC%83%81%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;인사이트 3 주석도 관리 대상이다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인사이트 3: 주석도 관리 대상이다&lt;/h2&gt;
&lt;p&gt;요즘 코드 이해도를 높이겠다고 주석을 꽤 열심히 달고 있었다. 그런데 이 책을 읽으면서 불편한 진실 하나를 마주했다. 주석이 길어지는 순간, 그것도 코드처럼 관리해야 할 대상이 된다는 것이다. 아직까지는 기존 코드를 자주 건드리면서 주석도 함께 수정하는 경우가 많지 않았어서 이 부분은 크게 체감하지 못했다. 하지만 코드가 바뀌면 주석도 바꿔야 한다. 안 바꾸면 거짓말하는 주석이 된다. 코드는 최신인데 주석은 옛날 로직을 설명하고 있는 상황, 한 번쯤은 다들 겪어봤을 것이다. 결국 주석이 길수록 유지 비용도 그만큼 올라간다. 테스트 코드도 마찬가지라고 생각한다. 코드가 바뀌면 테스트 코드, 주석이 함께 바뀌어야 한다. 어떻게 효율적으로 관리할 수 있는지 고민이 필요하다.&lt;/p&gt;
&lt;p&gt;책에서 강조하는 방향은 코드 자체가 의도를 드러내도록 짜는 것이다. 변수명, 함수명, 구조로 설명이 되어야 한다. 주석이 필요하다면 “왜(Why)“를 적는 것이지, “무엇을(What)“을 풀어 쓰는 게 아니다. 앞으로는 주석을 달기 전에 “이게 코드로 표현될 수 없는 내용인가”를 먼저 물어봐야겠다.&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/59Ud6XJ.jpeg&quot; alt=&quot;인사이트 3&quot; style=&quot;max-width: 400px;&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h2&gt;
&lt;p&gt;AI로 코드를 짜다보면 생각보다 복잡하고, 많은 양의 코드가 생성되는 일이 많다. 이 책을 읽고 나서 그런 복잡함을 경계하는 태도를 연습해야겠다는 생각이 들었다. 책의 분량이 많지도 않았지만 얻을 수 있는건 명확했다.&lt;/p&gt;
&lt;p&gt;#한빛미디어 #나는리뷰어다 #미니멀리즘프로그래머&lt;/p&gt;</content:encoded></item><item><title><![CDATA[컨텍스트 엔지니어링으로 구축하는 AI 에이전트 리뷰 - 한빛미디어]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/컨텍스트-엔지니어링으로-구축하는-ai-에이전트-도서-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/컨텍스트-엔지니어링으로-구축하는-ai-에이전트-도서-리뷰/</guid><pubDate>Mon, 02 Mar 2026 15:30:00 GMT</pubDate><content:encoded>&lt;figure style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt; &lt;!-- 📸 직접 촬영한 책 표지 사진으로 교체 추천 --&gt; &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/555c18b8-6c46-4c04-af96-fd58ac403442.jpg&quot; alt=&quot;컨텍스트 엔지니어링으로 구축하는 AI 에이전트&quot; width=&quot;300&quot; height=&quot;auto&quot;&gt; &lt;figcaption&gt;출처: 한빛미디어&lt;/figcaption&gt; &lt;/figure&gt;
&lt;h3 id=&quot;한빛미디어-서평단-나는리뷰어다-활동을-위해-도서를-제공받아-작성된-서평입니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%9C%EB%B9%9B%EB%AF%B8%EB%94%94%EC%96%B4-%EC%84%9C%ED%8F%89%EB%8B%A8-%EB%82%98%EB%8A%94%EB%A6%AC%EB%B7%B0%EC%96%B4%EB%8B%A4-%ED%99%9C%EB%8F%99%EC%9D%84-%EC%9C%84%ED%95%B4-%EB%8F%84%EC%84%9C%EB%A5%BC-%EC%A0%9C%EA%B3%B5%EB%B0%9B%EC%95%84-%EC%9E%91%EC%84%B1%EB%90%9C-%EC%84%9C%ED%8F%89%EC%9E%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;한빛미디어 서평단 나는리뷰어다 활동을 위해 도서를 제공받아 작성된 서평입니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“한빛미디어 서평단 &amp;#x3C;나는리뷰어다&gt; 활동을 위해 도서를 제공받아 작성된 서평입니다.”&lt;/h3&gt;
&lt;hr&gt;
&lt;p&gt;최근 회사에서 학습 컨텐츠를 만드는 일을 하면서, 생각보다 많은 시간을 프롬프트에 쓰고 있었다. 예시 문제(원본)가 있고, 사용자의 상황(직무/레벨/목표)에 맞게 문제를 re-writing한 뒤, 정해진 JSON 스키마에 맞춰 컨텐츠를 생성해 반환하는 작업이다.&lt;/p&gt;
&lt;p&gt;겉으로 보면 단순하다. “규칙만 잘 지키면 자동으로 안정적인 결과가 나오겠지”라고 생각했다. 근데 운영으로 들어가니 제일 곤란한 문제가 생겼다. 결과가 항상 일정하지 않다. 어떤 날은 규칙이 잘 적용되는데, 어떤 날은 규칙이 누락되는 느낌이 들었고 컨텐츠 퀄리티도 들쭉날쭉했다.&lt;/p&gt;
&lt;p&gt;특히 제일 치명적인 건 “형식”보다 “내용”이었다. 형식은 대부분 잘 맞춰주는데 정작 사용자 맥락을 제대로 반영하지 못하는 결과가 종종 나왔다. 사용자 입장에서는 “그럴듯한 문제”가 아니라 “내 상황에 맞는 문제”가 필요한데, 그걸 놓친 결과물은 결국 내가 다시 손으로 고쳐야 했다. 그리고 특정 한두가지 property값만 기대치에 못 미치면 스트레스를 받았다.&lt;/p&gt;
&lt;p&gt;이 책을 읽고 나서 내가 바꾼 건 프롬프트 문장력이 아니라, 컨텍스트를 다루는 방식이었다. 특히 두 가지가 결정적이었다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;강화형 컨텍스트 학습으로 “생성 후 보완” 루프를 만들기&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/rXfKvLq.png&quot; alt=&quot;&quot;&gt;
2. re-writing 컨텍스트와 컨텐츠 생성 컨텍스트를 분리하기
&lt;img src=&quot;https://i.imgur.com/CsHuTpQ.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;문제는 ‘규칙이 부족해서’가 아니라 ‘규칙이 강화되지 않아서’였다. 규칙을 전부 적어놓긴 했지만 그럼에도 고려하지 못한 부분, 엣지 케이스들이 훨씬 많았다. 그래서 필요한 건 “처음부터 완벽한 규칙”이 아니라, 구멍을 발견하면 강화하는 게 맞아 보였다.&lt;/p&gt;
&lt;h3 id=&quot;1-강화형-컨텍스트-학습으로-생성-후-보완-루프-만들기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EA%B0%95%ED%99%94%ED%98%95-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%95%99%EC%8A%B5%EC%9C%BC%EB%A1%9C-%EC%83%9D%EC%84%B1-%ED%9B%84-%EB%B3%B4%EC%99%84-%EB%A3%A8%ED%94%84-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;1 강화형 컨텍스트 학습으로 생성 후 보완 루프 만들기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 강화형 컨텍스트 학습으로 ‘생성 후 보완’ 루프 만들기&lt;/h3&gt;
&lt;p&gt;강화형 컨텍스트 학습 플로우를 만들기 위해서 결과물을 만든 다음,그 결과물에서 “규칙을 보완할 지점”을 찾아 다음 생성에 반영해 강화했다. 그러다보니 계속 진행할수록 퀄리티가 올라갔다. 생성하고 피드백한만큼 강화되는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;2-re-writing과-컨텐츠-생성-컨텍스트를-분리하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-re-writing%EA%B3%BC-%EC%BB%A8%ED%85%90%EC%B8%A0-%EC%83%9D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%A5%BC-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0&quot; aria-label=&quot;2 re writing과 컨텐츠 생성 컨텍스트를 분리하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. re-writing과 컨텐츠 생성 컨텍스트를 분리하기&lt;/h3&gt;
&lt;p&gt;또 하나 크게 바꾼 건 “한 번에 다 하게 만들지 말자”였다.&lt;/p&gt;
&lt;p&gt;이전에는 한 프롬프트 안에서 원본 예시 문제를 해석하고 사용자 맥락을 반영해 re-writing하고 JSON 스키마에 맞춰 컨텐츠를 생성하고 이 모든 걸 동시에 시켰다. 내용은 빠진 게 없었지만 AI가 한번에 하려니까 퀄리티가 잘 안 나왔다.&lt;/p&gt;
&lt;p&gt;그래서 나는 컨텍스트를 의도적으로 두 덩어리로 분리했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;re-writing 컨텍스트&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;사용자 맥락을 “어떻게” 반영할지에 집중&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;직무/레벨/목표를 반영하는 기준을 명시&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;원본 문제의 핵심을 유지하는 규칙 포함&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ 여기서 결과물은 “텍스트”다. (아직 JSON 아님)&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;컨텐츠 생성 컨텍스트&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;re-writing 결과를 입력으로 받아&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JSON 스키마 준수에 집중&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;금지어/길이/톤 등 출력 제약을 강하게 적용&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ 여기서 결과물은 “JSON”이다.&lt;/p&gt;
&lt;p&gt;이렇게 하니까 퀄리티가 훨씬 올라갔고 디버깅하기도 쉬워졌다. 중간단계인 re-writing 결과를 로그로 찍어보면 re-writing 단계의 문제인지, 뒷단의 문제인지 쉽게 판단할 수 있었다. 무엇보다 “사용자 맥락 반영”이 컨텐츠 생성 과정에서 묻히지 않았다. 맥락을 반영하는 일과, 형식을 맞추는 일을 분리하니 서로의 품질을 갉아먹지 않게 됐다.&lt;/p&gt;
&lt;h3 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h3&gt;
&lt;p&gt;이 책을 읽고 나서 내가 얻은 건 “프롬프트를 잘 쓰는 법”이 아니었다. 운영 가능한 컨텍스트 설계 방법이었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;규칙은 한 번에 완성되지 않는다 → 강화 루프가 필요하다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;한 프롬프트에 모든 걸 넣으면 흔들린다 → 컨텍스트를 분리해야 한다&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;기존에는 너무 사람처럼 생각했는데 이제는 AI의 입장에서 조금이나마 프롬프트를 작성할 수 있게 되지 않았나 싶다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/Ijyt3kl.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;#한빛미디어 #나는리뷰어다 #컨텍스트엔지니어링으로구축하는AI에이전트&lt;/p&gt;</content:encoded></item><item><title><![CDATA[소프트웨어 아키텍처 The Basics(2판) 리뷰 - 한빛미디어]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/소프트웨어-아키텍처-the-basics-2판-리뷰(한빛미디어)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/소프트웨어-아키텍처-the-basics-2판-리뷰(한빛미디어)/</guid><pubDate>Sat, 31 Jan 2026 15:30:00 GMT</pubDate><content:encoded>&lt;figure style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/6a07fbac-3b16-4d77-869b-c72df22804e7.jpg&quot; alt=&quot;소프트웨어 아키텍처 The Basics(2판)&quot; width=&quot;300&quot; height=&quot;auto&quot;&gt;
  &lt;figcaption&gt;출처: 한빛미디어&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;한빛미디어-서평단-나는리뷰어다-활동을-위해서-책을-협찬-받아-작성된-서평입니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%9C%EB%B9%9B%EB%AF%B8%EB%94%94%EC%96%B4-%EC%84%9C%ED%8F%89%EB%8B%A8-%EB%82%98%EB%8A%94%EB%A6%AC%EB%B7%B0%EC%96%B4%EB%8B%A4-%ED%99%9C%EB%8F%99%EC%9D%84-%EC%9C%84%ED%95%B4%EC%84%9C-%EC%B1%85%EC%9D%84-%ED%98%91%EC%B0%AC-%EB%B0%9B%EC%95%84-%EC%9E%91%EC%84%B1%EB%90%9C-%EC%84%9C%ED%8F%89%EC%9E%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;한빛미디어 서평단 나는리뷰어다 활동을 위해서 책을 협찬 받아 작성된 서평입니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“한빛미디어 서평단 &amp;#x3C;나는리뷰어다&gt; 활동을 위해서 책을 협찬 받아 작성된 서평입니다.”&lt;/h3&gt;
&lt;h2 id=&quot;시작하며&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%9C%EC%9E%91%ED%95%98%EB%A9%B0&quot; aria-label=&quot;시작하며 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;시작하며&lt;/h2&gt;
&lt;p&gt;연차가 쌓이면서 코드 외적인 것들을 자연스레 신경쓰게 된다. 슬슬 인프라쪽도 더 공부해서 팀원들 도움받지 않고 구축하고 싶었는데 “이 책이 답을 줄 수 있을까?” 기대하며 펼쳤다. 이 책의 내용은 오히려 더 베이스를 이루는 아키텍처들을 다뤘다. 그래서 책을 쭉 봤을 때 내용이 많이 어려웠다. 하지만 여러번 읽다보면 이해가 될 것이라 기대했다.&lt;/p&gt;
&lt;p&gt;책에서 소개하는 여러 아키텍처 패턴들은 익숙한 프론트엔드 디자인 패턴과는 사뭇 다른 느낌이었다. 근데 끝까지 읽고 나니 아키텍트들이 어떤 고민을 하고, 어떤 기준으로 결정을 내리는지 조금은 이해할 수 있었다.&lt;/p&gt;
&lt;p&gt;하지만 돌이켜 생각해봤을 때 나도 자잘하게 이런 결정들을 했었다.&lt;/p&gt;
&lt;h2 id=&quot;개발자와-아키텍트는-뭐가-다를까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%99%80-%EC%95%84%ED%82%A4%ED%85%8D%ED%8A%B8%EB%8A%94-%EB%AD%90%EA%B0%80-%EB%8B%A4%EB%A5%BC%EA%B9%8C&quot; aria-label=&quot;개발자와 아키텍트는 뭐가 다를까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;개발자와 아키텍트는 뭐가 다를까&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;“이 함수를 어떻게 짤까?”&lt;/li&gt;
&lt;li&gt;“어떤 라이브러리를 쓸까?”&lt;/li&gt;
&lt;li&gt;“이 버그는 어떻게 고치지?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;책에서는 이런 고민들을 &lt;strong&gt;전술적(tactical) 결정&lt;/strong&gt;이라고 불렀다.&lt;/p&gt;
&lt;p&gt;반면 아키텍트는 &lt;strong&gt;전략적(strategic) 결정&lt;/strong&gt;을 한다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“우리 시스템에 정말 중요한 건 뭘까?”&lt;/li&gt;
&lt;li&gt;“어떤 구조가 우리 비즈니스에 맞을까?”&lt;/li&gt;
&lt;li&gt;“이 선택을 하면 뭘 포기해야 할까?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;아키텍트는 시스템 전체로 넓게 보는 느낌이다.&lt;/p&gt;
&lt;p&gt;예를 들어, 내가 버튼 컴포넌트를 만들 때는 “어떻게 예쁘게 만들지”를 고민한다. 하지만 아키텍트는 “100개 넘는 버튼의 일관성을 어떻게 유지할지”, “각 팀이 독립적으로 개발하려면 어떤 구조가 필요할지”를 고민하더라.&lt;/p&gt;
&lt;p&gt;나는 코드 한 줄에 집중하는데, 아키텍트는 시스템 전체를 본다. 줌 아웃의 정도가 다르달까. 그 간격이 생각보다 크다는 걸 이 책을 통해 체감했다.&lt;/p&gt;
&lt;h2 id=&quot;아키텍트는-번역가다-기술과-비즈니스-사이&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%95%84%ED%82%A4%ED%85%8D%ED%8A%B8%EB%8A%94-%EB%B2%88%EC%97%AD%EA%B0%80%EB%8B%A4-%EA%B8%B0%EC%88%A0%EA%B3%BC-%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4-%EC%82%AC%EC%9D%B4&quot; aria-label=&quot;아키텍트는 번역가다 기술과 비즈니스 사이 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;아키텍트는 번역가다: 기술과 비즈니스 사이&lt;/h2&gt;
&lt;p&gt;책에서 가장 인상 깊었던 부분 중 하나는 아키텍트의 &lt;strong&gt;번역자 역할&lt;/strong&gt;이구나 싶었다.&lt;/p&gt;
&lt;p&gt;개발자는 “React 18로 마이그레이션해야 합니다”, “Redis 캐시를 도입하면 됩니다”처럼 기술 언어로 말한다. 하지만 경영진은 “그래서 매출이 늘어나나요?”, “비용은 얼마나 드나요?”, “언제 끝나나요?”를 궁금해한다.&lt;/p&gt;
&lt;p&gt;아키텍트는 이 둘 사이를 연결한다.&lt;/p&gt;
&lt;p&gt;“Redis 캐시를 도입하면 페이지 로딩 속도가 2초 빨라집니다. 이는 사용자 이탈률을 15% 줄이고, 월 매출을 약 500만원 증가시킬 수 있습니다. 초기 구축 비용은 2주, 200만원 정도 예상됩니다.”&lt;/p&gt;
&lt;p&gt;기술적 결정을 비즈니스 가치로 변환하는 것.
“좋은 코드”가 아니라 “좋은 코드가 만드는 비즈니스 임팩트”를 설명해야 한다.&lt;/p&gt;
&lt;p&gt;나는 지금까지 “좋은 코드를 짜면 인정받는다”고 생각했다. 근데 실제로는 &lt;strong&gt;그 코드가 비즈니스에 어떤 영향을 주는지 설명할 수 있어야&lt;/strong&gt; 인정받는다는 걸 깨달았다.&lt;/p&gt;
&lt;p&gt;“컴포넌트 재사용성을 높였습니다”보다 “개발 시간을 30% 단축해서 기능 출시를 2주 앞당길 수 있습니다”가 더 설득력 있다.&lt;/p&gt;
&lt;p&gt;책에서는 이런 소통 능력을 기술만큼이나 중요하게 다룬다. 아무리 좋은 아키텍처를 설계해도, 이해관계자를 설득하지 못하면 실행할 수 없기 때문이다.&lt;/p&gt;
&lt;p&gt;실제 회사에서도 기술스택 변경 마이그레이션을 하려고 C레벨을 설득해야 했을 때가 있었는데, 이런 경험을 바탕으로 이해가 됐고 이것은 단순 아키텍트만이 아니라 개발자들도 갈고 닦아야 하는 능력이었다.&lt;/p&gt;
&lt;h2 id=&quot;모든-결정은-트레이드오프다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AA%A8%EB%93%A0-%EA%B2%B0%EC%A0%95%EC%9D%80-%ED%8A%B8%EB%A0%88%EC%9D%B4%EB%93%9C%EC%98%A4%ED%94%84%EB%8B%A4&quot; aria-label=&quot;모든 결정은 트레이드오프다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;모든 결정은 트레이드오프다&lt;/h2&gt;
&lt;p&gt;책을 읽으면서 계속 “응, 그렇지” 하게 되더라. 책에서 가장 많이 나온 단어가 &lt;strong&gt;트레이드오프&lt;/strong&gt;. 모든 걸 다 잘할 수는 없다.&lt;/p&gt;
&lt;p&gt;성능을 올리려면? 코드가 복잡해진다.
보안을 강화하면? 개발 속도가 느려진다.
처음부터 확장 가능하게 만들려면? 초기 비용이 크다.
유연한 구조를 만들려면? 단순함을 포기해야 한다.&lt;/p&gt;
&lt;p&gt;항상 뭔가를 포기해야 한다는 걸 머리로는 알았는데,
이렇게 명시적으로 정리해주니까 속이 시원했다.&lt;/p&gt;
&lt;p&gt;프론트엔드로 예를 들면, SSR을 도입하면 초기 로딩은 빨라지지만 서버 비용이 증가하고 배포가 복잡해진다. 타입스크립트를 쓰면 안정성은 높아지지만 초기 러닝커브와 설정 비용이 든다.&lt;/p&gt;
&lt;p&gt;아키텍트는 “무엇이 우리에게 가장 중요한가?”를 먼저 정한다. 그리고 나머지는 어느 정도 포기한다.&lt;/p&gt;
&lt;p&gt;이커머스 사이트라면 성능이 최우선일 수 있다. 0.1초 지연이 매출에 직접 영향을 주니까. 반면 내부 관리 도구라면 빠른 개발과 유지보수성이 더 중요할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;완벽은 없다. 그때그때 최선이 있을 뿐이다.&lt;/strong&gt; 이 문장이 책 전체를 관통하는 메시지라고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;기술보다-중요한-것-소프트-스킬&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EC%88%A0%EB%B3%B4%EB%8B%A4-%EC%A4%91%EC%9A%94%ED%95%9C-%EA%B2%83-%EC%86%8C%ED%94%84%ED%8A%B8-%EC%8A%A4%ED%82%AC&quot; aria-label=&quot;기술보다 중요한 것 소프트 스킬 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기술보다 중요한 것: 소프트 스킬&lt;/h2&gt;
&lt;p&gt;이 책에서도 소프트 스킬을 강조한다. 아무리 좋은 아키텍처를 설계해도, PM을 설득하지 못하면 실행할 수 없다. CEO에게 비즈니스 가치를 설명하지 못하면 예산을 못 받는다. 팀원들의 협조를 얻지 못하면 혼자 고군분투하다 끝난다.&lt;/p&gt;
&lt;p&gt;특히 기억에 남는 건 &lt;strong&gt;트레이드오프를 설명하는 법&lt;/strong&gt;이다. “모든 기능 다 넣어야 해요!”라고 할 때, “안 됩니다”가 아니라 “A를 선택하면 B를 포기해야 하는데, 어떻게 할까요?”처럼 현실적인 대안을 제시하는 것이다. 무조건 받아들이는 것도, 무조건 거절하는 것도 아니고, 함께 최선을 찾아가는 거다.&lt;/p&gt;
&lt;p&gt;이런 능력은 지금도, 시니어가 되어서도 계속 필요할 것 같다.&lt;/p&gt;
&lt;h2 id=&quot;실용적인-조언들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%EC%A1%B0%EC%96%B8%EB%93%A4&quot; aria-label=&quot;실용적인 조언들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실용적인 조언들&lt;/h2&gt;
&lt;p&gt;이 책에서 설명하는 20분 규칙은 하루에 딱 20분만 투자해서 새로운 기술들을 훑어보고 판단하는 것이다.&lt;/p&gt;
&lt;p&gt;프론트엔드는 트렌드가 빠르게 바뀌니까, 모든 걸 다 깊게 공부할 수는 없다. 하지만 완전히 무시하기도 찝찝하다. 20분 규칙은 그 중간 지점을 찾는 현실적인 방법이다.&lt;/p&gt;
&lt;p&gt;또 하나는 &lt;strong&gt;생성형 AI 시대의 개발자 역할&lt;/strong&gt;에 대한 내용이다. AI가 코드를 짜주는 시대지만, “어디에 어떤 코드를 둘지”, “어떤 구조가 맞는지”, “무엇을 포기하고 무엇을 선택할지”는 여전히 사람이 결정해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h2&gt;
&lt;p&gt;지금은 컴포넌트나 함수 레벨에서 고민하지만, 점점 더 시스템 전체를 설계하는 쪽으로 생각하려고 한다.&lt;/p&gt;
&lt;p&gt;그때 이 책에서 배운 것들이 도움이 될 것 같다. 특히 **“정답은 없다. 항상 트레이드오프다. 그때그때 최선을 찾는 거다”**라는 생각. 완벽을 추구하다가 아무것도 못 하는 것보다, 그때의 최선을 선택하고 나중에 개선하는 게 낫다. 이게 아키텍처의 본질인 것 같다.&lt;/p&gt;
&lt;p&gt;어려운 책이었지만, 읽길 잘했다고 생각한다. 읽다보면 더 디테일한 내용들도 이해될 것 같다.&lt;/p&gt;
&lt;p&gt;다음 단계로 성장하기 위한 준비를 조금은 한 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GitKraken에서 AI로 merge conflict 쉽게 해결하기]]></title><description><![CDATA[브랜치를 머지하려는데 conflict…]]></description><link>https://donghoon-song.github.io/GitKraken/gitkraken에서-ai로-merge-conflict-쉽게-해결하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/GitKraken/gitkraken에서-ai로-merge-conflict-쉽게-해결하기/</guid><pubDate>Fri, 05 Dec 2025 23:13:29 GMT</pubDate><content:encoded>&lt;p&gt;브랜치를 머지하려는데 conflict가 발생하면 막막한 경우가 많습니다. 보통 팀원들의 작업과 충돌하는 경우가 많아서 해결하기 어려운 경우가 많습니다. 많이 조심스럽기도 하구요. 심지어 비슷한 라인을 건드리면 더 막막해집니다. 보통의 경우 동료를 소환해서 같이 보면서 해결하는 경우가 많았습니다. 그렇게 하는 편이 정확도가 높았습니다. 언제나 빠르게 같이 보고 해결할 수 있다면 좋겠지만, 동료가 부재중이거나 바쁜 경우에는 작업을 이어나가기가 힘들었습니다. 그래서 요즘에는 제가 자주 사용하는 Git GUI 툴인 GitKraken Desktop에서 AI가 merge conflict를 분석해서 해결 방법을 제안해주는 기능을 애용하고 있습니다. 써보니까 이 과정이 정말 많이 편해져서 경험을 공유해보려고 합니다.&lt;/p&gt;
&lt;h2 id=&quot;gitkraken-ai가-제안하는-해결책&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#gitkraken-ai%EA%B0%80-%EC%A0%9C%EC%95%88%ED%95%98%EB%8A%94-%ED%95%B4%EA%B2%B0%EC%B1%85&quot; aria-label=&quot;gitkraken ai가 제안하는 해결책 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;GitKraken AI가 제안하는 해결책&lt;/h2&gt;
&lt;p&gt;GitKraken을 사용하고 있다면 별다른 설정없이 해당 기능을 사용할 수 있습니다. 이해를 돕기 위해 &lt;a href=&quot;https://www.youtube.com/watch?v=gQYKs4Z7mJ0&quot;&gt;GitKraken youtube에서 해당 기능을 설명하는 영상&lt;/a&gt;을 캡쳐해봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/MWnYcYW.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/s9GGNUo.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/BoO926Q.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;충돌이 발생하면 GitKraken AI가 양쪽 변경 내역을 분석해서 어떻게 해결하면 좋을지 제안해줍니다. 단순히 “이쪽 선택하세요”가 아니라, 각 선택지가 정답일 확률(Confidence)를 수치로 함께 제시합니다. 그래서 단순히 AI의 선택에 맡기는 것이 아니라 개발자가 납득할 수 있고, 최종적으로 결정할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;h3 id=&quot;정확도가-올라갔습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%ED%99%95%EB%8F%84%EA%B0%80-%EC%98%AC%EB%9D%BC%EA%B0%94%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;정확도가 올라갔습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정확도가 올라갔습니다&lt;/h3&gt;
&lt;p&gt;혼자서 merge conflict를 해결할 때 한번에 완벽하게 해결되는 경우는 드물었습니다. 해결하고 나서 개발 환경에서 다시 살펴보면서 빠진 부분은 없는지, 잘못 들어간 부분은 없는지를 다시 체크하는 경우가 많았습니다. 하지만 AI의 도움을 받았을 때는 시행착오가 적었고 병합 과정에서 의사 결정에 도움을 많이 받기 때문에 더 정확하게 해결할 수 있었습니다.&lt;/p&gt;
&lt;h3 id=&quot;동료를-덜-부르게-됐습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8F%99%EB%A3%8C%EB%A5%BC-%EB%8D%9C-%EB%B6%80%EB%A5%B4%EA%B2%8C-%EB%90%90%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;동료를 덜 부르게 됐습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;동료를 덜 부르게 됐습니다&lt;/h3&gt;
&lt;p&gt;이 기능을 쓰면서 제일 좋았던 건, 혼자 해결할 수 있는 충돌의 범위가 확실히 넓어졌다는 것입니다. 동료가 부재중일 때도 혼자서 conflict를 해결할 수 있게 됐습니다. 맥락 파악 시간을 줄임과 동시에 AI의 코멘트를 읽으면서 공부하는 기회가 되기도 했습니다.&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;저번에는 AI의 도움을 받아 커밋 메시지를 작성하는 GitKraken의 기능을 사용해봤는데, 이번에는 AI의 도움을 받아 merge conflict를 해결하는 기능을 사용해봤습니다. 이렇게 GitKraken이 유저들에게 필요한 기능이 뭔지 고민하고 빠르게 도입해보는 모습이 보기 좋았습니다. 이런 도구들이 개발자들의 일상적인 고민을 해결해주는 모습을 보면서, 정말 개발 환경이 많이 좋아졌다는 생각이 듭니다. 혹시 GitKraken을 아직 사용해보지 않으셨다면, 한 번 체험해보시는 것도 좋을 것 같아요.&lt;/p&gt;
&lt;p&gt;아래 링크를 사용하시면 GitKraken Pro를 50% 할인된 가격에 구독하실 수 있습니다.&lt;br/&gt;
&lt;a href=&quot;https://gitkraken.cello.so/u1THZtouxdr&quot;&gt;프로모션 링크&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[바이브코딩 너머 개발자 생존법(한빛미디어) 도서 리뷰]]></title><description><![CDATA[“한빛미디어 <나는 리뷰어다> 활동을 위해서 책을 제공받아 작성된 서평입니다.” 왜 이 책을 집었는가 – “AI를 잘 쓰고 있는 게 맞을까?” 저는 6년차 웹 프론트엔드 개발자이자 한 제품개발 셀의 리드입니다. 이미 팀에서 AI…]]></description><link>https://donghoon-song.github.io/books/바이브코딩-너머-개발자-생존법(한빛미디어)-도서-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/바이브코딩-너머-개발자-생존법(한빛미디어)-도서-리뷰/</guid><pubDate>Sat, 29 Nov 2025 20:11:52 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/c3bfebce-031f-4a97-9e34-d6b6ee2fd2d4.jpg&quot; alt=&quot;바이브코딩 너머 개발자 생존법 책 사진&quot;&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;왜-이-책을-집었는가--ai를-잘-쓰고-있는-게-맞을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%9C-%EC%9D%B4-%EC%B1%85%EC%9D%84-%EC%A7%91%EC%97%88%EB%8A%94%EA%B0%80--ai%EB%A5%BC-%EC%9E%98-%EC%93%B0%EA%B3%A0-%EC%9E%88%EB%8A%94-%EA%B2%8C-%EB%A7%9E%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;왜 이 책을 집었는가  ai를 잘 쓰고 있는 게 맞을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왜 이 책을 집었는가 – “AI를 잘 쓰고 있는 게 맞을까?”&lt;/h2&gt;
&lt;p&gt;저는 6년차 웹 프론트엔드 개발자이자 한 제품개발 셀의 리드입니다. 이미 팀에서 AI를 꽤 쓰고 있고, 저도 업무 중에 자연스럽게 AI를 켜놓고 개발하는 편입니다. 덕분에 생산성이 많이 올라갔습니다. 코드 생성 속도가 빨라져서 AI없이는 지키기 힘든 일정으로 제품을 개발할 수 있게 됐고 문서화에 도움을 받기도 합니다. 또한 테스트 코드를 작성하기도 수월해져서 코드 안정성도 많이 올라가고 있습니다. 이렇게 AI를 활용하고 있지만 더 잘 활용할 수 있을까 하는 기대감에 이 책을 읽어보기로 했습니다.&lt;/p&gt;
&lt;p&gt;책을 읽어봤을 때 이 책은 “AI 입문자”에게는 좋은 네비게이션이 되고, “이미 쓰고 있는 사람”에게는 브레이크와 안전벨트를 다시 달아주는 느낌에 가깝습니다.&lt;/p&gt;
&lt;h2 id=&quot;이-책이-던진-핵심-메시지-ai가-짠-코드는-끝이-아니라-시작이다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4-%EC%B1%85%EC%9D%B4-%EB%8D%98%EC%A7%84-%ED%95%B5%EC%8B%AC-%EB%A9%94%EC%8B%9C%EC%A7%80-ai%EA%B0%80-%EC%A7%A0-%EC%BD%94%EB%93%9C%EB%8A%94-%EB%81%9D%EC%9D%B4-%EC%95%84%EB%8B%88%EB%9D%BC-%EC%8B%9C%EC%9E%91%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;이 책이 던진 핵심 메시지 ai가 짠 코드는 끝이 아니라 시작이다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이 책이 던진 핵심 메시지: &lt;strong&gt;“AI가 짠 코드는 끝이 아니라 시작이다.”&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;책을 읽으면서 가장 많이 반복해서 느낀 키워드는 두 가지였습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;검증&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;소화&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI가 코드를 만들어주는 건 이제 너무 자연스러운 일이 됐는데, 이 책은 그다음 단계를 집요하게 묻습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;그 코드가 &lt;strong&gt;정말 문제를 해결하고 있는지&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;기존 시스템/아키텍처와 &lt;strong&gt;정합성이 맞는지&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;보안/성능/장기 유지보수 관점에서 &lt;strong&gt;괜찮은 선택인지&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;즉, AI가 만들어 준 코드는 결과물이 아니라 일종의 &lt;strong&gt;초안&lt;/strong&gt;이고,
그걸 검증하고, 맥락 안에 끌어와서 소화하는 과정이 바로 개발자의 역할이라는 메시지를 강하게 던집니다. 그리고 AI를 활용하는 것은 사람을 대체하는게 아니라 AI의 도움을 받아 생산성을 증폭시킨다는 AI와 함께 코딩한다는 메시지에 깊이 공감했습니다.&lt;/p&gt;
&lt;h2 id=&quot;부트스트래퍼-마인드셋--가설-검증을-위해-빠르게-만들어보자&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%98%ED%8D%BC-%EB%A7%88%EC%9D%B8%EB%93%9C%EC%85%8B--%EA%B0%80%EC%84%A4-%EA%B2%80%EC%A6%9D%EC%9D%84-%EC%9C%84%ED%95%B4-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90&quot; aria-label=&quot;부트스트래퍼 마인드셋  가설 검증을 위해 빠르게 만들어보자 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;부트스트래퍼 마인드셋 – “가설 검증을 위해 빠르게 만들어보자”&lt;/h2&gt;
&lt;p&gt;이 책에서 특히 재미있게 읽었던 부분이 &lt;strong&gt;‘부트스트래퍼’ 방식의 개발&lt;/strong&gt;을 강조하는 대목입니다. 최근에 회사의 대표님께서 강조하셔서 셀에서도 실험적으로 도입해본 방식이었는데 상당히 효과가 좋았습니다. 셀 구성원들이 직군 상관없이 가설을 세우고 검증하기 위해 각자의 프로토타입을 AI로 제작해서 빠르게 피드백을 받는 방식이었고 사내 구성원들에게 공유할 때도 반응이 좋았습니다.&lt;/p&gt;
&lt;p&gt;여기서 말하는 부트스트래퍼는:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;완벽한 제품을 만드는 사람이 아니라&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;가설을 검증하기 위해 빠르게 프로토타입을 만드는 사람&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;에 가깝습니다.&lt;/p&gt;
&lt;p&gt;AI와 이 마인드셋이 만나면 워크플로가 이렇게 바뀝니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;비즈니스/제품 가설을 명확히 적습니다.&lt;/li&gt;
&lt;li&gt;그 가설을 검증하기 위한 &lt;strong&gt;최소한의 기능&lt;/strong&gt;을 정합니다.&lt;/li&gt;
&lt;li&gt;AI를 활용해 프로토타입 코드를 빠르게 만듭니다.&lt;/li&gt;
&lt;li&gt;직접 코드 검증/리팩터링을 해서 “대충 굴러가지만 이해는 되는 상태”까지 끌어올립니다.&lt;/li&gt;
&lt;li&gt;실제 사용자나 이해관계자에게 보여주고, 다음 가설/다음 실험으로 넘어갑니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;실무에-적용해볼만한-점들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%EB%AC%B4%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%BC%EB%A7%8C%ED%95%9C-%EC%A0%90%EB%93%A4&quot; aria-label=&quot;실무에 적용해볼만한 점들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실무에 적용해볼만한 점들&lt;/h2&gt;
&lt;p&gt;먼저 문서를 항상 남겨야겠다는 생각을 하고 있었는데 책을 읽고 나서 확실히 도움이 될 것이라는 생각이 들었습니다. 보통의 경우 작은 기능 단위로 AI를 활용해서 개발했고 리팩토링도 했기 때문에 그 내역을 문서화하진 않았습니다. 하지만 나중에 작업을 이어서하고 싶을 때 컨텍스트를 다시 주입해줘야 하는 문제가 생겼습니다. 문서로 작업 내역과 의사 결정 과정, 결과를 문서화하면 다음에 이어서 작업하는데 도움이 되고 코드를 이해하는데에도 많은 도움이 되었습니다.&lt;/p&gt;
&lt;h2 id=&quot;ai가-개발자를-대체할까에서-ai와-함께-어떻게-일할까로&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ai%EA%B0%80-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EB%8C%80%EC%B2%B4%ED%95%A0%EA%B9%8C%EC%97%90%EC%84%9C-ai%EC%99%80-%ED%95%A8%EA%BB%98-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9D%BC%ED%95%A0%EA%B9%8C%EB%A1%9C&quot; aria-label=&quot;ai가 개발자를 대체할까에서 ai와 함께 어떻게 일할까로 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“AI가 개발자를 대체할까?”에서 “AI와 함께 어떻게 일할까?”로&lt;/h2&gt;
&lt;p&gt;“AI와 함께 일하는 개발자는 무엇을 책임져야 할까?”라는 질문이 이 책을 관통하는 것 같습니다. AI가 짠 코드는 결과물이 아니라 일종의 초안이고, 그걸 검증하고, 맥락 안에 끌어와서 소화하는 과정이 바로 개발자의 역할이라는 메시지를 강하게 던집니다. AI를 활용하는데 있어 좋은 가이드라인이 되었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[밑바닥부터 시작하는 웹 브라우저(한빛미디어) 도서 리뷰]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/밑바닥부터-시작하는-웹-브라우저(한빛미디어)-도서-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/밑바닥부터-시작하는-웹-브라우저(한빛미디어)-도서-리뷰/</guid><pubDate>Sun, 26 Oct 2025 19:10:35 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/099100fb-3dff-4448-bd4b-40b893147f82.jpg&quot; alt=&quot;개발자 기술 면접 노트 책 사진&quot;&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;시작에-앞서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%9C%EC%9E%91%EC%97%90-%EC%95%9E%EC%84%9C&quot; aria-label=&quot;시작에 앞서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;시작에 앞서&lt;/h2&gt;
&lt;p&gt;웹 개발자라면 한 번쯤 “브라우저는 내부에서 어떤 과정을 거쳐 페이지를 띄우는 걸까?”라는 궁금증을 가져보셨을 겁니다. 저도 브라우저를 언젠가 더 공부해봐야지 생각하고 있었는데 마침 그럴 기회가 생겼습니다. &lt;strong&gt;밑바닥부터 시작하는 웹 브라우저&lt;/strong&gt;는 단순히 원리를 설명하는 데 그치지 않고, &lt;strong&gt;브라우저의 핵심 기능을 직접 구현해보며 동작 원리를 체득하는 과정&lt;/strong&gt;에 초점을 맞춥니다. 무언가를 배우는 가장 좋은 방법은 직접 해보는 것이라는 말이 있는 것처럼 이 책을 통해 브라우저의 동작 원리를 직접 구현해보며 이해할 수 있었습니다.&lt;/p&gt;
&lt;h2 id=&quot;챕터별-내용-요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B1%95%ED%84%B0%EB%B3%84-%EB%82%B4%EC%9A%A9-%EC%9A%94%EC%95%BD&quot; aria-label=&quot;챕터별 내용 요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;챕터별 내용 요약&lt;/h2&gt;
&lt;h3 id=&quot;prologue-브라우저와-나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prologue-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%99%80-%EB%82%98&quot; aria-label=&quot;prologue 브라우저와 나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PROLOGUE 브라우저와 나&lt;/h3&gt;
&lt;p&gt;브라우저의 기본 개념과 이 책에서 구현할 브라우저의 전체적인 구조를 소개합니다.&lt;/p&gt;
&lt;h3 id=&quot;part-1-페이지-로딩&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part-1-%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%A1%9C%EB%94%A9&quot; aria-label=&quot;part 1 페이지 로딩 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PART 1 페이지 로딩&lt;/h3&gt;
&lt;h4 id=&quot;chapter-1-웹페이지-다운로드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-1-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C&quot; aria-label=&quot;chapter 1 웹페이지 다운로드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 1 웹페이지 다운로드&lt;/h4&gt;
&lt;p&gt;HTTP 프로토콜을 통한 서버 연결과 데이터 다운로드 과정을 구현합니다. TCP 소켓 연결, HTTP 요청/응답 처리, HTTPS 암호화 연결까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-2-화면에-그리기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-2-%ED%99%94%EB%A9%B4%EC%97%90-%EA%B7%B8%EB%A6%AC%EA%B8%B0&quot; aria-label=&quot;chapter 2 화면에 그리기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 2 화면에 그리기&lt;/h4&gt;
&lt;p&gt;tkinter를 이용해 브라우저 창을 만들고 기본적인 그래픽 렌더링을 구현합니다. 텍스트 배치, 스크롤 기능, 렌더링 최적화 기법을 학습합니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-3-텍스트-포맷팅하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-3-%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%8F%AC%EB%A7%B7%ED%8C%85%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chapter 3 텍스트 포맷팅하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 3 텍스트 포맷팅하기&lt;/h4&gt;
&lt;p&gt;폰트의 기본 개념부터 시작해 텍스트 측정, 스타일링, 레이아웃 객체 설계까지 텍스트 렌더링의 모든 과정을 구현합니다.&lt;/p&gt;
&lt;h3 id=&quot;part-2-문서-표시&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part-2-%EB%AC%B8%EC%84%9C-%ED%91%9C%EC%8B%9C&quot; aria-label=&quot;part 2 문서 표시 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PART 2 문서 표시&lt;/h3&gt;
&lt;h4 id=&quot;chapter-4-문서-트리-구축하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-4-%EB%AC%B8%EC%84%9C-%ED%8A%B8%EB%A6%AC-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chapter 4 문서 트리 구축하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 4 문서 트리 구축하기&lt;/h4&gt;
&lt;p&gt;HTML 파싱을 통해 DOM 트리를 구축하는 과정을 구현합니다. 파서 디버깅, 셀프 클로징 태그 처리, 오류 처리까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-5-페이지-레이아웃&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-5-%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83&quot; aria-label=&quot;chapter 5 페이지 레이아웃 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 5 페이지 레이아웃&lt;/h4&gt;
&lt;p&gt;렌더 트리와 레이아웃 계산 과정을 구현합니다. 블록 레이아웃, 크기/위치 계산, 재귀 페인팅, 배경 그리기까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-6-개발자-스타일-적용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-6-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%8A%A4%ED%83%80%EC%9D%BC-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chapter 6 개발자 스타일 적용하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 6 개발자 스타일 적용하기&lt;/h4&gt;
&lt;p&gt;CSS 파싱과 스타일 적용 과정을 구현합니다. 셀렉터 매칭, 캐스케이딩, 스타일 상속, 폰트 프로퍼티 처리까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-7-버튼과-링크-처리하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-7-%EB%B2%84%ED%8A%BC%EA%B3%BC-%EB%A7%81%ED%81%AC-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chapter 7 버튼과 링크 처리하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 7 버튼과 링크 처리하기&lt;/h4&gt;
&lt;p&gt;인터랙티브 요소들의 처리 방법을 구현합니다. 링크 처리, 클릭 이벤트, 탭 브라우징, 히스토리 탐색, URL 입력까지 다룹니다.&lt;/p&gt;
&lt;h3 id=&quot;part-3-애플리케이션-실행&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part-3-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89&quot; aria-label=&quot;part 3 애플리케이션 실행 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PART 3 애플리케이션 실행&lt;/h3&gt;
&lt;h4 id=&quot;chapter-8-서버로-정보-보내기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-8-%EC%84%9C%EB%B2%84%EB%A1%9C-%EC%A0%95%EB%B3%B4-%EB%B3%B4%EB%82%B4%EA%B8%B0&quot; aria-label=&quot;chapter 8 서버로 정보 보내기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 8 서버로 정보 보내기&lt;/h4&gt;
&lt;p&gt;HTML 폼의 동작 원리와 서버로 데이터를 전송하는 과정을 구현합니다. 폼 요소 렌더링, 상호작용, POST 요청 처리까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-9-대화형-스크립트-실행하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-9-%EB%8C%80%ED%99%94%ED%98%95-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chapter 9 대화형 스크립트 실행하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 9 대화형 스크립트 실행하기&lt;/h4&gt;
&lt;p&gt;DukPy 자바스크립트 엔진을 이용해 JS 코드 실행 환경을 구현합니다. 브라우저 API 노출, 이벤트 처리, DOM 조작까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-10-사용자-데이터-보호하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-10-%EC%82%AC%EC%9A%A9%EC%9E%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chapter 10 사용자 데이터 보호하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 10 사용자 데이터 보호하기&lt;/h4&gt;
&lt;p&gt;웹 보안의 핵심 개념들을 구현합니다. 쿠키, 인증 시스템, CORS, Same-Origin Policy, CSRF/XSS 방어, CSP까지 다룹니다.&lt;/p&gt;
&lt;h3 id=&quot;part-4-모던-브라우저-기능&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part-4-%EB%AA%A8%EB%8D%98-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EA%B8%B0%EB%8A%A5&quot; aria-label=&quot;part 4 모던 브라우저 기능 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PART 4 모던 브라우저 기능&lt;/h3&gt;
&lt;h4 id=&quot;chapter-11-시각적-효과&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-11-%EC%8B%9C%EA%B0%81%EC%A0%81-%ED%9A%A8%EA%B3%BC&quot; aria-label=&quot;chapter 11 시각적 효과 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 11 시각적 효과&lt;/h4&gt;
&lt;p&gt;Skia와 SDL을 이용한 하드웨어 가속 그래픽 렌더링을 구현합니다. 컴포지팅, 투명도, 블렌딩, 마스킹까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-12-태스크와-스레드-스케줄링&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-12-%ED%83%9C%EC%8A%A4%ED%81%AC%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81&quot; aria-label=&quot;chapter 12 태스크와 스레드 스케줄링 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 12 태스크와 스레드 스케줄링&lt;/h4&gt;
&lt;p&gt;비동기 작업 관리와 멀티스레딩을 구현합니다. 태스크 큐, 타이머, 렌더링 주기, 성능 최적화까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-13-애니메이션과-컴포지팅&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-13-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98%EA%B3%BC-%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8C%85&quot; aria-label=&quot;chapter 13 애니메이션과 컴포지팅 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 13 애니메이션과 컴포지팅&lt;/h4&gt;
&lt;p&gt;GPU 가속 애니메이션과 컴포지팅을 구현합니다. JS 애니메이션, CSS 트랜지션, 컴포지팅 최적화까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-14-콘텐츠-접근성-향상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-14-%EC%BD%98%ED%85%90%EC%B8%A0-%EC%A0%91%EA%B7%BC%EC%84%B1-%ED%96%A5%EC%83%81&quot; aria-label=&quot;chapter 14 콘텐츠 접근성 향상 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 14 콘텐츠 접근성 향상&lt;/h4&gt;
&lt;p&gt;웹 접근성 기능들을 구현합니다. 줌, 다크 모드, 키보드 내비게이션, 스크린 리더 지원까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-15-삽입된-콘텐츠-지원&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-15-%EC%82%BD%EC%9E%85%EB%90%9C-%EC%BD%98%ED%85%90%EC%B8%A0-%EC%A7%80%EC%9B%90&quot; aria-label=&quot;chapter 15 삽입된 콘텐츠 지원 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 15 삽입된 콘텐츠 지원&lt;/h4&gt;
&lt;p&gt;이미지와 iframe 등 복잡한 콘텐츠를 처리합니다. 이미지 렌더링, iframe 통신, 보안 고려사항까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-16-이전-결과-재사용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-16-%EC%9D%B4%EC%A0%84-%EA%B2%B0%EA%B3%BC-%EC%9E%AC%EC%82%AC%EC%9A%A9&quot; aria-label=&quot;chapter 16 이전 결과 재사용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 16 이전 결과 재사용&lt;/h4&gt;
&lt;p&gt;렌더링 성능 최적화를 위한 캐싱과 무효화 전략을 구현합니다. 의존성 관리, 캐시 무효화, 불필요한 재계산 방지까지 다룹니다.&lt;/p&gt;
&lt;h4 id=&quot;chapter-17-이-책에서-다루지-않은-내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chapter-17-%EC%9D%B4-%EC%B1%85%EC%97%90%EC%84%9C-%EB%8B%A4%EB%A3%A8%EC%A7%80-%EC%95%8A%EC%9D%80-%EB%82%B4%EC%9A%A9&quot; aria-label=&quot;chapter 17 이 책에서 다루지 않은 내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CHAPTER 17 이 책에서 다루지 않은 내용&lt;/h4&gt;
&lt;p&gt;현대 브라우저의 고급 기능들과 향후 학습 방향을 제시합니다.&lt;/p&gt;
&lt;h3 id=&quot;epilogue-변화하는-환경&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#epilogue-%EB%B3%80%ED%99%94%ED%95%98%EB%8A%94-%ED%99%98%EA%B2%BD&quot; aria-label=&quot;epilogue 변화하는 환경 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;EPILOGUE 변화하는 환경&lt;/h3&gt;
&lt;p&gt;웹 기술의 발전과 브라우저의 미래에 대한 전망을 다룹니다.&lt;/p&gt;
&lt;h2 id=&quot;입력에서-렌더링까지-브라우저의-모든-여정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%85%EB%A0%A5%EC%97%90%EC%84%9C-%EB%A0%8C%EB%8D%94%EB%A7%81%EA%B9%8C%EC%A7%80-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EB%AA%A8%EB%93%A0-%EC%97%AC%EC%A0%95&quot; aria-label=&quot;입력에서 렌더링까지 브라우저의 모든 여정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;입력에서 렌더링까지, 브라우저의 모든 여정&lt;/h2&gt;
&lt;p&gt;이 책은 사용자가 주소창에 URL을 입력한 순간부터 화면에 결과가 그려지기까지의 전체 과정을 코드와 함께 따라갑니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Part 1에서는 DNS, HTTP, TLS 등 네트워크 단계에서 실제 요청과 응답이 어떻게 이루어지는지를 다룹니다.&lt;/li&gt;
&lt;li&gt;Part 2에서는 HTML 파싱, DOM 트리 생성, CSS 스타일 적용, 레이아웃 계산과 같은 렌더링 파이프라인을 구현합니다.&lt;/li&gt;
&lt;li&gt;Part 3~4에서는 자바스크립트 실행, 이벤트 처리, 폼 제출, 스레드 및 GPU 가속 등 현대 브라우저의 복잡한 동작까지 확장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;직접-만드는-브라우저--실습-중심-학습&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A7%81%EC%A0%91-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80--%EC%8B%A4%EC%8A%B5-%EC%A4%91%EC%8B%AC-%ED%95%99%EC%8A%B5&quot; aria-label=&quot;직접 만드는 브라우저  실습 중심 학습 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;직접 만드는 브라우저 – 실습 중심 학습&lt;/h2&gt;
&lt;p&gt;이 책의 가장 큰 매력은 &lt;strong&gt;파이썬으로 브라우저를 한 줄씩 구현해 나가는 구성&lt;/strong&gt;입니다.
단순히 설명을 읽는 것이 아니라, 직접 코드를 작성해 실행하면서 “내가 만든 프로그램이 웹페이지를 띄운다”는 감각을 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;특히 프론트엔드 개발자에게는 “렌더링 과정의 원리”를 실감나게 이해할 수 있는 실습 경험이 될 것입니다.
렌더링 속도나 레이아웃 변화 같은 현상을 단순히 ‘느낌’으로 접근하는 대신, 그 근거를 브라우저 내부 구조에서 찾아볼 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;처음엔 간단한 글자들을 렌더링하는 것부터 렌더 트리를 구축하고 레이아웃, 스타일을 적용하는 등 점진적으로 브라우저의 기능들을 하나씩 구현해 나가는 구성이 좋았습니다. 이 과정을 직접 구현해보며, “웹 브라우저가 화면을 만드는 과정이 얼마나 세밀한 설계 위에 있는지”를 몸소 경험할 수 있습니다.&lt;/p&gt;
&lt;p&gt;그리고 연습 문제를 통해서 책에서 구현한 부분에서 더 나아가 도전적인 기능들을 구현해 볼 수 있는 기회를 제공합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[커밋 메시지가 고민일 때 GitKraken이 대신 써줍니다]]></title><description><![CDATA[코드를 다 짜놓고 git commit을 치려는데… 커서 앞에서 멍하니 멈춘 적, 다들 있지 않나요? 컨벤션에 맞게 prefix…]]></description><link>https://donghoon-song.github.io/GitKraken/커밋-메시지가-고민일-때-gitkraken이-대신-써줍니다/</link><guid isPermaLink="false">https://donghoon-song.github.io/GitKraken/커밋-메시지가-고민일-때-gitkraken이-대신-써줍니다/</guid><pubDate>Sun, 21 Sep 2025 11:10:10 GMT</pubDate><content:encoded>&lt;p&gt;코드를 다 짜놓고 git commit을 치려는데… 커서 앞에서 멍하니 멈춘 적, 다들 있지 않나요?&lt;/p&gt;
&lt;p&gt;컨벤션에 맞게 prefix를 정하려고 하는데 이것도 맞는 것 같고 저것도 맞는 것 같고 애매한 경우도 있었고 커밋 제목을 깔끔하게 정리하고 싶은데 주저리 적는 것 같고 그랬던 적이 있어요. 요즘에 AI가 있어서 편해졌다지만 AI에게 물어보려면 제 작업 내역을 전달해야 하는데 방법도 마땅치가 않았구요. 제가 주로 사용하고 있는 Git GUI 툴인 GitKraken에서 AI가 커밋 메시지를 자동으로 생성해 주는 기능이 생겨서 써 본 경험을 공유해요.&lt;/p&gt;
&lt;h2 id=&quot;gitkraken-ai가-제시한-새로운-해법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#gitkraken-ai%EA%B0%80-%EC%A0%9C%EC%8B%9C%ED%95%9C-%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%95%B4%EB%B2%95&quot; aria-label=&quot;gitkraken ai가 제시한 새로운 해법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;GitKraken AI가 제시한 새로운 해법&lt;/h2&gt;
&lt;p&gt;GitKraken Desktop을 애용하고 있었는데 언제부턴가 Commit summary 옆에 마법이 일어날 것 같은 버튼이 생겼어요.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/JmiqDhW.png&quot; alt=&quot;GitKraken AI 커밋 메시지 생성 버튼&quot;&gt;&lt;/p&gt;
&lt;p&gt;GitKraken이 제가 바꾼 코드를 분석해서 자동으로 메시지를 제안해 줬어요. “오, 이거 괜찮은데?” 싶은 순간이었어요. 고민 없이 메시지가 툭 나오니까 확실히 편했어요.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/Z4LdpSG.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;커스텀-지침-설정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%A7%80%EC%B9%A8-%EC%84%A4%EC%A0%95&quot; aria-label=&quot;커스텀 지침 설정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;커스텀 지침 설정&lt;/h2&gt;
&lt;p&gt;하지만 한 가지 문제가 있었어요. 일단 영어로 나왔고 AI는 저희 회사의 커밋 컨벤션을 모르니까 feat:, fix: 같은 prefix를 붙여주지 않았어요. 하지만 분명히 커스텀 지침을 설정할 수 있을 거라고 생각해서 설정 화면을 찾아보다가 관련 기능을 발견했어요.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/8gqd81S.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;회사의 커밋 컨벤션과 함께&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;한글로 작성하기&lt;/li&gt;
&lt;li&gt;prefix의 맨 앞글자는 소문자로 작성하기&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;를 instruction에 추가했더니 이젠 마치 제가 작성한 것처럼 잘 뽑아줬어요.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/bNmtjMK.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;핵심은-작성이-아닌-검토&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B5%EC%8B%AC%EC%9D%80-%EC%9E%91%EC%84%B1%EC%9D%B4-%EC%95%84%EB%8B%8C-%EA%B2%80%ED%86%A0&quot; aria-label=&quot;핵심은 작성이 아닌 검토 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;핵심은 “작성”이 아닌 “검토”&lt;/h2&gt;
&lt;p&gt;AI 커밋 메시지 생성 기능을 사용하면서 깨달은 점이 있습니다. 이 기능은 개발자를 대신하는 게 아니라, 개발자가 뇌정지하지 않게 도와주는 도구라는 것입니다. 어떻게 써야 할지 모르겠을 때도 물론 사용하겠지만 나는 이렇게 메시지를 작성했는데 AI라면 어떻게 작성했을까? 궁금할 때도 비교하는 용도로 사용하고 있어요. 실제로 비교해보면서 사고가 확장되는 경험도 많이 했어요.&lt;/p&gt;
&lt;h2 id=&quot;유저-친화적인-gitkraken의-빠른-변화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9C%A0%EC%A0%80-%EC%B9%9C%ED%99%94%EC%A0%81%EC%9D%B8-gitkraken%EC%9D%98-%EB%B9%A0%EB%A5%B8-%EB%B3%80%ED%99%94&quot; aria-label=&quot;유저 친화적인 gitkraken의 빠른 변화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;유저 친화적인 GitKraken의 빠른 변화&lt;/h2&gt;
&lt;p&gt;GitKraken을 오랫동안 사용했던 유저로서, 계속해서 업데이트하고 AI 기능을 실험적으로 시도하고 있는 부분들이 굉장히 긍정적이었어요. 이런 도구들이 개발자들의 일상적인 고민을 해결해주는 모습을 보면서, 정말 개발 환경이 많이 좋아졌다는 생각이 들어요. 혹시 GitKraken을 아직 사용해보지 않으셨다면, 한 번 체험해보시는 것도 좋을 것 같아요.&lt;/p&gt;
&lt;p&gt;아래 링크를 사용하시면 GitKraken Pro를 50% 할인된 가격에 구독하실 수 있어요.&lt;br/&gt;
&lt;a href=&quot;https://gitkraken.cello.so/u1THZtouxdr&quot;&gt;프로모션 링크&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[타입스크립트(TypeScript)로 에러 핸들링하기]]></title><description><![CDATA[기존에 try catch 문으로 에러를 처리하던 방식을 벗어나 타입스크립트로 에러를 처리해봤습니다. 에러 타입이 명확해지니 코드가 훨씬 명확해졌습니다. 1. 에러의 종류: 예상된 비즈니스 에러 vs…]]></description><link>https://donghoon-song.github.io/typescript/타입스크립트(typescript)로-에러-핸들링하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/typescript/타입스크립트(typescript)로-에러-핸들링하기/</guid><pubDate>Thu, 07 Aug 2025 22:08:50 GMT</pubDate><content:encoded>&lt;p&gt;기존에 try catch 문으로 에러를 처리하던 방식을 벗어나 타입스크립트로 에러를 처리해봤습니다. 에러 타입이 명확해지니 코드가 훨씬 명확해졌습니다.&lt;/p&gt;
&lt;h3 id=&quot;1-에러의-종류-예상된-비즈니스-에러-vs-예상치-못한-에러&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%97%90%EB%9F%AC%EC%9D%98-%EC%A2%85%EB%A5%98-%EC%98%88%EC%83%81%EB%90%9C-%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4-%EC%97%90%EB%9F%AC-vs-%EC%98%88%EC%83%81%EC%B9%98-%EB%AA%BB%ED%95%9C-%EC%97%90%EB%9F%AC&quot; aria-label=&quot;1 에러의 종류 예상된 비즈니스 에러 vs 예상치 못한 에러 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 에러의 종류: 예상된 비즈니스 에러 vs. 예상치 못한 에러&lt;/h3&gt;
&lt;p&gt;에러 핸들링 전략을 수립하기 전에, 에러를 두 가지 주요 유형으로 구분하는 것이 매우 유용했습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;예상된 비즈니스 에러 (Expected Business Errors)&lt;/strong&gt;: 시스템의 정상적인 운영 과정에서 발생할 수 있는 에러입니다. 예를 들어, 사용자 등록 시 이미 존재하는 사용자 이름을 입력하거나, 유효하지 않은 입력 값을 제출하는 경우 등이 있습니다. 이러한 에러는 사용자에게 명확한 피드백을 제공하고, 경우에 따라 사용자가 직접 문제를 해결할 수 있도록 안내해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;예상치 못한 에러 (Unexpected Errors)&lt;/strong&gt;: 시스템의 정상적인 작동 중에는 발생하지 않을 것으로 예상되는 에러입니다. 데이터베이스 연결 실패, 서버 내부 로직 오류, 외부 API 호출 실패 등이 여기에 해당합니다. 이러한 에러는 일반적으로 복구하기 어렵고, 개발자에게 알림을 보내고 로그를 기록하는 것이 주된 처리 방법이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;어떤 에러가 예상된 에러이고 예상치 못한 에러인지는 애플리케이션의 도메인과 비즈니스 로직에 따라 달라질 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;2-전통적인-code-classlanguage-texttrycatchcode와-code-classlanguage-textthrowcode의-기본과-한계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EC%A0%84%ED%86%B5%EC%A0%81%EC%9D%B8-code-classlanguage-texttrycatchcode%EC%99%80-code-classlanguage-textthrowcode%EC%9D%98-%EA%B8%B0%EB%B3%B8%EA%B3%BC-%ED%95%9C%EA%B3%84&quot; aria-label=&quot;2 전통적인 code classlanguage texttrycatchcode와 code classlanguage textthrowcode의 기본과 한계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. 전통적인 &lt;code class=&quot;language-text&quot;&gt;try...catch&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;의 기본과 한계&lt;/h3&gt;
&lt;p&gt;JavaScript에서 에러를 발생시키고 처리하는 가장 기본적인 방법은 &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;try...catch&lt;/code&gt; 문입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 에러 발생시키기 (throw)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;User with id &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; not found&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 수동으로 에러 발생&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; user
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 에러 잡기 (try...catch)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;An error occurred:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;code-classlanguage-textunknowncode-타입-에러와-타입-좁히기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code-classlanguage-textunknowncode-%ED%83%80%EC%9E%85-%EC%97%90%EB%9F%AC%EC%99%80-%ED%83%80%EC%9E%85-%EC%A2%81%ED%9E%88%EA%B8%B0&quot; aria-label=&quot;code classlanguage textunknowncode 타입 에러와 타입 좁히기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; 타입 에러와 타입 좁히기&lt;/h4&gt;
&lt;p&gt;TypeScript에서 &lt;code class=&quot;language-text&quot;&gt;catch&lt;/code&gt; 블록의 &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt; 변수는 기본적으로 &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; 타입입니다. 이는 JavaScript에서 문자열, 숫자, 객체 등 어떤 것이든 &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;될 수 있기 때문입니다. &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; 타입의 에러를 다루기 위해서는 해당 에러의 타입을 명확히 좁혀야 합니다. &lt;code class=&quot;language-text&quot;&gt;instanceof&lt;/code&gt; 연산자를 사용하여 에러의 타입을 좁힐 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Error 인스턴스인지 확인하여 타입 좁히기&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Error message:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;An unknown error occurred:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;code-classlanguage-textthrowcode의-한계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code-classlanguage-textthrowcode%EC%9D%98-%ED%95%9C%EA%B3%84&quot; aria-label=&quot;code classlanguage textthrowcode의 한계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;의 한계&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;try...catch&lt;/code&gt;는 간단하지만 몇 가지 한계가 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;모든 가능한 에러에 대한 지식 요구&lt;/strong&gt;: 함수가 어떤 에러를 던질 수 있는지 파악하려면 해당 함수와 그 함수가 호출하는 모든 함수를 검사해야 합니다. 이는 문서화가 최신 상태로 유지되지 않으면 파악하기 어렵습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;제어 흐름의 불연속성&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;가 발생하면 코드의 제어 흐름이 예측하기 어렵게 “점프”합니다. 코드를 읽는 사람이 &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; 문을 만났을 때 해당 에러가 어디서 처리될지 (또는 처리될지 여부) 파악하기 어렵습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;3-객체-지향적-접근-커스텀-에러-클래스-활용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5%EC%A0%81-%EC%A0%91%EA%B7%BC-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%97%90%EB%9F%AC-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%99%9C%EC%9A%A9&quot; aria-label=&quot;3 객체 지향적 접근 커스텀 에러 클래스 활용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. 객체 지향적 접근: 커스텀 에러 클래스 활용&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; 타입 에러 문제를 해결하고 에러를 더 구조적으로 관리하기 위해 커스텀 에러 클래스를 정의하는 디자인 패턴이 유용합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;커스텀 에러 타입 생성&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;Error&lt;/code&gt; 객체를 확장하는 클래스를 정의합니다. 이 클래스는 스택 트레이스를 포함할 수 있게 해줍니다. 에러 이름에 대한 유니온 타입을 유지하여 타입 안전성과 자동 완성을 제공할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// errors.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProjectErrorName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_LIMIT_REACHED&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_NOT_FOUND&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProjectError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProjectErrorName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setPrototypeOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ProjectError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 상속 체인 유지&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;커스텀 에러 던지기&lt;/strong&gt;: 새로운 커스텀 에러를 인스턴스화할 때, 정의된 유니온 타입 내에서 &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt; 값을 선택할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createProject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; projectName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserProjectCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_PROJECT_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProjectError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_LIMIT_REACHED&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;프로젝트 생성 한도에 도달했습니다.&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... 프로젝트 생성 로직&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;커스텀 에러 잡기&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;catch&lt;/code&gt; 블록에서 &lt;code class=&quot;language-text&quot;&gt;instanceof&lt;/code&gt;를 사용하여 커스텀 에러 타입을 좁힐 수 있습니다. 에러가 좁혀지면 &lt;code class=&quot;language-text&quot;&gt;error.name&lt;/code&gt;을 통해 특정 에러에 대한 로직을 수행할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;createProject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;My New Project&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProjectError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_LIMIT_REACHED&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;사용자에게 메시지 표시:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_NOT_FOUND&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;프로젝트를 찾을 수 없습니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;일반 에러:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;알 수 없는 에러:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;재사용 가능한 에러 베이스 만들기&lt;/strong&gt;: 여러 도메인에서 커스텀 에러 클래스를 사용해야 할 경우, DRY(Don’t Repeat Yourself) 원칙을 위해 제네릭을 사용하는 &lt;code class=&quot;language-text&quot;&gt;ErrorBase&lt;/code&gt; 클래스를 만들 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// base-error.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ErrorBase&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setPrototypeOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// project-errors.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProjectErrorName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_LIMIT_REACHED&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PROJECT_NOT_FOUND&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProjectError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ErrorBase&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ProjectErrorName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;4-함수형-접근-code-classlanguage-textresultcode-타입-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-%ED%95%A8%EC%88%98%ED%98%95-%EC%A0%91%EA%B7%BC-code-classlanguage-textresultcode-%ED%83%80%EC%9E%85-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;4 함수형 접근 code classlanguage textresultcode 타입 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. 함수형 접근: &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; 타입 패턴&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; 방식의 한계를 극복하기 위해 함수형 프로그래밍에서 영감을 받은 &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; 타입을 사용하는 방법이 있습니다. 이 접근 방식은 함수가 에러를 발생시킬 수 있다는 사실을 반환 타입에 명시적으로 인코딩합니다.&lt;/p&gt;
&lt;h4 id=&quot;code-classlanguage-textresultltt-ecode-타입의-개념&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code-classlanguage-textresultltt-ecode-%ED%83%80%EC%9E%85%EC%9D%98-%EA%B0%9C%EB%85%90&quot; aria-label=&quot;code classlanguage textresultltt ecode 타입의 개념 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T, E&gt;&lt;/code&gt; 타입의 개념&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; 타입은 성공적인 값(&lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;) 또는 에러 값(&lt;code class=&quot;language-text&quot;&gt;E&lt;/code&gt;) 중 하나를 포함할 수 있는 공용체(discriminated union)입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;E&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newUser&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NewUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Error&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; newUser &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Username already taken&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 호출 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hunter2&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Failed to create user: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;User created: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 방식은 함수가 반환할 수 있는 모든 에러를 명시적으로 선언하므로, 호출하는 쪽에서 어떤 에러를 처리해야 하는지 쉽게 알 수 있습니다. 또한, 제어 흐름이 순차적으로 진행되어 코드 가독성이 향상됩니다.&lt;/p&gt;
&lt;p&gt;함수형 접근을 하니 예상된 비즈니스 에러를 핸들링하기 수월해졌고 catch 절에서는 여전히 예상치 못한 에러를 처리할 수 있어서 컨텍스트를 분리해서 생각할 수 있었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[엔지니어링 리더십 – 실력 있는 개발자에서 조직적 영향력자로 성장하기까지]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/엔지니어링-리더십-–-실력-있는-개발자에서-조직적-영향력자로-성장하기까지/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/엔지니어링-리더십-–-실력-있는-개발자에서-조직적-영향력자로-성장하기까지/</guid><pubDate>Fri, 30 May 2025 21:06:25 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div style=&quot;display: flex; flex-direction: column; align-items:center; margin: 2rem 0;&quot;&gt;
  &lt;img src=&quot;https://cdn-prod.hanbit.co.kr/books/B1433757806_l.jpg&quot; alt=&quot;엔지니어링 리더십 책 표지&quot; style=&quot;max-width: 300px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1);&quot;&gt;
&lt;/div&gt;
&lt;p&gt;시니어 개발자라면 누구나 한번쯤 고민한다. &lt;strong&gt;“다음 단계는 무엇인가?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;윌 라슨의 『엔지니어링 리더십』은 그 질문에 조직적 영향력과 기술적 전략을 통해 답한다. 스태프 엔지니어의 역할을 다루는 이 책은, 특히 다음 세 가지 주제를 깊이 있고 현실감 있게 다룬다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;엔지니어링 전략 세우기&lt;/li&gt;
&lt;li&gt;리더십 스타일 개발하기&lt;/li&gt;
&lt;li&gt;우선순위와 에너지 관리하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 리뷰는 이 세 가지 관점에 집중해, 실제 실무에 어떤 통찰을 줄 수 있는지 살펴본다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;엔지니어링-전략-수립-실행-가능한-기술-방향을-설계하라&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81-%EC%A0%84%EB%9E%B5-%EC%88%98%EB%A6%BD-%EC%8B%A4%ED%96%89-%EA%B0%80%EB%8A%A5%ED%95%9C-%EA%B8%B0%EC%88%A0-%EB%B0%A9%ED%96%A5%EC%9D%84-%EC%84%A4%EA%B3%84%ED%95%98%EB%9D%BC&quot; aria-label=&quot;엔지니어링 전략 수립 실행 가능한 기술 방향을 설계하라 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;엔지니어링 전략 수립: 실행 가능한 기술 방향을 설계하라&lt;/h2&gt;
&lt;p&gt;『엔지니어링 리더십』은 전략을 &lt;strong&gt;‘문서화된 방향성’이 아니라, 조직이 실제로 따라가고 싶은 기술적 경로&lt;/strong&gt;로 정의한다.&lt;/p&gt;
&lt;p&gt;단순히 기술 스택을 정하는 것이 아니라, **“우리가 왜 이 방향으로 가야 하는가”**를 팀 전체가 이해하고 납득하도록 만드는 것이 핵심이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“전략 없는 엔지니어링은, 구현만 있고 목적이 없다.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;전략은 기술적 선택뿐 아니라, 리소스 분배, 기술 부채 관리, 아키텍처 결정까지 관통한다. 나는 이 부분을 읽고 나서 팀에 ‘기술 투자 우선순위 문서’를 만들어서, 리팩터링과 신기능 사이의 판단 기준을 명확히 하기 시작했다.&lt;/p&gt;
&lt;p&gt;실제로 이 문서 덕분에 팀 내에서 “이번 스프린트에 리팩터링을 할까, 신기능을 만들까?”라는 논의가 훨씬 구체적이고 생산적으로 바뀌었다. 단순히 개발자의 취향이나 그때그때 상황에 따라 결정하는 게 아니라, 명확한 기준에 따라 판단할 수 있게 된 것이다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;리더십-스타일-개발-복제-가능한-리더가-되지-마라&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%EB%8D%94%EC%8B%AD-%EC%8A%A4%ED%83%80%EC%9D%BC-%EA%B0%9C%EB%B0%9C-%EB%B3%B5%EC%A0%9C-%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%A6%AC%EB%8D%94%EA%B0%80-%EB%90%98%EC%A7%80-%EB%A7%88%EB%9D%BC&quot; aria-label=&quot;리더십 스타일 개발 복제 가능한 리더가 되지 마라 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리더십 스타일 개발: 복제 가능한 리더가 되지 마라&lt;/h2&gt;
&lt;p&gt;책에서 특히 인상적인 점은, **‘리더십은 따라 하는 게 아니라 구축하는 것’**이라는 메시지다.&lt;/p&gt;
&lt;p&gt;각자의 리더십은 자신이 만든 성공 경험, 성격, 신념에서 나온다. 그래서 책은 이렇게 묻는다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;당신은 결정을 빠르게 내리는 타입인가?&lt;/li&gt;
&lt;li&gt;조율과 설득에 강점을 두는가?&lt;/li&gt;
&lt;li&gt;문제 해결에 열정을 가지는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“당신의 리더십 스타일은, 당신이 꾸준히 반복한 선택들의 결과다.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 말은 마치 코딩 스타일을 정립하는 것처럼, 리더십도 자기화해야 지속 가능하다는 통찰을 준다.&lt;/p&gt;
&lt;p&gt;나는 이걸 계기로, 의견 충돌 시 나의 접근 방식, 회고 작성 방식, PR 리뷰 피드백 스타일 등을 분석해서 **‘내가 지향하는 리더십 톤’**을 정리해봤다.&lt;/p&gt;
&lt;p&gt;예를 들어, 나는 직접적인 피드백보다는 질문을 통해 상대방이 스스로 답을 찾도록 유도하는 편이라는 걸 깨달았다. “이 코드가 문제야”라고 말하기보다는 “이 부분에서 예상되는 시나리오는 뭐가 있을까?”라고 묻는 식으로 말이다. 이런 패턴을 의식적으로 정리하니, 팀 커뮤니케이션이 훨씬 일관되고 예측 가능해졌다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;우선순위와-에너지-관리-임팩트-있는-것에-집중하라&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%EC%99%80-%EC%97%90%EB%84%88%EC%A7%80-%EA%B4%80%EB%A6%AC-%EC%9E%84%ED%8C%A9%ED%8A%B8-%EC%9E%88%EB%8A%94-%EA%B2%83%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EB%9D%BC&quot; aria-label=&quot;우선순위와 에너지 관리 임팩트 있는 것에 집중하라 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;우선순위와 에너지 관리: 임팩트 있는 것에 집중하라&lt;/h2&gt;
&lt;p&gt;성장할수록 일이 많아지는 게 아니라, &lt;strong&gt;집중해야 할 일이 명확해진다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;이 책은 단순한 할 일 관리보다 훨씬 높은 수준의 메타인지 전략을 다룬다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“모든 기술 과제를 처리할 수는 없다. 처리할 가치가 있는 일을 선택하는 것이 리더십이다.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;책은 우선순위를 ‘비용 대비 가치’로 판단하라고 말하지 않는다. 오히려 &lt;strong&gt;조직이 가장 아파하는 지점을 식별하고, 거기에 기술적 해법을 던질 수 있는 역량&lt;/strong&gt;을 강조한다. 이를 위해선 자기 에너지를 어디에 쓸지 먼저 정해야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;나 역시 업무량이 과중했던 시기에, ‘조직 전체가 겪는 병목을 해결하면 내 시간도 줄어든다’는 인식 전환으로 릴리즈 자동화 파이프라인을 먼저 개선했다.&lt;/p&gt;
&lt;p&gt;당시에는 매번 배포할 때마다 개발자들이 수동으로 체크리스트를 확인하고, 슬랙에서 “배포 시작합니다”, “배포 완료했습니다” 메시지를 주고받았다. 하루에 3-4번씩 이런 과정을 반복하다 보니 정작 개발에 집중할 시간이 부족했다.&lt;/p&gt;
&lt;p&gt;자동화 파이프라인을 구축한 후에는 팀 전체의 생산성이 눈에 띄게 올라갔고, 결과적으로 내 업무 부담도 크게 줄었다. 이 책은 그런 시야의 전환을 도와준다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;총평-직급이-아닌-전략으로-리드하라&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B4%9D%ED%8F%89-%EC%A7%81%EA%B8%89%EC%9D%B4-%EC%95%84%EB%8B%8C-%EC%A0%84%EB%9E%B5%EC%9C%BC%EB%A1%9C-%EB%A6%AC%EB%93%9C%ED%95%98%EB%9D%BC&quot; aria-label=&quot;총평 직급이 아닌 전략으로 리드하라 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;총평: 직급이 아닌 전략으로 리드하라&lt;/h2&gt;
&lt;p&gt;『엔지니어링 리더십』은 단순한 직책이 아니라, &lt;strong&gt;기술적 영향력의 디자인 방법&lt;/strong&gt;을 알려주는 책이다.&lt;/p&gt;
&lt;p&gt;스태프 엔지니어라는 포지션을 빌려, 어떻게 전략적으로 사고하고, 자기 리더십을 정의하고, 에너지를 임팩트 있게 배분할 수 있는지를 정제된 언어로 전달한다.&lt;/p&gt;
&lt;p&gt;특히 이 책이 좋은 점은, 추상적인 리더십 이론이 아니라 &lt;strong&gt;실제 엔지니어링 조직에서 마주하는 구체적인 상황들&lt;/strong&gt;을 다룬다는 것이다. 기술 부채를 어떻게 관리할지, 팀 간 의견 충돌을 어떻게 조율할지, 한정된 리소스로 어떤 프로젝트를 우선할지 같은 현실적인 고민들 말이다.&lt;/p&gt;
&lt;h3 id=&quot;추천-대상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%94%EC%B2%9C-%EB%8C%80%EC%83%81&quot; aria-label=&quot;추천 대상 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;추천 대상&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;기술 방향 설정에 관여하고 싶은 시니어 개발자&lt;/li&gt;
&lt;li&gt;비공식적 리더 역할을 수행 중인 팀원&lt;/li&gt;
&lt;li&gt;“잘하는 개발자”에서 “조직에 필요한 기술 리더”로 성장하고 싶은 사람&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;한줄-평&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%9C%EC%A4%84-%ED%8F%89&quot; aria-label=&quot;한줄 평 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;한줄 평&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;“혼자 잘하는 개발자에서, 조직을 설계하는 기술 리더로 가는 가장 명료한 로드맵.”&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[FormData 전송 시 Content-Type 헤더를 설정하면 안 되는 이유]]></title><description><![CDATA[“왜 파일 업로드가 계속 실패하지?” - 많은 개발자들이 겪는 흔한 실수 🤔 문제 상황 파일 업로드 기능을 구현했는데 이유없이 실패하는 문제를 맞닥뜨렸다. 서버에서는 400 Bad Request…]]></description><link>https://donghoon-song.github.io/web/formdata-전송-시-content-type-헤더를-설정하면-안-되는-이유/</link><guid isPermaLink="false">https://donghoon-song.github.io/web/formdata-전송-시-content-type-헤더를-설정하면-안-되는-이유/</guid><pubDate>Sat, 24 May 2025 09:05:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;“왜 파일 업로드가 계속 실패하지?” - 많은 개발자들이 겪는 흔한 실수&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;-문제-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%AC%B8%EC%A0%9C-%EC%83%81%ED%99%A9&quot; aria-label=&quot; 문제 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🤔 문제 상황&lt;/h2&gt;
&lt;p&gt;파일 업로드 기능을 구현했는데 이유없이 실패하는 문제를 맞닥뜨렸다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 이렇게 했는데 왜 안 될까? 🤷‍♂️&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;file&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/upload&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;multipart/form-data&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 이게 문제!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;서버에서는 400 Bad Request나 파일 파싱 오류가 발생하고, 몇 시간을 디버깅해도 원인을 찾기 어려웠다.&lt;/p&gt;
&lt;h2 id=&quot;-해결책-헤더를-아예-생략하세요&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%ED%95%B4%EA%B2%B0%EC%B1%85-%ED%97%A4%EB%8D%94%EB%A5%BC-%EC%95%84%EC%98%88-%EC%83%9D%EB%9E%B5%ED%95%98%EC%84%B8%EC%9A%94&quot; aria-label=&quot; 해결책 헤더를 아예 생략하세요 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;💡 해결책: 헤더를 아예 생략하세요&lt;/h2&gt;
&lt;p&gt;이것저것 찾아본 결과 내가 찾은 해결책은 정말 파격적이었다. formData를 보낼 때마다 당연히 헤더를 설정했는데 말이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ✅ 올바른 방법&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;file&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;My awesome file&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/upload&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 끝! 이게 전부입니다.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;-왜-이런-일이-생길까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%99%9C-%EC%9D%B4%EB%9F%B0-%EC%9D%BC%EC%9D%B4-%EC%83%9D%EA%B8%B8%EA%B9%8C&quot; aria-label=&quot; 왜 이런 일이 생길까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🔍 왜 이런 일이 생길까?&lt;/h2&gt;
&lt;h3 id=&quot;boundary의-비밀&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#boundary%EC%9D%98-%EB%B9%84%EB%B0%80&quot; aria-label=&quot;boundary의 비밀 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Boundary의 비밀&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;multipart/form-data&lt;/code&gt;로 데이터를 전송할 때, 각 필드를 구분하기 위해 &lt;strong&gt;boundary&lt;/strong&gt;라는 특별한 구분자가 필요하다.&lt;/p&gt;
&lt;p&gt;아래와 같이 boundary가 없는 경우 서버는 어떤 문자열로 필드를 구분해야 하는지 모르게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;john_doe&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;john@example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bio&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;I love coding!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Content-Disposition: form-data; name=&quot;username&quot;
john_doe
Content-Disposition: form-data; name=&quot;email&quot;
john@example.com
Content-Disposition: form-data; name=&quot;bio&quot;
I love coding!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아래와 같이 boundary가 있는 경우 서버는 어떤 문자열로 필드를 구분해야 하는지 알 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;photo.jpg&quot;
Content-Type: image/jpeg

[파일 바이너리 데이터]
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=&quot;description&quot;

My awesome file
------WebKitFormBoundary7MA4YWxkTrZu0gW--&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;------WebKitFormBoundary7MA4YWxkTrZu0gW&lt;/code&gt;가 바로 boundary다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ❌ 이렇게 하면...&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;multipart/form-data&apos;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// boundary가 없음!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 내가 헤더를 수동으로 설정하면 boundary가 포함되지 않는다. 그래서 서버는 “어떤 문자열로 필드를 구분해야 하는지” 모르게 된다. 마치 책에서 페이지 번호가 없는 것과 같다.&lt;/p&gt;
&lt;h2 id=&quot;-올바른-동작-원리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%98%AC%EB%B0%94%EB%A5%B8-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC&quot; aria-label=&quot; 올바른 동작 원리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🛠 올바른 동작 원리&lt;/h2&gt;
&lt;h3 id=&quot;자동-설정-과정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%90%EB%8F%99-%EC%84%A4%EC%A0%95-%EA%B3%BC%EC%A0%95&quot; aria-label=&quot;자동 설정 과정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;자동 설정 과정&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;FormData 감지&lt;/strong&gt;: axios가 요청 본문이 FormData 객체임을 인식&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boundary 생성&lt;/strong&gt;: 고유한 랜덤 문자열 생성 (예: &lt;code class=&quot;language-text&quot;&gt;----formdata-axios-0.27.2-1234567890&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;헤더 설정&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;Content-Type: multipart/form-data; boundary=----formdata-axios-0.27.2-1234567890&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 구성&lt;/strong&gt;: 생성된 boundary로 각 필드를 구분하여 전송&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;개발자-도구에서-확인해보기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%9C%EB%B0%9C%EC%9E%90-%EB%8F%84%EA%B5%AC%EC%97%90%EC%84%9C-%ED%99%95%EC%9D%B8%ED%95%B4%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;개발자 도구에서 확인해보기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;개발자 도구에서 확인해보기&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;file&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/upload&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Network 탭에서 Request Headers를 보면:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Content-Type: multipart/form-data; boundary=----formdata-axios-0.27.2-16789012345&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;-다른-http-클라이언트들도-마찬가지&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%8B%A4%EB%A5%B8-http-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EB%93%A4%EB%8F%84-%EB%A7%88%EC%B0%AC%EA%B0%80%EC%A7%80&quot; aria-label=&quot; 다른 http 클라이언트들도 마찬가지 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🌐 다른 HTTP 클라이언트들도 마찬가지&lt;/h2&gt;
&lt;p&gt;이는 axios만의 특별한 기능이 아니다. &lt;strong&gt;모든 HTTP 클라이언트&lt;/strong&gt;에서 동일하다.&lt;/p&gt;
&lt;h3 id=&quot;fetch-api&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#fetch-api&quot; aria-label=&quot;fetch api permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fetch API&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ✅ 올바른 방법&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/upload&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Content-Type 자동 설정&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;curl&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#curl&quot; aria-label=&quot;curl permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;cURL&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# ✅ 자동으로 boundary 설정&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; POST &lt;span class=&quot;token parameter variable&quot;&gt;-F&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file=@photo.jpg&quot;&lt;/span&gt; http://example.com/upload&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;nodejs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nodejs&quot; aria-label=&quot;nodejs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Node.js&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Node.js에서 form-data 라이브러리 사용 시&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; FormData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;form-data&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;file&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createReadStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;file.txt&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/upload&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; form&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 올바른 헤더 자동 생성&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;왜-모든-클라이언트가-이렇게-동작하는가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%9C-%EB%AA%A8%EB%93%A0-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EA%B0%80-%EC%9D%B4%EB%A0%87%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94%EA%B0%80&quot; aria-label=&quot;왜 모든 클라이언트가 이렇게 동작하는가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왜 모든 클라이언트가 이렇게 동작하는가?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc7578&quot;&gt;HTTP 표준 (RFC 7578)&lt;/a&gt;에서 정의:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;multipart/form-data는 반드시 boundary 파라미터가 필요&lt;/li&gt;
&lt;li&gt;Boundary는 고유하고 예측 불가능한 문자열이어야 함&lt;/li&gt;
&lt;li&gt;각 구현체(브라우저, 라이브러리)가 자동으로 생성하도록 설계&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;-핵심-정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%ED%95%B5%EC%8B%AC-%EC%A0%95%EB%A6%AC&quot; aria-label=&quot; 핵심 정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🎯 핵심 정리&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;FormData 사용 시 Content-Type 헤더를 생략하기&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP 클라이언트가 자동으로 올바른 boundary와 함께 설정한다&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;이는 웹 표준(RFC 7578)을 따르는 모든 구현체의 공통 동작이다&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[패턴으로 익히고 설계로 완성하는 리액트 리뷰(한빛미디어)]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/패턴으로-익히고-설계로-완성하는-리액트-리뷰(한빛미디어)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/패턴으로-익히고-설계로-완성하는-리액트-리뷰(한빛미디어)/</guid><pubDate>Thu, 27 Mar 2025 21:04:16 GMT</pubDate><content:encoded>&lt;h3 id=&quot;한빛미디어-서평단-나는리뷰어다-활동을-위해서-책을-협찬-받아-작성된-서평입니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%9C%EB%B9%9B%EB%AF%B8%EB%94%94%EC%96%B4-%EC%84%9C%ED%8F%89%EB%8B%A8-%EB%82%98%EB%8A%94%EB%A6%AC%EB%B7%B0%EC%96%B4%EB%8B%A4-%ED%99%9C%EB%8F%99%EC%9D%84-%EC%9C%84%ED%95%B4%EC%84%9C-%EC%B1%85%EC%9D%84-%ED%98%91%EC%B0%AC-%EB%B0%9B%EC%95%84-%EC%9E%91%EC%84%B1%EB%90%9C-%EC%84%9C%ED%8F%89%EC%9E%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;한빛미디어 서평단 나는리뷰어다 활동을 위해서 책을 협찬 받아 작성된 서평입니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“한빛미디어 서평단 &amp;#x3C;나는리뷰어다&gt; 활동을 위해서 책을 협찬 받아 작성된 서평입니다.”&lt;/h3&gt;
&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B2951140790_l.jpg&quot; alt=&quot;책 표지&quot;&gt;
  출처: 한빛미디어
&lt;/div&gt;
&lt;h2 id=&quot;책-소개&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B1%85-%EC%86%8C%EA%B0%9C&quot; aria-label=&quot;책 소개 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;책 소개&lt;/h2&gt;
&lt;p&gt;최근에 어떻게 하면 코드를 더 잘 짤 수 있을지 고민하다가 『패턴으로 익히고 설계로 완성하는 리액트』라는 책을 접했다. 표지의 “패턴”과 “설계”라는 글자가 와닿았고 TDD와 리팩터링으로 계속 코드를 개선하는 가이드를 제시해줄 것이라고 기대했다.&lt;/p&gt;
&lt;h2 id=&quot;책의-구성-및-내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B1%85%EC%9D%98-%EA%B5%AC%EC%84%B1-%EB%B0%8F-%EB%82%B4%EC%9A%A9&quot; aria-label=&quot;책의 구성 및 내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;책의 구성 및 내용&lt;/h2&gt;
&lt;p&gt;이 책은 리액트 애플리케이션 개발 시 자주 발생하는 안티패턴을 정의하고, 이를 해결하기 위한 설계 원칙과 패턴을 제시한다. 특히 TDD(테스트 주도 개발)와 리팩터링을 통해 코드 품질을 높이는 방법을 실용적인 예제를 통해 보여준다.&lt;/p&gt;
&lt;p&gt;책은 크게 리액트 기본 개념, 안티패턴 이해하기, 효과적인 패턴과 테스트 방법, 그리고 실제 프로젝트 구현 등의 섹션으로 나누어져 있다.&lt;/p&gt;
&lt;h2 id=&quot;part2-테스팅-기법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part2-%ED%85%8C%EC%8A%A4%ED%8C%85-%EA%B8%B0%EB%B2%95&quot; aria-label=&quot;part2 테스팅 기법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Part2 테스팅 기법&lt;/h2&gt;
&lt;p&gt;Part2에서 테스트 방법론 같은 부분은 다른 책과 내용이 비슷했다. 하지만 7장에서 테스트 주도 개발을 제대로 보여줬다. 예시로 ‘코드 오븐’ 애플리케이션을 만들었는데 요구사항 분석과 세분화를 통해 테스트를 먼저 짜놓고 컴포넌트 개발에 들어갔다.&lt;/p&gt;
&lt;h2 id=&quot;part3-비즈니스-로직과-디자인-패턴-알아보기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part3-%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4-%EB%A1%9C%EC%A7%81%EA%B3%BC-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;part3 비즈니스 로직과 디자인 패턴 알아보기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Part3 비즈니스 로직과 디자인 패턴 알아보기&lt;/h2&gt;
&lt;p&gt;가장 관심있던 부분은 &lt;code class=&quot;language-text&quot;&gt;Part3 비즈니스 로직과 디자인 패턴 알아보기&lt;/code&gt;였다. 요즘에 비즈니스 로직을 어떻게 잘 분리해서 작성할 수 있을지 고민이 많았기 때문이다. Part3의 내용을 요약해보면 다음과 같다.&lt;/p&gt;
&lt;h3 id=&quot;acl오류-방지-계층anti-corruption-layer&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#acl%EC%98%A4%EB%A5%98-%EB%B0%A9%EC%A7%80-%EA%B3%84%EC%B8%B5anti-corruption-layer&quot; aria-label=&quot;acl오류 방지 계층anti corruption layer permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ACL(오류 방지 계층)(Anti-Corruption Layer)&lt;/h3&gt;
&lt;p&gt;ACL은 각각 다른 언어를 사용하는 다른 서브시스템 간의 중재자 역할을 한다. 프론트엔드 ACL은 서버에서 받아 온 데이터를 프론트엔드에서 이해할 수 있는 형태로 변환한다. 그리고 캐시 처리, 오류 변환과 같은 여러 문제를 처리하는 전략 계층으로도 활용할 수 있다.&lt;/p&gt;
&lt;p&gt;변환 함수를 사용하면 백엔드에서 주는 데이터 형식이 바뀌더라도 변경의 범위를 변환 함수로 제한할 수 있기 때문에 컴포넌트를 보존할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;context-api를-통한-prop-drilling-문제-해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#context-api%EB%A5%BC-%ED%86%B5%ED%95%9C-prop-drilling-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;context api를 통한 prop drilling 문제 해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Context API를 통한 Prop Drilling 문제 해결&lt;/h3&gt;
&lt;p&gt;보통의 Prop Drilling은 상태값을 넘길 때 일어났지만 예시에서는 함수를 넘길 때의 상황을 다뤘다. 겹겹이 쌓인 컴포넌트에서 자식 컴포넌트의 onClick 함수를 그대로 전달하기 위해 부모 컴포넌트를 무의미하게 거치는 상황을 Context API를 통해 해결했다. 그러면 자식 컴포넌트에서 바로 onClick 함수에 접근이 가능해진다.&lt;/p&gt;
&lt;h3 id=&quot;단일-책임-원칙&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A8%EC%9D%BC-%EC%B1%85%EC%9E%84-%EC%9B%90%EC%B9%99&quot; aria-label=&quot;단일 책임 원칙 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;단일 책임 원칙&lt;/h3&gt;
&lt;p&gt;가장 많이 사용되는 기술&lt;/p&gt;
&lt;h4 id=&quot;render-prop&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#render-prop&quot; aria-label=&quot;render prop permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;render prop&lt;/h4&gt;
&lt;p&gt;리액트 컴포넌트 간 코드 공유를 위해 함수 prop을 사용&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Title&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;부모 컴포넌트가 자식 컴포넌트의 렌더링 로직을 제어할 수 있어 컴포넌트를 더욱 유연하게 하고 재사용할 수 있게 한다.&lt;/p&gt;
&lt;p&gt;핵심 로직을 변경하지 않고 컴포넌트 동작을 확장하거나 사용자에 맞게 지정할 수 있다.&lt;/p&gt;
&lt;h4 id=&quot;합성composition&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%A9%EC%84%B1composition&quot; aria-label=&quot;합성composition permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;합성(composition)&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;MyAvatar&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Tooltip&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My Avatar&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Avatar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Tooltip&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;예제와 같이 Tooltip 컴포넌트와 Avatar 컴포넌트를 분리함으로써 각자의 역할을 하면서 서로 합성할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;part4-실무에서의-구현&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#part4-%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C%EC%9D%98-%EA%B5%AC%ED%98%84&quot; aria-label=&quot;part4 실무에서의 구현 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Part4 실무에서의 구현&lt;/h2&gt;
&lt;p&gt;Part4에서는 앞에서 배운 개념들을 가지고 ‘코드 오븐’이라는 피자 가게 애플리케이션을 개발한다. 여기서는 타입을 클래스 기반의 모델로 변환하면서 데이터의 모든 변환 로직을 이곳에 모은다. 그리고 전략 패턴을 통해 할인을 제공하는 등의 요구사항을 개발했다. 이렇게 개발한 코드들을 마지막 계층 구조 챕터에서 봤을 때 유지 보수하기 쉬운 코드가 되었다는걸 알 수 있었다.&lt;/p&gt;
&lt;h2 id=&quot;정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리&lt;/h2&gt;
&lt;p&gt;책의 난이도는 어렵지 않은 편이라서 프론트엔드 개발자라면 누구나 읽을 수 있을 것이다. 그리고 이론과 실제 예제의 조화가 적절하고 예제가 이론을 이해하는데 큰 도움이 됐다.
어떻게 하면 더 나은 코드를 작성할 수 있을지 고민하고 있다면 큰 도움이 될 거라고 생각한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[최근에 내가 구현했던 흔하지 않았던 UI들 모음]]></title><description><![CDATA[프론트엔드 개발자로 일하다 보면 디자이너가 제안한 UI를 구현하는 과정에서 표준 패턴만으로는 해결하기 어려운 상황을 종종 마주치게 된다. 이런 사례들을 해결하다 보면 역시 css 세계는 드넓구나 하는 생각이 들고 css…]]></description><link>https://donghoon-song.github.io/css/최근에-내가-구현했던-흔하지-않았던-ui들-모음/</link><guid isPermaLink="false">https://donghoon-song.github.io/css/최근에-내가-구현했던-흔하지-않았던-ui들-모음/</guid><pubDate>Sun, 16 Mar 2025 16:03:15 GMT</pubDate><content:encoded>&lt;p&gt;프론트엔드 개발자로 일하다 보면 디자이너가 제안한 UI를 구현하는 과정에서 표준 패턴만으로는 해결하기 어려운 상황을 종종 마주치게 된다. 이런 사례들을 해결하다 보면 역시 css 세계는 드넓구나 하는 생각이 들고 css의 가능성에 대해서 더 시야가 트이는 것 같다. 그리고 거기서 찾아오는 성취감은 덤이다. 사례가 아직 많진 않지만 마주할 때마다 이것도 모아두면 유용한 참고자료가 되지 않을까 싶어서 적어보고 계속해서 업데이트 해보려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;1-중간에-있는-텍스트-truncateellipsis하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%A4%91%EA%B0%84%EC%97%90-%EC%9E%88%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8-truncateellipsis%ED%95%98%EA%B8%B0&quot; aria-label=&quot;1 중간에 있는 텍스트 truncateellipsis하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 중간에 있는 텍스트 truncate(ellipsis)하기&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/ZfI1NLE.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;보통 truncate는 이렇게 텍스트 전체에 적용하거나 끝 부분에 적용한다. 그리고 이런 효과를 주기 위해서 다음 속성들을 활용한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;overflow: hidden&lt;/code&gt;으로 컨테이너를 벗어나는 텍스트를 숨긴다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;text-overflow: ellipsis&lt;/code&gt;로 숨겨진 텍스트 대신 말줄임표를 표시한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/Xxr1aqJ.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;하지만 중간 텍스트에 truncate를 적용해야 하는 경우가 생겼다. 처음엔 어떻게 구현하지 싶었는데 같은 원리를 적용하니까 수월하게 풀렸다. 적용할 텍스트를 &lt;code class=&quot;language-text&quot;&gt;inline-block&lt;/code&gt;으로 만들었고 텍스트 정렬이 틀어지기 때문에 &lt;code class=&quot;language-text&quot;&gt;vertical-align&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;bottom&lt;/code&gt;으로 바꿨다.(&lt;a href=&quot;http://localhost:8000/css/textarea%EB%A5%BC-%EA%B0%90%EC%8B%B8%EB%8A%94-div%EC%97%90-%EC%97%AC%EB%B0%B1%EC%9D%B4-%EC%83%9D%EA%B2%A8%EB%B2%84%EB%A6%AC%EB%8A%94-%EC%9D%B4%EC%9C%A0/&quot;&gt;이렇게 처리하는 이유&lt;/a&gt;) 그 다음엔 똑같이 width 제한을 주고 text-overflow 등을 조절했다.&lt;/p&gt;
&lt;p&gt;이 방식의 핵심은 텍스트를 블록 요소처럼 다루면서도 인라인 흐름을 유지하는 것이다. &lt;code class=&quot;language-text&quot;&gt;inline-block&lt;/code&gt;은 요소가 인라인 요소처럼 텍스트 흐름 내에 배치되면서도 블록 요소처럼 너비와 높이를 가질 수 있게 해준다. 이를 통해 텍스트의 특정 부분만 제한된 너비를 갖도록 만들 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;실제-사용-사례와-고려사항&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%EC%A0%9C-%EC%82%AC%EC%9A%A9-%EC%82%AC%EB%A1%80%EC%99%80-%EA%B3%A0%EB%A0%A4%EC%82%AC%ED%95%AD&quot; aria-label=&quot;실제 사용 사례와 고려사항 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실제 사용 사례와 고려사항&lt;/h3&gt;
&lt;p&gt;이 패턴은 사용자 프로필이나 댓글 시스템에서 특히 유용하다. 예를 들어, “홍길동님이 댓글을 남겼습니다”와 같은 알림에서 사용자 이름이 너무 길 경우 중간 부분을 생략하면서도 문장의 흐름을 유지할 수 있다. 또한 이메일 주소를 표시할 때 도메인 부분은 항상 보여주면서 사용자 이름 부분만 truncate하는 경우에도 활용할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.nickname&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inline-block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nowrap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;text-overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ellipsis&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bottom&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;iframe src=&quot;https://codesandbox.io/embed/nfwrjr?view=preview&amp;module=%2Findex.html&amp;hidenavigation=1&quot;
     style=&quot;width:100%; height: 500px; border:0; border-radius: 4px; overflow:hidden;&quot;
     title=&quot;중간 텍스트를 truncate하는 경우&quot;
     allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot;
     sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;
   &gt;&lt;/iframe&gt;
&lt;h2 id=&quot;2-grid-열의-높이를-자식-중-가장-높은-요소에-맞추기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-grid-%EC%97%B4%EC%9D%98-%EB%86%92%EC%9D%B4%EB%A5%BC-%EC%9E%90%EC%8B%9D-%EC%A4%91-%EA%B0%80%EC%9E%A5-%EB%86%92%EC%9D%80-%EC%9A%94%EC%86%8C%EC%97%90-%EB%A7%9E%EC%B6%94%EA%B8%B0&quot; aria-label=&quot;2 grid 열의 높이를 자식 중 가장 높은 요소에 맞추기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Grid 열의 높이를 자식 중 가장 높은 요소에 맞추기&lt;/h2&gt;
&lt;p&gt;보통의 경우에는 grid를 사용할 때 자식 요소들 크기가 일정해서 높이에 대해 신경 쓸 일이 별로 없었는데 특정 케이스에서 높이가 더 긴 자식 요소가 있었고 그 행의 높이를 가장 높은 자식의 높이에 맞춰야했다. 이럴 때 &lt;code class=&quot;language-text&quot;&gt;grid-auto-rows&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;minmax&lt;/code&gt;를 활용했다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;minmax&lt;/code&gt; 함수는 CSS Grid의 강력한 기능 중 하나로, 첫 번째 인자는 최소값, 두 번째 인자는 최대값을 의미한다. 최소 높이를 요구사항에 맞게 정하고 &lt;code class=&quot;language-text&quot;&gt;auto&lt;/code&gt; 값을 최대값으로 사용하면 콘텐츠에 따라 자동으로 크기가 조정된다. 이를 통해 콘텐츠의 양이 적을 때는 최소 높이를 유지하고, 콘텐츠가 많을 때는 자동으로 확장되는 유연한 레이아웃을 만들 수 있다. 아래 예시에서는 &lt;code class=&quot;language-text&quot;&gt;grid-auto-rows: minmax(200px, auto);&lt;/code&gt;로 스타일을 설정했다.&lt;/p&gt;
&lt;iframe src=&quot;https://codesandbox.io/embed/kgqk9k?view=preview&amp;module=%2Fstyles.css&quot;
     style=&quot;width:100%; height: 500px; border:0; border-radius: 4px; overflow:hidden;&quot;
     title=&quot;Grid 열의 높이를 가장 높은 자식 요소에 맞추는 경우&quot;
     allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot;
     sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;
   &gt;&lt;/iframe&gt;
&lt;h3 id=&quot;브라우저-호환성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%ED%98%B8%ED%99%98%EC%84%B1&quot; aria-label=&quot;브라우저 호환성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;브라우저 호환성&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;grid-auto-rows&lt;/code&gt; 속성은 2017년 업데이트 버전 이후 버전에서는 대부분 작동한다. Firefox for Android 브라우저의 경우에는 79버전(Released 2020-07-28) 이후 버전에서 정상 작동한다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows&quot;&gt;mdn 링크&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[전문가를 위한 리액트 도서 리뷰(한빛미디어)]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/전문가를-위한-리액트-도서-리뷰(한빛미디어)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/전문가를-위한-리액트-도서-리뷰(한빛미디어)/</guid><pubDate>Fri, 28 Feb 2025 19:02:44 GMT</pubDate><content:encoded>&lt;h3 id=&quot;한빛미디어-서평단-나는리뷰어다-활동을-위해서-책을-협찬-받아-작성된-서평입니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%9C%EB%B9%9B%EB%AF%B8%EB%94%94%EC%96%B4-%EC%84%9C%ED%8F%89%EB%8B%A8-%EB%82%98%EB%8A%94%EB%A6%AC%EB%B7%B0%EC%96%B4%EB%8B%A4-%ED%99%9C%EB%8F%99%EC%9D%84-%EC%9C%84%ED%95%B4%EC%84%9C-%EC%B1%85%EC%9D%84-%ED%98%91%EC%B0%AC-%EB%B0%9B%EC%95%84-%EC%9E%91%EC%84%B1%EB%90%9C-%EC%84%9C%ED%8F%89%EC%9E%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;한빛미디어 서평단 나는리뷰어다 활동을 위해서 책을 협찬 받아 작성된 서평입니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“한빛미디어 서평단 &amp;#x3C;나는리뷰어다&gt; 활동을 위해서 책을 협찬 받아 작성된 서평입니다.”&lt;/h3&gt;
&lt;br&gt;
&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
&lt;img src=&quot;https://www.hanbit.co.kr/data/books/B3738518904_l.jpg&quot; alt=&quot;전문가를 위한 리액트&quot;&gt;
출처: 한빛미디어
&lt;/div&gt;
&lt;h2 id=&quot;책-소개&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B1%85-%EC%86%8C%EA%B0%9C&quot; aria-label=&quot;책 소개 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;책 소개&lt;/h2&gt;
&lt;p&gt;“전문가를 위한 리액트”는 단순히 리액트의 기본 사용법을 넘어 고급 패턴과 성능 최적화, 확장 가능한 아키텍처를 구축하는 방법을 다루는 책이다. 이 책은 리액트를 이미 사용해 본 개발자가 더 깊이 있는 이해와 실무적인 기술을 습득하는 데 초점을 맞추고 있다.&lt;/p&gt;
&lt;h2 id=&quot;인상-깊었던-내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%83%81-%EA%B9%8A%EC%97%88%EB%8D%98-%EB%82%B4%EC%9A%A9&quot; aria-label=&quot;인상 깊었던 내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인상 깊었던 내용&lt;/h2&gt;
&lt;p&gt;리액트를 오래전에 다뤄봤던 터라 버전이 올라가면서 내부 동작 원리도 많이 바뀌었다는 것을 느꼈다.&lt;/p&gt;
&lt;h3 id=&quot;파이버-데이터-구조&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%8C%EC%9D%B4%EB%B2%84-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0&quot; aria-label=&quot;파이버 데이터 구조 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;파이버 데이터 구조&lt;/h3&gt;
&lt;p&gt;리액트는 16 미만 버전 ‘스택 재조정자’를 사용했었다고 한다. 작업을 일시 중지하거나 연기하지 않고 쌓여 있는대로 렌더링하기 때문에 업데이트의 우선순위를 설정할 수 없었다. 그래서 덜 중요한 업데이트가 더 중요한 업데이트를 방해하는 문제가 생겼다. 그래서 파이버라는 데이터 구조를 사용해 이 문제를 해결했다고 한다. 파이버 재조정자를 활용한 재조정 과정을 깊이있게 학습할 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;메모화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A9%94%EB%AA%A8%ED%99%94&quot; aria-label=&quot;메모화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;메모화&lt;/h3&gt;
&lt;p&gt;컴포넌트에 메모화를 적용하면 내부적으로 어떤 일이 일어나는지 학습할 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;고차-컴포넌트-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B3%A0%EC%B0%A8-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;고차 컴포넌트 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;고차 컴포넌트 패턴&lt;/h3&gt;
&lt;p&gt;고차 컴포넌트는 컴포넌트를 입력으로 받아 새로운 컴포넌트를 반환하는 함수다. 이 책에서는 고차 컴포넌트를 활용한 다양한 패턴을 소개한다. 특히 컴포넌트 합성, 고차 컴포넌트, 렌더 프롭스, 커스텀 훅 등을 활용한 다양한 패턴과 각각의 장단점이 비교되어 있어 상황에 맞는 패턴을 선택하는 데 도움이 되었다.&lt;/p&gt;
&lt;h3 id=&quot;리액트-동시성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%8F%99%EC%8B%9C%EC%84%B1&quot; aria-label=&quot;리액트 동시성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리액트 동시성&lt;/h3&gt;
&lt;p&gt;동시성 렌더링을 사용해 렌더링 과정에서 어떻게 우선순위를 설정하고 구성하는지 학습할 수 있었다. 처음 보는 훅도 있었는데 &lt;code class=&quot;language-text&quot;&gt;useDeferredValue&lt;/code&gt; 훅은 특정 UI 업데이트를 나중으로 미룰 수 있어서 실무에서 사용해 볼 수 있겠다는 생각이 들었다.&lt;/p&gt;
&lt;h3 id=&quot;프레임워크&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC&quot; aria-label=&quot;프레임워크 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;프레임워크&lt;/h3&gt;
&lt;p&gt;Next.js는 계속 써보고 있지만 Remix는 따로 사용해 볼 일이 없었다. Remix에 대한 글도 점점 많이 보이고 기업에서 채택하는 경우도 있었는데 뭐가 좋길래 그렇게 채택을 하는지 궁금했는데 대략적으로나마 Remix가 추구하는 방향을 알 수 있었다.
Remix는 코드가 프레임워크 안에 숨겨져 있지 않고 외부로 드러나 있기 때문에 사용자가 입맛대로 수정할 수 있는게 인상적이었다. 그리고 웹의 기본적인 기능들을 적극적으로 활용하려고 한다. 폼을 사용할 때도 따로 input값을 상태값으로 저장하지 않고 native input 자체로 활용한다.&lt;/p&gt;
&lt;h2 id=&quot;추천-대상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%94%EC%B2%9C-%EB%8C%80%EC%83%81&quot; aria-label=&quot;추천 대상 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;추천 대상&lt;/h2&gt;
&lt;p&gt;이 책은 다음과 같은 분들에게 추천한다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;리액트의 기본을 이미 알고 있고 더 깊이 이해하고 싶은 개발자&lt;/li&gt;
&lt;li&gt;대규모 리액트 애플리케이션의 설계와 구현에 고민이 있는 개발자&lt;/li&gt;
&lt;li&gt;성능 최적화와 코드 품질 향상에 관심이 있는 프론트엔드 개발자&lt;/li&gt;
&lt;li&gt;리액트 아키텍처 패턴을 학습하고 싶은 프론트엔드 리드 개발자&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h2&gt;
&lt;p&gt;“전문가를 위한 리액트”는 단순한 리액트 입문서를 넘어서, 실제 복잡한 애플리케이션 개발에 필요한 고급 기술과 패턴을 체계적으로 정리한 책이다. 요즘에 내부 구현 및 원리에 관심이 많아서 입문서 이상의 책을 찾고 있었는데 마침 좋은 기회로 이 책을 만나서 좋았고 한번에 내용들을 완전히 이해하긴 어려웠기 때문에 여러번 반복숙달하면서 내 것으로 만들어 보려고 한다. 리액트를 사용하는 개발자라면 한 번쯤 읽어볼 가치가 있는 책이라고 생각한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[CSS white-space 속성 적재적소에 활용하기!]]></title><description><![CDATA[웹 개발하면서 white-space…]]></description><link>https://donghoon-song.github.io/css/css-white-space-속성-적재적소에-활용하기!/</link><guid isPermaLink="false">https://donghoon-song.github.io/css/css-white-space-속성-적재적소에-활용하기!/</guid><pubDate>Wed, 05 Feb 2025 22:03:02 GMT</pubDate><content:encoded>&lt;p&gt;웹 개발하면서 white-space 속성은 신경쓰지 않으면 놓치기 쉬운 부분인 것 같다. 계속 필요할 때마다 찾아 봤었는데 머리 속에서 제대로 정리되지 않아서 계속 찾아보게 되는 거 같아 이번에 좀 정리해보려고 한다. 결국엔 각 속성이 어떤 역할을 하고 어떤 상황에서 써야 할지 정리해두는 게 좋을 것 같다.&lt;/p&gt;
&lt;h2 id=&quot;white-space-속성이란&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#white-space-%EC%86%8D%EC%84%B1%EC%9D%B4%EB%9E%80&quot; aria-label=&quot;white space 속성이란 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;white-space 속성이란?&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;white-space&lt;/code&gt; 속성은 텍스트의 공백 처리 방법을 지정하는 CSS 속성이다. 이 속성은 요소 안에 있는 공백 문자와 줄바꿈 문자를 어떻게 처리할지를 정한다. 브라우저는 이 설정에 따라 &lt;code class=&quot;language-text&quot;&gt;텍스트의 줄바꿈, 공백 축소, 자동 줄바꿈 여부&lt;/code&gt; 등을 결정한다. 기본 값은 &lt;code class=&quot;language-text&quot;&gt;normal&lt;/code&gt;이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; normal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;white-space의-다양한-값&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#white-space%EC%9D%98-%EB%8B%A4%EC%96%91%ED%95%9C-%EA%B0%92&quot; aria-label=&quot;white space의 다양한 값 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;white-space의 다양한 값&lt;/h2&gt;
&lt;h3 id=&quot;pre&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pre&quot; aria-label=&quot;pre permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;pre&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;소스 코드에 쓴 그대로 모든 공백과 줄바꿈을 그대로 보여준다. 자동 줄바꿈은 발생하지 않아서 너비를 넘으면 스크롤이 생길 수 있다.&lt;/li&gt;
&lt;li&gt;사용 예: 코드 스니펫이나 시, 혹은 서식이 중요한 텍스트에 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;nowrap&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nowrap&quot; aria-label=&quot;nowrap permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;nowrap&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;연속된 공백은 축소되지만 텍스트는 한 줄로 유지된다. 줄바꿈이 없어서 긴 텍스트가 한 줄로 쭉 이어진다.&lt;/li&gt;
&lt;li&gt;사용 예: 메뉴, 버튼처럼 텍스트가 한 줄에 유지되어야 하는 경우에 적합하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;pre-wrap&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pre-wrap&quot; aria-label=&quot;pre wrap permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;pre-wrap&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;사용자가 입력한 모든 줄바꿈과 연속 공백을 그대로 유지하면서, 요소 너비를 넘어가는 경우 자동 줄바꿈도 적용된다.&lt;/li&gt;
&lt;li&gt;사용 예: 포럼 게시글이나 채팅 메시지처럼 사용자가 입력한 텍스트 포맷(줄바꿈, 들여쓰기 등)을 그대로 보여줘야 할 때 좋다. 코드나 시처럼 정밀한 포맷이 필요한 경우에 유용하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;pre-line&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pre-line&quot; aria-label=&quot;pre line permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;pre-line&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;사용자가 입력한 줄바꿈은 유지하면서 연속된 공백은 하나로 축소하고, 자동 줄바꿈도 적용된다.&lt;/li&gt;
&lt;li&gt;사용 예: 댓글이나 사용자 리뷰처럼, 사용자가 의도한 줄바꿈은 살리면서 불필요한 공백을 줄여 깔끔한 레이아웃을 유지하고 싶을 때 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;white-space-속성-요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#white-space-%EC%86%8D%EC%84%B1-%EC%9A%94%EC%95%BD&quot; aria-label=&quot;white space 속성 요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;white-space 속성 요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;normal&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;공백 처리:&lt;/strong&gt; 연속 공백 축소&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;줄바꿈 처리:&lt;/strong&gt; HTML 태그 및 기본 규칙에 따름&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동 줄바꿈:&lt;/strong&gt; 요소 너비에 따라 wrap&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;사용 예:&lt;/strong&gt; 일반 텍스트 콘텐츠 (기본 설정)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;pre&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;공백 처리:&lt;/strong&gt; 입력한 공백 그대로 유지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;줄바꿈 처리:&lt;/strong&gt; 소스 코드상의 줄바꿈 그대로 적용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동 줄바꿈:&lt;/strong&gt; 지원하지 않음 (오버플로우 시 스크롤 발생)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;사용 예:&lt;/strong&gt; 코드 스니펫, 시 또는 포맷이 중요한 텍스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;nowrap&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;공백 처리:&lt;/strong&gt; 연속 공백 축소&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;줄바꿈 처리:&lt;/strong&gt; 모든 줄바꿈 무시&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동 줄바꿈:&lt;/strong&gt; 지원하지 않음 (한 줄로 표시)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;사용 예:&lt;/strong&gt; 메뉴, 버튼 등 한 줄로 유지해야 하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;pre-wrap&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;공백 처리:&lt;/strong&gt; 입력한 공백 그대로 유지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;줄바꿈 처리:&lt;/strong&gt; 소스 상의 줄바꿈 그대로 적용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동 줄바꿈:&lt;/strong&gt; 지원 (요소 범위 내 자동 wrap)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;사용 예:&lt;/strong&gt; 사용자가 입력한 텍스트의 형식을 유지할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;pre-line&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;공백 처리:&lt;/strong&gt; 연속 공백 축소&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;줄바꿈 처리:&lt;/strong&gt; 입력한 줄바꿈은 유지하지만 불필요한 공백은 축소&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동 줄바꿈:&lt;/strong&gt; 지원&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;사용 예:&lt;/strong&gt; 불필요한 공백은 제거하면서 필수 줄바꿈만 유지할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;h2 id=&quot;다양한-상황에서-테스트-해보기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%EC%96%91%ED%95%9C-%EC%83%81%ED%99%A9%EC%97%90%EC%84%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%B4%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;다양한 상황에서 테스트 해보기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다양한 상황에서 테스트 해보기&lt;/h2&gt;
&lt;iframe height=&quot;900&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Untitled&quot; src=&quot;https://codepen.io/donghoon759/embed/VYZJjJw?default-tab=result&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/donghoon759/pen/VYZJjJw&quot;&gt;
  Untitled&lt;/a&gt; by Donghoon Song (&lt;a href=&quot;https://codepen.io/donghoon759&quot;&gt;@donghoon759&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;h3 id=&quot;css-white-space를-완벽히-내-것으로-만들었나요&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#css-white-space%EB%A5%BC-%EC%99%84%EB%B2%BD%ED%9E%88-%EB%82%B4-%EA%B2%83%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%EC%97%88%EB%82%98%EC%9A%94&quot; aria-label=&quot;css white space를 완벽히 내 것으로 만들었나요 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CSS white-space를 완벽히 내 것으로 만들었나요?&lt;/h3&gt;
&lt;p&gt;이제 배운 내용을 실전에서 확인할 시간이에요!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ducklog.vercel.app/&quot;&gt;Ducklog 🐥&lt;/a&gt;에서 각 white-space 옵션의 특성과 사용하면 좋을 상황들을 쭉 적어보고 확인해보세요!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Zustand의 shallow comparison으로 최적화하기]]></title><description><![CDATA[Zustand store에서 객체 상태를 구독할 때  비교를 사용하면 불필요한 리렌더링을 방지할 수 있다는 것을 알게 되었다. Zustand의 기본 동작 Zustand는 기본적으로 상태를 비교할 때 Object.is를 사용한다. shallow…]]></description><link>https://donghoon-song.github.io/react.js/zustand의-shallow-comparison으로-최적화하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/react.js/zustand의-shallow-comparison으로-최적화하기/</guid><pubDate>Sun, 02 Feb 2025 18:02:18 GMT</pubDate><content:encoded>&lt;p&gt;Zustand store에서 객체 상태를 구독할 때 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt; 비교를 사용하면 불필요한 리렌더링을 방지할 수 있다는 것을 알게 되었다.&lt;/p&gt;
&lt;h2 id=&quot;zustand의-기본-동작&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#zustand%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EB%8F%99%EC%9E%91&quot; aria-label=&quot;zustand의 기본 동작 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Zustand의 기본 동작&lt;/h2&gt;
&lt;p&gt;Zustand는 기본적으로 상태를 비교할 때 &lt;a href=&quot;https://github.com/pmndrs/zustand/blob/main/src/vanilla.ts#L73&quot;&gt;Object.is&lt;/a&gt;를 사용한다.&lt;/p&gt;
&lt;h2 id=&quot;shallow-비교란&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shallow-%EB%B9%84%EA%B5%90%EB%9E%80&quot; aria-label=&quot;shallow 비교란 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;shallow 비교란?&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;는 간단한 데이터에 대해서 빠르게 비교할 수 있는 방식이다. 중첩된 객체의 경우에는 내부 속성까지 비교하지 않고 참조값을 기준으로 판단한다. 이를 통해 선택자에서 반환하는 객체가 새로 생성되더라도 실제로 필요한 값이 변경되지 않았다면 리렌더링을 피할 수 있다.&lt;/p&gt;
&lt;p&gt;아래 처럼 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 전달해서 사용할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; shallow &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zustand/shallow&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    shallow &lt;span class=&quot;token comment&quot;&gt;// 👈 명시적 설정 필요&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;primitive-타입-비교&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#primitive-%ED%83%80%EC%9E%85-%EB%B9%84%EA%B5%90&quot; aria-label=&quot;primitive 타입 비교 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Primitive 타입 비교&lt;/h3&gt;
&lt;p&gt;숫자, 문자열, 불리언 등 primitive 타입은 &lt;code class=&quot;language-text&quot;&gt;Object.is&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt; 모두 값 자체를 비교한다. 따라서, primitive 값을 선택자로 사용할 경우 별도의 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt; 비교 없이도 값이 같으면 리렌더링이 발생하지 않는다.&lt;/p&gt;
&lt;h3 id=&quot;객체-비교&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%9D%EC%B2%B4-%EB%B9%84%EA%B5%90&quot; aria-label=&quot;객체 비교 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;객체 비교&lt;/h3&gt;
&lt;p&gt;객체를 비교할 때 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;는 각 객체의 최상위 속성 값만을 비교한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; shallow &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zustand/shallow&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; obj1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; obj2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; obj2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shallow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; obj2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예제에서 두 객체의 참조값은 다르지만 top-level 속성(a, b, c)의 값이 모두 같기 때문에 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt; 함수는 &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;를 반환한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; shallow &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zustand/shallow&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; obj1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; obj2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; obj2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shallow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; obj2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 객체 내부에 중첩된 객체가 포함되어 있을 경우, shallow 비교는 해당 속성의 참조만을 비교하기 때문에 &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;를 반환한다.&lt;/p&gt;
&lt;h2 id=&quot;shallow-비교의-동작-원리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shallow-%EB%B9%84%EA%B5%90%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC&quot; aria-label=&quot;shallow 비교의 동작 원리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;shallow 비교의 동작 원리&lt;/h2&gt;
&lt;p&gt;Zustand의 shallow 함수는 다음과 같은 방식으로 두 객체를 비교한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;두 객체가 같은 참조(메모리 주소)를 가지면 true를 반환한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;두 객체의 키 개수가 다르면 false를 반환한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;각 속성 값을 비교하며, 값이 다르면 false를 반환한다. 단, 객체나 배열인 경우 참조가 같으면 true를 반환한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;속성 값이 객체나 배열이면 참조(메모리 주소)를 비교하지만, 최상위 속성의 값이 동일하면 같다고 판단한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;github에 있는 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt; 함수의 코드는 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; shallow&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;objB&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; objB&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; objA &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;object&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    objA &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; objB &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;object&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    objB &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; objB &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; objB&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; objA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; objB&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; objB &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; objB&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; objA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;objB&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; keysA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;keysA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objB&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; keyA &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; keysA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; keyA &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; string&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objA&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keyA &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; keyof &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; objB&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keyA &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; keyof &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;불필요한-리렌더링을-방지&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B6%88%ED%95%84%EC%9A%94%ED%95%9C-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%84-%EB%B0%A9%EC%A7%80&quot; aria-label=&quot;불필요한 리렌더링을 방지 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;불필요한 리렌더링을 방지&lt;/h2&gt;
&lt;p&gt;이제 본론으로 넘어 와 보자. Zustand의 useStore 훅에서 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 활용하면 불필요한 리렌더링을 방지할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; create &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zustand&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; useUserStore &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;John&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 전체 user를 변경하는 함수&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;setUser&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// user 객체의 일부 속성을 업데이트하는 함수&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;updateUser&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;updates&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;updates &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    shallow &lt;span class=&quot;token comment&quot;&gt;// 👈 명시적 설정 필요&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 초기 상태: { user: { id: 123, name: &apos;John&apos; } }&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id1 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 123 반환&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 1. id가 변경되지 않은 업데이트&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jane&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id2 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 123 → 리렌더링 발생 ❌&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 2. id가 변경된 업데이트&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;456&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jane&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id3 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 123 → 리렌더링 발생 ✅&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 3. email이 추가된 업데이트&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jane&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test@test.com&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id4 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 123 → 리렌더링 발생 ❌&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 사용하면 1번의 경우 id2를 사용하는 컴포넌트는 리렌더링이 발생하지 않는다. 왜냐하면 name은 바뀌었지만 구독하고 있는 id의 값은 123 그대로 유지되었기 때문이다.&lt;/p&gt;
&lt;p&gt;2번의 경우는 구독하고 있는 id값이 달라졌으므로 id3을 사용하는 컴포넌트는 리렌더링이 발생한다.&lt;/p&gt;
&lt;p&gt;3번처럼 새로운 속성이 추가되어도 id값은 바뀌지 않았기 때문에 id4를 사용하는 컴포넌트는 리렌더링이 발생하지 않는다.
만약에 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 사용하지 않으면 1번, 2번, 3번 모두 리렌더링이 발생할 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 중첩되지 않는 객체나 배열을 구독하는 경우 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 사용하면 불필요한 리렌더링을 방지할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;필요한-값만-구독하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%84%EC%9A%94%ED%95%9C-%EA%B0%92%EB%A7%8C-%EA%B5%AC%EB%8F%85%ED%95%98%EA%B8%B0&quot; aria-label=&quot;필요한 값만 구독하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;필요한 값만 구독하기&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 사용하지 않고 이렇게 필요한 값만 구독하면 primitive 타입을 반환하기 때문에 &lt;code class=&quot;language-text&quot;&gt;Object.is&lt;/code&gt;에서 같다고 판단해 리렌더링이 발생하지 않는다. 그래서 보통의 경우에는 이렇게 필요한 값만 구독하는 것이 좋다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserNo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;불가피하게-객체를-구독하는-경우&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B6%88%EA%B0%80%ED%94%BC%ED%95%98%EA%B2%8C-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EA%B5%AC%EB%8F%85%ED%95%98%EB%8A%94-%EA%B2%BD%EC%9A%B0&quot; aria-label=&quot;불가피하게 객체를 구독하는 경우 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;불가피하게 객체를 구독하는 경우&lt;/h2&gt;
&lt;p&gt;하지만 객체에서 사용하는 값이 많고 업데이트가 자주 일어난다면 이렇게 객체를 한번에 구독하고 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt; 함수를 사용하는 것을 고려해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; create &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zustand&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; shallow &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zustand/shallow&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Zustand 스토어 정의: 여러 user 관련 속성을 포함합니다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; useUserStore &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;John&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;john@example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;phone&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;010-1234-5678&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Seoul, Korea&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// user 객체의 일부 또는 전체를 업데이트하는 함수&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;updateUser&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;updates&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;updates &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 전체 user 객체를 shallow 비교와 함께 구독하는 훅&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shallow&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 예시 컴포넌트: 여러 user 관련 속성을 렌더링합니다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 전체 user 객체를 구독&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;UserComponent rendered&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Address&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 예시 업데이트 코드 (실제 환경에서는 이벤트 핸들러 등에서 호출)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 예를 들어, 1초 후 name과 email을 업데이트하는 경우:&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  useUserStore
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jane&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;jane@example.com&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; UserComponent&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;정리해보면 불필요한 리렌더링을 방지하기 위해서는&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;객체의 특정 속성만 선택하는 것이 좋다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;중첩되지 않은 객체나 배열을 구독하는 경우 &lt;code class=&quot;language-text&quot;&gt;shallow&lt;/code&gt;를 사용하면 불필요한 리렌더링을 방지할 수 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[가운데 정렬된 네비게이션 혹은 헤더 grid로 구현하기]]></title><description><![CDATA[UI…]]></description><link>https://donghoon-song.github.io/css/가운데-정렬된-네비게이션-혹은-헤더-grid로-구현하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/css/가운데-정렬된-네비게이션-혹은-헤더-grid로-구현하기/</guid><pubDate>Sat, 01 Feb 2025 14:02:56 GMT</pubDate><content:encoded>&lt;iframe src=&quot;https://codesandbox.io/embed/vkfqck?view=preview&amp;module=%2Findex.html&quot;
     style=&quot;width:100%; height: 500px; border:0; border-radius: 4px; overflow:hidden;&quot;
     title=&quot;focused-dhawan&quot;
     allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot;
     sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;
   &gt;&lt;/iframe&gt;
&lt;p&gt;UI를 구현하다보면 이런 식으로 가운데 정렬된 네비게이션 혹은 헤더를 구현해야 할 때가 있다. &lt;code class=&quot;language-text&quot;&gt;absolute&lt;/code&gt;를 이용해서 가운데 요소를 가운데 정렬하거나 &lt;code class=&quot;language-text&quot;&gt;flex&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;justfify-content: space-between&lt;/code&gt; 사용해서 레이아웃을 구현하기도 한다. 하지만 후자의 경우에는 왼쪽이나 오른쪽 요소가 사라질 경우 레이아웃이 깨질 위험이 있다. 이번 포스트에서는 &lt;code class=&quot;language-text&quot;&gt;grid&lt;/code&gt;를 사용해서 구현하는 방법을 알아보려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;html-구조&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#html-%EA%B5%AC%EC%A1%B0&quot; aria-label=&quot;html 구조 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;HTML 구조&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;page-navigation-controls&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;left-button-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-button&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;prevButton&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;⬅️&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;progressText&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1 / 5&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;right-button-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-button&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;nextButton&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;➡️&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;css-스타일링&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#css-%EC%8A%A4%ED%83%80%EC%9D%BC%EB%A7%81&quot; aria-label=&quot;css 스타일링 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CSS 스타일링&lt;/h2&gt;
&lt;p&gt;네비게이션 컨트롤을 그리드 레이아웃을 사용하여 배치하고, 버튼 스타일을 설정한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.page-navigation-controls&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1fr auto 1fr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;align-items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.left-button-wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;justify-self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex-start&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.right-button-wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;justify-self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex-end&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.icon-button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pointer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.icon&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 24px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 24px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 중요한 부분은 &lt;code class=&quot;language-text&quot;&gt;grid-template-columns: 1fr auto 1fr;&lt;/code&gt;이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;1fr&lt;/code&gt; : 첫 번째, 세번째 열(왼쪽 버튼, 오른쪽 버튼)이 가변 크기를 가지며, 공간이 있으면 확장된다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;auto&lt;/code&gt; : 가운데 열(페이지 진행률 표시)은 내용 크기만큼 유지된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이렇게 하면 왼쪽 버튼과 오른쪽 버튼이 화면 크기에 따라 확장되면서 가운데 열은 고정된 크기를 유지한다. 이 방법은 레이아웃이 유연하면서도 왼쪽이나 오른쪽 요소가 사라지는 경우에도 레이아웃이 깨지지 않는다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[테오의 스프린트 18기 참가 후기]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/회고/테오의-스프린트-18기-참가-후기/</link><guid isPermaLink="false">https://donghoon-song.github.io/회고/테오의-스프린트-18기-참가-후기/</guid><pubDate>Thu, 26 Dec 2024 17:13:07 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가며&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EB%A9%B0&quot; aria-label=&quot;들어가며 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가며&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;좋은 사람들과 함께 잘 만들어진 협업 프로세스를 배우고 경험한다.&lt;/code&gt;라는 슬로건으로 운영중인 테오의 스프린트에 드디어 참여했다. 후기 글들과 스프린트 결과물을 보면서 꼭 한번 참여해 보고 싶었는데 항상 시간이 안 맞아서 참여하지 못해서 항상 아쉬웠다. 컨퍼런스 발표를 마치고 숨을 돌리고 있던 와중에 모집 글이 올라와서 다행히 이번엔 참여할 수 있겠다 싶어서 부리나케 지원 폼을 작성했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/mQfjF8t.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;테오의-스프린트란&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%EC%98%A4%EC%9D%98-%EC%8A%A4%ED%94%84%EB%A6%B0%ED%8A%B8%EB%9E%80&quot; aria-label=&quot;테오의 스프린트란 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테오의 스프린트란&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;구글 스프린트는 짧은 시간 내에 아이디어 검증을 하기 위한 그럴싸한 MVP를 효율적으로 만들어내는 방법론입니다. **[6일간 좋은 사람들과 잘 만들어진 협업 프로세스를 함께 경험한다]**라는 슬로건 아래 스프린트를 직접 경험해 본 9명의 퍼실리테이터가 모여, 스프린트에서의 경험을 잘 이어가기 위해 1개월간 열심히 준비했습니다. 다양한 생각과 경험이 모여 더욱 풍성한 스프린트가 되길 기대합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://teo-sprint.oopy.io/&quot;&gt;https://teo-sprint.oopy.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;테오의 스프린트는 위에서 소개한 내용처럼 아이디어 검증을 위한 협업 프로세스를 타이트하게 경험할 수 있는 스프린트이다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/vZysTAD.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;스프린트에서 어떤 걸 경험하고 배웠는지 날짜별로 정리해 봤다.&lt;/p&gt;
&lt;h2 id=&quot;day1-팀-캔버스-작성하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#day1-%ED%8C%80-%EC%BA%94%EB%B2%84%EC%8A%A4-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0&quot; aria-label=&quot;day1 팀 캔버스 작성하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Day1. 팀 캔버스 작성하기&lt;/h2&gt;
&lt;p&gt;우리는 아이디어를 중심으로 팀을 구성했다. 나도 아이디어를 냈는데 놀랄 만큼 아무런 관심도 받지 못했다. 하지만 그런 아이디어들이 꽤 여럿있었고 다른 좋은 아이디어들이 많아서 딱히 신경쓰진 않았다. 😅&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://mblogthumb-phinf.pstatic.net/MjAxNzEwMzBfMTYy/MDAxNTA5MzMxNDg1Mzk4.2Q9VXi4Jhx2MuKOtT-RA1qyYMw8ETzDyYrkwWEl3XMMg.xfjwmuD87GAg-xpYWMxOHkCfeIVEttU4DAs0y75udCEg.JPEG.smoker3/001.jpg?type=w800&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;아이디어-즉석-대화-소재-생성기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%95%84%EC%9D%B4%EB%94%94%EC%96%B4-%EC%A6%89%EC%84%9D-%EB%8C%80%ED%99%94-%EC%86%8C%EC%9E%AC-%EC%83%9D%EC%84%B1%EA%B8%B0&quot; aria-label=&quot;아이디어 즉석 대화 소재 생성기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;아이디어: 즉석 대화 소재 생성기&lt;/h2&gt;
&lt;p&gt;내가 선택한 아이디어는 &lt;code class=&quot;language-text&quot;&gt;즉석 대화 소재 생성기&lt;/code&gt;이다. &lt;code class=&quot;language-text&quot;&gt;낯선 사람과 대화할 때 할 말이 없으면 대화 소재를 추천해주는 서비스&lt;/code&gt;인 것이다. 정말 나같은 사람에게 필요하겠다 싶어서 냅다 선택했다. 하지만 나같은 사람들이 많아서 우리 팀의 아이디어는 반응이 뜨거웠고 많은 사람들이 모였다.&lt;/p&gt;
&lt;h3 id=&quot;팀-빌딩&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%80-%EB%B9%8C%EB%94%A9&quot; aria-label=&quot;팀 빌딩 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;팀 빌딩&lt;/h3&gt;
&lt;p&gt;우리는 1조가 되었고 서로에 대해 알아가는 시간을 가졌다. 다양한 사람들이 모였는데 우리는 공통적으로 모두 MBTI I였고 아이디어에 대해 많이 공감하는 사람들이었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/aAQYVa7.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;그리고 나서 우리는 여러가지 이야기를 나눴다.&lt;/p&gt;
&lt;h3 id=&quot;팀의-성공을-어떻게-정의할-것인가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%80%EC%9D%98-%EC%84%B1%EA%B3%B5%EC%9D%84-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%A0%95%EC%9D%98%ED%95%A0-%EA%B2%83%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;팀의 성공을 어떻게 정의할 것인가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;팀의 성공을 어떻게 정의할 것인가?&lt;/h3&gt;
&lt;p&gt;공통적인 의견으로는 &lt;code class=&quot;language-text&quot;&gt;서비스의 완성&lt;/code&gt;, 그리고 &lt;code class=&quot;language-text&quot;&gt;사용자가 있을 것&lt;/code&gt;이었다. 생각이 잘 맞아서 좋았다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/95Xtc8z.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;우리-서비스는-어떤-가치를-줄-것인가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%B0%EB%A6%AC-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%8A%94-%EC%96%B4%EB%96%A4-%EA%B0%80%EC%B9%98%EB%A5%BC-%EC%A4%84-%EA%B2%83%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;우리 서비스는 어떤 가치를 줄 것인가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;우리 서비스는 어떤 가치를 줄 것인가?&lt;/h3&gt;
&lt;p&gt;우리는 &lt;code class=&quot;language-text&quot;&gt;좋은 대화 소재&lt;/code&gt;를 추천하고 &lt;code class=&quot;language-text&quot;&gt;누구나 빠르게&lt;/code&gt;사용할 수 있게 하고 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/2j4lEzG.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;그 외에 우리는 가진 능력과 기술스택, 약점과 리스크, 꼭 지켜줬으면 하는 규칙에 대한 얘기를 나누면서 팀 캔버스를 완성했다. 이런 내용들도 미리 얘기를 하니까 협업하면서 생길 수 있는 이슈에 대해 미리 생각해볼 수 있었고 서로 어떤 부분을 걱정하는지 알 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/P6GRkjk.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;숙제로 비슷한 앱의 레퍼런스를 찾아 왔었는데 우리 아이디어를 실현한 앱들이 꽤 보여서 놀랐다. 이 앱들에서 찾은 아쉬운 점들을 개선해서 우리 서비스에 넣으면 좋지 않을까 하는 생각을 했다.&lt;/p&gt;
&lt;h2 id=&quot;day2-지도-그리기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#day2-%EC%A7%80%EB%8F%84-%EA%B7%B8%EB%A6%AC%EA%B8%B0&quot; aria-label=&quot;day2 지도 그리기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Day2. 지도 그리기&lt;/h2&gt;
&lt;p&gt;Day2는 생각의 주파수를 맞추는 날이었다.
그라운드 룰이 있었는데 아래와 같았고 굉장히 인상깊었다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;결정하지 않기&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;새로운 가능성을 차단하지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;A vs B 가 아니라 A + B = C&lt;/code&gt;가 되도록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;기록하기&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;리액션하기&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 룰들을 가지고 또 여러가지 이야기를 나눴다.&lt;/p&gt;
&lt;h3 id=&quot;서비스의-목적&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%9C%EB%B9%84%EC%8A%A4%EC%9D%98-%EB%AA%A9%EC%A0%81&quot; aria-label=&quot;서비스의 목적 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;서비스의 목적&lt;/h3&gt;
&lt;p&gt;우리는 서비스의 목적을 &lt;code class=&quot;language-text&quot;&gt;대화의 어려움 해소&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;즐거운 대화&lt;/code&gt;라고 생각했고 말을 잘 못하는 I들을 타겟이라고 생각했다. 한 팀원분은 서비스 타겟이 우리 팀이라고 적었는데 맞는 말이었다. 😅&lt;/p&gt;
&lt;h3 id=&quot;painwow-point&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#painwow-point&quot; aria-label=&quot;painwow point permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Pain/Wow Point&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/4dxDYcr.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;기존 사람들이 목적을 달성하기 위해 어떤 행동을 하고 있는지를 생각해 봤을 때 이런 것들이 있었다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;그냥 침묵하기&lt;/li&gt;
&lt;li&gt;관심사를 명찰이나 옷에 붙이기&lt;/li&gt;
&lt;li&gt;어떻게든 머리 짜내기&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그리고 우리가 찾았던 비슷한 서비스들엔 어떤 아쉬운 부분들이 있었을까 생각해봤는데 아무도 그런 앱이 있다는 것을 알지 못했고 찾아보려는 생각조차 못했었다는 것이 공통된 의견이었다. 그래서 일단 이런 부분들이 기회가 될 수 있겠다는 생각이 들었다.
그리고 우리 앱을 사용해서 대화를 쉽게 할 수 있다는 것을 깨달으면 그게 WOW point가 되지 않을까 하는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/LGMwrqt.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;워드-클라우드-만들기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9B%8C%EB%93%9C-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;워드 클라우드 만들기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;워드 클라우드 만들기&lt;/h3&gt;
&lt;p&gt;우리가 얘기할 때 나왔던 단어들을 가지고 워드 클라우드를 만들었다. 빈도수가 높았던 단어일수록 크게 작성했다. 불편, 부담, 다양한 주제, 침묵 등이 눈에 띈다.
&lt;img src=&quot;https://i.imgur.com/5shM00F.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;어떻게-하면-질문-만들기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EC%A7%88%EB%AC%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;어떻게 하면 질문 만들기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 하면~ 질문 만들기&lt;/h3&gt;
&lt;p&gt;이 활동이 상당히 인상적이었다. 우리가 갖고 있는 고민 포인트들을 구체화할 수 있었고 해소하는 방법에 대해 생각해 볼 수 있었다.
&lt;img src=&quot;https://i.imgur.com/C0WsB4T.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;어떻게-하면-이-앱을-꺼낼-때-부담스럽지-않을-수-있을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EC%9D%B4-%EC%95%B1%EC%9D%84-%EA%BA%BC%EB%82%BC-%EB%95%8C-%EB%B6%80%EB%8B%B4%EC%8A%A4%EB%9F%BD%EC%A7%80-%EC%95%8A%EC%9D%84-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;어떻게 하면 이 앱을 꺼낼 때 부담스럽지 않을 수 있을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 하면 이 앱을 꺼낼 때 부담스럽지 않을 수 있을까?&lt;/h3&gt;
&lt;p&gt;이 앱을 어떻게 자연스럽게 꺼낼 수 있을지에 대한 고민에서부터 나온 질문이다. 낯선 사람과 앉아 있는데 갑자기 이 앱을 꺼내면서 대화를 시작하면 상대방도 당황하지 않을까 하는 생각이 들었다. 그래서 “빌드업을 하면 괜찮을 거 같다.”, “상대방이 이 앱을 인지하고 거부감을 줄일 수 있는 시간이 필요하다. ex) 앱에 게임을 같이 제공”는 의견들이 나왔다.
&lt;img src=&quot;https://i.imgur.com/3ewhvVy.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;어떻게-하면-다양한-주제의-토픽을-효과적으로-분류할-수-있을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EB%8B%A4%EC%96%91%ED%95%9C-%EC%A3%BC%EC%A0%9C%EC%9D%98-%ED%86%A0%ED%94%BD%EC%9D%84-%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%B6%84%EB%A5%98%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;어떻게 하면 다양한 주제의 토픽을 효과적으로 분류할 수 있을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 하면 다양한 주제의 토픽을 효과적으로 분류할 수 있을까?&lt;/h3&gt;
&lt;p&gt;우리 주제들을 어떻게 분류해야 사용자가 쉽게 사용할 수 있을지에 대한 고민도 했다.
&lt;img src=&quot;https://i.imgur.com/zNJnkl1.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;다른-서비스와-차별화된-주제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%EB%A5%B8-%EC%84%9C%EB%B9%84%EC%8A%A4%EC%99%80-%EC%B0%A8%EB%B3%84%ED%99%94%EB%90%9C-%EC%A3%BC%EC%A0%9C&quot; aria-label=&quot;다른 서비스와 차별화된 주제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다른 서비스와 차별화된 주제&lt;/h3&gt;
&lt;p&gt;어떻게 하면 우리 서비스의 주제들을 차별화할 수 있을지에 대한 고민도 했다.
&lt;img src=&quot;https://i.imgur.com/AdjW383.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;이런 질문들을 통해서 핵심적인 고민거리에 대한 서로의 생각을 들어볼 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;기능-및-페이지-정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EB%8A%A5-%EB%B0%8F-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;기능 및 페이지 정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기능 및 페이지 정리&lt;/h3&gt;
&lt;p&gt;다음으로는 필요한 기능들을 쭉 나열하고 페이지별로 나누고 정리하는 시간을 가졌다.
&lt;img src=&quot;https://i.imgur.com/Fo6UMpv.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;화면-스케치&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%99%94%EB%A9%B4-%EC%8A%A4%EC%BC%80%EC%B9%98&quot; aria-label=&quot;화면 스케치 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;화면 스케치&lt;/h3&gt;
&lt;p&gt;숙제로는 각자가 생각하는 화면을 스케치했다.
&lt;img src=&quot;https://i.imgur.com/zFXU0X5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;day3-스케치&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#day3-%EC%8A%A4%EC%BC%80%EC%B9%98&quot; aria-label=&quot;day3 스케치 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Day3. 스케치&lt;/h2&gt;
&lt;p&gt;Day3에서는 각자의 스케치를 화면 별로 정리하고 좋았던 &lt;code class=&quot;language-text&quot;&gt;요소&lt;/code&gt;에 투표를 하는 시간을 가졌다. 여기서 &lt;code class=&quot;language-text&quot;&gt;좋았던 요소에 투표&lt;/code&gt;를 하는 게 인상적이었다. 이것도 &lt;code class=&quot;language-text&quot;&gt;A + B = C&lt;/code&gt;가 되도록 하는 장치였다.
&lt;img src=&quot;https://i.imgur.com/JiGs2IF.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;서로의 스케치를 보면서 스케치도 각자가 생각하는 게 달라서 정말 신기했다. 다양한 스케치들이 나왔다.
&lt;img src=&quot;https://i.imgur.com/dIy1mKX.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;요소에 투표했던 예시를 들어보면 아래 처럼 &lt;code class=&quot;language-text&quot;&gt;토픽 추천받아 대화 시작해보기&lt;/code&gt; 버튼에 많이 투표를 했다. 밸런스 게임을 통해서 어느정도 어색함이 사라지면 바로 대화를 시작할 수 있게 하는 장치여서 좋다고 생각했다.
&lt;img src=&quot;https://i.imgur.com/gGy47O3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 투표를 하고 &lt;code class=&quot;language-text&quot;&gt;UX/UI 최고 권위자&lt;/code&gt;를 뽑았다. 우리 팀은 디자이너가 있기 때문에 자연스레 디자이너가 최고 권위자가 되었다.
&lt;img src=&quot;https://i.imgur.com/AX1fAjS.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;또 &lt;code class=&quot;language-text&quot;&gt;PL(Project Leader)&lt;/code&gt;를 뽑았는데 내가 맡았다. 아무래도 회사에서 하는 역할이랑 비슷한 거 같기도 하고 데모 퀄리티를 꼭 지켜보고 싶었다. 잘 해낼 수 있을 거라는 근거 없는 자신감도 뿜뿜했다.
&lt;img src=&quot;https://i.imgur.com/T6iP2Pn.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;우선순위-결정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%EA%B2%B0%EC%A0%95&quot; aria-label=&quot;우선순위 결정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;우선순위 결정&lt;/h3&gt;
&lt;p&gt;그럴싸함 챙기는 법을 읽었는데 대부분 하고 있던 생각이랑 비슷했다. 하지만 &lt;code class=&quot;language-text&quot;&gt;미구현 기능에 대해 &apos;준비중입니다&apos; 알림 띄우기&lt;/code&gt; 항목이 인상적이었다.
&lt;img src=&quot;https://i.imgur.com/OPPsF3R.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;다음으로는 임팩트와 Effort(걸리는 시간)을 기준으로 기능들의 우선순위를 나눴다.
&lt;img src=&quot;https://i.imgur.com/YShJ3fG.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;day4-결정하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#day4-%EA%B2%B0%EC%A0%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;day4 결정하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Day4. 결정하기&lt;/h2&gt;
&lt;p&gt;드디어 결정하는 시간이 왔다. 이제까지의 활동에는 결정하는 시간이 없어서 몸이 근질거렸다.&lt;/p&gt;
&lt;h3 id=&quot;bdd로-태스크-분배&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bdd%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-%EB%B6%84%EB%B0%B0&quot; aria-label=&quot;bdd로 태스크 분배 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;BDD로 태스크 분배&lt;/h3&gt;
&lt;p&gt;사용자의 행위를 중심으로 태스크를 나눴다. BDD를 처음 해봐서 이게 맞나 걱정이 됐지만 그래도 얼추 잘 해낸 거 같다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/zMkIINY.png&quot; alt=&quot;&quot;&gt;
&lt;img src=&quot;https://i.imgur.com/CF0tm7J.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;태스크를 분배하고 컨벤션, 기술스택, 배포에 대한 결정을 했는데 프론트엔드 팀원들은 대부분 스택이 비슷했기 때문에 정하는데 크게 어려움은 없었다.&lt;/p&gt;
&lt;h2 id=&quot;day56-개발&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#day56-%EA%B0%9C%EB%B0%9C&quot; aria-label=&quot;day56 개발 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Day5~6. 개발&lt;/h2&gt;
&lt;p&gt;주말에 드디어 개발을 했다. 개발을 이틀만 하니까 시간이 많이 부족하긴 했는데 초반부에서 생각을 맞추는 활동들을 하다 보니까 확실히 많은 시간이 들고 꼭 필요한 시간들이라는 생각이 들었다. 이렇게 하는 게 맞다는 생각이 들었다. &lt;code class=&quot;language-text&quot;&gt;이렇게 많은 시간을 투자했는데도 아직도 생각이 다른 부분들이 남아 있을 수 있기 때문&lt;/code&gt;이다.&lt;/p&gt;
&lt;p&gt;개발할 때는 PL로서 아래 항목들을 챙기려고 노력했다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;스케쥴 투명하게 관리
&lt;ul&gt;
&lt;li&gt;작업 가능한 시간, 불가능한 시간 공유&lt;/li&gt;
&lt;li&gt;온라인이면 zep에 항상 들어 와 있기
&lt;ul&gt;
&lt;li&gt;소통하기 편하고&lt;/li&gt;
&lt;li&gt;궁금한 거 봐주고&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자리 비울 때 디스코드에 올리기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;작업 상황 투명하게 관리
&lt;ul&gt;
&lt;li&gt;노션에 todo로 관리
&lt;ul&gt;
&lt;li&gt;실패(?)&lt;/li&gt;
&lt;li&gt;모두가 해당 항목에 동의했고 멤버들을 초대하려고 메일을 남겨달라고 했지만 전부가 남기진 않았음. 그래서 활용하지 못했음.&lt;/li&gt;
&lt;li&gt;하지만 노션 없이도 빠트린 내용없이 잘 완수했음. -&gt; 우리 팀엔 필요없는 거 같음!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;도와주기
&lt;ul&gt;
&lt;li&gt;모르는 거 봐주기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서로의 작업물 연결하기
&lt;ul&gt;
&lt;li&gt;밸런스 게임 2명, 토픽 추천 2명 이렇게 맡았기 때문에 서로의 작업물을 연결하는 작업을 해야했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;적절히 위임하기
&lt;ul&gt;
&lt;li&gt;챙기려고 했으나 신경써야 할 게 너무 많아서 밸런스 게임 주제, 대화 소재 등 데이터 부분을 백엔드에 챙겨달라고 위임.&lt;/li&gt;
&lt;li&gt;README → 써 본 경험 있는 팀원에게 위임. 대신 그 팀원의 개발 태스크를 도와줌.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;먼저 배포하기
&lt;ul&gt;
&lt;li&gt;배포하면 문제가 생기는 경우가 많아서 미리 미리 배포해보기
&lt;ul&gt;
&lt;li&gt;실제로 배포했는데 api가 안 불러와져서 보니까 vercel에 환경변수 등록하는걸 빼먹었었음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;덜어내기
&lt;ul&gt;
&lt;li&gt;카드 UI, interaction가 굉장히 어려웠다. 이 부분을 조금 덜어냈어야 했는데 그거라도 없으면 너무 심심할 거 같아서 미련을 좀 가지고 시간을 투자했다. 역시나 빠르게 덜어내는 게 더 나았을 것이라는 생각을 했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;day7-데모&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#day7-%EB%8D%B0%EB%AA%A8&quot; aria-label=&quot;day7 데모 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Day7. 데모&lt;/h2&gt;
&lt;p&gt;개발을 무사히 마치고 데모날이 왔다. 그리고 이렇게 메시지를 남겼다.
&lt;img src=&quot;https://i.imgur.com/it7YREu.png&quot; alt=&quot;&quot;&gt;
기능을 마무리하고 서비스에 크게 지장이 없는 선에서 챙길 수 있는 디테일을 계속 챙겨 나가다 보니 직전까지 정신이 없었다.&lt;/p&gt;
&lt;h3 id=&quot;페어-데모&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8E%98%EC%96%B4-%EB%8D%B0%EB%AA%A8&quot; aria-label=&quot;페어 데모 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;페어 데모&lt;/h3&gt;
&lt;p&gt;데모는 아래의 방식으로 진행했는데 데모를 하는 방식도 인상깊었다. 데모를 위한 데모가 아니라 정말 유저의 찐 반응을 볼 수 있도록 설계된 거 같아서 마음에 들었다.
&lt;img src=&quot;https://i.imgur.com/4GJzUhM.png&quot; alt=&quot;&quot;&gt;
&lt;img src=&quot;https://i.imgur.com/myuAAjs.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;사람-사는-거-다-똑같구나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%82%AC%EB%9E%8C-%EC%82%AC%EB%8A%94-%EA%B1%B0-%EB%8B%A4-%EB%98%91%EA%B0%99%EA%B5%AC%EB%82%98&quot; aria-label=&quot;사람 사는 거 다 똑같구나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;사람 사는 거 다 똑같구나&lt;/h3&gt;
&lt;p&gt;테오의 스프린트에서는 모두가 매끄러운 경험을 할 줄 알았는데 데모 때 보니까 사람 사는 거 다 똑같구나 하는 생각이 들었다. 디자이너가 도중에 이탈한 팀도 있고 배포했는데 문제가 생겨서 데모를 못한 팀도 있었다. 참 안쓰러우면서도 내가 정말 운이 좋아서 좋은 사람들을 만난 거였구나 하는 감사한 마음이 들었다.&lt;/p&gt;
&lt;p&gt;회사에서 이 경험을 공유했을 때 한 분이 “물론 운이 좋았다고 하실 거 같지만 그것 외에 데모를 성공적으로 마칠 수 있었던 비결이 뭐라고 생각하시나요?”라는 질문을 하셨다. 그 분이 원하는 대답을 하고 싶었지만 아무리 생각해봐도 이건 “운이 좋았다.” 라고밖에 설명할 길이 없었다. 좋은 사람들이 모여서 맡은 바 역할을 다 한 게 성공의 요인이었다는 게 내 결론이다.&lt;/p&gt;
&lt;h2 id=&quot;팀-회고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%80-%ED%9A%8C%EA%B3%A0&quot; aria-label=&quot;팀 회고 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;팀 회고&lt;/h2&gt;
&lt;p&gt;데모 후에 팀 회고를 하면서 스프린트를 마쳤다.&lt;/p&gt;
&lt;p&gt;모두 소통도 잘 되고 책임감 있게 서로의 역할을 다 했던 부분들이 좋았다고 작성했고 완성할 수 있어 좋았다고 했다. 의견을 나눌 때도 서로 잘 들어주고 존중하면서 진행했던 부분이 좋았다.&lt;/p&gt;
&lt;p&gt;아쉬웠던 부분은&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;데이터 부분이 조금 아쉬웠는데 대화 소재는 아이디에이션을 하고 투표를 해서 높은 투표 수를 받은 소재들을 위주로 쓰고 싶었는데 마음이 급해서 아이디에이션까지밖에 하지 못했다.&lt;/li&gt;
&lt;li&gt;밸런스 게임도 선택지 별로 질문을 다 다르게 하고 싶었는데 시간상 질문을 통일해야 했다. 하지만 질문을 통일하다 보니까 질문과 답변 사이 관계가 어색한 부분이 있었다.&lt;/li&gt;
&lt;li&gt;데모 때 카드가 스와이프 되는 걸 몰랐다는 피드백을 받았는데 이 부분이 많이 아쉬웠다. 시간 관계상 디자인을 바꿨는데 우리 팀원들이야 스와이프 되게 만들었다는 걸 알지만 모르는 사람이 봤을 때 스와이프 된다는 걸 충분히 인지하지 못 할 수 있었기 때문이다.
&lt;img src=&quot;https://i.imgur.com/jer6rpi.png&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;길게 썼지만 아쉬웠던 부분들은 다 나에 대한 내용이다. 내 욕심 그리고 셀프 회고 느낌. 다른 부분에 대해선 아쉬운 게 없을만큼 좋았다. 👍🏻&lt;/p&gt;
&lt;h3 id=&quot;다음-번-스프린트를-한다면&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%EC%9D%8C-%EB%B2%88-%EC%8A%A4%ED%94%84%EB%A6%B0%ED%8A%B8%EB%A5%BC-%ED%95%9C%EB%8B%A4%EB%A9%B4&quot; aria-label=&quot;다음 번 스프린트를 한다면 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다음 번 스프린트를 한다면&lt;/h3&gt;
&lt;p&gt;다음 번 스프린트를 상상하면서 어떤 것을 하면 좋을지 얘기를 하고 회고를 마무리했다. 이 부분도 의견들이 비슷해서 좋았다.
&lt;img src=&quot;https://i.imgur.com/5sUBDTJ.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;롤링-페이퍼&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A1%A4%EB%A7%81-%ED%8E%98%EC%9D%B4%ED%8D%BC&quot; aria-label=&quot;롤링 페이퍼 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;롤링 페이퍼&lt;/h3&gt;
&lt;p&gt;롤링 페이퍼도 썼는데 개인 것들은 이렇게 남겨두려고 한다. 대놓고 칭찬 받을 기회는 잘 없기 때문에 🤣 읽으면서 서툴지만 그래도 역할은 다 해낸 거 같다는 뿌듯한 마음이 들었다.
&lt;img src=&quot;https://i.imgur.com/PGsEjrK.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;대화가-어려운-당신을-위한-말해머해&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8C%80%ED%99%94%EA%B0%80-%EC%96%B4%EB%A0%A4%EC%9A%B4-%EB%8B%B9%EC%8B%A0%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%A7%90%ED%95%B4%EB%A8%B8%ED%95%B4&quot; aria-label=&quot;대화가 어려운 당신을 위한 말해머해 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;대화가 어려운 당신을 위한 말해머해&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mh-mh.vercel.app/&quot;&gt;서비스 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/p2UGPCv.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;좋았다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A2%8B%EC%95%98%EB%8B%A4&quot; aria-label=&quot;좋았다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;좋았다&lt;/h2&gt;
&lt;p&gt;일주일동안 정말 값진 경험을 할 수 있었다. 많이 배웠고 업무에서 써 먹으면 좋을 것 같은 부분들도 많았다. 그리고 부족했던 부분들은 채워 나가려고 한다. 누군가 테오의 스프린트에 참여하는 것을 고민하고 있다면 적극 추천하고 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[소플의 처음 만난 AWS 리뷰(한빛미디어)]]></title><description><![CDATA[AWS…]]></description><link>https://donghoon-song.github.io/books/소플의-처음-만난-aws-리뷰(한빛미디어)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/소플의-처음-만난-aws-리뷰(한빛미디어)/</guid><pubDate>Thu, 26 Dec 2024 15:13:30 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B9493989392_l.jpg&quot; alt=&quot;소플의 처음 만난 AWS&quot;&gt;
&lt;/div&gt;
&lt;p&gt;AWS는 처음 접할 때부터 어렵게 느껴졌다. 서비스가 워낙 많기도 하고 공식 문서나 자료를 읽는 것도 쉽지 않아서 공부 과정에서 많은 어려움을 겪었는데, 이 책은 그런 저에게 새로운 길을 열어주었다.&lt;/p&gt;
&lt;h3 id=&quot;쉽고-친근한-설명&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%89%BD%EA%B3%A0-%EC%B9%9C%EA%B7%BC%ED%95%9C-%EC%84%A4%EB%AA%85&quot; aria-label=&quot;쉽고 친근한 설명 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;쉽고 친근한 설명&lt;/h3&gt;
&lt;p&gt;이 책의 가장 큰 장점은 쉽게 풀어 쓴 설명이다. AWS의 기본 개념과 서비스 사용법을 마치 친근한 선생님이 알려주는 듯한 방식으로 전달해 주어 부담 없이 내용을 이해할 수 있었다. 이러한 접근 방식 덕분에 내용들이 친근하게 다가왔다. 또한, 깔끔하고 직관적인 책 디자인도 학습 효율을 높이는 데 큰 역할을 했다. 책의 구성이 체계적이어서 초보자들도 큰 부담 없이 차근차근 학습할 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;구체적이고-직관적인-실습-내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%EC%B2%B4%EC%A0%81%EC%9D%B4%EA%B3%A0-%EC%A7%81%EA%B4%80%EC%A0%81%EC%9D%B8-%EC%8B%A4%EC%8A%B5-%EB%82%B4%EC%9A%A9&quot; aria-label=&quot;구체적이고 직관적인 실습 내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;구체적이고 직관적인 실습 내용&lt;/h3&gt;
&lt;p&gt;책에 담긴 실습 내용은 AWS 서비스를 이해하는 데 큰 도움이 되었다. 실습이 상당히 구체적이고 따라 하기 쉬워서 저자가 실습을 구성하는 데 많은 고민을 했겠다는 생각이 들었다. 예를 들어, 사진 공유 웹사이트를 만드는 과정을 통해 S3와 EC2 같은 서비스의 실제 사용법을 체득할 수 있었다. 이러한 실습은 단순히 개념적인 이해를 넘어 실질적으로 클라우드 기반 애플리케이션을 구현하고 운영하는 데 필요한 자신감을 주었다. 실습 과정에서 마주친 문제들도 저자가 제공한 가이드라인 덕분에 쉽게 해결할 수 있었다는 점이 인상 깊었다.&lt;/p&gt;
&lt;h3 id=&quot;풍부한-그림-자료&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%92%8D%EB%B6%80%ED%95%9C-%EA%B7%B8%EB%A6%BC-%EC%9E%90%EB%A3%8C&quot; aria-label=&quot;풍부한 그림 자료 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;풍부한 그림 자료&lt;/h3&gt;
&lt;p&gt;이 책은 각 장에서 AWS 서비스의 동작 방식과 설정 과정을 이해하기 쉽게 그림과 다이어그램을 풍부하게 제공한다. 덕분에 독자가 복잡한 개념을 시각적으로 이해할 수 있었고, 책의 전반적인 접근성이 높아졌다. 예를 들어, IAM에서 사용자와 그룹을 설정하는 과정을 다이어그램으로 상세히 설명해 주어, 시각적인 자료 덕분에 이해도가 크게 높아졌다. 그림 자료가 부족하면 내용을 이해하기 어려웠을 부분도 쉽게 파악할 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;간결하고-핵심적인-내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%84%EA%B2%B0%ED%95%98%EA%B3%A0-%ED%95%B5%EC%8B%AC%EC%A0%81%EC%9D%B8-%EB%82%B4%EC%9A%A9&quot; aria-label=&quot;간결하고 핵심적인 내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;간결하고 핵심적인 내용&lt;/h3&gt;
&lt;p&gt;이 책의 구성은 아래와 같다. 간결하고 핵심적인 내용만 다루면서도 다양한 서비스를 다뤘다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클라우드 컴퓨팅과 AWS 기초(0~2장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;클라우드 컴퓨팅의 기본 개념과 AWS의 핵심 개념을 소개한다. 이를 통해 AWS를 처음 접하는 독자들도 쉽게 따라올 수 있도록 기초적인 배경지식을 제공한다. AWS의 탄생 배경, 주요 서비스의 역할, 클라우드 컴퓨팅의 장점 등을 다루며, 클라우드를 사용해야 하는 이유를 명확히 설명한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS 핵심 서비스 이해 및 실습(3장~8장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AWS의 주요 서비스를 다룬다. EC2, S3, RDS와 같은 핵심 서비스부터 Auto Scaling, ELB, IAM 같은 인프라 및 보안 관리 서비스까지 폭넓게 설명한다. 각 장은 개념 학습 파트와 실습 파트로 구성되어 있어 독자가 주요 서비스의 개념과 필요성을 이해한 뒤 실제 AWS 환경에서 직접 실습하며 해당 서비스의 작동 원리와 사용법을 익힐 수 있도록 돕는다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;심화 서비스와 운영 관리(9장~15장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AWS의 심화 서비스를 다룬다. CloudFront를 활용한 콘텐츠 전송 네트워크(CDN) 설정, Route 53을 통한 도메인 관리, DynamoDB와 같은 비관계형 데이터베이스 활용, Lambda를 사용한 서버리스 컴퓨팅 등의 고급 개념을 설명하며, AWS의 다양한 서비스가 어떻게 연동되고 운영되는지를 살펴본다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로젝트 실습(16장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AWS를 활용하여 실제 웹 애플리케이션을 구축하는 프로젝트를 진행한다. 앞서 배운 모든 내용을 바탕으로 사진 공유 웹사이트를 만들면서 AWS의 다양한 서비스를 어떻게 통합적으로 사용할 수 있는지를 직접 경험해본다. 이를 통해 실무에 바로 적용할 수 있는 클라우드 애플리케이션 구축 능력을 키울 수 있다.실무에 바로 적용 가능한 내용&lt;/p&gt;
&lt;p&gt;회사에서 자주 사용하는 IAM, S3, EC2, CloudWatch 같은 핵심 서비스에 대한 이해도를 높이는 데 큰 도움이 되었다. 이러한 서비스들이 실제 업무에서 어떻게 활용될 수 있는지 구체적인 사례와 함께 설명되어 있어서 실질적으로 바로 적용할 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;추천&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%94%EC%B2%9C&quot; aria-label=&quot;추천 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;추천&lt;/h3&gt;
&lt;p&gt;이 책은 AWS를 처음 접하거나 기존의 복잡한 문서에 지친 분들에게 강력히 추천할 만한 책이다. 특히, 클라우드 컴퓨팅에 대한 막연한 두려움을 가지고 있는 초보자들에게 적합한 길잡이가 되어 줄 것이다. 저처럼 AWS를 어렵게 느꼈던 독자라면, 이 책을 통해 새로운 자신감을 얻을 수 있을 것이다. 실습과 설명이 체계적으로 구성되어 있어 AWS에 대한 두려움을 없애고 새로운 도전을 시작할 수 있는 계기가 될 것이다. 이 책과 함께 AWS의 세계로 첫발을 내디뎌 보시기 바란다.&lt;/p&gt;
&lt;p&gt;“한빛미디어 &amp;#x3C;나는리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/p&gt;</content:encoded></item><item><title><![CDATA[테오콘(TEOConf 2024) 참가 후기]]></title><description><![CDATA[테오콘 작년 테오콘은 참석하지 못했는데 이번 테오콘은 스피커라서 10…]]></description><link>https://donghoon-song.github.io/회고/테오콘(teoconf-2024)-참가-후기/</link><guid isPermaLink="false">https://donghoon-song.github.io/회고/테오콘(teoconf-2024)-참가-후기/</guid><pubDate>Wed, 27 Nov 2024 20:11:09 GMT</pubDate><content:encoded>&lt;h2 id=&quot;테오콘&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%EC%98%A4%EC%BD%98&quot; aria-label=&quot;테오콘 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테오콘&lt;/h2&gt;
&lt;p&gt;작년 테오콘은 참석하지 못했는데 이번 테오콘은 스피커라서 100% 확률로 참석할 수 있었다. 😎 발표 준비를 하면서 테오님이 이 컨퍼런스를 열게 된 계기를 말씀해 주셨었는데 &lt;code class=&quot;language-text&quot;&gt;컨퍼런스가 끝나면 뭔가 열심히 들은 거 같은데 남은 게 없는듯한 기분으로 집에 돌아간 적이 많으시다고.&lt;/code&gt; 나도 실제로 컨퍼런스가 끝나고 공허한 상태에서 집에 간 적이 많았다. 머릿속은 발표 내용들로 꽉 찼는데 딱 거기까지였었다. 그래서 이번 테오콘이 기대됐다. 과연 이 문제를 어떻게 해결하실까 궁금했다.&lt;/p&gt;
&lt;h2 id=&quot;네트워킹-중심의-컨퍼런스&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9-%EC%A4%91%EC%8B%AC%EC%9D%98-%EC%BB%A8%ED%8D%BC%EB%9F%B0%EC%8A%A4&quot; aria-label=&quot;네트워킹 중심의 컨퍼런스 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;네트워킹 중심의 컨퍼런스&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/QMRJ76s.jpeg&quot; alt=&quot;네트워킹 중심의 컨퍼러스&quot;&gt;
테오콘은 철저히 네트워킹 중심의 새로운 포맷의 컨퍼런스였다. 우리는 정면을 바라보고 앉지 않고 원형 테이블을 중심으로 둥글게 앉았다.&lt;/p&gt;
&lt;p&gt;우리는 모두 닉네임을 가지고 편하게 소통했다. 그리고 닉네임과 관심사가 적힌 멋진 명함도 받았다.
&lt;img src=&quot;https://i.imgur.com/rsdjEHS.png&quot; alt=&quot;명함 굿즈&quot;&gt;
서로가 닉네임을 말하고 닉네임의 유래를 말하는데 정말 재밌었다. “주사위”를 좋아하시는 분도 계셨고 “이 세상의 중심은 나다”라는 의미의 닉네임을 가지신 분도 계셨다. 난 딱히 닉네임이 없어서 본명을 썼지만, 이 글을 쓰고 있는 시점에선 하나 만들었다. (드디어)&lt;/p&gt;
&lt;p&gt;자리에 앉자마자 발표를 듣지 않았고 서로 친해질 수 있는 충분한 시간을 가졌다. 처음에는 “개발을 시작한 계기”, “삶의 목표”, “이성을 볼 때 중요한 것”을 서로 적어보고 얘기하면서 말문을 틀 수 있었다. 여기서 팀원들의 다양한 배경과 가치관을 알 수 있었다. 이런 스몰토크를 진행할 수 있는 MC도 팀에서 뽑았는데 유치원 교사를 하시다가 개발자가 되신 분이 계셔서 ‘아 이분이다’ 싶었다. 기대에 부응해서 진행을 너무 잘 해주셨다. 유치원생이 된 기분이었다. 👶🏻
&lt;img src=&quot;https://i.imgur.com/SRu4W7h.jpeg&quot; alt=&quot;생각 보드&quot;&gt;&lt;/p&gt;
&lt;p&gt;서로 얼굴 그려주기 게임도 했는데 방식이 독특했다. 자신이 자주 쓰지 않는 손(난 오른손잡이니까 왼손)으로 그려야 했고 5초인가 동안 그리고 시계 방향으로 종이를 넘겨야 했다. 그렇게 모든 구성원이 짧은 시간 동안 불편한 손으로 그린 그림을 받을 수 있었는데 난 푸근한 군밤 같은 느낌으로 그려졌다.
&lt;img src=&quot;https://i.imgur.com/hYhz1Ia.jpeg&quot; alt=&quot;팀원들이 나를 그린 그림&quot;&gt;&lt;/p&gt;
&lt;p&gt;같이 게임을 하면서 서로의 무시무시한 승부욕도 볼 수 있었다. 초성 게임도 하고 노래 맞히기도 했다. 꽤 많이 맞춘 것 같았는데 순위권에 들기엔 조금 부족했다. 😅&lt;/p&gt;
&lt;p&gt;루키라는 분이 MC를 보셨는데 진짜 정말 재밌었다. 너무 잘하신다. 말이 안 된다고 생각했다. 그분도 분명 개발자실텐데.. 너무 멋졌다. 그래서 앞에 서로 친해질 수 있는 시간이 너무 빠르고 재밌게 흘러갔다.&lt;/p&gt;
&lt;h2 id=&quot;네트워킹-세션&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9-%EC%84%B8%EC%85%98&quot; aria-label=&quot;네트워킹 세션 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;네트워킹 세션&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;각 발표가 끝나고 네트워킹 세션을 통해 발표에 대해 팀원들과 의견을 나눌 수 있었다.&lt;/code&gt; 그게 정말 좋았다. 내가 듣고 느낀 것을 서로 나누는 그런 시간이 이전의 컨퍼런스에서는 빠져 있었던 것 같다. 이게 테오콘의 킥이었다고 생각한다. 나도 발표 준비를 하면서 네트워킹 질문들을 준비했는데 종이에 적혀 있는 내 질문을 보니까 기분이 신기했고 팀원들이 술술 얘기하는 걸 들으니, 질문도 잘 뽑았다는 생각이 들었다.&lt;/p&gt;
&lt;h2 id=&quot;선물-교환식&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%A0%EB%AC%BC-%EA%B5%90%ED%99%98%EC%8B%9D&quot; aria-label=&quot;선물 교환식 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;선물 교환식&lt;/h2&gt;
&lt;p&gt;선물 교환식도 너무 재밌었다. 만 원 이하의 선물을 준비해야 했는데 의미를 왕창 부여해도 되고 쓸데없는 걸 준비해도 됐다.
나는 앞날 창창 감성 LED 모던 수정구슬 침실 무드등을 준비했는데 굳이 의미 부여를 해보자면 우주의 중심 어쩌구 저쩌구..라고 할 수 있다!&lt;/p&gt;
&lt;div style=&quot;display: flex; justify-content: center;&quot;&gt;
&lt;img src=&quot;https://i.imgur.com/aSoQEwn.png&quot; alt=&quot;무드등&quot; style=&quot;width: 50%;&quot;&gt;
&lt;/div&gt;
나는 핸드워시를 받았는데 향도 좋았고 아주 유용하기도 했다. 마침 집에 있는 비누가 거품이 잘 안 나서 고민하고 있었는데 잘된 일이다.
&lt;h2 id=&quot;테오님의-마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%EC%98%A4%EB%8B%98%EC%9D%98-%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;테오님의 마무리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테오님의 마무리&lt;/h2&gt;
&lt;p&gt;테오님이 좋은 말씀 해주시면서 마무리할 수 있었다. 말씀을 들으면서 다른 분들이 사전에 제출했던 고민들도 들을 수 있었고 그에 대한 테오님의 조언도 들을 수 있었다. 계속하는 고민이지만 내가 성장했다는 것을 어떻게 측정할 수 있는지, 나는 성장하고 있는지, 더 잘하려면 어떻게 해야 할지 등에 대해서 곰곰이 생각해 볼 수 있었다. 아직 많이 멀었다. 주말에 귀중한 시간을 내서 테오콘에 참여했던 많은 분과 좋은 에너지를 나눌 수 있어서 좋았다. 내년에도 가고 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[소프트웨어 엔지니어 가이드북(The Software Engineers Guidebook) 리뷰 - 한빛미디어]]></title><description><![CDATA[“소프트웨어 엔지니어 가이드북”. 이 책이 나온다고 했을 때 꼭 읽어보고 싶었는데 운좋게 한빛미디어에서 제공받을 수 있었다. 이 책의 저자는 Pragmatic Programmers…]]></description><link>https://donghoon-song.github.io/books/소프트웨어-엔지니어-가이드북(the-software-engineers-guidebook)-리뷰---한빛미디어/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/소프트웨어-엔지니어-가이드북(the-software-engineers-guidebook)-리뷰---한빛미디어/</guid><pubDate>Tue, 26 Nov 2024 00:12:23 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B2570473158_l.jpg&quot; alt=&quot;소프트웨어 엔지니어 가이드북&quot;&gt;
&lt;/div&gt;
&lt;p&gt;“소프트웨어 엔지니어 가이드북”. 이 책이 나온다고 했을 때 꼭 읽어보고 싶었는데 운좋게 한빛미디어에서 제공받을 수 있었다. 이 책의 저자는 Pragmatic Programmers의 창시자인 게르겔리 오로스이다. 커리어를 시작한 단계부터 수석 엔지니어까지 커리어 전반에 걸친 포괄적인 가이드를 제공한다.&lt;/p&gt;
&lt;h2 id=&quot;-책의-구성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%B1%85%EC%9D%98-%EA%B5%AC%EC%84%B1&quot; aria-label=&quot; 책의 구성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📑 책의 구성&lt;/h2&gt;
&lt;p&gt;이 책은 크게 6부로 구성되어 있다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;개발자 커리어의 기본 사항&lt;/li&gt;
&lt;li&gt;유능한 소프트웨어 개발자&lt;/li&gt;
&lt;li&gt;다재다능한 시니어 엔지니어&lt;/li&gt;
&lt;li&gt;실용주의 테크리드&lt;/li&gt;
&lt;li&gt;롤모델로서의 스태프 및 수석 엔지니어&lt;/li&gt;
&lt;li&gt;결론&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;-주요-내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%A3%BC%EC%9A%94-%EB%82%B4%EC%9A%A9&quot; aria-label=&quot; 주요 내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;💡 주요 내용&lt;/h2&gt;
&lt;h3 id=&quot;1-커리어-관리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%BB%A4%EB%A6%AC%EC%96%B4-%EA%B4%80%EB%A6%AC&quot; aria-label=&quot;1 커리어 관리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 커리어 관리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;엔지니어로서의 커리어 패스 이해&lt;/li&gt;
&lt;li&gt;성과 평가 및 승진 전략&lt;/li&gt;
&lt;li&gt;자신의 성과를 효과적으로 공유하는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-기술적-역량-강화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EA%B8%B0%EC%88%A0%EC%A0%81-%EC%97%AD%EB%9F%89-%EA%B0%95%ED%99%94&quot; aria-label=&quot;2 기술적 역량 강화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. 기술적 역량 강화&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;효율적인 코딩 방법&lt;/li&gt;
&lt;li&gt;문제 해결과 디버깅 기술&lt;/li&gt;
&lt;li&gt;코드 품질 향상과 리팩토링&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-협업과-리더십&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%ED%98%91%EC%97%85%EA%B3%BC-%EB%A6%AC%EB%8D%94%EC%8B%AD&quot; aria-label=&quot;3 협업과 리더십 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. 협업과 리더십&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;코드 리뷰와 페어 프로그래밍&lt;/li&gt;
&lt;li&gt;효과적인 멘토링&lt;/li&gt;
&lt;li&gt;다양한 직군과의 협업 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-아키텍처와-시스템-설계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%84%A4%EA%B3%84&quot; aria-label=&quot;4 아키텍처와 시스템 설계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. 아키텍처와 시스템 설계&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;대규모 애플리케이션 구조 설계&lt;/li&gt;
&lt;li&gt;신뢰성 있는 시스템 구축&lt;/li&gt;
&lt;li&gt;성능 최적화 전략&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;-개인적인-소감&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EA%B0%9C%EC%9D%B8%EC%A0%81%EC%9D%B8-%EC%86%8C%EA%B0%90&quot; aria-label=&quot; 개인적인 소감 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🤔 개인적인 소감&lt;/h2&gt;
&lt;p&gt;이번에 셀리드를 맡으면서 어떻게 하면 더 잘 할 수 있을까 고민하고 있는데 업무에 적용해 볼 만한 포인트들이 많았다. 요즘에 서비스의 안정성을 높이기 위해 로깅 작업도 많이 해서 관심이 갔는데 좋은 내용들이 있었다. 로그에 어떤 내용을 담아야 좋은 로그가 되는지를 알려줬고 지금 내가 쌓고 있는 로그는 한참 부족하다는 것을 깨달았다. 개발자로서 설정할 수 있는 OKR에 대한 예시가 있는 것도 좋았다. 개발자는 평가를 어떻게 할지, OKR을 어떤 것으로 잡을지 사내 구성원들이 고민이 많았는데 예시를 보니 아이디어가 떠올랐다. 소프트 스킬에 대한 내용도 많이 강조됐다. 최근에 커뮤니케이션과 관련해서 발표했었는데 비슷한 내용이 책에 나와서 기뻤다. 목차 순서대로 주니어부터 시니어를 넘어서까지 포괄하고 있기 때문에 따라가며 읽기가 수월했다. 기나긴 커리어가 아직 한참 펼쳐질 것이라는 기대도 됐다.&lt;/p&gt;
&lt;h2 id=&quot;-결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot; 결론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📌 결론&lt;/h2&gt;
&lt;p&gt;이 책은 단순한 기술 서적을 넘어서는 포괄적인 가이드북이다. 특히 다음과 같은 독자에게 추천한다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;커리어 방향성을 고민하는 주니어 개발자&lt;/li&gt;
&lt;li&gt;리더십 역할을 준비하는 시니어 개발자&lt;/li&gt;
&lt;li&gt;체계적인 성장을 원하는 모든 소프트웨어 엔지니어&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 책은 계속 끼고 살아야 할 책이다. 이 책의 내용들을 체화한다면 정말 멋진 개발자가 되어 있지 않을까 싶기도 하다. 하나씩 체화해 볼 생각에 설렌다.&lt;/p&gt;
&lt;p&gt;한빛미디어 &amp;#x3C;나는리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[I in We x AWS] Mentoring Program 2024 후기]]></title><description><![CDATA[[I in We x AWS] Mentoring Program 202…]]></description><link>https://donghoon-song.github.io/회고/[i-in-we-x-aws]-mentoring-program-2024-후기/</link><guid isPermaLink="false">https://donghoon-song.github.io/회고/[i-in-we-x-aws]-mentoring-program-2024-후기/</guid><pubDate>Sun, 24 Nov 2024 08:11:53 GMT</pubDate><content:encoded>&lt;h2 id=&quot;i-in-we-x-aws-mentoring-program-2024-후기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#i-in-we-x-aws-mentoring-program-2024-%ED%9B%84%EA%B8%B0&quot; aria-label=&quot;i in we x aws mentoring program 2024 후기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;[I in We x AWS] Mentoring Program 2024 후기&lt;/h2&gt;
&lt;p&gt;이번달은 유난히 바빴다. 항상 일을 벌여 놓으면 한번에 몰려 오더라. 컨퍼런스 발표 준비와 멘토링이 겹치니 한달동안 퇴근 후에도, 주말에도 카페에 가면서 달렸다. 멘토링 시작할 때 쯤에 자취생의 야매요리도 시작했는데 그것도 이젠 잠시 쉬고 있다.&lt;/p&gt;
&lt;h3 id=&quot;-드디어-고민-해소&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%93%9C%EB%94%94%EC%96%B4-%EA%B3%A0%EB%AF%BC-%ED%95%B4%EC%86%8C&quot; aria-label=&quot; 드디어 고민 해소 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;💡 드디어 고민 해소&lt;/h3&gt;
&lt;p&gt;정신없이 하루하루를 보내다가 멘토링 초중반 쯤에 글또(개발자 글쓰기 모임) 9기가 끝났을 때가 생각났다. 2주에 글 하나씩 쓰는 것도 벅차서 커피챗도 많이 못하고 모임도 못 나갔던 게 아쉬웠는데, 이번 멘토링도 그렇게 흘려 보내고 싶지 않았다. 그런 생각을 하던 찰나에 멘토님께서 중요한 말씀을 해주셨는데 그 말씀 덕분에 멘토링에 임하는 태도를 크게 바꿀 수 있었다. 더 적극적으로, 더 치열하게 고민할 수 있었고 멘토링을 시작하기 전에 했던 묵혀뒀던 많은 고민들을 해소할 수 있었다.&lt;/p&gt;
&lt;p&gt;가장 큰 고민은 ‘내가 지금 잘 하고 있는가’ 였다. 누구나 할 수 있는 고민일거 같은데 해소하기가 참 어려웠다. 그래서 컨퍼런스 네트워킹 세션에 가서도 비슷한 연차의 개발자들과 얘기해보고 싶었는데 그런 사람을 만나기가 쉽지 않았다. 다행히 이번 멘토링을 통해서 나를 객관화해 볼 수 있는 방법을 배웠다.&lt;/p&gt;
&lt;h3 id=&quot;️-멋진-멘토님&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EF%B8%8F-%EB%A9%8B%EC%A7%84-%EB%A9%98%ED%86%A0%EB%8B%98&quot; aria-label=&quot;️ 멋진 멘토님 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🙋‍♂️ 멋진 멘토님&lt;/h3&gt;
&lt;p&gt;SungHyun Lim 멘토님은 정말 멋진 분이시다. 정말 도움이 되는 말씀들을 많이 해주셔서 좋았고 멘티들의 목소리 하나하나에 귀기울여 주셔서 좋았다. 보통의 멘토링의 경우 멘티 한명 한명의 뾰족한 고민들을 해소하기가 쉽지 않았는데 그걸 해주셨다. 최근에 발표 준비를 하면서 어떤 분이 다른 분에게 피드백해주신 내용을 간접적으로 들을 수 있었는데 “자신이 하고 싶은 말과 청자가 듣고 싶은 말을 균형있게 하는 게 중요하다” 였다. 딱 그걸 멘토님께서 해주신 것 같다. 온라인 멘토링을 할 때마다 하나하나 주옥 같은 말씀에 머리가 띵했고 시간이 너무나도 짧게 느껴졌다. 난 왜 이렇게 모르는 게 많을까 싶기도 했고. 이제서야 알았다는 사실에 다행이기도 싶었다. 커뮤니케이션도 너무 잘하시고 경험도 풍부하셔서 닮고 싶다는 생각이 자연스럽게 들었다. 그리고 나중에 멘토님처럼 다른 사람들을 돕고 싶다는 생각도 들었다.&lt;/p&gt;
&lt;h3 id=&quot;-멋진-멘티님들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%A9%8B%EC%A7%84-%EB%A9%98%ED%8B%B0%EB%8B%98%EB%93%A4&quot; aria-label=&quot; 멋진 멘티님들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;👥 멋진 멘티님들&lt;/h3&gt;
&lt;p&gt;다양한 배경의 멋진 멘티님들과도 함께 할 수 있어서 좋았다. 한분 한분 다 멋지셔서 배울점이 있다는 생각이 들었다. 온라인 멘토링 때는 얘기를 많이 못 해봤지만 이번 목요일에는 얘기를 해 볼 수 있을 거 같아서 기대된다 :)&lt;/p&gt;
&lt;h3 id=&quot;-스페셜-세션&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%8A%A4%ED%8E%98%EC%85%9C-%EC%84%B8%EC%85%98&quot; aria-label=&quot; 스페셜 세션 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📚 스페셜 세션&lt;/h3&gt;
&lt;p&gt;좋은 내용의 스페셜 세션들도 많이 준비되어 있어서 좋았다. 나는 그중에 Amazon의 10가지 개발문화 세션이 도움이 많이 됐는데, 문서에 집중하고 문서로 소통한다는 내용이 특히나 인상깊었다. 문서를 잘 작성하지 못하는 나도 한번 따라해 봐야겠다는 생각이 들었다.&lt;/p&gt;
&lt;h3 id=&quot;-멘티-미션들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%A9%98%ED%8B%B0-%EB%AF%B8%EC%85%98%EB%93%A4&quot; aria-label=&quot; 멘티 미션들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;✅ 멘티 미션들&lt;/h3&gt;
&lt;p&gt;다른 팀의 멘토, 멘티님들도 간접적으로 노션 페이지에서 만날 수 있었고 알아가는 게 즐거웠다. 준비된 미션을 하나하나 따라가다 보니 어느새 멘토링이 끝났다.&lt;/p&gt;
&lt;p&gt;나는 이 멘토링이 터닝 포인트가 되지 않을까 생각하고 있는데, 몇년 후에 다시 돌이켜봐도 이 멘토링이 터닝 포인트였다고 생각하지 않을까 싶다. 좋은 프로그램 준비해주신 유성실님, Olivia Son님과 다른 운영진 분들께도 너무 감사드린다. ☺️&lt;/p&gt;</content:encoded></item><item><title><![CDATA[TEOConf 2024 발표 후기]]></title><description><![CDATA[TEOConf 2024
스피커 사진
출처: TEOConf 2024 테오의 컨퍼런스(TEOConf)…]]></description><link>https://donghoon-song.github.io/회고/teoconf-2024-발표-후기/</link><guid isPermaLink="false">https://donghoon-song.github.io/회고/teoconf-2024-발표-후기/</guid><pubDate>Sun, 24 Nov 2024 08:11:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/n9RXs4l.png&quot; alt=&quot;TEOConf 2024&quot;&gt;
&lt;img src=&quot;https://i.imgur.com/0DtZfJ8.png&quot; alt=&quot;스피커 사진&quot;&gt;
출처: &lt;a href=&quot;https://www.teoconf.com/&quot;&gt;TEOConf 2024&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;테오의 컨퍼런스(TEOConf) 3회차에 드디어 발표했다! 발표했던 소감과 발표 준비 과정을 적어보려고 한다. 이 글에서 발표 준비는 어떤 식으로 이루어졌고 이런 부분에선 도움을 좀 받을 수 있겠구나 하는 점들을 전달하고 싶다.&lt;/p&gt;
&lt;h2 id=&quot;발표&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%9C%ED%91%9C&quot; aria-label=&quot;발표 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;발표&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&quot;출근해서 바로 써 먹을 수 있는 커뮤니케이션 팁&quot;&lt;/code&gt;이라는 주제로 발표했다. 생산성에 관심이 많은 나는 커뮤니케이션을 잘해서 나의 시간, 팀원들과 시간을 아끼고 싶었는데 커뮤니케이션을 잘해보려는 시행착오를 겪으며 좋았던 점들을 8가지 팁으로 정리했다. 거창한 주제는 아니지만 내 경험이 조금이나마 도움이 됐으면 하는 마음에서 발표했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/SKANq3Y.jpeg&quot; alt=&quot;발표 중&quot;&gt;&lt;/p&gt;
&lt;p&gt;발표하고 자리로 돌아와서 조원들과 얘기하는데 공감이 가는 부분이 많다고 해주셔서 뿌듯했다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;한 분은 비슷한 사례를 겪은 적이 있다고 자기 경험을 공유해주셨고&lt;/li&gt;
&lt;li&gt;다른 분은 팁을 하나씩 들을 때마다 모두 공감 가는 얘기여서 지난 경험을 떠올리며 들었다고 해주셨다.&lt;/li&gt;
&lt;li&gt;같은 조였던 내 친구는 실제 사례가 있으니 이해하기가 훨씬 쉽고 재밌었다고 했다. 마음 같아선 회사 벽에 팁을 인쇄해서 붙여놓고 싶다고 했다. 😅&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;모든 분의 의견을 들을 수는 없었지만 그래도 최소한 우리 조에서 이렇게 도움이 됐다고 해주셨으니, 전반적으로 도움이 됐을 거라는 생각이 들었다.&lt;/p&gt;
&lt;h2 id=&quot;어떻게-이-발표를-준비했나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9D%B4-%EB%B0%9C%ED%91%9C%EB%A5%BC-%EC%A4%80%EB%B9%84%ED%96%88%EB%82%98&quot; aria-label=&quot;어떻게 이 발표를 준비했나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 이 발표를 준비했나&lt;/h2&gt;
&lt;h3 id=&quot;도전하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8F%84%EC%A0%84%ED%95%98%EA%B8%B0&quot; aria-label=&quot;도전하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;도전하기&lt;/h3&gt;
&lt;p&gt;테오의 컨퍼런스 3회차 스피커 모집을 보고 신청했다. 많은 사람들 앞에서 오프라인으로 발표하는건 너무나 긴장되는 일이지만 도전하고 싶었다. 처음에 생각했던 제목은 “비개발직군과의 소통, 한 걸음 더 나아가기”였다. 회사에서 FE 개발자로 일하는 나는 비개발직군 팀원들과 소통을 많이 해야 했고 잘하고 싶은 마음에 이것저것 시도해 본 것을 공유하고 싶었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/JVX7p9h.png&quot; alt=&quot;테오의 컨퍼런스 3회차 스피커 모집&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;피드백&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%BC%EB%93%9C%EB%B0%B1&quot; aria-label=&quot;피드백 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;피드백&lt;/h3&gt;
&lt;p&gt;그렇게 준비했고 테오님과 온라인 미팅을 하면서 피드백을 받았다. 그때 나는 말을 제대로 못했다. 무슨 의미냐면, 이런 주제로 발표해야겠다는 생각은 했지만, 내용을 제대로 구체화하지 않아서 머릿속에 떠다니는 생각을 그 자리에서 설명하려고 하니까 테오님에게 제대로 내용이 전달되지 않았다. 테오님이 그 생각을 구체화할 수 있게 많이 도와주셨지만 나도 내가 하고 싶은 말을 정확히 전달할 수 없어서 답답했었다. 그래서 미팅이 끝나고 발표를 준비할 때 최대한 실제 사례를 가져오려고 노력했다. 그리고 주제도 바꿨다. 내가 전하고 싶은 내용이 꼭 비개발직군 팀원들과 소통할 때만 적용되는 내용은 아닌 것 같아서 더 보편적인 제목으로 바꿨다.&lt;/p&gt;
&lt;h3 id=&quot;리허설&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%ED%97%88%EC%84%A4&quot; aria-label=&quot;리허설 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리허설&lt;/h3&gt;
&lt;p&gt;발표 한 달 전에 오프라인 리허설을 했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/W4IGi1v.jpeg&quot; alt=&quot;스피커 리허설&quot;&gt;
출처: 테오의 프론트엔드 디스코드&lt;/p&gt;
&lt;p&gt;테오님과 솔싹님(스태프), 병스커님(스피커)를 만날 수 있었다! 3명 앞에서 발표하는데도 많이 긴장됐다. 하지만 엄청나게 몰입해서 들어주셔서 어느새 긴장감은 사라졌다. 이때 ppt의 내용을 채우는 것조차 힘들어서 정말 러프하게 내용만 있는 ppt를 가지고 발표했다. 이번에는 아무래도 실제 사례를 많이 들고 왔다 보니까 전달하고자 하는 바가 명확했고, 주제가 유니크하기도 하고 많이 공감할 수 있는 주제이기 때문에 더 재밌다고 해주셨다. 세 분이 너무나 좋은 피드백을 많이 해주셨는데 꼭 반영해야겠다 생각했던 것들을 꼽아봤다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;핵심 키워드인데 장표에 담겨 있지 않은 경우 -&gt; 장표에 넣어주기&lt;/li&gt;
&lt;li&gt;강조할 점 볼드처리하거나 색상 바꾸기&lt;/li&gt;
&lt;li&gt;팁이 여러 개여서 상단에 진행 상황을 보여주는 게 있으면 좋겠다.&lt;/li&gt;
&lt;li&gt;발표 톤이 기술 세미나 하는 톤이어서(말끝을 “습니다.&quot;&quot; 라고만 끝냈음 😅) 아쉽다. 팁을 주고 있는 입장이기 때문에 자신 있는 강사 톤이었으면 좋겠다.&lt;/li&gt;
&lt;li&gt;팁을 먼저 제시하기보다는 사례 탐구 식으로 사례 -&gt; 팁 순서로 하면 좋겠다.&lt;/li&gt;
&lt;li&gt;HOW가 부족하다. 실제로 어떻게 적용해 볼 수 있는지 구체적인 문장이 팁이 됐으면 좋겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;장표는 거의 새로 만드는 수준으로 많이 바꿨고 시간도 엄청나게 오래 걸렸다. 발표 전주에 오늘은 끝내야지 오늘은 끝내야지 하다가 안 끝나서 주말에 겨우겨우 끝낼 수 있었다.&lt;/p&gt;
&lt;p&gt;이렇게 피드백해 주시는 내용들이 너무 좋았다. 아마 이 &lt;code class=&quot;language-text&quot;&gt;피드백들이 없었다면 발표나 장표 퀄리티가 엄청 안 좋았을 것이라고 확신&lt;/code&gt;한다. 많이 도와주셔서 너무 감사했다.&lt;/p&gt;
&lt;h3 id=&quot;연습-또-연습&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%97%B0%EC%8A%B5-%EB%98%90-%EC%97%B0%EC%8A%B5&quot; aria-label=&quot;연습 또 연습 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;연습 또 연습&lt;/h3&gt;
&lt;p&gt;나는 발표할 때 사람 눈을 마주치면 그렇게 머리가 하얘지더라. 그리고 발표자 노트를 안 보고도 잘 해내고 싶어서 연습 또 연습했다.&lt;/p&gt;
&lt;h2 id=&quot;다음에-발표를-또-한다면&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%EC%9D%8C%EC%97%90-%EB%B0%9C%ED%91%9C%EB%A5%BC-%EB%98%90-%ED%95%9C%EB%8B%A4%EB%A9%B4&quot; aria-label=&quot;다음에 발표를 또 한다면 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다음에 발표를 또 한다면&lt;/h2&gt;
&lt;p&gt;발표 준비 과정도 그때그때 글로 남기면 좋겠다 싶다. 지금 이 글을 쓰고 있는 시점에서 회상하려고 하니까 역시나 잘 생각이 나지 않는다. 🫨&lt;/p&gt;
&lt;p&gt;리허설을 한 달 전에 빠르게 해보는 건 너무나 좋았다. 다음에도 그렇게 하고 싶다. 리허설을 빠르게 하지 않았다면 나는 아마 발표 전날까지도 ppt를 만들고 있었을지도..&lt;/p&gt;
&lt;p&gt;같은 내용으로 다른 데서 발표해 보는 것도 좋겠다는 생각이 들었다.&lt;/p&gt;
&lt;h3 id=&quot;발표하고-싶지만-머뭇거리고-있는-당신-바로-신청하시죠&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%9C%ED%91%9C%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%A7%80%EB%A7%8C-%EB%A8%B8%EB%AD%87%EA%B1%B0%EB%A6%AC%EA%B3%A0-%EC%9E%88%EB%8A%94-%EB%8B%B9%EC%8B%A0-%EB%B0%94%EB%A1%9C-%EC%8B%A0%EC%B2%AD%ED%95%98%EC%8B%9C%EC%A3%A0&quot; aria-label=&quot;발표하고 싶지만 머뭇거리고 있는 당신 바로 신청하시죠 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;발표하고 싶지만 머뭇거리고 있는 당신! 바로 신청하시죠&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/donghoon759/culgeunhaeseo-baro-sseo-meogeul-su-issneun-keomyunikeisyeon-tib&quot;&gt;발표자료 링크&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[textarea를 감싸는 div에 여백이 생겨버리는 이유]]></title><description><![CDATA[개발을 하다가 단순히 textarea 하나만을 감싸는 div의 높이가 textarea…]]></description><link>https://donghoon-song.github.io/css/textarea를-감싸는-div에-여백이-생겨버리는-이유/</link><guid isPermaLink="false">https://donghoon-song.github.io/css/textarea를-감싸는-div에-여백이-생겨버리는-이유/</guid><pubDate>Sun, 10 Nov 2024 10:11:03 GMT</pubDate><content:encoded>&lt;p&gt;개발을 하다가 단순히 textarea 하나만을 감싸는 div의 높이가 textarea보다 더 큰 문제가 있었는데 개발자도구로 요리보고 저리봐도 원인을 찾지 못했다. 마치 투명한 뭔가가 사이에 끼어 있는 것 같았는데 이 답답함을 말로 형용할 수 없었다. 이걸 뭐라고 검색해야 할지조차 몰라서 영원한 친구 ChatGPT에게 물어보고 실마리를 찾을 수 있었다.&lt;/p&gt;
&lt;p&gt;코드는 다음과 같다. 정말 간단하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;textarea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;textarea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;생기는 여백을 더 쉽게 보기 위해 아래 codepen을 추가했다.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Untitled&quot; src=&quot;https://codepen.io/donghoon759/embed/KKOrYxP?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/donghoon759/pen/KKOrYxP&quot;&gt;
  Untitled&lt;/a&gt; by Donghoon Song (&lt;a href=&quot;https://codepen.io/donghoon759&quot;&gt;@donghoon759&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;분명히 두 태그 사이에는 아무런 여백이 없는데 textarea를 감싸는 div의 높이가 textarea보다 더 크게 나타나는 문제가 있었다.&lt;/p&gt;
&lt;h2 id=&quot;원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;원인 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;원인&lt;/h2&gt;
&lt;p&gt;이런 현상은 textarea의 기본 display 속성이 inline-block이기 때문에 발생한다. &lt;a href=&quot;https://webclub.tistory.com/533&quot;&gt;inline 또는 inline-block 요소 사이에 생기는 여백&lt;/a&gt; 또한 예상치 못했던 문제 상황이었는데 이 이슈는 inline-block 요소의 수직 정렬 방식 때문에 발생한다.&lt;/p&gt;
&lt;h2 id=&quot;수직-정렬-문제와-descender-공간&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%88%98%EC%A7%81-%EC%A0%95%EB%A0%AC-%EB%AC%B8%EC%A0%9C%EC%99%80-descender-%EA%B3%B5%EA%B0%84&quot; aria-label=&quot;수직 정렬 문제와 descender 공간 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;수직 정렬 문제와 descender 공간&lt;/h2&gt;
&lt;p&gt;inline 또는 inline-block 요소는 텍스트와 같은 방식으로 수직 정렬이 이루어진다. 기본적으로 vertical-align 속성이 명시되지 않으면, 요소는 부모 요소의 &lt;code class=&quot;language-text&quot;&gt;기준선(baseline)&lt;/code&gt;에 맞춰진다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.w3.org/TR/css-inline-3/images/text-edge.png&quot; alt=&quot;text-edge&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;기준선(baseline): 텍스트에서 소문자 ‘x’의 하단에 해당하는 가상의 선으로, 대부분의 문자들이 이 선 위에 위치한다.&lt;/li&gt;
&lt;li&gt;descender: ‘g’, ‘p’, ‘q’와 같이 기준선 아래로 내려오는 문자 부분을 말한다. 이러한 문자들을 고려하여 텍스트의 하단에는 약간의 여백이 필요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;textarea 내부에 텍스트가 없어도 브라우저는 descender가 입력될 때를 대비해서 미리 공간을 확보해 놓는다. 이로 인해 textarea의 높이가 예상보다 크게 나타나는 것이다.&lt;/p&gt;
&lt;p&gt;descender라는 개념은 &lt;a href=&quot;https://wit.nts-corp.com/2017/09/25/4903&quot;&gt;font metrics&lt;/a&gt;와 관련이 있다.&lt;/p&gt;
&lt;h2 id=&quot;해결-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;해결 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결 방법&lt;/h2&gt;
&lt;p&gt;가장 간단하고 직관적으로 해결하는 방법은 textarea의 display 속성을 block으로 변경하는 것이다. 이렇게 하면 textarea는 블록 요소로 취급되어 수직 정렬 이슈가 사라진다. 블록 요소는 자동으로 새로운 줄에서 시작하고, 전체 가로 너비를 차지하므로 추가적인 여백이 제거된다.&lt;/p&gt;
&lt;p&gt;textarea의 vertical-align값을 top이나 middle로 수정하는 방법도 있다. 이렇게 하면 textarea의 display속성을 바꾸지 않고 해결할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;textarea&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; top&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;비슷한-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B9%84%EC%8A%B7%ED%95%9C-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;비슷한 문제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;비슷한 문제&lt;/h3&gt;
&lt;p&gt;이미지 태그를 사용할 때도 비슷한 문제가 발생한다. 이미지 아래에 불필요한 여백이 생기는데, 이것도 이미지가 inline 요소이기 때문에 발생하는 문제이다. 이런 경우에도 이미지의 display 속성을 block으로 변경하거나 vertical-align 속성을 수정하면 해결할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* 또는 */&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bottom&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리&lt;/h2&gt;
&lt;p&gt;정리하자면 textarea를 감싸는 div의 높이가 예상보다 크게 나타나는 문제는 inline-block 요소의 수직 정렬 방식과 descender 공간 때문에 발생한다. css의 세계는 무궁무진하고 공부해야 할 것들이 정말 많은 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;참고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0&quot; aria-label=&quot;참고 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;vertical align: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align&quot;&gt;MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;이미지-출처&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B6%9C%EC%B2%98&quot; aria-label=&quot;이미지 출처 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이미지 출처&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/css-inline-3/&quot;&gt;w3.org&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[마무리가 약한 나의 마무리]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/maker-log/마무리가-약한-나의-마무리/</link><guid isPermaLink="false">https://donghoon-song.github.io/maker-log/마무리가-약한-나의-마무리/</guid><pubDate>Sun, 13 Oct 2024 16:10:54 GMT</pubDate><content:encoded>&lt;p&gt;서울국제도서전에 다녀왔던 적이 있다. 많은 부스가 있었지만 커다란 벽에 자기만 알고 있는 동네 서점을 소개하는 공간이 있었다. 지금은 사라진 곳도 있고 엄청 큰 서점도 있고 아주 다양한 서점을 담고 있는 포스트잇들이 붙어 있었다. 지금은 사라졌지만 어릴적 아버지가 운영했다는 서점도 있었고 친구들과의 추억이 담긴 서점도 있었다.&lt;/p&gt;
&lt;p&gt;서울국제도서전에 다녀왔던 적이 있다. 많은 부스가 있었지만, 특히 내 눈길을 끈 건 커다란 벽에 사람들이 자기만 알고 있는 동네 서점을 소개하는 공간이었다. 벽에는 각기 다른 사람들의 이야기가 담긴 포스트잇들이 빼곡히 붙어 있었다. 지금은 사라진 서점도 있었고 한 참가자는 어릴 적 아버지가 운영했던 서점이라고 적어 놓았다. 또 다른 사람들은 친구들과의 추억이 깃든 서점을 공유하며 그 순간의 특별함을 나누었다. 지금은 볼 수 없는 작은 서점도 있었고, 이미 유명해진 대형 서점도 있었다. 이 다양한 서점들을 보면서 문득 이런 서점들을 모아볼 수 있는 공간이 있으면 얼마나 재미있을까 하는 생각이 들었다. 게다가 이런 서점들은 기존 지도 앱에서는 찾아보기 힘들 것이다. 그렇게 나는 작은 아이디어에서 출발해 지도 앱을 만들기 시작했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/bUzOQZV.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/rMKy9Sr.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 나는 충동적으로 프로젝트를 시작하는 데 능숙하다. 나에게 작업했던 다른 사이드 프로젝트들도 많다. 그러나 문제는 마무리를 잘 짓지 못한다는 점이다. 프로젝트의 초반에는 열정적이지만, 시간이 지나면서 동기가 약해지거나 더 재미있어 보이는 새로운 아이디어가 생겨서 기존 프로젝트를 끝내지 못하고 중단하게 된다. 특히 이번에도 어김없이 여러 가지 생각들이 머리를 스쳐 지나갔다. 그중 가장 큰 고민은 역시나 ‘내가 이걸 만든다고 해서 사람들이 정말 사용할까?‘라는 의문이었다. 나는 내가 만든 서비스가 사람들에게 유용하게 사용되길 바라는 마음이 크다. 하지만 이러한 기대감이 오히려 나를 주저하게 만들었다는 것을 깨닫게 되었다.&lt;/p&gt;
&lt;p&gt;이번에는 이러한 마음을 이겨내기로 했다. 이런 마음 때문에 마무리하지 못한 프로젝트들이 얼마나 많은지 알기 때문이다. 처음부터 사람들이 사용해 줄 거라는 욕심과 기대는 버리기로 했다. 대신 이 프로젝트들을 끝까지 완성하면서 배우려는 자세로 임하기로 했다. 생각해 보면, 애초에 내가 홍보하지 않는 한 내가 만든 서비스를 사람들이 알지 못할 것이다. 그렇다면, 사용자에 대한 기대보다 내가 무엇을 배울 수 있을지에 집중하는 것이 더 의미 있을 것이다. 회사에서는 다루지 않는 기능을 구현하고, 마주치지 않는 문제들을 해결해 나가면서 경험을 하나씩 쌓아가는 것이 훨씬 더 중요한 자산이 될 것이라고 생각했다. 그렇게 하나의 프로젝트를 완성하고 경험을 쌓아가는 과정이 나중에는 진정으로 사람들이 원하는 서비스를 만드는 데 큰 도움이 될 것이라는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;나는 또한 배포 과정에서 생기는 문제들을 빨리 마주하는 것을 선호한다. 보통은 프로젝트가 완전히 끝난 후에 배포하는 경우가 많지만, 나는 되도록 빨리 배포하는 편이다. 왜냐하면 배포 과정에서 항상 예상치 못한 문제가 발생하기 때문이다. 빌드 에러가 그중 하나다. 개발 중에는 전혀 보이지 않던 타입 에러들이 빌드할 때 한꺼번에 드러나는 경우가 많다. 그래서 나는 이런 에러들을 빨리 발견하고 수정하는 것이 마음이 편하다. 무엇보다도 배포를 완료했을 때 비로소 내가 이 프로젝트를 만들었다는 실감이 난다. 로컬에서 혼자 개발하는 것과 실제로 다른 사람들도 볼 수 있게 배포하는 것은 큰 차이가 있다. 그래서 배포를 완료하는 것이 나에게는 프로젝트의 하나의 마무리이자 동시에 진정한 시작이라고 느껴진다.&lt;/p&gt;
&lt;p&gt;이번 지도 앱 프로젝트에서도 지도 API를 처음 사용해 보면서 여러 문제에 부딪혔다. 처음 접하는 기술을 사용하다 보니 막히는 부분도 많았지만, 그 과정을 통해 정말 많은 것을 배울 수 있었다. 결국 나는 광활한 인터넷에 또 하나의 작은 씨앗을 심었다. 그렇게 나만의 독립 서점 지도 웹앱이 탄생했다. 이 프로젝트는 단순히 한낱 사이드 프로젝트로 끝나는 것이 아니라, 나에게 있어서 의미 있는 배움의 과정이었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://indie-bookstore.vercel.app/&quot;&gt;https://indie-bookstore.vercel.app/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이번 프로젝트가 나의 터닝 포인트가 됐으면 좋겠다. 이전에 같은 이유로 관뒀던 프로젝트들도 다시 들여다보고 세상에 내보이고 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[그림으로 이해하는 서버 구조와 기술 리뷰 - 길벗]]></title><description><![CDATA[정말 쉬운 네트워크 책 이 책은 정말 쉽습니다. 복잡한 개념을 시각적으로 쉽게 이해할 수 있도록 돕는 213개의 그림과 1…]]></description><link>https://donghoon-song.github.io/books/그림으로-이해하는-서버-구조와-기술-리뷰---길벗/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/그림으로-이해하는-서버-구조와-기술-리뷰---길벗/</guid><pubDate>Mon, 30 Sep 2024 21:09:33 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://gimg.gilbut.co.kr/book/BN004119/rn_view_BN004119.jpg&quot; alt=&quot;그림으로 이해하는 서버 구조와 기술&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;정말-쉬운-네트워크-책&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A7%90-%EC%89%AC%EC%9A%B4-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B1%85&quot; aria-label=&quot;정말 쉬운 네트워크 책 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정말 쉬운 네트워크 책&lt;/h2&gt;
&lt;p&gt;이 책은 정말 쉽습니다. 복잡한 개념을 시각적으로 쉽게 이해할 수 있도록 돕는 213개의 그림과 17개의 표를 활용합니다. 어려운 용어나 전문적인 설명을 최소화하고, 대신 일상적인 비유와 실용적인 예시를 통해 서버의 역할, 운영체제, 네트워크 장비의 기능을 설명합니다. 예를 들어, TCP/IP 모델을 설명할 때, 각 계층의 기능을 마치 우편 배달 시스템처럼 단순화해 설명하는 방식은 큰 도움이 됩니다.
여러번 읽어도 기억에 잘 남지 않았던 TCP/IP의 각 계층별 역할도 택배에 비유해서 설명해주는데 이해가 잘 됐습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/WshCXTR.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/LNGRcT4.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;작고-가벼운-책&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%91%EA%B3%A0-%EA%B0%80%EB%B2%BC%EC%9A%B4-%EC%B1%85&quot; aria-label=&quot;작고 가벼운 책 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;작고 가벼운 책&lt;/h2&gt;
&lt;p&gt;보통 네트워크 책이라고 하면 500쪽 정도 되는 들고 다니기도 힘든 무거운 책이 대부분인데 이 책은 정말 가볍습니다. 가방에 넣고 다니면서 자투리 시간에 읽기에도 딱 좋습니다. 이 책이 제가 대학생 때 나왔다면 네트워크 개념을 더 쉽게 이해할 수 있었을 것 같은데 아쉽습니다. 책을 읽으면서 알고 있던 개념은 쉽게 리마인드하고 새로운 개념들은 빠르게 이해할 수 있었습니다.&lt;/p&gt;
&lt;h2 id=&quot;다양한-주제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%EC%96%91%ED%95%9C-%EC%A3%BC%EC%A0%9C&quot; aria-label=&quot;다양한 주제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다양한 주제&lt;/h2&gt;
&lt;p&gt;책이 가볍지만 정말 다양한 주제를 다룹니다. 처음에는 서버와 클라이언트 등 기본 개념을 설명하고 서버의 종류, 요구사항, 다양한 구성, 보안, 장애 대응 기술 등 실무에서 사용되는 개념들도 설명합니다. 그래서 단순한 입무서를 넘어 서버와 네트워크의 전체적인 흐름을 이해하는데 아주 유용합니다. 1장에서는 서버, 클라이언트 등 기초 지식을 배웁니다. 2장에서는 네트워크를 배우며 OSI 참조 모델, TCP/IP 등 데이터 전송을 이해하는데 중요한 개념들을 배웁니다. 3장에서는 서버 형태를 배우며 우리가 흔히 사용하는 클라우드형 서버에 대해서도 배웁니다. 온프레미스, 클라우드, 하이브리드 등의 형태를 배우고 각 형태의 장단점을 배웁니다. 4장에서는 웹 서버, DNS 서버 등 외부용 서버를 배웁니다. 5장에서는 파일 서버, 프린터 서버 등 내부용 서버를 배우고 6장에서는 서버 보안에 대해서 배웁니다. 방화벽과 SSL, VPN의 개념이 등장합니다. 후반부인 7장에서는 서버 장애에 대비하는 기술들을 배우며 8장에서는 서버 운용에 대해서 배웁니다.&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;이미 네트워크 개념을 알고 있지만 빠르게 정리하고 싶은 분들에게도 좋고 두껍고 어려운 네트워크 책은 소화하기 힘든 입문자분들에게도 좋겠다는 생각이 들었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[두부의 캐릭터 드로잉 리뷰 with 프로크리에이트  - 한빛미디어]]></title><description><![CDATA[“두부의 캐릭터 드로잉 with…]]></description><link>https://donghoon-song.github.io/books/두부의-캐릭터-드로잉-리뷰-with-프로크리에이트----한빛미디어/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/두부의-캐릭터-드로잉-리뷰-with-프로크리에이트----한빛미디어/</guid><pubDate>Sun, 29 Sep 2024 20:09:33 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B9711360107_l.jpg&quot; alt=&quot;두부의 캐릭터 드로잉 with 프로크리에이트&quot;&gt;
&lt;/div&gt;
&lt;p&gt;“두부의 캐릭터 드로잉 with 프로크리에이트”는 프로크리에이트를 활용한 캐릭터 드로잉 기법을 다룬 책입니다. 이 책은 디지털 드로잉을 처음 시작하는 사람들을 위해 프로크리에이트의 기초부터 나만의 캐릭터와 굿즈를 만드는 방법까지 단계별로 설명하고 있습니다. 취미로 귀엽고 아기자기한 캐릭터를 그려보고 싶으신 분들에게 추천하는 책입니다. 책의 후반부에는 만든 작품을 굿즈로 발주하는 과정도 담겨 있어서 굿즈에 관심이 많으신 분들에게도 추천할 수 있습니다.&lt;/p&gt;
&lt;p&gt;1장에서는 프로크리에이트의 기본적인 기능을 익히고 간단한 드로잉을 합니다. 2장에서는 동물 캐릭터를 그리기 위한 이론들(얼굴형, 특징 파악하기 등)을 배웁니다. 작가님이 준비해주신 프리셋 파일이 있어서 편하게 참고할 수 있습니다. 3장에서는 그렸던 캐릭터들에 표정, 동작을 추가합니다. 그 외에 음료를 잡고 있거나 돗자리 위에 앉아 있거나 하는 등 다양한 상황에서의 드로잉 방법을 배웁니다. 4장에서는 채색 개념부터 시작해서 개념을 토대로 채색하는 팁을 배웁니다.&lt;/p&gt;
&lt;p&gt;저는 그림을 정말 못 그리는데 책을 읽고 천천히 따라가다보니 너무 재밌고 아기자기한 캐릭터들을 그릴 수 있어서 좋았습니다. 저같은 경우에는 사이드 프로젝트에서 사용할만한 캐릭터를 그려보고 싶어서 읽었는데, 책을 읽고 나니 굿즈로 만들어서 나만의 캐릭터를 만들어보고 싶은 생각이 들었습니다. 그리고 프로크리에이트가 엄청 사용하기 편하다는 생각이 많이 들었습니다. 손가락 두개로 터치하면 실행취소, 세개로 터치하면 다시 실행인데 그 외에도 사용자를 고려한 기능들이 많아서 사용하기 편했습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[실무로 통하는 클린 코드(한빛미디어) 리뷰]]></title><description><![CDATA[25장, 20…]]></description><link>https://donghoon-song.github.io/books/실무로-통하는-클린-코드(한빛미디어)-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/실무로-통하는-클린-코드(한빛미디어)-리뷰/</guid><pubDate>Tue, 27 Aug 2024 21:08:20 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B2230430901_l.jpg&quot; alt=&quot;실무로 통하는 클린 코드&quot;&gt;
&lt;/div&gt;
&lt;p&gt;25장, 200가지 이상의 예시로 이루어진 이 책은 백과사전 같은 느낌을 줍니다. 내용이 방대해 읽을 엄두는 안 나지만 컴퓨터 옆에 놓고 필요할 때마다 참고할 수 있는 든든한 동반자 같은 느낌을 줬습니다. 큰 업무를 작게 나누듯 패턴들을 한번에 이해하기 부담없는 작은 단위들로 나눠놨습니다. 그리고 대부분의 클린 코드 책이 Java코드를 예제로 사용했는데 이 책은 python, javascript, c++ 등 다양한 언어를 사용해서 읽을 때마다 환기되는 느낌이었습니다. 그 외에 특히 도움이 됐던 내용들을 나열하면 다음과 같습니다.&lt;/p&gt;
&lt;h2 id=&quot;기본형-데이터-구체화하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EB%B3%B8%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%B2%B4%ED%99%94%ED%95%98%EA%B8%B0&quot; aria-label=&quot;기본형 데이터 구체화하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기본형 데이터 구체화하기&lt;/h2&gt;
&lt;p&gt;이 챕터를 읽고 나니 기본형 타입을 많이 썼던 것 같습니다. 아래와 같은 식으로 작성하면 ‘무엇’과 ‘어떻게’를 명확하게 분리할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Port&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;www.example.org:8080&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;Port&lt;/span&gt; in &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;URI&lt;/span&gt; uri &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;InetSocketAddress&lt;/span&gt; address &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asInetSocketAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Path&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/index.html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;삼항식-제거&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%82%BC%ED%95%AD%EC%8B%9D-%EC%A0%9C%EA%B1%B0&quot; aria-label=&quot;삼항식 제거 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;삼항식 제거&lt;/h2&gt;
&lt;p&gt;중첩된 삼항식을 피하는 부분도 좋았습니다. 한 줄에 쓰기 간결해서 삼항식도 자주 작성했지만 시간이 지날수록 코드를 이해하는데 시간이 더 드는 느낌이 강했습니다.&lt;/p&gt;
&lt;h2 id=&quot;주석을-테스트로-대체하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A3%BC%EC%84%9D%EC%9D%84-%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A1%9C-%EB%8C%80%EC%B2%B4%ED%95%98%EA%B8%B0&quot; aria-label=&quot;주석을 테스트로 대체하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;주석을 테스트로 대체하기&lt;/h2&gt;
&lt;p&gt;새로운 함수를 작성하면 주석을 작성하는 일이 많아졌습니다. 하지만 이를 테스트 케이스로 남기면, 함수의 동작을 더 정확하게 보장할 수 있고 읽는 사람도 이해하기 더 쉬울 것 같습니다.&lt;/p&gt;
&lt;h2 id=&quot;전제-조건-적용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%84%EC%A0%9C-%EC%A1%B0%EA%B1%B4-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;전제 조건 적용하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;전제 조건 적용하기&lt;/h2&gt;
&lt;p&gt;성능에 심각한 문제가 있지 않는 한, 어서션을 제대로 구성합니다. 데이터가 정상적인 범위 내에 있을 거라는 확신을 버리고 예외 케이스에 대해서 예외 처리를 항상 해서 빠르게 실패하는 편이 오히려 데이터 손상을 찾는 빠른 길이라는 것을 배웠습니다.&lt;/p&gt;
&lt;h2 id=&quot;총평&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B4%9D%ED%8F%89&quot; aria-label=&quot;총평 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;총평&lt;/h2&gt;
&lt;p&gt;디자인 시스템 책은 내용이 방대하기 때문에 읽고 지나치는 등 적용하지 못했던 경우가 많았습니다. 이 책을 읽고 나니 알고 있던 내용들은 환기가 되고 새로운 내용 또한 도움이 많이 됐습니다. 앞으로는 각 항목에 대해 활용 사례를 같이 적으면서 천천히 적용해보려고 합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[자바스크립트 리액트 디자인패턴(한빛미디어) 도서 리뷰]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/자바스크립트-리액트-디자인패턴(한빛미디어)-도서-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/자바스크립트-리액트-디자인패턴(한빛미디어)-도서-리뷰/</guid><pubDate>Mon, 26 Aug 2024 19:08:34 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B2831932445_l.jpg&quot; alt=&quot;자바스크립트+리액트 디자인 패턴&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;자바스크립트리액트-디자인-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;자바스크립트리액트 디자인 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;자바스크립트+리액트 디자인 패턴&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;자바스크립트+리액트 디자인 패턴&lt;/strong&gt;은 최신 자바스크립트 디자인 패턴과 함께 리액트에서 적용할 수 있는 패턴까지 광범위하게 다룹니다.&lt;/p&gt;
&lt;h2 id=&quot;디자인-패턴은-왜-디자인-패턴인가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4%EC%9D%80-%EC%99%9C-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;디자인 패턴은 왜 디자인 패턴인가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;디자인 패턴은 왜 디자인 패턴인가&lt;/h2&gt;
&lt;p&gt;이 책은 보통의 디자인 패턴 책들과 다르게 앞장에서 스스로 생각해 볼 거리들을 많이 던져줍니다.&lt;/p&gt;
&lt;p&gt;1장에서는 디자인 패턴을 개념적으로 어떻게 정의하는지 설명합니다. 디자인 패턴을 그냥 받아들이던 저에게 패턴에 대해 생각해 볼 수 있는 질문을 던질 수 있었습니다. 그리고 2장과 3장에서는 좋은 패턴은 어떤 특성을 가지는지 설명합니다. 수없이 탄생하는 패턴들로부터 어떤 패턴이 살아남아 우리가 공부하고 있는지, 그리고 왜 그 패턴이 살아남았는지에 대해 생각해 볼 수 있었습니다. 4장에서는 우리가 피해야 할 안티 패턴을 제공해 좋은 패턴과 비교해볼 수 있었습니다.&lt;/p&gt;
&lt;h2 id=&quot;최신-문법과-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B5%9C%EC%8B%A0-%EB%AC%B8%EB%B2%95%EA%B3%BC-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;최신 문법과 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;최신 문법과 패턴&lt;/h2&gt;
&lt;p&gt;5장에서는 최신 자바스크립트 모듈과 클래스 문법을 배웁니다. 그리고 이를 바탕으로 11장까지 디자인 패턴을 배우고 적용해보는 실습을 진행합니다.&lt;/p&gt;
&lt;h2 id=&quot;리액트-디자인-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;리액트 디자인 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리액트 디자인 패턴&lt;/h2&gt;
&lt;p&gt;12장부터는 리액트 디자인 패턴을 배웁니다. 고차 컴포넌트 패턴으로 시작해서 Hooks 패턴으로 진행하면서 기존 패턴의 문제점은 이후에 나오는 패턴이 어떻게 해결하는지를 배울 수 있었습니다. 또한, 로더블 컴포넌트, PRPL 패턴 등 리액트 애플리케이션의 성능도 챙길 수 있는 방법들을 배웠습니다.&lt;/p&gt;
&lt;h2 id=&quot;성능-최적화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94&quot; aria-label=&quot;성능 최적화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;성능 최적화&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/zuRLVpl.jpeg&quot; alt=&quot;&quot;&gt;
실용적인 팁들이 많이 나와서 좋았습니다. 예를 들어, preload를 사용하는 것까진 알고 있었는데 FCP 또는 LCP에 필요한 리소스의 로딩이 지연되는 것과 트레이드 오프라는 것을 생각해야 한다는 것을 배웠습니다.&lt;/p&gt;
&lt;h2 id=&quot;구성상-좋았던-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%EC%84%B1%EC%83%81-%EC%A2%8B%EC%95%98%EB%8D%98-%EC%A0%90&quot; aria-label=&quot;구성상 좋았던 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;구성상 좋았던 점&lt;/h2&gt;
&lt;p&gt;내용을 정리할 때 표를 함께 첨부해서 배웠던 개념들을 한눈에 비교할 수 있는 게 좋았습니다.
&lt;img src=&quot;https://i.imgur.com/h9RKhr7.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;한 개념에 대해 내용이 길지가 않아 짧게 나눠서 부담없이 나눠서 공략하기가 쉬웠습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[혼자 해도 프로처럼 잘 만드는 굿즈 제작 비법 리뷰]]></title><description><![CDATA[굿즈를 제작하려고 할 때 드는 막막함들이 있습니다. 스마트폰으로 업로드한 이미지를 PC…]]></description><link>https://donghoon-song.github.io/books/혼자-해도-프로처럼-잘-만드는-굿즈-제작-비법-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/혼자-해도-프로처럼-잘-만드는-굿즈-제작-비법-리뷰/</guid><pubDate>Sun, 28 Jul 2024 15:08:27 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B8109032364_l.jpg&quot; alt=&quot;책 표지&quot;&gt;
  출처: 한빛
&lt;/div&gt;
&lt;p&gt;굿즈를 제작하려고 할 때 드는 막막함들이 있습니다. 스마트폰으로 업로드한 이미지를 PC로 봤을 때 색상이 왜 달라 보이는지 그 이유도 모르겠고, 마음먹고 제작하려는데 굿즈를 제작할 수 있다는 사이트들(인쇄소들)에 들어가보니 모르는 용어들의 나열이라 포기한 적이 있습니다.&lt;/p&gt;
&lt;p&gt;굿즈제작비법 책에서는 굿즈를 만들려고 마음을 먹어봤지만 어려워서 힘들어하고 있는 사람들에게 필요한 내용들이 들어있는데요. 특히, 이런 책들은 단순한 정보의 나열인 경우가 많은데 이 책은 굿즈를 처음 제작하는 사람들에게 필요한 정보를 순서대로 제공하는 점이 좋았어요. 의식의 흐름을 읽고 있는 것처럼 “이건 뭐지?”라는 의문이 드는 순간 정보가 나와서 놀랐습니다.&lt;/p&gt;
&lt;p&gt;책의 초반부에서는 굿즈 제작에 필요한 순서를 상세히 설명하고, 만들고 싶은 굿즈별 추천 제작 업체 리스트도 포함되어 있어요! 많은 업체들 중 빨간고래님의 경험으로 선정한 업체들이라 믿음도 갑니다. 또 반드시 일러스트와 포토샵을 사용해서 제작하라고 나와있는데, 프로크리에이트만을 사용하지 않는 이유에 대한 설명도 잘나와있어요.&lt;/p&gt;
&lt;p&gt;특히나 중간중간 적혀있는 실무 꿀팁에 도움되는 내용들이 많았습니다! 예를 들어, 종이에 작품을 인쇄하는 경우 포토샵을 사용하는 것이 좋고, 패브릭이나 화지에 인쇄하는 경우에는 프로크리에이트도 품질 차이가 나지 않기에 사용해도 좋다는 실무적인 팁들이 있습니다. 책의 중반부에는 각 굿즈별 포토샵과 일러스트를 활용해 만드는 상세 과정, 프로그램 기능 설명들에 대한 내용이 나와있습니다. 책에 담기 어려운 내용들 (실제 인쇄소에서 만들어져 나온 굿즈 검수하는 과정들)은 QR로 바로 동영상 시청이 가능한 점도 좋았습니다.&lt;/p&gt;
&lt;p&gt;후반부에는 일러스트페어에 대한 내용도 있어요! 일러스트페어가 유명하지만 그들만의 세계같고 어려운데 정말 자세히 나와있어요. 어디서 신청을 받고, 얼마나 걸리고, 어떤걸 준비해야하는지에 대한 내용이 전부 나와있습니다. 심지어 빨간고래님이 일러스트 페어에서 평균 어느정도 벌었는지에 대한 현실적인 정보도 제공해주십니다.&lt;/p&gt;
&lt;p&gt;마지막엔 인쇄에 대한 자세한 정보들이 나열되어있는데 종이에 대한 궁금증을 해결해주는 다양한 지류 설명도 포함되어 있습니다. 저는 종이에 관심이 많아 이 부분을 관심있게 보았는데, 띤또레또와 같은 고급 종이에 대한 설명이나 리소그래프 인쇄 등 다양한 인쇄 방법도 다루고 있습니다. 몰랐던 인쇄 용어들도 많았습는데요. ‘오시’는 인쇄물을 접어야 하는 경우 누름자국을 넣어주는 것, ‘미싱’은 티켓처럼 점선으로 쉽게 뜯을 수 있게 해주는 것, ‘형압’은 올록볼록한 느낌을 주는 인쇄 기법 등 다양한 인쇄 용어에 대해 상세히 설명하고 있습니다.&lt;/p&gt;
&lt;p&gt;이미 경험이 있는 사람이 읽어도 좋지만, 처음 굿즈 제작을 시도하는 사람에게 너무 추천하는 책이에요! 독자를 고려한 책의 흐름과 현실적인 팁들이 중간중간에 포함되어 있어 당장 굿즈를 만들고 싶을 때 바로 실행이 가능할만큼 많은 도움이 됩니다. 굿즈 제작에 관심이 있다면 꼭 한 번 읽어보길 추천합니다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[컨텐츠에 따라 높이가 자동으로 조절되는 textarea 구현하기]]></title><description><![CDATA[높이가 컨텐츠에 따라 조절되는 textarea는 다음과 같이 구현합니다. 원리는 다음과 같습니다. 사용자가 값을 입력할 때마다 height를 ‘auto’로 설정하여 scrollHeight가 컨텐츠 높이만큼 만듭니다. 그 scrollHeight…]]></description><link>https://donghoon-song.github.io/javascript/컨텐츠에-따라-높이가-자동으로-조절되는-textarea-구현하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/javascript/컨텐츠에-따라-높이가-자동으로-조절되는-textarea-구현하기/</guid><pubDate>Sat, 13 Jul 2024 16:08:37 GMT</pubDate><content:encoded>&lt;p&gt;높이가 컨텐츠에 따라 조절되는 textarea는 다음과 같이 구현합니다. 원리는 다음과 같습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;사용자가 값을 입력할 때마다 height를 ‘auto’로 설정하여 scrollHeight가 컨텐츠 높이만큼 만듭니다.&lt;/li&gt;
&lt;li&gt;그 scrollHeight값을 height에 반영합니다.&lt;/li&gt;
&lt;li&gt;높이가 늘어나더라도 스크롤바가 생기지 않도록 overflow를 hidden으로 설정합니다.&lt;/li&gt;
&lt;li&gt;사용자가 수동으로 크기를 조절하지 못하게 하기 위해 resize를 none으로 설정합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;UTF-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;width=device-width, initial-scale=1.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Auto-resizing Textarea&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
      &lt;span class=&quot;token selector&quot;&gt;textarea&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;box-sizing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; border-box&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* 스크롤바 숨김 */&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* 사용자가 수동으로 크기 조절하지 못하게 함 */&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;textarea&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;autoResizeTextarea&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;oninput&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;autoResize(this)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;textarea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;autoResize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;textarea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        textarea&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;auto&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 높이를 자동으로 초기화&lt;/span&gt;
        textarea&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; textarea&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scrollHeight &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;px&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 스크롤 높이에 맞게 높이 설정&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[ChatGPT랑 비슷한 File Input 컴포넌트 구현하고 react-hook-form에 연동하기(파일 누적 관리하기)]]></title><description><![CDATA[오늘은 ChatGPT에서 사용하는 파일 인풋을 유사하게 구현했습니다. ChatGPT…]]></description><link>https://donghoon-song.github.io/react.js/chatgpt랑-비슷한-file-input-컴포넌트-구현하고-react-hook-form에-연동하기(파일-누적-관리하기)/</link><guid isPermaLink="false">https://donghoon-song.github.io/react.js/chatgpt랑-비슷한-file-input-컴포넌트-구현하고-react-hook-form에-연동하기(파일-누적-관리하기)/</guid><pubDate>Thu, 11 Jul 2024 21:08:00 GMT</pubDate><content:encoded>&lt;p&gt;오늘은 ChatGPT에서 사용하는 파일 인풋을 유사하게 구현했습니다. ChatGPT에서는 파일을 입력할때마다 업로드를 하기 때문에 실제 처리 방식은 다르지만 파일들을 모아서 한번에 업로드 해야 한다고 가정했습니다. 즉, 여러 파일을 선택하고 폼에 누적해서 관리하는 기능을 구현했습니다. 아래에 ChatGPT의 인풋 컴포넌트를 가져왔습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/dAK5M7x.png&quot; alt=&quot;ChatGPT 인풋 컴포넌트&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;구현사항&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%ED%98%84%EC%82%AC%ED%95%AD&quot; aria-label=&quot;구현사항 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;구현사항&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;파일을 입력하면 미리보기로 보여줬습니다.&lt;/li&gt;
&lt;li&gt;기존 file input과 다르게 파일을 여러번에 걸쳐 추가로 입력해도 누적이 되도록 했습니다.&lt;/li&gt;
&lt;li&gt;react-hook-form을 연동하여 form을 관리했습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useForm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Controller &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-hook-form&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;FileInputForm&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; handleSubmit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; control&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getValues &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useForm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;filesArray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setFilesArray&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;onSubmit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Submitted files:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;files&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleFileChange&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; selectedFiles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;selectedFiles&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Array.from에 넣는 이유는 selectedFiles가 array가 아닌 FileList이기 때문입니다.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; selectedFilesArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;selectedFiles&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// 보여주는 파일 리스트 정보 처리&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newFileInfoList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; selectedFilesArray&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; KB&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;setFileInfoList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;prevFileInfoList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;prevFileInfoList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;newFileInfoList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// files form value 처리&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 기존 파일 목록과 새로 선택한 파일 목록을 합칩니다.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 이렇게 처리하지 않으면 새로 선택한 파일이 기존 파일을 대체합니다.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentFiles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;files&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; updatedFiles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;currentFiles&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;selectedFilesArray&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// array에 담긴 정보를 가지고 FileList를 만듭니다.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataTransfer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      updatedFiles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; fileList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;files&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fileList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onSubmit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Controller&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;defaultValue&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleFileChange&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;multiple&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;filesArray&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Upload&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; FileInputForm&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ChatGPT를 사용할 때는 저런걸 어떻게 보여주지 생각했었는데 실제로 구현해보니까 신기했습니다. 보통 이렇게 누적식으로 관리해본 적은 처음이었고, n번째 파일을 제거할 때 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer&quot;&gt;DataTransfer api&lt;/a&gt;를 사용해서 FileList를 다시 만드는 게 인상적이었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[실전 예제로 알아보는 react hook form 사용법]]></title><description><![CDATA[안녕하세요. 요즘 실무에서 form을 다룰 때 react-hook-form library를 사용하고 있습니다. form의 input을 상태로 관리하면 상태가 바뀔 때마다 리렌더링이 발생해 불필요한 리렌더링이 많아집니다. react-hook-form…]]></description><link>https://donghoon-song.github.io/react.js/실전-예제로-알아보는-react-hook-form-사용법/</link><guid isPermaLink="false">https://donghoon-song.github.io/react.js/실전-예제로-알아보는-react-hook-form-사용법/</guid><pubDate>Wed, 19 Jun 2024 23:07:20 GMT</pubDate><content:encoded>&lt;p&gt;안녕하세요. 요즘 실무에서 form을 다룰 때 &lt;a href=&quot;https://react-hook-form.com/&quot;&gt;react-hook-form&lt;/a&gt; library를 사용하고 있습니다.&lt;/p&gt;
&lt;p&gt;form의 input을 상태로 관리하면 상태가 바뀔 때마다 리렌더링이 발생해 불필요한 리렌더링이 많아집니다. react-hook-form을 사용하면 각 form을 독립적으로 관리할 수 있어서 다른 form의 리렌더링을 방지할 수 있습니다. 또한 성능 최적화도 잘 되어 있고 쉽게 사용가능한 유용한 api들도 제공해줘서 form 관리가 편해졌습니다.&lt;/p&gt;
&lt;p&gt;실무에서 다양한 요구사항을 구현하면서 많이 검색해봤지만, 검색해도 안 나오는 부분들이 많아서 api의 type을 보면서 스스로 터득한 것들을 sandbox와 함께 공유하려고 합니다. 코드의 각 줄에 주석을 달아 설명을 추가했습니다. 코드 아래에 sandbox 링크를 첨부할테니 활용해보시면 좋을 것 같습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useEffect&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; useState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; ReactDOM &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-dom&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; useForm &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-hook-form&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./styles.css&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;formatPhoneInput&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    value
      &lt;span class=&quot;token comment&quot;&gt;// 숫자를 제외한 입력값 제거&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;[^0-9]&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 휴대폰 번호 형식으로 하이픈 추가&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;(^02|^0505|^1[0-9]{3}|^0[0-9]{2})([0-9]+)?([0-9]{4})&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;$1-$2-$3&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 하이픈이 여러개면 제거&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;--&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;includePhone&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIncludePhone&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    register&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    handleSubmit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    watch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    formState&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; errors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    control&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useForm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    mode&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;onChange&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// form value 초기값을 설정할 수 있습니다.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 해당 객체의 key값은 항목의 &apos;name&apos;입니다.&lt;/span&gt;
    defaultValues&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      exampleRequired&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      exampleRequiredWithMessage&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      mobile&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abc@abc.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// errors는 각 항목 name들을 key로 가지는 map입니다.&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 예를 들어 type은 다음과 같으며 등록된 항목에 따라 바뀝니다.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// DeepMap&amp;lt;{example: string; exampleRequired: string; exampleRequiredWithMessage: string;}, FieldError&gt;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// error가 없을 땐 빈 map입니다.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// {}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// error가 발생하면 해당 항목에 에러 정보가 담깁니다. error가 없으면 해당 항목 error 정보는 없습니다.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// message는 사용자가 지정한 메시지이고, type에는 어떤 validation rule인지가 담깁니다.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// {&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   phone: {&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//     message: &apos;올바른 휴대폰 번호를 입력해주세요.&quot;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//     ref: HTMLInputElement,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//     type: &apos;pattern&apos;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   },&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   exampleRequiredWithMessage: {&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//     message: &apos;example required&apos;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//     ref: HTMLInputElement,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//     type: &apos;required&apos;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   }&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// }&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 유저가 입력할 때 하이푼이 자동으로 들어가도록 설정하고 싶음.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 커스텀하기 위해 controller를 사용합니다.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; mobileField &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;mobile&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    control&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    rules&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;휴대폰 번호를 입력해주세요.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      pattern&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^01(0|1|[6-9])-(?:\d{3}|\d{4})-\d{4}$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;올바른 휴대폰 번호를 입력해주세요.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      maxLength&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;errors : &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; errors&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;errors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// watch에 항목의 &apos;name&apos;을 넘겨서 값이 바뀔 때마다 체크할 수 있습니다.&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;example&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// form 제출을 할 때 유효성 검사에 성공하면 handleSubmit callback의 parameter로 form data가 넘어옵니다.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 유효성 검사에 실패하면 실패한 input에 focus가 됩니다.&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Example&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* 항목을 등록할 때 register 함수를 사용합니다.
      &apos;example&apos; 항목을 등록합니다. */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;example&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;ExampleRequired&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &amp;lt;input
        /* register의 두번째 인자로 ValidationRule option을 넘길 수 있습니다.
        require rule과 maxLength rule을 추가합니다. */
        &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;exampleRequired&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maxLength&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      /&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* validation을 통과하지 못하면 errors 객체에 정보가 넘어옵니다.
      message를 등록할 때 지정하지 않고 이렇게 임의로 보여줄 수 있습니다. */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exampleRequired &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;This field is required&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;ExampleRequiredWithMessage&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// required rule validation을 통과하지 못했을 때 메시지를 에러 정보에 담고 싶다면 메시지를 바로 넘기면 됩니다.&lt;/span&gt;
        &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;exampleRequiredWithMessage&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;example required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// validation rule에 조건을 주고 싶을 때가 있습니다. 그러면 ValidationRule의 형태로 넘기면 됩니다.&lt;/span&gt;
        &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;exampleRequiredWithMessage&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 원하는 조건식&lt;/span&gt;
            message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;example required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* errors에 담긴 message를 사용합니다. */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exampleRequiredWithMessage &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exampleRequiredWithMessage&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;ExampleRequiredWithMessage&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// validation을 통과하지 못했을 때 메시지를 보여주고 싶다면 required rule에 string을 넘기면 됩니다.&lt;/span&gt;
        &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;exampleRequiredWithMessage&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;example required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exampleRequiredWithMessage &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exampleRequiredWithMessage&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;
        &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;이메일을 입력해 주세요.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          pattern&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\S+@\S+\.\S+&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;올바른 이메일 주소를 입력해주세요&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;htmlFor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;includePhone&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Include Phone&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;includePhone&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; checked &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setIncludePhone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checked&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;auto&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;includePhone &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Mobile&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// 하이픈이 들어간 휴대폰 번호를 받고 싶다면&lt;/span&gt;
            &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;mobileField&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formattedValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;formatPhoneInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              mobileField&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formattedValue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mobile &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mobile&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rootElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;root&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
ReactDOM&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;App&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rootElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://codesandbox.io/p/sandbox/react-hook-form-get-started-ts-forked-3x52vc?file=%2Fsrc%2Findex.tsx%3A85%2C32&quot;&gt;sandbox link&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Javascript Nullish Coalescing Operator (??) 자바스크립트 연산자]]></title><description><![CDATA[개발을 하다보면 변수가  또는 일 때 기본값을 설정하는 경우가 많습니다. 이를 효과적으로 처리하기 위해 ECMAScript 2020(ES11)에서는 가 도입되었습니다. 이 글에서는 의 개념, 사용법, 그리고 활용 예시를 살펴보겠습니다. Nullish…]]></description><link>https://donghoon-song.github.io/javascript/javascript-nullish-coalescing-operator-자바스크립트-연산자/</link><guid isPermaLink="false">https://donghoon-song.github.io/javascript/javascript-nullish-coalescing-operator-자바스크립트-연산자/</guid><pubDate>Wed, 12 Jun 2024 22:06:45 GMT</pubDate><content:encoded>&lt;p&gt;개발을 하다보면 변수가 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;일 때 기본값을 설정하는 경우가 많습니다. 이를 효과적으로 처리하기 위해 ECMAScript 2020(ES11)에서는 &lt;code class=&quot;language-text&quot;&gt;Nullish Coalescing Operator (??)&lt;/code&gt;가 도입되었습니다. 이 글에서는 &lt;code class=&quot;language-text&quot;&gt;Nullish Coalescing Operator&lt;/code&gt;의 개념, 사용법, 그리고 활용 예시를 살펴보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;nullish-coalescing-operator란&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nullish-coalescing-operator%EB%9E%80&quot; aria-label=&quot;nullish coalescing operator란 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nullish Coalescing Operator란?&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Nullish Coalescing Operator (??)&lt;/code&gt;는 JavaScript에서 변수가 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;인 경우에만 오른쪽 피연산자를 할당합니다. 아래 예시를 보면 변수가 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;&apos;&apos;&lt;/code&gt; 같은 값일 땐 오른쪽 피연산자를 할당하지 않는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;default value&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo2 &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;default value&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo3 &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: 0&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo4 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar4 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo4 &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar4&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;-연산자와의-차이점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%97%B0%EC%82%B0%EC%9E%90%EC%99%80%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90&quot; aria-label=&quot; 연산자와의 차이점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;|| 연산자와의 차이점&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;||&lt;/code&gt; 연산자와 비슷해 보이지만 다릅니다. &lt;code class=&quot;language-text&quot;&gt;||&lt;/code&gt;연산자는 &lt;code class=&quot;language-text&quot;&gt;falsy&lt;/code&gt; 값인 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;&apos;&apos;&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;NaN&lt;/code&gt; 등을 &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;로 처리합니다. 따라서 &lt;code class=&quot;language-text&quot;&gt;||&lt;/code&gt; 연산자는 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;&apos;&apos;&lt;/code&gt; 같은 값이 들어왔을 때도 오른쪽 피연산자를 할당합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;default value&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo2 &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;default value&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo3 &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;default value&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo4 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar4 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; foo4 &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;default value&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bar4&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;default value&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://ko.javascript.info/nullish-coalescing-operator&quot;&gt;https://ko.javascript.info/nullish-coalescing-operator&lt;/a&gt; 문서에서 좋은 표현을 찾았는데요. &lt;code class=&quot;language-text&quot;&gt;||&lt;/code&gt; 연산자는 첫 번째 &lt;code class=&quot;language-text&quot;&gt;truthy&lt;/code&gt; 값을 반환하는 반면, &lt;code class=&quot;language-text&quot;&gt;??&lt;/code&gt; 연산자는 첫 번째 &lt;code class=&quot;language-text&quot;&gt;defined&lt;/code&gt; 값을 반환한다고 생각하면 이해하기 쉽습니다.&lt;/p&gt;
&lt;h2 id=&quot;활용-예시&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%99%9C%EC%9A%A9-%EC%98%88%EC%8B%9C&quot; aria-label=&quot;활용 예시 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;활용 예시&lt;/h2&gt;
&lt;h3 id=&quot;로컬-저장소-값-처리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A1%9C%EC%BB%AC-%EC%A0%80%EC%9E%A5%EC%86%8C-%EA%B0%92-%EC%B2%98%EB%A6%AC&quot; aria-label=&quot;로컬 저장소 값 처리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;로컬 저장소 값 처리&lt;/h3&gt;
&lt;p&gt;로컬 저장소에서 값이 없을 때 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;이기 때문에 기본값을 쉽게 처리할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; storedValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; storedValue &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Default Value&apos;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: &apos;Default Value&apos; (로컬 저장소에 값이 없을 때)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;환경-설정-값-처리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95-%EA%B0%92-%EC%B2%98%EB%A6%AC&quot; aria-label=&quot;환경 설정 값 처리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;환경 설정 값 처리&lt;/h3&gt;
&lt;p&gt;환경 설정에서 설정되지 않은 값이 있을 때 기본값으로 처리하기 쉽습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;apiEndpoint&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;API_ENDPOINT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://default.api.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TIMEOUT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;apiEndpoint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 환경 변수에 따라 다름, 기본 값은 &apos;https://default.api.com&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 환경 변수에 따라 다름, 기본 값은 5000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;0이-할당될-수-있는-변수-처리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#0%EC%9D%B4-%ED%95%A0%EB%8B%B9%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%B3%80%EC%88%98-%EC%B2%98%EB%A6%AC&quot; aria-label=&quot;0이 할당될 수 있는 변수 처리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;0이 할당될 수 있는 변수 처리&lt;/h3&gt;
&lt;p&gt;예를 들어, 사용자의 만족도 조사 점수로 0부터 5까지의 값을 받는데, 사용자가 응답하지 않았을 때 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;이 할당될 수 있습니다. 이때 &lt;code class=&quot;language-text&quot;&gt;??&lt;/code&gt; 연산자를 사용하면 기본값을 설정할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;displayScore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; finalScore &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; score &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;조사에 참여하지 않았습니다.&apos;&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;만족도 점수: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;finalScore&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;displayScore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: 만족도 점수: 5&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;displayScore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: 만족도 점수: 0&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;displayScore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: 만족도 점수: 조사에 참여하지 않았습니다.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;displayScore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 출력: 만족도 점수: 조사에 참여하지 않았습니다.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;참고-글&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0-%EA%B8%80&quot; aria-label=&quot;참고 글 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고 글&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://ko.javascript.info/nullish-coalescing-operator&quot;&gt;https://ko.javascript.info/nullish-coalescing-operator&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Tidy First 리뷰]]></title><description><![CDATA[켄트 벡의 “Tidy First?”는 코드 정리를 언제, 왜, 어떻게 해야 하는지에 대한 가이드라인을 제시합니다. 굉장히 얇아서 내용을 컴팩트하게 다루고 그만큼 빠르게 적용해 볼 수 있는 장점이 있습니다. Part…]]></description><link>https://donghoon-song.github.io/books/tidy-first-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/tidy-first-리뷰/</guid><pubDate>Sun, 26 May 2024 23:05:53 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B1474193984_l.jpg&quot; alt=&quot;Tidy First?&quot;&gt;
&lt;/div&gt;
&lt;p&gt;켄트 벡의 “Tidy First?”는 코드 정리를 언제, 왜, 어떻게 해야 하는지에 대한 가이드라인을 제시합니다. 굉장히 얇아서 내용을 컴팩트하게 다루고 그만큼 빠르게 적용해 볼 수 있는 장점이 있습니다.&lt;/p&gt;
&lt;p&gt;Part1에서는 코드 정리법을 다룹니다. 여러가지 방법을 제시하지만 저자가 강조하는 것은 “코드를 읽고 이해하는 데 드는 비용”이 높다는 것입니다. 그래서 코드를 읽기 쉽게 만들어야 한다는 것이 중요하다고 합니다.&lt;/p&gt;
&lt;p&gt;Part2에서는 코드 정리를 언제 해야 하는지에 대해 다룹니다. 정리할 부분이 보인다고 무작정 하는 것이 아니라 코드 정리하는데 들어가는 비용까지 고려해서 합니다. 예를 들어, 다시는 코드를 변경할 일이 없는 컴포넌트의 경우에는 정리를 하지 않습니다. 코드 정리를 했을 때, 이해가 쉬워지거나 동작 변경이 쉬워지는 즉각적인 효과를 얻을 수 있으면 정리를 하는 것이 좋다고 합니다.&lt;/p&gt;
&lt;p&gt;Part3에서는 코드 정리를 왜 해야 하는지에 대해 다룹니다. 개발에 들어가는 비용을 돈에 빗대어 설명하면서, 스스로 코드 정리를 해야 하는 이유에 대해서 찾을 수 있도록 합니다.&lt;/p&gt;
&lt;p&gt;저자는 이 책이 코드 정리에 대해서 다룬다고 해서 코드 정리를 무조건 해야 한다고 말하지 않습니다. 대신에 스스로 생각할 수 있는 능력을 길러줍니다. 이제까지는 코드 정리를 뭐라도 하면 좋지 라고 생각했지만 이 책을 읽고 나서 돌이켜보면 굳이 안 해도 됐을 경우도 있었고 더 신경써서 해야 했을 경우도 있었던 것 같습니다. 앞으로 개발을 하면서 이 책의 내용을 체화한다면 변화에 유연하면서도 읽기 쉬운 코드를 작성해 장기적으로 많은 비용을 줄일 수 있을 것이라고 기대하고 있습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[NavigationDuplicated Avoided navigation to current location - vue router 에러]]></title><description><![CDATA[이슈 NavigationDuplicated: Avoided navigation to current location: “abc” Tabs 컴포넌트로 페이지 이동을 하는데 이런 에러를 만났습니다. 탭을 빠르게 왔다갔다 하면 생겼는데요. vue router…]]></description><link>https://donghoon-song.github.io/vue.js/navigationduplicated-avoided-navigation-to-current-location---vue-router-에러/</link><guid isPermaLink="false">https://donghoon-song.github.io/vue.js/navigationduplicated-avoided-navigation-to-current-location---vue-router-에러/</guid><pubDate>Thu, 23 May 2024 21:06:09 GMT</pubDate><content:encoded>&lt;h2 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;NavigationDuplicated: Avoided navigation to current location: “abc”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Tabs 컴포넌트로 페이지 이동을 하는데 이런 에러를 만났습니다. 탭을 빠르게 왔다갔다 하면 생겼는데요. vue router에서 현재 페이지와 같은 path로 &lt;code class=&quot;language-text&quot;&gt;this.$router.push(path)&lt;/code&gt;를 하면 발생합니다. 현재 페이지에서 같은 경로의 페이지로 이동할 수 없기 때문입니다.&lt;/p&gt;
&lt;h2 id=&quot;해결방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;해결방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결방법&lt;/h2&gt;
&lt;p&gt;해결방법은 여러가지가 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;1-에러-메시지를-무시하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%97%90%EB%9F%AC-%EB%A9%94%EC%8B%9C%EC%A7%80%EB%A5%BC-%EB%AC%B4%EC%8B%9C%ED%95%98%EA%B8%B0&quot; aria-label=&quot;1 에러 메시지를 무시하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 에러 메시지를 무시하기&lt;/h3&gt;
&lt;p&gt;catch문으로 에러를 잡아버리는 방법입니다. 근본적인 해결책이라고는 볼 수 없습니다. 다른 에러도 같이 무시되기 때문입니다. 단순히 에러메시지를 보기 싫다면 적용할 수 있는 방법입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-경로-비교하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EA%B2%BD%EB%A1%9C-%EB%B9%84%EA%B5%90%ED%95%98%EA%B8%B0&quot; aria-label=&quot;2 경로 비교하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. 경로 비교하기&lt;/h3&gt;
&lt;p&gt;$router.push하기 전에 경로를 비교합니다. 근본적인 원인을 없앨 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; targetPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;currentPath &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; targetPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;targetPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-thisrouterreplace-사용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-thisrouterreplace-%EC%82%AC%EC%9A%A9&quot; aria-label=&quot;3 thisrouterreplace 사용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. this.$router.replace 사용&lt;/h3&gt;
&lt;p&gt;push 방식과 동작 방식이 다르긴 하지만 옵션이 될 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;thisrouterpush&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#thisrouterpush&quot; aria-label=&quot;thisrouterpush permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;this.$router.push&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;히스토리에 새 항목이 추가됩니다.&lt;/li&gt;
&lt;li&gt;브라우저의 뒤로 가기 버튼을 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;일반적인 네비게이션 용도로 사용됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;thisrouterreplace&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#thisrouterreplace&quot; aria-label=&quot;thisrouterreplace permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;this.$router.replace&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;히스토리의 현재 항목이 새로운 경로로 대체됩니다.&lt;/li&gt;
&lt;li&gt;브라우저의 뒤로가기 버튼을 사용할 수 없습니다.&lt;/li&gt;
&lt;li&gt;로그인 후 리디렉션, 오류 페이지로 리디렉션 등의 상황에서 사용됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;참고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0&quot; aria-label=&quot;참고 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://im-designloper.tistory.com/71&quot;&gt;https://im-designloper.tistory.com/71&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/57837758/navigationduplicated-navigating-to-current-location-search-is-not-allowed&quot;&gt;https://stackoverflow.com/questions/57837758/navigationduplicated-navigating-to-current-location-search-is-not-allowed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/vuejs/vue-router/issues/2872&quot;&gt;https://github.com/vuejs/vue-router/issues/2872&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[읽기 쉬운 코드 도서 리뷰]]></title><description><![CDATA[읽기 쉬운 코드 읽기 쉬운 코드(로버트 C…]]></description><link>https://donghoon-song.github.io/books/읽기-쉬운-코드-도서-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/읽기-쉬운-코드-도서-리뷰/</guid><pubDate>Mon, 13 May 2024 23:06:35 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://gimg.gilbut.co.kr/book/BN004042/rn_view_BN004042.jpg&quot; alt=&quot;읽기 쉬운 코드 책 사진&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;읽기-쉬운-코드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%BD%EA%B8%B0-%EC%89%AC%EC%9A%B4-%EC%BD%94%EB%93%9C&quot; aria-label=&quot;읽기 쉬운 코드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;읽기 쉬운 코드&lt;/h2&gt;
&lt;p&gt;읽기 쉬운 코드(로버트 C.마틴 / 길벗)는 “레스토랑 예약 시스템”을 통째로 구현하는 과정을 예시로 들어 시작부터 개선과정까지를 담았습니다. 그 과정에서 어떻게 하면 좋은 코드를 짤 수 있는지를 녹여냈습니다. 프론트엔드 개발자인 제가 이 책에서 인상깊었던 내용들을 몇 자 적어보려고 합니다.&lt;/p&gt;
&lt;h2 id=&quot;처음부터-순서대로&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B2%98%EC%9D%8C%EB%B6%80%ED%84%B0-%EC%88%9C%EC%84%9C%EB%8C%80%EB%A1%9C&quot; aria-label=&quot;처음부터 순서대로 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;처음부터 순서대로&lt;/h2&gt;
&lt;p&gt;저는 책을 읽을 때 관심이 가는 부분을 먼저 읽는 편입니다. 하지만 이 책은 시스템을 통째로 구현하는 순서로 구성되어 있기 때문에 이미 설명했던 부분이나 이전 챕터의 코드를 참고해야 할 때가 많습니다. 그래서 처음부터 순서대로 읽으면 더 이해하기 쉬울 것입니다.&lt;/p&gt;
&lt;h2 id=&quot;프로젝트라고-생각해서-발생하는-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%9D%BC%EA%B3%A0-%EC%83%9D%EA%B0%81%ED%95%B4%EC%84%9C-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;프로젝트라고 생각해서 발생하는 문제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;프로젝트라고 생각해서 발생하는 문제&lt;/h2&gt;
&lt;p&gt;이 책은 소프트웨어 개발을 프로젝트라고 생각하는 것이 좋지 않다고 서술합니다. 프로젝트는 시작과 끝이 있어 마지막에 도달하면 작업이 끝납니다. 하지만 &lt;code class=&quot;language-text&quot;&gt;성공한 소프트웨어는 지속되고 계속 유지보수해야&lt;/code&gt; 합니다. 그래서 오히려 정원 가꾸기에 비유합니다. 소프트웨어를 살아 있는 유기체로 보고 계속 살아가게 하기 위해서 리팩토링을 하거나 죽은 코드를 삭제하는 것에 비유할 수 있기 때문입니다.&lt;/p&gt;
&lt;h2 id=&quot;주기적으로-의존성-갱신하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A3%BC%EA%B8%B0%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%9D%98%EC%A1%B4%EC%84%B1-%EA%B0%B1%EC%8B%A0%ED%95%98%EA%B8%B0&quot; aria-label=&quot;주기적으로 의존성 갱신하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;주기적으로 의존성 갱신하기&lt;/h2&gt;
&lt;p&gt;의존성을 갱신하는 작업은 상당히 번거롭습니다. 이 책에서는 &lt;code class=&quot;language-text&quot;&gt;의존성 업데이트를 위한 일정을 따로 잡으라&lt;/code&gt;고 합니다. 그렇지 않으면 다른 업무에 우선순위가 밀려 하기 힘들 것이기 때문입니다. 이 내용에 많이 공감이 갔습니다. 의존성을 관리하지 않으면 나중에 업데이트하기가 무섭기도 하고, 업데이트 했을 때 엮여 있는 의존성들 때문에 쉽지가 않았기 때문입니다. 더군다나 프론트엔드 생태계는 라이브러리 업데이트 주기가 빠르기 때문에 더더욱 신경써야겠다는 생각을 했습니다. 회사에서 업데이트 일정을 따로 잡고 실천해보려고 합니다.&lt;/p&gt;
&lt;h2 id=&quot;문제-해결법---이분법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B2%95---%EC%9D%B4%EB%B6%84%EB%B2%95&quot; aria-label=&quot;문제 해결법   이분법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제 해결법 - 이분법&lt;/h2&gt;
&lt;p&gt;코드에 문제가 생겼을 때 이분법을 활용할 수 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;문제를 감지하거나 재현할 방법을 찾습니다.&lt;/li&gt;
&lt;li&gt;코드의 절반을 제거합니다.&lt;/li&gt;
&lt;li&gt;문제가 계속되면 2단계부터 반복합니다. 문제가 해결되면 제거한 코드를 복원하고 나머지 절반을 제거한 후 다시 2단계부터 반복합니다.&lt;/li&gt;
&lt;li&gt;문제가 재현되는 코드에서 어떤 일이 일어나는지 이해할 수 있을 정도로 충분히 코드가 작아질 때까지 반복합니다.
실제로 저도 사용하고 있던 방법인데 책에서 이렇게 이론으로 정리하니까 무척 반가웠습니다. 또한 &lt;code class=&quot;language-text&quot;&gt;git bisect&lt;/code&gt; 명령을 사용하면 보다 쉽게 결함이 있는 커밋을 찾을 수 있다는 것도 배웠습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;관심사의-분리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B4%80%EC%8B%AC%EC%82%AC%EC%9D%98-%EB%B6%84%EB%A6%AC&quot; aria-label=&quot;관심사의 분리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;관심사의 분리&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/zfefMci.jpeg&quot; alt=&quot;관심사의 분리 챕터 책 사진&quot;&gt;&lt;/p&gt;
&lt;p&gt;중요한 동작을 숨기는 형태로 작성하면, 코드를 이해하기 어려워진다고 합니다. 대신에 순수 함수의 반환값이 다른 순수 함수의 입력으로 들어가는 형태를 가지는 순차적 조합이 더 읽기 쉽다고 합니다. 이것도 업무에서 적용해볼만한 부분이었습니다. 또한, &lt;code class=&quot;language-text&quot;&gt;비결정적 쿼리와 부수 효과를 가진 동작들을 시스템의 바깥 부분에 가깝게 유지하고, 핵심이 되는 복잡한 논리는 순수 함수로 작성하라&lt;/code&gt;고 합니다. 그렇게 해서 개선한 코드를 봤을 때 뇌가 더 받아들이기 편하고 읽기 쉬웠습니다.&lt;/p&gt;
&lt;h2 id=&quot;정리하며&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC%ED%95%98%EB%A9%B0&quot; aria-label=&quot;정리하며 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리하며&lt;/h2&gt;
&lt;p&gt;책의 예상 독자가 ‘숙련도를 높이고 싶은 개발자’인만큼 한번 읽어서 소화하기에는 어려운 내용이었습니다. 하지만 여러번 읽어서 내용을 이해할 때 오는 쾌감은 더 컸습니다. 조금 느리지만 한 챕터씩 계속해서 정복해보겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[개발자 기술 면접 노트(한빛미디어) 도서 리뷰]]></title><description><![CDATA[개발자 기술 면접 노트 한빛미디어의 “개발자 기술 면접 노트”를 소개합니다. 1…]]></description><link>https://donghoon-song.github.io/books/개발자-기술-면접-노트(한빛미디어)-도서-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/개발자-기술-면접-노트(한빛미디어)-도서-리뷰/</guid><pubDate>Sun, 28 Apr 2024 18:05:35 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://i.imgur.com/lYFmqKs.png&quot; alt=&quot;개발자 기술 면접 노트 책 사진&quot;&gt;
&lt;/div&gt;
&lt;h2 id=&quot;개발자-기술-면접-노트&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%9C%EB%B0%9C%EC%9E%90-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%85%B8%ED%8A%B8&quot; aria-label=&quot;개발자 기술 면접 노트 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;개발자 기술 면접 노트&lt;/h2&gt;
&lt;p&gt;한빛미디어의 “개발자 기술 면접 노트”를 소개합니다. 18년 차 카카오 면접관을 맡고 계시는 저자가 취업 및 이직에 도움이 되는 가이드를 작성해주셨습니다. 내용은 크게 &lt;code class=&quot;language-text&quot;&gt;서류 준비&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;면접과 코딩 테스트&lt;/code&gt; 두 파트로 나뉩니다.&lt;/p&gt;
&lt;p&gt;책을 읽다가 특히나 좋았던 부분 몇가지 소개해 드리겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;면접관의-입장에서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A9%B4%EC%A0%91%EA%B4%80%EC%9D%98-%EC%9E%85%EC%9E%A5%EC%97%90%EC%84%9C&quot; aria-label=&quot;면접관의 입장에서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;면접관의 입장에서&lt;/h2&gt;
&lt;p&gt;이 책을 추천한다면 &lt;strong&gt;면접관의 입장에서&lt;/strong&gt; 서술한 부분이 많은 것이 그 이유입니다. 보통의 면접 관련 책들을 보면 지원자의 입장에서 서술한 경우가 많았습니다. 그런 내용들도 물론 도움이 되지만 저는 이 책이 면접관의 시선에서 쓰여 있어서 더 도움이 됐습니다.&lt;/p&gt;
&lt;h2 id=&quot;가장-적절한-이직-시즌&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%80%EC%9E%A5-%EC%A0%81%EC%A0%88%ED%95%9C-%EC%9D%B4%EC%A7%81-%EC%8B%9C%EC%A6%8C&quot; aria-label=&quot;가장 적절한 이직 시즌 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;가장 적절한 이직 시즌&lt;/h2&gt;
&lt;p&gt;이 책을 읽기 전에는 수시 채용은 수시 채용. 공채는 공채였습니다. 하지만 아래와 같은 관점을 제시해줘서 언제 어떻게 지원해야 합격률을 높일 수 있을지 생각해 볼 수 있었습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;대규모 공채 때에는 실력 있는 직원들을 많이 뽑았기 때문에 이후에는 채용 난이도가 올라갈 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;공채는 마감 날짜가 가까울수록 서류가 몰리기 때문에 몰리기 전에 미리 서류를 제출해야 채용 담당자가 서류를 읽을 시간이 충분하고 경합을 벌일 대상이 적다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;면접관의-의식의-흐름&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A9%B4%EC%A0%91%EA%B4%80%EC%9D%98-%EC%9D%98%EC%8B%9D%EC%9D%98-%ED%9D%90%EB%A6%84&quot; aria-label=&quot;면접관의 의식의 흐름 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;면접관의 의식의 흐름&lt;/h3&gt;
&lt;p&gt;이런식으로 면접관은 면접 보는 동안 어떤 의식의 흐름을 겪는지 적어주신 것도 면접관의 심리를 생각해보는데 많은 도움이 됐습니다. 면접관이 물어보는 질문의 난이도도 낮아지는지, 높아지는지도 지원자 입장에서 생각해 볼만한 점이라고 생각했습니다.
&lt;img src=&quot;https://i.imgur.com/8n6lIpj.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;스터디를-해야-하는-이유&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8A%A4%ED%84%B0%EB%94%94%EB%A5%BC-%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; aria-label=&quot;스터디를 해야 하는 이유 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;스터디를 해야 하는 이유&lt;/h2&gt;
&lt;p&gt;이런저런 스터디를 해봤는데 완주한 스터디도 있었고 흐지부지된 스터디도 있었습니다. 보통은 친구들과 하거나 회사 동료들과 했는데 모르는 사람들과 하는 스터디는 부담감이 많이 컸습니다. 그럼에도 저자는 스터디가 스펙을 올리기 가장 비효율적이고 번거로운 길이라고 소개합니다. 하지만 공부한 지식을 정리하는 방법과 끝까지 완주하는 방법을 배울 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;사람들-만나기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%82%AC%EB%9E%8C%EB%93%A4-%EB%A7%8C%EB%82%98%EA%B8%B0&quot; aria-label=&quot;사람들 만나기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;사람들 만나기&lt;/h2&gt;
&lt;p&gt;내부 추천의 기회도 많이 중요하다고 합니다. 아무래도 같이 일하는 사람을 뽑는 입장에서 이미 잘 알고 합을 맞춰 본 사람들이 눈에 더 들어오기 때문입니다. 그래서 대외활동, 스터디를 통해 사람들을 많이 만나라고 조언합니다. 이 부분은 제가 많이 약한데 어떻게 하면 좋을지 고민해보려고 합니다.&lt;/p&gt;
&lt;h2 id=&quot;대화-잘-하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8C%80%ED%99%94-%EC%9E%98-%ED%95%98%EA%B8%B0&quot; aria-label=&quot;대화 잘 하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;대화 잘 하기&lt;/h2&gt;
&lt;p&gt;결국에는 면접에서 ‘대화’를 잘 해야 한다고 합니다. 면접에 들어가보면 역량은 뛰어나신데 질문을 잘 이해하지 못하시거나 엉뚱한 대답을 하시는 등 의사소통에서 아쉬운 분들을 만난 적이 있습니다. 같이 일할 때 의사소통이 어려우면 많이 삐걱거리기 때문에 이 관점에서도 자신을 많이 돌아봐야겠다고 생각했습니다.&lt;/p&gt;
&lt;h2 id=&quot;회고와-성장&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%9A%8C%EA%B3%A0%EC%99%80-%EC%84%B1%EC%9E%A5&quot; aria-label=&quot;회고와 성장 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;회고와 성장&lt;/h2&gt;
&lt;p&gt;연차가 쌓이면서 어떤 모습의 개발자가 되어야 할까 많은 고민을 했었는데 제가 생각하고 있는 것과 같은 내용이 나와서 반가웠고 확신이 조금 들었습니다. 짧게 추상화해보면 결국에는 &lt;strong&gt;주변 사람들에게까지 영향력을 미치는 개발자&lt;/strong&gt;가 되어야겠고 그런 방향으로 나아가야겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마치며&lt;/h2&gt;
&lt;p&gt;신입, 경력 개발자 두 관점에서 내용들이 모두 서술되어 있어서 취업과 이직을 잘 하고 싶거나 성장하고 싶은 개발자분들은 누구나 읽기 좋은 책이지 않나 생각했습니다. 18년의 경력에서 우러나오는 경험을 다 정리해주신 것 같아 너무 좋았고 서평단을 통해 감사하게도 읽을 수 있어서 좋았습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.”&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Clerk를 사용해서 유저 정보 관리하기]]></title><description><![CDATA[Clerk Clerk…]]></description><link>https://donghoon-song.github.io/clerk/clerk를-사용해서-유저-정보-관리하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/clerk/clerk를-사용해서-유저-정보-관리하기/</guid><pubDate>Sun, 28 Apr 2024 16:04:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/qWiTyQQ.jpeg&quot; alt=&quot;Clerk&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://clerk.com/&quot;&gt;Clerk&lt;/a&gt;라고 하는 유저 관리 플랫폼이 있습니다. 몇달 전에 뉴스레터에서 봤을 때는 이게 뭐지 싶었는데 요즘 듣고 있는 사이드 프로젝트 강의에서 사용했는데 번거로운 부분들을 많이 줄여줘서 재밌었습니다. 굉장히 직관적이고 편해서 제가 사용했던 컴포넌트들을 예시와 함께 소개합니다.&lt;/p&gt;
&lt;h2 id=&quot;signinbutton&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#signinbutton&quot; aria-label=&quot;signinbutton permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SignInButton&lt;/h2&gt;
&lt;p&gt;sign in page로 이동시키거나 modal을 띄워줍니다. &lt;a href=&quot;https://clerk.com/docs/components/unstyled/sign-in-button&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;props&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#props&quot; aria-label=&quot;props permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;props&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fallbackRedirectUrl&lt;/code&gt; - user가 sign in한 후에 redirect되는 url&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;signUpFallbackRedirectUrl&lt;/code&gt; - user가 sign up한 후에 redirect되는 url&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;mode&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;redirect&lt;/code&gt; - sign in page로 redirect합니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;modal&lt;/code&gt; - modal을 띄웁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;signupbutton&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#signupbutton&quot; aria-label=&quot;signupbutton permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SignUpButton&lt;/h2&gt;
&lt;p&gt;sign up page로 이동시키거나 modal을 띄워줍니다. &lt;a href=&quot;https://clerk.com/docs/components/unstyled/sign-up-button&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;props-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#props-1&quot; aria-label=&quot;props 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;props&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fallbackRedirectUrl&lt;/code&gt; - user가 sign up한 후에 redirect되는 url&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;signInFallbackRedirectUrl&lt;/code&gt; - user가 sign in한 후에 redirect되는 url&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;mode&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;redirect&lt;/code&gt; - sign up page로 redirect합니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;modal&lt;/code&gt; - modal을 띄웁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;사용법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%82%AC%EC%9A%A9%EB%B2%95&quot; aria-label=&quot;사용법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;사용법&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SignInButton &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@clerk/nextjs&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Home&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignInButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;각 컴포넌트는 아래와 같이 기본적인 UI를 제공해주는데
&lt;img src=&quot;https://i.imgur.com/ireLM8C.png&quot; alt=&quot;버튼들 기본 UI&quot;&gt;&lt;/p&gt;
&lt;p&gt;커스텀이 필요하면 wrapper 형식으로 사용하면 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SignInButton &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@clerk/nextjs&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Home&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignInButton&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Sign in with Clerk&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignInButton&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;signedin&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#signedin&quot; aria-label=&quot;signedin permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SignedIn&lt;/h2&gt;
&lt;p&gt;유저 세션이 있을 때 렌더링되는 컴포넌트입니다.
&lt;a href=&quot;https://clerk.com/docs/components/control/signed-in&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;signedout&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#signedout&quot; aria-label=&quot;signedout permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SignedOut&lt;/h2&gt;
&lt;p&gt;유저 세션이 없을 때 렌더링되는 컴포넌트입니다.
&lt;a href=&quot;https://clerk.com/docs/components/control/signed-out&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;clerkloaded&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#clerkloaded&quot; aria-label=&quot;clerkloaded permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ClerkLoaded&lt;/h2&gt;
&lt;p&gt;Clerk object가 로드된 상태를 보장하는 컴포넌트입니다.
&lt;a href=&quot;https://clerk.com/docs/components/control/clerk-loaded&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;clerkloading&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#clerkloading&quot; aria-label=&quot;clerkloading permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ClerkLoading&lt;/h2&gt;
&lt;p&gt;Clerk object가 로딩중 일 때 렌더링되는 컴포넌트입니다.
&lt;a href=&quot;https://clerk.com/docs/components/control/clerk-loading&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;userbutton&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#userbutton&quot; aria-label=&quot;userbutton permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;UserButton&lt;/h2&gt;
&lt;p&gt;계정을 관리하거나 Sign out할 수 있는 버튼입니다. Clerk는 구글처럼 multi-session을 지원하기 때문에 계정간 전환도 가능합니다. &lt;a href=&quot;https://clerk.com/docs/components/user/user-button&quot;&gt;docs&lt;/a&gt;
&lt;img src=&quot;https://i.imgur.com/6BFbIMW.png&quot; alt=&quot;UserButton 예시&quot;&gt;&lt;/p&gt;
&lt;p&gt;이 컴포넌트들을 종합적으로 아래와 같이 사용할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 로딩 시에&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClerkLoading&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClerkLoading&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 로딩이 끝나면&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClerkLoaded&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
 // 유저 세션이 있다면
 &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignedIn&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;afterSignOutUrl&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignedIn&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
 //유저 세션이 없다면
 &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignedOut&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignInButton&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;token attr-name&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;modal&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;token attr-name&quot;&gt;fallbackRedirectUrl&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/learn&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;token attr-name&quot;&gt;signUpFallbackRedirectUrl&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/learn&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;variant&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ghost&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    Login
   &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignInButton&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SignedOut&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClerkLoaded&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;기존에는 예를 들어서, firebase를 쓴다고 하면 auth change를 watch해서 상태를 바꾸는 로직 등이 필요했는데 Clerk를 사용하면 그런 번거로운 작업들을 많이 줄일 수 있었습니다. 아직 초반부라 사용한 코드가 적었는데 나중에 user 정보를 어떻게 가져오고 어떻게 활용할 수 있을지 배울 수 있을 거 같아서 기대가 됩니다. 배우면 또 업데이트 해보겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[AI 프로필을 팔기 시작한 개발자 이야기]]></title><description><![CDATA[Carat carat 홈페이지
출처: carat.im 인스타그램을 보다가 우연히 발견했던 Carat…]]></description><link>https://donghoon-song.github.io/mystory/ai-프로필을-팔기-시작한-개발자-이야기/</link><guid isPermaLink="false">https://donghoon-song.github.io/mystory/ai-프로필을-팔기-시작한-개발자-이야기/</guid><pubDate>Fri, 19 Apr 2024 20:05:38 GMT</pubDate><content:encoded>&lt;h2 id=&quot;carat&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#carat&quot; aria-label=&quot;carat permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Carat&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/v6IyFeU.png&quot; alt=&quot;carat 홈페이지&quot;&gt;
출처: &lt;a href=&quot;https://carat.im/&quot;&gt;carat.im&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;인스타그램을 보다가 우연히 발견했던 &lt;a href=&quot;https://carat.im/&quot;&gt;Carat&lt;/a&gt;은 사진 필터앱이었습니다. 사람들이 색감이나 특수효과를 입혀 놓은 필터를 유저들이 구매할 수 있는 서비스였는데요. 취미로 인물사진을 찍던 저는 ‘나도 필터를 만들어볼까’하고 잠시 생각했었지만 색감에 자신이 없어 도전하지 않았었습니다. 그러다가 최근에 Carat 측에서 AI필터를 출시해보자고 연락이 왔습니다.
&lt;img src=&quot;https://i.imgur.com/MwwhMbI.png&quot; alt=&quot;carat 홈페이지&quot;&gt;
출처: &lt;a href=&quot;https://carat.im/&quot;&gt;carat.im&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;보니까 비슷한 인물사진들을 여러장 학습시켜서 AI 사진을 만들 수 있는 기능이었습니다. 저는 AI 프로필을 구매한 적도 없고 솔직히 사람들이 많이 쓸까 싶었습니다. 스노우에서 AI 프로필 기능을 출시했을 때 ‘이걸 진짜 프사로 쓸까?’ 생각했었는데 재미로 해보고 인스타 스토리나 게시물로 올리는 정도였던 거 같아서 더욱 그랬었습니다. Carat 앱을 둘러보니 필터의 공유수나 저장수를 봤을 때 사람들이 꽤나 쓰는 것 같았습니다. 그래서 한두개 정도 만들어보고 조금이라도 팔리면 더 만들어봐야겠다 생각했습니다.&lt;/p&gt;
&lt;p&gt;작업했던 모델분께 허락을 받고 두개 정도 만들었는데 이틀동안 3번 정도 구매가 일어났습니다. 재밌어서 무료필터를 한개 더 만들었는데 확실히 무료필터는 사용량이 많아서 금새 10회에 도달했습니다. 수수료를 떼면 커피값도 안 나왔지만 passive income을 만들 수 있는 가능성에 기분이 좋았고 기존 작업물들을 활용하면 리소스는 충분하기 때문에 필터만 열심히 만들면 될 것 같았습니다. 그리고 꾸준히 올리다보면 트래픽은 지금보다는 오를거라고 생각했습니다. 그래서 기존에 작업했던 모델분들에게 전부 연락을 돌려서 허락을 받았습니다. 아쉽게도 협업이 어려운 분들도 계셨지만 대부분 결과물이 궁금하기도 하고 신기하다며 허락해주셔서 다행이었습니다.(TMI인데 연락을 돌리면서 Carat 앱을 아는 모델님은 한 두분 정도밖에 없었습니다.)&lt;/p&gt;
&lt;p&gt;글을 쓰면서 앱의 다른 부분들을 들여다 봤습니다. 이제까지는 시간이 조금씩 날 때 필터만 만들러 들어와서 몰랐던 부분이었습니다.&lt;/p&gt;
&lt;p&gt;앱의 피드탭을 쭉 봤는데 유저들은 사진을 올릴 수 있고 좋아요랑 댓글로 소통할 수 있는 구조였습니다. 필터를 엄청 많이 쓰시는 헤비유저들도 계셨습니다. 하지만 피드에 헤비유저분들 몇 분만 보여서 여전히 노출 알고리즘은 모르겠습니다. 이젠 자주 들여다 봐야겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;기존에는 200P짜리 필터만 만들었었는데 포인트 충전 가격 정책을 보니 150P짜리 필터도 몇개 만들어야겠다는 생각이 들었습니다. 최소 충전금액이 3,300원이고 300P를 받을 수 있는데 시험삼아 최소금액으로 충전하는 유저 입장에서 150P짜리 필터는 두개 살 수 있는데 200P짜리는 하나밖에 구매할 수 없기 때문입니다.&lt;/p&gt;
&lt;p&gt;그렇게 지금은 총 6개의 필터를 업로드했습니다. 팔로워도 조금씩 생기고 있고 사용량이 오를 때마다 뿌듯합니다. 정산을 받으면 얼마가 될진 모르겠는데 지금 커피 몇잔 값은 벌었습니다. 필터들이 어떤 식으로 노출되는지도 아직은 모르고 수익이 얼마나 더 날지는 모르겠는데 잘 되서 허락해준 모델님들에게도 감사함을 표현하는 날이 왔으면 좋겠습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[생산성 향상을 위한 실무에서의 비동기 커뮤니케이션]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/생산성/생산성-향상을-위한-실무에서의-비동기-커뮤니케이션/</link><guid isPermaLink="false">https://donghoon-song.github.io/생산성/생산성-향상을-위한-실무에서의-비동기-커뮤니케이션/</guid><pubDate>Sun, 31 Mar 2024 15:04:19 GMT</pubDate><content:encoded>&lt;p&gt;작은 조직에서 일하면 갑작스러운 대면 커뮤니케이션이 잦다. 궁금한 점이 생기거나 논의할 게 생기면 자리로 찾아가 바로 말을 거는 케이스가 많다. 그렇게 빠르게 움직이는 것이 작은 조직의 장점이기도 하다. 하지만 너무 잦다 보면 작업 흐름이 깨지기도 한다. 몰입 상태에 있다가 동료가 불러서 얘기를 하다가 다시 돌아오면 몰입 상태로 다시 들어가는데 또 시간이 걸린다. 또한 능률도 떨어진다.&lt;/p&gt;
&lt;h2 id=&quot;컨텍스트-스위칭-비용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%8A%A4%EC%9C%84%EC%B9%AD-%EB%B9%84%EC%9A%A9&quot; aria-label=&quot;컨텍스트 스위칭 비용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;컨텍스트 스위칭 비용&lt;/h2&gt;
&lt;p&gt;능률이 떨어지는 것은 컨텍스트 스위칭 비용이 있기 때문이다. 컨텍스트 스위칭을 하면 이전에 하던 작업이 머릿속에 조금씩 남는다고 한다. 그래서 다른 작업을 시작해도 이전 작업을 깔끔하게 멈추는 것이 아니게 된다.&lt;/p&gt;
&lt;h2 id=&quot;비동기-커뮤니케이션-지향&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%BB%A4%EB%AE%A4%EB%8B%88%EC%BC%80%EC%9D%B4%EC%85%98-%EC%A7%80%ED%96%A5&quot; aria-label=&quot;비동기 커뮤니케이션 지향 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;비동기 커뮤니케이션 지향&lt;/h2&gt;
&lt;p&gt;회사에서 일을 하면서 생산성이나 커뮤니케이션 방식에 대해 많이 고민한다. 그렇게 이것저것 시도해 보면서 정착한 것 중 하나는 &lt;code class=&quot;language-text&quot;&gt;비동기 커뮤니케이션&lt;/code&gt;을 지향하는 것이다. 여기서 비동기 커뮤니케이션이란 메일이나 글의 댓글처럼 &lt;code class=&quot;language-text&quot;&gt;커뮤니케이션 대상이 동시에 실시간으로 커뮤니케이션하지 않는 방식&lt;/code&gt;을 뜻하는 개념으로 썼다. 비동기 커뮤니케이션을 하면 나뿐만 아니라 동료의 &lt;code class=&quot;language-text&quot;&gt;작업 흐름을 끊지 않고 집중력을 보장&lt;/code&gt;할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;비동기-커뮤니케이션의-적용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%BB%A4%EB%AE%A4%EB%8B%88%EC%BC%80%EC%9D%B4%EC%85%98%EC%9D%98-%EC%A0%81%EC%9A%A9&quot; aria-label=&quot;비동기 커뮤니케이션의 적용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;비동기 커뮤니케이션의 적용&lt;/h2&gt;
&lt;p&gt;내가 상대방에게 먼저 요청하는 경우와 상대방이 나에게 먼저 요청하는 경우 두 가지로 나누어 얘기해 보겠다.&lt;/p&gt;
&lt;p&gt;먼저, 내가 상대에게 무언가를 요청하는 경우에는 우선순위에 따라서 전달 방식을 결정한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;지금 당장 얘기해야 하는 건 어쩔 수 없이 자리로 찾아가지만 가기 전에 채팅으로 “급하게 논의해야 할 게 있어서 그런데 잠깐 시간 내 주실 수 있나요?”라고 조금이라도 미리 요청드린다.&lt;/li&gt;
&lt;li&gt;지금 당장은 아니지만 근시일 내에 얘기해야 하는 것은 채팅으로 “이런 부분에 대해서 논의가 필요한데 가능할까요? 가능하신 시간을 알려주시면 감사하겠습니다.”하고 채팅을 먼저 보낸다.&lt;/li&gt;
&lt;li&gt;그 외에는 요청 글이나 댓글을 작성한다.
&lt;ol&gt;
&lt;li&gt;이때 “급한 건 아니라서 시간 되실 때 봐주세요.”라든지 “급한 건 아닌데 언제까진 봐주시면 좋겠어요.”같이 상대방이 작업할 때 참고할 수 있도록 나의 우선순위를 같이 전달한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이제 반대의 경우이다. 나는 작업 사이클을 25분 정도로 잡아두고(&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%8F%AC%EB%AA%A8%EB%8F%84%EB%A1%9C_%EA%B8%B0%EB%B2%95&quot;&gt;포모도로&lt;/a&gt;) 그 시간에는 온전히 작업에 집중하려고 한다. 채팅이나 알림은 사이클이 끝나고 한 번에 확인한다. 바로 답장할 수 있는 건 바로 답장하지만 뭔가 확인해야 하거나 작업이 필요해 그렇지 않은 경우들이 있다. 그런 경우에는 “확인해 보고 몇 시까지 답변드릴게요”라고 미리 알려 드린다. 채팅 또는 글만 읽고 작업하러 가면 상대는 내가 확인은 했는지, 뭘 하고 있는지 모르기 때문이다. 또한 작업흐름을 유지하고 싶고 급하지 않다고 생각하는 경우 “지금 이런 작업을 하고 있어서 끝나고 볼게요.”라고 보낸다. 가끔 얼마나 빨리 피드백을 드려야 하는지 모르겠는 경우가 있는데 우선순위 파악이 잘 안되는 경우에는 얼마나 급하고 중요한 건지 먼저 물어보고 참고한다. 이렇게 하면 상대방 입장에서는 작업을 언제 할지, 답장은 언제 정도에 올지 예측 가능하고 기다리는 동안 다른 일을 계획할 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예를 들어보자면, 백엔드 개발자분이 API를 개발하시는 동안 테이블에 데이터를 출력하는 작업을 하고 있었다. 커스텀이 필요하다 보니까 로직을 짜는 데 오래 걸렸고 꽤 집중해서 하고 있었다. 백엔드 개발자분이 API 개발이 다 됐다고 확인하고 알려달라고 하셨다. 그래서 “테이블에 데이터 출력하는 작업을 하고 있는데 생각보다 어려워서 작업 다 하고 확인해 볼게요.”라고 보냈다. 백엔드 개발자분은 다음 API를 작업하시면 되고 바로 확인해야 할 사항은 아니라고 생각해서 그렇게 답했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;더-빠른-커뮤니케이션을-위한-팁&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8D%94-%EB%B9%A0%EB%A5%B8-%EC%BB%A4%EB%AE%A4%EB%8B%88%EC%BC%80%EC%9D%B4%EC%85%98%EC%9D%84-%EC%9C%84%ED%95%9C-%ED%8C%81&quot; aria-label=&quot;더 빠른 커뮤니케이션을 위한 팁 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;더 빠른 커뮤니케이션을 위한 팁&lt;/h2&gt;
&lt;p&gt;비동기 커뮤니케이션을 하다 보면 메시지를 주고받는 게 느리다고 느낄 수 있다. 그럴 때 더 빠르게 커뮤니케이션하기 위해서는 한번 메시지를 보낼 때 다음에 필요한 걸 미리미리 요청하는 것이다. 예를 들어서, 상대방에게 미팅을 요청하고 싶을 때, “이러이러한 것에 대해서 오늘 얘기를 나누고 싶은데 시간 괜찮으실까요?”라고만 보내면 상대방은 긍정 혹은 부정의 답변을 보낼 것이다. 긍정의 답변을 받았다면 오늘 몇 시에 시간이 되는지, 부정의 답변을 받았다면 되는 날은 언제인지 다시 물어봐야 할 것이다. 하지만 처음에 요청할 때 “이러이러한 것에 대해서 오늘 얘기를 나누고 싶은데 시간 괜찮으실까요? 가능하시다면 되는 시간을 알려주시면 감사하겠습니다. 혹시 오늘 안 된다면 다른 되는 날과 시간을 알려주시면 감사하겠습니다.”라고 필요한 정보를 미리 요청하면 커뮤니케이션 과정이 훨씬 단축된다.&lt;/p&gt;
&lt;h2 id=&quot;정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리&lt;/h2&gt;
&lt;p&gt;비동기 커뮤니케이션을 지향하다 보니 작업에 집중할 수 있는 시간이 많이 늘어났다. 이렇게 쭉 적고 보니까 아래 두 가지로 요약할 수 있을 거 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;서로가 커뮤니케이션 과정을 &lt;code class=&quot;language-text&quot;&gt;예측 가능하게 하기&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;서로의 &lt;code class=&quot;language-text&quot;&gt;작업 흐름을 존중&lt;/code&gt;해주기&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[조코딩의 챗GPT API를 활용한 수익형 웹 서비스 만들기 책 리뷰]]></title><description><![CDATA[한빛미디어 <나는 리뷰어다> 활동을 위해서 책을 제공받아 작성된 서평입니다. 서비스 구현부터 수익화까지: 챗GPT API…]]></description><link>https://donghoon-song.github.io/books/조코딩의-챗gpt-api를-활용한-수익형-웹-서비스-만들기-책-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/조코딩의-챗gpt-api를-활용한-수익형-웹-서비스-만들기-책-리뷰/</guid><pubDate>Tue, 20 Feb 2024 21:02:48 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://www.hanbit.co.kr/data/books/B6931916070_l.jpg&quot; alt=&quot;책 표지&quot;&gt;
  출처: 한빛미디어
&lt;/div&gt;
&lt;br&gt;
&lt;blockquote&gt;
&lt;p&gt;한빛미디어 &amp;#x3C;나는 리뷰어다&gt; 활동을 위해서 책을 제공받아 작성된 서평입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;서비스-구현부터-수익화까지-챗gpt-api의-실전-활용-가이드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B5%AC%ED%98%84%EB%B6%80%ED%84%B0-%EC%88%98%EC%9D%B5%ED%99%94%EA%B9%8C%EC%A7%80-%EC%B1%97gpt-api%EC%9D%98-%EC%8B%A4%EC%A0%84-%ED%99%9C%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9C&quot; aria-label=&quot;서비스 구현부터 수익화까지 챗gpt api의 실전 활용 가이드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;서비스 구현부터 수익화까지: 챗GPT API의 실전 활용 가이드&lt;/h2&gt;
&lt;p&gt;이 책은 &lt;code class=&quot;language-text&quot;&gt;챗GPT API를 활용해 서비스를 구현하고 수익화하는 과정&lt;/code&gt;을 전반적으로 다루며, 개발자와 비개발자 모두에게 접근 가능한 가이드를 제공한다. 저자가 &lt;code class=&quot;language-text&quot;&gt;실제로 만들었던 &quot;운세 보는 챗도지&quot; 서비스 구현을 목표로 필요한 것들을 위주로&lt;/code&gt; 군더더기없이 배울 수 있었다. 빠르게 서비스를 만들고 고도화하며 배포하는 방법과 수익화 전략까지 상세히 다루고 있다. 실제 서비스를 구현할 때 적용해보면 좋을 순서로 구성되어 있어, 사이드 프로젝트를 생각하고 있다면 적용해보면 좋을 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;인상-깊은-프롬프트-실전-팁&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%83%81-%EA%B9%8A%EC%9D%80-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%8B%A4%EC%A0%84-%ED%8C%81&quot; aria-label=&quot;인상 깊은 프롬프트 실전 팁 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인상 깊은 프롬프트 실전 팁&lt;/h3&gt;
&lt;p&gt;책에서 가장 유용했던 부분은 프롬프트 실전 팁이다. 저자는 챗GPT와의 상호작용에서 어떤 단어를 사용해야 효과적으로 의도를 전달할 수 있는지, 역할을 어떻게 잘 부여할 수 있는지에 대해 공유했는데 이렇게까지 구체적이고 유용한 팁은 처음 봤다. 그래서 저자가 얼마나 연구를 많이 했는지 보여주는 부분이라고 생각했다. 예를 들어서, 프롬프트에는 보편적인 단어를 사용해야 한다. GPT에 사전 학습 데이터에 포함된 단어여야 결과가 더 정확하다. 가장 보편적인 단어를 찾는 방법은 구글에 여러가지 표현을 검색해보고 결과가 가장 많은 단어를 찾는 것이다. 또 다른 예로는 “무조건 답을 할 수 있다”라고 주입시키는 것이다. 가끔 가다가 사과를 하면서 원하는 대답을 하지 않을 때가 있는데 이 팁은 그것을 방지해준다.&lt;/p&gt;
&lt;h3 id=&quot;접근성과-이해도&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%91%EA%B7%BC%EC%84%B1%EA%B3%BC-%EC%9D%B4%ED%95%B4%EB%8F%84&quot; aria-label=&quot;접근성과 이해도 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;접근성과 이해도&lt;/h3&gt;
&lt;p&gt;책은 개발 지식이 부족한 사람도 충분히 따라할 수 있도록 최대한 범용적인 기술스택을 사용했다. 프론트엔드 프레임워크를 사용하지 않고 순수하게 HTML에 Javascript를 넣는 형태로 작성했다. api 서버도 가장 범용적인 expressjs를 사용했다. 챗GPT를 api에만 사용하는 것이 아니라 실제 개발과정에서 모르는 지식이 있을 때 챗GPT에게 어떤 식으로 질문하면서 정보를 얻을 수 있는지도 보여준다. 이런 특징으로 책의 접근성을 높였고 다양한 배경의 독자들을 고려했다.&lt;/p&gt;
&lt;h3 id=&quot;수익화-전략&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%88%98%EC%9D%B5%ED%99%94-%EC%A0%84%EB%9E%B5&quot; aria-label=&quot;수익화 전략 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;수익화 전략&lt;/h3&gt;
&lt;p&gt;애드센스와 토스 후원 링크를 삽입해 수익화를 노린 것도 이 책의 특징이다. 애드센스는 워낙 많이 쓰이는 방식이라 알고 있었는데 토스 후원 링크를 넣는건 처음 봤다. 물론 링크를 본 사람이 진짜 후원해주고 싶은 마음이 생겨야 돈을 보내겠지만 그래도 재미있는 방식이었다. 이런 수익화 전략을 적용해보고 싶은 사람에게는 유용한 정보가 될 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;추천-독자층&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%94%EC%B2%9C-%EB%8F%85%EC%9E%90%EC%B8%B5&quot; aria-label=&quot;추천 독자층 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;추천 독자층&lt;/h3&gt;
&lt;p&gt;이 책은 챗GPT API를 활용해 자신만의 서비스를 만들고, 그 과정에서 수익화까지 해보고 싶은 사람이 읽으면 좋겠다는 생각이 들었다. 그리고 웹개발에 그렇게까지 익숙하지 않아도 책을 따라하면 서비스가 뚝딱 만들어진다. 이 책에서 배운 내용을 잘 활용하면 여러가지 서비스를 만들 수 있을 것 같다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[해결할 프로덕트 도서 리뷰 - 고객과 가까워지기]]></title><description><![CDATA[책 소개 라는 문장이 나의 프로덕트에 대한 고민을 해결할 열쇠처럼 다가왔다. 길벗 출판사에서 리뷰어를 모집한다는 소식을 듣고 홀리듯이 신청했다. 솔직히 신청할 때는 이 책이 57…]]></description><link>https://donghoon-song.github.io/books/해결할-프로덕트-도서-리뷰---고객과-가까워지기/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/해결할-프로덕트-도서-리뷰---고객과-가까워지기/</guid><pubDate>Sun, 18 Feb 2024 22:02:05 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction: column; align-items:center;&quot;&gt;
  &lt;img src=&quot;https://gimg.gilbut.co.kr/book/BN003904/rn_view_BN003904.jpg&quot; alt=&quot;책 표지&quot;&gt;
  출처: 길벗
&lt;/div&gt;
&lt;h2 id=&quot;책-소개&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B1%85-%EC%86%8C%EA%B0%9C&quot; aria-label=&quot;책 소개 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;책 소개&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;임팩트 하나만 만들어라&lt;/code&gt;라는 문장이 나의 프로덕트에 대한 고민을 해결할 열쇠처럼 다가왔다. 길벗 출판사에서 리뷰어를 모집한다는 소식을 듣고 홀리듯이 신청했다. 솔직히 신청할 때는 이 책이 572 페이지나 되는 줄 몰랐다. 그래서 책을 받고 나서 ‘언제 다 읽지’라는 생각을 했다. 하지만 책을 훑어보니 그렇지 않아도 되겠다는 생각이 들었다. 책의 서론에서도 얘기하지만 백과사전식으로 필요한 부분부터 읽으면 되기 때문이다.&lt;/p&gt;
&lt;h2 id=&quot;요약하자면&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD%ED%95%98%EC%9E%90%EB%A9%B4&quot; aria-label=&quot;요약하자면 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약하자면&lt;/h2&gt;
&lt;p&gt;이 책은 제품 회사의 수명 주기를 1. 아이디어, 2. 스타트업, 3. 성장, 4. 확장, 5. 성숙, 6. 회고로 세세히 나누어 접근한다. 각 단계별로 &lt;code class=&quot;language-text&quot;&gt;유저와 어떻게 가까워질 수 있는지&lt;/code&gt;에 대해 얘기한다. 설명이 잘 되어 있고 구체적인 액션 플랜도 제시해줘서 쉽게 행동으로 옮길 수 있을 것 같다. 자사 서비스가 있는 회사에서 일하고 있는 사람이 읽는다면 유용할 것이라는 생각이 들었다.&lt;/p&gt;
&lt;h2 id=&quot;리뷰하자면&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%EB%B7%B0%ED%95%98%EC%9E%90%EB%A9%B4&quot; aria-label=&quot;리뷰하자면 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리뷰하자면&lt;/h2&gt;
&lt;h3 id=&quot;나의-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%82%98%EC%9D%98-%EC%83%81%ED%99%A9&quot; aria-label=&quot;나의 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;나의 상황&lt;/h3&gt;
&lt;p&gt;우리 조직은 제품 중심의 스쿼드에서 목적 중심의 셀로 조직 개편을 해서 일하는 실험을 하고 있다. 그래서 셀로 일하는 방식에 적응해야 하는데 이 책을 읽다보니 적용해 볼만한 지점들이 많았다. 필요한 부분들부터 몰입해서 빠르게 읽을 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;가치-제공-평가하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%80%EC%B9%98-%EC%A0%9C%EA%B3%B5-%ED%8F%89%EA%B0%80%ED%95%98%EA%B8%B0&quot; aria-label=&quot;가치 제공 평가하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;가치 제공 평가하기&lt;/h3&gt;
&lt;p&gt;가장 먼저 읽었던 부분은 “가치 제공 평가하기” 챕터였다. 우리 셀이 1년 목표를 잡고 나아갈 때 얼마나 고객에게 가치를 제공하는지 제대로 측정하고 싶었다.&lt;/p&gt;
&lt;p&gt;책에서 고객 연구를 아무리 열심히 하더라도 그들이 원하는 100% 완벽한 제품을 한번에 만들 수는 없다고 한다.&lt;/p&gt;
&lt;p&gt;대신에&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;고객 요구를 찾아 몇번의 이터레이션을 거쳐야 하고&lt;/li&gt;
&lt;li&gt;제품을 유연하게 만들어 실험하기 좋게 만들어야 하며&lt;/li&gt;
&lt;li&gt;단순하게 유지해서 제품이 복잡해지기 전 핵심 기능의 가치를 평가할 수 있어야&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;한다고 한다. 대표님이 우리 셀은 목표를 달성하기 위한 모든 방법을 나열하고 우선순위에 따라 실행하면서 고객을 학습하는 식으로 그로스 해보라고 하셨다. 책에 관련한 내용이 있어서 왜 이런 방식으로 접근하면 좋은지 더 깊게 이해할 수 있어서 도움이 많이 됐다.&lt;/p&gt;
&lt;h3 id=&quot;실험과-학습&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%ED%97%98%EA%B3%BC-%ED%95%99%EC%8A%B5&quot; aria-label=&quot;실험과 학습 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실험과 학습&lt;/h3&gt;
&lt;p&gt;“복리식 승리” 챕터에서 우리가 승리하는 유일한 방법은 &lt;code class=&quot;language-text&quot;&gt;훨씬 더 많이 실험하고, 그 과정에서 어떤 것이 통하는지 운 좋게 발견하는 것&lt;/code&gt;이라고 한다. 트위터는 2011년부터 주당 실험 횟수를 0.5에서 10으로 증가시켜 가파르게 성장했고, 더 많은 실험이 더 이상 빠른 성장으로 이어지지 않을때까지 했다고 한다.&lt;/p&gt;
&lt;p&gt;빠른 실험 과정의 성과는&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;통찰력과 고객 연구의 질. → &lt;code class=&quot;language-text&quot;&gt;좋은 가설&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;실험 속도&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;실험 &lt;code class=&quot;language-text&quot;&gt;결과로부터 학습&lt;/code&gt;할 수 있는 능력&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;에 달려 있다고 한다. 지난 달을 돌이켜보면 실험 속도는 충분히 빠르다고 생각하는데 좋은 가설을 세우는 능력, 학습하는 능력은 많이 부족하다는 생각이 들었다.&lt;/p&gt;
&lt;h3 id=&quot;고객과-가까워지기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B3%A0%EA%B0%9D%EA%B3%BC-%EA%B0%80%EA%B9%8C%EC%9B%8C%EC%A7%80%EA%B8%B0&quot; aria-label=&quot;고객과 가까워지기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;고객과 가까워지기&lt;/h3&gt;
&lt;p&gt;그리고 다른 챕터에서 고객에게 가까이 다가가는 방법을 많이 배웠다.&lt;/p&gt;
&lt;p&gt;예를 들어, “후속 이메일을 통한 학습” 챕터에서는 &lt;code class=&quot;language-text&quot;&gt;이탈한 고객은 붙잡기 어렵지만 그들로부터 배울 수 있는 것이 많다&lt;/code&gt;고 한다. 그래서 &lt;code class=&quot;language-text&quot;&gt;스크럼 때 이탈 고객들에게 이메일을 보내보자고 제안&lt;/code&gt;했다.&lt;/p&gt;
&lt;p&gt;그리고 “단일 용이성 질문” 챕터에서는 사용 용이성을 평가하는 툴로 태스크 수행 후 태스크 완료가 얼마나 어려웠는지 혹은 쉬웠는지 물어보는 방법을 소개했다. 이 방식도 셀에 제안해서 &lt;code class=&quot;language-text&quot;&gt;서비스 대학 제휴 후에 제휴 과정이 얼마나 매끄러웠는지 물어보는 설문을 추가&lt;/code&gt;했다.&lt;/p&gt;
&lt;h2 id=&quot;마무리하자면&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC%ED%95%98%EC%9E%90%EB%A9%B4&quot; aria-label=&quot;마무리하자면 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리하자면&lt;/h2&gt;
&lt;p&gt;리뷰를 작성하면서 좋은 책이라는 걸 다시 한번 느꼈다. 이 정도만 읽어도 배울 게 이렇게나 많은데 내가 아직 읽지 않은 챕터들까지 포함해서 액션 아이템을 뽑아서 적용해본다면 어떤 모습일지 너무 기대된다. 어떤 제품을 만들어야 할지 고민하고 있다면 꼭 읽어보길 추천한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[openai api code 429, You exceeded your current quota, please check your plan and billing details 에러 해결하기]]></title><description><![CDATA[openai api를 사용하다가 status code 429, You exceeded your current quota, please check your plan and billing details…]]></description><link>https://donghoon-song.github.io/트러블슈팅/openai-api-code-429,-you-exceeded-your-current-quota,-please-check-your-plan-and-billing-details-에러-해결하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/트러블슈팅/openai-api-code-429,-you-exceeded-your-current-quota,-please-check-your-plan-and-billing-details-에러-해결하기/</guid><pubDate>Thu, 08 Feb 2024 15:02:57 GMT</pubDate><content:encoded>&lt;p&gt;openai api를 사용하다가 &lt;strong&gt;status code 429, You exceeded your current quota, please check your plan and billing details.&lt;/strong&gt; 라는 에러를 만났다. 이 에러의 해결 과정을 정리했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/yMCyOT9.png&quot; alt=&quot;에러 이미지&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/4ph2DK5.png&quot; alt=&quot;에러 이미지&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;openai에서 제공하는 &lt;a href=&quot;https://platform.openai.com/docs/guides/error-codes/api-errors&quot;&gt;api error 문서&lt;/a&gt;를 찾아보니 다음과 같은 내용이 있었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/GiFsUHc.png&quot; alt=&quot;openai api error document&quot;&gt;&lt;/p&gt;
&lt;p&gt;openai api를 사용해 본 적이 없는 계정은 account page에 들어가보면 Usage limits이 free로 되어 있다. 나는 문제를 해결하고 이 글을 쓰는 것이기 때문에 지금은 Usage tier1로 되어 있다. 이건 내가 설정하는 것이 아니라 내가 api를 사용하면 자동으로 업데이트되는 거라 확인만 하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/jYyeOM0.png&quot; alt=&quot;openai usage limit 화면&quot;&gt;&lt;/p&gt;
&lt;p&gt;내 크레딧이 0이었기 때문에 아래 Add to credit balance 버튼을 눌러서 작고 소중한 5달러를 충전했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/piraBjx.png&quot; alt=&quot;openai billing 화면&quot;&gt;&lt;/p&gt;
&lt;p&gt;이 에러를 만났다면 API key를 이미 발급받은 상태일텐데, 이 상태에서 다시 시도해도 똑같은 에러가 떴다. 그래서 당황했다가 API key를 새로 발급받으니 에러가 사라졌다.&lt;/p&gt;
&lt;h2 id=&quot;요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot; aria-label=&quot;요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;openai 크레딧이 없거나 api 사용량을 넘으면 &lt;strong&gt;status code 429, You exceeded your current quota, please check your plan and billing details.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;크레딧을 충전하거나 api key를 새로 발급받아 해결할 수 있다.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[글쓰기 세미나 및 글쓰기 프로세스 회고]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/feedback/글쓰기-세미나-및-글쓰기-프로세스-회고/</link><guid isPermaLink="false">https://donghoon-song.github.io/feedback/글쓰기-세미나-및-글쓰기-프로세스-회고/</guid><pubDate>Wed, 07 Feb 2024 19:03:13 GMT</pubDate><content:encoded>&lt;p&gt;글또의 글쓰기 세미나를 듣고 머릿속에만 있던 나의 글쓰기 프로세스를 끄집어 내 정리해보고자 한다. 나는 이제껏 어떤 플로우로 글을 썼는지, 개선할 부분은 없는지 보고 싶었다.&lt;/p&gt;
&lt;h2 id=&quot;나의-글쓰기-프로세스&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%82%98%EC%9D%98-%EA%B8%80%EC%93%B0%EA%B8%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4&quot; aria-label=&quot;나의 글쓰기 프로세스 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;나의 글쓰기 프로세스&lt;/h2&gt;
&lt;p&gt;나의 글쓰기 프로세스를 도식화하면 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/2F6cxV8.png&quot; alt=&quot;제목 없음-2024-02-07-1940.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;글감-모으기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EA%B0%90-%EB%AA%A8%EC%9C%BC%EA%B8%B0&quot; aria-label=&quot;글감 모으기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글감 모으기&lt;/h3&gt;
&lt;p&gt;나는 글 소재나 아이디어가 생각날 때마다 아이폰 메모에 모아 놓는 편이다. 아이폰 기기라면 동기화가 돼서 어디에서나 쉽게 접근할 수 있어서 그렇다. 소재만 남길 때도 있고, 간단하게 몇 문장 덧붙여서 남길 때도 있다. 그 뒤에도 소재에 대해 생각 나는 것이 있으면 바로 적는다. 그것들이 모여서 초안의 재료가 된다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/BZvD9j9.png&quot; alt=&quot;진짜 중구난방인 메모&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;글-작성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80-%EC%9E%91%EC%84%B1&quot; aria-label=&quot;글 작성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글 작성&lt;/h3&gt;
&lt;p&gt;글또 글을 써야 할 때는 메모에서 주제를 찾아보고, 마땅한 게 없으면 다시 생각해본다. 아직까지 뭔가 새로 공부하면서 쓴 적은 없고, 내가 했던 경험들을 글로 남겼었다. 자리에 앉아서 소재를 초안으로 만들 때는 글또 노션 템플릿을 활용한다. 템플릿에 있는 질문들을 답하다보면 어떤 식으로 쓰면 좋을지 도움이 많이 된다. 질문에 답하고 나서 글을 쓰기 시작하는데 나는 구조를 먼저 생각하기보다는 의식의 흐름대로 생각나는걸 쭉 써놓는다. 처음부터 구조대로 쓰려고 하면 잘 생각이 나지 않는데, 생각나는 대로 막 쓰면 그나마 잘 써진다. 그리고 글을 오래 쓰고 있으면 몸이 근질거려서 시동이 걸릴 때 확 쓰고 다음 사이클 때 또 쓰는 편이다. 생각나는대로 적어놓았던 것들을 서론, 본론, 결론으로 구조에 맞게 다듬으면서 정리한다.&lt;/p&gt;
&lt;h2 id=&quot;개선&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%9C%EC%84%A0&quot; aria-label=&quot;개선 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;개선&lt;/h2&gt;
&lt;h3 id=&quot;글감-폴더&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EA%B0%90-%ED%8F%B4%EB%8D%94&quot; aria-label=&quot;글감 폴더 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글감 폴더&lt;/h3&gt;
&lt;p&gt;아이폰 메모에 글감 폴더를 만들었다. 메모 앱에는 글감이 다른 것들(사이드 프로젝트 아이디어, 주저리 주저리 생각 등)이 섞여 있으니까 글감을 얼마나 모았는지, 어떤 글감들이 있는지 모아보기 힘들었다. 글감폴더에 있는 글감들. 확실히 구분하니까 보기 쉽다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/rLjNHHW.png&quot; alt=&quot;글감폴더에 있는 글감들. 확실히 구분하니까 보기 쉽다&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;일상-소재&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%BC%EC%83%81-%EC%86%8C%EC%9E%AC&quot; aria-label=&quot;일상 소재 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;일상 소재&lt;/h3&gt;
&lt;p&gt;아무래도 주로 글을 쓰게 되면 글또에 제출할 글을 쓴다. 그래서 소재를 떠올릴 때도 글또 글 소재로 쓸 수 있는걸 떠올리는 편인데, 꽤나 잘 생각이 나지 않았다.&lt;/p&gt;
&lt;p&gt;밀리의 서재의 &lt;code class=&quot;language-text&quot;&gt;쓸 게 없다뇨, 이렇게 많은데&lt;/code&gt; 라는 책을 읽었는데 &lt;code class=&quot;language-text&quot;&gt;글 쓸 게 없다는건 핑계다. 흘러가는 일분 일초를 자세히 들여다보면 충분히 글로 적어낼 부분이 많다.&lt;/code&gt; 라는 문장이 나온다.&lt;/p&gt;
&lt;p&gt;그래서 이제는 일상 소재도 많이 메모해 두려고 한다. 글또에 제출할 수 없는 경우가 많겠지만 그럼에도 따로 적어보려고 한다. 많이 써봐야 글을 더 잘 쓸 거 같아서.&lt;/p&gt;
&lt;h3 id=&quot;실행&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%ED%96%89&quot; aria-label=&quot;실행 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실행&lt;/h3&gt;
&lt;p&gt;마감기한이 닥쳐 와서 쫓기듯 글을 쓰면 잘 되지 않는다. 그리고 쓰다보면 고칠 것이나 떠오르는 것이 있기 때문에 글이 애매해질 때가 많다. 이 글도 더 일찍 사이클을 돌리면서 썼어야 했는데 너무 미뤘던 거 같다. 그래서 이제는 글을 더 빨리 쓰고, 더 빨리 다듬어야겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[작은 조직에서 개발문화를 제안했던 경험과 알아두면 좋을 느낀점]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/culture/작은-조직에서-개발문화를-제안했던-경험과-알아두면-좋을-느낀점/</link><guid isPermaLink="false">https://donghoon-song.github.io/culture/작은-조직에서-개발문화를-제안했던-경험과-알아두면-좋을-느낀점/</guid><pubDate>Fri, 02 Feb 2024 23:02:22 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/wfMIqA9.png&quot; alt=&quot;개발 문화를 도입하는 사진&quot;&gt;&lt;/p&gt;
&lt;p&gt;최근에 슬랙에 올라 온 고민글 중에 개발 문화가 없는 조직에서 개발 문화를 어떻게 도입할 수 있을지 고민이라는 글이 있었다. 그 글을 보니 내가 프론트엔드 팀에 제안했던 경험들이 떠올라서 열심히 댓글을 남겼다. 그 경험들을 정리해서 남겨보고자 한다.&lt;/p&gt;
&lt;h2 id=&quot;테스트-코드를-작성하는-문화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%98%EB%8A%94-%EB%AC%B8%ED%99%94&quot; aria-label=&quot;테스트 코드를 작성하는 문화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테스트 코드를 작성하는 문화&lt;/h2&gt;
&lt;p&gt;내가 프론트엔드 팀에 제안했던 문화는 &lt;strong&gt;테스트 코드를 작성하는&lt;/strong&gt; 문화였다.&lt;/p&gt;
&lt;p&gt;우리 서비스는 유저가 어떤 행동을 하면 gtm(google tag manager) event를 trigger해서 수집한다. 입사 초반에 내가 코드를 수정했다가 이 event가 발동하지 않으면 어쩌지? 하는 걱정에 이 로직들을 테스트 자동화 해놓으면 미리 알아차릴 수 있지 않을까 하는 생각을 했다. 빨리 알아차릴수록 고치는 비용이 작기 때문이다. 그 순간이 테스트 코드에 관심을 가지기 시작한 순간이었고 e2e test tool인 cypress를 설치해서 열심히 뚝딱거렸다. 하지만 내가 생각했던 대로 테스트 환경을 구축하지는 못했다. 시나리오대로 app을 mocking하는 게 쉬운 일은 아니었고, 프론트 앱 뿐만 아니라 이것저것 얽혀 있었기 때문이었다. 그래서 혼자서 만져보기만 하고 팀에 도입하지는 못했다.&lt;/p&gt;
&lt;p&gt;시간이 지나고 jest를 이용해 컴포넌트 단위 테스트를 짜보면 어떨까 하는 생각이 들었다. 대상 컴포넌트만 mocking하면 되기 때문에 단위가 작아서 구현이 쉽고 더 효용이 있을 것이라는 생각이 들었다. 하지만 개발하면서 약속한 일정을 맞추다보면 테스트 코드를 항상 같이 짜진 못했다. 대신에 생각보다 빨리 개발하면 개발 후에라도 테스트 코드를 붙이는 경우가 있었다. 또한 사이즈가 작은 업무인 경우 테스트 코드를 먼저 작성해보고 컴포넌트를 개발해 본 경우도 있었다. 이렇게 테스트 코드를 놓지 않고 계속 붙들고 있으니까 아래와 같은 효용을 느낄 수 있었다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;테스트 코드 자체가 컴포넌트의 기능 명세가 된다.&lt;/li&gt;
&lt;li&gt;변경으로 인한 예상치 못한 버그를 예방할 수 있다.&lt;/li&gt;
&lt;li&gt;테스트 코드를 먼저 작성했을 때는 UI를 뺀 기능구현에 먼저 집중을 하니 오히려 더 빨리 개발하는 경우도 있었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그리고 팀원들을 설득했다. 팀 미팅 때마다 테스트 코드가 좋다고 노래를 부르고, 위의 효용을 느꼈다고 했다. 물론 팀원들도 이게 좋은지는 안다. 하지만 내가 얘기를 꺼낸다고 해서 100% 설득되지는 않는다. 좋은지는 알지만 직접 효용을 느끼지 못한다면 설득되지 않는다.&lt;/p&gt;
&lt;p&gt;그래서 github action을 통해 PR을 올리면 자동으로 테스트가 돌아가도록 해놓았는데 이거라도 붙여보자고 했다. 이걸 붙인다고 지금부터 당장 테스트 코드를 써야 하는건 아니기 때문에 넣어만 보자는 것이다. 나중에 정말 필요없다고 생각하면 그 때 지워도 되니까. 결국 그렇게 붙인 github action이 빛을 발했다. 팀원이 테스트 코드가 달린 컴포넌트를 수정할 일이 있었는데 수정하고 보니 테스트 코드 통과를 못 한 것이다. 그래서 테스트 코드를 보니 미처 생각하지 못한 부분이 있었음을 깨달으시고 다시 수정했다고 하셨다. 그리고 PR을 올릴때마다 계속 돌아가니, 팀원들도 시간이 날 때 하나씩 테스트 코드를 작성해보기도 했다.&lt;/p&gt;
&lt;h2 id=&quot;적용해볼만한-느낀점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%BC%EB%A7%8C%ED%95%9C-%EB%8A%90%EB%82%80%EC%A0%90&quot; aria-label=&quot;적용해볼만한 느낀점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;적용해볼만한 느낀점&lt;/h2&gt;
&lt;p&gt;그 후에도 유용한 툴을 같이 쓰자고 제안하거나 스터디를 같이 하거나 팀에서 여러가지 시도를 했었다. 그러면서 느꼈던 점을 요약해보면 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;팀원들이 쉽게 설득될 것이라는 기대는 버린다.&lt;/li&gt;
&lt;li&gt;팀원들이 직접 효용을 느끼게 해야 한다. 좋다고 느끼면 설득하지 않아도 자발적으로 참여할 것이다.&lt;/li&gt;
&lt;li&gt;모든 문화가 팀에 맞는 것은 아니다. 해보고 맞지 않는 문화는 과감히 버리는 게 좋을 수도 있다.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[shadcn, react-hook-form useFieldArray, zod로 동적 form 관리하기]]></title><description><![CDATA[이 글에서는 shadcn + react-hook-form useFieldArray + zod로 동적 form을 만드는 과정을 소개한다. shadcn: UI library react-hook-form: 폼을 만드는 라이브러리 zod…]]></description><link>https://donghoon-song.github.io/react.js/shadcn,-react-hook-form-usefieldarray,-zod로-동적-form-관리하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/react.js/shadcn,-react-hook-form-usefieldarray,-zod로-동적-form-관리하기/</guid><pubDate>Fri, 02 Feb 2024 22:02:50 GMT</pubDate><content:encoded>&lt;p&gt;이 글에서는 shadcn + react-hook-form useFieldArray + zod로 동적 form을 만드는 과정을 소개한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ui.shadcn.com/&quot;&gt;shadcn&lt;/a&gt;: UI library&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react-hook-form.com/&quot;&gt;react-hook-form&lt;/a&gt;: 폼을 만드는 라이브러리&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zod.dev/&quot;&gt;zod&lt;/a&gt;: 스키마 타입 검증을 해주는 라이브러리&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;책에서 액션 아이템을 뽑는 앱을 사이드 프로젝트로 만들고 있다. 그러다 form을 만들 일이 생겼다. 회사에서는 Vue를 주로 쓰고 있어서 React를 사이드 프로젝트로 공부하고 있다. 안 그래도 React는 form을 만들기가 어렵다는 얘기를 많이 들어서 살짝 겁났다.&lt;/p&gt;
&lt;p&gt;먼저 내가 쓰고 있는 shadcn의 Form component를 살펴봤다. shadcn은 form을 만들 때 React Hook Form과 Zod를 사용한다. 공식문서를 따라가 보면 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;먼저 form의 스키마를 만든다. 이 예제에서 username은 최소 2, 최대 50의 길이를 가지는 문자열이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;use client&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zod&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;useForm hook으로 form을 만든다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use client&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; zodResolver &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@hookform/resolvers/zod&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useForm &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &quot;react&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;hook&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;form

&lt;span class=&quot;token comment&quot;&gt;// 1. Define your form.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; useForm&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;typeof&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;formSchema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;zodResolver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formSchema&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;defaultValues&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;)

// 2. Define a submit handler.
// values로 데이터를 확인할 수 있다.
function onSubmit(values: z.infer&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;typeof&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;formSchema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Do something with the form values.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ✅ This will be type-safe and validated.&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;컴포넌트는 아래와 같이 구성하면 form이 연동된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onSubmit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;space-y-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormField&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Username&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Input&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shadcn&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormDescription&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;This is your public display name.&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormDescription&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Submit&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 가이드를 기반으로 내가 작성한 코드는 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;use client&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Drawer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerClose&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerContent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerHeader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerTitle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerTrigger&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/drawer&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Form&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormControl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormField&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormItem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormLabel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormMessage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/form&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Button &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/button&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Input &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/input&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; toast &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/use-toast&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zod&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; zodResolver &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@hookform/resolvers/zod&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useForm &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-hook-form&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lucide-react&apos;&lt;/span&gt;

type Props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; FormSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;출처는 반드시 필요합니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;제목은 반드시 필요합니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ActionItemCreateDrawer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    useForm &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
    z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; FormSchema &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;zodResolver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FormSchema&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;defaultValues&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;typeof&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;FormSchema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;toast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;You submitted the following values:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pre&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mt-2 w-[340px] rounded-md bg-slate-950 p-4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;code&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text-white&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;code&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pre&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  return (
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Drawer&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTrigger&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTrigger&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerContent&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;h-screen mt-0 max-w-sm mx-auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerHeader&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerClose&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;X&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mb-10&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerClose&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTitle&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;액션 아이템 만들기&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTitle&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerHeader&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;px-4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt;
              &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onSubmit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
              &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;w-full space-y-6&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormField&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;from&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;출처&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Input&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;부자아빠 가난한아빠&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormField&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;제목&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Input&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;힘든 일 먼저 하기&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;w-full&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                액션아이템 만들기
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerContent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Drawer&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  )
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;내 form은 string type인 from과 title field를 가지고 있다. 여기까진 좋았다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/1Km1icN.png&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;p&gt;생각해보니 액션 아이템이 여러개일 수 있다는 사실을 간과했다. 그래서 다급하게 &lt;code class=&quot;language-text&quot;&gt;react-hook-form dynamic&lt;/code&gt;이라는 키워드를 검색했다. 찾아보니 useFieldArray라는 hook이 있었는데 이걸 쓰면 될 것 같았다. 참고해서 코드를 수정했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// actionItem -&gt; actionItems 배열로 바뀌었다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; FormSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;출처는 반드시 필요합니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;actionItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;actionItem&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;액션 아이템은 반드시 필요합니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// initValue도 그에 맞게 수정해줬다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; initValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;actionItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;actionItem&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  useForm &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; FormSchema &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;zodResolver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FormSchema&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;defaultValues&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; initValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// useFieldArray의 control에는 기존의 form.control을 넘긴다.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// name은 이 hook으로 관리하는 field array의 이름을 넘겨주면 된다.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// fields는 관리하는 field들, append는 field를 추가할 때, remove는 제거할 때 사용할 수 있다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fields&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; append&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; remove &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useFieldArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;actionItems&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;UI 부분은 다음과 같이 수정했다. &lt;code class=&quot;language-text&quot;&gt;name에는 아래와 같이 형식에 맞춰서 적어줘야 한다. 형식이 다르면 Input component에서 type error가 났다.&lt;/code&gt; append를 할 수 있는 Button도 추가해봤다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  fields&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;field&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormField&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;form-field-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;actionItems.&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.actionItem&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;액션 아이템&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Input&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;힘든 일 먼저 하기&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;flex justify-end&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;actionItem&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;추가하기&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;최종 코드는 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;use client&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Drawer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerClose&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerContent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerHeader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerTitle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  DrawerTrigger&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/drawer&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Button &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/button&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Form&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormControl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormField&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormItem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormLabel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  FormMessage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/form&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; toast &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/use-toast&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Input &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/components/ui/input&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zod&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; zodResolver &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@hookform/resolvers/zod&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useForm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; useFieldArray &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-hook-form&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lucide-react&apos;&lt;/span&gt;

type Props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; boolean&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;setOpen&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; FormSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;출처는 반드시 필요합니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;actionItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;actionItem&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;액션 아이템은 반드시 필요합니다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; initValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;actionItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;actionItem&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ActionItemCreateDrawer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  children&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  open&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  setOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    useForm &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
    z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; FormSchema &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;zodResolver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FormSchema&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;defaultValues&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; initValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fields&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; append&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; remove &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useFieldArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;actionItems&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;typeof&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;FormSchema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;toast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;You submitted the following values:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pre&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mt-2 w-[340px] rounded-md bg-slate-950 p-4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;code&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text-white&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;code&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pre&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  return (
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Drawer&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;open&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onOpenChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;setOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTrigger&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTrigger&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerContent&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;h-screen mt-0 max-w-sm mx-auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerHeader&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerClose&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;X&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mb-10&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerClose&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTitle&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;액션 아이템 만들기&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerTitle&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerHeader&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;px-4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt;
              &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSubmit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onSubmit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
              &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;w-full space-y-6&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormField&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;from&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;출처&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Input&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;부자아빠 가난한아빠&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;fields&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;field&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormField&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;form-field-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token attr-name&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;control&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;actionItems.&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.actionItem&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token attr-name&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; field &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;액션 아이템&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormLabel&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Input&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;힘든 일 먼저 하기&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;field&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormControl&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormItem&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;flex justify-end&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;actionItem&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                  추가하기
                &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;w-full&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
                액션아이템 만들기
              &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DrawerContent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Drawer&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  )
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/donghoon-song/meeting-room-reservation-app/assets/32301380/122fa149-b62a-4a04-bb70-354be6567bad&quot; alt=&quot;화면 기록 2024-01-30 오후 10 34 57&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/i8nZ0bG.png&quot; alt=&quot;스크린샷 2024-01-30 오후 10.35.19.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;멋진 라이브러리들의 도움으로 동적 form을 손쉽게 만들어봤다. actionItems를 string 배열로 만들어보고 싶었는데 하다보니 타입 에러가 나서 이건 아직 구현 방법을 모르겠다. 손에 익도록 다양한 형태의 form도 만들어봐야겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[슬랙 커뮤니티를 처음 운영해보고 배운 점]]></title><description><![CDATA[이 글에서는 제가 겪는 문제에서 비롯해 슬랙 커뮤니티를 처음 만들고 운영해 본 경험을 나누고자 합니다. 채널을 만들고 나서 날짜별로 현황을 조금씩 정리했었는데 그 형식대로 적어볼까 합니다. 1월…]]></description><link>https://donghoon-song.github.io/mystory/슬랙-커뮤니티를-처음-운영해보고-배운-점/</link><guid isPermaLink="false">https://donghoon-song.github.io/mystory/슬랙-커뮤니티를-처음-운영해보고-배운-점/</guid><pubDate>Sun, 21 Jan 2024 00:02:37 GMT</pubDate><content:encoded>&lt;p&gt;이 글에서는 제가 겪는 문제에서 비롯해 슬랙 커뮤니티를 처음 만들고 운영해 본 경험을 나누고자 합니다. 채널을 만들고 나서 날짜별로 현황을 조금씩 정리했었는데 그 형식대로 적어볼까 합니다.&lt;/p&gt;
&lt;h2 id=&quot;1월-5일&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9B%94-5%EC%9D%BC&quot; aria-label=&quot;1월 5일 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1월 5일&lt;/h2&gt;
&lt;h3 id=&quot;계기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B3%84%EA%B8%B0&quot; aria-label=&quot;계기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;계기&lt;/h3&gt;
&lt;p&gt;링크드인에서 어떤 분이 프론트엔드 슬랙을 만드신다는 글을 봤는데 참여하고 싶다는 댓글이 엄청나게 달렸습니다. 그 글을 보고는 수요가 엄청 많구나 싶었는데 문득 소규모 스타트업 프론트엔드 개발자들을 모아보면 어떨까 하는 생각이 들었습니다. 보통의 아티클들을 보면 내용이 좋고 너무 훌륭하지만 팀 규모가 다르다 보니 실제로 적용해 보기 힘든 부분들이 많았습니다. 그래서 &lt;strong&gt;작은 조직에서 겪는 문제와 그 해결책을 서로 나눈다면 그 경험들이 더 현실적이고 와닿지 않을까&lt;/strong&gt; 하는 생각이 들었습니다.&lt;/p&gt;
&lt;h3 id=&quot;두려움&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%91%90%EB%A0%A4%EC%9B%80&quot; aria-label=&quot;두려움 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;두려움&lt;/h3&gt;
&lt;p&gt;만드는 과정에서 어려움이 많았습니다. 제가 사내에서 슬랙을 주로 사용하지도 않고 커뮤니티 운영도 처음이었기 때문입니다. 그래서 시작하기 전에 사람들이 괜히 들어왔다가 실망하고 나가지는 않을지 많이 걱정했습니다.&lt;/p&gt;
&lt;h3 id=&quot;실행&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%ED%96%89&quot; aria-label=&quot;실행 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실행&lt;/h3&gt;
&lt;p&gt;하지만 &lt;strong&gt;일단 만들어보고 싶었습니다&lt;/strong&gt;. 필요한 건 그때마다 배우면 되고 모르면 물어보고 싶었습니다. 설령 실패하더라도 많이 배울 것 같았습니다. 그래서 글에도, 초대 메시지에도 서툴 수도 있으니 같이 만들어 갔으면 좋겠다는 메시지를 추가했습니다. 처음으로 슬랙 워크스페이스를 생성해 보고 채널을 생성해 봤습니다. 취지에 맞게 비슷한 환경의 멤버분들끼리 묶어 드리는 걸 1순위로 생각해서 채널을 나눠보고 싶었습니다. 하지만 기준을 어떻게 잡아야 할지 고민이었습니다. 조직규모에 따라 나눌지, 프론트팀 또는 개발팀 규모에 따라 나눌지 고민했습니다. 처음엔 후자로 기준을 잡았는데 조직규모가 크면 개인이 활용할 수 있는 리소스가 더 많을 거 같아서 전자가 더 적합할 거 같아서 기준을 바꿨습니다. 어떤 게 더 적합할진 모르겠습니다. 하다가 안 맞으면 바꾸면 될 거 같아서 이렇게 진행했습니다.&lt;/p&gt;
&lt;p&gt;덤으로 chatGPT로 멋진 로고도 만들어 봤는데 꽤 만족스러웠습니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 248px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 103.2258064516129%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAABYlAAAWJQFJUiTwAAAEIElEQVR42q2U+08UVxTH+aH/QJv0xzY2NsY2JjVNS2wN0aaCWJGiVjAFpS0Y66bRsiAgT3eFXZdlQR4rwlJQV2BBloUqiFSw1fBSgUDow7QNxlqEthikhS3M49NhZnVBm/7USU7m3rnnfObcc+79BvA/PwEgKy/pX01G0N6yz9BsuZ+4ZCwvAp9ekB+PRRUgCgsIoqCMlZ/Lj3wexQjL4gP8E81kWUCSBB4ogX3SPINzf5JiMFPhaqSfeUalBf7y+cmyuAS6DCipH9UtKqBRZbFt/BfGxn+loe0rVkbGs+HTFIa//Y6Bn37k4vQf3F8smLyYp+ADCsuBkvLnxeekw4mprJrRoSFKixyExSXwXJKJFw9mE7c/kfraRnr7+unsv8HU75O+GgtPb/lvcYEpZZRtLiY2/nN2H0hhhd3FS8HbWB+6jXUb3+X5mH2sKa3DYiqktqYBV0+vGoMkPK57gOwrsndulsRME4fTjWTkWIhKyuaNLxtZ9fMwhuTtROUlEDI7yeaRQfbV1mPMtaJLTKfv5qDStHl/ho+69ZsoE5dmQpdgJPxAKmv27CNQn0ZgwUneNJsJNFvZkHeC4OR0Xs04SmxxJXU1Hpp6h5hT6ylox0bLEMamHnBx8DbWtB3oYkKJU2q2I+YzwrfEERybws74DKK27+cTZduR0XqM+veoO23h8g/3mPHOqjDZD5S4MztPRZWTbmc47rx4bFXNGM+3YW7uJM/ZROmFqzjar1HTdgV9VhGjZ3ZTk78dd+ctpoUF39lcArzv9VJV38LXlheo1m/Adq6dSs9FPKfsnHK3crC+i+abw4yP9JJ+rIxrxtW4zOvx9HzPnCw8CZS5OzGpdDifkIi1REaFY/VcpWRshoeNZdzzfME3bS2UjNzj0G0v+uwT7PpwE1t3BmE/68Y779W2LC8BTszMcCT1OGuj1xGYFI3usI1UewNGex1pyUexZpvIKzmD8aSLiL3JvGXeweubg3CcbWZeFv0ZSuoErty4SbC1kJejPmBtWCgbI/YTEqlTghMw2BwkGIrYtEvHlt0HeTvsY1ZtfYcVe2OJLa/kzt27aBdHOTaiD3jM1cJqp5sjBeXkuLsUa8fQ0EpOUzs551sp6biOyXNZadQlslwXKLvUi77axcryWjqu96gMURIVoKQBs5ytPJtaz3GzjQJ7BcVllUrXz5GVW0iZ0v0e5arZSiswHi8kOTOXjssdOJq7eObQabq6+/1AyQfsHhjhtT1HCIr4iKJTVZhsdgyWYixF5eSXOCitOKPOTQV2cvLtZOYW8EroXt5PKWRycsK/Ze1ya9Dphw+4MTikypcmvLJPXEWfAGhCq/lO03drwCcqsu/qyX5xWGyOpC7Aco1couCy+MR31DhZFpcqNsuyEUV/dv9li77CU77wDyW6d0gt7NgkAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;logo&quot;
        title=&quot;&quot;
        src=&quot;/static/ea46862528112c68de72e0abd86cc3f8/544ba/slack-logo.png&quot;
        srcset=&quot;/static/ea46862528112c68de72e0abd86cc3f8/544ba/slack-logo.png 248w&quot;
        sizes=&quot;(max-width: 248px) 100vw, 248px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;모집글-게시&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AA%A8%EC%A7%91%EA%B8%80-%EA%B2%8C%EC%8B%9C&quot; aria-label=&quot;모집글 게시 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;모집글 게시&lt;/h3&gt;
&lt;p&gt;그렇게 링크드인에 &lt;a href=&quot;https://www.linkedin.com/posts/donghoonsong_%EC%86%8C%EA%B7%9C%EB%AA%A8-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%B6%84%EB%93%A4-%EC%8A%AC%EB%9E%99%EC%9C%BC%EB%A1%9C-%EB%AA%A8%EC%97%AC%EC%9A%94-%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94-activity-7149015841496272896-O8Bd?utm_source=share&amp;#x26;utm_medium=member_desktop&quot;&gt;글&lt;/a&gt;을 올렸습니다.&lt;/p&gt;
&lt;p&gt;(별개로 초대 링크를 메시지로 보내는데 일촌이 아니면 보낼 수 없다는 걸 글을 올리고 나서 알아서 일촌이 아니신 분들에게는 열심히 신청하고 있습니다. 오히려 좋아 😅)&lt;/p&gt;
&lt;h2 id=&quot;1월-6일&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9B%94-6%EC%9D%BC&quot; aria-label=&quot;1월 6일 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1월 6일&lt;/h2&gt;
&lt;p&gt;자기소개를 아무도 쓰지 않아서 자기소개 템플릿을 만들고 첫 글을 올렸습니다. 아래와 같은 형식이었는데 생각해 보니 너무 딱딱한 거 같았습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;어떤 규모의 조직에서 일하시는지&lt;/li&gt;
&lt;li&gt;어떤 문제를 풀고 있는지&lt;/li&gt;
&lt;li&gt;어떤 문제를 풀어봤는지&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;자기소개는 조금 더 편하게 작성하도록 하는 것이 좋은 거 같다는 생각이 들었습니다. 그래서 아래와 같이 템플릿을 바꿨습니다.&lt;/p&gt;
&lt;ol&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;/ol&gt;
&lt;p&gt;제 첫 자기소개를 올리고 3일 후에 멤버분들께서 하나둘씩 글을 올리셔서 제일 활성화된 채널이 됐습니다. 글들의 4번과 5번 문항을 읽다 보니까 멤버분들의 니즈를 파악할 수 있어서 좋았습니다.&lt;/p&gt;
&lt;h2 id=&quot;1월-7일&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9B%94-7%EC%9D%BC&quot; aria-label=&quot;1월 7일 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1월 7일&lt;/h2&gt;
&lt;p&gt;그래도 14명 정도 모였습니다. 링크드인에 참여 신청 댓글 알람이 오면 기분이 좋은데 아무도 글을 쓰지 않아 신경이 쓰였습니다. 채널을 만들면 엄청 활발하게 이야기하실 줄 알았는데 그건 제 고정관념이었던 거 같습니다. 80%의 결과가 20%의 원인에 의해 발생한다는 파레토의 법칙이 있습니다. 이걸 여기 적용해 보면 80퍼센트의 글은 20퍼센트의 멤버들이 작성한다는 가설이 나오는데, 생각해 보니 제가 속해 있는 다른 채널도 항상 글이 엄청 활발하진 않다는 걸 깨달았습니다. 예외로 글또 채널이 있긴 한데(글또 사랑해요) 여기는 멤버분들이 엄청 활발하십니다 👍🏻. 아무래도 글또 채널에 주로 접속해 있다 보니까 제 채널도 그랬으면 좋겠다는 마음에 조바심이 컸던 거 같습니다. 그래서 20퍼센트의 멤버들만이라도 글을 쓰게 해보자는 방향으로 생각을 바꿨고 마음이 한결 편해졌습니다.&lt;/p&gt;
&lt;h2 id=&quot;1월-8일&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9B%94-8%EC%9D%BC&quot; aria-label=&quot;1월 8일 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1월 8일&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;아티클-공유해요&lt;/code&gt; 채널을 생성했습니다. 처음에는 조직규모에 따른 채널만 만들었는데 사람도 없는데 이런 채널에 처음 들어와서 말을 시작하기 어려울 거 같아서 장벽이 낮은 채널을 만들었습니다. 글을 하나 공유했는데 멤버분도 글을 공유해주셔서 신이 나서 댓글을 달았습니다. &lt;code class=&quot;language-text&quot;&gt;자유로운-이야기&lt;/code&gt; 채널에도 생각나는 대로 글을 작성했습니다. 화목순대국을 먹은 얘기를 할까 하다가 너무 갑분싸가 될 거 같아서 참았습니다.&lt;/p&gt;
&lt;h2 id=&quot;1월-9일&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9B%94-9%EC%9D%BC&quot; aria-label=&quot;1월 9일 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1월 9일&lt;/h2&gt;
&lt;p&gt;회사에서 유저 인터뷰를 하다가 &lt;code class=&quot;language-text&quot;&gt;“커뮤니티는 글 리젠률이 중요한 거 같다. 글이 어느 정도 올라와야 커뮤니티의 성격을 파악하고 그것에 맞게 글을 작성할 수 있다.”&lt;/code&gt;라는 말을 들었습니다. 이 말을 곰곰이 생각해 보니 제가 먼저 글을 많이 써봐야겠다는 생각이 들었습니다. 멤버분들은 제 글을 읽고 초대받긴 했지만 텅 빈 채널들을 보며 커뮤니티의 무드를 파악하긴 힘드리라 생각했습니다.&lt;/p&gt;
&lt;h2 id=&quot;1월-11일&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9B%94-11%EC%9D%BC&quot; aria-label=&quot;1월 11일 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1월 11일&lt;/h2&gt;
&lt;p&gt;자기소개 채널에 글이 엄청 많이 올라왔습니다! 그래서 굉장히 반가웠습니다. 다양한 조직, 다양한 환경에 멤버분들이 속해 있다는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;이 이후로는 멤버분들이 이런저런 글을 올려주셔서 커뮤니티 운영에 대한 걱정이 거의 사라져서 따로 기록하지 않았습니다. 그리고 자유게시판에 커피챗을 하거나 모임을 해도 좋겠다는 멤버분들이 있으셔서 커피챗 채널을 만들었습니다 ☕️.&lt;/p&gt;
&lt;h3 id=&quot;채널-데이터&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B1%84%EB%84%90-%EB%8D%B0%EC%9D%B4%ED%84%B0&quot; aria-label=&quot;채널 데이터 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;채널 데이터&lt;/h3&gt;
&lt;p&gt;슬랙의 분석 기능을 사용해 채널 데이터를 살펴봤습니다. 그래서 활성 멤버와 포스트한 멤버가 같이 우상향을 그리고 있어 기분이 좋습니다 ☺️&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABYlAAAWJQFJUiTwAAAA3klEQVR42p1RwY5DIQj0///wXbf3Ju1TEQTZgT7TzR42zWomkDgMMpTjOPz2dXMi8t57xjGGi4j/55TneTozp1hrLXMzS3xyFq4t87VWoqjqH+wXSSE+VC7wL4h3YW+MqaBVTN/qUThN84EmO4GYMQEx2HDSSNQf6AMTsviEVonvBtjEaXcDQlTmdAYI5CgKQb3sMFsZVaN+5fDp4R0e3mv1Jzo9an8V8vRG7LWTs2h2NjSIKcKGyBWN0hKIxgK35yV+cfF8It8PUTx1eicsCwuL5e238H17n7wQv7b8DUmkJ1ijGDW2AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;채널 데이터&quot;
        title=&quot;&quot;
        src=&quot;/static/f0464969c07d37f592eff532a0434f3b/c1b63/channel-data-graph.png&quot;
        srcset=&quot;/static/f0464969c07d37f592eff532a0434f3b/5a46d/channel-data-graph.png 300w,
/static/f0464969c07d37f592eff532a0434f3b/0a47e/channel-data-graph.png 600w,
/static/f0464969c07d37f592eff532a0434f3b/c1b63/channel-data-graph.png 1200w,
/static/f0464969c07d37f592eff532a0434f3b/d61c2/channel-data-graph.png 1800w,
/static/f0464969c07d37f592eff532a0434f3b/97a96/channel-data-graph.png 2400w,
/static/f0464969c07d37f592eff532a0434f3b/ddb69/channel-data-graph.png 2684w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAcVZrYsH/8QAGBABAQEBAQAAAAAAAAAAAAAAAgEDEgD/2gAIAQEAAQUCzBSgPThiOvNDPVufv//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAARASEiMf/aAAgBAQAGPwJClGYoZo6f/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFBYYH/2gAIAQEAAT8hNID5HqgHdRIeCyZJ4idMl6P/2gAMAwEAAgADAAAAEOM//8QAFhEBAQEAAAAAAAAAAAAAAAAAEQEQ/9oACAEDAQE/ECGf/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQAh/9oACAECAQE/EE2b/8QAHhABAQACAAcAAAAAAAAAAAAAAREAMSFBcYGhwdH/2gAIAQEAAT8QF9oqz4y/8In055QydjrhBA1OF3jsYYtLvtmnadH5n//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;채널 순항중&quot;
        title=&quot;&quot;
        src=&quot;/static/16a1a9255d9626a470f65d299060493e/c08c5/channel-going-well.jpg&quot;
        srcset=&quot;/static/16a1a9255d9626a470f65d299060493e/f93b5/channel-going-well.jpg 300w,
/static/16a1a9255d9626a470f65d299060493e/b4294/channel-going-well.jpg 600w,
/static/16a1a9255d9626a470f65d299060493e/c08c5/channel-going-well.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이렇게 슬랙으로 처음 커뮤니티를 개설해 운영해 본 초기 경험을 적어봤습니다. 채널 운영은 순항 중이라고 생각합니다. 멤버분들이 필요한 게 뭔지, 필요하지 않은 게 뭔지 귀 기울여서 적재적소에 제공해 좋은 커뮤니티를 한번 만들어보고 싶습니다. 현재는 45명의 멤버분들이 함께 하고 계십니다. 그리고 아직 초대하지 못한 분들도 계시는데요. 이 글을 마치며 마저 초대하러 가보겠습니다 🫡&lt;/p&gt;</content:encoded></item><item><title><![CDATA[2023년의 나는 어땠나]]></title><description><![CDATA[순식간에 지나가 버린 2023년에는 어떤 일들이 있었고 어떤 나였는지 회고하려고 한다. 방향성과 성과에 대한 고민을 많이 했던 한해였다. 업무 어떻게 제품에 더 임팩트 있게 기여할 수 있을까? 대표님이 11월부터 OKR…]]></description><link>https://donghoon-song.github.io/회고/2023년의-나는-어땠나/</link><guid isPermaLink="false">https://donghoon-song.github.io/회고/2023년의-나는-어땠나/</guid><pubDate>Sat, 06 Jan 2024 00:01:56 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1024px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEsklEQVR42h2OaWhTBwCAH8zBEDY2a4/Y1txJc7y8vKQvL3nJy9EkL/edNEmT5r76alpzNGnTpCmpZtW2zqlUaUSx29iQKROtIs7VgRtuf8YOEAZjf8eOH2P7IQPnZPD9+Ph+fcBhptyN4yKJGufyPRJRkcCiuCyAQC+FNMj/RxHH4JelYMB8CKQf4wslOs1kYVTuBXR6/5gEl2O60oTMYnQpjf6gwxpNxkLppH8qGEpMT0YjwWwmEAmbbR5M55wjVBOogoa5KWILkLMaNCLYLEO2sy6uJnxAEBDg9uT5nrO96aqtWuonndXV6MX3tY2NQ7B7QBbsJAIOJYq1dkXkWYADqoyEOaRX7eRdEm9pgKgeGBSXC9ELW81up3S6U2kvFivHUsmI703Ix3EtbJExj1qhm5xHzUnAIFNNuu2kSXplPmhd3eOUH4zI3JUSmcmm5uZmllv1eCadmy3oTRZOeEPe/mxnpRZUI1SW7CgDBgYobA2Dn1KP31sMnV//qFa7PuVM+P3pst0SSWSdM01Tdp4o1GxWbzG9ebq7v9dZiKshRzSvtoQBSGFqhSO9acODmnt+pr5Z6zxskbcb9vubhvu7qfu7ub1N896K+4NS5NPVt/e3rj3uHAtrkdjGTj4VA7g8qV6CkGroatGii5V75yu/3Kv8fKP+4sfZf/++/eL5o+c/lP/8nHz2benZE/LG9vL1hVRMBVkEYw4eA3AKmGLRuG1CdzmtcSRmfdlquVg/12r2Gks3O/m7W4Xd5mLpWGmtWW+1u/WF1pmVhUkD7lPL+nhqYFGPFFxW0qarOzCz0fbhhYY/XzJXT7738KEJV48M0Teu9VKXPsbDpczcSoIsxfIzGZPyTN4rRycAAUtAGzqqg0CHK9pdP/HbVzuZ4zXz0rnf//lLIZH2949+/8fT7t1H+niFyDQ1UyUD2bBbrH5czGPwAKF5Wt7oebfvGKpnN4+HLp2cV0WrU6evfv3dE0SmGuBr7uzf2rj3GE83TIm60lPwu7y3utHLZJgmngC4pljii1/LP72w9fZTSumVcjDn0Ndm09WZiJArYB5lTwcczXIhGfA24j69XLnmVFw61Q5hZrYQA1gc2FNsR9Z76cbaTtm/XvBcrHi6Oes0YSJUOo1CGyIsGZv2Zsu3Vgy8W3adWiLf+fKbXCLOYQoADYs1IxefcGPbCfxiFiUnBIQMEVG5iND4OuI7iHglsJt5eCyqldZDmt05RcOLx7XosmXcD/EAeJiZlsJhUKCnMSFEEw6HEQRjjXAw2EZBXYOoTQy7xXS4f5Tx1rgOeKWPPjBan7JnjHbRIBPQMagn9OIlrTCPcqay1eXOWXeEZLFEiMjeh7jegE180AkJtZhsHFZZuVSWXS7Juwi3DFXTqABOo7W1cEUFJkUMpm8hcecpYkm8enCQfQQcpqH9VBl3SHiIJbURRIHQ8WkcGMa4MsIejPPYYgCkUL18vpnNIZj0MUvesPEJbIpRBulC1HjwCPQaBaSDarZEFYChICikUhi4GKUjRNemZr/cHh9lKagcFY1lYjH1EKqEVX5MQYgh9jBnaJjfNwKO9tOVQrikBHNyUVwhccJiJyiICEH+EP0/JYKTSHOMjkQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;썸네일&quot;
        title=&quot;&quot;
        src=&quot;/static/f7b73722ce9a3a8776aeddb8d0645f64/2bef9/thumbnail.png&quot;
        srcset=&quot;/static/f7b73722ce9a3a8776aeddb8d0645f64/5a46d/thumbnail.png 300w,
/static/f7b73722ce9a3a8776aeddb8d0645f64/0a47e/thumbnail.png 600w,
/static/f7b73722ce9a3a8776aeddb8d0645f64/2bef9/thumbnail.png 1024w&quot;
        sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;순식간에 지나가 버린 2023년에는 어떤 일들이 있었고 어떤 나였는지 회고하려고 한다. 방향성과 성과에 대한 고민을 많이 했던 한해였다.&lt;/p&gt;
&lt;h2 id=&quot;업무&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%97%85%EB%AC%B4&quot; aria-label=&quot;업무 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;업무&lt;/h2&gt;
&lt;h3 id=&quot;어떻게-제품에-더-임팩트-있게-기여할-수-있을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%A0%9C%ED%92%88%EC%97%90-%EB%8D%94-%EC%9E%84%ED%8C%A9%ED%8A%B8-%EC%9E%88%EA%B2%8C-%EA%B8%B0%EC%97%AC%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;어떻게 제품에 더 임팩트 있게 기여할 수 있을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 제품에 더 임팩트 있게 기여할 수 있을까?&lt;/h3&gt;
&lt;p&gt;대표님이 11월부터 OKR을 달성하기 위해 스쿼드가 &lt;code class=&quot;language-text&quot;&gt;그로스 모드&lt;/code&gt;로 일하는 것을 제안해 주셨다. 기존에 진행했던 실험들은 정합성을 높이는 방향으로 설계하다 보니 시간이 많이 들었다. 대신 그로스 모드에서는 정합성을 높이는 대신 야구 방망이를 많이 휘두르라고 하셨다. 측정하는 방식을 잘 설계하고 많은 실험 아이디어를 내서 그 내용을 토대로 조건도 바꿔보고 메시지, 채널도 바꿔보면서 &lt;code class=&quot;language-text&quot;&gt;최대한 많이 실험&lt;/code&gt;해 보는 것이다. &lt;code class=&quot;language-text&quot;&gt;우리는 가설만 가지고 있을 뿐이고 판단은 고객에게 맡기면 된다.&lt;/code&gt;라는 말씀이 가장 인상적이었고 핵심을 찌르는 조언이었다. 그래서 나는 &lt;code class=&quot;language-text&quot;&gt;실험을 하나라도 더 하려면 무엇을 해야 할까?&lt;/code&gt;라는 질문에 리소스를 집중했다.&lt;/p&gt;
&lt;p&gt;내가 작업할 실험들은 UI/UX를 변경하는 방식이 대부분이었고 그러면 기획, 디자인 리소스가 들어간다. 그래서 디자이너 리소스가 가득 차면 자연스레 개발자는 그걸 기다릴 수밖에 없었다. 기존에는 시간이 좀 남으면 기술 공부를 하거나 백로그에 있는 작업을 조금씩 했는데 그로스 모드에서는 &lt;code class=&quot;language-text&quot;&gt;내가 먼저 작업할 수 있는 실험들&lt;/code&gt;을 찾았다. 이 실험들은&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;새로운 디자인 작업이 필요 없거나(간단한 문구 변경, 기존 컴포넌트를 재활용하는데 UX도 동일한 경우)&lt;/li&gt;
&lt;li&gt;디자인이 최소한으로 들어가는 실험들&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 있다.&lt;/p&gt;
&lt;p&gt;1의 경우 문구가 필요하면 팀 아이디에이션을 통해 해결했다. 기존 컴포넌트를 재활용하는 경우는 기존 실험에서 성공했던 UI/UX를 다른 퍼널에 맞게 변형해 적용해 보는 것이었다. 예를 들어, A-&gt;B 퍼널에서 native card 광고를 통한 실험의 전환율이 높았었다면 다른 퍼널에도 똑같이 적용해 보는 것이다. 2의 경우 세부 디자인을 뺀 대략적인 설계를 해놓고 디자이너님에게 도움을 받았다.&lt;/p&gt;
&lt;p&gt;11월 한 달은 실험 38개를 돌렸다. 그럼 업무일 동안 하루에 넉넉잡아 최소 1.7개는 돌렸다는 뜻이 된다. 엄청났다. 12월에는 실험 사이즈를 조금 크게 해서 주당 5개를 돌렸다. 그렇게 유저를 학습하고 학습점을 다음 실험에 반영하기를 반복했다.&lt;/p&gt;
&lt;p&gt;계속 비슷한 퍼널의 실험 아이디어를 떠올리다 보니 스쿼드 구성원들 전부 아이디어가 고갈되어서 고생했던 부분도 있었지만 너무 재미있던 두 달이었다.&lt;/p&gt;
&lt;h3 id=&quot;팀이-일을-더-잘할-수-있도록&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%80%EC%9D%B4-%EC%9D%BC%EC%9D%84-%EB%8D%94-%EC%9E%98%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8F%84%EB%A1%9D&quot; aria-label=&quot;팀이 일을 더 잘할 수 있도록 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;팀이 일을 더 잘할 수 있도록&lt;/h3&gt;
&lt;p&gt;많이 고민했다. 노션으로 프로젝트들을 관리하고 있었는데, 노션의 sprint 템플릿을 사용해 sprint 식으로 움직이려고 노력했다. 그래서 한 스프린트에 할당한 task 달성률을 통해 현재 스쿼드가 어떤 텐션으로 일하고 있는지 가늠해 보려고 했다. 또한 회고에 많이 신경 썼다. 작은 프로젝트라도 끝난 후에 회고를 통해 개선점을 서로 얘기한 부분이 도움이 많이 됐다. 실험이 끝나고 나서는 학습점을 한문장으로 정리하려고 노력했다. 한문장으로 만들려고 고민하는 부분에서 생각이 많이 정리됐다.&lt;/p&gt;
&lt;h2 id=&quot;글쓰기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EC%93%B0%EA%B8%B0&quot; aria-label=&quot;글쓰기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글쓰기&lt;/h2&gt;
&lt;p&gt;나는 글을 지지리도 쓰지 않는 사람이다. 글쓰기가 중요하다는 소리는 많이 들었지만 정말 실천하기 힘들었다. 자기 생각을 글로 잘 표현하는 것은 엄청난 역량이라는 생각이 들었고 열심히 훈련해야겠다는 생각이 들었다. 실무에서도 너무나 중요한 부분을 차지한다고 생각한다. 지금의 나는 글또 9기에서 활동하고 있고 이렇게 노력하고 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;글을 한 번에 술술 써내려 가는 것은 너무나 어렵기 때문에 여러 가지 주제를 펼쳐놓고 생각날 때마다 내용을 채우고 있다.&lt;/li&gt;
&lt;li&gt;사내 블로그에 글을 작성할 때는 팀원들의 피드백을 많이 받았는데 글을 잘 쓰시는 분들이 많아서 많이 고치면서 배웠다.&lt;/li&gt;
&lt;li&gt;많은 부분을 의도적으로 글로 남기려고 하고 있다. 무언가를 할 때 애초에 글을 쓸 생각으로 시작하면 도움이 많이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;계획-메모&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B3%84%ED%9A%8D-%EB%A9%94%EB%AA%A8&quot; aria-label=&quot;계획 메모 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;계획, 메모&lt;/h2&gt;
&lt;p&gt;MBTI 대문자 P인 나는 계획, 습관이랑은 먼 사람 같았다. 계획을 세워놔도 며칠 지나면 잘 안 보게 되고, 눈앞의 반짝이는 것에 매달렸다. 몇장 쓰다 만 다이어리도 엄청 많다. Todo app도 이것저것 써봤는데 이것도 몇일 후엔 잘 보지 않았다. 그런 내가 계획, 메모의 필요성을 느낀 부분은 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;내가 기억력이 별로 좋지 않다.
&lt;ul&gt;
&lt;li&gt;기억에 의존하는데 기억력이 좋지 않으니 다시 떠올릴 때 노력이 배로 든다.&lt;/li&gt;
&lt;li&gt;할 일 또는 하고 싶은 일이 많은데 “나중에 해야지” 하고 기억하려고 하니 뇌에 부하가 왔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;시간은 유한하다.
&lt;ul&gt;
&lt;li&gt;내가 하고 싶은 걸 전부 다 하면서 살 순 없다.&lt;/li&gt;
&lt;li&gt;그중에 중요한 것부터 해야 한다.&lt;/li&gt;
&lt;li&gt;그러기 위해선 미리 기준을 세우고 라벨을 붙여놔야 한다.&lt;/li&gt;
&lt;li&gt;그렇지 않으면 어떤 일을 시작할 때마다 우선순위를 다시 고민해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Todo app에 기억을 위임하고 있다. 할 일이 생각하면 바로 Todo app에 마감 기한까지 찍어서 추가하고 있다. 그러면 그 일에 대한 생각을 그만하고 더 중요한 것에 집중할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;시간-블록&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%9C%EA%B0%84-%EB%B8%94%EB%A1%9D&quot; aria-label=&quot;시간 블록 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;시간 블록&lt;/h3&gt;
&lt;p&gt;캘린더에 시간 블록을 추가한다. 꼭 이 시간에 이걸 해야 하는 건 아니지만 이렇게 가이드라인을 추가해 놓는 것만으로도 내가 정신없을 때 뭘 해야 할지 고민하지 않고 바로 실행할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 19.333333333333332%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAnElEQVR42mNwDcp3Ca2y8i609imy9ikGIe8iayAXHyqw8S0xdYxlCEntD8la6BE/zTNhOhhN806e5Zu20Cd1AU6UMt8vY6lTSANDWGJbcOo0j+gez5hez5ger9h+15BaK5ckS+dkS5cUHCjZyjXd1CaEwTW60zt1rmv8NNf46a5x01wT5zoHFbk6Wrg52znbWznammNFTnYWlmZGACuyUqQDhys1AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;캘린더에 시간 블록을 추가한 모습&quot;
        title=&quot;&quot;
        src=&quot;/static/f44cd3d2b7a8dd053dc3fd2fa0b14e7e/c1b63/calendar-view.png&quot;
        srcset=&quot;/static/f44cd3d2b7a8dd053dc3fd2fa0b14e7e/5a46d/calendar-view.png 300w,
/static/f44cd3d2b7a8dd053dc3fd2fa0b14e7e/0a47e/calendar-view.png 600w,
/static/f44cd3d2b7a8dd053dc3fd2fa0b14e7e/c1b63/calendar-view.png 1200w,
/static/f44cd3d2b7a8dd053dc3fd2fa0b14e7e/d61c2/calendar-view.png 1800w,
/static/f44cd3d2b7a8dd053dc3fd2fa0b14e7e/780d5/calendar-view.png 2306w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;리추얼&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%EC%B6%94%EC%96%BC&quot; aria-label=&quot;리추얼 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리추얼&lt;/h3&gt;
&lt;p&gt;생산성 관련 강의를 참고해 리추얼을 만들고 계속 수정해 나가고 있다. 반복되는 작업을 습관으로 만들면 뇌가 그 일을 하는데 쓰는 에너지가 줄어든다고 해서 해보고 있다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAyElEQVR42pWR627DIAxGeZWYq8OaQIOhyqqypp32/m9Up1Wm/WnLDhJCgs8+gDhm83Ot5/Olnk7LsszzXGs1xgCAfI5Sis8Ihx+8khL+bsg2xLQPOSeQVv4fEWOgOIFcPX9pDYMCIOnQOh4bjebCOoNHRN8jYt+vs3NOa90WtnbOheWHYYgxjuPoveeX7LrufZi7fV++DoeSc+F/SilxCdbWd177C5YsFDNNDzhMRKUUohRC4NIv3k9o4/pd2sVP9CO3URstd74Bi1JbDiajw/EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ticktick 앱에 리추얼을 만든 모습&quot;
        title=&quot;&quot;
        src=&quot;/static/f111d8ba60eb18aea09beed64b7a6568/c1b63/ticktick.png&quot;
        srcset=&quot;/static/f111d8ba60eb18aea09beed64b7a6568/5a46d/ticktick.png 300w,
/static/f111d8ba60eb18aea09beed64b7a6568/0a47e/ticktick.png 600w,
/static/f111d8ba60eb18aea09beed64b7a6568/c1b63/ticktick.png 1200w,
/static/f111d8ba60eb18aea09beed64b7a6568/d0c2f/ticktick.png 1362w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;성취&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%B1%EC%B7%A8&quot; aria-label=&quot;성취 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;성취&lt;/h2&gt;
&lt;h3 id=&quot;헬스&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%97%AC%EC%8A%A4&quot; aria-label=&quot;헬스 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;헬스&lt;/h3&gt;
&lt;p&gt;몇 달 동안 헬스를 했다. 식단도 같이 했다. 하는 동안 몸의 변화도 조금 느껴졌다. 더 건강해졌을까? 잘 모르겠다. 소화를 잘 못하는 내가 단백질 양을 채우려고 쉴 틈 없이 닭가슴살을 먹었는데 평소에 활동량이 부족하다 보니 버겁긴 했다. 운 좋게 공용으로 쓸 수 있는 인바디 측정기가 있어서 주기적으로 측정했는데 체지방량과 근육량의 변화에 일희일비하며 살았던 시기가 있었다. 😅 웃기게도 헬스장이 내부 보수공사에 들어가면서 쉬게 됐는데 공사가 끝났는데도 아직도 쉬고 있다. 겨울은 게을러지는 계절..&lt;/p&gt;
&lt;h3 id=&quot;밴드-공연&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%B4%EB%93%9C-%EA%B3%B5%EC%97%B0&quot; aria-label=&quot;밴드 공연 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;밴드 공연&lt;/h3&gt;
&lt;p&gt;일렉기타를 배웠다. 한달동안 레슨받고 한달동안 합주해서 공연까지 하느라고 짧은 기간동안 엄청나게 연습했고 실력이 단기간에 늘었다. 이 시기에는 퇴근하고 정말 기타만 쳤다. 처음에는 C코드도 잡지 못했던 내가 세컨 기타로 4곡이나 공연하기까지의 레벨이 오른 경험이 정말 뜻깊었다. 공연이 끝나고 연습이 부족해서 아쉬워하고 싶지 않아서 악보도 다 외우고, 손에 익을 때까지 열심히 연습한 후에 무대에 올라 만족스러웠다.&lt;/p&gt;
&lt;h2 id=&quot;2024년의-나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2024%EB%85%84%EC%9D%98-%EB%82%98&quot; aria-label=&quot;2024년의 나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2024년의 나&lt;/h2&gt;
&lt;h3 id=&quot;기술-공부&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EC%88%A0-%EA%B3%B5%EB%B6%80&quot; aria-label=&quot;기술 공부 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기술 공부&lt;/h3&gt;
&lt;p&gt;올해는 기술 공부에 많은 시간을 투자하려고 한다. 작년에 시간을 많이 투자하지 못한 게 아쉽다. 기술 서적도 많이 읽고 블로그에도 많이 남겨보려고 한다.&lt;/p&gt;
&lt;h3 id=&quot;사이드-프로젝트&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8&quot; aria-label=&quot;사이드 프로젝트 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;사이드 프로젝트&lt;/h3&gt;
&lt;p&gt;요즘에 사이드 프로젝트 관련 글을 많이 읽어서 더 노력해야겠다는 생각이 들었다. 내가 생각하는 아이디어를 빠르게 구현할 수 있는 모습이 내 목표다. 나만의 보일러 플레이트, 손에 익은 기술스택을 갖고 싶다.&lt;/p&gt;
&lt;h3 id=&quot;글쓰기-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EC%93%B0%EA%B8%B0-1&quot; aria-label=&quot;글쓰기 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글쓰기&lt;/h3&gt;
&lt;p&gt;계속 글을 써서 습관으로 만들고 싶다. 내 생각을 조리있게 표현하는 것이 목표다. 블로그 글, 문서를 더 잘 쓰고싶다.&lt;/p&gt;
&lt;h3 id=&quot;회고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%9A%8C%EA%B3%A0&quot; aria-label=&quot;회고 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;회고&lt;/h3&gt;
&lt;p&gt;올해는 달마다 회고글을 작성하고 싶다. 그러면 저절로 한 해 회고가 되지 않을까. 한번에 회고하고 작성하려니까 너무 어렵다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[초보 개발자도 오픈소스에 기여할 수 있다 - Notion Avatar Maker 한국어 버전 개발기]]></title><description><![CDATA[오픈소스는 어렵다 개발자의 성장에 대한 글을 보면 자주 강조되는 부분이 오픈소스 기여다. 성장하고 싶었던 나도 오픈소스에 기여하고 싶었다. 하지만 우리가 사용하는 오픈소스 React, Vue.js…]]></description><link>https://donghoon-song.github.io/opensource/초보-개발자도-오픈소스에-기여할-수-있다-notion-avatar-maker-한국어-버전-개발기/</link><guid isPermaLink="false">https://donghoon-song.github.io/opensource/초보-개발자도-오픈소스에-기여할-수-있다-notion-avatar-maker-한국어-버전-개발기/</guid><pubDate>Sun, 10 Dec 2023 15:13:06 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1024px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAXAQADAQAAAAAAAAAAAAAAAAABAgMA/9oADAMBAAIQAxAAAAHr3wzy9KFJ1gIuCv8A/8QAGhAAAwEBAQEAAAAAAAAAAAAAAAECERIDE//aAAgBAQABBQKfTa2RMbU1NojGuFvzSJXJ/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERAiH/2gAIAQMBAT8BWeDlKxn/xAAYEQADAQEAAAAAAAAAAAAAAAAAAQIREP/aAAgBAgEBPwGqxoRnP//EABwQAAMAAQUAAAAAAAAAAAAAAAABIUEQESIxof/aAAgBAQAGPwJplO/B5LdkcTOkP//EABwQAQEBAAIDAQAAAAAAAAAAAAERACExQVGRsf/aAAgBAQABPyGQSHrIJy+6wsv4wv2ct5hp153JxLgqGjF0vPeiiZ3v/9oADAMBAAIAAwAAABAEAL//xAAYEQEBAQEBAAAAAAAAAAAAAAABABEhMf/aAAgBAwEBPxDRIRCLt7JXW//EABkRAQADAQEAAAAAAAAAAAAAAAEAESExof/aAAgBAgEBPxBBbT5LJrKVyAT/xAAgEAEAAgICAQUAAAAAAAAAAAABESEAMUFhsVFxgZGh/9oACAEBAAE/EIqNJYm439YDAywWmcJgS0dGu8a6g0nLKetnsZISBSKca5ckJ8w1p5MGFSQzqd+cmsXFV/nXnAc5LaG34z//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;코딩하고 있는 오리&quot;
        title=&quot;&quot;
        src=&quot;/static/d49a1fae19d23eaded18b698bc556672/72e01/notion-avatar-maker-story-thumbnail.jpg&quot;
        srcset=&quot;/static/d49a1fae19d23eaded18b698bc556672/f93b5/notion-avatar-maker-story-thumbnail.jpg 300w,
/static/d49a1fae19d23eaded18b698bc556672/b4294/notion-avatar-maker-story-thumbnail.jpg 600w,
/static/d49a1fae19d23eaded18b698bc556672/72e01/notion-avatar-maker-story-thumbnail.jpg 1024w&quot;
        sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;오픈소스는-어렵다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4%EB%8A%94-%EC%96%B4%EB%A0%B5%EB%8B%A4&quot; aria-label=&quot;오픈소스는 어렵다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;오픈소스는 어렵다&lt;/h2&gt;
&lt;p&gt;개발자의 성장에 대한 글을 보면 자주 강조되는 부분이 오픈소스 기여다. 성장하고 싶었던 나도 오픈소스에 기여하고 싶었다. 하지만 우리가 사용하는 오픈소스 &lt;a href=&quot;https://github.com/facebook/react&quot;&gt;React&lt;/a&gt;, &lt;a href=&quot;https://github.com/vuejs/core&quot;&gt;Vue.js&lt;/a&gt;등의 이슈를 찾아 해결해보려고 해도 이해하기도 어렵고 어떻게 고칠 수 있는지 감도 잘 안 오지 않았다. 그래도 굴하지 않고 코드를 보고 이해해 보려고 해도 역시나 어려웠다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaElEQVR42lVSa3OCMBDke6sIgZCQBySENyiitXY6/f9/qwu0Os4szJK729u74PWfl+nrXndTO85Vd2r6hXTjXDYjPuvuBOLqoWqPONS2FtoFEXc/Q9pYr7h3Zu4iKmmaUa5jpijPokQhI4hTvA+Ehf9kH9ANPkn2IfWUKqQqi3pgwsRch7E4EB5E6QsIJ7EIqSCJ2AXxQ8LzCbNVP9++XTOqzGW2VqaSeQl7Ki9BZOa0qWKmYceWA2V6d/ir9979CDHMXPcTEzmThgPKMJkLXaSAsiJzcA5Tpuilrp6dUYwO4/TRDmeUITVKJLSBtz1B9AGcYy4QP0yApRhJ2BMWC/THy3C6DhAaZwghvKkAqCFUYpZH25fOuBXY5sDqHByt4JZgT1Rg2+BcWfCl7Tq2B29Y0jYwwigAkLGYZAp7Wi9PbyrYJXQjpsJVzsNjXDueb/gBtpm3d6rtk68E6pltcKlle8xdy0T+C+p6Qb0Woxc+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;해결되지 않은 React issue&quot;
        title=&quot;&quot;
        src=&quot;/static/a1a2caca98e78d9b537a7d202cb72ebf/c1b63/notion-avatar-maker-story-thumbnail-1.png&quot;
        srcset=&quot;/static/a1a2caca98e78d9b537a7d202cb72ebf/5a46d/notion-avatar-maker-story-thumbnail-1.png 300w,
/static/a1a2caca98e78d9b537a7d202cb72ebf/0a47e/notion-avatar-maker-story-thumbnail-1.png 600w,
/static/a1a2caca98e78d9b537a7d202cb72ebf/c1b63/notion-avatar-maker-story-thumbnail-1.png 1200w,
/static/a1a2caca98e78d9b537a7d202cb72ebf/d61c2/notion-avatar-maker-story-thumbnail-1.png 1800w,
/static/a1a2caca98e78d9b537a7d202cb72ebf/97a96/notion-avatar-maker-story-thumbnail-1.png 2400w,
/static/a1a2caca98e78d9b537a7d202cb72ebf/70d4c/notion-avatar-maker-story-thumbnail-1.png 2548w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;그런 나도 엄청나진 않지만 작게나마 오픈소스에 기여하면서 살고 있는데 &lt;code class=&quot;language-text&quot;&gt;기여 기회를 찾는 나만의 꿀팁&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;실제로 기여했던 프로세스&lt;/code&gt;를 공유하고자 한다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1116px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 89.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAABYlAAAWJQFJUiTwAAADn0lEQVR42oWU229UVRTGj+j0MvfLOWefM+fWuTIzpzMOHaYM9GIbG5v4IppyMWZMNMTLA1bRiA8NDyQEK+GWPhjDAwkJL+WitQiP/glGjT40oRHhgYjYIC0I0+Zz7T1jY23Vk6zs7L1Ofnutb+21JK8/inS5H/UDR1F/+yBUI4FAWIXhpGF2ZcFoH5bjiCjGqoViOoJRbY3xM26SbCYxcf5rXJlbwtS17/DiO0cQkk2o8S74fAFIUgdZO1lbyzzo8EUEJBBha4yfSflKBc+9sgcvjNXxfP1NDLw6DndrPw4dOYajJ47j8MeTODw5icljJ/AJ2clTU6j1DaHNG6aI1kMlJ5NFdXgQA/2j2L1rL3LVXlRqA7j1y238ev933P/jIRrLy1heWcEKGf9e2/cWpKe8Qop1QD/p5aSyyOR7sKVvGIphoViu4vrNG5if/xlLi0tYJHv06DEeLj9Gg4Cv/xfQSuZQeLqKUk8Nup2BpzOMVNbF+ekLuDRzBRcuf4GZ2a8wPX0RJ09P4dPPzqB/8Fl4RMr6xsBSz3ZkC2Wkc0Wqool8sQfffvMD5ud+wo/fz+HB4iLOnj1HBZGwqc2PTn9sw6KsAotbtqFUqaFc7YNGVef7OzeuA/fuonHnttBtZvYqnmwPIKqa/woTQFmzoVsp2Mk8vb2MOCwR8OYt0u/BEn5bWBDAi5c+xxMe/4a6rQHqdhpuuVdA+aPl2nSTpgsL9wSo0WiI9UvSUfL4/h+oGTzFGrqyJeqKLuoSRUS6f/97OPD+hxh/9wMc/GgCL429jM5AbG2XRLR1HSMlcgX0DgyiVCjASXYjoKbhaNRi1JIdHi+8bT500hr0hqDRQ2ZRBjWi0qrSXhV7RuealoCm2pCGxkYwMbEHh/bV8cb4cVSGd9IPCpxcBUbChaI7CPH+baXKI2ROAVYiA8exEGgVyM99PEK3bxTujhHRn2ElDoUxaLTKBIqoltDsn0MgqnGfTf9bqxJwcJgDZdOGbGUQjJniJl+YQVebUTDHFUOCT5+/RA/LOnQnC8UuQLM3I0IX+lt+AbQSm6n18iI1Ne4IJ1MoCmYhxigK2WhOkr8BFd0mPxllEJKN1uiKN4Em3fbM0ChSeVc4ONDQTMRTRcSsPM3HJKVnIkIXcC2DVADFzJDPpczI7G4wKy0uCEX5OzRS2LVzL0rVrfAGZQIy2ExHgqSIM0PANYqYyRpUXmVaHRoghvAZ0JVm5ZVos+J/AvW1TjSZmjrXAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;내 Github 프로필에 있는 내가 기여한 내용&quot;
        title=&quot;&quot;
        src=&quot;/static/3d24b65adec401455e9935f25e9f084e/ea64c/notion-avatar-maker-story-thumbnail-2.png&quot;
        srcset=&quot;/static/3d24b65adec401455e9935f25e9f084e/5a46d/notion-avatar-maker-story-thumbnail-2.png 300w,
/static/3d24b65adec401455e9935f25e9f084e/0a47e/notion-avatar-maker-story-thumbnail-2.png 600w,
/static/3d24b65adec401455e9935f25e9f084e/ea64c/notion-avatar-maker-story-thumbnail-2.png 1116w&quot;
        sizes=&quot;(max-width: 1116px) 100vw, 1116px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;기회-잡기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%ED%9A%8C-%EC%9E%A1%EA%B8%B0&quot; aria-label=&quot;기회 잡기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기회 잡기&lt;/h2&gt;
&lt;p&gt;나는 기여하려고 기회를 찾기 보다는 오는 기회를 잡는 편이다. 예를 들어, 공식문서를 보는데 스타일이 깨져서 보인 경우, 좋은 자료가 담긴 repository가 있는데 한국어 버전이 없는 경우, 공식 문서에 잘못된 명령어가 적혀 있는 걸 찾은 경우, 흥미로운 사이트를 찾았는데 한국어 버전이 없는 경우 등이다. 이번에 소개할 예는 흥미로운 사이트를 찾았는데 한국어 버전이 없는 경우이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://notion-avatar.vercel.app/&quot;&gt;Notion Avatar Maker&lt;/a&gt;라는 사이트를 구독중인 뉴스레터에서 발견했다. 노션 스타일의 아바타를 직접 만들 수 있는 사이트이다. 요소들을 클릭해서 나만의 아바타를 만들 수 있고 노션 스타일로 만들 수 있다는 게 매력적이었다. 가지고 놀다가 이 사이트의 한국어 버전이 없다는 것을 깨닫고 기여해보고 싶다는 생각이 들었다. 그리고 내가 기여할 수 있는지 체크했다. 일단 이슈나 PR에 한국어 지원 관련 내용은 없어서 다른 사람이 작업 중이진 않은 것 같았다. 그 다음으로는 어떻게 작업하면 될지 살펴봤다.&lt;/p&gt;
&lt;p&gt;일단 README 파일에 I18n로 영어와 중국어를 지원한다고 적혀 있었다. 그래서 파일을 찾아보니 &lt;code class=&quot;language-text&quot;&gt;public/locales&lt;/code&gt; 디렉토리 내부에 관련 파일들이 있었다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 55.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABA0lEQVR42qWTXU/CMBSGd6tICxsb7HujH+IEwcBAUSIhJiYm/v+f83raRKPxhrqL0za9eHqe86ZeMZ3h+PqO9e6A9vEFu+cTtvsjTm8fSEuFi34A5k/QH47PKi8Y5yhFg7TSyOtrVLKBeaTWc8S5cIJZYJRUkLMFVLNERtCkkLYmBMvogWGY4moQnQ8cjBJk6h7J9I4uIqt4yUa2zNkFZoE95oMXa/CyBSPgl6LZXXUt0MxtQ2FEaY0eD50Bf4DMjyG0pESFnZ0JyVXztzKPoKVE+3CgYFbgQdytQ9ONUnPcLrcIKfGu2p5Z8lpj1e6hqcMuut9ArQT9lCfcLDb/SvYn8BNtGRSsEqOaiwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Notion Avatar Maker README파일&quot;
        title=&quot;&quot;
        src=&quot;/static/c0b3f8bb6448010ca11ae7b7cd228712/c1b63/notion-avatar-maker-story-thumbnail-3.png&quot;
        srcset=&quot;/static/c0b3f8bb6448010ca11ae7b7cd228712/5a46d/notion-avatar-maker-story-thumbnail-3.png 300w,
/static/c0b3f8bb6448010ca11ae7b7cd228712/0a47e/notion-avatar-maker-story-thumbnail-3.png 600w,
/static/c0b3f8bb6448010ca11ae7b7cd228712/c1b63/notion-avatar-maker-story-thumbnail-3.png 1200w,
/static/c0b3f8bb6448010ca11ae7b7cd228712/56e36/notion-avatar-maker-story-thumbnail-3.png 1750w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;다음으로는 repository를 clone해서 &lt;code class=&quot;language-text&quot;&gt;public/locales/zh/common.json&lt;/code&gt; 파일의 변경내역을 살폈다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAACSUlEQVR42o2T6XLaMBSFeZGGgHd5lW15kfFuMCEk6bTT93+U0ysRGGb6pz/OSL62Pp97JG1EKcGzAkHEEWol8MMEnh/BDxK4XogoSeF4AUzLhWl7MGh0WQgWxLAcpmvqfSYqbORhgChqhDFHwnNwnmq47frw7FDXGU9g0sKd4WD/rd3exvbVxOvOumlvIYhTbOqmg3LpskA7Y+RKAU3Hg2v4iOijrWHiZWsQ4Ek7Q9detnutHy87bWKT5iVK2YFFGVjIqdVbKwpomR48anlnWd8Q86HXu/Y3d6qm2tYOm/6EbrogrzqUdYN7riG5Cyk/lU3CBXha6LoycX+vunrWZpxXDNOCaTmhHRcc13eM8wlCUK4iR3WZIa8L4lWCDQL+UDzEenFTlyOYS0SVwGaYjjh0k4bU7QD1g/m4oqYYvJwjO/cQXyOCaw3vWGi533o8zwLhlbrqaJfbfsKBNBJYtiMGAqufiELCyxLkZzoFnyPYqYQ3E2D5V+4kEFwkkpaA3TBDQZXDA83n0xuK6gDmx9qhIGD1MSN4q/8P2PYzFFQBZUvg5YyOskw4ZZSnyNcexccEfy31QtWeBj/JHQn4dnfYj+hJI21MozKkzRnnBWmagwmO4jJB/jwi+mwIWmunbK10BDdVlGNJGTY3oByuaJdf6E+/IacvDOc/kOMXMvkOP2/giBhukcAuIthlDLuiMypCGBldxfw26jnVWELHhmcVuOhILeLsgLToECQVQk6bEqTY07WybQbXDeDYvh7vsizvMXccX9/9vyern4W+HN/nAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;common.json 변경 내역&quot;
        title=&quot;&quot;
        src=&quot;/static/9773e6f77536e055904fcfd9ec38ee2d/c1b63/notion-avatar-maker-story-thumbnail-4.png&quot;
        srcset=&quot;/static/9773e6f77536e055904fcfd9ec38ee2d/5a46d/notion-avatar-maker-story-thumbnail-4.png 300w,
/static/9773e6f77536e055904fcfd9ec38ee2d/0a47e/notion-avatar-maker-story-thumbnail-4.png 600w,
/static/9773e6f77536e055904fcfd9ec38ee2d/c1b63/notion-avatar-maker-story-thumbnail-4.png 1200w,
/static/9773e6f77536e055904fcfd9ec38ee2d/d61c2/notion-avatar-maker-story-thumbnail-4.png 1800w,
/static/9773e6f77536e055904fcfd9ec38ee2d/97a96/notion-avatar-maker-story-thumbnail-4.png 2400w,
/static/9773e6f77536e055904fcfd9ec38ee2d/efe17/notion-avatar-maker-story-thumbnail-4.png 2860w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Mayandev/notion-avatar/commit/dd2e414bc9163af943c289e4f798fe755fbb051c&quot;&gt;커밋 전체 내역&lt;/a&gt;을 보니까 아래와 같은 작업 내역들이 있었는데, 초기 작업이다 보니까 i18n 라이브러리를 설치하고 세팅하는 부분들이 있다. 여기서 나는 &lt;code class=&quot;language-text&quot;&gt;next-i18next.config.js&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;locales/ko/common.json&lt;/code&gt;을 추가하면 될 것 같았다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABtklEQVR42m2SWXLbMBBEeYFIFjfsC0mAqyzblZQ/cv97dVpLOWGsj1cggcFgumcK02XEvMH3M0JaYbsJJo441npPqXCs1P2ba9k6xs7QfoQhyiW0KqJQ0wUuX2D7Vwi/oNIZNWnsdMdMEHGCHVboboH0GSIwJoyoXP6iDhNO14TSMsAOaPUAYYhNd27f3Jc9wseC4fc7/Ocn3PsKuXSo5oj6X5aIMjgUrY64Im50j/WB4ZkI8K8j4iWhydybSHaokkOd/V9Gj5M3lDws9O8MHRc0Oj3HJChWq1m5piLpRtozobXj7exKy/1KBhSm26DCfNusKfv/ZLUcoJYZ7sK4eWV1TDTOlL1BjBOqvr8zDDhZj0IzWZx/0a+Ml0cHd7C7J6VhxwXd+SdEzwkQGj8agUMr9zQSRePYenZYxTMrTDiJSLo9bYeSzRF+RetWqhm/xVUq4aVlhTa/IcxvHIntPjIMfkZD3xp6dn30WZyKvK86Vug7mHXmy3yhNpSp91BypdjFEG4jo4aZFTkcG9rR6C8O/D/UCkWpLFRKkBzMb/6RQylZkUNpDcyW6eVG+ZaXBRPJPbXEH30GI0fluOmNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Untitled&quot;
        title=&quot;&quot;
        src=&quot;/static/2dd7b4041c4112b085f07432e139f78c/c1b63/notion-avatar-maker-story-thumbnail-5.png&quot;
        srcset=&quot;/static/2dd7b4041c4112b085f07432e139f78c/5a46d/notion-avatar-maker-story-thumbnail-5.png 300w,
/static/2dd7b4041c4112b085f07432e139f78c/0a47e/notion-avatar-maker-story-thumbnail-5.png 600w,
/static/2dd7b4041c4112b085f07432e139f78c/c1b63/notion-avatar-maker-story-thumbnail-5.png 1200w,
/static/2dd7b4041c4112b085f07432e139f78c/d61c2/notion-avatar-maker-story-thumbnail-5.png 1800w,
/static/2dd7b4041c4112b085f07432e139f78c/97a96/notion-avatar-maker-story-thumbnail-5.png 2400w,
/static/2dd7b4041c4112b085f07432e139f78c/30f63/notion-avatar-maker-story-thumbnail-5.png 2816w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이제 내가 작업할 내용이 어느정도 보였기 때문에 로컬 서버를 실행했다. &lt;code class=&quot;language-text&quot;&gt;public/locales/ko/common.json&lt;/code&gt;을 생성하고, &lt;code class=&quot;language-text&quot;&gt;next-i18next.config.js&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;locale&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;ko&lt;/code&gt;를 추가했다. 작업 후 실행해보니 아주 잘 적용되는 것을 볼 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABkElEQVR42nVSyU4CQRAl4YP4EG74D/If6l3+gJN6Ue9gNJGz0QSjUQj7sA37MmvPzLOqmAFhoJNKd1dVv3r1uhKNeg2a1sZqOQcCL2a+54oFvjoaFz+tj/c3JJNJJMgTBuMPAt6jtc07YvDhKRd3tzcMeKrqJimbPcdZJoPZdBLinmLqwbLM44CecuRxsVBAKpVCOp3G48O9+CR2gimDJv7TpoPsyrXl8dXlBfL5PMrlMnK5a/GxnjsQf08KZp+IkBnEdSw4tgU/FLpYLODl+QnV6i9Kpdddy1SU9XXpjbdXgBlS0LFNaJ0WWs2G7MZ6Cctcw6ECvqegSEtPKZkE2zIk3zBW0NotTCdj6SzSVgBNDhJQv6eRddFuNaAP+3Lv0kiN9AG6nTYqlR8MBj3odB9SfEjnxXx6nOFkrKPZqEkSM1SuIz4GZB+zY994pFMn9W2x2XS80X8LGA4vs1wuZlivFqSlLbqypjz431+folfA3ZAUizCPizCZGODhL0c/zTafTaR9HhfbNg7ygtjA/wF4N0W33TNl1wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Untitled&quot;
        title=&quot;&quot;
        src=&quot;/static/ab216c48de5f1d13b999d92e576b321f/c1b63/notion-avatar-maker-story-thumbnail-6.png&quot;
        srcset=&quot;/static/ab216c48de5f1d13b999d92e576b321f/5a46d/notion-avatar-maker-story-thumbnail-6.png 300w,
/static/ab216c48de5f1d13b999d92e576b321f/0a47e/notion-avatar-maker-story-thumbnail-6.png 600w,
/static/ab216c48de5f1d13b999d92e576b321f/c1b63/notion-avatar-maker-story-thumbnail-6.png 1200w,
/static/ab216c48de5f1d13b999d92e576b321f/d61c2/notion-avatar-maker-story-thumbnail-6.png 1800w,
/static/ab216c48de5f1d13b999d92e576b321f/97a96/notion-avatar-maker-story-thumbnail-6.png 2400w,
/static/ab216c48de5f1d13b999d92e576b321f/196e0/notion-avatar-maker-story-thumbnail-6.png 2626w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;빠진 부분이 없는지 이것저것 기능을 테스트해보는 데 걸리는 부분이 있었다. 영어와 한국어가 어순이 다르기 때문에 “눈 선택”이라고 나와야 자연스러운 부분이 “선택 눈”이라고 나오고 있었다. 그래서 이 부분을 코드에서 찾아봤다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABfklEQVR42o2TW07CUBCGux19E6RAKeUmkdhGEMplF7gftkFXgNgl4KMChgdQKff7rzPJqdX2gUn+pHNm5ps5c1JJlmXE4zEkkyrS6RRLVRU+U5R4oFIpzc0lZbMZhEJXkCQJkjdAouRi8R7VqolKpexTufzAAC80k0mzf3l54QdqmgbLsuA4DubzuavZbIbVaoXRaIRarYpEQmHQ//oAYBKdTgdkm80Gh8MB6/Wav8kI3GjUzwNSAu3Stp9d4PF45GmXyyWfOc70PCDtgETAbrfLxYvFAvv9HpPJhCcjm05/gaLOB6Rr0qvGYlHIcuQH+MTFtLPdbseTbrdb98r1eo1z6cVVNfFnUhdIHSlIibZtczFdV9jpdGJ/PB7DNE1uTPmkwAmpWzQqIxK5Rrtt4ePzC69vffQHQwyG7+j1XtBqtdBsPqJUKiEcDnFzH9A7LoFpJ4XCLQzDgG7oyOdvkMtloet3fE6+d+fiMYUkEfCKHkb8FTQ1SfgUC6oR+gafou9jiPXvrQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Untitled&quot;
        title=&quot;&quot;
        src=&quot;/static/0d3c1e939849fbd7b6622e2f5d510857/c1b63/notion-avatar-maker-story-thumbnail-7.png&quot;
        srcset=&quot;/static/0d3c1e939849fbd7b6622e2f5d510857/5a46d/notion-avatar-maker-story-thumbnail-7.png 300w,
/static/0d3c1e939849fbd7b6622e2f5d510857/0a47e/notion-avatar-maker-story-thumbnail-7.png 600w,
/static/0d3c1e939849fbd7b6622e2f5d510857/c1b63/notion-avatar-maker-story-thumbnail-7.png 1200w,
/static/0d3c1e939849fbd7b6622e2f5d510857/d61c2/notion-avatar-maker-story-thumbnail-7.png 1800w,
/static/0d3c1e939849fbd7b6622e2f5d510857/97a96/notion-avatar-maker-story-thumbnail-7.png 2400w,
/static/0d3c1e939849fbd7b6622e2f5d510857/196e0/notion-avatar-maker-story-thumbnail-7.png 2626w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이 컴포넌트는 AvatarPicker였고 어순을 바꾸기 위해 한국어일 때 분기하는 방법을 찾아봤다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;useTranslation&lt;/code&gt; hook에서 &lt;code class=&quot;language-text&quot;&gt;i18n.language&lt;/code&gt;에 현재 언어가 무엇인지 담겨 있었다. 그래서 아래와 같이 작성해보려고 했는데 한국어 한정 코드인 거 같아서 마음에 걸렸다. 그래서 이 작업은 커밋하지 않고 메인테이너에게 설명을 하고 조언을 구하고자 했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  t&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;i18n&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; language &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTranslation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;common&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;py-4 w-full&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;language &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ko&apos;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;avatarPart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;part&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Choose&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Choose&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;avatarPart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;part&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇게 아래 &lt;a href=&quot;https://github.com/Mayandev/notion-avatar/pull/35&quot;&gt;PR&lt;/a&gt;을 작성하고 어순을 바꾸는 부분은 &lt;a href=&quot;https://github.com/Mayandev/notion-avatar/pull/35#issuecomment-1800912347&quot;&gt;코멘트&lt;/a&gt;로 달았다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABWElEQVR42o2R2XKCUBBEeY+C7AKyL5dNgiIhmviW//+lztyLmCqTSvJwqpuB6aFmpLwbETUjvLSHXwywwz0Mv4ZJqA6DbGUzNtcUCqliz7XNtoAZ7KH7LfW09JxBMp0Qlp+jfD6jOb6h7i/IaADrXoXG5RFpfUJSDcjbSWhSnci/CF90ZyT1iCDroTsppCfZwFq1ESQMYVqSlvCj4uaZ8FyX97sohx8XiLIKQUw1qttuBM3ysDFcSDxsrW6xDejDpILlJbB3KTQ7gL4Nb0R3bzg/+Yh6aU1ucgvUHHgRQ9NP6Md3oTHrRDhv4iyDuC5+QdRIVSv4CnTCAofpiun6gW64oOLHyltBQuF8oOnG98BH7MdAN2TYxSXy+gC2H5DVPVhLS2+OIpyv49+BMgXqtDNFd7DaWDNU/8KCTO8UWvpvyDo/CjUrhieOsNrMf8sHfFM63J9oLj4BApnw8dPJwmIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Untitled&quot;
        title=&quot;&quot;
        src=&quot;/static/6ed2c5ac58a5c49ec525696f62d68b9b/c1b63/notion-avatar-maker-story-thumbnail-8.png&quot;
        srcset=&quot;/static/6ed2c5ac58a5c49ec525696f62d68b9b/5a46d/notion-avatar-maker-story-thumbnail-8.png 300w,
/static/6ed2c5ac58a5c49ec525696f62d68b9b/0a47e/notion-avatar-maker-story-thumbnail-8.png 600w,
/static/6ed2c5ac58a5c49ec525696f62d68b9b/c1b63/notion-avatar-maker-story-thumbnail-8.png 1200w,
/static/6ed2c5ac58a5c49ec525696f62d68b9b/d61c2/notion-avatar-maker-story-thumbnail-8.png 1800w,
/static/6ed2c5ac58a5c49ec525696f62d68b9b/6fa81/notion-avatar-maker-story-thumbnail-8.png 1856w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;그러자 메인테이너가 i18n의 &lt;code class=&quot;language-text&quot;&gt;interpolation&lt;/code&gt; 기능을 사용하면 해결할 수 있을 거 같고 일단 머지하고 싶다고 했다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAABYlAAAWJQFJUiTwAAABeUlEQVR42oWS3U7CQBCFe61QCqV/Cy39hQIFBCKYmJjovRc+g+//DMczgy2SaLw4md2zu9/MdGq9f3zieH5FvmgwK9eIkgpmNle5YYJREMMNJP6mGCM/hj/JEcal7q1JUiOgEcUFpukC06yGIXSSzgkv6Zd6ZrgWX6Qe93InnOZMXpGRYeBGsO5sF/YoVEMOfEbPZJokJCiIL1EqaGMwpU+QQDXSk3fCsfrDQMlizJuDtp3NNzDMLq0I/D/JvSRfwhmbFmj0YNEc0eyfsNqdUK32Wsk4SlXtw78kd7RlBZIspoBOz284nF+wfjhzUFsU9Q4l4SmrvoUUN2tJeAVy4ZlUv4+0Ki23rQs0qxokxQo+73jRrKv6p+S9AnuOD8ebcGKcbMKPLa19P9SoukAGYQnXFDpZmbxEGaYMSxhSnAKH3Cy3jyjrDYHpLZCxrcoOKoxCDipKuvNWUl03ZVlE/JFtL8W946FHrxMTXtY+K/A1dr5z3ffJEOAX9X0I+yWJbWAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Untitled&quot;
        title=&quot;&quot;
        src=&quot;/static/5b46aa18360c499a8acd0749c51d9611/c1b63/notion-avatar-maker-story-thumbnail-9.png&quot;
        srcset=&quot;/static/5b46aa18360c499a8acd0749c51d9611/5a46d/notion-avatar-maker-story-thumbnail-9.png 300w,
/static/5b46aa18360c499a8acd0749c51d9611/0a47e/notion-avatar-maker-story-thumbnail-9.png 600w,
/static/5b46aa18360c499a8acd0749c51d9611/c1b63/notion-avatar-maker-story-thumbnail-9.png 1200w,
/static/5b46aa18360c499a8acd0749c51d9611/d61c2/notion-avatar-maker-story-thumbnail-9.png 1800w,
/static/5b46aa18360c499a8acd0749c51d9611/ca3c3/notion-avatar-maker-story-thumbnail-9.png 1850w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;그렇게 내 작업은 머지가 됐고 &lt;a href=&quot;https://notion-avatar.vercel.app/ko&quot;&gt;노션 아바타 메이커의 한국어 버전&lt;/a&gt;이 탄생했다. 🐥 뿌-듯&lt;/p&gt;
&lt;p&gt;조만간 interpolation 기능도 공부해서 작업을 마무리하려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;작은-관심&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%91%EC%9D%80-%EA%B4%80%EC%8B%AC&quot; aria-label=&quot;작은 관심 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;작은 관심&lt;/h2&gt;
&lt;p&gt;이렇게 초보 컨트리뷰터가 기여할 수 있는 가장 현실적인 방법은 작은 관심이라고 생각한다. 막상 뭘 기여할까 찾다 보면 잘 안 보이지만 이렇게 관심을 가지다보면 기회가 생겼었다. 내 프로젝트는 아니지만 기여해보면 애착도 생기고 엄청나게 뿌듯하다. 그리고 새로운 배움의 기회가 온다.&lt;/p&gt;
&lt;p&gt;나는 이런 경험들이 좋아서 기회를 찾자마자 신나서 회사의 팀원들과 나누려고 했는데 작업해야 할 부분이 너무 작아서 혼자 하기로 했다. 아래는 검토를 안하고 공유한 결과다 😅&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;공유 직후&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 465px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 113.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAAAsTAAALEwEAmpwYAAACxklEQVR42qVVS2/TQBDO/z9ScQHBsT2hcuBCVSG1CC70QGmbtLiPNHH8iB1712+vvf6Y2dRNGi6BWPo0s6PN7Dy+mQyG37/i/PQEVV1BRAtkWYqcEIYBpIjRti3apkHXddjmGxwdfsCng32IvMXEieEGKWZ+iqnLeoaFbBAKhThr6Y6GJIhMo6yXD/BD648NemW60BjZLa4Jl48KlqtxM2sxmjaEpX04acjW4IrkItVLh0+/Z58M45DTiqKI0s1QliUUpSikhCQkaWp0c04Sc46FNPcYUibGrpSC1t3SIb8ihUCaCMRRiDzP6IEF5vM55kEAx3Xhe97yTHAchxzR3TiG5/kED1VVrSJkh2kqUOQJOt2grihKVVEEhbnYUMQcQS+fQefmCVxH3fURklKUDfJCIS8ZDZK8RpJVyIoGpVpe1k8N6GW3YXuR8tTPMLzzcWm5uL4PcPnbwc1DiF83M9zbMbb9Bpp5piiVRhMXKV3VGllWythqgmq77R2eH5/g7PMXSi+BS8UOgrkhdV/ouubu6e0d5tTynKjAtBmPx6bYu3zPxGYK2LYNQfTZZP9/ORREVsuyjNOdIgwfx/DGD4ZLzPy6ro1MqQxFUUC32kzS1svh8P1b7L/egyTOTWzHpM71dGk6WCpiADdma4eG7RSFPc8wdgR2/QaKFoLKcsM35l5HFGFw6txx0yBDm/UIu43zmsOP797gYO8VjVtJQ+8iCBeEEPbMMToTnR8yI9avqd5lt5LPDj1nBm82gxsWuLIcDG8dGj2fxs7H7WSB6zuP9LnRrccQd9PY3BuR/d7oVOtU/U0bXgJxUkIkFeKUIElPa2MzdrIJkjKrjR4bXSGStJHq1SQNTr6d4fj0BypaVVEcmT3Io9fXkCnzT035eTHCxdCiBSvh+/7yT4nA88vriLFeN3Qv/0c26bRKmbrNZN6VNn8AJhz4tviYLHkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;팀원들에게 공유한 채팅방1&quot;
        title=&quot;&quot;
        src=&quot;/static/1feebdfcb48f587bef3611bdc03207e4/9ff85/notion-avatar-maker-story-thumbnail-10.png&quot;
        srcset=&quot;/static/1feebdfcb48f587bef3611bdc03207e4/5a46d/notion-avatar-maker-story-thumbnail-10.png 300w,
/static/1feebdfcb48f587bef3611bdc03207e4/9ff85/notion-avatar-maker-story-thumbnail-10.png 465w&quot;
        sizes=&quot;(max-width: 465px) 100vw, 465px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;작업량 검토 후&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 360px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABcElEQVR42p1Ty06DQBTtB7rwT/wO4y+4cOEXmLg0MV3YZZtYKFQoQ6E8CqXIQ0p5HO9MW6KJxaSTnNx7ZyaHc89lBv5MQroJUTcNiqIQKMtSYLcrkec57X2hrmtCg4bu9a3BzfUVHu5ukWQZTNOEvVohDEP4vg/HdcGYCdf1iHSHcl/Rh/Zo2x7Ct+Er2FxFUQMLK8JqncHyU5hOjKWXwHQPcel+wrAj2HRe9xGekk1S4V21MTcCaMsN5mwNRfdoz8Js4UG3tpA1Bx8sQCMI/2YdtOSJwPHKL7Q/Ype3/S2/3D9iOhwhzclDxuA4jvCPwzAM8s8RvgkP//FPEI6enrGYTsnwPQIaRhRFhC3iOBbgdZpmSNKU4gF88u0Z5s7DjKbM1bk0WQ6eK4qC8XgMTdOgqipkWRY1o07OEx4N5v9fkiSCmIOr2JPqqqo68Pq0d5bwdBAEASRJgq7rmEwmQuElq2uZvwyukivgOY+XEH4DvZRPH0wvWeMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;팀원들에게 공유한 채팅방2&quot;
        title=&quot;&quot;
        src=&quot;/static/bcb9de0ae6f5d5b6e16ae3da7e7579b4/f21e7/notion-avatar-maker-story-thumbnail-11.png&quot;
        srcset=&quot;/static/bcb9de0ae6f5d5b6e16ae3da7e7579b4/5a46d/notion-avatar-maker-story-thumbnail-11.png 300w,
/static/bcb9de0ae6f5d5b6e16ae3da7e7579b4/f21e7/notion-avatar-maker-story-thumbnail-11.png 360w&quot;
        sizes=&quot;(max-width: 360px) 100vw, 360px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[테크 커리어 리뷰]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/books/테크-커리어-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/테크-커리어-리뷰/</guid><pubDate>Wed, 30 Aug 2023 22:08:31 GMT</pubDate><content:encoded>&lt;p&gt;같은 시리즈로 나온 다른 책들도 읽어 봤고 내용이 좋아서 이 책도 기대를 많이 했다. 개발자로서 어떻게 경력을 관리하고 쌓아갈지, 그리고 회사에서 성과를 내기 위한 태도와 마음가짐 등 인사이트를 주는 책이었다. 그래서 어느 정도 일을 해 보신 분들이 예상 독자가 아닐까 싶다.&lt;/p&gt;
&lt;p&gt;특히 이 책은 각 장이 끝날 때마다 실천해 볼 수 있는 실천 과제를 줘서 액션 아이템을 세우는데 도움을 받을 수 있었다. 한 장을 읽고 실천 과제를 수행해보면 내용 정리하기 수월했다.&lt;/p&gt;
&lt;p&gt;이런 내용을 구체적으로 다루는 블로그 글이나 영상은 찾아보기 힘들다. 그래서 가뭄에 단비 같은 책이었다. 내가 일을 어떻게 바라보면 좋을지 그리고 나 자신을 어떻게 바라볼지에 대해 배우고 그 관점을 기반으로 경력 및 브랜드 관리, 네트워킹, 학습과 태도, 시간관리, 커뮤니케이션, 의사 결정 방법 등에 대해 배웠다.&lt;/p&gt;
&lt;p&gt;실제로 적용해 볼 수 있는 내용들이고 양이 많아 한번에 모든 내용을 소화하기 보다는 두고두고 꺼내 볼 수 있게 백과사전식으로 활용해보면 좋을 거 같다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://image.yes24.com/goods/118106959/XL&quot; alt=&quot;image&quot;&gt;
출처 : yes24&lt;/p&gt;
&lt;p&gt;길벗 출판사에서 책을 제공받아 읽고 작성한 서평이다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[인프콘 2023 후기]]></title><description><![CDATA[이 웅장한 인파가 얼마나 열기가 뜨거웠는지를 보여주는 것 같다. 작년엔 못 갔는데 이번엔 운이 너무너무 좋아서 인프콘 202…]]></description><link>https://donghoon-song.github.io/mystory/인프콘-2023-후기/</link><guid isPermaLink="false">https://donghoon-song.github.io/mystory/인프콘-2023-후기/</guid><pubDate>Tue, 15 Aug 2023 21:08:59 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwT/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABUaGWUYP/xAAbEAACAgMBAAAAAAAAAAAAAAABAgADERIiIf/aAAgBAQABBQJbTlu4x6zoBbH8f//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/AVf/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwFH/8QAGBABAQADAAAAAAAAAAAAAAAAAQARIVH/2gAIAQEABj8Czpl5csFsJL//xAAbEAEAAwEAAwAAAAAAAAAAAAABABEhMUFRYf/aAAgBAQABPyFgeGNEOEKpjGFVfPZcKTbyOWKFH1MxzxP/2gAMAwEAAgADAAAAEDs//8QAFhEBAQEAAAAAAAAAAAAAAAAAAAFx/9oACAEDAQE/EJWH/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAFx/9oACAECAQE/ELGn/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFBUaGB/9oACAEBAAE/EEuoV2Y2X7CbQVmOSEYDh6fZRBApFXTqusRLGMC1743GAaLh0Oa9n//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 메인&quot;
        title=&quot;&quot;
        src=&quot;/static/fff0651da2193f3cfeed0f7277d70aea/e5166/infcon-2023-main.jpg&quot;
        srcset=&quot;/static/fff0651da2193f3cfeed0f7277d70aea/f93b5/infcon-2023-main.jpg 300w,
/static/fff0651da2193f3cfeed0f7277d70aea/b4294/infcon-2023-main.jpg 600w,
/static/fff0651da2193f3cfeed0f7277d70aea/e5166/infcon-2023-main.jpg 1200w,
/static/fff0651da2193f3cfeed0f7277d70aea/d9c39/infcon-2023-main.jpg 1800w,
/static/fff0651da2193f3cfeed0f7277d70aea/e1596/infcon-2023-main.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이 웅장한 인파가 얼마나 열기가 뜨거웠는지를 보여주는 것 같다.&lt;/p&gt;
&lt;p&gt;작년엔 못 갔는데 이번엔 운이 너무너무 좋아서 인프콘 2023을 갈 수 있었다. 😆&lt;/p&gt;
&lt;p&gt;큰 오프라인 행사에 가는 게 너무나도 오랜만이다.&lt;/p&gt;
&lt;h2 id=&quot;등록&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%B1%EB%A1%9D&quot; aria-label=&quot;등록 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;등록&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1011px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBP/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAFV2QBCI3//xAAbEAABBAMAAAAAAAAAAAAAAAACAAEDERASIf/aAAgBAQABBQIZEejjTUEYupeY/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxABAQEBAAAAAAAAAAAAAAAAAAEQgf/aAAgBAQAGPwKKjm//xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhMUFhcf/aAAgBAQABPyGlBTlbLZx+eQzl55GOdUIUAr8i1VZk/9oADAMBAAIAAwAAABAc/wD/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxCH/8QAHBABAQACAgMAAAAAAAAAAAAAAREAITFRQWGh/9oACAEBAAE/EILhoHPOT0SduxXfrNpAn4yyVAbnT5mGK2IdjjIyYaguf//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 등록&quot;
        title=&quot;&quot;
        src=&quot;/static/872bf7b59f43dfae501cdf8b49155373/6fbf4/infcon-2023-registration.jpg&quot;
        srcset=&quot;/static/872bf7b59f43dfae501cdf8b49155373/f93b5/infcon-2023-registration.jpg 300w,
/static/872bf7b59f43dfae501cdf8b49155373/b4294/infcon-2023-registration.jpg 600w,
/static/872bf7b59f43dfae501cdf8b49155373/6fbf4/infcon-2023-registration.jpg 1011w&quot;
        sizes=&quot;(max-width: 1011px) 100vw, 1011px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;등록하러 갔을 때부터 사람이 엄청 많았다. 😱&lt;/p&gt;
&lt;h2 id=&quot;이벤트들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EB%B2%A4%ED%8A%B8%EB%93%A4&quot; aria-label=&quot;이벤트들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이벤트들&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 133.33333333333331%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEBQb/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABewekxSGffz2nLYTFf//EABwQAAICAgMAAAAAAAAAAAAAAAEDAAIQExIjM//aAAgBAQABBQJS6FWlc0LiPHCGdYhiSQKstxrYkf/EABYRAQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAwEBPwHIj//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EAB0QAAMAAAcAAAAAAAAAAAAAAAABAhAgITEyQXH/2gAIAQEABj8CluUcTsnzGVk3NT//xAAfEAEBAAECBwAAAAAAAAAAAAABABEQITFBUXGB4fD/2gAIAQEAAT8hRGU4yvR2b4uleZbYElOU94RhvVCy5Zc3/9oADAMBAAIAAwAAABDb/wD9/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAQEf/aAAgBAwEBPxDDqUX/xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQIBAT8Q1q3Er//EACAQAAICAgEFAQAAAAAAAAAAAAERACExQWFRcYHB4fD/2gAIAQEAAT8QuuLIWbM2XuR7hMaI8D5mgM5PkxFYNKxFJ5UODWAQvJjIRaF0VSkxDoIVcKf6UOMUNCf/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 지도&quot;
        title=&quot;&quot;
        src=&quot;/static/1ba1868a491de04cf5b71c111f943bda/47311/infcon-2023-map.jpg&quot;
        srcset=&quot;/static/1ba1868a491de04cf5b71c111f943bda/f93b5/infcon-2023-map.jpg 300w,
/static/1ba1868a491de04cf5b71c111f943bda/b4294/infcon-2023-map.jpg 600w,
/static/1ba1868a491de04cf5b71c111f943bda/47311/infcon-2023-map.jpg 1080w&quot;
        sizes=&quot;(max-width: 1080px) 100vw, 1080px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 133.33333333333331%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAwADAAAAAAAAAAAAAAAAAAMEAQIG/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAGwZmEjCpquduHYkNH/xAAcEAEAAgIDAQAAAAAAAAAAAAACAAEDEwQQESP/2gAIAQEAAQUC1iaxNI7T8hye3U5K+hVlVlcd2l//xAAVEQEBAAAAAAAAAAAAAAAAAAAQMf/aAAgBAwEBPwEh/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAExMhEgIYH/2gAIAQEABj8CqiiI28OEmWf/xAAeEAEAAgEEAwAAAAAAAAAAAAABABEQITFBcWHR4f/aAAgBAQABPyHqusZf9sXcwTDxOXwrIcCJbVpK3qRQts//2gAMAwEAAgADAAAAEGsyz//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/EIkf/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAEhEf/aAAgBAgEBPxDrU1H/xAAfEAEAAgEDBQAAAAAAAAAAAAABABExIaHBUWGRseH/2gAIAQEAAT8QFGhGCLzXcPTMq52qgDdSsFMt+TmIxLbby/CELrGxvlPMMHyYvWNLl1+UuadW1U//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 프로그램&quot;
        title=&quot;&quot;
        src=&quot;/static/961ce151133e120c910961ef1c87d653/47311/infcon-2023-program.jpg&quot;
        srcset=&quot;/static/961ce151133e120c910961ef1c87d653/f93b5/infcon-2023-program.jpg 300w,
/static/961ce151133e120c910961ef1c87d653/b4294/infcon-2023-program.jpg 600w,
/static/961ce151133e120c910961ef1c87d653/47311/infcon-2023-program.jpg 1080w&quot;
        sizes=&quot;(max-width: 1080px) 100vw, 1080px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;전체적인 지도는 이랬다. 101~105호는 발표 듣는 곳. 외에 인프런 및 참가 회사들의 부스가 있었다.
2층은 핸즈온이나 프로그램이 따로 열렸다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1080px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 133.33333333333331%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAMBBAUCBv/EABYBAQEBAAAAAAAAAAAAAAAAAAIBAP/aAAwDAQACEAMQAAABl3dpDHILn6PmrgSxYp//xAAeEAACAQMFAAAAAAAAAAAAAAACAwEABCMQEhQhM//aAAgBAQABBQJaYIOPFMHYVv40+ctseOmdsWUwJGUaf//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8BCBs5F//EABcRAQADAAAAAAAAAAAAAAAAAAEAEBH/2gAIAQIBAT8BWbf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAQIQESEycf/aAAgBAQAGPwJSydGBVIVS9NM6df/EABwQAAMAAgMBAAAAAAAAAAAAAAABESFhMUFREP/aAAgBAQABPyFzHV18VN3TZ7K9lCsi+ij7Go2EaiyJscnpyf/aAAwDAQACAAMAAAAQhAJN/8QAGBEBAQEBAQAAAAAAAAAAAAAAAQARMcH/2gAIAQMBAT8QDN9kHYRoIYBf/8QAGREBAQEAAwAAAAAAAAAAAAAAAQARITFR/9oACAECAQE/EFHJHlovc8t//8QAIBABAAICAgEFAAAAAAAAAAAAAQAhETFBYVFxgZGhsf/aAAgBAQABPxBcDlVioIIIfKTAKwHJ3G0PoHcwDfLiX50h8EBsU094Usfc7R/Saj9p7gRO5m/iKpW1tn//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 프로그램&quot;
        title=&quot;&quot;
        src=&quot;/static/490eb695571ae0cb6ed3cb868d5c88db/47311/infcon-2023-stamp-tour.jpg&quot;
        srcset=&quot;/static/490eb695571ae0cb6ed3cb868d5c88db/f93b5/infcon-2023-stamp-tour.jpg 300w,
/static/490eb695571ae0cb6ed3cb868d5c88db/b4294/infcon-2023-stamp-tour.jpg 600w,
/static/490eb695571ae0cb6ed3cb868d5c88db/47311/infcon-2023-stamp-tour.jpg 1080w&quot;
        sizes=&quot;(max-width: 1080px) 100vw, 1080px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;스탬프 받는 곳으로 가서 이벤트에 참여하면 스탬프를 모을 수 있고 4개당 한번! 뽑기 기회가 주어졌다.&lt;/p&gt;
&lt;h2 id=&quot;오프닝&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%98%A4%ED%94%84%EB%8B%9D&quot; aria-label=&quot;오프닝 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;오프닝&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHApOIKD//EABcQAAMBAAAAAAAAAAAAAAAAAAAQEQH/2gAIAQEAAQUCJjq//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFhABAQEAAAAAAAAAAAAAAAAAADEQ/9oACAEBAAY/Al2I/8QAHBAAAgICAwAAAAAAAAAAAAAAAAERQRAxIXHx/9oACAEBAAE/IVy9wOCz6xqkNXQlej//2gAMAwEAAgADAAAAEO8//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EKr/xAAbEAEAAQUBAAAAAAAAAAAAAAABABEhQVGRMf/aAAgBAQABPxBoFAcsBWPQWdiRTM7PU1WWLw//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 오프닝 시작 전&quot;
        title=&quot;&quot;
        src=&quot;/static/355b322cc4647df532cd6721becee57b/e5166/infcon-2023-opening-before-start.jpg&quot;
        srcset=&quot;/static/355b322cc4647df532cd6721becee57b/f93b5/infcon-2023-opening-before-start.jpg 300w,
/static/355b322cc4647df532cd6721becee57b/b4294/infcon-2023-opening-before-start.jpg 600w,
/static/355b322cc4647df532cd6721becee57b/e5166/infcon-2023-opening-before-start.jpg 1200w,
/static/355b322cc4647df532cd6721becee57b/d9c39/infcon-2023-opening-before-start.jpg 1800w,
/static/355b322cc4647df532cd6721becee57b/e1596/infcon-2023-opening-before-start.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;자리에 앉아서 어둠 속에서 오프닝을 기다리는 순간은 정말 가슴이 웅장해졌다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABxaJ2E0lHP//EABoQAQADAQEBAAAAAAAAAAAAAAEAAgMREhP/2gAIAQEAAQUCrRtPg+zMA05Dbi2Gf//EABYRAQEBAAAAAAAAAAAAAAAAAAASYf/aAAgBAwEBPwFOv//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AVf/xAAaEAEAAgMBAAAAAAAAAAAAAAAAEjEBESGh/9oACAEBAAY/AkcW6puPqn//xAAaEAADAAMBAAAAAAAAAAAAAAAAAREhMUGx/9oACAEBAAE/IUyfLBzQwEhRR3IgbEGF9H//2gAMAwEAAgADAAAAEJjv/8QAFhEBAQEAAAAAAAAAAAAAAAAAABFh/9oACAEDAQE/EJqj/8QAFxEBAAMAAAAAAAAAAAAAAAAAABFhcf/aAAgBAgEBPxCaZf/EAB0QAQEAAQQDAAAAAAAAAAAAAAERACExQWGBwfH/2gAIAQEAAT8QIG7yZQaQdWFlcAFzXbTAgEDtPecoCiLFNS8fOf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 오프닝 ceo님&quot;
        title=&quot;&quot;
        src=&quot;/static/82497a781d7ae04a702654cf5a093cdb/e5166/infcon-2023-opening-ceo.jpg&quot;
        srcset=&quot;/static/82497a781d7ae04a702654cf5a093cdb/f93b5/infcon-2023-opening-ceo.jpg 300w,
/static/82497a781d7ae04a702654cf5a093cdb/b4294/infcon-2023-opening-ceo.jpg 600w,
/static/82497a781d7ae04a702654cf5a093cdb/e5166/infcon-2023-opening-ceo.jpg 1200w,
/static/82497a781d7ae04a702654cf5a093cdb/d9c39/infcon-2023-opening-ceo.jpg 1800w,
/static/82497a781d7ae04a702654cf5a093cdb/e1596/infcon-2023-opening-ceo.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;멋진 성장을 이뤄낸 지표를 바탕으로 행사를 여시는 CEO님!&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABQADBv/EABYBAQEBAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAABNd5vasUYuD//xAAaEAEAAgMBAAAAAAAAAAAAAAACAQMABBMh/9oACAEBAAEFAtavquZBUe12IYtixR2UZ//EABkRAAEFAAAAAAAAAAAAAAAAAAABAgMRE//aAAgBAwEBPwF0dqZH/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEh/9oACAECAQE/Aax//8QAGhABAAIDAQAAAAAAAAAAAAAAAQAQESEiYf/aAAgBAQAGPwLqYK5cRFN+V//EABsQAQACAgMAAAAAAAAAAAAAAAEAESExUWGR/9oACAEBAAE/IRUtQahSAHUDWZPzRawwYBBhrkn/2gAMAwEAAgADAAAAEKzv/8QAGBEBAQADAAAAAAAAAAAAAAAAAQARMbH/2gAIAQMBAT8QRl1yyv/EABYRAQEBAAAAAAAAAAAAAAAAAAEREP/aAAgBAgEBPxAMmf/EABoQAQEBAQEBAQAAAAAAAAAAAAERACExQaH/2gAIAQEAAT8QT5iQMvdGtezP3GXxlmo8eHC2bwGv0xB6Tf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 오프닝 cto님&quot;
        title=&quot;&quot;
        src=&quot;/static/169b9a180df8ad97daf14ca147cff374/e5166/infcon-2023-opening-cto.jpg&quot;
        srcset=&quot;/static/169b9a180df8ad97daf14ca147cff374/f93b5/infcon-2023-opening-cto.jpg 300w,
/static/169b9a180df8ad97daf14ca147cff374/b4294/infcon-2023-opening-cto.jpg 600w,
/static/169b9a180df8ad97daf14ca147cff374/e5166/infcon-2023-opening-cto.jpg 1200w,
/static/169b9a180df8ad97daf14ca147cff374/d9c39/infcon-2023-opening-cto.jpg 1800w,
/static/169b9a180df8ad97daf14ca147cff374/e1596/infcon-2023-opening-cto.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;유튜브로만 뵀던 CTO 향로님! 연예인 보는 기분이었다.&lt;/p&gt;
&lt;h2 id=&quot;듣고-싶었던-세션과-그-이유-발표-내용-요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A3%EA%B3%A0-%EC%8B%B6%EC%97%88%EB%8D%98-%EC%84%B8%EC%85%98%EA%B3%BC-%EA%B7%B8-%EC%9D%B4%EC%9C%A0-%EB%B0%9C%ED%91%9C-%EB%82%B4%EC%9A%A9-%EC%9A%94%EC%95%BD&quot; aria-label=&quot;듣고 싶었던 세션과 그 이유 발표 내용 요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;듣고 싶었던 세션과 그 이유, 발표 내용 요약&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEA//EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABtXFSciNH/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECAyES/9oACAEBAAEFAuHC2k3rKHtBpfqv/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRABAAMBAQAAAAAAAAAAAAAAAAERMSFB/9oACAEBAAY/AsZDHberh//EAB0QAAICAQUAAAAAAAAAAAAAAAABESFRMWGRwdH/2gAIAQEAAT8hSwcDSvoExQ0wQ9E7CD8CpmoP/9oADAMBAAIAAwAAABB/H//EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxBMn//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAgEBPxAdgv/EABwQAQEAAgIDAAAAAAAAAAAAAAERADFBkSFRcf/aAAgBAQABPxC5Gd5GKU6OSY2tPbitU4Fa3gxEiD8d4VUzPJM//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 시간표&quot;
        title=&quot;&quot;
        src=&quot;/static/33f4e551930c85032844d2651e998dbb/e5166/infcon-2023-time-table.jpg&quot;
        srcset=&quot;/static/33f4e551930c85032844d2651e998dbb/f93b5/infcon-2023-time-table.jpg 300w,
/static/33f4e551930c85032844d2651e998dbb/b4294/infcon-2023-time-table.jpg 600w,
/static/33f4e551930c85032844d2651e998dbb/e5166/infcon-2023-time-table.jpg 1200w,
/static/33f4e551930c85032844d2651e998dbb/644c5/infcon-2023-time-table.jpg 1440w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;구글-apps-script와-chatgpt로-많은-동료들-생산성-향상-시킨-썰&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%EA%B8%80-apps-script%EC%99%80-chatgpt%EB%A1%9C-%EB%A7%8E%EC%9D%80-%EB%8F%99%EB%A3%8C%EB%93%A4-%EC%83%9D%EC%82%B0%EC%84%B1-%ED%96%A5%EC%83%81-%EC%8B%9C%ED%82%A8-%EC%8D%B0&quot; aria-label=&quot;구글 apps script와 chatgpt로 많은 동료들 생산성 향상 시킨 썰 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;구글 Apps Script와 ChatGPT로 많은 동료들 생산성 향상 시킨 썰&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;구성원들의 생산성을 향상하는 데 관심이 많아 다른 회사 사례도 들어보고 싶었다. 어떤 계기로 어떤 작업을 어떻게 줄였는지 궁금했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;메일을 대량 발송하는 업무를 하고 계신 동료분의 메시지를 받고 몇백 개의 메일을 한 번에 보내다 보면 시간이 꽤 걸린다고 계산하셨다. 그래서 이를 자동화할 수 있다면 소중한 시간을 꽤 단축할 수 있을 거로 생각하시고 방법을 찾아가셨다. Apps Script에 익숙지 않아 ChatGPT에게 물어보고 원하는 결과를 얻을 때까지 피드백을 주면서 기능을 구현하셨다.&lt;/p&gt;
&lt;p&gt;문제는 이걸 개발자가 아닌 동료분이 사용하셔야 했던 건데, 한 줄 한 줄 친절하게 주석을 달아주셨다. 더 사용하기 쉽도록 동영상 강의를 직접 찍어서 공유하셨다고 한다. 그러고 나서 사용하던 동료분들의 새로운 요구사항이 등장했다. 그것은 바로 특정 이메일은 첨부파일을 다르게 보내는 기능이었는데, 이것도 구현을 해내셨다. 그리고 이 문제를 겪고 있는 다른 동료분들도 계실 거로 생각해서 전사에 공유하셨다고 한다. 👍&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;많은 동료의 시간을 아껴준&lt;/code&gt; 엄청 임팩트 있는 일을 해내셨다는 게 인상 깊었고, 사용법을 알려주는 &lt;code class=&quot;language-text&quot;&gt;동영상 강의를 직접 찍어서 공유&lt;/code&gt;하신 점, 더 나아가 &lt;code class=&quot;language-text&quot;&gt;전사에 공유&lt;/code&gt;하신 점이 좋았다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;나도 회사에서 그렇게 어렵지 않은 작업으로 동료들의 생산성을 향상한 사례가 있다. 어드민에서 테이블 텍스트를 클릭하면 자동으로 복사가 되는 기능이었다. 테이블 텍스트를 클릭하면 테이블에 따라 그 데이터의 편집 페이지로 이동하는 등 기존의 액션이 있어서 텍스트만 복사하기가 어렵다고 하셨었는데 불편해하시는 줄 몰랐었다가 그 목소리를 늦게나마 들어서 작업했었다. 반응이 너무 좋아서 뿌듯하기도 했지만 😎 그런 목소리를 들을 수 있는 환경을 구축해야 더 쉽게 불편함을 캐치할 수 있을 거라는 생각이 들었다. 🦻🏻&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;출시-3일만에-앱스토어-2위를-달성한-사이드-프로젝트&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%9C%EC%8B%9C-3%EC%9D%BC%EB%A7%8C%EC%97%90-%EC%95%B1%EC%8A%A4%ED%86%A0%EC%96%B4-2%EC%9C%84%EB%A5%BC-%EB%8B%AC%EC%84%B1%ED%95%9C-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8&quot; aria-label=&quot;출시 3일만에 앱스토어 2위를 달성한 사이드 프로젝트 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;출시 3일만에 앱스토어 2위를 달성한 사이드 프로젝트&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;disquiet이라는 커뮤니티에 글이 올라와서 시간 가는 줄 모르고 읽었던 흥미로운 경험이었다. gas라는 앱을 카피해서 한국에서 디지털미디어 고등학교(이하 디미고) 학생들이 가설을 세우고 검증하면서 그로스해 나갔던 이야기가 담겨 있는데 개발 담당이었던 김아인 님도 발표에 참여해서 더 풍부한 내용을 들을 수 있을거라 생각했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;미국의 gas라는 앱이 성공하면서 한국에도 똑같은 앱이 먹힐지 가설을 세우고 검증해본 이야기이다. 미국의 15~19세 인구와 한국의 인구를 비교해 &lt;code class=&quot;language-text&quot;&gt;미국에서 기간별로 이만큼 매출이 일어났으니 한국에서 이정도 매출이 나야 성공으로 정의할 수 있다.&lt;/code&gt;라고 지표를 세웠다. 아이디어 불패의 법칙이라는 책에 나온 &lt;code class=&quot;language-text&quot;&gt;XYZ 가설&lt;/code&gt;8을 활용해 가설을 세웠다고 한다. =&gt; skrr 미디어에 3번 이상 노출된 유저들의 n%는 앱을 설치할 것이다, 과금을 할 것이다 등.&lt;/p&gt;
&lt;p&gt;디미고 특성 상 전국 각지에서 학생들이 모이기 때문에 전국적으로 바이럴이 일어나기 좋은 환경이라고 생각했다고 한다. 처음에 인스타그램 마케팅(계정을 만들어 디미고 학생들 팔로우하기), 쪽지 GTM(오프라인에서 그럴듯한 쪽지를 적어서 건네주는) 등의 활동을 하면서 유저를 모았다고 한다.&lt;/p&gt;
&lt;p&gt;몇일이 지나 1일 7천명이 설치하며 앱스토어 소셜 2위에 올랐다고 한다. 하지만 여기에 안주해 결국 경쟁사가 더 치고 올라갔다고 한다.&lt;/p&gt;
&lt;p&gt;실패의 원인으로는 먼저 팀원들을 지속적으로 동기부여하지 못했으며 제어 불가능한 변수를 만나기도 했다고 한다. 그래서 mvp단계에 머무르다 보니 다음 단계로 나아가지 못했다고 한다.&lt;/p&gt;
&lt;p&gt;개발 프로세스에서 Feature Develop Cycle(1FDC)를 잘개 기능별로 쪼개서 빠르게 피드백 받으며 나아갔다고 한다. 쪼갠 기능으로는 “마이페이지에서 친구초대하기”, “친구 검색 기능” 등이 있다.&lt;/p&gt;
&lt;p&gt;초기에 데이터를 json file로 관리했다고 한다. 서버 개발 지식과 경험이 많지 않아 익숙한 방법을 사용했다고 하는데 트래픽이 올라가면서 파일 읽기 쓰기가 많이 발생, 동시성 제어가 안됨, 파일이 길어질수록 속도가 느려지는 등의 이슈가 발생했다고 한다.&lt;/p&gt;
&lt;p&gt;서비스 로그를 중요한 부분만 남기고, json 구조 개선 등을 통해 성능 개선을 하다가 json 형식을 거의 그대로 쓸 수 있는 mongodb로 넘어갔다고 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;XYZ 가설의 경우 프로젝트 근래에 읽은 책에서 배운 내용인데 &lt;code class=&quot;language-text&quot;&gt;바로 적용&lt;/code&gt;해봤다는 점이 참 좋았다. 나도 책에서 배운 내용을 적용하는데에는 아직 서툰데, &lt;code class=&quot;language-text&quot;&gt;실행력&lt;/code&gt;이 굉장히 멋지다. 미국의 사례를 바탕으로 한국과 비교해 목표를 세운 점도 배울 점이었고 실패했던 원인은 내가 비슷한 상황을 만났을 때 어떻게 개선할 수 있을지 고민해보면 좋을 거 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;왜-내가-만든-서비스는-아무도-안-쓰지-개발자가-알아두면-좋은-사이드-프로젝트-제작-팁&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%9C-%EB%82%B4%EA%B0%80-%EB%A7%8C%EB%93%A0-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%8A%94-%EC%95%84%EB%AC%B4%EB%8F%84-%EC%95%88-%EC%93%B0%EC%A7%80-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EC%95%8C%EC%95%84%EB%91%90%EB%A9%B4-%EC%A2%8B%EC%9D%80-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A0%9C%EC%9E%91-%ED%8C%81&quot; aria-label=&quot;왜 내가 만든 서비스는 아무도 안 쓰지 개발자가 알아두면 좋은 사이드 프로젝트 제작 팁 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왜 내가 만든 서비스는 아무도 안 쓰지?: 개발자가 알아두면 좋은 사이드 프로젝트 제작 팁&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;내 이야기이다 😂. 사실 나는 작은 사이드 프로젝트를 개발하고 출시해서 사용자 피드백을 받고 다시 개선하고 있다. 사이드 프로젝트에 관심이 많지만 아직 경험이 부족한 내가 정말 관심이 갔던 이야기였다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;사이드 프로젝트를 29개나 하셨다는 점이 인상깊었다. 그 중 코로나맵이 일주일 1000만 조회, 1400만 사용자를 이끌어 내셨다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;좋은 문제를 찾고 이해하고 해결하기&lt;/code&gt;라는 부분을 강조하셨는데 우리가 간과하는 점이 &lt;code class=&quot;language-text&quot;&gt;상품은 시장의 니즈로부터 나와야&lt;/code&gt; 하지만 우리는 솔루션을 먼저 정의하고 고객을 끼워 맞춘다는 것이다. 그러니까 사람들이 쓰지 않는다. 즉, 내가 만들고 싶은 서비스를 만들고 있었다고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;좋은 문제를 찾으려면&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;주변에 당연하다고 생각하는 것에 반문하고&lt;/li&gt;
&lt;li&gt;관찰하며&lt;/li&gt;
&lt;li&gt;펼쳐봐야&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;한다고 하셨다.&lt;/p&gt;
&lt;p&gt;코로나 맵을 만들 때 패턴화된 페이스북 댓글을 감지했다고 하셨다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;오늘 오후 3시에 서울역에서 확진자 나왔다는데 진짜인가&lt;/code&gt;라는 댓글인데 여기서&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;불안감을 남들과 공유&lt;/li&gt;
&lt;li&gt;위치, 시간 정보 알고 싶음&lt;/li&gt;
&lt;li&gt;정확한 정보를 찾을 수 없음&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;을 파악하셨다. 코로나 정보를 얻기 위해 가독성 떨어지는 보도 자료를 읽어야 한다는 점을 개선하려고 하신 것에서 출발했다.&lt;/p&gt;
&lt;p&gt;가능한 &lt;code class=&quot;language-text&quot;&gt;짧은 시간&lt;/code&gt; 안에 &lt;code class=&quot;language-text&quot;&gt;완성&lt;/code&gt;하는 것을 강조하셨다. 프로젝트를 계속 하다보면 동기가 점점 떨어지기 때문이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;어떤 문제를 어떻게 해결하려고 했는지&lt;/li&gt;
&lt;li&gt;어떤 기술스택을 왜 사용했는지&lt;/li&gt;
&lt;li&gt;어떤 결과가 나왔고 얻은점은 무엇인지&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;를 기반으로 &lt;code class=&quot;language-text&quot;&gt;경험을 잘 기록&lt;/code&gt;하라고 하셨다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;성공한 프로젝트가 나오기 까지 수많은 실패와 도전이 있었다는 게 인상깊었고 동기부여가 됐다. 또한 주변을 관찰하다가 불편함을 찾아내고, 개선방향을 생각해낸 인사이트도 좋았고 짧은 시간안에 완성해야 한다는 것에 공감을 많이 했다. 또 이제까진 기록을 별로 하지 않았지만 앞으로라도 경험을 기록해야겠다는 생각이 들었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;어느-날-고민-많은-주니어-개발자가-찾아왔다-2탄-주니어-시절-성장과-고민들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%8A%90-%EB%82%A0-%EA%B3%A0%EB%AF%BC-%EB%A7%8E%EC%9D%80-%EC%A3%BC%EB%8B%88%EC%96%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EC%B0%BE%EC%95%84%EC%99%94%EB%8B%A4-2%ED%83%84-%EC%A3%BC%EB%8B%88%EC%96%B4-%EC%8B%9C%EC%A0%88-%EC%84%B1%EC%9E%A5%EA%B3%BC-%EA%B3%A0%EB%AF%BC%EB%93%A4&quot; aria-label=&quot;어느 날 고민 많은 주니어 개발자가 찾아왔다 2탄 주니어 시절 성장과 고민들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어느 날 고민 많은 주니어 개발자가 찾아왔다 2탄: 주니어 시절 성장과 고민들&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;요즘 성장에 대한 고민을 많이 하고 있어서 비슷한 사례가 있을지, 그에 대한 조언이 있을지 궁금해서 듣고 싶었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;듣지 못했다. 😭 인기가 너무 많아서 자리가 없었다. 대신 사람이 없는 이 시간을 활용해 스탬프 투어를 완료하고 밥을 먹었다. 👍&lt;/p&gt;
&lt;h3 id=&quot;팀플레이어-101-팀의-성공을-위해-달리는-메이커-되기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%80%ED%94%8C%EB%A0%88%EC%9D%B4%EC%96%B4-101-%ED%8C%80%EC%9D%98-%EC%84%B1%EA%B3%B5%EC%9D%84-%EC%9C%84%ED%95%B4-%EB%8B%AC%EB%A6%AC%EB%8A%94-%EB%A9%94%EC%9D%B4%EC%BB%A4-%EB%90%98%EA%B8%B0&quot; aria-label=&quot;팀플레이어 101 팀의 성공을 위해 달리는 메이커 되기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;팀플레이어 101: 팀의 성공을 위해 달리는 메이커 되기&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;팀원으로서 어떻게 움직여야 팀에 도움이 되고 서비스에 도움이 될지 고민이 많아서 관심이 갔다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 발표는 사례 중심이었고 내가 빠르게 못 적어서 정리를 많이 못했다. 영상으로 다시 볼 예정이다.&lt;/p&gt;
&lt;p&gt;더 나은 팀플레이어가 되기 위해&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;멋지다&lt;/code&gt; 싶으면 적는다.&lt;/li&gt;
&lt;li&gt;실천하기 위해 &lt;code class=&quot;language-text&quot;&gt;액션 아이템&lt;/code&gt;으로 적는다.&lt;/li&gt;
&lt;li&gt;반면교사도 적는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;를 실천하셨다. 노션에 81개의 best practice를 정리해서 모아놓으셨다. 성공보다는 &lt;code class=&quot;language-text&quot;&gt;시도가 중요하다&lt;/code&gt;고 하셨다. 적은 내용을 자기만의 방식으로 시도하는 것이다.&lt;/p&gt;
&lt;p&gt;예를 들면, 이 맥북으로 교체하면 로컬 빌드 속도가 n% 빨라지고, 개발이 이정도 빨라지니 같은 기간 내에 배포를 m번 더 할 수 있다. 라고 맥북 구매 이유를 적은 사례가 있었다.&lt;/p&gt;
&lt;p&gt;다른 사례로는, 구현하기 굉장히 어려운 디자인 시안을 받았을 때, 기간 내에 하기 위해 야근을 하는 게 아니라, 이 부분은 이런 이유로 이 기간 내에 완성하기가 어렵다. 기능이 같지만 공수가 적게 드는 대안으로 기간 내에 배포를 하고 추후 데이터를 보면서 개선하는 건 어떨까요? 라고 커뮤니케이션 하는 것이다.&lt;/p&gt;
&lt;p&gt;이런 사례들이 몇 개 더 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;맥북 사례는 비슷하게 경험을 했었는데, 빌드 속도가 n% 빨라진다는 것까진 생각을 했는데 이로 인해 배포를 m번 더 할 수 있다는 생각까진 도달하지 못했었다. 😂 그래서 사고가 확장된 느낌을 받았고 두번째 예 같은 경우에는 나도 해봤던 커뮤니케이션 방식이어서 신기했다. 그 외 다른 예들을 들어보면 내가 커뮤니케이션 하는 방식보다 조금 더 본질적이고 깊게 들어가는 거 같아서, 나중에 영상이 올라오면 다시 정리해보고 적용해보려고 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;주니어-프론트엔드-엔지니어의-성과-및-역량-향상을-위한-실전-가이드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A3%BC%EB%8B%88%EC%96%B4-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EC%9D%98-%EC%84%B1%EA%B3%BC-%EB%B0%8F-%EC%97%AD%EB%9F%89-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%8B%A4%EC%A0%84-%EA%B0%80%EC%9D%B4%EB%93%9C&quot; aria-label=&quot;주니어 프론트엔드 엔지니어의 성과 및 역량 향상을 위한 실전 가이드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;주니어 프론트엔드 엔지니어의 성과 및 역량 향상을 위한 실전 가이드&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;어떻게 하면 내 역량을 더 향상시킬 수 있을지 실제로 적용해 볼 수 있을법한 내용을 기대했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;저번에 공유해주신 너무 좋은 자료였던 &lt;a href=&quot;https://steady-study.super.site/frontend-engineer-career-roadmap&quot;&gt;프론트엔드 엔지니어 커리어 로드맵: 주니어를 위한 3가지 전문성 트랙&lt;/a&gt;에서 더 나아간 실질적인 실행방법들, 이론들이 주된 내용이었다. 이 발표도 정리를 잘 하지 못했다. 장표에 글이 많고 새로운 용어가 많아서 한번에 이해하기는 쉽지 않았다. 발표 속도도 빨라서 다른 분들도 필기 대신 장표를 폰으로 찍는 방법을 택하셨다. 이 발표도 영상으로 나오면 천천히 다시 볼 예정이다. 소화하고 체득하면 분명히 성장하는데 도움이 될만한 좋은 내용들이었다.&lt;/p&gt;
&lt;h2 id=&quot;테크-챗&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%ED%81%AC-%EC%B1%97&quot; aria-label=&quot;테크 챗 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테크 챗&lt;/h2&gt;
&lt;p&gt;발표도 너무 좋았지만 테크 챗도 너무 좋았다. 내가 고민하고 있는 부분들을 직접 물어보고 조언을 구할 수 있기 때문이다. 카카오페이는 사전접수, 인프랩은 현장접수로 진행할 수 있었다. 😆&lt;/p&gt;
&lt;p&gt;기획부터 배포까지의 사이클이 어떻게 진행되는지, 테스트 코드 작성, 팀 규모, api 명세, 팀 분위기 등에 대한 이야기를 나눴다. 카카오페이 개발자분은 같은 연차셔서 경험적인 부분에서는 공감하는 부분이 많았다. 인프랩 개발자분은 연차가 더 높으셔서 너무나 좋은 인사이트를 공유해주셨다.&lt;/p&gt;
&lt;p&gt;테크 챗을 진행하면서 고민하고 있던 부분들 중 많은 게 해소됐고 시간 가는 줄 모르고 너무 재미있게 얘기를 나눌 수 있어 좋았다.&lt;/p&gt;
&lt;h2 id=&quot;네트워킹&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9&quot; aria-label=&quot;네트워킹 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;네트워킹&lt;/h2&gt;
&lt;p&gt;MBTI ISTP인 나에게 네트워킹 시간은 아직도 어렵다. 남들이 먼저 얘기하고 있으면 그 자리에 끼는 게 나는 너무나 어렵다. 이번에는 인프랩 직원분들이 도와주신다고 해서 그래도 괜찮지 않을까 기대하고 들어갔는데 다행히 인싸 직원분께서 프론트엔드 써클에 넣어주셔서 한 8분 정도의 개발자분들과 얘기를 나눌 수 있었다. 먼저 &lt;code class=&quot;language-text&quot;&gt;내가 개발하는 서비스 코멘토를 사용해보셨던 유저분&lt;/code&gt;이 계셔서 뿌듯했다. 😎&lt;/p&gt;
&lt;p&gt;보통의 경우 다른 분들의 얘기를 들었었는데 이번에는 반대였다. 내가 연차가 가장 많았어서 😱 다른 개발자분들이 막 질문을 하셔서 긴장됐다. 😂 얘기를 많이 해서 오히려 좋았고 다른 저연차 개발자분들은 이런게 궁금하시구나 싶었다. &lt;code class=&quot;language-text&quot;&gt;도움이 됐으면 좋겠다.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;혹시라도 이 글을 보고 계신분들 중에도 저랑 커피챗 하시고 싶으신 분들은 언제나 환영입니다 :) 아래 메일로 남겨주세요!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;mailto:thdehdgns@gmail.com&quot;&gt;thdehdgns@gmail.com&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;특히-좋았던-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8A%B9%ED%9E%88-%EC%A2%8B%EC%95%98%EB%8D%98-%EC%A0%90&quot; aria-label=&quot;특히 좋았던 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;특히 좋았던 점&lt;/h2&gt;
&lt;h3 id=&quot;발표주제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%9C%ED%91%9C%EC%A3%BC%EC%A0%9C&quot; aria-label=&quot;발표주제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;발표주제&lt;/h3&gt;
&lt;p&gt;발표 주제들이 대부분 발표자분들의 경험에서 우러나온 것들이어서 특히 좋았다. 그래서 발표자분들만의 고유한 이야기가 된 거 같다.&lt;/p&gt;
&lt;h3 id=&quot;시간배분&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%9C%EA%B0%84%EB%B0%B0%EB%B6%84&quot; aria-label=&quot;시간배분 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;시간배분&lt;/h3&gt;
&lt;p&gt;전체적인 발표 세션을 40분으로 잡아놓고, 실제 발표 20분, QnA시간 20분을 배정한 게 좋았다. 쉬는 시간도 20분으로 넉넉해서 숨을 좀 돌리거나(연속으로 발표를 듣는건 은근 힘들다) 화장실에 가기 충분한 시간이었다.&lt;/p&gt;
&lt;h3 id=&quot;qna&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#qna&quot; aria-label=&quot;qna permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;QnA&lt;/h3&gt;
&lt;p&gt;보통 발표가 끝나면 다음 발표가 이어지기도 하고, 발표자분께 가서 따로 물을 환경이 안되면 연락하기가 힘든데, 발표가 끝나고 깃발을 든 직원분을 따라가면 QnA 장소에서 더 궁금했던 것을 편하게 물어볼 수 있어서 너무 좋았다.&lt;/p&gt;
&lt;h3 id=&quot;네트워킹-경험&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9-%EA%B2%BD%ED%97%98&quot; aria-label=&quot;네트워킹 경험 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;네트워킹 경험&lt;/h3&gt;
&lt;p&gt;네트워킹에서 스티커로 명찰을 꾸밀 수 있었는데 &lt;code class=&quot;language-text&quot;&gt;말 걸어주세요&lt;/code&gt; 스티커가 보여서 취향저격 당했었다. 😂 네트워킹이 어려운 사람들을 많이 배려해주신 모습이라고 생각했고, 직원분들께서 네트워킹을 도와주셔서 너무 편했다. 테크챗을 하고 나서 가서 시간이 많지 않았는데 재밌어서 시간가는 줄 모르고 대화하니까 정말 빨리 지나갔다.&lt;/p&gt;
&lt;h2 id=&quot;아쉬웠던-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%95%84%EC%89%AC%EC%9B%A0%EB%8D%98-%EC%A0%90&quot; aria-label=&quot;아쉬웠던 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;아쉬웠던 점&lt;/h2&gt;
&lt;p&gt;점심시간이 조금 아쉬웠다. 특이 케이스긴 하지만 나의 경우는 점심 시간 전 세션에서 QnA까지 진행했는데 끝나니까 1시 40분으로 점심시간을 20분만 쓸 수 있었다. 그렇다고 QnA를 포기할 수는 없었다. 너무 좋은 말씀을 많이 해주셔서 엄청나게 도움이 됐다. 😱&lt;/p&gt;
&lt;p&gt;시간보다도 광활한 코엑스에서 밥집을 찾아서 식사를 해결하는 게 시간이 조금 걸렸다. 다른 분들 얘기를 들어보니까 인파가 한번에 몰려서 줄을 서기도 했다고 하셨다. 그리고 그쪽 물가가 비싸기도 하다. 🥲&lt;/p&gt;
&lt;p&gt;도시락을 한번에 주문해서 제공하면 불편함도 줄이고, 식사하면서 자연스럽게 네트워킹 하시는 분들이 계실 수도 있고, 비용도 덜 수 있지 않을까 하는 아이디어가 생각났다.&lt;/p&gt;
&lt;h2 id=&quot;행사-풍경&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%96%89%EC%82%AC-%ED%92%8D%EA%B2%BD&quot; aria-label=&quot;행사 풍경 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;행사 풍경&lt;/h2&gt;
&lt;p&gt;리코gr3 똑딱이 카메라를 오랜만에 들고 갔다. 그냥 잠깐잠깐 허리춤에서 꺼내서 찍느라고 구도가 이쁘거나 하지 않다. 날것의 시선이었다. 사람이 너무 많아 많이 찍지도 않았다.&lt;/p&gt;
&lt;p&gt;현장을 가니까 전문 작가분들이 사진부터 동영상까지 전담하고 계셔서 멋있다고 생각이 들었다. 저번 엑셀콘에서는 내가 사진을 찍고 있었는데 역시 인프콘이다 싶었다 👍 발표 중간에 사진 찍으려고 포지션 잡는 작가님들을 보면서 이런 위치에서 이런 각으로 찍으시는구나 슬쩍슬쩍 보기도 했다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAD/9oADAMBAAIQAxAAAAHMaVvQECIT/wD/xAAaEAACAgMAAAAAAAAAAAAAAAAAAQIDECIy/9oACAEBAAEFAqFs4kuqxvH/xAAWEQADAAAAAAAAAAAAAAAAAAACEDL/2gAIAQMBAT8BOl//xAAXEQADAQAAAAAAAAAAAAAAAAACEBEx/9oACAECAQE/AQyr/8QAFhAAAwAAAAAAAAAAAAAAAAAAARAg/9oACAEBAAY/AkY//8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERITFRYZH/2gAIAQEAAT8ha2nR4CSzpSelI8n/2gAMAwEAAgADAAAAEBz/AP/EABgRAQEAAwAAAAAAAAAAAAAAAAEAETFR/9oACAEDAQE/ECuHI1f/xAAYEQACAwAAAAAAAAAAAAAAAAAAAREhYf/aAAgBAgEBPxBI0G7P/8QAHBABAAIDAAMAAAAAAAAAAAAAAQARITFBUWHw/9oACAEBAAE/EGVXoXqNloPSnEEh2uy117BjH24qRCraPEVpez//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 팜플렛&quot;
        title=&quot;&quot;
        src=&quot;/static/75101236b1347cb366b13f027316db85/e5166/infcon-2023-pamphlet.jpg&quot;
        srcset=&quot;/static/75101236b1347cb366b13f027316db85/f93b5/infcon-2023-pamphlet.jpg 300w,
/static/75101236b1347cb366b13f027316db85/b4294/infcon-2023-pamphlet.jpg 600w,
/static/75101236b1347cb366b13f027316db85/e5166/infcon-2023-pamphlet.jpg 1200w,
/static/75101236b1347cb366b13f027316db85/d9c39/infcon-2023-pamphlet.jpg 1800w,
/static/75101236b1347cb366b13f027316db85/e1596/infcon-2023-pamphlet.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQL/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB3tNbMo8l/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAAwQREyH/2gAIAQEAAQUCRlEGSOpvr2jw1jp5P//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AUf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAQIhEBExEv/aAAgBAQAGPwJO5MfparHCUjh//8QAGxAAAwEBAAMAAAAAAAAAAAAAAAERITFxgZH/2gAIAQEAAT8hxzBEzTnDPJQ78LNKFqEqPUFCg//aAAwDAQACAAMAAAAQpN//xAAWEQADAAAAAAAAAAAAAAAAAAABEDH/2gAIAQMBAT8QEX//xAAXEQEAAwAAAAAAAAAAAAAAAAAAAREx/9oACAECAQE/EJ1V/8QAHBABAQACAgMAAAAAAAAAAAAAAREAIUFRMWFx/9oACAEBAAE/EFgsCCt+YlZQ1dbe+ccgIrKr5yFEG7zbAoNCGxwDgy7s5XjP/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 포토존&quot;
        title=&quot;&quot;
        src=&quot;/static/7b0b2770b068b64a78574367ae5eb226/e5166/infcon-2023-photo-zone.jpg&quot;
        srcset=&quot;/static/7b0b2770b068b64a78574367ae5eb226/f93b5/infcon-2023-photo-zone.jpg 300w,
/static/7b0b2770b068b64a78574367ae5eb226/b4294/infcon-2023-photo-zone.jpg 600w,
/static/7b0b2770b068b64a78574367ae5eb226/e5166/infcon-2023-photo-zone.jpg 1200w,
/static/7b0b2770b068b64a78574367ae5eb226/d9c39/infcon-2023-photo-zone.jpg 1800w,
/static/7b0b2770b068b64a78574367ae5eb226/e1596/infcon-2023-photo-zone.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAv/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABTueuFgZf/8QAGhABAAIDAQAAAAAAAAAAAAAAAgMRAAESIf/aAAgBAQABBQJSGvNLuM41WcFkRar/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwGH/8QAHhAAAgEDBQAAAAAAAAAAAAAAAAEhAhESIjFRYXH/2gAIAQEABj8C1ppo3jkinLsUF2h+n//EABwQAAMAAgMBAAAAAAAAAAAAAAABETFRQYGRsf/aAAgBAQABPyFy8JOZEpHbacmE0IIW7Em8LO6fp//aAAwDAQACAAMAAAAQtO//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQMBAT8QFy2//8QAFhEAAwAAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/EGlIf//EABwQAQACAwADAAAAAAAAAAAAAAERMQAhQVFxsf/aAAgBAQABPxAtpkdafScKDMhIQike+soTtHXDXwpSxrSeHE3CgpALF4umATVEs//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 라운지1&quot;
        title=&quot;&quot;
        src=&quot;/static/f3bc23542819f9cd3436d79d75aa3fa8/e5166/infcon-2023-lounge-1.jpg&quot;
        srcset=&quot;/static/f3bc23542819f9cd3436d79d75aa3fa8/f93b5/infcon-2023-lounge-1.jpg 300w,
/static/f3bc23542819f9cd3436d79d75aa3fa8/b4294/infcon-2023-lounge-1.jpg 600w,
/static/f3bc23542819f9cd3436d79d75aa3fa8/e5166/infcon-2023-lounge-1.jpg 1200w,
/static/f3bc23542819f9cd3436d79d75aa3fa8/d9c39/infcon-2023-lounge-1.jpg 1800w,
/static/f3bc23542819f9cd3436d79d75aa3fa8/e1596/infcon-2023-lounge-1.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABSudXiBmh/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAEQMSIRP/2gAIAQEAAQUCXoC6z3WAUOHG603/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAdEAADAAAHAAAAAAAAAAAAAAAAARECEiExQWGR/9oACAEBAAY/AnYhZtjQ48EsSvZD/8QAHBAAAwACAwEAAAAAAAAAAAAAAAERIXExUWGh/9oACAEBAAE/IeMQVqx8GO26jRhE0do2Jcb1kpUf/9oADAMBAAIAAwAAABBjz//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/EFWf/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEB/9oACAECAQE/EJiP/8QAHBABAQADAQADAAAAAAAAAAAAAREAITFBUWGB/9oACAEBAAE/ENEVsaugfq4kSEEDd+MdhHtM3EqFh5zkxdRqlwK37wDEhy5//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 라운지2&quot;
        title=&quot;&quot;
        src=&quot;/static/319043dfa7eb6981c596ef3a40da0e39/e5166/infcon-2023-lounge-2.jpg&quot;
        srcset=&quot;/static/319043dfa7eb6981c596ef3a40da0e39/f93b5/infcon-2023-lounge-2.jpg 300w,
/static/319043dfa7eb6981c596ef3a40da0e39/b4294/infcon-2023-lounge-2.jpg 600w,
/static/319043dfa7eb6981c596ef3a40da0e39/e5166/infcon-2023-lounge-2.jpg 1200w,
/static/319043dfa7eb6981c596ef3a40da0e39/7d013/infcon-2023-lounge-2.jpg 1343w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACA//EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/aAAwDAQACEAMQAAABC7fSJYVi/8QAGxAAAwACAwAAAAAAAAAAAAAAAAECAwQREiH/2gAIAQEAAQUCcdCHJWz7GKSoQ4XP/8QAFxEAAwEAAAAAAAAAAAAAAAAAAQIQIf/aAAgBAwEBPwFtE//EABYRAAMAAAAAAAAAAAAAAAAAAAEQIf/aAAgBAgEBPwERf//EABcQAAMBAAAAAAAAAAAAAAAAAAABISD/2gAIAQEABj8CrRGTH//EABkQAQADAQEAAAAAAAAAAAAAAAEAESFBgf/aAAgBAQABPyG2+ggaLq2EZCcghwgDKINWT//aAAwDAQACAAMAAAAQZA//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPxArE//EABYRAQEBAAAAAAAAAAAAAAAAAAEAIf/aAAgBAgEBPxBisv/EAB0QAQEAAgIDAQAAAAAAAAAAAAERACFBUTFhodH/2gAIAQEAAT8QEJIhdTfrvnEihLZFE6xna7TyYSDDvd/cExAkDz9w7ptdM5z/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 라운지3&quot;
        title=&quot;&quot;
        src=&quot;/static/4563c408b319a5f85e1604afde348e2c/e5166/infcon-2023-lounge-3.jpg&quot;
        srcset=&quot;/static/4563c408b319a5f85e1604afde348e2c/f93b5/infcon-2023-lounge-3.jpg 300w,
/static/4563c408b319a5f85e1604afde348e2c/b4294/infcon-2023-lounge-3.jpg 600w,
/static/4563c408b319a5f85e1604afde348e2c/e5166/infcon-2023-lounge-3.jpg 1200w,
/static/4563c408b319a5f85e1604afde348e2c/d6bfc/infcon-2023-lounge-3.jpg 1363w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQL/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAP/2gAMAwEAAhADEAAAAWdyY85hZL//xAAbEAACAgMBAAAAAAAAAAAAAAABAgMRAAQSE//aAAgBAQABBQI+dgoDLGGkYdS7NK3VZ//EABgRAAMBAQAAAAAAAAAAAAAAAAABAhEh/9oACAEDAQE/AYeSjp//xAAXEQEBAQEAAAAAAAAAAAAAAAABAAIR/9oACAECAQE/AXPWDN//xAAaEAADAQADAAAAAAAAAAAAAAAAARECEFGB/9oACAEBAAY/ApvLvZExvLiPBxcf/8QAGRABAAMBAQAAAAAAAAAAAAAAAQARQSFR/9oACAEBAAE/Ibxoa+Qkqn3JZsHY4doByAQitl+J/9oADAMBAAIAAwAAABBTH//EABgRAAIDAAAAAAAAAAAAAAAAAAABESEx/9oACAEDAQE/ELkNzw//xAAXEQEBAQEAAAAAAAAAAAAAAAABABEh/9oACAECAQE/EGcLD1b/xAAdEAACAgIDAQAAAAAAAAAAAAABEQAhMVFhcZHh/9oACAEBAAE/EANiARIXq+uYXyxB3wW5aEJALOxeIJi4CjdnyHygApmx8gr0QMOf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 라운지4&quot;
        title=&quot;&quot;
        src=&quot;/static/be4b040b9ea682703b1d45782b570cff/e5166/infcon-2023-lounge-4.jpg&quot;
        srcset=&quot;/static/be4b040b9ea682703b1d45782b570cff/f93b5/infcon-2023-lounge-4.jpg 300w,
/static/be4b040b9ea682703b1d45782b570cff/b4294/infcon-2023-lounge-4.jpg 600w,
/static/be4b040b9ea682703b1d45782b570cff/e5166/infcon-2023-lounge-4.jpg 1200w,
/static/be4b040b9ea682703b1d45782b570cff/d9c39/infcon-2023-lounge-4.jpg 1800w,
/static/be4b040b9ea682703b1d45782b570cff/e1596/infcon-2023-lounge-4.jpg 2048w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;얼굴이 나오는 사진은 블러처리를 했는데 혹시라도 문제가 있다면 알려주시면 감사하겠습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;굿즈-모음&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%BF%EC%A6%88-%EB%AA%A8%EC%9D%8C&quot; aria-label=&quot;굿즈 모음 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;굿즈 모음&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1200px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAQADBP/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/aAAwDAQACEAMQAAABzRMXLPP/xAAaEAABBQEAAAAAAAAAAAAAAAAAAQIREjEh/9oACAEBAAEFAly0Fx/Bwu//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAWEQEBAQAAAAAAAAAAAAAAAAAAASH/2gAIAQIBAT8BrH//xAAYEAACAwAAAAAAAAAAAAAAAAAQICFBgf/aAAgBAQAGPwKbTB//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhUTFBgaH/2gAIAQEAAT8hXSp9SwF8CCMBg2TgrUVrcPOf/9oADAMBAAIAAwAAABB/P//EABYRAAMAAAAAAAAAAAAAAAAAAAABIf/aAAgBAwEBPxBOlP/EABcRAQEBAQAAAAAAAAAAAAAAAAEAIVH/2gAIAQIBAT8QODDxf//EAB0QAQACAQUBAAAAAAAAAAAAAAEAESExQVFhoeH/2gAIAQEAAT8QFdIObQFexY4XwE7fnUGTqIa+sAjgJv2ILI5F7RqLQMFYn//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;인프콘 라운지4&quot;
        title=&quot;&quot;
        src=&quot;/static/cde01ca2352fa203d2a54d76659e1241/e5166/infcon-2023-goods.jpg&quot;
        srcset=&quot;/static/cde01ca2352fa203d2a54d76659e1241/f93b5/infcon-2023-goods.jpg 300w,
/static/cde01ca2352fa203d2a54d76659e1241/b4294/infcon-2023-goods.jpg 600w,
/static/cde01ca2352fa203d2a54d76659e1241/e5166/infcon-2023-goods.jpg 1200w,
/static/cde01ca2352fa203d2a54d76659e1241/d9c39/infcon-2023-goods.jpg 1800w,
/static/cde01ca2352fa203d2a54d76659e1241/df51d/infcon-2023-goods.jpg 2400w,
/static/cde01ca2352fa203d2a54d76659e1241/8ec0a/infcon-2023-goods.jpg 2560w&quot;
        sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;굿즈가 너무 푸짐해서 어깨가 아팠다. 😂&lt;/p&gt;
&lt;p&gt;스탬프 찍으러 부스에 가면 받을 수 있었는데 귀염뽀짝한 스티커부터 티셔츠, 수건, 키보드 덮개, 안경닦이, 칫솔세트, 키캡, 썬스틱, 부채 등 실용적인 굿즈까지 너무 좋았다. ☺️&lt;/p&gt;</content:encoded></item><item><title><![CDATA[쉽게 시작하는 타입스크립트 책 리뷰]]></title><description><![CDATA[캡틴판교님이 쓰신 쉽게 시작하는 타입스크립트 책을 리뷰하려고 합니다. 🥰 독자(나)의 수준 실무에서 메인 프로젝트에는 도입하려다가 에러가 너무 많이 나서 보류했고(nuxt…]]></description><link>https://donghoon-song.github.io/books/쉽게-시작하는-타입스크립트-책-리뷰/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/쉽게-시작하는-타입스크립트-책-리뷰/</guid><pubDate>Sat, 12 Aug 2023 09:09:32 GMT</pubDate><content:encoded>&lt;div style=&quot;display: flex; flex-direction:column; align-items:center&quot;&gt;
&lt;img src=&quot;https://contents.kyobobook.co.kr/sih/fit-in/458x0/pdt/addt/9791140704750_01.jpg&quot; width=&quot;50%&quot; style=&quot;margin: 0 auto 8px auto&quot;&gt;
&lt;/div&gt;
&lt;p&gt;캡틴판교님이 쓰신 쉽게 시작하는 타입스크립트 책을 리뷰하려고 합니다. 🥰&lt;/p&gt;
&lt;h3 id=&quot;독자나의-수준&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8F%85%EC%9E%90%EB%82%98%EC%9D%98-%EC%88%98%EC%A4%80&quot; aria-label=&quot;독자나의 수준 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;독자(나)의 수준&lt;/h3&gt;
&lt;p&gt;실무에서 메인 프로젝트에는 도입하려다가 에러가 너무 많이 나서 보류했고(nuxt는 웁니다), 서브 프로젝트, 사이드 프로젝트에서는 조금 써봤던 정도의 수준이기에 &lt;code class=&quot;language-text&quot;&gt;입문자&lt;/code&gt; 정도라고 생각합니다.&lt;/p&gt;
&lt;h3 id=&quot;좋았던-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A2%8B%EC%95%98%EB%8D%98-%EC%A0%90&quot; aria-label=&quot;좋았던 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;좋았던 점&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;글과 함께 실려있는 &lt;code class=&quot;language-text&quot;&gt;많은 이미지들&lt;/code&gt;이 도움이 많이 됐습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;책이나 블로그에서 타입스크립트를 마주하면 텍스트만 있는 경우가 대부분이었는데, 이 책은 코드를 IDE나 플레이그라운드에 직접 작성하고 보여지는 &lt;code class=&quot;language-text&quot;&gt;에러 밑줄, 툴팁 등&lt;/code&gt;을 같이 첨부해줘서 내용을 이해하기 수월했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이미지 외에도 새로운 개념이 나타났을 때 &lt;code class=&quot;language-text&quot;&gt;부연설명이 자세&lt;/code&gt;해서 따로 검색해보지 않아도 책을 읽는데 문제가 없었습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;예시들이 실무에 가깝습니다.&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;책을 읽다가 &lt;code class=&quot;language-text&quot;&gt;이런 부분은 프로젝트에 이렇게 적용해보면 되겠다.&lt;/code&gt; 하는 부분들이 많았습니다.&lt;/li&gt;
&lt;li&gt;특히 Partial 유틸리티 타입은 처음 알았는데 너무 편해보였습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;개념 설명에 끝나지 않고, &lt;code class=&quot;language-text&quot;&gt;이 개념의 장단점은 이런데 이런 상황에서 쓰면 더 좋다&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;이 개념이 꼭 필요한 이유 등 사용해야 하는 이유&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;활용방법&lt;/code&gt;에 대해서 같이 고민해볼 수 있어서 좋았습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;앞에서 배운 내용을 바로 써 볼 수 있는 실습&lt;/code&gt;이 제공되어서 도움이 많이 됐습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;타입스크립트 설정 부분에서 속성 하나하나 자세한 설명이 있어서 좋았고, &lt;code class=&quot;language-text&quot;&gt;실무에선 어떤 식으로 활용하는지&lt;/code&gt;도 나와있어 좋았습니다. 설정 속성이 궁금해서 찾아봐도 내용이 너무 간결하거나, 읽어도 이해 안됐던 적이 많았는데 이 책을 통해서 확실히 이해할 수 있었습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;뒷 부분에 있는 외부 라이브러리 타입 정의 방법 등 &lt;code class=&quot;language-text&quot;&gt;저자분의 경험이 녹아 있는 꿀팁들&lt;/code&gt;도 정말 도움이 많이 됐습니다. “와 이런게 있구나”하면서 재미있게 읽었습니다 😂.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;추천하는-대상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%94%EC%B2%9C%ED%95%98%EB%8A%94-%EB%8C%80%EC%83%81&quot; aria-label=&quot;추천하는 대상 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;추천하는 대상&lt;/h3&gt;
&lt;p&gt;그래서 저는 타입스크립트를 막 시작하는 입문자분들이나 이미 사용하고 계신 분들도 읽으시면 많이 배우실거라고 생각합니다.&lt;/p&gt;
&lt;h3 id=&quot;구매-링크&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%EB%A7%A4-%EB%A7%81%ED%81%AC&quot; aria-label=&quot;구매 링크 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;구매 링크&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000202595007&quot;&gt;교보문고&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/119410497&quot;&gt;yes24&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.aladin.co.kr/m/mproduct.aspx?ItemId=318151378&quot;&gt;알라딘&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[supabase + typescript DB schema 연동하기]]></title><description><![CDATA[이슈 supabase로 사이드 프로젝트를 하고 있다. Talk table에서 데이터를 가져오기 위해 interface를 선언했고 ref에 generic으로 넘겼다. 예시 코드는 vue3 + typescript 환경이다. supabase…]]></description><link>https://donghoon-song.github.io/supabase/supabase-+-typescript-db-schema-연동하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/supabase/supabase-+-typescript-db-schema-연동하기/</guid><pubDate>Sun, 23 Jul 2023 21:07:45 GMT</pubDate><content:encoded>&lt;h2 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h2&gt;
&lt;p&gt;supabase로 사이드 프로젝트를 하고 있다. Talk table에서 데이터를 가져오기 위해 interface를 선언했고 ref에 generic으로 넘겼다.&lt;/p&gt;
&lt;p&gt;예시 코드는 vue3 + typescript 환경이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Talk&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
  speaker_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  topic&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  created_at&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  duration&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; talkList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Talk&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;supabase를 이용한 select 결과에서 data를 검사하면 string key와 any value를 가지는 일반적인 타입으로 추론되는 것을 확인할 수 있다.
&lt;img src=&quot;https://i.imgur.com/mL94ZOM.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그래서 Talk interface와 맞지 않기 때문에 타입 에러가 난다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/cRq3acO.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;설령 data type을 단언한다 해도, DB schema가 변하면 다시 작성해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결&lt;/h2&gt;
&lt;p&gt;supabase-cli를 활용하면 DB schema를 추출해 supabase sdk와 연동할 수 있다.
아래 링크를 보면 쉽게 따라갈 수 있다.
&lt;a href=&quot;https://supabase.com/docs/guides/api/rest/generating-types&quot;&gt;https://supabase.com/docs/guides/api/rest/generating-types&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PROJECT_REF를 찾는 게 처음에 어려웠는데, supabase dashboard를 들어간 후에 url에서 project 뒤에 오는 부분을 PROJECT_REF 칸에 넣어주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;https://supabase.com/dashboard/project/$PROJECT_REF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx supabase gen types typescript --project-id &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$PROJECT_REF&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--schema&lt;/span&gt; public &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; src/types/supabase.ts&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;생성된 Database interface를 generic으로 넘긴다.
&lt;img src=&quot;https://i.imgur.com/rb7KkVs.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 적용하고 기존 코드를 다시 보면 data 타입이 바뀐 것을 볼 수 있다!
&lt;img src=&quot;https://i.imgur.com/BDmN0eY.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;기존에 선언했던 Talk interface는 다음과 같이 Database interface에서 꺼내온 것으로 대체할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /types/talk.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Database &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./supabase&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Talk&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Database&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;public&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Tables&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;talk&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Row&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[회의실 예약 시스템을 내렸습니다.]]></title><description><![CDATA[이전 포스트에서 회의실 예약 시스템을 만들어서 팀 내 시스템 문제를 해결하려고 했다. 그리고 이 글을 여러군데에 올렸는데, 생활코딩에서 내 글을 본 동료 개발자분에게 카톡이 왔다. image 내가 아는 구글 캘린더에서 위치, 메모, URL…]]></description><link>https://donghoon-song.github.io/maker-log/회의실-예약-시스템을-내렸습니다./</link><guid isPermaLink="false">https://donghoon-song.github.io/maker-log/회의실-예약-시스템을-내렸습니다./</guid><pubDate>Tue, 18 Jul 2023 23:08:21 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://donghoon-song.github.io/maker-log/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A1%9C-%EC%97%85%EB%AC%B4-%EB%B6%88%ED%8E%B8%ED%95%A8-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0/&quot;&gt;이전 포스트&lt;/a&gt;에서 회의실 예약 시스템을 만들어서 팀 내 시스템 문제를 해결하려고 했다.&lt;/p&gt;
&lt;p&gt;그리고 이 글을 여러군데에 올렸는데, 생활코딩에서 내 글을 본 동료 개발자분에게 카톡이 왔다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/Paf3B6J.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;내가 아는 구글 캘린더에서 위치, 메모, URL은 추가해봤는데 회의실 기능은 처음 들어봤다. 그래서 관련 문서를 열심히 찾아봤다.&lt;/p&gt;
&lt;p&gt;먼저 건물을 추가해야 회의실을 추가할 수 있는데 &lt;a href=&quot;https://admin.google.com/Dashboard?hl=ko&quot;&gt;구글 관리 콘솔&lt;/a&gt;에 관리자 계정으로 로그인하고 &lt;a href=&quot;https://support.google.com/a/answer/1033925?sjid=16151968928702818978-AP&quot;&gt;캘린더 건물, 기능, 캘린더 리소스 만들기&lt;/a&gt;를 따라 추가하면 금방 한다.&lt;/p&gt;
&lt;p&gt;그렇게 작고 소중한 회의실 2개를 추가할 수 있었고&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/WMtBqxk.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;팀원들에게 빠르게 이 사실을 알려주었다. &lt;code class=&quot;language-text&quot;&gt;회의실 예약 시스템을 공개한지 단 이틀만이다 😅&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/x0KK2AD.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;기존 문제는 그대로 해결할 수 있고, 구글 캘린더 연동 기능은 생각도 하지 않아도 되니 너무 좋은 발견이었다.&lt;/p&gt;
&lt;p&gt;소중한 사이드 프로젝트를 내려야 해서 조금 아쉬웠지만 나는 &lt;code class=&quot;language-text&quot;&gt;다른 문제를 해결하는데 시간을 쓸 수 있다&lt;/code&gt;는 생각이 더 앞섰다. 풀어야 할 문제는 많으니까.&lt;/p&gt;
&lt;h3 id=&quot;글을-쓰는건-부끄럽지만-도움이-된다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EC%9D%84-%EC%93%B0%EB%8A%94%EA%B1%B4-%EB%B6%80%EB%81%84%EB%9F%BD%EC%A7%80%EB%A7%8C-%EB%8F%84%EC%9B%80%EC%9D%B4-%EB%90%9C%EB%8B%A4&quot; aria-label=&quot;글을 쓰는건 부끄럽지만 도움이 된다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글을 쓰는건 부끄럽지만 도움이 된다&lt;/h3&gt;
&lt;p&gt;사실 내가 뭐 대단한 걸 해서 글을 쓰고 여기저기 올리는 것은 아니다. 잘 쓰는 것도 아니도 그렇게 깊지도 길지도 않다. 작은 경험이라도 누군가에겐 재미있고 도움이 되지 않을까 해서 올리는건데 이 글을 올리지 않았다면 나는 예약 시스템을 머리 싸매고 열심히 개발하고 있었을 것이다.&lt;/p&gt;
&lt;p&gt;저번에도 &lt;a href=&quot;https://donghoon-song.github.io/supabase/db-trigger%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%B4-supabase-signUp-%ED%9B%84%EC%97%90--users-table%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0/&quot;&gt;트리거 관련 글&lt;/a&gt;을 썼다가 어떤 개발자님께서 댓글을 달아주신 적도 있다. 내 친구 개발자도, 아는 개발자분도 현업에서 trigger가 어떻게 쓰이는지 내 글을 보고 알려주셨다. 프론트 개발자인 나는 아마 평생 몰랐을 지식이었을 것이다.&lt;/p&gt;
&lt;p&gt;카톡을 보내준 갓개발자님께 감사드리며 이 글을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[주니어 프론트엔드 개발자의 6월 회고]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/feedback/주니어-프론트엔드-개발자의-6월-회고/</link><guid isPermaLink="false">https://donghoon-song.github.io/feedback/주니어-프론트엔드-개발자의-6월-회고/</guid><pubDate>Sun, 09 Jul 2023 22:08:29 GMT</pubDate><content:encoded>&lt;h2 id=&quot;회사에서의-나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%9A%8C%EC%82%AC%EC%97%90%EC%84%9C%EC%9D%98-%EB%82%98&quot; aria-label=&quot;회사에서의 나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;회사에서의 나&lt;/h2&gt;
&lt;h3 id=&quot;-업무&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%97%85%EB%AC%B4&quot; aria-label=&quot; 업무 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🧑🏻‍💻 업무&lt;/h3&gt;
&lt;p&gt;커뮤니티 광고 구좌를 만들기 위해서 여러 곳에 광고를 넣어보고 클릭 전환율을 측정하는 실험을 디자이너님과 진행했다. 아직 측정 중인 실험도 있고 가드레일 지표가 무너져서 실패한 실험들도 있다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;무작정 광고를 추가하기보다는 먼저 실험해 본 경험&lt;/code&gt;이 좋았다. 생각 외로 가드레일 지표가 무너져 버렸던 점도 인상 깊었다.&lt;/p&gt;
&lt;p&gt;데이터 분석을 더 정교하게 하기 위한 gtm 수정 작업을 했고 데이터 이관 작업 때문에 스쿼드가 정신없었다.&lt;/p&gt;
&lt;h3 id=&quot;-스터디&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%8A%A4%ED%84%B0%EB%94%94&quot; aria-label=&quot; 스터디 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📝 스터디&lt;/h3&gt;
&lt;p&gt;프론트팀 javascript 스터디를 완주했다. 👏 알다가도 모를 javascript를 조금 덜 헷갈리게 해 준 스터디였다. 7월에 전체적으로 한 번 더 봐야겠다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;진행하다가 흐지부지된 스터디들도 있었기에 뿌듯했다. 스터디를 이어 나가는 게 참 어렵다. 학습자료의 분량, 난이도, 스터디 방식 등 생각해야 할 것들이 많다. &lt;code class=&quot;language-text&quot;&gt;이것저것 하다 보면 그래도 성공률이 높은 데이터들이 남아 있을 것이다.&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;-메이커로서의-나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%A9%94%EC%9D%B4%EC%BB%A4%EB%A1%9C%EC%84%9C%EC%9D%98-%EB%82%98&quot; aria-label=&quot; 메이커로서의 나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;👨🏻‍🔧 메이커로서의 나&lt;/h2&gt;
&lt;p&gt;메이커로서의 역량을 키우고 싶다. 내가 생각하는 걸 빠르게 구현하는 능력을 갖추는 게 목표다. 그래야 문제를 맞닥뜨렸을 때 잘 해결할 수 있기 때문이라고 생각한다. 또한 여러 가지 문제 상황에 노출되면서 내가 성장할 수 있다고 믿고 있다.&lt;/p&gt;
&lt;p&gt;그렇게 혼자 처음 만든 고무 오리 앱이 아래 있다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://my-rubber-duck.vercel.app&quot;&gt;궁금하시다면 ☺️&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;혼자서 기획, 디자인하는 게 정말 어렵다. “이게 최선인가?” 계속 되묻지만, 아직 “예”라는 답이 나오려면 멀었다. 아무래도 피그마를 다뤄야 할 거 같아서 유튜브에서 열심히 공부했는데 간단한 걸 만드는 데 큰 도움이 되었다.&lt;/p&gt;
&lt;p&gt;사람들에게 공개했을 때 반응은&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;무슨 앱인지 모르겠다.&lt;/li&gt;
&lt;li&gt;왜 써야 하는지 모르겠다. (from INTP 동료)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1은 내가 예상했던 것과 다른 반응이었다. 고무 오리 앱에 대한 개념이 사람들에게 생소한 것일 줄은 몰랐는데 나의 착각이었다.&lt;/p&gt;
&lt;p&gt;2는 친한 동료분께서 말해주신 피드백이다. 차갑게 들릴 수 있는데 나는 괜찮다 😂. 나는 입에 발린 말보다 쓴소리를 좋아하는 사람이기 때문. 맞는 말이다. 아직 &lt;code class=&quot;language-text&quot;&gt;&quot;굳이 브라우저를 켜서 여기 왜 들어와야 하는가?&quot;&lt;/code&gt;하고 물어봤을 때 대답하지 못한다. 그 경험을 찾는 여정이 될 거 같다.&lt;/p&gt;
&lt;p&gt;배운 점을 요약하면 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;회사 밖 환경에서 혼자 만드는 스킬은 숙련되지 않았다.&lt;/li&gt;
&lt;li&gt;배포하고 사람들의 반응을 봐야 한다. 그래야 내 착각들이 깨진다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;-대외활동&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%8C%80%EC%99%B8%ED%99%9C%EB%8F%99&quot; aria-label=&quot; 대외활동 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🐥 대외활동&lt;/h3&gt;
&lt;p&gt;여름엔 무지하게 더우니까, 사진 찍는 건 엄두가 안 나고 에어컨 바람 맞으면서 코딩을 열심히 하려고 생각했다. 좋은 동료들과 함께 프로덕트를 만들어 보고 싶은 마음에 IT 동아리를 지원했는데 아쉽게도 함께 하지 못했다. 면접을 못 본 게 아니어서 더욱 아쉬웠는데 어쩌겠나. 다음 기수에 다시 지원해야겠다는 생각이 들었다. 그 엄청난 경쟁률을 뚫으려면 더 열심히 해야겠다는 생각이 들었다. 그리고 오랜만에 면접을 본 경험도 좋았다. 내가 알고 있는 걸 잘 말할 수 있도록 더 연습해야겠다.&lt;/p&gt;
&lt;h3 id=&quot;-모임&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%AA%A8%EC%9E%84&quot; aria-label=&quot; 모임 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📖 모임&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/119108069&quot;&gt;필독! 개발자 온보딩 가이드&lt;/a&gt;라는 책을 읽고 있었는데 마침 이 책을 가지고 열린 독서 모임이 있어서 참여해 봤다. 친구들이랑 개발 서적 스터디를 했을 때 서로의 생각과 경험을 공유했던 점이 좋았었기 때문이다. 다양한 직군과 연차의 개발자분들과 책에서 좋았던 점, 얘기해 보고 싶었던 점 등에 관해서 얘기를 나눌 수 있어서 좋았다. 그룹을 지어서 20분 정도 얘기하고 그룹을 섞는 식으로 진행했는데 얘기하다 보니까 시간이 너무 금방 가서 다음에는 좀 더 길게 했으면 하는 바람이 있었다.&lt;/p&gt;
&lt;h2 id=&quot;취미생활을-하는-나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B7%A8%EB%AF%B8%EC%83%9D%ED%99%9C%EC%9D%84-%ED%95%98%EB%8A%94-%EB%82%98&quot; aria-label=&quot;취미생활을 하는 나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;취미생활을 하는 나&lt;/h2&gt;
&lt;h3 id=&quot;-독서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%8F%85%EC%84%9C&quot; aria-label=&quot; 독서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📚 독서&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/75448373&quot;&gt;미치지 않고서야&lt;/a&gt;라는 책을 읽고 디스콰이엇이라는 메이커 커뮤니티에 기록을 남겼다. &lt;a href=&quot;https://disquiet.io/@hoonportrait/makerlog/%EB%AF%B8%EC%B9%98%EC%A7%80-%EC%95%8A%EA%B3%A0%EC%84%9C%EC%95%BC&quot;&gt;기록&lt;/a&gt;을 어딘가에 남기고 싶었는데 마침 북클럽이 있어서 하나씩 작성해 보고 있다.&lt;/p&gt;
&lt;p&gt;이번 달에 다 읽은 책은 &lt;a href=&quot;https://www.yes24.com/Product/Goods/75448373&quot;&gt;미치지 않고서야&lt;/a&gt;, &lt;a href=&quot;https://www.yes24.com/Product/Goods/118858218&quot;&gt;딸아, 돈 공부 절대 미루지 마라&lt;/a&gt;, &lt;a href=&quot;https://www.yes24.com/Product/Goods/53214530&quot;&gt;나는 4시간만 일한다&lt;/a&gt;가 있다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://disquiet.io/@hoonportrait&quot;&gt;디스콰이엇&lt;/a&gt;은 메이커분들이 양질의 글을 올려주셔서 읽고 배우는 재미가 있다.&lt;/p&gt;
&lt;h3 id=&quot;-사진&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%82%AC%EC%A7%84&quot; aria-label=&quot; 사진 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📸 사진&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://excelcon.day/&quot;&gt;엑셀콘&lt;/a&gt;이라는 개발자 컨퍼런스에서 행사 사진을 찍었다. 인물 스냅만 주로 찍고 있어서 행사 사진을 찍을 기회가 없었는데 좋은 경험이었다.&lt;/p&gt;
&lt;p&gt;주로 낮에 야외에서 찍는 것과는 다르게 장소가 넓지 않고, 조명에 의존해야 했기 때문에 사진 찍기에 어려운 조건이었다. 또한, 여러 인물에 초점을 맞춰야 했기에 어느정도의 노이즈를 감수하고 조리개를 조여야 했다. 그 &lt;code class=&quot;language-text&quot;&gt;순간순간 최선의 판단&lt;/code&gt;을 하느라 정신이 없었다.&lt;/p&gt;
&lt;p&gt;스태프로 이렇게 참가해 보니 정말 컨퍼런스를 준비하는데 많은 사람의 시간과 노력이 들어간다는 걸 깨달을 수 있었고, 정성껏 준비한 행사를 잘 즐겨주신 참가자분들이 고마웠다. 개개인의 순간을 담는 인물 스냅도 좋지만, 행사의 분위기를 담을 수 있는 행사 사진을 찍으면서 재밌어서 지치지 않았고 즐거웠다.&lt;/p&gt;
&lt;p&gt;여담인데 데이먼스이어 사인회와 엑셀콘 시간이 겹쳐서 가지 못한 사연이 있다. 데이먼스이어를 가까이서 볼 수 있는 다시 올지 모르는 소중한 기회였는데 아쉬웠다. 언젠가 기회가 또 생기겠지. &lt;code class=&quot;language-text&quot;&gt;가끔은 원하는 걸 포기해야 하는 상황도 있겠구나 싶었다.&lt;/code&gt; 이 글도 데이먼스이어 노래를 들으면서 작성하고 있다.&lt;/p&gt;
&lt;h3 id=&quot;-음악&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%9D%8C%EC%95%85&quot; aria-label=&quot; 음악 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🎵 음악&lt;/h3&gt;
&lt;p&gt;너드커넥션 공연을 두 번이나 봤다. 운이 좋았다. 돈이 많아서 그런건 아니고 운이 좋게 지역문화센터에서 저렴하게 열린 공연 예매에 성공했다. ✌🏻 최유리님 공연도 들을 수 있었는데 정말 너무 좋았다… 최고야…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[사이드 프로젝트로 업무 불편함 해결하기]]></title><description><![CDATA[배경 사무실에는 회의실로 사용하는 임의의 두 공간이 있다. 예약하려면 공용 캘린더에 등록을 하는데, 임의의 공간이기 때문에 예약 시스템이 있는 것이 아니라 “저 여기 사용해요”라고 글을 적어놓는 것이랑 같다. image…]]></description><link>https://donghoon-song.github.io/maker-log/사이드-프로젝트로-업무-불편함-해결하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/maker-log/사이드-프로젝트로-업무-불편함-해결하기/</guid><pubDate>Mon, 03 Jul 2023 22:08:07 GMT</pubDate><content:encoded>&lt;h2 id=&quot;배경&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%B0%EA%B2%BD&quot; aria-label=&quot;배경 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;배경&lt;/h2&gt;
&lt;p&gt;사무실에는 회의실로 사용하는 임의의 두 공간이 있다. 예약하려면 공용 캘린더에 등록을 하는데, 임의의 공간이기 때문에 예약 시스템이 있는 것이 아니라 “저 여기 사용해요”라고 글을 적어놓는 것이랑 같다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/kzqrVoe.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;문제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제&lt;/h2&gt;
&lt;p&gt;별 불편함없이 쓰고 있었지만 거슬리는 문제가 터진다. 바로 &lt;code class=&quot;language-text&quot;&gt;중복 예약&lt;/code&gt;이다. 이미 예약된 시간에 예약글을 적어도 글이 써지기 때문에 생기는 문제이다. 회의실에 갔는데 이미 사용하는 팀원이 있고, 예약내역을 다시 살펴보지만 중복예약이 되어 있다는 것을 발견하는 경험을 하면 굉장히 당황스럽다.&lt;/p&gt;
&lt;h2 id=&quot;해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결&lt;/h2&gt;
&lt;p&gt;그래서 사이드 프로젝트로 이 문제를 풀어보려고 했다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예약시스템? 만들면 되지. 하고 살짝 가볍게 생각하긴 했다. 😅&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;일단 예약하는 기능만 있더라도 중복 예약 문제를 해결할 수 있을 거라고 생각했다.&lt;/p&gt;
&lt;p&gt;또한 회의실은 팀원들이 많이 사용하므로 개발하면&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;팀원들의 불편함을 많이 덜어줄 것이고&lt;/li&gt;
&lt;li&gt;트래픽이 꾸준하게 있어, 주기적으로 피드백도 받을 수 있었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;팀원들에게도, 나에게도 좋은 프로젝트&lt;/code&gt;라고 생각해서 퇴근 후 짬을 내서 개발했다.&lt;/p&gt;
&lt;p&gt;개발 과정을 온전히 기록하진 못했으나(아직 기록하는 게 서툴다) 우여곡절 끝에 예약 기능이 담긴 MVP 제품이 나왔다. 기획하면서 생각해낸 여러 편의기능들은 다 빼고 제일 중요한 예약 기능, 예약 현황 확인 기능만 먼저 개발했다. 수정? 삭제? 안 넣었다.&lt;/p&gt;
&lt;h3 id=&quot;그것보다-예약-기능에-집중하고-싶었다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B7%B8%EA%B2%83%EB%B3%B4%EB%8B%A4-%EC%98%88%EC%95%BD-%EA%B8%B0%EB%8A%A5%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%97%88%EB%8B%A4&quot; aria-label=&quot;그것보다 예약 기능에 집중하고 싶었다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;그것보다 예약 기능에 집중하고 싶었다&lt;/h3&gt;
&lt;p&gt;예약 시스템을 처음 만들다보니 이것저것 생각해볼 게 많았고(예를 들어, 근무 시간 외의 시간 제외하기, 예약 모달을 열었을 때 예약 시간 기본값 등) 아직까지 엣지 케이스들이 다 잡히지 않은 거 같았다. 그래서 먼저 팀원들에게 열어놓고, 피드백을 받으면서 살을 붙이고 싶었다. 기존 시스템과 병행하면서 쓰다가 문제가 없다 싶은 타이밍에 기존 시스템을 대체하고 싶었다.&lt;/p&gt;
&lt;h3 id=&quot;그리고-짜잔-오늘-공지글을-올리면서-세상에-내놓았다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A7%9C%EC%9E%94-%EC%98%A4%EB%8A%98-%EA%B3%B5%EC%A7%80%EA%B8%80%EC%9D%84-%EC%98%AC%EB%A6%AC%EB%A9%B4%EC%84%9C-%EC%84%B8%EC%83%81%EC%97%90-%EB%82%B4%EB%86%93%EC%95%98%EB%8B%A4&quot; aria-label=&quot;그리고 짜잔 오늘 공지글을 올리면서 세상에 내놓았다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;그리고 짜잔! 오늘 공지글을 올리면서 세상에 내놓았다&lt;/h3&gt;
&lt;p&gt;공지글을 요약해보자면 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;현재의 시스템 -&gt; 중복 예약 문제가 있습니다. 그래서 문제를 해결하고자 만들었습니다. 작은 단위로 개발했기 때문에 이런 기능들만 있습니다. 지금 시스템과 병행해서 써보시면서 버그나 개선점을 마구마구 남겨주시면 감사하겠습니다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;예약하기 기능&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/14SQMof.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;예약현황 보기(피드백을 대놓고 받기 위해 Alert로 넣은게 회심의 포인트다)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/k2DNxu6.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;예약 상세 내역 확인&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/waH7o6N.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;피드백 남기기 버튼을 클릭하면 구글폼으로 이동한다. 팍팍한 일상 속에서 한번 웃으시라고 귀여운 고양이 사진도 넣었다 😻&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/f3sTIEk.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;솔직히 이렇게까지 반응이 뜨거울 줄 몰랐는데 많이 뜨거웠다. 🔥🔥&lt;/p&gt;
&lt;p&gt;만들어 둔 구글폼으로, 댓글로 많은 의견을 남겨주셨다. 그 중에는 내가 생각해놓았던 기능들도 있었는데 의견들을 보면서 우선순위를 매기는데 참고하려고 한다.&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://i.imgur.com/IBy0pCe.png&quot;&gt;
&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://i.imgur.com/vsMZ1WD.png&quot;&gt;
&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Do not use "new" for side effects eslint rule]]></title><description><![CDATA[주어진 url이 유효한지 검사하는 기능이 필요해서 관련 함수를 작성했다. 아래와 같이  함수를 작성했는데 라는 eslint rule를 위반했다고 경고가 떴다. eslint 문서를 참고하면, 보통의 경우 new…]]></description><link>https://donghoon-song.github.io/eslint/do-not-use-&quot;new&quot;-for-side-effects-eslint-rule/</link><guid isPermaLink="false">https://donghoon-song.github.io/eslint/do-not-use-&quot;new&quot;-for-side-effects-eslint-rule/</guid><pubDate>Wed, 14 Jun 2023 23:07:29 GMT</pubDate><content:encoded>&lt;p&gt;주어진 url이 유효한지 검사하는 기능이 필요해서 관련 함수를 작성했다. 아래와 같이 &lt;code class=&quot;language-text&quot;&gt;isValidUrl&lt;/code&gt; 함수를 작성했는데 &lt;code class=&quot;language-text&quot;&gt;ESLint: Do not use &apos;new&apos; for side effects.(no-new)&lt;/code&gt;라는 eslint rule를 위반했다고 경고가 떴다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isValidUrl&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isValidUrl error : &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;eslint 문서를 참고하면, 보통의 경우 new를 통해 인스턴스를 생성하고 변수에 할당해 사용하는데, 저장하지 않으면 &lt;code class=&quot;language-text&quot;&gt;reference가 어디에도 남지 않기 때문에&lt;/code&gt; 이를 방지하기 위함이라고 한다.
그렇다고 인스턴스를 변수에 할당하면 그 변수는 사용하지 않아 &lt;code class=&quot;language-text&quot;&gt;no-unused-vars&lt;/code&gt; rule을 위반하기 때문에 &lt;code class=&quot;language-text&quot;&gt;즉시실행함수&lt;/code&gt;로 감싸주었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isValidUrl&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isValidUrl error : &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;테스트 코드는 아래와 같이 작성했다. chatGPT를 통해서 테스트 케이스를 얻는데 도움을 받았다. 케이스가 많은 거 같긴 하지만 어떤 인풋값들이 들어올 수 있을지 예상할 수 있어서 도움이 많이 됐다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isValidUrl function&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;유효한 URL에 대해서 true를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;유효하지 않은 URL에 대해서 false를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;not a valid url&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;프로토콜이 없는 URL에 대해서 false를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;query parameter가 있는 유효한 URL에 대해서 true를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://www.example.com/?id=123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;hash fragment가 있는 유효한 URL에 대해서 true를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://www.example.com/#about&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;빈 문자열에 대해서 false를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;null에 대해서 false를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;undefined에 대해서 false를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;문자열이 아닌 값에 대해서 false를 반환한다.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[db trigger를 활용해 supabase signUp 후에  users table에 데이터 추가하기]]></title><description><![CDATA[배경 supabase를 활용해 사이드 프로젝트를 하다가 겪었던 문제를 해결한 경험이다. supabase auth를 활용해 google signUp을 했는데, data는  schema의 users table…]]></description><link>https://donghoon-song.github.io/supabase/db-trigger를-활용해-supabase-signUp-후에--users-table에-데이터-추가하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/supabase/db-trigger를-활용해-supabase-signUp-후에--users-table에-데이터-추가하기/</guid><pubDate>Fri, 09 Jun 2023 16:06:59 GMT</pubDate><content:encoded>&lt;h2 id=&quot;배경&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%B0%EA%B2%BD&quot; aria-label=&quot;배경 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;배경&lt;/h2&gt;
&lt;p&gt;supabase를 활용해 사이드 프로젝트를 하다가 겪었던 문제를 해결한 경험이다. supabase auth를 활용해 google signUp을 했는데, data는 &lt;code class=&quot;language-text&quot;&gt;auth&lt;/code&gt; schema의 users table에 저장되는데, 보안상의 목적으로 외부에서 접근할 수 없도록 설정되어 있다.&lt;/p&gt;
&lt;h2 id=&quot;내용&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%82%B4%EC%9A%A9&quot; aria-label=&quot;내용 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;내용&lt;/h2&gt;
&lt;p&gt;그래서 user data로 다른 table의 data와 상호작용하기 위해 &lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt; schema에 table을 만들어야 했다.&lt;/p&gt;
&lt;p&gt;이와 관련한 supabase docs가 아래 있었고 나는 이렇게 학부생 때 배웠던 db trigger를 사이드 프로젝트 하면서 처음 쓰게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://supabase.com/docs/guides/auth/managing-user-data&quot;&gt;supabase-auth/managing-user-data&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- inserts a row into public.profiles&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handle_new_user&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;trigger&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;language&lt;/span&gt; plpgsql
security &lt;span class=&quot;token keyword&quot;&gt;definer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; search_path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; $$
&lt;span class=&quot;token keyword&quot;&gt;begin&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;into&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profiles &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;new&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; new&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
$$&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- trigger the function every time a user is created&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;trigger&lt;/span&gt; on_auth_user_created
  &lt;span class=&quot;token keyword&quot;&gt;after&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;on&lt;/span&gt; auth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;users
  &lt;span class=&quot;token keyword&quot;&gt;for each row&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;procedure&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handle_new_user&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

$$&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;예제를 보면, auth.users table에 insert가 일어나면 &lt;code class=&quot;language-text&quot;&gt;handle_new_user&lt;/code&gt; function이 실행되고, public.profiles table에 id를 넣는다.&lt;/p&gt;
&lt;p&gt;나는 사용자가 회원가입을 하면 public.users table에 id, email, name(email에서 @앞)을 넣고 싶었다.&lt;/p&gt;
&lt;p&gt;email에서 name을 추출하기 위해서 postgre &lt;code class=&quot;language-text&quot;&gt;split_part&lt;/code&gt; function을 활용할 수 있었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;replace&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handle_new_user&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;trigger&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;language&lt;/span&gt; plpgsql
security &lt;span class=&quot;token keyword&quot;&gt;definer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; search_path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; $$
&lt;span class=&quot;token keyword&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;into&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;users &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;new&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; split_part&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;new&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; new&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; new&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
$$&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;피드백&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%BC%EB%93%9C%EB%B0%B1&quot; aria-label=&quot;피드백 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;피드백&lt;/h2&gt;
&lt;p&gt;생활코딩에 글을 공유하니까 지나가던 개발자님께서 왜 트리거를 썼는지 물어봐주셨다. 글을 본 내 친구와 지인분도 현업에서 트리거는 거의 쓰지 않는다고 알려줬다.
가장 큰 이유는 유지보수가 힘들다는 것이다. 데이터베이스에 달려 있다 보니 파악하기가 어렵고, 예상치 못한 오류가 발생할 수도 있다. 그래서 로직은 모두 코드단에서 구현하고 관리한다고 한다. 그리고 또 다른 이유는 성능인데, 아무래도 디비 CPU를 사용하다 보니까 성능이 저하될 수 있다.&lt;/p&gt;
&lt;p&gt;아무래도 프론트엔드 개발자이다보니까, trigger는 현업에서도 쓸 일이 없어서 이런 실무지식은 아예 모르고 있었는데 이번 일을 계기로 알 수 있어서 좋았다. 지식이 늘었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[supabase로 구글로그인(소셜로그인) 구현하기]]></title><description><![CDATA[supabase로 구글로그인을 구현하기 위해서는 어떤 세팅을 해야 하고 코드로는 어떻게 구현하는지 적어보았다. supabase, google cloud console 세팅하기 먼저 supabase의 Authentication - Providers…]]></description><link>https://donghoon-song.github.io/supabase/supabase로-구글로그인(소셜로그인)-구현하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/supabase/supabase로-구글로그인(소셜로그인)-구현하기/</guid><pubDate>Tue, 06 Jun 2023 17:06:25 GMT</pubDate><content:encoded>&lt;p&gt;supabase로 구글로그인을 구현하기 위해서는 어떤 세팅을 해야 하고 코드로는 어떻게 구현하는지 적어보았다.&lt;/p&gt;
&lt;h2 id=&quot;supabase-google-cloud-console-세팅하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#supabase-google-cloud-console-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0&quot; aria-label=&quot;supabase google cloud console 세팅하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;supabase, google cloud console 세팅하기&lt;/h2&gt;
&lt;p&gt;먼저 &lt;a href=&quot;https://supabase.io/&quot;&gt;supabase&lt;/a&gt;의 Authentication - Providers에서 Google을 enable 시키면 Client ID와 Client Secret을 입력하는 창이 나온다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/JRUJYCT.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://console.cloud.google.com/&quot;&gt;Google cloud console&lt;/a&gt;에서 새 프로젝트를 만든다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/RU9aEwO.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그리고 &lt;code class=&quot;language-text&quot;&gt;OAuth 동의 화면&lt;/code&gt;에서 User Type 외부를 선택하고 생성한다. 검색창에 &lt;code class=&quot;language-text&quot;&gt;OAuth&lt;/code&gt;라고 치면 쉽게 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/jVyhnHl.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/fK2FBzS.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그리고 나서 &lt;code class=&quot;language-text&quot;&gt;사용자 인증 정보&lt;/code&gt;에서 OAuth 클라이언트 ID를 만든다. 검색창에 &lt;code class=&quot;language-text&quot;&gt;credential&lt;/code&gt;이라고 치면 쉽게 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/D0QKpij.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/NP54F46.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;유형은 각자의 환경에 맞게 골라주면 된다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/yglDcVZ.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그리고 아까 열어둔 supabase 화면에서 Redirect URL을 복사해서 승인 목록에 추가해준다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/B6gFrrL.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/6NtXobt.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그리고 만들기를 하면 아래 처럼 클라이언트 ID와 비밀번호를 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/8WJv9bE.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이걸 supabase 화면에 붙여넣고 저장하면 준비는 끝이다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/4VmCzEf.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;클라이언트단&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EB%8B%A8&quot; aria-label=&quot;클라이언트단 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;클라이언트단&lt;/h2&gt;
&lt;p&gt;sdk를 설치하고&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; @supabase/supabase-js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아래처럼 supabase client를 만든다. 나는 next.js에서 만들었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// supabase.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createClient &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@supabase/supabase-js&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; supabaseUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NEXT_PUBLIC_SUPABASE_URL&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; supabaseAnonKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NEXT_PUBLIC_SUPABASE_ANON_KEY&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;supabaseUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Supabase URL not found.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;supabaseAnonKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Supabase Anon key not found.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; supabase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;supabaseUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; supabaseAnonKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수는 아래와 같이 작성하고, redirectTo options을 통해서 원하는 곳으로 redirect시킬 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleSignInWithGoogle&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; supabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;signInWithOAuth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            provider&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;google&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            options&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                redirectTo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://localhost:3000/auth/callback&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;큰 틀은 이렇고, 아래 onAuthStateChange method로 세션을 가져올 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;supabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onAuthStateChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; session&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;SIGNED_OUT&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; session&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;보통 SPA의 경우 App.js 같은데서 store에 값을 넣어주는 거 같고&lt;/p&gt;
&lt;p&gt;next.js의 경우 아래 문서를 참고해서 추가적인 로직을 구현하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://supabase.com/docs/guides/auth/auth-helpers/nextjs-pages&quot;&gt;next.js pages directory를 사용하는 경우&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://supabase.com/docs/guides/auth/auth-helpers/nextjs&quot;&gt;next.js app router를 사용하는 경우&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[alwayz를 만드는 레브잇팀은 어떻게 성장했는가]]></title><description><![CDATA[배운 점 요약 가장 인상 깊었던 것은 모두가 로  실행한다는 것이었다. 이 부분은 회사에서 실험 DRI를 맡게 된 큰 동기가 되었다. 실험 DRI…]]></description><link>https://donghoon-song.github.io/growth/alwayz를 만드는 레브잇팀은-어떻게-성장했는가/</link><guid isPermaLink="false">https://donghoon-song.github.io/growth/alwayz를 만드는 레브잇팀은-어떻게-성장했는가/</guid><pubDate>Wed, 17 May 2023 23:05:49 GMT</pubDate><content:encoded>&lt;h2 id=&quot;배운-점-요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%B0%EC%9A%B4-%EC%A0%90-%EC%9A%94%EC%95%BD&quot; aria-label=&quot;배운 점 요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;배운 점 요약&lt;/h2&gt;
&lt;p&gt;가장 인상 깊었던 것은 모두가 &lt;code class=&quot;language-text&quot;&gt;problem solver&lt;/code&gt;로 &lt;code class=&quot;language-text&quot;&gt;문제를 해결하는데 필요한 모든 것을 배우면서&lt;/code&gt; 실행한다는 것이었다. 이 부분은 회사에서 실험 DRI를 맡게 된 큰 동기가 되었다. 실험 DRI를 맡으면서 실험 횟수가 늘어나고 있어 뿌듯하고 더 빨리, 더 많이 실험하고 싶다.&lt;/p&gt;
&lt;p&gt;그리고 &lt;code class=&quot;language-text&quot;&gt;높은 목표&lt;/code&gt;를 세우고 많은 부분을 이뤄낸 것도 인상적이었다. 높은 목표를 세우면 확실히 그 목표에 가까워지도록 사고방식이 좀 트이는 거 같다. 하지만 아직까지는 폭발적이고 과감한 성장을 이뤄내보지 못했다. 올해 큰 거 하나 터트려보고 싶다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;본질 지표&lt;/code&gt;도 중요하다는 것에 공감한다. 실험만 하다보면 퍼널별 전환율에 집중하게 되고, 숲을 보는 것을 놓치고 있을 수 있다. 오늘 실제로 실험설계를 하면서 PM님과 리텐션 지표에 대해 잠깐 얘기 나눴는데 리텐션을 어떻게 잘 측정할지도 고민 포인트인 거 같다.&lt;/p&gt;
&lt;h2 id=&quot;영상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%98%81%EC%83%81&quot; aria-label=&quot;영상 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;영상&lt;/h2&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/-GFK8MkXSs0&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2 id=&quot;1-어떻게-성장했는가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%84%B1%EC%9E%A5%ED%96%88%EB%8A%94%EA%B0%80&quot; aria-label=&quot;1 어떻게 성장했는가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 어떻게 성장했는가?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;모두가 매일 사용하는 소프트웨어&lt;/code&gt;를 만드는 것이 꿈. 나이브하게 접근하면 꿈을 이루지 못할 것이라 생각.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;갈망론&lt;/code&gt; → 모든 것은 사람들의 갈망에서 출발&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;구매&lt;/li&gt;
&lt;li&gt;소셜(소통, 관계)&lt;/li&gt;
&lt;li&gt;엔터&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;중국의 &lt;code class=&quot;language-text&quot;&gt;핀둬둬&lt;/code&gt;를 벤치마킹. 3가지 갈망을 다 담고 싶었음.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;좋은 제품을 싸게 살 수 있음&lt;/li&gt;
&lt;li&gt;팀구매를 통한 소통, 관계&lt;/li&gt;
&lt;li&gt;나중에 개발할 엔터쪽 요소&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MVP&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;2달정도 걸림&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;만들어낼 수 있는 부분에 집중&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;- 만들어낼 수 있는 부분 → `바이럴`, `성장`
- 만들어낼 수 없는 부분 → 가격에 `WOW`를 느끼고 계속 구매할지?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MVP에 8천개의 상품을 올림(어떻게?)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;- 셀러를 모집하는건 불가능.
- `오픈마켓에 있는 상품들을 대신 올리고, 주문이 들어오면 주문대행을 하는 식.`
- 20% 낮은 가격으로 세팅하고 손해본건 시드투자금으로 메움.
- week1 재구매율이 `30%` 정도면 확신을 얻을 것이라 생각. 실데이터 `48~50%` 나옴.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;빠른 실행과 피드백 루프(A/B Test)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;가설을 세우고 A/B test를 많이 함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;낮은 가격에 대한 갈망&lt;/code&gt;을 기반으로 한 ‘팀 구매’ 바이럴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;바이럴 종류&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;카카오톡 바이럴&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;![image](https://github.com/vuejs/core/assets/32301380/fa47dc1a-63db-4319-8899-3b67065d2c76)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;네이버 카페 바이럴&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;![image](https://github.com/vuejs/core/assets/32301380/45ed5238-e975-4855-82b0-c5884472bcf4)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;카카오 오픈 채팅방 바이럴&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/vuejs/core/assets/32301380/267cfcaf-d857-4b7a-b975-7d2eef8de6bc&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;100원짜리 양파&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/vuejs/core/assets/32301380/5e5667a5-0cb8-4b11-b648-4e14f55f1e9b&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;가격이 낮은건 좋지만 친구 초대는 부담스러울 수 있음(민폐처럼 느낄 수 있다고 생각)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;허들을 낮추는 방향으로 가봤지만 작동하지 않음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;가격이 더 낮으면(&lt;code class=&quot;language-text&quot;&gt;갈망이 극대화되면&lt;/code&gt;) 허들을 뛰어넘지 않을까?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CAC(Customer acquisition cost) 15000~20000원대(큰 회사는 50000원대)인데 &lt;code class=&quot;language-text&quot;&gt;월 3배 성장하면서 CAC 3000원&lt;/code&gt;으로 가고 싶음&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2900원짜리 양파를 100원에 팔아보자.&lt;/li&gt;
&lt;li&gt;100원 짜리 양파(&lt;code class=&quot;language-text&quot;&gt;CAC를 담보하는 핵심상품&lt;/code&gt;)으로 유입 → 다른 상품도 사지 않을까?
&lt;ul&gt;
&lt;li&gt;셀러분이 감당할 수 없다고 품절처리 하셔서 3억원을 들여 양파 80톤을 매입.
&lt;ul&gt;
&lt;li&gt;초기 1만명까지의 그로스를 담당.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10000원짜리 → 100원&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/vuejs/core/assets/32301380/a9caa5a9-ccdc-45a6-ba61-572eaa721c85&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;99인 100원 팀구매&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;실패시 → 비용이 들지 않으므로&lt;/code&gt; CAC 조절 가능&lt;/li&gt;
&lt;li&gt;추첨도 마찬가지. &lt;code class=&quot;language-text&quot;&gt;상품 수량을 조절&lt;/code&gt;해 CAC 조절 가능&lt;/li&gt;
&lt;li&gt;100팀(1만명)이 성사시킴. → 1억원 지출&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;실패담&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;리텐션을 유지하기 위해 &lt;code class=&quot;language-text&quot;&gt;본질을 잊고&lt;/code&gt; 트라이함&lt;/li&gt;
&lt;li&gt;점점 객단가가 더 비싼(테팔 → 아이패드 → 샤넬백 → 벤츠) 것으로 추첨을 돌림&lt;/li&gt;
&lt;li&gt;DAU는 10만으로 정체&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;전사 지표 재설정&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;6월 이전 → 거래액&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;거래액이 갖는 허점 → 리텐션이 없으면 유지가 힘듦&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RGMV → 건전하고 유지 가능한 GMV&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;![image](https://github.com/vuejs/core/assets/32301380/aca1598e-65b4-446b-b8b0-dc43aed65e14)

![image](https://github.com/vuejs/core/assets/32301380/d5a3049f-0bd8-416f-840a-2e1d44f3074c)

![image](https://github.com/vuejs/core/assets/32301380/1ec70b6b-9315-4489-a84d-f2e468c1b952)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2-key-lessons&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-key-lessons&quot; aria-label=&quot;2 key lessons permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Key lessons&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;MVP는 만들어낼 수 없는 것 중심&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;빠른 실험, 피드백&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;장기적이고 본질적인 가치 추구&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;본질 중심의 전사지표 설정 및 Align&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;레브잇의 조직문화(TBC)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;중요한 것은 도구가 아닌 문제 해결.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;7 Standards&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Madly Motivated&lt;/li&gt;
&lt;li&gt;Fastest&lt;/li&gt;
&lt;li&gt;Focused&lt;/li&gt;
&lt;li&gt;Humble&lt;/li&gt;
&lt;li&gt;Resilient&lt;/li&gt;
&lt;li&gt;Smart&lt;/li&gt;
&lt;li&gt;Impact Oriented&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[프론트엔드 테스트에서의 정규식의 활용]]></title><description><![CDATA[이슈 component test를 하다보면 렌더링된 결과물을 비교하는데, 텍스트가 길어져서 line break…]]></description><link>https://donghoon-song.github.io/test/프론트엔드-테스트에서의-정규식의-활용/</link><guid isPermaLink="false">https://donghoon-song.github.io/test/프론트엔드-테스트에서의-정규식의-활용/</guid><pubDate>Wed, 17 May 2023 22:06:23 GMT</pubDate><content:encoded>&lt;h2 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h2&gt;
&lt;p&gt;component test를 하다보면 렌더링된 결과물을 비교하는데, 텍스트가 길어져서 line break가 발생하거나, 의도치 않은 공백이 생기는 등의 상황에서 텍스트 단언문에서 애를 먹는다. 이럴 때 정규식을 사용해 공백을 제거하면 수월하게 테스트할 수 있다!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;   This  is     a    test.   &apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\\s\\s+&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Output: &quot;This is a test.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// mount한 결과물의 text가 아래와 같이 나올 때&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &apos;   This  is     a    test.   &apos;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; wrapper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;component&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\\s\\s+&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toContain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;This is a test.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;정규식-해석&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%EC%8B%9D-%ED%95%B4%EC%84%9D&quot; aria-label=&quot;정규식 해석 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규식 해석&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;.replace(/\\s\\s+/g, &apos; &apos;)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;스페이스, 탭, 라인브레이크 등을 하나의 스페이스로 치환해준다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;/\\s\\s+/&lt;/code&gt; 는 여러개의 white space character를 뜻한다&lt;/li&gt;
&lt;li&gt;맨 뒤의 ‘g’는 글로벌 적용을 의미한다.(한번 패턴을 마주하면 적용하고 끝이 아니라 문자열 끝까지 검사함)&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[vscode error lens extension(야무진 익스텐션 추천)]]></title><description><![CDATA[세미나에 참여하다가 정말 편해보이는 vscode 익스텐션을 발견했다. image Error Lens라는 익스텐션인데, 마우스 호버하지 않아도 에러 메시지를 읽을 수 있어 정말 편리하다. image]]></description><link>https://donghoon-song.github.io/vscode/vscode-error-lens-extension(야무진-익스텐션-추천)/</link><guid isPermaLink="false">https://donghoon-song.github.io/vscode/vscode-error-lens-extension(야무진-익스텐션-추천)/</guid><pubDate>Sat, 06 May 2023 22:06:22 GMT</pubDate><content:encoded>&lt;p&gt;세미나에 참여하다가 정말 편해보이는 vscode 익스텐션을 발견했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/236611641-ddf5db3f-58b6-45e8-8849-174db0bb3010.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;Error Lens라는 익스텐션인데, 마우스 호버하지 않아도 에러 메시지를 읽을 수 있어 정말 편리하다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/236625905-b75c56e2-88e3-4928-91e0-ec9b5843de9a.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[nuxt3 server api 만들기 & env 접근]]></title><description><![CDATA[nuxt3 서버에서 api를 만들려면  디렉토리 안에 파일을 만들면 된다.
nuxt는  directory를 자동으로 스캔해 api를 등록한다. 예를 들어,  ->  endpoint가 생긴다. 앱 내에서 를 통해 API…]]></description><link>https://donghoon-song.github.io/nuxt/nuxt3-server-api-만들기-&amp;-env-접근/</link><guid isPermaLink="false">https://donghoon-song.github.io/nuxt/nuxt3-server-api-만들기-&amp;-env-접근/</guid><pubDate>Sat, 06 May 2023 19:06:33 GMT</pubDate><content:encoded>&lt;p&gt;nuxt3 서버에서 api를 만들려면 &lt;code class=&quot;language-text&quot;&gt;server/api&lt;/code&gt; 디렉토리 안에 파일을 만들면 된다.
nuxt는 &lt;code class=&quot;language-text&quot;&gt;~/server/api&lt;/code&gt; directory를 자동으로 스캔해 api를 등록한다.&lt;/p&gt;
&lt;p&gt;예를 들어, &lt;code class=&quot;language-text&quot;&gt;server/api/ai.ts&lt;/code&gt; -&gt; &lt;code class=&quot;language-text&quot;&gt;/api/ai&lt;/code&gt; endpoint가 생긴다.&lt;/p&gt;
&lt;p&gt;앱 내에서 &lt;code class=&quot;language-text&quot;&gt;$fetch(&quot;/api/ai&quot;)&lt;/code&gt;를 통해 API를 호출할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ~/server/api/ai.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineEventHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;예제로 잘 작동하는 것을 확인한 후에 구현하고자 하는 로직을 추가했다.
간단하게 message를 받아 openai api에 보낸 응답값을 return하는 api이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ~/server/api/ai.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Configuration&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OpenAIApi &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;openai&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineEventHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; event &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OPENAI_API_KEY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useRuntimeConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; configuration &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    apiKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; openai &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OpenAIApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configuration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; completion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; openai&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createCompletion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text-davinci-003&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    prompt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; completion&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;choices&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;파일은 보는바와 같이 defineEventHandler로 감싸서 export하면 된다.&lt;/p&gt;
&lt;p&gt;여기서 문서를 참고해야 했던 부분은&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;env값에 접근하는 방식&lt;/li&gt;
&lt;li&gt;request body를 읽는 방식
이었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;먼저 env는 process.env를 통해 접근할 수 없고, nuxt runtime config를 이용해야 했다.
&lt;code class=&quot;language-text&quot;&gt;nuxt.config.ts&lt;/code&gt;에서 runtimeConfig에 등록하면 앱에서 &lt;code class=&quot;language-text&quot;&gt;useRuntimeConfig&lt;/code&gt;를 통해 접근할 수 있다.&lt;/p&gt;
&lt;p&gt;사용하기에 번거로워진 거 같은데, 공식문서에서 이는 .env 내용이 변경되었을 때 변화를 감지해 HMR을 지원하기 위함이라고 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// nuxt.config.ts&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// https://nuxt.com/docs/api/configuration/nuxt-config&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineNuxtConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  runtimeConfig&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;전달받는 event가 H3Event 타입이어서 생소했는데, body를 읽는 방식은 공식 문서에 나와 있듯이 &lt;code class=&quot;language-text&quot;&gt;readBody&lt;/code&gt; api를 활용하면 됐다.&lt;/p&gt;
&lt;p&gt;추가적으로, 파일명으로 allow method를 지정할 수 있다.
&lt;code class=&quot;language-text&quot;&gt;ai.ts&lt;/code&gt; -&gt; &lt;code class=&quot;language-text&quot;&gt;ai.post.ts&lt;/code&gt;로 변경하면 post method만 허용한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[vue composition api]]></title><description><![CDATA[options api 정의 data, method 등을 options object에 담아서 정의하는 방식. 문제 관련 로직이 분산되어 있음 믹스인으로 로직을 재사용하는데에 한계가 있음 컴포넌트 데이터의 출처가 모호해짐 개발할 때, IDE…]]></description><link>https://donghoon-song.github.io/vue.js/vue-composition-api/</link><guid isPermaLink="false">https://donghoon-song.github.io/vue.js/vue-composition-api/</guid><pubDate>Sat, 06 May 2023 10:06:14 GMT</pubDate><content:encoded>&lt;h2 id=&quot;options-api&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#options-api&quot; aria-label=&quot;options api permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;options api&lt;/h2&gt;
&lt;h3 id=&quot;정의&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EC%9D%98&quot; aria-label=&quot;정의 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정의&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;data, method 등을 options object에 담아서 정의하는 방식.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;문제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;관련 로직이 분산되어 있음&lt;/li&gt;
&lt;li&gt;믹스인으로 로직을 재사용하는데에 한계가 있음
&lt;ul&gt;
&lt;li&gt;컴포넌트 데이터의 출처가 모호해짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개발할 때, IDE에서도 로직을 파악하기 어려움&lt;/li&gt;
&lt;li&gt;이름이 중복될 수 있음&lt;/li&gt;
&lt;li&gt;타입스크립트 지원이 제한적&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.vueschool.io/wp-content/uploads/2023/01/composition-api-after.e3f2c350.png&quot; alt=&quot;image&quot;&gt;
이미지 출처: &lt;a href=&quot;https://vueschool.io/articles/vuejs-tutorials/options-api-vs-composition-api/&quot;&gt;https://vueschool.io/articles/vuejs-tutorials/options-api-vs-composition-api/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;composition-api&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#composition-api&quot; aria-label=&quot;composition api permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;composition api&lt;/h2&gt;
&lt;h3 id=&quot;특징&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8A%B9%EC%A7%95&quot; aria-label=&quot;특징 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;반응형 api&lt;/li&gt;
&lt;li&gt;라이프사이클 훅을 지원&lt;/li&gt;
&lt;li&gt;의존성 주입&lt;/li&gt;
&lt;li&gt;관심사를 한데 모을 수 있어 읽고 이해하기 쉬움&lt;/li&gt;
&lt;li&gt;문맥에 따라 사용하는 부분들의 이름을 다시 지을 수 있음&lt;/li&gt;
&lt;li&gt;로직을 재사용하기 쉬움&lt;/li&gt;
&lt;li&gt;타입스크립트 지원이 잘됨
&lt;ul&gt;
&lt;li&gt;ref의 초기값으로 타입 추론 가능&lt;/li&gt;
&lt;li&gt;computed가 반환하는 값으로 타입 추론 가능&lt;/li&gt;
&lt;li&gt;interface로 reactive data의 타입을 정의할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(vue2.7 버전부터 빌트인 되어 있다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setup&quot; aria-label=&quot;setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;setup&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;setup 은 Vue가 컴포넌트 생성전에 props가 전달되면 자동으로 실행됨.&lt;/li&gt;
&lt;li&gt;인자로 props, context를 받는다.&lt;/li&gt;
&lt;li&gt;setup이 불릴 때 컴포넌트가 생성되지 않았으므로 this로 접근 불가&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;price&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;img width=&quot;100%&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/226094414-f2b0b380-a86d-4904-b7eb-d43358f6be77.png&quot;&gt;
&lt;h3 id=&quot;context&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#context&quot; aria-label=&quot;context permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;context&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;attrs&lt;/li&gt;
&lt;li&gt;slots&lt;/li&gt;
&lt;li&gt;emit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;reactive data가 아니므로 context는 destructure 가능. props는 불가능.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; attrs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; slots&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; emit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;price&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ref로 값을 전달하면 Vue는 value property를 가지는 object로 감싼다.&lt;/p&gt;
&lt;p&gt;그래서 접근하거나 변형할 때 .value를 통한다. wrapper로 감싸면 반응성을 잃지 않고 안전하게 사용할 수 있다.
script 외부에서는 unwrap한다.&lt;/p&gt;
&lt;p&gt;아래 예제에서, name을 let으로 선언하고, .value를 통해 값을 바꿔도 반응성은 유지된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;The Snazzy Burger&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nice Burger&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;placeOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Your order has been placed!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;addItemToCart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;You added &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;item&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; to your cart!&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; placeOrder&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; addItemToCart &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 .value를 빼먹으면 값이 교체되서 반응성을 잃는다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;h1&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt; v&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;model&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;template&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ref &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;The Snazzy Burger&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nice Burger&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;img width=&quot;334&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/226095551-9a618e8a-abcb-4439-ac0f-1707447ed010.png&quot;&gt;
&lt;h2 id=&quot;ref&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ref&quot; aria-label=&quot;ref permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ref&lt;/h2&gt;
&lt;h3 id=&quot;장점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%A5%EC%A0%90&quot; aria-label=&quot;장점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;장점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;primitive, non-primitive 둘 다 쓸 수 있음&lt;/li&gt;
&lt;li&gt;destructuring하기 좋음&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ref &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vue&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Pizza&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;단점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A8%EC%A0%90&quot; aria-label=&quot;단점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;단점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;.value를 쓰는 게 성가실 수 있다.&lt;/li&gt;
&lt;li&gt;context에 따라 쓰는 방법이 달라서 헷갈린다.
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;template&lt;/code&gt;에선 &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;setup&lt;/code&gt;에선 &lt;code class=&quot;language-text&quot;&gt;name.value&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;options api&lt;/code&gt;에선 &lt;code class=&quot;language-text&quot;&gt;this.name&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;reactive&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reactive&quot; aria-label=&quot;reactive permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;reactive&lt;/h2&gt;
&lt;h3 id=&quot;장점-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%A5%EC%A0%90-1&quot; aria-label=&quot;장점 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;장점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;.value를 안 써도 됨&lt;/li&gt;
&lt;li&gt;context가 달라도 문법이 똑같음&lt;/li&gt;
&lt;li&gt;toRefs를 사용하면 destructuring이 가능하긴 함
&lt;ul&gt;
&lt;li&gt;toRefs =&gt; reactive object property를 돌면서 하나씩 ref로 변경해줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reactive&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toRefs &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vue&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toRefs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;reactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Pizza&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;단점-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A8%EC%A0%90-1&quot; aria-label=&quot;단점 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;단점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;primitive에 사용하지 못함&lt;/li&gt;
&lt;li&gt;reassign을 하면 반응성을 잃음&lt;/li&gt;
&lt;li&gt;전체 object를 교체하지 못함.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; posts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;post 1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;post 2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
posts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;post 3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;post 4&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;computed&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#computed&quot; aria-label=&quot;computed permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;computed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;getter, setter 선언이 가능&lt;/li&gt;
&lt;li&gt;.value를 사용해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pricePretty &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;computed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pricePrettySentence &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;computed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Price: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;pricePretty&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;watch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#watch&quot; aria-label=&quot;watch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;watch&lt;/h3&gt;
&lt;p&gt;options api처럼, immediate, deep option이 가능&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;newName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; oldName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Name changed from &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;oldName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;newName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;deep&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;의견&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%98%EA%B2%AC&quot; aria-label=&quot;의견 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;의견&lt;/h3&gt;
&lt;p&gt;이상 vue school 강의를 듣고 요약한 내용이다. 아무래도 vue core member들이 강의한 내용이다 보니 이해도 잘 되고, 일반 블로그 글들에선 볼 수 없었던 관점 등을 배울 수 있었다.&lt;/p&gt;
&lt;p&gt;경험이 쌓여서 ref와 reactive 중 어느 것을 선호할 수 있는 정도가 되고 싶다. options api의 코드 재사용성은 정말 안 좋았는데, composition api로 많이 개선됐으면 한다. 이것도 많이 써보면서 사례들을 경험해나가고 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[supabase edge function 빠르게 시작하기]]></title><description><![CDATA[notion database에서 값을 가져오고 싶었는데 생각해보니, client단에서 notion api call을 하면 CORS 에러가 났다. 그래서 Proxy server가 필요했고, lambda로 만들까 하다가 생각해보니 supabase…]]></description><link>https://donghoon-song.github.io/supabase/supabase-edge-function-빠르게-시작하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/supabase/supabase-edge-function-빠르게-시작하기/</guid><pubDate>Sat, 06 May 2023 09:05:56 GMT</pubDate><content:encoded>&lt;p&gt;notion database에서 값을 가져오고 싶었는데 생각해보니, client단에서 notion api call을 하면 CORS 에러가 났다. 그래서 Proxy server가 필요했고, lambda로 만들까 하다가 생각해보니 supabase에 edge function이라는 기능이 있었다. 그래서 이것을 사용해 봤다!&lt;/p&gt;
&lt;p&gt;처음에 무척 애를 먹었다. supabase cli 설치가 마음대로 안됐다. 결국 유튜브 동영상을 보고 명령어를 찾았다.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/rzglqRdZUQE&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; supabase/tap/supabase&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;설치를 하고 함수 생성한 뒤 바로 배포했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;supabase functions new notion-api-proxy
supabase functions deploy notion-api-proxy --project-ref &lt;span class=&quot;token variable&quot;&gt;${PROJECT_REF}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edge functions 대시보드에 들어가면 배포한 함수가 짜잔!
&lt;img width=&quot;1257&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/227210415-9630273f-16b4-47db-8c2e-e736aedf1bc1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;새로 생성한 함수는 functions directory 안에 들어 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/227208711-083c4de9-ca4b-4312-90a1-72864c44619b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;서버는 deno로 되어 있다. 와우. 한번도 안 써봤는데 잘 됐다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/227211674-d0a46324-edcf-4b2d-950d-c79132ab7116.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;로컬로 돌려보기 위한 과정을 쭉 적어보면, docker가 필요했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt; supabase functions serve notion-api-proxy
Error: cannot &lt;span class=&quot;token builtin class-name&quot;&gt;read&lt;/span&gt; config &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; /Users/songdonghoon/study: &lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt; supabase/config.toml: no such &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; or directory
Have you &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; up the project with supabase init?

 supabase init
Finished supabase init.

 supabase functions serve notion-api-proxy
Error: supabase start is not running.
Try rerunning the &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; with &lt;span class=&quot;token parameter variable&quot;&gt;--debug&lt;/span&gt; to troubleshoot the error.

 supabase start
Error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; daemon running?
  &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; github.com/supabase/cli/internal/utils.AssertDockerIsRunning:48
  &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; github.com/supabase/cli/internal/start.Run:36
Try rerunning the &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; with &lt;span class=&quot;token parameter variable&quot;&gt;--debug&lt;/span&gt; to troubleshoot the error.
Status: Downloaded newer image &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; public.ecr.aws/supabase/deno-relay:v1.6.0
Seeding data supabase/seed.sql&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Started supabase &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; development setup.

         API URL: http://localhost:54321
         &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.

 supabase functions serve notion-api-proxy
Starting supabase/functions/notion-api-proxy
Serving supabase/functions/notion-api-proxy
Watcher Process started.
Check file:///home/deno/functions/notion-api-proxy/index.ts
Hello from Functions&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
Listening on http://localhost:8000/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 코드 아래에 있는 invoke 명령어를 사용하면 테스트 해볼 수 있었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl --request POST &apos;https://&amp;lt;project_ref&gt;.functions.supabase.co/hello-world&apos; \ --header &apos;Authorization: Bearer ANON_KEY&apos; \ --header &apos;Content-Type: application/json&apos; \ --data &apos;{ &quot;name&quot;:&quot;Functions&quot; }&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;참고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0&quot; aria-label=&quot;참고 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://supabase.com/docs/guides/functions/quickstart&quot;&gt;https://supabase.com/docs/guides/functions/quickstart&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[셀프 브랜딩에서 가장 중요한 것]]></title><description><![CDATA[…]]></description><link>https://donghoon-song.github.io/mystory/셀프-브랜딩에서-가장-중요한-것/</link><guid isPermaLink="false">https://donghoon-song.github.io/mystory/셀프-브랜딩에서-가장-중요한-것/</guid><pubDate>Sat, 06 May 2023 00:06:27 GMT</pubDate><content:encoded>&lt;p&gt;개발이나, 사진이나 셀프 브랜딩에 관심이 많다. 그러다가 유튜브에서 아래 영상을 마주했는데 정말 주옥같은 내용들이 많고 내 자신을 돌아볼 수 있는 기회를 얻어서 공유해본다.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/nzc3hUfe4kg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;가장 와닿아서 메모했던 내용은 다음과 같다.&lt;/p&gt;
&lt;ol&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&gt;이걸 내 경험에 비추어서 답해보면 다음과 같다.
여기서 내 고객은 지금 다니고 있는 회사가 될 것이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;회사가 해결하려는 문제를 해결한다.&lt;/li&gt;
&lt;li&gt;회사는 성장할 수 있고, 유저들에게 가치를 전달할 수 있다.&lt;/li&gt;
&lt;li&gt;문제 해결.&lt;/li&gt;
&lt;li&gt;회사는 더 나아진 기능, 새로운 기능 등을 가질 수 있고 유저들에게 더 좋은 UX, UI, 서비스를 제공할 수 있다.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[Amplify pwa Manifest: Line: 1, column: 1, Syntax error 해결법]]></title><description><![CDATA[이슈 aws amplify에 pwa앱을 배포했는데 manifest파일을 읽지 못하는 이슈가 있었다. image error message를 클릭하면 index.html이 보인다. 오잉? image…]]></description><link>https://donghoon-song.github.io/pwa/amplify-pwa-manifest:-line:-1,-column:-1,-syntax-error-해결법/</link><guid isPermaLink="false">https://donghoon-song.github.io/pwa/amplify-pwa-manifest:-line:-1,-column:-1,-syntax-error-해결법/</guid><pubDate>Sat, 06 May 2023 00:05:20 GMT</pubDate><content:encoded>&lt;h2 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h2&gt;
&lt;p&gt;aws amplify에 pwa앱을 배포했는데 manifest파일을 읽지 못하는 이슈가 있었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/236499526-192b87ba-3d7f-4813-8f1a-a9f7f01e31d1.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;error message를 클릭하면 index.html이 보인다. 오잉?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/236499669-ba3c246d-3a99-4e81-a2b7-6365f5d9b014.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;원인 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;원인&lt;/h2&gt;
&lt;p&gt;다시 쓰기 및 리디렉션을 처음 설정한 것 때문에 요청이 index.html로 가고 있었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/236499947-6747af2f-5170-4d5c-a7c2-8de6f1c50524.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결&lt;/h2&gt;
&lt;p&gt;/manifest.webmanifest는 그대로 다시 쓰게하고 우선순위를 높여서 해결했다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/236499838-080767f3-4271-4def-abc1-2e404cee993f.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[AWS WAF 정리]]></title><description><![CDATA[WAF(Web Application Firewall) http(s) 요청을 모니터링하고 관리하는 방화벽
규칙을 정하고 어떤 액션을 취할지 정의할 수 있음 액션 종류 허용(Allow) 차단(Block) 카운팅(Count) CAPTCHAR…]]></description><link>https://donghoon-song.github.io/aws/aws-waf-정리/</link><guid isPermaLink="false">https://donghoon-song.github.io/aws/aws-waf-정리/</guid><pubDate>Sat, 06 May 2023 00:05:18 GMT</pubDate><content:encoded>&lt;h1 id=&quot;wafweb-application-firewall&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#wafweb-application-firewall&quot; aria-label=&quot;wafweb application firewall permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;WAF(Web Application Firewall)&lt;/h1&gt;
&lt;p&gt;http(s) 요청을 모니터링하고 관리하는 방화벽
규칙을 정하고 어떤 액션을 취할지 정의할 수 있음&lt;/p&gt;
&lt;h3 id=&quot;액션-종류&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%95%A1%EC%85%98-%EC%A2%85%EB%A5%98&quot; aria-label=&quot;액션 종류 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;액션 종류&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;허용(Allow)&lt;/li&gt;
&lt;li&gt;차단(Block)&lt;/li&gt;
&lt;li&gt;카운팅(Count)&lt;/li&gt;
&lt;li&gt;CAPTCHAR를 실행시키거나 사람인지, 브라우저인지 체크&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;waf-rules&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#waf-rules&quot; aria-label=&quot;waf rules permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;WAF Rules&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;요청을 검사할 때 사용할 기준을 정하고 action을 적용할지 정함&lt;/li&gt;
&lt;li&gt;ex) Bot이면 요청을 차단
IP 주소 기준, 지역 기준 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;actions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#actions&quot; aria-label=&quot;actions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Actions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Allow and Block actions
&lt;ul&gt;
&lt;li&gt;terminating action&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;terminate되면 그 후 다른 rule을 거치지 않는다.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Count action
&lt;ul&gt;
&lt;li&gt;non-terminating action&lt;/li&gt;
&lt;li&gt;WAS는 request를 count하고 다음 룰로 넘어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CAPTCHA and Challenge
&lt;ul&gt;
&lt;li&gt;terminating or non-terminating action&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;rule-action-overriding&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#rule-action-overriding&quot; aria-label=&quot;rule action overriding permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Rule action overriding&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Allow
&lt;ul&gt;
&lt;li&gt;보호받는 자원으로 forward하기 전에 request에 custom header를 넣을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Block
&lt;ul&gt;
&lt;li&gt;status code 403&lt;/li&gt;
&lt;li&gt;rule을 통해 response도 커스터마이즈할 수 있다.&lt;/li&gt;
&lt;li&gt;block 당하면 block action setting이 설정한 response를 client에게 전송한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Count
&lt;ul&gt;
&lt;li&gt;남은 rule을 거친다.&lt;/li&gt;
&lt;li&gt;custom header를 request에 넣거나 label을 붙인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CAPTCHA and Challenge
&lt;ul&gt;
&lt;li&gt;CAPTCHA plzzle을 쓰거나&lt;/li&gt;
&lt;li&gt;silent challenge를 사용해 request가 bot인지 아닌지 체크한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;overriding-the-rule-action-to-count&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overriding-the-rule-action-to-count&quot; aria-label=&quot;overriding the rule action to count permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overriding the rule action to Count&lt;/h3&gt;
&lt;p&gt;룰의 action을 Count로 overriding할 수 있다. 프로덕션에 룰을 적용하기전에 로그를 보면서 테스트, 모니터링하는데 주로 쓰임.&lt;/p&gt;
&lt;h3 id=&quot;temporary-inconsistencies-during-updates&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#temporary-inconsistencies-during-updates&quot; aria-label=&quot;temporary inconsistencies during updates permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Temporary inconsistencies during updates&lt;/h3&gt;
&lt;p&gt;web ACL 생성 혹은 편집 시에 전 영역으로 퍼지는데 시간이 조금 걸리기 때문에 싱크 이슈가 있을 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How browser automation works behind the scenes - JSWORLD 2023]]></title><description><![CDATA[https://www.youtube.com/watch?v=6vwWBKfwTWk 을 시청하고 정리한 글입니다. Debugging & Testing DevTools Browser Automation ChromeDriver WebDriver BiDi…]]></description><link>https://donghoon-song.github.io/test/how-browser-automation-works-behind-the-scenes---jsworld-2023/</link><guid isPermaLink="false">https://donghoon-song.github.io/test/how-browser-automation-works-behind-the-scenes---jsworld-2023/</guid><pubDate>Wed, 22 Mar 2023 16:03:22 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6vwWBKfwTWk&quot;&gt;https://www.youtube.com/watch?v=6vwWBKfwTWk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;을 시청하고 정리한 글입니다.&lt;/p&gt;
&lt;h2 id=&quot;debugging--testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#debugging--testing&quot; aria-label=&quot;debugging  testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Debugging &amp;#x26; Testing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;DevTools&lt;/li&gt;
&lt;li&gt;Browser Automation&lt;/li&gt;
&lt;li&gt;ChromeDriver&lt;/li&gt;
&lt;li&gt;WebDriver BiDi&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;webdriver-classic-protocol---conventional&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#webdriver-classic-protocol---conventional&quot; aria-label=&quot;webdriver classic protocol   conventional permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;WebDriver “Classic” Protocol - Conventional&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;전통적인 프로토콜&lt;/li&gt;
&lt;li&gt;모든 브라우저에서 동작&lt;/li&gt;
&lt;li&gt;pull-based - 클라이언트는 서버에 HTTP 통신을 해서 응답을 받아야 함 - 서버가 클라이언트에 직접적으로 메시지를 보내지 못함&lt;/li&gt;
&lt;li&gt;command 마다 HTTP handshake가 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;chromedevtools-protocolcdp---non-standard&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chromedevtools-protocolcdp---non-standard&quot; aria-label=&quot;chromedevtools protocolcdp   non standard permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ChromeDevTools Protocol(CDP) - Non-standard&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;크로미움 기반 브라우저에서만 동작&lt;/li&gt;
&lt;li&gt;Puppeteer, Playwright, Selenium, Nightwatch, WebdriverIO, Cypress, Testcafe&lt;/li&gt;
&lt;li&gt;Browser drivers를 사용하지 않음&lt;/li&gt;
&lt;li&gt;웹소켓 기반으로 빠른 커뮤니케이션 가능&lt;/li&gt;
&lt;li&gt;chatty - 프로토콜단에서 많은 command를 생성 - 원래 디버깅을 목적으로 디자인되었음&lt;/li&gt;
&lt;li&gt;low-level control 지원 - device mode 시뮬레이션 - geolocation 시뮬레이션 - 네트워크 요청 intercept - console log message&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 아래 명령어를 사용해 프로토콜단에서 벌어지는 일들의 로그를 볼 수 있음
DEBUG=puppeteer:protocol:SEND*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;web-apis--javascript---non-standard&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#web-apis--javascript---non-standard&quot; aria-label=&quot;web apis  javascript   non standard permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Web APIs + JavaScript - Non-standard&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;크로미움 기반 브라우저에서 동작&lt;/li&gt;
&lt;li&gt;개발자 -&gt; 자동화 툴 -&gt; 테스트 스크립트&lt;/li&gt;
&lt;li&gt;자동화 툴 -&gt; 프로토콜로 브라우저에서 스크립트 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cypress&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cypress&quot; aria-label=&quot;cypress permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Cypress&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;브라우저에서 실행&lt;/li&gt;
&lt;li&gt;Nodejs 서버 프로세스로 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;testcafe&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#testcafe&quot; aria-label=&quot;testcafe permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TestCafe&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Node server side test code -&gt; client-side javascript&lt;/li&gt;
&lt;li&gt;브라우저에 삽입&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;크로스-브라우저-자동화를-어떻게-더-잘할-수-있을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%81%AC%EB%A1%9C%EC%8A%A4-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9E%90%EB%8F%99%ED%99%94%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8D%94-%EC%9E%98%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;크로스 브라우저 자동화를 어떻게 더 잘할 수 있을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;크로스 브라우저 자동화를 어떻게 더 잘할 수 있을까?&lt;/h2&gt;
&lt;h3 id=&quot;webdriver-bidi&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#webdriver-bidi&quot; aria-label=&quot;webdriver bidi permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;WebDriver BiDi&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;WebDriver BiDi protocol을 통해 명령을 수행&lt;/li&gt;
&lt;li&gt;웹소켓 사용&lt;/li&gt;
&lt;li&gt;크로스브라우저 지원&lt;/li&gt;
&lt;li&gt;빠르고, 양방향 메시징 가능&lt;/li&gt;
&lt;li&gt;low level control도 지원&lt;/li&gt;
&lt;li&gt;Ergonomic API build for testing - Ergonomic : 인체공학적이라는 뜻인데, 의역하기 어려움.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;new-protocol을-도입하기-위해-체크해야-되는-부분&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#new-protocol%EC%9D%84-%EB%8F%84%EC%9E%85%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EC%B2%B4%ED%81%AC%ED%95%B4%EC%95%BC-%EB%90%98%EB%8A%94-%EB%B6%80%EB%B6%84&quot; aria-label=&quot;new protocol을 도입하기 위해 체크해야 되는 부분 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;New protocol을 도입하기 위해 체크해야 되는 부분&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Specification(RFC)&lt;/li&gt;
&lt;li&gt;Verification&lt;/li&gt;
&lt;li&gt;Implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;발표자님의-말씀&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%9C%ED%91%9C%EC%9E%90%EB%8B%98%EC%9D%98-%EB%A7%90%EC%94%80&quot; aria-label=&quot;발표자님의 말씀 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;발표자님의 말씀&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;DX 발전과 ecosystem에 기여 중&lt;/li&gt;
&lt;li&gt;테스팅 툴들이 사람들에게 도움이 되길 바라며&lt;/li&gt;
&lt;li&gt;WebDriver BiDi를 사용하는 프레임워크가 출시되면 빨리 써보고 예제를 많이 올려주시길!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;느낀점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8A%90%EB%82%80%EC%A0%90&quot; aria-label=&quot;느낀점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;느낀점&lt;/h2&gt;
&lt;p&gt;구글 크롬 new features 탭에 나오시는데 너무 반가웠다.
이런 툴들은 어떻게 돌아가나 신기했는데 원리를 알고 나니 더 재밌어졌다.
cypress를 사용해봤는데 너무 무거워서 로컬로 돌리면 pc가 감당하지 못했다.
WebDriver BiDi가 나오면 써보고 싶다. 가볍고 빠르길 바라며.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/GoogleChromeLabs/chromium-bidi/milestones&quot;&gt;https://github.com/GoogleChromeLabs/chromium-bidi/milestones&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[vue3 typescript props interface issue]]></title><description><![CDATA[문제 상황 vue3 + typescript로 개발을 하던 중, props에 type을 추가하고 싶었는데 예상치 못한 이슈를 마주했다.
interface로 선언했는데 처음 보는 에러가 떴다. image
image 원인 https://github.com…]]></description><link>https://donghoon-song.github.io/vue3/vue3-typescript-props-interface-issue/</link><guid isPermaLink="false">https://donghoon-song.github.io/vue3/vue3-typescript-props-interface-issue/</guid><pubDate>Thu, 16 Mar 2023 23:03:49 GMT</pubDate><content:encoded>&lt;h2 id=&quot;문제-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C-%EC%83%81%ED%99%A9&quot; aria-label=&quot;문제 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제 상황&lt;/h2&gt;
&lt;p&gt;vue3 + typescript로 개발을 하던 중, props에 type을 추가하고 싶었는데 예상치 못한 이슈를 마주했다.
interface로 선언했는데 처음 보는 에러가 떴다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/225346350-e613ee22-a398-4cf8-9ed6-26bf52d49797.png&quot; alt=&quot;image&quot;&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/225346382-b64b34fd-9585-4480-9eb3-88a2770adccc.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;원인 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;원인&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vuejs/language-tools/discussions/2421&quot;&gt;https://github.com/vuejs/language-tools/discussions/2421&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;위의 글을 참고하면 모든 프로젝트에서 발생하는 것은 아닌데 tsconfig에서 아래 옵션이 켜져 있으면 발생한다고 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;composite&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&quot;declaration&quot;: true&lt;/code&gt;도 같은 에러를 발생시킨다.&lt;/p&gt;
&lt;p&gt;본문에 따르면 props는 component에서 export된 type중 하나이고, &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;defineProps&lt;/code&gt;에 전달되면 &lt;code class=&quot;language-text&quot;&gt;setup&lt;/code&gt; 함수 내부에 들어가기 때문에 이 에러를 피하려면 hoisting이 필요하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;   msg&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;     msg&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;defineProps&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Props&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;해결책&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%EC%B1%85&quot; aria-label=&quot;해결책 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결책&lt;/h2&gt;
&lt;p&gt;현재로서는, Volar에서 hoisting을 하려면 &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt;를 사용할 수 밖에 없는데, 이걸 사용자에게 강제하는건 별로 직관적이지 않다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/225351075-f357028f-691f-4291-b054-27265d3d2011.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;우회하는 다른 방법으로는 &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; 대신 &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt;을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/225351710-665a1cbb-1667-4abb-9c91-90ba7b5de04f.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;읽으면서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%BD%EC%9C%BC%EB%A9%B4%EC%84%9C&quot; aria-label=&quot;읽으면서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;읽으면서&lt;/h2&gt;
&lt;p&gt;나는 일단 &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt;해서 우회하고자 한다. &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt;으로 바꾸면 나중에 확장하지 못할 거 같아서.
개발자들이 이 문제를 어떻게 해결할지 궁금하다. 살포시 watch를 눌러본다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[window is undefined, vue-test-utils needs to be run in a browser environment 이슈 해결법]]></title><description><![CDATA[이슈 기존 프로젝트에 vue-test-utils v1, jest로 테스트 환경을 구축하는데 다음과 같은 에러를 만났다. image 원인 이슈에 대해서 검색해보다가 아래 글을 찾았다. https://github.com/vuejs/vue-test…]]></description><link>https://donghoon-song.github.io/test/window-is-undefined,-vue-test-utils-needs-to-be-run-in-a-browser-environment-이슈-해결법/</link><guid isPermaLink="false">https://donghoon-song.github.io/test/window-is-undefined,-vue-test-utils-needs-to-be-run-in-a-browser-environment-이슈-해결법/</guid><pubDate>Sun, 05 Mar 2023 15:04:29 GMT</pubDate><content:encoded>&lt;h2 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h2&gt;
&lt;p&gt;기존 프로젝트에 vue-test-utils v1, jest로 테스트 환경을 구축하는데 다음과 같은 에러를 만났다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/221463165-2bb56138-f202-46bb-a40f-75da98f0b53d.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;원인 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;원인&lt;/h2&gt;
&lt;p&gt;이슈에 대해서 검색해보다가 아래 글을 찾았다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vuejs/vue-test-utils/issues/999&quot;&gt;https://github.com/vuejs/vue-test-utils/issues/999&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;jest27부터 성능 이슈 때문에 기본 테스트 환경값을 &lt;code class=&quot;language-text&quot;&gt;&quot;jsdom&quot;&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;&quot;node&quot;&lt;/code&gt;로 바꿨다고 한다. &lt;code class=&quot;language-text&quot;&gt;jest-environment-jsdom&lt;/code&gt; 또한 기본 종속성 트리에서 제거했다고 한다.&lt;/p&gt;
&lt;h2 id=&quot;해결책&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%EC%B1%85&quot; aria-label=&quot;해결책 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결책&lt;/h2&gt;
&lt;p&gt;이를 해결하려면 &lt;code class=&quot;language-text&quot;&gt;jest-environment-jsdom&lt;/code&gt; 패키지를 설치하고 testEnvironment값을 지정해주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm i --save-dev jest-environment-jsdom&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// jest.config.js&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
 &lt;span class=&quot;token literal-property property&quot;&gt;testEnvironment&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;jsdom&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[구글 스프레드시트에서 javascript 코드 실행하기(Apps Script, custom function)]]></title><description><![CDATA[사이드 프로젝트로 database의 data를 migration하다가 스프레드시트 상에서 데이터를 쉽게 변환할 수 있는 방법으로 Apps Script 기능을 찾을 수 있었습니다. 저에겐 unix timestamp 데이터가 있었고, 이것을 ISO…]]></description><link>https://donghoon-song.github.io/excel/구글-스프레드시트에서-javascript-코드-실행하기(apps-script,-custom-function)/</link><guid isPermaLink="false">https://donghoon-song.github.io/excel/구글-스프레드시트에서-javascript-코드-실행하기(apps-script,-custom-function)/</guid><pubDate>Sun, 19 Feb 2023 18:03:01 GMT</pubDate><content:encoded>&lt;p&gt;사이드 프로젝트로 database의 data를 migration하다가 스프레드시트 상에서 데이터를 쉽게 변환할 수 있는 방법으로 Apps Script 기능을 찾을 수 있었습니다.&lt;/p&gt;
&lt;p&gt;저에겐 unix timestamp 데이터가 있었고, 이것을 ISO String으로 변환해서 새로운 데이터베이스에 bulk로 insert하고 싶었습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/219938526-70679086-0c56-445e-a7d6-3f9bc5922a2c.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;확장 프로그램의 Apps Script 메뉴를 활용합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/219938591-963b5bf0-15d4-4fc2-9af0-4589f9dc2f12.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그러면 코드를 작성하는 화면이 나오는데, 함수를 작성만 한다고 추가되지는 않고 스크린샷에서 보시는 것처럼 customfunction이라는 주석을 달아야 등록이 됩니다. jsDoc 형식으로 부가적인 주석도 달 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/219939054-8d29b2f8-461e-4f54-b227-524cb64d5b64.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;주석을 작성하고 저장후에 스프레드시트로 돌아오면 저희가 작성했던 커스텀 함수가 보이고, 주석도 잘 보이는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/219939119-a2868ea8-0a85-4b09-90f1-7ddbe8028ecb.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/219939239-bfa810eb-5cc6-4f55-b5b9-92ef559110d0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;데이터를 변환할 때 자바스크립트가 필요하거나, 편한 경우에 데이터를 복사해서 변환 후에 다시 붙여넣는 작업을 했었는데 이 기능을 사용하면 너무 편하게 변환할 수 있고, 자주 사용하는 스크립트는 저장해 놓을 수 있어서 더 좋은 거 같습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[특정 셀로 바로 가는 엑셀 링크 만드는 방법]]></title><description><![CDATA[스프레드시트로 작업하면서 데이터가 많아지면 동료에게 공유하는 것도 일입니다. 특정 데이터를 찾을 때 문서링크로 이동 후에 직접 검색을 하시는 동료들의 모습을 보고 특정 셀로 바로 이동할 수는 없을까 생각해보다가 찾은 방법입니다. 예시의 데이터는 A…]]></description><link>https://donghoon-song.github.io/excel/특정-셀로-바로-가는-엑셀-링크-만드는-방법/</link><guid isPermaLink="false">https://donghoon-song.github.io/excel/특정-셀로-바로-가는-엑셀-링크-만드는-방법/</guid><pubDate>Fri, 17 Feb 2023 09:02:14 GMT</pubDate><content:encoded>&lt;p&gt;스프레드시트로 작업하면서 데이터가 많아지면 동료에게 공유하는 것도 일입니다. 특정 데이터를 찾을 때 문서링크로 이동 후에 직접 검색을 하시는 동료들의 모습을 보고 특정 셀로 바로 이동할 수는 없을까 생각해보다가 찾은 방법입니다.&lt;/p&gt;
&lt;p&gt;예시의 데이터는 A열 19행에 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217991961-75d0835b-20b1-4648-9979-a8109fbfce1a.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;바로 이동하고자 하는 셀에서 &lt;code class=&quot;language-text&quot;&gt;이 셀의 링크 얻기&lt;/code&gt;로 링크를 얻으시고 접속해보시면&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217992003-bc04fd15-e54a-4972-809b-5ad94562c5b6.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;아래와 같이 해당 셀로 바로 갈 수 있는 링크를 얻게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217992042-cc01430f-a255-4f1a-a754-51bef2ab3962.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이 시트의 몇열 몇행에 데이터가 있다고 전달하기보다는 이 링크를 바로 공유해보면 어떨까요 :)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[supabase bucket new row violates row-level security policy for table "objects" 이슈 해결법(policy 설정법)]]></title><description><![CDATA[이슈 supabase storage bucket에서 권한이 없는 경로로 operation을 수행하면 다음과 같은 권한 이슈가 발생합니다. 아래 이슈는 제가 권한이 없는 경로로 image를 upload할 때 발생했습니다. image image…]]></description><link>https://donghoon-song.github.io/supabase/supabase-bucket-new-row-violates-row-level-security-policy-for-table-&quot;objects&quot;-이슈-해결법(policy-설정법)/</link><guid isPermaLink="false">https://donghoon-song.github.io/supabase/supabase-bucket-new-row-violates-row-level-security-policy-for-table-&quot;objects&quot;-이슈-해결법(policy-설정법)/</guid><pubDate>Fri, 10 Feb 2023 00:03:29 GMT</pubDate><content:encoded>&lt;h2 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h2&gt;
&lt;p&gt;supabase storage bucket에서 권한이 없는 경로로 operation을 수행하면 다음과 같은 권한 이슈가 발생합니다.&lt;/p&gt;
&lt;p&gt;아래 이슈는 제가 권한이 없는 경로로 image를 upload할 때 발생했습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217840289-d7da44bb-1145-4ac2-b549-fc6a606d6ab7.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217840234-b4ee8b65-6966-400d-9d25-f0c3cb415b7b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;new row violates row-level security policy for table \&quot;objects\&quot;&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결&lt;/h2&gt;
&lt;p&gt;권한이 없으면 권한을 설정해주면 됩니다! bucket policy 메뉴로 접속합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217853203-8ec72588-29d3-4605-86a6-4ad7a141d281.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;해당 bucket의 New policy 메뉴를 클릭해서 새로운 정책을 추가합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217854925-e02b417d-e4b4-4018-b1ee-d2073e871cde.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;저는 간단하게 기존의 템플릿에서 가져오도록 했습니다.&lt;/p&gt;
&lt;p&gt;커스터마이징이 필요하시면 아래 버튼을 클릭하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217840069-886c3b10-5558-41a0-81ca-cb9f2d59624b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;맨 첫번째 정책인 “public folder에 있는 JPG image에 대해 유저에게 권한 부여하기”를 선택합니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217840460-064c48a7-501b-433a-a5e3-8ec3ae82e280.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;여기서 Allowed operation에 체크해주시고, 저는 &lt;code class=&quot;language-text&quot;&gt;Policy definition&lt;/code&gt;에서 JPG image인 조건을 제거했습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217855693-f0b90ff5-6b05-4a06-90aa-6b291fa65ced.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그렇게 정책을 생성한 후에 다시 이미지를 업로드해보면 정상적으로 작동하는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/217856852-64cb6752-3020-4c0b-bbe0-8ff2916c750d.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[vue3 composition api로 재사용가능한 코드 만들기 & toRefs 기능]]></title><description><![CDATA[vue3의 composition api를 사용하면 로직을 재사용할 수 있습니다. 직접 짜보니 react hook과 흡사하다는 생각이 많이 들었습니다. supabase에서 id에 해당하는 data…]]></description><link>https://donghoon-song.github.io/vue3/vue3-composition-api로-재사용가능한-코드-만들기-&amp;-torefs-기능/</link><guid isPermaLink="false">https://donghoon-song.github.io/vue3/vue3-composition-api로-재사용가능한-코드-만들기-&amp;-torefs-기능/</guid><pubDate>Tue, 07 Feb 2023 23:03:23 GMT</pubDate><content:encoded>&lt;p&gt;vue3의 composition api를 사용하면 로직을 재사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;직접 짜보니 react hook과 흡사하다는 생각이 많이 들었습니다.&lt;/p&gt;
&lt;p&gt;supabase에서 id에 해당하는 data의 한글이름을 가져오는 코드를 재사용하기 위해 짜보았습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// @/modules/useKoreanName.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; supabase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/utils/supabase&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reactive&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toRefs &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vue&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserKoreanName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;userKoreanName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;이름&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;loadUserKoreanName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; koreanName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUserKoreanName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;koreanName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userKoreanName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; koreanName
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fetchUserKoreanName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; supabase
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;korean_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;users&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;korean_name
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toRefs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fetchUserKoreanName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loadUserKoreanName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 눈여겨볼 점은 state를 &lt;code class=&quot;language-text&quot;&gt;...toRefs(state)&lt;/code&gt;의 형태로 반환하는 점입니다. 이렇게 해야 반응성이 유지된다고 하는데요. 이 모듈을 컴포넌트에서 불러와서 사용해봤습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userKoreanName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loadUserKoreanName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useKoreanName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;onMounted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;fetchNotes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;loadUserKoreanName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text-4xl mr-4&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userKoreanName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 님 담벼락&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;template에서 userKoreanName을 출력하는데 아래와 같이 잘 동작하는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;img width=&quot;210&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/217270090-637770b3-9f26-46b4-8950-b5f33dde0c37.png&quot;&gt;
&lt;p&gt;만약에 toRefs를 빼보면 어떨까요?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// @/modules/useKoreanName.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; supabase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/utils/supabase&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reactive &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vue&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserKoreanName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;userKoreanName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;이름&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;loadUserKoreanName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; koreanName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUserKoreanName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;koreanName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userKoreanName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; koreanName
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;koreanName after load : &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userKoreanName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fetchUserKoreanName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; supabase
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;korean_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;users&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;korean_name
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fetchUserKoreanName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loadUserKoreanName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 경우에는 로그를 찍어보면 useUserKoreanName 함수 내부에서는 state가 반응성을 띕니다.&lt;/p&gt;
&lt;img width=&quot;437&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/217271719-847b1c3c-09d9-4d33-92a0-bc05df2831be.png&quot;&gt;
&lt;p&gt;하지만 컴포넌트에서 userKoreanName을 출력해보면 기본값이 들어가 있는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;img width=&quot;183&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/217269520-8c1f4676-3cab-4378-9a37-9cadf8529259.png&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://vuejs.org/api/reactivity-utilities.html#torefs&quot;&gt;toRefs에 관한 공식문서&lt;/a&gt;
공식문서를 살펴보면 &lt;code class=&quot;language-text&quot;&gt;toRefs&lt;/code&gt;는 composable function에서 반응형의 객체를 반환할 때, 사용하는 컴포넌트에서는 객체를 destructure나 spread를 하더라도 반응성을 잃지 않도록 한다고 합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[vite lib production build에서 css 파일명 변경하기]]></title><description><![CDATA[해결법 vite를 사용해 library mode로 빌드할 때 나오는 css파일의 이름을 변경하는 방법은 다음과 같습니다. 의 build/rollupOptions에 output, 를 설정합니다. 결과 Pasted image 20230127143035]]></description><link>https://donghoon-song.github.io/vite/vite-lib-production-build에서-css-파일명-변경하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/vite/vite-lib-production-build에서-css-파일명-변경하기/</guid><pubDate>Sat, 04 Feb 2023 20:03:38 GMT</pubDate><content:encoded>&lt;h3 id=&quot;해결법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%EB%B2%95&quot; aria-label=&quot;해결법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결법&lt;/h3&gt;
&lt;p&gt;vite를 사용해 library mode로 빌드할 때 나오는 css파일의 이름을 변경하는 방법은 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;vite.config.js&lt;/code&gt;의 build/rollupOptions에 output, &lt;code class=&quot;language-text&quot;&gt;assetFileNames&lt;/code&gt;를 설정합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token literal-property property&quot;&gt;rollupOptions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;token literal-property property&quot;&gt;assetFileNames&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;LIBRARY_NAME&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.[ext]&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;결과&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EA%B3%BC&quot; aria-label=&quot;결과 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결과&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/216765268-c0b603c9-c5bc-4440-8bee-fa57c20f91fa.png&quot; alt=&quot;Pasted image 20230127143035&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[vite에서 전역 scss 파일 추가하기]]></title><description><![CDATA[vite에서 전역 scss를 추가하는 방법을 다음과 같습니다. 해결법 에 css, preprocessorOptions, scss, additionalData 속성을 추가해주시면 됩니다.]]></description><link>https://donghoon-song.github.io/vite/vite에서-전역-scss-파일-추가하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/vite/vite에서-전역-scss-파일-추가하기/</guid><pubDate>Sat, 04 Feb 2023 20:02:02 GMT</pubDate><content:encoded>&lt;p&gt;vite에서 전역 scss를 추가하는 방법을 다음과 같습니다.&lt;/p&gt;
&lt;h3 id=&quot;해결법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%EB%B2%95&quot; aria-label=&quot;해결법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결법&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;vite.config.js&lt;/code&gt;에 css, preprocessorOptions, scss, additionalData 속성을 추가해주시면 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; defineConfig &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vite&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;vue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./src&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 이 부분 추가&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;preprocessorOptions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;scss&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;additionalData&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;@import &quot;@/assets/style/base/main&quot;;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[vue3 vite 프로젝트에 tailwind 설치하는 법]]></title><description><![CDATA[패키지 설치 Tailwind와 peer-dependencies를 설치합니다. 설정 파일 생성 , 를 아래 명령어로 생성합니다.  옵션을 주면 Tailwind가 을 하면서 사용하지 않는 스타일을 production build에서 제거합니다. index…]]></description><link>https://donghoon-song.github.io/vue.js/vue3-vite-프로젝트에-tailwind-설치하는-법/</link><guid isPermaLink="false">https://donghoon-song.github.io/vue.js/vue3-vite-프로젝트에-tailwind-설치하는-법/</guid><pubDate>Sat, 28 Jan 2023 09:02:23 GMT</pubDate><content:encoded>&lt;h3 id=&quot;패키지-설치&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%84%A4%EC%B9%98&quot; aria-label=&quot;패키지 설치 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;패키지 설치&lt;/h3&gt;
&lt;p&gt;Tailwind와 peer-dependencies를 설치합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; tailwindcss@latest postcss@latest autoprefixer@latest&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;설정-파일-생성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%A4%EC%A0%95-%ED%8C%8C%EC%9D%BC-%EC%83%9D%EC%84%B1&quot; aria-label=&quot;설정 파일 생성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;설정 파일 생성&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;tailwind.config.js&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;postcss.config.js&lt;/code&gt;를 아래 명령어로 생성합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;npx tailwindcss init &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;perge&lt;/code&gt; 옵션을 주면 Tailwind가 &lt;code class=&quot;language-text&quot;&gt;tree-shaking&lt;/code&gt;을 하면서 사용하지 않는 스타일을 production build에서 제거합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tailwind.config.js&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;purge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./index.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./src/**/*.{vue,js,ts,jsx,tsx}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;darkMode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// or &apos;media&apos; or &apos;class&apos;&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;variants&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;indexcss-추가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#indexcss-%EC%B6%94%EA%B0%80&quot; aria-label=&quot;indexcss 추가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;index.css 추가&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;@tailwind&lt;/code&gt; directive를 사용해 Tailwind style들을 추가합니다. Tailwind가 build time에 해당 directive들을 스타일로 변환합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* ./src/index.css */&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@tailwind&lt;/span&gt; base&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@tailwind&lt;/span&gt; components&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@tailwind&lt;/span&gt; utilities&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;indexcss-import&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#indexcss-import&quot; aria-label=&quot;indexcss import permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;index.css import&lt;/h3&gt;
&lt;p&gt;마지막으로 main.js에 css 파일을 추가해주면 끝입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createApp &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vue&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; App &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./App.vue&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index.css&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;createApp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;App&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;#app&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;설정-변화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%A4%EC%A0%95-%EB%B3%80%ED%99%94&quot; aria-label=&quot;설정 변화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;설정 변화&lt;/h3&gt;
&lt;p&gt;tailwind v3이상을 쓰신다면! &lt;code class=&quot;language-text&quot;&gt;purge -&gt; content&lt;/code&gt;로 rename되었으니 바꿔주세요.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tailwind.config.js&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./index.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./src/**/*.{vue,js,ts,jsx,tsx}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;darkMode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// or &apos;media&apos; or &apos;class&apos;&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;variants&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 darkMode 기본값이 &lt;code class=&quot;language-text&quot;&gt;media&lt;/code&gt;로 변경되었다고 합니다. 그래서 따로 지정해주시려는 게 아니면 darkMode를 지워주셔도 되겠습니다 :)&lt;/p&gt;
&lt;p&gt;더 자세한 내용은 아래 가이드를 참고해주시면 됩니다. 감사합니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tailwindcss.com/docs/upgrade-guide#configure-content-sources&quot;&gt;tailwindcss upgrade guide&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Failed to load plugin import declared in .eslintrc.js eslint 이슈 해결법]]></title><description><![CDATA[eslint를 upgrade한 lint 명령어를 실행시켰는데 아래와 같은 에러를 만났습니다. 아래 명령어를 실행해서 plugin을 upgrade했더니 해결됐습니다. https://github.com/import-js/eslint-plugin…]]></description><link>https://donghoon-song.github.io/eslint/failed-to-load-plugin-import-declared-in-.eslintrc.js-eslint-이슈-해결법/</link><guid isPermaLink="false">https://donghoon-song.github.io/eslint/failed-to-load-plugin-import-declared-in-.eslintrc.js-eslint-이슈-해결법/</guid><pubDate>Thu, 26 Jan 2023 23:02:22 GMT</pubDate><content:encoded>&lt;p&gt;eslint를 upgrade한 lint 명령어를 실행시켰는데 아래와 같은 에러를 만났습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ eslint &lt;span class=&quot;token parameter variable&quot;&gt;--ext&lt;/span&gt; .js,.vue --ignore-path .gitignore &lt;span class=&quot;token parameter variable&quot;&gt;--fix&lt;/span&gt; src

Oops&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; Something went wrong&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; :&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;

ESLint: &lt;span class=&quot;token number&quot;&gt;8.32&lt;/span&gt;.0

Error &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ERR_PACKAGE_PATH_NOT_EXPORTED&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;: Failed to load plugin &lt;span class=&quot;token string&quot;&gt;&apos;import&apos;&lt;/span&gt; declared &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.eslintrc.js&apos;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; Package subpath &lt;span class=&quot;token string&quot;&gt;&apos;./lib/util/glob-util&apos;&lt;/span&gt; is not defined by &lt;span class=&quot;token string&quot;&gt;&quot;exports&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; /Users/donghoonsong/project/comento-ui/node_modules/eslint/package.json
Referenced from: /Users/donghoonsong/project/comento-ui/.eslintrc.js
    at new NodeError &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/errors:371:5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at throwExportsNotFound &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/esm/resolve:440:9&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at packageExportsResolve &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/esm/resolve:692:3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at resolveExports &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/cjs/loader:482:36&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at Function.Module._findPath &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/cjs/loader:522:31&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at Function.Module._resolveFilename &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/cjs/loader:919:27&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at Function.Module._load &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/cjs/loader:778:27&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at Module.require &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/cjs/loader:1005:19&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at require &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:internal/modules/cjs/helpers:102:18&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    at Object.&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;anonymous&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;/Users/donghoonsong/project/comento-ui/node_modules/eslint-plugin-import/lib/rules/no-unused-modules.js:43:34&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
error Command failed with &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; code &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아래 명령어를 실행해서 plugin을 upgrade했더니 해결됐습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; upgrade eslint-plugin-import&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/import-js/eslint-plugin-import/issues/2252&quot;&gt;https://github.com/import-js/eslint-plugin-import/issues/2252&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[vscode prettier format on save 적용]]></title><description><![CDATA[format on save는 파일을 저장할 때 포맷을 적용하는 기능입니다. vscode에서 prettier를 설치한 후에 format on save를 적용하고 싶으시다면
(mac 기준) 로 설정창을 열고 를 검색합니다.
image…]]></description><link>https://donghoon-song.github.io/prettier/vscode-prettier-format-on-save-적용/</link><guid isPermaLink="false">https://donghoon-song.github.io/prettier/vscode-prettier-format-on-save-적용/</guid><pubDate>Thu, 26 Jan 2023 23:02:20 GMT</pubDate><content:encoded>&lt;p&gt;format on save는 파일을 저장할 때 포맷을 적용하는 기능입니다.&lt;/p&gt;
&lt;p&gt;vscode에서 prettier를 설치한 후에 format on save를 적용하고 싶으시다면
(mac 기준) &lt;code class=&quot;language-text&quot;&gt;command + ,&lt;/code&gt;로 설정창을 열고 &lt;code class=&quot;language-text&quot;&gt;default formatter&lt;/code&gt;를 검색합니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/214856315-448267f8-bfbd-4719-91b2-5330cae814b9.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;해당 값을 &lt;code class=&quot;language-text&quot;&gt;prettier&lt;/code&gt;로 설정해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/214856583-fae5e9d0-5b01-44cb-816e-20a811676d38.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그리고 다시 &lt;code class=&quot;language-text&quot;&gt;format on save&lt;/code&gt;를 검색해서 활성화시켜주시면 끝입니다!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/214856908-ca8f741d-7f86-402e-8171-a50b96c76137.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Vue] Component name should always be multi-word eslint error]]></title><description><![CDATA[이슈 eslint를 8로 업데이트 하니 새로운 eslint error가 발생했습니다. 해결 아래 줄을 eslint rules에 삽입했습니다. 공부 https://eslint.vuejs.org/rules/multi-word-component-names…]]></description><link>https://donghoon-song.github.io/eslint/[vue]-component-name-should-always-be-multi-word-eslint-error/</link><guid isPermaLink="false">https://donghoon-song.github.io/eslint/[vue]-component-name-should-always-be-multi-word-eslint-error/</guid><pubDate>Thu, 26 Jan 2023 23:01:55 GMT</pubDate><content:encoded>&lt;h3 id=&quot;이슈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%8A%88&quot; aria-label=&quot;이슈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이슈&lt;/h3&gt;
&lt;p&gt;eslint를 8로 업데이트 하니 새로운 eslint error가 발생했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt; &lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt;:8  error  Component name &lt;span class=&quot;token string&quot;&gt;&quot;Loader&quot;&lt;/span&gt; should always be multi-word  vue/multi-word-component-names
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결&lt;/h3&gt;
&lt;p&gt;아래 줄을 eslint rules에 삽입했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string-property property&quot;&gt;&apos;vue/multi-word-component-names&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;off&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;공부&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B3%B5%EB%B6%80&quot; aria-label=&quot;공부 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;공부&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://eslint.vuejs.org/rules/multi-word-component-names.html&quot;&gt;https://eslint.vuejs.org/rules/multi-word-component-names.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;문서를 살펴보면 &lt;code class=&quot;language-text&quot;&gt;root App component나 &amp;lt;transition&gt;, &amp;lt;component&gt; 같은 vue의 built-in 컴포넌트가 아니면 component name은 multi-word가 되어야 한다&lt;/code&gt;는 규칙이 있습니다. 이 규칙이 생겨난 이유는 &lt;code class=&quot;language-text&quot;&gt;HTML element(single-word)와의 혼동을 막기 위함&lt;/code&gt;입니다.&lt;/p&gt;
&lt;p&gt;eslint-plugin-vue v7.20.0 부터 추가되었다고 하는데, 매번 component name을 multi-word로 짓는 것도 일일 거 같고, 이름이 겹칠 확률이 얼마나 될까 싶습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Vue3 + Vite에서 환경변수(env) 사용하는 방법]]></title><description><![CDATA[create-vue를 사용해 생성한 Vue3 프로젝트는 Vite를 기반으로 합니다. 이 환경에서는 env에 어떻게 접근할까요? 먼저, 을 prefix로 사용해야 합니다. 그러면 로 접근할 수 있습니다.]]></description><link>https://donghoon-song.github.io/vue.js/vue3-+-vite에서-환경변수(env)-사용하는-방법/</link><guid isPermaLink="false">https://donghoon-song.github.io/vue.js/vue3-+-vite에서-환경변수(env)-사용하는-방법/</guid><pubDate>Tue, 24 Jan 2023 18:02:35 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/vuejs/create-vue&quot;&gt;create-vue&lt;/a&gt;를 사용해 생성한 Vue3 프로젝트는 Vite를 기반으로 합니다. 이 환경에서는 env에 어떻게 접근할까요?&lt;/p&gt;
&lt;p&gt;먼저, &lt;code class=&quot;language-text&quot;&gt;VITE_&lt;/code&gt;을 prefix로 사용해야 합니다. 그러면 &lt;code class=&quot;language-text&quot;&gt;import.meta.env&lt;/code&gt;로 접근할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;VITE_ENV_VARIABLE = EXAMPLE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; variable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;meta&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;VITE_ENV_VARIABLE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[php version upgrade 이슈 해결]]></title><description><![CDATA[저희는 백엔드가 php로 되어 있는데요. php version을 8.0 -> 8.1로 올리셔서 그에 대응해야 하는 상황이었습니다. 기존에는 아래와 같은 방식으로 설치하고, 링크를 다시 해주면 반영됐었는데, 이번에는 link를 해도 version…]]></description><link>https://donghoon-song.github.io/php/php-version-upgrade-이슈-해결/</link><guid isPermaLink="false">https://donghoon-song.github.io/php/php-version-upgrade-이슈-해결/</guid><pubDate>Tue, 10 Jan 2023 14:01:31 GMT</pubDate><content:encoded>&lt;p&gt;저희는 백엔드가 php로 되어 있는데요. php version을 8.0 -&gt; 8.1로 올리셔서 그에 대응해야 하는 상황이었습니다.&lt;/p&gt;
&lt;p&gt;기존에는 아래와 같은 방식으로 설치하고, 링크를 다시 해주면 반영됐었는데, 이번에는 link를 해도 version이 바뀌지 않는 이슈가 생겼습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; php@8.1
brew unlink php@8.0
brew &lt;span class=&quot;token function&quot;&gt;link&lt;/span&gt; php@8.1
// php version check
php &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그래서 원인을 찾다보니까 &lt;code class=&quot;language-text&quot;&gt;~/.zshrc&lt;/code&gt;에 아래와 같이 php version을 명시하는 코드가 들어 있었고 이 부분을 제거했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;PATH&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/opt/homebrew/opt/php@8.0/bin:&lt;span class=&quot;token environment constant&quot;&gt;$PATH&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 버전을 다시 확인해봤는데 이번에는 엉뚱하게 아래와 같은 메시지가 떴습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;WARNING: PHP is not recommended&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;PHP is included in macOS for compatibility with legacy software.
Future versions of macOS will not include PHP.
PHP 7.3.29-to-be-removed-in-future-macOS (cli) (built: Sep  6 2021 05:14:39) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.29, Copyright (c) 1998-2018 Zend Technologies&lt;/p&gt;
&lt;p&gt;메시지로 구글링을 해봤는데 보통은 php를 다시 설치하고, 다시 링크 과정을 거쳐서 해결했다고 나와 있었습니다. 하지만 저는 그런 방법들만으로는 해결하지 못했고, 이것저것 해보다가 &lt;code class=&quot;language-text&quot;&gt;~/.zshrc&lt;/code&gt;에 다시 버전을 명시해주는 코드를 넣어서 해결했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;PATH&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/opt/homebrew/opt/php@8.1/bin:&lt;span class=&quot;token environment constant&quot;&gt;$PATH&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[[intellij] 인텔리제이 단어 찾아바꾸기 단축키]]></title><description><![CDATA[웹스톰에서 단축키 로 코드 검색을 주로 했었는데요 을 사용하면 찾아바꾸기가 가능합니다. 저는 라이브러리 업데이트 후에 변경사항을 일괄 적용해야 했는데요. Typography의 기존 headline6 type을 headline…]]></description><link>https://donghoon-song.github.io/tools/[intellij]-인텔리제이-단어-전체-바꾸기-단축키/</link><guid isPermaLink="false">https://donghoon-song.github.io/tools/[intellij]-인텔리제이-단어-전체-바꾸기-단축키/</guid><pubDate>Tue, 10 Jan 2023 11:02:02 GMT</pubDate><content:encoded>&lt;p&gt;웹스톰에서 단축키 &lt;code class=&quot;language-text&quot;&gt;ctrl + shift + f&lt;/code&gt;로 코드 검색을 주로 했었는데요&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;ctrl + shift + r&lt;/code&gt;을 사용하면 찾아바꾸기가 가능합니다.&lt;/p&gt;
&lt;p&gt;저는 라이브러리 업데이트 후에 변경사항을 일괄 적용해야 했는데요. Typography의 기존 headline6 type을 headline7로 바꿔야 했습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/211447711-094d4609-9227-44f4-b699-d208b9aec458.png&quot; alt=&quot;image&quot;&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/211447896-0b414371-9267-4475-b343-cc94588eb330.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;메뉴 하단에 있는 &lt;code class=&quot;language-text&quot;&gt;replace All&lt;/code&gt; 버튼으로 쉽게 변경할 수 있었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[실용주의 프로그래머 리뷰 (2장)]]></title><description><![CDATA[동료들과 실용주의 프로그래머라는 책을 같이 읽고 있습니다. 공부하면서 정리한 내용을 블로그에도 남겨볼까 합니다. 아직 못 읽은 부분은 계속 업데이트하려고 합니다.…]]></description><link>https://donghoon-song.github.io/books/실용주의-프로그래머-리뷰-(2장)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/실용주의-프로그래머-리뷰-(2장)/</guid><pubDate>Sun, 08 Jan 2023 20:14:25 GMT</pubDate><content:encoded>&lt;p&gt;동료들과 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001033128&quot;&gt;실용주의 프로그래머&lt;/a&gt;라는 책을 같이 읽고 있습니다. 공부하면서 정리한 내용을 블로그에도 남겨볼까 합니다. 아직 못 읽은 부분은 계속 업데이트하려고 합니다.&lt;/p&gt;
&lt;h1 id=&quot;2장-실용주의-접근법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2%EC%9E%A5-%EC%8B%A4%EC%9A%A9%EC%A3%BC%EC%9D%98-%EC%A0%91%EA%B7%BC%EB%B2%95&quot; aria-label=&quot;2장 실용주의 접근법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2장. 실용주의 접근법&lt;/h1&gt;
&lt;p&gt;새로운 아이디어에 전력투구하기 전에 먼저 아이디어를 검증하고 피드백을 받아 보는 것이 매우 중요하다.&lt;/p&gt;
&lt;h2 id=&quot;topic8-좋은-설계의-핵심&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic8-%EC%A2%8B%EC%9D%80-%EC%84%A4%EA%B3%84%EC%9D%98-%ED%95%B5%EC%8B%AC&quot; aria-label=&quot;topic8 좋은 설계의 핵심 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic8 좋은 설계의 핵심&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;좋은 설계는 나쁜 설계보다 바꾸기 쉽다.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;ETC(Easier to Change)&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;‘내가 방금 한 일이 전체 시스템을 바꾸기 쉽게 만들었을까, 어렵게 만들었을까?’&lt;/code&gt; → 파일 저장, 테스트 작성, 버그 수정시에 물어보기&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;코드의 결합도를 낮추고 응집도를 높인다.&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;컴포넌트 개발할 때 신경쓰고 있지만 정말 어렵다. 버튼 등 간단한 컴포넌트는 원칙을 지키기 비교적 쉬우나, 여러 개의 컴포넌트를 같이 쓰는 등의 컴포넌트는 결합도가 높으면 사용하기는 쉬워지나, 유지보수가 안 좋음. 디자인 시스템을 개발할 때 처음에는 바뀔일이 없던 컴포넌트도 나중에는 바뀌기 시작하고, 그래서 컴포넌트를 미리 넣어놓기 보다는 위치 정도만 잡아두고, 사용할 때 그 위치에 컴포넌트를 넣는 식으로 구현&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;도전해-볼-것&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8F%84%EC%A0%84%ED%95%B4-%EB%B3%BC-%EA%B2%83&quot; aria-label=&quot;도전해 볼 것 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;도전해 볼 것&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;일상적으로 사용하는 설계 원칙
&lt;ul&gt;
&lt;li&gt;DRY…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ETC를 따르는 코드를 작성할 때 큰 도움을 주거나 걸림돌이 되는 부분?&lt;/li&gt;
&lt;li&gt;에디터에 “ETC?” 기능을 설정해 볼 것
&lt;ul&gt;
&lt;li&gt;webstorm file watcher → 되나?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FileWatcher는 컴파일러 같은건 할 수 있는데 메시지 띄우는건 못할 듯.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic9-dry-중복의-해악&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic9-dry-%EC%A4%91%EB%B3%B5%EC%9D%98-%ED%95%B4%EC%95%85&quot; aria-label=&quot;topic9 dry 중복의 해악 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic9 DRY: 중복의 해악&lt;/h2&gt;
&lt;p&gt;모든 지식은 시스템 내에서 단 한 번만, 애매하지 않고, 권위 있게 표현되어야 한다.&lt;/p&gt;
&lt;p&gt;주석을 달기 전에 먼저 코드에 의도를 드러낼 것.&lt;/p&gt;
&lt;p&gt;모듈이 자료 구조를 노출하면 언제나 모듈의 구현과 그 자료 구조를 사용하는 코드 사이에 결합이 생긴다. 가능하다면 언제나 객체의 속성을 읽고 쓸 때 접근자 함수를 사용할 것.&lt;/p&gt;
&lt;p&gt;개발자 간의 중복 → &lt;code class=&quot;language-text&quot;&gt;적극적이고 빈번한 소통&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;개발자 간의 중복은 엄청 공감됨. 이번에 만든 기능이 다른 분이 먼저 개발했었던 경우가 많음. 이런걸 찾기가 굉장히 힘듦. 그래서 요즘에는 다른 분들에게 먼저 물어보고 시작함.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;topic10-직교성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic10-%EC%A7%81%EA%B5%90%EC%84%B1&quot; aria-label=&quot;topic10 직교성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic10 직교성&lt;/h3&gt;
&lt;p&gt;하나가 바뀌어도 나머지에 어떤 영향도 주지 않으면 서로 직교한다.&lt;/p&gt;
&lt;p&gt;우리가 설계하고 싶은 것은 자족적인(단일하고 잘 정의된 목적을 가진) 독립적인 컴포넌트&lt;/p&gt;
&lt;p&gt;직교적인 컴포넌트들을 결합함으로써 단위 노력당 더 많은 기능을 얻을 수 있다.(M x N)&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;‘특정 기능에 대한 요구 사항을 대폭 변경하는 경우 몇 개의 모듈이 영향을 받는가?’ → 한개여야 한다.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;불필요한 것은 다른 모듈에 보여 주지 않으며, 다른 모듈의 구현에 의존하지 않는 코드를 작성할 것.(shy)&lt;/p&gt;
&lt;p&gt;직교적으로 설계하고 구현한 시스템 → 테스트하기 더 쉽다&lt;/p&gt;
&lt;p&gt;모듈 수준의 테스트나 단위 테스트가 통합 테스트보다 테스트 케이스를 만들고 수행하기 훨씬 쉽다.&lt;/p&gt;
&lt;p&gt;단위 테스트를 작성하는 행위는 직교성을 테스트해 볼 수 있는 기회&lt;/p&gt;
&lt;h3 id=&quot;도전해-볼-것-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8F%84%EC%A0%84%ED%95%B4-%EB%B3%BC-%EA%B2%83-1&quot; aria-label=&quot;도전해 볼 것 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;도전해 볼 것&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;GUI가 있는 경우 여러 기능을 묶어서 사용하거나 할 때에는 수동으로 해야 함. 셸 프롬프트에서는 그걸 묶은 새로운 명령어를 만들어서 사용 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;연습-문제-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C-1&quot; aria-label=&quot;연습 문제 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;연습 문제 1&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Split2가 직교적이라고 생각. Split1에는 다음 줄로 이동하는 역할이 포함. 하지만 바로 다음 줄이 아니라 한 줄씩 건너뛰는 등 요구사항이 변경되면 readNextLine을 변경해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;topic11-가역성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic11-%EA%B0%80%EC%97%AD%EC%84%B1&quot; aria-label=&quot;topic11 가역성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic11 가역성&lt;/h2&gt;
&lt;p&gt;되돌릴 수 없는 결정을 최대한 줄인다. → 우리의 선택은 최선이 아닐 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;새로운 프로젝트의 백엔드 서버(파일 업로드가 있는)를 람다로 올렸다가 request size 제한이 있다는 걸 알아서 옮겼던 기억이…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;컴포넌트 설계할 때도 어렵다. 어느 정도의 미래까지 대비해야 할지&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic12-예광탄&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic12-%EC%98%88%EA%B4%91%ED%83%84&quot; aria-label=&quot;topic12 예광탄 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic12 예광탄&lt;/h2&gt;
&lt;p&gt;요구 사항으로부터 최종 시스템의 일부 측면까지 빨리, 눈에 보이게, 반복적으로 도달하게 해 줄 무언가가 있어야 한다.&lt;/p&gt;
&lt;p&gt;요구 사항에서 &lt;code class=&quot;language-text&quot;&gt;의문이 드는 부분&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;가장 위험이 커 보이는 곳&lt;/code&gt;의 코드를 가장 먼저 작성&lt;/p&gt;
&lt;p&gt;시스템을 구성하는 요소를 모두 연결해 놓은 후라면 목표물에 얼마나 근접했는지 확인할 수 있고, 조정이 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;목표물에 맞을 때까지 조준을 옮겨야 한다.&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예광탄 코드
&lt;ul&gt;
&lt;li&gt;기능은 별로 없지만 완결된 코드&lt;/li&gt;
&lt;li&gt;최종 시스템 골격 중 일부가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로토타입
&lt;ul&gt;
&lt;li&gt;예광탄을 발사하기 전에 수행하는 정찰 단계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;한 사이클을 한 기능에서 쭉 돌아보는 방식. 배포 환경에서 발견되는 문제점을 미리 발견할 수 있음. 가장 큰 위험 요소를 빨리 파악할수록 고치는데 필요한 비용은 줄어든다고 생각.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic13-프로토타입과-포스트잇&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic13-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EA%B3%BC-%ED%8F%AC%EC%8A%A4%ED%8A%B8%EC%9E%87&quot; aria-label=&quot;topic13 프로토타입과 포스트잇 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic13 프로토타입과 포스트잇&lt;/h2&gt;
&lt;p&gt;프로토타입은 위험 요소를 분석하고 노출 시킨 후, &lt;code class=&quot;language-text&quot;&gt;매우 저렴한 비용&lt;/code&gt;으로 바로잡을 기회를 얻는 것&lt;/p&gt;
&lt;p&gt;당장 중요하지 않은 세부 사항이라면 일단 무시하면서 코딩할 수 있다.&lt;/p&gt;
&lt;p&gt;프로토타이핑의 대상은 &lt;code class=&quot;language-text&quot;&gt;위험을 수반하는 모든 것&lt;/code&gt; → &lt;code class=&quot;language-text&quot;&gt;이를 통해 배우는 교훈&lt;/code&gt;이 가치가 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;아키텍처&lt;/li&gt;
&lt;li&gt;추가 기능&lt;/li&gt;
&lt;li&gt;외부 데이터 구조 혹은 내용&lt;/li&gt;
&lt;li&gt;외부 도구나 컴포넌트&lt;/li&gt;
&lt;li&gt;성능&lt;/li&gt;
&lt;li&gt;사용자 인터페이스&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;무시해도-좋을-것들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B4%EC%8B%9C%ED%95%B4%EB%8F%84-%EC%A2%8B%EC%9D%84-%EA%B2%83%EB%93%A4&quot; aria-label=&quot;무시해도 좋을 것들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;무시해도 좋을 것들&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;정확성
&lt;ul&gt;
&lt;li&gt;더미 데이터 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;완전성
&lt;ul&gt;
&lt;li&gt;입력 데이터 하나와 한 가지 메뉴 항목만 작동해도 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;안정성
&lt;ul&gt;
&lt;li&gt;오류 검사는 빼먹거나 무시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스타일
&lt;ul&gt;
&lt;li&gt;주석이나 문서가 많지 않아야 한다.&lt;/li&gt;
&lt;li&gt;프로토타입 결과를 문서로 많이 작성할 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;규명할-만한-사항&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B7%9C%EB%AA%85%ED%95%A0-%EB%A7%8C%ED%95%9C-%EC%82%AC%ED%95%AD&quot; aria-label=&quot;규명할 만한 사항 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;규명할 만한 사항&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;주요 영역의 책임이 잘 정의되었고 적절한지&lt;/li&gt;
&lt;li&gt;주요 컴포넌트 간의 협력 관계가 잘 정의됐는지&lt;/li&gt;
&lt;li&gt;결합도는 최소화했는지&lt;/li&gt;
&lt;li&gt;중복이 발생할 만한 곳이 있는지&lt;/li&gt;
&lt;li&gt;정의된 인터페이스와 제약 사항을 수용할만 한지&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;각 모듈이 실행 중에 필요한 데이터에 접근할 수 있는 경로를 갖고 있는지&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;모듈에 데이터가 필요한 시점에 데이터 접근이 가능한지&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;프론트 단에는 데이터 별로 필요한 시점이 있는데 개발하다 보면 필요한데 아직 못 불러오거나 하는 경우가 있음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;이번에 게시판에 대댓글을 추가하는데 (댓글까지 있었음) 저와 백엔드 개발자님은 현재 디비로 충분히 대댓글까지 커버할 수 있을거라고 생각했었는데, 만들고보니 현재 구조에서는 따로 분리하는 편이 더 나을 거 같다는 판단을 함.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;이것도 UI를 만들어놓고 api 연동을 했었는데, UI는 텍스트만 나와도 되니까 api 연동을 맨 먼저 해보는 것이 어땠을까 하는 생각이 듦.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;프로토타입을 코드로 만들 때는 시작하기 전에 항상 모든 사람에게 폐기 처분할 코드임을 밝혀야 한다.&lt;/p&gt;
&lt;h3 id=&quot;연습-문제-3&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C-3&quot; aria-label=&quot;연습 문제 3 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;연습 문제 3&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;디자인 팀에게 피그마로 만들어줄 것을 요청&lt;/li&gt;
&lt;li&gt;react, vue&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;topic17-셸-가지고-놀기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic17-%EC%85%B8-%EA%B0%80%EC%A7%80%EA%B3%A0-%EB%86%80%EA%B8%B0&quot; aria-label=&quot;topic17 셸 가지고 놀기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic17. 셸 가지고 놀기&lt;/h2&gt;
&lt;p&gt;GUI 환경의 기능은 설계자가 의도한 범위를 넘어설 수 없다.&lt;/p&gt;
&lt;p&gt;도커로 서버를 켜는 명령어는 만들어놓고 유용하게 쓰고 있다. 하지만 그 이상의 활용은 못 해봄.&lt;/p&gt;
&lt;h3 id=&quot;도전해보기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8F%84%EC%A0%84%ED%95%B4%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;도전해보기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;도전해보기&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;가르쳐 줘 본 적 없음. 알아서 잘함. 자동화 할만한건 아직 없음&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;셸을 사용할 일이 많이 없어서 와닿지는 않지만 저자의 의도는 알겠음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic18-파워-에디팅&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic18-%ED%8C%8C%EC%9B%8C-%EC%97%90%EB%94%94%ED%8C%85&quot; aria-label=&quot;topic18 파워 에디팅 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic18. 파워 에디팅&lt;/h2&gt;
&lt;p&gt;유창해지는 것의 가장 큰 이점은 사용법을 생각하지 않아도 된다는 것. 속도가 빨라지면 이점이 있음&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;텍스트 편집 시 문자, 단어, 줄, 문단 단위로 커서를 이동하거나 내용 선택&lt;/li&gt;
&lt;li&gt;반대쪽 괄호로 이동 → control + M&lt;/li&gt;
&lt;li&gt;control + option + [] ⇒ navigate between code blocks&lt;/li&gt;
&lt;li&gt;option + command + L ⇒ reformat code&lt;/li&gt;
&lt;li&gt;command + shift + / ⇒ 여러줄 주석&lt;/li&gt;
&lt;li&gt;shift + command + z ⇒ redo&lt;/li&gt;
&lt;li&gt;shift + command + [] ⇒ move between tabs&lt;/li&gt;
&lt;li&gt;command + L ⇒ go to line number&lt;/li&gt;
&lt;li&gt;search “sort lines” on command panel&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;트랙패드없이 작업을 해봐야겠다. 분명히 생산성 향상에 큰 도움이 될 거 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic19-버전-관리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic19-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC&quot; aria-label=&quot;topic19 버전 관리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic19. 버전 관리&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;롤백하기 → revert commit&lt;/li&gt;
&lt;li&gt;신입이 들어왔을 때 초기 세팅을 하나의 셸 스크립트로 퉁칠 수 있을까? 있다면 편하긴 하겠다.&lt;/li&gt;
&lt;li&gt;다른데는 깃허브에서 어떤 기능까지 쓰는지 궁금. discussion도 쓰나? 이슈는?&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;topic20-디버깅&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic20-%EB%94%94%EB%B2%84%EA%B9%85&quot; aria-label=&quot;topic20 디버깅 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic20. 디버깅&lt;/h2&gt;
&lt;ol&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;“select”는 망가지지 않았다. 컴퓨터는 거짓말하지 않는다. 시스템 탓을 하지 말 것&lt;/li&gt;
&lt;li&gt;가정하지 말고 증명하라.&lt;/li&gt;
&lt;li&gt;버그를 미리 잡을 순 없는지 계속 고민해볼 것&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;프론트는 사용자의 환경이 매우 다양하다. 값을 참조하는 것도 그 구문을 실제로 호출하는 시점에 따라 에러가 날 수 있음.&lt;/p&gt;
&lt;h2 id=&quot;topic21-텍스트-처리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic21-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC&quot; aria-label=&quot;topic21 텍스트 처리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic21. 텍스트 처리&lt;/h2&gt;
&lt;p&gt;기본적인 도구만으로는 해내기 힘든 종류의 변환 작업이 있을 수 있고, 이를 위해 텍스트 처리 도구가 필요하다. ex) json -&gt; yaml 변환기&lt;/p&gt;
&lt;h2 id=&quot;topic22-엔지니어링-일지&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic22-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81-%EC%9D%BC%EC%A7%80&quot; aria-label=&quot;topic22 엔지니어링 일지 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic22. 엔지니어링 일지&lt;/h2&gt;
&lt;p&gt;파일이나 위키말고 종이를 사용해볼 것&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;기억보다 믿을 만하다.&lt;/li&gt;
&lt;li&gt;진행 중인 작업과 관련없는 발상을 일단 쌓아놓을 수 있다.&lt;/li&gt;
&lt;li&gt;고무 오리와 같은 역할&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;개발자는 노트북에 적는게 편하겠지만 항상 들고 다닐 수 있는가? 라고 물어본다면 No인 거 같다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[실용주의 프로그래머 리뷰 (1장)]]></title><description><![CDATA[동료들과 실용주의 프로그래머라는 책을 같이 읽고 있습니다. 공부하면서 정리한 내용을 블로그에도 남겨볼까 합니다. 아직 못 읽은 부분은 계속 업데이트하려고 합니다. 1장. 실용주의 철학 Topic…]]></description><link>https://donghoon-song.github.io/books/실용주의-프로그래머-리뷰-(1장)/</link><guid isPermaLink="false">https://donghoon-song.github.io/books/실용주의-프로그래머-리뷰-(1장)/</guid><pubDate>Sat, 12 Nov 2022 10:11:04 GMT</pubDate><content:encoded>&lt;p&gt;동료들과 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001033128&quot;&gt;실용주의 프로그래머&lt;/a&gt;라는 책을 같이 읽고 있습니다. 공부하면서 정리한 내용을 블로그에도 남겨볼까 합니다. 아직 못 읽은 부분은 계속 업데이트하려고 합니다.&lt;/p&gt;
&lt;h1 id=&quot;1장-실용주의-철학&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EC%9E%A5-%EC%8B%A4%EC%9A%A9%EC%A3%BC%EC%9D%98-%EC%B2%A0%ED%95%99&quot; aria-label=&quot;1장 실용주의 철학 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1장. 실용주의 철학&lt;/h1&gt;
&lt;h2 id=&quot;topic1-당신의-인생이다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic1-%EB%8B%B9%EC%8B%A0%EC%9D%98-%EC%9D%B8%EC%83%9D%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;topic1 당신의 인생이다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic1 당신의 인생이다&lt;/h2&gt;
&lt;p&gt;우리에게는 스스로의 행동을 직접 결정할 수 있는 힘이 있다. 이 업계는 우리에게 다양한 기회를 주고, 주도권은 우리에게 있으니 행동하라.&lt;/p&gt;
&lt;h2 id=&quot;topic2-고양이가-내-소스-코드를-삼켰어요&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic2-%EA%B3%A0%EC%96%91%EC%9D%B4%EA%B0%80-%EB%82%B4-%EC%86%8C%EC%8A%A4-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%82%BC%EC%BC%B0%EC%96%B4%EC%9A%94&quot; aria-label=&quot;topic2 고양이가 내 소스 코드를 삼켰어요 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic2 고양이가 내 소스 코드를 삼켰어요&lt;/h2&gt;
&lt;p&gt;개인적으로 최선을 다하는 것이 전부가 아니다. 불가능하거나 위험 요소가 크면 책임을 맡지 않을 권리가 있고 실수를 저지르거나 잘못된 판단을 내렸다면 잘못을 인정하고 대안을 제시해야 한다. 책임을 맡은 업무에서 외부 요인이 문제가 있더라도 그것까지 커버해야 한다.&lt;/p&gt;
&lt;p&gt;“잘 모르겠어요. 하지만 알아볼게요” → 모른다는 것을 인정하고 전문가답게 책임을 지는 방법&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;현재 회사를 다니면서 스스로 결정을 많이 합니다. 그 결정이 합리적이라면 전적으로 믿어주는 팀원들이 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic3-소프트웨어-엔트로피&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic3-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%97%94%ED%8A%B8%EB%A1%9C%ED%94%BC&quot; aria-label=&quot;topic3 소프트웨어 엔트로피 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic3 소프트웨어 엔트로피&lt;/h2&gt;
&lt;p&gt;나쁜 설계, 잘못된 결정, 형편없는 코드 등은 모두 깨진 창문이며 발견하자마자 고칠 것. 엔트로피가 우리를 지배하도록 내버려두지 말 것&lt;/p&gt;
&lt;p&gt;그러기 위해서는 먼저 망가트리지 말아야 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;프로젝트에 깨진 창문은 얼마나 많은지? 어떻게 고칠 것인지?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic4-돌멩이-수프와-삶은-개구리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic4-%EB%8F%8C%EB%A9%A9%EC%9D%B4-%EC%88%98%ED%94%84%EC%99%80-%EC%82%B6%EC%9D%80-%EA%B0%9C%EA%B5%AC%EB%A6%AC&quot; aria-label=&quot;topic4 돌멩이 수프와 삶은 개구리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic4 돌멩이 수프와 삶은 개구리&lt;/h2&gt;
&lt;p&gt;변화의 촉매가 될 것. 사람들은 각자 자신의 자원을 지키려고 한다. (시작 피로) 계속되는 성공에는 합류하기 쉽다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;비슷한 경험을 했습니다. 같이 일하는 디자이너분들과 사이드 프로젝트를 하는데, 첫 미팅 후에 다음 미팅 때 간단하게라도 데모 버전을 보여드렸던 적이 있습니다. 굉장히 반응은 뜨거웠고 크게 동기부여가 되서, 아이디어도 많이 나왔고 디자이너 분들의 의욕이 넘쳐나는 것이 보였습니다. 다음 미팅때도 기능을 조금 더 추가한 데모 버전을 보여드렸고 그 결과 업무에 지쳐있던 분들의 컨디션을 끌어올릴 수 있었고 계속해서 동기를 부여할 수 있었습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;큰 그림을 기억하라. 당장 하고 있는 일에만 정신을 쏟지 말고, 주변에서 무슨 일이 벌어지는지 살펴봐야 한다.&lt;/p&gt;
&lt;h2 id=&quot;topic5-적당히-괜찮은-소프트웨어&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic5-%EC%A0%81%EB%8B%B9%ED%9E%88-%EA%B4%9C%EC%B0%AE%EC%9D%80-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4&quot; aria-label=&quot;topic5 적당히 괜찮은 소프트웨어 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic5 적당히 괜찮은 소프트웨어&lt;/h2&gt;
&lt;p&gt;완벽한 소프트웨어를 만들 순 없지만 적당히 괜찮은 소프트웨어를 만들 순 있다.&lt;/p&gt;
&lt;p&gt;우리가 생산해 낸 것이 적당히 괜찮게 사용자의 요구를 충족하는지 결정하는 과정에 &lt;code class=&quot;language-text&quot;&gt;사용자가 참여할 기회&lt;/code&gt;를 가져야 한다.&lt;/p&gt;
&lt;p&gt;완벽하게 훌륭한 프로그램을 과도하게 장식하거나 지나칠 정도로 다듬느라 망치지 말 것.&lt;/p&gt;
&lt;h2 id=&quot;topic6-지식-포트폴리오&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic6-%EC%A7%80%EC%8B%9D-%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4&quot; aria-label=&quot;topic6 지식 포트폴리오 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic6 지식 포트폴리오&lt;/h2&gt;
&lt;p&gt;지식에 대한 투자가 언제나 최고의 이윤을 낸다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;매우 인상깊은 말&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;우리 지식은 &lt;code class=&quot;language-text&quot;&gt;기한이 있는 지식&lt;/code&gt;이다. &lt;code class=&quot;language-text&quot;&gt;새로운 것을 배우는 능력&lt;/code&gt;이 가장 중요한 능력 자산&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;알고 있지만 참 어려운… react, vue도 나중에 보면 한물 간 기술이겠지&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&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;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;많이 하지 않더라도 조금씩 공부하자. -&gt; 새로운 것을 접하는 것만으로도 리프레쉬되고 나를 객관적으로 돌아보는데 도움이 많이 됨.
중심을 잡을 기술(react 등)과 새롭지만 높은 보상이 있는 기술을 섞어볼 것.(deno, next13 등)
포트폴리오에 비유를 하니까 되게 재밌고 유사한 점이 많은 거 같음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;목표&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AA%A9%ED%91%9C&quot; aria-label=&quot;목표 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;목표&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;매년 새로운 언어를 최소 하나는 배우기
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;언어는 동일한 문제를 다르게 푼다&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;사고방식의 확장에 도움을 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;기술 서적을 한 달에 한 권씩 읽기
&lt;ul&gt;
&lt;li&gt;제일 실천하고 싶은 것&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;깊이 있는 지식 → 긴 글 형식의 책&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모임에 참여할 것
&lt;ul&gt;
&lt;li&gt;고립은 경력에 치명적일 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다른 환경에서 실험
&lt;ul&gt;
&lt;li&gt;새로운 환경은 자극을 준다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;책은 읽기 시작했는데 기술 서적을 읽을 생각은 못했음. 주기적으로 읽어야겠다 라는 생각이 듦.
모임에 참여하자. 겨울엔 사진을 좀 줄이고 모임을!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;비판적-사고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B9%84%ED%8C%90%EC%A0%81-%EC%82%AC%EA%B3%A0&quot; aria-label=&quot;비판적 사고 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;비판적 사고&lt;/h3&gt;
&lt;ol&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;li&gt;조직원?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;어떤 맥락인가?
&lt;ul&gt;
&lt;li&gt;전제 조건이 뭔지&lt;/li&gt;
&lt;li&gt;그 결과의 장,단기적 여파는 무엇인지?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;언제 혹은 어디서 효과가 있을까?
&lt;ul&gt;
&lt;li&gt;다음에 어떤 일이 일어날까 → 그 다음엔 어떤 일이 일어날까? 멀리 생각해볼 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;왜 이것이 문제인가?&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;일을 할 때, 왜 하는지, 공수대비 얼마나 임팩트, 컨피던스가 있는지를 항상 생각하는데 더 다각화해서 생각해볼만 하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;topic7-소통하라&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#topic7-%EC%86%8C%ED%86%B5%ED%95%98%EB%9D%BC&quot; aria-label=&quot;topic7 소통하라 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Topic7 소통하라!&lt;/h2&gt;
&lt;p&gt;청중을 알고 내용을 그에 맞게 각색해서 전달.&lt;/p&gt;
&lt;p&gt;멋지게 보이게 할 것. (개발자라는 핑계로 디자인을 소홀히 하지말자.)&lt;/p&gt;
&lt;p&gt;타이밍도 중요(청중이 내 전달 내용을 필요로 하는 타이밍을 찾아보자)&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;청중을 참여시켜라&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;결국 듣는 사람이 듣고 싶은 얘기를 해야 한다.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;문서화 → 코드의 용도와 목적을 논해야 한다. 동작 방식은 코드가 보여주므로 불필요.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;청중 참여, 타이밍 등 청중을 계속 생각하는 걸 연습해야겠음.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[Jest로 next component test하기]]></title><description><![CDATA[Next.js 환경의 실무 프로젝트에서 Report라는 페이지 컴포넌트를 처음 테스트하면서 겪었던 이슈들을 정리했습니다. 먼저 테스트 코드의 많은 예제에서 다루는 것처럼 테스트의 기본은  확인하는 것이라 생각하여 render…]]></description><link>https://donghoon-song.github.io/test/jest로-next-component-test하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/test/jest로-next-component-test하기/</guid><pubDate>Wed, 02 Nov 2022 22:11:06 GMT</pubDate><content:encoded>&lt;h3 id=&quot;nextjs-환경의-실무-프로젝트에서-report라는-페이지-컴포넌트를-처음-테스트하면서-겪었던-이슈들을-정리했습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nextjs-%ED%99%98%EA%B2%BD%EC%9D%98-%EC%8B%A4%EB%AC%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90%EC%84%9C-report%EB%9D%BC%EB%8A%94-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%A5%BC-%EC%B2%98%EC%9D%8C-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%98%EB%A9%B4%EC%84%9C-%EA%B2%AA%EC%97%88%EB%8D%98-%EC%9D%B4%EC%8A%88%EB%93%A4%EC%9D%84-%EC%A0%95%EB%A6%AC%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;nextjs 환경의 실무 프로젝트에서 report라는 페이지 컴포넌트를 처음 테스트하면서 겪었던 이슈들을 정리했습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Next.js 환경의 실무 프로젝트에서 Report라는 페이지 컴포넌트를 처음 테스트하면서 겪었던 이슈들을 정리했습니다.&lt;/h3&gt;
&lt;p&gt;먼저 테스트 코드의 많은 예제에서 다루는 것처럼 테스트의 기본은 &lt;code class=&quot;language-text&quot;&gt;컴포넌트가 제대로 render되는지&lt;/code&gt; 확인하는 것이라 생각하여 render시키고 난 후에 다음 것들을 생각해보고자 하였습니다. 분명히 마음처럼 쉽게 되지 않을 거라는 것을 알았기 때문입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Report &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../components/TabContent/Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@testing-library/react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should render&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Report&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;바로 첫번째 이슈를 겪었습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Jest useNavigate() may be used only in the context of a Router component&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/199504248-26f9ee11-51bf-4769-a18d-65c42bb7e4d3.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;컴포넌트 내부에서 useNavigate()를 사용하고 있었는데 Router component로 감싸지 않아서 에러가 났습니다. Router component로 감싸서 해결했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Report &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../components/TabContent/Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@testing-library/react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; BrowserRouter &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Router &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should render&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
				&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Report&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
			&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제는 react-redux 관련 에러가 났습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;could not find react-redux context value; please ensure the component is wrapped in a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;Provider&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/199507538-c5626084-0149-4a54-ade4-7455c5a394fc.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://redux.js.org/usage/writing-tests#components&quot;&gt;Writing Tests | Redux&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;관련 이슈를 검색해보니 redux를 test에서 사용할 때 가이드라인이 있어 해당 코드를 추가했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/utils/test-utils.tsx&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PropsWithChildren &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@testing-library/react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; RenderOptions &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@testing-library/react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; configureStore &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@reduxjs/toolkit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PreloadedState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@reduxjs/toolkit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Provider &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-redux&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppStore&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RootState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/store&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reducers &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/store&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExtendedRenderOptions&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Omit&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;RenderOptions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;queries&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	preloadedState&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PreloadedState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;RootState&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	store&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AppStore&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderWithProviders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	ui&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactElement&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		preloadedState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		store &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configureStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reducer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; reducers&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; preloadedState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;renderOptions
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ExtendedRenderOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Wrapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropsWithChildren&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Element &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Provider&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;store&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Provider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ui&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; wrapper&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Wrapper&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;renderOptions &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Report &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../components/TabContent/Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; BrowserRouter &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Router &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; renderWithProviders &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/utils/test-utils&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should render&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;renderWithProviders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
				&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Report&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
			&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다시 돌려보니까 새로운 에러를 발견했습니다. 검색해보니 아래와 같은 솔루션을 발견할 수 있었습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;window.matchMedia is not a function&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/199510198-e94fa6f5-59f3-456a-8110-e55036b59fd3.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/39830580/jest-test-fails-typeerror-window-matchmedia-is-not-a-function&quot;&gt;Jest test fails : TypeError: window.matchMedia is not a function&lt;/a&gt;
&lt;a href=&quot;https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom&quot;&gt;Manual Mocks · Jest&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Report &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../components/TabContent/Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; BrowserRouter &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Router &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; renderWithProviders &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/utils/test-utils&apos;&lt;/span&gt;

Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;matchMedia&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	writable&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mockImplementation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		matches&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		media&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		onchange&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		addListener&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Deprecated&lt;/span&gt;
		removeListener&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Deprecated&lt;/span&gt;
		addEventListener&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		removeEventListener&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		dispatchEvent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should render&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;renderWithProviders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
				&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Report&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
			&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/199513145-42ef17da-c200-49b0-82b8-3f5a5abb910d.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;다시 돌려봤는데 다른 에러가 발생했습니다. 하지만 비슷한 원인의 에러인거 같아서 더 찾아봤고, window가 아닌 global 객체의 matchMedia를 mocking해야 하는 상황이었습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Report &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../components/TabContent/Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; BrowserRouter &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Router &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; renderWithProviders &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/utils/test-utils&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchMedia &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
	global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchMedia &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			addListener&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			removeListener&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Report&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should render&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;renderWithProviders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
				&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Report&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
			&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;드디어 정상적으로 작동했습니다 🙂&lt;/p&gt;
&lt;p&gt;global.matchMedia를 mocking하는 부분은 공통적으로 실행될 수 있는 영역에다가 넣어야겠다는 생각이 들었습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[20220829 TIL]]></title><description><![CDATA[yarn berry는 어떤 문제를 해결해주는가? 비효율적인 의존성 검색 기존 : node_modules 선회 yarn berry : .pnp.cjs 사용 재현 가능성 기존 : npm은 패키지를 찾지 못하면 상위 디렉토리의 node_modules…]]></description><link>https://donghoon-song.github.io/TIL/20220829-til/</link><guid isPermaLink="false">https://donghoon-song.github.io/TIL/20220829-til/</guid><pubDate>Mon, 29 Aug 2022 22:09:10 GMT</pubDate><content:encoded>&lt;h2 id=&quot;yarn-berry는-어떤-문제를-해결해주는가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#yarn-berry%EB%8A%94-%EC%96%B4%EB%96%A4-%EB%AC%B8%EC%A0%9C%EB%A5%BC-%ED%95%B4%EA%B2%B0%ED%95%B4%EC%A3%BC%EB%8A%94%EA%B0%80&quot; aria-label=&quot;yarn berry는 어떤 문제를 해결해주는가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;yarn berry는 어떤 문제를 해결해주는가?&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;비효율적인 의존성 검색
&lt;ul&gt;
&lt;li&gt;기존 : node_modules 선회&lt;/li&gt;
&lt;li&gt;yarn berry : .pnp.cjs 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;재현 가능성
&lt;ul&gt;
&lt;li&gt;기존 : npm은 패키지를 찾지 못하면 상위 디렉토리의 node_modules를 찾으므로, 상위 디렉토리 환경에 따라 달라짐.&lt;/li&gt;
&lt;li&gt;yarn berry : 의존성이 외부 환경에 영향을 받지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;의존성 설치
&lt;ul&gt;
&lt;li&gt;node_modules 필요없음. 같은 버전의 패키지 여러 번 설치되는거 방지&lt;/li&gt;
&lt;li&gt;Zero-install을 사용하면 라이브러리를 설치 없이 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;의존성 관리
&lt;ul&gt;
&lt;li&gt;의존성을 끌어올리지 않으므로 유령 의존성 현상 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;msw로-server-api-mocking-성공&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#msw%EB%A1%9C-server-api-mocking-%EC%84%B1%EA%B3%B5&quot; aria-label=&quot;msw로 server api mocking 성공 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;msw로 server api mocking 성공&lt;/h2&gt;
&lt;p&gt;현재 cypress로 e2e test를 해보려고 함. api mocking에 &lt;a href=&quot;https://docs.cypress.io/api/commands/intercept&quot;&gt;cy.intercept()&lt;/a&gt;를 사용하거나 &lt;a href=&quot;https://mswjs.io/&quot;&gt;msw&lt;/a&gt;를 사용할 수 있지만 문제는 nuxt의 server side에서 부르는 api를 intercept하지 못함.
이에 대해 검색해보면&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@developer_key/Cypress-SSR-API-intercept-%EC%B2%98%EB%A6%AC%EB%B2%95&quot;&gt;next.js 서버를 하나 더 만든다.&lt;/a&gt; -&gt; 실패
&lt;ul&gt;
&lt;li&gt;동시에 돌리니까 nuxt page가 렌더링되지 않음. (정확한 이유는 잘 모르겠음.)&lt;/li&gt;
&lt;li&gt;api mocking하자고 next.js, react 등을 설치해야 하는 문제.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/cypress-io/cypress-mock-ssr&quot;&gt;cypress-mock-ssr&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;아직 사용해보지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.mathpresso.com/msw%EB%A1%9C-api-%EB%AA%A8%ED%82%B9%ED%95%98%EA%B8%B0-2d8a803c3d5c&quot;&gt;msw&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;브라우저 환경에서만 동작하는 줄 알았는데 확장하여 node 환경에서 동작하는 모듈도 있음.&lt;/li&gt;
&lt;li&gt;이 방법으로 성공했고, 글 작성 예정.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;참고&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://toss.tech/article/node-modules-and-yarn-berry&quot;&gt;https://toss.tech/article/node-modules-and-yarn-berry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[github action으로 gatsby 블로그 github.io에 배포하기]]></title><description><![CDATA[blog template을 바꾸면서 main branch에 merge하면 자동으로 배포될 수 있도록 설정하고 싶었습니다. 이를 지원하는 액션이 있을거라고 생각하고 검색해보았더니 아래의 액션을 발견했습니다. Gatsby Publish…]]></description><link>https://donghoon-song.github.io/CI/CD/github-action으로-gatsby-블로그-github.io에-배포하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/CI/CD/github-action으로-gatsby-블로그-github.io에-배포하기/</guid><pubDate>Sun, 14 Aug 2022 21:08:26 GMT</pubDate><content:encoded>&lt;p&gt;blog template을 바꾸면서 main branch에 merge하면 자동으로 배포될 수 있도록 설정하고 싶었습니다. 이를 지원하는 액션이 있을거라고 생각하고 검색해보았더니 아래의 액션을 발견했습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/marketplace/actions/gatsby-publish&quot;&gt;Gatsby Publish&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;기존 배포 명령어는 다음과 같았습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;deploy&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gatsby build &amp;amp;&amp;amp; gh-pages -d public -b master -r &apos;git@github.com:donghoon-song/donghoon-song.github.io.git&apos;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;.github &gt; workflows directory에 auto-deploy.yml 파일을 생성했습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Gatsby Publish

// main branch에 push할 때 실행
&lt;span class=&quot;token key atrule&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; main

&lt;span class=&quot;token key atrule&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ubuntu&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;latest
    &lt;span class=&quot;token key atrule&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; actions/checkout@v1
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; enriikke/gatsby&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;gh&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pages&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;action@v2
        &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;access-token&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; secrets.ACCESS_TOKEN &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          // 배포될 repository의 이름을 적습니다.
          // 따로 명시하지 않으면 이 action이 실행되는 repository에 배포됩니다.
          &lt;span class=&quot;token key atrule&quot;&gt;deploy-repo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;donghoon-song.github.io&apos;&lt;/span&gt;
          // 배포될 branch를 적습니다.
          // 따로 명시하지 않으면 &apos;master&apos; branch가 기본값입니다.
          &lt;span class=&quot;token key atrule&quot;&gt;deploy-branch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;main&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ACCESS_TOKEN은 secrets에서 읽어오는데 아래 공식문서를 참고해 발급받으시고 repository -&gt; settings -&gt; secrets에 추가해주시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token&quot;&gt;Creating a token&lt;/a&gt;&lt;/p&gt;
&lt;img alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/184536260-469e201d-2304-434a-bf94-e35b2ba56d35.png&quot;&gt;</content:encoded></item><item><title><![CDATA[lodash collection flatMapDeep 활용]]></title><description><![CDATA[개발을 하다가 여러가지 input값들을 한번에 관리하는 경우가 생겼고, 각 input이 모두 비어있는지를 체크하고 싶었습니다. 활용할만한 라이브러리를 찾아보다가 lodash collection의 flatMapDeep…]]></description><link>https://donghoon-song.github.io/javascript/lodash-collection-flatmapdeep-활용/</link><guid isPermaLink="false">https://donghoon-song.github.io/javascript/lodash-collection-flatmapdeep-활용/</guid><pubDate>Sun, 14 Aug 2022 20:09:36 GMT</pubDate><content:encoded>&lt;p&gt;개발을 하다가 여러가지 input값들을 한번에 관리하는 경우가 생겼고, 각 input이 모두 비어있는지를 체크하고 싶었습니다. 활용할만한 라이브러리를 찾아보다가 lodash collection의 flatMapDeep을 활용하면 쉽게 해결할 수 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://codesandbox.io/s/lodash-playground-forked-pm6lyx?file=/src/index.js&quot;&gt;코드 확인하기&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;콘솔창을 보시면 모든 input value값들을 펼쳐서 배열에 저장할 수 있었고 문제를 해결할 수 있었습니다 :)
&lt;img alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/32301380/./184536409-f5399eeb-0b48-496f-9f33-fbd7b748d10f.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;flatMapDepth의 내부구현은 어떻게 되어 있을지 궁금해서 찾아봤습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; baseFlatten &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./.internal/baseFlatten.js&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; map &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./map.js&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * This method is like `flatMap` except that it recursively flattens the
 * mapped results up to `depth` times.
 *
 * @since 4.7.0
 * @category Collection
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {number} [depth=1] The maximum recursion depth.
 * @returns {Array} Returns the new flattened array.
 * @see flatMap, flatMapDeep, flatten, flattenDeep, flattenDepth, map, mapKeys, mapValues
 * @example
 *
 * function duplicate(n) {
 *   return [[[n, n]]]
 * }
 *
 * flatMapDepth([1, 2], duplicate, 2)
 * // =&gt; [[1, 1], [2, 2]]
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flatMapDepth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;collection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; iteratee&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; depth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  depth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; depth &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;depth
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;baseFlatten&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;collection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; iteratee&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; depth&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; flatMapDepth&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; isFlattenable &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./isFlattenable.js&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * The base implementation of `flatten` with support for restricting flattening.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {number} depth The maximum recursion depth.
 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;baseFlatten&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;array&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; depth&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; predicate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isStrict&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  predicate &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;predicate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isFlattenable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  result &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;depth &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;predicate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;depth &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Recursively flatten arrays (susceptible to call stack limits).&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;baseFlatten&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; depth &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; predicate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isStrict&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isStrict&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      result&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; baseFlatten&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;collection의 요소들을 iteratee에 넣고 돌린 결과들을 가지고 &lt;code class=&quot;language-text&quot;&gt;baseFlatten&lt;/code&gt; 함수에 전달하네요. 그러면 depth만큼 재귀적으로 함수를 반복한 결과를 반환합니다. 생각보다 단순합니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;여기에서 나머지 인자 predicate, isStrict는 사용하지 않는데, 설명만 읽고서는 어떤 역할인지 이해가 잘 안되네요.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[한 권으로 배우는 Vue.js3 서평]]></title><description><![CDATA[구성 크게 보면 Vue.js에 대한 소개 -> Vue3 기초(Vue2와 비교) -> Vue3로 애플리케이션 개발 순입니다. 난이도 제 생각에는 Vue2를 이미 어느정도 알고 계신 분이라면 수월하게 읽을 수 있을 것이라는 생각이 들었습니다. Vue…]]></description><link>https://donghoon-song.github.io/development/2021-09-22---한-권으로-배우는-Vue.js3-서평/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2021-09-22---한-권으로-배우는-Vue.js3-서평/</guid><pubDate>Wed, 22 Sep 2021 18:47:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;구성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%EC%84%B1&quot; aria-label=&quot;구성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;구성&lt;/h2&gt;
&lt;p&gt;크게 보면 Vue.js에 대한 소개 -&gt; Vue3 기초(Vue2와 비교) -&gt; Vue3로 애플리케이션 개발 순입니다.&lt;/p&gt;
&lt;h2 id=&quot;난이도&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%82%9C%EC%9D%B4%EB%8F%84&quot; aria-label=&quot;난이도 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;난이도&lt;/h2&gt;
&lt;p&gt;제 생각에는 Vue2를 이미 어느정도 알고 계신 분이라면 수월하게 읽을 수 있을 것이라는 생각이 들었습니다. Vue2를 아예 모른다면 이해하는데 시간이 좀 걸릴수도 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;추천-독자&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%94%EC%B2%9C-%EB%8F%85%EC%9E%90&quot; aria-label=&quot;추천 독자 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;추천 독자&lt;/h2&gt;
&lt;p&gt;Vue2를 어느정도 알고 있는 사람&lt;/p&gt;
&lt;h2 id=&quot;좋았던-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A2%8B%EC%95%98%EB%8D%98-%EC%A0%90&quot; aria-label=&quot;좋았던 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;좋았던 점&lt;/h2&gt;
&lt;p&gt;Vue3 기초개념 챕터에서 “Vue2에서 이렇게 표현되는 것들이 Vue3에는 이렇게 표현된다.”라는 비교 형식의 서술방식이 주였고, 다음 챕터부터는 Vue3 내용이 주입니다. 내용이 자세하기 때문에 Vue2를 이미 알고 있어도 Vue2에 대한 이해가 깊어지는 느낌이 들었고 Vue3에 대한 내용도 쉽게 이해됐습니다. 그리고 뒤에 Vue3를 이용해 애플리케이션을 만들어보면서 Vue3를 충분히 익힐 수 있었습니다.&lt;br/&gt;아직 Vue3로 완전히 마이그레이션을 할수는 없지만 미래에 마이그레이션을 대비해 읽으면 도움이 될 책이라는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;[출판사로부터 도서를 제공받아 주관적으로 작성한 리뷰입니다]&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Vue.js 화살표 함수(arrow function) 주의점]]></title><description><![CDATA[Vue.js의 data 및 lifcecycle hook(created, mounted…)에서 화살표 함수를 사용하면 어떻게 될까요? image image this가 라고 합니다. 왜 이런 일이 발생할까요? 공식문서에 설명이 나와 있습니다. Vue…]]></description><link>https://donghoon-song.github.io/development/2021-03-31---Vue.js-화살표-함수(arrow-function)-주의점/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2021-03-31---Vue.js-화살표-함수(arrow-function)-주의점/</guid><pubDate>Wed, 31 Mar 2021 22:47:00 GMT</pubDate><content:encoded>&lt;h3 id=&quot;vuejs의-data-및-lifcecycle-hookcreated-mounted에서-화살표-함수를-사용하면-어떻게-될까요&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#vuejs%EC%9D%98-data-%EB%B0%8F-lifcecycle-hookcreated-mounted%EC%97%90%EC%84%9C-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A9%B4-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%90%A0%EA%B9%8C%EC%9A%94&quot; aria-label=&quot;vuejs의 data 및 lifcecycle hookcreated mounted에서 화살표 함수를 사용하면 어떻게 될까요 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Vue.js의 data 및 lifcecycle hook(created, mounted…)에서 화살표 함수를 사용하면 어떻게 될까요?&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113174861-c6e2f380-9285-11eb-84f7-a6eb709dc537.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113163015-bb3dff80-927a-11eb-89b0-0d3f966beaa4.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;this가 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;라고 합니다. 왜 이런 일이 발생할까요?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks&quot;&gt;공식문서&lt;/a&gt;에 설명이 나와 있습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vue instance는 몇가지의 초기화 과정을 거칩니다. created, mounted 등의 생명주기 훅들은 this context가 Vue instance를 가리키도록 설정되고 나서 실행됩니다. 화살표 함수를 option property나 callback (created, watch … ) 에서 실행하지 말아야 합니다. 화살표 함수는 this를 가지고 있지 않기 때문에 this는 다른 변수들처럼 부모 스코프까지 렉시컬하게 조회되어 &lt;code class=&quot;language-text&quot;&gt;Uncaught TypeError: Cannot read property of undefined&lt;/code&gt; 나 &lt;code class=&quot;language-text&quot;&gt;Uncaught TypeError: this.myMethod is not a function&lt;/code&gt; 같은 에러를 발생시킬 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;저는 여기서 Vue가 &lt;code class=&quot;language-text&quot;&gt;this context&lt;/code&gt;를 어떻게 &lt;code class=&quot;language-text&quot;&gt;Vue instance&lt;/code&gt;에 바인딩하는지 궁금해졌습니다. Vue core 코드를 뜯어보았습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113174801-b6327d80-9285-11eb-8f2e-42e6c038061d.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;initMixin을 따라가봅니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113174807-b894d780-9285-11eb-97bc-75642cf9a002.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;initState가 data를 초기화하는 부분같습니다. initState를 따라갑니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113174818-bc285e80-9285-11eb-93dc-942c57603ed5.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;data가 있으면 initData를 호출합니다. 따라들어갑니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/114290899-ecf66800-9abd-11eb-904a-0e4acf891207.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;data가 함수타입이면 getData를 실행합니다. 따라들어갑니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113174829-bf234f00-9285-11eb-9a86-be48a52a0287.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;드디어 찾고있던 마지막 종착지입니다. &lt;code class=&quot;language-text&quot;&gt;data.call(vm,vm)&lt;/code&gt;을 return합니다.&lt;/p&gt;
&lt;p&gt;lifecycle hook의 경우에는 어떨까요?
init.js에서 &lt;code class=&quot;language-text&quot;&gt;callHook(vm, &apos;created&apos;)&lt;/code&gt;를 따라갑니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/114291077-70fd1f80-9abf-11eb-880b-fd4283478cb0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;invokeWithErrorHandling에 vm을 넘겨주고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/114291104-a275eb00-9abf-11eb-98ff-25af11ebcb55.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;똑같이 &lt;code class=&quot;language-text&quot;&gt;handler&lt;/code&gt;에게 &lt;code class=&quot;language-text&quot;&gt;context&lt;/code&gt;를 바인딩하면서 실행합니다.&lt;/p&gt;
&lt;p&gt;예제를 만들어서 일반 함수와 화살표 함수의 동작원리를 비교해봤습니다. (Node.js 환경)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113175262-3527b600-9286-11eb-92d3-3f5c70135703.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;첫번째 예제에서는 this가 전부 전역 객체를 가리킵니다. ({})&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113175554-82a42300-9286-11eb-9690-c6ad6db3a0d1.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;두번째 예제에서는 생성자 함수로 객체를 만들어 바인딩해봤습니다. 화살표 함수의 경우 this context가 vm을 가리키지 못합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113175871-dc0c5200-9286-11eb-9daa-34717229e9fe.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;call method의 첫번째 인자는 this, 두번째 인자부터는 함수의 매개변수로 값들이 전달됩니다. 화살표 함수도 vm을 잘 전달받습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/113176085-14ac2b80-9287-11eb-84f1-21589938598b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;결론적으로, data에서 this를 사용하는 경우 화살표 함수를 쓰고 싶다면 vm을 인수로 넘겨줘야 하는데 굳이 이렇게까지 해서 화살표 함수를 쓰는 이점이 있을까? 라는 생각이 듭니다.&lt;/p&gt;
&lt;p&gt;긴 글 읽어주셔서 감사합니다. 피드백은 언제나 환영입니다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Django framework로 간단한 api 만들기]]></title><description><![CDATA[본 포스트는 인프런의 플러터와 장고로 1시간만에 퀴즈 앱/서버 만들기 [무작정 풀스택] 강의를 듣고 내용을 정리한 것입니다. 퀴즈 모델에 관한 api…]]></description><link>https://donghoon-song.github.io/development/2021-03-07---Django-framework로-간단한-api-만들기/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2021-03-07---Django-framework로-간단한-api-만들기/</guid><pubDate>Sun, 07 Mar 2021 22:31:00 GMT</pubDate><content:encoded>&lt;p&gt;본 포스트는 &lt;a href=&quot;https://www.inflearn.com/course/%ED%94%8C%EB%9F%AC%ED%84%B0-%EC%9E%A5%EA%B3%A0-%ED%80%B4%EC%A6%88%EC%95%B1-%EC%84%9C%EB%B2%84-%ED%92%80%EC%8A%A4%ED%83%9D&quot;&gt;인프런의 플러터와 장고로 1시간만에 퀴즈 앱/서버 만들기 [무작정 풀스택] 강의&lt;/a&gt;를 듣고 내용을 정리한 것입니다. 퀴즈 모델에 관한 api를 만들어봅니다.&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;venv-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;먼저-가상환경을-설정합니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A8%BC%EC%A0%80-%EA%B0%80%EC%83%81%ED%99%98%EA%B2%BD%EC%9D%84-%EC%84%A4%EC%A0%95%ED%95%A9%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;먼저 가상환경을 설정합니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;먼저 &lt;a href=&quot;#venv-content&quot;&gt;가상환경&lt;/a&gt;을 설정합니다.&lt;/h2&gt;
&lt;p&gt;가상환경을 설정하는 명령어는 다음과 같습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 가상환경 설정
python3 &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;m venv venv&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;본인의 가상환경 이름&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 가상환경 활성화
source venv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;activate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 Django project를 cli로 생성합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 프로젝트 생성 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;을 꼭 적어야함&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
django&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;admin startproject myapi &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
python manage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py startapp quiz&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;settingspy-파일을-수정합니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#settingspy-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%88%98%EC%A0%95%ED%95%A9%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;settingspy 파일을 수정합니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;settings.py 파일을 수정합니다.&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 모든 호스트 허용
ALLOWED_HOSTS &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 타임존 변경
TIME_ZONE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Asia/Seoul&apos;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 스태틱 파일 경로 추가
STATIC_ROOT &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;BASE_DIR&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;staticfiles&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; INSTALLED_APPS에 &lt;span class=&quot;token string&quot;&gt;&apos;quiz&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rest_framework&apos;&lt;/span&gt; 추가&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a id=&quot;installed-app-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#installed-app-content&quot;&gt;INSTALLED_APP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;migration-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;migration을-합니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#migration%EC%9D%84-%ED%95%A9%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;migration을 합니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;#migration-content&quot;&gt;migration&lt;/a&gt;을 합니다.&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; migration 파일 생성
python manage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py makemigrations
&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; migration 진행
python manage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py migrate
&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; 서버 구동
python manage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py runserver&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지 하면 기본적인 서버를 만들었습니다.&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;model-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;다음으로-model을-생성하겠습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%EC%9D%8C%EC%9C%BC%EB%A1%9C-model%EC%9D%84-%EC%83%9D%EC%84%B1%ED%95%98%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;다음으로 model을 생성하겠습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다음으로 &lt;a href=&quot;#model-content&quot;&gt;Model&lt;/a&gt;을 생성하겠습니다.&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; quiz&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models

&lt;span class=&quot;token comment&quot;&gt;# Create your models here.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Quiz&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    answer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IntegerField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a id=&quot;serializer-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;serializer-생성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#serializer-%EC%83%9D%EC%84%B1&quot; aria-label=&quot;serializer 생성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;#serializer-content&quot;&gt;Serializer&lt;/a&gt; 생성&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; serializers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; serializers
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Quiz

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;QuizSerializer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serializers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModelSerializer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        model &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Quiz
        fields &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;body&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;answer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Model과 Serializer를 만들었으니, 이제는 실제로 api를 만들어봅니다.&lt;/p&gt;
&lt;h2 id=&quot;api-생성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#api-%EC%83%9D%EC%84%B1&quot; aria-label=&quot;api 생성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;api 생성&lt;/h2&gt;
&lt;p&gt;&lt;a id=&quot;view-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#view-content&quot;&gt;view&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; quiz&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;views&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Response
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decorators &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; api_view
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Quiz
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serializers &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; QuizSerializer
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; random
&lt;span class=&quot;token comment&quot;&gt;# Create your views here.&lt;/span&gt;
&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@api_view&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;randomQuiz&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    totalQuizs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Quiz&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; sample의 두번째 인자는 length
    randomQuizs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sample&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;totalQuizs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; serializer에 many&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;를 주면&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 다수의 데이터도 직렬화해줍니다&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    serializer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QuizSerializer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;randomQuizs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; many&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serializer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;이제-api를-url에-연결하면-됩니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%A0%9C-api%EB%A5%BC-url%EC%97%90-%EC%97%B0%EA%B2%B0%ED%95%98%EB%A9%B4-%EB%90%A9%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;이제 api를 url에 연결하면 됩니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이제 api를 url에 연결하면 됩니다.&lt;/h2&gt;
&lt;p&gt;myapi내의 &lt;code class=&quot;language-text&quot;&gt;urls.py&lt;/code&gt;는 전체 app에 대한 url을 관리하고, &lt;code class=&quot;language-text&quot;&gt;quiz/urls.py&lt;/code&gt;는 quiz app에 대한 url만 관리합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; quiz&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;views &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; randomQuiz

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;int:id&gt;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; randomQuiz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; myapi&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;contrib &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; admin
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;admin/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; admin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;site&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;quiz/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;quiz.urls&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a id=&quot;dynamic-url-header&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#dynamic-url-content&quot;&gt;django에서 동적 url 작성법&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;api-개발을-완료했습니다-이제-model-data를-생성하기-위해-admin을-등록해봅니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#api-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%99%84%EB%A3%8C%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%9D%B4%EC%A0%9C-model-data%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-admin%EC%9D%84-%EB%93%B1%EB%A1%9D%ED%95%B4%EB%B4%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;api 개발을 완료했습니다 이제 model data를 생성하기 위해 admin을 등록해봅니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;api 개발을 완료했습니다. 이제 model data를 생성하기 위해 admin을 등록해봅니다.&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; quiz&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;py
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;contrib &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; admin
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Quiz

&lt;span class=&quot;token comment&quot;&gt;# Register your models here.&lt;/span&gt;
admin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;site&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;register&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Quiz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;model이 변경되었기 떄문에 migration을 한번 더 진행합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/110243829-6d95e600-7f9f-11eb-90a3-7aad363ddebe.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;이제-admin에-접속할-수-있는-슈퍼계정을-만듭니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%A0%9C-admin%EC%97%90-%EC%A0%91%EC%86%8D%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%8A%88%ED%8D%BC%EA%B3%84%EC%A0%95%EC%9D%84-%EB%A7%8C%EB%93%AD%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;이제 admin에 접속할 수 있는 슈퍼계정을 만듭니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이제 admin에 접속할 수 있는 슈퍼계정을 만듭니다.&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;python manage.py createsuperuser&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;서버를-구동해봅니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%9C%EB%B2%84%EB%A5%BC-%EA%B5%AC%EB%8F%99%ED%95%B4%EB%B4%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;서버를 구동해봅니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;서버를 구동해봅니다.&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;python manage.py runserver&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;어드민에-접속해서-model을-만들어봅니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%93%9C%EB%AF%BC%EC%97%90-%EC%A0%91%EC%86%8D%ED%95%B4%EC%84%9C-model%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B4%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;어드민에 접속해서 model을 만들어봅니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어드민에 접속해서 Model을 만들어봅니다.&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/110244000-13e1eb80-7fa0-11eb-8ed6-ab76b5ccdbcb.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;model-data를-4개-이상-만들고-quiz3을-호출해봅니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#model-data%EB%A5%BC-4%EA%B0%9C-%EC%9D%B4%EC%83%81-%EB%A7%8C%EB%93%A4%EA%B3%A0-quiz3%EC%9D%84-%ED%98%B8%EC%B6%9C%ED%95%B4%EB%B4%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;model data를 4개 이상 만들고 quiz3을 호출해봅니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Model data를 4개 이상 만들고 “/quiz/3”을 호출해봅니다.&lt;/h2&gt;
&lt;p&gt;api가 잘 작동하는 것을 확인할 수 있습니다!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/110244192-e5b0db80-7fa0-11eb-8e5b-4acb4ae19639.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 django framework로 model 생성 및 api를 만들어보았습니다. 코드를 따라치다가 원리가 궁금해서 내용을 정리해보았습니다. 다음에는 flutter app부분도 내용을 정리할까 합니다.&lt;/p&gt;
&lt;h2 id=&quot;내용-정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;내용 정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;내용 정리&lt;/h2&gt;
&lt;p&gt;&lt;a id=&quot;venv-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#venv-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
가상환경이란
&lt;/summary&gt;
가상환경은 해당 프로젝트의 Python 개발환경을 구축하기 위해 모듈을 독립적으로 관리하는 환경입니다. 가상환경을 설정하는 이유는 각 모듈이 다른 모듈에 의존성을 가지고 있기 때문에 이것저것 설치하다가 충돌이 날 수 있기 때문입니다.
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a id=&quot;installed-app-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#installed-app-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
INSTALLED_APPS란
&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/ko/3.1/intro/tutorial02/&quot;&gt;참고&lt;/a&gt;&lt;br/&gt;
INSTALLED_APPS는 Django와 함께 딸려오는 다음의 앱들 등을 포함합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;django.contrib.admin - 관리용 사이트&lt;/li&gt;
&lt;li&gt;django.contrib.auth - 인증 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그외 앱들
…&lt;/p&gt;
&lt;p&gt;Django 인스턴스에서 활성화된 모든 Django application들의 이름을 담고 있습니다.&lt;/p&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a id=&quot;migration-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#migration-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
migration이란
&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/ko/3.1/intro/tutorial02/&quot;&gt;참고&lt;/a&gt;&lt;br/&gt;
Django framework는 기본적으로 SQLite를 사용하도록 구성되어 있습니다. migrate 명령어를 실행하면 INSTALLED_APPS를 참고해 필요한 데이터베이스 테이블을 생성합니다.&lt;/p&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a id=&quot;model-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#model-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
Model field reference
&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/3.1/ref/models/fields&quot;&gt;참고&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CharField
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;class CharField(max_length=None, **options)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;small to large string field&lt;/li&gt;
&lt;li&gt;대량의 텍스트는 TextField를 사용할 것&lt;/li&gt;
&lt;li&gt;max_length는 required argument&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TextField
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;class TextField(**options)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;large textfield&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;InterField
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;class IntegerField(**options)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An integer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a id=&quot;serializer-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#serializer-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
Serializer란
&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://www.django-rest-framework.org/api-guide/serializers/&quot;&gt;참고&lt;/a&gt;&lt;br/&gt;
쿼리셋, 모델 인스턴스 등의 복잡한 데이터를 JSON, XML 등의 컨텐츠 타입으로 쉽게 변환시켜주는 역할.
여기서는 Django의 모델 데이터를 JSON 타입으로 바꿔주는(직렬화) 코드(클래스)&lt;/p&gt;
&lt;h3 id=&quot;modelserializer&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#modelserializer&quot; aria-label=&quot;modelserializer permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ModelSerializer&lt;/h3&gt;
&lt;p&gt;이 class는 &lt;code class=&quot;language-text&quot;&gt;Serializer&lt;/code&gt; class와 같지만 다음 차이점이 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;model을 기반으로 field를 자동생성합니다.&lt;/li&gt;
&lt;li&gt;validator를 자동생성합니다.&lt;/li&gt;
&lt;li&gt;간단한 &lt;code class=&quot;language-text&quot;&gt;.create()&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;.update()&lt;/code&gt; 메서드를 기본적으로 가지고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;따라서, 간단하게 Serializer를 만들 때 사용됩니다.&lt;/p&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a id=&quot;view-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#view-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
view란
&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/3.1/topics/http/views/&quot;&gt;참고&lt;/a&gt;&lt;br/&gt;
프론트엔드 개발자로서 view란 view template을 의미하는 줄 알았지만, Django에서의 view function은 &lt;strong&gt;Web request를 받고 Web response를 return&lt;/strong&gt;하는 역할을 합니다. express framework의 route와 유사하다는 생각이 들었습니다.&lt;/p&gt;
&lt;/details&gt;
&lt;br/&gt;
&lt;p&gt;&lt;a id=&quot;dynamic-url-content&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;#dynamic-url-header&quot;&gt;돌아가기&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
django에서 동적 url 작성법
&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;str - ’/‘를 제외한 비어있지 않은 문자열&lt;/li&gt;
&lt;li&gt;int - 0이상의 정수&lt;/li&gt;
&lt;li&gt;slug - 아스키 문자나 숫자, 하이픈, 언더스코어 등으로 이루어진 slug string
&lt;ul&gt;
&lt;li&gt;ex. building-your-1st-django-site&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;uuid - UUID&lt;/li&gt;
&lt;li&gt;path - ’/‘를 포함한 비어있지 않은 문자열
&lt;ul&gt;
&lt;li&gt;str은 부분 URL path&lt;/li&gt;
&lt;li&gt;path는 완전한 URL path&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;br/&gt;</content:encoded></item><item><title><![CDATA[오픈소스를 번역할 때 유용한 Git Localize 사용법]]></title><description><![CDATA[바로가기 등록하기 번역하기 리뷰하기  등록하기 Git Localize Git Localize는 Git Repository의 내용 번역을 쉽게 도와주는 사이트입니다. Git Localize…]]></description><link>https://donghoon-song.github.io/development/2021-01-02---오픈소스를-번역할-때-유용한-Git-Localize-사용법/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2021-01-02---오픈소스를-번역할-때-유용한-Git-Localize-사용법/</guid><pubDate>Sat, 02 Jan 2021 00:48:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;바로가기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B0%94%EB%A1%9C%EA%B0%80%EA%B8%B0&quot; aria-label=&quot;바로가기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;바로가기&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#register&quot;&gt;등록하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#translate&quot;&gt;번역하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#review&quot;&gt;리뷰하기&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a name=&quot;register&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;등록하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0&quot; aria-label=&quot;등록하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;등록하기&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441476-9e048f80-4c91-11eb-92b2-90674cde683c.png&quot; alt=&quot;Git Localize&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;git-localize는-git-repository의-내용-번역을-쉽게-도와주는-사이트입니다-git-localize&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#git-localize%EB%8A%94-git-repository%EC%9D%98-%EB%82%B4%EC%9A%A9-%EB%B2%88%EC%97%AD%EC%9D%84-%EC%89%BD%EA%B2%8C-%EB%8F%84%EC%99%80%EC%A3%BC%EB%8A%94-%EC%82%AC%EC%9D%B4%ED%8A%B8%EC%9E%85%EB%8B%88%EB%8B%A4-git-localize&quot; aria-label=&quot;git localize는 git repository의 내용 번역을 쉽게 도와주는 사이트입니다 git localize permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Git Localize는 Git Repository의 내용 번역을 쉽게 도와주는 사이트입니다. &lt;a href=&quot;https://gitlocalize.com/&quot;&gt;Git Localize&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;로그인을 해서 &lt;code class=&quot;language-text&quot;&gt;Add Repository&lt;/code&gt;를 누르면 번역할 대상을 등록할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441527-005d9000-4c92-11eb-839f-7b103eb0a26d.png&quot; alt=&quot;image&quot;&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441536-1703e700-4c92-11eb-9b6b-2c55980ddf92.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;다음으로 번역할 Repository를 고르는데, 접근 권한 설정이 되어 있어야 보이겠죠?
Repository를 고른 뒤에는, 대상 Branch를 작성합니다. 저는 번역용 Branch를 따로 생성해서 PR을 생성할 것이기 때문에 제가 새로 만든 Branch이름을 적었습니다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;default branch&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;master&lt;/code&gt;인데, master를 main으로 바꾸신 분들은 main을 적어주세요!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441547-2daa3e00-4c92-11eb-8ec3-892e576fe574.png&quot; alt=&quot;image&quot;&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441603-706c1600-4c92-11eb-8bed-44568d5c06cd.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Project Paths&lt;/code&gt; 항목에서는 Repository 안에서 &lt;code class=&quot;language-text&quot;&gt;번역할 대상을 지정&lt;/code&gt;할 수 있습니다.
&lt;code class=&quot;language-text&quot;&gt;Directory&lt;/code&gt;로 설정하면 해당 Directory에 있는 모든 파일이 대상이 되며, &lt;code class=&quot;language-text&quot;&gt;File&lt;/code&gt;을 선택하면 특정 File만 선택할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;%lang%&lt;/code&gt;이라는 placeholder는 번역 세팅에 따라 &lt;code class=&quot;language-text&quot;&gt;target language&lt;/code&gt;로 자동 변환됩니다.
예를 들어서, &lt;code class=&quot;language-text&quot;&gt;target language&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;ko&lt;/code&gt;로 설정한다면 &lt;code class=&quot;language-text&quot;&gt;Microsoft-Web-Dev-For-Beginners&lt;/code&gt;에 있는 파일들을 번역하면 &lt;code class=&quot;language-text&quot;&gt;Microsoft-Web-Dev-For-Beginners/ko&lt;/code&gt;에 저장됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441644-b628de80-4c92-11eb-8831-e0b19a209bca.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;저는 모든 파일들을 번역할 것이 아니라 특정 파일들만 번역할 예정이라 &lt;code class=&quot;language-text&quot;&gt;File&lt;/code&gt;로 Path들을 추가해나갔습니다.
&lt;code class=&quot;language-text&quot;&gt;%lang%&lt;/code&gt; 부분이 &lt;code class=&quot;language-text&quot;&gt;target language&lt;/code&gt;로 자동 변환된다고 했죠? 제가 설정한걸 예로 들어보면
&lt;code class=&quot;language-text&quot;&gt;assignment.md&lt;/code&gt; 파일을 번역하면 &lt;code class=&quot;language-text&quot;&gt;./translations/assignment.ko.md&lt;/code&gt;파일로 저장된다고 볼 수 있습니다!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441685-04d67880-4c93-11eb-8172-a961ca59c94c.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그 다음엔 &lt;code class=&quot;language-text&quot;&gt;Project languages&lt;/code&gt; 설정입니다. 제가 이 글을 쓰게 된 이유이기도 합니다.
&lt;code class=&quot;language-text&quot;&gt;ko&lt;/code&gt;라고 검색하면 두개가 나오는데 [ko-KR]을 선택하고 제출하면, &lt;strong&gt;계속 로딩만 되고 아무것도 안됩니다.&lt;/strong&gt;
&lt;strong&gt;위에 있는 &lt;code class=&quot;language-text&quot;&gt;[ko]&lt;/code&gt;를 선택하셔야 합니다.&lt;/strong&gt;
그리고 나서 Submit 버튼을 누르시면 정상적으로 등록됩니다. 😎 파일이 많을수록 로딩이 오래 걸리니 조금만 기다려주시면 됩니다. 준비가 되면 이메일로 알려줍니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441755-4bc46e00-4c93-11eb-8326-a4ab650983df.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;등록이 되면 리스트에 등록한 결과가 나오며, 여러가지 메뉴가 나옵니다.
Overview 메뉴에서는 번역 상태를 볼수 있고 번역 언어도 관리할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441817-d7d69580-4c93-11eb-9c0c-dfea934aea23.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;Team 메뉴에서는 함께 작업할 유저들을 초대하고 관리할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441820-e0c76700-4c93-11eb-9485-7998c08219c2.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;Settings 메뉴에서는 Project Paths를 수정할 수 있으며 Sync Repository, Repository 제거 등을 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441821-e58c1b00-4c93-11eb-9e28-2b63d79cbf04.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;Badge 메뉴에서는 프로젝트의 README.md에 추가할 수 있는 귀여운 배지를 제공해주네요!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103441822-e8870b80-4c93-11eb-8a84-3c55ee287fb8.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;translate&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;번역하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B2%88%EC%97%AD%ED%95%98%EA%B8%B0&quot; aria-label=&quot;번역하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;번역하기&lt;/h1&gt;
&lt;p&gt;번역하려는 파일을 클릭하면 다음과 같은 화면이 나옵니다.&lt;/p&gt;
&lt;p&gt;여기서 각각의 블럭들을 &lt;code class=&quot;language-text&quot;&gt;segment&lt;/code&gt;라고 부릅니다. 원본 &lt;code class=&quot;language-text&quot;&gt;segment&lt;/code&gt;랑 번역본 &lt;code class=&quot;language-text&quot;&gt;segment&lt;/code&gt;랑 일대일로 &lt;code class=&quot;language-text&quot;&gt;link&lt;/code&gt;되어 있습니다.&lt;/p&gt;
&lt;p&gt;ex) Reading the Docs - 문서 읽기&lt;/p&gt;
&lt;p&gt;Git Localize는 &lt;code class=&quot;language-text&quot;&gt;Machine Translate&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Pretranslate from TM&lt;/code&gt; 기능을 제공합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455092-4a478400-4d2d-11eb-97ce-57c66d250d2f.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Machine Translate&lt;/code&gt;은 말그대로 번역을 자동으로 한번 해주는 기능입니다. 버튼을 클릭하면, 기계가 번역할 수 있는 부분만큼 번역해줍니다. 번역이 막막할 때 큰 도움이 되는 기능입니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455204-7fa0a180-4d2e-11eb-9b23-deb74d55678a.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Pretranslate from TM&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;suggestion&lt;/code&gt;을 바탕으로 번역을 해주는 기능입니다. 여기서 &lt;code class=&quot;language-text&quot;&gt;suggestion&lt;/code&gt;은 이전에 다른 파일들을 번역했던 기록을 가지고 제안해주는 기능입니다. 밑에 &lt;code class=&quot;language-text&quot;&gt;Suggestions&lt;/code&gt;에서 그 기록들을 확인할 수 있습니다. 이 기능을 사용하면 협업할 때, &lt;code class=&quot;language-text&quot;&gt;다른 작업자들이 해당 단어를 어떻게 번역했는지&lt;/code&gt; 찾아보지 않아도 파악할 수 있어서 굉장히 좋습니다.
최초에 빨갛게 나오는 부분은 눌러보면 왼쪽의 원본이랑 &lt;code class=&quot;language-text&quot;&gt;링크되지 않는 segment&lt;/code&gt;라고 나오는데 왜 두개씩 나오는지는 아직 파악하지 못했습니다. 같은 것이 두개씩 나온거라서 저는 빨간색 부분은 삭제했습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455143-ab6f5780-4d2d-11eb-9446-e735e029c17b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;segment&lt;/code&gt;를 클릭하면 내용을 수정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455260-02296100-4d2f-11eb-937d-e47643bffca0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;review&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;리뷰하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A6%AC%EB%B7%B0%ED%95%98%EA%B8%B0&quot; aria-label=&quot;리뷰하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리뷰하기&lt;/h1&gt;
&lt;p&gt;번역을 완료하면 &lt;code class=&quot;language-text&quot;&gt;Create Review Request&lt;/code&gt; 버튼을 눌러서 리뷰를 요청할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455358-add2b100-4d2f-11eb-99f2-c79bc3a07791.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;코멘트를 남기고 제출하면 리뷰 요청 목록에서 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455382-e3779a00-4d2f-11eb-872e-b5542bf31593.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455397-07d37680-4d30-11eb-9946-48dfe7339c83.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;파일 이름을 눌러서 들어가보면 Approve할 수 있도록 체크박스가 나옵니다.
&lt;strong&gt;현재 &lt;code class=&quot;language-text&quot;&gt;Approve all&lt;/code&gt; 체크박스를 눌러서 &lt;code class=&quot;language-text&quot;&gt;Approve&lt;/code&gt;한 경우 승인 상황이 저장되지 않는 버그가 있습니다.&lt;/strong&gt; report를 넣어야겠네요!😎 &lt;code class=&quot;language-text&quot;&gt;체크박스를 하나하나씩 일일이 눌러야&lt;/code&gt; 저장이 되네요. 확인해보려면 approve후에 다른 페이지에 갔다가 다시 이 페이지로 돌아와보시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455417-5123c600-4d30-11eb-8bfd-33b1d075e2c0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 나와야 잘 저장된 거겠죠?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455509-14a49a00-4d31-11eb-955a-4d6acac73ddf.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;해당 요청에 코멘트도 남길 수 있고, 리뷰를 마치고 &lt;code class=&quot;language-text&quot;&gt;Send Pull Request&lt;/code&gt; 기능을 활용해서 기존 저장소에 merge를 하면 번역이 끝나겠네요.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455669-49fdb780-4d32-11eb-89d7-526808cd5a21.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455406-35202480-4d30-11eb-9bfb-25d734426b93.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Translated Texts&lt;/code&gt; 메뉴를 이용하면 그 자리에서 번역 요약정보를 확인할 수 있습니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103455545-5cc3bc80-4d31-11eb-8f61-6680f24243f5.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 Git Localize에 등록하는 부분부터 번역, 리뷰하는 방법까지 알아봤습니다. 이번에 처음 써보면서 몇몇 버그도 발견했는데 잘 정리해서 Git Localize측에 알려주고 싶고, 좋은 도구를 찾은 거 같아 기분이 굉장히 좋습니다 :) 영어가 어려워서 번역을 망설이시는 분들도 Git Localize와 함께 다시 시작해보셨으면 하는 바램입니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[스타트업 주니어 개발자의 2020년 연말회고]]></title><description><![CDATA[image 연말회고 두둥등장! (요즘에 머쉬베놈에 빠져있음) 스타트업에서 개발자로 일한다는 것 올해초에 서울로 올라와서 취준을 하다가 운이 좋게…]]></description><link>https://donghoon-song.github.io/development/2020-12-31---스타트업-주니어-개발자의-2020년-연말회고/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-12-31---스타트업-주니어-개발자의-2020년-연말회고/</guid><pubDate>Thu, 31 Dec 2020 16:13:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103399499-baff6c80-4b84-11eb-84bb-7022393eaf02.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;연말회고 두둥등장! (요즘에 머쉬베놈에 빠져있음)&lt;/p&gt;
&lt;h1 id=&quot;스타트업에서-개발자로-일한다는-것&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85%EC%97%90%EC%84%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%EC%9D%BC%ED%95%9C%EB%8B%A4%EB%8A%94-%EA%B2%83&quot; aria-label=&quot;스타트업에서 개발자로 일한다는 것 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;스타트업에서 개발자로 일한다는 것&lt;/h1&gt;
&lt;p&gt;올해초에 서울로 올라와서 취준을 하다가 운이 좋게 3월말이라는 빠른 타이밍에 지금의 회사에 합류해서 지금까지 개발자로 일하고 있다. 나와 내 대학동기들이 지겹게 겪었던 &lt;code class=&quot;language-text&quot;&gt;정보격차&lt;/code&gt; 문제, 관심 분야의 &lt;code class=&quot;language-text&quot;&gt;실제 직무를 체험&lt;/code&gt;하기 힘든 문제를 해결하는 회사이다. &lt;code class=&quot;language-text&quot;&gt;수평적인 환경&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;독자적인 개인&lt;/code&gt;으로서 성장할 수 있는 환경도 마음에 들었다.&lt;/p&gt;
&lt;p&gt;우리 회사는 &lt;code class=&quot;language-text&quot;&gt;데이터에 기반하여 의사결정&lt;/code&gt;을 한다. 그리고 끊임없이 &lt;code class=&quot;language-text&quot;&gt;실험&lt;/code&gt;한다. 처음에는 이 말이 잘 와닿지 않았는데 계속 일을 하다보니 피부로 와닿았다. 제품을 개선하거나 수정할 때 “이게 더 이쁘다.”, “이게 더 나아보인다.” 라는 추상적인 생각은 근거가 되지 않는다. “이 부분을 이렇게 바꾸면 제품의 어떤 면이 더 좋아져서 어떤 퍼널로의 전환율이 증가할 것이다.” 라는 &lt;code class=&quot;language-text&quot;&gt;가설&lt;/code&gt;을 세우고 &lt;code class=&quot;language-text&quot;&gt;A/B 테스트&lt;/code&gt;를 진행한다. 해당 url로 들어오는 유저들에게 A안 또는 B안을 보여주고 유저들의 행동을 분석한다. 실험이 끝나면 실험 결과를 분석하고 문서화해서 의사결정에 사용한다. 이렇게 유저들을 &lt;code class=&quot;language-text&quot;&gt;학습&lt;/code&gt;한다.&lt;/p&gt;
&lt;p&gt;수평적인 문화를 바탕으로 구성원 누구나 눈치를 보지않고 목소리를 낼 수 있다. 그 목소리들이 누군가가 놓치고 있는 것을 캐치해줄 수 있었고, 누군가에게 발상의 전환점이 될 수 있었다.&lt;/p&gt;
&lt;p&gt;대표님(사내에선 대표님이라고 안부름)이 중요하게 생각하시는 &lt;code class=&quot;language-text&quot;&gt;결정하는 연습&lt;/code&gt;을 계속하고 있다. 업무의 우선순위, 예상마감일 등을 스스로 결정하면서 자신의 업무를 관리한다. 그 과정속에서 &lt;code class=&quot;language-text&quot;&gt;독자적인 개인&lt;/code&gt;으로 성장하고 있다고 느낀다.&lt;/p&gt;
&lt;h1 id=&quot;프론트엔드-팀내에서-나의-역할&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%8C%80%EB%82%B4%EC%97%90%EC%84%9C-%EB%82%98%EC%9D%98-%EC%97%AD%ED%95%A0&quot; aria-label=&quot;프론트엔드 팀내에서 나의 역할 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;프론트엔드 팀내에서 나의 역할&lt;/h1&gt;
&lt;h2 id=&quot;기술적으로-괴롭히기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EC%88%A0%EC%A0%81%EC%9C%BC%EB%A1%9C-%EA%B4%B4%EB%A1%AD%ED%9E%88%EA%B8%B0&quot; aria-label=&quot;기술적으로 괴롭히기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기술적으로 괴롭히기&lt;/h2&gt;
&lt;p&gt;나의 팀내 주 역할은 &lt;code class=&quot;language-text&quot;&gt;기술적으로 괴롭히기&lt;/code&gt;라고 생각한다. 코드를 보다가 개선할만한 지점이 있거나 새로 적용해볼만한 기술들이 있으면 정리해서 프론트엔드 스크럼 때 공유했다. 다른 분들도 많이 공유를 해주셨다. 공유를 하면 잘 귀기울여주시고, 각자 생각하는 의견을 말씀해주셔서 피드백도 자유롭게 이루어졌다. 그런 팀원들이 정말 고맙고 같이 일을 할 수 있어서 고맙게 생각하고 있다.&lt;/p&gt;
&lt;h2 id=&quot;프론트엔드팀-datadog-관리자&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%ED%8C%80-datadog-%EA%B4%80%EB%A6%AC%EC%9E%90&quot; aria-label=&quot;프론트엔드팀 datadog 관리자 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;프론트엔드팀 Datadog 관리자(?)&lt;/h2&gt;
&lt;p&gt;어쩌다보니 프론트엔드팀에서 Datadog 매니저님과 커뮤니케이션 하는 사람이 내가 되었다. 프론트엔드 팀에서 사용하고 있는 서비스의 요금도 내가 모니터링하고 관리하고 있다. 내가 Datadog에 가장 관심이 많아서였는지 Datadog이라는 미지의 세계를 가장 먼저 개척하고, 사용법을 요약해 팀내에 공유한적이 있다.&lt;/p&gt;
&lt;h1 id=&quot;기억에-남는-활동들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EC%96%B5%EC%97%90-%EB%82%A8%EB%8A%94-%ED%99%9C%EB%8F%99%EB%93%A4&quot; aria-label=&quot;기억에 남는 활동들 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;기억에 남는 활동들&lt;/h1&gt;
&lt;h2 id=&quot;junction-x-seoul-2020-해커톤&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#junction-x-seoul-2020-%ED%95%B4%EC%BB%A4%ED%86%A4&quot; aria-label=&quot;junction x seoul 2020 해커톤 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Junction X Seoul 2020 해커톤&lt;/h2&gt;
&lt;p&gt;작년에 같이했던 팀원 한명이랑 회사 동료들 3명과 함께 참여했다. 포지션은 기획1, 디자인1, 프론트엔드3(?)이었다. serverless framework + lambda로 해커톤 규모의 백엔드 정도는 구현할 수 있을 거 같아서 내가 백엔드를 자처했다. 그렇게 나는 프론트엔드 + 가성비 백엔드(팀원피셜) 역할을 맡았다. &lt;code class=&quot;language-text&quot;&gt;가성비 백엔드&lt;/code&gt;라는 별명이 매우 마음에 들었다. 🤣  작년에는 내 구현능력이 많이 부족했고, 핵심을 파악하지 못했어서 많이 아쉬운 부분이 있었다. 그래서 이번에는 &lt;code class=&quot;language-text&quot;&gt;코어 기능의 완전한 구현&lt;/code&gt;을 목표로 삼았다.&lt;/p&gt;
&lt;p&gt;기획단계부터 개발단계까지 순조롭게 진행됐다. 작년에 참여했던 경험도 도움이 됐고 많이 비교가 됐다. 사이드 프로젝트가 아닌 해커톤이라는 걸 명심하고 주제와 서비스 타겟을 기준으로 아이디어들을 필터링했으며, 코어 기능을 중심으로 세부기능들을 가지치기 해나갔다. 그 결과 코어 기능을 만족스럽게 구현했고 발표자료도 잘 만들었다. 그리고 운이 좋게 해당 트랙에서 2등상을 수상할 수 있었다. 🎉&lt;/p&gt;
&lt;p&gt;내 친구가 연말회고 때 인용했던 말이 있다. &lt;code class=&quot;language-text&quot;&gt;&quot;최고의 복지는 동료다.&quot;&lt;/code&gt; 이 때 나는 해커톤에 나가자고 하면 기쁜 마음으로 승낙해주는 동료들이 있다는 것이 참 고마웠다.&lt;/p&gt;
&lt;h2 id=&quot;오픈소스-컨트리뷰톤&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A8%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%86%A4&quot; aria-label=&quot;오픈소스 컨트리뷰톤 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;오픈소스 컨트리뷰톤&lt;/h2&gt;
&lt;p&gt;작년에는 여유가 없어서 참여하지 못했던 컨트리뷰톤이었다. 올해 컨트리뷰톤 신청 당시에는 회사 업무가 널널해서 충분히 소화할 수 있을 것이라고 생각했는데 거짓말처럼 컨트리뷰톤 활동 시작시점부터 회사 업무가 많아져서 컨트리뷰톤에 시간을 많이 쓰지 못했다. 처음 2주간은 회의에 참여하는 것이 활동의 전부였다. 회의에 참여해도 무슨 내용인지 이해하기 힘들었고 잘 따라가는 다른 멘티분들이 대단해보이고 부러웠다. 스트레스를 많이 받아서 포기할까 하는 생각도 들었다. 내 목표는 &lt;code class=&quot;language-text&quot;&gt;PR 최소 1개 작성&lt;/code&gt; 이었는데, 뭐라도 해보자는 생각으로 프로젝트 코드를 쭉 읽어보면서 오타를 찾아냈다. 이렇게 많은 사람들이 유지보수하는 프로젝트에는 오타가 별로 없을 줄 알았는데 5개나 찾았다. 생각보다 많아서 놀랐다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mochajs/mocha/pull/4404&quot;&gt;Fixing typos by donghoon-song · Pull Request #4404 · mochajs/mocha&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;원래 오픈소스 입문은 오타찾기나 번역이라고 했다 😎  이렇게 PR을 올리고 merge가 되니까 뭐라도 했다는 &lt;code class=&quot;language-text&quot;&gt;뿌듯함&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;자신감&lt;/code&gt;이 생겼다. 최소한의 목표를 이뤘던 나는 그 후로 &lt;code class=&quot;language-text&quot;&gt;오기&lt;/code&gt;가 생겨서 뭐라도 한개만 더 해보자라는 마음가짐으로 task를 찾게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mochajs/mocha/pull/4431&quot;&gt;Fix: Broken wallaby logo on mochajs.org #4430 by donghoon-song · Pull Request #4431 · mochajs/mocha&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;위의 PR을 올리면서 디버깅하는 실력이 많이 늘었다. 패키지들을 타고 타고 들어가다보니까 이슈를 해결할 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mochajs/mocha/pull/4439&quot;&gt;Add support for node v8 option ‘prof’ parameter (#4433) by donghoon-song · Pull Request #4439 · mochajs/mocha&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mochajs/mocha/pull/4443&quot;&gt;Update eslint version by donghoon-song · Pull Request #4443 · mochajs/mocha&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이슈 해결과정을 정리해서 블로그 글로 남겨보기도 했다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://donghoon-song.github.io/posts/2020-09-06---%EC%B4%88%EB%B3%B4-%EC%BB%A8%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%84%B0%EC%9D%98-Mocha-issue-%ED%95%B4%EA%B2%B0-%EB%8F%84%EC%A0%84%EA%B8%B0/&quot;&gt;초보 컨트리뷰터의 Mocha issue 해결 도전기
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;중도 포기하는 분들도 계셨지만 열심히 참여하다보니 어느새 활동을 마무리할 수 있었고 상도 받을 수 있었다.
컨트리뷰톤을 통해 오픈소스를 바라보는 관점이 달라졌다. 활동전에는 미지의 영역이고, 어렵게만 보이던 것들이 어느정도 눈에 들어오기 시작했으며 다른 기여활동으로 이어지기도 했다. 조금이나마 성장했다는 확신을 할 수 있는 계기가 되었다. 그리고 추후에 사내 컴포넌트 패키지를 관리하는데도 큰 도움이 되었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://donghoon-song.github.io/posts/2020-09-09---%EC%B4%88%EB%B3%B4-%EC%BB%A8%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%84%B0%EC%9D%98-Nuxt-docs-PR-%EB%8F%84%EC%A0%84%EA%B8%B0/&quot;&gt;[OpenSource] 초보 컨트리뷰터의 Nuxt docs PR 도전기&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;figma---agit-webhook-연동&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#figma---agit-webhook-%EC%97%B0%EB%8F%99&quot; aria-label=&quot;figma   agit webhook 연동 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Figma - agit webhook 연동&lt;/h2&gt;
&lt;p&gt;디자이너 분들과 협업을 하다가 개발했다. 개발자는 아무래도 피그마(디자인툴)를 자주 보지는 않기 때문에 디자인 변경사항을 실시간으로 체크할 수 없다. 또한 디자이너분들이 어떤 것을 요청했을 때, 작업이 됐는지, 확인은 했는지 여부가 불투명하여 커뮤니케이션 비용이 발생한다.&lt;/p&gt;
&lt;p&gt;그래서 디자이너님들이 특정 조건으로 메시지를 남기면 아지트(협업툴)에 프론트 개발자를 담당자로 해서 글이 남겨지도록 만들었다. 나는 메시지에 &lt;code class=&quot;language-text&quot;&gt;[개발팀]&lt;/code&gt; 이라는 텍스트가 포함되면 발동하도록 조건을 걸어놨다.(아주 간단) 그러면 개발자는 피그마를 계속 확인하지 않아도 꼭 필요한 메시지를  비동기적으로 받을 수 있다. 피그마에서는 디자이너분들끼리의 코멘트와, 개발자에게 보내는 메시지가 분리된다. 또한, 아지트에서 각 코멘트에 대한 업무 진행 상황을 투명하게 체크할 수 있다.&lt;/p&gt;
&lt;p&gt;정말 간단한 로직과 기능임에도 불구하고 팀원들은 아주 잘써주고 있고, 생산성도 많이 향상되었다. 이렇게 &lt;code class=&quot;language-text&quot;&gt;팀원들의 생산성 향상에 기여&lt;/code&gt;했다.&lt;/p&gt;
&lt;h2 id=&quot;프론트엔드와-백엔드의-코드-분리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%B0%B1%EC%97%94%EB%93%9C%EC%9D%98-%EC%BD%94%EB%93%9C-%EB%B6%84%EB%A6%AC&quot; aria-label=&quot;프론트엔드와 백엔드의 코드 분리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;프론트엔드와 백엔드의 코드 분리&lt;/h2&gt;
&lt;p&gt;기존 레거시 시스템은 &lt;code class=&quot;language-text&quot;&gt;laravel framework&lt;/code&gt; 위에서 &lt;code class=&quot;language-text&quot;&gt;blade template engine&lt;/code&gt;으로 vue파일을 렌더링하는 구조이다. 이렇게 laravel에 의존적인 구조여서 프론트엔드의 자유도가 낮았다. routing을 백엔드에서 주로 담당해서 vue store를 제대로 활용할 수 없었고 뭔가를 수정할 때 백엔드 개발자의 도움이 필요한 경우도 많았다. 또한 사용하려고 하는 패키지 중에 잘 호환되지 않는 패키지들도 있었다.&lt;/p&gt;
&lt;p&gt;그래서 오랜시간 PS(Problem Solving)세션과 회의를 거쳐 점진적으로 코드를 분리하기로 결정했다. 새로운 프로젝트에서는 &lt;code class=&quot;language-text&quot;&gt;Nuxt framework&lt;/code&gt;를 사용하기로 했다.
&lt;code class=&quot;language-text&quot;&gt;SEO&lt;/code&gt;가 필요한 페이지에서 &lt;code class=&quot;language-text&quot;&gt;SSR&lt;/code&gt;을 부분적으로 적용할 수 있다는 점이 가장 큰 장점이었다.&lt;/p&gt;
&lt;h2 id=&quot;design-system-개발&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#design-system-%EA%B0%9C%EB%B0%9C&quot; aria-label=&quot;design system 개발 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Design System 개발&lt;/h2&gt;
&lt;h3 id=&quot;component-package-개발-link&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#component-package-%EA%B0%9C%EB%B0%9C-link&quot; aria-label=&quot;component package 개발 link permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Component package 개발 &lt;a href=&quot;https://github.com/comento/comento-ui&quot;&gt;link&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;코멘토에서 쓰이는 Component들을 디자이너들과 함께 Design System화하는 중이다.&lt;/li&gt;
&lt;li&gt;양도 많고 복병들이 있어 난이도도 높았지만 하고 싶었던 업무이고, 완성하고 난 뒤 얻을 수 있는 생산성, 재사용성을 생각하며 즐겁게 만들고 있다.&lt;/li&gt;
&lt;li&gt;모든 작업은 개별 branch에서 이루어지며 develop branch로의 모든 merge는 &lt;code class=&quot;language-text&quot;&gt;PR&lt;/code&gt;을 통해 이루어지며 최소한 한명의 리뷰어가 &lt;code class=&quot;language-text&quot;&gt;리뷰&lt;/code&gt;를 남겨야하고, &lt;code class=&quot;language-text&quot;&gt;CI test&lt;/code&gt;를 모두 통과해야 merge할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;프론트팀은 디자이너팀의 동의를 받아 패키지를 공개하기로 결정했다. 이 결정을 하기까지는 많은 고민이 있었다. 공개 하는 것도 버전1이 만들어지면 공개할지, 미완성상태에서 공개할지도 고민을 많이 했다. 아무래도 주니어들끼리 작업하다보니 서투른 부분도 있고 비효율적인 로직도 있어 공개하기 부끄러운 마음도 있었다.&lt;/p&gt;
&lt;p&gt;하지만 그걸 무릅쓰고 공개를 하는 이유는 그 반대의 사고과정을 거쳐 찾았다. 지나가다 볼 누군가가 &lt;code class=&quot;language-text&quot;&gt;피드백&lt;/code&gt;을 주면 그걸 자양분삼아 더 &lt;code class=&quot;language-text&quot;&gt;발전&lt;/code&gt;시킬 수 있을 것이라는 생각을 했고, 아직 완성되지는 않았지만 완성해 가는 과정, 개선해나가는 과정을 공개적으로 진행하는 것도 누군가에게는 &lt;code class=&quot;language-text&quot;&gt;자극&lt;/code&gt;, 누군가에게는 &lt;code class=&quot;language-text&quot;&gt;도움&lt;/code&gt;이 될 수 있을 것이라고 생각했다.&lt;/p&gt;
&lt;h3 id=&quot;ci&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ci&quot; aria-label=&quot;ci permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CI&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;chromatic 도입
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;visual test tool&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;chromatic을 이용하면 storybook을 빌드할 때마다 해당 버전과 비교할 base 버전과의 &lt;code class=&quot;language-text&quot;&gt;UI상의, code상의 차이&lt;/code&gt;를 보여준다. 구성원들이 차이를 비교하면서 변경 사항을 approve해야 리뷰가 통과된다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://donghoon-song.github.io/posts/2020-09-12---Storybook-visual-test-with-Chromatic/&quot;&gt;[Storybook] Storybook visual test with Chromatic&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PR을 올리거나 올린 상태에서 변경사항이 생기면 chromatic github action이 동작한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;slack에 연동하여 빌드될때마다 메시지가 오고, 결과물을 바로 확인 및 리뷰할 수 있게 했다. 리뷰가 완료되면 완료 메시지도 보내준다. 팀원들이 &lt;code class=&quot;language-text&quot;&gt;PR을 확인하기까지의 시간이 대폭 감소&lt;/code&gt;하였으며, 자신의 PR이 &lt;code class=&quot;language-text&quot;&gt;리뷰됐는지도 빠르게 확인&lt;/code&gt;할 수 있어 좋았다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;build test 도입
&lt;ul&gt;
&lt;li&gt;정말 간단하게 github action을 통해 build를 해보는 test이다.&lt;/li&gt;
&lt;li&gt;처음에는 이런게 필요할지 몰랐지만 작업을 하다보니 필요성을 느껴서 만들었다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;당연히 되어야 할 것도 테스트 해야한다.&lt;/strong&gt; 는 마음가짐이 이때 생겼다.&lt;/li&gt;
&lt;li&gt;코드 상에서 실수를 해서 빌드가 안되거나, merge를 했는데 lint에서 통과를 못해서 빌드가 안되는 경우를 방지할 수 있었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cd&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cd&quot; aria-label=&quot;cd permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CD&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;shipjs 도입&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;오픈소스 라이브러리를 배포하는 것은 간단하지 않았다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;버저닝, npm에 배포, 태그 생성, changelog 작성 등의 일련의 과정들로 이루어졌다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이 과정들을 항상 수동으로 하기에는 &lt;code class=&quot;language-text&quot;&gt;실수&lt;/code&gt;도 많이 나고, &lt;code class=&quot;language-text&quot;&gt;리소스&lt;/code&gt;가 많이 들겠다고 생각했다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;마침 JSConf Korea 2020에서 이은재님께서 &lt;code class=&quot;language-text&quot;&gt;shipjs&lt;/code&gt;라는 라이브러리를 소개해주셔서 사용중이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://jsconfkorea.com/ko/speakers/eunjae&quot;&gt;JSConf Korea 2020 - 발표자 | 이은재&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;사용하다가 변수명 오타를 발견해서 기여를 한건 덤이다!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/algolia/shipjs/pull/928&quot;&gt;fix: typo in GitHubAction config by donghoon-song · Pull Request #928 · algolia/shipjs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;나의 작은 발자취를 남길 수 있었다. 😎&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/103403244-cb1e4880-4b92-11eb-9965-1a6fee0f43e3.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;storybook deployer 도입&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;storybook deployer라는 툴을 이용해 공식 버전의 스토리북을 배포한다.&lt;/li&gt;
&lt;li&gt;이것도 배포할 때 자동으로 실행될 수 있도록 github-action에 등록해두었다.&lt;/li&gt;
&lt;li&gt;현재는 &lt;code class=&quot;language-text&quot;&gt;github pages&lt;/code&gt;에서 호스팅하고 있다. &lt;a href=&quot;https://comento.github.io/comento-ui/&quot;&gt;link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;todos&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#todos&quot; aria-label=&quot;todos permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TODOS&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;번들러 변경
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Rollup&lt;/code&gt;을 통해 &lt;code class=&quot;language-text&quot;&gt;Single File Component&lt;/code&gt; 형식으로 필요한 컴포넌트만 import해서 사용하는 구조로 패키지화하려고 하였으나 밑바닥부터 새로 세팅하는 과정에서 에러들을 발견했고, 시간이 오래 걸려서 잠시 보류해두었다. 내년에 해결해보려고 한다.&lt;/li&gt;
&lt;li&gt;현재는 vue-cli-service의 build 명령어를 사용해서 패키지화하고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;패키지 경량화
&lt;ul&gt;
&lt;li&gt;현재 패키지 파일이 굉장히 크다. 아직은 세팅에 미숙해서 최적화 및 경량화 하는 방법을 적용하지 못했고, 차차 공부하면서 적용해볼 생각이다. (웹팩 주니어이다. 🐣)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단위 테스트 코드 작성
&lt;ul&gt;
&lt;li&gt;jest를 이용해 단위 테스크 코드를 모두 작성하고 개발과정에 넣고 싶었다.&lt;/li&gt;
&lt;li&gt;하지만 구현해야 할 컴포넌트의 양이 너무 많아서 보류 중이다.&lt;/li&gt;
&lt;li&gt;내년에는 열심히 테스트를 작성해서 CI과정에 넣고 싶다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;datadog&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#datadog&quot; aria-label=&quot;datadog permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Datadog&lt;/h3&gt;
&lt;p&gt;개발팀에서 &lt;code class=&quot;language-text&quot;&gt;Datadog&lt;/code&gt;을 도입했다. 프론트엔드의 경우 모니터링할 툴이 없었는데 Datadog의 도입으로 여러가지 지표 확인, 로깅, 테스팅, 유저 분석, 알람 등이 가능해졌다. 서비스가 커져감에 따라 이 기능들의 필요성은 더욱 증가할 것이라고 생각했고 정말 중요하게 생각했다.&lt;/p&gt;
&lt;p&gt;처음 체험기간을 거치고 나서, 팀장님이 꼭 필요한 기능이 아니면 구독을 해지하는 가지치기를 하려고 하셨다. 처음 그말을 듣고 겸사겸사 쓰면 안될까? 하는 생각이 들었는데 시간이 지나고보니 팀장님의 뜻을 이해할 수 있었다. &lt;code class=&quot;language-text&quot;&gt;모든 것은 비용이다.&lt;/code&gt; 굳이 필요로 하지 않는 서비스를 이용하는데 돈을 낼 필요는 전혀 없으며 우리가 꼭 사용해야 할 서비스는 누가 들어도 &lt;code class=&quot;language-text&quot;&gt;설득될만한 이유&lt;/code&gt;를 바탕으로 하고 있어야 함을 말이다.&lt;/p&gt;
&lt;p&gt;솔직히 그 이유를 작성하기가 꽤 어려웠다. 아직 Datadog의 기능들에 익숙해지지 않아 기본적인 사용법 정도밖에 숙지를 못했다. 하지만 최대한 설득해보려고 노력했다. &lt;code class=&quot;language-text&quot;&gt;설득하는 과정도 성장의 과정&lt;/code&gt;이라고 생각했다. 또한, 지금뿐만이 아니라 장기적인 관점에서 꼭 필요하다고 생각했다.&lt;/p&gt;
&lt;p&gt;연말회고를 하는 지금 시점에서 돌이켜보면 굉장히 잘한 선택이라고 생각한다. 현재는 데이터독을 그때보다 더 잘 활용하고 있다. Front End단에서 기본 로그말고도 &lt;code class=&quot;language-text&quot;&gt;custom logger&lt;/code&gt;를 개발해 &lt;code class=&quot;language-text&quot;&gt;특정 이벤트 모니터링&lt;/code&gt;에 활용하며, &lt;code class=&quot;language-text&quot;&gt;이슈 해결용&lt;/code&gt;에도 쓰고 있다.
모니터링을 하지 않을 땐 발견하기 쉽지 않았던 이슈들도 발견해서 고칠 수 있었고 로그를 활용하는 것도 점점 익숙해졌다. &lt;code class=&quot;language-text&quot;&gt;핵심 활용 사례들을 노션에 정리&lt;/code&gt;해서 계속 쌓아가고 있다.&lt;/p&gt;
&lt;h1 id=&quot;마법이-마법이-아니게-되는-순간&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%B2%95%EC%9D%B4-%EB%A7%88%EB%B2%95%EC%9D%B4-%EC%95%84%EB%8B%88%EA%B2%8C-%EB%90%98%EB%8A%94-%EC%88%9C%EA%B0%84&quot; aria-label=&quot;마법이 마법이 아니게 되는 순간 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마법이 마법이 아니게 되는 순간&lt;/h1&gt;
&lt;p&gt;어떤 유명한 개발자분이 &lt;code class=&quot;language-text&quot;&gt;기초가 부족하면 그 기술이 마법처럼 보인다.&lt;/code&gt; 라고 말씀하셨다. 내가 초반에 겪었던 현상이었다. 하지만 시간이 지날수록 어떤 패키지나 프레임워크의 코드를 뜯어보는 경우가 생기면서 신기했던 &lt;code class=&quot;language-text&quot;&gt;마법&lt;/code&gt;들이 &lt;code class=&quot;language-text&quot;&gt;마법이 아니게&lt;/code&gt; 되는 순간들이 찾아왔다. 결국엔 모두 &lt;code class=&quot;language-text&quot;&gt;기초를 기반으로 한 코드 덩어리&lt;/code&gt;들이라는 생각이 들었다. 아직은 많이 부족하지만 조금씩 성장해감을 느낄 수 있었다. 물론 그 코드들을 보고 한번에 이해할 수는 없어 여러번 읽어야 겨우 이해할 수 있는 상태지만 이해할 수 있는 &lt;code class=&quot;language-text&quot;&gt;근육&lt;/code&gt;을 키우고 싶다.&lt;/p&gt;
&lt;h1 id=&quot;2021년에는&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2021%EB%85%84%EC%97%90%EB%8A%94&quot; aria-label=&quot;2021년에는 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2021년에는&lt;/h1&gt;
&lt;p&gt;2021년에는 업무에 더 능숙해지고 싶고, 그만큼의 여유를 만들고 싶다. 그 여유를 가지고 생각만 하고 못해봤던 것들을 해보고 싶다. 2020년에 기술도입이 많았다. 많은만큼 아직 깊이가 쌓이지 않았다. 그 기술들과 기초지식들의 깊이를 쌓고 싶다. 그래서 &lt;code class=&quot;language-text&quot;&gt;남들에게 설명할 수 있을 때까지&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;질문을 해도 답해줄 수 있을 때까지&lt;/code&gt; 익히고 싶다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[serverless] serverless로 AWS Lambda 배포 시 memory, timeout 설정하기]]></title><description><![CDATA[이미지에서 dominant color를 추출하는 AWS Lambda 함수를 Serverless Framework로 배포하여 사용하고 있습니다. 이미지가 클 때 에러가 나는 경우가 있었는데, 너무 오래 걸려서 나는 timeout…]]></description><link>https://donghoon-song.github.io/development/2020-12-02---serverless로-AWS-Lambda-배포-시-memory,-timeout-설정하기/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-12-02---serverless로-AWS-Lambda-배포-시-memory,-timeout-설정하기/</guid><pubDate>Wed, 02 Dec 2020 22:23:00 GMT</pubDate><content:encoded>&lt;p&gt;이미지에서 dominant color를 추출하는 AWS Lambda 함수를 Serverless Framework로 배포하여 사용하고 있습니다. 이미지가 클 때 에러가 나는 경우가 있었는데, 너무 오래 걸려서 나는 timeout 이슈였습니다. 동료 개발자분이 Lambda함수의 memory와 timeout설정을 바꿔야겠다고 얘기해주셨습니다.&lt;/p&gt;
&lt;p&gt;Lambda함수를 serverless로 배포하면 &lt;code class=&quot;language-text&quot;&gt;memorySize&lt;/code&gt;의 기본값은 &lt;code class=&quot;language-text&quot;&gt;1024&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;timeout&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;초라고 합니다. 이 설정은 aws console에서 확인할 수 있는데,
Lambda -&gt; 함수 -&gt; 함수 상세 화면 -&gt; 기본 설정에서 아래와 같이 볼 수 있고 편집도 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://gblobscdn.gitbook.com/assets%2F-MFOfJZX0e3z30df_HuB%2F-MNYWQHF6BYJyVS7gSUq%2F-MNYa7_GaRVMUnjPYL88%2Fimage.png?alt=media&amp;#x26;token=40f4f1a6-06d2-4aea-ac78-90c8a127dd15&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;aws console에서 설정을 편집할 수 있지만, 새롭게 배포할 때는 serverless.yml에 명시된 설정값으로 배포가 되기 때문에 편집값이 초기화됩니다. 그래서 serverless.yml에 사용할 값을 명시해 주는 것이 좋습니다.&lt;/p&gt;
&lt;p&gt;provider 항목의 &lt;code class=&quot;language-text&quot;&gt;memorySize&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;timeout&lt;/code&gt;을 변경해주시면 쉽게 적용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://gblobscdn.gitbook.com/assets%2F-MFOfJZX0e3z30df_HuB%2F-MNYWQHF6BYJyVS7gSUq%2F-MNYamQjZ5NVijcgcJoq%2Fimage.png?alt=media&amp;#x26;token=a91d5af7-6e1b-4b7d-9c5d-074bc0ad96ee&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;참고&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/&quot;&gt;serverless.yml aws guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[Node.js] Node.js 15 변경점 번역]]></title><description><![CDATA[주요 변경점 AbortController N-API Version 7 npm 7 Throw on unhandled rejections QUIC (experimental) V8 8.6 AbortController AbortController…]]></description><link>https://donghoon-song.github.io/development/2020-11-15---Node.js-15-변경점/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-11-15---Node.js-15-변경점/</guid><pubDate>Sun, 15 Nov 2020 16:25:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;주요-변경점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A3%BC%EC%9A%94-%EB%B3%80%EA%B2%BD%EC%A0%90&quot; aria-label=&quot;주요 변경점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;주요 변경점&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;AbortController&lt;/li&gt;
&lt;li&gt;N-API Version 7&lt;/li&gt;
&lt;li&gt;npm 7&lt;/li&gt;
&lt;li&gt;Throw on unhandled rejections&lt;/li&gt;
&lt;li&gt;QUIC (experimental)&lt;/li&gt;
&lt;li&gt;V8 8.6&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;abortcontroller&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#abortcontroller&quot; aria-label=&quot;abortcontroller permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AbortController&lt;/h2&gt;
&lt;p&gt;AbortController의 구현체를 실험적으로 포함합니다. AbortController는 하나 이상의 웹 요청을 필요할 때 중단시키는 인터페이스입니다. 자세한 설명은 아래의 링크를 참고하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/AbortController&quot;&gt;AbortController&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ac &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbortController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abort&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Aborted!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;aborted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Prints True&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예제에서, ac.abort()가 호출될 때, AbortController가 abort event를 trigger합니다.&lt;/p&gt;
&lt;p&gt;AbortSignal에 달린 Eventlistener는 반드시 &lt;code class=&quot;language-text&quot;&gt;{ once: true }&lt;/code&gt; 옵션을 주거나 &lt;code class=&quot;language-text&quot;&gt;EventEmitter의 once()&lt;/code&gt; 메서드를 호출해 &lt;code class=&quot;language-text&quot;&gt;abort&lt;/code&gt; 이벤트를 한번만 핸들링하고 사라지도록 해야합니다.&lt;/p&gt;
&lt;h2 id=&quot;n-api-7&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#n-api-7&quot; aria-label=&quot;n api 7 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;N-API 7&lt;/h2&gt;
&lt;p&gt;우리는 새로운 N-API 버전을 다른 LTS Node.js 버전에도 백포트하여 사용합니다. N-API 7은 가장 최신 메이저 릴리즈 이후 새 버전이고, ArrayBuffers를 다루는 추가 메서드들을 포함합니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;백포트(backport) : 최신 버전의 소프트웨어 시스템 또는 소프트웨어 구성 요소에서 부품을 가져 와서 동일한 소프트웨어의 이전 버전으로 포팅하는 작업&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;npm-7&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#npm-7&quot; aria-label=&quot;npm 7 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;npm 7&lt;/h2&gt;
&lt;p&gt;Node.js 15는 npm 7을 사용합니다. Npm 7에는 다양한 새로운 기능들이 추가되었습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;npm workspace&lt;/li&gt;
&lt;li&gt;새로운 &lt;code class=&quot;language-text&quot;&gt;package-lock.json&lt;/code&gt; 포맷&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;yarn.lock&lt;/code&gt; 지원&lt;/li&gt;
&lt;li&gt;Peer dependency들이 기본적으로 설치됩니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.blog/2020-10-13-presenting-v7-0-0-of-the-npm-cli/&quot;&gt;Presenting v7.0.0 of the npm CLI - The GitHub Blog&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;throw-on-unhandled-rejections&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#throw-on-unhandled-rejections&quot; aria-label=&quot;throw on unhandled rejections permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Throw on unhandled rejections&lt;/h2&gt;
&lt;p&gt;Node.js 15에서는 &lt;code class=&quot;language-text&quot;&gt;unhandledRejection&lt;/code&gt;에 대한 기본 mode가 &lt;code class=&quot;language-text&quot;&gt;warn&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;로 바뀝니다. &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; mode에서는, &lt;code class=&quot;language-text&quot;&gt;unhandledRejection&lt;/code&gt; hook이 설정되어 있지 않으면, &lt;code class=&quot;language-text&quot;&gt;unhandledRejection&lt;/code&gt;는 uncaught exception으로 잡힙니다. &lt;code class=&quot;language-text&quot;&gt;unhandledRejection&lt;/code&gt; hook을 설정한 사용자들은 그대로 사용하면 됩니다. &lt;code class=&quot;language-text&quot;&gt;-unhandled-rejections=mode&lt;/code&gt; 라는 process flag를 사용하여 mode를 변경하는 것이 여전히 가능합니다.&lt;/p&gt;
&lt;p&gt;Node.js는 &lt;code class=&quot;language-text&quot;&gt;UnhandledPromiseRejectionWarning&lt;/code&gt;는 많은 버전에서 emit해왔는데, &lt;a href=&quot;https://ko.surveymonkey.com/results/SM-82X6PX3B7/&quot;&gt;Node.js User Insights: Unhandled Promise Rejections&lt;/a&gt; 설문조사와, &lt;a href=&quot;https://github.com/nodejs/TSC/issues/916&quot;&gt;Node.js Technical Steering Committee vote&lt;/a&gt; 의 결과를 바탕으로 mode를 &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt;로 변경하는 결정을 내렸습니다.&lt;/p&gt;
&lt;h2 id=&quot;quicexperimental&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#quicexperimental&quot; aria-label=&quot;quicexperimental permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;QUIC(experimental)&lt;/h2&gt;
&lt;p&gt;QUIC는 새로운 UDP 기반 transport protocol이며, HTTP/3의 기반이 됩니다. QUIC는 TLS 3.1, 흐름 제어, 오류 수정, 연결 마이그레이션 및 멀티플렉싱을 통한 내장된 보안 기능을 제공합니다.&lt;/p&gt;
&lt;p&gt;Node.js 15는 QUIC을 실험적으로 제공하고 있으며, &lt;code class=&quot;language-text&quot;&gt;--experimental-quic&lt;/code&gt; 라는 configuration flag를 통해 Node.js를 컴파일하면 사용할 수 있습니다. Node.js QUIC 구현체는 core &lt;code class=&quot;language-text&quot;&gt;net&lt;/code&gt; 모듈에서 expose 됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createQuicSocket &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘net’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;QUIC에 대한 더 자세한 설명은 &lt;a href=&quot;https://nodejs.org/dist/latest-v15.x/docs/api/quic.html&quot;&gt;Node.js 문서&lt;/a&gt;를 참고하시면 됩니다.&lt;/p&gt;
&lt;h2 id=&quot;v8-86&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#v8-86&quot; aria-label=&quot;v8 86 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;V8 8.6&lt;/h2&gt;
&lt;p&gt;V8 자바스크립트 엔진이 V8 8.6으로 업데이트되었습니다. (V8 8.4가 Node.js 14에서 사용가능한 가장 최신버전이었습니다.)  성능 개선과 함께 V8 업데이트는 아래의 language feature를 포함합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Promise.any()&lt;/code&gt; — &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any&quot;&gt;MDN&lt;/a&gt; (from V8 8.5)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;AggregateError&lt;/code&gt; — &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError&quot;&gt;MDN&lt;/a&gt; (from V8 8.5)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;String.prototype.replaceAll()&lt;/code&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll&quot;&gt;MDN&lt;/a&gt; (from V8 8.5)&lt;/li&gt;
&lt;li&gt;Logical assignment operators &lt;code class=&quot;language-text&quot;&gt;&amp;amp;&amp;amp;=, ||=,&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;??=&lt;/code&gt; — &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators&quot;&gt;MDN&lt;/a&gt; (from V8 8.5)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.medium.com/node-js-v15-0-0-is-here-deb00750f278&quot;&gt;출처&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Storybook] Vue Storybook addon-docs 사용해서 docs 만들기]]></title><description><![CDATA[storybookjs/design-system repository Storybook example 위의 멋진 Storybook example을 보고, 멋진 docs page를 제 프로젝트에도 추가하고 싶었습니다. @storybook/addon-docs…]]></description><link>https://donghoon-song.github.io/development/2020-10-01---Vue-Storybook-addon-docs-사용해서-docs-만들기/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-10-01---Vue-Storybook-addon-docs-사용해서-docs-만들기/</guid><pubDate>Thu, 01 Oct 2020 23:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/design-system&quot;&gt;storybookjs/design-system repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://5ccbc373887ca40020446347-vehbzpmjqt.chromatic.com/?path=/docs/design-system-button--basic&quot;&gt;Storybook example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;위의 멋진 Storybook example을 보고, 멋진 docs page를 제 프로젝트에도 추가하고 싶었습니다.&lt;/p&gt;
&lt;h2 id=&quot;storybookaddon-docs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#storybookaddon-docs&quot; aria-label=&quot;storybookaddon docs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;@storybook/addon-docs&lt;/h2&gt;
&lt;p&gt;addon-docs는 스토리북에서 docs를 만드는 것을 도와줍니다. docs를 만드는데에는 크게 두가지 방식이 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DocsPage
&lt;ul&gt;
&lt;li&gt;스토리의 정보를 기반으로 자동으로 docs를 만듭니다.&lt;/li&gt;
&lt;li&gt;stories, text descriptions, docgen comments, props tables, code examples 등을 참고하여 페이지로 만들어줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MDX
&lt;ul&gt;
&lt;li&gt;markdown 문법으로 docs를 작성합니다.&lt;/li&gt;
&lt;li&gt;자동은 아니지만, 작성자 마음대로 커스터마이징이 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/@storybook/addon-docs#be-sure-to-check-framework-specific-installation-needs&quot;&gt;@storybook/addon-docs installation&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; @storybook/addon-docs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음의 peer dependency를 가집니다. vue를 쓰지만 react를 설치해야 하는…&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; react react-is babel-loader&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;설치를 다 하고 난 후에 &lt;code class=&quot;language-text&quot;&gt;main.js&lt;/code&gt;에 다음을 추가해줍니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .storybook/main.js&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;stories&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;../src/**/*.stories.@(js|mdx)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;addons&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@storybook/addon-docs&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 나서 &lt;code class=&quot;language-text&quot;&gt;preview.js&lt;/code&gt;에 다음 코드를 추가하면, 모든 story에 대해 자동으로 DocsPage가 생성됩니다. 아래 코드를 지워도 기본적으로 Docs가 자동으로 생성됩니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .storybook/preview.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; addParameters &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@storybook/vue&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DocsPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DocsContainer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@storybook/addon-docs/blocks&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;token function&quot;&gt;addParameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;docs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DocsContainer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DocsPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831255-7827de80-0447-11eb-894f-6da38fadb347.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831266-7cec9280-0447-11eb-8390-48328c68df64.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;스토리를 기반으로, Docs 페이지가 생성되었습니다. 스토리에 정보가 별로 없어서, Docs에 들어가는 내용도 별로 없습니다. 저는 MDX를 이용해 저만의 docs를 작성하고 싶었습니다.&lt;/p&gt;
&lt;h2 id=&quot;mdx-docs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mdx-docs&quot; aria-label=&quot;mdx docs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;MDX Docs&lt;/h2&gt;
&lt;p&gt;MDX로 Docs를 만든 것을 적용하려면, 아래와 같이 코드를 작성하여, Docs 자동생성 기능을 꺼줘야 합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .storybook/preview.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; addParameters &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@storybook/vue&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;addParameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;docs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.stories.mdx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Meta&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Story&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Props &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@storybook/addon-docs/blocks&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Button &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/src/Components/Button/Button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Meta&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;Button&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Button&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

# Button

&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; 컴포넌트의 문서입니다&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Story&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;docs&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;100px&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Button &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;Button&gt;Button&amp;lt;/Button&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Story&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리가 새로 만든 docs로 대체되었습니다!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831284-80801980-0447-11eb-9c97-e210a73b3765.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;storybookaddon-controls&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#storybookaddon-controls&quot; aria-label=&quot;storybookaddon controls permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;@storybook/addon-controls&lt;/h2&gt;
&lt;p&gt;addon-controls는 사용자가 스토리북에서 직접 컴포넌트의 arguments를 바꿔볼 수 있도록 도와줍니다. 저는 단순 props table이 아니라 이 기능을 원했기 때문에 추가해주었습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; @storybook/addon-controls&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ./storybook/main.js&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;addons&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@storybook/addon-controls&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id=&quot;doc-blocks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#doc-blocks&quot; aria-label=&quot;doc blocks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Doc Blocks&lt;/h1&gt;
&lt;p&gt;Storybook의 document page를 작성할 때 쓰입니다. 여기서 &lt;code class=&quot;language-text&quot;&gt;ArgsTable&lt;/code&gt;을 사용해볼 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://storybook.js.org/docs/react/writing-docs/doc-blocks&quot;&gt;Doc Blocks&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;argstable&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#argstable&quot; aria-label=&quot;argstable permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ArgsTable&lt;/h2&gt;
&lt;p&gt;Storybook docs는 컴포넌트의 args table을 자동으로 만듭니다. controls와 연동하여 사용자가 컴포넌트의 args를 직접 수정해볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;Button Component의 ArgsTable을 만들어봅시다. &lt;code class=&quot;language-text&quot;&gt;addon-controls&lt;/code&gt; 없이 만들면 아래와 같이 나옵니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.stories.mdx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ArgsTable &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@storybook/addon-docs/blocks&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Button &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/src/Components/Button/Button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Meta&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;Button&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Button&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgsTable&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Button&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831298-84ac3700-0447-11eb-8bce-58260942c578.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;addon-controls&lt;/code&gt; 를 설치하고 만들면 아래와 같이 나옵니다. &lt;code class=&quot;language-text&quot;&gt;Control&lt;/code&gt; 열이 더 생겨서, 사용자가 직접 수정할 수 있게끔 도와줍니다. 이것은 Button 컴포넌트의 props를 읽어서 자동생성되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831311-883fbe00-0447-11eb-8bfe-c98a89ed14bb.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.vue&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;validator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;small&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;large&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;xlarge&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;primary&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;validator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;primary&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;gray&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;fill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;validator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;outlined&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;full&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Boolean&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// disabled&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Boolean&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;size, color, type의 경우, String type이긴 하지만 사용할 수 있는 값들의 종류가 미리 정해져 있습니다. 그러면 굳이 text로 안바꾸고, select로 바꿀 수 있다면 스토리북을 사용할 때 편할 것입니다. 이걸 override하려면 따로 설정을 해줘야 합니다.&lt;/p&gt;
&lt;p&gt;Meta에 argTypes를 작성하여, Template에 넘겨줍니다. 아래 ArgTypes 문서를 보면 어떻게 작성해야 할지 감이 오고, 이것저것 해보다보면 원하는 형태의 문서를 작성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://storybook.js.org/docs/react/api/argtypes&quot;&gt;ArgTypes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831329-8d047200-0447-11eb-9df1-a7e4cdf70eee.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;controls-작성법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#controls-%EC%9E%91%EC%84%B1%EB%B2%95&quot; aria-label=&quot;controls 작성법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;controls 작성법&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831343-92fa5300-0447-11eb-8241-ef6c945005c3.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;두 문서를 바탕으로 작성한 문서입니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.stories.mdx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ArgsTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Meta&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Story&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Props &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@storybook/addon-docs/blocks&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Button &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@/src/Components/Button/Button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Meta title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Button&apos;&lt;/span&gt; component&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Button&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; argTypes&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;버튼에 들어갈 텍스트&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;defaultValue&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;답변 추가하기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token literal-property property&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          &lt;span class=&quot;token literal-property property&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;버튼의 크기&amp;lt;br/&gt;`String`&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token literal-property property&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          &lt;span class=&quot;token literal-property property&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;목록&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          &lt;span class=&quot;token literal-property property&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&quot;small&quot; &quot;medium&quot; &quot;large&quot; &quot;xlarge&quot;&apos;&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;select&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;small&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;large&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;xlarge&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;버튼의 색상 타입&amp;lt;br/&gt;`String`&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;token literal-property property&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;목록&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
        &lt;span class=&quot;token literal-property property&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&quot;primary&quot; &quot;success&quot; &quot;gray&quot;&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;select&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;primary&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;gray&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;버튼의 타입&amp;lt;br/&gt;`String`&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;token literal-property property&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;목록&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
        &lt;span class=&quot;token literal-property property&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&quot;fill&quot; &quot;outlined&quot; &quot;text&quot;&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;select&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;outlined&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;full&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;버튼의 너비가 부모컴포넌트의 100%를 차지할지&amp;lt;br/&gt;`Boolean`&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;token literal-property property&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;버튼의 disabled 상태&amp;lt;br/&gt;`Boolean`&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;token literal-property property&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Template&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argTypes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argTypes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Button &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;Button :size=&quot;size&quot; :color=&quot;color&quot; :type=&quot;type&quot; :full=&quot;full&quot; :disabled=&quot;disabled&quot;&gt;{{label}}&amp;lt;/Button&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

# Button

&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; 컴포넌트의 문서입니다&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Story&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;docs&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;100px&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
	&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Story&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgsTable&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;story&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;docs&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;해당 작업까지 완료되었다면 제가 원했던 원하는 docs를 만드실 수 있습니다. 아래 &lt;code class=&quot;language-text&quot;&gt;ArgsTable&lt;/code&gt;에서 arguments를 마음대로 수정하여 컴포넌트의 상태를 변경할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/94831357-98579d80-0447-11eb-8279-b94696386677.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Storybook] Storybook visual test with Chromatic]]></title><description><![CDATA[하라는 컴포넌트화는 안하고 테스팅만 찾아보는 당신은 대체… Storybook Tutorial에서 제시하는 테스트는 크게 세가지가 있다. Visual tests : 직접 보고 의도대로 모양이 나왔는지 체크하는 방법 Snapshot tests…]]></description><link>https://donghoon-song.github.io/development/2020-09-12---Storybook-visual-test-with-Chromatic/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-09-12---Storybook-visual-test-with-Chromatic/</guid><pubDate>Sat, 12 Sep 2020 00:11:00 GMT</pubDate><content:encoded>&lt;h3 id=&quot;하라는-컴포넌트화는-안하고-테스팅만-찾아보는-당신은-대체&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%98%EB%9D%BC%EB%8A%94-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%ED%99%94%EB%8A%94-%EC%95%88%ED%95%98%EA%B3%A0-%ED%85%8C%EC%8A%A4%ED%8C%85%EB%A7%8C-%EC%B0%BE%EC%95%84%EB%B3%B4%EB%8A%94-%EB%8B%B9%EC%8B%A0%EC%9D%80-%EB%8C%80%EC%B2%B4&quot; aria-label=&quot;하라는 컴포넌트화는 안하고 테스팅만 찾아보는 당신은 대체 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;하라는 컴포넌트화는 안하고 테스팅만 찾아보는 당신은 대체…&lt;/h3&gt;
&lt;p&gt;Storybook Tutorial에서 제시하는 테스트는 크게 세가지가 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Visual tests : 직접 보고 의도대로 모양이 나왔는지 체크하는 방법&lt;/li&gt;
&lt;li&gt;Snapshot tests : Storybook이 렌더된 markup의 snapshot을 찍어서 비교한다.&lt;/li&gt;
&lt;li&gt;Unit tests : Jest를 사용해 같은 인풋에 대해 같은 아웃풋이 나오는지 체크한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;하지만 앞서 언급했던 방법들은 UI bug를 감지하기 힘들다. UI bug는 경우에 따라 굉장히 미미한 차이일 수도 있기 때문에, Visual tests는 너무 수동이고, Snapshot tests는 UI에 적용했을 때 너무 많은 false positive(실제론 false인데 positive라고 나오는)를 발생시키며, pixel-level unit tests는 의미가 없다. 그래서 Storybook은 &lt;code class=&quot;language-text&quot;&gt;visual regression tests&lt;/code&gt;를 제안한다.&lt;/p&gt;
&lt;h2 id=&quot;visual-regression-testing-for-storybook&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#visual-regression-testing-for-storybook&quot; aria-label=&quot;visual regression testing for storybook permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Visual regression testing for Storybook&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Visual regression tests&lt;/code&gt;는 렌더링된 모양의 차이를 잡아내도록 디자인되었다. 모든 스토리의 스크린샷을 찍어서, 커밋별 변화점을 잡아낸다. 많은 visual regression testing 도구가 있지만, Storybook에선 클라우드에서 테스트를 할 수 있는 &lt;code class=&quot;language-text&quot;&gt;Chromatic&lt;/code&gt;을 제안한다!&lt;/p&gt;
&lt;h2 id=&quot;setup-visual-regression-testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setup-visual-regression-testing&quot; aria-label=&quot;setup visual regression testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup visual regression testing&lt;/h2&gt;
&lt;h3 id=&quot;bring-git-up-to-date&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bring-git-up-to-date&quot; aria-label=&quot;bring git up to date permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Bring git up to date&lt;/h3&gt;
&lt;p&gt;먼저 storybook project의 git 저장소가 있어야 합니다! 기존에 만들었으면 상관없겠죠?&lt;/p&gt;
&lt;h3 id=&quot;get-chromatic&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#get-chromatic&quot; aria-label=&quot;get chromatic permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Get Chromatic&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;chromatic을 설치해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; chromatic&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;chromatic에서 git으로 로그인을 하고, repository를 추가합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.chromatic.com/start?invite-token=dnjk1zik&amp;#x26;utm_source=https://learnstorybook.com&amp;#x26;utm_medium=tutorial&amp;#x26;utm_campaign=learnstorybook&quot;&gt;Chromatic&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;그러면 &lt;code class=&quot;language-text&quot;&gt;project-token&lt;/code&gt;을 받을 수 있고, 해당 명령어를 실행해 deploy합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx chromatic --project-token&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;project-token&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;details&gt;
&lt;summary&gt;package.json에 build-storybook이 없다고 한다면?&lt;/summary&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;&quot;build-storybook&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;build-storybook&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;그러고 나서 chromatic에 들어가면 정상적으로 배포된 것을 볼 수 있습니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92944506-03d4cd80-f48f-11ea-8b6b-9a6ea1befa5b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;진짜 chromatic의 기능은 여기부터 시작입니다. 아무 변화나 주고 다시 배포를 해봅시다. 저는 버튼의 background-color를 파랑에서 빨강으로 바꿔봤습니다.
그럼 다음처럼 변경점이 감지되었음을 보여줍니다. Review changes 버튼을 클릭해서 들어가봅시다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92947467-ff121880-f492-11ea-9062-499e544c7400.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;다음 처럼 UI 변경점을 보여줍니다. 바뀐 지점이 연두색으로 덮혀있습니다. DOM에서도 바뀐게 감지되었죠.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92947491-0afdda80-f493-11ea-8b97-186ef3ddd49a.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;이렇게 배포할 때마다 UI의 변경점을 감지하고, 둘 중에 하나를 선택해서 적용할 수 있습니다. 내가 작업한 결과물이 기존것과 잘 매치되는지, 잘 변경되는지 등을 손쉽게 테스트할 수 있어 정말 유용한 서비스 같습니다.&lt;/p&gt;
&lt;h2 id=&quot;manage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#manage&quot; aria-label=&quot;manage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Manage&lt;/h2&gt;
&lt;p&gt;PR을 보냈을 때에도 똑같이 테스트를 해 볼 수 있네요! 정말 유용합니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92945175-e0f6e900-f48f-11ea-998c-0c75244dc55a.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;브라우저별 테스트를 제공합니다. 제일 말썽인 IE가 포함되어 있네요. IE를 누르면 다음 가격 정책이 뜹니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92944752-5910df00-f48f-11ea-966b-49d3bec1e4b4.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;그렇다면 가격 정책에 대해서 알아봅시다!
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92944786-65953780-f48f-11ea-81bb-6642f8f3a1eb.png&quot; alt=&quot;image&quot;&gt;
그만 알아봅시다 ㅠㅠ 너무 비싸네요. 그런데 Free인 5000 snapshots도 다 못 채울 것 같습니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[OpenSource] 초보 컨트리뷰터의 Nuxt docs PR 도전기]]></title><description><![CDATA[Nuxt docs가 크롬에서 깨지는 현상 chrome에서 https://nuxtjs.org/ 를 열면 다음 이미지처럼 보이는 현상이 있었습니다. 개발자 도구로 살펴보니, 라는 클래스에  style…]]></description><link>https://donghoon-song.github.io/development/2020-09-09---초보-컨트리뷰터의-Nuxt-docs-PR-도전기/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-09-09---초보-컨트리뷰터의-Nuxt-docs-PR-도전기/</guid><pubDate>Wed, 09 Sep 2020 22:26:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;nuxt-docs가-크롬에서-깨지는-현상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nuxt-docs%EA%B0%80-%ED%81%AC%EB%A1%AC%EC%97%90%EC%84%9C-%EA%B9%A8%EC%A7%80%EB%8A%94-%ED%98%84%EC%83%81&quot; aria-label=&quot;nuxt docs가 크롬에서 깨지는 현상 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nuxt docs가 크롬에서 깨지는 현상&lt;/h1&gt;
&lt;h3 id=&quot;chrome에서-httpsnuxtjsorg-를-열면-다음-이미지처럼-보이는-현상이-있었습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chrome%EC%97%90%EC%84%9C-httpsnuxtjsorg-%EB%A5%BC-%EC%97%B4%EB%A9%B4-%EB%8B%A4%EC%9D%8C-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%B2%98%EB%9F%BC-%EB%B3%B4%EC%9D%B4%EB%8A%94-%ED%98%84%EC%83%81%EC%9D%B4-%EC%9E%88%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;chrome에서 httpsnuxtjsorg 를 열면 다음 이미지처럼 보이는 현상이 있었습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;chrome에서 &lt;a href=&quot;https://nuxtjs.org/&quot;&gt;https://nuxtjs.org/&lt;/a&gt; 를 열면 다음 이미지처럼 보이는 현상이 있었습니다.&lt;/h3&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/91999436-561f3b80-ed77-11ea-922a-47ed15fb38ad.png&quot;&gt;
&lt;p&gt;개발자 도구로 살펴보니, &lt;code class=&quot;language-text&quot;&gt;svg&lt;/code&gt;라는 클래스에 &lt;code class=&quot;language-text&quot;&gt;width: 20px&lt;/code&gt; style이 전역으로 적용되고 있었습니다.&lt;/p&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/91999543-7b13ae80-ed77-11ea-9895-b55a5a93e11a.png&quot;&gt;
&lt;p&gt;오픈소스 컨트리뷰톤에서 활동중이던 차에 직접 PR을 올려볼까? 하는 생각이 스쳤습니다. 그래서 다짜고짜 nuxtjs.org repo를 fork했습니다.
dev 모드에선 해당 이슈가 없었는데 prod 모드에서 이슈가 재현되었고, &lt;code class=&quot;language-text&quot;&gt;svg class&lt;/code&gt;가 어디에서 오는건지 찾아봤습니다.
찾아보니, &lt;code class=&quot;language-text&quot;&gt;AppModal.vue&lt;/code&gt;이라는 컴포넌트에 있었습니다. 여기서 주목할만한 점은 &lt;code class=&quot;language-text&quot;&gt;style&lt;/code&gt;이 &lt;strong&gt;전역으로 적용&lt;/strong&gt;되고 있었다는 점입니다.
정확한 빌드과정은 모르겠지만, 스타일이 전역으로 적용되면서 &lt;code class=&quot;language-text&quot;&gt;html&lt;/code&gt; 태그안에 &lt;code class=&quot;language-text&quot;&gt;class&lt;/code&gt;로 들어간 것 같았습니다.
그래서 &lt;code class=&quot;language-text&quot;&gt;svg class&lt;/code&gt;가 다른데에서도 쓰이나 전체검색을 해봤는데, &lt;code class=&quot;language-text&quot;&gt;AppModal.vue&lt;/code&gt;에서 밖에 쓰이지 않았습니다. &lt;em&gt;&lt;strong&gt;(여기서 저는 마음속으로 소리를 질렀습니다.)&lt;/strong&gt;&lt;/em&gt;
&lt;code class=&quot;language-text&quot;&gt;style&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;scoped&lt;/code&gt; 속성을 주고 빌드를 해보니 &lt;code class=&quot;language-text&quot;&gt;html&lt;/code&gt; 태그에서 &lt;code class=&quot;language-text&quot;&gt;svg class&lt;/code&gt;가 빠지는 것을 확인할 수 있었습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vue&quot;&gt;&lt;pre class=&quot;language-vue&quot;&gt;&lt;code class=&quot;language-vue&quot;&gt;./components/global/bases/AppModal.vue

...
&amp;lt;style&amp;gt;
.svg {
  width: 20px;
  color: black;
}
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇게 PR을 올릴까 하다가 혹시 몰라서 디렉토리 안의 다른 파일들도 살펴보았는데, &lt;code class=&quot;language-text&quot;&gt;BaseAlert.vue&lt;/code&gt; 컴포넌트도 똑같이 &lt;code class=&quot;language-text&quot;&gt;scoped&lt;/code&gt; 적용이 되어있지 않았습니다.
이것을 바탕으로 다음 PR을 작성했습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nuxt/nuxtjs.org/pull/639&quot;&gt;https://github.com/nuxt/nuxtjs.org/pull/639&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PR template이 따로 없어서, 어떤 현상인지, 어떻게 고쳤는지, 제 생각을 작성했습니다.&lt;br&gt;
maintainer가 이슈를 재현할 순 없지만, 위의 스타일들이 scoped되어야 하는 것은 동의한다고 merge 해주셨습니다.&lt;/p&gt;
&lt;h3 id=&quot;vue에서-style에-scoped속성을-적절히-사용하는-것은-vue의-기본-중-기본입니다-이런-기본-개념으로-이슈를-해결할-수-있어서-뜻깊었고-기여가-항상-거창해야-하는-것은-아니라는-것을-느꼈습니다-또한-제가-자주-사용하는-프로젝트에-기여할-수-있어서-좋았습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#vue%EC%97%90%EC%84%9C-style%EC%97%90-scoped%EC%86%8D%EC%84%B1%EC%9D%84-%EC%A0%81%EC%A0%88%ED%9E%88-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%80-vue%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%A4%91-%EA%B8%B0%EB%B3%B8%EC%9E%85%EB%8B%88%EB%8B%A4-%EC%9D%B4%EB%9F%B0-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90%EC%9C%BC%EB%A1%9C-%EC%9D%B4%EC%8A%88%EB%A5%BC-%ED%95%B4%EA%B2%B0%ED%95%A0-%EC%88%98-%EC%9E%88%EC%96%B4%EC%84%9C-%EB%9C%BB%EA%B9%8A%EC%97%88%EA%B3%A0-%EA%B8%B0%EC%97%AC%EA%B0%80-%ED%95%AD%EC%83%81-%EA%B1%B0%EC%B0%BD%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%80-%EC%95%84%EB%8B%88%EB%9D%BC%EB%8A%94-%EA%B2%83%EC%9D%84-%EB%8A%90%EA%BC%88%EC%8A%B5%EB%8B%88%EB%8B%A4-%EB%98%90%ED%95%9C-%EC%A0%9C%EA%B0%80-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EA%B8%B0%EC%97%AC%ED%95%A0-%EC%88%98-%EC%9E%88%EC%96%B4%EC%84%9C-%EC%A2%8B%EC%95%98%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;vue에서 style에 scoped속성을 적절히 사용하는 것은 vue의 기본 중 기본입니다 이런 기본 개념으로 이슈를 해결할 수 있어서 뜻깊었고 기여가 항상 거창해야 하는 것은 아니라는 것을 느꼈습니다 또한 제가 자주 사용하는 프로젝트에 기여할 수 있어서 좋았습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Vue에서 style에 scoped속성을 적절히 사용하는 것은 Vue의 기본 중 기본입니다. 이런 기본 개념으로 이슈를 해결할 수 있어서 뜻깊었고 기여가 항상 거창해야 하는 것은 아니라는 것을 느꼈습니다. 또한 제가 자주 사용하는 프로젝트에 기여할 수 있어서 좋았습니다.&lt;/h3&gt;</content:encoded></item><item><title><![CDATA[[OpenSource] 초보 컨트리뷰터의 Mocha issue 해결 도전기]]></title><description><![CDATA[저는 현재 오픈소스 컨트리뷰톤 Mocha팀에서 멘티로 활동하고 있습니다. Mocha의 #4433 이슈를 해결하면서 배운 점들을 적어봤습니다. 최대한 raw…]]></description><link>https://donghoon-song.github.io/development/2020-09-06---초보-컨트리뷰터의-Mocha-issue-해결-도전기/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-09-06---초보-컨트리뷰터의-Mocha-issue-해결-도전기/</guid><pubDate>Sun, 06 Sep 2020 18:19:00 GMT</pubDate><content:encoded>&lt;p&gt;저는 현재 오픈소스 컨트리뷰톤 Mocha팀에서 멘티로 활동하고 있습니다. Mocha의 #4433 이슈를 해결하면서 배운 점들을 적어봤습니다. 최대한 raw하게, 혼잣말 하듯이 의식의 흐름대로 작성해보았습니다. 양해부탁드립니다 :) 저처럼 오픈소스에 대한 경험이 많이 없고, 두려운 초보자들에게 큰 도움이 되었으면 합니다.&lt;/p&gt;
&lt;h1 id=&quot;mocha-does-not-pass-prof-parameter-to-node-and-thus-does-not-allow-for-profiling-4433&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mocha-does-not-pass-prof-parameter-to-node-and-thus-does-not-allow-for-profiling-4433&quot; aria-label=&quot;mocha does not pass prof parameter to node and thus does not allow for profiling 4433 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Mocha does not pass “—prof” parameter to Node and thus does not allow for profiling (#4433)&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mochajs/mocha/issues/4433&quot;&gt;Mocha does not pass “—prof” parameter to Node and thus does not allow for profiling · Issue #4433 · mochajs/mocha&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;mocha에서 Node의 &lt;code class=&quot;language-text&quot;&gt;—prof&lt;/code&gt; argument를 넘겨줬는데 Node가 처리하지 못하는 이슈이다.&lt;/p&gt;
&lt;p&gt;멘토님께서 &lt;code class=&quot;language-text&quot;&gt;lib/cli/node-flags.js&lt;/code&gt;를 참고하라고 해주셨다. 링크를 열어보면, node에서 기본적으로 제공하는 flag의 목록이 보인다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org/dist/latest-v12.x/docs/api/process.html#process_process_allowednodeenvironmentflags&quot;&gt;Node.js v14.9.0 Documentation&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;lib&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;cli&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;node&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;flags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js

&lt;span class=&quot;token string&quot;&gt;&apos;use strict&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Some settings and code related to Mocha&apos;s handling of Node.js/V8 flags.
 * @private
 * @module
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nodeFlags &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;allowedNodeEnvironmentFlags&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isMochaFlag&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./run-option-metadata&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;코드를 보면 &lt;code class=&quot;language-text&quot;&gt;process.allowedNodeEnvironmentFlags&lt;/code&gt;안에 node의 flag들이 들어있다. 그리고 &lt;code class=&quot;language-text&quot;&gt;./lib/cli/run-option-metadata&lt;/code&gt;안에 mocha flag들이 들어있다. &lt;code class=&quot;language-text&quot;&gt;—-prof&lt;/code&gt;는 이 두 곳에 속해있지 않았다.&lt;/p&gt;
&lt;p&gt;밑으로 내려가보면 다음 코드를 볼 수 있다. &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;v8&lt;/code&gt; 플래그를 여기서 따로 처리하는가보다. 이 목록에 &lt;code class=&quot;language-text&quot;&gt;—-prof&lt;/code&gt;가 빠져 있으니 추가하면 되지 않을까? 라는 생각이 먼저 들었다. 내가 해야하는 일은 &lt;code class=&quot;language-text&quot;&gt;--prof&lt;/code&gt; 플래그를 Node가 처리하도록 잘 넘겨주는 일이기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;—-prof&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;node --v8-options&lt;/code&gt;을 실행하면 나오는 옵션이기 때문이다. &lt;code class=&quot;language-text&quot;&gt;—es-staging&lt;/code&gt;도 여기서 찾을 수 있었다.  command 창에서 보기 힘들면, 다음 글에서 찾아보면 쉽다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://flaviocopes.com/node-runtime-v8-options/&quot;&gt;The Node.js Runtime v8 options list&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;먼저, &lt;code class=&quot;language-text&quot;&gt;isNodeFlag&lt;/code&gt;가 어디서 쓰이는지 찾아보았다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;lib&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;cli&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;node&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;flags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js

&lt;span class=&quot;token comment&quot;&gt;/**
 * Mocha has historical support for various `node` and V8 flags which might not
 * appear in `process.allowedNodeEnvironmentFlags`.
 * These include:
 *   - `--preserve-symlinks`
 *   - `--harmony-*`
 *   - `--gc-global`
 *   - `--trace-*`
 *   - `--es-staging`
 *   - `--use-strict`
 *   - `--v8-*` (but *not* `--v8-options`)
 * @summary Whether or not to pass a flag along to the `node` executable.
 * @param {string} flag - Flag to test
 * @param {boolean} [bareword=true] - If `false`, we expect `flag` to have one or two leading dashes.
 * @returns {boolean} If the flag is considered a &quot;Node&quot; flag.
 * @private
 */&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;isNodeFlag&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bareword &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;bareword&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// check if the flag begins with dashes; if not, not a node flag.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^--?&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// strip the leading dashes to match against subsequent checks&lt;/span&gt;
    flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^--?&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// check actual node flags from `process.allowedNodeEnvironmentFlags`,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// then historical support for various V8 and non-`NODE_OPTIONS` flags&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// and also any V8 flags with `--v8-` prefix&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isMochaFlag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; nodeFlags &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; nodeFlags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    debugFlags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;(?:preserve-symlinks(?:-main)?|harmony(?:[_-]|$)|(?:trace[_-].+$)|gc(?:[_-]global)?$|es[_-]staging$|use[_-]strict$|prof$|v8[_-](?!options).+?$)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      flag
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음 파일에서 &lt;code class=&quot;language-text&quot;&gt;isNodeFlag&lt;/code&gt;를 찾을 수 있었고, &lt;code class=&quot;language-text&quot;&gt;isNodeFlag&lt;/code&gt;가 true이면 &lt;code class=&quot;language-text&quot;&gt;nodeArgs&lt;/code&gt;에 붙여주는 형식이었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;lib&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;cli&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js

&lt;span class=&quot;token comment&quot;&gt;/**
 * Wrapper around `yargs-parser` which applies our settings
 * @param {string|string[]} args - Arguments to parse
 * @param {Object} defaultValues - Default values of mocharc.json
 * @param  {...Object} configObjects - `configObjects` for yargs-parser
 * @private
 * @ignore
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;parse&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;args &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; defaultValues &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;configObjects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// save node-specific args for special handling.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 1. when these args have a &quot;=&quot; they should be considered to have values&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 2. if they don&apos;t, they just boolean flags&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 3. to avoid explicitly defining the set of them, we tell yargs-parser they&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//    are ALL boolean flags.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 4. we can then reapply the values after yargs-parser is done.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nodeArgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; args &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pair &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;=&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pair&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isNodeFlag : &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isNodeFlag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isNodeFlag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^--?&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; arg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;=&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; acc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pair&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; acc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; acc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; yargsParser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;detailed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    configuration&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    configObjects&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; defaultValues&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;coerce&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; coerceOpts&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;narg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; nargOpts&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; aliases&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; types&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; types&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; types&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; types&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boolean&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodeArgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; pair&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ansi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// reapply &quot;=&quot; arg values from above&lt;/span&gt;
  nodeArgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아무 테스트 파일이나 실행시켜서, &lt;code class=&quot;language-text&quot;&gt;—-es-staging&lt;/code&gt; 옵션을 줄 때와 &lt;code class=&quot;language-text&quot;&gt;—-prof&lt;/code&gt; 옵션을 줄 때 결과가 똑같으면 될 것이라고 생각했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;./bin/mocha ./test/only/bdd.spec.js --es-staging

console.log&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isNodeFlag : &apos;&lt;/span&gt;, isNodeFlag&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag, &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;es-staging&apos;&lt;/span&gt;, &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 목록에 &lt;code class=&quot;language-text&quot;&gt;—-prof&lt;/code&gt;가 빠져있으니 추가해준다. &lt;code class=&quot;language-text&quot;&gt;—-prof&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;mochaFlag&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;nodeFlag&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;debugFlag&lt;/code&gt;가 아니므로 &lt;code class=&quot;language-text&quot;&gt;네번째 or문&lt;/code&gt;에서 처리된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;lib&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;cli&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;node&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;flags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js

&lt;span class=&quot;token comment&quot;&gt;/**
 * Mocha has historical support for various `node` and V8 flags which might not
 * appear in `process.allowedNodeEnvironmentFlags`.
 * These include:
 *   - `--preserve-symlinks`
 *   - `--harmony-*`
 *   - `--gc-global`
 *   - `--trace-*`
 *   - `--es-staging`
 *   - `--use-strict`
 *   - &apos;--prof&apos;
 *   - `--v8-*` (but *not* `--v8-options`)
 * @summary Whether or not to pass a flag along to the `node` executable.
 * @param {string} flag - Flag to test
 * @param {boolean} [bareword=true] - If `false`, we expect `flag` to have one or two leading dashes.
 * @returns {boolean} If the flag is considered a &quot;Node&quot; flag.
 * @private
 */&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;isNodeFlag&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bareword &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;bareword&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// check if the flag begins with dashes; if not, not a node flag.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^--?&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// strip the leading dashes to match against subsequent checks&lt;/span&gt;
    flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^--?&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// check actual node flags from `process.allowedNodeEnvironmentFlags`,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// then historical support for various V8 and non-`NODE_OPTIONS` flags&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// and also any V8 flags with `--v8-` prefix&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isMochaFlag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; nodeFlags &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; nodeFlags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    debugFlags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;
    &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;(?:preserve-symlinks(?:-main)?|harmony(?:[_-]|$)|(?:trace[_-].+$)|gc(?:[_-]global)?$|es[_-]staging$|use[_-]strict$|prof$|v8[_-](?!options).+?$)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      flag
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;실행결과 똑같은 결과가 나왔다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;./bin/mocha ./test/only/bdd.spec.js &lt;span class=&quot;token parameter variable&quot;&gt;--prof&lt;/span&gt;

console.log&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isNodeFlag : &apos;&lt;/span&gt;, isNodeFlag&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flag, &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;prof&apos;&lt;/span&gt;, &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;동작을 잘하는지 더 확실히 하고자 찾아봤는데, profiling을 하면 log file이 아웃풋 결과로 나온다고 한다. 잘 나오고 있었다!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org/en/docs/guides/simple-profiling/&quot;&gt;Easy profiling for Node.js Applications | Node.js&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Since we ran our application using the —prof option, a tick file was generated in the same directory as your local run of the application. It should have the form isolate-0xnnnnnnnnnnnn-v8.log (where n is a digit).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div style=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/92322688-ba8b1500-f06d-11ea-84dd-0a1cd4f0268b.png&quot;&gt;&lt;br&gt;
&lt;span&gt;profiling 아웃풋 파일들&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;추가적으로, 멘토님께서 &lt;code class=&quot;language-text&quot;&gt;./test/node-unit/cli/node-flags-spec.js&lt;/code&gt; 파일에서 테스트도 작성하면 좋을 거 같다고 하셨다. 그래서 아래 테스트 구문까지 추가해서 pr을 작성했다 🙂&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;it&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should return true for &quot;prof&quot; itself&apos;&lt;/span&gt;, &lt;span class=&quot;token function-name function&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  expect&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isNodeFlag&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;prof&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&apos;to be true&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mochajs/mocha/pull/4439&quot;&gt;Add support for node v8 option ‘prof’ parameter (#4433) by Donghoon759 · Pull Request #4439 · mochajs/mocha&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;처음에는 되게 막막했는데, 코드를 따라가다보니 어디를 수정해야 될지 알 수 있었고, node flag를 주면 node가 처리하도록 넘기는구나, node에 profiling하는 옵션도 있구나 하는 새로운 내용도 배울 수 있어 좋았다. 정말 하면 할수록 알아가는 게 많았고, mocha 코드를 수정하는 pr은 처음이라 자신감도 붙었다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Husky] Git hook library Husky 사용]]></title><description><![CDATA[설치  vue-cli로 프로젝트를 만든 후에 lint를 설치하고 commit 전에 lint를 실행하도록 설정해보았습니다. lint를 고치지 않은 채로 commit을 했더니, 예상대로 commit이 막혔습니다. image lint를 고치고 commit…]]></description><link>https://donghoon-song.github.io/development/2020-08-22---Husky-사용/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-08-22---Husky-사용/</guid><pubDate>Sat, 22 Aug 2020 23:59:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;설치&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%A4%EC%B9%98&quot; aria-label=&quot;설치 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;설치&lt;/h1&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;npm install husky --save-dev&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;husky&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;hooks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm test&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;pre-push&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm test&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;...&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;vue-cli로 프로젝트를 만든 후에 lint를 설치하고 commit 전에 lint를 실행하도록 설정해보았습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token property&quot;&gt;&quot;serve&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue-cli-service serve&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;token property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue-cli-service build&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;token property&quot;&gt;&quot;lint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue-cli-service lint&quot;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;husky&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;hooks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm run lint&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;lint를 고치지 않은 채로 commit을 했더니, 예상대로 commit이 막혔습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/90959393-c5727100-e4d5-11ea-9e8f-e3bb5048efdc.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;lint를 고치고 commit을 하니, 정상적으로 통과되었습니다!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/90959399-d3c08d00-e4d5-11ea-9b7a-d3ae02a20c10.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://git-scm.com/docs/githooks&quot;&gt;Githook list&lt;/a&gt;
Githook list안에 있는 hook들을 지원한다고 합니다. 저는 pre-commit과 pre-merge-commit hook에 lint를 적용시키고자 합니다. 실제로 작업할 때 merge하는 단계에서 코드가 꼬여버리는 걸 제때 찾지 못해서 이슈가 생기는 경우가 많았기 때문입니다.&lt;/p&gt;
&lt;h1 id=&quot;참고문서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%EB%AC%B8%EC%84%9C&quot; aria-label=&quot;참고문서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고문서&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/typicode/husky&quot;&gt;Husky repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[Nuxt.js] Nuxt.js에서 global scss 설정]]></title><description><![CDATA[Nuxt.js에서 global scss 설정 Nuxt.js 프레임워크를 사용해 개발하려고 세팅중에 global scss…]]></description><link>https://donghoon-song.github.io/development/2020-07-28---Nuxt.js에서-global-scss-설정/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-07-28---Nuxt.js에서-global-scss-설정/</guid><pubDate>Tue, 28 Jul 2020 00:40:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;nuxtjs에서-global-scss-설정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nuxtjs%EC%97%90%EC%84%9C-global-scss-%EC%84%A4%EC%A0%95&quot; aria-label=&quot;nuxtjs에서 global scss 설정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nuxt.js에서 global scss 설정&lt;/h1&gt;
&lt;p&gt;Nuxt.js 프레임워크를 사용해 개발하려고 세팅중에 global scss 변수를 사용하고 싶었습니다.
자주 사용하는 변수들을 한데 모아놓고, 꺼내서 사용하려는데 잘 불러와지지 않아서 그 해결과정을 공유합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// @/assets/style/base/color.scss&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$primary&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #00C850&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;// Color.vue
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;컬러&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Color&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;scoped&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;scss&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
&lt;span class=&quot;token selector&quot;&gt;.color&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $primary&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nuxt를 실행하면, 에러가 뜹니다. 이를 해결하기 위해 module을 설치해야 합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i --save-dev @nuxtjs/style-resources
&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-dev&lt;/span&gt; @nuxtjs/style-resources&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 나서 nuxt.config.js에서 세팅해줍니다.
module.exports 안에 다음 속성을 추가해줍니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;styleResources&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token literal-property property&quot;&gt;scss&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@/assets/style/base/color.scss&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;modules&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;@nuxtjs&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;style&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;resources&apos;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러면, styleResources안에 들어있는 scss 파일들이 전역으로 적용됩니다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Storybook] Storybook + 전역 scss 설정]]></title><description><![CDATA[Storybook에서 전역 scss파일 불러오기 Storybook을 이용해 디자인 시스템을 만들기 위해 세팅하고 있었습니다.
주로 쓰일 색상 변수들을 color.scss에 모아두고, @assets/style/base…]]></description><link>https://donghoon-song.github.io/development/2020-07-28---Storybook-+-전역-scss-설정/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-07-28---Storybook-+-전역-scss-설정/</guid><pubDate>Tue, 28 Jul 2020 00:08:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;storybook에서-전역-scss파일-불러오기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#storybook%EC%97%90%EC%84%9C-%EC%A0%84%EC%97%AD-scss%ED%8C%8C%EC%9D%BC-%EB%B6%88%EB%9F%AC%EC%98%A4%EA%B8%B0&quot; aria-label=&quot;storybook에서 전역 scss파일 불러오기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Storybook에서 전역 scss파일 불러오기&lt;/h1&gt;
&lt;p&gt;Storybook을 이용해 디자인 시스템을 만들기 위해 세팅하고 있었습니다.&lt;br/&gt;
주로 쓰일 색상 변수들을 color.scss에 모아두고, @assets/style/base 폴더에 넣어두고 쓰려고 했는데 그냥 불러와지진 않더라구요.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// @assets/style/base/color.scss&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$primary&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #00C850&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;// Color.vue
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;컬러&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Color&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;scoped&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;scss&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
&lt;span class=&quot;token selector&quot;&gt;.color&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $primary&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;main.js는 다음과 같이 기본 scss 설정만 되어있었습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ./storybook/main.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Export a function. Accept the base config as the only param.&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;webpackFinal&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; configType &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// `configType` has a value of &apos;DEVELOPMENT&apos; or &apos;PRODUCTION&apos;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// You can change the configuration based on that.&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// &apos;PRODUCTION&apos; is used when building the static version of storybook.&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Make whatever fine-grained changes you need&lt;/span&gt;
        config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rules&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\.scss$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;style-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;css-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;sass-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Return the altered config&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; run storybook&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;storybook을 실행하면 다음과 같은 에러가 뜹니다.
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/88559627-0490dc00-d068-11ea-88fd-48f01985745a.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;변수를 찾을 수 없답니다! 그래서 이 친구를 찾게 도와주는 세팅을 해야됩니다.
아까 봤던 ./storybook/main.js을 다음과 같이 수정합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Export a function. Accept the base config as the only param.&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;webpackFinal&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; configType &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// `configType` has a value of &apos;DEVELOPMENT&apos; or &apos;PRODUCTION&apos;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// You can change the configuration based on that.&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// &apos;PRODUCTION&apos; is used when building the static version of storybook.&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Make whatever fine-grained changes you need&lt;/span&gt;
        config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rules&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\.scss$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;style-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;css-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;sass-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;additionalData&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
						@import &quot;assets/style/base/color.scss&quot;;
					&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Return the altered config&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러고나서 다시 Storybook을 실행하면, 정상적으로 작동합니다! vue파일이 scoped임에도 불구하고, 전역 scss 변수를 사용할 수 있으니, 정말 큰 메리트가 있다고 생각합니다! 이 설정을 적용하지 않는다면, vue파일마다 사용할 변수를 style태그안에 매번 작성해줘야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://webpack.js.org/loaders/sass-loader/#additionaldata&quot;&gt;https://webpack.js.org/loaders/sass-loader/#additionaldata&lt;/a&gt;
&lt;br/&gt;참고로 우리가 사용한 sass-loader의 options의 additionalData 속성은, sass/scss 파일을 entry file앞에 붙여준다고 합니다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Github Notification (깃허브 알림)]]></title><description><![CDATA[Github Notification 깃허브에서 알림 기능을 활용하는 방법입니다! Managing notifications from your inbox image…]]></description><link>https://donghoon-song.github.io/development/2020-04-27---Github-Notification-(깃허브-알림)/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-04-27---Github-Notification-(깃허브-알림)/</guid><pubDate>Mon, 27 Apr 2020 21:32:13 GMT</pubDate><content:encoded>&lt;h1 id=&quot;github-notification&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#github-notification&quot; aria-label=&quot;github notification permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Github Notification&lt;/h1&gt;
&lt;h3 id=&quot;깃허브에서-알림-기능을-활용하는-방법입니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B9%83%ED%97%88%EB%B8%8C%EC%97%90%EC%84%9C-%EC%95%8C%EB%A6%BC-%EA%B8%B0%EB%8A%A5%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95%EC%9E%85%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;깃허브에서 알림 기능을 활용하는 방법입니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;깃허브에서 알림 기능을 활용하는 방법입니다!&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://help.github.com/en/github/managing-subscriptions-and-notifications-on-github/managing-notifications-from-your-inbox#supported-queries-for-custom-filters&quot;&gt;Managing notifications from your inbox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/80373073-7a51a400-88cf-11ea-98ba-b6def5408142.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;기존에 알림 기능으로 사용하던 종모양 버튼을 누르면 알림을 관리할 수 있는 페이지로 이동합니다.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/80373409-ff3cbd80-88cf-11ea-92da-5931dd34fc60.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;오른쪽 리스트에는 전체적인 알림들이 보입니다.
왼쪽 파란부분은 필터 기능으로, 속성값에 따라서 모아볼 수 있습니다. 필터의 설정버튼을 클릭하면 필터를 커스터마이징할 수 있습니다.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/80373611-462ab300-88d0-11ea-9bbf-d81492f1322d.png&quot; alt=&quot;image&quot;&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;그림에서 제 KNUCafeMap이라는 repository에서 review-request를 필터링하는 커스텀 필터를 만들어보았습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Name : KNUCafeMap review-requested
Filter inbox by... : repo:Donghoon759/KNUCafeMap reason:review-requested&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/80374193-3fe90680-88d1-11ea-83a2-27420527aeaf.png&quot; alt=&quot;image&quot;&gt;
커스텀 필터는 15개까지 등록할 수 있다고 합니다.
커스텀 필터는 필터 쿼리를 사용해 커스터마이징할 수 있으며, 쿼리의 종류는 다음과 페이지에서 확인할 수 있습니다. &lt;a href=&quot;https://help.github.com/en/github/managing-subscriptions-and-notifications-on-github/managing-notifications-from-your-inbox#supported-queries-for-custom-filters&quot;&gt;Supported queries for custom filters&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;repo:아이디/저장소이름&lt;/code&gt; 형식으로 작성하시면 됩니다 :)
&lt;br&gt;&lt;br&gt;&lt;br&gt;
&lt;img src=&quot;https://user-images.githubusercontent.com/32301380/80374265-63ac4c80-88d1-11ea-8d73-3548a00a115c.png&quot; alt=&quot;image&quot;&gt;
필터 만드는게 익숙하지 않으시다면 검색창에서 마우스로 클릭하여 쿼리를 만들수도 있으니 너무 겁먹지 마세요.&lt;/p&gt;
&lt;p&gt;깃허브에서 받고 싶은 알림들만 받을 수 있어서 좋은 거 같습니다! 다양한 활용 케이스들이 공유되었으면 하네요&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Vue.js] 데이터 바인딩]]></title><description><![CDATA[데이터 바인딩 데이터 바인딩은 HTML 화면 요소를 뷰 인스턴스의 데이터와 연결하는 것 {{}} - 콧수염 괄호 뷰 인스턴스의 데이터를 HTML 태그에 연결하는 가장 기본적인 텍스트 삽입 방식, 템플릿 문법 data의 text…]]></description><link>https://donghoon-song.github.io/development/2020-03-06---Vue.js-데이터-바인딩/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-03-06---Vue.js-데이터-바인딩/</guid><pubDate>Fri, 06 Mar 2020 21:34:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;데이터-바인딩&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B0%94%EC%9D%B8%EB%94%A9&quot; aria-label=&quot;데이터 바인딩 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;데이터 바인딩&lt;/h1&gt;
&lt;p&gt;데이터 바인딩은 HTML 화면 요소를 뷰 인스턴스의 데이터와 연결하는 것&lt;/p&gt;
&lt;h2 id=&quot;---콧수염-괄호&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#---%EC%BD%A7%EC%88%98%EC%97%BC-%EA%B4%84%ED%98%B8&quot; aria-label=&quot;   콧수염 괄호 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;{{}} - 콧수염 괄호&lt;/h2&gt;
&lt;h3 id=&quot;뷰-인스턴스의-데이터를-html-태그에-연결하는-가장-기본적인-텍스트-삽입-방식-템플릿-문법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B7%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-html-%ED%83%9C%EA%B7%B8%EC%97%90-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-%EA%B0%80%EC%9E%A5-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%82%BD%EC%9E%85-%EB%B0%A9%EC%8B%9D-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%AC%B8%EB%B2%95&quot; aria-label=&quot;뷰 인스턴스의 데이터를 html 태그에 연결하는 가장 기본적인 텍스트 삽입 방식 템플릿 문법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;뷰 인스턴스의 데이터를 HTML 태그에 연결하는 가장 기본적인 텍스트 삽입 방식, 템플릿 문법&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;data의 text 속성이 바뀌면 뷰 반응성에 의해 화면이 자동으로 갱신된다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  {{text}}
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#app&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello World!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;뷰 데이터가 변경되어도 값을 유지하고 싶다면 v-once 속성을 사용한다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;v-once&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  {{ text }}
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;v-bind&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#v-bind&quot; aria-label=&quot;v bind permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;v-bind&lt;/h2&gt;
&lt;h1 id=&quot;참고문서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%EB%AC%B8%EC%84%9C&quot; aria-label=&quot;참고문서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고문서&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a src=&quot;http://www.yes24.com/Product/Goods/58206961&quot;&gt;Do it! Vue.js 입문&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a src=&quot;https://kr.vuejs.org/v2/api/#updated&quot;&gt;Vue.js 공식문서&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[Vue.js] 컴포넌트 간 통신]]></title><description><![CDATA[뷰 컴포넌트 통신 컴포넌트로 화면을 구성하므로 같은 웹페이지라도 데이터를 공유할 수 없다. 컴포넌트마다 자체적으로 고유한 유효 범위를 가지기 때문 상하위 컴포넌트 관계 상위(부모) - 하위(자식) 컴포넌트 간의 데이터 전달 props…]]></description><link>https://donghoon-song.github.io/development/2020-03-06---Vue.js-컴포넌트-간-통신/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-03-06---Vue.js-컴포넌트-간-통신/</guid><pubDate>Fri, 06 Mar 2020 20:51:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;뷰-컴포넌트-통신&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B7%B0-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%ED%86%B5%EC%8B%A0&quot; aria-label=&quot;뷰 컴포넌트 통신 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;뷰 컴포넌트 통신&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;컴포넌트로 화면을 구성하므로 같은 웹페이지라도 데이터를 공유할 수 없다.&lt;/li&gt;
&lt;li&gt;컴포넌트마다 자체적으로 고유한 유효 범위를 가지기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;상하위-컴포넌트-관계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%83%81%ED%95%98%EC%9C%84-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B4%80%EA%B3%84&quot; aria-label=&quot;상하위 컴포넌트 관계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;상하위 컴포넌트 관계&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;상위(부모) - 하위(자식) 컴포넌트 간의 데이터 전달&lt;/li&gt;
&lt;li&gt;props로 데이터를 전달한다.&lt;/li&gt;
&lt;li&gt;하위에서 상위로는 기본적으로 이벤트만 전달가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;상위에서-하위로-데이터-전달&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%83%81%EC%9C%84%EC%97%90%EC%84%9C-%ED%95%98%EC%9C%84%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%84%EB%8B%AC&quot; aria-label=&quot;상위에서 하위로 데이터 전달 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;상위에서 하위로 데이터 전달&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;Vue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;child-component&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&apos;propsName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;child-component 컴포넌트 태그에 v-bind 속성을 추가한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;child&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;component v&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;bind&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;propsName&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;child&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;component&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;하위에서-상위로-이벤트-전달&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%98%EC%9C%84%EC%97%90%EC%84%9C-%EC%83%81%EC%9C%84%EB%A1%9C-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%A0%84%EB%8B%AC&quot; aria-label=&quot;하위에서 상위로 이벤트 전달 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;하위에서 상위로 이벤트 전달&lt;/h2&gt;
&lt;h3 id=&quot;이벤트-발생과-수신&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B0%9C%EC%83%9D%EA%B3%BC-%EC%88%98%EC%8B%A0&quot; aria-label=&quot;이벤트 발생과 수신 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이벤트 발생과 수신&lt;/h3&gt;
&lt;p&gt;이벤트를 발생시켜 (event emit) 상위 컴포넌트에 신호를 보낸다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 이벤트 발생&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;eventName&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;// 이벤트 수신
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;child-component&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;v-on:&lt;/span&gt;eventName&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;상위 컴포넌트의 메서드명&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;child-component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;관계-없는-컴포넌트간-통신---이벤트-버스&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B4%80%EA%B3%84-%EC%97%86%EB%8A%94-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EA%B0%84-%ED%86%B5%EC%8B%A0---%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EC%8A%A4&quot; aria-label=&quot;관계 없는 컴포넌트간 통신   이벤트 버스 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;관계 없는 컴포넌트간 통신 - 이벤트 버스&lt;/h2&gt;
&lt;h3 id=&quot;이벤트-버스는-개발자가-지정한-2개의-컴포넌트-간에-데이터를-주고받을-수-있는-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EC%8A%A4%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EC%A7%80%EC%A0%95%ED%95%9C-2%EA%B0%9C%EC%9D%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B0%84%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%A3%BC%EA%B3%A0%EB%B0%9B%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;이벤트 버스는 개발자가 지정한 2개의 컴포넌트 간에 데이터를 주고받을 수 있는 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이벤트 버스는 개발자가 지정한 2개의 컴포넌트 간에 데이터를 주고받을 수 있는 방법&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;child-component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;child-component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; eventBus &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  Vue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;child-component&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;div&gt;하위 컴포넌트 영역.&amp;lt;button v-on:click=&quot;showLog&quot;&gt;show&amp;lt;/button&gt;&amp;lt;/div&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function-variable function&quot;&gt;showLog&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        eventBus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;triggerEventBus&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#app&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;created&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      eventBus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;triggerEventBus&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;이벤트를 전달받음. 값: &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;보내는 컴포넌트에서는 .&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mtext&gt;을&lt;/mtext&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mtext&gt;받는컴포넌트에서는&lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;emit()을, 받는 컴포넌트에서는 .&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathdefault&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathdefault&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathdefault&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathdefault&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;을&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.16666666666666666em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;받&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;는&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;컴&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;포&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;넌&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;트&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;에&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;서&lt;/span&gt;&lt;span class=&quot;mord hangul_fallback&quot;&gt;는&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;on()을 구현한다.&lt;/li&gt;
&lt;li&gt;애플리케이션 로직을 담는 인스턴스와 별개로 새 인스턴스 1개 더 생성한 후, 그것을 이용해 이벤트를 보내고 받는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;컴포넌트가 많아지면 데이터의 from과 to를 관리하기 어렵다 =&gt; Vuex(상태 관리 도구) 사용&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;참고문서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%EB%AC%B8%EC%84%9C&quot; aria-label=&quot;참고문서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고문서&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a src=&quot;http://www.yes24.com/Product/Goods/58206961&quot;&gt;Do it! Vue.js 입문&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a src=&quot;https://kr.vuejs.org/v2/api/#updated&quot;&gt;Vue.js 공식문서&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[Vue.js] 라이프사이클]]></title><description><![CDATA[beforeCreate 인스턴스가 생성되고 나서 가장 처음으로 실행되는 라이프 사이클 data 속성과 methods 속성 접근 불가 돔에도 접근 불가 React.js의 constructor과 유사한 거 같습니다. created beforeCreate…]]></description><link>https://donghoon-song.github.io/development/2020-03-06---Vue.js-라이프사이클/</link><guid isPermaLink="false">https://donghoon-song.github.io/development/2020-03-06---Vue.js-라이프사이클/</guid><pubDate>Fri, 06 Mar 2020 10:51:00 GMT</pubDate><content:encoded>&lt;img src=&quot;https://kr.vuejs.org/images/lifecycle.png&quot; alt=&quot;Vue.js 라이프사이클&quot;&gt;
&lt;h2 id=&quot;beforecreate&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#beforecreate&quot; aria-label=&quot;beforecreate permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;beforeCreate&lt;/h2&gt;
&lt;h3 id=&quot;인스턴스가-생성되고-나서-가장-처음으로-실행되는-라이프-사이클&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EA%B0%80-%EC%83%9D%EC%84%B1%EB%90%98%EA%B3%A0-%EB%82%98%EC%84%9C-%EA%B0%80%EC%9E%A5-%EC%B2%98%EC%9D%8C%EC%9C%BC%EB%A1%9C-%EC%8B%A4%ED%96%89%EB%90%98%EB%8A%94-%EB%9D%BC%EC%9D%B4%ED%94%84-%EC%82%AC%EC%9D%B4%ED%81%B4&quot; aria-label=&quot;인스턴스가 생성되고 나서 가장 처음으로 실행되는 라이프 사이클 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인스턴스가 생성되고 나서 가장 처음으로 실행되는 라이프 사이클&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;data 속성과 methods 속성 접근 불가&lt;/li&gt;
&lt;li&gt;돔에도 접근 불가
&lt;blockquote&gt;
&lt;p&gt;React.js의 constructor과 유사한 거 같습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;created&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#created&quot; aria-label=&quot;created permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;created&lt;/h2&gt;
&lt;h3 id=&quot;beforecreate-단계-다음에-실행&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#beforecreate-%EB%8B%A8%EA%B3%84-%EB%8B%A4%EC%9D%8C%EC%97%90-%EC%8B%A4%ED%96%89&quot; aria-label=&quot;beforecreate 단계 다음에 실행 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;beforeCreate 단계 다음에 실행&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;data 속성과 methods 속성이 접근 가능&lt;/li&gt;
&lt;li&gt;this.data 또는 this.fetchData()와 같은 로직들을 이용해 data 속성과 methods 속성에 정의된 값에 접근하여 로직 실행가능&lt;/li&gt;
&lt;li&gt;돔 요소 접근 불가&lt;/li&gt;
&lt;li&gt;Why? &lt;strong&gt;인스턴스가 생성되었지만, 화면요소에 부착되기 전이므로&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;서버에 데이터를 요청해 받아오는 로직을 수행하기 좋다.&lt;/em&gt;&lt;/strong&gt; (vuex에서 actions)&lt;/li&gt;
&lt;li&gt;Why? data 속성과 methods 속성에 접근 가능한 가장 첫 라이프 사이클&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;options 속성이나 콜백에 화살표 함수 사용을 지양한다. &lt;strong&gt;화살표 함수들은 부모 컨텍스트에 바인딩&lt;/strong&gt;되기 때문에 this 컨텍스트가 Vue 인스턴스를 호출하지 못한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;beforemount&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#beforemount&quot; aria-label=&quot;beforemount permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;beforeMount&lt;/h2&gt;
&lt;h3 id=&quot;template-속성에-지정한-마크업-속성을-render-함수로-변환한-후-el-속성에-지정한-화면-요소에-인스턴스를-부착하기-전-단계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#template-%EC%86%8D%EC%84%B1%EC%97%90-%EC%A7%80%EC%A0%95%ED%95%9C-%EB%A7%88%ED%81%AC%EC%97%85-%EC%86%8D%EC%84%B1%EC%9D%84-render-%ED%95%A8%EC%88%98%EB%A1%9C-%EB%B3%80%ED%99%98%ED%95%9C-%ED%9B%84-el-%EC%86%8D%EC%84%B1%EC%97%90-%EC%A7%80%EC%A0%95%ED%95%9C-%ED%99%94%EB%A9%B4-%EC%9A%94%EC%86%8C%EC%97%90-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EB%A5%BC-%EB%B6%80%EC%B0%A9%ED%95%98%EA%B8%B0-%EC%A0%84-%EB%8B%A8%EA%B3%84&quot; aria-label=&quot;template 속성에 지정한 마크업 속성을 render 함수로 변환한 후 el 속성에 지정한 화면 요소에 인스턴스를 부착하기 전 단계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;template 속성에 지정한 마크업 속성을 render() 함수로 변환한 후 el 속성에 지정한 화면 요소에 인스턴스를 부착하기 전 단계&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;render() 함수가 호출되기 직전의 로직을 추가하기 좋다.
&lt;blockquote&gt;
&lt;p&gt;React.js의 componentWillMount()와 유사한 거 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;mounted&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mounted&quot; aria-label=&quot;mounted permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;mounted&lt;/h2&gt;
&lt;h3 id=&quot;el-속성에서-지정한-화면-요소에-인스턴스가-부착되고-나면-호출되는-단계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#el-%EC%86%8D%EC%84%B1%EC%97%90%EC%84%9C-%EC%A7%80%EC%A0%95%ED%95%9C-%ED%99%94%EB%A9%B4-%EC%9A%94%EC%86%8C%EC%97%90-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EA%B0%80-%EB%B6%80%EC%B0%A9%EB%90%98%EA%B3%A0-%EB%82%98%EB%A9%B4-%ED%98%B8%EC%B6%9C%EB%90%98%EB%8A%94-%EB%8B%A8%EA%B3%84&quot; aria-label=&quot;el 속성에서 지정한 화면 요소에 인스턴스가 부착되고 나면 호출되는 단계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;el 속성에서 지정한 화면 요소에 인스턴스가 부착되고 나면 호출되는 단계&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;template 속성의 돔 요소에 접근 가능&lt;/li&gt;
&lt;li&gt;돔에 인스턴스가 부착되자마자 바로 호출되므로 하위 컴포넌트나 외부 라이브러리에 의해 추가된 화면 요소들이 최종 HTML 코드로 변환되는 시점과 다를 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;beforeupdate&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#beforeupdate&quot; aria-label=&quot;beforeupdate permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;beforeUpdate&lt;/h2&gt;
&lt;h3 id=&quot;인스턴스가-부착되고-나면-인스턴스에-정의한-속성들이-화면에-치환된다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EA%B0%80-%EB%B6%80%EC%B0%A9%EB%90%98%EA%B3%A0-%EB%82%98%EB%A9%B4-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EC%97%90-%EC%A0%95%EC%9D%98%ED%95%9C-%EC%86%8D%EC%84%B1%EB%93%A4%EC%9D%B4-%ED%99%94%EB%A9%B4%EC%97%90-%EC%B9%98%ED%99%98%EB%90%9C%EB%8B%A4&quot; aria-label=&quot;인스턴스가 부착되고 나면 인스턴스에 정의한 속성들이 화면에 치환된다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;인스턴스가 부착되고 나면 인스턴스에 정의한 속성들이 화면에 치환된다.&lt;/h3&gt;
&lt;h3 id=&quot;치환된-값은-뷰의-반응성reactivity을-제공하기-위해-watch-속성으로-감시한다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B9%98%ED%99%98%EB%90%9C-%EA%B0%92%EC%9D%80-%EB%B7%B0%EC%9D%98-%EB%B0%98%EC%9D%91%EC%84%B1reactivity%EC%9D%84-%EC%A0%9C%EA%B3%B5%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-watch-%EC%86%8D%EC%84%B1%EC%9C%BC%EB%A1%9C-%EA%B0%90%EC%8B%9C%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;치환된 값은 뷰의 반응성reactivity을 제공하기 위해 watch 속성으로 감시한다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;치환된 값은 뷰의 반응성(Reactivity)을 제공하기 위해 $watch 속성으로 감시한다.&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;관찰하고 있는 데이터가 변경되면 가상 돔으로 화면을 다시 그리기 전에 호출되는 단계&lt;/li&gt;
&lt;li&gt;변경 예정인 새 데이터에 접근할 수 있어 변경 예정 데이터의 값과 관련된 로직을 넣을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;React.js의 componentWillUpdate(nextProps, nextState)와 유사한 거 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;updated&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#updated&quot; aria-label=&quot;updated permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;updated&lt;/h2&gt;
&lt;h3 id=&quot;데이터가-변경되고-나서-가상-돔으로-다시-화면을-그리고-나면-실행되는-단계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8D%B0%EC%9D%B4%ED%84%B0%EA%B0%80-%EB%B3%80%EA%B2%BD%EB%90%98%EA%B3%A0-%EB%82%98%EC%84%9C-%EA%B0%80%EC%83%81-%EB%8F%94%EC%9C%BC%EB%A1%9C-%EB%8B%A4%EC%8B%9C-%ED%99%94%EB%A9%B4%EC%9D%84-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EB%82%98%EB%A9%B4-%EC%8B%A4%ED%96%89%EB%90%98%EB%8A%94-%EB%8B%A8%EA%B3%84&quot; aria-label=&quot;데이터가 변경되고 나서 가상 돔으로 다시 화면을 그리고 나면 실행되는 단계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;데이터가 변경되고 나서 가상 돔으로 다시 화면을 그리고 나면 실행되는 단계&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;데이터 변경으로 인한 화면 요소 변경까지 완료된 시점&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 변경 후 화면 요소 제어와 관련된 로직을 추가하기 위해 좋음&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 값을 갱신하는 로직은 가급적 beforeUpdate에 추가하고, updated에서는 변경 데이터의 화면 요소와 관련되 로직을 추가하는 것이 좋다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;beforedestroy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#beforedestroy&quot; aria-label=&quot;beforedestroy permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;beforeDestroy&lt;/h2&gt;
&lt;h3 id=&quot;뷰-인스턴스가-파기되기-직전에-호출되는-단계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B7%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EA%B0%80-%ED%8C%8C%EA%B8%B0%EB%90%98%EA%B8%B0-%EC%A7%81%EC%A0%84%EC%97%90-%ED%98%B8%EC%B6%9C%EB%90%98%EB%8A%94-%EB%8B%A8%EA%B3%84&quot; aria-label=&quot;뷰 인스턴스가 파기되기 직전에 호출되는 단계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;뷰 인스턴스가 파기되기 직전에 호출되는 단계&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;아직 인스턴스에 접근할 수 있다.&lt;/li&gt;
&lt;li&gt;뷰 인스턴스의 데이터를 삭제하기 좋은 단계&lt;/li&gt;
&lt;li&gt;ex) removeEventListener 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#app&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;created&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;click&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; funcion&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;beforeDestroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;click&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; funcion&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;beforeDestoy 단계에서 이벤트를 해제시켜주지 않으면, document.body에는 계속해서 해당 event가 바인딩되어 실행된다.&lt;/p&gt;
&lt;h2 id=&quot;destroyed&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#destroyed&quot; aria-label=&quot;destroyed permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;destroyed&lt;/h2&gt;
&lt;h3 id=&quot;뷰-인스턴스가-파괴되고-나서-호출되는-단계&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B7%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EA%B0%80-%ED%8C%8C%EA%B4%B4%EB%90%98%EA%B3%A0-%EB%82%98%EC%84%9C-%ED%98%B8%EC%B6%9C%EB%90%98%EB%8A%94-%EB%8B%A8%EA%B3%84&quot; aria-label=&quot;뷰 인스턴스가 파괴되고 나서 호출되는 단계 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;뷰 인스턴스가 파괴되고 나서 호출되는 단계&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;뷰 인스턴스에 정의한 모든 속성이 제거되고 하위에 선언한 인스턴스들 또한 모두 파괴&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;참고문서&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%EB%AC%B8%EC%84%9C&quot; aria-label=&quot;참고문서 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고문서&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a src=&quot;http://www.yes24.com/Product/Goods/58206961&quot;&gt;Do it! Vue.js 입문&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a src=&quot;https://blog.martinwork.co.kr/vuejs/2018/02/05/vue-lifecycle-hooks.html&quot;&gt;Vue의 Lifecycle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a src=&quot;https://kr.vuejs.org/v2/api/#updated&quot;&gt;Vue.js 공식문서&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[about]]></title><description><![CDATA[Your name Thank you for reading my resume. If you want to contact me, Please send me an email.]]></description><link>https://donghoon-song.github.io/resume-en/</link><guid isPermaLink="false">https://donghoon-song.github.io/resume-en/</guid><pubDate>Sun, 27 Jan 2019 16:21:13 GMT</pubDate><content:encoded>&lt;h1 id=&quot;your-name&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#your-name&quot; aria-label=&quot;your name permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Your name&lt;/h1&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;&lt;em&gt;Thank you for reading my resume. If you want to contact me, Please send me an email.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;</content:encoded></item></channel></rss>