# soohan-dev

- URL: https://soohan.dev/projects/personal/soohan-dev
- Category: projects/personal
- Published: 2026-07-21
- Tags: nextjs, mdx, vercel
- Author: Soohan Park

> 경력과 프로젝트, 오픈소스 기여 과정에서 남은 기록들과 이런저런 생각들을 한 곳에 모으기 위해 만든 장소.

---

이력서는 결과를 짧게 압축하고 저장소는 코드를 보관합니다. 둘 다 필요하지만, 왜 그런 구조를
선택했는지, 라이브에서 무엇이 달라졌는지, 몇 년 뒤에도 직접 고치고 있는 것은 무엇인지까지
담기에는 부족했습니다. 프로젝트가 끝날 때마다 판단의 배경과 운영 이후의 경험이 흩어지는 것도
아쉬웠습니다.

`soohan-dev`는 그 사이를 채우기 위해 만든 개인 사이트입니다. 경력과 프로젝트, 오픈소스 기여,
일하며 부딪힌 문제와 그 밖의 기록을 한곳에 모읍니다. 완성된 결과를 전시하는 포트폴리오보다,
시간이 지나도 작업의 맥락을 다시 찾을 수 있는 저장소에 가깝습니다.

## 흩어진 기록을 한곳에

내용은 역할에 따라 세 갈래로 나눴습니다.

| 경로 | 담는 내용 |
| --- | --- |
| [`/user`](/user) | 지금 하는 일과 지금까지의 경력 |
| [`/projects`](/projects) | 소속별로 직접 책임진 작업, 개인 프로젝트, 오픈소스 기여 |
| [`/notes`](/notes) | 프로젝트 결과물 밖의 생각과 조사 기록 |

경력은 `/user`에서 한 번에 읽을 수 있지만, 프로젝트는 이력서의 한 줄로 끝내지 않습니다.
문제를 만난 배경, 선택한 설계, 운영하며 확인한 결과를 각각의 글로 남깁니다. 오픈소스 기여도
저장소 이름만 나열하지 않고 기여 하나마다 무엇을 바꿨고 왜 병합됐는지 기록합니다.

`notes`는 조금 다른 역할을 합니다. 아직 프로젝트로 묶이지 않는 생각이나 정기적으로 살펴보는
주제를 보관합니다. 무엇을 만들었는지뿐 아니라, 그 과정에서 무엇을 읽고 생각했는지도 시간이
지나면 작업을 설명하는 맥락이 되기 때문입니다.

## 구조가 곧 탐색 방식

사이트의 정보 구조와 파일 구조를 일치시켰습니다. `content/` 아래의 디렉터리는 카테고리가 되고,
파일명은 URL이 됩니다. 이 구조를 왼쪽 사이드바가 그대로 보여줍니다.

```text
content/
├── _pages/user.mdx                 → /user
├── projects/
│   ├── nexon/                      → /projects/nexon
│   ├── open-source/                → /projects/open-source
│   └── personal/soohan-dev.mdx     → /projects/personal/soohan-dev
└── notes/
    ├── soohan/                     → /notes/soohan
    └── hanibot/research/           → /notes/hanibot/research
```

별도의 메뉴 데이터와 글 목록을 각각 관리하지 않습니다. 카테고리를 한 번 정의하고 MDX 파일을
추가하면 URL, 사이드바, 목록, 이전·다음 글이 같은 구조에서 파생됩니다. 콘텐츠가 늘어날수록
관리 지점도 함께 늘어나는 상황을 피하려는 선택입니다.

## 하나의 원본, 여러 독자

글의 원본은 MDX 파일 하나입니다. 빌드 과정이 파일을 읽고 검증한 뒤, 사람과 프로그램이 각자
읽기 좋은 형태를 만듭니다.

```text
content/**/*.mdx
        ↓ parse · validate
Post
├── HTML                  웹에서 읽는 글
├── /md/{slug}            Markdown 원문
├── rss.xml · sitemap.xml 구독과 검색
├── llms.txt              글 목록과 요약
├── llms-full.txt         전체 본문
└── BlogPosting JSON-LD   구조화된 메타데이터
```

