<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>xtring.dev</title>
    <link>https://xtring-dev.tistory.com/</link>
    <description>&amp;quot;세상을 보고 무수한 장애물을 넘어 벽을 허물고 더 가까이 다가가, 서로를 알아가고 느끼는 것, 그것이 바로 우리가 살아가는 인생의 목적이다.&amp;quot;</description>
    <language>ko</language>
    <pubDate>Tue, 30 Jun 2026 03:45:27 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>xtring</managingEditor>
    <image>
      <title>xtring.dev</title>
      <url>https://tistory1.daumcdn.net/tistory/3454876/attach/7713b233a2de4f02a349601803907ccf</url>
      <link>https://xtring-dev.tistory.com</link>
    </image>
    <item>
      <title>[React] React UI 패키지를 개발하기 위해 필요한 것들(feat. 다중 어플리케이션에 적용하기)</title>
      <link>https://xtring-dev.tistory.com/entry/React-%EC%84%B8-%EA%B0%9C%EC%9D%98-%EC%95%B1%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-React-UI-%ED%8C%A8%ED%82%A4%EC%A7%80-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-03-02 at 23.53.45.png&quot; data-origin-width=&quot;1546&quot; data-origin-height=&quot;1566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgC71G/btsMAMmMJpQ/Ut1LigoWHAY5qRKJuQ9DL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgC71G/btsMAMmMJpQ/Ut1LigoWHAY5qRKJuQ9DL1/img.png&quot; data-alt=&quot;&amp;quot;세 개 앱에서 사용할 UI 패키지를 만들어야 한다구요?&amp;quot;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgC71G/btsMAMmMJpQ/Ut1LigoWHAY5qRKJuQ9DL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgC71G%2FbtsMAMmMJpQ%2FUt1LigoWHAY5qRKJuQ9DL1%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;1546&quot; height=&quot;1566&quot; data-filename=&quot;Screenshot 2025-03-02 at 23.53.45.png&quot; data-origin-width=&quot;1546&quot; data-origin-height=&quot;1566&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&quot;세 개 앱에서 사용할 UI 패키지를 만들어야 한다구요?&quot;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 새로운 프로젝트 중 React 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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 기술 스펙 정의하기 ⭐️⭐️⭐️&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; React UI 패키지를 각각 다른 스팩을 가진 앱들에서 사용하기 위해서는 기술 스택과 스팩에 대해서 면밀한 고려가 필요합니다. 저의 경우엔 UI 패키지는 최신 React를 사용하고 싶었고, 해당 패키지를 사용하는 앱들의 React 버전은 모두 상이했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 기술 스택&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; UI 패키지는 &lt;code&gt;Vite&lt;/code&gt; 번들러와 최신 &lt;code&gt;React 18&lt;/code&gt; 버전을 선택하여 개발하고 싶었으며, &lt;code&gt;TypeScript&lt;/code&gt; 사용 가능한 높은 버전을 활용하고 싶었습니다. 스타일링은 &lt;code&gt;Vanilla Extract&lt;/code&gt;을 선택하였습니다. &lt;code&gt;Vanilla Extract&lt;/code&gt;는 일반적으로 많이 사용되는 다른 css-in-js 라이브러리와 다르게 정적 CSS 파일을 생성하여 run-time에 CSS를 생성하지 않고, 번들 사이즈도 작아 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;패키지의 최적화를 위해 package.json 파일에 &lt;code&gt;sideEffects: false&lt;/code&gt; 설정을 적용했습니다. 이 설정은 사용되지 않는 불필요한 코드가 포함되지 않도록 합니다. 번들 사이즈를 줄여 사용하는 앱에서도 부담을 많이 줄일 수 있습니다. 하지만 일부 경우 예상치 못한 동작을 유발할 수 있어, tree-shaking이 정상적으로 동작하는지 충분한 테스트가 필요합니다.&lt;/p&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;code&gt;Storybook&lt;/code&gt;를 활용하며, 개발된 최신 UI들을 눈으로 바로바로 확인할 수 있도록 했습니다.(Storybook에 대해서도 할 얘기가 많지만 이번 글에서는 포함하지 않고 다른 글을 작성해보겠습니다) 코드 품질을 유지하기 위해 &lt;code&gt;ESLint&lt;/code&gt;, &lt;code&gt;Prettier&lt;/code&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;code&gt;애자일(agile)&lt;/code&gt;의 일부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인 &lt;b&gt;&amp;ldquo;빠르게 만들기 위해서 제대로 만들어야 한다&amp;rdquo;&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;2. UI 컴포넌트 정의하기 ⭐️⭐️&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 어떤 요소를 조합하여 여러 케이스에서 활용하기 위해서는 가장 작은 단위의 요소를 조립(;조합)하여 사용하는 것이 가장 확장성과 유지보수성을 보장할 수 있습니다. 따라서 해당 UI 패키지는 앱에서 사용될 가장 작은 단위의 요소부터 개발되었습니다. 해당 패키지는 상품상세의 상품설명을 구성하는 요소들을 UI 컴포넌트 조합으로 만들기 위해서 만들어졌습니다. 따라서 가장 작은 단위는 텍스트, 이미지, 버튼, 아코디언, 슬라이드 등이 될 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;⛓️ 설계를 위한 정의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특별히 &lt;b&gt;Atomic Design System&lt;/b&gt;을 철저히 준수하기보다 UI 패키지가 각 앱에서 사용될 UI를 고려하여 프로젝트 디렉토리를 설계했습니다. 가장 작은 단위는 텍스트, 이미지, 버튼, 아코디언, 슬라이드 등으로 정의하고 에디터앱과 상품설명을 구성하기 위해 모듈(Module)과 블록(Block)이라는 단위를 만들었습니다. 그렇게하여 구성을 위한 가장 작은 단위의 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;기술적으로는 React 18의 Strict Mode에서도 정상적으로 동작하도록 개발 했습니다. 그러나 Strict Mode에서는 &lt;code&gt;useEffect&lt;/code&gt;의 실행 방식이 달라질 수 있으므로, 주요 훅(&lt;code&gt;useEffect&lt;/code&gt;, &lt;code&gt;useLayoutEffect&lt;/code&gt; 등)의 동작을 점검했습니다. Next.js를 어플리케이션에서도 사용할 예정이라 SSR을 지원해야 하는 환경에서도 안정적으로 사용할 수 있도록 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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. TypeScript 버전이 다른 애플리케이션을 지원하는 방법 ⭐️⭐️⭐️&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; UI 패키지를 사용하는 애플리케이션마다 TypeScript 버전이 다를 경우, 타입 정의 파일(&lt;code&gt;.d.ts&lt;/code&gt;)의 호환성 문제 또는 빌드 과정에서 에러가 발생할 수 있습니다. 아래 사항들을 필수적으로 고려해야합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  필수 고려 사항&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;최소 요구 TypeScript 버전 명시하기&lt;/b&gt;&lt;br /&gt;&lt;code&gt;package.json&lt;/code&gt;의 &lt;code&gt;peerDependencies&lt;/code&gt;에 최소 요구 TypeScript 버전을 명확히 설정합니다. 하지만 이 값이 실제 프로젝트에서 사용하는 TypeScript 기능과 맞는지 주기적으로 검토해야 합니다.TypeScript 최신 기능을 적극적으로 사용하려면 최소 요구 버전을 높게 설정할 필요가 있습니다. &lt;code class=&quot;language-json&quot;&gt;&quot;peerDependencies&quot;: {
  &quot;typescript&quot;: &quot;&amp;gt;=4.3.0&quot;
}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;타입 정의 파일 별도 제공&lt;/b&gt;&lt;br /&gt;&lt;code&gt;.d.ts&lt;/code&gt; 파일을 패키지 내부에 포함하되, &lt;code&gt;tsconfig.json&lt;/code&gt;의 &lt;code&gt;declarationMap&lt;/code&gt; 옵션을 활용하여 타입 정보를 명확하게 제공할 수 있습니다. 이를 통해 개발자가 TypeScript 버전과 무관하게 정확한 타입 정보를 확인할 수 있습니다. &lt;code class=&quot;language-json&quot;&gt;&quot;compilerOptions&quot;: {
  &quot;declaration&quot;: true,
  &quot;declarationMap&quot;: true
}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 TypeScript 버전 테스트&lt;/b&gt;&lt;br /&gt;GitHub Actions를 활용하여 다양한 TypeScript 버전에서 정상적으로 동작하는지 테스트합니다. 최신 LTS 버전까지 포함하는 것이 중요합니다.이를 통해 여러 버전에서 타입 충돌이 발생하지 않도록 검증할 수 있습니다. &lt;code class=&quot;language-yaml&quot;&gt;strategy:
  matrix:
    ts-version: [4.3.5, 4.5.4, 4.7.0, 5.0.0]&lt;/code&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;⚠️ 고려사항&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최신 TypeScript 기능을 사용할 경우, 낮은 버전을 사용하는 애플리케이션에서 빌드 오류가 발생할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strict&lt;/code&gt; 옵션을 강제하면 TypeScript 버전 간 호환성이 떨어질 수 있으므로, 적절한 유연성을 유지해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;esModuleInterop&lt;/code&gt; 및 &lt;code&gt;moduleResolution&lt;/code&gt; 옵션을 명확히 설정하여 다른 TypeScript 설정에서도 안정적으로 동작하도록 해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;4. 배포 전략 ⭐️&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 패키지 배포는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;http://github.com/changesets/changesets&quot;&gt;changesets&lt;/a&gt;를 활용하여 배포 프로세스를 구성하고 팀과 협업을 위한 환경을 만들었습니다. changesets에 대해서 궁금하다면 레포지터리를 살펴보면 좋을 것 같습니다 :)&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  배포 프로세스(운영 기준)&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 코드 변경 사항은 PR을 통해 관리되며, 코드 리뷰 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;main으로 병합합니다. 병합 시 패키지 버전 변경 필수입니다.&lt;/li&gt;
