<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>생각 많은 개발자의 놀이터</title>
    <link>https://think-dev.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 17 Jul 2026 11:06:19 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>꾸럭</managingEditor>
    <image>
      <title>생각 많은 개발자의 놀이터</title>
      <url>https://tistory1.daumcdn.net/tistory/4695860/attach/d5abccae9f654e26a752b7034440f53b</url>
      <link>https://think-dev.tistory.com</link>
    </image>
    <item>
      <title>npm-check-updates와 npm audit으로 Node.js 패키지 취약점 손쉽게 관리하기</title>
      <link>https://think-dev.tistory.com/50</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js로 프로젝트를 만들다 보면 수십 개, 많게는 수백 개의 패키지를 설치하게 된다. 직접 설치한 것도 있지만 대부분은 의존성으로 따라온 것들이다. 문제는 이 패키지들 중 하나라도 취약점이 생기면, 전체 프로젝트가 위험해질 수 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 보고되지 않은 잠재적인 취약점까지 개발자 선에서 모두 찾아내고 조치하는 건 사실상 불가능에 가깝다. 그렇기 때문에 &lt;span&gt;&lt;b&gt;적어도 이미 보고된 취약점에 대해서는 빠르게 대응하는 태도&lt;/b&gt;&lt;/span&gt;가 필요하다. 이런 취약점은 공개된 만큼 악용될 가능성도 높고, 보안 사고로 이어질 위험도 크다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보고된 취약점에 대응하는 방법은 크게 두 가지다. &lt;span&gt;하나는 &lt;/span&gt;&lt;b&gt;내가 직접 package.json에 선언한 의존성 패키지의 버전을 가능한 최신으로 유지하는 것&lt;/b&gt;&lt;span&gt;, 다른 하나는 &lt;/span&gt;&lt;b&gt;이런 패키지에 딸려온 하위 의존성들 중 취약점이 있는 버전을 찾아내어, 이를 해결한 버전으로 교체하는 것&lt;/b&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, 이런 복잡한 일들을 개발자가 매번 손으로 일일이 확인하고 처리해야 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히, 꼭 그럴 필요는 없다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ncu (npm-check-updates): 직접 선언한 패키지 버전 관리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 소개할 도구는 &lt;span&gt;ncu&lt;/span&gt;, 정확한 이름은 &lt;span&gt;npm-check-updates&lt;/span&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 도구는 내가 직접 &lt;span&gt;package.json&lt;/span&gt;에 명시한 의존성들의 최신 버전을 확인하고, 한 줄 명령어로 업데이트해주는 역할을 한다. 기본적인 &lt;span&gt;npm install&lt;/span&gt;만으로는 메이저 버전 업데이트가 자동으로 되지 않기 때문에, &lt;span&gt;ncu&lt;/span&gt;를 활용하면 놓치고 있던 중요한 업데이트도 쉽게 반영할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치는 전역으로 하는 게 일반적이다.&lt;/p&gt;
&lt;pre id=&quot;code_1743034814074&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g npm-check-updates&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 끝났다면, 프로젝트 루트 디렉토리에서 아래 명령어를 실행하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1743034833278&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ncu&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어는 현재 사용 중인 패키지들과 업데이트 가능한 최신 버전의 목록을 보여준다. 실제로 버전을 올리고 싶다면 다음과 같이 하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1743034852627&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ncu -u&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 &lt;span&gt;npm install&lt;/span&gt;만 해주면 최신 버전이 적용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;최신 버전 업데이트, 항상 좋은 걸까?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ncu -u&lt;/span&gt;는 기본적으로 모든 패키지를 &lt;span&gt;&lt;b&gt;가장 최신 버전으로 올리려는 시도&lt;/b&gt;&lt;/span&gt;를 한다. 그런데 프로젝트가 점점 커질수록, 모든 패키지를 항상 최신 상태로 유지하는 건 어렵고 위험한 일이 되기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이저 버전이 올라가면서 API가 크게 바뀌는 경우도 있고, 최신 버전에 오히려 치명적인 버그가 있어 업데이트를 미뤄야 할 때도 있다. 이럴 땐 다음과 같이 범위를 좁힌 업데이트가 유용하다.&lt;/p&gt;
&lt;pre id=&quot;code_1743034930268&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ncu -t minor
ncu -t patch&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-t minor&lt;/span&gt;는 마이너와 패치만, &lt;span&gt;-t patch&lt;/span&gt;는 패치만 업데이트한다. 안정성을 유지하면서도 적절한 수준의 업데이트를 할 수 있는 옵션이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;특정 패키지를 업데이트에서 제외하고 싶다면?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 패키지는 버전을 고정해두고 싶은 경우도 있다. &lt;span&gt;ncu&lt;/span&gt;는 &lt;span&gt;-x&lt;/span&gt; 옵션으로 예외를 둘 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1743034970017&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ncu -x react,react-dom&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 &lt;span&gt;.ncurc.json&lt;/span&gt;, &lt;span&gt;.ncurc.js&lt;/span&gt; 등의 설정 파일을 통해 반복적으로 사용하는 옵션들을 미리 정의해둘 수도 있다. 예를 들어 아래처럼 구성할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1743035004828&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;target&quot;: &quot;minor&quot;,
  &quot;reject&quot;: [&quot;react&quot;, &quot;react-dom&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ncu&lt;/span&gt;의 다양한 옵션과 설정 파일 구성 방법은 &lt;a href=&quot;https://github.com/raineorshine/npm-check-updates&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 문서&lt;/a&gt;를 참고하면 더 자세히 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;npm audit: 하위 의존성 취약점 점검 도구&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 명시한 패키지는 &lt;span&gt;ncu&lt;/span&gt;로 관리할 수 있지만, 그에 딸려오는 하위 의존성들에 대해서는 &lt;span&gt;npm audit&lt;/span&gt;이 필요하다. &lt;span&gt;npm audit&lt;/span&gt;은 설치된 모든 패키지를 대상으로, 이미 알려진 취약점이 있는 버전이 있는지 점검해주는 도구다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어로 간단히 실행할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1743035083342&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm audit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하면 취약점의 개수, 심각도, 어떤 패키지에서 발생했는지, 어떤 경로로 설치됐는지까지 상세히 알려준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;자동으로 고칠 수 있다면?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취약점 중 일부는 자동으로 해결할 수 있다. 그럴 땐 다음 명령어를 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1743035115541&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm audit fix&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한 범위 내에서 &lt;span&gt;package-lock.json&lt;/span&gt;을 수정하고 안전하게 취약점을 해결해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 강제적인 해결을 원한다면 다음과 같이 사용할 수도 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1743035136988&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm audit fix --force&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;span&gt;--force&lt;/span&gt;는 메이저 버전 업데이트까지 강제로 수행하기 때문에, 예기치 않은 문제를 유발할 수 있다. 신중하게 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;업데이트 이후, 어떤 점을 주의해야 할까?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ncu와 npm audit 모두 결국은 &lt;span&gt;&lt;b&gt;의존성의 버전을 변경하는 도구&lt;/b&gt;&lt;/span&gt;다. 버전을 바꾼다는 건 코드의 동작이 달라질 수 있다는 뜻이고, 이는 프로젝트 전반에 영향을 줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 변경은 &lt;span&gt;&lt;b&gt;개발 단계에서의 에디터 오류&lt;/b&gt;&lt;/span&gt;, &lt;span&gt;&lt;b&gt;빌드 시점의 컴파일 실패&lt;/b&gt;&lt;/span&gt;, &lt;span&gt;&lt;b&gt;실행 후의 런타임 예외&lt;/b&gt;&lt;/span&gt; 등으로 나타날 수 있다. 특히 버전 변화가 클수록 이러한 문제가 생길 가능성도 커진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성 업데이트 이후에는 반드시 테스트를 돌리고, 앱을 직접 실행해보면서 주요 기능이 정상적으로 동작하는지 확인해야 한다. 변경된 패키지가 어떤 기능과 연결돼 있는지를 잘 파악하고 있다면 훨씬 수월하게 검증할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실무 팁: Cursor로 변경 영향도 분석해보기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 점검 과정을 조금 더 수월하게 하고 싶다면, &lt;a href=&quot;https://www.cursor.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;Cursor&lt;/b&gt;&lt;/span&gt;&lt;/a&gt; 같은 AI 기반 코드 편집기를 활용해보는 것도 방법이다. Cursor는 프로젝트 전반을 백그라운드로 불러와 문맥을 이해하고 명령을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접적으로 영향도를 분석하는 기능이 내장돼 있는 건 아니지만, 프롬프트를 잘 작성하면 매우 효과적인 도구가 된다. 예를 들어 아래와 같은 식으로 요청할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&amp;ldquo;지금 ncu -u를 실행해서 package.json이 바뀌었어. 이 변경이 프로젝트에 어떤 영향을 줄 수 있을지 전체적으로 확인해줘.&amp;rdquo;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 방식으로 변경된 버전이 사용된 코드 위치를 추적하고, 영향 가능성이 있는 부분을 빠르게 짚어낼 수 있다. 다만, &lt;/span&gt;&lt;b&gt;아무리 AI의 도움을 받더라도 의존도가 높거나, 말썽이 잦았던 패키지에 대해서는 반드시 직접 런타임에서 확인해보는 것이 안전하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;정기적인 관리가 최고의 보안, 그리고 최고의 유지보수&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성 관리는 한 번 하고 끝나는 일이 아니다. 시간이 지날수록 패키지는 계속 업데이트되고, 새로운 취약점도 발견된다. 결국 중요한 건 얼마나 자주, 꾸준히 점검하고 관리하느냐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 현실적인 방법은 루틴을 만드는 것이다. 예를 들어 매주 월요일 오전이나 배포가 끝난 직후, &lt;span&gt;ncu&lt;/span&gt;와 &lt;span&gt;npm audit&lt;/span&gt;을 정기적으로 실행해보는 시간을 정해두는 식이다. 팀 단위로는 CI 파이프라인에 &lt;span&gt;npm audit&lt;/span&gt;을 자동화해서 돌리는 것도 효과적이다. pull request마다 자동 점검을 하도록 설정하면 사전에 문제를 걸러낼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 회사를 거치면서 느낀 건, 지금처럼 보안 도메인을 다루는 회사를 제외하면 대부분의 팀은 패키지 관리를 체계적으로 하지 않았다는 점이다. 의존성 업데이트는 대체로 지금 필요한 기능이 최신 버전에 있을 때만 하는 경우가 많았고, 주기적인 점검은 문화 자체에 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 결과, 프로젝트 전체가 구버전에 강하게 결합돼 버리는 일이 많았다. 한두 개 패키지를 바꾸는 데도 관련된 모든 코드가 줄줄이 영향을 받아 안정성을 해치는 경우가 많았다. 이런 상황을 겪고 나서야 &amp;ldquo;처음부터 조금씩 관리했으면 더 좋았을 텐데&amp;rdquo;라는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 지금은 &lt;/span&gt;&lt;span&gt;ncu&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;npm audit&lt;/span&gt;&lt;span&gt;을 기반으로 한 &lt;/span&gt;&lt;b&gt;정기적인 의존성 관리 루틴이 단지 보안을 위한 게 아니라, 프로젝트를 오래도록 안정적으로 유지하는 가장 현실적인 방법&lt;/b&gt;&lt;span&gt;이라고 생각하게 됐다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;자주, 작게, 꾸준히&lt;/b&gt;&lt;/span&gt; 관리하는 것이 결국엔 더 빠르고 더 안전한 길이다.&lt;/p&gt;</description>
      <category>개발/개발 환경</category>
      <category>cursor</category>
      <category>NCU</category>
      <category>node.js</category>
      <category>NPM</category>
      <category>npm audit</category>
      <category>백엔드 보안</category>
      <category>보안 점검</category>
      <category>의존성 관리</category>
      <category>패키지 업데이트</category>
      <category>프론트엔드 보안</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/50</guid>
      <comments>https://think-dev.tistory.com/50#entry50comment</comments>
      <pubDate>Thu, 27 Mar 2025 09:31:34 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript Enum, 그리고 숨어있는 활용 꿀팁</title>
      <link>https://think-dev.tistory.com/49</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;TypeScript의 Enum의 기본 개념과 사용법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Enum이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Enum(열거형)은 TypeScript에서 여러 개의 상수 값을 하나의 그룹으로 묶어 관리할 수 있게 도와주는 데이터 타입이다. 주로 코드의 가독성을 높이고, 유지보수를 편리하게 하는 데 사용된다. Enum을 사용하면 숫자나 문자열 값을 명확한 이름으로 나타낼 수 있어 코드 작성과 관리가 쉬워진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Enum의 기본 사용법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 Enum 사용법은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;enum Direction {
  Up,
  Down,
  Left,
  Right,
}