브라우저로 방문한 사람에게는 정적 HTML을 제공하고, 피드 리더에는 RSS를 제공합니다. Markdown
원문과 `llms.txt`, `llms-full.txt`도 함께 만들어 AI나 다른 도구가 화면을 다시 파싱하지 않고
내용에 접근할 수 있게 했습니다. 독자마다 별도의 콘텐츠를 작성하는 대신 같은 원본을 다른
인터페이스로 내보냅니다.

Next.js App Router는 이 경로들을 정적으로 생성하고, MDX는 글 안에서 링크·표·코드뿐 아니라
이미지처럼 동작이 필요한 컴포넌트도 사용할 수 있게 합니다. 기술을 선택한 기준은 기능의 수보다
하나의 원본으로 이 인터페이스들을 얼마나 단순하게 유지할 수 있는지였습니다.

## 배포 전에 실패하게

파일 기반 구조는 단순하지만 잘못된 파일도 그대로 원본이 될 수 있습니다. 그래서 콘텐츠를 읽는
단계에서 `title`, `date`, `summary`가 모두 있는지, 날짜가 유효한지, 등록된 카테고리인지
검사합니다. URL로 쓰는 슬러그는 ASCII 소문자·숫자·하이픈만 허용합니다. 정적 생성에서는
통과하지만 실제 요청에서는 404가 되는 파일명이나, XML 피드를 깨뜨리는 문자를 배포 전에
차단하기 위해서입니다.

`draft: true`인 글은 개발 환경에서만 보이고 프로덕션 빌드에서는 제외됩니다. MDX 주석에 적어둔
작성 메모도 HTML뿐 아니라 Markdown과 `llms-full.txt`에서 함께 제거합니다. 어느 한 출력만
정상인 상태를 피하려고 모든 공개 경로가 같은 파싱 결과를 사용합니다.

빌드 뒤에는 실제 서버를 띄워 HTML과 Markdown 경로, 리다이렉트, RSS, sitemap, LLM용 문서를
확인합니다. 잘못된 콘텐츠를 런타임에서 조용히 보여주는 것보다 배포 파이프라인을 명확하게
실패시키는 편을 택했습니다.

## 적게 운영하고 오래 남기기

CMS와 데이터베이스는 두지 않았습니다. 이 사이트에서 필요한 편집 화면은 에디터이고, 버전 관리는
Git이며, 배포 트리거는 push로 충분했습니다. 관리 화면과 인증, 데이터베이스 백업을 운영하는 대신
텍스트 파일을 오래 보관하고 어디서든 다시 빌드할 수 있는 구조에 집중했습니다.

텍스트와 이미지는 분리했습니다. MDX는 저장소에 두고, 이미지는 Vercel Blob에 올린 뒤 크기 정보가
포함된 컴포넌트로 본문에 연결합니다. 저장소를 가볍게 유지하고 `next/image`의 최적화를 활용할 수
있는 대신, 외부 스토리지가 사라지면 과거 글의 이미지가 깨진다는 의존성을 받아들였습니다.
편의만 기록하지 않고 복구 비용까지 알고 선택하려고 했습니다.

검색과 댓글도 아직 넣지 않았습니다. 글이 적은 동안에는 사이드바와 카테고리만으로 충분하고,
대화를 운영하는 기능보다 기록을 꾸준히 남기는 일이 먼저라고 판단했습니다. 필요가 확인되면
추가하되, 가능성만으로 관리 대상을 늘리지는 않는 것이 이 사이트의 기준입니다.

## 계속 바뀌는 홈 디렉터리

`soohan-dev`는 완성된 포트폴리오가 아닙니다. 지금까지 한 일을 한 번 정리하고 멈추는 페이지도
아닙니다. 새로운 프로젝트를 맡고, 오픈소스에 기여하고, 일하는 방식이 달라질 때마다 구조와
내용이 함께 바뀌는 개인적인 홈 디렉터리입니다.

무엇을 만들었는지만큼 왜 그렇게 만들었고 이후에 어떻게 책임졌는지를 남기는 것. 이 사이트는
그 기록을 내 손에 계속 쌓아두기 위한 기반입니다.
