Home Jekyll 블로그 설치 및 로컬 실행 가이드
Post
Cancel

Jekyll 블로그 설치 및 로컬 실행 가이드

개요

  • Jekyll 기반 GitHub Pages 블로그를 처음부터 설치하고 로컬에서 실행하는 과정을 설명함

사전 준비사항

필수 도구 확인

  • 블로그 구축에 필요한 도구들
    • Git
      • 버전 관리 시스템
      • GitHub Pages 배포에 필수
    • Ruby
      • Jekyll이 동작하는 런타임 환경
      • 버전 2.5 이상 권장
    • RubyGems
      • Ruby 패키지 관리자
      • Ruby 설치 시 함께 설치됨
    • Bundler
      • Ruby 의존성 관리 도구
      • Jekyll 프로젝트 관리에 필수

운영체제별 도구 설치

Windows

  • Ruby 설치
    • RubyInstaller 다운로드
    • 설치 과정
      • 다운로드한 설치 파일 실행
      • “Add Ruby executables to your PATH” 옵션 체크
      • MSYS2 설치 단계에서 모든 옵션 선택 (1, 2, 3)
    • 설치 확인
      1
      2
      
      ruby -v
      gem -v
      
  • Git 설치
    • Git for Windows 다운로드
    • 설치 과정
      • 기본 설정으로 설치 진행
    • 설치 확인
      1
      
      git --version
      
  • Bundler 설치
    1
    2
    3
    4
    
    gem install bundler
      
    # 설치 확인
    bundle -v
    

macOS

  • Homebrew 설치
    • 터미널에서 실행
      1
      
      /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      
    • 설치 확인
      1
      
      brew --version
      
  • Ruby 설치
    • rbenv를 통한 Ruby 설치
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      # rbenv 설치
      brew install rbenv ruby-build
          
      # rbenv 초기화
      rbenv init
          
      # .zshrc 또는 .bash_profile에 추가
      echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc
      source ~/.zshrc
          
      # 설치 가능한 Ruby 버전 확인
      rbenv install -l
          
      # Ruby 설치 (최신 안정 버전)
      rbenv install 3.2.2
      rbenv global 3.2.2
          
      # 설치 확인
      ruby -v
      
  • Git 설치
    1
    2
    3
    4
    5
    
    # Git 설치
    brew install git
      
    # 설치 확인
    git --version
    
  • Bundler 설치
    1
    2
    3
    4
    
    gem install bundler
      
    # 설치 확인
    bundle -v
    

Jekyll 테마 선택 및 설치

테마 찾기

  • Jekyll 테마 사이트

인기 Jekyll 테마 소개

  • Chirpy
    • 깔끔한 디자인의 블로그 테마
    • 다크 모드 지원
    • 카테고리, 태그, 검색 기능 내장
    • GitHub Repository
  • Minimal Mistakes
    • 가장 많이 사용되는 테마 중 하나
    • 반응형 디자인
    • 다양한 레이아웃 옵션
    • GitHub Repository
  • Beautiful Jekyll
  • TeXt Theme
  • Basically Basic

GitHub에서 테마 가져오기

  • 방법 1, 2 중 선택
    1. Fork 하기
    • GitHub에서 테마 Repository 접속
    • 예시: Chirpy 테마
    • Fork 버튼 클릭
      • Repository name을 username.github.io 형식으로 변경
      • username은 자신의 GitHub 사용자명
    • 생성된 Repository 확인

    • 로컬로 Clone
      1
      2
      3
      4
      5
      6
      7
      8
      
        # 원하는 디렉토리로 이동
        cd ~/Documents
              
        # Repository Clone
        git clone https://github.com/username/username.github.io.git
              
        # 프로젝트 디렉토리로 이동
        cd username.github.io
      
  1. Template 사용하기

    • GitHub에서 “Use this template” 버튼 클릭
    • Repository name 입력
      • username.github.io 형식 권장
    • Public으로 설정
      • GitHub Pages는 Public Repository에서만 무료
    • “Create repository from template” 클릭

    • 생성된 Repository Clone
      1
      2
      
        git clone https://github.com/username/username.github.io.git
        cd username.github.io
      

Jekyll 블로그 설정

의존성 설치

  • Gemfile 확인
    • 프로젝트 루트에 있는 Gemfile 열기
    • 테마에서 제공하는 기본 Gemfile 사용
    • 필요한 gem 패키지 목록 예시
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      
      source "https://rubygems.org"
          
      gem "jekyll"
      gem "jekyll-theme-chirpy"
          
      # Windows and JRuby does not include zoneinfo files
      install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do
        gem "tzinfo"
        gem "tzinfo-data"
      end
          
      # Performance-booster for watching directories on Windows
      gem "wdm", :install_if => Gem.win_platform?
          
      # Jekyll compatibility with Ruby 3.0
      gem "webrick"
      
  • Bundle 설치 실행
    1
    2
    
    # 의존성 설치
    bundle install
    
  • 설치 확인
    1
    2
    
    # Jekyll 버전 확인
    bundle exec jekyll -v
    