&lt;li&gt;PR 머지 후 Github bot를 통해 변경사항에 대한 PR이 올라옵니다.&lt;/li&gt;
&lt;li&gt;2번 PR이 머지되면&lt;span&gt;&amp;nbsp;&lt;/span&gt;GitHub Actions를 통해 패키지 빌드가 실행됩니다. 빌드가 성공적으로 이루어지면 Github Packages 에서 사용할 수 있도록 배포가 진행됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  배포된 패키지는 어디에?&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 배포된 패키지는 NPM Registry에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;@scope/ui-package&lt;span&gt;&amp;nbsp;&lt;/span&gt;형태로 제공됩니다. 해당 패키지는 사내 앱에서만 사용되기 원하기 때문에 위 배포 프로세스에서 확인했듯이 인증을 통해 Github Packages에 배포합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  어플리케이션에 패키지 설치하기&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 패키지가 배포되면 Github Packages에서 확인할 수 있습니다. 그리고 해당 패키지를 적용할 어플리케이션의 package.json에 설치하여 사용할 수 있습니다. 다만 주의할 점으로 적용할 버전을 정확히 명시하여 설치해야하고 새로운 버전의 패키지를 설치하는 경우 해당 어플리케이션도 새로 빌드하여 배포를 진행해야 실제 환경(운영)에 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이러한 전략을 활용하면 유지보수가 용이하고 확장성이 높은 React UI 패키지를 운영할 수 있습니다. 어플리케이션에 새로운 패키지를 적용하기 위해 매번 새롭게 배포하는 것이 불편하다면 모노레포를 통해 한번에 빌드하고 배포하는 방식도 있겠는데요. 이렇게 분리된 환경에서 패키지를 관리하는 방식은 완전 독립적으로 해당 패키지를 운용할 수 있다는데 특징이 있습니다. 모든 설계는 장단이 있고 트레이드오프(trade off)가 있기 마련이죠. 살펴보고 운영하면서 통합할지 그대로 운영해볼지는 다시한번 고민해봐야겠습니다. 감사합니다.&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>REACT</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/140</guid>
      <comments>https://xtring-dev.tistory.com/entry/React-%EC%84%B8-%EA%B0%9C%EC%9D%98-%EC%95%B1%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-React-UI-%ED%8C%A8%ED%82%A4%EC%A7%80-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0#entry140comment</comments>
      <pubDate>Sun, 2 Mar 2025 23:50:59 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트 서버 컴포넌트(React Server Components, RSC) 이야기</title>
      <link>https://xtring-dev.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%84%9C%EB%B2%84-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8React-Server-Components-RSC-%EC%9D%B4%EC%95%BC%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;og-home.png&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DYcQg/btsMkzIoZcQ/1RivXuVKBxhokKhUjGDYk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DYcQg/btsMkzIoZcQ/1RivXuVKBxhokKhUjGDYk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DYcQg/btsMkzIoZcQ/1RivXuVKBxhokKhUjGDYk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDYcQg%2FbtsMkzIoZcQ%2F1RivXuVKBxhokKhUjGDYk1%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;1080&quot; height=&quot;567&quot; data-filename=&quot;og-home.png&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 리액트 팀에서 React 18 릴리즈를 통해 &lt;b&gt;리액트 서버 컴포넌트(React Server Components, RSC)&lt;/b&gt;를 소개했습니다. RSC는 서버와 클라이언트 간의 경계를 명확히 하고, DX(Developer Experience)와 성능을 끌어올리기 위해서 도입되었다고 합니다. RSC는 기존 클라이언트 전용 컴포넌트와는 '다른' 렌더링 전략을 통해 서버측에서 컴포넌트를 build-time에 실행해두고 필요할때 클라이언트로 전달하는 방식으로 자바스크립트 객체를 전달하여 컴포넌트를 렌더링합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; RSC의 동작 방식&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 리액트 서버 컴포넌트(React Server Components, RSC)는 컴포넌트를 클라이언트가 아닌 &lt;b&gt;서버에서 렌더링&lt;/b&gt;하는 방식입니다. 클라이언트에서 컴포넌트를 생성하는 것이 아닌 &lt;b&gt;서버에서 컴포넌트를 build-time 컴파일하여 UI 결과물을 미리 정적 자바스크립트 객체로 생성해둡니다.&lt;/b&gt; 그리고 클라이언트 사이드에서 RSC가 필요하면 HTML이나 직렬화된 데이터(Serialization)를 통해 전달하고, 이 과정에서 클라이언트는 해당 컴포넌트(RSC) 불필요하게 자바스크립트 번들(JavaScript Bundle)에 포함하지 않습니다.&lt;/p&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; 렌더링된 컴포넌트는 JSON 등으로 &lt;b&gt;직렬화(Serialization)&lt;/b&gt;되어, 네트워크를 통해 클라이언트에 전송합니다. 이때 &lt;span&gt;&lt;b&gt;스트리밍(Streaming)&lt;/b&gt;&lt;/span&gt; 기법을 사용하면, 서버가 렌더링한 결과를 한 번에 모두 보내지 않고, 필요한 부분부터 순차적으로 전송할 수 있습니다. 이를 통해 초기 로딩 속도가 크게 개선됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;b&gt;효율적인 리소스 관리 &lt;/b&gt;측면에서는 서버에서 데이터를 미리 페칭(Fetching)하고 렌더링 결과를 구성하기 때문에, 클라이언트는 단순히 렌더링된 결과를 받아 표시하는 역할만 수행합니다. 이로 인해 클라이언트 측 부담이 줄어들고, 불필요한 렌더링 로직이 제거돼 전체 애플리케이션의 성능 최적화됩니다.&lt;/p&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; RSC는 전통적인 &lt;span&gt;&lt;b&gt;React DOM Server&lt;/b&gt;&lt;/span&gt;의 개념을 확장한 형태로, 서버에서 컴포넌트를 처리한 후 클라이언트에 필요한 데이터를 전달하는 과정을 세밀하게 제어할 수 있도록 설계되어 있습니다. 이와 같이, RSC의 서버 렌더링 내부 구조는 서버와 클라이언트 간의 역할을 명확하게 구분하고, 데이터 전송 및 렌더링 과정을 최적화하여 사용자 경험(UX)과 성능을 동시에 개선하는 데 중점을 두고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; RSC의 장점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 컴포넌트는 위 동작 방식에서 본 것에 대비한 여러 장점을 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;성능 향상(Performance Boost)&lt;/b&gt;: 서버에서 렌더링을 처리함으로써, 클라이언트에 불필요한 자바스크립트 번들을 전달하지 않아 초기 로딩 속도가 개선됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;2. &lt;/span&gt;&lt;/span&gt;&lt;b&gt;데이터 페칭 최적화(Data Fetching Optimization)&lt;/b&gt;: 서버 컴포넌트는 서버 사이드에서 컴포넌트를 만들며 데이터를 주입할 수 있어, 클라이언트에서 별도의 데이터 페칭 로직을 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;3. &lt;/span&gt;&lt;/span&gt;&lt;b&gt;보안 강화(Security Enhancement)&lt;/b&gt;: 민감한 로직이나 데이터를 서버에서만 처리할 수 있어, 클라이언트로 노출되는 코드의 양을 줄여 보안을 강화할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 클라이언트 컴포넌트와 서버 컴포넌트의 상호작용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 클라이언트 컴포넌트(Client Components)는 서버 컴포넌트(Server Components)를 가져올(import) 수 있습니다. 단, 서버 컴포넌트는 브라우저 API나 클라이언트 전용 훅(예: &lt;span&gt;useState&lt;/span&gt;, &lt;span&gt;useEffect&lt;/span&gt;)을 사용할 수 없으므로, 클라이언트 컴포넌트는 서버 컴포넌트가 가진 제약 사항을 인지하고 적절히 분리해 사용해야 합니다.&amp;nbsp;서버 컴포넌트는 순수 데이터 페칭이나 UI 구성을 담당하고, 클라이언트 컴포넌트는 사용자 상호작용 등 동적 기능을 구현하는 역할을 구분해서 사용하는 것이 중요합니다. 그리고 이를 지키지 않는 경우에 리액트에서 자동으로 감지하여 에러를 알려주니 당황하지 않아도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 트레이드오프(Trade-offs)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 클라이언트 컴포넌트 대신 서버 컴포넌트를 사용할 때 발생하는 트레이드 오프도 분명 존재합니다. 먼저, 번들 크기 및 성능에서 장점이 있습니다. 서버 컴포넌트를 활용하면 클라이언트로 전달되는 번들 크기가 줄어들어 성능이 개선됩니다. 하지만, 서버에서의 렌더링 부담이 증가할 수 있어 이 부분은 적절한 유의가 필요합니다.&amp;nbsp;서버 컴포넌트는 서버 측에서 렌더링을 미리하는 것입니다. 따라서 서버 컴포넌트를 사용할때는 그 만큼 신경써야하는 부분이 늘어나 개발 복잡도가 올라갈 수 있습니다. 서버/클라이언트 컴포넌트의 역할을 분리해야 하므로, 기존 클라이언트 전용 애플리케이션에 비해 개발 및 유지 보수 시 추가적인 고려 사항이 생길 수 있습니다. &lt;b&gt;상태 관리 및 인터랙션 &lt;/b&gt;부분에서&amp;nbsp;서버 컴포넌트는 순수 함수형으로 작성되어 상태 관리나 이벤트 핸들링이 제한되므로, 복잡한 상호작용은 클라이언트 컴포넌트에서 처리해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 모듈 참조(Module References)와 재조정(Reconciliation) 과정에서의 처리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; RSC는 서버와 클라이언트에서 각각 다른 방식으로 모듈을 처리하여, 불필요한 자원 낭비를 줄이고 성능을 최적화합니다. 이 과정에서 &lt;b&gt;모듈 참조(Module References)&lt;/b&gt;와 &lt;b&gt;재조정(Reconciliation)&lt;/b&gt;은 밀접하게 연관되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;모듈 참조(Module References)의 역할&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; 모듈 참조&lt;/b&gt;란 컴포넌트가 다른 파일이나 패키지를 참조하는 것을 의미합니다. RSC 환경에서는 서버 전용 모듈과 클라이언트 전용 모듈이 구분되어, 서버에서만 필요한 모듈은 클라이언트 번들에 포함되지 않도록 관리합니다. 서버 컴포넌트는 클라이언트로 불필요한 자바스크립트 코드를 전달하지 않기 위해, 서버 전용 모듈 참조를 별도로 처리합니다. 이로 인해 클라이언트는 반드시 필요한 모듈만 로드하게 되고, 번들 크기와 초기 로딩 시간이 크게 줄어들어 성능이 향상됩니다.&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;재조정(Reconciliation) 과정에서의 처리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 리액트는 UI 업데이트 시 컴포넌트 트리의 변화(또는 상태 변화)를 비교하여 최소한의 변경만 DOM에 반영하는 과정을 재조정(Reconciliation)이라고 합니다. RSC에서는 서버와 클라이언트 사이에서 전달되는 직렬화된 데이터와 모듈 참조 정보를 기준으로, 클라이언트에서 필요한 부분만 렌더링하도록 효율적으로 업데이트를 관리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 서버에서 렌더링할 때 사용된 모듈 참조 정보는, 클라이언트에서 재조정 과정 중에 불필요한 모듈 로드를 방지하는 역할을 합니다. 예를 들어, 서버 전용 모듈은 클라이언트에 전달할 필요가 없으므로, 재조정 과정에서 이를 감지하여 클라이언트는 해당 모듈을 건너뛰고 필요한 컴포넌트만 렌더링할 수 있습니다. 그렇게 하여 모듈 참조 기반의 재조정 처리는 클라이언트의 부담을 경감시키고, 애플리케이션의 초기 로딩 속도와 전반적인 성능을 향상시키며, 개발자가 보다 명확하게 서버와 클라이언트 역할을 분리할 수 있도록 돕는 효과를 가져옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 요약하자면, &lt;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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 서버 액션(Server Actions)을 통한 애플리케이션 접근성 향상&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버 액션(Server Actions)&lt;/b&gt;은 클라이언트에서 호출하면, 해당 함수가 서버로 전송되어 실행되는 방식으로 동작합니다. 이를 통해 데이터 업데이트나 서버 사이드 로직을 간편하게 처리할 수 있습니다. &lt;b&gt;애플리케이션 접근성 향상적 측면에서&lt;/b&gt;&amp;nbsp;서버 액션을 사용하면, 클라이언트와 서버 간의 데이터 전송이 간소화되고, 불필요한 클라이언트 로직이 줄어들어 코드베이스가 간결해집니다. 결과적으로, 애플리케이션의 성능이 개선되고, 접근성(Accessibility)과 유지 보수성이 향상됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 결론&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; RSC는 기존 클라이언트 전용 리액트 애플리케이션과 비교했을 때 성능 최적화, 데이터 페칭 효율성, 보안 강화 등 여러 면에서 강점을 제공합니다. 다만, 서버와 클라이언트 간 역할 분담, 모듈 참조 처리, 재조정(Reconciliation) 과정 등에서 고려해야 할 트레이드오프(Trade-offs)와 주의할 점들이 존재합니다. 또한, 서버 액션(Server Actions)을 통한 접근성 향상과 같은 새로운 기능들 사용할 수 있도록 해줍니다.&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;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 참고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://react.dev/reference/rsc/server-components&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://react.dev/reference/rsc/server-components&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739717638284&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;Server Components &amp;ndash; React&quot; data-og-description=&quot;The library for web and native user interfaces&quot; data-og-host=&quot;react.dev&quot; data-og-source-url=&quot;https://react.dev/reference/rsc/server-components&quot; data-og-url=&quot;https://react.dev/reference/rsc/server-components&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ch14wD/hyYfJZLrxL/CkAgerXr9lTfoKy120xSw0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/eHyii1/hyYfI0R1fT/up9aHMeQ9M7ltKNk983cj1/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567&quot;&gt;&lt;a href=&quot;https://react.dev/reference/rsc/server-components&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://react.dev/reference/rsc/server-components&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ch14wD/hyYfJZLrxL/CkAgerXr9lTfoKy120xSw0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/eHyii1/hyYfI0R1fT/up9aHMeQ9M7ltKNk983cj1/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567');&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;Server Components &amp;ndash; React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The library for web and native user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;react.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>REACT</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/139</guid>
      <comments>https://xtring-dev.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%84%9C%EB%B2%84-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8React-Server-Components-RSC-%EC%9D%B4%EC%95%BC%EA%B8%B0#entry139comment</comments>
      <pubDate>Sun, 16 Feb 2025 23:52:14 +0900</pubDate>
    </item>
    <item>
      <title>[dev.log] 12-Apps Challenge</title>
      <link>https://xtring-dev.tistory.com/entry/xtringlog-12-Apps-Challenge</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-01-28 at 02.34.34.png&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIBZAn/btsL5k5g1QB/Aco8WPxKqRh1CoIQ14FJ01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIBZAn/btsL5k5g1QB/Aco8WPxKqRh1CoIQ14FJ01/img.png&quot; data-alt=&quot;&amp;quot;하면 된다&amp;quot;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIBZAn/btsL5k5g1QB/Aco8WPxKqRh1CoIQ14FJ01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIBZAn%2FbtsL5k5g1QB%2FAco8WPxKqRh1CoIQ14FJ01%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;745&quot; height=&quot;709&quot; data-filename=&quot;Screenshot 2025-01-28 at 02.34.34.png&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&quot;하면 된다&quot;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 전세계 인디 해커분들에 대한 이야기가 Geek News를 통해 종종 올라오고는 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직장을 다니거나 혹은 프리랜서로 일을 하며 자신이 필요로하거나 만들고 싶은 앱들을 A~Z까지 기획, 디자인, 개발, 마케팅해가면 새로운 수익을 창출하는 이야기를 보았다. 어떤 이야기들을 볼때면 나도 해볼 수 있을까라는 상상과 나는 개발자로서 일을 제외한 생산적인 것들을 했었지라며 되짚어 보곤했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 학창시절 큰 포부로 여러 번의 창업을 시도했었다. &lt;b&gt;'세상 사람들에게 변화를 줄 생산성 앱'&lt;/b&gt;을 만들고 유저들이 편리함과 도움을 얻을 수 있는 것들을 찾고 개발하려고 했었다. 몇몇 경진대회에서는 수상과 함께 지원금을 받으며 빌드업에 대한 고민도 해갔지만 그때의 경험과 능력 안에서는 많이 부족할 수 밖에 없었고 지금은 0에 수렴하는 결과로 남았다.&lt;/p&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;b&gt;2025년에는 작지만 뚜렷한 기능을 가지고 일반 유저들이 사용 할 수 있으며 가능하면 멀리까지 발전시킬 수 있을 만한 제품&lt;/b&gt;을 만들어보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서&amp;nbsp;&lt;b&gt;12-Apps Challenge&lt;/b&gt;라는 프로젝트를 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/x6tri3n0g/12-apps&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/x6tri3n0g/12-apps&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738506327434&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - x6tri3n0g/12-apps&quot; data-og-description=&quot;Contribute to x6tri3n0g/12-apps development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/x6tri3n0g/12-apps&quot; data-og-url=&quot;https://github.com/x6tri3n0g/12-apps&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/FGsaY/hyX7018p1p/ZQCAYc5WXvox720lCgBKUK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Xz1TP/hyX71fLPhh/dUGDko9GWfNO5KkcovrgDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/x6tri3n0g/12-apps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/x6tri3n0g/12-apps&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/FGsaY/hyX7018p1p/ZQCAYc5WXvox720lCgBKUK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Xz1TP/hyX71fLPhh/dUGDko9GWfNO5KkcovrgDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - x6tri3n0g/12-apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to x6tri3n0g/12-apps development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일년 열두달 동안 매달 하나의 제품을 스스로 기획부터 개발, 마케팅까지 해보며 개발자 그리고 나의 사업적 능력치에 대해서 시도한다. 이 시도 중 내가 성공하거나 잘 해내지 못하더라도 남는 것들은 분명하다고 생각했다. 5년차 FE 개발자로서의 능력치 증명과 스스로에 대한 실행력 검증, (이제는 해보고 싶은) 사업 능력 테스트 등 이뤄낼 수 있는 것들이 많다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혼자서 개발을 하게되면 분명 딥다이브하는 경험을 하기는 어려울 것이라고 생각되지만 개발에 대한 시각의 확장과 내가 필요한 것들에 대한 객관화가 가능할 것이다. 다양한 앱을 구상하고 개발하며 필요한 것들에 대한 구멍을 메우는 기회도 생길 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 반복할 과정은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;아이디어 구체화&lt;/li&gt;
