Obsidian, Quartz, Cloudflare Pages로 공개 개발노트를 만들며 배운 것

Share
Obsidian, Quartz, Cloudflare Pages로 공개 개발노트를 만들며 배운 것

Goodtek을 만들면서 계속 고민하던 것이 하나 있었습니다.

“개발하면서 생기는 생각과 시행착오를 어디에 남길 것인가?”

블로그에 정리하면 좋다는 것은 알고 있었습니다. 하지만 매번 블로그 글처럼 제목을 정하고, 문단을 다듬고, 썸네일까지 고민하다 보면 막상 기록 자체가 부담이 됩니다.

개발 과정에서는 짧은 결정들이 계속 생깁니다.

왜 이 구조를 선택했는지,
어떤 설정에서 막혔는지,
무엇을 바꿨더니 해결됐는지,
어떤 방향은 별로였는지.

이런 것들은 시간이 지나면 금방 잊힙니다. 그런데 나중에 보면 오히려 이런 작은 기록들이 더 중요합니다.

그래서 Goodtek의 공개 개발노트를 만들기로 했습니다.

도메인은 이렇게 정했습니다.

notes.goodtek.xyz

목적은 단순합니다.

Goodtek을 만들어가는 과정에서 생기는 빌드로그, 기술 결정, 위키, 실험 기록을 공개적으로 쌓는 공간입니다.

블로그가 “정리된 글”이라면, Notes는 “만드는 과정의 기록”에 가깝습니다.

처음 생각한 구조

처음에는 Obsidian을 서버에 올리고, 거기에 도메인을 붙이면 되지 않을까 생각했습니다.

Obsidian은 Markdown 기반이고, 폴더 구조도 단순합니다. 개발 노트나 아이디어 정리에 이미 많이 쓰이는 도구라서, 공개 노트에도 잘 맞아 보였습니다.

하지만 곧 생각이 바뀌었습니다.

Obsidian 자체를 웹 서비스처럼 운영하는 것보다, Obsidian은 작성 도구로만 쓰고, 배포는 정적 사이트로 하는 편이 더 안정적이라고 판단했습니다.

그래서 구조를 이렇게 잡았습니다.

Obsidian
→ Markdown
→ Quartz
→ GitHub
→ Cloudflare Pages
→ notes.goodtek.xyz

Obsidian에서는 content 폴더만 Vault로 엽니다.

글은 Markdown으로 작성합니다.

Quartz는 이 Markdown 파일들을 정적 웹사이트로 변환합니다.

GitHub에 push하면 Cloudflare Pages가 자동으로 빌드하고 배포합니다.

이 구조의 장점은 명확했습니다.

로컬에서 편하게 쓰고, Git으로 버전 관리하고, Cloudflare Pages로 무료에 가깝게 배포할 수 있습니다. 무엇보다 특정 서비스에 갇히지 않고, Markdown 파일 자체가 남습니다.

시작은 간단해 보였지만, 바로 막혔다

처음에는 단순할 줄 알았습니다.

폴더를 만들고, Quartz를 설치하고, GitHub에 올리고, Cloudflare Pages에 연결하면 끝날 것 같았습니다.

그런데 실제로는 작은 문제들이 계속 나왔습니다.

먼저 Quartz 설치부터 달랐습니다.

예전 자료에서는 npm create quartz@latest 같은 방식이 보였는데, 실제로 실행하니 npm registry에서 패키지를 찾지 못했습니다.

결국 Quartz v5 방식에 맞춰 저장소를 준비하고, npx quartz create로 초기화했습니다.

초기화 과정에서는 템플릿을 선택하고, content 폴더를 만들고, base URL을 입력했습니다. 여기서도 처음에는 mysite.github.io 같은 예시값이 나와서 헷갈렸습니다. 최종적으로는 Goodtek Notes 구조에 맞게 정리했습니다.

그리고 폴더 구조도 한 번 꼬였습니다.

처음에는 goodtek-notes 폴더 안에 다시 goodtek-notes가 생기는 구조가 되었습니다. 다행히 바로 정리해서 프로젝트 루트에 Quartz 파일들이 오도록 맞췄습니다.

이런 종류의 문제는 작지만, 초반에 방향을 흐리게 만듭니다.

Obsidian은 전체 프로젝트가 아니라 content 폴더만 열었다

중요한 결정 중 하나는 Obsidian에서 어떤 폴더를 Vault로 열 것인가였습니다.

처음에는 전체 프로젝트 폴더를 열어도 되지 않을까 생각했습니다.