블로그 기본 설정

  • _config.yml 파일 수정
    • 기본 정보 설정
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      
      # 사이트 제목
      title: 
          
      # 사이트 설명
      tagline: 
          
      # 사이트 URL
      url: "https://username.github.io"
          
      # GitHub 사용자명
      github:
        username: username
          
      # 소셜 정보
      social:
        name: Your Name
        email: your.email@example.com
        links:
          - https://github.com/username
          - https://twitter.com/username
          
      # 타임존 설정
      timezone: Asia/Seoul
          
      # 언어 설정
      lang: ko-KR
      
    • 테마 설정
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      
      # 테마 모드
      theme_mode: dual  # [light | dark | dual]
          
      # 아바타 이미지
      avatar: /assets/img/profile.jpg
          
      # TOC (Table of Contents) 설정
      toc: true
          
      # 댓글 시스템 설정
      comments:
        active: giscus  # [disqus | utterances | giscus]
            
        # Giscus 설정 
        giscus:
          repo: username/username.github.io
          repo_id: YOUR_REPO_ID
          category: Comments
          category_id: YOUR_CATEGORY_ID
          
      # Google Analytics
      google_analytics:
        id: G-XXXXXXXXXX
      

프로필 이미지 추가

  • 이미지 파일 준비
    • 정사각형 이미지 권장
      • 추천 크기: 512x512px
    • 파일 형식
      • PNG, JPG 지원
    • 파일 배치
      • assets/img 디렉토리에 이미지 파일 복사
      • _config.yml의 avatar 경로와 일치하도록 저장

로컬에서 블로그 실행하기

Jekyll 개발 서버 시작

  • 기본 실행 방법
    1
    2
    
    # 프로젝트 디렉토리에서 실행
    bundle exec jekyll serve
    
  • 자동 새로고침 옵션
    1
    2
    3
    4
    
    # LiveReload 기능 활성화
    bundle exec jekyll serve --livereload
      
    # 브라우저에서 파일 수정 시 자동 새로고침됨
    
  • 포트 변경
    1
    2
    
    # 다른 포트로 실행 (기본: 4000)
    bundle exec jekyll serve --port 4001
    
  • 빌드 캐시 초기화
    1
    2
    3
    
    # 기존 빌드 파일 삭제 후 실행
    bundle exec jekyll clean
    bundle exec jekyll serve
    

브라우저에서 확인

  • 로컬 서버 접속
    • 주소창에 입력
      • http://localhost:4000
      • http://127.0.0.1:4000
    • 블로그 메인 페이지 확인
    • 메뉴 및 기능 테스트
  • 변경사항 실시간 확인
    • 파일 수정 후 저장
    • LiveReload 사용 시 자동 새로고침
    • 수동 새로고침 필요 시
      • Windows: Ctrl + R 또는 F5
      • Mac: Cmd + R
    • 브라우저 캐시 강제 새로고침
      • Windows: Ctrl + Shift + R
      • Mac: Cmd + Shift + R

첫 번째 포스트 작성하기

포스트 파일 생성

  • 파일 이름 규칙
    • 형식
      • YYYY-MM-DD-title.md
    • 예시
      • 2025-10-11-my-first-post.md
    • 위치
      • _posts 디렉토리에 생성
  • 포스트 파일 생성
    • _posts 디렉토리에 새 파일 생성
      • 파일명: 2025-10-11-my-first-post.md
    • 텍스트 편집기로 열기
      • VSCode, 메모장 등 사용

Front Matter 작성

  • 기본 구조 ```yaml — title: “첫 번째 포스트” author: name: Your Name link: https://github.com/username date: 2025-10-11 14:00:00 +0900 category:
    • [Blog] tags:
    • [first post, jekyll, blog]

      ```

  • 주요 옵션 설명
    • title
      • 포스트 제목
      • 따옴표로 감싸기 권장
    • date
      • 작성 날짜와 시간
      • 타임존 포함
    • category
      • 카테고리 분류
      • 배열 형식으로 작성
      • 대분류, 소분류 지원
    • tags
      • 태그 목록
      • 배열 형식으로 작성
    • pin
      • 메인 페이지에 고정
      • true/false
    • math
      • 수학 수식 렌더링 활성화
      • true/false
    • mermaid
      • 다이어그램 렌더링 활성화
      • true/false

본문 작성

  • Markdown 기본 문법
    1
    2
    3
    4
    5
    6
    
    # 제목 1
    ## 제목 2
    ### 제목 3
      
    - 일반 텍스트 작성
      - 들여쓰기를 통한 계층 구조
    
  • 이미지 삽입
    • 이미지 추가 방법
      • 이미지 파일을 assets/img 폴더에 저장
      • Markdown에서 참조
        1
        
        ![이미지 설명](/assets/img/sample-image.jpg)
        
  • 코드 블록
    • 코드 작성 예시
      1
      2
      
      def hello_world():
          print("Hello, Jekyll!")
      
  • 링크 추가

GitHub Pages에 배포하기

