๐ miri.dev ์ ๊ธฐ๋ฅ: ํ๋ก์ ํธ ๊ธฐ๋ฐ ๋ฐฐํฌ ์์คํ
์๋ ํ์ธ์! miri.dev์ ๊ฒ์ ์ฒด์ธ์ ๊ฐ ๋ ์๋ก์ด ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์์ต๋๋ค! ๐
๊ธฐ์กด์ ๋จ์ํ ํ์ผ ์ ๋ก๋ ๋ฐฉ์์์ ํ ๋จ๊ณ ๋ฐ์ ํ์ฌ, ํ๋ก์ ํธ ๊ธฐ๋ฐ ๋ฐฐํฌ ์์คํ ์ ๋์ ํ์ต๋๋ค. ์ด์ ํ๋์ ํ๋ก์ ํธ์์ ์ฌ๋ฌ ๋ฐฐํฌ ๋ฒ์ ์ ๊ด๋ฆฌํ๊ณ , ๊ณ ์ ๋ ๋๋ฉ์ธ์ผ๋ก ํญ์ ์ต์ ๋ฒ์ ์ ์ ๊ทผํ ์ ์์ต๋๋ค!
๐ฏ ๋ฌด์์ด ๋ฌ๋ผ์ก๋์?
๊ธฐ์กด ๋ฐฉ์์ ํ๊ณ
- ๐ ์์ ๋๋ฉ์ธ: ๋ฐฐํฌํ ๋๋ง๋ค ์๋ก์ด ๋๋ค ๋๋ฉ์ธ ์์ฑ
- ๐ ๋ฒ์ ๊ด๋ฆฌ ๋ถ์ฌ: ์ด์ ๋ฐฐํฌ์์ ์ฐ๊ฒฐ์ฑ ์์
- ๐ ๋ถํธํ ์ ๋ฐ์ดํธ: ์ ๋ฐฐํฌ ์๋ง๋ค ๋๋ฉ์ธ์ด ๋ฐ๋์ด ๋งํฌ ๊ด๋ฆฌ ์ด๋ ค์
- ๐ ํต๊ณ ๋ถ์ฐ: ๋ฐฐํฌ๋ณ๋ก ์กฐํ์๊ฐ ๋ถ๋ฆฌ๋์ด ์ ์ฒด ์ฑ๊ณผ ํ์ ์ด๋ ค์
๐ ์๋ก์ด ํ๋ก์ ํธ ์์คํ
- ๐ ๊ณ ์ ๋๋ฉ์ธ:
project-name-12345678.miri.dev
ํํ์ ์๊ตฌ ๋๋ฉ์ธ - ๐ ๋ฒ์ ๊ด๋ฆฌ: ํ๋์ ํ๋ก์ ํธ์ ์ฌ๋ฌ ๋ฐฐํฌ ์ฐ๊ฒฐ ๋ฐ ์ด๋ ฅ ๊ด๋ฆฌ
- โก ๋ฌด์ค๋จ ๋ฐฐํฌ: ์ ๋ฐฐํฌ ์ ์๋์ผ๋ก ํ์ฌ ๋ฒ์ ๊ต์ฒด
- ๐ ํตํฉ ํต๊ณ: ํ๋ก์ ํธ ๋จ์๋ก ๋ฐฐํฌ ํํฉ๊ณผ ์ฑ๊ณผ ์ถ์
๐ ๏ธ ์๋ก์ด ๊ธฐ๋ฅ ์์ธ ๊ฐ์ด๋
1. ๐ฆ ํ๋ก์ ํธ ์์ฑํ๊ธฐ
๋ง์ดํ์ด์ง์์ "๐ฆ ํ๋ก์ ํธ" ํญ์ ํด๋ฆญํ๊ณ "์ ํ๋ก์ ํธ" ๋ฒํผ์ ๋๋ฌ๋ณด์ธ์!
// ํ๋ก์ ํธ ์์ฑ ์ ์๋์ผ๋ก ์์ฑ๋๋ ๊ตฌ์กฐ
{
projectName: "my-portfolio",
subdomain: "my-portfolio-a1b2c3d4", // 8์๋ฆฌ ๊ณ ์ ID ์ถ๊ฐ
domain: "my-portfolio-a1b2c3d4.miri.dev",
deployments: [], // ๋ฐฐํฌ ์ด๋ ฅ
currentVersion: null // ํ์ฌ ํ์ฑ ๋ฐฐํฌ
}
ํ๋ก์ ํธ ์ด๋ฆ ๊ท์น:
- โ ์๋ฌธ, ์ซ์, ํ์ดํ(-) ์ฌ์ฉ ๊ฐ๋ฅ
- โ 1-50์ ์ ํ
- โ ํน์๋ฌธ์๋ ์๋์ผ๋ก ํ์ดํ์ผ๋ก ๋ณํ
- โ 8์๋ฆฌ ๊ณ ์ ID๊ฐ ์๋ ์ถ๊ฐ๋์ด ์ค๋ณต ๋ฐฉ์ง
2. ๐ ํ๋ก์ ํธ์ ๋ฐฐํฌํ๊ธฐ
๊ธฐ์กด ๋ฐฐํฌ ๋ฐฉ์์ ํ๋ก์ ํธ ์ฐ๊ฒฐ ์ต์ ์ด ์ถ๊ฐ๋์์ต๋๋ค:
์ ํ๋ก์ ํธ๋ก ๋ฐฐํฌ:
// ๋ฐฐํฌ ์ ํ๋ก์ ํธ๋ช
์
๋ ฅ
{
files: [...],
projectName: "์-ํ๋ก์ ํธ๋ช
", // ์ ํ๋ก์ ํธ ์๋ ์์ฑ
deploymentNotes: "์ฒซ ๋ฒ์งธ ๋ฐฐํฌ"
}
๊ธฐ์กด ํ๋ก์ ํธ์ ์ถ๊ฐ ๋ฐฐํฌ:
// ๊ธฐ์กด ํ๋ก์ ํธ ID๋ก ์ฐ๊ฒฐ
{
files: [...],
projectId: "abc123...", // ๊ธฐ์กด ํ๋ก์ ํธ ID
deploymentNotes: "๋ฒ๊ทธ ์์ ๋ฐ ์ฑ๋ฅ ๊ฐ์ "
}
3. ๐ ์๋ ๋ฒ์ ๊ด๋ฆฌ
ํ๋ก์ ํธ์ ์๋ก์ด ๋ฐฐํฌ๊ฐ ์ถ๊ฐ๋ ๋๋ง๋ค:
- ๋ฒ์ ๋ฒํธ ์๋ ์ฆ๊ฐ: v1, v2, v3...
- ์ด์ ๋ฐฐํฌ ๋ณด๊ด: ๋ชจ๋ ๋ฐฐํฌ ์ด๋ ฅ ์ ์ง
- ํ์ฌ ๋ฐฐํฌ ๊ต์ฒด: ์ ๋ฐฐํฌ๊ฐ ์๋์ผ๋ก ํ์ฑํ
- ๋๋ฉ์ธ ์ ์ง: ๊ฐ์ ํ๋ก์ ํธ ๋๋ฉ์ธ์ผ๋ก ์ต์ ๋ฐฐํฌ ์ ๊ทผ
graph TD
A[์ ๋ฐฐํฌ ์
๋ก๋] --> B[๋ฒ์ ๋ฒํธ ํ ๋น]
B --> C[์ด์ ๋ฐฐํฌ ๋นํ์ฑํ]
C --> D[์ ๋ฐฐํฌ ํ์ฑํ]
D --> E[ํ๋ก์ ํธ ๋๋ฉ์ธ ์๋ ์ฐ๊ฒฐ]
E --> F[์ฌ์ฉ์๋ ๊ฐ์ URL๋ก ์ ๊ทผ]
๐ฑ ์๋ก์์ง ๋ง์ดํ์ด์ง UI
๐๏ธ ํญ ๊ธฐ๋ฐ ๊ด๋ฆฌ ์์คํ
๋ง์ดํ์ด์ง๊ฐ ๋์ฑ ์ง๊ด์ ์ผ๋ก ๊ฐํธ๋์์ต๋๋ค:
- ๐ ์ฌ์ดํธ ๋ชฉ๋ก: ๊ฐ๋ณ ๋ฐฐํฌ๋ค์ ๊ด๋ฆฌ
- ๐ฆ ํ๋ก์ ํธ: ํ๋ก์ ํธ ๋จ์๋ก ๊ด๋ฆฌ
๐จ ํฅ์๋ ์ฌ์ดํธ ์นด๋ ๋์์ธ
๊ฐ ์ฌ์ดํธ ์นด๋์์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ํ๋์:
interface EnhancedSiteCard {
// ๊ธฐ๋ณธ ์ ๋ณด
name: string;
url: string;
createdAt: string;
expiresAt: string;
// ๐ ํ๋ก์ ํธ ์ฐ๊ฒฐ ์ ๋ณด
projectName?: string;
projectDomain?: string;
deploymentVersion?: number;
isCurrent?: boolean; // ํ์ฌ ํ์ฑ ๋ฐฐํฌ์ธ์ง
deploymentNotes?: string;
// ๐ ์ฐ๊ฒฐ ์ํ (์ด์ค ํ์ธ ์์คํ
)
connectionStatus: 'full' | 'db_only' | 'metadata_only' | 'partial';
confidence: number; // ๋ฐ์ดํฐ ์ ๋ขฐ๋ (0-100%)
}
๐ฏ ํ๋ก์ ํธ ์นด๋ ์ ๋์์ธ
ํ๋ก์ ํธ๋ณ๋ก ํตํฉ๋ ์ ๋ณด๋ฅผ ์ ๊ณต:
- ๐ ๊ณ ์ ๋๋ฉ์ธ: ํด๋ฆญ ํ ๋ฒ์ผ๋ก ๋ฐ๋ก ์ ๊ทผ
- ๐ ๋ฐฐํฌ ํต๊ณ: ์ด ๋ฐฐํฌ ์, ํ์ฑ ๋ฐฐํฌ ์
- ๐ ๋ง์ง๋ง ๋ฐฐํฌ: ์ต๊ทผ ๋ฐฐํฌ ์๊ฐ
- โญ ํ์ฌ ๋ฒ์ : ํ์ฌ ํ์ฑํ๋ ๋ฐฐํฌ ์ ๋ณด
๐ง ๊ฐ๋ฐ์๋ฅผ ์ํ ๊ธฐ์ ์ ์ธ๋ถ์ฌํญ
๐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง
-- ํ๋ก์ ํธ ํ
์ด๋ธ
CREATE TABLE projects (
id UUID PRIMARY KEY,
project_name TEXT NOT NULL,
short_id VARCHAR(8) UNIQUE NOT NULL, -- ๊ณ ์ 8์๋ฆฌ ID
subdomain TEXT UNIQUE NOT NULL, -- project-name-shortid
user_id TEXT NOT NULL,
current_deployment_id UUID, -- ํ์ฌ ํ์ฑ ๋ฐฐํฌ
created_at TIMESTAMPTZ DEFAULT now()
);
-- ํ์ฅ๋ ๋ฐฐํฌ ํ
์ด๋ธ
ALTER TABLE deployed_sites ADD COLUMN
project_id UUID, -- ํ๋ก์ ํธ ์ฐ๊ฒฐ
deployment_version INTEGER DEFAULT 1, -- ๋ฒ์ ๋ฒํธ
is_current BOOLEAN DEFAULT false, -- ํ์ฌ ํ์ฑ ์ฌ๋ถ
deployment_notes TEXT; -- ๋ฐฐํฌ ๋
ธํธ
๐ฆ ์๋ ๋ผ์ฐํ ์์คํ
๋ฏธ๋ค์จ์ด์์ ํ๋ก์ ํธ ๋๋ฉ์ธ์ ์๋ ๊ฐ์ง:
// ํ๋ก์ ํธ ๋๋ฉ์ธ ํจํด ๋งค์นญ
const projectDomainPattern = /^(.+)-([a-f0-9]{8})$/;
if (projectDomainPattern.test(subdomain)) {
// ํ๋ก์ ํธ์ ํ์ฌ ๋ฐฐํฌ๋ก ์๋ ๋ผ์ฐํ
const currentDeployment = await getCurrentDeployment(subdomain);
return NextResponse.rewrite(new URL(`/site/${currentDeployment.id}`, request.url));
}
๐ ๋ฐฐํฌ ํจ์
ํต์ฌ ํ๋ก์ ํธ ๊ด๋ฆฌ ํจ์๋ค:
-- ํ๋ก์ ํธ ์์ฑ
CREATE FUNCTION create_project(
p_project_name TEXT,
p_user_id TEXT
) RETURNS project_info;
-- ํ๋ก์ ํธ์ ๋ฐฐํฌ ์ถ๊ฐ
CREATE FUNCTION deploy_to_project(
p_project_id UUID,
p_site_id UUID,
p_deployment_notes TEXT
) RETURNS BOOLEAN;
-- ํ์ฌ ๋ฐฐํฌ ์กฐํ
CREATE FUNCTION get_current_deployment(
p_subdomain TEXT
) RETURNS deployment_info;
๐ฏ ์ฌ์ฉ ์๋๋ฆฌ์ค
๐ ๊ฐ์ธ ํฌํธํด๋ฆฌ์ค ๊ด๋ฆฌ
# 1. ํ๋ก์ ํธ ์์ฑ
Project: "my-portfolio"
Domain: my-portfolio-a1b2c3d4.miri.dev
# 2. ์ด๊ธฐ ๋ฒ์ ๋ฐฐํฌ
Version: v1 (๊ธฐ๋ณธ ํฌํธํด๋ฆฌ์ค)
# 3. ๋์์ธ ์
๋ฐ์ดํธ
Version: v2 (์๋ก์ด ํ
๋ง ์ ์ฉ)
# 4. ํ๋ก์ ํธ ์ถ๊ฐ
Version: v3 (์๋ก์ด ํ๋ก์ ํธ ์ถ๊ฐ)
# ์ฌ์ฉ์๋ ํญ์ ๊ฐ์ URL๋ก ์ต์ ๋ฒ์ ํ์ธ ๊ฐ๋ฅ!
๐ข ํด๋ผ์ด์ธํธ ํ๋ก์ ํธ ๊ด๋ฆฌ
# ํ๋ก์ ํธ๋ณ๋ก ๋ณ๋ ๋๋ฉ์ธ ๊ด๋ฆฌ
company-website-b2c3d4e5.miri.dev # ํ์ฌ ์น์ฌ์ดํธ
landing-page-c3d4e5f6.miri.dev # ๋๋ฉํ์ด์ง
event-site-d4e5f6g7.miri.dev # ์ด๋ฒคํธ ์ฌ์ดํธ
# ๊ฐ๊ฐ ๋
๋ฆฝ์ ์ธ ๋ฐฐํฌ ์ด๋ ฅ๊ณผ ๋ฒ์ ๊ด๋ฆฌ
๐ฎ ์์ผ๋ก์ ๊ณํ
Phase 1 (์๋ฃ) โ
- โ ๊ธฐ๋ณธ ํ๋ก์ ํธ ์์คํ
- โ ์๋ ๋ผ์ฐํ
- โ ๋ง์ดํ์ด์ง UI ๊ฐ์
Phase 2 (์งํ ์ค) ๐ง
- ๐ ๋ฐฐํฌ ํ์คํ ๋ฆฌ ์์ธ ๋ณด๊ธฐ
- ๐ ํ๋ก์ ํธ ์ค์ ๊ด๋ฆฌ
- ๐ ์ปค์คํ ๋๋ฉ์ธ ์ฐ๊ฒฐ
Phase 3 (๊ณํ) ๐
- ๐ Git ์ ์ฅ์ ์ฐ๋
- ๐ ์นํ ๊ธฐ๋ฐ ์๋ ๋ฐฐํฌ
- ๐ ํ๊ฒฝ๋ณ ๋ฐฐํฌ (dev/staging/prod)
- ๐ ํ์ ๊ธฐ๋ฅ (ํ ๋ฉค๋ฒ ์ด๋)
Phase 4 (๋ฏธ๋) ๐
- ๐ CI/CD ํ์ดํ๋ผ์ธ ์ฐ๋
- ๐ A/B ํ ์คํธ ์ง์
- ๐ ์ค์๊ฐ ๋ถ์ ๋์๋ณด๋
- ๐ ๋ชจ๋ฐ์ผ ์ฑ ๋ฐฐํฌ ์ง์
๐ ์ง๊ธ ๋ฐ๋ก ์ฒดํํด๋ณด์ธ์!
- miri.dev ์ ์
- ์นด์นด์ค/๋ค์ด๋ฒ ๋ก๊ทธ์ธ ํ ๋ง์ดํ์ด์ง ์ด๋
- "๐ฆ ํ๋ก์ ํธ" ํญ์์ ์ฒซ ํ๋ก์ ํธ ์์ฑ
- ํ์ผ ์ ๋ก๋ ์ ํ๋ก์ ํธ ์ฐ๊ฒฐ ์ ํ
- ๊ณ ์ ๋๋ฉ์ธ์ผ๋ก ๋ฐ๋ก ํ์ธ!
๐ฌ ํผ๋๋ฐฑ์ ๊ธฐ๋ค๋ฆฝ๋๋ค
์๋ก์ด ํ๋ก์ ํธ ์์คํ ์ด ์ด๋ ์ ๊ฐ์?
- ๐ ๋ฒ๊ทธ ๋ฆฌํฌํธ: ์ด์ ์ ๋ณด
- ๐ก ๊ธฐ๋ฅ ์ ์: ์์ด๋์ด ๊ณต์
- ๐ค ์ฌ์ฉ ํ๊ธฐ: ๊ฒฝํ ๊ณต์
์ฌ๋ฌ๋ถ์ ์์คํ ์๊ฒฌ์ผ๋ก miri.dev๊ฐ ๋์ฑ ๋ฐ์ ํ ์ ์์ต๋๋ค! ๐
miri.dev์ ํจ๊ป ๋ ์ค๋งํธํ ์น ๊ฐ๋ฐ์ ๊ฒฝํํด๋ณด์ธ์! ๐ปโจ