์คํฐ๋ ์ฐธ๊ฐ์ ํผ๋๋ฐฑ์ ํ๊ณณ์ ๋ชจ์ผ๋ ์ฌ์ดํธ. https://feedback.dalestudy.com
์คํฐ๋ยทํ๋ก์ ํธ(dalestudy.com/programs ์ ํ๋ก๊ทธ๋จ) ๋ฆฌ๋๋ง๋ค ๋ค๋ฅธ ๋๊ตฌ๋ก ํผ๋๋ฐฑ์ ๋ฐ๋ค ๋ณด๋ ์ง๋ ๊ธฐ์ ํผ๋๋ฐฑ์ ์ฐพ๊ธฐ๋, ๊ธฐ์ ๊ฐ ๋น๊ต๋ ์ด๋ ค์ ๋ค. GitHub ๋ก๊ทธ์ธ์ผ๋ก ์ค๋ณต ์๋ต๋ง ๋ง๊ณ , ์๋ต์ ์ต๋ช ์ผ๋ก D1 ์ ์๋๋ค.
- TanStack Start (React) on Cloudflare Workers
- D1 (SQLite) + Drizzle
- daleui ๋์์ธ ์์คํ
- ๋ก๊ทธ์ธ: DaleStudy GitHub App ์ user-to-server OAuth
programs โโฌโ cohorts โ surveys โ questions cohort: ๊ธฐ์์ ๋ฉด '1๊ธฐ', ์์๋ฉด '2026 ํ๋ฐ๊ธฐ'
โ โโ responses โ answers
โโ leaders (program_id, login) โ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์๋ ์ฌ๋
์ฐธ๊ฐ์ ๋ช ๋จ์ ๋์ง ์๋๋ค. ์ค๋ฌธ ๋งํฌ๋ ํด๋น ํ๋ก๊ทธ๋จ ์ฑ๋์๋ง ๊ณต์ ๋๊ณ , ๋ตํ๋ ค๋ฉด GitHub ๋ก๊ทธ์ธ์ด ํ์ํ๋ฉฐ, ๊ฐ์ ์ฌ๋์ ์ค๋ณต ์๋ต์ ๋งํ๋ฏ๋ก ๋ช ๋จ์ด ์ฃผ๋ ์ถ๊ฐ ์์ ์ด DiscordโGitHub ๋งคํ์ ์ ์งํ๋ ๋น์ฉ๋ณด๋ค ์๋ค.
์ต๋ช
์ค๋ฌธ์ responses.respondent_key ๋ HMAC(HMAC_SECRET, surveyId:userId) ๋ค.
๊ฐ์ ์ฌ๋์ ์ค๋ณต ์๋ต๋ง ๋ง๊ณ , ๋๊ฐ ๋ตํ๋์ง๋ ๋ฆฌ๋๋ ์๋ฒ๋ ๋ณต์ํ ์ ์๋ค. ์ค๋ช
์ค๋ฌธ์ด๋ฉด GitHub login ์ ๊ทธ๋๋ก ์ด๋ค.
bun install
bun run cf-typegen # wrangler.jsonc ๋ฐ๋ ๋๋ง๋ค
bun run db:migrate:local
bun run db:seed:local seed/example.json
bun run dev # http://localhost:3000๋ก์ปฌ ์ํฌ๋ฆฟ์ .dev.vars ์ ๋๋ค (git ์ ์ฌ๋ผ๊ฐ์ง ์์).
GITHUB_CLIENT_ID=... # DaleStudy GitHub App ์ Client ID
GITHUB_CLIENT_SECRET=... # ๊ฐ์ ์ฑ์ Client secret
HMAC_SECRET=... # openssl rand -hex 32
GitHub App ์ค์ ์ Callback URL ์ http://localhost:3000/auth/callback ์ด ๋ฑ๋ก๋ผ ์์ด์ผ ํ๋ค.
__Host- ์ ๋์ฌ ์ฟ ํค๋ Secure ๊ฐ ํ์๋ผ ๋ก์ปฌ ๊ฐ๋ฐ์ localhost ๋ฅผ secure context ๋ก ์ทจ๊ธํ๋ Chrome/Firefox ์์ ํ๋ค.
๊ด๋ฆฌ ํ๋ฉด์ ์์ง ์๋ค. seed/ ์ JSON ์ ์ฐ๊ณ ๋ฃ๋๋ค. seed/blog01-final.json ์ด ์ค์ ์, seed/example.json ์ด ํ์ ์ค๋ช
์ด๋ค.
bun run db:seed:local seed/blog01-final.json
bun run db:seed:remote seed/blog01-final.jsonํ๋ก๊ทธ๋จยท๊ธฐ์ยท๋ฆฌ๋๋ ์ด๋ฏธ ์์ผ๋ฉด ๊ฑด๋๋ฐ๊ณ , ์ค๋ฌธ์ ๊ฐ์ id ๊ฐ ์์ผ๋ฉด ์คํจํ๋ค.
๋ฌธํญ์ ๋ ์ข ๋ฅ๋ค.
{ "common": "goal_achieved" }โsrc/questions/common.ts์ ๊ณตํต ๋ฌธํญ. ๋ชจ๋ ํ๋ก๊ทธ๋จ์ด ๊ฐ์key๋ก ๋ฌป๋๋ค. ๋ฌธ๊ตฌ ์{program},{activity}๊ฐ์ ์๋ฆฌํ์์๋ ์ค๋ฌธ์vars๋ก ์ฑ์ด๋ค. ํ๋ก๊ทธ๋จ๋ณ ๊ฐ์ docs/questions.md ์ฐธ๊ณ . ๊ธฐ์ยทํ๋ก๊ทธ๋จ ๊ฐ ๋น๊ต๋ ์ดkey๋ก ํ๋ค. ๊ณตํต ๋ฌธํญ ๋ฌธ๊ตฌ๋ฅผ ๊ณ ์น๋ฉด ์ด์ ๊ธฐ์์ ๋น๊ต๊ฐ ๊นจ์ง๋ฏ๋ก ์ ์คํ.{ "type": "long", "label": "โฆ" }โ ์ด ์ค๋ฌธ๋ง์ ๋ฌธํญ.key๋ ๋น์ด ์๋ค.
๋ ๋ค required(๊ธฐ๋ณธ true)์ config ๋ฅผ ์ค ์ ์๋ค. ์ ํ์ scale, short, long, choice ๋ค ๊ฐ์ง.
๊ฐ ์ ํ์ ์ ์ฅ๊ฐยท๊ฒ์ฆยทconfigยท๊ณตํต ๋ฌธํญ ๋ชฉ๋กยท์ ํ ์ถ๊ฐ ์ ์ฐจ๋ docs/questions.md ์ ์๋ค.
# src/db/schema.ts ์์ ํ
bunx drizzle-kit generate --name <์ค๋ช
>
bun run db:migrate:localmain ์ push ํ๋ฉด Cloudflare Workers Builds ๊ฐ bun run build โ npx wrangler deploy ๋ฅผ ์คํํ๋ค.
๋ค๋ฅธ ๋ธ๋์น๋ฅผ push ํ๋ฉด ํ๋ฆฌ๋ทฐ ๋น๋๊ฐ ๋๋ค. bun run deploy ๋ ์๋ ๋ฐฐํฌ๊ฐ ์ ๋ ๋์ ์๋ fallback.
์ด๋ฏธ ์ค์ ๋ ๊ฒ (๋ค์ ๋ง๋ค ํ์ ์์):
- D1
feedback(APAC) โ id ๋wrangler.jsonc์ ์์ - ์ํฌ๋ฆฟ
GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET,HMAC_SECRET - ์ปค์คํ
๋๋ฉ์ธ
feedback.dalestudy.com(wrangler.jsonc์routes) - Workers Builds โ
DaleStudy/feedback์ฐ๊ฒฐ. ๋น๋ ๋ณ์BUN_VERSION=1.4.0(๋น๋ ์ด๋ฏธ์ง ๊ธฐ๋ณธ bun 1.2.15 ๋ lockfile v2 ๋ฅผ ๋ชป ์ฝ๋๋ค. ๋ก์ปฌ bun ์ ์ฌ๋ฆฌ๋ฉด ๊ฐ์ด ์ฌ๋ฆฐ๋ค) - GitHub App Callback URL:
http://localhost:3000/auth/callback,https://feedback.dalestudy.com/auth/callback
HMAC_SECRET ์ ๋ฐ๊พธ๋ฉด ๊ธฐ์กด ์ต๋ช
์๋ต์์ ์ค๋ณต ๋ฐฉ์ง ํค๊ฐ ๋ฌ๋ผ์ง๋ฏ๋ก ๊ต์ฒดํ์ง ์๋๋ค.
์คํค๋ง๊ฐ ๋ฐ๋๋ฉด ๋ฐฐํฌ ์ ์ bun run db:migrate:remote ๋ฅผ ์ง์ ์คํํ๋ค.