Git 설정

  • Git 사용자 정보 설정
    1
    2
    3
    4
    5
    6
    
    # 전역 설정
    git config --global user.name "Your Name"
    git config --global user.email "your.email@example.com"
      
    # 설정 확인
    git config --list
    
  • Git 저장소 확인
    1
    2
    3
    
    # 이미 Clone한 경우 이 단계는 건너뜀
    # Git 상태 확인
    git status
    

변경사항 커밋

  • 작성한 포스트 추가
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # 새 파일 추가
    git add _posts/2025-10-11-my-first-post.md
      
    # 또는 모든 변경사항 추가
    git add .
      
    # 상태 확인
    git status
      
    # 커밋
    git commit -m "첫 번째 포스트 작성"
    
  • 설정 파일 변경사항 커밋
    1
    2
    3
    4
    5
    
    # 설정 파일 추가
    git add _config.yml
      
    # 커밋
    git commit -m "블로그 기본 설정 완료"
    

GitHub에 푸시

  • 원격 저장소 확인
    1
    2
    
    # 원격 저장소 목록 확인
    git remote -v
    
  • 변경사항 푸시
    1
    2
    3
    4
    5
    
    # main 브랜치에 푸시
    git push origin main
      
    # 또는 master 브랜치인 경우
    git push origin master
    

GitHub Pages 설정 확인

  • GitHub Repository 설정
    • GitHub에서 Repository 접속
    • Settings 메뉴 클릭
    • Pages 섹션으로 이동
    • Source 설정 확인
      • Branch: main (또는 master)
      • Folder: / (root)
    • Save 버튼 클릭
  • 배포 상태 확인
    • Actions 탭에서 빌드 진행 상황 확인
    • 녹색 체크 표시가 나타나면 배포 완료
  • 배포된 사이트 접속
    • 브라우저에서 접속
      • https://username.github.io
    • 포스트 확인
    • 기능 테스트

주요 디렉토리 구조 이해하기

Jekyll 프로젝트 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
username.github.io/
├── _config.yml           # 사이트 전역 설정
├── _posts/              # 블로그 포스트
│   └── YYYY-MM-DD-title.md
├── _layouts/            # 레이아웃 템플릿
│   ├── default.html
│   └── post.html
├── _includes/           # 재사용 가능한 컴포넌트
│   ├── header.html
│   └── footer.html
├── _sass/               # SASS 스타일시트
│   └── main.scss
├── assets/              # 정적 파일
│   ├── css/
│   ├── js/
│   └── img/
├── _site/               # 생성된 사이트 (Git 무시)
├── .gitignore           # Git 무시 파일 목록
├── Gemfile              # Ruby 의존성 정의
├── Gemfile.lock         # 의존성 버전 고정
└── index.html           # 메인 페이지

중요 디렉토리 설명

  • _posts
    • 역할
      • 블로그 포스트 저장 위치
    • 파일 규칙
      • YYYY-MM-DD-title.md 형식
    • 주의사항
      • 날짜가 미래인 포스트는 표시되지 않음
      • –future 옵션으로 확인 가능
  • assets
    • 역할
      • 이미지, CSS, JavaScript 등 정적 파일
    • 구조
      • img: 이미지 파일
      • css: 스타일시트
      • js: JavaScript 파일
    • 참조 방법
      • Markdown: /assets/img/image.jpg
      • HTML: /assets/img/image.jpg
  • _site
    • 역할
      • Jekyll이 생성한 정적 사이트
    • 특징
      • 빌드할 때마다 자동 생성
      • Git에 커밋하지 않음
    • 주의사항
      • 직접 수정하지 말 것
      • 수정 사항은 소스 파일에서

테마 커스터마이징

스타일 수정

  • SCSS 파일 위치
    • _sass 디렉토리
    • assets/css 디렉토리
  • 커스텀 스타일 추가
    • _sass 디렉토리에 custom.scss 파일 생성
  • 색상 변경 예시
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    // _sass/custom.scss
      
    // 메인 컬러 변경
    $primary-color: #007bff;
    $secondary-color: #6c757d;
      
    // 다크 모드 배경색
    $dark-bg: #1a1a1a;
      
    // 링크 색상
    a {
      color: $primary-color;
        
      &:hover {
        color: darken($primary-color, 10%);
      }
    }
    

