<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발자 연습생의 기록</title>
    <link>https://eznnni.tistory.com/</link>
    <description>  성장하는 개발자 연습생 eznnni입니다!</description>
    <language>ko</language>
    <pubDate>Thu, 23 Jul 2026 11:27:36 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>eznnni</managingEditor>
    <image>
      <title>개발자 연습생의 기록</title>
      <url>https://tistory1.daumcdn.net/tistory/8706228/attach/69fa65ce1ccc40a6841cc4fca57acdb5</url>
      <link>https://eznnni.tistory.com</link>
    </image>
    <item>
      <title>[10x 1회차] 블로그 콘텐츠 기회를 포착하는 방법</title>
      <link>https://eznnni.tistory.com/12</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;본 포스팅은 10x 체험단 활동의 일환으로 강의 수강권을 제공받아 작성한 후기입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;안녕하세요, 이번에 아주 좋은 기회로 &lt;b&gt;코드잇 10x&lt;/b&gt; - &lt;b&gt;&quot;초기 비용 0원으로 부수입 창출 AI로 블로그 수익화 하기&quot; &lt;/b&gt;강의를 수강하게 되었습니다! &lt;br /&gt;앞으로 5주 동안 해당 강의를 수강하며 얻은 정보들을 바탕으로 꾸준히 성장 기록을 남기려고 합니다.&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;u&gt;깊이 있는 정보&lt;/u&gt;와 &lt;u&gt;실제 경험 정보&lt;/u&gt;를 찾는 사람들에게 블로그는 여전히 수요가 강한 매개체입니다.&lt;br /&gt;네이버 블로그 리포트 기준 2025년 한 해 동안 3억 3천만 개의 글이 발행되며 역대 최대 규모를 기록했고, 순 방문자 수도 4,500만 명을 돌파했다고 하네요! &lt;br /&gt;이처럼 블로그는 여러 서비스와 플랫폼이 발달한 지금에도 &lt;b&gt;여전히 영향력있는 정보 전달의 매개&lt;/b&gt;로 자리 잡고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텐엑스의 해당 강의는 &lt;b&gt;블로거가 사람들이 궁금해할 정보를 제공하며 부차적인 수익을 획득할 수 있는 구조 흐름을 이해&lt;/b&gt;할 수 있도록 돕습니다. 더 나아가 그런 블로거가 될 수 있는 방법에 대해 배우고 매 주차마다 관련 실습을 참여하며 직접 경험해 볼 수 있습니다!&lt;br /&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;background-color: #f6e199;&quot;&gt;&lt;u&gt;콘텐츠 기회를 포착하고, AI로 키워드를 발굴하는 법&lt;/u&gt;&lt;/span&gt;에 대해 배우며 직접 제가 실습한 내용을 담고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&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;br /&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;SNS, 뉴스, 정부 정책 사이트 등 다양한 플랫폼에서 사람들에게 많은 검색을 불러일으킨 내용들을 직접 찾아볼 수도 있고, 데이터를 제공하는 여러 서비스들을 활용할 수도 있습니다. 또 LLM 서비스를 활용할 수도 있겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  키워드 찾기1: 데이터 기반 분석&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구글 트렌드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt; &lt;a href=&quot;https://trends.google.co.kr/home&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://trends.google.co.kr/home&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1783849442470&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;Google 트렌드&quot; data-og-description=&quot;FIFA 월드컵 2026 사람들이 토너먼트를 어떻게 검색하고 있는지 확인해 보세요.&quot; data-og-host=&quot;trends.google.co.kr&quot; data-og-source-url=&quot;https://trends.google.co.kr/home&quot; data-og-url=&quot;https://trends.google.co.kr/home&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/emdBpw/dJMb9kUeTMK/4Zi4LZ0bRt0rkY6DaKCyWK/img.png?width=1900&amp;amp;height=906&amp;amp;face=0_0_1900_906,https://scrap.kakaocdn.net/dn/IH6M6/dJMb8WeLUWy/CVknGyXHRauQaViafQio70/img.png?width=1636&amp;amp;height=758&amp;amp;face=0_0_1636_758,https://scrap.kakaocdn.net/dn/ZVgIS/dJMb81f4Hj4/gbAk086R1iWQ1sgeYKNMc1/img.jpg?width=1600&amp;amp;height=666&amp;amp;face=0_0_1600_666&quot;&gt;&lt;a href=&quot;https://trends.google.co.kr/home&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trends.google.co.kr/home&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/emdBpw/dJMb9kUeTMK/4Zi4LZ0bRt0rkY6DaKCyWK/img.png?width=1900&amp;amp;height=906&amp;amp;face=0_0_1900_906,https://scrap.kakaocdn.net/dn/IH6M6/dJMb8WeLUWy/CVknGyXHRauQaViafQio70/img.png?width=1636&amp;amp;height=758&amp;amp;face=0_0_1636_758,https://scrap.kakaocdn.net/dn/ZVgIS/dJMb81f4Hj4/gbAk086R1iWQ1sgeYKNMc1/img.jpg?width=1600&amp;amp;height=666&amp;amp;face=0_0_1600_666');&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;Google 트렌드&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;FIFA 월드컵 2026 사람들이 토너먼트를 어떻게 검색하고 있는지 확인해 보세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trends.google.co.kr&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-filename=&quot;screencapture-trends-google-co-kr-trending-2026-07-12-18_34_19.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CxBmv/dJMcagGgSab/hC93PB3CDbESkOXqq6xkY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CxBmv/dJMcagGgSab/hC93PB3CDbESkOXqq6xkY1/img.png&quot; data-alt=&quot;Google Trends 실시간 인기 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CxBmv/dJMcagGgSab/hC93PB3CDbESkOXqq6xkY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCxBmv%2FdJMcagGgSab%2FhC93PB3CDbESkOXqq6xkY1%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;1920&quot; height=&quot;1121&quot; data-filename=&quot;screencapture-trends-google-co-kr-trending-2026-07-12-18_34_19.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1121&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Google Trends 실시간 인기 탭&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;실시간 인기&quot; 탭에서 최근 트렌드 검색어를, &quot;탐색&quot; 탭에서는 특정 키워드의 관심도 변화를 확인 가능합니다.&lt;br /&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;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt; &lt;a href=&quot;https://datalab.naver.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://datalab.naver.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1783849437963&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;네이버 데이터랩&quot; data-og-description=&quot;네이버의 검색 트렌드 및 급상승검색어 이력, 쇼핑 카테고리별 검색 트렌드 제공&quot; data-og-host=&quot;datalab.naver.com&quot; data-og-source-url=&quot;https://datalab.naver.com/&quot; data-og-url=&quot;https://datalab.naver.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cujW3y/dJMb82MPf3J/rprkSQHxwarOLR9cm5hnrK/img.jpg?width=244&amp;amp;height=244&amp;amp;face=0_0_244_244&quot;&gt;&lt;a href=&quot;https://datalab.naver.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://datalab.naver.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cujW3y/dJMb82MPf3J/rprkSQHxwarOLR9cm5hnrK/img.jpg?width=244&amp;amp;height=244&amp;amp;face=0_0_244_244');&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;네이버 데이터랩&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;네이버의 검색 트렌드 및 급상승검색어 이력, 쇼핑 카테고리별 검색 트렌드 제공&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;datalab.naver.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-filename=&quot;screencapture-datalab-naver-2026-07-12-18_39_02.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BtwUL/dJMcab5X4yv/ahCXaLZ9XHFW3QAqfh8M01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BtwUL/dJMcab5X4yv/ahCXaLZ9XHFW3QAqfh8M01/img.png&quot; data-alt=&quot;Naver DataLab 데이터랩 홈&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BtwUL/dJMcab5X4yv/ahCXaLZ9XHFW3QAqfh8M01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBtwUL%2FdJMcab5X4yv%2FahCXaLZ9XHFW3QAqfh8M01%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;1920&quot; height=&quot;862&quot; data-filename=&quot;screencapture-datalab-naver-2026-07-12-18_39_02.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Naver DataLab 데이터랩 홈&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 검색량 기반 데이터로, 국내 독자 기준 더 직접적인 데이터를 다룹니다.&lt;br /&gt;특정 검색어의 추이를 보며 반복되는 시즌형인지, 최근 급등한 트렌딩 키워드인지 판단할 수 있게 돕습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 네이버의 실시간 검색어 순위 기능이 사라진 줄 알았는데 위와 같은 서비스가 존재한다는 것에 매우 반갑기도 했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;국내 사용자&lt;/b&gt; 기준 &lt;b&gt;키워드 분석&lt;/b&gt;에 아주 유리한 서비스 입니다 ❗&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;네이버 크리에이터 어드바이저&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;  &lt;a href=&quot;https://creator-advisor.naver.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://creator-advisor.naver.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1783849433383&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;Naver Creator Advisor&quot; data-og-description=&quot;네이버의 크리에이터들이 데이터 분석을 통해 더 스마트한 창작활동을 할 수 있도록 지원합니다.&quot; data-og-host=&quot;creator-advisor.naver.com&quot; data-og-source-url=&quot;https://creator-advisor.naver.com/&quot; data-og-url=&quot;https://creator-advisor.naver.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cOxWkI/dJMb8WeLUWs/HSipuauTUsPgRHkGKusc90/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192,https://scrap.kakaocdn.net/dn/byT13B/dJMb8XkrC4F/EmnNrddBUgDlMt4TkrKNHk/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192&quot;&gt;&lt;a href=&quot;https://creator-advisor.naver.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://creator-advisor.naver.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cOxWkI/dJMb8WeLUWs/HSipuauTUsPgRHkGKusc90/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192,https://scrap.kakaocdn.net/dn/byT13B/dJMb8XkrC4F/EmnNrddBUgDlMt4TkrKNHk/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192');&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;Naver Creator Advisor&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;네이버의 크리에이터들이 데이터 분석을 통해 더 스마트한 창작활동을 할 수 있도록 지원합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;creator-advisor.naver.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-filename=&quot;blob&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;919&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NBDCQ/dJMcafAxHJE/kjS9qcvKKXKyaR3iYLERE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NBDCQ/dJMcafAxHJE/kjS9qcvKKXKyaR3iYLERE0/img.png&quot; data-alt=&quot;Naver Creator Advisor 트렌드 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NBDCQ/dJMcafAxHJE/kjS9qcvKKXKyaR3iYLERE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNBDCQ%2FdJMcafAxHJE%2FkjS9qcvKKXKyaR3iYLERE0%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;765&quot; height=&quot;919&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;919&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Naver Creator Advisor 트렌드 탭&lt;/figcaption&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;br /&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;h3 data-ke-size=&quot;size23&quot;&gt;네이버 인플루언서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;https://in.naver.com/keywords&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://in.naver.com/keywords&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1783851510839&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;네이버 인플루언서&quot; data-og-description=&quot;관심분야의 전문 창작자를 만나는 곳&quot; data-og-host=&quot;in.naver.com&quot; data-og-source-url=&quot;https://in.naver.com/keywords&quot; data-og-url=&quot;https://in.naver.com/keywords&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bu8dgq/dJMb9eT1uyK/4cijH4lBHLJG2OBa7IKMqK/img.png?width=1440&amp;amp;height=1440&amp;amp;face=0_0_1440_1440&quot;&gt;&lt;a href=&quot;https://in.naver.com/keywords&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://in.naver.com/keywords&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bu8dgq/dJMb9eT1uyK/4cijH4lBHLJG2OBa7IKMqK/img.png?width=1440&amp;amp;height=1440&amp;amp;face=0_0_1440_1440');&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;네이버 인플루언서&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;관심분야의 전문 창작자를 만나는 곳&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;in.naver.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;829&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P5wwK/dJMcagTKZ9o/0a39v6iWHUd64pOw0Z24Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P5wwK/dJMcagTKZ9o/0a39v6iWHUd64pOw0Z24Kk/img.png&quot; data-alt=&quot;네이버 인플루언서&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P5wwK/dJMcagTKZ9o/0a39v6iWHUd64pOw0Z24Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP5wwK%2FdJMcagTKZ9o%2F0a39v6iWHUd64pOw0Z24Kk%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;829&quot; height=&quot;913&quot; data-origin-width=&quot;829&quot; data-origin-height=&quot;913&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;해당 서비스는 네이버에서 직접 추천 키워드를 제공해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참여한 인원의 수로 어떤 키워드가 핫하게 다뤄지는지 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  검색 데이터 서비스로 키워드 직접 찾아보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소개는 이쯤 하고 이제 직접 활용해 보겠습니다!&lt;br /&gt;앞서 소개해드린 구글 트렌드와 네이버 크리에이터 어드바이저를 활용하여 어떤 키워드가 인기 있는지 확인해 보겠습니다 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구글 트렌드 - 실시간 인기 &amp;amp; 탐색 탭&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-trends-google-co-kr-trending-2026-07-12-18_51_32.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWDuJv/dJMcacX6uJF/WuROVyMCdykKKTZXriWbF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWDuJv/dJMcacX6uJF/WuROVyMCdykKKTZXriWbF0/img.png&quot; data-alt=&quot;실시간 인기 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWDuJv/dJMcacX6uJF/WuROVyMCdykKKTZXriWbF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWDuJv%2FdJMcacX6uJF%2FWuROVyMCdykKKTZXriWbF0%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;1920&quot; height=&quot;1121&quot; data-filename=&quot;screencapture-trends-google-co-kr-trending-2026-07-12-18_51_32.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1121&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;실시간 인기 탭에서 필터 기능을 통해 지난 48시간 동안 한국에서 가장 관심도가 높은 트렌드는 무엇이었는지 확인해 보았습니다. &lt;br /&gt;아무래도 지금이 월드컵 시즌이다 보니 축구 관련 검색어가 높은 검색량을 차지한 것을 확인할 수 있었습니다!&lt;br /&gt;또한 인기드라마 도깨비가 올해 10주년을 맞았고, 해당 드라마의 출연진인 배우 김성겸 님의 감동적인 인터뷰가 많은 사람들에게 울림을 주어서인지 많은 검색량을 차지했네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-trends-google-co-kr-explore-2026-07-12-18_55_44.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mAcnA/dJMcagzpXLM/tiKt4DFJtbiC80XbbCJDNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mAcnA/dJMcagzpXLM/tiKt4DFJtbiC80XbbCJDNK/img.png&quot; data-alt=&quot;탐색 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mAcnA/dJMcagzpXLM/tiKt4DFJtbiC80XbbCJDNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmAcnA%2FdJMcagzpXLM%2FtiKt4DFJtbiC80XbbCJDNK%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;1920&quot; height=&quot;1471&quot; data-filename=&quot;screencapture-trends-google-co-kr-explore-2026-07-12-18_55_44.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1471&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;한편, 탐색 탭에서는 한국에서 지난 1년간 사람들이 가장 많이 검색한 항목과 급상승 검색어를 확인 가능합니다.&lt;br /&gt;인상 깊은 것들을 몇까지 짚어보자면, 네이버, 유튜브, 커뮤니티, LLM 서비스가 많이 검색되었네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글이 많은 사람들의 기본 브라우저이다 보니 구글이 검색을 통해 해당 서비스로 넘어가는 경로로서도 중요한 역할을 하는 것을 알 수 있었습니다! 그 외에는 앞서 말했듯이 지금이 월드컵 시즌이라 축구 관련 검색어들도 많이 보이네요 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 트렌드는 &lt;b&gt;실시간 이슈 파악&lt;/b&gt;에 가장 빠른 도구라 할 수 있겠습니다 ❗&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;네이버 크리에이터 어드바이저 - 트렌드 탭&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRMehq/dJMcagTKZW2/3C3b3vSeQblAmBkUJSAgBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRMehq/dJMcagTKZW2/3C3b3vSeQblAmBkUJSAgBk/img.png&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;925&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; width=&quot;281&quot; height=&quot;338&quot; style=&quot;width: 49.3814%; margin-right: 10px;&quot; data-widthpercent=&quot;49.96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRMehq/dJMcagTKZW2/3C3b3vSeQblAmBkUJSAgBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRMehq%2FdJMcagTKZW2%2F3C3b3vSeQblAmBkUJSAgBk%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;769&quot; height=&quot;925&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/booA6H/dJMcabZfMej/pelESSzd0lkqkIOdN97TL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/booA6H/dJMcabZfMej/pelESSzd0lkqkIOdN97TL0/img.png&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;914&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4558%;&quot; data-widthpercent=&quot;50.04&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/booA6H/dJMcabZfMej/pelESSzd0lkqkIOdN97TL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbooA6H%2FdJMcabZfMej%2FpelESSzd0lkqkIOdN97TL0%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;914&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;검색 유입 트렌드(왼) 메인 유입 트렌드(오)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 크리에이티브 어드바이저는 정말 많은 기능을 제공하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌측의 이미지는 검색 유입 트렌드로 다양한 카테고리별/성별&amp;amp;연령별 인기유입 검색어를 조회 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일상 카테고리에선 날씨에 관련된 검색어가 많이 보이네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우측의 메인 유입 트렌드는 네이버 메인에서 어떤 콘텐츠가 많이 유입되었는지를 확인 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 모바일 유저들의 유입 수가 압도적이고, 엔터 관련 검색어들의 점유율이 매우 높은 것을 확인할 수 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  키워드 찾기2: AI 활용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에선 실제 운용되는 데이터 서비스를 통해 키워드를 찾아보았다면, &lt;br /&gt;이제부턴 LLM 서비스를 활용하여 AI에게 직접 트렌드와 키워드를 묻는 방법에 대해 알아보려 합니다!&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;Perplexity&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;perplexity는 제가 학부생일 때도 과제를 위해 정말 많이 사용한 서비스입니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-perplexity-ai-search-d7c23ebd-d031-436b-b536-5df0e5f539b4-2026-07-12-19_33_15.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7bkxR/dJMcadbybCz/x1eTFIWY8jsyTiKyIsjIF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7bkxR/dJMcadbybCz/x1eTFIWY8jsyTiKyIsjIF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7bkxR/dJMcadbybCz/x1eTFIWY8jsyTiKyIsjIF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7bkxR%2FdJMcadbybCz%2Fx1eTFIWY8jsyTiKyIsjIF1%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;1920&quot; height=&quot;1440&quot; data-filename=&quot;screencapture-perplexity-ai-search-d7c23ebd-d031-436b-b536-5df0e5f539b4-2026-07-12-19_33_15.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1440&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  키워드 검증: 경쟁도 분석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키워드를 결정했다면, 해당 키워드가 어느 정도의 경쟁력을 갖췄는지 알 필요도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 키워드가 나에게만 흥미롭고 남들에겐 그렇지 않을 수도 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색량이 너무 적지 않으며 그렇다고 경쟁이 너무 심하지도 않은 적절한 키워드가 필요합니다.&lt;br /&gt;이를 도와주는 서비스가 존재합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블랙키위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블랙키위는 키워드 검색량&amp;middot;경쟁도&amp;middot;콘텐츠 포화도 등을 보여주는 키워드 분석 플랫폼으로, 블로거나 마케터가 어떤 주제로 글을 써야 유입을 기대할 수 있는지 데이터로 판단하게 해 줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;817&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byp7hx/dJMcahd6JB3/l3cK2rRYqK2kyKtKtx1DSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byp7hx/dJMcahd6JB3/l3cK2rRYqK2kyKtKtx1DSK/img.png&quot; data-alt=&quot;블랙키위 랜딩페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byp7hx/dJMcahd6JB3/l3cK2rRYqK2kyKtKtx1DSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyp7hx%2FdJMcahd6JB3%2Fl3cK2rRYqK2kyKtKtx1DSK%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;1920&quot; height=&quot;817&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;817&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;간단한 회원가입을 통해 해당 서비스를 이용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;919&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y1OqC/dJMcaixi8Ee/oW7YssUluGld6iwaNN6wd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y1OqC/dJMcaixi8Ee/oW7YssUluGld6iwaNN6wd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y1OqC/dJMcaixi8Ee/oW7YssUluGld6iwaNN6wd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy1OqC%2FdJMcaixi8Ee%2FoW7YssUluGld6iwaNN6wd0%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;1920&quot; height=&quot;919&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;919&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;월간 검색량과 월간 콘텐츠 발행량을 확인 가능하며, 해당 월의 예상 검색량과 콘텐츠 포화 지수 등의 수치도 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색량이 발행량보다 높으면 경쟁도가 낮고, 그 반대면 경쟁도가 높은 편이라 판단할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;825&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q8tZ0/dJMcaic3pCs/Y0AAoGnFHuYwbZbCE9Ou9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q8tZ0/dJMcaic3pCs/Y0AAoGnFHuYwbZbCE9Ou9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q8tZ0/dJMcaic3pCs/Y0AAoGnFHuYwbZbCE9Ou9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq8tZ0%2FdJMcaic3pCs%2FY0AAoGnFHuYwbZbCE9Ou9K%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;1920&quot; height=&quot;825&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;825&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외에도 연관 키워드 제공 기능을 통해 더 경쟁력 있는 키워드로의 변경도 고려해볼 수 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 무료 제공은 한계가 존재하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 주차 미션은 앞서 소개한 다양한 서비스를 활용해, 예비 블로거로서 실제 유입을 이끌 수 있는 트렌드 키워드를 선정해보는 것이었습니다. 가이드라인에 따라 하나씩 실습을 진행하며 제 블로그에 적합한 키워드를 구체적으로 정할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 네이버 크리에이터 어드바이저와 AI 추천을 바탕으로 &amp;lsquo;장마철 빨래 냄새 제거&amp;rsquo;라는 키워드를 선택했습니다.&lt;br /&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;br /&gt;내가 쓰고 싶은 글도 의미 있지만, 사람들이 실제로 찾는 정보를 기반으로 콘텐츠를 구성하는 것이 더욱 중요하다는 것을 배우게 된 의미 있는 시간이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 남은 기간 동안에도 꾸준히 실습을 이어가며, 실제로 유입을 만들어낼 수 있는 블로그 운영 역량을 길러보고자 합니다 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 주차는 실제로 블로그를 작성하는 방법을 다룰 것 같습니다. 아주 기대되네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>  기타 활동/텐엑스</category>
      <category>부수입 강의</category>
      <category>블로그 강의</category>
      <category>블로그 수익화</category>
      <category>코드잇 10x</category>
      <category>코드잇 텐엑스</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/12</guid>
      <comments>https://eznnni.tistory.com/12#entry12comment</comments>
      <pubDate>Tue, 14 Jul 2026 20:34:13 +0900</pubDate>
    </item>
    <item>
      <title>Next.js 서버 액션 사용 시 발생한 데이터 직렬화 불일치 문제</title>
      <link>https://eznnni.tistory.com/11</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 진행하고 있는 코드잇 스프린트의 미션 판다 마켓에서&lt;br /&gt;발생한 장애 상황에 대한 트러블 슈팅입니다 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 미션에 대해 간단하게 설명하자면,&lt;br /&gt;판다마켓은 중고상품을 등록하여 사고팔 수 있으며 다른 사용자들과 소통하는 중고거래를 위한 커뮤니티 플랫폼입니다.&lt;br /&gt;현재 백엔드는 Node.js + Express 기반으로, DB는 PostgreSql + Prisma를 사용하여 구축하고 있습니다.&lt;br /&gt;프론트엔드는 JavaScript + Next.js를 사용하고 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 서비스는 자유 게시판에서 자유롭게 글을 올려 다른 사용자들과 소통할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 게시물 등록 페이지를 구현하면서 Next.js의 서버 액션(Server Action)을 사용하여 폼 데이터를 백엔드 API로 전송하는 기능을 구현했습니다. 그런데 로컬 환경에서 테스트할 때, 프론트엔드에서 분명히 데이터를 전송했음에도 백엔드 서버에서 이를 인식하지 못하여 400 Bad Request 에러가 발생하는 현상을 겪었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 에러의 이유는 바로 &lt;b&gt;데이터 직렬화 불일치 문제&lt;/b&gt;였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드의 경우에는 다음의 코드에서 확인할 수 있듯이 Express 서버에서 &lt;code&gt;app.use(express.json())&lt;/code&gt; 미들웨어를 사용하여 JSON 형식의 요청 본문(body)만을 파싱하도록 설정되어 있었습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import dotenv from &quot;dotenv&quot;;
