<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>현기의 개발블로그</title>
    <link>https://hyunki99.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 6 Aug 2026 18:40:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>현기</managingEditor>
    <image>
      <title>현기의 개발블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/5428570/attach/f9436ac212544554b81945a22e031817</url>
      <link>https://hyunki99.tistory.com</link>
    </image>
    <item>
      <title>[React] FSD 아키텍처란? 유지보수하기 좋은 프론트엔드 구조</title>
      <link>https://hyunki99.tistory.com/137</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;들어가며&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;201&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/poVaG/dJMcaaLcMpR/lfRQZAki6iFP0v2y2X7BY0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/poVaG/dJMcaaLcMpR/lfRQZAki6iFP0v2y2X7BY0/img.jpg&quot; data-alt=&quot;출처 : https://www.instagram.com/p/DR4F7zGiScJ/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/poVaG/dJMcaaLcMpR/lfRQZAki6iFP0v2y2X7BY0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpoVaG%2FdJMcaaLcMpR%2FlfRQZAki6iFP0v2y2X7BY0%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;314&quot; height=&quot;392&quot; data-origin-width=&quot;201&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://www.instagram.com/p/DR4F7zGiScJ/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;어느 정도 프론트엔드 개발에 익숙해지다 보니, 신규 기능 개발은 이제 크게 어렵지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실상 가장 힘든 일은 이해하기 어렵게 짜여진 코드의 맥락을 추적하고, 파편화되어 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;흩어져 있는 코드를 유지 보수하는 일&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 이런 어려움을 해소할 수 있는 방법 중 하나인 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Feature-Sliced Design (FSD) 아키텍처 방법론&lt;/span&gt;&lt;/b&gt;을 소개합니다.  &lt;/p&gt;
&lt;p style=&quot;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;b&gt;보통 리액트 프로젝트의 폴더구조&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1292&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csqmNc/dJMcaaqUoHO/Z1KP5VakXbVsALGFzWKOi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csqmNc/dJMcaaqUoHO/Z1KP5VakXbVsALGFzWKOi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csqmNc/dJMcaaqUoHO/Z1KP5VakXbVsALGFzWKOi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsqmNc%2FdJMcaaqUoHO%2FZ1KP5VakXbVsALGFzWKOi0%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;546&quot; height=&quot;290&quot; data-origin-width=&quot;1292&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리에게 익숙한 간단하고 대중적인 폴더 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일의 역할에 따라 폴더를 나눕니다. 계층형 구조 혹은 역할 기반 구조라고 부르기도 합니다.&lt;/p&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2BO8S/dJMcagq6VeE/C00WW4tKY14giK8TbNQInk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2BO8S/dJMcagq6VeE/C00WW4tKY14giK8TbNQInk/img.png&quot; data-alt=&quot;나노바나나 - 파일들의 의존성이 복잡하게 얽혀있어 머리아픈 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2BO8S/dJMcagq6VeE/C00WW4tKY14giK8TbNQInk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2BO8S%2FdJMcagq6VeE%2FC00WW4tKY14giK8TbNQInk%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;551&quot; height=&quot;291&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;541&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;나노바나나 - 파일들의 의존성이 복잡하게 얽혀있어 머리아픈 이미지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;ldquo;컴포넌트가 소비되는 곳과 가까운 곳에 위치하지 않는다.&amp;rdquo;&lt;/span&gt;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 컴포넌트 하나를 수정하기 위해 components, api, hooks 폴더를 이리저리 뒤적여야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연관된 파일을 파악하기 어려운 구조는 개발자의 실수를 유발하고, 피로도를 높입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;✅ 짧은 팁&lt;/b&gt;&lt;br /&gt;IDE의 전체 검색 Ctrl + Shift + F, 이 파일이 어디에서 사용중인지 확인하는 Find Usages를 사용하면 &lt;br /&gt;조금 더 편하게 폴더를 이리저리 뒤적일 수 있습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;React Colocation - 가까이 둡시다.&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1772703571892&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 계층형 구조 : 흩어져있는 코드
src/
 ├── api/ (UserAPI, PostAPI, AuthAPI...)
 ├── components/ (UserCard, PostList, Button...)
 ├── hooks/ (useUser, usePost, useAuth...)
 └── types/ (user.d.ts, post.d.ts...)

// colocation : 자주 함께 변경되는 파일들을 같이 보관해보자
src/
 └── features/
      └── user/
           ├── UserProfile.tsx
           ├── useUser.ts      
           ├── user.api.ts
           ├── user.d.ts
           └── UserProfile.styles.css&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;React에서 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://kentcdodds.com/blog/colocation#lets-talk-about-code-comments&quot;&gt;Colocation&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;은 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;ldquo;일반적으로 자주 함께 변경되는 것들을 같이 보관&amp;rdquo;&lt;/span&gt;&lt;/b&gt;하는 원칙을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 로직, 파일을 가깝게 배치하는 것만으로도 가독성과 유지보수성이 향상됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 프로젝트의 규모가 거대해지고, &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;수십 개의 컴포넌트가 서로 엉키기 시작하면 어떨까요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 '가깝게 두는 것'만으로는 해결되지 않는 순환 참조와 의존성 지옥이 기다리고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;user 폴더의 컴포넌트에서 post 폴더를 참조해도 되는지 등의 규칙&lt;/b&gt;&lt;/span&gt;이 없기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 더 견고한 아키텍처를 위한 어떠한 규칙, 방법론이 필요하게 됩니다.&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p 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;b&gt;FSD(&lt;span data-token-index=&quot;1&quot;&gt;Feature-Sliced Design)란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://feature-sliced.design/kr/docs/get-started/overview&quot;&gt;https://feature-sliced.design/kr/docs/get-started/overview&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1772704457600&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;Overview | Feature-Sliced Design&quot; data-og-description=&quot;Feature-Sliced Design (FSD) 는 프론트엔드 애플리케이션의 코드를 구조화하기 위한 아키텍처 방법론입니다.&quot; data-og-host=&quot;feature-sliced.design&quot; data-og-source-url=&quot;https://feature-sliced.design/kr/docs/get-started/overview&quot; data-og-url=&quot;https://feature-sliced.design/kr/docs/get-started/overview&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5TbMD/dJMb8RRPHwh/avJsAbzKH2Z6TTVXUZbq70/img.png?width=1200&amp;amp;height=630&amp;amp;face=298_67_408_177,https://scrap.kakaocdn.net/dn/biCb97/dJMb8XkdaKr/MhbR1j3NZtCBGotXmCAH6k/img.png?width=1200&amp;amp;height=630&amp;amp;face=298_67_408_177,https://scrap.kakaocdn.net/dn/dlpNrq/dJMb88eYso7/lwC0MCiVAPFCtylrRwLLT1/img.png?width=2920&amp;amp;height=1040&amp;amp;face=0_0_2920_1040&quot;&gt;&lt;a href=&quot;https://feature-sliced.design/kr/docs/get-started/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://feature-sliced.design/kr/docs/get-started/overview&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5TbMD/dJMb8RRPHwh/avJsAbzKH2Z6TTVXUZbq70/img.png?width=1200&amp;amp;height=630&amp;amp;face=298_67_408_177,https://scrap.kakaocdn.net/dn/biCb97/dJMb8XkdaKr/MhbR1j3NZtCBGotXmCAH6k/img.png?width=1200&amp;amp;height=630&amp;amp;face=298_67_408_177,https://scrap.kakaocdn.net/dn/dlpNrq/dJMb88eYso7/lwC0MCiVAPFCtylrRwLLT1/img.png?width=2920&amp;amp;height=1040&amp;amp;face=0_0_2920_1040');&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;Overview | Feature-Sliced Design&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Feature-Sliced Design (FSD) 는 프론트엔드 애플리케이션의 코드를 구조화하기 위한 아키텍처 방법론입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;feature-sliced.design&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxJfeL/dJMcaiCvxBv/iGJjHCDmmgftsfZ3eSiFE1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxJfeL/dJMcaiCvxBv/iGJjHCDmmgftsfZ3eSiFE1/img.jpg&quot; data-alt=&quot;https://feature-sliced.design/docs/get-started/overview&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxJfeL/dJMcaiCvxBv/iGJjHCDmmgftsfZ3eSiFE1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxJfeL%2FdJMcaiCvxBv%2FiGJjHCDmmgftsfZ3eSiFE1%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;619&quot; height=&quot;344&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;712&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://feature-sliced.design/docs/get-started/overview&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;FSD&lt;/b&gt;&lt;/span&gt;는 프론트엔드 애플리케이션의 코드를 구조화하기 위한 아키텍처 방법론입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 프로젝트에서 유지보수를 쉽게 만들기 위해 등장했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드가 &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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 레이어 (Layer)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;382&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Npjvm/dJMcabpPVh5/InKue508mYkNtbGvk5LkU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Npjvm/dJMcabpPVh5/InKue508mYkNtbGvk5LkU1/img.png&quot; data-alt=&quot;https://feature-sliced.design/kr/docs/reference/layers&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Npjvm/dJMcabpPVh5/InKue508mYkNtbGvk5LkU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNpjvm%2FdJMcabpPVh5%2FInKue508mYkNtbGvk5LkU1%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;217&quot; height=&quot;303&quot; data-origin-width=&quot;382&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://feature-sliced.design/kr/docs/reference/layers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;레이어는 FSD에서 코드를 나눌 때 사용하는 가장 큰 구분 단위입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;핵심은 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;ldquo;상위 레이어는 하위 레이어만 참조할 수 있다&amp;rdquo;&lt;/span&gt;&lt;/b&gt;는 단방향 의존성 규칙입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; 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;span style=&quot;color: #9d9d9d;&quot;&gt;(리액트도 그렇고 프론트엔드 생태계는 단방향을 참 좋아하는 것 같아요.)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6개의 주요 레이어 요약&lt;/b&gt;&lt;/p&gt;