레이아웃 수정

  • 레이아웃 파일 확인
    • _layouts 디렉토리
    • default.html
      • 기본 레이아웃
    • post.html
      • 포스트 레이아웃
    • page.html
      • 페이지 레이아웃
  • 커스텀 레이아웃 생성 ```html — layout: default —

    Jekyll 블로그 설치 및 로컬 실행 가이드

    <!DOCTYPE html>
Jekyll 블로그 이미지 자동 최적화 | MXXI.kr
Home Jekyll 블로그 이미지 자동 최적화
Post
Cancel

Jekyll 블로그 이미지 자동 최적화

개요

</h2>
  • Jekyll 기반 블로그에서 이미지 자동 최적화 시스템을 구축하여 웹 성능을 개선한 과정을 소개함

문제 상황 분석

</h2>

초기 성능 문제

</h3>
  • 기술 블로그에서 측정된 성능 지표
    • 이미지 용량
      • 149MB
    • 페이지 로딩 시간
      • 3-5초 (이미지 중심 페이지)
    • 이미지 파일 수
      • 1,000개 이상

이미지 현황 파악

</h3>
1
2
3
4
5
6
7
# 이미지 디렉토리 용량 분석
du -sh assets/img
# 결과: 149M	assets/img

# 이미지 파일 개수 확인
find assets/img -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" \) | wc -l
# 결과: 1,000개 이상의 이미지 파일
  • 이미지 파일 특성
    • 파일 형식
      • PNG, JPEG
    • 압축 상태
      • 압축되지 않은 원본 파일
    • 파일 수
      • 1,000개 이상의 이미지 파일

Core Web Vitals 측정

</h3>
  • Core Web Vitals 지표
    • Google이 정의한 웹사이트 사용자 경험을 측정하는 핵심 지표

    • 측정 방법
      • 측정 도구
        • Chrome DevTools, Lighthouse
      • 측정 환경
        • 로컬 Jekyll 서버 (localhost:4000)
      1
      2
      3
      
        # Lighthouse CLI를 사용한 성능 측정
        npm install -g lighthouse
        lighthouse http://localhost:4000 --output=json --output-path=./lighthouse-report.json
      
    • 측정된 Core Web Vitals 지표

      • LCP (Largest Contentful Paint): 3.2초
      • 페이지의 가장 큰 콘텐츠 요소가 화면에 렌더링되는 시간
      • 좋은 점수: 2.5초 이하, 개선 필요: 4.0초 초과
      • 이미지가 가장 큰 콘텐츠인 경우 로딩 시간에 직접 영향

      • CLS (Cumulative Layout Shift): 0.15
      • 페이지 로딩 중 예상치 못한 레이아웃 변화의 정도
      • 좋은 점수: 0.1 이하, 개선 필요: 0.25 초과
      • 이미지 로딩 시 크기 변화로 인한 레이아웃 시프트 발생

      • FID (First Input Delay): 180ms
      • 사용자가 페이지와 처음 상호작용할 때의 응답 시간
      • 좋은 점수: 100ms 이하, 개선 필요: 300ms 초과
      • 대용량 이미지 로딩으로 인한 메인 스레드 블로킹 영향

자동화 시스템 구성

</h2>

이미지 최적화 도구 설치

</h3>
1
2
3
4
5
# 이미지 최적화 도구 설치
brew install pngquant jpegoptim

# 설치 확인
which pngquant && which jpegoptim

자동 최적화 스크립트 생성

</h3>
  • 파일 생성 위치
    • 프로젝트 루트 디렉토리에 auto-optimize-images.js 파일 생성
    • 실행 권한 부여
      1
      
        chmod +x auto-optimize-images.js
      
  • auto-optimize-images.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    
      #!/usr/bin/env node
    
      const fs = require('fs');
      const path = require('path');
      const { execSync } = require('child_process');
    
      // 설정
      const IMG_DIR = 'assets/img';
      const QUALITY = 85;
      const SKIP_FAVICONS = true;
    
      // 이미지 최적화 함수
      function optimizeImage(filePath) {
          const ext = path.extname(filePath).toLowerCase();
            
          try {
              if (ext === '.png') {
                  execSync(`pngquant --force --ext .png --quality=65-${QUALITY} "${filePath}"`, { stdio: 'ignore' });
              } else if (ext === '.jpg' || ext === '.jpeg') {
                  execSync(`jpegoptim --max=${QUALITY} --strip-all "${filePath}"`, { stdio: 'ignore' });
              }
              return true;
          } catch (error) {
              return false;
          }
      }
    
      // 새로 추가된 이미지 파일 찾기
      function getNewImages() {
          try {
              const addedFiles = execSync('git diff --cached --name-status', { encoding: 'utf8' });
              const newImages = [];
              const lines = addedFiles.split('\n');
                
              lines.forEach(line => {
                  if (line.startsWith('A\t') && line.includes(IMG_DIR)) {
                      const filePath = line.substring(2);
                      const ext = path.extname(filePath).toLowerCase();
                      if (['.png', '.jpg', '.jpeg'].includes(ext)) {
                          if (!SKIP_FAVICONS || !filePath.includes('favicon')) {
                              newImages.push(filePath);
                          }
                      }
                  }
              });
                
              return newImages;
          } catch (error) {
              return [];
          }
      }
    
      // 메인 실행
      function main() {
          console.log('이미지 자동 최적화 시작...');
            
          const newImages = getNewImages();
            
          if (newImages.length === 0) {
              console.log('최적화할 새 이미지가 없습니다.');
              return;
          }
            
          console.log(`${newImages.length}개의 새 이미지를 발견했습니다.`);
            
          let optimized = 0;
          let failed = 0;
            
          newImages.forEach(imagePath => {
              console.log(`최적화 중: ${imagePath}`);
                
              if (optimizeImage(imagePath)) {
                  optimized++;
                  console.log(`완료: ${imagePath}`);
              } else {
                  failed++;
                  console.log(`실패: ${imagePath}`);
              }
          });
            
          console.log(`최적화 완료: ${optimized}개 성공, ${failed}개 실패`);
            
          if (optimized > 0) {
              console.log('최적화된 파일들을 Git에 다시 추가합니다...');
              try {
                  execSync(`git add ${newImages.join(' ')}`, { stdio: 'ignore' });
                  console.log('Git에 추가 완료!');
              } catch (error) {
                  console.log('Git 추가 실패:', error.message);
              }
          }
      }
    
      main();
    

Git 훅 설정

</h3>
  • 파일 생성 위치
    • .git/hooks/pre-commit 파일 생성
    • 실행 권한 부여
      1
      
        chmod +x .git/hooks/pre-commit
      
  • pre-commit 훅

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
      #!/bin/bash
    
      # 자동 이미지 최적화 Git 훅
      echo "이미지 최적화를 확인합니다..."
    
      # Node.js가 설치되어 있는지 확인
      if ! command -v node &> /dev/null; then
          echo "Node.js가 설치되어 있지 않습니다. 이미지 최적화를 건너뜁니다."
          exit 0
      fi
    
      # 이미지 최적화 도구가 설치되어 있는지 확인
      if ! command -v pngquant &> /dev/null || ! command -v jpegoptim &> /dev/null; then
          echo "이미지 최적화 도구가 설치되어 있지 않습니다."
          echo "다음 명령어로 설치하세요: brew install pngquant jpegoptim"
          exit 0
      fi
    
      # 자동 최적화 스크립트 실행
      node auto-optimize-images.js
    
      echo "이미지 최적화 완료!"
    

실시간 파일 감시 스크립트

</h3>
  • 파일 생성 위치
    • 프로젝트 루트 디렉토리에 watch-images.js 파일 생성
    • 실행 권한 부여
      1
      
        chmod +x watch-images.js
      
  • watch-images.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
      #!/usr/bin/env node
    
      const fs = require('fs');
      const path = require('path');
      const { execSync } = require('child_process');
    
      // 설정
      const IMG_DIR = 'assets/img';
      const QUALITY = 85;
    
      // 이미지 최적화 함수
      function optimizeImage(filePath) {
          const ext = path.extname(filePath).toLowerCase();
            
          try {
              if (ext === '.png') {
                  execSync(`pngquant --force --ext .png --quality=65-${QUALITY} "${filePath}"`, { stdio: 'ignore' });
              } else if (ext === '.jpg' || ext === '.jpeg') {
                  execSync(`jpegoptim --max=${QUALITY} --strip-all "${filePath}"`, { stdio: 'ignore' });
              }
              return true;
          } catch (error) {
              return false;
          }
      }
    
      // 파일 감시 시작
      function startWatching() {
          console.log('이미지 파일 감시를 시작합니다...');
          console.log('감시 디렉토리:', IMG_DIR);
          console.log('품질 설정:', QUALITY + '%');
          console.log('종료하려면 Ctrl+C를 누르세요\n');
            
          fs.watch(IMG_DIR, { recursive: true }, (eventType, filename) => {
              if (eventType === 'rename' && filename) {
                  const filePath = path.join(IMG_DIR, filename);
                  const ext = path.extname(filename).toLowerCase();
                    
                  if (['.png', '.jpg', '.jpeg'].includes(ext)) {
                      setTimeout(() => {
                          if (fs.existsSync(filePath)) {
                              console.log(`새 이미지 발견: ${filename}`);
                                
                              if (optimizeImage(filePath)) {
                                  console.log(`최적화 완료: ${filename}`);
                              } else {
                                  console.log(`최적화 실패: ${filename}`);
                              }
                          }
                      }, 1000);
                  }
              }
          });
      }
    
      startWatching();
    

사용 방법

</h2>

Git 훅 방식

</h3>
1
2
3
4
# 이미지 추가 후 커밋하면 자동으로 최적화됨
git add assets/img/new-image.png
git commit -m "새 이미지 추가"
# 자동으로 최적화 후 커밋됨

수동 실행

</h3>
1
2
# 새로 추가된 이미지만 최적화
npm run auto-optimize

실시간 감시

</h3>
1
2
# 터미널에서 실행하면 이미지 추가 시 실시간 최적화
npm run watch-images

package.json 설정

</h3>
  • 파일 생성 위치
    • 프로젝트 루트 디렉토리의 package.json 파일에 scripts 섹션 추가
    • 기존 scripts 섹션이 있다면 해당 내용을 추가
  • package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      {
      "scripts": {
          "build": "gulp build",
          "dev": "gulp dev",
          "optimize-images": "node optimize-images-safe.js",
          "auto-optimize": "node auto-optimize-images.js",
          "watch-images": "node watch-images.js",
          "test": "echo 'Testing blog functionality...'"
      }
      }
    

성능 최적화 결과

</h2>

최적화 전후 비교

</h3>
  • 용량 최적화 결과

    1
    2
    3
    4
    5
    6
    7
    
      # 최적화 전
      du -sh assets/img
      # 결과: 149M	assets/img
    
      # 최적화 후
      du -sh assets/img
      # 결과: 45M	assets/img
    
  • 페이지 로딩 시간 개선 (Chrome DevTools 기준)

    페이지 유형최적화 전최적화 후개선율
    이미지 중심 포스트3-5초1-2초60-70%
    일반 포스트2-3초0.8-1.5초50-60%
    메인 페이지4-6초1.5-2.5초60-70%

Core Web Vitals 개선 효과

</h3>
  • Lighthouse 성능 점수
    • 최적화 전
      • Performance: 65-70점
      • LCP: 3.2초
      • CLS: 0.15
      • FID: 180ms
    • 최적화 후
      • Performance: 85-90점
      • LCP: 1.8초 (44% 개선)
      • CLS: 0.05 (67% 개선)
      • FID: 95ms (47% 개선)

최적화 결과 요약

</h2>

핵심 성과

</h3>
항목최적화 전최적화 후개선율
이미지 용량149MB45MB70% 감소
페이지 로딩 시간3-5초1-2초60-70% 단축
Lighthouse 점수65-70점85-90점20-25점 향상
LCP3.2초1.8초44% 개선
CLS0.150.0567% 개선
FID180ms95ms47% 개선

적용된 기술

</h3>
  • 이미지 압축
    • pngquant, jpegoptim
  • 자동화
    • Git pre-commit 훅
  • 모니터링
    • Lighthouse, Chrome DevTools
  • 스크립트
    • Node.js 기반 최적화 도구

트러블슈팅

</h2>

자주 발생하는 문제와 해결 방법

</h3>
  • 이미지 최적화 도구 설치 오류
    • 문제
      • pngquant 또는 jpegoptim 명령어를 찾을 수 없음
      1
      2
      3
      
        # 오류 메시지
        command not found: pngquant
        command not found: jpegoptim
      
    • 해결 방법

      1
      2
      3
      4
      5
      
        # macOS
        brew install pngquant jpegoptim
      
        # Ubuntu/Debian
        sudo apt-get install pngquant jpegoptim
      
  • Git 훅 실행 권한 문제
    • 문제
      • pre-commit 훅이 실행되지 않음
      1
      2
      
        # 오류 메시지
        .git/hooks/pre-commit: Permission denied
      
    • 해결 방법

      1
      2
      3
      4
      5
      
        # 실행 권한 부여
        chmod +x .git/hooks/pre-commit
      
        # 권한 확인
        ls -la .git/hooks/pre-commit
      
  • 이미지 최적화 실패
    • 문제: 일부 이미지 파일이 최적화되지 않음

    • 원인 분석
      • 손상된 이미지 파일
      • 권한 문제
      • 디스크 공간 부족
    • 해결 방법
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
        # 이미지 파일 무결성 확인
        file assets/img/problematic-image.png
      
        # 권한 확인 및 수정
        chmod 644 assets/img/*.png
        chmod 644 assets/img/*.jpg
      
        # 디스크 공간 확인
        df -h
      
  • Node.js 버전 호환성 문제
    • 문제
      • 스크립트 실행 시 Node.js 버전 오류
    • 해결 방법
      1
      2
      3
      4
      5
      6
      
        # Node.js 버전 확인
        node --version
      
        # nvm을 사용한 버전 관리
        nvm install 16
        nvm use 16
      
  • Git 훅이 실행되지 않는 문제
    • 문제
      • pre-commit 훅을 설정했지만 이미지 최적화가 실행되지 않음
    • 원인 분석
      • Git 훅이 비활성화되어 있음
      • 훅 파일이 올바른 위치에 없음
      • Git 설정에서 훅이 무시됨
    • 해결 방법
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        # Git 훅 활성화 확인
        git config core.hooksPath
      
        # 훅 파일 위치 확인
        ls -la .git/hooks/pre-commit
      
        # Git 훅 경로 설정 (필요시)
        git config core.hooksPath .git/hooks
      
        # 훅 테스트
        git add assets/img/test-image.png
        git commit -m "훅 테스트"
      
  • 이미지 품질 최적화 문제
    • 문제
      • 최적화 후 이미지 품질이 너무 낮아짐
      • 일부 이미지에서 아티팩트 발생
    • 원인 분석
      • 압축 품질 설정이 너무 낮음 (85%)
      • 이미지 유형에 따른 최적화 설정 부족
      • 원본 이미지 품질 문제
    • 해결 방법
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
        # 품질 설정 조정 (auto-optimize-images.js 수정)
        const QUALITY = 90; // 85에서 90으로 상향 조정
      
        # 이미지 유형별 품질 설정
        if (ext === '.png') {
            // PNG는 더 높은 품질 유지
            execSync(`pngquant --quality=80-95 "${filePath}"`);
        } else if (ext === '.jpg' || ext === '.jpeg') {
            // JPEG는 적당한 품질
            execSync(`jpegoptim --max=90 "${filePath}"`);
        }
      
        # 원본 이미지 품질 확인
        identify -verbose assets/img/sample-image.jpg
      

Reference

</h2>
Contents
1
2
  </div>
</article>

</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
### 메뉴 커스터마이징

- Chirpy 테마 메뉴 관리
  - `_tabs` 디렉토리에서 관리
  - 기본 메뉴
    - about.md, archives.md, categories.md, tags.md

- 새 메뉴 추가하기
  - _tabs 디렉토리에 새 파일 생성
    - 예: projects.md
  - Front Matter 설정
    ```yaml
    ---
    layout: page
    title: Projects
    icon: fas fa-folder
    order: 5
    ---
    
    # Projects
    
    - 여기에 프로젝트 내용 작성
    ```
  - order 값으로 메뉴 순서 조정
    - 숫자가 작을수록 왼쪽에 배치
    - 기본 메뉴들의 order 값 참고
  - 아이콘 변경
    - Font Awesome 아이콘 사용
    - [Font Awesome Icons](https://fontawesome.com/icons) 참고

## 트러블슈팅

### 자주 발생하는 문제와 해결 방법

#### Ruby 버전 호환성 문제

- 문제 상황
  - Jekyll 빌드 시 Ruby 버전 오류 발생
    ```bash
    # 오류 메시지
    Error: Your Ruby version is 2.7.0, but your Gemfile specified ~> 3.0
    ```

- 해결 방법
  - rbenv로 Ruby 버전 변경
    ```bash
    # 설치 가능한 Ruby 버전 확인
    rbenv install -l
    
    # 필요한 버전 설치 (Gemfile 요구사항에 맞는 버전)
    rbenv install [버전번호]
    
    # 프로젝트에 Ruby 버전 설정
    rbenv local [버전번호]
    
    # 버전 확인
    ruby -v
    
    # Bundle 재설치
    bundle install
    ```

#### Bundler 버전 충돌

- 문제 상황
  - Gemfile.lock에 명시된 Bundler 버전과 설치된 버전이 다름
    ```bash
    # 오류 메시지
    Bundler could not find compatible versions for gem "bundler"
    ```

- 해결 방법
  ```bash
  # Bundler 업데이트
  gem install bundler
  bundle install
  
  # 또는 Gemfile.lock 삭제 후 재생성
  # Windows PowerShell: Remove-Item Gemfile.lock
  # Git Bash / Mac / Linux: rm Gemfile.lock
  bundle install
  
  # 또는 특정 버전 설치 후 사용 (Gemfile.lock에 명시된 버전)
  gem install bundler -v [버전번호]
  bundle install

