import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
async function testPRDDocuments() {
try {
const db = await open({
filename: './data/workflow.db',
driver: sqlite3.Database
});
console.log('๐ PRD ๋ฌธ์ ๊ธฐ๋ฅ ํ
์คํธ ์์...\n');
// 1. ๋จผ์ PRD ๋ชฉ๋ก ํ์ธ
console.log('1๏ธโฃ ๊ธฐ์กด PRD ๋ชฉ๋ก:');
const prds = await db.all('SELECT id, title FROM prds LIMIT 3');
prds.forEach(prd => {
console.log(` - [${prd.id}] ${prd.title}`);
});
if (prds.length === 0) {
console.log(' โ PRD๊ฐ ์์ต๋๋ค.');
await db.close();
return;
}
const testPRD = prds[0];
console.log(`\n๐ ํ
์คํธ ๋์: ${testPRD.title}\n`);
// 2. PRD์ ์์ธ ๋ฌธ์ ์์ฑ
console.log('2๏ธโฃ PRD ์์ธ ๋ฌธ์ ์์ฑ...');
const documentResult = await db.run(`
INSERT INTO documents (title, content, doc_type, category, tags, summary, created_by, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`, [
`${testPRD.title} - ์์ธ ๊ธฐ์ ๋ช
์ธ์`,
`# ${testPRD.title} ์์ธ ๋ช
์ธ
## ๋น์ฆ๋์ค ๋ชฉํ
๊ฐ๋ฐ์ ์ค์ฌ MCP ํจํค์ง ๊ณต์ ์ปค๋ฎค๋ํฐ ๊ตฌ์ถ. ๋ฌด๋ฃ 6๊ฐ์ ์ด์ ํ ๊ด๊ณ +๊ตฌ๋
์์ต ๋ชจ๋ธ๋ก ์ง์๊ฐ๋ฅํ ๋น์ฆ๋์ค ๋ชจ๋ธ ๋ฌ์ฑ.
## ํ๊ฒ ์ฌ์ฉ์
- MCP ํจํค์ง ๊ฐ๋ฐ์
- ํด๋ก๋ ์ฌ์ฉ์
- AI ์ ํ๋ฆฌ์ผ์ด์
๊ฐ๋ฐ์
## ์ฑ๊ณต ๊ธฐ์ค
- 6๊ฐ์๊ฐ ์์ ๋ฌด๋ฃ ์ด์ ๋ฌ์ฑ
- 3๊ฐ์ ๋ด ์ $100+ ์์ต ์ ํ
- 10,000 MAU ๋ฌ์ฑ
- ์์ต ๋๋น ์ธํ๋ผ ๋น์ฉ 20% ์ดํ ์ ์ง
## ๊ธฐ์ ์ ์ฝ์ฌํญ
- ์คํ: SvelteKit + Vercel + Supabase
- ๋์ญํญ ํ๊ณ: Supabase 2GB ์ ํ
- ๋ฌด๋ฃ ํ๋ ์ต๋ ํ์ฉ
- 30๋ถ ๋ด MVP ๋ฐฐํฌ ๊ฐ๋ฅ
## ํต์ฌ ๊ธฐ๋ฅ
### ์ธ์ฆ ์์คํ
- Google OAuth ์์
๋ก๊ทธ์ธ
- Supabase Auth ํ์ฉ
### ํจํค์ง ๊ด๋ฆฌ
- GitHub API ์ฐ๋ ์๋ ์์ง
- ํจํค์ง ๋ฉํ๋ฐ์ดํฐ ๊ด๋ฆฌ
### ํ๊ฐ ์์คํ
- 5์ ๋ง์ ๋ณ์ ํ๊ฐ
- ์์ธ ๋ฆฌ๋ทฐ ์์ฑ
### ์์ต ๋ชจ๋ธ
- Google AdSense ๊ด๊ณ
- ํ๋ฆฌ๋ฏธ์ ๊ตฌ๋
($5/์)`,
'specification',
`prd-${testPRD.id}`,
'["mcp", "package-hub", "specification", "technical-spec"]',
'MCP Hub ํจํค์ง ๊ณต์ ํ๋ซํผ์ ์์ธ ๊ธฐ์ ๋ช
์ธ์ - ๋น์ฆ๋์ค ๋ชฉํ, ๊ธฐ์ ์ ์ฝ, ํต์ฌ ๊ธฐ๋ฅ ํฌํจ',
'test-script',
'approved'
]);
let documentId = documentResult.lastInsertRowid;
// SQLite lastInsertRowid๊ฐ undefined์ธ ๊ฒฝ์ฐ ์ง์ ์กฐํ
if (!documentId) {
const lastDoc = await db.get('SELECT last_insert_rowid() as id');
documentId = lastDoc.id;
}
console.log(` โ
๋ฌธ์ ์์ฑ ์๋ฃ! ID: ${documentId}`);
if (!documentId) {
console.error(' โ ๋ฌธ์ ID๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.');
await db.close();
return;
}
// 3. PRD์ ๋ฌธ์ ์ฐ๊ฒฐ
console.log('\n3๏ธโฃ PRD-๋ฌธ์ ์ฐ๊ฒฐ ์์ฑ...');
await db.run(`
INSERT INTO document_links (document_id, linked_entity_type, linked_entity_id, link_type)
VALUES (?, ?, ?, ?)
`, [documentId, 'prd', testPRD.id, 'specification']);
console.log(' โ
PRD-๋ฌธ์ ์ฐ๊ฒฐ ์๋ฃ!');
// 4. ์ฐ๊ฒฐ๋ ๋ฌธ์ ์กฐํ ํ
์คํธ
console.log('\n4๏ธโฃ PRD ์ฐ๊ฒฐ ๋ฌธ์ ์กฐํ...');
const linkedDocs = await db.all(`
SELECT d.id, d.title, d.doc_type, d.summary, d.created_at,
dl.link_type, dl.created_at as linked_at
FROM documents d
INNER JOIN document_links dl ON d.id = dl.document_id
WHERE dl.linked_entity_type = 'prd' AND dl.linked_entity_id = ?
`, [testPRD.id]);
console.log(` ๐ ์ฐ๊ฒฐ๋ ๋ฌธ์ ${linkedDocs.length}๊ฐ:`);
linkedDocs.forEach(doc => {
console.log(` - [${doc.id}] ${doc.title}`);
console.log(` ๐ ์ ํ: ${doc.doc_type} | ๐ ๋งํฌ: ${doc.link_type}`);
console.log(` ๐ ์์ฝ: ${doc.summary}`);
console.log(` ๐
์์ฑ: ${new Date(doc.created_at).toLocaleString('ko-KR')}`);
});
// 5. FTS ๊ฒ์ ํ
์คํธ
console.log('\n5๏ธโฃ ์ ๋ฌธ ๊ฒ์ ํ
์คํธ...');
const searchResults = await db.all(`
SELECT d.id, d.title,
snippet(documents_fts, 1, '<mark>', '</mark>', '...', 15) as snippet
FROM documents d
INNER JOIN document_links dl ON d.id = dl.document_id
INNER JOIN documents_fts ON documents_fts.rowid = d.id
WHERE dl.linked_entity_type = 'prd'
AND dl.linked_entity_id = ?
AND documents_fts MATCH ?
ORDER BY rank
`, [testPRD.id, '์์ต']);
console.log(` ๐ "์์ต" ๊ฒ์ ๊ฒฐ๊ณผ ${searchResults.length}๊ฐ:`);
searchResults.forEach(result => {
console.log(` - [${result.id}] ${result.title}`);
console.log(` ๐ ์ค๋ํซ: ${result.snippet}`);
});
// 6. ์
๋ฐ์ดํธ ํ
์คํธ
console.log('\n6๏ธโฃ ๋ฌธ์ ์
๋ฐ์ดํธ ํ
์คํธ...');
await db.run(`
UPDATE documents
SET summary = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?
`, [
'MCP Hub ํ๋ซํผ ์์ธ ๋ช
์ธ - ์
๋ฐ์ดํธ๋จ (๋น์ฆ๋์ค ๋ชฉํ, ๊ธฐ์ ์คํ, ์์ต ๋ชจ๋ธ ํฌํจ)',
documentId
]);
console.log(` โ
๋ฌธ์ [${documentId}] ์
๋ฐ์ดํธ ์๋ฃ!`);
// 7. ์ต์ข
๊ฒ์ฆ
console.log('\n7๏ธโฃ ์ต์ข
๊ฒ์ฆ...');
const finalDoc = await db.get(`
SELECT d.*, dl.link_type
FROM documents d
INNER JOIN document_links dl ON d.id = dl.document_id
WHERE d.id = ?
`, [documentId]);
console.log(' ๐ ์ต์ข
๋ฌธ์ ์ ๋ณด:');
console.log(` - ID: ${finalDoc.id}`);
console.log(` - ์ ๋ชฉ: ${finalDoc.title}`);
console.log(` - ์ ํ: ${finalDoc.doc_type}`);
console.log(` - ๋งํฌ: ${finalDoc.link_type}`);
console.log(` - ์นดํ
๊ณ ๋ฆฌ: ${finalDoc.category}`);
console.log(` - ์ํ: ${finalDoc.status}`);
console.log(` - ์์ฝ: ${finalDoc.summary}`);
await db.close();
console.log('\n๐ PRD ๋ฌธ์ ์์คํ
ํ
์คํธ ์๋ฃ!');
console.log('\n๐ ํ
์คํธ ๊ฒฐ๊ณผ:');
console.log(' โ
PRD ์์ธ ๋ฌธ์ ์์ฑ');
console.log(' โ
PRD-๋ฌธ์ ์๋ ์ฐ๊ฒฐ');
console.log(' โ
์ฐ๊ฒฐ ๋ฌธ์ ์กฐํ');
console.log(' โ
์ ๋ฌธ ๊ฒ์ (FTS)');
console.log(' โ
๋ฌธ์ ์
๋ฐ์ดํธ');
console.log(' โ
๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฆ');
} catch (error) {
console.error('โ ํ
์คํธ ์คํจ:', error.message);
console.error(error.stack);
}
}
testPRDDocuments();