&lt;table id=&quot;31aa4252-adf6-8040-bfa5-c573f793bc69&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;31aa4252-adf6-8035-bc5b-f6ad800a5501 background-color:#E3F2FD &quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;레이어&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;31aa4252-adf6-801d-a99b-df235cb9e410&quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;App&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;애플리케이션의 설정, 전역 스타일, 프로바이더(Provider) 등&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;AppProvider, GlobalStyles, main.tsx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;31aa4252-adf6-8081-bde8-c044a10358a6&quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;Pages&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;사용자에게 보여지는 개별 페이지 단위로 실제 콘텐츠를 조립하는 곳&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;HomePage, ProductDetailPage, LoginPage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;31aa4252-adf6-80ce-94b9-dc7a97eed2e2&quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;Widgets&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;독립적인 UI 블록으로 여러 페이지에서 재사용되는 대규모 기능 또는 UI&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;Header, Sidebar, Footer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;31aa4252-adf6-80c0-920b-ead3ee5699ac&quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;Features&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;사용자의 행동(Action)과 관련된 비즈니스 가치를 제공&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;LoginByEmail, AddToCart, SearchProducts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;31aa4252-adf6-809c-a7f9-fd6512ad3c14&quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;Entities&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;비즈니스 실체(객체)를 나타냅니다. 데이터 모델, 상태, API 요청이 포함됩니다.&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;User, Product, Order, Comment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;31aa4252-adf6-80ec-b4b8-eb185583e8b8&quot;&gt;
&lt;td id=&quot;q{zf&quot; style=&quot;width: 11.7442%;&quot;&gt;&lt;b&gt;Shared&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;AS;S&quot; style=&quot;width: 59.9999%;&quot;&gt;프로젝트 전반에서 재사용되는 인프라성 코드와 공통 UI 컴포넌트입니다.&lt;/td&gt;
&lt;td id=&quot;J=bO&quot; style=&quot;width: 28.1396%;&quot;&gt;Button, Input, APIClient, DateUtils&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Slice - &lt;span data-token-index=&quot;0&quot;&gt;비즈니스 도메인에 따른 최소 단위의 구분&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;슬라이스는 FSD 아키텍처의 2번째 계층입니다. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;레이어 내 코드를 비즈니스 도메인별로 나눕니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;슬라이스의 이름은 비즈니스 도메인에 맞게 자유롭게 정할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;핵심 규칙은 &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;&quot;슬라이스끼리는 서로를 알 수 없다.&quot;&lt;/b&gt;&lt;/span&gt; 입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어, features/auth 슬라이스는 같은 레이어에 있는 features/cart 슬라이스를 참조할 수 없습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(import 못한다는 소리입니다.)&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  왜 서로 참조하지 못하게 하나요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;파일들을 비즈니스 맥락에 따라 한곳에 모음으로써 &lt;b data-index-in-node=&quot;40&quot; data-path-to-node=&quot;14,3&quot;&gt;높은 응집도&lt;/b&gt;를 확보하고, 슬라이스 간의 의존성을 끊어 &lt;b data-index-in-node=&quot;70&quot; data-path-to-node=&quot;14,3&quot;&gt;낮은 결합도&lt;/b&gt;를 유지하기 위해서입니다. 덕분에 프로젝트가 거대해져도 특정 기능을 수정할 때 발생하는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;사이드 이펙트를 최소화하고 코드 베이스를 훨씬 쉽게 탐색&lt;/b&gt;&lt;/span&gt;할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. Segment -&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;파일의 역할에 따른 최종 분류&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;세그먼트는 FSD 아키텍쳐의 3번째 계층입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;슬라이스가 하나의 비즈니스 도메인으로 분류된다면,&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;세그먼트는 슬라이스의 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;비즈니스 덩어리를 기술적인 역할에 따라 다시 한번 분리합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이름은 자유롭게 정할 수 있지만 보통 아래와 같은 이름을 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1773218092973&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;user
 ├ ui     // 화면에 보여지는 모든 것(컴포넌트, 스타일)
 ├ api    // 서버와의 통신
 ├ model  // 데이터 핵심 로직 (인터페이스, 상태 관리/Store)
 ├ lib    // 이 슬라이스에서만 사용하는 보조 도구 (라이브러리, 유틸)
 └ config // 설정 값&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  &lt;/b&gt;모든 레이어에서 세그먼트가 꼭 같아야할까?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;반드시 그렇지 않습니다. 대부분의 경우 위의 세그먼트만으로 충분합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만, 공유(shared) 레이어나 앱(app) 레이어에서는 필요에 따라 새로운 세그먼트를 만들어도 됩니다. (강제된 규칙이 아닙니다.)&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 기본 구조는 유지하되, 필요하면 유연하게 확장할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+ FSD 전체 폴더 구조 예시&lt;/b&gt;&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;pre id=&quot;code_1773218491958&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;src
│
├ app
│  ├ providers
│  ├ router
│  ├ styles
│  └ index.tsx
│
├ pages
│  ├ home
│  │  ├ ui
│  │  │  └ HomePage.tsx
│  │  └ index.ts
│  │
│  └ profile
│     ├ ui
│     │  └ ProfilePage.tsx
│     └ index.ts
│
├ widgets
│  ├ header
│  │  ├ ui
│  │  │  └ Header.tsx
│  │  └ index.ts
│  │
│  └ sidebar
│     ├ ui
│     │  └ Sidebar.tsx
│     └ index.ts
│
├ features
│  ├ login
│  │  ├ ui
│  │  │  └ LoginForm.tsx
│  │  ├ model
│  │  │  └ useLogin.ts
│  │  ├ api
│  │  │  └ loginApi.ts
│  │  └ index.ts
│  │
│  └ add-to-cart
│     ├ ui
│     │  └ AddToCartButton.tsx
│     ├ model
│     │  └ cartStore.ts
│     ├ api
│     │  └ addCartApi.ts
│     └ index.ts
│
├ entities
│  ├ user
│  │  ├ ui
│  │  │  └ UserAvatar.tsx
│  │  ├ model
│  │  │  └ userStore.ts
│  │  ├ api
│  │  │  └ userApi.ts
│  │  └ index.ts
│  │
│  └ product
│     ├ ui
│     │  └ ProductCard.tsx
│     ├ model
│     │  └ productTypes.ts
│     ├ api
│     │  └ productApi.ts
│     └ index.ts
│
├ shared
│  ├ ui
│  │  ├ Button
│  │  │  └ Button.tsx
│  │  └ Input
│  │     └ Input.tsx
│  │
│  ├ lib
│  │  └ formatDate.ts
│  │
│  ├ api
│  │  └ baseApi.ts
│  │
│  └ config
│     └ env.ts
│
└ main.tsx&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;FSD의 장점과 단점&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. 프로젝트 구조가 통일됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 기능이 같은 구조를 사용하기 때문에 코드가 훨씬 일관성 있게 정리됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;새로운 개발자가 프로젝트에 투입되어도 어디에 코드가 있고, 어디를 수정해야 하는지 빠르게 이해할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 변경과 리펙토링이 쉬워집니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위에서 설명한 FSD의 계층별 규칙(레이어, 슬라이스)을 통해 한 기능을 수정해도 다른 기능에 영향을 줄 가능성이 줄어듭니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. 유지 보수성이 향상됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;어떤 코드는 여러 곳에서 재사용해야 하고, 어떤 코드는 특정 기능에서만 사용해야 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;FSD 아키텍쳐를 사용하면 공유 코드는 shared, 특정 기능 코드는 feature처럼 재사용 범위를 자연스럽게 나눌 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4. 비즈니스 중심 구조가 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;폴더 이름을 비즈니스 용어로 만들기 때문에 실제 서비스 개념과 코드 구조가 맞춰집니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;개발자는 프로젝트 전체를 완벽하게 이해하지 않아도 자신이 맡은 기능을 개발할 수 있게 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 신규 입사자의 온보딩 속도가 빨라지겠죠 !&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. 초기 구조가 복잡하다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;레이어, 슬라이스, 세그먼트로 분리하기 때문에 폴더 구조가 꽤 많아집니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 작은 프로젝트에는 오히려 오버 엔지니어링이 될 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이런 경우에는 공식 문서에서 소개하는 &lt;u&gt;&lt;a href=&quot;https://feature-sliced.design/docs/get-started/overview#incremental-adoption&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;점진적 도입&lt;/a&gt;&lt;/u&gt;을 참고하세요.  &lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 러닝 커브&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;FSD는 일반적인 React 폴더 구조와 다르고, 각 계층의 규칙이 존재하기 때문에 처음 접하는 개발자에게는 이해하기 어려울 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. 규칙이 중요하다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;FSD는 정해진 규칙도 있고, 유연하게 팀에서 만든 규칙을 적용할 수도 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 규칙을 잘 정하고 잘 지키지 않으면 FSD의 구조가 망가지게 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(같은 팀에서 같은 컨벤션도 지키기 힘든데 잘 지켜지는 회사의 모습이 궁금하네요  )&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;참고 문헌:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #353638; text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://feature-sliced.design/kr/docs/get-started/overview&quot;&gt;https://feature-sliced.design/kr/docs/get-started/overview&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://tech.kakaopay.com/post/fsd/&quot;&gt;https://tech.kakaopay.com/post/fsd/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>fsd 아키텍처</category>
      <category>react fsd</category>
      <category>리액트 폴더구조</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/137</guid>
      <comments>https://hyunki99.tistory.com/137#entry137comment</comments>
      <pubDate>Wed, 11 Mar 2026 23:40:11 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] AI 에이전트가 Vercel 엔지니어처럼 코드 리뷰를 해준다면? (프론트엔드 성능 최적화 가이드, react-best-practices)</title>
      <link>https://hyunki99.tistory.com/136</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;들어가며&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드 코드를 처음 사용하고 3달이 지난 2026년 현재, 개발하는 방식이 또 완전히 달라졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗GPT에게 질문하고 답변을 받아 직접 코딩하던 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&amp;lsquo;AI 어시스턴트&amp;rsquo;&lt;/b&gt;&lt;/span&gt; 방식에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커서나 클로드 코드 같이 스스로 판단하고 행동하며 작업을 자율적으로 수행하는 &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;&amp;lsquo;AI 에이전트 방식&amp;rsquo;&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;많은 기업과 개발자들이 AI 에이전트에 관심을 갖고, 실제 업무에 적극적으로 도입하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 AI를 잘 다루는 개발자와 그렇지 않은 개발자의 생산성 차이는 매우 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 앞으로 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;ldquo;코딩을 얼마나 잘하는가?&amp;rdquo;&lt;/span&gt;&lt;/b&gt;보다, &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;ldquo;AI 에이전트를 얼마나 더 잘 다루고 활용할 수 있는가?&amp;rdquo;&lt;/span&gt;&lt;/b&gt;가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 핵심 역량이 될 것이라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 Vercel에서 React/Next.js 개발 10년의 노하우가 담긴 react-best-practices를 공개했습니다.&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;그냥 읽어도 큰 도움이 되지만, 클로드 코드 같은 AI 에이전트에게 Skill로 주입해서 사용하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;프론트엔드 레전드 시니어 개발자&lt;/b&gt;&lt;/span&gt;에게 코드 리뷰를 무한대로 요청할 수 있게 됩니다. (물론 토큰 내에서요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함께 알아봅시다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;프론트엔드의 성능 최적화에 대해서&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8x7Rf/dJMcaiISXXX/xcE7BZqi6kqf5UJhbk2aj1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8x7Rf/dJMcaiISXXX/xcE7BZqi6kqf5UJhbk2aj1/img.jpg&quot; data-alt=&quot;출처: https://imgflip.com/i/6ck6k5&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8x7Rf/dJMcaiISXXX/xcE7BZqi6kqf5UJhbk2aj1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8x7Rf%2FdJMcaiISXXX%2FxcE7BZqi6kqf5UJhbk2aj1%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;403&quot; height=&quot;451&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://imgflip.com/i/6ck6k5&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;b&gt;&amp;lsquo;성능 최적화&amp;rsquo;&lt;/b&gt;는 프론트엔드 개발자에게 있어 아마도 골치 아픈 주제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱이 느린데 왜 느린지 모르겠고 성능 개선을 위해 코드 스플리팅, 이미지 &amp;amp; 폰트 최적화, memo와 useCallback 등 다양한 방법을 동원해봅니다.&lt;/p&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;lsquo;성능 최적화&amp;rsquo; 문제를 &lt;b&gt;AI 에이전트와 함께 검토하고 빠르게 개선해볼 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;React &lt;span data-token-index=&quot;0&quot;&gt;Best Practices&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://vercel.com/blog/introducing-react-best-practices&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://vercel.com/blog/introducing-react-best-practices&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1769673730212&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;Introducing: React Best Practices - Vercel&quot; data-og-description=&quot;We've encapsulated 10+ years of React and Next.js optimization knowledge into react-best-practices, a structured repository optimized for AI agents and LLMs.&quot; data-og-host=&quot;vercel.com&quot; data-og-source-url=&quot;https://vercel.com/blog/introducing-react-best-practices&quot; data-og-url=&quot;https://vercel.com/blog/introducing-react-best-practices&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dFiUrL/dJMb9kTXKc2/NXqxbT9PX1uTpkK2KPwFv1/img.png?width=720&amp;amp;height=377&amp;amp;face=0_0_720_377,https://scrap.kakaocdn.net/dn/c99957/dJMb9kl7BgT/k4ExvG9kmBuC2Y5TJBE6ok/img.png?width=720&amp;amp;height=377&amp;amp;face=0_0_720_377,https://scrap.kakaocdn.net/dn/Fa04e/dJMb9iIBTZG/au7MWqwk7vkUkp3YdKwN6K/img.png?width=828&amp;amp;height=964&amp;amp;face=0_0_828_964&quot;&gt;&lt;a href=&quot;https://vercel.com/blog/introducing-react-best-practices&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vercel.com/blog/introducing-react-best-practices&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dFiUrL/dJMb9kTXKc2/NXqxbT9PX1uTpkK2KPwFv1/img.png?width=720&amp;amp;height=377&amp;amp;face=0_0_720_377,https://scrap.kakaocdn.net/dn/c99957/dJMb9kl7BgT/k4ExvG9kmBuC2Y5TJBE6ok/img.png?width=720&amp;amp;height=377&amp;amp;face=0_0_720_377,https://scrap.kakaocdn.net/dn/Fa04e/dJMb9iIBTZG/au7MWqwk7vkUkp3YdKwN6K/img.png?width=828&amp;amp;height=964&amp;amp;face=0_0_828_964');&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;Introducing: React Best Practices - Vercel&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;We've encapsulated 10+ years of React and Next.js optimization knowledge into react-best-practices, a structured repository optimized for AI agents and LLMs.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vercel.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;React의 성능 최적화 작업은 대개 사후 대응적입니다.&lt;br /&gt;&lt;b&gt;앱이 출시되고 나면 앱 속도가 느려진 것처럼 느껴지고 그제서야 팀은 원인을 찾기 시작합니다.&lt;/b&gt;&lt;br /&gt;우리는 10년 넘게 운영 중인 코드베이스 전반에서 동일한 근본 원인을 목격해 왔습니다.&lt;br /&gt;-Vercel&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;너무 낮은 단계에서 시작하기 때문에 실패&lt;/b&gt;&lt;/span&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청 워터폴 때문에 대기 시간이 600ms 증가한다면, 최적화가 아무리 잘 되어 있어도 소용 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 최적화 우선순위에 따라서 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;높은 단계에서 아래 단계로 순서로 진행&lt;/span&gt;&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. 워터폴을 제거합니다.&lt;br /&gt;2. 번들 크기를 줄입니다.&lt;br /&gt;...&lt;br /&gt;~ 8.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;주요 카테고리 및 최적화 우선순위&lt;/b&gt;&lt;/p&gt;