포트 충돌 오류

  • 문제 상황
    • 4000번 포트가 이미 사용 중
      1
      2
      
      # 오류 메시지
      Address already in use - bind(2) for 127.0.0.1:4000
      
  • 해결 방법
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    # 다른 포트로 실행
    bundle exec jekyll serve --port 4001
      
    # 또는 기존 프로세스 종료 (Windows)
    netstat -ano | findstr :4000
    taskkill /PID [프로세스ID] /F
      
    # 또는 기존 프로세스 종료 (Mac/Linux)
    lsof -ti:4000 | xargs kill -9
    

파일 변경사항이 반영되지 않음

  • 문제 상황
    • 파일 수정 후 변경사항이 보이지 않음
    • LiveReload가 작동하지 않음
  • 해결 방법
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    # 캐시 삭제 후 재실행
    bundle exec jekyll clean
    bundle exec jekyll serve --livereload
      
    # 브라우저 캐시 강제 새로고침
    # Windows: Ctrl + Shift + R
    # Mac: Cmd + Shift + R
      
    # _config.yml 변경 시 서버 재시작 필요
    # Ctrl + C로 중단 후 다시 실행
    

이미지가 표시되지 않음

  • 문제 상황
    • Markdown에 이미지 추가했지만 화면에 나타나지 않음
  • 원인 분석
    • 이미지 경로 오류
    • 파일 이름 대소문자 불일치
    • 상대 경로 문제
  • 해결 방법
    • 절대 경로 사용 권장
      • 올바른 방법
        1
        
        ![이미지 설명](/assets/img/sample.jpg)
        
      • 잘못된 방법
        1
        
        ![이미지 설명](../../assets/img/sample.jpg)
        
    • 파일 이름 확인
      • Linux/Mac은 대소문자 구분
      • sample.jpg ≠ Sample.jpg
    • 이미지 파일 존재 확인
      • 파일 탐색기에서 assets/img 디렉토리 확인
      • 파일 이름과 경로가 정확한지 확인

