과정을 공개하며,함께 만듭니다

goodtek은 ‘대신 만들어 주는’ 곳이 아니에요. 지금 만드는 것, 막힌 것, 시행착오까지 모두 공개합니다.

블로그에서 만드는 이야기

롱폼 글은 goodtek과 동일 운영자가 운영하는 blog.goodtek.xyz에서 이어집니다.

블로그 전체 보기

최신 글

  • 1인 SaaS

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

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

    블로그에서 읽기
  • ● goodtek

    "—"로 비어 있던 화면을, 진짜 제품으로

    백엔드가 아무리 잘 돌아도, 사용자가 보는 게 빈칸이면 그건 아직 제품이 아닙니다. 이번 TASK-012는 그 빈칸을 채우는 일이었습니다. 대시보드 요약, 모니터 상세(가동률·지연 차트·장애 타임라인), 알림 채널 관리, 알림 이력까지 — 한 호흡에 "실서비스 급" 화면을 만들었습니다.

    블로그에서 읽기

추천 글

  • ● goodtek

    "—"로 비어 있던 화면을, 진짜 제품으로

    백엔드가 아무리 잘 돌아도, 사용자가 보는 게 빈칸이면 그건 아직 제품이 아닙니다. 이번 TASK-012는 그 빈칸을 채우는 일이었습니다. 대시보드 요약, 모니터 상세(가동률·지연 차트·장애 타임라인), 알림 채널 관리, 알림 이력까지 — 한 호흡에 "실서비스 급" 화면을 만들었습니다.

    블로그에서 읽기
  • ● goodtek

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

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

    블로그에서 읽기

빌드 노트

짧은 작업 메모는 notes.goodtek.xyz에서 이어집니다.

노트 전체 보기
  • Build Log

    Summary CI/CD를 CI / CD 워크플로 분리로 정리하고, Actions 이름을 읽기 쉽게 맞춘 뒤 main까지 반영했다. 이어서 **React hydration 418 수정, 모바일·데스크톱 헤더/navigation 개선(TASK-020~023)을 develop에 merge했다. CI/CD — TASK-019 배경 TASK-018 workflo…

  • Build Log

    오늘은 notes.goodtek.xyz를 위한 공개 노트 구조를 만들었다. Obsidian에서 Markdown을 작성하고, Quartz로 정적 사이트를 만든 뒤, Cloudflare Pages로 배포하는 방식을 선택했다. 오늘 한 일 goodtek-notes 저장소를 준비했다. Quartz를 설치하고 초기화했다. notes.goodtek.xyz를 기본 U…

  • Wiki

    빌드 로그는 힘줘서 쓰지 않는다. 목표는 좋은 글을 쓰는 것이 아니라, 나중에 다시 볼 수 있는 작업 흔적을 남기는 것이다. 블로그 글처럼 완성도를 높이려고 하면 지속하기 어렵다. 빌드 로그는 작업이 끝난 뒤 짧게 남기는 기록이면 충분하다. 원칙 작업 중간에는 쓰지 않는다. 작업이 끝난 뒤 5분만 정리한다. 문장보다 bullet 위주로 남긴다. 모든 로그…

커뮤니티에서 이어지는 대화

토론과 질문은 community.goodtek.xyz에서 이어집니다.

