careermate 0.1.0

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.
Files changed (124) hide show
  1. package/README.md +256 -0
  2. package/THIRD_PARTY_NOTICES.md +40 -0
  3. package/apps/mcp/src/index.ts +66 -0
  4. package/apps/web/DESIGN_GUIDE.md +105 -0
  5. package/apps/web/UI_CONTRACT.md +44 -0
  6. package/apps/web/public/app.js +118 -0
  7. package/apps/web/public/fonts/PretendardVariable.woff2 +0 -0
  8. package/apps/web/public/index.html +41 -0
  9. package/apps/web/public/lib.js +282 -0
  10. package/apps/web/public/pages/applications.js +98 -0
  11. package/apps/web/public/pages/documents.js +446 -0
  12. package/apps/web/public/pages/home.js +263 -0
  13. package/apps/web/public/pages/interview.js +230 -0
  14. package/apps/web/public/pages/jobs.js +494 -0
  15. package/apps/web/public/pages/profile.js +576 -0
  16. package/apps/web/public/pages/settings.js +233 -0
  17. package/apps/web/public/styles.css +426 -0
  18. package/apps/web/src/exports.ts +68 -0
  19. package/apps/web/src/http.ts +180 -0
  20. package/apps/web/src/index.ts +49 -0
  21. package/apps/web/src/info.ts +50 -0
  22. package/apps/web/src/routes.ts +350 -0
  23. package/apps/web/src/security.ts +102 -0
  24. package/apps/web/src/server.ts +141 -0
  25. package/apps/web/src/settings.ts +88 -0
  26. package/bin/careermate.mjs +74 -0
  27. package/dist/careermate.mcpb +0 -0
  28. package/dist/install-page/index.html +474 -0
  29. package/dist/install-page/style.css +391 -0
  30. package/dist/install-page/vercel.json +20 -0
  31. package/dist/mcp-smoke.err +3 -0
  32. package/dist/mcp.mjs +23704 -0
  33. package/dist/mcpb-stage/README.md +219 -0
  34. package/dist/mcpb-stage/dist/install-page/index.html +434 -0
  35. package/dist/mcpb-stage/dist/install-page/style.css +407 -0
  36. package/dist/mcpb-stage/dist/install-page/vercel.json +20 -0
  37. package/dist/mcpb-stage/dist/mcp.mjs +23704 -0
  38. package/dist/mcpb-stage/dist/public/app.js +118 -0
  39. package/dist/mcpb-stage/dist/public/fonts/PretendardVariable.woff2 +0 -0
  40. package/dist/mcpb-stage/dist/public/index.html +41 -0
  41. package/dist/mcpb-stage/dist/public/lib.js +282 -0
  42. package/dist/mcpb-stage/dist/public/pages/applications.js +98 -0
  43. package/dist/mcpb-stage/dist/public/pages/documents.js +446 -0
  44. package/dist/mcpb-stage/dist/public/pages/home.js +263 -0
  45. package/dist/mcpb-stage/dist/public/pages/interview.js +230 -0
  46. package/dist/mcpb-stage/dist/public/pages/jobs.js +494 -0
  47. package/dist/mcpb-stage/dist/public/pages/profile.js +576 -0
  48. package/dist/mcpb-stage/dist/public/pages/settings.js +233 -0
  49. package/dist/mcpb-stage/dist/public/styles.css +420 -0
  50. package/dist/mcpb-stage/dist/web.mjs +7240 -0
  51. package/dist/mcpb-stage/manifest.json +40 -0
  52. package/dist/public/app.js +118 -0
  53. package/dist/public/fonts/PretendardVariable.woff2 +0 -0
  54. package/dist/public/index.html +41 -0
  55. package/dist/public/lib.js +282 -0
  56. package/dist/public/pages/applications.js +98 -0
  57. package/dist/public/pages/documents.js +446 -0
  58. package/dist/public/pages/home.js +263 -0
  59. package/dist/public/pages/interview.js +230 -0
  60. package/dist/public/pages/jobs.js +494 -0
  61. package/dist/public/pages/profile.js +576 -0
  62. package/dist/public/pages/settings.js +233 -0
  63. package/dist/public/styles.css +426 -0
  64. package/dist/web.mjs +7240 -0
  65. package/docs/ARCHITECTURE.md +208 -0
  66. package/docs/CHANGES_V1.md +103 -0
  67. package/docs/DATA_MODEL.md +460 -0
  68. package/docs/DECISIONS.md +277 -0
  69. package/docs/DEMO.md +242 -0
  70. package/docs/INSTALL.md +148 -0
  71. package/docs/INSTALL_AND_USAGE.md +99 -0
  72. package/docs/MCP_TOOLS.md +233 -0
  73. package/docs/ROADMAP.md +134 -0
  74. package/docs/START_WORKFLOW.md +125 -0
  75. package/docs/SUPPORTED_AI_APPS.md +60 -0
  76. package/docs/TODO.md +57 -0
  77. package/docs/UX_NOTES.md +247 -0
  78. package/docs/WORKFLOWS.md +200 -0
  79. package/install-page/index.html +474 -0
  80. package/install-page/style.css +391 -0
  81. package/install-page/vercel.json +20 -0
  82. package/package.json +68 -0
  83. package/packages/core/src/context.ts +74 -0
  84. package/packages/core/src/index.ts +8 -0
  85. package/packages/core/src/onboarding.ts +81 -0
  86. package/packages/core/src/services.ts +146 -0
  87. package/packages/core/src/summary.ts +104 -0
  88. package/packages/db/src/connection.ts +46 -0
  89. package/packages/db/src/index.ts +22 -0
  90. package/packages/db/src/paths.ts +41 -0
  91. package/packages/db/src/repositories.ts +828 -0
  92. package/packages/db/src/runtime.ts +58 -0
  93. package/packages/db/src/schema.ts +189 -0
  94. package/packages/exporters/src/html.ts +113 -0
  95. package/packages/exporters/src/index.ts +364 -0
  96. package/packages/exporters/src/markdown.ts +178 -0
  97. package/packages/mcp-tools/src/bridge.ts +83 -0
  98. package/packages/mcp-tools/src/index.ts +8 -0
  99. package/packages/mcp-tools/src/result.ts +49 -0
  100. package/packages/mcp-tools/src/tools.ts +455 -0
  101. package/packages/parsers/src/html.ts +86 -0
  102. package/packages/parsers/src/index.ts +228 -0
  103. package/packages/parsers/src/keywords.ts +151 -0
  104. package/packages/prompts/src/humanize.ts +59 -0
  105. package/packages/prompts/src/index.ts +82 -0
  106. package/packages/prompts/src/install.ts +43 -0
  107. package/packages/prompts/src/onboarding.ts +35 -0
  108. package/packages/prompts/src/system.ts +53 -0
  109. package/packages/shared/src/enums.ts +103 -0
  110. package/packages/shared/src/index.ts +18 -0
  111. package/packages/shared/src/schemas.ts +398 -0
  112. package/packages/workflows/src/definitions.ts +107 -0
  113. package/packages/workflows/src/index.ts +39 -0
  114. package/scripts/build-dist.mjs +62 -0
  115. package/scripts/build-mcpb.mjs +70 -0
  116. package/scripts/doctor.ts +81 -0
  117. package/scripts/init.ts +342 -0
  118. package/scripts/mcp-probe.ts +55 -0
  119. package/scripts/migrate.ts +6 -0
  120. package/scripts/run.mjs +33 -0
  121. package/scripts/seed.ts +129 -0
  122. package/scripts/test.ts +117 -0
  123. package/scripts/ui-smoke.ts +73 -0
  124. package/tsconfig.json +29 -0