GitHub Pages 배포 실패

  • 문제 상황
    • Push 후 사이트가 업데이트되지 않음
    • GitHub Actions에서 빌드 실패
  • 해결 방법
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    # 1. Actions 탭에서 오류 로그 확인
    # GitHub Repository > Actions 탭 클릭
    # 실패한 워크플로우 클릭하여 로그 확인
      
    # 2. 로컬에서 빌드 테스트
    bundle exec jekyll build
      
    # 3. Gemfile.lock 커밋 확인
    git add Gemfile.lock
    git commit -m "Update Gemfile.lock"
    git push origin main
      
    # 4. GitHub Pages 설정 재확인
    # Settings > Pages > Source 확인
    

Liquid 문법 오류

  • 문제 상황
    • 포스트에서 중괄호 사용 시 빌드 오류
      1
      2
      
      # 오류 메시지
      Liquid Exception: Liquid syntax error
      
  • 해결 방법
    • Liquid 문법 이스케이프
      • raw 태그 사용
        1
        2
        3
        
              
        {{ 중괄호 내용을 그대로 표시 }}
              
        
    • 코드 블록에서 자동 이스케이프
      • 백틱 3개로 감싸기
        1
        
        print("")
        

한글 깨짐 문제

  • 문제 상황
    • Windows에서 한글이 깨져서 표시됨
  • 해결 방법
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    # 파일 인코딩을 UTF-8로 저장
    # VSCode 설정
    # File > Preferences > Settings
    # "files.encoding": "utf8" 확인
      
    # PowerShell 인코딩 설정
    chcp 65001
      
    # _config.yml에 인코딩 명시
    encoding: utf-8
    