let move: Direction = Direction.Up;
console.log(move); // 0 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서&amp;nbsp;Direction은 Enum 타입으로,&amp;nbsp;Up,&amp;nbsp;Down,&amp;nbsp;Left,&amp;nbsp;Right는 Enum의 멤버이다. Enum 멤버는 기본적으로 0부터 시작하여 자동으로 증가하는 숫자 값을 갖는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Enum의 값 설정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Enum의 멤버 값은 원하는 값으로 직접 설정할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;enum Direction {
  Up = 1,
  Down,
  Left,
  Right,
}

console.log(Direction.Down); // 2 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서&amp;nbsp;Up을 1로 설정하면 나머지 멤버는 자동으로 1씩 증가한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문자열 Enum&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서는 문자열 값도 Enum 멤버로 사용할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}

console.log(Direction.Left); // &quot;LEFT&quot; 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 Enum은 코드를 좀 더 직관적으로 만들어 주고, 디버깅 시 유용하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Enum의 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Enum은 아래와 같은 상황에서 특히 유용하게 사용된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명확한 상태 관리를 위한 값 정의&lt;/li&gt;
&lt;li&gt;코드 가독성 향상&lt;/li&gt;
&lt;li&gt;오타 방지 및 코드 유지보수 용이&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Enum을 적극적으로 사용하면 코드 품질을 높이고, 협업 시에도 더 나은 코드 일관성을 유지할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Enum을 활용한 다양한 접근 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체로서 Enum의 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript의 Enum은 type이나 interface와는 달리 컴파일 이후에도 존재한다. 즉, TypeScript의 Enum은 컴파일 시 JavaScript 객체로 변환되어 결과물에 포함된다는 말이다. 따라서&amp;nbsp;Object.keys,&amp;nbsp;Object.values,&amp;nbsp;Object.entries&amp;nbsp;등을 이용해 Enum의 값을 동적으로 활용할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}

const directions = Object.values(Direction);
console.log(directions); // [&quot;UP&quot;, &quot;DOWN&quot;, &quot;LEFT&quot;, &quot;RIGHT&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UI 구성 시 Enum 활용 예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 UI를 구성할 때, 예를 들어 선택 옵션(select option) 목록을 구성하는 데에도 유용하다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;enum Color {
  Red = '빨강',
  Green = '초록',
  Blue = '파랑',
}

// Enum을 이용한 select option 생성 예제
const options = Object.entries(Color).map(([key, value]) =&amp;gt; ({
  label: value,
  value: key
}));