import express from &quot;express&quot;;
import cors from &quot;cors&quot;;

import articleRouter from &quot;./routes/article.js&quot;;
import productRouter from &quot;./routes/product.js&quot;;
import commentRouter from &quot;./routes/comment.js&quot;;
import { PORT } from &quot;./constants/common.js&quot;;

dotenv.config();

const app = express();

app.use(cors());
app.use(express.json());

app.use(&quot;/products&quot;, productRouter);
app.use(&quot;/articles&quot;, articleRouter);
app.use(&quot;/comments&quot;, commentRouter);

app.listen(PORT, () =&amp;gt; {
  console.log(`✅ Server running on http://localhost:${PORT}`);
});&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;프론트엔드의 경우에는 다음의 코드에서 확인할 수 있듯이 Next.js의 서버 액션에서 &lt;code&gt;&amp;lt;form action = {handleCreate}&amp;gt;&lt;/code&gt; 형태로 폼 데이터를 직접 넘겼습니다. 이럴 경우 브라우저는 기본적으로 폼 데이터를 &lt;code&gt;multipart/form-data&lt;/code&gt; 타입으로 인코딩하여 전송한다고 합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import PostForm from &quot;@/components/common/PostForm&quot;;
import { createPost } from &quot;@/services/postService&quot;;
import { redirect } from &quot;next/navigation&quot;;

