<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko_KR"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://yebinable.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://yebinable.github.io/" rel="alternate" type="text/html" hreflang="ko_KR" /><updated>2025-11-24T13:04:44+09:00</updated><id>https://yebinable.github.io/feed.xml</id><title type="html">Yebin’s Tech Log</title><subtitle>기술과 성장의 기록</subtitle><author><name>예빈</name></author><entry><title type="html">웹 렌더링 방식(SSR, CSR, SSG)</title><link href="https://yebinable.github.io/SSR-CSR-SSG-%EB%B0%A9%EC%8B%9D%EB%B3%84-%EC%B0%A8%EC%9D%B4/" rel="alternate" type="text/html" title="웹 렌더링 방식(SSR, CSR, SSG)" /><published>2025-11-21T00:00:00+09:00</published><updated>2025-11-21T00:00:00+09:00</updated><id>https://yebinable.github.io/SSR-CSR-SSG-%EB%B0%A9%EC%8B%9D%EB%B3%84-%EC%B0%A8%EC%9D%B4</id><content type="html" xml:base="https://yebinable.github.io/SSR-CSR-SSG-%EB%B0%A9%EC%8B%9D%EB%B3%84-%EC%B0%A8%EC%9D%B4/"><![CDATA[<h1 id="웹-렌더링-방식이란">웹 렌더링 방식이란?</h1>

<ul>
  <li>웹사이트를 만드는 재료(데이터, HTML, CSS, JS)를 누가, 언제, 어떻게 조립해서 사용자에게 보여줄 것 인가에 대한 전체 과정과 전략을 말함</li>
</ul>

<h2 id="렌더링-방식의-핵심-원리">렌더링 방식의 핵심 원리</h2>

<ul>
  <li>웹 렌더링을 <code class="language-plaintext highlighter-rouge">서버</code>, <code class="language-plaintext highlighter-rouge">클라이언트</code>, <code class="language-plaintext highlighter-rouge">빌드 도구</code> 중 누가 주도권을 쥐느냐에 따라 나뉜다.
<img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763699403805.png" alt="640x349" /></li>
</ul>

<h2 id="렌더링-방식이-중요한-이유">렌더링 방식이 중요한 이유?</h2>

<ul>
  <li>조금 과장해서 렌더링 방식에 따라 웹사이트의 성패가 달라질 수 있기에, 웹페이지를 운영하는 목적에 따라 렌더링 방식을 전략적으로 고려하는 것도 좋은 방법일 것 같다.
    <ul>
      <li>성능(Performance) : 첫 페이지가 얼마나 빨리 뜨는지</li>
      <li>사용자 경험(UX) : 페이지를 이동하거나 상호작용 할 때 얼마나 부드러운지</li>
      <li>검색엔진 최적화(SEO) : 검색엔진이 웹페이지의 내용을 얼마나 잘 읽어갈 수 있는지</li>
    </ul>
  </li>
</ul>

<h1 id="웹-렌더링-방식">웹 렌더링 방식</h1>

<h2 id="ssr-server-side-rendering">SSR (Server Side Rendering)</h2>

<ul>
  <li>SSR은 <strong>초기 웹 환경에서부터 사용된 고전적인 방식</strong>이었으나, 최근에는 사용자 경험과 SEO를 위해 <strong>현대적인 프레임워크(Next.js 등)에서 재도입되어 활용</strong>되고 있다.</li>
  <li>웹 렌더링의 주도권을 <code class="language-plaintext highlighter-rouge">Server</code> 가 가지는 방식으로, 여기서 말하는 서버는 웹 호스팅 서버이다.</li>
  <li>파일 서버이자 호스팅을 담당하면서 <code class="language-plaintext highlighter-rouge">데이터 처리</code>와 <code class="language-plaintext highlighter-rouge">HTML조립</code>을 모두 맡아 처리한다.</li>
</ul>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763700412881.png" alt="640x515" /></p>

<h3 id="장점-1-seo-검색-엔진-최적화에-유리"><strong>장점 1. SEO (검색 엔진 최적화)에 유리</strong></h3>

<ul>
  <li>위 시퀀스 다이어그램에서 보이듯, 요청 순간 데이터를 조회하고 HTML에 바인딩하여 완성된 HTML을 반환하기 때문에, 크롤러가 사이트 방문 시 페이지 결과를 바로 볼 수 있고, 좋은 컨텐츠로 인식하여 검색 결과에 노출하기가 수월한 편이다.</li>
</ul>

<h4 id="구글-공식-검색-프로세스3단계">구글 공식 검색 프로세스(3단계)</h4>

<ul>
  <li>발견하고 Crawling</li>
  <li>이해하고 Indexing</li>
  <li>순위를 매겨 보여주는 Serving</li>
</ul>

<p>위 세 단계를 통해 검색 결과를 제공하는데, 세 단계가 동시에 진행되는 것이 아니라 며칠에 걸쳐 이뤄진다. 특히 구글은 크롤링(HTML 다운로드)과 인덱싱(콘텐츠 분석)을 한 번에 처리하지 않고, 효율성을 위해 <strong>두 단계(Two-Pass)</strong>로 나누어 처리한다.</p>