&lt;table id=&quot;2f5a4252-adf6-80a6-a7c8-f9b3928496ae&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;2f5a4252-adf6-80c2-900a-d73a0e1c0bb5&quot; style=&quot;background-color: #eaf4ff;&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;우선순위&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%; text-align: center;&quot;&gt;&lt;b&gt;카테고리 (Category)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%; text-align: center;&quot;&gt;&lt;b&gt;영향도 (Impact)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%; text-align: center;&quot;&gt;&lt;b&gt;접두사 &lt;br /&gt;(Prefix)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%; text-align: center;&quot;&gt;&lt;b&gt;번역 및 설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-801b-8ffa-f68bcc9d8c68&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Eliminating Waterfalls&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;CRITICAL (치명적)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;async-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;워터폴(연쇄 지연) 제거&lt;/b&gt;: 데이터 요청이 꼬리에 꼬리를 물고 늦어지는 현상 방지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-80f7-a2a0-c77499819be3&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Bundle Size Optimization&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;CRITICAL (치명적)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;bundle-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;번들 크기 최적화&lt;/b&gt;: 자바스크립트 파일 용량을 줄여 초기 로딩 속도 개선&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-805d-a478-c61a796c8251&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;3&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Server-Side Performance&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;HIGH (높음)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;server-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;서버 사이드 성능&lt;/b&gt;: SSR이나 API 응답 등 서버 측 처리 효율화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-808c-bd94-fd92bc3421cb&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;4&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Client-Side Data Fetching&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;MEDIUM-HIGH (중상)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;client-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;클라이언트 데이터 페칭&lt;/b&gt;: 브라우저에서 데이터를 가져오는 방식 최적화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-8014-b8e1-c27b06669f7d&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;5&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Re-render Optimization&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;MEDIUM (보통)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;rerender-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;리렌더링 최적화&lt;/b&gt;: 불필요한 컴포넌트 재그리기를 방지하여 반응성 향상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-8082-96b0-ca16f2a27646&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;6&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Rendering Performance&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;MEDIUM (보통)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;rendering-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;렌더링 성능&lt;/b&gt;: 브라우저가 화면을 그리는 과정(Layout/Paint)의 효율성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-8017-877a-e89247caf6da&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;7&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;JavaScript Performance&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;LOW-MEDIUM (중하)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;js-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;자바스크립트 성능&lt;/b&gt;: 순수 로직 및 알고리즘 실행 속도 개선&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f5a4252-adf6-8000-99a6-c1ac833348fa&quot;&gt;
&lt;td id=&quot;[\d{&quot; style=&quot;width: 8.13953%; text-align: center;&quot;&gt;&lt;b&gt;8&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;Foo=&quot; style=&quot;width: 18.8372%;&quot;&gt;&lt;b&gt;Advanced Patterns&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;xafn&quot; style=&quot;width: 16.3953%;&quot;&gt;&lt;b&gt;LOW (낮음)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;|wh&amp;gt;&quot; style=&quot;width: 11.6279%;&quot;&gt;advanced-&lt;/td&gt;
&lt;td id=&quot;M?zD&quot; style=&quot;width: 44.8837%;&quot;&gt;&lt;b&gt;고급 패턴&lt;/b&gt;: 코드의 구조나 확장성을 위한 심화 설계 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 개선의 영향도에 따라 CRITICAL 단계부터 LOW 단계까지 8개 카테고리로 분류됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재&lt;b&gt; 8개의 카테고리&lt;/b&gt; 속에 &lt;b&gt;57개의 규칙&lt;/b&gt;이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;1288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHKXWD/dJMcahpI6O7/0ikIWLKQ1SKG5ry8CSGMsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHKXWD/dJMcahpI6O7/0ikIWLKQ1SKG5ry8CSGMsk/img.png&quot; data-alt=&quot;react-best-practices/rules/async-api-routes.md&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHKXWD/dJMcahpI6O7/0ikIWLKQ1SKG5ry8CSGMsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHKXWD%2FdJMcahpI6O7%2F0ikIWLKQ1SKG5ry8CSGMsk%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;514&quot; height=&quot;459&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;1288&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;react-best-practices/rules/async-api-routes.md&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;a href=&quot;https://github.com/vercel-labs/agent-skills/tree/main/skills/react-best-practices&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;깃허브 레포&lt;/a&gt;에 있는 마크다운 문서를 직접 읽어보는 것을 추천합니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;클로드 스킬(Claude Skills)로 사용하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;설치 방법&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769674218789&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 설치
npx add-skill vercel-labs/agent-skills&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dgEhZh/dJMcadAMSNz/o6J46O2OLaUMf5zSNRGYQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dgEhZh/dJMcadAMSNz/o6J46O2OLaUMf5zSNRGYQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dgEhZh/dJMcadAMSNz/o6J46O2OLaUMf5zSNRGYQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdgEhZh%2FdJMcadAMSNz%2Fo6J46O2OLaUMf5zSNRGYQ1%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;714&quot; height=&quot;373&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;738&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;명령어 입력 시 4가지 스킬 선택 화면이 나옵니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1.&amp;nbsp;vercel-composition-patterns : 컴포넌트 간의 의존성 복잡도를 깔끔하게 정리하는 방법을 제공합니다.&lt;br /&gt;2.&amp;nbsp;vercel-react-best-practices : 리액트 최적의 실무 관행&lt;br /&gt;3.&amp;nbsp;vercel-react-native-skills : 리액트 네이티브(앱)을 위한 기술 모음&lt;br /&gt;4.&amp;nbsp;web-design-guidelines : UI/UX를 만드는 기준&lt;/blockquote&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXVsSQ/dJMcaia55Cy/JnOFZJfWTTI6OuGwASZJ7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXVsSQ/dJMcaia55Cy/JnOFZJfWTTI6OuGwASZJ7k/img.png&quot; data-alt=&quot;/skills&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXVsSQ/dJMcaia55Cy/JnOFZJfWTTI6OuGwASZJ7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXVsSQ%2FdJMcaia55Cy%2FJnOFZJfWTTI6OuGwASZJ7k%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;584&quot; height=&quot;309&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;/skills&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SmmPz/dJMcaiWqE2N/LnTgCwwjgAOUyTIe57OmYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SmmPz/dJMcaiWqE2N/LnTgCwwjgAOUyTIe57OmYK/img.png&quot; data-alt=&quot;폴더에 저장 됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SmmPz/dJMcaiWqE2N/LnTgCwwjgAOUyTIe57OmYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSmmPz%2FdJMcaiWqE2N%2FLnTgCwwjgAOUyTIe57OmYK%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;589&quot; height=&quot;226&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;폴더에 저장 됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되면 &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;/skills 명령어&lt;/b&gt;&lt;/span&gt;를 통해 클로드 스킬을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 컴퓨터에 마크다운 파일이 설치된 것이기 때문에, 폴더에서도 확인 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;코드 리뷰 요청하기&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;(컴포넌트 태그) vercel-react-best-practices 코드 리뷰&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQDEBd/dJMcagEm2gz/UpL54xYfIyTz1dexzzW5d1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQDEBd/dJMcagEm2gz/UpL54xYfIyTz1dexzzW5d1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQDEBd/dJMcagEm2gz/UpL54xYfIyTz1dexzzW5d1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQDEBd%2FdJMcagEm2gz%2FUpL54xYfIyTz1dexzzW5d1%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;707&quot; height=&quot;240&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 명시적으로 스킬 이름을 적어주면 클로드 코드가 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;SKILL.md 상단의 YAML 프론트 메터를 참조&lt;/b&gt;&lt;/span&gt;하여 계획을 세우고 작업을 실행합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* YAML 프론트 메터 예시&lt;br /&gt;---&lt;br /&gt;name: my-skill&lt;br /&gt;description: 이 기술이 하는 것&lt;br /&gt;disable-model-invocation: true&lt;br /&gt;allowed-tools: Read, Grep&lt;br /&gt;---&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 리뷰 결과 확인하기&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QxU08/dJMcafSYFEB/Je1hZcIMc2lv0ydgxfeMI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QxU08/dJMcafSYFEB/Je1hZcIMc2lv0ydgxfeMI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QxU08/dJMcafSYFEB/Je1hZcIMc2lv0ydgxfeMI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQxU08%2FdJMcafSYFEB%2FJe1hZcIMc2lv0ydgxfeMI1%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;724&quot; height=&quot;335&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 언급한 성능 최적화 우선순위에 따라 솔루션을 제안합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드 코드가 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Vercel 시니어 엔지니어&lt;/span&gt;&lt;/b&gt;로 거듭난 순간입니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;❯&amp;nbsp;1번 2번 적용하고, 전후 측정 결과 얼마나 개선되었는지 알려줘&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0zdVw/dJMcaac3LIm/12aIMrQAxYGUq7gw4Kl7OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0zdVw/dJMcaac3LIm/12aIMrQAxYGUq7gw4Kl7OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0zdVw/dJMcaac3LIm/12aIMrQAxYGUq7gw4Kl7OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0zdVw%2FdJMcaac3LIm%2F12aIMrQAxYGUq7gw4Kl7OK%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;652&quot; height=&quot;393&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 컴포넌트만 태그해서 테스트한 건데, &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;번들 크기를 14.8%나 개선&lt;/b&gt;&lt;/span&gt;할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇을, 어떻게, 왜 수정했는지 추가적으로 질문하면 더 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 결과 측정은 약 13분이 걸렸는데, 토큰도 아깝고 CLI나 툴을 따로 사용해 직접 측정하는 것이 좋아 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 시니어 개발자의 코드 리뷰를 눈치 보지 않고 토큰이 허용하는 내에서 무한대로 받아볼 수 있게 되었습니다 !  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP부터 클로드 스킬까지 요즘 LLM을 더 다양하게, 더 잘 활용하는 방법이 굉장히 빠르게 나오고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불과 1~2년 사이에 AI의 발전 속도가 정말 말이 안 되는데요  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 개인적으로 밥그릇 뺏길까 봐 걱정인 건 당연히 있지만, (이미 뺏긴 것 같습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편으로는 기술의 경계가 사라지고 아이디어만 있어도 러닝 커브 없이 빠르게 뭔가를 만들 수 있다는 게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설렘으로 다가오는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분은 어떠신가요?!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;참고 문헌:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://vercel.com/blog/introducing-react-best-practices&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://vercel.com/blog/introducing-react-best-practices&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End/Next</category>
      <category>2026 프론트엔드 성능 최적화</category>
      <category>React Best Practices</category>
      <category>클로드 스킬</category>
      <category>클로드 코드</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/136</guid>
      <comments>https://hyunki99.tistory.com/136#entry136comment</comments>
      <pubDate>Thu, 29 Jan 2026 17:37:32 +0900</pubDate>
    </item>
    <item>
      <title>[FE] Next.js 로컬 개발환경에서 HTTPS 적용하기 (mkcert, 서브도메인 쿠키 공유)</title>
      <link>https://hyunki99.tistory.com/135</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2306&quot; data-origin-height=&quot;1833&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/80KWM/dJMcaaxmgEZ/EtQ6qfoII8izR1s6GpcPXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/80KWM/dJMcaaxmgEZ/EtQ6qfoII8izR1s6GpcPXK/img.png&quot; data-alt=&quot;출처: https://www.descope.com/learn/post/enterprise-sso&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/80KWM/dJMcaaxmgEZ/EtQ6qfoII8izR1s6GpcPXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F80KWM%2FdJMcaaxmgEZ%2FEtQ6qfoII8izR1s6GpcPXK%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;566&quot; height=&quot;450&quot; data-origin-width=&quot;2306&quot; data-origin-height=&quot;1833&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.descope.com/learn/post/enterprise-sso&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 문제 상황&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 개발 환경에서 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;SSO(Single Sign-On)&lt;/span&gt;&lt;/b&gt; 로직을 구현하고 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 서비스가 동일한 서브도메인 형태로 분리된 구조고, 인증은 하나의 인증 서버에서 담당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;흐름&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;(A 사이트)&lt;/span&gt; 로그인 -&amp;gt; &lt;span style=&quot;color: #ef5369;&quot;&gt;(B 사이트 SSO 담당)&lt;/span&gt; 로그인 페이지 -&amp;gt; 로그인 및 쿠키 저장 -&amp;gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;(A 사이트)&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;개발 환경&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;278&quot; data-start=&quot;256&quot;&gt;프론트엔드: HTTP (로컬)&lt;/li&gt;
&lt;li data-end=&quot;297&quot; data-start=&quot;279&quot;&gt;인증 서버: HTTPS&lt;/li&gt;
&lt;li data-end=&quot;355&quot; data-start=&quot;298&quot;&gt;인증 쿠키 옵션:&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Secure=true SameSite=None&lt;/li&gt;
&lt;li data-end=&quot;373&quot; data-start=&quot;356&quot;&gt;서브도메인 기반 SSO 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;381&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 현상&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;449&quot; data-start=&quot;382&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;391&quot; data-start=&quot;382&quot;&gt;로그인은 성공&lt;/li&gt;
&lt;li data-end=&quot;408&quot; data-start=&quot;392&quot;&gt;쿠키는 저장된 것처럼 보임&lt;/li&gt;
&lt;li data-end=&quot;434&quot; data-start=&quot;409&quot;&gt;다른 서브도메인에서는 쿠키가 전달되지 않음&lt;/li&gt;
&lt;li data-end=&quot;449&quot; data-start=&quot;435&quot;&gt;결과적으로 SSO 실패&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 원인은 쿠키의 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Secure 옵션&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 보안 정책상 이 옵션이 설정된 쿠키는 HTTPS에서만 동작하며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 사이트가 HTTPS 사이트의 쿠키를 읽거나 공유하는 것을 차단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.&amp;nbsp; mkcert로 로컬 HTTPS 환경 구성&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;mkcert란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;618&quot; data-start=&quot;552&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/FiloSottile/mkcert&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;mkcert&lt;/a&gt;는 복잡한 설정 없이 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;로컬 개발용으로 SSL 인증서를 만들어주는 간단한 도구&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;695&quot; data-start=&quot;620&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;639&quot; data-start=&quot;620&quot;&gt;로컬 CA 생성 및 OS에 등록&lt;/li&gt;
&lt;li data-end=&quot;695&quot; data-start=&quot;665&quot;&gt;운영 환경과 거의 동일한 HTTPS 조건 구성 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치하기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769590034409&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. 터미널 명령어 실행 (Mac 기준)
brew install mkcert                                                                                                                                                                                                              
mkcert -install                                                                                                                                                                                                                  

# 2. React/Next 프로젝트 루트에 인증서 생성
cd /Users/hyunki/Desktop/project/my-proj
mkcert &quot;*.example.io&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;로컬 호스트를 특정한 도메인으로 변경하는 방법 (선택)&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;아래와 같이 host를 추가해 주면 내부적으로는 로컬 호스트지만 도메인을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1769590417224&quot; class=&quot;accesslog&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;sudo nano /etc/hosts

* 추가
127.0.0.1 auth.example.com

* 종료
!wq&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;package.json 스크립트 수정해서 실행하기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769590198989&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;scripts&quot;: {
    // 기존 스크립트 예시
    &quot;dev:auth&quot;: &quot;next dev --turbopack --hostname auth.example.com --port 3000&quot;,
    
    // HTTPS 실행 스크립트
    &quot;dev:auth:https&quot;: &quot;next dev --turbopack --hostname auth.example.com --port 3000 --experimental-https --experimental-https-key ./_wildcard.example.com-key.pem --experimental-https-cert ./_wildcard.example.com.pem&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;/p&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;Next.js 실행 스크립트 속성 설명&lt;/b&gt;&lt;/p&gt;
&lt;table id=&quot;2f618b83-5c6b-80ec-bf57-c6df6c91f144&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;2f618b83-5c6b-8032-95ea-e0771e7eabff&quot;&gt;
&lt;td id=&quot;l?lK&quot;&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;=aDG&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f618b83-5c6b-809a-b1c9-f68ea2371ed5&quot;&gt;
&lt;td id=&quot;l?lK&quot;&gt;&lt;b&gt;--experimental-https&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;=aDG&quot;&gt;Next.js에게 &quot;이제 HTTP가 아니라 &lt;b&gt;HTTPS 프로토콜&lt;/b&gt;로 서버를 열어줘&quot;라고 명령하는 핵심 스위치입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f618b83-5c6b-80fb-b6a8-e03547af02a1&quot;&gt;
&lt;td id=&quot;l?lK&quot;&gt;&lt;b&gt;--experimental-https-key&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;=aDG&quot;&gt;mkcert로 생성한 파일 중 &lt;b&gt;개인키(&lt;/b&gt;&lt;b&gt;-key.pem&lt;/b&gt;&lt;b&gt;)&lt;/b&gt; 파일의 경로를 지정합니다. 서버가 데이터를 암호화할 때 사용합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2f618b83-5c6b-8060-99f2-c86555a17d0c&quot;&gt;
&lt;td id=&quot;l?lK&quot;&gt;&lt;b&gt;--experimental-https-cert&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;=aDG&quot;&gt;mkcert로 생성한 &lt;b&gt;인증서(&lt;/b&gt;&lt;b&gt;.pem&lt;/b&gt;&lt;b&gt;)&lt;/b&gt; 파일의 경로를 지정합니다. 브라우저에게 &quot;이 서버는 신뢰할 수 있어&quot;라고 증명하는 신분증 역할을 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;3. 결과&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oX3AZ/dJMcaivllg1/9FNTw6G7sk2HWCz0CSwi2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oX3AZ/dJMcaivllg1/9FNTw6G7sk2HWCz0CSwi2k/img.png&quot; data-alt=&quot;HTTPS로 실행된 로컬호스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oX3AZ/dJMcaivllg1/9FNTw6G7sk2HWCz0CSwi2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoX3AZ%2FdJMcaivllg1%2F9FNTw6G7sk2HWCz0CSwi2k%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;673&quot; height=&quot;147&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HTTPS로 실행된 로컬호스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 호스트가 HTTPS로 실행 가능하게 되었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키의 Secure 옵션 때문에 서브도메인간 쿠키 공유가 되지 않던 이슈도 해결되었습니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mkcert는 로컬 개발용입니다 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- rootCA-key.pem이 유출되지 않도록 조심하세요 !&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;+ 약간의 소개&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 제가 포스팅하던 형식은 머릿글에 중앙 정렬하고 조금 이쁘장하게 전달하려는 의도가 있었는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트러블슈팅이나 오늘처럼 간단한 포스팅은 요런 간결한 velog 스타일로 작성해보려고 합니다  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;</description>
      <category>etc</category>
      <category>mkcert</category>
      <category>로컬 https</category>
      <category>서브도메인 쿠키</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/135</guid>
      <comments>https://hyunki99.tistory.com/135#entry135comment</comments>
      <pubDate>Wed, 28 Jan 2026 23:23:09 +0900</pubDate>
    </item>
    <item>
      <title>[AI] Vercel v0을 활용한 10분만에 개발자 포트폴리오 만들기</title>
      <link>https://hyunki99.tistory.com/134</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;815&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btgmwm/dJMcadm1kpn/9fKPecRPlVWEK0aZ1Wa8Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btgmwm/dJMcadm1kpn/9fKPecRPlVWEK0aZ1Wa8Q0/img.png&quot; data-alt=&quot;Vercel의 v0으로 개발된 포트폴리오 사이트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btgmwm/dJMcadm1kpn/9fKPecRPlVWEK0aZ1Wa8Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbtgmwm%2FdJMcadm1kpn%2F9fKPecRPlVWEK0aZ1Wa8Q0%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;645&quot; height=&quot;428&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;815&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Vercel의 v0으로 개발된 포트폴리오 사이트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 프론트엔드 생태계를 이끌고 있는 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Vercel&lt;/span&gt;&lt;/b&gt;에서&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;출시한 흥미로운 서비스인 &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;v0&lt;/b&gt;&lt;/span&gt;에 대해서 소개해드리려고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;v0는 우리가 잘 아는 ChatGPT나 제미나이처럼 프롬프트를 입력하면,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그 결과물로 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;즉시 사용 가능한 UI 컴포넌트 코드를 생성&lt;/span&gt;&lt;/b&gt;해 주는 도구입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;살짝 찍어먹어 본 후기를 공유하고자 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;함께 알아봅시다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  v0이란?&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://v0.app/docs/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://v0.app/docs/introduction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766474486213&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;What is v0? | v0 Docs&quot; data-og-description=&quot;v0 is an AI-powered development platform that turns ideas into production-ready, full-stack web apps.&quot; data-og-host=&quot;v0.app&quot; data-og-source-url=&quot;https://v0.app/docs/introduction&quot; data-og-url=&quot;https://v0.app/docs/introduction&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnyQEe/hyZPYg2Hs1/Ncr3qX6Pmq5R2chDH1ppzK/img.png?width=3600&amp;amp;height=1884&amp;amp;face=0_0_3600_1884,https://scrap.kakaocdn.net/dn/eMQ19/hyZPLamGcb/T9ztIGhKCDbwKoL5DsCf21/img.png?width=3600&amp;amp;height=1884&amp;amp;face=0_0_3600_1884&quot;&gt;&lt;a href=&quot;https://v0.app/docs/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://v0.app/docs/introduction&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnyQEe/hyZPYg2Hs1/Ncr3qX6Pmq5R2chDH1ppzK/img.png?width=3600&amp;amp;height=1884&amp;amp;face=0_0_3600_1884,https://scrap.kakaocdn.net/dn/eMQ19/hyZPLamGcb/T9ztIGhKCDbwKoL5DsCf21/img.png?width=3600&amp;amp;height=1884&amp;amp;face=0_0_3600_1884');&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;What is v0? | v0 Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;v0 is an AI-powered development platform that turns ideas into production-ready, full-stack web apps.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;v0.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&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;v0은 아이디어를 실제 사용 가능한 풀스택 웹 애플리케이션으로 구현해 주는 AI 기반 플랫폼입니다.&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;Next.js를 만든 Vercel에서 개발했기 때문에 구현 결과물은 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;React/Next.js + Shadcn + Tailwind CSS&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 가장 트렌디한 조합이죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⦁ 특징 1. 자연어 기반 이미지 생성&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;&lt;b&gt;⦁ 특징 2. 반복 수정 및 버전 관리&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;이 수정사항은 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;버전이 기록&lt;/span&gt;&lt;/b&gt;되어 쉽게 롤백이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⦁ 특징 3. 깃허브 연동 !&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;깃허브 계정을 연동&lt;/span&gt;&lt;/b&gt;하고 권한을 주면, 새 레포를 생성하고 push하는 등의 작업도 수행해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 굉장히 편리했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁ 가격 정보&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;990&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b90bAI/dJMcabQkq3x/a4IKx2mAKqcNfzzRUsXkOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b90bAI/dJMcabQkq3x/a4IKx2mAKqcNfzzRUsXkOK/img.png&quot; data-alt=&quot;v0 가격 정보&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b90bAI/dJMcabQkq3x/a4IKx2mAKqcNfzzRUsXkOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb90bAI%2FdJMcabQkq3x%2Fa4IKx2mAKqcNfzzRUsXkOK%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;576&quot; height=&quot;268&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;990&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;v0 가격 정보&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 출시했을 때는 대기 명단을 등록하고 기다려야 했지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;하루 7개의 메시지를 무료&lt;/span&gt;&lt;/b&gt;로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 많이 사용해 보지는 않았지만 저는 20달러라면 클로드 코드를 결제할 것 같긴 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 무료 플랜으로 체험해 보시는 것을 추천드립니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  개발자 포트폴리오 만들기&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://v0.app/templates&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://v0.app/templates&lt;/a&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766475679815&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;v0 Templates - v0 by Vercel&quot; data-og-description=&quot;Your collaborative AI assistant to design, iterate, and scale full-stack applications for the web.&quot; data-og-host=&quot;v0.app&quot; data-og-source-url=&quot;https://v0.app/templates&quot; data-og-url=&quot;https://v0.app/templates&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cX83ob/hyZPF2hK6t/djy9L0xxGvH6pGiia1VfBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bzkARC/hyZPRn68gk/Pt6hpOSHvy9Mx1k5Y38vC0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dnA3ET/hyZPDXHOT1/3Aw4Kbbksi9pVEphBk096K/img.png?width=3370&amp;amp;height=1890&amp;amp;face=0_0_3370_1890&quot;&gt;&lt;a href=&quot;https://v0.app/templates&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://v0.app/templates&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cX83ob/hyZPF2hK6t/djy9L0xxGvH6pGiia1VfBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bzkARC/hyZPRn68gk/Pt6hpOSHvy9Mx1k5Y38vC0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dnA3ET/hyZPDXHOT1/3Aw4Kbbksi9pVEphBk096K/img.png?width=3370&amp;amp;height=1890&amp;amp;face=0_0_3370_1890');&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;v0 Templates - v0 by Vercel&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Your collaborative AI assistant to design, iterate, and scale full-stack applications for the web.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;v0.app&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;우선 채팅으로 직접 만들기 전에, Templates 탭을 한번 둘러 보시는 것을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 사용자가 만들어 둔 멋있는 예제들을 볼 수 있어요. ☺️&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rr3id/dJMcab3RL4d/wMh3v0hvIu317ZbjJccW4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rr3id/dJMcab3RL4d/wMh3v0hvIu317ZbjJccW4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rr3id/dJMcab3RL4d/wMh3v0hvIu317ZbjJccW4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frr3id%2FdJMcab3RL4d%2FwMh3v0hvIu317ZbjJccW4k%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;451&quot; height=&quot;258&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEYYi1/dJMcabQkrir/5HruHpv8mYWNMgzvUJQQ8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEYYi1/dJMcabQkrir/5HruHpv8mYWNMgzvUJQQ8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEYYi1/dJMcabQkrir/5HruHpv8mYWNMgzvUJQQ8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEYYi1%2FdJMcabQkrir%2F5HruHpv8mYWNMgzvUJQQ8k%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;443&quot; height=&quot;251&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yB0dS/dJMcaiPpFxS/PlxoLQUpkEuKnZDPm4MxS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yB0dS/dJMcaiPpFxS/PlxoLQUpkEuKnZDPm4MxS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yB0dS/dJMcaiPpFxS/PlxoLQUpkEuKnZDPm4MxS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyB0dS%2FdJMcaiPpFxS%2FPlxoLQUpkEuKnZDPm4MxS0%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;438&quot; height=&quot;205&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYeai2/dJMb9953qoU/HfswmZAfapI6HExxQT4Ggk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYeai2/dJMb9953qoU/HfswmZAfapI6HExxQT4Ggk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYeai2/dJMb9953qoU/HfswmZAfapI6HExxQT4Ggk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYeai2%2FdJMb9953qoU%2FHfswmZAfapI6HExxQT4Ggk%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;436&quot; height=&quot;237&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r2kCP/dJMcaaKEFq1/kMsIk481KxpOmb3wUvvEM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r2kCP/dJMcaaKEFq1/kMsIk481KxpOmb3wUvvEM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r2kCP/dJMcaaKEFq1/kMsIk481KxpOmb3wUvvEM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr2kCP%2FdJMcaaKEFq1%2FkMsIk481KxpOmb3wUvvEM0%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;434&quot; height=&quot;231&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddc7bM/dJMb99LJ41x/rSr2YoQ726Ocx4OKEBscw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddc7bM/dJMb99LJ41x/rSr2YoQ726Ocx4OKEBscw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddc7bM/dJMb99LJ41x/rSr2YoQ726Ocx4OKEBscw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fddc7bM%2FdJMb99LJ41x%2FrSr2YoQ726Ocx4OKEBscw1%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;431&quot; height=&quot;236&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;242&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;여기서는 질문을 막 던졌지만, 제미나이나 GPT에게 프롬프트 생성을 요청하면 더 효율적입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1766551493937&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 프롬프트
v0에 입력할 프롬프트 생성해줘
요구사항 
1. ~~
2. ~~
3. ~~&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;size18&quot;&gt;&lt;b&gt;⦁ 각 질문 버전 확인 방법&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rXs9d/dJMcac2JlHH/p9FygpbsnuBhRhuInoCVh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rXs9d/dJMcac2JlHH/p9FygpbsnuBhRhuInoCVh0/img.png&quot; data-alt=&quot;우측 상단 Latest 클릭 시 이전 버전 변경 가능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rXs9d/dJMcac2JlHH/p9FygpbsnuBhRhuInoCVh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrXs9d%2FdJMcac2JlHH%2Fp9FygpbsnuBhRhuInoCVh0%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;278&quot; height=&quot;288&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;355&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;우측 상단 Latest 클릭 시 이전 버전 변경 가능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손 쉽게 이전 채팅의 코드로 돌아갈 수 있어서 UX가 참 좋았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁ 결과물 템플릿 !&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://v0.app/templates/aSh4U6MpBRp&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://v0.app/templates/aSh4U6MpBRp&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766477196528&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;v0 - Developer portfolio - v0 by Vercel&quot; data-og-description=&quot;A modern developer portfolio featuring a glassmorphism design with soft blur effects.&quot; data-og-host=&quot;v0.app&quot; data-og-source-url=&quot;https://v0.app/templates/aSh4U6MpBRp&quot; data-og-url=&quot;https://v0.app/templates/aSh4U6MpBRp&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f26kZ/hyZPOx89xF/XEhemQBLyluF8iv3NMyEr1/img.png?width=1228&amp;amp;height=815&amp;amp;face=0_0_1228_815,https://scrap.kakaocdn.net/dn/I28na/hyZPL9iCDk/seXkk6i5vi6WTmp6S6cut0/img.png?width=1228&amp;amp;height=815&amp;amp;face=0_0_1228_815,https://scrap.kakaocdn.net/dn/eknF3t/hyZPDQXhSv/iFJUJeeyVitbDFSsYaz9u1/img.png?width=2854&amp;amp;height=1752&amp;amp;face=0_0_2854_1752&quot;&gt;&lt;a href=&quot;https://v0.app/templates/aSh4U6MpBRp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://v0.app/templates/aSh4U6MpBRp&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f26kZ/hyZPOx89xF/XEhemQBLyluF8iv3NMyEr1/img.png?width=1228&amp;amp;height=815&amp;amp;face=0_0_1228_815,https://scrap.kakaocdn.net/dn/I28na/hyZPL9iCDk/seXkk6i5vi6WTmp6S6cut0/img.png?width=1228&amp;amp;height=815&amp;amp;face=0_0_1228_815,https://scrap.kakaocdn.net/dn/eknF3t/hyZPDQXhSv/iFJUJeeyVitbDFSsYaz9u1/img.png?width=2854&amp;amp;height=1752&amp;amp;face=0_0_2854_1752');&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;v0 - Developer portfolio - v0 by Vercel&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A modern developer portfolio featuring a glassmorphism design with soft blur effects.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;v0.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;결과물은 v0에 템플릿으로 공개했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;어디서 많이 보던 디자인 같기는 하지만&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 정도면 제 눈에는 굉장히 예뻐 보입니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;( v0 사용 10분 포스팅 2시간  )&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;&lt;a style=&quot;color: #dddddd;&quot; href=&quot;https://v0.app/docs/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://v0.app/docs/introduction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI 랜딩페이지</category>
      <category>Vercel v0</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/134</guid>
      <comments>https://hyunki99.tistory.com/134#entry134comment</comments>
      <pubDate>Tue, 23 Dec 2025 23:00:56 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드 코드 직접 사용해보기 (CLAUDE.md, 자주 쓰이는 명령어, 프롬프트)</title>
      <link>https://hyunki99.tistory.com/132</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://hyunki99.tistory.com/131&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hyunki99.tistory.com/131&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1761728709767&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[AI] 클로드 코드 설치 방법 + 가격 정보 (feat. 인텔리제이에서 실행하기)&quot; data-og-description=&quot;요즘 생성형 AI를 활용한 바이브 코딩이 뜨거운 주제인 것 같습니다. 저는 시간이 날 때마다 IT 칼럼을 즐겨보는데,클로드 코드에 대해서 아주 많은 칼럼들이 보입니다. 운이 좋게도 회사에서 클&quot; data-og-host=&quot;hyunki99.tistory.com&quot; data-og-source-url=&quot;https://hyunki99.tistory.com/131&quot; data-og-url=&quot;https://hyunki99.tistory.com/131&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cLbrEf/hyZMoUVbmB/FFKDDRp7idbqFkdsVV9HkK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Nxn8Z/hyZLgCD2SF/4pn8jdQPyyigV93mYkTjvk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cbQRt5/hyZMVXVI2T/mOKwKcU66bjODNYXSzl8BK/img.png?width=1416&amp;amp;height=776&amp;amp;face=0_0_1416_776&quot;&gt;&lt;a href=&quot;https://hyunki99.tistory.com/131&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hyunki99.tistory.com/131&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cLbrEf/hyZMoUVbmB/FFKDDRp7idbqFkdsVV9HkK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Nxn8Z/hyZLgCD2SF/4pn8jdQPyyigV93mYkTjvk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cbQRt5/hyZMVXVI2T/mOKwKcU66bjODNYXSzl8BK/img.png?width=1416&amp;amp;height=776&amp;amp;face=0_0_1416_776');&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;[AI] 클로드 코드 설치 방법 + 가격 정보 (feat. 인텔리제이에서 실행하기)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;요즘 생성형 AI를 활용한 바이브 코딩이 뜨거운 주제인 것 같습니다. 저는 시간이 날 때마다 IT 칼럼을 즐겨보는데,클로드 코드에 대해서 아주 많은 칼럼들이 보입니다. 운이 좋게도 회사에서 클&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hyunki99.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;지난 글에서 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;클로드 코드를 설치&lt;/span&gt;&lt;/b&gt;하고 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;IDE에 통합&lt;/span&gt;&lt;/b&gt;까지 완료했습니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이제 직접 사용해봐야겠죠?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;어디에 먼저 사용해볼까 고민하다가&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;예전에 만들어두고 방치한 제 개인 보일러플레이트 프로젝트인&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/HongHyunKi/nextjs-shadcn-boilerplate&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt; nextjs-shadcn-boilerplate&lt;/span&gt;&lt;/a&gt;에 적용해보기로 했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;클로드 코드 사용하는 방법 함께 알아봅시다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  프로젝트 정보 저장하기&amp;nbsp; (CLAUDE.md 생성)&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁CLAUDE.md 파일이란?&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;653&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcksrY/dJMb9LDZbLm/Kk6VfUB40cQXCdIcmipFw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcksrY/dJMb9LDZbLm/Kk6VfUB40cQXCdIcmipFw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcksrY/dJMb9LDZbLm/Kk6VfUB40cQXCdIcmipFw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcksrY%2FdJMb9LDZbLm%2FKk6VfUB40cQXCdIcmipFw1%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;378&quot; height=&quot;463&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;653&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;클로드 코드는 마크다운 파일에 AI와 협업하기 위한 문서를 작성할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이곳에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;프로젝트 정보, 기술 스택 버전, 코딩 컨벤션 등의 정보&lt;/span&gt;&lt;/b&gt;를 작성하면 클로드 코드가 이를 참고한 답변을 생성해 줍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;간단하게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;/init &lt;/b&gt;&lt;/span&gt;명령어를 통해 생성하고 필요한 부분을 수정해 보세요.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프롬프트를 통해서도 생성 및 수정이 가능합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이 문서 그 자체로도 프로젝트를 설명할 수 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;좋은 문서&lt;/span&gt;&lt;/b&gt;가 되기도 합니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;프롬프트 예시)&lt;/span&gt; &lt;/b&gt;프로젝트 분석해서 CLAUDE.md 생성. package.json 및 주요 컴포넌트 참고해서 기술 스택, 프로젝트 구조 포함&lt;/p&gt;
&lt;p style=&quot;; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁ CLAUDE.md 잘 작성하는 방법&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. &lt;/b&gt;&lt;b&gt;기술 스택 및 버전 명시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드는 프로젝트의 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;코드를 탐색하는 과정&lt;/span&gt;&lt;/b&gt;을 통해 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;라이브러리의 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;버전을 추론&lt;/span&gt;&lt;/b&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이대로도 크게 문제는 발생하지 않지만, 추론이 틀렸을 경우 LTS 버전으로 코드를 작성해 주기 때문에&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&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;기술 스택의 버전을 명시&lt;/b&gt;&lt;/span&gt;하는 것이 좋겠죠?  &lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;* Claude Code의 버전 처리 방식&lt;/b&gt;&lt;br /&gt;CLAUDE.md 파일에는 프로젝트의 도구와 버전을 선언해야 합니다. (예: Tailwind CSS 4.1)&lt;br /&gt;이를 통해 Claude Code가 프로젝트 컨텍스트를 이해합니다&lt;br /&gt;&lt;br /&gt;&lt;b&gt;* 버전이 명시되지 않았을 경우에는?&lt;/b&gt;&lt;br /&gt;다음과 같은 순서로 판단합니다.&lt;br /&gt;1. package.json / requirements.txt 등 확인 프로젝트의 의존성 파일을 먼저 읽음 실제 설치된 버전 확인&lt;br /&gt;&lt;br /&gt;2. 코드 패턴 분석 코드 작성 스타일로 버전 추론 예: async/await 사용 &amp;rarr; 최신 Node.js&lt;br /&gt;&lt;br /&gt;3. 최신 안정 버전 가정 명시가 없으면 일반적으로 최신 LTS 버전 사용 -&amp;gt; &lt;b&gt;⚠️ 위험성 존재&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;- 클로드 코드&amp;nbsp; product-self-knowledge/SKILL.md&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;예시)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1761729965530&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;## Tech Stack
Next.js ^15.4.7 with App Router
React ^19.1.0
TypeScript ^5
Tailwind CSS ^4.1.4
shadcn/ui with Radix UI primitives
next-themes ^0.4.4 for dark mode
lucide-react ^0.477.0 for icons
ESLint ^8 + Prettier ^3.5.2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 프로젝트 아키텍쳐, 폴더 구조 명시&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buRIs3/dJMcaeeTCSl/zKIfOF5dQ6yCRUkNT0JHHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buRIs3/dJMcaeeTCSl/zKIfOF5dQ6yCRUkNT0JHHk/img.png&quot; data-alt=&quot;CLAUDE.md -&amp;amp;gt; 폴더 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buRIs3/dJMcaeeTCSl/zKIfOF5dQ6yCRUkNT0JHHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuRIs3%2FdJMcaeeTCSl%2FzKIfOF5dQ6yCRUkNT0JHHk%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;405&quot; height=&quot;296&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CLAUDE.md -&amp;gt; 폴더 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더 구조를 명시해 놓았더니, 컴포넌트를 생성할 때 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;규칙에 맞는 폴더로 파일이 생성&lt;/span&gt;&lt;/b&gt;되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 보고 깜짝 놀랐습니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 많은 내용이 있지만 직접 만들어보고 점점 개선해 나가는 방법을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분의 방법도 공유해 주세요 !  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁   CLAUDE.md&amp;nbsp; 전체 예제&lt;/b&gt;&lt;/h4&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;pre id=&quot;code_1763361390822&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is a Next.js 15+ boilerplate with Tailwind CSS v4.1 and shadcn/ui components. It uses TypeScript and includes a pre-configured setup with dark mode support using next-themes.

## Tech Stack

- **Next.js** ^15.4.7 with App Router
- **React** ^19.1.0
- **TypeScript** ^5
- **Tailwind CSS** ^4.1.4
- **shadcn/ui** with Radix UI primitives
- **next-themes** ^0.4.4 for dark mode
- **lucide-react** ^0.477.0 for icons
- **ESLint** ^8 + **Prettier** ^3.5.2

## Development Commands

### Development

```bash
yarn dev        # Start development server
yarn build      # Build production bundle
yarn start      # Start production server
yarn lint       # Run ESLint
yarn prettier   # Check code formatting with Prettier
```

## Architecture

### Directory Structure

- **`src/app/`** - Next.js App Router pages and layouts
  - **`(Main)/`** - Route group with MainLayout wrapper
  - Uses route groups for shared layouts without affecting URL structure
- **`src/components/`** - React components organized by category
  - **`ui/`** - shadcn/ui components (button, dropdown-menu, etc.)
  - **`layouts/`** - Layout components (Header, Footer, MainLayout)
  - **`theme/`** - Theme-related components (ThemeProvider, ModeToggle)
  - **`common/`** - Common/shared components
- **`src/constants/`** - Application constants including routes
- **`src/lib/`** - Utility functions (includes `cn()` for Tailwind class merging)
- **`src/hooks/`** - Custom React hooks
- **`src/css/`** - Global styles and Tailwind configuration
- **`src/api/`** - API-related code

### Path Aliases

TypeScript paths are configured with `@/*` pointing to `src/*`:

```typescript
import { cn } from '@/lib/utils';
import { Header } from '@/components/layouts/Header';
```

### Layout System

The app uses a nested layout structure:

1. **Root Layout** (`src/app/layout.tsx`) - Wraps everything with ThemeProvider
2. **Main Layout** (`src/app/(Main)/layout.tsx`) - Applies MainLayout component to pages in the (Main) route group
3. **MainLayout Component** (`src/components/layouts/MainLayout.tsx`) - Contains Header, main content area, and Footer with predefined spacing

### Theming

- Uses **next-themes** with class-based dark mode (`attribute=&quot;class&quot;`)
- Theme toggles between light/dark/system modes
- Custom color tokens defined in `src/css/globals.css` using OKLCH color space
- CSS variables for layout dimensions:
  - `--header-height: 64px`
  - `--container-max-width: 1200px`
  - `--container-px: 16px`

### Styling Approach

- **Tailwind CSS v4.1** with native CSS imports (`@import 'tailwindcss'`)
- Uses Pretendard font loaded from CDN
- `cn()` utility function combines clsx and tailwind-merge for conditional classes
- Prettier with `prettier-plugin-tailwindcss` automatically sorts Tailwind classes

### shadcn/ui Configuration

The project uses shadcn/ui with the following config (from `components.json`):

- **Style**: default
- **Base color**: zinc
- **CSS Variables**: enabled
- **Icon library**: lucide-react
- **RSC**: enabled (React Server Components)

To add new shadcn/ui components, the config expects:

- Components in `@/components` (mapped to `src/components/`)
- UI components in `@/components/ui`
- Utils in `@/lib/utils`

### Code Style

ESLint and Prettier are configured:

- Extends `next/core-web-vitals` and `prettier`
- Single quotes, semicolons, 2-space indentation
- Trailing commas for ES5
- 80 character line width

### Navigation

Navigation routes are centralized in `src/constants/routes.ts` as `NAV_LIST` array with `name` and `href` properties.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  명령어 &amp;amp; 프롬프트&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://docs.claude.com/en/resources/prompt-library/library&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.claude.com/en/resources/prompt-library/library&lt;/a&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1761556451356&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;Prompt Library - Claude Docs&quot; data-og-description=&quot;Responses are generated using AI and may contain mistakes.&quot; data-og-host=&quot;docs.claude.com&quot; data-og-source-url=&quot;https://docs.claude.com/en/resources/prompt-library/library&quot; data-og-url=&quot;https://docs.claude.com/en/resources/prompt-library/library&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/RcnA3/hyZLhuCJSC/cYHlY4aRedg4p7mmp1cEGk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bkSpqB/hyZMc0I3iP/Xb93GfrjgPc7kPlmnj2mJ0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://docs.claude.com/en/resources/prompt-library/library&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.claude.com/en/resources/prompt-library/library&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/RcnA3/hyZLhuCJSC/cYHlY4aRedg4p7mmp1cEGk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bkSpqB/hyZMc0I3iP/Xb93GfrjgPc7kPlmnj2mJ0/img.png?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;Prompt Library - Claude Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Responses are generated using AI and may contain mistakes.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁자주 쓰이는 명령어&lt;/b&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 55.2326%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/clear&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;대화 기록을 컨텍스트 윈도우에서 제거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/explain&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;선택한 코드의 동작을 자세히 설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/edit&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;선택한 코드 블록을 특정 요구사항에 맞게 수정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/test&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;유닛 테스트 코드 자동 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/refactor&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;가독성/성능 개선을 위한 코드 리팩토링 제안&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/comment&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;코드에 주석 자동 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/doc&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;함수/컴포넌트 문서화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/commit&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;커밋 메시지를 생성하거나 변경 요약 작성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/review&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;현재 변경된 코드 리뷰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.854%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/run&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.6759%;&quot;&gt;현재 실행 가능한 명령어나 스크립트 실행 요청&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이건 작은 팁인데, &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;토큰 사용량&lt;/span&gt;&lt;/b&gt;을 줄이기 위해서는 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;/clear&lt;/span&gt;&lt;/b&gt;를 주기적으로 실행해야 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;새로운 작업을 시작할 경우 한 번씩 컨텍스트를 초기화 해주세요!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;컨텍스트가 많이 쌓이면 질문 한번에 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;사용량 20%&lt;/span&gt;&lt;/b&gt;씩도 소모하더라고요  &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁자주 쓰이는 프롬프트 예시&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  코드 설명 요청&lt;br /&gt;이 코드가 어떤 역할을 하는지 간단히 설명&lt;br /&gt;&lt;br /&gt;  코드 리팩토링&lt;br /&gt;이 코드의 중복을 줄이고, 더 모듈화된 형태로 리팩토링&lt;br /&gt;&lt;br /&gt;  테스트 생성&lt;br /&gt;이 함수에 대한 Jest 테스트 코드 생성&lt;br /&gt;&lt;br /&gt;  문서화&lt;br /&gt;이 React 컴포넌트에 대한 JSDoc 주석 생성&lt;br /&gt;&lt;br /&gt;  성능 개선&lt;br /&gt;이 코드의 렌더링 최적화를 위한 개선 방안 제안&lt;br /&gt;&lt;br /&gt;  새로운 기능 추가&lt;br /&gt;이 컴포넌트에 검색 필터 기능을 추가&lt;br /&gt;&lt;br /&gt;  리뷰 요청&lt;br /&gt;이 변경사항에 대한 코드 리뷰&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗️프롬프트가 길어질 수록 사용하는 토큰이 늘어날 수 있으니, &lt;span style=&quot;color: #006dd7;&quot;&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  실제 사용기&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://github.com/HongHyunKi/nextjs-shadcn-boilerplate&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;깃허브링크&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1763363234031&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 - HongHyunKi/nextjs-shadcn-boilerplate&quot; data-og-description=&quot;Contribute to HongHyunKi/nextjs-shadcn-boilerplate development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/HongHyunKi/nextjs-shadcn-boilerplate&quot; data-og-url=&quot;https://github.com/HongHyunKi/nextjs-shadcn-boilerplate&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fbvHA/hyZNPkfCus/IVAuwSvRUd6om5234mTIL1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bn6bex/hyZNOlnOMg/AHHGHhImsisORM5JnjuSO1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/HongHyunKi/nextjs-shadcn-boilerplate&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/HongHyunKi/nextjs-shadcn-boilerplate&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fbvHA/hyZNPkfCus/IVAuwSvRUd6om5234mTIL1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bn6bex/hyZNOlnOMg/AHHGHhImsisORM5JnjuSO1/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 - HongHyunKi/nextjs-shadcn-boilerplate&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to HongHyunKi/nextjs-shadcn-boilerplate development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;프롬프트 : 이 프로젝트는 보일러 플레이트 프로젝트야. 개선점을 찾고 모던하게 코드 변경&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;1712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2mlal/dJMcacO1jbp/NV1LHbszLAai6eOjrmkeT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2mlal/dJMcacO1jbp/NV1LHbszLAai6eOjrmkeT1/img.png&quot; data-alt=&quot;클로드 코드의 작업 리뷰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2mlal/dJMcacO1jbp/NV1LHbszLAai6eOjrmkeT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2mlal%2FdJMcacO1jbp%2FNV1LHbszLAai6eOjrmkeT1%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;658&quot; height=&quot;792&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;1712&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;클로드 코드의 작업 리뷰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ 프롬프트 한줄에 엄청난 양의 작업을 해냈습니다. 헐랭  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;프롬프트 : Next.js + tailwind + shadcn 보일러 플레이트에 맞는 메인페이지 꾸며서 만들어줘 완벽한 반응형으로 세련되게&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xfwzN/dJMcaaDFxuZ/oiRkW2ckhSrllIPno5RxXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xfwzN/dJMcaaDFxuZ/oiRkW2ckhSrllIPno5RxXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xfwzN/dJMcaaDFxuZ/oiRkW2ckhSrllIPno5RxXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxfwzN%2FdJMcaaDFxuZ%2FoiRkW2ckhSrllIPno5RxXK%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;673&quot; height=&quot;377&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;504&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2028&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qVhGj/dJMcaa4JXw4/1XZeSrKXxD9LRhYckGQfak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qVhGj/dJMcaa4JXw4/1XZeSrKXxD9LRhYckGQfak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qVhGj/dJMcaa4JXw4/1XZeSrKXxD9LRhYckGQfak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqVhGj%2FdJMcaa4JXw4%2F1XZeSrKXxD9LRhYckGQfak%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;675&quot; height=&quot;314&quot; data-origin-width=&quot;2028&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ 프로젝트 세팅은 되었으니, 샘플 페이지를 부탁해 보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;next.js 공식 문서 같은 디자인의 UI가 뚝딱 완성되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 &lt;a href=&quot;https://nextjs-shadcn-boilerplate-beta.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;에서 확인하실 수 있습니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패딩 값 같은 디테일한 조정은 잘 못 하더라고요.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UBgF3/dJMcacapWjO/TnL3n5QVozs3EKbdd6lDP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UBgF3/dJMcacapWjO/TnL3n5QVozs3EKbdd6lDP1/img.png&quot; data-alt=&quot;약 10번의 질문 이후 사용량&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UBgF3/dJMcacapWjO/TnL3n5QVozs3EKbdd6lDP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUBgF3%2FdJMcacapWjO%2FTnL3n5QVozs3EKbdd6lDP1%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;761&quot; height=&quot;130&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;약 10번의 질문 이후 사용량&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30분 정도 사용했고, 프로젝트 전체에 걸친 코드 수정이 몇번 발생해서, Pro 플랜 사용량의 약 30%를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 5시간마다 세션이 초기화 돼서 아직까지 엄청 부족하다는 느낌은 못받았습니다.  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  사용 후기&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;최근까지는 적절히 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;코드 조각을 잘라 붙여&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;ChatGPT에게 질문하는 방식으로 AI를 사용해왔습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;클로드 코드는 코드 조각을 직접 입력할 필요 없이&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;프로젝트 전체를 컨텍스트&lt;/span&gt;&lt;/b&gt;로 사용할 수 있고,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;심지어 직접 파일까지 제어 할 수 있기 때문에&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;더욱 강력한 생산성을 체감했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;현재 회사에서는 두가지 방법을 적절히 섞어가며&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;업무에 AI를 사용하고 있습니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이제는 확실히 AI 없이 개발하던 시절로는&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;점점 더 돌아가기 힘들어 질 것 같습니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이길 수 없다면 합류하라!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;개발자 여러분 모두 화이팅입니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;(추가) 클로드는 코딩만 하자&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1614&quot; data-origin-height=&quot;1160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ1si1/dJMcaaXYoyx/OKw3r9S9fk4EkTuld5f5c1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ1si1/dJMcaaXYoyx/OKw3r9S9fk4EkTuld5f5c1/img.png&quot; data-alt=&quot;클로드가 생성한 - 개발자가 의자에 누워서 바이브 코딩하는 밈 이미지 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ1si1/dJMcaaXYoyx/OKw3r9S9fk4EkTuld5f5c1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ1si1%2FdJMcaaXYoyx%2FOKw3r9S9fk4EkTuld5f5c1%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;422&quot; height=&quot;303&quot; data-origin-width=&quot;1614&quot; data-origin-height=&quot;1160&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;클로드가 생성한 - 개발자가 의자에 누워서 바이브 코딩하는 밈 이미지 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>Claude Code 사용 방법</category>
      <category>클로드 코드 사용 후기</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/132</guid>
      <comments>https://hyunki99.tistory.com/132#entry132comment</comments>
      <pubDate>Mon, 17 Nov 2025 21:30:44 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드 코드 설치 방법 + 가격 정보 (feat. 인텔리제이에서 실행하기)</title>
      <link>https://hyunki99.tistory.com/131</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;992&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq5UEU/dJMb84Dt9gU/yBRXIas4TCNgimoizoQvV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq5UEU/dJMb84Dt9gU/yBRXIas4TCNgimoizoQvV1/img.png&quot; data-alt=&quot;30분만에 완성된 샘플 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq5UEU/dJMb84Dt9gU/yBRXIas4TCNgimoizoQvV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq5UEU%2FdJMb84Dt9gU%2FyBRXIas4TCNgimoizoQvV1%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;587&quot; height=&quot;291&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;992&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;30분만에 완성된 샘플 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;요즘 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;생성형 AI&lt;/span&gt;&lt;/b&gt;를 활용한 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;바이브 코딩&lt;/span&gt;&lt;/b&gt;이 뜨거운 주제인 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;저는 시간이 날 때마다 IT 칼럼을 즐겨보는데,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;클로드 코드&lt;/span&gt;&lt;/b&gt;에 대해서 아주 많은 칼럼들이 보입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;운이 좋게도 회사에서 클로드 코드 연간 구독권을 지원받아&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;직접 한번 사용해 봤습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(이 녀석 아주 물건입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;함께 알아봅시다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  클로드 코드&amp;nbsp;&lt;/b&gt;가격&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://www.claude.com/pricing&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.claude.com/pricing&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1761030729824&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;Pricing | Claude&quot; data-og-description=&quot;Explore Claude pricing plans and API costs. Choose from Free, Pro, Max, Team, or Enterprise options to get started with Claude.&quot; data-og-host=&quot;www.claude.com&quot; data-og-source-url=&quot;https://www.claude.com/pricing&quot; data-og-url=&quot;https://www.claude.com/pricing&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b4ZOKc/hyZL15Emux/1TZtM4JzxvEj6iFqzWCuK1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cMJjcY/hyZL1EBa2Z/ofDJrhKmkc9SJ17rdAkPw1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.claude.com/pricing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.claude.com/pricing&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b4ZOKc/hyZL15Emux/1TZtM4JzxvEj6iFqzWCuK1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cMJjcY/hyZL1EBa2Z/ofDJrhKmkc9SJ17rdAkPw1/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;Pricing | Claude&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Explore Claude pricing plans and API costs. Choose from Free, Pro, Max, Team, or Enterprise options to get started with Claude.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWqC8v/dJMb86BiJ8j/ZGGzzGzqU7ztOfkzgLho4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWqC8v/dJMb86BiJ8j/ZGGzzGzqU7ztOfkzgLho4k/img.png&quot; data-alt=&quot;Free, Pro, Max&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWqC8v/dJMb86BiJ8j/ZGGzzGzqU7ztOfkzgLho4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWqC8v%2FdJMb86BiJ8j%2FZGGzzGzqU7ztOfkzgLho4k%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;697&quot; height=&quot;382&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Free, Pro, Max&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;size18&quot;&gt;&lt;b&gt;⦁개인&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* Free : $0&lt;br /&gt;- 사용량이 금방 부족해짐&lt;br /&gt;&lt;br /&gt;* Pro : 연간 구독 $17, 월별 구독 $20&lt;br /&gt;- Free 대비 약 5배 더 많은 사용량 제공&lt;br /&gt;&lt;br /&gt;* Max : 월 $100 부터 시작&lt;br /&gt;- Pro 대비 5배 또는 20배 많은 사용량 선택 가능&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용량에 따라 가격이 달라지는 플랜을 선택하는 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드 코드가 처음이시라면, Free로 체험해 보고 괜찮다 싶으면 Pro를 한두 달 정도 체험해 보시는 것을 추천드립니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 사용해보니 일을 좀 많이 시키면 Pro도 금방 세션 사용량을 초과할 것 같더라고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션은 5시간마다 초기화 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  &lt;/b&gt;설치 및 실행 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.claude.com/en/docs/claude-code/overview&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1761031324053&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;Claude Code overview - Claude Docs&quot; data-og-description=&quot;Learn about Claude Code, Anthropic's agentic coding tool that lives in your terminal and helps you turn ideas into code faster than ever before.&quot; data-og-host=&quot;docs.claude.com&quot; data-og-source-url=&quot;https://docs.claude.com/en/docs/claude-code/overview&quot; data-og-url=&quot;https://docs.claude.com/en/docs/claude-code/overview&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fiuEi/hyZL1YSQ5W/tJ47k40bRzFmOUeBlm7MYK/img.png?width=1200&amp;amp;height=630&amp;amp;face=502_363_693_571,https://scrap.kakaocdn.net/dn/bMJjkM/hyZLeqrF1K/F4sMP3fnRf5lNmGIxkThP1/img.png?width=1200&amp;amp;height=630&amp;amp;face=502_363_693_571&quot;&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.claude.com/en/docs/claude-code/overview&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fiuEi/hyZL1YSQ5W/tJ47k40bRzFmOUeBlm7MYK/img.png?width=1200&amp;amp;height=630&amp;amp;face=502_363_693_571,https://scrap.kakaocdn.net/dn/bMJjkM/hyZLeqrF1K/F4sMP3fnRf5lNmGIxkThP1/img.png?width=1200&amp;amp;height=630&amp;amp;face=502_363_693_571');&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;Claude Code overview - Claude Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Learn about Claude Code, Anthropic's agentic coding tool that lives in your terminal and helps you turn ideas into code faster than ever before.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ 공식문서에 정리가 잘 되어있으니 한번 읽어보시는 것을 추천드립니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁터미널 입력&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1761031414738&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Install Claude Code
npm install -g @anthropic-ai/claude-code

# 프로젝트 폴더 이동
cd your-awesome-project

# 클로드 코드 실행
claude&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;1432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ7Izu/dJMb9NaJnZq/rl8yiLtLnq0tleLaEteDrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ7Izu/dJMb9NaJnZq/rl8yiLtLnq0tleLaEteDrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ7Izu/dJMb9NaJnZq/rl8yiLtLnq0tleLaEteDrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ7Izu%2FdJMb9NaJnZq%2Frl8yiLtLnq0tleLaEteDrK%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;450&quot; height=&quot;454&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;1432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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; 처음 실행 시 아주 귀여운 도트와 함께 테마를 선택하라는 UI가 표시됩니다. &lt;/span&gt;&lt;/span&gt;&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;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d; text-align: start;&quot;&gt;저는 이런 도트 감성이 좋더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;클로드 코드를&lt;span&gt; 개발한 Anthropic은 사내에서 다양한 개발 환경을 사용하고 있는 &lt;/span&gt;&lt;/span&gt;&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;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;CLI를 선택했다고 합니다.  &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;VSCode || 인텔리제이에서 클로드 코드 사용하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁VS Code&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/vs-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.claude.com/en/docs/claude-code/vs-code&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1761031948620&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;Visual Studio Code - Claude Docs&quot; data-og-description=&quot;Use Claude Code with Visual Studio Code through our native extension or CLI integration&quot; data-og-host=&quot;docs.claude.com&quot; data-og-source-url=&quot;https://docs.claude.com/en/docs/claude-code/vs-code&quot; data-og-url=&quot;https://docs.claude.com/en/docs/claude-code/vs-code&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b4R81J/hyZMahe3Wn/EjhS5pIJNJJgMTxzcq3YF1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cTyryV/hyZMaVSJjN/4JOlCOwIs4dn1qyqRpuecK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/sE2vB/hyZLXWvlhL/YKZqqn1HBs2xIfKj5Ppnx0/img.jpg?width=2500&amp;amp;height=1155&amp;amp;face=0_0_2500_1155&quot;&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/vs-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.claude.com/en/docs/claude-code/vs-code&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b4R81J/hyZMahe3Wn/EjhS5pIJNJJgMTxzcq3YF1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cTyryV/hyZMaVSJjN/4JOlCOwIs4dn1qyqRpuecK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/sE2vB/hyZLXWvlhL/YKZqqn1HBs2xIfKj5Ppnx0/img.jpg?width=2500&amp;amp;height=1155&amp;amp;face=0_0_2500_1155');&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;Visual Studio Code - Claude Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Use Claude Code with Visual Studio Code through our native extension or CLI integration&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 인텔리제이를 사용하기 때문에 VSCode는 해당 글을 참고해주세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁JetBrains IDE (인텔리제이)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/jetbrains&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.claude.com/en/docs/claude-code/jetbrains&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1761032060060&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;JetBrains IDEs - Claude Docs&quot; data-og-description=&quot;Use Claude Code with JetBrains IDEs including IntelliJ, PyCharm, WebStorm, and more&quot; data-og-host=&quot;docs.claude.com&quot; data-og-source-url=&quot;https://docs.claude.com/en/docs/claude-code/jetbrains&quot; data-og-url=&quot;https://docs.claude.com/en/docs/claude-code/jetbrains&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bY3rXh/hyZLbmWQ9n/gNNzD1vPDsqw54j1Sbo1Qk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/mcF8L/hyZL33vmmd/RrHmQlX0zyG5GrO6Rk1cKK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/jetbrains&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.claude.com/en/docs/claude-code/jetbrains&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bY3rXh/hyZLbmWQ9n/gNNzD1vPDsqw54j1Sbo1Qk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/mcF8L/hyZL33vmmd/RrHmQlX0zyG5GrO6Rk1cKK/img.png?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;JetBrains IDEs - Claude Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Use Claude Code with JetBrains IDEs including IntelliJ, PyCharm, WebStorm, and more&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ 인텔리제이 내부에서 클로드 코드를 사용하기 위해서는, &lt;a href=&quot;https://plugins.jetbrains.com/plugin/27310-claude-code-beta-&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;플러그인&lt;/a&gt;을 설치해야합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4E9u4/dJMb9OAHZKi/FZDKwbgfJRJKB6SdPtVEG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4E9u4/dJMb9OAHZKi/FZDKwbgfJRJKB6SdPtVEG0/img.png&quot; data-alt=&quot;IDE 버전이 낮다는 경고 메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4E9u4/dJMb9OAHZKi/FZDKwbgfJRJKB6SdPtVEG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4E9u4%2FdJMb9OAHZKi%2FFZDKwbgfJRJKB6SdPtVEG0%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;509&quot; height=&quot;189&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IDE 버전이 낮다는 경고 메시지&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;해당 플로그인을 사용하기 위해서는 최소 2025.2.3 버전의 인텔리제이가 필요합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;253&quot; data-origin-height=&quot;113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFFM8R/dJMb84cpIaV/f6QxQgni9GSGfoQMpK3S3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFFM8R/dJMb84cpIaV/f6QxQgni9GSGfoQMpK3S3k/img.png&quot; data-alt=&quot;인텔리제이 업데이트 하는 방법 (mac)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFFM8R/dJMb84cpIaV/f6QxQgni9GSGfoQMpK3S3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFFM8R%2FdJMb84cpIaV%2Ff6QxQgni9GSGfoQMpK3S3k%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;253&quot; height=&quot;113&quot; data-origin-width=&quot;253&quot; data-origin-height=&quot;113&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인텔리제이 업데이트 하는 방법 (mac)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미뤄왔던 IDE 업데이트를 이번 기회에 진행했습니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹에서 설치할 필요 없이 인텔리제이의 Check for Updates 기능을 통해 쉽게 업데이트 할 수 있었습니다.&lt;/p&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;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;cmd + ESC&lt;/span&gt;&lt;/b&gt; 혹은 상단 클로드 버튼 클릭을 통해서 IDE 내부에서 클로드 코드 실행이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5IPjp/dJMb9O8ya2T/CoTRnM0WpaairpORyZpj61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5IPjp/dJMb9O8ya2T/CoTRnM0WpaairpORyZpj61/img.png&quot; data-alt=&quot;인텔리제이 클로드 코드 터미널&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5IPjp/dJMb9O8ya2T/CoTRnM0WpaairpORyZpj61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5IPjp%2FdJMb9O8ya2T%2FCoTRnM0WpaairpORyZpj61%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;588&quot; height=&quot;281&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인텔리제이 클로드 코드 터미널&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;작성하다 보니, 내용이 길어져서&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다음 글에는 클로드 코드의 활용 방법과&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;&lt;a style=&quot;color: #dddddd;&quot; href=&quot;https://claude.com/product/claude-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://claude.com/product/claude-code&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude code</category>
      <category>클로드 코드</category>
      <category>클로드 코드 가격</category>
      <category>클로드 코드 인텔리제이</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/131</guid>
      <comments>https://hyunki99.tistory.com/131#entry131comment</comments>
      <pubDate>Mon, 27 Oct 2025 21:00:10 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] 이전 페이지 뒤로 가기 구현하기 (세션 스토리지, 히스토리 스택)</title>
      <link>https://hyunki99.tistory.com/130</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  문제 상황&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Next.js 14버전&lt;/span&gt;&lt;/b&gt;을 사용하던 중&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;router.back() 함수에서 이슈&lt;/span&gt;&lt;/b&gt;가 발생했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1756113805914&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ArrowBackIosNewIcon
  onClick={() =&amp;gt; {
    router.back(); // 문제 코드 !
  }}
&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;router.back()은 그냥 사용하면 문제없이 동작하지만&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;새로고침 후 실행되면 RSC가 무한히 pending 되면서 결국 웹사이트가 터져버렸습니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSMUMS/btsP4lAMgwe/h7MBrkt5WEYIYIABpbi0jK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSMUMS/btsP4lAMgwe/h7MBrkt5WEYIYIABpbi0jK/img.png&quot; data-alt=&quot;무한 pending ...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSMUMS/btsP4lAMgwe/h7MBrkt5WEYIYIABpbi0jK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSMUMS%2FbtsP4lAMgwe%2Fh7MBrkt5WEYIYIABpbi0jK%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;746&quot; height=&quot;46&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;무한 pending ...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;router.back()을 계속 사용하면서,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;해결할 수 있는 방법은 없나 찾아봤지만 마땅한 방법을 찾지 못했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;저희 프로젝트만 그런가요?? 댓글로 알려주세요&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 결국 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;세션 스토리지에 히스토리를 직접 저장&lt;/span&gt;&lt;/b&gt;하고&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;goBack()&lt;/span&gt; &lt;/b&gt;함수를 구현하기로 했습니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  해결 방법&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁1. 히스토리 저장을 위한 HistoryTracker 컴포넌트&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756115505757&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const STORAGE_KEY = 'pageHistory';

/**
 * HistoryTracker
 * - 루트에 한 번만 마운트
 * - pathname 변화 시 세션스토리지에 기록
 */
export const HistoryTracker = () =&amp;gt; {
  const pathname = usePathname();
  const searchParams = useSearchParams();

  useEffect(() =&amp;gt; {
    // 쿼리스트링 포함
    const fullPath = searchParams
      ? `${pathname}?${searchParams.toString()}`
      : pathname;
    const history = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '[]');

    // 중복 방지
    if (history[history.length - 1] !== fullPath) {
      history.push(fullPath);
      sessionStorage.setItem(STORAGE_KEY, JSON.stringify(history));
    }
  }, [pathname, searchParams]);

  return null;
};

// 선택사항입니다 ! -&amp;gt; 필요하면 suspense를 감싸서 사용하세요.
/**
 * SuspenseWrapper
 */
export const SuspenseHistoryTracker = () =&amp;gt; (
  &amp;lt;Suspense fallback={null}&amp;gt;
    &amp;lt;HistoryTracker /&amp;gt;
  &amp;lt;/Suspense&amp;gt;
);


// 루트 컨테이너 등에서 한번만 렌더링
&amp;lt;SWRConfig&amp;gt;
	...
    &amp;lt;SuspenseHistoryTracker /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트래커는 언마운트 되지 않고 계속 유지되면서 path를 저장해야 하기 때문에 Provider를 넣는 곳에 위치시켜주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 path가 변경되면 세션 스토리지에 배열로 저장됩니다.&lt;/p&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. useHistory : 저장된 히스토리 관련 유틸 함수 모음 훅&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756115830888&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * useHistory
 * - goBack(): 페이지 뒤로가기
 */
export const useHistory = (fallbackPath = '/') =&amp;gt; {
  const router = useRouter();

  const goBack = useCallback(() =&amp;gt; {
    const history = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '[]');

    if (history.length &amp;gt; 1) {
      history.pop(); // 현재 페이지 제거
      const prev = history.pop(); // 이전 페이지
      sessionStorage.setItem(STORAGE_KEY, JSON.stringify(history));

      if (prev) {
        router.replace(prev);
        return;
      }
    }

    router.replace(fallbackPath);
  }, [router, fallbackPath]);

  return { goBack };
};&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;지금은 goBack밖에 없지만, 히스토리와 관련된 함수를 추가할 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이곳에 작성하고 return만 해주면 되기 때문에 확장성도 좋습니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 새로고침해도 세션스토리지에 남아있는 path는 휘발되지 않기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 뒤로 가기가 동작합니다 !  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;+ 09/05 추가 :&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;신규 프로젝트에서 Next.js 15.4.5 사용하는데, router.back() 함수가 잘 동작하네요 뭐지 &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7; text-align: left;&quot;&gt;+ 09/23 추가 :&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;문제가 발생한 프로젝트는 Next.js &lt;b&gt;v14.2.29&lt;/b&gt;를 사용하고 있었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;router.back()뿐만 아니라 브라우저 뒤로가기 시 간헐적으로 RSC가 무한 대기 상태가 되며 앱이 터지는 현상이 있었습니다.&lt;br /&gt;Next.js를 최신 버전인 &lt;b&gt;v15.5.3&lt;/b&gt;으로 마이그레이션하니 문제는 해결되었습니다.  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/Next</category>
      <category>Next.js</category>
      <category>next.js 뒤로가기</category>
      <category>next.js 히스토리스택</category>
      <category>router.back()</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/130</guid>
      <comments>https://hyunki99.tistory.com/130#entry130comment</comments>
      <pubDate>Mon, 25 Aug 2025 19:06:12 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] Pretendard 숫자 데이터 고정폭 적용하기</title>
      <link>https://hyunki99.tistory.com/127</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;542&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rUiZO/btsNLsPpGoQ/bOV6bzckbYXySCX4FseHy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rUiZO/btsNLsPpGoQ/bOV6bzckbYXySCX4FseHy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rUiZO/btsNLsPpGoQ/bOV6bzckbYXySCX4FseHy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrUiZO%2FbtsNLsPpGoQ%2FbOV6bzckbYXySCX4FseHy0%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;291&quot; height=&quot;434&quot; data-origin-width=&quot;542&quot; data-origin-height=&quot;808&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;사내 백오피스 프로젝트에서 숫자의 단위가 같은데&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;폰트의 크기가 달라 가독성이 떨어진다&lt;/span&gt;&lt;/b&gt;는 요구사항을 받았습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 프로젝트는 특성상 가격 데이터를 많이 다루기 때문에&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;숫자의 가독성이 중요했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;해결방법 함께 알아봅시다.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  문제 상황&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pXC9U/btsNLS8enOq/ZDFrebFcmTwvWnpyAhqyb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pXC9U/btsNLS8enOq/ZDFrebFcmTwvWnpyAhqyb1/img.png&quot; data-alt=&quot;https://en.wikipedia.org/wiki/Monospaced_font&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pXC9U/btsNLS8enOq/ZDFrebFcmTwvWnpyAhqyb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpXC9U%2FbtsNLS8enOq%2FZDFrebFcmTwvWnpyAhqyb1%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;356&quot; height=&quot;176&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://en.wikipedia.org/wiki/Monospaced_font&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁가변폭 폰트 vs 고정폭 폰트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 현상이 발생한 이유는 사용중인 Pretendard 폰트가 가변폭 폰트이기 때문입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;⦁ 가변폭 폰트 (Proportional Font)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;글자마다 너비가 서로 다르게 설정된 폰트입니다. 예를 들어 i는 좁고, m은 넓게 표시됩니다.&lt;br /&gt;&lt;br /&gt;- 일반적인 본문에 사용&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;⦁ 고정폭 폰트 (monospaced font, fixed-pitch, fixed-width, non-proportional font)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;모든 글자와 기호가 동일한 너비를 가지는 폰트입니다. i, m, 1, W가 모두 같은 폭을 차지합니다.&lt;br /&gt;&lt;br /&gt;- 숫자가 나란히 보여야 할 때&lt;br /&gt;- 시계나 타이머 (ex. 12:34:56)&lt;br /&gt;- 가격 리스트 (ex. ₩1,000 / ₩10,000 / ₩100,000)&lt;br /&gt;- 회계나 통계 관련 표&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  해결 방법&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTtayG/btsNUcjTDI8/rbaR3RzY8HQmvFSMqsO1t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTtayG/btsNUcjTDI8/rbaR3RzY8HQmvFSMqsO1t0/img.png&quot; data-alt=&quot;https://github.com/orioncactus/pretendard/discussions/110&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTtayG/btsNUcjTDI8/rbaR3RzY8HQmvFSMqsO1t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTtayG%2FbtsNUcjTDI8%2FrbaR3RzY8HQmvFSMqsO1t0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;676&quot; height=&quot;349&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;988&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/orioncactus/pretendard/discussions/110&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ Pretendard는 고정폭 숫자 기능을 지원합니다. 사용하는 폰트가 고정폭 숫자를 지원하는지 확인해보세요 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1746594794589&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// globlas.css