&lt;li&gt;Github를 통한 기획-개발 내용 공유&lt;/li&gt;
&lt;li&gt;제품 개발 후 앱 출시 및 홍보&lt;/li&gt;
&lt;li&gt;제품 개발 후 회고&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 4가지 과정을 열두번 반복한다. 그리고 잘 되는게 있다면 유저에 대한 피드백과 고도화를 통해서 지속할 수 있는 무엇인가를 만들어내고 싶다. 이게 결국 사업으로 이어질 수 있다고 생각하지는 않지만 배움이 과정이 될 수 있다고 생각한다. 결국 결과에 남는 것은 시도한 흔적과 남은 제품들이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목표는 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트를 진행하며 아래 세가지 철학을 따른다.&lt;br /&gt;&lt;b&gt;간단하게 설계하고, 작은 범위라도 빨리 만들어 공개하며, 빠른 피드백으로 점차 완성도를 높이는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;스스로의 개발 문화를 실천할 수 있도록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;KISS(;Keep It Simple, Stupid)&lt;/b&gt;: 불필요한 복잡함을 줄이고 &amp;ldquo;가장 단순한 해결책&amp;rdquo;을 찾으라는 가르침&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Prototype Fast, Iterate Faster&lt;/b&gt;: 빠르게 시도하고 빠르게 개선하라는 행동 철학, 기민한 피드백 수렴이 핵심&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ship it!&lt;/b&gt;: 완벽함을 기다리기보다 실행(출시)을 통해 현실적인 가치를 창출하고, 실제 사용자의 의견을 기반으로 발전해 나가자는 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이&amp;nbsp;목표를&amp;nbsp;통해&amp;nbsp;&lt;b&gt;self-communication&lt;/b&gt;을 시도한다. 스스로 어떤 가치를 전달할 제품을 만들 것인지 고민하고 실행에 옮겨 내가 만든 제품에 자신감을 가질 수 있도록 한다. 그리고 벌써 이 프로젝트는 시작했다. Pomodori라는 이름으로 뽀모도르 기법과 Todo 앱을 접목한 앱이다. 이 기획이 성공적으로 이루어진 뒤 다시 회고 글로 남는 날이 돌아오면 좋겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*인디해커 이야기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://news.hada.io/search?q=%EC%9D%B8%EB%94%94%ED%95%B4%EC%BB%A4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://news.hada.io/search?q=%EC%9D%B8%EB%94%94%ED%95%B4%EC%BB%A4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738506884197&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;GeekNews - 개발/기술/스타트업 뉴스 서비스&quot; data-og-description=&quot;개발 뉴스, 기술 관련 새소식, 스타트업 정보와 노하우, 세상의 재미난 것들을 좋아하는 사람들을 위한 뉴스 사이트. 이메일 뉴스레터/트위터/슬랙 봇으로 구독 가능&quot; data-og-host=&quot;news.hada.io&quot; data-og-source-url=&quot;https://news.hada.io/search?q=%EC%9D%B8%EB%94%94%ED%95%B4%EC%BB%A4&quot; data-og-url=&quot;https://news.hada.io/search?q=%EC%9D%B8%EB%94%94%ED%95%B4%EC%BB%A4&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://news.hada.io/search?q=%EC%9D%B8%EB%94%94%ED%95%B4%EC%BB%A4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://news.hada.io/search?q=%EC%9D%B8%EB%94%94%ED%95%B4%EC%BB%A4&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;GeekNews - 개발/기술/스타트업 뉴스 서비스&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;news.hada.io&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;</description>
      <category>dev.log</category>
      <category>12-apps challenge</category>
      <category>xtring.log</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/138</guid>
      <comments>https://xtring-dev.tistory.com/entry/xtringlog-12-Apps-Challenge#entry138comment</comments>
      <pubDate>Sun, 2 Feb 2025 23:31:56 +0900</pubDate>
    </item>
    <item>
      <title>[React] React Reconciliation 알아보기</title>
      <link>https://xtring-dev.tistory.com/entry/React-React-Reconciliation-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-01-19 at 23.07.31.png&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ooHWX/btsLT5msNx5/PYONZHjKL86E6t4aOJlpj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ooHWX/btsLT5msNx5/PYONZHjKL86E6t4aOJlpj1/img.png&quot; data-alt=&quot;React&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ooHWX/btsLT5msNx5/PYONZHjKL86E6t4aOJlpj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FooHWX%2FbtsLT5msNx5%2FPYONZHjKL86E6t4aOJlpj1%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;1626&quot; height=&quot;848&quot; data-filename=&quot;Screenshot 2025-01-19 at 23.07.31.png&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;React&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'전문가를 위한 리액트' 4장 재조정(reconciliation)을 읽으며 알게된 내용을 정리합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt; React의 Reconciliation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 UI 업데이트를 효율적으로 처리하기 위해 &lt;code&gt;Reconciliation&lt;/code&gt;라는 과정을 사용합니다. 간단하게 설명하자면, 이 과정은 React의 Virtual DOM과 실제 브라우저의 DOM의 차이를 계산하고, 최소한의 DOM 조작으로 UI를 업데이트하기 위한 목적을 가지고 만들어졌습니다. 종종 'React의 장점이 뭐에요?'라는 질문을 받곤하면 업데이트할 내용을 한번에 계산하고 Virtual DOM과 실제 DOM 간의 비교를 통해 렌더링을 최소화하는 과정을 통해 UI의 업데이트가 사용자에게 자연스럽게 보인다고 설명했습니다. 여기서 이 과정이 &lt;b&gt;Reconciliation&lt;/b&gt;이라는 것이며 자세히 알아보며 새로운 부분도 알게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reconciliation의 가장 중요한 목표는 &lt;b&gt;빠르고 부드러운 UX&lt;/b&gt;를 보장하는 것입니다. React가 Reconciliation 이라는 과정을 어떤 식으로 처리할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 상태가 변경되면 새로운 Virtual DOM을 생성합니다. 이는 컴포넌트의 상태를 표현하는 Tree 데이터 구조 형태를 가집니다. 이후, 기존 Virtual DOM과 새로운 Virtual DOM을 비교(diffing)하여 변경 사항을 계산합니다. 마지막으로 변경이 필요한 부분만 실제 DOM에 적용하여 업데이트합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Virtual DOM 생성&lt;/b&gt;: UI 변경이 발생하면 React는 새로운 가상 DOM 트리를 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;변경 사항 계산&lt;/b&gt;: 기존의 가상 DOM과 새로 생성된 Virtual DOM을 비교(diffing)하여 변경 사항을 계산&lt;/li&gt;