@@ -0,0 +1,474 @@
1
+ <!DOCTYPE html>
2
+ <html lang="ko" data-theme="">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>CareerMate โ€” ๋‚ด AI๋ฅผ ์ปค๋ฆฌ์–ด ๋น„์„œ๋กœ</title>
7
+ <meta name="description" content="Claude DesktopยทClaude CodeยทCodex ๊ฐ™์€ ๋กœ์ปฌ AI ์•ฑ์— ์—ฐ๊ฒฐํ•˜์„ธ์š”. CareerMate๊ฐ€ ์ด๋ ฅ์„œยท์ž๊ธฐ์†Œ๊ฐœ์„œยท์ง€์› ํ˜„ํ™ฉ์„ ์ด ์ปดํ“จํ„ฐ์—๋งŒ ์ €์žฅํ•˜๊ณ  MCP๋กœ ๋‹น์‹ ์˜ AI์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค." />
8
+ <link rel="stylesheet" href="style.css" />
9
+ </head>
10
+ <body>
11
+ <!-- ============================================================ nav -->
12
+ <nav class="nav">
13
+ <a class="nav__brand" href="#top">
14
+ <span class="nav__logo" aria-hidden="true">C</span>
15
+ <span class="nav__name">CareerMate</span>
16
+ </a>
17
+ <div class="nav__links">
18
+ <a href="#how">๋™์ž‘ ๋ฐฉ์‹</a>
19
+ <a href="#features">๊ธฐ๋Šฅ</a>
20
+ <a href="#install">์„ค์น˜</a>
21
+ <a href="#privacy">๊ฐœ์ธ์ •๋ณด</a>
22
+ </div>
23
+ <div class="nav__actions">
24
+ <button class="theme-toggle" id="theme-toggle" type="button" aria-label="๋‹คํฌ ๋ชจ๋“œ ์ „ํ™˜" title="๋‹คํฌ ๋ชจ๋“œ ์ „ํ™˜">
25
+ <svg class="i-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
26
+ <svg class="i-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
27
+ </button>
28
+ <a class="btn btn--ghost" href="#install">์„ค์น˜ํ•˜๊ธฐ</a>
29
+ </div>
30
+ </nav>
31
+
32
+ <main id="top">
33
+
34
+ <!-- ========================================================== hero -->
35
+ <header class="hero">
36
+ <span class="pill-badge">
37
+ <span class="pill-badge__dot" aria-hidden="true"></span>
38
+ ๋กœ์ปฌ ์ „์šฉ ยท ์˜คํ”ˆ์†Œ์Šค ยท Claude Desktop ์›ํด๋ฆญ
39
+ </span>
40
+ <h1 class="hero__title">
41
+ ๋‚ด๊ฐ€ ์“ฐ๋˜ <span class="accent">AI</span>๋ฅผ<br />
42
+ ๋‚˜๋งŒ์˜ <span class="accent">์ปค๋ฆฌ์–ด ๋น„์„œ</span>๋กœ
43
+ </h1>
44
+ <p class="hero__lede">
45
+ ์ด๋ ฅ์„œยท์ž๊ธฐ์†Œ๊ฐœ์„œยท์ง€์› ํ˜„ํ™ฉ์„ <strong>์ด ์ปดํ“จํ„ฐ ์•ˆ์—์„œ</strong> ๊ด€๋ฆฌํ•˜์„ธ์š”.<br />
46
+ ๋ถ„์„๊ณผ ๊ธ€์“ฐ๊ธฐ๋Š” ํ‰์†Œ ์“ฐ๋˜ AI๊ฐ€, ๋ฐ์ดํ„ฐ ๋ณด๊ด€์€ CareerMate๊ฐ€ ๋งก์Šต๋‹ˆ๋‹ค.
47
+ </p>
48
+
49
+ <div class="hero__cta">
50
+ <a class="btn btn--primary" href="#install">
51
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
52
+ ์„ค์น˜ ๋ฐฉ๋ฒ• ๋ณด๊ธฐ
53
+ </a>
54
+ <a class="btn btn--ghost" href="#install-other">๊ธฐํƒ€ MCP ํด๋ผ์ด์–ธํŠธ</a>
55
+ </div>
56
+
57
+ <p class="hero__note">
58
+ CareerMate๋Š” <strong>๋‚ด ์ปดํ“จํ„ฐ์—์„œ ๋„๋Š” ๋กœ์ปฌ ๋„๊ตฌ</strong>๋ผ, ๋‚ด ์ปดํ“จํ„ฐ์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” AI์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค โ€” <strong>Claude Desktop ยท Claude Code ยท Codex</strong>.
59
+ ์„ค์น˜๋ฅผ ๋งˆ์ณค๋‹ค๋ฉด ๋Œ€์‹œ๋ณด๋“œ <code>http://127.0.0.1:4319</code>์—์„œ ๋‚ด ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
60
+ </p>
61
+ </header>
62
+
63
+ <!-- ========================================================== how -->
64
+ <section id="how" class="section">
65
+ <div class="section__head">
66
+ <span class="eyebrow">๋™์ž‘ ๋ฐฉ์‹</span>
67
+ <h2>๋‹น์‹ ์˜ AI๊ฐ€ <span class="accent">๋‘๋‡Œ</span>,<br />CareerMate๋Š” <span class="accent">์ปค๋ฆฌ์–ด ์„œ๋ž์žฅ</span></h2>
68
+ <p>CareerMate ์•ˆ์—๋Š” AI๊ฐ€ ๋“ค์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.<br />์ƒ๊ฐํ•˜๋Š” ์ผ์€ ๋‹น์‹ ์˜ AI๊ฐ€, ๋ฐ์ดํ„ฐ ๋ณด๊ด€์€ CareerMate๊ฐ€ ๋งก์Šต๋‹ˆ๋‹ค.</p>
69
+ </div>
70
+ <div class="cards-3">
71
+ <article class="feature">
72
+ <div class="feature__icon">
73
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5a3 3 0 1 0-5.99.13 3 3 0 0 0-1.5 5.5A3 3 0 0 0 6 16.5a3 3 0 0 0 6 .5V5z"/><path d="M12 5a3 3 0 1 1 5.99.13 3 3 0 0 1 1.5 5.5A3 3 0 0 1 18 16.5a3 3 0 0 1-6 .5V5z"/></svg>
74
+ </div>
75
+ <h3>1. ๋‹น์‹ ์˜ AI์™€ ๋Œ€ํ™”</h3>
76
+ <p>ํ‰์†Œ ์“ฐ๋˜ Claude์—๊ฒŒ ๋ง๋กœ ์‹œํ‚ค๋ฉด ๋ฉ๋‹ˆ๋‹ค.<br />๋ถ„์„ยท๊ธ€์“ฐ๊ธฐ ๊ฐ™์€ โ€œ์ƒ๊ฐโ€์€ ์ „๋ถ€ ๋‹น์‹ ์˜ AI๊ฐ€ ํ•ฉ๋‹ˆ๋‹ค.</p>
77
+ </article>
78
+ <article class="feature">
79
+ <div class="feature__icon">
80
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 12h6"/><path d="M9 12a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3"/><path d="M15 12a3 3 0 0 0 3 3v2a3 3 0 0 1-3 3"/></svg>
81
+ </div>
82
+ <h3>2. MCP๋กœ ์—ฐ๊ฒฐ</h3>
83
+ <p>ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ MCP๊ฐ€ AI์™€ CareerMate๋ฅผ ์ž‡๋Š” โ€œUSB-Cโ€ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.<br />AI๊ฐ€ 24๊ฐœ ๋„๊ตฌ๋กœ ๋‹น์‹ ์˜ ์ปค๋ฆฌ์–ด DB๋ฅผ ์ฝ๊ณ  ์”๋‹ˆ๋‹ค.</p>
84
+ </article>
85
+ <article class="feature">
86
+ <div class="feature__icon">
87
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="6" rx="1.5"/><rect x="3" y="14" width="18" height="6" rx="1.5"/><path d="M7 7h.01M7 17h.01"/></svg>
88
+ </div>
89
+ <h3>3. ์ด ์ปดํ“จํ„ฐ์— ์ €์žฅ</h3>
90
+ <p>๋ชจ๋“  ๋ฐ์ดํ„ฐ๋Š” ๋กœ์ปฌ SQLite(<code>~/.careermate</code>)์—๋งŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.<br />์™ธ๋ถ€ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹œ๋ณด๋“œ๋กœ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•˜์„ธ์š”.</p>
91
+ </article>
92
+ </div>
93
+ </section>
94
+
95
+ <!-- ====================================================== features -->
96
+ <section id="features" class="section">
97
+ <div class="section__head">
98
+ <span class="eyebrow">ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ</span>
99
+ <h2>์ง€์› ํ•œ ๊ฑด์„ <span class="accent">๋๊นŒ์ง€</span> ํ•จ๊ป˜ ์ฒ˜๋ฆฌ</h2>
100
+ <p>ํ”„๋กœํ•„ ์ •๋ฆฌ๋ถ€ํ„ฐ ๋ฉด์ ‘ ์ค€๋น„๊นŒ์ง€, AI์™€ ๋Œ€ํ™”๋งŒ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.</p>
101
+ </div>
102
+ <div class="checks">
103
+ <div class="check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><div><strong>ํ”„๋กœํ•„ยท์ด๋ ฅ์„œ ๊ตฌ์กฐํ™”</strong><span>์—…๋กœ๋“œํ•œ ํŒŒ์ผ์„ ์ฝ์–ด ๊ฒฝ๋ ฅยทํ”„๋กœ์ ํŠธยท์Šคํ‚ฌ๋กœ ์ •๋ฆฌยท๋ณด๊ด€.</span></div></div>
104
+ <div class="check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><div><strong>์ฑ„์šฉ๊ณต๊ณ  ํŒŒ์‹ฑยท์ €์žฅ</strong><span>๋ถ™์—ฌ๋„ฃ์€ ๊ณต๊ณ  ํ…์ŠคํŠธ์—์„œ ํšŒ์‚ฌยท์ง๋ฌดยท์ž๊ฒฉ์š”๊ฑด์„ ์ถ”์ถœ.</span></div></div>
105
+ <div class="check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><div><strong>์ ํ•ฉ๋„(ํ•) ๋ถ„์„</strong><span>๋‚ด ๊ฒฝ๋ ฅ๊ณผ ๊ณต๊ณ ๋ฅผ ๋น„๊ตํ•ด ๊ฐ•์ ยท๋ณด์™„์ ยท๋งค์นญ ํ‚ค์›Œ๋“œ ๋„์ถœ.</span></div></div>
106
+ <div class="check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><div><strong>๋งž์ถค ์ž์†Œ์„œ + ๋ฒ„์ „ ๊ด€๋ฆฌ</strong><span>๊ณต๊ณ ๋ณ„ ์ž๊ธฐ์†Œ๊ฐœ์„œ๋ฅผ ๋ฒ„์ „์œผ๋กœ ์Œ“๊ณ  ๋น„๊ต, ํŒŒ์ผ๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ.</span></div></div>
107
+ <div class="check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><div><strong>์ง€์› ์ƒํƒœ 8๋‹จ๊ณ„ ๊ด€๋ฆฌ</strong><span>์ž‘์„ฑ ์ค‘ โ†’ ์ง€์› โ†’ ์„œ๋ฅ˜ ํ•ฉ๊ฒฉ โ†’ ๋ฉด์ ‘ โ†’ ์ตœ์ข…๊นŒ์ง€ ์นธ๋ฐ˜์œผ๋กœ.</span></div></div>
108
+ <div class="check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><div><strong>๋ฉด์ ‘ ์ค€๋น„</strong><span>์„œ๋ฅ˜ ํ•ฉ๊ฒฉ ์‹œ ์˜ˆ์ƒ ์งˆ๋ฌธยทSTAR ๋‹ต๋ณ€ยท1๋ถ„ ์ž๊ธฐ์†Œ๊ฐœ ์ดˆ์•ˆ ์ƒ์„ฑ.</span></div></div>
109
+ </div>
110
+ </section>
111
+
112
+ <!-- ======================================================= install -->
113
+ <section id="install" class="section">
114
+ <div class="section__head">
115
+ <span class="eyebrow">์„ค์น˜</span>
116
+ <h2>์„ธ ๊ฐ€์ง€ AI ์•ฑ์— ์—ฐ๊ฒฐ</h2>
117
+ <p>์ง€์›ํ•˜๋Š” ๋กœ์ปฌ AI ์•ฑ์€ <strong>Claude Desktop ยท Claude Code ยท Codex</strong> ์…‹์ž…๋‹ˆ๋‹ค. ์–ด๋А ์ชฝ์ด๋“  ๊ฐ™์€ ์ฝ”์–ด(๋กœ์ปฌ DB + ๋„๊ตฌ 24๊ฐœ)๋ฅผ ์”๋‹ˆ๋‹ค.</p>
118
+ </div>
119
+
120
+ <div class="note">
121
+ <strong>์–ด๋–ค AI์—์„œ ๋˜๋‚˜์š”?</strong> CareerMate๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‚ด ์ปดํ“จํ„ฐ์—๋งŒ ๋‘๋Š” <strong>๋กœ์ปฌ MCP ๋„๊ตฌ</strong>์ž…๋‹ˆ๋‹ค.
122
+ ๊ทธ๋ž˜์„œ <strong>๋‚ด ์ปดํ“จํ„ฐ์—์„œ ์‹คํ–‰๋˜๋ฉฐ ๋กœ์ปฌ ํ”„๋กœ๊ทธ๋žจ์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” AI</strong>์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค โ€” Claude Desktop ยท Claude Code ยท Codex(๊ทธ ์™ธ CursorยทClineยทWindsurf ๋“ฑ๋„ ๊ฐ€๋Šฅ).
123
+ ChatGPTยทGeminiยทClaude์˜ <strong>์›น/๋ชจ๋ฐ”์ผ ์•ฑ</strong>์€ ํด๋ผ์šฐ๋“œ์—์„œ ๋Œ์•„ ๋‚ด ์ปดํ“จํ„ฐ์˜ ๋กœ์ปฌ ์„œ๋ฒ„์— ์ง์ ‘ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(์›๊ฒฉ URL ๊ธฐ๋ฐ˜ MCP๋งŒ ์ง€์›).
124
+ </div>
125
+
126
+ <!-- track 1 ยท Claude Desktop -->
127
+ <div class="track">
128
+ <div class="track__head">
129
+ <span class="track__tag">1 ยท Claude Desktop</span>
130
+ <h3>์›ํด๋ฆญ <code>.mcpb</code> ์„ค์น˜</h3>
131
+ <p>ํ„ฐ๋ฏธ๋„๋„, Node ์„ค์น˜๋„ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ ํ•˜๋‚˜๋ฅผ ๋”๋ธ”ํด๋ฆญํ•˜๋ฉด ๋๋‚ฉ๋‹ˆ๋‹ค.</p>
132
+ </div>
133
+ <ol class="steps">
134
+ <li class="step">
135
+ <div class="step__no">1</div>
136
+ <div class="step__body">
137
+ <h3>์„ค์น˜ ํŒŒ์ผ ๋ฐ›๊ธฐ</h3>
138
+ <p><code>careermate.mcpb</code> ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. <strong>(Release <code>v0.1.0</code>์— ์žˆ์œผ๋‚˜ ์ €์žฅ์†Œ๊ฐ€ ๋น„๊ณต๊ฐœ๋ผ ๊ณต๊ฐœ ๋‹ค์šด๋กœ๋“œ ๋งํฌ๋Š” ์•„์ง ์—†์Šต๋‹ˆ๋‹ค.)</strong></p>
139
+ <!-- TODO: ์ €์žฅ์†Œ๋ฅผ public์œผ๋กœ ์ „ํ™˜ํ•˜๋ฉด https://github.com/osntak/CareerMate/releases/latest ์˜ .mcpb๋กœ ์ด ๋ฒ„ํŠผ์„ ํ™œ์„ฑํ™”. ํ˜„์žฌ๋Š” private repo๋ผ ๊ณต๊ฐœ ๋‹ค์šด๋กœ๋“œ ๋ถˆ๊ฐ€. -->
140
+ <button class="btn btn--primary" type="button" disabled aria-disabled="true">
141
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
142
+ careermate.mcpb ๋‹ค์šด๋กœ๋“œ (๋น„๊ณต๊ฐœ ์ €์žฅ์†Œ)
143
+ </button>
144
+ <p class="step__tip">์ ‘๊ทผ ๊ถŒํ•œ์ด ์žˆ์œผ๋ฉด Release <code>v0.1.0</code>์—์„œ ๋ฐ›๊ณ , ์—†์œผ๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ <code>npx -y careermate init</code>๋กœ ์„ค์น˜ํ•˜๊ฑฐ๋‚˜ ์†Œ์Šค์—์„œ <code>npm run build:mcpb</code>๋กœ ๋นŒ๋“œํ•˜์„ธ์š”.</p>
145
+ </div>
146
+ </li>
147
+ <li class="step">
148
+ <div class="step__no">2</div>
149
+ <div class="step__body">
150
+ <h3>๋”๋ธ”ํด๋ฆญ์œผ๋กœ ์„ค์น˜</h3>
151
+ <p>๋‚ด๋ ค๋ฐ›์€ <code>careermate.mcpb</code>๋ฅผ ๋”๋ธ”ํด๋ฆญํ•˜๋ฉด Claude Desktop์ด ์„ค์น˜ ์ฐฝ์„ ์—ฝ๋‹ˆ๋‹ค. <strong>์„ค์น˜</strong>๋ฅผ ๋ˆ„๋ฅด์„ธ์š”.
152
+ (๋˜๋Š” Claude Desktop โ†’ <strong>Settings โ†’ Extensions</strong>์— ํŒŒ์ผ์„ ๋Œ์–ด๋‹ค ๋†“์•„๋„ ๋ฉ๋‹ˆ๋‹ค.)</p>
153
+ </div>
154
+ </li>
155
+ <li class="step">
156
+ <div class="step__no">3</div>
157
+ <div class="step__body">
158
+ <h3>์žฌ์‹œ์ž‘ํ•˜๊ณ  ํ™•์ธ</h3>
159
+ <p>Claude Desktop์„ ์™„์ „ํžˆ ์ข…๋ฃŒํ–ˆ๋‹ค ๋‹ค์‹œ ์ผœ์„ธ์š”. ๊ทธ๋‹ค์Œ Claude์—๊ฒŒ
160
+ <strong>โ€œ<code>get_onboarding_status</code> ํ˜ธ์ถœํ•ด์„œ ์—ฐ๊ฒฐ๋๋Š”์ง€ ํ™•์ธํ•ด์ค˜โ€</strong>๋ผ๊ณ  ๋งํ•ด ๊ฒฐ๊ณผ๊ฐ€ ๋Œ์•„์˜ค๋ฉด ์ •์ƒ์ž…๋‹ˆ๋‹ค.</p>
161
+ </div>
162
+ </li>
163
+ </ol>
164
+ <p class="step__tip">Claude Desktop์ด Node๋ฅผ ๋‚ด์žฅํ•˜๋ฏ€๋กœ ๋”ฐ๋กœ ์„ค์น˜ํ•  ๊ฒŒ ์—†์Šต๋‹ˆ๋‹ค. ๋“œ๋ฌผ๊ฒŒ ๋‚ด์žฅ Node๊ฐ€ 22.5 ๋ฏธ๋งŒ์ด๋ผ ์„ค์น˜๊ฐ€ ๋ง‰ํžˆ๋ฉด ์•„๋ž˜ <a href="#install-other">ํ„ฐ๋ฏธ๋„ ๋ฐฉ์‹</a>์„ ์“ฐ์„ธ์š”.</p>
165
+ </div>
166
+
167
+ <!-- track 2 ยท Claude Code -->
168
+ <div class="track">
169
+ <div class="track__head">
170
+ <span class="track__tag">2 ยท Claude Code</span>
171
+ <h3>CareerMate ํด๋”์—์„œ ํ•œ ๋ฌธ์žฅ์œผ๋กœ</h3>
172
+ <p>๋ฃจํŠธ <code>CLAUDE.md</code>๊ฐ€ ์„ค์น˜ ์•ˆ๋‚ด ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํด๋”๋ฅผ ์—ด๊ณ  ์•„๋ž˜ ๋ฌธ์žฅ๋งŒ ๋งํ•˜์„ธ์š”.</p>
173
+ </div>
174
+ <ol class="steps">
175
+ <li class="step">
176
+ <div class="step__no">1</div>
177
+ <div class="step__body">
178
+ <h3>CareerMate ํด๋”์—์„œ Claude Code ์—ด๊ธฐ</h3>
179
+ <p>CareerMate ํด๋”์—์„œ <code>claude</code>๋ฅผ ์‹คํ–‰ํ•œ ๋’ค, ์•„๋ž˜ ๋ฌธ์žฅ์„ ๊ทธ๋Œ€๋กœ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. Claude๊ฐ€ <code>INSTALL.md</code>๋ฅผ ๋”ฐ๋ผ ๋“ฑ๋ก๊นŒ์ง€ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.</p>
180
+ <div class="code">
181
+ <button class="copy-btn" type="button" data-copy-target="code-prompt-cc">๋ณต์‚ฌ</button>
182
+ <pre id="code-prompt-cc">CareerMate๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์„ค์ •ํ•ด์ค˜. INSTALL.md๋ฅผ ๋”ฐ๋ผ ์ง„ํ–‰ํ•ด์ค˜.</pre>
183
+ </div>
184
+ </div>
185
+ </li>
186
+ <li class="step">
187
+ <div class="step__no">2</div>
188
+ <div class="step__body">
189
+ <h3>ํ•œ ๋ฒˆ๋งŒ ์Šน์ธํ•˜๊ณ  ํ™•์ธ</h3>
190
+ <p>Claude Code๊ฐ€ ํ”„๋กœ์ ํŠธ MCP ์„œ๋ฒ„ ๋“ฑ๋ก์„ <strong>ํ•œ ๋ฒˆ ์Šน์ธ</strong> ์š”์ฒญํ•˜๋ฉด ํ—ˆ์šฉํ•˜์„ธ์š”. ๊ทธ๋‹ค์Œ <strong>โ€œ<code>get_onboarding_status</code> ํ˜ธ์ถœํ•ด์„œ ์—ฐ๊ฒฐ๋๋Š”์ง€ ํ™•์ธํ•ด์ค˜โ€</strong>๋กœ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.</p>
191
+ </div>
192
+ </li>
193
+ </ol>
194
+ </div>
195
+
196
+ <!-- track 3 ยท Codex -->
197
+ <div class="track">
198
+ <div class="track__head">
199
+ <span class="track__tag">3 ยท Codex</span>
200
+ <h3>CareerMate ํด๋”์—์„œ ํ•œ ๋ฌธ์žฅ์œผ๋กœ</h3>
201
+ <p>๋ฃจํŠธ <code>AGENTS.md</code>๊ฐ€ ์„ค์น˜ ์•ˆ๋‚ด ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํด๋”๋ฅผ ์—ด๊ณ  ๊ฐ™์€ ๋ฌธ์žฅ์„ ๋งํ•˜์„ธ์š”.</p>
202
+ </div>
203
+ <ol class="steps">
204
+ <li class="step">
205
+ <div class="step__no">1</div>
206
+ <div class="step__body">
207
+ <h3>CareerMate ํด๋”์—์„œ Codex ์—ด๊ธฐ</h3>
208
+ <p>CareerMate ํด๋”์—์„œ <code>codex</code>๋ฅผ ์‹คํ–‰ํ•œ ๋’ค, ์•„๋ž˜ ๋ฌธ์žฅ์„ ๊ทธ๋Œ€๋กœ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. Codex๊ฐ€ <code>INSTALL.md</code>๋ฅผ ๋”ฐ๋ผ ๋“ฑ๋ก๊นŒ์ง€ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.</p>
209
+ <div class="code">
210
+ <button class="copy-btn" type="button" data-copy-target="code-prompt-codex">๋ณต์‚ฌ</button>
211
+ <pre id="code-prompt-codex">CareerMate๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์„ค์ •ํ•ด์ค˜. INSTALL.md๋ฅผ ๋”ฐ๋ผ ์ง„ํ–‰ํ•ด์ค˜.</pre>
212
+ </div>
213
+ </div>
214
+ </li>
215
+ <li class="step">
216
+ <div class="step__no">2</div>
217
+ <div class="step__body">
218
+ <h3><code>/mcp</code>๋กœ ํ™•์ธ</h3>
219
+ <p>Codex ์•ˆ์—์„œ <code>/mcp</code> ๋ช…๋ น์œผ๋กœ <code>careermate</code>๊ฐ€ ๋“ฑ๋ก๋๋Š”์ง€ ํ™•์ธํ•˜๊ณ , <strong>โ€œ<code>get_onboarding_status</code> ํ˜ธ์ถœํ•ด์„œ ์—ฐ๊ฒฐ๋๋Š”์ง€ ํ™•์ธํ•ด์ค˜โ€</strong>๋กœ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.</p>
220
+ </div>
221
+ </li>
222
+ </ol>
223
+ </div>
224
+
225
+ <!-- track ยท ๊ธฐํƒ€ MCP ํด๋ผ์ด์–ธํŠธ (ํ„ฐ๋ฏธ๋„) -->
226
+ <div class="track" id="install-other">
227
+ <div class="track__head">
228
+ <span class="track__tag">๊ธฐํƒ€ MCP ํด๋ผ์ด์–ธํŠธ ยท ํ„ฐ๋ฏธ๋„</span>
229
+ <h3>Cursor ๋“ฑ โ€” ์ง์ ‘ ๋“ฑ๋ก</h3>
230
+ <p>Cursor ยท Cline ยท Windsurf ๋“ฑ ๋‹ค๋ฅธ ๋กœ์ปฌ stdio MCP ํด๋ผ์ด์–ธํŠธ๋Š” ํ„ฐ๋ฏธ๋„์—์„œ ์ง์ ‘ ์„ค์น˜ยท๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.</p>
231
+ </div>
232
+
233
+ <div class="note">
234
+ <strong>์ค€๋น„๋ฌผ์€ Node.js 22.5 ์ด์ƒ</strong> ํ•˜๋‚˜๋ฟ์ž…๋‹ˆ๋‹ค. ๋‚ด์žฅ SQLite๋ฅผ ์“ฐ๋ฏ€๋กœ ๋ณ„๋„ ์ปดํŒŒ์ผ๋Ÿฌยท๋นŒ๋“œ ๋„๊ตฌ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.
235
+ ํ„ฐ๋ฏธ๋„(Windows๋Š” PowerShell)์—์„œ <code>node --version</code>์œผ๋กœ ํ™•์ธํ•˜๊ณ , ๋‚ฎ์œผ๋ฉด
236
+ <a href="https://nodejs.org/" rel="noopener" target="_blank">nodejs.org</a>์—์„œ LTS๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”.
237
+ </div>
238
+
239
+ <ol class="steps">
240
+ <li class="step">
241
+ <div class="step__no">1</div>
242
+ <div class="step__body">
243
+ <h3>์ฝ”๋“œ ๋ฐ›๊ธฐ</h3>
244
+ <p>CareerMate ์ €์žฅ์†Œ๋ฅผ ๋‚ด๋ ค๋ฐ›์Šต๋‹ˆ๋‹ค. (Git์ด ์—†์œผ๋ฉด <em>Code โ†’ Download ZIP</em>์œผ๋กœ ๋ฐ›์•„ ์••์ถ•์„ ํ’€์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.)</p>
245
+ <!-- ์ €์žฅ์†Œ(osntak/CareerMate)๋Š” ํ˜„์žฌ ๋น„๊ณต๊ฐœ๋ผ clone์— ์ ‘๊ทผ ๊ถŒํ•œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ถŒํ•œ์ด ์—†์œผ๋ฉด ์œ„ npx ๋ฐฉ์‹์„ ์“ฐ์„ธ์š”. -->
246
+ <div class="code">
247
+ <button class="copy-btn" type="button" data-copy-target="code-clone">๋ณต์‚ฌ</button>
248
+ <pre id="code-clone">git clone https://github.com/osntak/CareerMate.git
249
+ cd CareerMate</pre>
250
+ </div>
251
+ </div>
252
+ </li>
253
+ <li class="step">
254
+ <div class="step__no">2</div>
255
+ <div class="step__body">
256
+ <h3>์„ค์น˜</h3>
257
+ <p>์˜์กด์„ฑ์„ ํ•œ ๋ฒˆ๋งŒ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. (๋นŒ๋“œ ๋‹จ๊ณ„ ์—†์Œ) โ€” ๋˜๋Š” ํด๋ก  ์—†์ด <strong><code>npx -y careermate init</code></strong> ํ•œ ์ค„๋กœ๋„ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค(<code>careermate</code> npm ๊ฒŒ์‹œ ์™„๋ฃŒ).</p>
258
+ <div class="code">
259
+ <span class="code__label">ํ”„๋กœ์ ํŠธ ํด๋”์—์„œ</span>
260
+ <button class="copy-btn" type="button" data-copy-target="code-install">๋ณต์‚ฌ</button>
261
+ <pre id="code-install">npm install</pre>
262
+ </div>
263
+ </div>
264
+ </li>
265
+ <li class="step">
266
+ <div class="step__no">3</div>
267
+ <div class="step__body">
268
+ <h3>AI ํด๋ผ์ด์–ธํŠธ์— ์ž๋™ ์—ฐ๊ฒฐ</h3>
269
+ <p>๊ฐ์ง€๋œ ํด๋ผ์ด์–ธํŠธ์˜ MCP ์„ค์ •์— CareerMate๋ฅผ ์ž๋™ ๋“ฑ๋กํ•˜๊ณ , Claude Code ํ”„๋กœ์ ํŠธ ์„ค์ •(<code>.mcp.json</code>)์€ ํ•ญ์ƒ ํ•จ๊ป˜ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋๋‚˜๋ฉด ํ•ด๋‹น AI ํด๋ผ์ด์–ธํŠธ๋ฅผ <strong>์™„์ „ํžˆ ์ข…๋ฃŒํ–ˆ๋‹ค ๋‹ค์‹œ ์ผœ์„ธ์š”.</strong></p>
270
+ <div class="code">
271
+ <span class="code__label">์ž๋™ ๋“ฑ๋ก</span>
272
+ <button class="copy-btn" type="button" data-copy-target="code-init">๋ณต์‚ฌ</button>
273
+ <pre id="code-init">npm run init</pre>
274
+ </div>
275
+ <p class="step__tip">์ง์ ‘ ๋ถ™์—ฌ๋„ฃ๊ณ  ์‹ถ๋‹ค๋ฉด <code>npm run init -- --print</code>๋กœ ์„ค์ • JSONยท๋ช…๋ น๋งŒ ์ถœ๋ ฅํ•ด ํด๋ผ์ด์–ธํŠธ์— ์ถ”๊ฐ€ํ•˜์„ธ์š”. ํŠน์ • ํด๋ผ์ด์–ธํŠธ๋งŒ ๋“ฑ๋กํ•˜๋ ค๋ฉด <code>npm run init -- --client cursor</code>์ฒ˜๋Ÿผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋ณ„ ์„ค์ • ํŒŒ์ผ ์œ„์น˜๋Š” ์•„๋ž˜ ํƒญ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.</p>
276
+
277
+ <div class="tabs" role="tablist" aria-label="์„ค์ • ํŒŒ์ผ ์œ„์น˜">
278
+ <button class="tab is-active" id="tab-claude" role="tab" aria-controls="panel-claude" aria-selected="true">Claude Desktop</button>
279
+ <button class="tab" id="tab-cursor" role="tab" aria-controls="panel-cursor" aria-selected="false" tabindex="-1">Cursor / ๊ธฐํƒ€</button>
280
+ </div>
281
+ <div class="panel" id="panel-claude" role="tabpanel" aria-labelledby="tab-claude" data-active="true">
282
+ <p class="path-note">Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code> ยท macOS: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code><br />(Settings โ†’ Developer โ†’ Edit Config ๋กœ๋„ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <code>npm run init</code>์ด ์ด ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.)</p>
283
+ </div>
284
+ <div class="panel" id="panel-cursor" role="tabpanel" aria-labelledby="tab-cursor" data-active="false" hidden>
285
+ <p class="path-note">ํ”„๋กœ์ ํŠธ๋ณ„: <code>.cursor/mcp.json</code> ยท ์ „์—ญ: <code>~/.cursor/mcp.json</code> โ€” CursorยทClineยทWindsurf ๋“ฑ ๋Œ€๋ถ€๋ถ„ ๊ฐ™์€ ํ˜•์‹์ž…๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ํ›„ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜์„ธ์š”.</p>
286
+ </div>
287
+ </div>
288
+ </li>
289
+ <li class="step">
290
+ <div class="step__no">4</div>
291
+ <div class="step__body">
292
+ <h3>๋Œ€์‹œ๋ณด๋“œ ์‹คํ–‰ (์„ ํƒ)</h3>
293
+ <p>๋‚ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•˜๋ ค๋ฉด ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์ผญ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์ฃผ์†Œ๋Š” <code>http://127.0.0.1:4319</code>, ํฌํŠธ๊ฐ€ ์‚ฌ์šฉ ์ค‘์ด๋ฉด ๋‹ค์Œ ๋นˆ ํฌํŠธ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ข…๋ฃŒ๋Š” <kbd>Ctrl</kbd>+<kbd>C</kbd>.</p>
294
+ <div class="code">
295
+ <span class="code__label">๋Œ€์‹œ๋ณด๋“œ ์‹œ์ž‘</span>
296
+ <button class="copy-btn" type="button" data-copy-target="code-start">๋ณต์‚ฌ</button>
297
+ <pre id="code-start">npm start</pre>
298
+ </div>
299
+ </div>
300
+ </li>
301
+ <li class="step">
302
+ <div class="step__no">5</div>
303
+ <div class="step__body">
304
+ <h3>์—ฐ๊ฒฐ ํ™•์ธ</h3>
305
+ <p>AI์—๊ฒŒ <strong>โ€œ<code>get_onboarding_status</code>๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์—ฐ๊ฒฐ๋๋Š”์ง€ ํ™•์ธํ•ด์ค˜โ€</strong>๋ผ๊ณ  ๋งํ•ด ๋ณด์„ธ์š”. ๊ฒฐ๊ณผ๊ฐ€ ๋Œ์•„์˜ค๋ฉด ์ •์ƒ์ž…๋‹ˆ๋‹ค.</p>
306
+ </div>
307
+ </li>
308
+ </ol>
309
+
310
+ <details class="acc">
311
+ <summary>๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ <span class="acc__hint">ํฌํŠธ ์ถฉ๋Œ ยท MCP ์—ฐ๊ฒฐ ์‹คํŒจ ยท ๋ฐ์ดํ„ฐ ์œ„์น˜ ยท ์ดˆ๊ธฐํ™”</span></summary>
312
+ <div class="acc__body">
313
+ <div class="trouble">
314
+ <div class="trouble__item">
315
+ <h4>ํฌํŠธ๊ฐ€ ์ด๋ฏธ ์‚ฌ์šฉ ์ค‘</h4>
316
+ <p>4319๊ฐ€ ๋ง‰ํžˆ๋ฉด ์ž๋™์œผ๋กœ ๋‹ค์Œ ๋นˆ ํฌํŠธ๋กœ ์˜ฎ๊ฒจ๊ฐ‘๋‹ˆ๋‹ค. ํ„ฐ๋ฏธ๋„์— ์ถœ๋ ฅ๋œ ์‹ค์ œ ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, <code>CAREERMATE_PORT</code> ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๊ณ ์ •ํ•˜์„ธ์š”.</p>
317
+ </div>
318
+ <div class="trouble__item">
319
+ <h4>AI์— MCP๊ฐ€ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์Œ</h4>
320
+ <p>โ‘  <code>npm run init</code>์ด ์ •์ƒ ์ข…๋ฃŒ๋๋Š”์ง€ โ‘ก <code>node --version</code>์ด 22.5 ์ด์ƒ์ธ์ง€ โ‘ข ํด๋ผ์ด์–ธํŠธ๋ฅผ <strong>์™„์ „ํžˆ ์ข…๋ฃŒ ํ›„ ์žฌ์‹œ์ž‘</strong>ํ–ˆ๋Š”์ง€ โ‘ฃ <code>npm install</code>์ด ๋๋‚ฌ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ํด๋”๋ฅผ ์˜ฎ๊ธฐ๊ฑฐ๋‚˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟจ๋‹ค๋ฉด ๋“ฑ๋ก๋œ ๊ฒฝ๋กœ๊ฐ€ ๊นจ์ง€๋ฏ€๋กœ <code>npm run init</code>์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์„ธ์š”.</p>
321
+ </div>
322
+ <div class="trouble__item">
323
+ <h4>์ƒํƒœ ์ ๊ฒ€</h4>
324
+ <p>ํ”„๋กœ์ ํŠธ ํด๋”์—์„œ ์ง„๋‹จ์„ ์‹คํ–‰ํ•˜๋ฉด Node ๋ฒ„์ „ยท๋ฐ์ดํ„ฐ ํด๋”ยทDB ์ƒํƒœ๋ฅผ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.</p>
325
+ <div class="code">
326
+ <button class="copy-btn" type="button" data-copy-target="code-doctor">๋ณต์‚ฌ</button>
327
+ <pre id="code-doctor">npm run doctor</pre>
328
+ </div>
329
+ </div>
330
+ <div class="trouble__item">
331
+ <h4>๋ฐ์ดํ„ฐ ์œ„์น˜ / ์ดˆ๊ธฐํ™”</h4>
332
+ <p>๊ธฐ๋ณธ ์œ„์น˜๋Š” <code>~/.careermate/careermate.sqlite</code>(Windows: <code>%USERPROFILE%\.careermate</code>). <code>CAREERMATE_DATA_DIR</code>๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ. <code>npm run migrate</code>๋Š” DB๋ฅผ ์ค€๋น„/์—…๊ทธ๋ ˆ์ด๋“œ(๋ฐ˜๋ณต ์‹คํ–‰ ์•ˆ์ „)ํ•˜๊ณ , ์™„์ „ ์ดˆ๊ธฐํ™”๋Š” <code>careermate.sqlite</code> ์‚ญ์ œ ํ›„ ์žฌ์‹คํ–‰(๋ฐฑ์—… ๊ถŒ์žฅ)์ž…๋‹ˆ๋‹ค.</p>
333
+ </div>
334
+ </div>
335
+ </div>
336
+ </details>
337
+ </div>
338
+ </section>
339
+
340
+ <!-- ======================================================= privacy -->
341
+ <section id="privacy" class="section">
342
+ <div class="privacy-card">
343
+ <div class="privacy-card__icon" aria-hidden="true">
344
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="M9 12l2 2 4-4"/></svg>
345
+ </div>
346
+ <div class="privacy-card__text">
347
+ <h2>๋‹น์‹ ์˜ ๋ฐ์ดํ„ฐ๋Š” ๋‹น์‹  ์ปดํ“จํ„ฐ๋ฅผ ๋– ๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค</h2>
348
+ <p>๋Œ€์‹œ๋ณด๋“œ ์„œ๋ฒ„๋Š” <code>127.0.0.1</code>(์ด ์ปดํ“จํ„ฐ)์—๋งŒ ๋ฐ”์ธ๋”ฉ๋˜์–ด ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ณ ,<br />MCP ์„œ๋ฒ„๋Š” ๋„คํŠธ์›Œํฌ ํ˜ธ์ถœ์„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ถ„์„ยท๊ธ€์“ฐ๊ธฐ๋Š” ๋‹น์‹ ์ด ์ง์ ‘ ๊ณ ๋ฅธ AI๊ฐ€ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.</p>
349
+ <ul class="privacy-card__list">
350
+ <li><strong>์ €์žฅ ์œ„์น˜</strong> <code>~/.careermate/careermate.sqlite</code></li>
351
+ <li><strong>๋‚ด๋ณด๋‚ด๊ธฐ</strong> ์ž๊ธฐ์†Œ๊ฐœ์„œ ๋“ฑ์„ <code>~/.careermate/exports</code>๋กœ</li>
352
+ <li><strong>์‚ญ์ œยท๊ด€๋ฆฌ</strong> ๋Œ€์‹œ๋ณด๋“œ <strong>์„ค์ •(Settings)</strong>์—์„œ ์ง์ ‘</li>
353
+ </ul>
354
+ </div>
355
+ </div>
356
+ </section>
357
+
358
+ </main>
359
+
360
+ <footer class="foot">
361
+ <div class="foot__brand"><span class="nav__logo" aria-hidden="true">C</span> CareerMate</div>
362
+ <p>๋กœ์ปฌ์—์„œ ๋™์ž‘ํ•˜๋Š” MCP ๊ธฐ๋ฐ˜ ์ปค๋ฆฌ์–ด ๊ด€๋ฆฌ ๋„๊ตฌ. ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋Š” ์ด ์ปดํ“จํ„ฐ์—๋งŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.</p>
363
+ <div class="foot__links">
364
+ <a href="#top">๋งจ ์œ„๋กœ</a>
365
+ <a href="#features">๊ธฐ๋Šฅ</a>
366
+ <a href="#install">์„ค์น˜</a>
367
+ </div>
368
+ </footer>
369
+
370
+ <div class="sr-only" role="status" aria-live="polite" id="copy-status"></div>
371
+
372
+ <script>
373
+ (function () {
374
+ 'use strict';
375
+ var status = document.getElementById('copy-status');
376
+
377
+ // --- generic clipboard helper ------------------------------------
378
+ function legacyCopy(text) {
379
+ var ta = document.createElement('textarea');
380
+ ta.value = text; ta.setAttribute('readonly', '');
381
+ ta.style.position = 'absolute'; ta.style.left = '-9999px';
382
+ document.body.appendChild(ta); ta.select();
383
+ var ok = false;
384
+ try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
385
+ document.body.removeChild(ta);
386
+ return ok;
387
+ }
388
+ function copyText(text, onok) {
389
+ if (navigator.clipboard && navigator.clipboard.writeText) {
390
+ navigator.clipboard.writeText(text).then(onok, function () { if (legacyCopy(text)) onok(); });
391
+ } else if (legacyCopy(text)) { onok(); }
392
+ }
393
+ function announce(msg) { if (status) status.textContent = msg; }
394
+
395
+ // --- copy buttons (code blocks) ----------------------------------
396
+ function flashSmall(btn) {
397
+ var original = btn.textContent;
398
+ btn.textContent = '๋ณต์‚ฌ๋จ'; btn.classList.add('copied');
399
+ announce('ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
400
+ window.setTimeout(function () { btn.textContent = original; btn.classList.remove('copied'); }, 1600);
401
+ }
402
+ document.querySelectorAll('.copy-btn').forEach(function (btn) {
403
+ btn.addEventListener('click', function () {
404
+ var src = document.getElementById(btn.getAttribute('data-copy-target'));
405
+ if (src) copyText(src.textContent || '', function () { flashSmall(btn); });
406
+ });
407
+ });
408
+
409
+ // --- config tabs -------------------------------------------------
410
+ var tablist = document.querySelector('.tabs[role="tablist"]');
411
+ if (tablist) {
412
+ var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'));
413
+ function selectTab(tab) {
414
+ tabs.forEach(function (t) {
415
+ var sel = t === tab;
416
+ t.setAttribute('aria-selected', sel ? 'true' : 'false');
417
+ t.classList.toggle('is-active', sel);
418
+ t.tabIndex = sel ? 0 : -1;
419
+ var panel = document.getElementById(t.getAttribute('aria-controls'));
420
+ if (panel) {
421
+ panel.setAttribute('data-active', sel ? 'true' : 'false');
422
+ if (sel) panel.removeAttribute('hidden'); else panel.setAttribute('hidden', '');
423
+ }
424
+ });
425
+ }
426
+ tabs.forEach(function (tab, i) {
427
+ tab.addEventListener('click', function () { selectTab(tab); });
428
+ tab.addEventListener('keydown', function (e) {
429
+ var idx = null;
430
+ if (e.key === 'ArrowRight') idx = (i + 1) % tabs.length;
431
+ else if (e.key === 'ArrowLeft') idx = (i - 1 + tabs.length) % tabs.length;
432
+ else if (e.key === 'Home') idx = 0;
433
+ else if (e.key === 'End') idx = tabs.length - 1;
434
+ if (idx !== null) { e.preventDefault(); tabs[idx].focus(); selectTab(tabs[idx]); }
435
+ });
436
+ });
437
+ }
438
+
439
+ // --- scroll reveal (fade-up on enter) ----------------------------
440
+ var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
441
+ if (!reduceMotion && 'IntersectionObserver' in window) {
442
+ var revealEls = document.querySelectorAll('.section__head, .feature, .check, .track__head, .step, .acc, .privacy-card');
443
+ revealEls.forEach(function (el) { el.classList.add('reveal'); });
444
+ var io = new IntersectionObserver(function (entries) {
445
+ entries.forEach(function (e) {
446
+ if (e.isIntersecting) { e.target.classList.add('is-visible'); io.unobserve(e.target); }
447
+ });
448
+ }, { threshold: 0.1, rootMargin: '0px 0px -48px 0px' });
449
+ revealEls.forEach(function (el) { io.observe(el); });
450
+ }
451
+
452
+ // --- theme toggle (persist) --------------------------------------
453
+ var root = document.documentElement;
454
+ var toggle = document.getElementById('theme-toggle');
455
+ var saved = null;
456
+ try { saved = window.localStorage.getItem('cf-theme'); } catch (e) {}
457
+ if (saved === 'dark' || saved === 'light') root.setAttribute('data-theme', saved);
458
+ function isDark() {
459
+ var t = root.getAttribute('data-theme');
460
+ if (t === 'dark') return true;
461
+ if (t === 'light') return false;
462
+ return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
463
+ }
464
+ if (toggle) {
465
+ toggle.addEventListener('click', function () {
466
+ var next = isDark() ? 'light' : 'dark';
467
+ root.setAttribute('data-theme', next);
468
+ try { window.localStorage.setItem('cf-theme', next); } catch (e) {}
469
+ });
470
+ }
471
+ })();
472
+ </script>
473
+ </body>
474
+ </html>