architecture
기술 스택 매트릭스
6 프레임워크 × 6 데이터베이스 생태계 기술 현황
기술 스택 매트릭스
공통 기반
모든 앱이 공유하는 기술 기반입니다.
| 항목 | 값 |
|---|---|
| 런타임 | Bun |
| 언어 | TypeScript (strict mode) |
| 린터/포매터 | Biome v2 |
| 스타일링 | UnoCSS v66+ Wind4 프리셋 |
| 플랫폼 | Cloudflare Pages + Workers |
Tailwind CSS는 사용하지 않습니다. 전 프로젝트가 UnoCSS Wind4 프리셋을 표준으로 채택했습니다.
프레임워크 분포
6종의 프레임워크가 역할에 따라 배치되어 있습니다.
| 프레임워크 | 앱 수 | 주요 용도 |
|---|---|---|
| SvelteKit 5 | 9 | 핵심 앱 (SSO, 결제, LMS 등) |
| SolidStart | 4 | 고성능 인터랙티브 앱 |
| Astro | 3 + 모든 랜딩 | 정적 사이트, 문서, 마케팅 |
| Qwik | 2 | 점진적 하이드레이션 앱 |
| Hono | 1 | API 전용 서비스 |
| Nuxt 3 | 1 | Vue 기반 앱 |
프레임워크 선택 기준
인증/결제 등 핵심 서비스 → SvelteKit 5
실시간 인터랙션 중심 → SolidStart
콘텐츠/마케팅/문서 → Astro
초기 로드 성능 극대화 → Qwik
순수 API (UI 없음) → Hono
Vue 생태계 활용 필요 → Nuxt 3
데이터베이스 분포
6종의 DB가 데이터 특성에 따라 선택됩니다.
| 데이터베이스 | 앱 수 | 특성 |
|---|---|---|
| Neon Postgres | 9 | 관계형 데이터, 트랜잭션 |
| Cloudflare D1 | 6 | 경량 SQLite, 엣지 로컬 |
| Cloudflare R2 | 2 | 오브젝트 스토리지 (파일, 미디어) |
| Turso | 1 | 분산 SQLite (libSQL) |
| Durable Objects | 1 | 실시간 상태 (WebSocket) |
| Upstash Redis | 1 | 캐시, 세션, 레이트 리밋 |
외부 DB 연결
Neon Postgres와 Turso는 Cloudflare Workers에서 직접 접근이 불가능합니다. Hyperdrive를 경유하여 연결합니다.
// wrangler.jsonc
{
"hyperdrive": [{
"binding": "DB",
"id": "<hyperdrive-config-id>"
}]
}
// Worker 내부
const db = drizzle(env.DB);
UI 컴포넌트 전략
각 프레임워크에 맞는 헤드리스 UI 라이브러리를 사용합니다.
| 프레임워크 | 헤드리스 UI | 비고 |
|---|---|---|
| SvelteKit 5 | shadcn-svelte (Bits UI) | Svelte 5 runes 호환 |
| SolidStart | Kobalte | Solid 전용 접근성 프리미티브 |
| Nuxt 3 | Nuxt UI | Vue 3 기반 |
| Qwik | 커스텀 구현 | 전용 라이브러리 부재 |
| Astro | 커스텀 구현 | 정적 우선, JS 최소화 |
스타일링 규칙
// uno.config.ts — 모든 프로젝트 공통 구조
import { defineConfig, presetWind4 } from "unocss";
export default defineConfig({
presets: [presetWind4()],
// 앱별 커스텀 테마는 여기에 추가
});
House of Brands 원칙에 따라, 각 앱의 디자인 토큰(색상, 타이포그래피, 간격)은 완전히 독립적입니다. 공유 디자인 토큰 패키지는 존재하지 않습니다.
앱별 스택 매트릭스
Universal Services
| 앱 | 프레임워크 | DB | 헤드리스 UI |
|---|---|---|---|
| modfolio-connect | SvelteKit 5 | Neon Postgres | shadcn-svelte |
| modfolio-pay | SvelteKit 5 | Neon Postgres | shadcn-svelte |
Infrastructure
| 앱 | 프레임워크 | DB | 헤드리스 UI |
|---|---|---|---|
| modfolio-admin | SvelteKit 5 | D1 | shadcn-svelte |
| modfolio-dev | SvelteKit 5 | D1 | shadcn-svelte |
| modfolio-on | SvelteKit 5 | Neon Postgres | shadcn-svelte |
| modfolio-press | SvelteKit 5 | Neon Postgres | shadcn-svelte |
| modfolio-docs | Astro | — | 커스텀 |
Works 그룹
| 앱 | 프레임워크 | DB | 헤드리스 UI |
|---|---|---|---|
| Naviaca | SvelteKit 5 | Neon Postgres | shadcn-svelte |
| GistCore | SolidStart | Neon Postgres | Kobalte |
| Fortiscribe | SolidStart | Neon Postgres | Kobalte |
| KeepNBuild | SolidStart | D1 | Kobalte |
| Worthee | Qwik | D1 | 커스텀 |
LS 그룹
| 앱 | 프레임워크 | DB | 헤드리스 UI |
|---|---|---|---|
| Amberstella | Nuxt 3 | Neon Postgres | Nuxt UI |
| Munseo | SolidStart | D1 | Kobalte |
| Sincheong | Qwik | D1 | 커스텀 |
Axiom 그룹
| 앱 | 프레임워크 | DB | 헤드리스 UI |
|---|---|---|---|
| Umbracast | Hono | R2 + Durable Objects | — |
ORM: Drizzle
모든 SQL 기반 앱은 Drizzle ORM을 사용합니다.
// 스키마 정의 예시
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: uuid("id").primaryKey().defaultRandom(),
email: text("email").notNull().unique(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
DB별 Drizzle 드라이버 매핑은 다음과 같습니다.
| DB | Drizzle 드라이버 |
|---|---|
| Neon Postgres | drizzle-orm/neon-http |
| D1 | drizzle-orm/d1 |
| Turso | drizzle-orm/libsql |
각 어댑터별 상세 패턴(prefix 규칙, 마이그레이션, 인덱스 헬퍼)은 프로젝트별 Drizzle 설정을 따릅니다.