console.log(options);
/* 출력 결과:
[
  { label: &quot;빨강&quot;, value: &quot;Red&quot; },
  { label: &quot;초록&quot;, value: &quot;Green&quot; },
  { label: &quot;파랑&quot;, value: &quot;Blue&quot; }
]
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 접근법을 활용하면 Enum을 보다 실용적이고 다양한 방식으로 사용할 수 있다.&lt;/p&gt;</description>
      <category>개발/프로그래밍 언어</category>
      <category>enum</category>
      <category>enum ui 활용</category>
      <category>enum 객체</category>
      <category>enum 옵션 생성</category>
      <category>enum 활용법</category>
      <category>typescript</category>
      <category>typescript enum</category>
      <category>이넘</category>
      <category>타입스크립트 enum</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/49</guid>
      <comments>https://think-dev.tistory.com/49#entry49comment</comments>
      <pubDate>Wed, 19 Mar 2025 08:54:44 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript에서 interface와 type 중 무엇을 사용할까?</title>
      <link>https://think-dev.tistory.com/48</link>
      <description>&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;TypeScript에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;을 모두 사용하여 객체의 구조를 정의할 수 있다. 하지만 두 가지 개념 사이에는 미묘한 차이가 있다. 이번 글에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;의 특징과 차이점, 그리고 언제 어떤 것을 사용하는 것이 더 적절한지 정리해보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;의 특징&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;interface&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;는 TypeScript에서 객체의 구조를 정의하는 기본적인 방법으로, 다음과 같은 특징을 가진다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;객체의 구조를 명확하게 정의할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;선언 병합(Declaration Merging)이 가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;implements&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드를 사용하여 클래스에서 타입 검사를 수행할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드를 사용해 확장할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;type&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;은 보다 범용적인 타입 정의 방식으로, 객체뿐만 아니라 다양한 타입을 정의할 때도 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;유니온 타입(&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;) 또는 인터섹션 타입(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;)을 지원한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;튜플&lt;/span&gt;&lt;span&gt;이나 특정한 타입 조합을 정의할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기본 타입(alias)을 정의할 때 사용할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;처럼 선언 병합이 불가능하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;연산자를 사용하면 유사한 효과를 낼 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;언제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;를 사용할까?&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot; data-spread=&quot;false&quot;&gt;
&lt;li&gt;&lt;span&gt;클래스에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;implements&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드를 사용할 때이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른 정적 타입 언어(Java, C# 등)에서의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface + implements&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;조합과 동일한 개념이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;확장이 필요한 경우이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;의 인터섹션(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;)도 확장이 가능하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;를 사용하는 것이 의미 전달 측면에서 더 직관적이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;React 컴포넌트의 Props를 정의할 때이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;단순 객체라면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;을 사용하는 것이 간편하지만, React 컴포넌트의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt;는 확장될 가능성이 크기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;를 사용하는 것이 유리하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;다만 선언 병합은 지양하자.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;의 특징인 선언 병합은 코드 가독성이 떨어질 수 있으므로 피하는 것이 좋다. 필요하다면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;의 인터섹션(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;)을 활용하는 것이 낫다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;언제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;을 사용할까?&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;유니온(&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;) 또는 인터섹션(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) 타입을 사용할 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;튜플이나 특정한 타입 조합을 만들 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기본 타입(alias)을 정의할 때&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;TypeScript에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;이 공존하는 이유&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;TypeScript는 JavaScript에 정적 타입 시스템을 추가한 언어로, 다양한 프로그래밍 스타일을 지원하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 가지 개념을 제공한다. 초기에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;를 기본으로 사용하도록 권장되었지만, 점차&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;의 활용도가 높아지면서 개발자들은 필요에 따라 적절히 섞어서 사용하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이론적으로는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;만 사용해도 개발이 가능하다. 그래서 일부 팀에서는 별다른 고민 없이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;만 쓰는 컨벤션을 정하기도 한다. 그러나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;만 사용한다고 해서 최선의 선택이 되는 것은 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;다른 언어에서의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;의 활용&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;TypeScript의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;개념은 Java나 C# 같은 정적 타입 언어의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와 유사하다. 이들 언어에서도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;를 이용해 클래스의 구조를 정의하고 강제할 수 있다. 반면, TypeScript의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;은 Go나 Scala의 타입 별칭(&lt;/span&gt;&lt;span&gt;type alias&lt;/span&gt;&lt;span&gt;)과 유사한 개념으로 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;결론:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;을 어떻게 사용할까?&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;내가 생각하는 현재 시점(2025년 기준)에서 가장 합리적인 선택은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;클래스에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;implements&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드를 사용할 때는 &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;를 쓰자.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;확장이 필요한 경우 &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;를 사용하자.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;React 컴포넌트의 Props를 정의할 때 i&lt;/span&gt;&lt;span&gt;nterface&lt;/span&gt;&lt;span&gt;를 쓰는 것이 좋다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;그 외에는 &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;을 사용하는 것이 일반적으로 더 유연하고 편리하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;선언 병합은 피하자.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;팀 컨벤션이 가장 중요하다&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;위의 가이드는 절대적인 정답은 아니다. 시간이 지나면서 더 나은 방법이 나올 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;가장 중요한 것은 팀의 컨벤션을 따르는 것이다. 새로운 컨벤션을 정한다면 이 글이 참고할 만한 가치가 있겠지만, 기존의 컨벤션이 있다면 이를 유지하는 것이 팀 협업에서 더 중요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;사실 interface와 type을 그날 기분대로 골라 써도 휴먼 에러를 크게 유발하거나 하는 것은 아니기 때문에 이미 자리잡은 컨벤션이 있다면 그것을 지키는 것이 우선이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;결론적으로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;을 적절히 조합하여 사용하고, 팀 내부의 일관성을 유지하는 것이 가장 좋은 접근 방식이다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/프로그래밍 언어</category>
      <category>frontend</category>
      <category>interface</category>
      <category>javascript</category>
      <category>react</category>
      <category>type</category>
      <category>typescript</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <category>타입스크립트</category>
      <category>프론트엔드</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/48</guid>
      <comments>https://think-dev.tistory.com/48#entry48comment</comments>
      <pubDate>Wed, 19 Feb 2025 09:58:14 +0900</pubDate>
    </item>
    <item>
      <title>아직도 현역, 웹 프론트엔드 개발자의 MacBook Pro (M1 Pro) 32GB RAM 리뷰</title>
      <link>https://think-dev.tistory.com/47</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;네 번째 맥북 리뷰다. 돌이켜보니 2021년에만 세 번 포스팅을 했고, 벌써 3년이 훌쩍 지났다. 2025년 2월이 된 지금, 현역으로 쓰고 있는 맥북 프로(M1 Pro) 32GB RAM 이야기를 해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2021년 세 차례 리뷰를 돌아보며&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;첫 번째 리뷰: MacBook Air M1 기본형 (2021년 4월)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2021년 4월에 맥북 에어 M1 기본형(8GB RAM)을 리뷰했었다. 지금은 상상하기 힘든 8GB RAM이었지만 당시에는 만족스러웠다. 특히 인텔 맥 대비 배터리 성능이 크게 좋아졌고, 애플 실리콘 칩을 정식으로 지원하지 않는 앱조차 로제타를 통해 빠릿하게 돌아가는 모습이 인상적이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1739838463901&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;웹 개발자의 M1 MacBook Air 기본형 사용 후기&quot; data-og-description=&quot;2021년 3월 26일에 그 유명한 M1 맥북에어를 배송받았다. 나름 대학생이라 학생 할인을 받아서 116만원에 구매하고, 선물로 받은 에어팟2 유선은 당근에 팔았다. 어차피 업무용으로 쓸게 아니고 개&quot; data-og-host=&quot;think-dev.tistory.com&quot; data-og-source-url=&quot;https://think-dev.tistory.com/12&quot; data-og-url=&quot;https://think-dev.tistory.com/12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cMlY0W/hyYf08IECn/Yut4amUQZsZyok52hByQ7K/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/vbtvl/hyYfSbrAPi/YKeX9QCpa2ryOTqtiHkBA1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cTEPOm/hyYfTV3Et2/rOvestwcFZeqPqp3VtG9Dk/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788&quot;&gt;&lt;a href=&quot;https://think-dev.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://think-dev.tistory.com/12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cMlY0W/hyYf08IECn/Yut4amUQZsZyok52hByQ7K/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/vbtvl/hyYfSbrAPi/YKeX9QCpa2ryOTqtiHkBA1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cTEPOm/hyYfTV3Et2/rOvestwcFZeqPqp3VtG9Dk/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;웹 개발자의 M1 MacBook Air 기본형 사용 후기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2021년 3월 26일에 그 유명한 M1 맥북에어를 배송받았다. 나름 대학생이라 학생 할인을 받아서 116만원에 구매하고, 선물로 받은 에어팟2 유선은 당근에 팔았다. 어차피 업무용으로 쓸게 아니고 개&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;think-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;두 번째 리뷰: MacBook Pro M1 (2021년 7월)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그해 7월에는 회사에서 지급받은 맥북 프로 M1 모델을 잠깐 써봤다. M1 Pro 칩이 아닌, 순수 M1 칩이 들어 있던 모델이었다. 인텔 맥북과 거의 같은 디자인이어서 조금 과도기적이라는 생각이 들었다. 맥북 에어와 비교해 포트가 늘고 모니터를 2대 연결할 수 있다는 점이 그나마 감동이었지만, 무게가 무거웠고 팬도 열심히 돌아서 &amp;lsquo;프로&amp;rsquo;라는 이름만큼의 인상은 주지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1739838500318&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;웹 프론트엔드 개발자의 M1 MacBook Pro (16GB RAM, 1TB SSD) 사용 후기 (+ Caldigit TS3 Plus 썬더볼트 3 독, 리&quot; data-og-description=&quot;맥북 에어 후기는 지난 포스트를 참고 바란다. 웹 개발자의 M1 MacBook Air 기본형 사용 후기 2021년 3월 26일에 그 유명한 M1 맥북에어를 배송받았다. 나름 대학생이라 학생 할인을 받아서 116만원에 구&quot; data-og-host=&quot;think-dev.tistory.com&quot; data-og-source-url=&quot;https://think-dev.tistory.com/32&quot; data-og-url=&quot;https://think-dev.tistory.com/32&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJol5G/hyYfPF5jxE/KjTFwjiVW8xil8PRmcPgvk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/inrfw/hyYf2yF99e/dxFLM9szjhxMKonlcegCr0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/4NfnO/hyYfDezB55/YDQ7a4WM3WkHmwbh9qej60/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788&quot;&gt;&lt;a href=&quot;https://think-dev.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://think-dev.tistory.com/32&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJol5G/hyYfPF5jxE/KjTFwjiVW8xil8PRmcPgvk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/inrfw/hyYf2yF99e/dxFLM9szjhxMKonlcegCr0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/4NfnO/hyYfDezB55/YDQ7a4WM3WkHmwbh9qej60/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;웹 프론트엔드 개발자의 M1 MacBook Pro (16GB RAM, 1TB SSD) 사용 후기 (+ Caldigit TS3 Plus 썬더볼트 3 독, 리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;맥북 에어 후기는 지난 포스트를 참고 바란다. 웹 개발자의 M1 MacBook Air 기본형 사용 후기 2021년 3월 26일에 그 유명한 M1 맥북에어를 배송받았다. 나름 대학생이라 학생 할인을 받아서 116만원에 구&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;think-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;세 번째 리뷰: MacBook Air M1 재리뷰 (2021년 11월)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4월에 리뷰했던 맥북 에어 M1 기본형을 실무 장비로 직접 써보고 다시 리뷰를 썼다. 당시 회사에서는 장비를 따로 지급하지 않아서 개인 맥북을 사용할 수밖에 없었다. 로컬 서버를 장시간 돌리고, 4K 모니터를 연결하며, 원격 근무를 위한 애플리케이션을 항상 켜둘 수밖에 없었는데 결국 감당하기 어려운 수준의 발열과 성능 한계를 느꼈다.&lt;/p&gt;
&lt;figure id=&quot;og_1739838530306&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;웹 개발자의 M1 MacBook Air 기본형 실무에 사용 후기&quot; data-og-description=&quot;드디어 진정한 프로급의 M1 Pro/Max 칩이 탑재된 맥북 프로가 출시되었다. 아직 한국에는 판매 중이 아니고 곧 구매할 수 있을 거라 기대되는데... 나는 목이 빠지게 기다리고 있다. 웹 개발자의 M1 M&quot; data-og-host=&quot;think-dev.tistory.com&quot; data-og-source-url=&quot;https://think-dev.tistory.com/40&quot; data-og-url=&quot;https://think-dev.tistory.com/40&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kQ9SS/hyYf5a9ecG/EtbCCDkfdCatgIMaCDGxK0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/b3w1oX/hyYfBA4En1/SuprhRNUs1aLFAK8M1Vwlk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/fbkip/hyYf4pLdgL/cs5sVknt93nWeLfyA5EsSk/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788&quot;&gt;&lt;a href=&quot;https://think-dev.tistory.com/40&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://think-dev.tistory.com/40&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kQ9SS/hyYf5a9ecG/EtbCCDkfdCatgIMaCDGxK0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/b3w1oX/hyYfBA4En1/SuprhRNUs1aLFAK8M1Vwlk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/fbkip/hyYf4pLdgL/cs5sVknt93nWeLfyA5EsSk/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;웹 개발자의 M1 MacBook Air 기본형 실무에 사용 후기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;드디어 진정한 프로급의 M1 Pro/Max 칩이 탑재된 맥북 프로가 출시되었다. 아직 한국에는 판매 중이 아니고 곧 구매할 수 있을 거라 기대되는데... 나는 목이 빠지게 기다리고 있다. 웹 개발자의 M1 M&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;think-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MacBook Pro M1 Pro 32GB RAM, 3년째 잘 쓰고 있다&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2021년 11월 포스팅에서도 M1 Pro 칩 얘기를 잠깐 했었는데, 한국에는 출시가 안 돼 사지 못했다며 아쉬워했다. 이후 한국에 풀리자마자 맥북 프로(M1 Pro) 모델을 샀다. 구입 시기가 2021년 12월 아니면 2022년 1월쯤이었는데, 놀랍게도 2025년 2월인 지금까지도 불편함 없이 잘 쓰고 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;불편함이 없다. 오히려 더 좋아진다&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가끔 윈도우 프로그램이 필요할 때를 제외하면 전혀 불편하지 않다. 요즘 웹 환경이 점차 표준화되고, 스마트폰으로 할 수 있는 일도 늘어나면서 윈도우 PC 자체를 거의 켜지 않고 지낸다. 집에 오래된 프린터가 하나 있는데 맥 최신 OS와 호환이 안 돼서, 1년에 두세 번 정도 인쇄할 일이 생길 때만 윈도우 PC를 잠깐 켜는 정도다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롬, 파이어폭스, JetBrains IntelliJ, MySQL, 기타 여러 애플리케이션과 수십 개의 브라우저 탭을 동시에 띄워도 버벅이지 않는다. IntelliJ에 Github Copilot을 연동했을 때 잠시 느려진 적이 있었지만, 최대 힙 크기를 늘려놓으니 문제없이 돌아갔다. 동영상 편집이나 AI&amp;middot;머신러닝 작업을 로컬에서 굴리지 않는 이상, 앞으로도 최소 몇 년은 더 쓸 수 있을 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 말하는 일상은 그냥 웹서핑이 아니다. 실제 프론트엔드 개발 실무에서 썼을 때를 말한다. 2022년에 처음 샀을 당시부터 실무에 썼고, 이직한 뒤에도 회사에서 지급받은 장비가 동일하게 맥북 프로(M1 Pro) 32GB RAM이었다. 지금 회사에서는 빌드에 10분 넘게 걸리는 Monorepo를 다루고 있음에도 큰 불편을 느끼지 않았다. 물론 백엔드 개발이나 빌드 환경을 집중적으로 만지는 분들은 가끔 부족함을 느낀다고 하긴 했다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;웹 프론트엔드 개발자에겐 최고의 가성비 장비&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 이 맥북 프로(M1 Pro)를 샀을 때는 400만 원이 넘었지만, 지금은 중고 시세가 100만 원 중반에서 200만 원 초반 정도라고 들었다. 같은 급의 최신 모델(M4 Pro)을 살펴보면 램이 24GB 혹은 48GB로 갈리는데, 어떤 옵션으로 구성해도 300~400만 원은 예상해야 할 것 같다. M칩이 벌써 4세대까지 나왔으니 일반 M칩을 고려해도 램을 24GB 이상 맞추려면 300만 원 이상 든다는 얘기를 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 프론트엔드 개발 중심으로 일을 하고, 백엔드나 기타 분야도 조금씩 다룰 예정이며, 동시에 여러 애플리케이션을 켜놓고 쓸 거지만 로컬에서 동영상 편집이나 AI&amp;middot;머신러닝까지는 안 돌릴 거라면, 중고 M1 Pro 맥북이 가장 합리적이라고 생각한다. 그래도 웹개발 분야에서 컴퓨팅 자원을 많이 쓸 것 같아 걱정된다고 해도, 웬만하면 큰 문제 없이 돌아간다고 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;기타 옵션: 14인치? 16인치? SSD 용량?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥북 프로(M1 Pro)는 14인치와 16인치 모델이 있다. 둘 다 성능은 같고 모니터 크기만 다르다. 개인적으로는 16인치가 들고 다니기엔 너무 무거워서, 지금은 14인치만 쓰고 있다. 어차피 좋은 모니터에 연결해두고 쓰기 때문에 화면 크기는 상관없다고 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSD 용량도 가격에 영향을 많이 준다. 회사 장비라면 512GB여도 괜찮았지만, 개인 장비로는 사진이나 동영상 같은 멀티미디어 파일이 쌓일 수 있어서 1TB 이상이 좋다고 생각했다. 자금 사정이 괜찮다면 용량을 더 크게 가져가는 게 마음 편하다.&lt;/p&gt;</description>
      <category>리뷰/전자제품</category>
      <category>m1 pro vs m4 pro</category>
      <category>macbook pro 중고</category>
      <category>가성비 맥북</category>
      <category>맥북 프로 32gb ram</category>
      <category>맥북 프로(m1 pro)</category>
      <category>웹 프론트엔드 개발</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/47</guid>
      <comments>https://think-dev.tistory.com/47#entry47comment</comments>
      <pubDate>Tue, 18 Feb 2025 09:29:58 +0900</pubDate>
    </item>
    <item>
      <title>소프트웨어 코드 테스트에 대한 나의 생각 - 프론트엔드 테스트는 필요할까</title>
      <link>https://think-dev.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;소프트웨어 개발에서 코드 테스트는 단순히 실행해 보며 기능을 확인하는 단계를 넘어, 코드 품질 개선과 유지보수성 향상, 그리고 장기적인 제품 안정성을 보장하는 핵심 요소로 자리 잡았다. 여기서 언급하는 테스트는 제품을 직접 사용하는 방식이 아니라, 코드 기반의 자동화 테스트를 의미한다. 개인적으로는 유닛 테스트를 주로 활용하며, TDD(Test-Driven Development) 방법론을 선호한다. 직접 주도하지는 않았지만, 테스트 커버리지 100%를 달성한 경험이 있으며, 테스트가 전혀 없는 환경에서 테스트 문화를 구축하고 지속적으로 커버리지를 향상시킨 경험도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다양한 테스트 방법론과 적용 방식&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD 외에도 BDD(Behavior-Driven Development)와 DDD(Domain-Driven Design) 같은 개념이 존재하지만, 이들 방법론은 테스트에 대한 이해와 일정 수준의 성숙도를 요구하므로 조직과 프로젝트의 특성에 맞게 적절히 적용해야 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;b&gt;BDD&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비즈니스 요구사항을 중심으로 테스트를 작성하는 방법으로, 팀 내 협업이 중요한 환경에서 특히 유용하다. 다만, 효과적으로 활용하려면 개발 프로세스뿐만 아니라 팀 내 소통 방식도 개선되어야 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;b&gt;DDD&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 중심 설계를 강조하는 방법론으로, 도메인의 핵심 개념을 명확히 정의하고 이를 코드에 반영하는 과정이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 방법론이 무조건 우월한 것은 아니며, 프로젝트와 팀의 특성에 맞는 적절한 조합을 찾아 활용하는 것이 중요하다. 실제 프로젝트에서는 여러 방법론을 혼합해 사용하는 경우가 많다. 예를 들어, 핵심 로직에는 TDD를 적용하고 사용자 인터페이스(UI) 테스트에는 BDD를 활용할 수 있다. 또한, 도메인 모델이 중요한 대규모 프로젝트에는 DDD가 적합하지만, 작은 스타트업에서는 다소 과할 수 있다. 결국 각 방법론의 특성을 충분히 이해하고 상황에 맞게 조합하는 능력이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;테스트의 필요성과 흔한 오해&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 경우 테스트는 소프트웨어 품질을 높이는 긍정적인 역할을 하지만, 몇 가지 예외적인 상황도 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;테스트가 필수적이지 않은 경우&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;인력과 시간이 극도로 제한된 상황에서 프로토타입을 빠르게 제작해야 할 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;매우 단순한 기능만 포함된 작은 프로젝트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;PoC(Proof of Concept) 단계에서 신속한 검증이 필요한 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 장기적으로 유지보수가 필요한 제품이라면 테스트는 반드시 필수적이다. &amp;ldquo;테스트를 하면 개발 시간이 부족하다&amp;rdquo;는 의견이 자주 나오지만, 일정 수준 이상의 개발자라면 테스트 경험이 전무하더라도 2주에서 보름 정도면 충분히 익숙해질 수 있다. 단순히 시간이 부족하다는 이유만으로 테스트를 생략하는 것은 설득력이 부족하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트를 수행하면 코드의 신뢰성이 높아지고, 향후 코드 변경 시 발생할 수 있는 리스크를 최소화할 수 있다. 또한, 개발자들이 자신감을 가지고 코드를 리팩토링할 수 있는 환경이 마련되어 장기적으로 개발 속도를 높이는 효과도 있다. 테스트가 도입된 환경에서는 코드 수정이나 기능 추가가 보다 유연해져, 결국 유지보수 비용을 절감할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;테스트가 코드 품질에 미치는 영향&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지속적으로 테스트를 작성하면 자연스레 테스트하기 쉬운 코드가 만들어진다. 이러한 코드는 가독성이 높고 유지보수가 용이하며 확장성이 뛰어나다. 테스트는 단순히 실패 시 버그를 잡는 기능을 넘어, 코드 구조와 설계 자체를 개선하는 데에도 큰 기여를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트를 작성하는 과정에서 자연스럽게 모듈화와 관심사의 분리에 대해 고민하게 되며, 예를 들어 테스트하기 쉬운 코드를 만들기 위해 의존성 주입(DI, Dependency Injection)을 도입하거나 단일 책임 원칙(SRP, Single Responsibility Principle)을 따르게 된다. 이러한 습관이 쌓이면 개발자는 점점 유지보수성이 뛰어난 코드를 작성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 테스트는 협업 환경에서도 큰 역할을 한다. 새로운 개발자가 기존 코드를 이해하는 데 도움을 주고, 코드 리뷰 과정에서 논리적 오류를 사전에 방지할 수 있다. 특히 대규모 팀에서는 테스트가 코드 변경 사항을 추적하는 역할을 하여, 코드가 수정될 때 기존 기능이 정상적으로 동작하는지 확인할 수 있다는 점에서 필수적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프론트엔드 테스트의 중요성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드에서는 테스트가 불필요하다는 의견이 종종 제기되지만, 이는 오해이다. UI/UX 요소는 변화 가능성이 높지만, 실제로는 전체적인 디자인 개편보다는 기능 확장이나 개선이 주를 이룬다. 따라서 UI 변경을 이유로 테스트를 배제하는 것은 타당하지 않다. 오히려 UI 확장이나 기능 추가 과정에서 테스트가 없다면 예상치 못한 문제를 발견하기 어려워질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더불어, 프론트엔드에서 UI/UX를 제외한 핵심 로직&amp;mdash;예를 들어 상태 관리, 데이터 처리, API 통신 등&amp;mdash;은 애플리케이션의 중요한 부분이다. 이러한 기능들이 올바르게 동작하는지 확인하기 위해서는 테스트가 필수적이다. 즉, UI의 변화 가능성을 이유로 테스트를 회피하기보다는, 확장성과 유지보수를 고려하여 전략적으로 테스트를 수행하는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 테스트는 성능 최적화에도 기여할 수 있다. 성능 테스트를 통해 애플리케이션의 부하를 점검하면 병목 현상을 미리 발견하고 개선할 수 있으며, 이는 사용자 경험을 크게 향상시킨다. 특히 대규모 트래픽을 처리해야 하는 서비스에서는 더욱 중요한 요소이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 &amp;ldquo;테스트를 할 것인가 말 것인가&amp;rdquo;를 고민하기보다는, 특정 상황에서 어떤 테스트 전략을 선택할 것인지 고민하는 것이 더 중요해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 테스트는 단순한 버그 검출을 넘어, 코드 품질과 개발 프로세스를 개선하는 핵심 도구이다. 개발자는 프로젝트와 팀의 상황에 맞게 다양한 테스트 전략을 적절히 조합하고, 지속적으로 개선하는 자세가 필요하다. 테스트가 개발 프로세스의 필수적인 부분으로 자리 잡을수록 더욱 신뢰할 수 있는 소프트웨어를 만들 수 있다.&lt;/p&gt;</description>
      <category>개발</category>
      <category>BDD</category>
      <category>ddd</category>
      <category>TDD</category>
      <category>소프트웨어 테스트</category>
      <category>유닛 테스트</category>
      <category>코드 테스트</category>
      <category>코드 품질 향상</category>
      <category>테스트 자동화</category>
      <category>테스트 커버리지</category>
      <category>프론트엔드 테스트</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/46</guid>
      <comments>https://think-dev.tistory.com/46#entry46comment</comments>
      <pubDate>Tue, 11 Feb 2025 08:32:57 +0900</pubDate>
    </item>
    <item>
      <title>Next.js에서 Firebase Remote Config(원격 구성) 수정하기</title>
      <link>https://think-dev.tistory.com/44</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Firebase Remote Config란 애플리케이션의 각종 기본값들을 Firebase를 통해 손쉽게 관리할 수 있도록 하는 클라우드 툴이다.&lt;/p&gt;
&lt;figure id=&quot;og_1640124940004&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Firebase 원격 구성 &amp;nbsp;|&amp;nbsp; Firebase Documentation&quot; data-og-description=&quot;앱 업데이트를 게시하지 않고도 일일 활성 사용자 수 제한 없이 무료로 앱의 동작과 모양을 변경할 수 있습니다.&quot; data-og-host=&quot;firebase.google.com&quot; data-og-source-url=&quot;https://firebase.google.com/docs/remote-config?authuser=0&quot; data-og-url=&quot;https://firebase.google.com/docs/remote-config?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://firebase.google.com/docs/remote-config?authuser=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://firebase.google.com/docs/remote-config?authuser=0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Firebase 원격 구성 &amp;nbsp;|&amp;nbsp; Firebase Documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;앱 업데이트를 게시하지 않고도 일일 활성 사용자 수 제한 없이 무료로 앱의 동작과 모양을 변경할 수 있습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;firebase.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각종 기본값들의 경우 애플리케이션의 탭 리스트가 될 수도 있고 각종 스태틱한 값들이 될 수 있다. 이러한 값들의 경우 서비스 기획이나 정책에 따라 언제든지 변경될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 경우 보통 데이터베이스와 백엔드를 통해 관리를 하게 되는데 이것을 구현하는게 어렵지는 않지만 번거롭고 시간이 걸릴 수 있어서 프로덕트 스케줄에서 우선순위에서 밀릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이러한 값들은 처음에는 하드코딩해서 들어가는 경우가 왕왕 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션의 경우 조금 귀찮긴 하지만 언제든지 수정 배포가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 iOS나 Android 애플리케이션의 경우 배포 단계에서 구글 또는 애플의 심사 과정이 있으며, 사용자가 앱을 업데이트하는 데까지 시간이 걸리며, 일부 유저들은 끝까지 업데이트를 하지 않는 경우도 있기 때문에 서버 사이드를 통한 기본값 관리가 필수적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 규모가 작은 프로덕트 팀에서는 이러한 원격 구성 툴을 많이들 쓰곤 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-12-22 오전 7.22.17.png&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBDqZx/btrotlnKM3s/Nb8xgqKwfGq1VyAxWHkid1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBDqZx/btrotlnKM3s/Nb8xgqKwfGq1VyAxWHkid1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBDqZx/btrotlnKM3s/Nb8xgqKwfGq1VyAxWHkid1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBDqZx%2FbtrotlnKM3s%2FNb8xgqKwfGq1VyAxWHkid1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1324&quot; height=&quot;475&quot; data-filename=&quot;스크린샷 2021-12-22 오전 7.22.17.png&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 매개변수를 추가/수정 등이 가능하고 값을 바꾸면 애플리케이션에도 동적으로 반영이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 처음에는 좋다고 쓰지만 나중에는 파이어베이스 콘솔에 들어와서 저걸 또 수정하고 하는 작업들이 번거로워지게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 정말 자유롭게 수정할 수 있기 때문에 담당자가 혹시라도 잘못 건들면 그 순간 애플리케이션에서는 에러가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 담당자는 엔지니어가 아닐 확률이 매우 높으며, 이런 실수를 방지하기 위해 엔지니어에게 매번 요청하는 것도 번거롭다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 이러한 값들을 변경할 때는 엔지니어링 관점에서 구조적으로 뜯어고치는 것보다 운영팀에서 의사결정 후 빠르게 변경하는 경우가 많은데 매번 엔지니어에게 요청할 수는 없지 않은가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 내부 백오피스를 통해서 이러한 값들을 열람하고 수정하고 추가하는 등의 수요가 있을 수밖에 없다. 백오피스를 통해 개발을 하게 되면 특정 값들의 구조적인 제한도 자유롭게 걸 수 있고 이에 따른 UI도 편안하게 마련할 수 있기 때문에 일단 만들어 놓으면 운영팀에서 자유롭게 관리가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스트에서는 백오피스가 Next.js로 되어 있는 케이스에서 어떻게 적용하면 될지 다룬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 Firebase에서 제공하는 API나 SDK가 필요한데 다행히 둘 다 있으며, 여기에서는 SDK를 사용하는 방식을 다룬다.&lt;/p&gt;
&lt;figure id=&quot;og_1640125753512&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래매틱 방식으로 원격 구성 수정 &amp;nbsp;|&amp;nbsp; Firebase Documentation&quot; data-og-description=&quot;의견 보내기 프로그래매틱 방식으로 원격 구성 수정 이 문서에서는 JSON 형식의 매개변수 및 조건 집합을 프로그래매틱 방식으로 읽고 수정할 수 있는 원격 구성 템플릿에 대해 설명합니다. 이 &quot; data-og-host=&quot;firebase.google.com&quot; data-og-source-url=&quot;https://firebase.google.com/docs/remote-config/automate-rc?authuser=0&quot; data-og-url=&quot;https://firebase.google.com/docs/remote-config/automate-rc?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://firebase.google.com/docs/remote-config/automate-rc?authuser=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://firebase.google.com/docs/remote-config/automate-rc?authuser=0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래매틱 방식으로 원격 구성 수정 &amp;nbsp;|&amp;nbsp; Firebase Documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;의견 보내기 프로그래매틱 방식으로 원격 구성 수정 이 문서에서는 JSON 형식의 매개변수 및 조건 집합을 프로그래매틱 방식으로 읽고 수정할 수 있는 원격 구성 템플릿에 대해 설명합니다. 이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;firebase.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 파이어베이스 콘솔에 들어가서 아래 스크린샷과 같이 설정 아이콘을 누르고 &quot;프로젝트 설정&quot;에 접근한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-12-22 오전 7.31.51.png&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;193&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjoreL/btrowjXhQ8Z/2JtH8Nnue77lp8d95trum1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjoreL/btrowjXhQ8Z/2JtH8Nnue77lp8d95trum1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjoreL/btrowjXhQ8Z/2JtH8Nnue77lp8d95trum1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjoreL%2FbtrowjXhQ8Z%2F2JtH8Nnue77lp8d95trum1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;393&quot; height=&quot;193&quot; data-filename=&quot;스크린샷 2021-12-22 오전 7.31.51.png&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;193&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &quot;서비스 계정&quot; 탭으로 들어가면 아래와 같은 화면이 보인다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-12-22 오전 7.34.48.png&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;809&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VDQG6/btroxjvWZrI/ZwuG0TovfMjdU1KT1NVTKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VDQG6/btroxjvWZrI/ZwuG0TovfMjdU1KT1NVTKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VDQG6/btroxjvWZrI/ZwuG0TovfMjdU1KT1NVTKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVDQG6%2FbtroxjvWZrI%2FZwuG0TovfMjdU1KT1NVTKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;918&quot; height=&quot;809&quot; data-filename=&quot;스크린샷 2021-12-22 오전 7.34.48.png&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;809&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &quot;새 비공개 키 생성&quot;을 누르면 json 파일이 다운로드되는데 이제 이걸 가지고 인증을 하고 SDK를 활용할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 json 파일만 있으면 누구든지 나의 파이어베이스에 접근해 무슨 짓이든 할 수 있으니 반드시 잘 보관해야 하며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;이 파일이 절대로 Public으로 호스팅 되거나 클라이언트 사이드에서 접근할 수 있게 하면 안 된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 프로젝트에서 다음과 같이 firebase-admin을 설치한다.&lt;/p&gt;
&lt;pre id=&quot;code_1640125838357&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ npm install firebase-admin&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Admin SDK의 로직은 절대로 클라이언트 사이드에서 돌면 안 되기 때문에 이 로직은 src/pages/api/ 하위에 둘 것이며, 클라이언트 사이드, 즉 React 컴포넌트에서는 이러한 Next.js의 api 라우트를 활용하여 콜 해서 쓸 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래부터 설명하는 예시는 말 그대로 아주 간단한 예시일 뿐이며, 파일이나 세부 로직은 각 프로덕트의 성격이나 코딩 규칙에 따라 적절히 바꾸고 응용해서 쓰면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그야말로 돌아가게끔만 만든 코드일 뿐 각종 예외처리 등은 별도로 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 다운로드한 json 파일을 프로젝트에 넣자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서는 src/keys/config-adminsdk.json에 넣었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀의 보안 정책에 따라서 프로젝트 내부에 넣지 않고 또 다른 어딘가에 저장해 두고 API로 당겨서 사용할 수도 있으니 참고하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 API를 만들자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;src/pages/api/config/parameters.ts&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from 'next';
import admin, { remoteConfig } from 'firebase-admin';
import serviceAccount from 'keys/config-adminsdk.json';

interface ResData {
    parameters: { [p: string]: remoteConfig.RemoteConfigParameter };
}

// WAS가 떠 있을 때 한번만 호출하면 된다. 다른 방식으로 처리할 수도 있지만 그냥 귀찮아서 try catch문으로 처리했다.
// 만약 아무런 처리가 없으면 중복으로 초기화됐다고 에러가 나면서 진행되지 않을 것이다.
try {
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount as unknown as string),
    });
} catch (err) {}

export default async (req: NextApiRequest, res: NextApiResponse&amp;lt;ResData&amp;gt;) =&amp;gt; {
    const config = admin.remoteConfig();
    const { parameters } = await config.getTemplate();

    res.status(200).json({ parameters });
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;src/pages/api/config/patch.ts&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from 'next';
import admin from 'firebase-admin';
import serviceAccount from 'keys/config-adminsdk.json';

try {
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount as unknown as string),
    });
} catch (err) {}

export default async (req: NextApiRequest, res: NextApiResponse) =&amp;gt; {
    const config = admin.remoteConfig();
    const template = await config.getTemplate();

    const { key, value } = req.body;

    template.parameters[key] = {
        defaultValue: {
            value,
        },
    };

    await config.publishTemplate(template);

    res.status(200).json({});
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. /api/config/parameters를 호출하여 원격 구성의 값들을 가져올 수 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. /api/config/patch를 호출하여 원격 구성의 값들을 수정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 필요하다면 추가하는 작업까지 가능하나 여기서는 두 가지만 다룬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 클라이언트 사이드에서 폼을 만들고 이 API들을 호출하여 값을 가져오고 수정하는 코드를 보자. 이 역시 돌아가게끔만 만든 아주 간단한 예제로 적절히 응용하고 완성도 있게 바꿔서 써야 한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;import axios from 'axios';
import { NextPage } from 'next';
import React, { useEffect, useState } from 'react';

interface ResData {
    parameters: any; // 역시 귀찮아서 이렇게 했다. 상황에 따라 타입을 잘 만들어주면 된다.
}

const Firebase: NextPage = () =&amp;gt; {
    const [key1, setKey1] = useState('loading');
    const [inputKey, setInputKey] = useState('');

    const fetchData = async () =&amp;gt; {
        const { parameters } = (await axios.get('/api/config/parameters')).data as ResData;

        setKey1(String(parameters.key1.defaultValue.value));
    };

    const updateData = async () =&amp;gt; {
        setKey1('변경중...');

        await axios.patch('/api/config/patch', {
            key: 'key1',
            value: inputKey,
        });

        await fetchData();
    };

    useEffect(() =&amp;gt; {
        fetchData().then();
    }, []);
    return (
        &amp;lt;div&amp;gt;
            &amp;lt;div&amp;gt;
                &amp;lt;h1&amp;gt;key1&amp;lt;/h1&amp;gt;
                &amp;lt;p&amp;gt;{key1}&amp;lt;/p&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;input
                        type=&quot;text&quot;
                        value={inputKey}
                        onChange={(e) =&amp;gt; {
                            setInputKey(e.target.value);
                        }}
                    /&amp;gt;
                    &amp;lt;button onClick={updateData}&amp;gt;변경&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    );
};

export default Firebase;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 로드가 되면 우리가 파이어베이스 콘솔에서 세팅한 값이 보일 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 텍스트 필드에 값을 넣어서 옆에 변경 버튼을 누르면 &quot;변경중...&quot;이라고 값이 바뀌었다가 좀 기다리면 새로 세팅한 값이 나타나면 성공이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이어베이스 콘솔에 가서 보면 잘 바뀌어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이어베이스의 리모트 컨피그(원격 구성)를 프로덕트에서 활용할 때 백오피스에서 이런 식으로 기능을 만들면 엔지니어로서 귀찮은 일이 사라지고 운영팀에서도 보다 수월하게 프로덕트를 운영할 수 있다.&lt;/p&gt;</description>
      <category>개발/웹 개발</category>
      <category>firebase</category>
      <category>firebase-admin</category>
      <category>next.js</category>
      <category>react.js</category>
      <category>Remote Config</category>
      <category>리모트 컨피그</category>
      <category>원격 구성</category>
      <category>파이어베이스</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/44</guid>
      <comments>https://think-dev.tistory.com/44#entry44comment</comments>
      <pubDate>Wed, 22 Dec 2021 07:57:16 +0900</pubDate>
    </item>
    <item>
      <title>Typescript 타입을 배열로 정의해보자</title>
      <link>https://think-dev.tistory.com/43</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Typescript는 Javascript를 Java, C, Swift, Kotlin처럼 정적 타입으로 쓸 수 있게 해주는 Javascript의 슈퍼셋이다. 빌드가 되면 브라우저 또는 Node.js가 이해할 수 있는 퓨어한 Javascript로 바뀌어 동적 타입인 Javascript의 태생적 한계를 극복하고 Javascript 생태계를 보다 안정적으로 쓸 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음을 살펴보자&lt;/p&gt;
&lt;pre id=&quot;code_1640038153621&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let a = 1;
console.log(typeof a); // number

a = 'abc'
console.log(typeof a); // string&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript는 이처럼 변수를 선언해서 number 타입을 넣었다가 string 타입을 넣었다가 자유롭게 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 동적 타입이기 때문에 때로는 변수를 자유자재로 활용할 수 있으나 코드가 복잡하지고 길어지면 숫자를 넣어야 할 곳에 문자를 넣어 예기치 못한 에러가 발생할 수 있으며, 이는 실제 애플리케이션이 돌아가는 런타임에서만 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 예를 보자&lt;/p&gt;
&lt;pre id=&quot;code_1640038403307&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a = {
    abc: 1,
    bcd: 'aaa',
    efg: ['a', 'b', 'c']
};

a.hij = 'hello';
a.bcd = 3;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 a에는 없는 key인 hij를 넣어도 에러가 안나고 자연스럽게 hij라는 key가 생기고 'hello'라는 문자열 값이 들어가게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 기존 bcd는 문자열 타입이었으나 3이라는 숫자 타입을 넣어도 문제가 없이 잘 진행이 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-12-21 오전 7.16.42.png&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;87&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cH427N/btroplm5rSF/FwOMr5oaq7uw0P67LKdWz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cH427N/btroplm5rSF/FwOMr5oaq7uw0P67LKdWz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cH427N/btroplm5rSF/FwOMr5oaq7uw0P67LKdWz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcH427N%2Fbtroplm5rSF%2FFwOMr5oaq7uw0P67LKdWz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;484&quot; height=&quot;87&quot; data-filename=&quot;스크린샷 2021-12-21 오전 7.16.42.png&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;87&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 스크린샷처럼 IDE에서 인텔리센스를 통해 hij를 추론하지도 못한다.(물론 IDE에 따라 가능할 수도 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 위 예제를 Typescript로 바꿔보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-12-21 오전 7.19.16.png&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xAXyq/btroiaNvvgY/Qhng0fQDfDjEKdkJsm0WtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xAXyq/btroiaNvvgY/Qhng0fQDfDjEKdkJsm0WtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xAXyq/btroiaNvvgY/Qhng0fQDfDjEKdkJsm0WtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxAXyq%2FbtroiaNvvgY%2FQhng0fQDfDjEKdkJsm0WtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;506&quot; height=&quot;424&quot; data-filename=&quot;스크린샷 2021-12-21 오전 7.19.16.png&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;abc는 number, bcd는 string, efg는 string 배열, hij는 string이나 ?를 찍어서 옵션으로 두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 최초 a를 선언할 때 hij를 넣지 않아도 에러가 나지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 bcd에 3이라는 number 값을 넣으려고 하니 위와 같이 Type 'number' is not assignable to type 'string'이라는 에러가 떴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 Javascript라면 당연히 에러 없이 패스되는 케이스지만 Typescript에서는 에러가 발생하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 Typescript를 통해 보다 안전하게, 그리고 IDE에서 다양한 도움을 받을 수 있게 되어 개발이 보다 편해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 다음과 같은 케이스가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1640039103350&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type ColorType = 'white' | 'red' | 'yellow' | 'green' | 'black' | 'blue';
const color: ColorType = 'green';
const color2: ColorType = 'pink'; // error&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스의 경우 컬러 타입을 사전에 정의하고 이 타입에는 위에 나열한 컬러 문자열 값만 들어가도록 한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다음과 같이 color2와 같이 선언한다면 에러가 날 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본론이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 화면에 ColorType에서 정의한 컬러들을 나열해놓고 그 중에서 사용자에게 어떤 컬러를 선호하는지 받는다고 가정하자. 그럼 다음과 같이 colorList를 선언하고 이 배열을 이용해 UI를 멋지게 꾸밀 수 있을 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1640039299248&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type ColorType = 'white' | 'red' | 'yellow' | 'green' | 'black' | 'blue';
const colorList: ColorType[] = ['white', 'red', 'yellow', 'green', 'black', 'blue'];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제점을 캐치했을 것이다. 바로 똑같은 코드를 반복해서 썼다는 것이다. 프로그래밍에서 이런 케이스는 매우 좋지 않고 컬러값이 추가됐을 때 2군데 이상을 계속 수정해나가야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결 방법은 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1640039564489&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const COLORS = ['white', 'red', 'yellow', 'green', 'black', 'blue'] as const;

type ColorType = typeof COLORS[number]
const colorList: ColorType[] = [...COLORS]; // ['white', 'red', 'yellow', 'green', 'black', 'blue']
const colorList2: ColorType[] = ['pink']; // error&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1640039610297&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const COLORS = ['white', 'red', 'yellow', 'green', 'black', 'blue', 'pink'] as const;

type ColorType = typeof COLORS[number]
const colorList: ColorType[] = [...COLORS]; // ['white', 'red', 'yellow', 'green', 'black', 'blue', 'pink']
const colorList2: ColorType[] = ['pink']; // success&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;COLORS 배열을 한 번 선언함으로써 타입과 리스트 배열 변수를 멋지게 활용할 수 있게 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 기존 타입에 pink를 추가하고자 할 때 COLORS에만 추가를 하면 자연스럽게 타입도 바뀌며, 실제 사용할 때도 문제가 없게 된다.&lt;/p&gt;</description>
      <category>개발/프로그래밍 언어</category>
      <category>javscript</category>
      <category>typescript</category>
      <category>배열 타입</category>
      <category>자바스크립트</category>
      <category>타입스크립트</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/43</guid>
      <comments>https://think-dev.tistory.com/43#entry43comment</comments>
      <pubDate>Tue, 21 Dec 2021 07:37:24 +0900</pubDate>
    </item>
    <item>
      <title>[코로나 백신] 1차 얀센, 3차 모더나 접종 후기</title>
      <link>https://think-dev.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;팬데믹이 끝나지 않는다. 코로나19가 발생한지 2년이 넘어가고 있는데 대체 언제쯤 끝날까. 2차 접종까지 국민의 70%가 맞으면 집단면역이 가능해져서 마스크를 벗고 다녀도 된다는 예측은 이제 허상이 되어버렸다. 지난 6월, 내가 맞았던 얀센 백신도 한 번만 맞으면 된다는 장담도 이제 허상이 되었다.&lt;br&gt; &lt;br&gt;이제 누굴 탓해야 하는지도 모르겠다. 국내에 코로나를 널리 퍼뜨렸던 특정 종교와 그 신자들도 그때는 그렇게 욕을 많이 먹었는데 돌이켜보면 어차피 이렇게 될 거 좀 억울한 측면도 있지 않나 싶다.&lt;br&gt; &lt;br&gt;결과적으로 정부도 WHO도 제약회사들도 다 거짓말쟁이가 됐다. 그렇다고 누굴 탓하랴. 그냥 현실을 받아들이고 가장 현명하다고 하는 방법을 따르는 수밖에...&lt;br&gt; &lt;br&gt;그치만 화이자에서 2024년까지 코로나가 지속될 거고, 백신도 계속 맞아야 한다 뭐 그런 전망들은 이해하면서도 코로나로 돈 많이 버는 제약회사에 그러니 밉기도 하다.&lt;br&gt; &lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;코로나19 팬데믹 언제까지? 화이자 &amp;quot;2024년까지..&amp;quot;&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;글로벌 제약사 화이자 경영진이 코로바19가 2024년에는 독감과 유사한 풍토병이 될 것이라고 내다봤다./사진=뉴스1 [파이낸셜뉴스] 글로벌 제약사 화이자 경영진은 코로나19가 2024년에는 독감과 &quot; data-og-host=&quot;news.v.daum.net&quot; data-og-source-url=&quot;https://news.v.daum.net/v/20211218135311269&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bAznJ8/hyMKLNAVBj/0tWMPzOvZGg5GgZ9VGbeQ1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bL5Csf/hyMKNkli5c/loZevO3KqC5tJoIEiULvsk/img.jpg?width=570&amp;amp;height=321&amp;amp;face=0_0_570_321&quot; data-og-url=&quot;https://news.v.daum.net/v/ka2a6HSfbG&quot;&gt;
 &lt;a href=&quot;https://news.v.daum.net/v/ka2a6HSfbG&quot; target=&quot;_blank&quot; data-source-url=&quot;https://news.v.daum.net/v/20211218135311269&quot;&gt;
  &lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bAznJ8/hyMKLNAVBj/0tWMPzOvZGg5GgZ9VGbeQ1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bL5Csf/hyMKNkli5c/loZevO3KqC5tJoIEiULvsk/img.jpg?width=570&amp;amp;height=321&amp;amp;face=0_0_570_321')&quot;&gt; 
  &lt;/div&gt;
  &lt;div class=&quot;og-text&quot;&gt;
   &lt;p class=&quot;og-title&quot;&gt;코로나19 팬데믹 언제까지? 화이자 &quot;2024년까지..&quot;&lt;/p&gt;
   &lt;p class=&quot;og-desc&quot;&gt;글로벌 제약사 화이자 경영진이 코로바19가 2024년에는 독감과 유사한 풍토병이 될 것이라고 내다봤다./사진=뉴스1 [파이낸셜뉴스] 글로벌 제약사 화이자 경영진은 코로나19가 2024년에는 독감과 &lt;/p&gt;
   &lt;p class=&quot;og-host&quot;&gt;news.v.daum.net&lt;/p&gt;
  &lt;/div&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서두가 길었다.&lt;br&gt; &lt;br&gt;어쨌든 나는 지난 6월 12일에 얀센 코로나 백신을 맞았다. 오전 11시쯤에 주사를 맞고 집에 돌아와서 곧바로 타이레놀 2알을 먹었다. 오후 8시쯤 되니까 슬슬 오한이 오더니 열이 38도 전후로 나기 시작했다. 다시 타이레놀 2알을 먹었다. 30분 정도가 지나니 열이 정상수치로 내려오고 몸상태도 괜찮아졌다. 잠을 잤다. 새벽 4시쯤 깼다. 지난 저녁 8시에 느껴보지 못한, 그리고 과거 언젠가 엄청 앓았을 때의 느낌이 났다. 열도 38도가 넘고 오한, 인후통 등 꽤 세게 다가왔다. 다시 타이레놀 2알을 먹었다. 30분 정도가 지나니 아주 편안하지는 않지만 잠을 잘 정도까지는 괜찮아졌다. 다음날 9시쯤부터 일어나서 활동했는데 괜찮았다. 12시에서 1시 넘어갈 때 다시 열이 나기 시작했다. 역시 타이레놀 2알을 먹고 괜찮아졌다. 그날 저녁 8시에 다시 열이 나기 시작했으나 전날만큼 아프진 않았다. 또 타이레놀 2알을 먹었다. 이후에는 백신 부작용 증상이 나타나지 않았다.&lt;br&gt; &lt;br&gt;결과적으로 약 이틀 동안 발열, 오한, 인후통 등으로 꽤 앓았다. 아마 30년 넘게 살면서 겪은 감기몸살 중 세 손가락 안에 들지 않을까. 그때는 지금보다 백신이 귀했고 내 또래들은 잔여백신이 아니면 백신을 맞기 힘들던 시기였다. 그런데 미국 형님께서 대한민국 예비군과 민방위만을 위한 백신을 하사하니 왠지 2년 동안의 군복무를 인정 받는 느낌도 나고 특별 대우 받는 느낌도 나고 게다가 한방에 접종완료자가 된다니 이보다 좋을 수 없었다. 많이 아팠어도 기분은 좋았다. 이제 백신을 맞았으니 코로나 따위 다 이겨버릴 것만 같았다.&lt;br&gt; &lt;br&gt;11월 초였던 것으로 기억한다. 기존 얀센 백신 접종자들은 부스터샷을 맞아야한다는 보도가 나왔다. 얀센은 또 다른 백신들보다 효과가 덜하니 거의 필수적으로 맞아야 한다는... 억울했다. 나는 대한민국 예비군 출신 민방위로서 특별 대우를 받았다고 생각했는데, 아 또 속았나. 역시 군인들이 항상 실험 대상이고 잔반처리반이었나. 괜한 반발심이 생겨서 부스터샷을 맞지 않고 계속 버텼다.&lt;br&gt; &lt;br&gt;이번주 월요일(12월 13일)부터 방역패스를 도입했다. 이제 정부가 정한 주요 시설에서는 방역패스가 없으면 출입이 되지 않는다고 했다. 방역패스의 기준은 백신 접중 후 6개월까지. 어 생각해보니 6개월이 넘어버렸다. 더이상 버티기는 어려워서 어제 12월 17일에 부스터샷을 맞았다.&lt;br&gt; &lt;br&gt;부스터샷의 제약사는 모더나, 아가가 다니는 소아과로 예약해서 맞았다. 11시 예약이었는데 기다리가 싫어서 10시 좀 넘어서 가서 10시 18분쯤 접종을 완료했다. 팔에 힘을 쫙 빼고 맞았고 맞는줄도 모르고 끝났다. 얀센 맞을 땐 주사 맞고 약 들어가는 동안 꽤 아팠던 것으로 기억하는데 모더나는 주삿바늘이 들어가는 줄도 몰랐다. 15분 정도 병원에서 대기했는데 접종부위만 살짝 뻐근한 느낌만 나고 별다른 이상은 없었다.&lt;br&gt; &lt;br&gt;특이한 건 접종 증명서를 받았는데 이번에 맞은게 2차를 건너뛰고 3차라는 것!! 나는 코로나 백신을 두 번 맞았는데 3차 접종이다. 혼란스럽다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1113&quot; data-origin-height=&quot;1592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0Zwv8/btrocT5jvge/zxepYiZqdcL7zM77o7w6g0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0Zwv8/btrocT5jvge/zxepYiZqdcL7zM77o7w6g0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0Zwv8/btrocT5jvge/zxepYiZqdcL7zM77o7w6g0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Zwv8%2FbtrocT5jvge%2FzxepYiZqdcL7zM77o7w6g0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1113&quot; height=&quot;1592&quot; data-origin-width=&quot;1113&quot; data-origin-height=&quot;1592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;br&gt;이후 가족끼리 동네 카페에 가서 놀고, 집에 돌아와서는 타이레놀 2알을 먹고 뒹굴거리면서 아가랑 놀고 집안일도 하고 그랬다. 저녁 먹고 자기 전까지도 별다른 증상이 없었고 이마 열도 정상이었다. 아 팔은 점점 아파왔다. 가벼운 물건도 못 들 정도는 아니었지만 어쨌든 아팠다. 자기 전에 다시 타이레놀 2알을 먹었다. 1차 접종 때의 아픈 기억 때문에 긴장했지만 밤새 별일을 없었다. 지금 이 글을 쓰고 있는 백신 접종 다음날 오후에도 그냥 건강하다. 정상이다. 다만 내가 잘 때 왼쪽으로 누워 자는 습관이 있는데, 나도 모르게 그 자세를 할 때마다 접종 부위가 아팠는지 계속 깼다. 접종 부위는 항간에 모더나 암이라고 할 정도로 부풀어 오르거나 아프지는 않지만, 그냥 좀 불편한 정도이다.&lt;br&gt; &lt;br&gt;무사히 지나갔으면 좋겠고,&lt;br&gt; &lt;br&gt;세상아 부탁컨대 코로나 예방접종 10차 막 이렇게는 가지 않게 하자. 응?&lt;br&gt;&lt;br&gt;— 추가&lt;br&gt;3차 백신 접종 후 약 54시간 후 나는 매우매우 멀쩡하다. &lt;/p&gt;</description>
      <category>일상</category>
      <category>3차접종</category>
      <category>모더나</category>
      <category>방역패스</category>
      <category>부스터샷</category>
      <category>얀더나</category>
      <category>얀센</category>
      <category>코로나19</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/41</guid>
      <comments>https://think-dev.tistory.com/41#entry41comment</comments>
      <pubDate>Sat, 18 Dec 2021 15:37:00 +0900</pubDate>
    </item>
    <item>
      <title>웹 개발자의 M1 MacBook Air 기본형 실무에 사용 후기</title>
      <link>https://think-dev.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 진정한 프로급의 M1 Pro/Max 칩이 탑재된 맥북 프로가 출시되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 한국에는 판매 중이 아니고 곧 구매할 수 있을 거라 기대되는데... 나는 목이 빠지게 기다리고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1635463054595&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;웹 개발자의 M1 MacBook Air 기본형 사용 후기&quot; data-og-description=&quot;2021년 3월 26일에 그 유명한 M1 맥북에어를 배송받았다. 나름 대학생이라 학생 할인을 받아서 116만원에 구매하고, 선물로 받은 에어팟2 유선은 당근에 팔았다. 어차피 업무용으로 쓸게 아니고 개&quot; data-og-host=&quot;think-dev.tistory.com&quot; data-og-source-url=&quot;https://think-dev.tistory.com/12&quot; data-og-url=&quot;https://think-dev.tistory.com/12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/0WwNu/hyL8HfnB1p/rysEXw471A1dky3CRfl5U1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bcfkph/hyL8JdbR2B/dEjGZI9CAVrjdOEcyEUWQ1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/buDC6m/hyL8L9VFDa/8l7LbEimTg1GYJUNAjWqa1/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788&quot;&gt;&lt;a href=&quot;https://think-dev.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://think-dev.tistory.com/12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/0WwNu/hyL8HfnB1p/rysEXw471A1dky3CRfl5U1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bcfkph/hyL8JdbR2B/dEjGZI9CAVrjdOEcyEUWQ1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/buDC6m/hyL8L9VFDa/8l7LbEimTg1GYJUNAjWqa1/img.jpg?width=788&amp;amp;height=788&amp;amp;face=0_0_788_788');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;웹 개발자의 M1 MacBook Air 기본형 사용 후기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2021년 3월 26일에 그 유명한 M1 맥북에어를 배송받았다. 나름 대학생이라 학생 할인을 받아서 116만원에 구매하고, 선물로 받은 에어팟2 유선은 당근에 팔았다. 어차피 업무용으로 쓸게 아니고 개&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;think-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 지난 4월 25일에 3월 26일에 구입한 맥북 에어 기본형을 바탕으로 위와 같은 포스팅을 한 적이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스팅에서 100% 아니 200% 만족한다고 썼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 약 7개월 정도 사용했는데, 여전히 개인용 개발 작업으로 만족하지만 이걸 실무에서 하드하게 사용하니 생각이 조금 달라졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해는 나에게 많은 변화가 있던 해였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3년이 넘게 다닌 회사를 4월에 퇴사하고 5월에 새로운 회사에 입사하고, 다시 이번 10월에 현재 다니는 회사에 입사하여 아직 한 달도 채 되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4월에 퇴사한 회사에서는 인텔 i9 64GB RAM 16인치 맥북 프로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5월에 입사한 회사에서는 M1 16GB RAM 13인치 맥북 프로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 10월에 입사한 현재 회사에서는 내가 원래 보유했던 M1 맥북 에어 기본형(8GB RAM)을 쓰고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 전 회사들에서는 장비가 지급되었고 현재 회사에서는 BYOD라고 자신이 소유한 장비를 활용하고 연봉 외 장비 지원금을 지급하는 형태이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인텔 칩은 어느 정도 만족했으나 무겁고 펜이 맨날 돌아가서 시끄러웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M1 16GB RAM 13인치 맥북 프로는 모니터가 한대밖에 연결되지 않았지만 꽤 만족스러웠고 불편함이 없이 썼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 M1 맥 라인에서 가장 스펙이 떨어지는 맥북 에어 기본형을 실무에 아주 하드하게 활용하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로 말하자면 웹 프론트엔드 개발자로서 맥북 에어 기본형을 활용하기엔 문제가 좀 많다는 것!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이것도 모니터가 한대밖에 연결되지 않은 것은 불만이지만 뭐 원래 알던 거니 그러려니 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 웹 프론트엔드를 회사에서 전문적으로 한다면 대충 이 정도는 띄워놓지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 브라우저&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 크롬을 베이스로 작업중인 로컬 호스팅 페이지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기타 참고할 만한 여러 페이지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 크롬 외 브라우저에서의 작업중인 로컬 호스팅 페이지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. IDE&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 현재 작업중인 프로젝트 =&amp;gt; 개발 모드로 로컬 호스팅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 현재 작업중인 프로젝트에 상응하는 API 프로젝트 =&amp;gt; 개발 모드로 로컬 호스팅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 다른 참고할 만한 프로젝트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 기타&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DB 클라이언트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 피그마&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 제플린&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 슬랙&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저에서 상용 웹페이지들을 여러 개 막 띄우는 것 자체는 M1에서는 전혀 무리가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이제 개발을 한다고 IDE를 여러개 막 띄우고 이에 맞춰 브라우저도 띄우고 코드를 고치면서 계속 컴퓨팅 자원을 소모한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 여기서 그치지 않고 필요하다면 DB 클라이언트도 띄워고 디자인 툴인 피그마나 제플린도 띄워놓게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 사람들과 소통해야하니 메신저인 슬랙도 띄운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 업무용이라면 거의 당연히 모니터 한대 연결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 모니터도 아니고 최소 QHD, UHD(4K) 등을 연결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;슬슬 무리가 오기 시작하지만 M1에서는 충분히 감당 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특이점으로 지금 다니는 회사는 거의 대부분의 직원들이 재택근무를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 화상미팅이 자주 있고, 문서의 실시간 공유를 중요시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서는 화상미팅 툴로 디스코드를 쓰고 있고, 문서 공유 툴로 큅을 쓰고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화상 미팅은 많으면 10명 정도 참여를 하고 길어지면 2시간이 넘기도 하고 이 와중에 문서 공유 툴에서 실시간으로 회의록이 기록되고 필요하다면 내 화면을 보여주기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 여기서 우리의 맥북 에어가 미치기 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손을 갖다 대면 뜨겁고 메모리도 부족해지고 화상미팅에선 내가 멈춰있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M1 맥북 에어 기본형은 &quot;혼자서&quot; 무겁게 작업해도 아쉬움은 있지만 큰 무리는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 재택근무를 하면서 많은 사람들과 소통할 때는 써먹지 못할 만한 물건이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 M1 Pro 32GB RAM 맥북 프로로 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언제 나오냐....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>리뷰/전자제품</category>
      <category>apple</category>
      <category>m1</category>
      <category>M1 Max</category>
      <category>M1 Pro</category>
      <category>Macbook</category>
      <category>개발자</category>
      <category>맥북에어</category>
      <category>맥북프로</category>
      <category>재택근무</category>
      <category>프론트</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/40</guid>
      <comments>https://think-dev.tistory.com/40#entry40comment</comments>
      <pubDate>Mon, 1 Nov 2021 07:34:46 +0900</pubDate>
    </item>
    <item>
      <title>전라도 여행(5) - 나주곰탕</title>
      <link>https://think-dev.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;전라도 여행 5번째 포스트는 &quot;나주곰탕&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여행지인 나주가 아닌 나주곰탕인 이유는 정말로 나주곰탕만 먹으러 나주에 갔기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2007년 대학교 1학년을 다닐 때 학교에서 전라도로 답사를 간 적이 있는데 나주 답사를 할 때 나주곰탕을 먹었었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그때 먹었던 식당이 어디인지는 모르겠으나 정말로 너무너무 맛있어서 나의 인생 국밥이 됐었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 나주목사 근처에서 먹었던 것으로 기억하여 지도를 검색해봤더니 정말로 그 근처가 나주곰탕 촌이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 진도를 빠져나와 무작정 나주목사로 향했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주차를 하고 &quot;나주곰탕 노안집&quot;이라는 식당으로 갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 택한 이유는 그냥 주차장이랑 가까워서...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-filename=&quot;IMG_2953.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRwgl6/btrfKByUafo/Z94kkp3bITsxHoi98NzCy0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRwgl6/btrfKByUafo/Z94kkp3bITsxHoi98NzCy0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRwgl6/btrfKByUafo/Z94kkp3bITsxHoi98NzCy0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRwgl6%2FbtrfKByUafo%2FZ94kkp3bITsxHoi98NzCy0%2Fimg.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-filename=&quot;IMG_2953.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노안이 노인의 얼굴을 말하는 건가 했더니 나주시에 &quot;노안면&quot;이라는 행정구역이 있고 그 동네를 뜻하는 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-filename=&quot;IMG_2951.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpwqCU/btrfIY18C42/2q82z56ffhGJTv1LLs3J11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpwqCU/btrfIY18C42/2q82z56ffhGJTv1LLs3J11/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpwqCU/btrfIY18C42/2q82z56ffhGJTv1LLs3J11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpwqCU%2FbtrfIY18C42%2F2q82z56ffhGJTv1LLs3J11%2Fimg.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-filename=&quot;IMG_2951.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-filename=&quot;IMG_2952.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzmEBG/btrfREOlWr7/nQYFFqToVk2IHq8WbUb2gK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzmEBG/btrfREOlWr7/nQYFFqToVk2IHq8WbUb2gK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzmEBG/btrfREOlWr7/nQYFFqToVk2IHq8WbUb2gK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzmEBG%2FbtrfREOlWr7%2FnQYFFqToVk2IHq8WbUb2gK%2Fimg.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-filename=&quot;IMG_2952.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 맛을 어떻게 표현해야할지 모르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 너무 맛있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깍두기는 2007년의 그 맛이 아니었지만 고기는 그때 그 집보다 훨씬 많이 들어갔고 쫀득쫀득했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식당 한쪽에서는 막 지은 가마솥의 밥을 뒤섞고 있었고 또 한쪽에서는 주문된 곰탕을 내놓기 위해 곰탕이 담긴 뚝배기에 밥을 토렴하고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다. 이 집의 나주곰탕은 토렴국밥이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토렴을 했기 때문에 밥이 따로 나오지 않고 말아서 나왔고, 밥알에 국물이 잘 배어있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한쪽 벽면에는 수많은 싸인들이 걸려있었는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 눈에 띄는 것은 문재인 대통령의 사진이었다. 대통령이 대통령 시절에 다년간 건지 그 전인지는 모르겠지만 아무튼 그 정도로 맛있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특으로 먹을걸 후회했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나주곰탕을 뒤로하고 나는 광주에 예약한 숙소로 가서 1박을 하고 아침에 다시 집으로 돌아가서 사실상 나주곰탕을 끝으로 여행이 마무리가 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언제쯤 우리 아들이 커서 다시 여기에 오려나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe mapdata=&quot;addr=%EC%A0%84%EB%82%A8%20%EB%82%98%EC%A3%BC%EC%8B%9C%20%EA%B8%88%EA%B3%84%EB%8F%99%2023-5&amp;amp;addtype=1&amp;amp;confirmid=25048962&amp;amp;docid=&amp;amp;idx=1&amp;amp;ifrH=362px&amp;amp;ifrW=490px&amp;amp;mapHeight=362&amp;amp;mapInfo=%7B%22version%22%3A2%2C%22mapWidth%22%3A490%2C%22mapHeight%22%3A362%2C%22mapCenterX%22%3A435330%2C%22mapCenterY%22%3A426548%2C%22mapLevel%22%3A4%2C%22coordinate%22%3A%22wcongnamul%22%2C%22markInfo%22%3A%5B%7B%22markerType%22%3A%22standPlace%22%2C%22coordinate%22%3A%22wcongnamul%22%2C%22x%22%3A435334%2C%22y%22%3A426554%2C%22clickable%22%3Atrue%2C%22draggable%22%3Atrue%2C%22icon%22%3A%7B%22width%22%3A35%2C%22height%22%3A56%2C%22offsetX%22%3A17%2C%22offsetY%22%3A56%2C%22src%22%3A%22%2F%2Ft1.daumcdn.net%2Flocalimg%2Flocalimages%2F07%2F2012%2Fattach%2Fpc_img%2Fico_marker2_150331.png%22%7D%2C%22content%22%3A%22%EC%82%BC%EB%8C%80%EB%82%98%EC%A3%BC%EA%B3%B0%ED%83%95%EC%9B%90%EC%A1%B0%EC%A7%91%20%EB%85%B8%EC%95%88%EC%A7%91%22%2C%22confirmid%22%3A25048962%7D%5D%2C%22graphicInfo%22%3A%5B%5D%2C%22roadviewInfo%22%3A%5B%5D%7D&amp;amp;mapWidth=490&amp;amp;mapX=435330&amp;amp;mapY=426548&amp;amp;map_hybrid=false&amp;amp;map_level=4&amp;amp;map_type=TYPE_MAP&amp;amp;rcode=4617054000&amp;amp;tel=061-333-2053&amp;amp;title=%EC%82%BC%EB%8C%80%EB%82%98%EC%A3%BC%EA%B3%B0%ED%83%95%EC%9B%90%EC%A1%B0%EC%A7%91%20%EB%85%B8%EC%95%88%EC%A7%91&quot; src=&quot;/proxy/plusmapViewer.php?id=maps_1632439807489&quot; id=&quot;maps_1632439807489&quot; width=&quot;540px&quot; height=&quot;350px&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; data-ke-type=&quot;map&quot; data-maps-data=&quot;addr=%EC%A0%84%EB%82%A8%20%EB%82%98%EC%A3%BC%EC%8B%9C%20%EA%B8%88%EA%B3%84%EB%8F%99%2023-5&amp;amp;addtype=1&amp;amp;confirmid=25048962&amp;amp;docid=&amp;amp;idx=1&amp;amp;ifrH=362px&amp;amp;ifrW=490px&amp;amp;mapHeight=362&amp;amp;mapInfo=%7B%22version%22%3A2%2C%22mapWidth%22%3A490%2C%22mapHeight%22%3A362%2C%22mapCenterX%22%3A435330%2C%22mapCenterY%22%3A426548%2C%22mapLevel%22%3A4%2C%22coordinate%22%3A%22wcongnamul%22%2C%22markInfo%22%3A%5B%7B%22markerType%22%3A%22standPlace%22%2C%22coordinate%22%3A%22wcongnamul%22%2C%22x%22%3A435334%2C%22y%22%3A426554%2C%22clickable%22%3Atrue%2C%22draggable%22%3Atrue%2C%22icon%22%3A%7B%22width%22%3A35%2C%22height%22%3A56%2C%22offsetX%22%3A17%2C%22offsetY%22%3A56%2C%22src%22%3A%22%2F%2Ft1.daumcdn.net%2Flocalimg%2Flocalimages%2F07%2F2012%2Fattach%2Fpc_img%2Fico_marker2_150331.png%22%7D%2C%22content%22%3A%22%EC%82%BC%EB%8C%80%EB%82%98%EC%A3%BC%EA%B3%B0%ED%83%95%EC%9B%90%EC%A1%B0%EC%A7%91%20%EB%85%B8%EC%95%88%EC%A7%91%22%2C%22confirmid%22%3A25048962%7D%5D%2C%22graphicInfo%22%3A%5B%5D%2C%22roadviewInfo%22%3A%5B%5D%7D&amp;amp;mapWidth=490&amp;amp;mapX=435330&amp;amp;mapY=426548&amp;amp;map_hybrid=false&amp;amp;map_level=4&amp;amp;map_type=TYPE_MAP&amp;amp;rcode=4617054000&amp;amp;tel=061-333-2053&amp;amp;title=%EC%82%BC%EB%8C%80%EB%82%98%EC%A3%BC%EA%B3%B0%ED%83%95%EC%9B%90%EC%A1%B0%EC%A7%91%20%EB%85%B8%EC%95%88%EC%A7%91&quot; data-maps-mapx=&quot;435330&quot; data-maps-mapy=&quot;426548&quot; data-maps-thumbnail=&quot;https://ssl.daumcdn.net/map3/staticmap/image?center=435330%2C426548&amp;amp;lv=4&amp;amp;size=540x350&amp;amp;srs=WCONGNAMUL&amp;amp;markers=symbol%3Asc_marker%7Clocation%3A435334%2C426554&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상/여행</category>
      <category>나주곰탕</category>
      <category>노안집</category>
      <category>대통령</category>
      <category>문재인</category>
      <category>여행</category>
      <category>전라도</category>
      <category>토렴국밥</category>
      <author>꾸럭</author>
      <guid isPermaLink="true">https://think-dev.tistory.com/39</guid>
      <comments>https://think-dev.tistory.com/39#entry39comment</comments>
      <pubDate>Fri, 24 Sep 2021 08:31:08 +0900</pubDate>
    </item>
  </channel>
</rss>