<p><strong>1단계 : Crawling</strong></p>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763709769245.png" alt="640x164" /></p>

<p>CSR의 경우 구글은 이 단계에서 <code class="language-plaintext highlighter-rouge">&lt;title&gt;</code> 태그와 <code class="language-plaintext highlighter-rouge">&lt;meta&gt;</code> 태그 등 <strong>페이지의 기본 정보는 우선 파악하고 색인에 포함</strong>시키긴 하지만 <strong>실제 콘텐츠(본문)</strong>는 2단계 WRS를 거쳐야만 읽을 수 있다.</p>

<p><strong>2단계 : Indexing</strong></p>

<p>색인이 되기 위해 콘텐츠가 반드시 필요한 CSR 페이지들은 1단계에서 보류된 후, 구글의 <strong>웹 렌더링 서비스(WRS: Web Rendering Service)</strong> 라는 별도의 시스템으로 보내지는데, 이것이 시간 지연의 원인이 된다.</p>

<h3 id="장점-2-초기-로딩-속도가-빠름fcp-한정"><strong>장점 2. 초기 로딩 속도가 빠름(FCP 한정)</strong></h3>

<ul>
  <li>SSR이 초기 로딩 속도가 빠르다는 것은 FCP (First Contentful Paint)를 의미하는데, 이는 사용자가 화면에서 의미 있는 콘텐츠를 처음 볼 수 있을 때까지 걸리는 시간을 말한다.</li>
  <li>React.js(CSR) 와 Next.js(SSR) 로 간단히 비교하자면, CSR(React.js)은 빈 DOM 구조를 먼저 파싱한 후 <strong>JS 파일을 다운로드하고 실행</strong>하여 데이터를 가져와 최종 화면을 렌더링하는 반면, SSR(Next.js)은 응답 시점에 <strong>완성된 HTML</strong>을 전달하므로 FCP가 빠를 수밖에 없다.</li>
</ul>

<h4 id="초기-로딩-속도에서-중요한-세-가지-지표"><strong>‘초기 로딩 속도’에서 중요한 세 가지 지표</strong></h4>

<ul>
  <li>
    <p><strong>TTFB (Time To First Byte) :</strong> 서버가 요청을 받고, 첫 번째 데이터를 브라우저에 보내는 데 걸리는 시간. (SSR 느림 &lt; CSR 빠름)</p>
  </li>
  <li>
    <p><strong>FCP (First Contentful Paint) :</strong> 사용자가 <strong>화면에서 의미 있는 콘텐츠(텍스트나 이미지)</strong>를 <strong>처음 볼 수 있을 때</strong>까지 걸리는 시간. (SSR 빠름 &gt; CSR 느림)</p>
  </li>
  <li>
    <p><strong>TTL (Time To Interactive)</strong> : 사용자가 페이지와 상호작용 할 수 있을 때까지 걸리는 시간 (SSR은 FCP와 TTL의 간격이 크고, CSR은 FCP와 TTL의 간격이 거의 차이가 없음)</p>
  </li>
</ul>

<h4 id="ssr과-csr의-fcp-vs-tti-비교"><strong>SSR과 CSR의 FCP vs TTI 비교</strong></h4>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763709796918.png" alt="640x228" /></p>

<h3 id="장점-3-낮은-초기-처리-부하-저-사양-기기-유리"><strong>장점 3. 낮은 초기 처리 부하 (저 사양 기기 유리)</strong></h3>

<ul>
  <li>앞서 보았듯 SSR은 페이지를 그리는 모든 무거운 작업 (데이터 바인딩, HTML 조립 등)들이 성능 좋은 서버에서 미리 처리되므로 상대적으로 <strong>브라우저</strong> 의 부하가 크게 줄어든다. 그래서 클라이언트(브라우저) 성능에 크게 좌우되지 않는 편이다. (하이드레이션으로 인한 부하는 제외 - 이미 화면에 그려진 DOM 구조를 다시 스캔하여 이벤트 리스너 등을 하나하나 연결하는 작업)</li>
</ul>

<h3 id="단점-1-느린-서버-응답-시간-ttfb-지연-가능성"><strong>단점 1. 느린 서버 응답 시간 (TTFB 지연 가능성)</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> SSR은 사용자의 요청이 있을 때마다 서버에서 데이터베이스(DB)에 접속하여 데이터를 조회하고, 템플릿에 렌더링하여 <strong>완성된 HTML을 즉시 생성</strong>해야 함. 이 일련의 서버 처리 과정 자체가 시간이 소요됨.</p>
  </li>
  <li>
    <p><strong>문제점:</strong> 동시에 많은 요청이 들어오거나(트래픽 급증), DB 조회 시간이 길어지면, <strong>서버에 과부하</strong>가 걸려 응답 시간이 느려짐.</p>
  </li>
  <li>
    <p><strong>결과:</strong> 사용자가 첫 번째 데이터(첫 바이트)를 받을 때까지 걸리는 시간인 <strong>TTFB (Time To First Byte)가 CSR보다 길어질 수 있음.</strong> (CSR은 빈 HTML만 즉시 보내면 되므로 TTFB가 빠름.)</p>
  </li>
</ul>

