個人ブログ
2025-02-10 ~ Present
説明
Astroで作った個人ブログです。
自分の簡単な紹介、これまでのプロジェクト、時間のあるときに書いた記事を読めます。
Blog・Project・PlaygroundにはAstroのContent Apiを使い、各投稿を.mdxファイルで書くことでコンポーネントを埋め込めるようにしています。
プロジェクトの画面





サイトリンク
技術スタック
- Astro: SSGフレームワーク
- React: 主要コンポーネントの作成
- TailwindCSS: スタイリング
- Framer Motion: アニメーション
- Github Actions: 自動デプロイ
- Docker: コンテナイメージのビルド
- Nginx: Webサーバー
- Cloudflare: ドメイン管理
開発の過程
技術の選定
- Astro
- state of js 2024で関心・注目・肯定的評価の3冠を獲得するほど、メタフレームワークとして注目されていた
- そこでAstroを使った個人ブログを作りたくなり、このプロジェクトを始めた
- Astroの詳しい評価はブログ記事を参照。
Astroフレームワークの評価
- React
- 今も多くの人から圧倒的に支持されるReactに、もっと慣れたかった
- 最近とても人気のあるReactベースのCSS Library、Shadcn UIを使ってみたかった
UIの構成
- アニメーションや動きのある効果を付けたくて、MotionとTailwindCSSを組み合わせて実装した。
![]() | ![]() |
- 使いやすさのため、レスポンシブUIとDark/Lightモードを開発
| PC画面 | Mobile画面 |
|---|---|
![]() | ![]() |
| Darkモード | Lightモード |
|---|---|
![]() | ![]() |
ブログページの開発
-
AstroのContent APIを活用
- ブログ記事をMarkdownで書きたかったため、AstroのContent APIを使った
/*** 파일 경로: ./src/content/config.ts* 역할 설명: mdx의 frontmatter에 적혀있는 속성을 스키마로 가지는 콜렉션 지정*/import { defineCollection, z } from 'astro:content';const blog = defineCollection({type: 'content',schema: z.object({title: z.string(),category: z.string(),thumbnail: z.string().optional(),created: z.coerce.date(),tags: z.array(z.string()).optional(),updated: z.coerce.date().optional(),}),});export const collections = { blog };/*** 파일 경로: ./pages/blog/[...slug].astro* 역할 설명: post slug 경로와 일치하는 mdx를 렌더링하는 동적 페이지 생성*/---import { type CollectionEntry, getCollection } from 'astro:content';export async function getStaticPaths() {const posts = await getCollection('blog');return posts.map((post, index) => ({params: { slug: post.slug },props: {post,prev: posts[index - 1] || null,next: posts[index + 1] || null,},}));}const { post, prev, next } = Astro.props;const { Content } = await post.render();---<MdLayout post={post.data} nav={{ prev, next }} url={`/blog/${post.slug}`}><Content /></MdLayout> -
画面構成
ブログ一覧画面 ブログ記事画面 

-
投稿検索用のfuzz searchを実装
- fuse.jsを使い、ユーザーが検索しやすいようにした
-
アセットローダーとコード表示のためのMDX処理
- Expressive code、Mermaid、Katexを追加
- 詳しくはブログ記事を参照。https://www.jun-devlog.win/blog/web/common/markdown-test-mdx
Expressive code Mermaid Katex 


-
画像の遅延読み込みに対応したImageLoaderを開発
// 이미지 로더---import { getBasePathWithUrl } from '@/utils/getBasePathWithUrl.ts';import React from 'react';type Props = {src?: string;alt?: string;class?: string;width?: number;height?: number;};const { src, alt = 'blog-image', class: className, width, height } = Astro.props;---<imgsrc={getBasePathWithUrl(src)}alt={alt ?? 'blog-image'}loading="lazy"onerror={`this.src='/fallbackImg.svg'`}class={className}width={width}height={height}/>// mdx 파일---title: Astro에 대해서created: 2025-02-26updated: 2025-02-27tags: ['blog', 'astro', 'meta-framework']category: Webthumbnail: /files/blog/web/astro/assets/CleanShot_2025-02-26_20.22.28@2x.webp---import ImageLoader from '@/components/Blog/ImageLoader.astro';import VideoLoader from '@/components/Blog/VideoLoader.astro';<ImageLoader src="/files/blog/web/astro/assets/[email protected]" alt="CleanShot_2025-02-26_20.22.28@2x" />## 시작으로앞서 작성한 블로그 소개 글에서 언급했듯, 개발 블로그를 만들기 위하여 Astro를 사용해본 경험, 사용법에 대하여 기술하겠습니다....
-
投稿データを前処理するjsファイルを追加
- Markdownエディターで記事を書いてからブログサイトに追加するため、前処理が必要
- 画像パスや他のコンポーネントを追加する前処理プラグインを作り、コンテンツ追加前に実行する
- addMdEnter.js
- convertLoader.js
- removeUnusedImages.js
Docker・NginxによるWebサーバーと自動デプロイ環境の構築
問題の把握と解決策の検討
- 開発初期はnetlifyにデプロイしてサイトを作成
- 問題: 写真が増えるにつれ、GitHubで容量超過の警告が出始めた
- 解決策: Amazon S3か個人のファイルサーバーを用意し、ブログのアセットを保存する
- 個人のLinuxサーバーにファイルサーバーを構築することにしたが、 構成を変えるついでに、WebサーバーもLinuxサーバーへ移すことにした
Webサーバーと自動デプロイ環境の構成
-
Github Action runnerのインストール
- GitHubのガイドに従い、Linuxサーバーにself-hosted runnerをインストール
-
nginx・docker file・workflowの設定
- リモートブランチへのpush時にrunnerがビルド・デプロイするようworkflowを設定
- デプロイ時にdocker fileでイメージをビルドし、指定設定でNginxコンテナを作成・実行
- Cloud flareでドメインを設定し、ネームサーバー経由でアクセス可能にした
workflow.yaml name: Astro Blogon:push:branches:- master # 배포를 트리거하는 브랜치jobs:build:runs-on: self-hostedsteps:- name: Checkoutuses: actions/checkout@v4- uses: pnpm/action-setup@v4name: Install pnpmwith:version: 10run_install: false- name: Install Node.jsuses: actions/setup-node@v4with:node-version: 22cache: 'pnpm'- name: Install dependenciesrun: pnpm install- name: Buildrun: pnpm builddeploy:runs-on: self-hostedneeds: buildsteps:- name: Build Docker Imagerun: DOCKER_BUILDKIT=1 docker build -t astro-blog .- name: docker stop & remove prerun: docker stop astro-blog && docker rm astro-blog- name: docker runrun: docker run -d -v astro-blog-volume:/home/files --name astro-blog -p 4321:80 astro-blogDockerfile FROM ubuntu/nginx:1.18-22.04_betaENV TZ="Asia/Seoul"COPY ./nginx.conf /etc/nginx/nginx.confCOPY ./dist /var/www/htmlnginx.conf worker_processes 1;events {worker_connections 1024;}http {server {listen 80;server_name _;root /var/www/html;index index.html index.htm;include /etc/nginx/mime.types;gzip on;gzip_min_length 1000;gzip_proxied expired no-cache no-store private auth;gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;error_page 404 /404.html;location = /404.html {root /var/www/html;internal;}location / { #try_files $uri $uri/index.html =404;}location /files { # 파일 서버alias /home/files;}}} -
docker volumeに画像を保存し、nginxで構成したファイルサーバーから読み込めるように設定