export default function RegisterPage() {
  async function handleCreate(formData) {
    &quot;use server&quot;;

    const result = await createPost(formData);

    if (result.error) {
      return { success: false, message: &quot;등록에 실패했습니다.&quot; };
    }
    redirect(ROUTES.COMMUNITY.BASE); //자유 게시판 페이지
  }
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;PostForm type=&quot;register&quot; action={handleCreate} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 백엔드는 &lt;code&gt;application/json&lt;/code&gt;을 기대하고 있는데, 프론트엔드는 &lt;code&gt;multipart/form-data&lt;/code&gt;로 데이터를 전송하여, 백엔드 서버의 JSON 파서가 이를 해석하지 못하여 데이터가 정상적으로 전송되지 않았던 것입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; ️ 문제 해결&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 액션 내에서 &lt;code&gt;FormData&lt;/code&gt; 객체를 바로 전송하는 대신, 이를 일반 객체 &lt;code&gt;Plain Object&lt;/code&gt;로 변환한 뒤 &lt;code&gt;JSON.stringify()&lt;/code&gt;를 통해 JSON 형태로 가공하여 API 서비스 함수 &lt;code&gt;createPost&lt;/code&gt;에 전달하도록 코드를 수정했습니다!&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import PostForm from &quot;@/components/common/PostForm&quot;;
import { ROUTES } from &quot;@/constants/navigation&quot;;
import { createPost } from &quot;@/services/postService&quot;;
import { revalidatePath } from &quot;next/cache&quot;;
import { redirect } from &quot;next/navigation&quot;;

export default function RegisterPage() {
  async function handleCreate(formData) {
    &quot;use server&quot;;
    const data = Object.fromEntries(formData.entries());
    const response = await createPost(data);
    const newPostId = response?.data?.id;

    revalidatePath(ROUTES.COMMUNITY.BASE);

    if (newPostId) {
      redirect(ROUTES.COMMUNITY.DETAIL(newPostId)); //게시글 상세 페이지
    } else {
      redirect(ROUTES.COMMUNITY.BASE);
    }
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;PostForm type=&quot;register&quot; action={handleCreate} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 Next.js의 서버 액션이 &lt;code&gt;FormData&lt;/code&gt;를 기본적으로 사용하기 때문에, 백엔드가 &lt;code&gt;application/json&lt;/code&gt;만 파싱하도록 구성되어 있는 것보다 그대로 수신하도록 맞추는 것이 더 범용적으로 낫지 않을까 생각했습니다.&lt;br /&gt;하지만 해당 기능이 단순한 텍스트 기반의 게시글 작성 API였기에 더 가볍고 타입 안전성이 보장되는 &lt;code&gt;application/json&lt;/code&gt;의 사용이 적합하다고 판단했습니다. 추후 이미지 파일 업로드가 필요한 API에서는 백엔드에서 &lt;code&gt;multipart/form-data&lt;/code&gt;도 처리할 수 있도록 수정할 예정입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js의 폼 제출 기반 Server Actions는 클라이언트와 서버 간의 경계를 허물어 폼 처리를 매우 강력하게 만들어 주지만, 기본적으로 브라우저 네이티브인 &lt;code&gt;multipart/form-data&lt;/code&gt; 방식을 따릅니다. &lt;br /&gt;하지만 대다수의 기존 Node.js/Express API 서버는 &lt;code&gt;application/json&lt;/code&gt; 파싱 위주로 세팅되어 있습니다. &lt;br /&gt;서버 액션을 사용할 때는 연동하는 백엔드가 요구하는 Content-Type이 무엇인지 먼저 명확히 파악해야 함을 배웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트와 백엔드 두 작업을 동시에 진행하지 않고 한쪽을 구현 한 뒤 다른 쪽을 시간이 지난 뒤에 구현하다 보니 Content-Type과 같은 세부적인 사항들을 종종 놓치는 것 같습니다.&lt;br /&gt;문서화를 통해 항상 기록해두거나 구현 시작 전에 프론트엔드 - 백엔드 사이의 원활한 연결을 위해 먼저 구현된 쪽을 확인하여 다시 복기한 후 나머지 한쪽을 마저 구현하는 것이 좋을 것 같습니다!&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고:&lt;br /&gt;  &lt;a href=&quot;https://zibu-story.tistory.com/219&quot;&gt;https://zibu-story.tistory.com/219&lt;/a&gt;&lt;br /&gt;  &lt;a href=&quot;https://nextjs.org/docs/app/getting-started/mutating-data&quot;&gt;https://nextjs.org/docs/app/getting-started/mutating-data&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>개발/ ️ 트러블슈팅</category>
      <category>Content-Type</category>
      <category>formdata</category>
      <category>Next.js</category>
      <category>Server Actions</category>
      <category>서버 액션</category>
      <category>직렬화</category>
      <category>폼데이터</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/11</guid>
      <comments>https://eznnni.tistory.com/11#entry11comment</comments>
      <pubDate>Mon, 29 Jun 2026 10:32:54 +0900</pubDate>
    </item>
    <item>
      <title>TanStack Query - TIL</title>
      <link>https://eznnni.tistory.com/10</link>
      <description>&lt;blockquote data-path-to-node=&quot;2&quot; data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;TanStack Query&lt;/b&gt;를 공부한 후 남긴 기록을 담은 포스팅&lt;br /&gt;직접 기록한 내용을 GPT를 활용하여 마크다운으로 변환했다!&lt;/blockquote&gt;
&lt;h2 data-path-to-node=&quot;3&quot; data-ke-size=&quot;size26&quot;&gt;1. TanStack Query&amp;nbsp;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,0,0&quot;&gt;리액트 쿼리(React Query):&lt;/b&gt; 서버 상태 관리를 쉽게 하도록 도와주는 라이브러리&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,0&quot;&gt;서버 상태(Server State):&lt;/b&gt; 원본이 서버에 있고, 클라이언트가 복사본을 잠깐 빌려와서 보고 있는 모든 &lt;b&gt;비동기&lt;/b&gt; 처리 데이터&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size18&quot;&gt;  주요 기능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API 호출 시 로딩, 에러, 성공 상태 자동 트래킹 (isPending, error, data)&lt;/li&gt;
&lt;li&gt;API 응답 데이터 캐싱 및 재사용&lt;/li&gt;
&lt;li&gt;데이터베이스(DB) 데이터와 UI 데이터의 동기화 및 업데이트&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size26&quot;&gt;2. 데이터 조회: useQuery (Read)&lt;/h2&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size18&quot;&gt;  기본 규칙&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;10&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;queryKey&lt;/b&gt;는 반드시&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt; 배열 형태&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt;queryFn&lt;/b&gt;은 반드시&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt; Promise&lt;/b&gt;를 반환!&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,2,0&quot;&gt;Next.js App Router&lt;/b&gt; 환경에서는 Root Layout에서 &lt;b&gt;QueryClientProvider&lt;/b&gt;로 감싸주어야 전역에서 사용할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi91_u40ZyVAxUAAAAAHQAAAAAQpAQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre id=&quot;code_1782200003335&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const getTodos = async () =&amp;gt; {
  return [1, 2, 3];
};

const { data, isPending, error } = useQuery({
  queryKey: [&quot;todos&quot;], // QueryCache(전역 저장소) 내에 데이터를 저장하는 고유 주소
  queryFn: getTodos,
});​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;div&gt;useQuery()는 서버로부터 데이터를 fetching해올 때 사용한다.&lt;br /&gt;마운트 이후 queryFn을 실행하여 가져온 데이터를 queryKey에 저장한다.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; &amp;zwj;♂️ 궁금증과 그에대한 답 (Q&amp;amp;A)&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q1. queryKey는 왜 꼭 '배열'이어야 할까?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;상세한 주소 지정과 계층 구조 관리:&lt;/b&gt; 단순히 문자열 하나만 쓰면 todos 전체를 다루기 어렵지만, &lt;br /&gt;배열을 쓰면 ['todos', 'page', 1] 또는 ['todos', id]처럼 세부적인 조건을 순서대로 담아 QueryCache 안에서 고유한 주소로 삼을 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0&quot;&gt;v4부터의 강제 규칙:&lt;/b&gt; 내부적인 안정성과 예측 가능성을 위해 TanStack Query(v4 이후)부터는&lt;span style=&quot;background-color: #f6e199; color: #ffffff;&quot;&gt; &lt;b&gt;무조건 배열 형태로만&lt;/b&gt;&lt;/span&gt; 전달하도록 규칙이 고정되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q2. queryFn이 반드시 Promise를 반환해야 하는 이유는?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;17&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 상태 관리는 &lt;b&gt;비동기 요청에만&lt;/b&gt; 해당하기 때문&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,1,0&quot;&gt;비동기 상태 추적의 기반:&lt;/b&gt; useQuery의 핵심 역할은 데이터를 가져오는 과정에서 발생하는 &lt;br /&gt;&lt;b&gt;isPending(로딩), error(실패), data(성공)&lt;span style=&quot;background-color: #f6e199; color: #ffffff;&quot;&gt; 상태를 자동으로 추적&lt;/span&gt;&lt;/b&gt;하는 것&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,2,0&quot;&gt;약속된 신호:&lt;/b&gt; 자바스크립트에서 비동기 작업의 성공(resolve)과 실패(reject)를 처리하는 표준 객체가 바로 Promise useQuery는 이 Promise의 상태 변화를 감시하다가 UI를 그에 맞춰 실시간으로 업데이트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q3. 여기서 말하는 '마운트(Mount)'란 무슨 뜻?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,0,0&quot;&gt;화면에 컴포넌트가 처음 등장하는 순간:&lt;/b&gt; 리액트에서 마운트(Mount)는 컴포넌트가 처음 화면에 그려지며 &lt;br /&gt;메모리에 얹어지는 시점&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,1,0&quot;&gt;TanStack Query에서의 의미:&lt;/b&gt; * &lt;b data-index-in-node=&quot;24&quot; data-path-to-node=&quot;19,1,0&quot;&gt;최초 실행:&lt;/b&gt; 컴포넌트가 화면에 마운트되면&lt;br /&gt;useQuery는 queryFn을 실행하여 데이터를 가져오고 캐시에 저장
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,1,1,0,0&quot;&gt;stale 상태와 refetch:&lt;/b&gt; 쿼리는 기본적으로 받아온 데이터를 즉시 stale(신선하지 않은 상태)로 취급한다. 유저가 다른 페이지에 갔다가 다시 이 컴포넌트로 돌아왔을 때(= 재마운트), &lt;i data-index-in-node=&quot;110&quot; data-path-to-node=&quot;19,1,1,0,0&quot;&gt;&quot;어? 데이터가 stale하네? 새로 받아와야지!&quot;&lt;/i&gt; 하고 자동으로 queryFn을 다시 실행(refetchOnMount: true)하여 화면을 최신 데이터로 동기화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size26&quot;&gt;3. 데이터 조작: useMutation (Create, Update, Delete)&lt;/h2&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;서버의 데이터를 수정, 추가, 삭제할 때 사용&lt;br /&gt;CUD 작업 이후에는 UI와 DB의 싱크를 맞춰주는 &lt;b data-index-in-node=&quot;59&quot; data-path-to-node=&quot;22&quot;&gt;동기화(Synchronization)&lt;/b&gt; 작업이 필수적&lt;/p&gt;
&lt;p data-path-to-node=&quot;23&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;23&quot; data-ke-size=&quot;size18&quot;&gt;  특징 및 규칙&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;24&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mutationFn은 &lt;b&gt;Promise&lt;/b&gt;를 반환&lt;/li&gt;
&lt;li&gt;mutationFn은 &lt;b data-index-in-node=&quot;12&quot; data-path-to-node=&quot;24,1,0&quot;&gt;단 하나의 매개변수&lt;/b&gt;만 받을 수 있다. (여러 인자가 필요할 경우 객체 구조 분해 할당을 사용)&lt;/li&gt;
&lt;li&gt;변경 작업이 성공하면 기존 캐시를 stale 상태로 변환시켜 새 데이터를 다시 패칭(fetching)해와야 한다.&lt;br /&gt;이때 창고 관리자인 queryClient의&lt;b&gt; invalidateQueries()&lt;/b&gt; 메서드를 사용!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;25&quot; data-ke-size=&quot;size23&quot;&gt; ️ 구현 흐름 및 사용 방법&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;26&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,0,0&quot;&gt;RootLayout에 QueryCache(창고) 생성&lt;/b&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;const client = new QueryClient();
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,1,0&quot;&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,1,0&quot;&gt;사용 컴포넌트에서 관리자 호출 및 호출 처리&lt;/b&gt;
&lt;div&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const queryClient = useQueryClient();

const postTodoMutation = useMutation({
  mutationFn: postTodo,
  onSuccess: () =&amp;gt; {
    // 'todos' 키를 가진 캐시를 stale하게 만들어 데이터를 새로고침(refetch)하도록 유도
    queryClient.invalidateQueries({ queryKey: [&quot;todos&quot;] });
  },
  onError: (error) =&amp;gt; { console.error(error); },
  onSettled: () =&amp;gt; { /* 성공/실패 여부와 상관없이 항상 실행 */ }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,2,0&quot;&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,2,0&quot;&gt;이벤트 트리거 (버튼 클릭 등)&lt;/b&gt;
&lt;div&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;&amp;lt;button onClick={() =&amp;gt; {
  // mutate()는 설정한 mutationFn을 당장 실행하라는 명령어 역할을 합니다.
  postTodoMutation.mutate({
    id: Date.now(),
    title: 'TanStack Query 공부'
  });
}}&amp;gt;
  투두 추가
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-path-to-node=&quot;28&quot; data-ke-size=&quot;size26&quot;&gt;4. TanStack Query의 캐싱 전략과 Lifecycle&lt;/h2&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size18&quot;&gt;  Stale-While-Revalidate (SWR)&lt;/p&gt;
&lt;blockquote data-path-to-node=&quot;30&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-path-to-node=&quot;30,0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;30,0&quot;&gt;&quot;새로운 데이터를 가져오는 동안, 우선은 기존에 캐싱된 데이터를 보여준다.&quot;&lt;/i&gt; 라는 전략&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;31&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;31,0,0&quot;&gt;예시 (Cache-Control: max-age=1, stale-while-revalidate=59)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;31,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;31,0,1,0,0&quot;&gt;0~1초 사이 재요청:&lt;/b&gt; 서버 호출 없이 캐시 데이터를 바로 사용&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;31,0,1,1,0&quot;&gt;1~60초 사이 재요청:&lt;/b&gt; 일단 가지고 있던 캐시 데이터를 화면에 즉시 보여주고, 백그라운드에서 서버로부터 최신 데이터를 받아와 자연스럽게 교체&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-path-to-node=&quot;32&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-path-to-node=&quot;32,0&quot; data-ke-size=&quot;size16&quot;&gt;  &lt;b data-index-in-node=&quot;3&quot; data-path-to-node=&quot;32,0&quot;&gt;캐시 데이터는 전역 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;32,0&quot; data-ke-size=&quot;size16&quot;&gt;QueryClientProvider는 내부적으로 리액트의 Context API를 사용하므로, &lt;br /&gt;그 자식에 속한 모든 컴포넌트는 전역적으로 관리되는 캐시 데이터 창고에 접근할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-path-to-node=&quot;33&quot; data-ke-size=&quot;size23&quot;&gt;⚙️ 기본 설정 (Default Config)과 라이프사이클 항목들&lt;/h3&gt;
&lt;p data-path-to-node=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;하나의 쿼리 인스턴스(Query Key)는 다음과 같은 생명주기를 가집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;35&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;35,0,0&quot;&gt;staleTime: 0&lt;/b&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;35,0,0&quot;&gt;데이터를 패치해 오는 즉시 해당 데이터는 stale(신선하지 않은 상태)이 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;35,1,0&quot;&gt;refetchOnMount: true&lt;/b&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;35,1,0&quot;&gt;컴포넌트가 마운트될 때 데이터가 stale 상태라면 자동으로 refetch를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;35,2,0&quot;&gt;refetchOnWindowFocus: true&lt;/b&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;35,2,0&quot;&gt;브라우저 화면(창)을 다시 포커스할 때마다 자동으로 refetch를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;35,3,0&quot;&gt;refetchOnReconnect: true&lt;/b&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;35,3,0&quot;&gt;네트워크가 끊겼다가 다시 연결되었을 때 자동으로 refetch를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;35,4,0&quot;&gt;gcTime: 5분 (v5 전에는 cacheTime)&lt;/b&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;35,4,0&quot;&gt;컴포넌트가 언마운트되면 해당 쿼리는 inactive 상태가 됩니다. 이 상태로 5분이 지나면 가비지 컬렉터(GC)에 의해 캐시 메모리에서 완전히 지워집니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;35,5,0&quot;&gt;retry: 3&lt;/b&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;35,5,0&quot;&gt;queryFn 요청이 실패하더라도 즉시 에러를 내지 않고 3번까지 재시도합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;36&quot; data-ke-size=&quot;size16&quot;&gt;  &lt;b data-index-in-node=&quot;3&quot; data-path-to-node=&quot;36&quot;&gt;staleTime vs gcTime 핵심 요약&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;37&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;37,0,0&quot;&gt;staleTime:&lt;/b&gt; 얼마의 시간이 흐른 뒤에 데이터를 '신선하지 않은 것'으로 취급할 것인가? &lt;br /&gt;(staleTime &amp;gt; 0 이면 fresh, 0 이면 즉시 stale)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;37,1,0&quot;&gt;gcTime:&lt;/b&gt; 컴포넌트가 언마운트(inactive)된 후, 얼마의 시간 뒤에 메모리 창고에서 데이터를 완전히 삭제할 것인가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-path-to-node=&quot;39&quot; data-ke-size=&quot;size26&quot;&gt;5. 꼭 알아야 할 주요 옵션들 (Must-Know Options)&lt;/h2&gt;
&lt;h3 data-path-to-node=&quot;40&quot; data-ke-size=&quot;size23&quot;&gt;① enabled (조건부 실행)&lt;/h3&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi91_u40ZyVAxUAAAAAHQAAAAAQqAQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;useQuery({
  queryKey: [&quot;todos&quot;], 
  queryFn: getTodos,
  enabled: true // false로 지정하면 컴포넌트가 마운트되어도 자동 실행되지 않음
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;42&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;42,0,0&quot;&gt;동작:&lt;/b&gt; true일 때만 queryFn이 실행됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;42,1,0&quot;&gt;활용:&lt;/b&gt; 이벤트 발생 시에만 쿼리를 트리거하고 싶을 때, 혹은 순차적 쿼리(Dependent Queries)를 실행하고 싶을 때 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi91_u40ZyVAxUAAAAAHQAAAAAQqQQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 순차적 쿼리 예제: 유저 정보가 먼저 조회되어 유저 ID가 존재할 때만 프로젝트 목록 조회
const { data: user } = useQuery({
  queryKey: ['user', email],
  queryFn: getUserByEmail,
});

const userId = user?.id;

const { data: projects } = useQuery({
  queryKey: ['projects', userId],
  queryFn: getProjectsByUser,
  enabled: !!userId, // userId가 존재(true)할 때만 쿼리 가동
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-path-to-node=&quot;44&quot; data-ke-size=&quot;size23&quot;&gt;② select (데이터 가공)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;45&quot; data-ke-size=&quot;size16&quot;&gt;서버에서 받아온 원본 데이터를 컴포넌트에 전달하기 전, 필요한 형태로 정제/변형하여 리턴&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi91_u40ZyVAxUAAAAAHQAAAAAQqgQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function User() {
  const { data } = useQuery({
    queryKey: ['user'], 
    queryFn: fetchUser,
    select: (user) =&amp;gt; user.username, // 데이터 중에서 username만 쏙 골라냄
  });
  
  return &amp;lt;div&amp;gt;Username: {data}&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-path-to-node=&quot;48&quot; data-ke-size=&quot;size26&quot;&gt;6. 로딩 및 페칭 상태 비교 (isPending vs isLoading vs isFetching)&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;49&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.0465%;&quot;&gt;&lt;b&gt;속성명&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20.1163%;&quot;&gt;&lt;b&gt;핵심 정의&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 11.8604%;&quot;&gt;&lt;b&gt;캐시 데이터 존재 여부&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.7907%;&quot;&gt;&lt;b&gt;현재 API 요청 여부 (Fetching)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.5116%;&quot;&gt;&lt;b&gt;주요 활용 UI 예시&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 22.4419%;&quot;&gt;&lt;b&gt;비고&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.0465%;&quot;&gt;&lt;span data-path-to-node=&quot;49,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;49,1,0,0&quot;&gt;isPending&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20.1163%;&quot;&gt;&lt;span data-path-to-node=&quot;49,1,1,0&quot;&gt;데이터가 없고 최초 실행 대기 중인 상태&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 11.8604%;&quot;&gt;&lt;span data-path-to-node=&quot;49,1,2,0&quot;&gt;없음 &lt;br /&gt;(undefined)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.7907%;&quot;&gt;&lt;span data-path-to-node=&quot;49,1,3,0&quot;&gt;상관없음 &lt;br /&gt;(대기 중일 수도 있음)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.5116%;&quot;&gt;&lt;span data-path-to-node=&quot;49,1,4,0&quot;&gt;진입 시의 &lt;br /&gt;전반적인 예외 처리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 22.4419%;&quot;&gt;&lt;span data-path-to-node=&quot;49,1,5,0&quot;&gt;v5부터 status === 'loading'이 pending으로 명칭 변경&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.0465%;&quot;&gt;&lt;span data-path-to-node=&quot;49,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;49,2,0,0&quot;&gt;isLoading&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20.1163%;&quot;&gt;&lt;span data-path-to-node=&quot;49,2,1,0&quot;&gt;데이터가 전혀 없는 상태에서 최초로 서버에 요청을 보낸 상태&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 11.8604%;&quot;&gt;&lt;span data-path-to-node=&quot;49,2,2,0&quot;&gt;없음 &lt;br /&gt;(undefined)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.7907%;&quot;&gt;&lt;span data-path-to-node=&quot;49,2,3,0&quot;&gt;현재 요청 중 &lt;br /&gt;(Yes)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.5116%;&quot;&gt;&lt;span data-path-to-node=&quot;49,2,4,0&quot;&gt;최초 화면 진입 시 &lt;br /&gt;전체 스켈레톤/로딩 스피너&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 22.4419%;&quot;&gt;&lt;span data-path-to-node=&quot;49,2,5,0&quot;&gt;isPending &amp;amp;&amp;amp; isFetching 개념 (하드 로딩 감지)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.0465%;&quot;&gt;&lt;span data-path-to-node=&quot;49,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;49,3,0,0&quot;&gt;isFetching&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20.1163%;&quot;&gt;&lt;span data-path-to-node=&quot;49,3,1,0&quot;&gt;기존 데이터 유무 불문, 지금 이 순간 서버에 요청을 보낸 상태&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 11.8604%;&quot;&gt;&lt;span data-path-to-node=&quot;49,3,2,0&quot;&gt;상관없음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.7907%;&quot;&gt;&lt;span data-path-to-node=&quot;49,3,3,0&quot;&gt;현재 요청 중 &lt;br /&gt;(Yes)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.5116%;&quot;&gt;&lt;span data-path-to-node=&quot;49,3,4,0&quot;&gt;백그라운드 새로고침 시 &lt;br /&gt;화면 상단 &lt;br /&gt;조그만 인디케이터&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 22.4419%;&quot;&gt;&lt;span data-path-to-node=&quot;49,3,5,0&quot;&gt;초기 로딩과 원격 새로고침을 모두 포함하는 속성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-path-to-node=&quot;51&quot; data-ke-size=&quot;size26&quot;&gt;7. useQuery 에러 핸들링 패턴&lt;/h2&gt;
&lt;h3 data-path-to-node=&quot;52&quot; data-ke-size=&quot;size23&quot;&gt;Pattern A. 컴포넌트 내부에서 처리 (표준 방식)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;53&quot; data-ke-size=&quot;size16&quot;&gt;가장 보편적인 방법으로, 컴포넌트 내의 분기 처리를 통해 처리하거나 필요한 부가 작업(Side-effect)은 useEffect를 활용&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi91_u40ZyVAxUAAAAAHQAAAAAQrQQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function TodoList() {
  const { data: todos, error, isPending } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
  });

  // 렌더링과 상관없는 사이드 이펙트는 useEffect 내에서 처리 (예: 알림창)
  useEffect(() =&amp;gt; { 
    if (error) {
      alert(error.message);
    }
  }, [error]);

  if (isPending) return &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;;

  // Standard Error Handling UI
  if (error) return &amp;lt;div style={{ fontSize: 24 }}&amp;gt;에러가 발생했습니다: {error.message}&amp;lt;/div&amp;gt;;

  return (
    &amp;lt;div&amp;gt;
      {todos.data.map((todo) =&amp;gt; (
        &amp;lt;Todo key={todo.id} {...todo} /&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 data-path-to-node=&quot;55&quot; data-ke-size=&quot;size23&quot;&gt;Pattern B. QueryCache를 통한 전역 에러 핸들링 (Global Callback)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;56&quot; data-ke-size=&quot;size16&quot;&gt;특정 도메인이나 공통적인 에러 처리가 반복될 때 중앙 저장소(QueryCache) 레벨에서 일괄 관리하는 방식&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi91_u40ZyVAxUAAAAAHQAAAAAQrgQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 1. main.jsx (설정부)
const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error, query) =&amp;gt; {
      // meta 설정을 확인하여 특정 출처의 에러만 골라 처리 가능
      if (query.meta?.source === &quot;todos&quot;) {
        toast.error(`Something went wrong in TodoList: ${error.message}`);
      }
    }
  }),
});

// 2. src/components/TodoList.jsx (사용부)
function TodoList() {
  const { data: todos, isPending } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
    meta: { source: &quot;todos&quot; } // 전역 콜백에서 알아채도록 메타데이터 심어두기
  });

  if (isPending) return &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;;

  return (
    &amp;lt;div&amp;gt;
      {todos.data.map((todo) =&amp;gt; (
        &amp;lt;Todo key={todo.id} {...todo} /&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;blockquote data-path-to-node=&quot;58&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-path-to-node=&quot;58,0&quot; data-ke-size=&quot;size16&quot;&gt;☝ &lt;b data-index-in-node=&quot;2&quot; data-path-to-node=&quot;58,0&quot;&gt;에러 처리 가이드라인&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;58,0&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로 UI 제어가 수월한 &lt;b data-index-in-node=&quot;31&quot; data-path-to-node=&quot;58,0&quot;&gt;컴포넌트 내 처리&lt;/b&gt;를 기본으로 하되, 아래와 같은 명확한 공통 로직이 필요할 때만 &lt;b data-index-in-node=&quot;76&quot; data-path-to-node=&quot;58,0&quot;&gt;전역 콜백(QueryCache)&lt;/b&gt; 활용을 권장&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;58,1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전역 에러 로깅 처리 알고리즘 적용시&lt;/li&gt;
&lt;li&gt;Sentry 등 외부 모니터링 서비스로의 일괄 전송&lt;/li&gt;
&lt;li&gt;401 Unauthorized 에러 발생 시 공통 로그아웃 및 /login 페이지 리다이렉트 처리 코드 등&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;</description>
      <category>FE/Next</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/10</guid>
      <comments>https://eznnni.tistory.com/10#entry10comment</comments>
      <pubDate>Tue, 23 Jun 2026 16:56:18 +0900</pubDate>
    </item>
    <item>
      <title>렌더링 전략: SSG, ISR, SSR, CSR</title>
      <link>https://eznnni.tistory.com/9</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Next.js를 다루게 되면서 일반 리액트의 렌더링 방식과는 다른 Next.js의 렌더링 방식에 대해 접하게 되었다.&lt;br /&gt;오늘은 웹 페이지의 네 가지 렌더링 방식에 대해 알아보려 한다!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Next.js에서의 렌더링&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로 Next.js는 모든 페이지를 &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;특히&lt;span&gt;&amp;nbsp;&lt;/span&gt;빌드 시점에 생성되는 SSG와 요청 시점에 생성되는 SSR을 지원한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Next는 각 페이지별로 사용할 프리렌더링 방식을 선택할 수 있게 해 준다는 엄청난 장점이 있다.&lt;br /&gt;따라서 용도에 맞게 다른 렌더링 방식을 선택할 수 있다!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;*프리렌더링 - 빌드 시점에 HTML을 미리 만들어 두거나, 요청 시 HTML을 생성해 두는 것&lt;/b&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;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;다음의 네 방식은 모두 page router 버전의 공식 명칭으로, app router에서는 다른 용어로 사용된다고 한다!&lt;br /&gt; 각각 SSG -&amp;gt; Static Rendering, SSR -&amp;gt; Dynamic Rendering, ISR -&amp;gt; Revalidation이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dna/vaIf9/dJMcabEwsEv/AAAAAAAAAAAAAAAAAAAAAEs6Kwq-jeHFxTwvAR1gGQGpj6Vlkfg5Ffg4NkFa9IJk/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&amp;amp;expires=1782831599&amp;amp;allow_ip=&amp;amp;allow_referer=&amp;amp;signature=W5bQNsZx1IayKjE8G1YbxzLfUo4%3D&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  Static Site Generation(SSG)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js의 기본적인 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;빌드&lt;/b&gt; 시에 미리 페이지를 만들어놓고 사용자가 해당 라우트에 들어왔을 때 바로 화면에 보여줄 수 있는 HTML 파일을 클라이언트에 주어 화면에 그리는 방식으로, 바뀌지 않는 정적인 컴포넌트에 적합한 기본 렌더링 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드 시에 해당 컴포넌트를 100% 프리렌더링해놓고 &lt;b&gt;클라이언트 요청 시&lt;/b&gt; 제공한다.&lt;br /&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;  Incremental Static Rendering(ISR)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드 시 100% 프리렌더링을 해놓고 지정된 주기마다 서버에서 백그라운드로 페이지를 다시 생성하여 업데이트를 하는 렌더링 방식이다.&lt;/p&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;  Server Side Rendering(SSR)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자 요청마다&lt;/b&gt; 매번 서버 컴포넌트가 실행되며 완전한 HTML을 브라우저에 제공한다.&lt;br /&gt;브라우저가 자바스크립트를 다운로드하고 실행하기 전에도 화면이 빠르게 표시되며, 검색 엔진 크롤러가 페이지의 내용을 쉽게 읽을 수 있어 SEO에 유리하다. 다만, 페이지를 이동할 때마다 서버에 새로운 HTML을 요청해야 하기에 트래픽이 몰릴 경우 서버 부하가 커질 수 있다.&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;  Client Side Rendering(CSR)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React의 기본 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React를 사용한 CSR에서 브라우저는 최소한의 HTML 페이지와 해당 페이지에 필요한 JS를 다운로드한다.&lt;br /&gt;다운로드된 JS는 DOM을 업데이트하고 페이지를 렌더링 하는 데 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지가 처음 로드된 후에 동일한 웹사이트의 다른 페이지로 이동하는 속도가 일반적으로 빠르다.&lt;br /&gt;필요한 데이터만 가져오고, 전체 페이지를 고치지 않고도 페이지의 일부를 다시 렌더링 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, SEO에 영향을 미칠 수 있다. 일부 검색 엔진 크롤러는 JS를 실행하지 않기 때문이다.&lt;br /&gt;또한 인터넷 연결 속도가 느리거나 기기 성능이 저하된 사용자는 모든 JS가 로드되고 실행된 후까지 기다려야 전체 페이지를 볼 수 있기에 성능 문제가 발생할 수 있다.&lt;br /&gt;따라서 Next.js는 애플리케이션의 각 페이지 요구 사항에 따라 CSR, SSR 및 SSG 하이브리드 방식을 권장한다.&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;  Hydration&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR과 SSR의 차이는 바로 하이드레이션 과정의 유무이다. 순수 CSR 방식에는 하이드레이션이 존재하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저가 JS를 이용해 처음부터 DOM을 직접 생성하기 때문이다.&lt;br /&gt;서버에서 렌더링 된 정적 HTML이 클라이언트로 전달된 후, 자바스크립트가 결합하여 웹 페이지가 사용자와 상호작용할 수 있는 상태가 되는 과정을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 측에서 렌더링된 SSR이나 SSG방식은 초기 로딩 시 HTML 형태만 전달받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 화면에 내용은 보이지만, 버튼을 클릭하거나 폼을 입력하는 등의 상호작용은 즉시 동작하지 않는 상태이다.&lt;br /&gt;이때 브라우저가 필요한 JS 번들을 다운로드하고 실행하면 정적인 페이지에 동적인 기능을 입히게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  어떤 방식을 택해야 할까?&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 110px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 7.67442%; height: 19px;&quot;&gt;렌더링 방식&lt;/td&gt;
&lt;td style=&quot;width: 15.407%; height: 19px;&quot;&gt;추천 사용 사례&lt;/td&gt;
&lt;td style=&quot;width: 26.9186%;&quot;&gt;이유&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 38px;&quot;&gt;
&lt;td style=&quot;width: 7.67442%; height: 38px;&quot;&gt;SSG&lt;/td&gt;
&lt;td style=&quot;width: 15.407%; height: 38px;&quot;&gt;마케팅 페이지, 블로그&lt;/td&gt;
&lt;td style=&quot;width: 26.9186%;&quot;&gt;데이터가 자주 변하지 않으므로, &lt;br /&gt;빌드 시 생성한 정적 파일을 배포하여 빠르게 로딩 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 7.67442%; height: 19px;&quot;&gt;ISR&lt;/td&gt;
&lt;td style=&quot;width: 15.407%; height: 19px;&quot;&gt;커머스 상품 목록, 뉴스&lt;/td&gt;
&lt;td style=&quot;width: 26.9186%;&quot;&gt;데이터가 주기적으로 변경되지만, &lt;br /&gt;매번 새로 빌드하는 것이 비효율적이기에 &lt;br /&gt;백그라운드에서 정적 페이지를 재생성하여 성능과 최신성을 모두 확보&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 7.67442%; height: 17px;&quot;&gt;SSR&lt;/td&gt;
&lt;td style=&quot;width: 15.407%; height: 17px;&quot;&gt;사용자 개인화 페이지, 대시보드&lt;/td&gt;
&lt;td style=&quot;width: 26.9186%;&quot;&gt;사용자마다 다른 데이터가 필요하여 &lt;br /&gt;매 요청마다 서버에서 최신 상태를 반영한 HTML을 즉시 생성해야하기에&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 7.67442%; height: 17px;&quot;&gt;CSR&lt;/td&gt;
&lt;td style=&quot;width: 15.407%; height: 17px;&quot;&gt;관리자 페이지, 개인 대시보드&lt;/td&gt;
&lt;td style=&quot;width: 26.9186%;&quot;&gt;화면 내 인터렉션이 매우 많고, &lt;br /&gt;이미 로그인된 사용자가 사용하는 페이지이기에 &lt;br /&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;출처:&lt;br /&gt;&lt;/span&gt;&lt;a href=&quot;https://nextjs-ko.org/docs/pages/building-your-application/Rendering&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Next.js - Rendering&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://nextjs.org/docs/pages/building-your-application/rendering/client-side-rendering&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Next.js - CSR&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>FE/Next</category>
      <category>CSR</category>
      <category>Hydration</category>
      <category>ISR</category>
      <category>Next.js</category>
      <category>PreRendering</category>
      <category>react</category>
      <category>Rendering</category>
      <category>SSG</category>
      <category>SSR</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/9</guid>
      <comments>https://eznnni.tistory.com/9#entry9comment</comments>
      <pubDate>Fri, 12 Jun 2026 17:18:09 +0900</pubDate>
    </item>
    <item>
      <title>React의 Component</title>
      <link>https://eznnni.tistory.com/8</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 JavaScript에서 React로 넘어가면서 느낀 두드러진 점 중 하나는 &lt;br /&gt;React엔 Component란 개념이 있다는 것이다.&lt;br /&gt;오늘은 그 컴포넌트에 대해 알아보려 한다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Component&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트는 독립적이고 재사용 가능한 코드 조각으로, &lt;br /&gt;js의 함수와 동일한 목적을 수행하지만 독립적으로 작용하며 &lt;b&gt;JSX&lt;/b&gt;를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;b&gt;JSX -&lt;/b&gt; JavaScript 안에서 HTML처럼 보이게 쓴 문법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;HTML 요소를 반환하는 &lt;b&gt;함수&lt;/b&gt;로 볼 수 있다.&lt;br /&gt;컴포넌트는 일종의 부품과 같다. 하나의 부품이 용도가 동일하다면 이곳저곳에 재사용될 수 있는 것처럼 컴포넌트 또한 그러하다.&lt;br /&gt;이처럼 컴포넌트는 여러 요소에 재사용되는 것을 핵심으로 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 사용하면 UI를 독립적이고 재사용 가능한 부분으로 나누고 각 부분을 개별적으로 고려할 수도 있다.&lt;br /&gt;재사용, 유지보수, 가독성의 측면에서 매우 유용하다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼, 카드, 네이비게이션 바, 모달 등 범용적으로 사용할 수 있는 UI를 컴포넌트로 만들면 재사용하기 편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  props&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편, React에선 &lt;code&gt;props&lt;/code&gt;란 개념이 존재한다.&lt;br /&gt;컴포넌트는 js의 함수처럼 &lt;code&gt;props&lt;/code&gt;란 인수를 입력으로 받아 화면에 보여줄 React 요소를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  함수 컴포넌트에서는 매개변수로 받고, 클래스 컴포넌트에서는 `this.props` 로 접근한다.&lt;br /&gt;&lt;b&gt;부모&lt;/b&gt;가 &lt;u&gt;자식에게&lt;/u&gt; 전달해야 할 속성이 있을 경우 &lt;code&gt;props&lt;/code&gt;를 통해 전달 한다.&lt;br /&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;버튼, 카드, 모달 등의 컴포넌트 내부에 내용을 props로 전달할 수 있다.&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;p data-ke-size=&quot;size16&quot;&gt;이러한 컴포넌트는 클래스 컴포넌트와 함수 컴포넌트 두 가지 종류가 존재한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  함수 컴포넌트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 컴포넌트는 다음과 같이 정의한다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function Child() {
    return (
      &amp;lt;h2&amp;gt; Hi, I am a child &amp;lt;/h2&amp;gt;
    );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 만든 이 함수 컴포넌트는 부모 컴포넌트 안에서 사용된다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function Parent() {
    return (
        &amp;lt;&amp;gt;
              &amp;lt;Child /&amp;gt;
          &amp;lt;/&amp;gt;
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 부모로부터 자식이 전달받아야 할 데이터가 존재할 경우 &lt;code&gt;props&lt;/code&gt;를 통해 자식으로 전달할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function Parent() {
    return (
        &amp;lt;&amp;gt;
              &amp;lt;Child color=&quot;red&quot; /&amp;gt;
          &amp;lt;/&amp;gt;
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 코드 재사용을 핵심으로 하기에 재사용성과 유지보수 측면에서 별도 파일로 분리해서 관리한다.&lt;br /&gt; &lt;code&gt;Child.jsx&lt;/code&gt;와 같이 대문자로 시작하는 &lt;b&gt;PascalCase&lt;/b&gt;를 사용하는 것이 관례이다.&lt;br /&gt;소문자로 시작하면 일반 HTML 태그로 인식될 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  클래스 컴포넌트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 컴포넌트는 js의 클래스로 정의된 React 컴포넌트의 기본 클래스이다.&lt;br /&gt;React 공식문서와 W3Schools에 의하면 클래스 컴포넌트 대신 &lt;b&gt;hook과 함께 함수 컴포넌트를 사용하는 것&lt;/b&gt;이 권장된다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 컴포넌트는 다음과 같은 방식으로 정의한다.&lt;br /&gt;내장 `Component` 클래스를 확장하고, 메서드를 정의해야 한다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import { Component } from &quot;react&quot;;

class Child extends Component {
    render() {
        return &amp;lt;h1&amp;gt;{this.props.color}&amp;lt;/h1&amp;gt;;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 props를 통해 속성을 전달한다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;class Child extends Component {
    render() {
        return &amp;lt;h1&amp;gt;{this.props.color}&amp;lt;/h1&amp;gt;;
    }
}

&amp;lt;Child color=&quot;red&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  함수 컴포넌트 VS 클래스 컴포넌트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 컴포넌트와 클래스 컴포넌트엔 차이점이 존재한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 143px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style3&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;함수 컴포넌트&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;클래스 컴포넌트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;정의 방식&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;JavaScript의 함수&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;ES6 class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;렌더링&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;JSX를 직접 반환&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;`render()` 에서 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;props 접근&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;매개변수로 받음&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;`this.props` 로 접근&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 38px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 38px;&quot;&gt;생명주기 / 사이드 이펙트 처리&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 38px;&quot;&gt;`useEffect` 등 hooks로 처리&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 38px;&quot;&gt;`componentDidMount`,&lt;br /&gt;`componentDidUpdate` 등을 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;현재 권장 상황&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;권장&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&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;과거에는 클래스 컴포넌트가 많이 사용되었으나, 지금은 함수 컴포넌트와 Hooks의 사용이 표준에 가깝다.&lt;br /&gt;둘 다 가능하지만, 현재는 함수 컴포넌트가 권장된다고 생각하면 될 것 같다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://www.w3schools.com/React/react_components.asp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;w3school - React Component&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://react.dev/reference/react/Component&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;React - Component&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>FE/React</category>
      <category>component</category>
      <category>Javascript</category>
      <category>Props</category>
      <category>react</category>
      <category>클래스 컴포넌트</category>
      <category>함수 컴포넌트</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/8</guid>
      <comments>https://eznnni.tistory.com/8#entry8comment</comments>
      <pubDate>Tue, 2 Jun 2026 18:43:43 +0900</pubDate>
    </item>
    <item>
      <title>[Git&amp;amp;Github] Branch Merge 방법</title>
      <link>https://eznnni.tistory.com/7</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Git Merge 전략&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Merge는 두 브랜치를 결합하는 작업이다.&lt;br /&gt;Git은 두 개 또는 그 이상의 커밋 포인터를 받아 공통 기준 커밋을 찾으려고 시도한다.&lt;br /&gt;Git은 기준 커밋을 찾는 여러 가지 방법을 가지고 있는데, 이러한 방법들을 &lt;b&gt;병합 전략&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격적으로 전략에 대해 얘기하기 전에 알아둘 것이 있다. 바로 &lt;code&gt;HEAD&lt;/code&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; HEAD&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HEAD란 현재 작업중인 브랜치의 최신 커밋을 가리키는 포인터이다.&lt;br /&gt;&lt;code&gt;git commit&lt;/code&gt;을 하면, 새 커밋이 생성되고 HEAD도 자동으로 새 커밋을 가리킨다.&lt;br /&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&gt;&lt;img src=&quot;https://velog.velcdn.com/images/eznnni/post/27466df2-5c77-4d2b-bbcd-7cc1e2459942/image.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Fast-Forward Merge&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 단순한 합치기 방식이다.&lt;br /&gt;HEAD 포인터가 Merge 과정 없이 그냥 최신 커밋으로 이동한다.&lt;br /&gt;&lt;code&gt;master&lt;/code&gt;에서 &lt;code&gt;feature&lt;/code&gt;를 분기한 후, &lt;code&gt;master&lt;/code&gt;에는 &lt;b&gt;아무런 커밋이 쌓이지 않은 상태&lt;/b&gt;에서 &lt;code&gt;master&lt;/code&gt; 브랜치의 HEAD 포인터를 그냥 &lt;code&gt;feature&lt;/code&gt;의 최신 commit으로 옮겨버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Merge commit&lt;/code&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&gt;&lt;img src=&quot;https://velog.velcdn.com/images/eznnni/post/8e1f7d44-664c-4692-bc05-b972e8149b41/image.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;feature 브랜치를 생성하여 이동&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git checkout -b &amp;lt;feature/...&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;feature 브랜치에 커밋 생성&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git commit -m &quot;feat: 기능1 구현&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;master 브랜치에서 merge&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git checkout master
$ git merge &amp;lt;feature/...&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  3-Way Merge&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 브랜치가 서로 다른 길로 빠질 때 사용하는 merge 방식이다.&lt;br /&gt;&lt;code&gt;master&lt;/code&gt;에서 &lt;code&gt;feature&lt;/code&gt;을 분기한 후, &lt;code&gt;master&lt;/code&gt;에도 새로운 커밋이 생기고 &lt;code&gt;feature&lt;/code&gt;에도 새로운 커밋이 생긴 상태에서 &quot;&lt;code&gt;master&lt;/code&gt;의 최신 커밋&quot;, &quot;&lt;code&gt;feature&lt;/code&gt;의 최신 커밋&quot;, &quot;공통 조상(두 브랜치가 갈라지기 전 마지막 지점)&quot;을 비교하여 합친다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 줄기의 역사를 합친 새로운 &lt;code&gt;Merge commit&lt;/code&gt;이 생성된다. 이 merge commit은 &lt;code&gt;master&lt;/code&gt;와 &lt;code&gt;feature&lt;/code&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&gt;&lt;img src=&quot;https://velog.velcdn.com/images/eznnni/post/17a75861-873d-41bc-9a6d-871686d300b9/image.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;feature 브랜치를 생성하고 작업&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git checkout -b &amp;lt;feature/...&amp;gt;
$ git commit -m &quot;feat: 기능2 구현&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;그 사이에 master에 커밋 발생&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git checkout master
$ git commit -m &quot;...&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;갈라진 두 브랜치를 merge&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git merge &amp;lt;feature/...&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Squash and Merge&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;feature&lt;/code&gt; 브랜치에서 발생한 여러 개의 커밋을 하나의 커밋으로 합쳐 &lt;code&gt;master&lt;/code&gt; 브랜치에 추가하는 방식이다. &lt;code&gt;feature&lt;/code&gt; 브랜치의 지저분한 로그를 지운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;feature&lt;/code&gt;의 모든 커밋이 하나로 압축되어 &lt;code&gt;master&lt;/code&gt;에 새로운 커밋으로 붙는다. 해당 시점에서 사용자가 커밋하면, &lt;code&gt;Merge commit&lt;/code&gt;도 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://velog.velcdn.com/images/eznnni/post/2b1ad1d9-ec1a-409c-a1e3-d90be5e12c97/image.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;feature에서 여러 번 커밋&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git checkout -b &amp;lt;feature/1...&amp;gt;
$ git commit -m &quot;...1&quot;
$ git commit -m &quot;...2&quot;
$ git commit -m &quot;...3&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;master로 merge할 때 squash 옵션 사용&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;$ git checkout master
$ git merge --squash &amp;lt;feature/1...&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  위에서의 커밋들을 모두 하나로 합쳐서 staging area에 올려놓는다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;3&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;합쳐진 변경사항을 하나의 커밋으로 기록&amp;nbsp;&lt;/li&gt;
&lt;li class=&quot;elixir&quot;&gt;&lt;code&gt;$ git commit -m &quot;...&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  병합 내용이 staging area에 오른 후 커밋 명령을 내리면, 부모가 &lt;code&gt;master&lt;/code&gt;인 최신 커밋이 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  squash 옵션을 사용하면 애초에 master 한 줄기만 있었던 것처럼 나타낼 수 있으며, 자잘한 feature의 히스토리는 날라가고 딱 master와 비교하여 달라진 코드 뭉치만 가져온다는 의미이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://www.atlassian.com/git/tutorials/using-branches/merge-strategy&quot;&gt;[ Git 병합 전략 옵션 및 예시]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/7</guid>
      <comments>https://eznnni.tistory.com/7#entry7comment</comments>
      <pubDate>Mon, 1 Jun 2026 15:45:22 +0900</pubDate>
    </item>
    <item>
      <title>[Git] Git Flow</title>
      <link>https://eznnni.tistory.com/6</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vincent Driessen의 a-successful-git-branching-model 을 정리한 글입니다.&lt;br /&gt; &lt;a href=&quot;https://nvie.com/posts/a-successful-git-branching-model/&quot;&gt;a-successful-git-branching-model&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Git Flow 전략엔 5가지 핵심 브랜치가 존재한다!&lt;br /&gt;이는 각각 master, develop, feature, release, hotfix이다.&lt;br /&gt;각 브랜치의 역할과 흐름을 알아보자!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://velog.velcdn.com/images/eznnni/post/3db9d8aa-a44c-4ada-9b2a-00ff20b2803c/image.png&quot; /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; 메인 브랜치&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중앙 저장소에 무기한 보존되는 두 개의 핵심 브랜치이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;master 브랜치 - 제품 출시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 중앙 저장소에 무기한 보존되는 주요 브랜치이며, 실제 사용 가능한 상태를 반영하는 메인 브랜치이다. 변경 사항이 merge 될 때마다 새로운 버전 릴리즈는 &lt;code&gt;master&lt;/code&gt; 브랜치의 것이다.&lt;br /&gt;실제 사용자에게 배포되는 가장 &lt;b&gt;안정적인&lt;/b&gt; 상태를 유지한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;develop 브랜치 - 다음 릴리즈 준비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: &lt;code&gt;master&lt;/code&gt; 브랜치처럼 중앙 저장소에 무기한 보존되는 주요 브랜치로, 다음 릴리즈를 위한 최신 개발 변경 사항이 항상 반영되어 있다. &lt;code&gt;통합 브랜치&lt;/code&gt;라고도 불린다. &lt;code&gt;develop&lt;/code&gt; 브랜치의 소스 코드가 안정화되어 릴리즈 준비가 완료되면, 모든 변경 사항을 &lt;code&gt;master&lt;/code&gt; 브랜치로 병합한 다음에 릴리즈 번호(태그)를 지정해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; 보조 브랜치&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 브랜치인 &lt;code&gt;master&lt;/code&gt;, &lt;code&gt;develop&lt;/code&gt; 브랜치 외에도 팀 구성원 간의 병렬 개발을 지원하고 기능 추적을 용이하게 하는 등 다양한 보조 브랜치를 사용한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;feature 브랜치 - 새 기능 개발&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 향후 릴리즈될 버전이나 먼 미래의 버전을 위한 새 기능을 개발하는 데 사용한다.&lt;br /&gt;&lt;code&gt;develop&lt;/code&gt; 브랜치에서 분기될 수 있으며, 다시 &lt;code&gt;develop&lt;/code&gt; 브랜치로 병합해야 하는 브랜치로,&lt;br /&gt;&lt;code&gt;master&lt;/code&gt;, &lt;code&gt;develop&lt;/code&gt;, &lt;code&gt;release&lt;/code&gt;, &lt;code&gt;hotfix&lt;/code&gt;를 제외한 모든 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;release 브랜치 - 새 출시 버전 준비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 새로운 프로덕션 릴리즈를 준비하는 브랜치이다. &lt;code&gt;release&lt;/code&gt; 브랜치를 통해 최종 단계에서 세부적인 사항을 확인하고, 사소한 버그를 수정하거나 릴리즈에 필요한 메타데이터를 준비할 수 있다.&lt;br /&gt;이러한 모든 작업을 &lt;code&gt;release&lt;/code&gt; 브랜치에서 완료하면, &lt;code&gt;develop&lt;/code&gt; 브랜치는 다음 주요 릴리즈에 포함될 새로운 기능을 추가할 준비가 된다.&lt;br /&gt;&lt;code&gt;develop&lt;/code&gt; 브랜치에서 분기될 수 있으며, 다시 &lt;code&gt;develop&lt;/code&gt; 그리고 &lt;code&gt;master&lt;/code&gt; 브랜치로 병합해야하는 브랜치로, release-*의 형식으로 명명된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;hotfix 브랜치 - 출시 버전에서의 버그 수정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 계획되지 않은 새로운 프로덕션 릴리즈를 준비하기 위한 브랜치이다. 실제 운영 중인 프로덕션 버전에서 바람직하지 않은 상태가 발생했을 때 즉시 조치를 취해야 한 경우에 사용한다. 심각한 버그를 즉시 해결해야 할 경우, 해당 프로덕션 버전을 나타내는 &lt;code&gt;master&lt;/code&gt; 브랜치의 태그에서 분기한다. 팀 구성원들이 &lt;code&gt;develop&lt;/code&gt; 브랜치에서 작업을 계속하는 동안 다른 사람이 신속하게 운영 환경 개선을 준비 가능하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; 요약&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;master&lt;/code&gt; 브랜치에서 &lt;code&gt;develop&lt;/code&gt; 브랜치를 분기한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;develop&lt;/code&gt; 브랜치에서 상시로 버그를 수정한 커밋이 추가된다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feature&lt;/code&gt; 브랜치에서 새 기능을 개발하고, 기능 추가 작업이 완료되었다면 &lt;code&gt;develop&lt;/code&gt; 브랜치로 merge 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;develop&lt;/code&gt; 브랜치에 새로이 추가될 기능이 merge 되었다면 QA를 위해 &lt;code&gt;release&lt;/code&gt; 브랜치를 분기한다.&lt;/li&gt;
&lt;li&gt;QA를 진행하며 발생된 버그들은 &lt;code&gt;release&lt;/code&gt; 브랜치에서 수정한다.&lt;/li&gt;
&lt;li&gt;QA를 무사히 통과했다면 &lt;code&gt;release&lt;/code&gt; 브랜치를 &lt;code&gt;master&lt;/code&gt; &amp;amp; &lt;code&gt;develop&lt;/code&gt; 브랜치로 merge 한다.&lt;/li&gt;
&lt;li&gt;마지막으로 출시된 &lt;code&gt;master&lt;/code&gt; 브랜치에 버전 태그를 추가한다.&lt;/li&gt;
&lt;li&gt;새 버전을 출시하고 운영 중에 급한 버그가 발견되면 &lt;code&gt;master&lt;/code&gt;에서 &lt;code&gt;hotfix&lt;/code&gt;를 분기해 수정 후 &lt;code&gt;master&lt;/code&gt;와 &lt;code&gt;develop&lt;/code&gt; 모두에 병합한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://nvie.com/posts/a-successful-git-branching-model/#why-git&quot;&gt;[a-successful-git-branching-model]&lt;/a&gt;, &lt;br /&gt;&lt;a href=&quot;https://techblog.woowahan.com/2553/&quot;&gt;[우아한 기술블로그 - 우린 Git-flow를 사용하고 있어요]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>WEB</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/6</guid>
      <comments>https://eznnni.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 1 Jun 2026 15:40:49 +0900</pubDate>
    </item>
    <item>
      <title>[Git&amp;amp;Github] Git Branch와 Merge</title>
      <link>https://eznnni.tistory.com/5</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음 협업을 진행할 때 Git은 매우 두려운 존재이다.&lt;br /&gt;낯설기도 하고, 내 잘못된 선택으로 프로젝트에 영향을 미칠 수도 있다는 걱정으로 &lt;br /&gt;실수하지 않도록 옳은 Branch &amp;amp; Merge 사용법을 알아두어야 할 필요가 있다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; Branch&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Git에는 Branch라는 개념이 있다. 개발을 하다 보면 코드를 여러 개로 복사해야 하는 일이 자주 생긴다. 기존의 모든 코드를 복사하고 나서 원래 코드에는 영향을 미치지 않고, 독립적으로 개발을 진행할 때 Branch를 사용한다!&lt;br /&gt;여러 브랜치를 만들어 개별적으로 작업하고 나중에 Merge 하는 방법이 권장된다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; Merge&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립적인 갈래에서 개발을 진행하다가&lt;br /&gt;변경사항을 원래의 갈래에 적용하고 싶을 때 Merge를 통해 병합한다!&lt;br /&gt;작업 내용을 합치는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립적인 브랜치에서 각자 의도와 목표에 맞는 개발을 진행하고 하나의 main branch에 merge 하는 것. 이 흐름은 Git에서의 이상적인 협업 방법이라고 말할 수 있다!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; Branch와 Merge의 사용&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격적으로 Git에서 Branch와 Merge를 사용하는 기본적인 커맨드를 알아보자&lt;br /&gt;*기본 디렉터리를 Git 저장소로 만드는 방법을 다룬다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. git init&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Git으로 버전관리를 하고 싶은 경우 우선 프로젝트의 디렉터리로 이동한다.&lt;br /&gt;그리고 터미널에서 &lt;code&gt;git init&lt;/code&gt;을 실행한다.&lt;br /&gt;이 명령을 통해 내 디렉터리에 코드 변경을 추적하는 감시자를 세우는 것이다!&lt;/p&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;$ git init&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. git add&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경사항이 생길 경우, 이 사항을 저장소에 기록해야 한다.&lt;br /&gt;이를 위해선 Git에게 이 사항을 알아두어라 = &lt;b&gt;staged&lt;/b&gt; 상태로 만들어야 한다!&lt;br /&gt;  unstaged 상태의 파일은 커밋되지 않는다.&lt;br /&gt;&lt;code&gt;git add (파일명)&lt;/code&gt; 또는 &lt;code&gt;git add. 를&lt;/code&gt; 사용한다. 후자는 현재까지 모든 변경사항이 존재하는 파일을 다 staging area로 올리는 것이다!&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;$ git add .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. git commit&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정한 것을 커밋하기 위해, 기록하기 위해. 앞의 단계에서 파일을 staged 상태로 만들었다.&lt;br /&gt;&lt;code&gt;git commit&lt;/code&gt; 명령어를 사용하여 커밋한다. 이때 해당 명령어를 입력하면 편집기가 실행되고, 편집기를 통해 어떤 변경사항이 존재하는지 기록할 수 있다.&lt;br /&gt;  &lt;code&gt;git commit -m &quot;(type): 메시지&quot;를&lt;/code&gt; 통해 편집기 없이도 커밋 메시지 작성이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;margin: 0 auto; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/2fb778f1-c23a-42e6-8369-d4930d4f392f/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋을 한 후 아직 아무것도 수정하지 않은 상태에서 어떤 파일을 수정하면, Git은 그 파일을 &lt;b&gt;modified&lt;/b&gt; 상태로 인식한다. 커밋을 하기 위해 앞선 과정처럼 수정한 파일을 &lt;b&gt;staged&lt;/b&gt; 상태로 만들고, &lt;b&gt;staged&lt;/b&gt; 상태의 파일을 커밋하는 라이프사이클을 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/b9583e44-0471-4856-8770-9f14080c4a5b/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처:  &lt;a href=&quot;https://git-scm.com/book/ko/v2/Git%EC%9D%98-%EA%B8%B0%EC%B4%88-%EC%88%98%EC%A0%95%ED%95%98%EA%B3%A0-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0&quot;&gt;Git&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격적으로 온라인에서 다른 사람들과 협업하기 위해서 사용하는 플랫폼이 있는데,&lt;br /&gt;바로 Github이다! Github을 통해 온라인 백업, 협업이 가능하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. git push&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 코드를 github에 반영하기 위해 사용하는 명령어이다!&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;$ git remote add origin &amp;lt;내 github 주소&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 통해 내 github 주소 (레포지터리 주소)를 연결해 주고,&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;$ git push -u origin &amp;lt;브랜치명&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 통해 업로드가 가능하다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  기본 브랜치명이 &lt;code&gt;master&lt;/code&gt;임을 확인할 수 있는데, 그보다는&amp;nbsp;&lt;code&gt;main&lt;/code&gt;으로 바꿔 사용하곤 한다.&lt;br /&gt;과거 노예제도를 연상시키기 때문이라고 한다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;$ git branch -M main&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. git checkout / switch&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 갈래에서 모든 개발을 진행하는 것은 git에서 권장하는 방식이 아니며, 협업과 버전관리에도 도움 되는 방식이 아니다. 새로 branch를 만들고, 이동하여 개발을 해야 한다!&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;$ git branch &amp;lt;브랜치명&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 통해 브랜치를 새로 만들 수 있다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;$ git checkout &amp;lt;브랜치명&amp;gt;
$ git switch &amp;lt;브랜치명&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 통해 앞서 만든 브랜치로 이동이 가능하다.&lt;br /&gt;  그리고 브랜치를 만들면서 바로 이동하는 엄청난 shortcut이 존재한다!&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;$ git checkout -b &amp;lt;브랜치명&amp;gt;
$ git switch -c &amp;lt;브랜치명&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. Pull Request&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립적인 갈래에서 개발을 완료했다면, 이제 남은 것은 &lt;b&gt;Merge&lt;/b&gt;이다. 하지만, 로컬에서 &lt;code&gt;git merge&lt;/code&gt;를 하는 대신 Github를 통해 병합하는 방법이 있다.&lt;br /&gt;그게 바로 &lt;b&gt;PR, Pull Request&lt;/b&gt;이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PR을 사용하면 팀원들과의 코드를 공유하고 리뷰할 수 있으며,&lt;br /&gt;기능 단위의 작업을 기록하고 관리하는 등의 장점이 존재한다!&lt;br /&gt;잘못된 코드를 리뷰를 거치지 않은 채 main에 병합해 버린다면,,, 매서운 눈초리를 받을 수 있다ㅎㅎ&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/715ae58f-60b0-42c4-805c-43d83c0b3e2e/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처: &lt;a href=&quot;https://docs.github.com/ko/enterprise-cloud@latest/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request&quot;&gt;GitHub문서&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;code&gt;github의 내 원격 브랜치에 업로드된 변경 사항&lt;/code&gt;을 &lt;b&gt;PR&lt;/b&gt;을 통해 main 브랜치에 merge 요청할 수 있다.&lt;br /&gt;만약 팀원들이 내 PR 요청을 보고 코드 리뷰를 마친 뒤, 병합하는 데에 문제가 없다고 판단하면 승인해 줄 수 있고 이후에 본인이 &lt;code&gt;Merge Pull Request&lt;/code&gt; 버튼을 눌러 병합하면 된다!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; 유용한 Git 커맨드&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 유용한 Git 명령어를 몇 가지 소개해보려고 한다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;7. git restore&lt;/h4&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;$ git restore --staged &amp;lt;파일명&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어를 통해 staged 상태인 파일을 unstaged 상태로 만들 수 있다.&lt;br /&gt;이렇게 해도 내 작업 디렉터리에 변경사항은 저장되어 있다.&lt;br /&gt;  커밋 단위를 분리하고 싶거나 원격 저장소에 올리고 싶지 않은 내용까지 staging area에 올라갔을 때 등의 상황에서 사용하면 좋다!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;8. git status&lt;/h4&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;$ git status&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git이 현재 인식하고 있는 프로젝트 관련 내용을 출력한다.&lt;br /&gt;현재 상태를 파악할 때 유용하다.&lt;br /&gt;  항상 내가 어느 branch에 있는지 확인하는 습관을 들일 것을 추천한다!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;9. git log&lt;/h4&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;$ git log&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어를 통해 커밋 히스토리를 볼 수 있다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;$ git log --pretty=oneline&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어는 한 줄로 커밋 히스토리를 깔끔하게 출력해 준다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;10. git tag&lt;/h4&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;$ git tag &amp;lt;태그명&amp;gt; &amp;lt;커밋아이디&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어는 일반 커밋과는 다르게 더 중요한 내용을 담고 있는 커밋에 태그를 지정할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;11. git clone&lt;/h4&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;$ git clone &amp;lt;레포지터리 주소&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어를 통해 다른 사람의 github 레포지터리를 내 컴퓨터로 옮겨올 수 있다.&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;p data-ke-size=&quot;size16&quot;&gt;해당 내용은 Git과 GitHub의 사용에서 가장 기본적인 것들이다.&lt;br /&gt;개발, 특히 협업에서 꼭 알아두어야 할 것이다!&lt;br /&gt;다음 포스트에서는 Branch를 병합하는 다양한 방법을 다루려고 한다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://git-scm.com/book/ko/v2/Git%EC%9D%98-%EA%B8%B0%EC%B4%88-%EC%88%98%EC%A0%95%ED%95%98%EA%B3%A0-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0&quot;&gt;[ Git]&lt;/a&gt;, &lt;br /&gt;&lt;a href=&quot;https://docs.github.com/ko/enterprise-cloud@latest/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request&quot;&gt;[ GitHub 문서]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>WEB</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/5</guid>
      <comments>https://eznnni.tistory.com/5#entry5comment</comments>
      <pubDate>Mon, 1 Jun 2026 15:34:18 +0900</pubDate>
    </item>
    <item>
      <title>Semantic Tag</title>
      <link>https://eznnni.tistory.com/4</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍에서 시맨틱은 코드 조각의 의미를 나타냅니다.&lt;br /&gt;&quot;이 HTML element가 가진 목적이나 역할은 무엇일까?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음의 두 코드는 화면상으로 동일하게 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://velog.velcdn.com/images/eznnni/post/201f8201-6e6c-41da-9a1e-7e74cff44f20/image.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;안녕하세요?&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;div style=&quot;
        display: block;
        font-size: 2em;
        margin-block-start: 0.67em;
        margin-block-end: 0.67em;
        margin-inline-start: 0px;
        margin-inline-end: 0px;
        font-weight: bold;
        unicode-bidi: isolate;&quot;&amp;gt;안녕하세요?&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 두 코드를 같다고 말할 수 있을까요?&lt;br /&gt;그 답은 &quot;아니&quot;입니다!&lt;br /&gt;두 코드를 &lt;b&gt;동일한 것처럼 보이지만&lt;/b&gt;, 사실 HTML에 스타일을 적용하여 입히는 것은 CSS의 역할이며&lt;br /&gt;두 코드의 &lt;b&gt;&quot;의미&quot;&lt;/b&gt;는 다릅니다.&lt;br /&gt;하나는 최상위 제목을 의미하고 다른 하나는 그것이 아니라는 것이죠!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; Semantic Tag란?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Semantic Tag는 의미를 지닌 태그를 의미합니다! Semantic 은 &quot;의미론적인&quot;이란 뜻의 형용사입니다.&lt;br /&gt;개발자가 각 태그를 보고 해당 요소가 어떤 의미를 담았고, 어떤 역할을 하는지 쉽게 파악할 수 있도록 돕습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외엔 어떤 이점이 있을까요?&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; Semantic Tag의 이점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;검색 엔진 최적화 (SEO): 검색 엔진이 의미론적 마크업을 페이지의 검색 순위에 영향을 줄 수 있는 중요한 키워드로 간주합니다.&lt;br /&gt;✔ 검색 엔진은 웹을 탐색하여 페이지에서 페이지로 링크를 따라가고, 찾은 콘텐츠의 인덱스를 생성합니다.&lt;br /&gt;우리가 검색 결과로 얻는 것이 바로 그 인덱스로 된 콘텐츠입니다!&lt;br /&gt;일정한 규칙에 따라 진행되기에 내가 만든 웹사이트가 해당 규칙을 적용할 경우,&lt;br /&gt;검색 결과의 최상위에 노출될 가능성이 올라갑니다!&lt;/li&gt;
&lt;li&gt;시각 장애인에게 친화적: 시각 장애가 있는 사용자가 화면 판독기로 페이지를 탐색할 경우 semantic Tag를 안내판으로 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;쉽게 찾을 수 있음: 일반 태그로 구성된 깊은 계층 요소보다 semantic tag를 사용한 요소 블록을 찾는 것이 훨씬 쉽습니다.&lt;/li&gt;
&lt;li&gt;개발자에게 태그 안에 채워질 데이터 유형을 제안해 줍니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; Semantic Tag의 종류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;... 외에도 사용가능한 100개 정도의 Semantic Tag들이 존재합니다!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 해당 Semantic Tag가 어디에 어떻게 사용되는지 확인해 볼까요?&lt;br /&gt;Mdn 홈페이지를 예로 들어보겠습니다!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/ffc8ed01-06b4-4cb9-aac4-9168491d2c12/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 위 홈페이지는 다양한 Semantic tag로 구성되어 있습니다. 어떤 것들이 있을까요?&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1️⃣ &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/33bf138a-f9b7-4c4e-bdf3-0cb222d18b4b/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; - &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;은 제목을 나타내는 요소입니다.&lt;br /&gt;숫자가 작을수록 구획 단계가 높습니다.&lt;br /&gt;✔ &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; 이 최상위 제목입니다.&lt;br /&gt;  또한, Mdn에선 &lt;b&gt;제목 단계를 건너뛰지 말고 페이지당 하나의 &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;만을 사용하라&lt;/b&gt;고 권장합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진에서도 Hero 부분에 큰 최상위 제목으로 사용된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2️⃣ &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/d9ab553b-0cf3-41fa-b749-92d821a61d3f/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; 요소는 문서의 부분 중 현재 페이지 내, 또는 다른 페이지로의 링크를 보여주는 구획을 나타냅니다.&lt;br /&gt;✔ 메뉴, 목차, 색인 등에 사용됩니다!&lt;br /&gt;한편, 스크린 리더 등 장애를 가진 사용자를 위한 사용자 에이전트는 최초 렌더링에서 탐색 전용 콘텐츠를 제외할지 결정할 때 &lt;code&gt;&amp;lt;nav&amp;gt;를&lt;/code&gt; 사용한다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진에서도 navigation 부분에 사용된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3️⃣ &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/bf87704e-b99a-43fa-b7af-45e9f18824d1/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; 요소는 문서, 애플리케이션의 일반적인 섹션을 나타냅니다. 이 섹션은 특정 주제에 따라 묶인 콘텐츠 그룹을 의미합니다.&lt;br /&gt;이 태그는 &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; 등 섹션을 나타내는 더 정확한 의미의 요소가 없을 때, 논리적인 측면에서 주제별 컨텐츠 그룹을 나타내는 데 사용됩니다.&lt;br /&gt;✔ 상품별 섹션, 소개, 뉴스 섹션 등으로 나눌 때 사용됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진에서도 hero 섹션을 나누는 데에 사용된 것을 볼 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4️⃣ &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/a6a22cbc-8f0d-48ff-8b63-8a3d812a469f/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; 요소는 클릭 가능한 버튼을 나타냅니다.&lt;br /&gt;  해당 요소에는 다양한 특성을 지정할 수 있습니다!&lt;br /&gt;클릭을 막는 &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; 요소와 연결하는 &lt;code&gt;form&lt;/code&gt; 등이 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5️⃣ &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/ca8e1d29-cbc0-412e-9003-e759f181bcf1/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; (앵커) 요소는 &lt;code&gt;href&lt;/code&gt; 특성을 통해 다른 페이지나 같은 페이지의 어느 위치 등으로 연결할 수 있는 하이퍼링크를 만듭니다.&lt;br /&gt;  해당 요소에도 특성을 지정할 수 있습니다!&lt;br /&gt;해당 링크를 현재 유지한 채/새 창에서 열기 등 여는 방법을 지정하는 &lt;code&gt;target&lt;/code&gt;, 새 창에서 열 때 보안 취약점에 대비하여 사용하는 &lt;code&gt;rel=&quot;noopener noreferrer&lt;/code&gt; 등이 있습니다.&lt;br /&gt;  현재 최신 브라우저(chrome, edge 등)에서는 &lt;code&gt;target=&quot;_blank&quot;&lt;/code&gt; 시 자동으로 &lt;code&gt;noopener&lt;/code&gt;가 적용된다고 합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진에서 해당 Blog 요소를 클릭하면, 현재 페이지에서 mdn의 블로그로 넘어가게 됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6️⃣ &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;img style=&quot;display: inline-block; margin: 0; padding: 0;&quot; src=&quot;https://velog.velcdn.com/images/eznnni/post/d2c6a425-e71f-4eb5-9712-d701fd5c4069/image.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; 요소는 문서에 이미지를 넣습니다.&lt;br /&gt;해당 요소는 &lt;code&gt;src와&lt;/code&gt; &lt;code&gt;alt&lt;/code&gt;가 거의 고정적으로 사용됩니다.&lt;br /&gt;각각 포함하고자 하는 이미지의 경로, 이미지의 텍스트 설명을 지정합니다.&lt;br /&gt;✔ JPEG, PNG, GIF, SVG 등의 미디어 형식을 지원합니다!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 mdn 홈페이지를 통해 Semantic Tag의 사용 예시를 살펴보았습니다.&lt;br /&gt;검색 엔진 최적화 등 많은 이점을 위해 알맞은 &lt;b&gt;Semantic Tag&lt;/b&gt;를 사용하여 개발하는 것이 중요할 것 같습니다! &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Glossary/Semantics&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[ mdn - Semantics ]&lt;/a&gt;, &lt;br /&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Glossary/SEO&quot;&gt;[ mdn - SEO ]&lt;/a&gt;, &lt;br /&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTML/Reference/Elements&quot;&gt;[ mdn - 여러 Semantic tag들]&lt;/a&gt;, &lt;br /&gt;&lt;a href=&quot;https://codingeverybody.kr/category/html/html-tag/&quot;&gt;[ codingEveryday - HTML 태그 ]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>FE/HTML</category>
      <category>FE</category>
      <category>HTML</category>
      <category>Sematic Tag</category>
      <category>Web</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/4</guid>
      <comments>https://eznnni.tistory.com/4#entry4comment</comments>
      <pubDate>Mon, 1 Jun 2026 15:14:08 +0900</pubDate>
    </item>
    <item>
      <title>Cascading</title>
      <link>https://eznnni.tistory.com/3</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Cascade란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;CSS 작성중에 하나의 HTML 요소에 대해 서로 다른 스타일 규칙이 동시에 적용되는 상황이 발생할 때, 브라우저는 정해진 알고리즘에 따라 어떤 스타일을 최종적으로 적용할지 결정한다.&lt;br /&gt;이 결정 과정이 바로 캐스케이드(Cascade)이다.&lt;br /&gt;  작은 폭포나 계단식으로 떨어지는 물 을 일컫는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✔ CSS는 바로 Cascading Style Sheet의 약어이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사이트의 복잡성이 증가함에 따라 스타일시트의 수가 증가하여,&lt;br /&gt;스타일시트의 소스 순서가 더 중요하고 복잡해진다.&lt;br /&gt;다양한 스타일 후보군중에서 내가 의도하는 방향으로 스타일을 적용하기 위해선 어떤 규칙으로 확정되는지 알 필요가 있다. 규칙은 다음과 같다!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Cascading&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;브라우저는 스타일 충돌이 발생하면 다음의 단계를 거쳐 모든 요소의 모든 속성에 할당되는 값을 결정한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;관련성: 각 요소에 대해 선택자가 일치하는 모든 선언 블록을 찾는다.&lt;/li&gt;
&lt;li&gt;중요도: 일반 스타일인지 중요 스타일인지에 따라 규칙을 정렬한다.&lt;br /&gt;✔ 중요 스타일은 !important 플래그가 설정된 스타일이다.&lt;/li&gt;
&lt;li&gt;출처: 두 개의 중요도 버킷 각각 내에서 작성자, 사용자 또는 사용자 에이전트 출처별로 규칙을 정렬한다. 우선 순위는 작성자, 사용자, 사용자 에이전트(브라우저) 순이다 (일반 스타일의 경우).&lt;br /&gt;✔ 두 개의 중요도 버킷은 각각 일반 스타일 선언, 중요(!important) 스타일 선언을 의미한다.&lt;/li&gt;
&lt;li&gt;계층: 6개의 출처 중요도 버킷 각각 내에서, 종속 계층별로 정렬한다. 일반 선언의 계층 순서는 생성된 첫 번째 계층부터 마지막 계층까지이며, 그 다음에는 레이어가 없는 일반 스타일이 있다. 이 순서는 중요한 스타일에 대해 반전되며 레이어가 없는 중요 스타일의 우선 순위가 가장 낮다.&lt;/li&gt;
&lt;li&gt;명시도: 우선 순위가 있는 계층의 경쟁 스타일에 대해 명시도별로 선언을 정렬한다.&lt;br /&gt;✔ 명시도는 CSS 선언에 적용되는 가중치로 선택자가 얼마나 구체적인가에 따라 측정된다.&lt;/li&gt;
&lt;li&gt;나타나는 순서: 우선 순위가 있는 출처 계층의 두 선택자가 동일한 특정성을 갖는 경우 가장 높은 특정성을 가진, 마지막으로 선언된 선택자의 속성 값이 우선한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  위 단계를 축약하여 3가지 우선순위인 중요도, 명시도, 코드 순서로 볼 수 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  3단계 판별 기준&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;  중요도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;가장 강력한 우선순위로, 다른 모든 규칙을 무시하고 강제로 스타일을 적용하고 싶을때 사용한다.&lt;br /&gt;속성값 뒤에 !important 키워드를 붙이면, 명시도나 코드 순서와 상관없이 무조건 최우선으로 적용된다.&lt;br /&gt;&lt;b&gt;단, 이는 자연스러운 흐름을 깨트리는 기능이므로 사용을 지양한다!!&lt;/b&gt; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 방식으로 사용할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;background-color: #fbfcfd; color: #24292e; text-align: left;&quot;&gt;&lt;code&gt;&amp;lt;p class=&quot;text&quot;&amp;gt; ... &amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 상황에서,&lt;/p&gt;
&lt;pre class=&quot;css&quot; style=&quot;background-color: #fbfcfd; color: #24292e; text-align: left;&quot;&gt;&lt;code&gt;p {
	color: green !important; 
  }

.text {
		color: red; /*무시됨*/
      }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;본래 p 태그는 클래스 선택자보다 우선순위가 낮다.&lt;br /&gt;하지만 !important 키워드로 인해 color가 green으로 정해진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  명시도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&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;!important &amp;gt; #id (ID 선택자) &amp;gt; .class (클래스 선택자) &amp;gt; 유형 선택자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택자의 &lt;b&gt;유형과 개수&lt;/b&gt;에 따라 가중치가 더해지며, &lt;b&gt;제일 구체적&lt;/b&gt;일수록! 까다로울수록! 명시도가 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  점수 산정 기준&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;브라우저는 CSS 규칙을 읽을 때마다 명시도 점수를 산정한다. 이는 선택자가 얼마나 구체적인가를 수치화한 것.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명시도 점수는 (인라인 스타일, 아이디, 클래스, 태그) 의 숫자 그룹으로 표현되며, 왼쪽 자리에 있는 숫자가 클수록 무조건 우선순위가 높다.&lt;/li&gt;
&lt;li&gt;선택자가 길어지면 각 구성 요소의 점수를 합산한다.&lt;br /&gt;-&amp;gt; 예를들어, h2는 (0,0,0,1) .container .box 는 클래스가 2개이기에 (0,0,2,0) 이 된다.&lt;/li&gt;
&lt;li&gt;또한, 두 선택자가 충돌할 때, 왼쪽 자리의 숫자가 높은 쪽이 무조건 승리하게 된다.&lt;br /&gt;-&amp;gt; 예를 들어 #box는 (0,1,0,0) 이고 .container .box는 (0,0,2,0) 인 상황에서 아이디가 존재하는 #box가 이기게 된다!!&lt;br /&gt;  &lt;b&gt;아무리 점수가 높아도 더 왼쪽에 있는 선택자를 이길 수가 없다!&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 명시도를 계산해주는 웹사이트이다!&lt;br /&gt;&lt;a style=&quot;background-color: #ffffff; color: #12b886; text-align: start;&quot; href=&quot;https://specificity.keegan.st/&quot;&gt; 명시도 계산기: CSS 규칙을 테스트하고 이해할 수 있는 대화형 웹사이트&lt;/a&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;중요도와 명시도가 모두 같다면, 가장 아래쪽에 즉, 마지막에 작성된 코드가 이긴다.&lt;br /&gt;CSS의 기본 성질인 &quot;위에서 아래로 흐른다&quot;는 원칙이 적용된다.&lt;br /&gt;같은 선택자를 사용하여 스타일을 덮어쓸 때(Overriding) 해당 원리가 작동한다.&lt;/p&gt;
&lt;pre class=&quot;css&quot; style=&quot;background-color: #fbfcfd; color: #24292e; text-align: left;&quot;&gt;&lt;code&gt;/* 1. 먼저 작성됨 */
h1 {
    color: tellow; /*무시됨*/
}

/* 2. 나중에 작성*/
h1 {
    color: green;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;두 태그는 명시도가 같으나 green으로 적용된다.&lt;br /&gt;이는 아래의 스타일이 나중에 적용되었기 때문이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;참고:  &lt;a style=&quot;background-color: #f8f9fa; color: #12b886; text-align: start;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Styling_basics/Cascade_layers&quot;&gt;mdn&lt;/a&gt;&lt;a style=&quot;background-color: #f8f9fa; color: #12b886; text-align: start;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Styling_basics/Cascade_layers&quot;&gt; - 종속 계층 &lt;/a&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;background-color: #f8f9fa; color: #12b886; text-align: start;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/Guides/Cascade/Specificity&quot;&gt; mdn - 명시도&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>FE/CSS</category>
      <category>cascading</category>
      <category>CSS</category>
      <category>HTML</category>
      <category>Web</category>
      <author>eznnni</author>
      <guid isPermaLink="true">https://eznnni.tistory.com/3</guid>
      <comments>https://eznnni.tistory.com/3#entry3comment</comments>
      <pubDate>Sun, 31 May 2026 17:16:05 +0900</pubDate>
    </item>
  </channel>
</rss>