하지만 Quartz 프로젝트 전체에는 node_modules, 설정 파일, 빌드 파일, 플러그인 파일들이 많습니다. 이걸 Obsidian에서 다 보게 되면 노트 공간이 지저분해집니다.

그래서 Obsidian에서는 이 폴더만 Vault로 열었습니다.

goodtek-notes/content

이렇게 하면 Obsidian 안에서는 순수하게 글만 보입니다.

예를 들어 구조는 이렇게 가져갔습니다.

content/
├─ index.md
├─ build-log.md
├─ decisions.md
├─ wiki.md
├─ experiments.md
└─ build-log/
   └─ 2026-05-26-goodtek-notes-setup.md

Goodtek Notes의 기본 섹션은 네 가지로 잡았습니다.

Build Log는 실제 만드는 과정의 기록입니다.

Decisions는 왜 이 기술과 방향을 선택했는지 남기는 공간입니다.

Wiki는 반복해서 참고할 기술 지식입니다.

Experiments는 실험, 실패, 검증 기록입니다.

처음부터 완벽한 정보 구조를 만들려고 하기보다는, 앞으로 계속 쌓아갈 수 있는 최소 구조를 만드는 데 집중했습니다.

GitHub push에서 계정 문제가 생겼다

다음 문제는 GitHub였습니다.

저장소를 만들고 push하려고 했는데 이런 에러가 나왔습니다.

ERROR: Repository not found.
fatal: 리모트 저장소에서 읽을 수 없습니다

처음에는 저장소 주소가 틀렸나 싶었습니다.

그런데 원인은 SSH 계정이었습니다.

제 Mac에서는 기존에 다른 GitHub 계정으로 SSH 인증이 되어 있었습니다. 그래서 goodtekxyz/goodtek-notes 저장소에 push하려고 해도, GitHub는 다른 계정이 접근하는 것으로 보고 권한이 없다고 판단했습니다.

확인해보니 이런 식이었습니다.

Hi trading-insight-sg! You've successfully authenticated

Goodtek 계정으로 인증되어야 하는데, 다른 계정으로 인증되고 있었던 것입니다.

해결은 SSH alias를 분리하는 방식으로 했습니다.

Host github-goodtekxyz
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_goodtekxyz
  IdentitiesOnly yes

그리고 remote 주소를 이렇게 바꿨습니다.

git@github-goodtekxyz:goodtekxyz/goodtek-notes.git

이후 push가 정상적으로 성공했습니다.

여기서 다시 느꼈습니다.

여러 GitHub 계정을 한 PC에서 쓸 때는 SSH 설정을 대충 두면 언젠가 반드시 꼬입니다. 특히 브랜드 계정이나 조직 계정으로 프로젝트를 관리할 때는 처음부터 SSH alias를 분리하는 것이 좋습니다.

Cloudflare Pages가 아니라 Worker로 잘못 만들었다

GitHub에 push한 다음에는 Cloudflare Pages에 연결했습니다.

여기서도 한 번 실수했습니다.

Cloudflare UI에서 Workers와 Pages가 같이 묶여 있다 보니, 처음에는 Worker 프로젝트 흐름으로 들어가 버렸습니다.

빌드 로그를 보니 이런 명령이 실행되고 있었습니다.

npx wrangler deploy

하지만 Quartz는 정적 사이트입니다.

우리가 원하는 것은 Worker 배포가 아니라 Pages 빌드였습니다.

정상적인 설정은 이렇습니다.

Framework preset: None
Build command: npx quartz build
Build output directory: public
Root directory: /

Worker 프로젝트를 만들면 wrangler deploy가 나오고, Pages 프로젝트를 만들면 npx quartz build가 실행됩니다.

이 차이를 로그에서 확인하고 나서야 제대로 된 Pages 프로젝트를 다시 만들었습니다.

작은 UI 선택 하나였지만, 배포 방식이 완전히 달라졌습니다.

Quartz v5 플러그인 때문에 Cloudflare 빌드가 깨졌다

Pages 설정을 맞춘 뒤에도 바로 성공하지는 않았습니다.

Cloudflare 빌드에서 이런 에러가 나왔습니다.

Could not resolve "../../.quartz/plugins"

로컬에서는 빌드가 되는데, Cloudflare에서는 실패했습니다.

원인은 .quartz 폴더가 Git에 올라가지 않았기 때문이었습니다. .gitignore.quartz/가 들어가 있었고, Cloudflare 빌드 환경에는 필요한 플러그인 파일이 없었습니다.

그래서 .gitignore에서 .quartz/를 제거하고 Git에 추가했습니다.

그런데 여기서 또 문제가 생겼습니다.