body {
  font-family: 'Pretendard', sans-serif;
  /* 
   font-variant-numeric: 숫자(0~9)의 스타일을 조절하는 CSS 속성입니다.
   tabular-nums: 숫자들을 같은 폭으로 출력하도록 지정합니다. 
  */
  font-variant-numeric: tabular-nums;
}&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;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;font-variant-numeric&lt;/span&gt;&lt;/b&gt;를 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⦁적용 결과&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcmIe8/btsNK4g44Qs/e2Srk1NIyb1U335ndH8Kck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcmIe8/btsNK4g44Qs/e2Srk1NIyb1U335ndH8Kck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcmIe8/btsNK4g44Qs/e2Srk1NIyb1U335ndH8Kck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcmIe8%2FbtsNK4g44Qs%2Fe2Srk1NIyb1U335ndH8Kck%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;321&quot; height=&quot;496&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자의 폰트 크기가 고정되어 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;가독성이 훨씬 개선&lt;/span&gt;&lt;/b&gt;되었습니다 !  &lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;&lt;a style=&quot;color: #dddddd;&quot; href=&quot;https://en.wikipedia.org/wiki/Monospaced_font&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://en.wikipedia.org/wiki/Monospaced_font&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;&lt;a style=&quot;color: #dddddd;&quot; href=&quot;https://velog.io/@aneb/css-%EA%B0%80%EB%B3%80%ED%8F%AD-%ED%8F%B0%ED%8A%B8%EB%A5%BC-%EA%B3%A0%EC%A0%95%ED%8F%AD-%ED%8F%B0%ED%8A%B8%EB%A1%9C-%EB%B0%94%EA%BE%B8%EB%8A%94-%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@aneb/css-%EA%B0%80%EB%B3%80%ED%8F%AD-%ED%8F%B0%ED%8A%B8%EB%A5%BC-%EA%B3%A0%EC%A0%95%ED%8F%AD-%ED%8F%B0%ED%8A%B8%EB%A1%9C-%EB%B0%94%EA%BE%B8%EB%8A%94-%EB%B0%A9%EB%B2%95&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End/HTML, CSS, JS</category>
      <category>가변폭 고정폭 폰트</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/127</guid>
      <comments>https://hyunki99.tistory.com/127#entry127comment</comments>
      <pubDate>Wed, 7 May 2025 20:20:21 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] next-intl 자바스크립트 프로젝트에서 다국어 메시지 자동완성 구현하기 (부분 타입스크립트 활용)</title>
      <link>https://hyunki99.tistory.com/126</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;980&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v8Vx6/btsNhK2VNeE/9N6aXkWqKXAeXPKPmXlxd0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v8Vx6/btsNhK2VNeE/9N6aXkWqKXAeXPKPmXlxd0/img.jpg&quot; data-alt=&quot;meme-arsenal&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v8Vx6/btsNhK2VNeE/9N6aXkWqKXAeXPKPmXlxd0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv8Vx6%2FbtsNhK2VNeE%2F9N6aXkWqKXAeXPKPmXlxd0%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;431&quot; height=&quot;587&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;980&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;meme-arsenal&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;신규 프로젝트의 다국어 적용을 마치고&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;기존 프로젝트에도 다국어 적용이 필요한 상황이었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;문제는 기존 프로젝트는 자바스크립트 프로젝트&lt;/span&gt;&lt;/b&gt;라는 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kESvc/btsNg93Tprw/SBWEMPgrVmLIOtJoPC4kG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kESvc/btsNg93Tprw/SBWEMPgrVmLIOtJoPC4kG1/img.png&quot; data-alt=&quot;사라져버린 다국어 메시지 자동완성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kESvc/btsNg93Tprw/SBWEMPgrVmLIOtJoPC4kG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkESvc%2FbtsNg93Tprw%2FSBWEMPgrVmLIOtJoPC4kG1%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;432&quot; height=&quot;180&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사라져버린 다국어 메시지 자동완성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;신규 프로젝트는 타입스크립트로 진행했기 때문에&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;어려움 없이 자동완성의 혜택을 누릴 수 있었지만,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트 프로젝트에서는 다국어 메시지 자동완성이 불가능했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;자동완성 없이 다국어 메시지를 적용한다고?  &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이건 여러모로 좋지 않을 것 같아서&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;방법을 찾아봤습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  JavaScript 프로젝트에서 .d.ts 파일 생성하기&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁1. 타입스크립트를 devDependencies로 설치&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1744336369052&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add -D typescript&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.d.ts 파일을 생성하기 위해선 타입스크립트를 설치해야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-D는 --dev의 줄임말로&lt;b&gt;, 개발에만 필요한 패키지를 설치할 때 사용&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;typescript는 우리가 작성한 JS 코드에 타입 자동완성을 위한 도구일 뿐, &lt;b&gt;실제 빌드나 배포에는 포함되지 않습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⦁2. .d.ts 파일이란?&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- 코드의 구현 없이 타입만 정의되어 있습니다.&lt;br /&gt;- JS 파일에서도 사용할 수 있어, 자동완성과 타입 체크를 가능하게 해줍니다.&lt;br /&gt;- 특히 다국어 JSON 메시지 같은 구조화된 데이터를 다룰 때, 키 자동완성에 매우 유용합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.d.ts 파일은 타입스크립트의 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;타입 선언 파일(declaration file)&lt;/span&gt;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저희는 i18n.d.ts 파일을 생성해서,&amp;nbsp;&lt;b&gt;다국어 메시지 자동완성&lt;/b&gt;을 구현할 거예요&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;JS 프로젝트에서 프로젝트 전체를 TS로 마이그레이션 하지 않아도 부분적으로 타입의 혜택을 누릴 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⦁3. jsconfig는 그대로 유지하세요!&lt;/b&gt;&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;&amp;nbsp;&lt;/span&gt;타입스크립트를 설치했다고 해서, &lt;span style=&quot;color: #006dd7;&quot;&gt;jsconfig.json&lt;/span&gt;을 &lt;span style=&quot;color: #ef5369;&quot;&gt;tsconfig.json&lt;/span&gt;으로 변경할 필요는 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;오히려 JS 기반 프로젝트라면&lt;span style=&quot;color: #ef5369;&quot;&gt; tsconfig.json&lt;/span&gt;으로 전환하면 에러가 너무 많이 생기고, 설정의 충돌이 발생할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt; jsconfig를 유지한 채 타입 보강&lt;/span&gt;&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_1744337383400&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// jsconfig.json