<h3 id="단점-2-ttl-지연-느린-상호작용"><strong>단점 2. TTL 지연 (느린 상호작용)</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> SSR은 HTML을 빠르게 보내 <strong>FCP</strong>를 달성하지만, 이후 <strong>Hydration(하이드레이션)</strong>이라는 무거운 클라이언트 측 JS 실행 및 연결 작업이 필수적임.</p>
  </li>
  <li>
    <p><strong>문제점:</strong> Hydration 과정이 끝날 때까지 페이지는 사용자 입력에 반응할 수 없는 <strong>‘먹통 구간’</strong>이 됨.</p>
  </li>
  <li>
    <p><strong>결과:</strong> 사용자 눈에는 페이지가 완성된 것처럼 보이지만, 클릭이 안 되는 답답한 경험을 주어 <strong>UX가 저하</strong>됨. (FCP와 TTI 간 간격이 큼.)</p>
  </li>
</ul>

<h3 id="단점-3-서버-리소스-및-운영-비용-증가"><strong>단점 3. 서버 리소스 및 운영 비용 증가</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> SSR은 모든 요청을 서버가 직접 처리하고 HTML을 생성해야 함. (CSR은 대부분의 렌더링 작업을 사용자의 브라우저에 떠넘김.)</p>
  </li>
  <li>
    <p><strong>문제점:</strong> 서버는 DB 조회, 템플릿 엔진 실행, HTML 생성 등 복잡한 연산을 반복적으로 수행해야 하므로 <strong>CPU와 메모리 사용량이 매우 높음.</strong></p>
  </li>
  <li>
    <p><strong>결과:</strong> 서버를 운영하기 위한 <strong>하드웨어 사양과 클라우드 비용이 CSR 대비 크게 증가</strong>함. 특히 트래픽이 폭증할 경우, 서버 증설 비용 부담이 커짐.</p>
  </li>
</ul>

<h2 id="csr-client-side-rendering">CSR (Client Side Rendering)</h2>

<ul>
  <li>CSR은 SSR과 정반대되는 철학을 가지는데, 서버의 부담을 최소화 하고, 모든 동적인 작업을 사용자의 브라우저에 맡기는 방식이다.</li>
  <li>웹 렌더링 주도권을 <code class="language-plaintext highlighter-rouge">Client(Browser)</code>가 가지는 형태이다.</li>
  <li>초기 로딩 시 기본 뼈대만 있는 HTML 파일과 JS 번들을 먼저 응답한 다음, JS 파싱 및 실행 후 데이터를 조회해 데이터 바인딩 및 완성된 HTML을 생성 한다.</li>
  <li>여기서 웹 서버는 단순히 파일 호스팅만 담당하고, 실제 HTML 조립은 브라우저의 Javascript 가 처리한다.</li>
</ul>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763705719321.png" alt="640x974" /></p>

<h3 id="장점-1-빠른-페이지-전환-부드러운-ux"><strong>장점 1. 빠른 페이지 전환 (부드러운 UX)</strong></h3>

<ul>
  <li>CSR 앱은 초기 로딩 시 한 번만 전체 JS 코드를 다운로드 하고 나면, 이후 페이지 이동 시 HTML 전체를 다시 서버에서 받아올 필요가 없다.</li>
  <li>필요한 <strong>데이터만 API를 통해 JSON 형태로 받아와</strong> 화면의 필요한 부분만 갱신함. 이는 페이지가 깜빡이거나 새로고침되는 현상 없이 매우 빠르고 부드러운 사용자 경험을 제공함.</li>
  <li>여기서 <code class="language-plaintext highlighter-rouge">SSR도 초기 로딩 시 전체 JS 코드를 다운받는데?</code> 라는 의문이 들 수 있는데, 여기서 중요한 사용 방식의 차이는 CSR은 기본적으로 SPA(Single Page Application) 형태로 동작한다는 것이다.</li>
</ul>

<h4 id="spa-vs-mpa-핵심-차이점-비교"><strong>SPA vs MPA 핵심 차이점 비교</strong></h4>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763709824009.png" alt="640x308" /></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-react-app/
├── public/
│   └── index.html          # 빈 껍데기 (단 하나의 HTML)
│
└── src/
    ├── pages/              # Home.jsx, About.jsx, Product.jsx
    ├── components/         # Header.jsx, Footer.jsx
    ├── App.jsx             # 라우팅 설정
    └── index.js            # ReactDOM.render 진입점
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- public/index.html: 유일한 HTML --&gt;</span>
<span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html&gt;</span>
  <span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"root"</span><span class="nt">&gt;&lt;/div&gt;</span>  <span class="c">&lt;!-- 비어있음 --&gt;</span>
    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"bundle.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
  <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>

<h3 id="장점-2-웹-호스팅-서버-부하-감소-및-비용-절감"><strong>장점 2. 웹 호스팅 서버 부하 감소 및 비용 절감</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> 웹 호스팅 서버는 데이터 처리(DB 조회)와 HTML 템플릿 렌더링을 할 필요가 없음.</p>
  </li>
  <li>
    <p><strong>결과:</strong> 서버는 요청에 대해 <strong>빈 HTML 뼈대와 JS 파일</strong>, 그리고 이후 <strong>순수한 데이터(JSON)</strong>만 제공하면 됨. 서버의 CPU 부담이 대폭 줄어들어, 운영 비용이 낮고 대용량 트래픽에도 안정적으로 대응함.</p>
  </li>