이번에는 Cloudflare가 .quartz/plugins 안의 여러 폴더를 Git submodule처럼 인식했습니다.

에러는 이랬습니다.

fatal: No url found for submodule path '.quartz/plugins/alias-redirects' in .gitmodules

확인해보니 .quartz/plugins 안의 각 플러그인 폴더에 내부 .git 폴더가 남아 있었습니다. Git은 이런 폴더를 일반 파일이 아니라 내장 Git 저장소, 즉 submodule처럼 인식합니다.

해결은 내부 .git 폴더를 제거한 뒤, 다시 일반 파일로 추가하는 것이었습니다.

find .quartz/plugins -name .git -type d -prune -exec rm -rf {} +
git rm -f --cached -r .quartz/plugins
git add .quartz/plugins

그 뒤 확인했을 때 Git 파일 모드가 160000이 아니라 100644로 바뀌었습니다.

100644 .quartz/plugins/...

이제야 Cloudflare Pages 빌드가 정상적으로 성공했습니다.

이 과정은 조금 번거로웠지만, Git이 submodule을 어떻게 인식하는지 다시 확인하는 계기가 되었습니다.

디자인 욕심을 냈다가 다시 기본으로 돌아왔다

배포가 끝난 뒤에는 디자인을 만지기 시작했습니다.

처음에는 Quartz 기본 디자인이 조금 올드해 보였습니다.

그래서 Vercel 스타일, Linear 스타일, Mintlify 스타일 같은 방향을 참고해서 CSS를 많이 바꿔봤습니다.

색상, 다크모드, 카드, 여백, 사이드바, 코드블록, 링크 컬러까지 여러 번 수정했습니다.

하지만 결과는 만족스럽지 않았습니다.

Quartz는 기본적으로 Obsidian 디지털 가든에 가까운 구조입니다. 여기에 SaaS 랜딩페이지 스타일을 억지로 덮으니 오히려 어색해졌습니다.

특히 다크모드가 깨지거나, 카드 대비가 이상해지거나, 폰트 자간이 과하게 붙어 보이는 문제가 생겼습니다.

결국 결론은 단순했습니다.

기본 Quartz 스타일은 유지한다.
폰트만 최소로 바꾼다.
타이틀만 Goodtek에 맞게 바꾼다.

그래서 custom.scss는 폰트 오버라이드만 남겼습니다.

body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
li,
a,
button,
input,
textarea,
.explorer,
.page-title,
.content-meta {
  font-family: var(--goodtek-font-sans) !important;
}

이렇게 하니 오히려 가장 안정적이고 보기 좋았습니다.

디자인을 잘하는 것과, 기존 프레임워크의 구조를 존중하는 것은 다른 문제였습니다.

이번에는 후자가 더 중요했습니다.

Footer도 Goodtek에 맞게 정리했다

기본 Quartz footer에는 이런 문구가 나옵니다.

Created with Quartz v5.0.0 © 2026
GitHub
Discord Community

공개 개발노트에 꼭 필요한 문구는 아니었습니다.

그래서 footer 링크는 Goodtek 관련 링크로 바꾸거나, 필요하면 숨길 수 있도록 정리했습니다.

Quartz 설정 파일에는 footer 플러그인 설정이 있었습니다.

- source: github:quartz-community/footer
  enabled: true
  options:
    links:
      GitHub: https://github.com/jackyzha0/quartz
      Discord Community: https://discord.gg/cRFFHYye7t

이런 기본값은 Goodtek 브랜드와는 맞지 않습니다.

작은 부분이지만, 공개 사이트라면 이런 기본 문구도 한 번은 정리해야 합니다.

다른 PC에서는 어떻게 이어서 작업할까?

저는 맥북과 맥미니를 모두 사용합니다.

그래서 한쪽에서 작성한 노트를 다른 쪽에서도 이어서 작성할 수 있어야 했습니다.

이 구조에서는 Obsidian Sync를 꼭 쓰지 않아도 됩니다.

GitHub가 동기화 중심이 됩니다.

흐름은 이렇게 가져가면 됩니다.

작업 시작 전: git pull
Obsidian에서 content 작성
작업 종료 후: git commit && git push

다른 PC에서는 저장소를 clone하고, Obsidian에서 content 폴더만 Vault로 열면 됩니다.

goodtek-notes/content

로컬 미리보기가 필요하면 Node.js를 설치하고 아래 명령을 실행하면 됩니다.

npm i
npx quartz build --serve

다만 가장 중요한 습관은 하나입니다.

작업 시작 전 pull
작업 끝나면 push

이걸 지키지 않으면 두 PC에서 같은 파일을 수정하다가 충돌이 날 수 있습니다.