&lt;li&gt;&lt;b&gt;업데이트 수행&lt;/b&gt;: 변경이 필요한 부분만 실제 DOM에 적용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무렇지 않게 사용중인 React는 실제로 바쁘게 계산하고 우리가 사용하기 편하도록 움직입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React의 Reconciliation 메커니즘은 초창기부터 고도화되고 있었습니다. 그러다 React 16에서 &lt;b&gt;Fiber Reconciliation&lt;/b&gt;라는 새로운 구조를 도입하면서 큰 변화가 생겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt; React 16 이전의 Stack Reconciliation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 16 이전에는 &lt;b&gt;Stack Reconciliation&lt;/b&gt;이라는 알고리즘을 통해 DOM 업데이트 사항을 체크했습니다. 이 방식은 우선적으로 업데이트해야할 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;특징과 한계점을 정리하자면 아래와 같습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; Stack Reconciliation 특징&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;동기적 처리&lt;/b&gt;&lt;br /&gt;&amp;bull; UI 업데이트는 재귀적으로 수행되며, 컴포넌트 트리의 루트에서 시작해 각 자식 컴포넌트를 순차적으로 처리한다.&lt;br /&gt;&amp;bull; JavaScript의 단일 스레드 특성을 따르며, 콜 스택을 이용해 깊이 우선 탐색 방식으로 실행된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최적화된 비교&lt;/b&gt;&lt;br /&gt;&amp;bull; React는 각 컴포넌트의 key를 기반으로 자식 목록을 비교하여, 불필요한 재렌더링을 줄였다.&lt;br /&gt;&amp;bull; 동일한 key를 가진 요소는 재사용하고, 변경된 부분만 다시 렌더링한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&amp;nbsp;&lt;/span&gt; 한계점&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;대규모 업데이트 처리가 어려움&lt;/b&gt;&lt;br /&gt;&amp;bull; UI가 복잡해지고, 업데이트가 오래 걸릴 경우, 메인 스레드가 차단(blocking)되어 사용자가 UI를 조작할 수 없는 상태가 발생&lt;/li&gt;
&lt;li&gt;&lt;b&gt;작업 중단 불가&lt;/b&gt;&lt;br /&gt;&amp;bull; 한 번 작업이 시작되면 중단 없이 끝까지 처리해야 하므로, 높은 우선순위의 작업(예: 사용자 인터렉션)을 끼워넣기 어려움&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 단점들은 React 팀에서 성능적인 개선이 필요하다고 생각했습니다. 그래서 새로운 알고리즘을 React 16에서 적용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt; Fiber Reconciliation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 16에서 도입된 &lt;b&gt;Fiber Reconciliation&lt;/b&gt;은 UI 업데이트를 더 유연하고 효율적으로 처리하기 위한 새로운 알고리즘으로 만들어졌습니다. Fiber는 React의 &lt;b&gt;코어 알고리즘을 재설계&lt;/b&gt;하여 이전의 Stack Reconciliation을 개선하여 다음과 같은 특징을 가지게 되었습니다.&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;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt; 주요 특징&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;작업의 단위화(Incremental Rendering)&lt;/b&gt;&lt;br /&gt;&amp;bull; Fiber는 작업을 &lt;b&gt;작은 단위(chunk)&lt;/b&gt;로 나누어 실행합니다.&lt;br /&gt;&amp;bull; 작업 중단과 재개가 가능해져, 긴 작업이 메인 스레드를 차단하지 않도록 설계되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;우선순위 기반 스케줄링&lt;/b&gt;&lt;br /&gt;&amp;bull; React는 업데이트의 중요도에 따라 우선순위 부여합니다. 따라서 Fiber는 낮은 우선순위의 작업을 잠시 중단하고, 높은 우선순위의 작업을 먼저 처리할 수 있습니다.(Stack Reconciliation의 동작 방식과 차이점)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리 효율성&lt;/b&gt;&lt;br /&gt;&amp;bull; Fiber는 &lt;b&gt;각 컴포넌트의 업데이트를 표현하는 데이터 구조&lt;/b&gt;로, 이전과 이후 상태를 추적할 수 있습니다. 딱 필요한 상태만을 추적하여 &lt;b&gt;시간을 절약&lt;/b&gt;하고 &lt;b&gt;메모리 사용을 최적화&lt;/b&gt;했습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt; 동작 과정&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;렌더 단계(Render Phase)&lt;/b&gt;&lt;br /&gt;&amp;bull; Fiber 트리를 순회하며 새로운 가상 DOM을 생성하고 변경 사항 계산합니다. 그리고 이 단계는 &lt;b&gt;비동기적&lt;/b&gt;으로 수행됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커밋 단계(Commit Phase)&lt;/b&gt;&lt;br /&gt;&amp;bull; 실제 DOM 업데이트와 같은 작업이 이 단계에서 이루어집니다. 이 단계는&amp;nbsp;&lt;b&gt;동기적&lt;/b&gt;으로 수행되며, 화면에 즉시 반영됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 Fiber Reconciliation의 장점은 아래와 같이 정리될 수 있겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;우선순위를 조정하여 선택 적인 렌더링을 통해 &lt;/b&gt;긴 작업 중에도 사용자 이벤트를 빠르게 처리할 수 있습니다.(중단 가능한 렌더링)&lt;br /&gt;&amp;bull; 프레임 단위로 작업을 나눌 수 있어, 애니메이션과 전환 효과를 부드럽게 처리할 수 있습니다.&lt;br /&gt;&amp;bull; 브라우저의 메인 스레드가 차단되지 않으므로, 사용자와의 상호작용이 끊기지 않아 &lt;b&gt;더 나은 사용자 경험을 제공할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거 React 16 이전의 Stack Reconciliation은 간단하고 동기적으로 동작했습니다. 이는 매우 파워풀했지만, 긴 작업이 메인 스레드를 차단하는 문제가 있었습니다.(큰 계산을 통한 UI 업데이트 시) &lt;b&gt;Fiber Reconciliation&lt;/b&gt;은 작업을 작은 단위(Chunk)로 나누고 우선순위를 고려하는 비동기적 방식으로, 사용자 경험을 크게 향상시켰습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fiber는 React가 더 복잡한 UI를 효과적으로 처리할 수 있는 기반을 제공하여 또 한번 React 개발자들의 생산성을 향상 시켜준 것 같습니다. 기술의 속을 자세히 들여다보는 것은 그 기술을 새롭게 볼 수 있는 창을 만들어 주는 것 같습니다.&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>REACT</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/137</guid>
      <comments>https://xtring-dev.tistory.com/entry/React-React-Reconciliation-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry137comment</comments>
      <pubDate>Sun, 19 Jan 2025 23:49:17 +0900</pubDate>
    </item>
    <item>
      <title>2024.log</title>
      <link>https://xtring-dev.tistory.com/entry/2024log</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_5991.jpg&quot; data-origin-width=&quot;2750&quot; data-origin-height=&quot;2750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BP6SI/btsLqx6TWBS/JAJWheU5fYzR3XtPKrc1ak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BP6SI/btsLqx6TWBS/JAJWheU5fYzR3XtPKrc1ak/img.jpg&quot; data-alt=&quot;2024.12.13 워크샵&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BP6SI/btsLqx6TWBS/JAJWheU5fYzR3XtPKrc1ak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBP6SI%2FbtsLqx6TWBS%2FJAJWheU5fYzR3XtPKrc1ak%2Fimg.jpg&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;2750&quot; height=&quot;2750&quot; data-filename=&quot;IMG_5991.jpg&quot; data-origin-width=&quot;2750&quot; data-origin-height=&quot;2750&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2024.12.13 워크샵&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'아무것도 남기지 않으면 아무것도 남지 않는다'는 말이 요즘은 더 와닿는다. 2024년은 어떻게 보냈는지 정리해 보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해는 상상만 하던 것들을 다양하고 길게 실행하는 한해였다. 운동을 꾸준히하고, 밴드 공연을 하고 미디를 배워서 음악을 기록으로 남기기도 했다. 그러다 바이크에 빠져 두발 라이프를 즐기기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #7e98b1;&quot;&gt;&amp;nbsp;&lt;/span&gt; 2024년 - 큰 목표 없음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 2023년은 &lt;b&gt;일하는 것 차체&lt;/b&gt;와 &lt;b&gt;그 일에 대한 스트레스를 푸는데&lt;/b&gt; 거의 모든 시간을 썼다고 생각한다. 그래서 해가 바뀌면서 큰 목표 없이 건강해지는 것, 자신에게 필요한 시간을 더 쏟는 것 집중하고자 했다. 일에서 얻는 배움은 분명했지만, 온전히 하고싶은 일을 하는 것보다 남는 것은 적다고 생각했다. 그래서 내가 하고 싶은 일에 대해서 생각하게 되었다. 운동, 책 읽기, 여행, 기록하기에 집중하고 싶었고 그렇게 24년이 시작되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #7e98b1;&quot;&gt;&amp;nbsp;&lt;/span&gt; 4년만에&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취업준비를 시작하면서 평생 친구라고도 할 수 있는 기타를 잠시 접었다. 나의 인생에 있어 아주 큰 부분이 음악이었고, 기타였다. 아쉬움을 뒤로하고 취업준비에 몰두했고 첫직장에서 23년 여름, 약 4년간 내 일의 전문가가되기 위해서 필사적으로 노력했다. 개발 뿐만 아닌 사람이나 인생의 방향 많은 것들을 얻어오며 다시금 내가 온전히 좋아할 수 있는 일을 찾아보았고 다시 기타를 잡게되었다. &lt;br /&gt;&lt;br /&gt;작년 친구와 술한잔하며 다시 밴드를 해보자는 이야기 있었고 술자리 내내 이야기하며 심장이 두근댔다. 가끔 만나면 밴드를 하자고 묻곤 했는데 다시 용기를 가지고&lt;b&gt;&amp;nbsp;'한팀'&lt;/b&gt;이 되었다. 용기를 가질 일이 었다는 것이 취업을 준비중, 신입으로 일하던 시간 동안 나에겐 개발 이외에 모든 일엔 용기가 필요했다. 그 덕에 새로운 취미이자 특기로서 개발을 하고 있다고 생각이 든다. 이전엔 시도 때도 없이 들고 다니던 기타 대신 가방에 노트북을 들고 다닌다. 키보드가 손에서 오래 잡히지 않으면 불안(?)하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 각 파트의 인원들을 모으고 약 일년 간 한달에 세네번 날이 좋든, 비가 오든, 눈이 오든 무거운 장비를 옮겨가며 합주를 했다. 대학시절에 푹 빠져있었고 행복한 일로서 '어쩌면 내 직업이 될수도 있겠다' 싶을 정도였지만 활활 타오르던 불꽃은 약간 작은 불꽃이 되었나보다.&amp;nbsp; 합주를 하며 희열을 느끼기도, 다시 무대에 서는 꿈도 꾸기도 시작했다. 그러나 각자의 개인적인 사정으로 연습하기 어렵거나 개인 연습을 제대로 준비하지 못해 아쉬운 일도 있었다. 시간이 지나서 귀도 생각도 달라져 그 시절 그 마음만큼 하나가 되기 힘들었다. 일년의 결실은 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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #7e98b1;&quot;&gt;&amp;nbsp;&lt;/span&gt; 기록의 중요성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음악은 시간 예술이다. 눈에 보이는 것이며, 기록하지 않은 연주는 말과 같이 공기중에 떠다니다 사라질 뿐이다. 오랫동안 밴드를하고 연주를 하면서 그 부분이 참 아쉬웠고 언젠간 녹음을 하고 앨범을 내보리라 마음먹어왔다. 그러나 우연히 인스타그램으로 좋아하는 아티스트가 레슨을 한다는 홍보를 보고 연락을 했고, 올해 초부터 배우기 시작했다. 지금까지 진행된 레슨을 통해 &lt;b&gt;미디 작업&lt;/b&gt;을 하는 방법부터 작곡, 음악은 어떻게 들어야하고 어떻게 만들어져야하는지에 대한 이야기를 들으면서 많은 궁금증을 풀어왔다. 나에게 또 다른 세계가 열렸다고 말하고 다닐만큼 즐거운 시간을 보내는 중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개발을 하면서 겪은 이야기, 혹은 기술적으로 정리하는 내용을 글로 남기지 않아 나의 작년은 일만 했던 기억뿐일지도 모른다.&lt;/b&gt; 그래서 다시 개인 블로그에 글을 통해 나의 경험과 생각, 개발 이야기를 남기려고 했고 블로그를 정리 중에 &lt;b&gt;글또 10기&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #7e98b1;&quot;&gt;&amp;nbsp;&lt;/span&gt; 첫 차&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 차를 샀다. 바퀴 네개의 자동차가 아닌 두 발의 &lt;b&gt;오토바이&lt;/b&gt;지만 기쁜 마음에 &lt;b&gt;첫 차&lt;/b&gt;를 샀다고 주변에 자랑도하고 다녔다. 오토바이를 타게된 계기는 초여름 좋은 날씨에 카페를 가던중 차가 있으면 더 멀리 또 다른 공간으로 가보고 싶다는 생각과 미디 선생님의 오토바이 이야기였다. 그렇게 바이커 라이프가 시작되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;125cc 엔진의 수동 바이크는 올라타는 순간 설렘과 충격이었다. 공도에 나가자 떨리는 마음과 함께 자신감이 꺾이고, 핸들은 똑바로 돌리기 어려웠다. 오토바이 운전이 쉬워보였지만 직접해보니 그렇지 않았다. 엔진의 고동감 느끼고, 엔진 소리를 들으며 출발하고 멈춰서는 모든 순간을 느껴갔다. 새로운 낭만을 찾아내기도 했고 차랑 다르게 길을 지나며 주변을 더 자세히 볼 수 있었다. 차 안에 있으면 밖과는 단절된 느낌이지만 오토바이 위에서 바라보는 도로는 훨씬 더 많은 것들이 보였다. 그래서 더 조심할 필요가 있었다. 요즘은 매일 영하에 너무 추운 날씨 때문에 뚜벅이 생활을 하고 있다. 두려움과 긴장감을 느낀 후 안전하게 바이크에서 내릴때의 그 안도감은 나에게 더 큰일도 할 수 있겠다라는 자신감을 주기도 했다. 꽤 괜찮은 취미일 수도 있겠다고 생각하여 내년엔 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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #7e98b1;&quot;&gt;&amp;nbsp;&lt;/span&gt; 5년 차 개발자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올초 팀장님과 1on1 미팅을 통해 &lt;b&gt;5년 차 개발자&lt;/b&gt;의 역할에 대해서 스스로 정의해보고 시도하고 피드백 받았다. 당연히 해내야하는 역할은 '맡은 프로젝트를 일정 내에 문제 없이 해결하는 것'이었다. 당연한 것인데 가장 부담이 되는 항목이었다. 나는 책임감이 강한 사람, 신뢰를 유지하는 사람이라는 확신이 있었지만 실망하는 결과가 생길까 두렵기도 했다. 하지만 다 해냈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 프로젝트에 들어가게 되면 일정 산정을 (정확할 수는 없지만) 좀더 정확하게 지킬 수 있도록 리뷰 전 기획서를 꼼꼼히 확인하여 필요한 요건들을 검토-검증 하는 과정을 하고 팀과는 기술과 아키텍처를 충분한 시간동안 함께 논의했다. '그래서 잘했는가?'라고 물으신다면 '조금은 아쉬웠다.'라고 말했다. 나 자신 그리고 팀원 모두 사람이라는 것에 대한 이해도가 부족했다. 일정을 무리하게 잡거나 큰 프로젝트 여러 개를 동시에 진행한다거 하는... '나는 지치지 않아'라는 말도 안되는 자신감으로 스스로 지치게 하는 실수를 하게 된 사건들이 만들었다. 주말 통째로 추가 근무를 하거나 몇 일 밤을 새워가며 작업하는 일이 최근 몇 번 있으면서 겸손함에 대해서 다시 배웠던 것 같다. 그래서 나의 6년차 개발자가 해야하는 일에도 자연스럽게 끼워넣으려고 한다. 아무튼 성장중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageslideblock alignCenter&quot; data-image=&quot;[{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/boZu8f/btsLu5I4O17/KktGmWUQ1tjW99oQCFidZk/img.jpg&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/cJNVHK/btsLxkRUk4a/o5QZkDkzdSWq7pPgjjZIBK/img.jpg&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/5uvfX/btsLuGCGThB/4yow9KYnPKgcESelu3RbO1/img.jpg&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/bcTIvr/btsLxhVaYpf/GEPopq6kwE3YIKSL6KYrck/img.jpg&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/bAMgp8/btsLv5n0XPs/pzJX24y3a2RQbNj80K9Ofk/img.jpg&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/cC8ZW7/btsLw2cTqxJ/xd2JY6TLflhItuOPxpVyOK/img.jpg&amp;quot;}]&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span class=&quot;image-wrap selected&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boZu8f/btsLu5I4O17/KktGmWUQ1tjW99oQCFidZk/img.jpg&quot; data-url=&quot;https://blog.kakaocdn.net/dn/boZu8f/btsLu5I4O17/KktGmWUQ1tjW99oQCFidZk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boZu8f/btsLu5I4O17/KktGmWUQ1tjW99oQCFidZk/img.jpg&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboZu8f%2FbtsLu5I4O17%2FKktGmWUQ1tjW99oQCFidZk%2Fimg.jpg&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; data-origin-width=&quot;3024&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJNVHK/btsLxkRUk4a/o5QZkDkzdSWq7pPgjjZIBK/img.jpg&quot; data-url=&quot;https://blog.kakaocdn.net/dn/cJNVHK/btsLxkRUk4a/o5QZkDkzdSWq7pPgjjZIBK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJNVHK/btsLxkRUk4a/o5QZkDkzdSWq7pPgjjZIBK/img.jpg&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJNVHK%2FbtsLxkRUk4a%2Fo5QZkDkzdSWq7pPgjjZIBK%2Fimg.jpg&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; data-origin-width=&quot;3024&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5uvfX/btsLuGCGThB/4yow9KYnPKgcESelu3RbO1/img.jpg&quot; data-url=&quot;https://blog.kakaocdn.net/dn/5uvfX/btsLuGCGThB/4yow9KYnPKgcESelu3RbO1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5uvfX/btsLuGCGThB/4yow9KYnPKgcESelu3RbO1/img.jpg&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5uvfX%2FbtsLuGCGThB%2F4yow9KYnPKgcESelu3RbO1%2Fimg.jpg&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; data-origin-width=&quot;3024&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcTIvr/btsLxhVaYpf/GEPopq6kwE3YIKSL6KYrck/img.jpg&quot; data-url=&quot;https://blog.kakaocdn.net/dn/bcTIvr/btsLxhVaYpf/GEPopq6kwE3YIKSL6KYrck/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcTIvr/btsLxhVaYpf/GEPopq6kwE3YIKSL6KYrck/img.jpg&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcTIvr%2FbtsLxhVaYpf%2FGEPopq6kwE3YIKSL6KYrck%2Fimg.jpg&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; data-origin-width=&quot;3024&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAMgp8/btsLv5n0XPs/pzJX24y3a2RQbNj80K9Ofk/img.jpg&quot; data-url=&quot;https://blog.kakaocdn.net/dn/bAMgp8/btsLv5n0XPs/pzJX24y3a2RQbNj80K9Ofk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAMgp8/btsLv5n0XPs/pzJX24y3a2RQbNj80K9Ofk/img.jpg&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAMgp8%2FbtsLv5n0XPs%2FpzJX24y3a2RQbNj80K9Ofk%2Fimg.jpg&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; data-origin-width=&quot;3024&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cC8ZW7/btsLw2cTqxJ/xd2JY6TLflhItuOPxpVyOK/img.jpg&quot; data-url=&quot;https://blog.kakaocdn.net/dn/cC8ZW7/btsLw2cTqxJ/xd2JY6TLflhItuOPxpVyOK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cC8ZW7/btsLw2cTqxJ/xd2JY6TLflhItuOPxpVyOK/img.jpg&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcC8ZW7%2FbtsLw2cTqxJ%2Fxd2JY6TLflhItuOPxpVyOK%2Fimg.jpg&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; data-origin-width=&quot;3024&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;button class=&quot;btn btn-prev&quot;&gt;&lt;span class=&quot;ico-prev&quot;&gt;이전&lt;/span&gt;&lt;/button&gt;&lt;button class=&quot;btn btn-next&quot;&gt;&lt;span class=&quot;ico-next&quot;&gt;다음&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
  &lt;div class=&quot;mark&quot;&gt;&lt;span data-index=&quot;0&quot;&gt;0&lt;/span&gt;&lt;span data-index=&quot;1&quot;&gt;1&lt;/span&gt;&lt;span data-index=&quot;2&quot;&gt;2&lt;/span&gt;&lt;span data-index=&quot;3&quot;&gt;3&lt;/span&gt;&lt;span data-index=&quot;4&quot;&gt;4&lt;/span&gt;&lt;span data-index=&quot;5&quot;&gt;5&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;2024&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>xtring.log</category>
      <category>2024</category>
      <category>회고</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/136</guid>
      <comments>https://xtring-dev.tistory.com/entry/2024log#entry136comment</comments>
      <pubDate>Sun, 22 Dec 2024 22:59:32 +0900</pubDate>
    </item>
    <item>
      <title>[모노레포] PNPM과 Turborepo로 말아올려 Vite 처럼 빠르게 Application과 UI 개발하기</title>
      <link>https://xtring-dev.tistory.com/entry/Products-PNPM%EA%B3%BC-Turborepo%EB%A1%9C-%EB%A7%90%EC%95%84%EC%98%AC%EB%A0%A4-Vite-%EC%B2%98%EB%9F%BC-%EB%B9%A0%EB%A5%B8-UI-%EA%B0%9C%EB%B0%9C%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;멍멍-min.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JRCEO/btsKVCMAmG2/y2O70XjmNiDqzXk1C2XBn0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JRCEO/btsKVCMAmG2/y2O70XjmNiDqzXk1C2XBn0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JRCEO/btsKVCMAmG2/y2O70XjmNiDqzXk1C2XBn0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJRCEO%2FbtsKVCMAmG2%2Fy2O70XjmNiDqzXk1C2XBn0%2Fimg.jpg&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;443&quot; height=&quot;591&quot; data-filename=&quot;멍멍-min.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 배경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이커머스 프로덕트는 상품을 전시하고 전시된 상품을 사용자들에게 자세한 설명을 전달하는 '상품 상세 페이지'가 있습니다. 상품의 콘텐츠를 만들기 위해서는 상품의 메타 정보 뿐만 아니라 상품에 대한 자세한 설명, 판매자의 의도가 담긴 글과 이미지를 잘 정리해서 설명해야합니다. 상품상세 페이지는 국내외 이커머스 서비스에서 10년 이상 대부분 비슷한 형상을 유지하고 있습니다. 상품 판매를 위한 설명 콘텐츠를 좀 더 쉽고 효율적으로 만들어내고 일관성있게 제공하는 것을 위해 업계는 많은 시도를 하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 저는 현재 회사에서 입사부터 지금까지 상품상세를 개발하고 고도화하는 작업을 해왔습니다. 수 많은 작업을 해왔지만 그 중 쉽게 고치거나 대체하기 어려운 부분 중 타사 에디터 기반의 상품 디스크립션 작성 서비스 였습니다. 각 회사의 핏의 맞는 콘텐츠를 생성하기 위한 에디터를 만들어내는 것은 여러 회사들에서 시도하는 방법이자 꽤나 부담스러운 작업으로도 유명합니다. 그래서 유연한 에디터를 만들기 위해서 다양한 케이스를 고민하고 제품의 스팩을 결정하다보면 오버 스팩을 정의하게 되어 개발 일정이 너무 많이 나온다거나 만들게 되더라도 유지하는데 너무 많은 리소스가 드는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 꼭 필요한 최소한의 스팩으로 개발하고 이터레이션을 통한 고도화를 진행해보면 좋겠다고 판단하였습니다. 그래서 팀은 완전 자유 양식 작성이 가능한 에디터가 아닌 회사의 상품 전시 운영자가 상품상세 디스크립션을 쉽게 만들 수 있도록 하는 템플릿 에디터를 만들게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 고민하는 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한가지 고려해볼 것은 만들어지는 템플릿 에디터는 여러 사이트에 제공될 수 있고 제공하고자 하는 플랫폼에 Plug-in 방식으로 적용할 수 있도록 하는 것이었습니다. 또 만들어질 템플릿 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 프로젝트 세팅하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;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;팀은 PNPM을 사용하여 모노레포를 구성하기로 결정하여 Vite를 사용하여 apps와 packages 디렉터리 내 React 프로젝트를 설정하게 되었습니다. 여기에 프로젝트 별 의존성 빌드를 쉽고 빠르게 관리하기 위해서 Turborepo를 선택하게 되었습니다.PNPM + TurboRepo 기반의 모노레포 환경을 전제로 합니다.&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;1. 프로젝트 구조&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PNPM 프로젝트에는 apps와 packages 디렉터리를 프로젝트를 세팅합니다. 일반적으로 apps 디렉터리 아래로는 실행 가능한 어플리케이션을 구성하고(예: 에디터), packages는 공통으로 관리하고 배포될 라이브러리(예: UI 컴포넌트)를 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pnpm.io/ko/installation&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://pnpm.io/ko/installation&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732445357956&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;설치하기 | pnpm&quot; data-og-description=&quot;필수 구성 요소&quot; data-og-host=&quot;pnpm.io&quot; data-og-source-url=&quot;https://pnpm.io/ko/installation&quot; data-og-url=&quot;https://pnpm.io/ko/installation&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CGmnl/hyXDaiVV2N/SJ0jYfKMLnIThZFIY1YBC0/img.png?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/FvDdH/hyXDkly4fu/0NCXXkdjFWV6XoAd3ntXhK/img.png?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200&quot;&gt;&lt;a href=&quot;https://pnpm.io/ko/installation&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pnpm.io/ko/installation&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CGmnl/hyXDaiVV2N/SJ0jYfKMLnIThZFIY1YBC0/img.png?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/FvDdH/hyXDkly4fu/0NCXXkdjFWV6XoAd3ntXhK/img.png?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200');&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;설치하기 | pnpm&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;pnpm.io&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;b&gt;* TurboRepo 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TurboRepo를 프로젝트에 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1732447421219&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm add turbo --save-dev --ignore-workspace-root-check&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;turbo.json&lt;/span&gt; 파일을 생성하고 파이프라인과 캐싱 규칙을 정의합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1732447451860&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;pipeline&quot;: {
    &quot;build&quot;: {
      &quot;dependsOn&quot;: [&quot;^build&quot;],
      &quot;outputs&quot;: [&quot;dist/**&quot;]
    },
    &quot;lint&quot;: {
      &quot;outputs&quot;: []
    },
    &quot;test&quot;: {
      &quot;dependsOn&quot;: [&quot;build&quot;],
      &quot;outputs&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 TurboRepo 명령어는 아래 접은 글에 간단하게 설명하겠습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;전체 빌드&lt;/p&gt;
&lt;pre id=&quot;code_1732447698310&quot; class=&quot;dockerfile&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;pnpm turbo run build&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;변경된 워크스페이스만 빌드&lt;/p&gt;
&lt;pre id=&quot;code_1732447698311&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;pnpm turbo run build --filter=[...changed]&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;3)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;특정 워크스페이스 실행&lt;/p&gt;
&lt;pre id=&quot;code_1732447698311&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;pnpm turbo run build --filter=@my-org/ui&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;4)&lt;span&gt;&amp;nbsp;&lt;/span&gt;캐싱 무효화&lt;/p&gt;
&lt;pre id=&quot;code_1732447698311&quot; class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;pnpm turbo run build --no-cache&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 아래와 같은 프로젝트가 설정되었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1732444778612&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/my-monorepo
  /apps
    /editor
  /packages
    /ui    
  pnpm-workspace.yaml
  turbo.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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 각 프로젝트에 Vite 프로젝트 설치 및 세팅하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀은 에디터 프로젝트는 최신 React를 사용하고, UI 컴포넌트 패키지는 다른 레포에서도 호환될 수 있도록 사용될 다른 프로젝트의 React 버전에 맞게 선택했습니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732445019470&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm create vite&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.vite.dev/guide/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ko.vite.dev/guide/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732445315361&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;Vite&quot; data-og-description=&quot;Vite, 프런트엔드 개발의 새로운 기준&quot; data-og-host=&quot;ko.vite.dev&quot; data-og-source-url=&quot;https://ko.vite.dev/guide/&quot; data-og-url=&quot;https://ko.vite.dev&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b0e8vM/hyXzKeWWbi/yNXPuilx3NdGkWhk8HliXk/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://ko.vite.dev/guide/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.vite.dev/guide/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b0e8vM/hyXzKeWWbi/yNXPuilx3NdGkWhk8HliXk/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Vite&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Vite, 프런트엔드 개발의 새로운 기준&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.vite.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI 컴포넌트의 경우 Github Packages로 배포하여 Organization 내 다른 프로젝트에서도 사용할 수 있도록 하기 위해 약간의 추가 세팅이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;packages/ui/vite.config.ts&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;packages/ui/vite.config.ts 파일을 생성하고 아래와 같이 설정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1732445564888&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import path from 'path';

export default defineConfig({
  plugins: [
    react(),
    dts({
      include: ['src'],
    }),
  ],
  build: {
    lib: {
      entry: path.resolve(__dirname, 'src/index.ts'),
      name: 'UIComponents',
      fileName: (format) =&amp;gt; `ui.${format}.js`,
    },
    rollupOptions: {
      external: ['react', 'react-dom'],
      output: {
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM',
        },
      },
    },
  },
});&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; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lib&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;span&gt;external&lt;/span&gt;: React와 ReactDOM은 외부 종속성으로 처리&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;span&gt;vite-plugin-dts&lt;/span&gt;: TypeScript 타입 정의 파일(&lt;span&gt;.d.ts&lt;/span&gt;) 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;packages/ui/tsconfig.json&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732445854202&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;esnext&quot;,
    &quot;module&quot;: &quot;esnext&quot;,
    &quot;lib&quot;: [&quot;dom&quot;, &quot;esnext&quot;],
    &quot;jsx&quot;: &quot;react-jsx&quot;,
    &quot;declaration&quot;: true,
    &quot;declarationMap&quot;: true,
    &quot;outDir&quot;: &quot;dist&quot;,
    &quot;strict&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;baseUrl&quot;: &quot;.&quot;,
    &quot;paths&quot;: {
      &quot;@my-monorepo/ui/*&quot;: [&quot;src/*&quot;]
    }
  },
  &quot;include&quot;: [&quot;src&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;b&gt;packages/ui/package.json&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1732446101627&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;@scope-name/ui&quot;,
  &quot;private&quot;: false,
  &quot;version&quot;: &quot;0.0.1&quot;,
  &quot;repository&quot;: {
    &quot;type&quot;: &quot;git&quot;,
    &quot;url&quot;: &quot;https://github.com/my-team/my-monorepo.git&quot;
  },
  &quot;author&quot;: &quot;FrontEndTeam&quot;,
  &quot;type&quot;: &quot;module&quot;,
  &quot;main&quot;: &quot;./dist/index.es.js&quot;,
  &quot;module&quot;: &quot;./dist/index.es.js&quot;,
  &quot;types&quot;: &quot;./dist/types/index.d.ts&quot;,
  &quot;files&quot;: [
    &quot;dist&quot;
  ],
  &quot;license&quot;: &quot;MIT&quot;,
  &quot;publishConfig&quot;: {
    &quot;&amp;lt;@scop-name&amp;gt;:registry&quot;: &quot;https://npm.pkg.github.com/&quot;
  },
  ...
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI 컴포넌트 패키지는 위에서 설명했듯이 Github Organization의 Packages에 배포되고 관리되어야하기 때문에 위 세팅이 필수입니다. 패키지가 배포될 scope-name을 정확히 입력하고 publishConfig를 정확히 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 배포 후 Github Actions를 사용하는 Organization의 다른 레포에서 사용하기 위해서는 Github Packages 에서 해당 프로젝트를 세팅을 추가로 해줘야합니다. Github Actions의 CI 실행중 해당 패키지를 설치하기 위해서는 &lt;a href=&quot;https://github.com/orgs/thefarmersfront/packages/npm/description-ui/settings&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/orgs/&amp;lt;organization-name&amp;gt;/packages/npm/&amp;lt;package-name&amp;gt;/settings&lt;/a&gt;에서 Manage Access Actions 항목에 엑세스 가능한 레포를 추가해줘야 합니다.&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;3. PNPM 프로젝트 실행시 필요한 기본 명령어&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 워크스페이스 연결&lt;/p&gt;
&lt;pre id=&quot;code_1732446674137&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루트 디렉터리에서 실행해 워크스페이스를 연결합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) UI 패키지 빌드&lt;/p&gt;
&lt;pre id=&quot;code_1732446711158&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm --filter @my-monorepo/ui build&lt;/code&gt;&lt;/pre&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;2-1) UI 패키지 Github Packages에 수동 배포&lt;/p&gt;
&lt;pre id=&quot;code_1732446926671&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm --filter &amp;lt;pakage-name&amp;gt; publish --access=public&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;3) 에디터 실행&lt;/p&gt;
&lt;pre id=&quot;code_1732446734909&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm --filter @my-monorepo/editor dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에디터 애플리케이션을 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 구성의 프로젝트에서 UI 패키지는 packages/ui에서 빌드되고, apps/editor 애플리케이션에서 로컬 참조됩니다. 또 Vite를 사용해 빠른 개발 환경과 최적화된 빌드를 제공하여 합니다.&lt;/p&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/Mono Repo</category>
      <category>pnpm</category>
      <category>모노레포</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/135</guid>
      <comments>https://xtring-dev.tistory.com/entry/Products-PNPM%EA%B3%BC-Turborepo%EB%A1%9C-%EB%A7%90%EC%95%84%EC%98%AC%EB%A0%A4-Vite-%EC%B2%98%EB%9F%BC-%EB%B9%A0%EB%A5%B8-UI-%EA%B0%9C%EB%B0%9C%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0#entry135comment</comments>
      <pubDate>Sun, 24 Nov 2024 20:29:53 +0900</pubDate>
    </item>
    <item>
      <title>[dev.log] 프론트엔드팀이 '리눅스 커널'이 주제로 스터디를 하게된 이야기</title>
      <link>https://xtring-dev.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%ED%8C%80-%EC%8A%A4%ED%84%B0%EB%94%94%EC%97%90%EC%84%9C-%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%BB%A4%EB%84%90%EC%9D%B4-%EC%84%A0%EC%A0%95%EB%90%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;zzal.jpg&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m4uKC/btsKDcBLFTH/KAEov1bglDnvCBG8Dr8C3k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m4uKC/btsKDcBLFTH/KAEov1bglDnvCBG8Dr8C3k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m4uKC/btsKDcBLFTH/KAEov1bglDnvCBG8Dr8C3k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm4uKC%2FbtsKDcBLFTH%2FKAEov1bglDnvCBG8Dr8C3k%2Fimg.jpg&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;960&quot; height=&quot;540&quot; data-filename=&quot;zzal.jpg&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 소개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 제가 속한 프런트엔드팀에서는 필요한 기술 스택이거나 함께 공부할 주제를 정해 주 1회 스터디를 진행하고 있습니다. 6~8명이 1년 넘게 운영해 오면서 다양한 책들을 함께 읽으며 토론했습니다. 주된 관심사는 대부분 프런트엔드 기술과 직간접적으로 연관 있는 내용들이었습니다. 이번엔 &lt;b&gt;새로운 스터디를 시작하기 전에 종종 추천 책으로 나오던 리눅스 커널이 주제인 책이 선정되었습니다.&lt;/b&gt; 어찌 보면 프런트엔드와는 직접적으로 관련이 없는 주제가 어떻게 프런트엔드 팀의 스터디 주제가 되었을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 이 주제를 선정하게된 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 최근 프론트엔드 진영에서는 React와 Next.js를 기반으로 웹 기술이 활성화되고 있습니다. 그리고 우리는 이 라이브러리와 프레임워크를 가지고 SPA, SSR, SSG, ISR 등 다양한 렌더링 방식으로 웹 사이트를 구성하는데요. 페이지를 어떻게 보여주고 어떤 전략을 가져가냐에 따라 우리는 여러 방식 중 1+a를 적용하곤 합니다. 그리고 Next.js의 SSR(Server Side Rendering) 메서드를 통해 간편하게 구현하여 성능과 간편함을 한 번에 가져갈 수 있어 최근 많은 팀에서 적용하곤 합니다. 프런트엔드 팀의 스터디 주제가 '리눅스 커널'이 된 이유는 여기에 있기도 합니다.&lt;br /&gt;*SSR에 대해서는 요즘 많은 분들이 소개하여 이 글에서는 다루지 않겠습니다.&lt;/p&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; 3~5년 이내 유행했던 JAM Stack에 대해서 들어보셨을까요? JAM Stack은 &lt;b&gt;JavaScript, API, Markup &lt;/b&gt;기술로 웹 서비스를 구현하는 Stack이라는 의미인데요. 이 기술의 Stack을 통해 정적 파일을 CDN을 통해 제공하고 서버의 부하를 줄이며, 서버 로직과 프론트엔드 로직을 분리하여 보안에도 강점을 가지고 있습니다. 또 서버리스&amp;nbsp; 아키텍처를 통해 확장성도 가지고 있지요. 그러나 개발팀이 비즈니스를 고도화하며 마주하는 여러 구현 사항을 적용하다보면 꼭 한가지 아키텍처나 패턴만을 사용할 수 없습니다. 따라서 아키텍처는 계속해서 변하고 진화하게 되는데 JAM Stack으로 유행했던 방식에서 요즘에는 Server Side Rendering(이하 SSR)을 통해 페이지를 렌더링하는 전략을 많이 가는 것 같습니다.&lt;/p&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; SSR은 제가 사용하고 있는 Next.js를 기준으로 Next Node 서버에서 HTML + CSS + JS를 다른 서버 API의 데이터를 하나로 Document로 만들어 클라이언트에게 전달하는 방식입니다. 즉 SSR을 하게 되면 우리의 서버 컴퓨터가 그만큼 일을 더 많이 해야한다는 말입니다. 우리는 SSR을 적용하고 운영하게 되면서 Node 서버 리소스를 직접 모니터링하고 관리하게 됐습니다.&lt;/p&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; 일반적으로 클라우드 환경에서 서비스를 다루는 백엔드 개발자의 경우 이런 과정과 환경이 익숙할테지만 프런트엔드 개발자 입장에서는 이러한 부분이 처음엔 쉽지 않습니다. 즉, 프런트엔드 개발자도 단순히 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 프런트엔드 개발자가 리눅스 커널에 대해 알고 있으면 좋은 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프런트엔드 개발자가 리눅스 커널에 대해서 알고 있으면 좋은 이유를 4가지로 정리해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 시스템 성능 최적화 이해&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 배포 및 서버 환경에 대한 깊은 이해&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;리눅스 기반 서버 환경은 대부분의 웹 애플리케이션 배포에 사용되며, 특히 프런트엔드 배포 시 Nginx, Docker, Kubernetes와 같은 툴을 다룰 때 유용합니다. 커널에 대한 이해는 이러한 환경에서 애플리케이션이 어떻게 동작하는지 더 잘 이해할 수 있게 해 줍니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 디버깅 능력 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;커널 지식이 있으면, 시스템 레벨에서 발생하는 문제나 오류를 더 잘 파악할 수 있습니다. 애플리케이션이 예기치 않은 방식으로 동작하거나 성능 이슈가 발생할 때, CPU 사용량이 높거나 메모리 누수가 있는 상황에서 커널 로그나 시스템 진단 도구를 통해 원인을 파악하고 디버깅할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 보안 강화 및 이해&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 위 내용을 기반으로 팀에서는 이 책을 결정하게 되었습니다. 애플리케이션에 지속적으로 머지되고 변화하는 과정에서 배포 전/후 서버 리소스가 변화되는 것들을 확인하면서 직접 관리할 수 있어야 한다고 생각했습니다. 또 트래픽이 몰리거나 서비스 API의 상태에 따라  팀이 대비할 수 있도록 하는 것이 목표입니다. 물론 여기에는 Node.js와 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;선정된 책은 &lt;b&gt;DevOps와 SE(Software Engineer)를 위한 리눅스 커널 이야기&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;*홍보의 목적이 아닌 정확한 정보 전달 위해 명시했습니다. 책 링크는 아래 달아두도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 참고&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001033135&quot;&gt;https://product.kyobobook.co.kr/detail/S000001033135&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>dev.log</category>
      <category>리눅스 커널</category>
      <category>프런트엔드</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/134</guid>
      <comments>https://xtring-dev.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%ED%8C%80-%EC%8A%A4%ED%84%B0%EB%94%94%EC%97%90%EC%84%9C-%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%BB%A4%EB%84%90%EC%9D%B4-%EC%84%A0%EC%A0%95%EB%90%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0#entry134comment</comments>
      <pubDate>Sun, 10 Nov 2024 20:47:38 +0900</pubDate>
    </item>
    <item>
      <title>[Products] 3주만에 가능할까? FE 개발자의 기획부터 개발까지의 이야기</title>
      <link>https://xtring-dev.tistory.com/entry/Products-3%EC%A3%BC%EB%A7%8C%EC%97%90-%EA%B0%80%EB%8A%A5%ED%95%A0%EA%B9%8C-FE-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EA%B8%B0%ED%9A%8D%EB%B6%80%ED%84%B0-%EA%B0%9C%EB%B0%9C%EA%B9%8C%EC%A7%80%EC%9D%98-%EC%9D%B4%EC%95%BC%EA%B8%B0-%EC%BB%AC%EB%A6%AC-%EC%87%BC%EC%BC%80%EC%9D%B4%EC%8A%A4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-10-13 at 18.32.08.png&quot; data-origin-width=&quot;2030&quot; data-origin-height=&quot;1978&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O4P0S/btsJ20CwcVz/OBjzIZapANoEagfWrO9ht1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O4P0S/btsJ20CwcVz/OBjzIZapANoEagfWrO9ht1/img.png&quot; data-alt=&quot;Created by ChatGPT&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O4P0S/btsJ20CwcVz/OBjzIZapANoEagfWrO9ht1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO4P0S%2FbtsJ20CwcVz%2FOBjzIZapANoEagfWrO9ht1%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;550&quot; height=&quot;536&quot; data-filename=&quot;Screenshot 2024-10-13 at 18.32.08.png&quot; data-origin-width=&quot;2030&quot; data-origin-height=&quot;1978&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Created by ChatGPT&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;기존의 전통적인 이커머스 서비스의 상품 탐색과 구매 여정을 새로운 방식으로 풀어가기 위해 만들어진 TF에 참여한 이야기를 소개합니다.&amp;nbsp; 새로운 서비스 &lt;code&gt;쇼케이스&lt;/code&gt;를 만들어가게되는 과정 속 실무자들과 긴밀하게 소통하여 제품을 출시하는 이야기도 함께하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;*개발 구현 사항에 아주 구체적인 이야기를 하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 &lt;b&gt;기획-디자인-개발-QA의 프로세스를 이터레이션&lt;/b&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;아이디어 수립은 여러가지 방법이 있습니다. 흔히 알고 있는 브레인 스토밍 기법 부터 단순히 생각나는 아이디어를 꺼내 이야기해보는 방법까지 다양합니다.(이 글에서는 아이디어를 수립하는 것이 주요한 주제가 아니기에 자세히 다루지 않겠습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에게 맛과 퀄리티가 검증된 상품을 제공한다는 컬리의 중요한 컨셉과 일치하여 재밌을 것 같다고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; UX/UI와 설계는&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이커머스의 제품에는 특정 카테고리의 상품을 전시하고 설명을 보여주는 전통적이고 관습적인 방식이 있습니다. 대부분의 이커머스는 상품 목록과 상품 상세 페이지를 통해서 상품을 탐색하고 설명하려고 합니다. 이러한 UX의 틀을 바꿔보기 위해서 목록의 탐색 경험과 상품 구매 경험을 함께 할 수 있도록 하는 UX/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;컬리는 하나의 상품을 출시하는 MD가 직접 검증하고 다수의 팀과 확인하여 제품을 소개합니다. 그 만큼의 컬리 상품상세는 직접 선택한 실무자의 의도가 많이 반영되어 있다는 것을 알 수 있는데, 그점에 착안하여 각 상품의 설명은 상품 상세 페이지의 디스크립션을 사용하여 만들어내는 것을 결정하게 되었습니다. 그렇게 하여 말 그대로 쇼케이스에 담긴 선정된 상품을 소개하는 쇼케이스라는 이름의 서비스가 탄생합니다.&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;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 개발을 위해 고려해야하는 것&lt;/h3&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;1. 재사용&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;h4 data-ke-size=&quot;size20&quot;&gt;2. 콘텐츠 제작을 쉽고 빠르게&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘텐츠는 출시된 상품의 상품상세 디스크립션을 사용하여 제작되기 때문에 특별히 검수해야 것은 없었기 때문에 데이터를 구성하여 템플릿에 집어 넣을지만 생각하면 됐습니다. 따라서 재사용되는 블록 단위의 컴포넌트를 어떤식으로 구성하냐를 결정하면 데이터를 나열하기만 하도록 결정했습니다. 그러나 쇼케이스에서 보여주고자 하는 특정한 정보만을 위해서 새로운 API를 구성하는 것보다 간단한 방식을 고민했고 AWS S3를 통해 콘텐츠 데이터를 관리하게 되었습니다.&lt;/p&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 중 유저 기반의 상품 정보 제공을 위한 API를 사용하게 되었습니다. 상품을 전시하는 것 중 유저에게 약간은 민감한 부분으로 가격과 할인 정보, 판매여부와 같은 것들이 있습니다. 기존에 잘 만들어진 API를 사용하여 실시간으로 변동되는 상품 정보를 가져올 수 있도록 합니다.&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;3. 지루한 콘텐츠는 보기 어렵다&lt;/h4&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;개발 과정&lt;/h2&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;매달 출시할 수 있도록 제공하는 방법으로 페이지를 모듈로 구성할 수 있게 만들었습니다. 상품에 구성될 요소들을 지정하고 정적 데이터를 통해 콘텐츠를 만들 수 있도록 구성요소를 모듈화하여 제공했습니다. 따라서 수십개의 상품을 단순히 JSON 수정을 통해서 간단히 조작할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; UI?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품의 지속가능성을 고려해 템플릿화(블록단위의 분리)를 했습니다. 각 블록 단위는 타입을 가지며 S3에 배포된 JSON 데이터에 명시되어 있는 형태에 끼워맞춰 콘텐츠를 보여줍니다. 그래서 각 블록을 구성하는 요소의 데이터 구조 단일화를 통해서 어떤 타입의 블록이더라도 마케팅팀이 원하는 블록을 사용할 수 있도록 분리했습니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;블록 단위로 운용되는 컴포넌트가 결정되니 각 위치에서 사용될 애니메이션이 쉽게 결정될 수 있었습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애니메이션 효과를 극적으로 만들어 눈에 띄는 UI를 만들어야 하는 미션이 있었습니다. 디자이너와의 협업을 통해 UX/UI를 만들어가는 경험을 했습니다. 의견을 제시하기도하고 프로토타입을 빠르게 만들어 공유하기도 했습니다.&amp;nbsp;애니메이션은 첫 화면에서 사용자가 스크롤을 통해 몰입감을 줄 수 있도록 'SHOW CASE' 라는 글자 속으로 들어가는 효과와 이번 쇼케이스의 키워드를 보여주는 페이지를 설정했습니다. 그리고 연속적으로 소개되는 상품 콘텐츠를 스크롤시 나타나게하여 스크롤 액션을 유도했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 데이터?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 없이 개인화된 상품 상태를 제공하는 방법은 기존 API를 사용해볼 수 있었습니다. 인증체계를 통해 사용자의 주문위치와 제공되는 상품의 상태를 쉽게 가져올 수 있었습니다. 상품 상태는 사용자에게 민감합니다. 실제 주문이 가능하지 않지만 주문이 가능하거나, 장바구니 담기지만 실제로 구매할 수 없다면 사용자에게 네거티브한 경험으로 연결됩니다. 상품 콘텐츠 번호를 쇼케이스 콘테츠 데이터와 1:1로 매칭하여 데이터의 연결하고 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #8a3db6;&quot;&gt;&amp;nbsp;&lt;/span&gt; 마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &lt;code&gt;컬리 쇼케이스&lt;/code&gt;를 개발했던 여정에 대해서 들려드렸습니다. 이번 과정을 통해 다시 한번 다양한 담당자들과 소통하고 협의하는 방법을 배우게 된 것 같습니다. 또 아이디어를 빠르게 구현하고 출시하는 것에 대해서 즐거움을 느꼈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 제품을 개발하는데 혼자 만들어내지 않습니다. 그렇기 때문에 제품이 만들어지는 과정의 전체적인 프로세스를 이해하고 과정중 병목지점과 실행방식을 계속해서 고민할 필요가 있습니다. 다만 이것들을 더 매끄럽게 진행해가는 것은 할때마다 쉽지만은 않다는 것을 느낍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쇼케이스 페이지&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;를 직접 확인해보세요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.kurly.com/events/showcase/202410&quot;&gt;https://www.kurly.com/events/showcase/202410&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d; text-align: start;&quot;&gt;*Mobile 브라우저와 앱에서만 확인가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/Products</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/133</guid>
      <comments>https://xtring-dev.tistory.com/entry/Products-3%EC%A3%BC%EB%A7%8C%EC%97%90-%EA%B0%80%EB%8A%A5%ED%95%A0%EA%B9%8C-FE-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EA%B8%B0%ED%9A%8D%EB%B6%80%ED%84%B0-%EA%B0%9C%EB%B0%9C%EA%B9%8C%EC%A7%80%EC%9D%98-%EC%9D%B4%EC%95%BC%EA%B8%B0-%EC%BB%AC%EB%A6%AC-%EC%87%BC%EC%BC%80%EC%9D%B4%EC%8A%A4#entry133comment</comments>
      <pubDate>Sun, 13 Oct 2024 17:36:49 +0900</pubDate>
    </item>
    <item>
      <title>5년차 FE의 과거부터 현재까지 - 삶의 지도</title>
      <link>https://xtring-dev.tistory.com/entry/%EC%82%B6%EC%9D%98-%EC%A7%80%EB%8F%84-5%EB%85%84%EC%B0%A8-FE-%EA%B3%BC%EA%B1%B0%EB%B6%80%ED%84%B0-%ED%98%84%EC%9E%AC%EA%B9%8C%EC%A7%80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.jpg&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1191&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yYKsp/btsJGuxmU3p/h7sc9ngQQrkRF0h31DXD1k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yYKsp/btsJGuxmU3p/h7sc9ngQQrkRF0h31DXD1k/img.jpg&quot; data-alt=&quot;&amp;quot;뭐 어쩌겠어. 해야지&amp;quot;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yYKsp/btsJGuxmU3p/h7sc9ngQQrkRF0h31DXD1k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyYKsp%2FbtsJGuxmU3p%2Fh7sc9ngQQrkRF0h31DXD1k%2Fimg.jpg&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;501&quot; height=&quot;506&quot; data-filename=&quot;1.jpg&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1191&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&quot;뭐 어쩌겠어. 해야지&quot;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;*이 글은 글또 10기 '삶의 지도'를 위해 작성된 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;과거부터 현재까지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;돌이켜보면 생각하는 것을 현실로 만들어내는 것을 좋아해오고 있다. 어릴적에는 노트에 게임을 만들거나 레고로 무언가를 만들고 과학 발명 경진대회에 나갔다. 성인이 된 이후에 밴드를 통해 작곡을 하고 창업 동아리를 운영하기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 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;부모님의 사업으로 스무살 이전에만 두 지역에서 8번 이사했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초등학교는 3번 전학을 다녔고 늘 새로운 친구들, 사람들을 만나고 적응하는데 애쓰기도 했다.&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;예술 계열에 관심이 많았던 터라 고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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5년차 개발자로 일하면서&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간은 너무 빠르게 지나가고 기록하고 남기지 않으면 결국 잊어버리게 된다는 것을 깨달았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힘들게 해결한 문제, 그 문제를 해결하기 위한 접근 방법과 과정, 기억하고 싶은 것들은 어딘가 기록하지 않으면 하루만 지나도 흐릿해진다. 그래서 개발자를 시작한지 얼마 안된 시기엔 다양한 방법으로 기록하려는 노력을 했고 공부한 것들을 블로그에 작성하는 습관을 가지기도 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연차가 쌓이고 더 아는게 많아지니 눈에 보이고 해야하는 것들이 더 많아지는 것을 알게 되었다. 그럴수록 배운 것, 실행한 것에 대해서 기록해야 했는데 일이 바쁘다는 이유로, 쉬고싶다는 이유로 기록을 위한 글쓰기를 멈추고 필요에 의한 글쓰기만 하게 된것 같다. 그래서 글또 10기에 지원하여 다양한 사람들의 글쓰기를 엿보며 자극을 받기도하고 내 글을 쓰는데 투자해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술에 대해서보다 함께 일하는 사람들(팀)에 대한 생각이 조금 더 커진 것 같다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;요즘은 새로운 것을 배우는 것에 큰 행복을 느낀다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 1년 동안 3가지 새로운 도전을 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PT를 시작해서 운동하는 습관을 만들어 건강에 대해 신경쓰게 되었고, MIDI를 배워서 내가 만든 노래를 스퀀스 프로그램에 기록할 수 있게 되었고, 매뉴얼 바이크를 구매하여 모터사이클 스포츠를 즐기고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계획을 통해 실행된 것들은 아니었지만 하고 싶은 것을 잘 배우고 자연스럽게 해나갈 때마다 그 짜릿함은 누워서 쉬거나, 쇼츠를 보거나, 술만 마시는 것보다 스트레스를 해소하고 삶의 행복을 느끼게 해주었다. 실제로도 이것들을 통해 새로운 성취감을 얻으니 번아웃이 오는 빈도가 확실히 줄어들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취미를 가지거나 일이 아닌 무언가를 잘하고 싶을 때면 '프로같은 아마추어가 되자'고&amp;nbsp;생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아버지가 어렸을 때 해주셨던 말인데 기억한다. 서른이 넘어가는 나이에도 나에게 매우 인상적이었나보다. 내 삶을 만들어준 중요한 한마디라고 생각하고 계속 실천할 생각이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;최근 커리어에 대한 고민을 다시 시작하고 있다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FE 서비스 개발자로서 다음 스탭을 어떤 방향으로 나가면 좋을지, 스스로 자신은 있는지 숨쉬고 밥먹고 걸으면서도 고민하고 있다. 대학 시절부터 관심이 많았던 데이터나 인공지능으로 나가볼지 서비스 개발자로서 풀스택 개발자가 되는 길이 맞을지 각 분야를 살짝 건들어보며 간을 보고 있다. 결정하면 고민없이 해볼 생각이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>xtring.log</category>
      <category>FE</category>
      <category>개발자</category>
      <category>삶의지도</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/132</guid>
      <comments>https://xtring-dev.tistory.com/entry/%EC%82%B6%EC%9D%98-%EC%A7%80%EB%8F%84-5%EB%85%84%EC%B0%A8-FE-%EA%B3%BC%EA%B1%B0%EB%B6%80%ED%84%B0-%ED%98%84%EC%9E%AC%EA%B9%8C%EC%A7%80#entry132comment</comments>
      <pubDate>Sat, 21 Sep 2024 17:02:04 +0900</pubDate>
    </item>
    <item>
      <title>[NPM] npm install시 --save-exact 옵션을 사용해주세요</title>
      <link>https://xtring-dev.tistory.com/entry/NPM-npm-install%EC%8B%9C-save-exact-%EC%98%B5%EC%85%98%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;node 기반 프로젝트 개발시 npm을 통해 여러 패키지를 설치하곤 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm에 배포된 수많은 패키지를 사용할때 주의할 점 중 하나로 node에 대한 호환성과 타 패키지와의 의존성을 고려해해야 한다. 보통 NPM이 이런 문제들을 해결해주곤하지만 때때로 의존성 충돌로 인해 골머리를 쓰게 될때도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 협업을 하며 하나의 프로젝트에서 npm를 통해 패키지를 다운로드하고 개발할때 서로 다른 버전의 패키지를 사용하면 개발중 문제가 발생할 수 있다.&lt;/p&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;code&gt;npm install&lt;/code&gt; 시 우리는 &lt;code&gt;npm install &amp;lt;package-name&amp;gt;&lt;/code&gt;하곤하는데 이는 다시 npm 패키지를 설치할때 틸드(~)나 캐럿(^)에 의해 특정 범위의 서로 다른 패키지를 다운로드할 수 있게 된다. 짧은 기간 내에 패키지의 코어한 기능이 수정되지 않는 경우 문제가 없겠지만 아닌 경우 갑자기 프로젝트의 동작이 이상해지거나 빌드가 안되는 이슈가 발생할 수 있다.(혹은 같은 로컬 빌드지만 동작이 다르다거나)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;따라서 패키지를 미리 설정된 정확한 버전으로 설치해줄 수 있도록하는 옵션이 필요하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm intall 시 사용할 수 있는 옵션 중 &lt;code&gt;--save-exact&lt;/code&gt; or &lt;code&gt;-E&lt;/code&gt;옵션은 '패키지의 정확한 버전을 고정으로 설치하겠다'는 기능이다.&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;$ npm install --save-exact &amp;lt;package-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 해당 프로젝트 내에서 항상 '정확한 버전만을 설치'하겠다는 세팅을 줄수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 npm 명령어로 세팅하거나 &lt;code&gt;.npmrc&lt;/code&gt;에 &lt;code&gt;save-exact=true&lt;/code&gt; 옵션을 추가한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;$ npm config set save-exact=true&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;// .npmrc

...
save-exact=true&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ref&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/front-end-weekly/how-to-save-exact-npm-package-versions-7f8ff9a0415a&quot;&gt;How to save exact npm package versions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Front-End/NPM</category>
      <category>npm</category>
      <category>save-exact</category>
      <author>xtring</author>
      <guid isPermaLink="true">https://xtring-dev.tistory.com/131</guid>
      <comments>https://xtring-dev.tistory.com/entry/NPM-npm-install%EC%8B%9C-save-exact-%EC%98%B5%EC%85%98%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94#entry131comment</comments>
      <pubDate>Mon, 22 Apr 2024 09:17:39 +0900</pubDate>
    </item>
  </channel>
</rss>