</ul>

<h3 id="장점-3-fcp와-tti-간격-최소화"><strong>장점 3. FCP와 TTI 간격 최소화</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> JS가 실행되어야만 콘텐츠가 화면에 보이기 시작함 (FCP). 이벤트 리스너도 이 과정에서 동시에 붙음 (TTI).</p>
  </li>
  <li>
    <p><strong>결과:</strong> TTI 자체가 늦어지더라도, <strong>FCP와 TTI 사이의 ‘먹통 구간’이 거의 없어</strong> 사용자에게 “보이는데 클릭은 안 되는” 답답함을 주지 않음.</p>
  </li>
</ul>

<h3 id="단점-1-느린-초기-로딩-속도-fcp-지연"><strong>단점 1. 느린 초기 로딩 속도 (FCP 지연)</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> 브라우저가 사용자에게 콘텐츠를 보여주기 위해 <strong>대용량의 JS 파일을 모두 다운로드하고 실행</strong>할 때까지 기다려야 함.</p>
  </li>
  <li>
    <p><strong>문제점:</strong> JS 파일이 클 경우, 사용자는 긴 시간 동안 <strong>하얀 화면(White Screen)만</strong> 보게 됨.</p>
  </li>
  <li>
    <p><strong>결과:</strong> 초기 로딩 속도 지표인 <strong>FCP가 SSR에 비해 현저히 느려지는</strong> 결정적인 단점이 있음.</p>
  </li>
</ul>

<h3 id="단점-2-검색-엔진-최적화-seo-불리"><strong>단점 2. 검색 엔진 최적화 (SEO) 불리</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> Googlebot이 1단계 크롤링 시점에 받아보는 HTML 파일이 <code class="language-plaintext highlighter-rouge">&lt;div id="root"&gt;&lt;/div&gt;</code>와 같은 <strong>빈 껍데기</strong>이기 때문임.</p>
  </li>
  <li>
    <p><strong>문제점:</strong> 실제 콘텐츠를 읽으려면 구글의 <strong>WRS(Web Rendering Service) 대기열</strong>을 거쳐 JS를 실행해야 함. 이 과정에서 색인에 시간이 더 오래 걸리는 지연(Delay) 이 발생할 수 있어 SSR보다 불리할 수 있음.</p>
  </li>
</ul>

<h3 id="단점-3-클라이언트-성능-의존성이-높음"><strong>단점 3. 클라이언트 성능 의존성이 높음</strong></h3>

<ul>
  <li>
    <p><strong>원인:</strong> 페이지 렌더링 및 상호작용 관련 모든 복잡한 연산을 사용자 기기의 CPU가 처리해야 함.</p>
  </li>
  <li>
    <p><strong>결과:</strong> 사용자의 <strong>네트워크 환경이 불안정하거나 저사양 스마트폰</strong>을 사용할 경우, JS 다운로드 및 실행 시간이 오래 걸려 앱이 느리게 느껴지거나 버벅거림.</p>
  </li>
</ul>

<h2 id="ssg-static-site-generation">SSG (Static Site Generation)</h2>

<ul>
  <li>SSG는 웹사이트를 사용자가 요청하는 시점이 아니라, 배포 및 빌드하는 시점에 미리 완성된 HTML 파일을 생성해 놓는 전략이다. 따라서 SSG의 장단점은 매우 명확한데, 속도는 엄청 빠르지만 데이터 변경 시에는 재 배포가 필요하다는 점이다.</li>
</ul>

<h3 id="작동-원리-빌드-시점의-ssr"><strong>작동 원리 (빌드 시점의 SSR)</strong></h3>

<ol>
  <li>
    <p><strong>빌드 시점:</strong> 개발자가 웹사이트를 서버에 올릴 때(빌드), SSG 도구(Next.js, Astro, Gatsby 등)가 데이터베이스에 접속하여 <strong>필요한 모든 데이터를 조회</strong>함.</p>
  </li>
  <li>
    <p><strong>HTML 생성:</strong> 조회된 데이터로 <strong>수천, 수만 개의 완성된 HTML 파일</strong>을 미리 만들어냄.</p>
  </li>
  <li>
    <p><strong>배포:</strong> 이렇게 만들어진 <strong>정적인 HTML, CSS, JS 파일 묶음</strong>을 CDN(Content Delivery Network) 같은 분산된 파일 서버에 저장함.</p>
  </li>
  <li>
    <p><strong>사용자 요청 (Runtime):</strong> 사용자가 페이지를 요청하면, 서버가 HTML을 만드는 것이 아니라, <strong>가장 가까운 CDN 위치</strong>에서 이미 만들어진 HTML 파일을 즉시 가져와 보여줌.</p>
  </li>
</ol>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763707996629.png" alt="640x718" /></p>

<h3 id="장점-1-압도적인-속도-ttfb-fcp-최상"><strong>장점 1. 압도적인 속도 (TTFB, FCP 최상)</strong></h3>