성능 최적화 팁

이미지 최적화

  • 이미지 압축 도구 사용
    • 도구 설치
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      # macOS
      brew install pngquant jpegoptim
          
      # Ubuntu/Debian
      sudo apt-get install pngquant jpegoptim
          
      # Windows
      # pngquant: https://pngquant.org/
      # jpegoptim: Linux/Mac 전용, Windows는 온라인 도구 사용 권장
      
    • 이미지 압축 실행
      1
      2
      3
      4
      5
      
      # PNG 압축
      pngquant --quality=65-80 assets/img/*.png
          
      # JPEG 압축 (Mac/Linux)
      jpegoptim --max=85 assets/img/*.jpg
      
  • WebP 형식 사용
    • 변환 도구 설치
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      # macOS
      brew install webp
          
      # Ubuntu/Debian
      sudo apt-get install webp
          
      # Windows
      # Google WebP 공식 사이트에서 다운로드
      # https://developers.google.com/speed/webp/download
      
    • 이미지 변환
      1
      
      cwebp -q 80 input.jpg -o output.webp
      

빌드 시간 단축

  • Incremental 빌드 활성화
    1
    
    bundle exec jekyll serve --incremental
    
    • 주의사항
      • 불안정할 수 있으며 변경사항이 누락될 수 있음
      • 파일 수정이 제대로 반영되지 않으면 jekyll clean 후 재실행 권장
      • 프로덕션 빌드에서는 사용하지 않는 것을 권장
  • 불필요한 플러그인 비활성화
    • _config.yml에서 사용하지 않는 플러그인 제거
  • 개발 환경 설정
    • _config.yml 파일 분리
      1
      2
      3
      4
      5
      
      # _config.yml (프로덕션)
      environment: production
          
      # _config_dev.yml (개발)
      environment: development
      
    • 개발 환경으로 실행
      1
      
      bundle exec jekyll serve --config _config.yml,_config_dev.yml
      

유용한 명령어 정리

Jekyll 명령어

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 새 Jekyll 사이트 생성
jekyll new my-blog

# 개발 서버 실행
bundle exec jekyll serve

# LiveReload로 실행
bundle exec jekyll serve --livereload

# 미래 날짜 포스트 포함
bundle exec jekyll serve --future

# 다른 포트로 실행
bundle exec jekyll serve --port 4001

# 증분 빌드 (주의: 불안정할 수 있음)
bundle exec jekyll serve --incremental

# 상세 로그 출력
bundle exec jekyll serve --verbose

# 빌드만 실행 (서버 미실행)
bundle exec jekyll build

# 캐시 삭제
bundle exec jekyll clean

# 버전 확인
bundle exec jekyll -v

Git 명령어

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 저장소 클론
git clone https://github.com/username/username.github.io.git

# 상태 확인
git status

# 변경사항 추가
git add .
git add filename

# 커밋
git commit -m "커밋 메시지"

# 푸시
git push origin main

# 풀
git pull origin main

# 브랜치 생성 및 전환
git checkout -b new-branch

# 브랜치 목록 확인
git branch

# 로그 확인
git log --oneline

# 변경사항 되돌리기
git checkout -- filename

Bundle 명령어

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 의존성 설치
bundle install

# 의존성 업데이트
bundle update

# 특정 gem 업데이트
bundle update jekyll

# 설치된 gem 목록
bundle list

# gem 정보 확인
bundle info jekyll

# 실행 환경 확인
bundle env

# Gemfile.lock 삭제 후 재생성
# Windows PowerShell
Remove-Item Gemfile.lock
bundle install

# Git Bash / Mac / Linux
rm Gemfile.lock
bundle install

Reference

Contents