빌드로그를 날짜별 파일로 나누는 것도 충돌을 줄이는 좋은 방법입니다.

이번 작업에서 배운 것

이번 작업은 단순히 노트 사이트 하나 만든 일이 아니었습니다.

Goodtek을 어떻게 기록할 것인가에 대한 첫 번째 구조를 만든 일이었습니다.

그리고 몇 가지 기준이 생겼습니다.

첫째, 기록 도구는 부담이 적어야 합니다.

블로그는 여전히 중요하지만, 모든 기록이 블로그 글이 될 필요는 없습니다. 짧은 결정, 실패, 설정 과정은 Notes에 먼저 쌓고, 나중에 가치가 있는 것만 블로그 글로 확장하면 됩니다.

둘째, 처음부터 디자인을 완벽하게 만들려고 하지 않는 것이 좋습니다.

이번에도 디자인을 많이 건드렸지만, 결국 가장 나았던 것은 기본 스타일을 유지하고 폰트만 최소로 바꾸는 방식이었습니다. 아직 콘텐츠가 많지 않은 단계에서는 디자인보다 기록 습관이 먼저입니다.

셋째, 자동 배포 구조는 초반에 만들어두는 게 좋습니다.

GitHub에 push하면 Cloudflare Pages가 자동으로 배포되는 구조를 만들어두니, 앞으로는 글을 쓰고 push하는 것만으로 공개됩니다. 이 흐름이 만들어진 것만으로도 큰 진전입니다.

넷째, 시행착오는 기록할 가치가 있습니다.

Quartz 설치 문제, GitHub SSH 계정 문제, Cloudflare Worker와 Pages 혼동, submodule 문제, CSS 실패까지. 당시에는 귀찮았지만, 이런 것들이 나중에는 누군가에게 도움이 되는 기록이 됩니다.

앞으로 Goodtek Notes를 어떻게 쓸 것인가

Goodtek Notes는 완성된 문서를 올리는 공간이 아닙니다.

오히려 완성되기 전의 생각, 결정, 실패를 쌓는 공간입니다.

앞으로 이곳에는 이런 기록을 남기려고 합니다.

AI automation을 만들며 생기는 기술 결정
SaaS 구조를 설계하며 겪는 시행착오
배포, 도메인, 인프라 설정 기록
제품 아이디어 검증 과정
실패한 접근과 다시 선택한 방향

Goodtek은 AI automation과 SaaS를 만들어가는 과정을 공개하려고 합니다.

좋은 결과만 보여주는 것이 아니라, 중간의 막힘과 수정 과정까지 남기는 것이 목표입니다.

이번 notes.goodtek.xyz 구축은 그 시작점입니다.

아직 완벽하지 않습니다.
하지만 이제 기록을 쌓을 공간은 생겼습니다.

그리고 지금은 그걸로 충분합니다.

Read more

AI와 함께 코딩할 때 먼저 배운 것: 만든 것과 만들려던 것을 구분하기

AI와 함께 코딩할 때 먼저 배운 것: 만든 것과 만들려던 것을 구분하기

AI와 함께 코딩하면 계획, 프롬프트, 문서, 실제 코드가 쉽게 섞입니다. 이번 TASK-013에서는 공개 상태 페이지를 만들려 했지만, 실제로 ship된 것은 실시간 대시보드, 알림 테스트 상태 추적, 디자인 정합 작업이었습니다. 이번 글에서는 TASK 이름보다 머지된 코드를 기준으로 사실을 검증한 과정과, Realtime 아키텍처·비동기 상태 모델·공통 계약 관리 등 AI와 함께 개발할 때 놓치기 쉬운 기준들을 정리합니다. Build in Public 관점에서 ‘만들려던 것’과 ‘실제로 만든 것’을 구분하는 방법을 공유합니다.

By ● goodtek
감지 → 판단 → 알림: vibePulse의 심장을 만든 6개의 TASK

감지 → 판단 → 알림: vibePulse의 심장을 만든 6개의 TASK

goodtek이 만들고 있는 vibePulse는 "내가 만든 웹/API가 지금 살아 있는가"를 확인하고, 죽으면 즉시 알려주는 초간단 생존 확인 SaaS입니다. 이번 글은 그 핵심 파이프라인 — 모니터를 만들고(TASK-006), 주기적으로 찌르고(007), 장애를 판단하고(008), 신호가 끊기면 알아채고(009), 알림을 큐에 태워(010), 슬랙·카카오톡으로 보내기까지(011) — 를 한 호흡에 만든 기록입니다.

By ● goodtek