<ul>
  <li><strong>TTFB</strong>가 매우 빠르다. 서버에서 데이터를 조회하고 HTML을 만들 필요가 없기 때문에, 단순 파일을 전송하는 속도만 나오기 때문이며, 이에 따라 <strong>FCP</strong> 역시 매우 빠른 편이다.</li>
</ul>

<h3 id="장점-2-최고의-seo"><strong>장점 2. 최고의 SEO</strong></h3>

<ul>
  <li>SSR처럼 <strong>이미 완성된 HTML</strong>이 크롤러에게 제공되므로, 구글의 WRS 대기열을 거칠 필요가 없다.</li>
</ul>

<h3 id="장점-3-낮은-비용-및-높은-안정성"><strong>장점 3. 낮은 비용 및 높은 안정성</strong></h3>

<ul>
  <li>웹 호스팅 서버 대신 CDN에서 단순 파일을 제공하므로, 서버 운영 비용이 거의 들지 않는 편이다. 또한 트래픽이 아무리 폭증해도 CDN은 안정적으로 파일을 제공할 수 있다.</li>
</ul>

<h3 id="단점-1-실시간-데이터-반영-어려움"><strong>단점 1. 실시간 데이터 반영 어려움</strong></h3>

<ul>
  <li>
    <p>데이터가 업데이트될 때마다 <strong>전체 웹사이트를 다시 빌드하고 배포</strong>해야 한다. (예: 블로그 포스팅 하나 수정 시 전체 사이트 재빌드)</p>
  </li>
  <li>
    <p>뉴스 사이트처럼 실시간으로 데이터가 바뀌어야 하는 곳에는 부적합하다.</p>
  </li>
  <li>
    <p>SSG는 데이터 업데이트 시 재빌드가 필요하지만, 최근에는 <strong>ISR</strong>과 같은 기술을 통해 <strong>일정 주기를 설정하여 부분적으로만 재빌드</strong>하여 실시간성 문제를 완화하고 있다고 한다.</p>
  </li>
</ul>

<h3 id="단점-2-개인화-어려움"><strong>단점 2. 개인화 어려움</strong></h3>

<p>페이지가 미리 만들어져 있기 때문에, 로그인한 사용자별로 내용이 달라지는 <strong>개인화된 페이지(Personalized Content)</strong>를 만드는데 제약이 따른다. (이 경우 SSR이나 CSR 혼합 방식이 필요함)</p>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763709878122.png" alt="640x163" /></p>

<h1 id="웹-렌더링-방식-3가지-핵심-비교">웹 렌더링 방식 3가지 핵심 비교</h1>

<p><img src="./2025-11-21-SSR-CSR-SSG-방식별-차이/attachment-1763709897136.png" alt="640x467" /></p>

<h1 id="참고자료">참고자료</h1>

<ul>
  <li><a href="https://www.google.com/intl/ko_ALL/search/howsearchworks/how-search-works/organizing-information/">Google 검색의 작동 방식</a></li>
  <li><a href="https://developers.google.com/search/docs/crawling-indexing?hl=ko">Google 크롤링 및 색인 생성</a></li>
  <li><a href="https://developers.google.com/search/docs/essentials?hl=ko">Google 검색 Essentials</a></li>
