@su-record/vibe 2.8.18 → 2.8.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/infra/lib/config/GlobalConfigManager.d.ts +8 -0
- package/dist/infra/lib/config/GlobalConfigManager.d.ts.map +1 -1
- package/dist/infra/lib/config/GlobalConfigManager.js +37 -0
- package/dist/infra/lib/config/GlobalConfigManager.js.map +1 -1
- package/hooks/scripts/context-save.js +88 -1
- package/hooks/scripts/pre-tool-guard.js +30 -5
- package/hooks/scripts/sentinel-guard.js +28 -4
- package/hooks/scripts/utils.js +48 -0
- package/package.json +1 -1
- package/skills/vibe-figma-analyze/SKILL.md +150 -34
- package/skills/vibe-figma-frame/SKILL.md +359 -47
- package/skills/vibe-figma-rules/SKILL.md +94 -51
|
@@ -15,6 +15,14 @@ type DeepPartial<T> = {
|
|
|
15
15
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
16
16
|
};
|
|
17
17
|
export declare function patchGlobalConfig(patch: DeepPartial<GlobalVibeConfig>): void;
|
|
18
|
+
/** .claude/vibe/config.json (프로젝트별 설정) */
|
|
19
|
+
export declare function getProjectConfigPath(projectDir: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* 다중 계층 설정 병합: 글로벌(~/.vibe) + 프로젝트(.claude/vibe)
|
|
22
|
+
* 우선순위: 프로젝트 > 글로벌 (프로젝트 설정이 글로벌을 덮어씀)
|
|
23
|
+
* credentials는 글로벌 전용 — 프로젝트에서 덮어쓰지 않음.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveConfig(projectDir: string): GlobalVibeConfig;
|
|
18
26
|
export declare function getGptApiKey(): string | null;
|
|
19
27
|
export declare function getGeminiApiKey(): string | null;
|
|
20
28
|
export declare function getModelOverride(key: string): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalConfigManager.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/config/GlobalConfigManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAsB9D,2BAA2B;AAC3B,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,0BAA0B;AAC1B,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAQD,wBAAgB,gBAAgB,IAAI,gBAAgB,CA6BnD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAQhE;AAID,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AAwBF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAK5E;AAID,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIhE;AA0DD;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CA2KzC"}
|
|
1
|
+
{"version":3,"file":"GlobalConfigManager.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/config/GlobalConfigManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAsB9D,2BAA2B;AAC3B,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,0BAA0B;AAC1B,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAQD,wBAAgB,gBAAgB,IAAI,gBAAgB,CA6BnD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAQhE;AAID,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AAwBF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAK5E;AAID,0CAA0C;AAC1C,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAeD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAiBlE;AAID,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIhE;AA0DD;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CA2KzC"}
|
|
@@ -95,6 +95,43 @@ export function patchGlobalConfig(patch) {
|
|
|
95
95
|
merged.version = '1';
|
|
96
96
|
writeGlobalConfig(merged);
|
|
97
97
|
}
|
|
98
|
+
// ─── Project config + layered merge ────────────────────────────────
|
|
99
|
+
/** .claude/vibe/config.json (프로젝트별 설정) */
|
|
100
|
+
export function getProjectConfigPath(projectDir) {
|
|
101
|
+
return path.join(projectDir, '.claude', 'vibe', 'config.json');
|
|
102
|
+
}
|
|
103
|
+
function readProjectConfig(projectDir) {
|
|
104
|
+
const configPath = getProjectConfigPath(projectDir);
|
|
105
|
+
try {
|
|
106
|
+
if (!fs.existsSync(configPath))
|
|
107
|
+
return {};
|
|
108
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
109
|
+
const parsed = JSON.parse(content);
|
|
110
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
111
|
+
return {};
|
|
112
|
+
return parsed;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return {};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 다중 계층 설정 병합: 글로벌(~/.vibe) + 프로젝트(.claude/vibe)
|
|
120
|
+
* 우선순위: 프로젝트 > 글로벌 (프로젝트 설정이 글로벌을 덮어씀)
|
|
121
|
+
* credentials는 글로벌 전용 — 프로젝트에서 덮어쓰지 않음.
|
|
122
|
+
*/
|
|
123
|
+
export function resolveConfig(projectDir) {
|
|
124
|
+
const global = readGlobalConfig();
|
|
125
|
+
const project = readProjectConfig(projectDir);
|
|
126
|
+
if (Object.keys(project).length === 0) {
|
|
127
|
+
return global;
|
|
128
|
+
}
|
|
129
|
+
// credentials는 글로벌 전용이므로 프로젝트에서 제거 후 병합
|
|
130
|
+
const { credentials: _ignored, ...projectWithoutCreds } = project;
|
|
131
|
+
const merged = deepMerge(global, projectWithoutCreds);
|
|
132
|
+
merged.version = '1';
|
|
133
|
+
return merged;
|
|
134
|
+
}
|
|
98
135
|
// ─── Credential helpers ─────────────────────────────────────────────
|
|
99
136
|
export function getGptApiKey() {
|
|
100
137
|
return readGlobalConfig().credentials?.gpt?.apiKey ?? null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalConfigManager.js","sourceRoot":"","sources":["../../../../src/infra/lib/config/GlobalConfigManager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GlobalConfigManager.js","sourceRoot":"","sources":["../../../../src/infra/lib/config/GlobalConfigManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
* Notification Hook - 컨텍스트 자동 저장 (80/90/95%) + 세션 요약 + Reflection
|
|
3
3
|
* Usage: node context-save.js <urgency>
|
|
4
4
|
* urgency: medium | high | critical
|
|
5
|
+
*
|
|
6
|
+
* 구조적 메타데이터를 자동 추출하여 세션 복원 품질을 높임.
|
|
7
|
+
* (claw-code compact.rs 패턴 참조)
|
|
5
8
|
*/
|
|
6
9
|
import { getToolsBaseUrl, getLibBaseUrl, PROJECT_DIR } from './utils.js';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import path from 'path';
|
|
7
13
|
|
|
8
14
|
const BASE_URL = getToolsBaseUrl();
|
|
9
15
|
const LIB_URL = getLibBaseUrl();
|
|
@@ -18,13 +24,94 @@ const summaryMap = {
|
|
|
18
24
|
// Debounce: track last reflection level per session to avoid duplicates
|
|
19
25
|
let lastReflectionLevel = null;
|
|
20
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 프로젝트 환경에서 구조적 메타데이터를 추출.
|
|
29
|
+
* 실패 시 빈 객체 반환 (non-blocking).
|
|
30
|
+
*/
|
|
31
|
+
function extractStructuredMetadata() {
|
|
32
|
+
const metadata = {
|
|
33
|
+
recentFiles: [],
|
|
34
|
+
gitBranch: null,
|
|
35
|
+
pendingWork: [],
|
|
36
|
+
toolsUsed: [],
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
// 최근 수정 파일 (최대 8개, 확장자 기반 필터)
|
|
42
|
+
const gitDiff = execSync('git diff --name-only HEAD 2>/dev/null || true', {
|
|
43
|
+
cwd: PROJECT_DIR, encoding: 'utf-8', timeout: 3000,
|
|
44
|
+
}).trim();
|
|
45
|
+
const staged = execSync('git diff --cached --name-only 2>/dev/null || true', {
|
|
46
|
+
cwd: PROJECT_DIR, encoding: 'utf-8', timeout: 3000,
|
|
47
|
+
}).trim();
|
|
48
|
+
|
|
49
|
+
const allFiles = [...new Set([...gitDiff.split('\n'), ...staged.split('\n')])]
|
|
50
|
+
.filter(f => f && /\.(ts|tsx|js|jsx|py|rs|go|java|json|md|css|html|vue|svelte)$/.test(f))
|
|
51
|
+
.slice(0, 8);
|
|
52
|
+
metadata.recentFiles = allFiles;
|
|
53
|
+
|
|
54
|
+
// 현재 브랜치
|
|
55
|
+
const branch = execSync('git branch --show-current 2>/dev/null || true', {
|
|
56
|
+
cwd: PROJECT_DIR, encoding: 'utf-8', timeout: 2000,
|
|
57
|
+
}).trim();
|
|
58
|
+
if (branch) metadata.gitBranch = branch;
|
|
59
|
+
} catch { /* git 없는 환경 무시 */ }
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
// SPEC/TODO에서 진행 중 작업 추출
|
|
63
|
+
const specDir = path.join(PROJECT_DIR, '.claude', 'vibe', 'specs');
|
|
64
|
+
if (fs.existsSync(specDir)) {
|
|
65
|
+
const specs = fs.readdirSync(specDir).filter(f => f.endsWith('.md')).slice(0, 3);
|
|
66
|
+
for (const spec of specs) {
|
|
67
|
+
metadata.pendingWork.push(`SPEC: ${spec.replace('.md', '')}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const todoDir = path.join(PROJECT_DIR, '.claude', 'vibe', 'todos');
|
|
71
|
+
if (fs.existsSync(todoDir)) {
|
|
72
|
+
const todos = fs.readdirSync(todoDir).filter(f => f.endsWith('.md')).slice(0, 3);
|
|
73
|
+
for (const todo of todos) {
|
|
74
|
+
metadata.pendingWork.push(`TODO: ${todo.replace('.md', '')}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch { /* 파일 시스템 접근 실패 무시 */ }
|
|
78
|
+
|
|
79
|
+
return metadata;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 구조적 요약 텍스트 생성 (claw-code compact.rs 패턴)
|
|
84
|
+
*/
|
|
85
|
+
function buildStructuredSummary(baseMessage, metadata) {
|
|
86
|
+
const sections = [baseMessage];
|
|
87
|
+
|
|
88
|
+
if (metadata.gitBranch) {
|
|
89
|
+
sections.push(`Branch: ${metadata.gitBranch}`);
|
|
90
|
+
}
|
|
91
|
+
if (metadata.recentFiles.length > 0) {
|
|
92
|
+
sections.push(`Key files: ${metadata.recentFiles.join(', ')}`);
|
|
93
|
+
}
|
|
94
|
+
if (metadata.pendingWork.length > 0) {
|
|
95
|
+
sections.push(`Pending work: ${metadata.pendingWork.join('; ')}`);
|
|
96
|
+
}
|
|
97
|
+
if (metadata.toolsUsed.length > 0) {
|
|
98
|
+
sections.push(`Tools used: ${metadata.toolsUsed.join(', ')}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return sections.join('\n');
|
|
102
|
+
}
|
|
103
|
+
|
|
21
104
|
async function main() {
|
|
22
105
|
try {
|
|
106
|
+
const metadata = extractStructuredMetadata();
|
|
107
|
+
const baseMessage = summaryMap[urgency] || summaryMap.medium;
|
|
108
|
+
const structuredSummary = buildStructuredSummary(baseMessage, metadata);
|
|
109
|
+
|
|
23
110
|
const module = await import(`${BASE_URL}memory/index.js`);
|
|
24
111
|
const result = await module.autoSaveContext({
|
|
25
112
|
urgency,
|
|
26
113
|
contextType: 'progress',
|
|
27
|
-
summary:
|
|
114
|
+
summary: structuredSummary,
|
|
28
115
|
projectPath: PROJECT_DIR,
|
|
29
116
|
});
|
|
30
117
|
const percent = urgency === 'critical' ? '95' : urgency === 'high' ? '90' : '80';
|
|
@@ -110,9 +110,34 @@ function formatOutput(toolName, validation) {
|
|
|
110
110
|
return lines.join('\n');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
/**
|
|
114
|
+
* stdin에서 JSON 페이로드 읽기 (Claude Code 하네스 호환)
|
|
115
|
+
* stdin이 없거나 파싱 실패 시 argv/env 폴백
|
|
116
|
+
*/
|
|
117
|
+
function readStdinSync() {
|
|
118
|
+
try {
|
|
119
|
+
if (process.stdin.isTTY) return null;
|
|
120
|
+
const fd = fs.openSync('/dev/stdin', 'r');
|
|
121
|
+
const buf = Buffer.alloc(65536);
|
|
122
|
+
const bytesRead = fs.readSync(fd, buf, 0, buf.length, null);
|
|
123
|
+
fs.closeSync(fd);
|
|
124
|
+
if (bytesRead > 0) {
|
|
125
|
+
return JSON.parse(buf.toString('utf-8', 0, bytesRead));
|
|
126
|
+
}
|
|
127
|
+
} catch { /* 파싱 실패 시 폴백 */ }
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
import fs from 'fs';
|
|
132
|
+
|
|
133
|
+
// 메인 실행: stdin JSON 우선, argv 폴백
|
|
134
|
+
const stdinPayload = readStdinSync();
|
|
135
|
+
const toolName = stdinPayload?.tool_name || process.argv[2] || 'Bash';
|
|
136
|
+
const toolInput = stdinPayload?.tool_input
|
|
137
|
+
? (typeof stdinPayload.tool_input === 'string'
|
|
138
|
+
? stdinPayload.tool_input
|
|
139
|
+
: JSON.stringify(stdinPayload.tool_input))
|
|
140
|
+
: (process.argv[3] || process.env.TOOL_INPUT || '');
|
|
116
141
|
|
|
117
142
|
const validation = validateCommand(toolName, toolInput);
|
|
118
143
|
const output = formatOutput(toolName, validation);
|
|
@@ -121,5 +146,5 @@ if (output) {
|
|
|
121
146
|
console.log(output);
|
|
122
147
|
}
|
|
123
148
|
|
|
124
|
-
// Exit code: 0 = allowed, 1 =
|
|
125
|
-
process.exit(validation.allowed ? 0 :
|
|
149
|
+
// Exit code: 0 = allowed, 2 = denied (claw-code 규약), 1 = 레거시 호환
|
|
150
|
+
process.exit(validation.allowed ? 0 : 2);
|
|
@@ -90,15 +90,39 @@ function guard(toolName, toolInput) {
|
|
|
90
90
|
return undefined;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
import fs from 'fs';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* stdin에서 JSON 페이로드 읽기 (Claude Code 하네스 호환)
|
|
97
|
+
*/
|
|
98
|
+
function readStdinSync() {
|
|
99
|
+
try {
|
|
100
|
+
if (process.stdin.isTTY) return null;
|
|
101
|
+
const fd = fs.openSync('/dev/stdin', 'r');
|
|
102
|
+
const buf = Buffer.alloc(65536);
|
|
103
|
+
const bytesRead = fs.readSync(fd, buf, 0, buf.length, null);
|
|
104
|
+
fs.closeSync(fd);
|
|
105
|
+
if (bytesRead > 0) {
|
|
106
|
+
return JSON.parse(buf.toString('utf-8', 0, bytesRead));
|
|
107
|
+
}
|
|
108
|
+
} catch { /* 폴백 */ }
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Main execution: stdin JSON 우선, argv 폴백
|
|
113
|
+
const stdinPayload = readStdinSync();
|
|
114
|
+
const toolName = stdinPayload?.tool_name || process.argv[2] || '';
|
|
115
|
+
const toolInput = stdinPayload?.tool_input
|
|
116
|
+
? (typeof stdinPayload.tool_input === 'string'
|
|
117
|
+
? stdinPayload.tool_input
|
|
118
|
+
: JSON.stringify(stdinPayload.tool_input))
|
|
119
|
+
: (process.argv[3] || process.env.TOOL_INPUT || '');
|
|
96
120
|
|
|
97
121
|
const result = guard(toolName, toolInput);
|
|
98
122
|
|
|
99
123
|
if (result) {
|
|
100
124
|
console.log(JSON.stringify(result));
|
|
101
|
-
process.exit(
|
|
125
|
+
process.exit(2); // deny 규약
|
|
102
126
|
}
|
|
103
127
|
|
|
104
128
|
process.exit(0);
|
package/hooks/scripts/utils.js
CHANGED
|
@@ -36,6 +36,54 @@ export function readVibeConfig() {
|
|
|
36
36
|
return {};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* 프로젝트 설정(.claude/vibe/config.json) 읽기
|
|
41
|
+
* @returns {object} 파싱된 config 또는 빈 객체
|
|
42
|
+
*/
|
|
43
|
+
export function readProjectConfig() {
|
|
44
|
+
const configPath = path.join(PROJECT_DIR, '.claude', 'vibe', 'config.json');
|
|
45
|
+
try {
|
|
46
|
+
if (fs.existsSync(configPath)) {
|
|
47
|
+
return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
48
|
+
}
|
|
49
|
+
} catch { /* ignore */ }
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Deep merge: source의 값이 target을 덮어씀 (배열은 교체)
|
|
55
|
+
*/
|
|
56
|
+
function deepMerge(target, source) {
|
|
57
|
+
const result = { ...target };
|
|
58
|
+
for (const key of Object.keys(source)) {
|
|
59
|
+
const srcVal = source[key];
|
|
60
|
+
if (srcVal === undefined) continue;
|
|
61
|
+
const tgtVal = target[key];
|
|
62
|
+
if (
|
|
63
|
+
tgtVal && typeof tgtVal === 'object' && !Array.isArray(tgtVal) &&
|
|
64
|
+
srcVal && typeof srcVal === 'object' && !Array.isArray(srcVal)
|
|
65
|
+
) {
|
|
66
|
+
result[key] = deepMerge(tgtVal, srcVal);
|
|
67
|
+
} else {
|
|
68
|
+
result[key] = srcVal;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 다중 계층 설정 병합: 글로벌 + 프로젝트
|
|
76
|
+
* 우선순위: 프로젝트 > 글로벌 (credentials는 글로벌 전용)
|
|
77
|
+
* @returns {object} 병합된 config
|
|
78
|
+
*/
|
|
79
|
+
export function resolveVibeConfig() {
|
|
80
|
+
const global = readVibeConfig();
|
|
81
|
+
const project = readProjectConfig();
|
|
82
|
+
if (Object.keys(project).length === 0) return global;
|
|
83
|
+
const { credentials: _ignored, ...projectWithoutCreds } = project;
|
|
84
|
+
return deepMerge(global, projectWithoutCreds);
|
|
85
|
+
}
|
|
86
|
+
|
|
39
87
|
/**
|
|
40
88
|
* 파일 시스템 경로를 file:// URL로 변환 (크로스 플랫폼)
|
|
41
89
|
* - macOS/Linux: /Users/grove/... → file:///Users/grove/...
|
package/package.json
CHANGED
|
@@ -132,25 +132,129 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
|
|
|
132
132
|
- 개요 JSDoc 주석 (A-2에서 추출한 overview)
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
###
|
|
135
|
+
### HARD RULE: 빈 template 금지
|
|
136
136
|
|
|
137
137
|
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
브라우저에서 열었을 때 화면에 텍스트가 보여야 한다.
|
|
139
|
+
빈 컴포넌트 shell은 Step A 미완성.
|
|
140
|
+
|
|
141
|
+
<template> 안에 반드시:
|
|
142
|
+
- 스토리보드에서 추출한 실제 텍스트 (제목, 설명, 버튼 라벨)
|
|
143
|
+
- 목 데이터가 렌더링되는 리스트 (v-for / .map)
|
|
144
|
+
- 클릭 가능한 버튼/링크
|
|
145
|
+
- 조건부 렌더링 (v-if / &&)
|
|
146
|
+
```
|
|
144
147
|
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
### 섹션 컴포넌트 — 실제 코드 예시 (Vue)
|
|
149
|
+
|
|
150
|
+
```vue
|
|
151
|
+
<template>
|
|
152
|
+
<section class="dailyCheckInSection">
|
|
153
|
+
<h2 class="dailyCheckInSection__title">일일 출석 미션</h2>
|
|
154
|
+
<p class="dailyCheckInSection__description">매일 출석하고 스노우 토큰을 받으세요!</p>
|
|
155
|
+
|
|
156
|
+
<div class="dailyCheckInSection__calendar">
|
|
157
|
+
<div
|
|
158
|
+
v-for="day in checkInDays"
|
|
159
|
+
:key="day.date"
|
|
160
|
+
class="dailyCheckInSection__day"
|
|
161
|
+
:class="{ 'is-checked': day.checked, 'is-today': day.isToday }"
|
|
162
|
+
@click="handleCheckIn(day)"
|
|
163
|
+
>
|
|
164
|
+
<span class="dailyCheckInSection__dayLabel">{{ day.date }}</span>
|
|
165
|
+
<span class="dailyCheckInSection__dayReward">{{ day.reward }} 토큰</span>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<div class="dailyCheckInSection__milestones">
|
|
170
|
+
<div
|
|
171
|
+
v-for="milestone in milestones"
|
|
172
|
+
:key="milestone.days"
|
|
173
|
+
class="dailyCheckInSection__milestone"
|
|
174
|
+
:class="{ 'is-claimable': milestone.claimable, 'is-claimed': milestone.claimed }"
|
|
175
|
+
@click="handleClaimReward(milestone)"
|
|
176
|
+
>
|
|
177
|
+
<span>{{ milestone.days }}일 달성</span>
|
|
178
|
+
<span>{{ milestone.reward }}</span>
|
|
179
|
+
<button v-if="milestone.claimable && !milestone.claimed">받기</button>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</section>
|
|
183
|
+
</template>
|
|
184
|
+
|
|
185
|
+
<script setup lang="ts">
|
|
186
|
+
/**
|
|
187
|
+
* 일일 출석 미션 섹션
|
|
188
|
+
*
|
|
189
|
+
* [기능 정의]
|
|
190
|
+
* - 매일 출석 시 스노우 토큰 즉시 지급
|
|
191
|
+
* - 누적 3/5/7일 달성 시 추가 보상
|
|
192
|
+
*
|
|
193
|
+
* [인터랙션]
|
|
194
|
+
* ① 출석하기 클릭 → 출석 처리 → 토큰 지급 표시
|
|
195
|
+
* ② 누적 보상 클릭 → 보상 수령
|
|
196
|
+
*
|
|
197
|
+
* [상태] default, checked, reward-claimed
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
interface CheckInDay {
|
|
201
|
+
date: string
|
|
202
|
+
checked: boolean
|
|
203
|
+
isToday: boolean
|
|
204
|
+
reward: number
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface Milestone {
|
|
208
|
+
days: number
|
|
209
|
+
claimable: boolean
|
|
210
|
+
claimed: boolean
|
|
211
|
+
reward: string
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// 목 데이터 — 빈 배열 금지!
|
|
215
|
+
const checkInDays = ref<CheckInDay[]>([
|
|
216
|
+
{ date: 'Day 1', checked: true, isToday: false, reward: 10 },
|
|
217
|
+
{ date: 'Day 2', checked: true, isToday: false, reward: 10 },
|
|
218
|
+
{ date: 'Day 3', checked: false, isToday: true, reward: 10 },
|
|
219
|
+
{ date: 'Day 4', checked: false, isToday: false, reward: 10 },
|
|
220
|
+
{ date: 'Day 5', checked: false, isToday: false, reward: 10 },
|
|
221
|
+
{ date: 'Day 6', checked: false, isToday: false, reward: 15 },
|
|
222
|
+
{ date: 'Day 7', checked: false, isToday: false, reward: 20 },
|
|
223
|
+
])
|
|
224
|
+
|
|
225
|
+
const milestones = ref<Milestone[]>([
|
|
226
|
+
{ days: 3, claimable: false, claimed: false, reward: '보상 상자 1개' },
|
|
227
|
+
{ days: 5, claimable: false, claimed: false, reward: '보상 상자 2개' },
|
|
228
|
+
{ days: 7, claimable: false, claimed: false, reward: '스페셜 보상' },
|
|
229
|
+
])
|
|
230
|
+
|
|
231
|
+
function handleCheckIn(day: CheckInDay): void {
|
|
232
|
+
// TODO: 출석 API 호출
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function handleClaimReward(milestone: Milestone): void {
|
|
236
|
+
// TODO: 누적 보상 수령 API 호출
|
|
237
|
+
}
|
|
238
|
+
</script>
|
|
239
|
+
<!-- 스타일은 외부 파일: styles/{feature}/components/_daily-checkin.scss -->
|
|
240
|
+
```
|
|
147
241
|
|
|
148
|
-
|
|
149
|
-
- 인터랙션 스펙에 맞는 함수 (body는 // TODO:)
|
|
242
|
+
### 필수 포함 사항 체크리스트
|
|
150
243
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
244
|
+
```
|
|
245
|
+
<template> 안에:
|
|
246
|
+
□ 섹션 제목 <h2> (스토리보드에서 추출한 실제 텍스트)
|
|
247
|
+
□ 설명 텍스트 <p> (스토리보드에서 추출)
|
|
248
|
+
□ 리스트 렌더링 (v-for + 목 데이터, 빈 배열 금지)
|
|
249
|
+
□ 버튼/CTA (실제 라벨 텍스트 + @click 핸들러)
|
|
250
|
+
□ 조건부 렌더링 (상태에 따른 v-if)
|
|
251
|
+
□ 클래스명 (Step B에서 외부 스타일과 매칭)
|
|
252
|
+
|
|
253
|
+
<script> 안에:
|
|
254
|
+
□ JSDoc: [기능 정의] + [인터랙션] + [상태]
|
|
255
|
+
□ TypeScript interface
|
|
256
|
+
□ 목 데이터 (기능 정의서에서 추출, 3~7개 아이템)
|
|
257
|
+
□ 이벤트 핸들러 함수 (body는 // TODO:)
|
|
154
258
|
```
|
|
155
259
|
|
|
156
260
|
### 스타일 분리 규칙
|
|
@@ -158,18 +262,21 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
|
|
|
158
262
|
```
|
|
159
263
|
컴포넌트 파일에 <style> 블록을 작성하지 않는다.
|
|
160
264
|
스타일은 Step B에서 외부 파일로 생성.
|
|
161
|
-
컴포넌트는 template + script 만 포함.
|
|
265
|
+
컴포넌트는 <template> + <script setup> 만 포함.
|
|
162
266
|
```
|
|
163
267
|
|
|
164
|
-
###
|
|
268
|
+
### Step A 완료 기준
|
|
165
269
|
|
|
166
270
|
```
|
|
167
|
-
|
|
168
|
-
✅
|
|
169
|
-
✅ 리스트
|
|
170
|
-
✅
|
|
171
|
-
✅
|
|
172
|
-
|
|
271
|
+
브라우저에서 열었을 때:
|
|
272
|
+
✅ 각 섹션의 제목/설명 텍스트가 화면에 보인다
|
|
273
|
+
✅ 리스트 아이템이 렌더링된다 (목 데이터)
|
|
274
|
+
✅ 버튼을 클릭하면 핸들러가 실행된다
|
|
275
|
+
✅ 탭/아코디언/모달이 동작한다
|
|
276
|
+
❌ 스타일은 없다 (Step B에서)
|
|
277
|
+
❌ 이미지는 없다 (Step B에서)
|
|
278
|
+
|
|
279
|
+
빈 화면 = Step A 미완성. 다음 단계로 넘어가지 않는다.
|
|
173
280
|
```
|
|
174
281
|
|
|
175
282
|
## A-6. 인터랙션 매핑 테이블
|
|
@@ -192,37 +299,46 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
|
|
|
192
299
|
### 검증 항목
|
|
193
300
|
|
|
194
301
|
```
|
|
302
|
+
0. 빈 화면 검사 (가장 중요 — 먼저 실행):
|
|
303
|
+
각 컴포넌트 파일을 Read로 열어서 <template> 안에 확인:
|
|
304
|
+
□ <h2> 또는 <h3> 섹션 제목 텍스트 존재
|
|
305
|
+
□ <p> 설명 텍스트 존재
|
|
306
|
+
□ v-for 또는 .map 렌더링 존재 (리스트 있는 섹션)
|
|
307
|
+
□ @click 또는 onClick 이벤트 존재 (인터랙션 있는 섹션)
|
|
308
|
+
<template> 안에 실제 HTML 태그가 없으면 → 빈 컴포넌트 → 재작성
|
|
309
|
+
Grep: "<template>" 다음 줄이 "</template>"이면 → 빈 template
|
|
310
|
+
|
|
195
311
|
1. 파일 존재 확인 (Glob 도구):
|
|
196
312
|
□ 루트 페이지 파일 존재
|
|
197
313
|
□ PAGE 프레임 수 = 컴포넌트 파일 수
|
|
198
314
|
□ styles 디렉토리 존재
|
|
199
|
-
□ 팝업 컴포넌트 존재 (스토리보드에 팝업이 있었으면)
|
|
200
|
-
→ 누락 시 Write로 생성
|
|
201
|
-
|
|
202
|
-
2. 기능 주석 확인 (Read 도구):
|
|
203
|
-
□ 모든 컴포넌트에 [기능 정의] + [인터랙션] + [상태] JSDoc
|
|
204
|
-
→ 누락 시 Edit으로 추가
|
|
205
315
|
|
|
206
|
-
|
|
316
|
+
2. 목 데이터 확인 (Grep 도구):
|
|
207
317
|
□ 빈 배열 (ref([]) 패턴) 검색 → 0건
|
|
208
318
|
→ 발견 시 목 데이터 채움
|
|
209
319
|
|
|
210
|
-
|
|
320
|
+
3. 스타일 분리 확인 (Grep 도구):
|
|
211
321
|
□ 컴포넌트 내 <style> 블록 0건
|
|
212
|
-
→ 발견 시 제거
|
|
213
322
|
|
|
214
|
-
|
|
323
|
+
4. 빌드 확인 (Bash 도구):
|
|
215
324
|
□ npm run build 성공
|
|
216
|
-
|
|
325
|
+
|
|
326
|
+
5. 브라우저 확인:
|
|
327
|
+
□ dev 서버 열어서 실제 화면 확인
|
|
328
|
+
□ 각 섹션에 텍스트가 보이는지
|
|
329
|
+
□ 빈 화면이면 → 해당 컴포넌트 재작성
|
|
217
330
|
```
|
|
218
331
|
|
|
219
332
|
### 완료 조건
|
|
220
333
|
|
|
221
334
|
```
|
|
335
|
+
✅ 빈 template 0개 — 모든 컴포넌트에 실제 HTML 마크업 존재
|
|
336
|
+
✅ 브라우저에서 텍스트/리스트/버튼이 보인다
|
|
222
337
|
✅ 파일 수 = PAGE 프레임 수
|
|
223
|
-
✅ 모든 JSDoc 주석 완비
|
|
224
338
|
✅ 빈 배열 0개
|
|
225
339
|
✅ <style> 블록 0개
|
|
226
340
|
✅ 빌드 성공
|
|
341
|
+
|
|
342
|
+
빈 화면 = Step A 미완성. Step B로 넘어가지 않는다.
|
|
227
343
|
→ Step B 진행 가능
|
|
228
344
|
```
|
|
@@ -16,6 +16,52 @@ triggers: []
|
|
|
16
16
|
> - 코드: Edit 도구로 Step A 컴포넌트의 template/style 채움
|
|
17
17
|
> - 토큰: Edit 도구로 _tokens 파일에 추출한 값 추가
|
|
18
18
|
|
|
19
|
+
## HARD RULES (위반 시 Step B 미완성)
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
1. PLACEHOLDER 금지
|
|
23
|
+
코드에 "placeholder", "Key Visual Image", 빈 dashed box,
|
|
24
|
+
alt="placeholder", src="" 등이 남아있으면 → Step B 미완성.
|
|
25
|
+
이미지를 추출 못하면 placeholder가 아니라 대체 추출(B-3.3 Step e)을 실행한다.
|
|
26
|
+
|
|
27
|
+
2. 이미지 없는 섹션은 완료가 아니다
|
|
28
|
+
스크린샷에 이미지(배경/캐릭터/일러스트/아이콘)가 보이는 섹션에서
|
|
29
|
+
생성 코드에 실제 이미지 파일이 없으면 → 해당 섹션 미완성.
|
|
30
|
+
다음 섹션으로 넘어가지 않고 현재 섹션의 이미지를 확보할 때까지 머문다.
|
|
31
|
+
|
|
32
|
+
3. 단색 배경으로 대체 금지
|
|
33
|
+
원본에 이미지 배경이 있는데 생성 코드가 CSS gradient/단색으로 대체하면 → P1.
|
|
34
|
+
이미지를 반드시 다운로드하여 background-image로 적용해야 한다.
|
|
35
|
+
|
|
36
|
+
4. 이미지 추출 실패 = 전체 실패
|
|
37
|
+
인벤토리의 이미지 중 하나라도 확보 못하면 Step B를 완료로 마킹하지 않는다.
|
|
38
|
+
대체 추출 경로(하위 노드 탐색 → 개별 스크린샷 → 크롭)를 전부 시도한 후,
|
|
39
|
+
그래도 실패하면 사용자에게 해당 이미지를 직접 제공해달라고 요청한다.
|
|
40
|
+
|
|
41
|
+
5. 텍스트 스타일 미적용 = 미완성
|
|
42
|
+
스크린샷에서 읽은 모든 텍스트 스타일을 코드에 반영해야 한다:
|
|
43
|
+
- font-size (스케일 팩터 적용)
|
|
44
|
+
- font-weight
|
|
45
|
+
- color
|
|
46
|
+
- line-height
|
|
47
|
+
- letter-spacing (있으면)
|
|
48
|
+
- text-align
|
|
49
|
+
제목, 본문, 버튼 텍스트, 설명 등 스크린샷에 보이는 모든 텍스트 요소에 적용.
|
|
50
|
+
스타일이 적용되지 않은 텍스트 요소가 있으면 → P1.
|
|
51
|
+
브라우저 기본 스타일(검은색 16px)로 보이는 텍스트가 있으면 → 미완성.
|
|
52
|
+
|
|
53
|
+
6. 스타일은 반드시 외부 파일에 작성
|
|
54
|
+
컴포넌트 파일(.vue/.tsx) 안에 <style> 블록이나 인라인 스타일을 작성하지 않는다.
|
|
55
|
+
모든 스타일은 외부 파일에 작성:
|
|
56
|
+
--new 모드: styles/{feature}/layout/_섹션.scss, components/_요소.scss
|
|
57
|
+
기본 모드: 프로젝트 기존 스타일 패턴에 따름
|
|
58
|
+
|
|
59
|
+
작성 후 검증:
|
|
60
|
+
Grep: "<style" in components/{feature}/ → 0건
|
|
61
|
+
Grep: "style=" in components/{feature}/ → 0건 (동적 바인딩 제외)
|
|
62
|
+
위반 시 → 해당 스타일을 외부 파일로 이동 후 재검증.
|
|
63
|
+
```
|
|
64
|
+
|
|
19
65
|
## 입력
|
|
20
66
|
|
|
21
67
|
- 디자인 Figma URL (전체 페이지)
|
|
@@ -59,54 +105,101 @@ AskUserQuestion (options 사용 금지, 자유 텍스트만):
|
|
|
59
105
|
|
|
60
106
|
**각 매핑된 섹션에 대해 순서대로:**
|
|
61
107
|
|
|
62
|
-
### 3-1.
|
|
108
|
+
### 3-1. 참조 코드에서 스타일 값 + 에셋 추출
|
|
63
109
|
|
|
64
110
|
```
|
|
65
|
-
|
|
66
|
-
→
|
|
111
|
+
get_design_context(fileKey, designFrame.nodeId)
|
|
112
|
+
→ 참조 코드 (React+Tailwind) + 에셋 URL
|
|
113
|
+
|
|
114
|
+
참조 코드에서 추출하는 것 (Figma 토큰 = 정확한 값):
|
|
115
|
+
✅ 색상: hex 값 (text-[#1B3A1D], bg-[#0A1628] 등)
|
|
116
|
+
✅ 폰트: font-size(px), font-weight, line-height, font-family
|
|
117
|
+
✅ 간격: padding, margin, gap (px)
|
|
118
|
+
✅ 장식: border-radius, box-shadow, opacity
|
|
119
|
+
✅ 에셋 URL: https://figma.com/api/mcp/asset/...
|
|
120
|
+
|
|
121
|
+
이 값들은 디자이너가 Figma UI에서 보는 것과 동일한 토큰 값.
|
|
122
|
+
스크린샷에서 추정하지 않고 이 값을 그대로 사용한다.
|
|
123
|
+
px 값에만 스케일 팩터(R-3)를 적용.
|
|
67
124
|
|
|
68
|
-
|
|
69
|
-
→
|
|
70
|
-
→ 배경 (이미지/단색/그라데이션, 오버레이 유무)
|
|
71
|
-
→ 색상 (배경, 텍스트, 버튼, 보더)
|
|
72
|
-
→ 타이포 (크기 비율, 굵기, 줄간격) — 스케일 팩터 적용 (R-3)
|
|
73
|
-
→ 간격 (패딩, gap, 마진) — 스케일 팩터 적용 (R-3)
|
|
74
|
-
→ 이미지 분류 (Background/Content/Overlay, R-4 참조)
|
|
75
|
-
→ z-index 관계 (겹침 구조, 투명도)
|
|
125
|
+
⚠️ HTML 구조는 레이어가 비정형이면 부정확할 수 있음.
|
|
126
|
+
→ 구조는 3-2 스크린샷에서 판단.
|
|
76
127
|
```
|
|
77
128
|
|
|
78
|
-
### 3-2.
|
|
129
|
+
### 3-2. 스크린샷으로 구조 + 이미지 인벤토리
|
|
79
130
|
|
|
80
131
|
```
|
|
81
|
-
|
|
82
|
-
→
|
|
132
|
+
get_screenshot(fileKey, designFrame.nodeId)
|
|
133
|
+
→ 원본 디자인 이미지 확보
|
|
134
|
+
|
|
135
|
+
스크린샷에서 판단하는 것 (구조):
|
|
136
|
+
→ 레이아웃 구조 (섹션 경계, flex/grid 방향, 요소 배치 순서)
|
|
137
|
+
→ 이미지 배치 분류 (Background/Content/Overlay, R-4 참조)
|
|
138
|
+
→ z-index 관계 (겹침 구조, 오버레이 유무)
|
|
139
|
+
→ 참조 코드에 없는 시각 요소 발견 → 추가 구현 대상
|
|
140
|
+
```
|
|
83
141
|
|
|
84
|
-
|
|
85
|
-
✅ 이미지 에셋 URL (https://figma.com/api/mcp/asset/...) — 핵심 가치
|
|
86
|
-
✅ 정확한 hex 색상값 (스크린샷 추정보다 정확할 때)
|
|
87
|
-
✅ 폰트 패밀리명, border-radius, shadow 값
|
|
88
|
-
⚠️ 레이아웃/구조 — 스크린샷과 대조 후 채택
|
|
89
|
-
❌ px 값 그대로 사용 금지 — 반드시 스케일 팩터 적용
|
|
142
|
+
**이미지 인벤토리 작성 (필수):**
|
|
90
143
|
|
|
91
|
-
|
|
92
|
-
|
|
144
|
+
```
|
|
145
|
+
스크린샷을 보고 해당 섹션에 보이는 모든 이미지를 목록화:
|
|
146
|
+
|
|
147
|
+
imageInventory = [
|
|
148
|
+
{ name: "hero-bg", type: "background", description: "눈 테마 풀스크린 배경" },
|
|
149
|
+
{ name: "hero-character", type: "overlay", description: "캐릭터 일러스트 우하단" },
|
|
150
|
+
{ name: "hero-vehicle", type: "content", description: "차량 이미지 중앙" },
|
|
151
|
+
{ name: "hero-logo", type: "content", description: "이벤트 로고 상단" },
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
→ 이 인벤토리가 B-3.3 다운로드의 체크리스트가 됨
|
|
155
|
+
→ B-5 검증에서 인벤토리 vs 코드의 이미지를 1:1 대조
|
|
156
|
+
→ 인벤토리에 있는데 코드에 없으면 = P1
|
|
93
157
|
```
|
|
94
158
|
|
|
95
159
|
### 3-3. 이미지 에셋 다운로드 (BLOCKING — 코드 반영 전 필수)
|
|
96
160
|
|
|
161
|
+
> **인벤토리의 모든 이미지가 로컬에 존재해야 다음 단계로 넘어갈 수 있다.**
|
|
162
|
+
|
|
97
163
|
```
|
|
98
164
|
Step a: 참조 코드에서 에셋 URL 추출
|
|
99
165
|
→ 모든 https://www.figma.com/api/mcp/asset/ URL 수집
|
|
166
|
+
→ 각 URL을 imageInventory 항목과 매칭
|
|
100
167
|
|
|
101
|
-
Step b:
|
|
102
|
-
|
|
103
|
-
|
|
168
|
+
Step b: 인벤토리 vs 에셋 URL 대조
|
|
169
|
+
→ 인벤토리에 있는데 에셋 URL이 없는 이미지 = 누락 후보
|
|
170
|
+
→ 누락 후보에 대해 대체 추출 실행 (Step e)
|
|
104
171
|
|
|
105
|
-
Step c:
|
|
172
|
+
Step c: 매칭된 에셋 다운로드
|
|
173
|
+
Bash: curl -L "{url}" -o static/images/{feature}/{name}.webp
|
|
174
|
+
파일명: 인벤토리 name 기반 kebab-case
|
|
106
175
|
|
|
107
176
|
Step d: 다운로드 검증
|
|
108
177
|
→ 파일 존재 + 0byte 아닌지 확인
|
|
109
178
|
→ 누락/실패 시 재다운로드
|
|
179
|
+
|
|
180
|
+
Step e: 대체 추출 (참조 코드에 에셋 URL이 없는 이미지)
|
|
181
|
+
레이어가 비정형("Frame 633372")이면 참조 코드에 이미지가 누락될 수 있음.
|
|
182
|
+
이 경우 다음 순서로 시도:
|
|
183
|
+
|
|
184
|
+
1. 하위 노드 탐색:
|
|
185
|
+
get_metadata로 섹션 하위 프레임 목록 확보
|
|
186
|
+
→ 이미지로 의심되는 하위 nodeId에 대해 get_design_context 재호출
|
|
187
|
+
→ 에셋 URL 확보되면 다운로드
|
|
188
|
+
|
|
189
|
+
2. 하위 노드 개별 스크린샷:
|
|
190
|
+
이미지로 의심되는 하위 nodeId에 대해 get_screenshot
|
|
191
|
+
→ 해당 스크린샷 자체를 이미지 에셋으로 저장
|
|
192
|
+
→ 배경 이미지: 스크린샷을 background-image로 사용
|
|
193
|
+
→ 콘텐츠 이미지: 스크린샷을 <img>로 사용
|
|
194
|
+
|
|
195
|
+
3. 섹션 전체 스크린샷 크롭:
|
|
196
|
+
위 방법이 다 실패하면, 섹션 스크린샷에서 해당 영역을 잘라서 사용
|
|
197
|
+
→ 최후 수단이지만 이미지 누락보다는 낫다
|
|
198
|
+
|
|
199
|
+
Step f: 최종 인벤토리 체크
|
|
200
|
+
인벤토리 항목 수 = 다운로드된 파일 수
|
|
201
|
+
하나라도 빠지면 → Step e 재시도
|
|
202
|
+
모든 이미지가 로컬에 있어야 → 3-4로 진행
|
|
110
203
|
```
|
|
111
204
|
|
|
112
205
|
### 3-4. 이미지 코드 패턴 적용
|
|
@@ -140,29 +233,211 @@ Step d: 다운로드 검증
|
|
|
140
233
|
}
|
|
141
234
|
```
|
|
142
235
|
|
|
143
|
-
### 3-5.
|
|
236
|
+
### 3-5. 글로벌 스타일 파일 구조 생성 (BLOCKING — 컴포넌트 수정 전 필수)
|
|
237
|
+
|
|
238
|
+
> **이 단계를 건너뛰면 Step B 미완성. 컴포넌트를 수정하기 전에 스타일 파일을 먼저 만든다.**
|
|
239
|
+
|
|
240
|
+
첫 번째 섹션 처리 시 전체 구조를 Write로 생성. 이후 섹션에서는 해당 파일에 Edit으로 추가.
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
styles/{feature}/
|
|
244
|
+
index.scss ← [1] 진입점 (모든 파일 import)
|
|
245
|
+
_tokens.scss ← [2] 토큰 (색상, 폰트, 간격 변수)
|
|
246
|
+
_mixins.scss ← [3] mixin (breakpoint, fluid 함수)
|
|
247
|
+
_base.scss ← [4] 공통 (reset, font-face, 전역 규칙)
|
|
248
|
+
layout/
|
|
249
|
+
_page.scss ← [5] 페이지 전체 레이아웃
|
|
250
|
+
_{section}.scss ← [6] 각 섹션별 배치/구조/배경
|
|
251
|
+
components/
|
|
252
|
+
_{element}.scss ← [7] 재사용 UI 요소 (card, button, badge 등)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### [1] index.scss — Write로 생성
|
|
256
|
+
|
|
257
|
+
```scss
|
|
258
|
+
// Foundation
|
|
259
|
+
@use 'tokens';
|
|
260
|
+
@use 'mixins';
|
|
261
|
+
@use 'base';
|
|
262
|
+
|
|
263
|
+
// Layout
|
|
264
|
+
@use 'layout/page';
|
|
265
|
+
@use 'layout/hero';
|
|
266
|
+
@use 'layout/daily-checkin';
|
|
267
|
+
// ... Step A의 모든 섹션
|
|
268
|
+
|
|
269
|
+
// Components
|
|
270
|
+
@use 'components/card';
|
|
271
|
+
@use 'components/button';
|
|
272
|
+
// ... 반복 패턴에서 추출된 재사용 요소
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### [2] _tokens.scss — 참조 코드에서 추출한 값으로 Write
|
|
276
|
+
|
|
277
|
+
```scss
|
|
278
|
+
@use 'sass:math';
|
|
279
|
+
|
|
280
|
+
// ── Colors (참조 코드 hex 그대로) ──
|
|
281
|
+
$figma-bg-primary: #0A1628;
|
|
282
|
+
$figma-bg-section: #1A2B4A;
|
|
283
|
+
$figma-text-heading: #1B3A1D;
|
|
284
|
+
$figma-text-body: #333333;
|
|
285
|
+
$figma-text-light: #FFFFFF;
|
|
286
|
+
$figma-accent: #FFD700;
|
|
287
|
+
|
|
288
|
+
// ── Typography (참조 코드 px × scaleFactor) ──
|
|
289
|
+
$figma-text-hero: 36px; // Figma 48px × 0.75
|
|
290
|
+
$figma-text-sub: 18px; // Figma 24px × 0.75
|
|
291
|
+
$figma-text-body: 14px; // Figma 18px × 0.75
|
|
292
|
+
$figma-text-caption: 12px; // Figma 16px × 0.75
|
|
293
|
+
$figma-font-family: 'Noto Sans KR', sans-serif;
|
|
294
|
+
|
|
295
|
+
// ── Spacing (참조 코드 px × scaleFactor) ──
|
|
296
|
+
$figma-space-section: 60px; // Figma 80px × 0.75
|
|
297
|
+
$figma-space-content: 24px; // Figma 32px × 0.75
|
|
298
|
+
$figma-space-element: 12px; // Figma 16px × 0.75
|
|
299
|
+
|
|
300
|
+
// ── Decorations ──
|
|
301
|
+
$figma-radius-card: 12px;
|
|
302
|
+
$figma-shadow-card: 0 4px 12px rgba(0,0,0,0.15);
|
|
303
|
+
|
|
304
|
+
// ── Breakpoints ──
|
|
305
|
+
$figma-bp: 1024px;
|
|
306
|
+
$figma-bp-mobile-min: 360px;
|
|
307
|
+
$figma-bp-pc-target: 1920px;
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### [3] _mixins.scss — Write로 생성
|
|
311
|
+
|
|
312
|
+
```scss
|
|
313
|
+
@use 'tokens' as t;
|
|
314
|
+
|
|
315
|
+
@mixin figma-pc { @media (min-width: t.$figma-bp) { @content; } }
|
|
316
|
+
|
|
317
|
+
@function figma-fluid($mobile, $desktop) {
|
|
318
|
+
// clamp 계산 (vibe-figma-rules R-3)
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### [4] _base.scss — Write로 생성
|
|
323
|
+
|
|
324
|
+
```scss
|
|
325
|
+
@use 'tokens' as t;
|
|
326
|
+
|
|
327
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
328
|
+
body { font-family: t.$figma-font-family; }
|
|
329
|
+
img { max-width: 100%; height: auto; }
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### [6] layout/_{section}.scss — 섹션별 Write
|
|
333
|
+
|
|
334
|
+
```scss
|
|
335
|
+
@use '../tokens' as t;
|
|
336
|
+
@use '../mixins' as m;
|
|
337
|
+
|
|
338
|
+
// 참조 코드의 레이아웃 관련 값 + 스크린샷의 구조를 적용
|
|
339
|
+
.heroSection {
|
|
340
|
+
position: relative;
|
|
341
|
+
overflow: hidden;
|
|
342
|
+
min-height: 100vh;
|
|
343
|
+
padding: t.$figma-space-section 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Multi-Layer 배경 (이미지가 있는 섹션)
|
|
347
|
+
.heroBg {
|
|
348
|
+
position: absolute; inset: 0; z-index: 0;
|
|
349
|
+
background-image: url('/images/{feature}/hero-bg.webp');
|
|
350
|
+
background-size: cover;
|
|
351
|
+
background-position: center;
|
|
352
|
+
}
|
|
353
|
+
.heroBgOverlay {
|
|
354
|
+
position: absolute; inset: 0; z-index: 1;
|
|
355
|
+
background: linear-gradient(to bottom, rgba(0,0,0,0.3), rgba(0,0,0,0.7));
|
|
356
|
+
}
|
|
357
|
+
.heroContent {
|
|
358
|
+
position: relative; z-index: 2;
|
|
359
|
+
display: flex; flex-direction: column; align-items: center;
|
|
360
|
+
padding: 0 t.$figma-space-content;
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### [7] components/_{element}.scss — 텍스트 + UI 요소
|
|
144
365
|
|
|
366
|
+
```scss
|
|
367
|
+
@use '../tokens' as t;
|
|
368
|
+
|
|
369
|
+
// 참조 코드의 Figma 토큰 값을 그대로 사용
|
|
370
|
+
.heroTitle {
|
|
371
|
+
font-size: t.$figma-text-hero;
|
|
372
|
+
font-weight: 900;
|
|
373
|
+
color: t.$figma-text-heading;
|
|
374
|
+
line-height: 1.2;
|
|
375
|
+
text-align: center;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.heroDescription {
|
|
379
|
+
font-size: t.$figma-text-sub;
|
|
380
|
+
font-weight: 400;
|
|
381
|
+
color: t.$figma-text-body;
|
|
382
|
+
line-height: 1.6;
|
|
383
|
+
text-align: center;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.heroCta {
|
|
387
|
+
font-size: t.$figma-text-body;
|
|
388
|
+
font-weight: 700;
|
|
389
|
+
color: t.$figma-text-light;
|
|
390
|
+
background: t.$figma-accent;
|
|
391
|
+
border-radius: t.$figma-radius-card;
|
|
392
|
+
padding: t.$figma-space-element t.$figma-space-content;
|
|
393
|
+
}
|
|
145
394
|
```
|
|
146
|
-
변환 순서 (스크린샷 분석 → 코드):
|
|
147
395
|
|
|
148
|
-
|
|
149
|
-
- 레이아웃 구조 (스크린샷에서 읽은 flex/grid, 배치)
|
|
150
|
-
- 스타일 값 (스크린샷에서 읽은 색상, 간격, 폰트 × 스케일 팩터)
|
|
151
|
-
- 배경 이미지 Multi-Layer 구조 (스크린샷에서 판단한 z-index)
|
|
396
|
+
### 3-6. 생성 확인 (BLOCKING)
|
|
152
397
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
- 정확한 hex 색상값, border-radius, shadow (스크린샷 추정보다 정확할 때)
|
|
398
|
+
```
|
|
399
|
+
스타일 파일 생성 후 반드시 확인:
|
|
156
400
|
|
|
157
|
-
|
|
401
|
+
Glob: styles/{feature}/index.scss → 존재
|
|
402
|
+
Glob: styles/{feature}/_tokens.scss → 존재
|
|
403
|
+
Glob: styles/{feature}/_mixins.scss → 존재
|
|
404
|
+
Glob: styles/{feature}/_base.scss → 존재
|
|
405
|
+
Glob: styles/{feature}/layout/*.scss → 섹션 수만큼 존재
|
|
406
|
+
Glob: styles/{feature}/components/*.scss → 1개 이상 존재
|
|
158
407
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
408
|
+
Grep: "font-size" in styles/{feature}/ → 0건이면 P1 (텍스트 스타일 미작성)
|
|
409
|
+
Grep: "color:" in styles/{feature}/ → 0건이면 P1
|
|
410
|
+
Grep: "background-image" in styles/{feature}/ → 배경 이미지 섹션 수만큼
|
|
162
411
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
412
|
+
하나라도 실패 → Write/Edit으로 보완 → 재확인
|
|
413
|
+
파일이 모두 존재하고 내용이 있어야 → 3-7로 진행
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### 3-7. 컴포넌트 파일에 반영 (Edit 도구)
|
|
417
|
+
|
|
418
|
+
```
|
|
419
|
+
컴포넌트 파일에는 template + script만 수정한다.
|
|
420
|
+
모든 스타일은 3-5에서 생성한 외부 파일에만 존재.
|
|
421
|
+
|
|
422
|
+
a. template 수정:
|
|
423
|
+
- placeholder → 실제 마크업으로 교체
|
|
424
|
+
- 클래스명 추가 (layout/*.scss, components/*.scss의 셀렉터와 매칭)
|
|
425
|
+
- 이미지 태그에 로컬 경로 설정
|
|
426
|
+
- Multi-Layer 구조 적용 (.{section}Bg + .{section}Content)
|
|
427
|
+
|
|
428
|
+
b. Step A 코드 보존:
|
|
429
|
+
- 기능 주석/핸들러/인터페이스 유지
|
|
430
|
+
- 목 데이터/이벤트 바인딩 유지
|
|
431
|
+
|
|
432
|
+
c. 스타일 import 설정:
|
|
433
|
+
- 루트 페이지 또는 설정 파일에서 styles/{feature}/index.scss import
|
|
434
|
+
- Nuxt: nuxt.config의 css 배열에 추가
|
|
435
|
+
- Next.js: _app 또는 layout에서 import
|
|
436
|
+
|
|
437
|
+
d. 컴포넌트 안에 스타일 작성 금지:
|
|
438
|
+
- <style> 블록 금지
|
|
439
|
+
- style="" 인라인 금지 (동적 바인딩 제외)
|
|
440
|
+
- 스타일이 필요하면 → 외부 파일에 추가 → 클래스명으로 연결
|
|
166
441
|
```
|
|
167
442
|
|
|
168
443
|
## B-4. 뷰포트 모드에 따른 스타일 적용
|
|
@@ -207,11 +482,48 @@ for each section in mappings:
|
|
|
207
482
|
### Step B 추가 검증 항목
|
|
208
483
|
|
|
209
484
|
```
|
|
210
|
-
1. 이미지
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
485
|
+
1. 이미지 인벤토리 대조:
|
|
486
|
+
for each item in imageInventory:
|
|
487
|
+
□ 로컬 파일 존재 (Glob)
|
|
488
|
+
□ 0byte 아님 (ls -la)
|
|
489
|
+
□ 코드에서 참조됨 (Grep: 파일명으로 검색)
|
|
490
|
+
□ 올바른 패턴 적용됨:
|
|
491
|
+
- background → .{section}Bg { background-image: url(...) }
|
|
492
|
+
- content → <img src="..." /> 또는 <Image />
|
|
493
|
+
- overlay → .{section}Character { background-image: url(...) }
|
|
494
|
+
하나라도 실패 → P1 → 수정 → 재검증
|
|
495
|
+
|
|
496
|
+
2. 텍스트 스타일 검증:
|
|
497
|
+
for each section:
|
|
498
|
+
□ 외부 스타일 파일 존재 (Glob: styles/{feature}/**/*.scss)
|
|
499
|
+
□ 스크린샷의 텍스트 요소 수 ≈ font-size 선언 수
|
|
500
|
+
Grep: "font-size" in styles/{feature}/
|
|
501
|
+
□ 브라우저 기본 스타일로 보이는 텍스트 0건
|
|
502
|
+
→ 모든 텍스트에 font-size, color, font-weight 지정 확인
|
|
503
|
+
□ color 값이 적용됨 (원본 스크린샷 색상과 매칭)
|
|
504
|
+
미적용 텍스트 발견 → P1
|
|
505
|
+
|
|
506
|
+
3. 스타일 분리 검증:
|
|
507
|
+
□ Grep: "<style" in components/{feature}/**/*.vue → 0건
|
|
508
|
+
□ Grep: "<style" in components/{feature}/**/*.tsx → 0건
|
|
509
|
+
□ Grep: 'style="' in components/{feature}/ → 0건 (v-bind:style 동적 바인딩 제외)
|
|
510
|
+
위반 → 외부 파일로 이동 → 재검증
|
|
511
|
+
|
|
512
|
+
4. Figma 임시 URL + placeholder 잔존 체크:
|
|
513
|
+
□ Grep: "figma.com/api/mcp/asset" → 0건
|
|
514
|
+
□ Grep: "placeholder" (대소문자 무시) → 0건
|
|
515
|
+
□ Grep: "Key Visual" → 0건
|
|
516
|
+
|
|
517
|
+
5. 배경 이미지 Multi-Layer 검증:
|
|
518
|
+
스크린샷에 배경 이미지가 보이는 섹션:
|
|
519
|
+
□ .{section}Bg 클래스 존재 (Grep)
|
|
520
|
+
□ .{section}Content 클래스 존재 (z-index 최상위)
|
|
521
|
+
□ 배경 위 텍스트 가독성 확보 (오버레이 유무)
|
|
522
|
+
누락 → P1
|
|
523
|
+
|
|
524
|
+
6. (responsive) 뷰포트별:
|
|
525
|
+
□ 뷰포트별 다른 배경 이미지 → @media 분기 있는지
|
|
526
|
+
□ 이전 뷰포트 스타일/이미지 깨지지 않았는지
|
|
215
527
|
```
|
|
216
528
|
|
|
217
529
|
## 참조 스킬
|
|
@@ -14,7 +14,7 @@ tier: standard
|
|
|
14
14
|
|
|
15
15
|
## R-0. 설계 철학
|
|
16
16
|
|
|
17
|
-
>
|
|
17
|
+
> **비정형 레이어에서도 원본 디자인 수준의 완성도를 달성한다.**
|
|
18
18
|
|
|
19
19
|
실무 Figma 파일의 현실:
|
|
20
20
|
```
|
|
@@ -24,39 +24,57 @@ tier: standard
|
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
레이어명이 "Frame 47", "Group 12"이고, Auto Layout 없이 절대 배치된 프레임이 대부분.
|
|
27
|
-
`get_design_context
|
|
27
|
+
그러나 `get_design_context`는 레이어가 비정형이어도 **스타일 토큰 값(색상, 폰트, 간격)과
|
|
28
|
+
에셋 URL은 정확하게 반환**한다. 이 값들은 디자이너가 Figma UI에서 보는 것과 동일한 값이다.
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
### 역할 분담
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
스크린샷이 답하는 것 (구조):
|
|
34
|
+
— WHAT goes WHERE: 레이아웃 구조, 섹션 경계, 이미지 배치, z-index, 겹침 관계
|
|
35
|
+
— 어떤 요소가 배경인지 콘텐츠인지, 어디에 오버레이가 있는지
|
|
36
|
+
— 참조 코드의 구조가 스크린샷과 다르면 → 스크린샷이 맞다
|
|
37
|
+
|
|
38
|
+
참조 코드가 답하는 것 (정확한 값):
|
|
39
|
+
— EXACT VALUES: hex 색상, font-size(px), font-weight, line-height,
|
|
40
|
+
padding, gap, margin, border-radius, shadow, 에셋 URL
|
|
41
|
+
— 이 값들은 Figma 디자인 토큰에서 직접 추출된 것이므로 정확하다
|
|
42
|
+
— 스크린샷에서 추정할 필요 없이 참조 코드의 값을 그대로 사용한다
|
|
43
|
+
— 단, px 값에는 스케일 팩터를 적용해야 한다 (R-3)
|
|
44
|
+
|
|
45
|
+
스크린샷이 검증하는 것 (최종 확인):
|
|
46
|
+
— 생성 코드의 렌더링 결과가 원본 스크린샷과 시각적으로 일치하는지
|
|
47
|
+
— Match Score 95%+, P1=0이 완료 기준
|
|
48
|
+
```
|
|
32
49
|
|
|
33
50
|
### 핵심 원칙
|
|
34
51
|
|
|
35
52
|
```
|
|
36
|
-
1.
|
|
37
|
-
—
|
|
38
|
-
—
|
|
53
|
+
1. 참조 코드의 스타일 값을 반드시 사용한다
|
|
54
|
+
— get_design_context가 반환하는 색상/폰트/간격 값은 Figma 토큰에서 온 정확한 값
|
|
55
|
+
— 스크린샷에서 색상을 추정하거나 폰트 크기를 눈대중으로 읽지 않는다
|
|
56
|
+
— 참조 코드의 값 + 스케일 팩터 적용 = 코드에 쓸 값
|
|
39
57
|
|
|
40
|
-
2.
|
|
41
|
-
—
|
|
42
|
-
— 참조 코드의
|
|
43
|
-
—
|
|
58
|
+
2. 스크린샷으로 구조를 결정한다
|
|
59
|
+
— 레이어 구조("Frame 633372")가 무의미해도 스크린샷에서 섹션 경계를 파악
|
|
60
|
+
— 참조 코드의 HTML 구조가 스크린샷과 다르면 → 스크린샷 기준으로 재구성
|
|
61
|
+
— 이미지 배치(배경/콘텐츠/오버레이)도 스크린샷에서 판단
|
|
44
62
|
|
|
45
|
-
3.
|
|
46
|
-
—
|
|
47
|
-
—
|
|
63
|
+
3. 스크린샷으로 누락을 잡는다
|
|
64
|
+
— 참조 코드에 없는 시각 요소가 스크린샷에 보이면 → 추가 구현
|
|
65
|
+
— 이미지 인벤토리는 스크린샷에서 작성 (참조 코드에 없는 이미지도 잡기 위해)
|
|
48
66
|
|
|
49
67
|
4. 검증은 항상 시각적 비교로
|
|
50
68
|
— 완료 기준: 원본 스크린샷 vs 생성 코드의 Match Score 95%+, P1=0
|
|
51
69
|
— 코드의 "정확성"이 아니라 "보이는 결과"가 기준이다
|
|
52
70
|
```
|
|
53
71
|
|
|
54
|
-
###
|
|
72
|
+
### MCP 도구별 역할
|
|
55
73
|
|
|
56
74
|
```
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
get_design_context → 정확한 스타일 값 + 에셋 URL (코드 작성의 데이터 소스)
|
|
76
|
+
get_screenshot → 구조 파악 + 누락 검출 + 최종 시각 검증 (구조의 진실)
|
|
77
|
+
get_metadata → 프레임 목록 + nodeId 확보 (탐색 용도)
|
|
60
78
|
```
|
|
61
79
|
|
|
62
80
|
---
|
|
@@ -323,12 +341,13 @@ Step A에서 get_screenshot으로 확보한 섹션별 원본 이미지를 기준
|
|
|
323
341
|
|
|
324
342
|
| 비교 항목 | P1 (필수 수정) | P2 (권장 수정) |
|
|
325
343
|
|----------|---------------|---------------|
|
|
344
|
+
| **이미지 인벤토리** | 인벤토리에 있는 이미지가 코드에 없음 | — |
|
|
345
|
+
| **배경 이미지** | 누락, Multi-Layer 미적용, 경로 깨짐 | 크기/위치 미세 차이 |
|
|
346
|
+
| **이미지 다운로드** | 파일 미존재, 0byte, Figma URL 잔존 | — |
|
|
326
347
|
| **레이아웃** | 요소 배치 방향 다름, 섹션 순서 다름 | 미세 정렬 차이 |
|
|
327
|
-
| **배경 이미지** | 누락, 완전히 다른 이미지 | 크기/위치 미세 차이 |
|
|
328
348
|
| **색상** | 배경/텍스트색 완전히 다름 | 미세한 톤 차이 (ΔE < 10) |
|
|
329
349
|
| **타이포** | 제목/본문 크기 비율 다름, 굵기 다름 | ±2px 차이 |
|
|
330
350
|
| **간격** | 섹션 간 간격 크게 다름, 요소 겹침 | ±4px 차이 |
|
|
331
|
-
| **이미지 에셋** | 다운로드 실패, 경로 깨짐 | 크기/비율 미세 차이 |
|
|
332
351
|
| **누락 요소** | 스크린샷에 보이는 요소가 코드에 없음 | — |
|
|
333
352
|
| **오버레이** | 배경 위 텍스트 가독성 확보 안 됨 | 투명도 미세 차이 |
|
|
334
353
|
|
|
@@ -372,49 +391,73 @@ P1이 있으면:
|
|
|
372
391
|
✅ P1 = 0 (전 섹션)
|
|
373
392
|
✅ 모든 이미지 에셋 표시 + Figma 임시 URL 잔존 0건
|
|
374
393
|
✅ (반응형) 각 뷰포트 독립 검증 통과
|
|
394
|
+
✅ placeholder 0건 — "placeholder", "Key Visual Image", 빈 dashed box,
|
|
395
|
+
alt="placeholder", src="" 등이 코드에 남아있으면 미완성
|
|
396
|
+
✅ 단색/gradient 대체 0건 — 원본에 이미지 배경인 곳이 CSS 단색으로 처리되면 미완성
|
|
397
|
+
✅ 텍스트 스타일 전수 적용 — 브라우저 기본 스타일(검은색 16px)로 보이는 텍스트 0건
|
|
398
|
+
✅ 스타일 외부 파일 — 컴포넌트 내 <style> 블록 0건, 인라인 style="" 0건
|
|
375
399
|
```
|
|
376
400
|
|
|
377
401
|
---
|
|
378
402
|
|
|
379
|
-
## R-7.
|
|
403
|
+
## R-7. 섹션별 분석 프로세스
|
|
380
404
|
|
|
381
|
-
###
|
|
405
|
+
### Step 1: get_design_context (스타일 값 + 에셋)
|
|
382
406
|
|
|
383
407
|
```
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
→ 시각 분석: 레이아웃 구조, 색상 팔레트, 폰트 크기/굵기, 간격, 배경 이미지 유무
|
|
408
|
+
get_design_context(fileKey, 섹션 nodeId)
|
|
409
|
+
→ 참조 코드 반환 (React+Tailwind 형태)
|
|
387
410
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
411
|
+
참조 코드에서 추출하는 것 (정확한 값 — Figma 토큰에서 직접 추출됨):
|
|
412
|
+
✅ 색상: hex 값 (text-[#1B3A1D], bg-[#0A1628] 등)
|
|
413
|
+
✅ 폰트: font-size(px), font-weight, line-height, font-family
|
|
414
|
+
✅ 간격: padding, margin, gap (px)
|
|
415
|
+
✅ 장식: border-radius, box-shadow, opacity
|
|
416
|
+
✅ 에셋 URL: const xxxImage = 'https://figma.com/api/mcp/asset/...'
|
|
392
417
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
→ 참조 코드 구조가 스크린샷과 다르면 → 스크린샷 기준으로 재구성
|
|
418
|
+
이 값들은 디자이너가 Figma UI 우측 패널에서 보는 것과 동일.
|
|
419
|
+
스크린샷에서 추정할 필요 없이 이 값을 그대로 사용한다.
|
|
420
|
+
단, px 값에는 스케일 팩터를 적용한다 (R-3).
|
|
397
421
|
```
|
|
398
422
|
|
|
399
|
-
###
|
|
423
|
+
### Step 2: get_screenshot (구조 + 이미지 인벤토리)
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
get_screenshot(fileKey, 섹션 nodeId)
|
|
427
|
+
→ 원본 디자인 이미지 확보
|
|
400
428
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
429
|
+
스크린샷에서 판단하는 것 (구조 — 참조 코드가 틀릴 수 있는 영역):
|
|
430
|
+
✅ 레이아웃 구조: 섹션 경계, flex/grid 방향, 요소 배치 순서
|
|
431
|
+
✅ 이미지 배치: 배경/콘텐츠/오버레이 분류, z-index 관계
|
|
432
|
+
✅ 이미지 인벤토리: 보이는 모든 이미지 목록 (참조 코드에 없는 것도 잡음)
|
|
433
|
+
✅ 겹침 구조: 텍스트-배경 관계, 오버레이 유무
|
|
434
|
+
✅ 누락 검출: 참조 코드에 없는 시각 요소 발견
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Step 3: 코드 생성
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
a. 참조 코드의 스타일 값을 그대로 사용하여 외부 스타일 파일 작성:
|
|
441
|
+
- 색상 hex → 토큰 변수로 정의
|
|
442
|
+
- font-size × scaleFactor → 토큰 변수로 정의
|
|
443
|
+
- 간격 × scaleFactor → 토큰 변수로 정의
|
|
444
|
+
|
|
445
|
+
b. 스크린샷의 구조로 HTML/template 결정:
|
|
446
|
+
- 레이아웃 방향, 요소 순서
|
|
447
|
+
- Multi-Layer 배경 구조 (배경 이미지가 있으면)
|
|
448
|
+
- 참조 코드의 구조가 스크린샷과 다르면 → 스크린샷 기준
|
|
449
|
+
|
|
450
|
+
c. 에셋 URL → 다운로드 → 로컬 경로로 교체
|
|
451
|
+
|
|
452
|
+
d. 스크린샷에 보이지만 참조 코드에 없는 요소 → 추가 구현
|
|
453
|
+
```
|
|
410
454
|
|
|
411
|
-
### 참조
|
|
455
|
+
### 참조 코드의 구조가 틀릴 때
|
|
412
456
|
|
|
413
457
|
```
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
❌ px 값 그대로 사용 — 반드시 스케일 팩터 적용
|
|
458
|
+
레이어가 "Frame 633372"면 참조 코드의 HTML 구조가 부정확할 수 있다.
|
|
459
|
+
이때:
|
|
460
|
+
- 스타일 값(색상, 폰트, 간격)은 여전히 정확 → 그대로 사용
|
|
461
|
+
- HTML 구조(어떤 요소가 어디에)만 스크린샷 기준으로 재배치
|
|
462
|
+
- 에셋 URL도 여전히 유효 → 그대로 다운로드
|
|
420
463
|
```
|