커뮤니티 전체 보기
  • 빌딩 인 퍼블릭

    요약 develop/main push 후 CD 파이프라인이 서버 디스크 부족으로 실패했습니다. 원인은 배포마다 쌓인 미사용 컨테이너 이미지이고, 즉시 조치는 수동 prune, 재발 방지는 deploy.sh에 자동 정리 추가로 처리했습니다. 증상 GitHub Actions CD의 SSH 배포 단계에서 exit code 125로 종료되었습니다. ==> pull ghcr.io/***/vibepulse-worker:b2bcf4b2... ... no space left on device web, api 이미지 pull은 성공 worker 이미지 unpack 중 실패 blue/green 배포에서 현재 슬롯(blue)은 그대로 — pull 실패는 health gate 이전이라 트래픽 전환 없음 원인 서버 root 볼륨이 100% 사용 상태였습니다. 항목 수치 디스크 89G 중 89G 사용 (~484M 여유) Podman 이미지 618개 중 8개만 사용 중 회수 가능 용량 ~48GB (96%) 매 push마다 web / api / worker 3개 이미지가 git SHA 태그로 pull되지만, deploy.sh에 이전 이미지 정리 로직이 없어 태그만 쌓였습니다. 추가로 api/worker 이미지는 아직 전체 monorepo node_modules를 포함하는 walking skeleton 구조라 태그당 ~2.3GB 수준입니다. (이미지 슬리밍은 TASK-018 예정) 배포 구조 (참고) Blue/Green: blue 311x, green 321x 포트 새 슬롯 pull → health check → Caddy 전환 → 구 슬롯 종료 런타임: rootless Podman 스토리지: ~/.local/share/containers/storage/ 실패 시점에는 green 슬롯 worker pull 중이었고, blue 슬롯이 계속 서비스 중이었습니다. 즉시 조치 (서버) 실행 중인 컨테이너가 참조하는 이미지는 유지됩니다. 실행 중 컨테이너 확인 podman ps --format 'table {{.Names}}\t{{.Image}}' 미사용 이미지·레이어 정리 podman image prune -a -f podman system prune -f 공간 확인 df -h / podman system df 약 45~48GB 회수 후 CD 워크플로를 재실행합니다. 재발 방지 (코드 변경) scripts/deploy.sh에 prune_unused_images()를 추가했습니다. 시점 동작 pull 전 미사용 이미지 정리 → 새 이미지 pull 전 디스크 확보 구 슬롯 compose down 후 이전 SHA 태그 이미지 정리 prune_unused_images() { echo "==> prune unused $CONTAINER_RUNTIME images" "$CONTAINER_RUNTIME" image prune -a -f "$CONTAINER_RUNTIME" system prune -f } 실행 중 컨테이너(현재 active 슬롯 + Postgres/Redis 등)가 쓰는 이미지는 삭제되지 않음 docker/podman 모두 동일 명령 사용 교훈 / 체크리스트 컨테이너 이미지도 디스크를 먹는다 — 로그·DB만 볼 게 아니라 podman system df도 주기적으로 확인 SHA 태그만 쓰는 CD는 prune이 필수 — 배포 스크립트에 정리 단계를 넣거나 cron으로 보완 blue/green은 일시적으로 이미지가 2세트 — 디스크 여유는 최소 태그 2~3세트 분량 권장 실패해도 서비스는 유지될 수 있음 — pull/health gate 실패 시 새 슬롯만 정리되고 기존 슬롯 유지 (의도된 동작) 후속 (선택) 항목 설명 TASK-018 api/worker 이미지 슬리밍 (prod-only node_modules) 디스크 용량 89G root에서 빈번한 CD 시 여유 확보 검토 모니터링 디스크 사용률 알람 (예: 85% 이상) 한 줄 요약 CD가 이미지를 계속 쌓아 root 디스크를 채웠고, podman image prune -a로 복구한 뒤 deploy.sh에 배포 전·후 자동 prune을 넣어 재발을 막았다.

    첫 답글을 남겨 보세요조회 29
    토론 참여하기
  • 빌딩 인 퍼블릭

    goodtek vibepulse % vibeops init Agent clients Which coding agents will you use? (Space toggle · Enter confirm) Cursor (.cursor/rules, .cursor/skills) Branch policy Branch policy GitFlow lite — develop (integration) + main (production) → vibeops init → /Users/hjhamm/goodtek/vibepulse project: vibepulse vibeops: 2.3.0 clients: Cursor (.cursor/rules, .cursor/skills) git: integration=develop, production=main ✓ created .cursor/rules/01-task-source-of-truth.mdc ✓ created .cursor/rules/02-git-safety.mdc ✓ created .cursor/rules/03-docs-before-ship.mdc ✓ created AGENTS.md ✓ created docs/logs/README.md ✓ created docs/project/03-architecture.md ✓ created docs/project/05-current-state.md ✓ created docs/project/06-decisions.md ✓ created docs/tasks/TASK-000-template.md ✓ created .cursor/skills/implement-task/SKILL.md ✓ created .cursor/skills/plan-task/SKILL.md ✓ created .vibeops.json ✓ created .vibeops.env.example ✓ created .gitignore done: 14 created, 0 overwritten, 0 skipped. Git repository Create initial commit? Yes Initial commit message initialize vibepulse project Git setup: ✓ git init ✓ production branch main ✓ initial commit on main ✓ integration branch develop Remote origin is required for push and merge requests. GitHub repository name (owner/repo or name for gh to create) vibepulse Creating GitHub repository via gh… Remote bootstrap: ✓ pushed main → origin ✓ pushed develop → origin Next steps: Read AGENTS.md Cursor: @docs/tasks/TASK-001-….md in Ask, then Agent (+ /plan-task, /implement-task) vibeops llm connect — LLM for task add / task ship Push branches to origin (first time only): git push -u origin main git push -u origin develop vibeops task add — branches from develop (pulls latest first) vibeops task ship → merge → sync — TASK lifecycle on github goodtek vibepulse %

    첫 답글을 남겨 보세요조회 40
    토론 참여하기
  • 질문과 답변

    여러분이라면 goodtek에 SSO를 지금 도입하시겠습니까? 솔직히 말하면, SSO라는 단어는 꽤 매력적입니다. 서비스가 여러 개로 나뉘기 시작하면 이런 생각이 바로 듭니다. “로그인을 하나로 묶어야 하지 않을까?” 현재 goodtek이 가려는 구조를 보면 더 그렇습니다. goodtek.xyz — 메인 웹사이트 blog.goodtek.xyz — Ghost 블로그 community.goodtek.xyz — NodeBB 커뮤니티 notes.goodtek.xyz — 공개 노트 / 개발 로그 app.goodtek.xyz — 나중에 SaaS 앱들 이렇게 보면 SSO 방향 자체는 맞아 보입니다. 웹사이트, 블로그, 커뮤니티, 노트, SaaS 앱이 하나의 생태계로 묶이는 그림이니까요. 사용자 입장에서도 한 번 로그인해서 여러 서비스를 오가는 경험은 분명 좋습니다. 그런데 여기서 질문이 하나 생깁니다. 지금 goodtek이 해결해야 할 가장 중요한 문제가 정말 “통합 로그인”일까요? 저는 이 지점에서 조금 멈췄습니다. SSO가 필요한가보다 중요한 질문 SSO가 필요한지 아닌지만 보면 답은 쉽습니다. 언젠가는 필요할 수 있습니다. 문제는 “언젠가”가 아니라 지금입니다. 지금 Keycloak 같은 중앙 인증 서버를 직접 붙이면, 인증은 단순 기능이 아니라 하나의 운영 대상이 됩니다. 로그인만 되는 게 아닙니다. 세션 관리 리프레시 토큰 이메일 인증 비밀번호 초기화 OAuth 설정 백업 업그레이드 장애 대응 보안 패치 운영 모니터링 이 모든 게 따라옵니다. 처음에는 “로그인 통합하면 깔끔하겠다”로 시작했는데, 어느 순간 인증 서버 자체가 또 하나의 제품이 될 수 있습니다. 문제는 SSO가 좋은 기술이냐가 아니라, 지금 인증이 goodtek의 핵심 병목이냐입니다. 지금 goodtek에 더 급한 것들 goodtek 입장에서는 이미 해야 할 일이 많습니다. 웹사이트를 만들고, 블로그를 운영하고, 커뮤니티를 키우고, 공개 노트를 정리하고, SaaS 앱을 만들고, CI/CD와 운영 자동화도 다듬어야 합니다. 이 상황에서 Keycloak까지 직접 운영하기 시작하면, 제품보다 인프라가 더 무거워질 수 있습니다. 제 기준으로 보면 지금은 이렇게 나누는 게 더 현실적입니다. 영역 지금 선택 이유 웹사이트 로그인 없음 랜딩, SEO, AdSense, 연결 구조가 먼저 Ghost 블로그 Ghost 기본 멤버 뉴스레터와 구독 기능이 이미 있음 NodeBB 커뮤니티 자체 로그인 + 소셜 로그인 초기 커뮤니티에는 충분함 Notes 공개 문서 신뢰 자산과 개발 로그 역할 SaaS 앱 앱 자체 인증 또는 SaaS형 인증 실제 인증이 필요한 핵심 영역 즉, 모든 곳에 중앙 인증을 먼저 깔기보다 로그인이 진짜 필요한 곳부터 가볍게 시작하는 방식입니다. Keycloak이 틀렸다는 말은 아닙니다 여기서 오해하면 안 되는 게 있습니다. 저는 Keycloak이 나쁘다고 생각하지 않습니다. 오히려 특정 시점이 오면 굉장히 좋은 선택이 될 수 있습니다. 예를 들면 이런 상황입니다. SaaS 앱이 여러 개 생긴다 커뮤니티 계정과 SaaS 계정을 반드시 하나로 묶어야 한다 조직/팀 단위 계정이 필요하다 RBAC, 그룹, 역할 관리가 복잡해진다 고객사별 SSO 요청이 들어온다 SAML, OIDC 같은 B2B 요구사항이 생긴다 자체 호스팅을 유지해야 하는 명확한 이유가 있다 이 정도까지 가면 이야기가 달라집니다. 그때는 Keycloak이 단순한 오버엔지니어링이 아니라 필요한 기반 인프라가 될 수 있습니다. 하지만 지금이 “나중에 필요할 것 같으니 미리 붙이자”에 가깝다면, 저는 조금 빠르다고 봅니다. 지금은 설계상 여지만 남기기 제가 생각하는 현실적인 선택은 이겁니다. SSO를 완전히 무시하지는 않되, 지금 당장 운영하지는 않는다. 예를 들어 SaaS 앱의 DB 설계에서 나중에 외부 IdP로 옮길 수 있는 여지만 남깁니다. users id email name avatar_url provider provider_account_id created_at accounts user_id provider provider_account_id access_token refresh_token memberships user_id product role status 이 정도만 해두면 나중에 Keycloak, Authentik, Zitadel, Auth0, Clerk 같은 선택지로 갈 때 완전히 막히지는 않습니다. 처음부터 중앙 인증 서버를 운영하는 것과, 나중에 옮길 수 있게 데이터 구조를 열어두는 것은 다릅니다. 저는 후자가 지금 goodtek에 더 맞다고 봅니다. 지금 필요한 건 완성된 통합 인증 시스템이 아니라, 나중에 통합할 수 있는 느슨한 구조입니다. 제 결론 제 결론은 이렇습니다. 지금 goodtek은 SSO를 도입하지 않는 쪽이 맞다. 조금 더 정확히 말하면, SSO 방향은 고려하되, Keycloak 같은 중앙 인증 서버를 지금 직접 운영하지는 않는다. 현재 단계에서는 이렇게 가는 게 가장 현실적이라고 봅니다. 웹사이트: 로그인 없음 블로그: Ghost 기본 멤버 기능 커뮤니티: NodeBB 기본 로그인 + Google/GitHub 로그인 Notes: 공개 운영 SaaS 앱: 앱 자체 인증 또는 Better Auth / Auth.js / Supabase Auth / Clerk 같은 가벼운 인증 그리고 실제로 커뮤니티와 SaaS가 연결되고, 결제/권한/등급/조직 계정이 얽히기 시작하면 그때 SSO를 진지하게 검토합니다. 그때 Keycloak을 붙여도 늦지 않다고 생각합니다. 오히려 지금은 콘텐츠, 커뮤니티, 제품이 먼저입니다. 인증 시스템이 아무리 잘 되어 있어도 들어올 사용자가 없으면 운영할 것도 없습니다. 반대로 사용자가 생기고 서비스 간 연결이 진짜 필요해지면, 그때의 SSO는 훨씬 명확한 이유를 갖게 됩니다. 여러분은 어떻게 생각하시나요? 여러분이라면 goodtek 같은 구조에서 SSO를 지금 도입하시겠습니까? 아니면 일단 각 서비스를 독립적으로 운영하고, SaaS 앱에만 가벼운 인증을 붙인 뒤 나중에 통합하시겠습니까? 특히 궁금한 건 이 부분입니다. 초기부터 SSO를 깔아두는 게 장기적으로 이득일까요, 아니면 지금은 오히려 제품보다 인프라를 키우는 선택일까요? 저는 지금 단계에서는 후자에 가깝다고 봅니다. 하지만 SSO를 초기에 깔아두고 나중에 덕을 본 경험이 있다면, 그 이야기도 들어보고 싶습니다.

    첫 답글을 남겨 보세요조회 33
    토론 참여하기

goodtek에서 만나는 것

  • 지금 만드는 것

    요즘 손대는 제품·이번 주 변경을 로그처럼 올려요.

    더 읽기
  • 시행착오까지 공개

    잘된 것만이 아니라, 포기·전환도 그대로 남겨요.

    더 읽기
  • 아이디어·협업

    맡겨 주세요가 아니라, 같이 고민하거나 합류 환영해요.

    더 읽기

관심 있으신가요?

아이디어, 같이 만들기, 구경, 뭐든 환영해요. 한 줄이면 충분해요.