</ul>]]></content><author><name>예빈</name></author><category term="웹렌더링" /><category term="웹개발" /><summary type="html"><![CDATA[웹사이트를 만드는 재료(데이터, HTML, CSS, JS)를 누가, 언제, 어떻게 조립해서 사용자에게 보여줄 것 인가에 대한 전체 과정과 전략에 대해 공부하고 정리해보았습니다.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yebinable.github.io/_posts/2025-11-21-SSR-CSR-SSG-%EB%B0%A9%EC%8B%9D%EB%B3%84-%EC%B0%A8%EC%9D%B4/attachment-1763709106408.png" /><media:content medium="image" url="https://yebinable.github.io/_posts/2025-11-21-SSR-CSR-SSG-%EB%B0%A9%EC%8B%9D%EB%B3%84-%EC%B0%A8%EC%9D%B4/attachment-1763709106408.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Google 검색에 내 Github Pages 노출하기</title><link href="https://yebinable.github.io/Github-Pages-%EB%85%B8%EC%B6%9C%ED%95%98%EA%B8%B0/" rel="alternate" type="text/html" title="Google 검색에 내 Github Pages 노출하기" /><published>2025-11-20T00:00:00+09:00</published><updated>2025-11-20T00:00:00+09:00</updated><id>https://yebinable.github.io/Github-Pages-%EB%85%B8%EC%B6%9C%ED%95%98%EA%B8%B0</id><content type="html" xml:base="https://yebinable.github.io/Github-Pages-%EB%85%B8%EC%B6%9C%ED%95%98%EA%B8%B0/"><![CDATA[<p>구글 검색에 내 GitHub Pages를 노출하고 싶어서 <code class="language-plaintext highlighter-rouge">Perplexity</code> 검색 도움을 받아 다음과 같이 설정하고 정리해보았다.</p>

<p>구글 검색 노출을 위해 해야 할 주요 설정은 다음과 같다.</p>

<ol>
  <li><strong>Google Search Console에 사이트 등록 및 소유권 확인</strong>
    <ul>
      <li>내 GitHub Pages 주소를 Google Search Console에 등록하고, 제공하는 HTML 소유권 확인 파일을 다운로드 받아 GitHub 저장소 루트에 업로드해 소유권을 인증합니다.</li>
    </ul>
  </li>
  <li><strong>sitemap.xml 파일 생성 및 업로드</strong> 및 <strong>Google Search Console에 sitemap 제출</strong>
    <ul>
      <li>사이트의 각 페이지 위치를 알리는 sitemap.xml 파일을 만들어 GitHub 저장소 루트에 추가합니다. 이 파일은 Google이 사이트 구조를 쉽게 파악하도록 돕습니다.</li>
      <li>Google Search Console에서 sitemap.xml 파일을 제출해 사이트 색인을 활성화합니다.</li>
    </ul>
  </li>
  <li><strong>robots.txt 파일 생성 및 업로드</strong>
    <ul>
      <li>robots.txt 파일을 만들어 모든 검색 엔진에 사이트 접근을 허용하고 sitemap 위치를 명시합니다.</li>
    </ul>
  </li>
  <li><strong>사이트 메타태그 및 SEO 최적화</strong>
    <ul>
      <li>Jekyll을 사용하는 경우 jekyll-seo-tag 플러그인 설정 등으로 메타태그를 추가해 검색 노출을 개선합니다.</li>
    </ul>
  </li>
</ol>

<p>나의 경우 Jekyll을 사용하여 블로그를 생성했기 때문에, Jekyll의 플러그인을 사용하여 아래 항목들은 손쉽게 해결했다.</p>
<ul>
  <li>sitemap</li>
  <li>SEO</li>
  <li>RSS feed
<img src="./2025-11-20-Github-Pages-노출하기/attachment-1763634445219.png" alt="|347x337" /></li>
</ul>

<h1 id="1-google-search-console에-사이트-등록-및-소유권-확인">1. <strong>Google Search Console에 사이트 등록 및 소유권 확인</strong></h1>

<table>
  <tbody>
    <tr>
      <td>![</td>
      <td>500x409](./2025-11-20-Github-Pages-노출하기/attachment-1763634462444.png)</td>
    </tr>
  </tbody>
</table>

<h2 id="githubio-를-등록할-때는-url-접두어-방식을-선택"><code class="language-plaintext highlighter-rouge">github.io</code> 를 등록할 때는 <code class="language-plaintext highlighter-rouge">URL 접두어</code> 방식을 선택</h2>

<ul>
  <li>
    <p><strong>왜?</strong> GitHub Pages는 GitHub가 소유한 도메인을 사용할 권한만 있고, <strong>도메인 관리 권한은 없기 때문</strong></p>
  </li>
  <li>
    <p>도메인 속성은 DNS 레코드를 직접 수정해야 하는데, <code class="language-plaintext highlighter-rouge">github.io</code>는 GitHub 소유라서 DNS 설정을 할 수가 없음</p>
  </li>
</ul>

<h2 id="파일-다운로드-후-github-pages의-최상단-폴더에-업로드">파일 다운로드 후 GitHub Pages의 최상단 폴더에 업로드</h2>
<p><img src="./2025-11-20-Github-Pages-노출하기/attachment-1763634477031.png" alt="|640x353" /></p>

<ul>
  <li>이후 [완료] 버튼을 누르면 아래와 같이 <code class="language-plaintext highlighter-rouge">소유권이 확인됨</code>
<img src="./2025-11-20-Github-Pages-노출하기/attachment-1763634497816.png" alt="|500x453" /></li>
</ul>

<h1 id="2--sitemapxml-파일-생성-및-업로드-및-google-search-console에-sitemap-제출">2.  <strong>sitemap.xml 파일 생성 및 업로드</strong> 및 <strong>Google Search Console에 sitemap 제출</strong></h1>

<ul>
  <li>앞서 말했다시피, Sitemap은 Jekyll을 사용하여 손쉽게 생성되었기에 사이트맵 주소만 Google Search Console에 추가하면 된다.
<img src="./2025-11-20-Github-Pages-노출하기/attachment-1763634521381.png" alt="|640x415" /></li>
</ul>

<h1 id="3-robotstxt-파일-생성-및-업로드">3. robots.txt 파일 생성 및 업로드</h1>

<ul>
  <li>robots.txt 파일 생성은 간단하다 아래와 같은 내용으로 파일을 만든 후 root(최상단)에 파일을 추가해주면 된다.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>﻿User-agent: *
Allow: /

Sitemap: https://yebinable.github.io/sitemap.xml
</code></pre></div></div>

<h1 id="4-사이트-메타태그-및-seo-최적화">4. <strong>사이트 메타태그 및 SEO 최적화</strong></h1>

<ul>
  <li>Jekyll 플러그인을 이용해 손쉽게 적용할 수 있다.</li>
  <li>Jekyll-seo-tag 플러그인이 front matter와 config.yml의 정보를 기반으로 다음 메타태그들을 자동으로 생성한다.
    <ul>
      <li>페이지 타이틀과 사이트 타이틀</li>
      <li>메타 description</li>
      <li>Canonical URL (중복 콘텐츠 방지)</li>
      <li>JSON-LD 구조화 데이터 (리치 스니펫용)</li>
      <li>이전/다음 페이지 URL (페이지네이션)
  …</li>
    </ul>
  </li>
  <li>이 방법을 사용하면 수동으로 메타태그를 작성할 필요 없이 Jekyll이 자동으로 SEO에 최적화된 메타태그를 생성하므로, front matter에 기본 정보만 잘 작성하면 된다.</li>
</ul>

<h2 id="레이아웃-파일에-태그-추가"><strong>레이아웃 파일에 태그 추가</strong></h2>

<ul>
  <li><code class="language-plaintext highlighter-rouge">_layouts/default.html</code> 의 <code class="language-plaintext highlighter-rouge">&lt;head&gt;</code> 섹션에 <code class="language-plaintext highlighter-rouge">seo</code> 태그를 삽입
<img src="./2025-11-20-Github-Pages-노출하기/attachment-1763636866545.png" alt="|640x105" /></li>
</ul>

<h2 id="_configyml-에-사이트-전체-seo-설정"><code class="language-plaintext highlighter-rouge">_config.yml</code> 에 사이트 전체 SEO 설정</h2>

<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">사이트</span><span class="nv"> </span><span class="s">제목"</span>
<span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">사이트</span><span class="nv"> </span><span class="s">설명"</span>
<span class="na">author</span><span class="pi">:</span> <span class="s2">"</span><span class="s">작성자</span><span class="nv"> </span><span class="s">이름"</span>
<span class="na">email</span><span class="pi">:</span> <span class="s2">"</span><span class="s">your@email.com"</span>
<span class="na">url</span><span class="pi">:</span> <span class="s2">"</span><span class="s">https://yourusername.github.io"</span>
<span class="na">locale</span><span class="pi">:</span> <span class="s">ko_KR</span>

<span class="c1"># 소셜 미디어 프로필</span>
<span class="na">social</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">작성자</span><span class="nv"> </span><span class="s">이름"</span>
  <span class="na">links</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">https://github.com/yourusername</span>
    <span class="pi">-</span> <span class="s">https://twitter.com/yourusername</span>
</code></pre></div></div>

<h2 id="각-포스트-별-개별-메타-데이터-설정-front-matter">각 포스트 별 개별 메타 데이터 설정 (front matter)</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>---
layout: post
title: "포스트 제목"
description: "포스트 설명 (메타 description으로 사용)"
date: 2025-11-19
author: "작성자 이름"
tags: [git, obsidian]
image: /assets/images/post-thumbnail.jpg
---

본문 입니다.

</code></pre></div></div>

<h1 id="참고자료">참고자료</h1>

<p><a href="https://support.google.com/webmasters/answer/10267942?hl=ko&amp;ref_topic=10265228&amp;sjid=15336440516382272933-NC">구글-Search Console 시작하기</a></p>]]></content><author><name>예빈</name></author><category term="github-pages" /><category term="google" /><summary type="html"><![CDATA[구글 검색에 내 GitHub Pages를 노출하고 싶어서 `Perplexity` 검색 도움을 받아 다음과 같이 설정해보고 정리해보았습니다.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yebinable.github.io/_posts/2025-11-20-Github-Pages-%EB%85%B8%EC%B6%9C%ED%95%98%EA%B8%B0/attachment-1763634567483.png" /><media:content medium="image" url="https://yebinable.github.io/_posts/2025-11-20-Github-Pages-%EB%85%B8%EC%B6%9C%ED%95%98%EA%B8%B0/attachment-1763634567483.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Git Submodule로 하나의 Obsidian Vault에서 여러 개의 git repository 관리하기</title><link href="https://yebinable.github.io/git-submodule/" rel="alternate" type="text/html" title="Git Submodule로 하나의 Obsidian Vault에서 여러 개의 git repository 관리하기" /><published>2025-11-19T00:00:00+09:00</published><updated>2025-11-19T00:00:00+09:00</updated><id>https://yebinable.github.io/git-submodule</id><content type="html" xml:base="https://yebinable.github.io/git-submodule/"><![CDATA[<h2 id="문제-상황">문제 상황</h2>
<p>GitHub로 기술 블로그(Wiki)를 만들고 싶고, Obsidian으로 편하게 관리하고 싶었다. 하지만 다음과 같은 요구사항이 있었다:</p>
<ul>
  <li><strong>비공개 노트</strong>: 업무 내용, 개인 메모, 작성 중인 초안은 Private으로 관리</li>
  <li><strong>공개 블로그</strong>: 완성된 기술 문서는 GitHub Pages(<code class="language-plaintext highlighter-rouge">username.github.io</code>)로 공개</li>
  <li><strong>단일 Vault</strong>: Obsidian에서 하나의 Vault로 모든 노트를 한 화면에서 관리</li>
  <li><strong>자동 Git 푸시</strong>: 파일 저장하면 자동으로 각 저장소에 커밋/푸시</li>
</ul>

<h3 id="시도한-방법들과-문제점">시도한 방법들과 문제점</h3>

<p><strong>방법 1: 심볼릭 링크</strong></p>
<ul>
  <li>Public 저장소를 심볼릭 링크로 연결</li>
  <li>문제: Public 폴더 수정 시 일일이 해당 폴더로 가서 수동으로 커밋/푸시해야 함</li>
  <li>문제: Obsidian Git이 심볼릭 링크 내부를 자동으로 처리하지 못함</li>
</ul>

<p><strong>방법 2: Vault 2개 분리</strong></p>
<ul>
  <li>Private Vault와 Public Vault를 완전히 분리</li>
  <li>문제: Vault를 전환해야 해서 불편함</li>
  <li>문제: Private와 Public 노트를 동시에 볼 수 없음</li>
</ul>

<p><strong>방법 3: <code class="language-plaintext highlighter-rouge">.gitignore</code>로 제외</strong></p>
<ul>
  <li>하나의 Public 저장소에서 특정 폴더만 <code class="language-plaintext highlighter-rouge">.gitignore</code>로 제외</li>
  <li>문제: 실수로 비공개 내용이 Public에 올라갈 위험</li>
  <li>문제: Private 내용이 Git 히스토리에 남을 수 있음</li>
</ul>

<h2 id="원인-분석">원인 분석</h2>
<p>Obsidian은 <strong>파일 시스템 기반</strong>이고, Git은 <strong>저장소 단위</strong>로 동작한다.</p>

<h3 id="필요한-조건">필요한 조건</h3>
<ol>
  <li>Private와 Public이 <strong>완전히 분리된 Git 저장소</strong>여야 함</li>
  <li>Obsidian에서는 <strong>하나의 Vault</strong>로 보여야 함</li>
  <li>Obsidian Git이 <strong>각 저장소를 독립적으로 자동 커밋/푸시</strong>해야 함</li>
</ol>

<h2 id="해결-방법">해결 방법</h2>

<h3 id="git-submodule">Git Submodule</h3>
<p>Git Submodule은 하나의 Git 저장소 안에 다른 Git 저장소를 포함시키는 기능이다.</p>

<h3 id="최종-구조">최종 구조</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>notes/ (Private Repository)
├── .git/                      ← Private 저장소
├── .gitmodules                ← Submodule 설정 파일
├── .obsidian/                 ← Obsidian 설정
├── private/                   ← 비공개 노트
│   ├── inbox/
│   ├── work/
│   └── life/
└── yebinable.github.io/       ← Public Repository (Submodule)
    ├── .git/                  ← Public 저장소 (독립적)
    ├── tech/
    └── README.md
</code></pre></div></div>

<h3 id="설정-과정">설정 과정</h3>

<h4 id="1-github-저장소-생성">1. GitHub 저장소 생성</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>**Private 저장소:**
- Repository name: `notes`
- Visibility: **Private**

**Public 저장소:**
- Repository name: `yebinable.github.io`
- Visibility: **Public**
</code></pre></div></div>

<h4 id="2-private-저장소-클론">2. Private 저장소 클론</h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/yebinable/notes.git
<span class="nb">cd </span>notes
</code></pre></div></div>

<h4 id="3-public-저장소를-private-저장소의-submodule로-추가">3. Public 저장소를 Private 저장소의 Submodule로 추가</h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Submodule 추가</span>
git submodule add https://github.com/yebinable/yebinable.github.io.git yebinable.github.io

<span class="c"># 커밋</span>
git add .gitmodules yebinable.github.io
git commit <span class="nt">-m</span> <span class="s2">"Add public wiki as submodule"</span>
git push
</code></pre></div></div>

<h4 id="4-obsidian-설정">4. Obsidian 설정</h4>

<ol>
  <li><strong>Vault 열기</strong>: <code class="language-plaintext highlighter-rouge">yebinable-private</code> 폴더를 Vault로 열기</li>
  <li><strong>Obsidian Git 플러그인 설치</strong></li>
  <li><strong>중요 설정:</strong>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Settings → Obsidian Git → Advanced
→ ✅ Update submodules (반드시 체크!)
   
Vault backup interval: 1분
Auto pull interval: 1분
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="작동-원리">작동 원리</h3>

<p>Obsidian Git의 “Update submodules” 옵션이 이 두 단계를 자동으로 처리한다.</p>

<h4 id="private-노트-작성-시">Private 노트 작성 시</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private/work/보안-취약점.md 작성 및 저장
→ 10분 후 Obsidian Git 자동 실행
→ yebinable-private 저장소에 커밋 &amp; 푸시 ✅
</code></pre></div></div>

<h4 id="public-노트-작성-시">Public 노트 작성 시</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yebinable.github.io/tech/Git-정리.md 작성 및 저장
→ 10분 후 Obsidian Git 자동 실행
→ 1단계: yebinable.github.io 내부 커밋 &amp; 푸시 ✅
→ 2단계: yebinable-private에서 참조 업데이트 &amp; 푸시 ✅
</code></pre></div></div>

<h3 id="다른-환경에서-클론-시">다른 환경에서 클론 시</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Submodule까지 함께 클론</span>
git clone <span class="nt">--recursive</span> https://github.com/yebinable/yebinable-private.git

<span class="c"># 또는 이미 클론했다면</span>
git submodule init
git submodule update
</code></pre></div></div>]]></content><author><name>예빈</name></author><category term="git" /><category term="obsidian" /><summary type="html"><![CDATA[Git Submodule을 어떻게 사용하고 왜 사용하게 되었는지를 기록했습니다.]]></summary></entry></feed>