{
  &quot;compilerOptions&quot;: {
    &quot;baseUrl&quot;: &quot;.&quot;,
    &quot;paths&quot;: {
      &quot;@/*&quot;: [&quot;src/*&quot;]
    },
    &quot;checkJs&quot;: true, // 이거랑
    &quot;resolveJsonModule&quot;: true // 이거만 추가해주세요
  },
  &quot;include&quot;: [&quot;src&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2가지 옵션 정도는 추가해 주셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- checkJs : JSDoc 사용하기 위함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- resolveJsonModule : JSON 파일을 import 하기 위해 필요 (다국어 메시지는 JSON이니까요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  필요한 파일 생성&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nxjyj/btsNh7J9eNO/0GNKJp1H049dMzkWQD2NMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nxjyj/btsNh7J9eNO/0GNKJp1H049dMzkWQD2NMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nxjyj/btsNh7J9eNO/0GNKJp1H049dMzkWQD2NMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNxjyj%2FbtsNh7J9eNO%2F0GNKJp1H049dMzkWQD2NMk%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;348&quot; height=&quot;284&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;✅ next-intl을 세팅했다면 위와 같이 i18n 폴더에 파일들이 있을 겁니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;** 3월 12일에 @4버전으로 올라가면서 라우팅 관련 래핑 컴포넌트를 export 하는 곳이&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;navigation으로 분리되었습니다. 참고하세요 !&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;⦁1.&amp;nbsp; i18n.d.ts&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1744343945867&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// i18n.d.ts

import en from '../../messages/en.json';

type Messages = typeof en;

/* 중첩 객체 자동 완성을 위한 코드 */
type NestedKeyOf&amp;lt;T&amp;gt; = {
  [K in keyof T &amp;amp; string]: T[K] extends object
    ? `${K}.${NestedKeyOf&amp;lt;T[K]&amp;gt;}`
    : K;
}[keyof T &amp;amp; string];

declare global {
  type TKey = NestedKeyOf&amp;lt;Messages&amp;gt;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트 프로젝트에서는, 메시지의 typeof만 넘겼을 때에도 정상적으로 자동완성이 되었지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 프로젝트에서는 NestedKeyOf 처럼 타입을 만들어줘야 자동완성을 사용할 수 있더라고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁2. useT() 커스텀 훅 생성&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1744344202586&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * @typedef {import('./i18n').TKey} TKey
 */
import { useTranslations } from 'next-intl';

/**
 * @returns {(key: TKey) =&amp;gt; string}
 */
export function useT() {
  const t = useTranslations();

  /**
   * @param {TKey} key
   */
  return function (key) {
    return t(key);
  };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useTranslations을 래핑한 커스텀 훅을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSDoc를 사용해서 JS에서도 타입 추론과 자동 완성을 제공합니다!  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁3. 사용해보기&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1744344324597&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useT } from '@/i18n/useT';

function Home() {
  const t = useT();
  
  ...
  
  {t('Common.action')}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daTFSc/btsNfqYZR3Z/WjHtEKhryaAstc4X7AahH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daTFSc/btsNfqYZR3Z/WjHtEKhryaAstc4X7AahH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daTFSc/btsNfqYZR3Z/WjHtEKhryaAstc4X7AahH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaTFSc%2FbtsNfqYZR3Z%2FWjHtEKhryaAstc4X7AahH1%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;719&quot; height=&quot;280&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;536&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;JS 프로젝트에서 다국어 메시지 자동완성 구현하기 끝 !  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;+ 4/15 추가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSDoc을 사용해 타입을 정의했을 때, 타입 추론 속도가 느린지 자동완성이 불안정한 문제가 발생했습니다.  &lt;br /&gt;결국 useT() 훅을 JSDoc 대신 TypeScript로 전환하여 문제를 해결했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;JSDoc 써보고 싶었는데 아쉽네요&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1744698568565&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1. i18n.d.ts 파일 제거
// 2. useT.js -&amp;gt; useT.ts 타입스크립트로 변환 및 타입 직접 사용

// useT.ts
import { useTranslations } from 'next-intl';
import en from '../../messages/en.json';

/* 다국어 메세지 타입 정의 */
type Messages = typeof en;

type NestedKeyOf&amp;lt;T&amp;gt; = {
  [K in keyof T &amp;amp; string]: T[K] extends object
    ? `${K}.${NestedKeyOf&amp;lt;T[K]&amp;gt;}`
    : K;
}[keyof T &amp;amp; string];

type TKey = NestedKeyOf&amp;lt;Messages&amp;gt;;

/* useTranslations 래핑 커스텀 훅 */
export function useT() {
  const t = useTranslations();

  return (key: TKey): string =&amp;gt; t(key);
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  마치면서&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 전체를 타입스크립트로 마이그레이션할 수 있으면&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;좋겠지만, 현실적으로 쉽지 않은 상황이 있을 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;사내 신규 프로젝트에 타입스크립트를 도입하길 정말 다행인 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이럴 땐 이 방법처럼 부분적으로만&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;타입스크립트를 적용하는 것도 좋은 방법인 것 같습니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/Next</category>
      <category>next-intl javascript</category>
      <category>자바스크립트 자동완성</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/126</guid>
      <comments>https://hyunki99.tistory.com/126#entry126comment</comments>
      <pubDate>Fri, 11 Apr 2025 21:30:11 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] 구글 스프레드시트로 i18n 메시지 관리하기 (Apps Script json 추출)</title>
      <link>https://hyunki99.tistory.com/125</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eFMxjZ/btsMH336wyi/jZOMLwHQr9CAtcB3wXl121/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eFMxjZ/btsMH336wyi/jZOMLwHQr9CAtcB3wXl121/img.jpg&quot; data-alt=&quot;https://ifunny.co/tags/i18n&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eFMxjZ/btsMH336wyi/jZOMLwHQr9CAtcB3wXl121/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeFMxjZ%2FbtsMH336wyi%2FjZOMLwHQr9CAtcB3wXl121%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;449&quot; height=&quot;457&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1100&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://ifunny.co/tags/i18n&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hyunki99.tistory.com/124&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hyunki99.tistory.com/124&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1741756574461&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Next.js] Next 15 국제화라이브러리 비교 + 적용하기 (i18n, next-intl)&quot; data-og-description=&quot; 요즘의 모던하고 글로벌한 웹에는 국제화(i18n)와 지역화(i10n)라는 개념이 등장합니다.쉽게 정리하면 다음과 같습니다.✅ 국제화(i18n, Internationalization): &amp;rarr; 다국어 지원을 위해 코드 구조를 준비&quot; data-og-host=&quot;hyunki99.tistory.com&quot; data-og-source-url=&quot;https://hyunki99.tistory.com/124&quot; data-og-url=&quot;https://hyunki99.tistory.com/124&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b6y8tW/hyYqK4YQyL/Pezq2awyQYYQ1h3bsxh9L1/img.gif?width=800&amp;amp;height=366&amp;amp;face=616_180_676_245,https://scrap.kakaocdn.net/dn/bRPb77/hyYrYaDbS1/OYAYP6ueQDqXlKKuqZQgg0/img.gif?width=800&amp;amp;height=366&amp;amp;face=616_180_676_245,https://scrap.kakaocdn.net/dn/5W5wI/hyYqYWtktR/xcIsfIb0viCYBV5EQm5Ilk/img.png?width=1916&amp;amp;height=1042&amp;amp;face=0_0_1916_1042&quot;&gt;&lt;a href=&quot;https://hyunki99.tistory.com/124&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hyunki99.tistory.com/124&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b6y8tW/hyYqK4YQyL/Pezq2awyQYYQ1h3bsxh9L1/img.gif?width=800&amp;amp;height=366&amp;amp;face=616_180_676_245,https://scrap.kakaocdn.net/dn/bRPb77/hyYrYaDbS1/OYAYP6ueQDqXlKKuqZQgg0/img.gif?width=800&amp;amp;height=366&amp;amp;face=616_180_676_245,https://scrap.kakaocdn.net/dn/5W5wI/hyYqYWtktR/xcIsfIb0viCYBV5EQm5Ilk/img.png?width=1916&amp;amp;height=1042&amp;amp;face=0_0_1916_1042');&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;[Next.js] Next 15 국제화라이브러리 비교 + 적용하기 (i18n, next-intl)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt; 요즘의 모던하고 글로벌한 웹에는 국제화(i18n)와 지역화(i10n)라는 개념이 등장합니다.쉽게 정리하면 다음과 같습니다.✅ 국제화(i18n, Internationalization): &amp;rarr; 다국어 지원을 위해 코드 구조를 준비&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hyunki99.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;지난 시간에 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;next-intl&lt;/span&gt; &lt;/b&gt;라이브러리를 사용해서&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다국어 지원을 구현했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이제 더 중요한 숙제가 남았는데요, 바로 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;다국어 메시지 관리&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트의 규모가 커지고 지원하는 언어가 늘어나면&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다국어 메시지를 관리하기 복잡해집니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 수정할 때마다 각각의 언어 파일의 Json을 찾아 수정하고&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;반복하면 번거롭겠죠? 이는 개발자가 실수할 확률도 높습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;개발팀 내부, 외부에서 다국어 메시지를 관리하고 공유할 수 있는&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;문서가 있으면 의사소통 비용이 줄고 생산성이 좋아질 것 같다는 생각에&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;구글 스프레드시트&lt;/span&gt;&lt;/b&gt;를 활용하기로 했습니다.  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  &lt;/b&gt;데이터 설계 &amp;amp; 작업 흐름&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁JSON 데이터 (원하는 데이터)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1741769754150&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// messages/en.json
{
  &quot;LoginPage&quot;: {
    &quot;login&quot;: &quot;Log in&quot;,
    &quot;logout&quot;: &quot;Log out&quot;,
    &quot;placeholder&quot;: {
      &quot;account&quot;: &quot;Account&quot;,
      &quot;password&quot;: &quot;Password&quot;,
      &quot;referralCode&quot;: &quot;Referral Code (6 digits)&quot;
    }
  },
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;next-intl의 메시지 파일입니다. placeholder는 중첩된 객체구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택적으로 활용하면 &lt;span style=&quot;text-align: start;&quot;&gt;메시지를 체계적인 구조로 사용할 수 있습니다. (더 복잡해지지 않도록 주의하세요)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;⦁스프레드 시트&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNsUZM/btsMIFBcpW0/6EUQkaHKIcrRrkdST05upK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNsUZM/btsMIFBcpW0/6EUQkaHKIcrRrkdST05upK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNsUZM/btsMIFBcpW0/6EUQkaHKIcrRrkdST05upK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNsUZM%2FbtsMIFBcpW0%2F6EUQkaHKIcrRrkdST05upK%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;710&quot; height=&quot;114&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시트로 표현하면 위와 같습니다. 중첩된 객체는 . 으로 구분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필터같은 엑셀의 데이터 관련 부가 기능을 사용할 수 있는 장점도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;br /&gt;⦁작업 흐름&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 저희가 원하는 작업 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. 다국어 메시지를 스프레드시트에 작성한다.&lt;br /&gt;&lt;br /&gt;2. 포맷팅 함수를 동작시켜 원하는 형식의 json을 얻는다.&lt;br /&gt;&lt;br /&gt;3. 복사 후 messages에 편리하게 붙여넣고 배포한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번 같은 경우는 프로젝트 환경에 따라 많이 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3에 json을 업데이트하는 방식도 있고 스프레드시트의 Api를 활용해 배포하는 방법도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 간단하게 시트에서 json만 추출해서 메시지에 바로 복사 붙여넣기를 할 수 있도록 구현했습니다.   (반자동입니다)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;  Apps Script 활용 Json 추출&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁시트 상단 확장 프로그램 -&amp;gt; Apps Script&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boIV4H/btsMI5sV3aq/Jk018O1csNrI1W2XKY1sEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boIV4H/btsMI5sV3aq/Jk018O1csNrI1W2XKY1sEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boIV4H/btsMI5sV3aq/Jk018O1csNrI1W2XKY1sEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboIV4H%2FbtsMI5sV3aq%2FJk018O1csNrI1W2XKY1sEk%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;454&quot; height=&quot;305&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 기능 때문에 Node 프로젝트를 하나 생성해야 하나 고민했는데,&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;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁소스코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1741773608227&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function generateTranslationsJson() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const data = sheet.getDataRange().getValues();
  
  // 첫 번째 행은 헤더이므로 두 번째 행부터 시작
  const translationsEn = {};
  const translationsJp = {};

  // 데이터를 순회하며 en과 jp 값을 각각 분리
  for (let i = 1; i &amp;lt; data.length; i++) {
    const [section, key, en, jp] = data[i];

    // section이 '.'을 포함하면 중첩된 구조로 처리
    const sectionKeys = section.split('.');

    let currentEn = translationsEn;
    let currentJp = translationsJp;

    // sectionKeys를 순회하며 중첩된 객체를 만듦
    sectionKeys.forEach((keyPart, index) =&amp;gt; {
      if (!currentEn[keyPart]) {
        currentEn[keyPart] = index === sectionKeys.length - 1 ? {} : {};
        currentJp[keyPart] = index === sectionKeys.length - 1 ? {} : {};
      }

      if (index === sectionKeys.length - 1) {
        // 마지막 부분이라면 값을 넣어줌
        currentEn[keyPart][key] = en;
        currentJp[keyPart][key] = jp;
      } else {
        // 중간 단계는 객체를 계속 내려가며 만듦
        currentEn = currentEn[keyPart];
        currentJp = currentJp[keyPart];
      }
    });
  }

  // 결과를 JSON 형식으로 출력
  const jsonEn = JSON.stringify(translationsEn, null, 2);
  const jsonJp = JSON.stringify(translationsJp, null, 2);
  
  // 잘못된 &quot;&quot; 두 번 문제를 해결하기 위한 추가 처리
  const correctedJsonEn = jsonEn.replace(/&quot;&quot;/g, '&quot;');
  const correctedJsonJp = jsonJp.replace(/&quot;&quot;/g, '&quot;');
  
  Logger.log(&quot;English JSON:\n&quot; + correctedJsonEn);
  Logger.log(&quot;Japanese JSON:\n&quot; + correctedJsonJp);

  // 예시로 스프레드시트에 결과를 붙여넣기 (옵션)
  const resultSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Results');
  if (!resultSheet) {
    resultSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet('Results');
  }
  resultSheet.getRange(1, 1).setValue(&quot;English JSON:&quot;);
  resultSheet.getRange(2, 1).setValue(correctedJsonEn);
  resultSheet.getRange(10, 1).setValue(&quot;Japanese JSON:&quot;);
  resultSheet.getRange(11, 1).setValue(correctedJsonJp);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⦁결과&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;1336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ic7Vu/btsMI7D7cmI/EaPikDNfBCml9rlnMcdFbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ic7Vu/btsMI7D7cmI/EaPikDNfBCml9rlnMcdFbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ic7Vu/btsMI7D7cmI/EaPikDNfBCml9rlnMcdFbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIc7Vu%2FbtsMI7D7cmI%2FEaPikDNfBCml9rlnMcdFbk%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;456&quot; height=&quot;477&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;1336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1YByx/btsMHU6M9mn/PyG0unbfHUUpVEhkJRhvpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1YByx/btsMHU6M9mn/PyG0unbfHUUpVEhkJRhvpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1YByx/btsMHU6M9mn/PyG0unbfHUUpVEhkJRhvpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1YByx%2FbtsMHU6M9mn%2FPyG0unbfHUUpVEhkJRhvpk%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;309&quot; height=&quot;287&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 이동할 필요 없이 간단하게 원하는 언어의 messages Json이 잘 추출 되었습니다.  &lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트가 커진다면 namespace 칼럼을 시트로 구분하는 것도 좋은 방법일 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분은 다국어의 Key값을 어떻게 구분하고 관리하는지 댓글로 알려주세요 !&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;+ 4/11일 추가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTJstL/btsNhc7BFHi/L3Yw1leupnqtd6XdskDvOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTJstL/btsNhc7BFHi/L3Yw1leupnqtd6XdskDvOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTJstL/btsNhc7BFHi/L3Yw1leupnqtd6XdskDvOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTJstL%2FbtsNhc7BFHi%2FL3Yw1leupnqtd6XdskDvOK%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;708&quot; height=&quot;186&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;368&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;key 같은 경우에는 개발자가 직접 만드는 것보다&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;b&gt;1. Apps Script에 유틸 함수 추가&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1744347210504&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * Converts a sentence to camelCase, removing punctuation like commas, periods, and quotes.
 *
 * @param {string} text The input text.
 * @param {number} [maxWords] Optional. Max number of words to include.
 * @return {string} The camelCase version of the text.
 * @customfunction
 */
function TO_CAMEL_CASE(text, maxWords=4) {
  if (typeof text !== 'string') return '';

  // 구두점 및 스마트 따옴표 제거
  const cleanText = text.replace(/[.,\/#!$%\^&amp;amp;\*;:{}=\-_`~()'&quot;&amp;rsquo;&amp;lsquo;&amp;rdquo;&amp;ldquo;]/g, '');

  // 단어 분리 및 제한
  const words = cleanText.trim().split(/\s+/);
  const limited = maxWords &amp;amp;&amp;amp; maxWords &amp;gt; 0 ? words.slice(0, maxWords) : words;

  // camelCase 변환
  return limited
    .map((word, i) =&amp;gt; {
      word = word.toLowerCase();
      return i === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1);
    })
    .join('');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 조금의 특수문자를 제거한 후, 4단어 까지만 카멜케이스로 변환하는 함수를 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 회사의 정책에 맞게 수정해서 사용하세요  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 셀에 사용&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf5r58/btsNiLAb6KE/WkXIgAl4FdtMZ7sA7ko6o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf5r58/btsNiLAb6KE/WkXIgAl4FdtMZ7sA7ko6o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf5r58/btsNiLAb6KE/WkXIgAl4FdtMZ7sA7ko6o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf5r58%2FbtsNiLAb6KE%2FWkXIgAl4FdtMZ7sA7ko6o1%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;651&quot; height=&quot;177&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 셀에 함수를 입력해서 사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;200개 정도의 다국어가 시트에 생성되었는데, 1초만에 key를 다 입력했네요  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;참고 문헌 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/Next</category>
      <category>I18N</category>
      <category>next-intl</category>
      <category>다국어 메시지 관리</category>
      <category>다국어 스프레드시트</category>
      <author>현기</author>
      <guid isPermaLink="true">https://hyunki99.tistory.com/125</guid>
      <comments>https://hyunki99.tistory.com/125#entry125comment</comments>
      <pubDate>Thu, 13 Mar 2025 22:00:24 +0900</pubDate>
    </item>
  </channel>
</rss>