๋ชฉ์ฐจ
- ๊ฐ์
- ๋ฐฐ๊ฒฝ์ง์
- ๊ฐ์ค
- ํ๊ณ์
- ๋ฐ๊ฒฌ
- ๊ฒฐ๋ก
๊ฐ์
์ํํธ์จ์ด ์์คํ ๋ถ์1 2์ ์ํด์๋ ์ฝ๋๋ฒ ์ด์ค์ ์์ฑ๋ ํ์ผ๋ค์ โ๋ฐฉ๋ฌธโํ๋ ๊ฒ์ด ํ์์ ์ด๋ค. ์๋ฅผ ๋ค์ด, ๋น์ฆ๋์ค ๋ก์ง์ ๊ดํ ์ง๋ฌธ์ LLM์ด ๋๋ตํ๊ธฐ ์ํด์๋, LLM์ ๊ทธ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ํ์ผ์ ์ฝ์ ์ ์์ด์ผ ํ๋ค3. ํํธ, ์ฝ๋๋ฒ ์ด์ค๋ ์ผ์ข ์ ๋น์ ํ ๋ฐ์ดํฐ์ ๋ชจ์์ผ๋ก ๋ณผ ์ ์๋๋ฐ, LLM์ด ๋น์ ํ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํ๋ ์ผ๋ฐํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฟ ์กด์ฌํ๋ค 4 5. ์ด ๊ธ์์๋ ์ฝ๋๋ฒ ์ด์ค๋ฅผ RAGํ๊ธฐ ์ํ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก์จ ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด๋ฅผ ์์ถํ ํ LLM์๊ฒ ์ ๊ณตํ๋ ๊ฒ์ ์๋ํ ๊ฒ์ด๋ค.
๋ฐฐ๊ฒฝ์ง์
โ์ฝ๋๋ฒ ์ด์คโ๋?
์ฌ์ง: ๋ฆฌ๋
์ค ์ฝ๋๋ฒ ์ด์ค
ํ ์ํํธ์จ์ด๋ฅผ ์ด๋ฃจ๋ ์์ค ์ฝ๋ ํ์ผ์ ๋ชจ์์ ์ฝ๋๋ฒ ์ด์ค๋ผ๊ณ ํ๋ค.
์ํํธ์จ์ด์ ๊ธฐ๋ฅ์ด ๋ง์์๋ก, ์ฝ๋๋ฒ ์ด์ค๋ ์์ฐ์ค๋ฝ๊ฒ ๋ฐฉ๋ํด์ง๋ค.
LLM์ด ๋ฐฉ๋ํ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์ดํดํ๋ ค๋ฉด
์ฝ๋๋ฒ ์ด์ค์ ๊ด๋ จ๋ ์์ ์ LLM์ด ์ฒ๋ฆฌํด์ค ์ ์์๊น?
- โ๋ก๊ทธ์ธ ํ์ด์ง์ ๋ฒํผ์ ์ถ๊ฐํด์คโ
- โ์์ค์ฝ๋์์ 'ํด๋ฉด ๊ณ์ '๊ณผ ๊ด๋ จ๋ ๋ก์ง์ ์ ๊ฑฐํด์คโ
- โ์ค๋ ์์ ํ ์ฝ๋๋ค์ ๋ํด ๋จ์ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด์คโ
- โ์ด ํด๋์ ๋ค์ด์๋ ์์ค์ฝ๋๋ค์ ํ ๋ฒ ๊ฒํ ํด์คโ
๋น์ฐํ๊ฒ๋ ์ฝ๋๋ฒ ์ด์ค๋ฅผ LLM์๊ฒ ์ ๋ฌํ๋ฉด ๋ ๊ฒ์ด๋ค. ํ์ง๋ง ์ฝ๋๋ฒ ์ด์ค๊ฐ ๋ฐฉ๋ํ ์๋ก ๊ณ ๋ คํ ์ ์ด ๋์ด๋๋ค.
- LLM์ด ํ ๋ฒ์ ๋ฐ์๋ค์ผ ์ ์๋ ์ ๋ณด์ ์์ LLM๋ง๋ค ๋ค๋ฅด๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ ๋ฌํ ์๋ก ๋น์ฉ์ด ๋ ๋ง์ด ๋ถ๊ณผ๋๋ค.
- ์ค์ฌ LLM์ด ๋ฐ์๋ค์ผ ์ ์๋ ์์ด ๋ฌด์ ํ์ด๋๋ผ๋, ์ฐ๋ฆฌ๋ ๊ทธ ๋ฐฉ๋ํ ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด๋ฅผ ๋คํธ์ํฌ๋ฅผ ํตํด ์ ๋ถ ์ ๋ฌํด์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ ๋ถ๋ดํด์ผ ํ ๊ฒ์ด๋ค.
์ด๊ฒ์ ๋น๋จ ์ฝ๋๋ฒ ์ด์ค๋ง์ ๋ฌธ์ ๋ ์๋๋ค. LLM์ ํตํด ๋ฐฉ๋ํ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌ์ํค๊ธฐ ์ํด์๋ ๋ฐ๋์ ํด๊ฒฐํด์ผ ํ๋ ๋ฌธ์ ์ด๋ค.
RAG์ ํ์์ฑ๊ณผ ํ๊ณ
์ฌ์ง: RAG์ ์ ์ฐจ
๋ฐฉ๋ํ ์ง์์ LLM์๊ฒ ์๋ ค์ฃผ๋ ๋ฐฉ๋ฒ ์ค ํ๋๋ก RAG(Retrieval-Augmented Generation)๊ฐ ์๋ค.
RAG๋ฅผ ๊ตฌํํ๋ ์๋จ ์ค ํ๋๋ก๋ semantic search๊ฐ ์๋ค. ์ฝ๊ฒ ๋งํ์๋ฉด ์ ์ฌ๋ ๊ฒ์์ ํตํ ์ง์ ์ ํ์ด๋ค. ์๋ต์ ์์ฑํ๊ธฐ ์ ์ ์ง์ ๋ฒ ์ด์ค์์ โ์ง๋ฌธ๊ณผ ๊ด๋ จ๋์์ ํ๋ฅ ์ด ๋์ ์ ๋ณด๋ค๋ง ์ฟผ๋ฆฌโํ์ฌ LLM์๊ฒ ์ ๋ฌํ๋ค. ์ง๋ฌธ๋ง๋ค ํ์ํ ์ง์๋ง์ ์ถ๋ ค์ ๋ต๋ณ์ ๋ฐ์ํ๋ ๊ฒ์ด๋ค. ํ์ง๋ง, ๋ฐ์ดํฐ๋ฒ ์ด์คํ๋ฅผ ์๋ฌด๋ฆฌ ์ ํ๋๋ผ๋, ์ํ๋ ์ง์์ด ์ ๋๋ก ์กฐํ๋์ง ์๋๋ค๋ฉด ๊ฒฐ๊ตญ ๋ต๋ณ์ ํ์ง์ด ๋จ์ด์ง ๊ฒ์ด๋ค.
์ฆ, RAG ์์คํ ์ ๊ตฌ์ถํ์ฌ LLM์ ์๋ต ํ์ง์ ๋์ผ ์ ์์ง๋ง, ์ง์์ ์ ์ ํ๊ฒ ์ ๊ณตํด์ผ ํ๋ ๊ฒ์ ๋ณ์น ์๋๋ค.
RAG ๋ฐฉ๋ฒ๋ก ์ ์ง๊ธ๋ ์๋กญ๊ฒ ์ฐ๊ตฌ๋๊ณ ์๋ค.
๊ฐ์ค
์ฝ๋๋ฒ ์ด์ค๋ฅผ (LLM์ด ํ์ฉํ๋ ์ ์์) ํต์งธ๋ก ์ ๋ฌํ ์ ์๋ค๋ฉด, ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด์ ๋ํ ์ ์๋ฏธํ RAG๋ฅผ ๋น๊ต์ ์ฝ๊ฒ ์ฑ์ทจํ ์ ์์ ๊ฒ์ด๋ค.
์ด๋ฌํ RAG์ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ด๋ค.
- RAG๋ฅผ ๊ตฌํํ๊ธฐ ์ํด โ๊ฒ์ ์์คํ โ์ ๋ฐ๋์ ๊ตฌํํ์ง ์์๋ ๋๋ค.
- ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด์ ๋ํ ๋ฌธ๋งฅ์ ํ๋ณดํ ์ ์์ด, ์ง๋ฌธ์๊ฐ ๊ณ ๋ คํ์ง ๋ชปํ ๋ถ๋ถ์ ๋ํด์๋ LLM์ด ํ์ ํด์ค ์ ์๋ค.
ํด๊ฒฐํด์ผ ํ๋ ๋ถ๋ถ์ ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
- ์ฝ๋๋ฒ ์ด์ค๋ฅผ โ์์ถ'ํด์ผ ํ๋ค.
- ๋ฌด์์ค ์์ถ์ ์ฌ์ค์ ๋ถ๊ฐ๋ฅํ๊ธฐ์, ์ ๋ณด ์์ค์ ๊ฐ์ํ๊ณ ์์ถ์ ์๋ํด์ผ ํ๋ค.
- ์์ถ ๋ฐฉ๋ฒ์ ์ผ๋ฐํ๊ฐ ๊ฐ๋ฅํด์ผ ํ๋ค.
๊ฐ์ค ๊ฒ์ฆ
๊ฒ์ฆ ๋ฐฉ๋ฒ
์ฝ๋๋ฒ ์ด์ค ์ ์ฒด๋ฅผ LLM์ RAGํ๊ธฐ ์ํ ์์ถ ๋ฐฉ๋ฒ์ผ๋ก์จ ๋ฒ๋ค๋ง์ ์ฌ์ฉํ๊ณ ์ ํ๋ค.
๋ง์ ํ์ผ์ ๋ดํฌํ๋ TypeScript ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ฒ๋ค๋ง์ ํตํด 1๊ฐ์ JavaScript ํ์ผ๋ก ์์ถํ ํ LLM์๊ฒ ์ ๋ฌํ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ , LLM์ด ์ฝ๋๋ฒ ์ด์ค์ ๊ด๋ จ๋ ์ง๋ฌธ์ ์ผ๋ง๋ ์ ํํ๊ฒ ๋ต๋ณํ ์ ์๋์ง ํ์ธํ ๊ฒ์ด๋ค.
๋ฒ๋ค๋ง์ด๋?
TypeScript/JavaScript ์ธ์ด ์ง์์์์ โ๋ฒ๋ค๋งโ(bundle, bundling)์ ์ฝ๋๋ฒ ์ด์ค ์์ ์์ฑ๋์ด ์๋ ์ฌ๋ฌ ์์ค ํ์ผ๋ค์ ๋จ ๋ช ๊ฐ์ ์์ค ํ์ผ๋ก ์ฎ๋ ํ์๋ฅผ ๋ปํ๋ค.
๋ฒ๋ค๋ง์ ํน์ง:
- ์ฃผ์, Dead Code, ํ ์คํธ ์ฝ๋ ๋ฑ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๊ด๊ณ์๋ ๊ฒ๋ค์ ์ ์ธ๋ ์ฝ๋๊ฐ ๋์ถ๋๋ค. ๊ทธ๋ผ์๋ ๋์์ ๋์ผ์ฑ์ด ๋ณด์ฅ๋๋ค.
- ๋ฐฉ๋ํ ์์กด์ฑ ํจํค์ง๋ค(์: node_modules)์ ์ ๋ถ ๋ชจ์ ํ ํ์ผ์ ํฌํจ์ํจ๋ค.
- Syntactic sugar๋ฅผ ์ ๊ทน ํ์ฉํ์ฌ ์ฝ๋๋ฅผ ์งง๊ฒ ์ค์ธ๋ค.
ํ ์คํธ ์ค๊ณ
๋ฒ๋ค๋ง์ ์ํด ์ฌ์ฉํ ์ค์ 6์ ์๋์ ๊ฐ๋ค.
const projectRoot = path.resolve(process.cwd(), "..", "..");
const commonBuildOptions = {
entryPoints: [
{
in: `${projectRoot}/apps/server/src/main.ts`,
out: "index"
}
],
tsconfig: `${projectRoot}/apps/server/tsconfig.json`,
format: "esm",
platform: "node",
target: "node19",
outExtension: { ".js": ".mjs" },
legalComments: "none",
banner: {
/** https://github.com/evanw/esbuild/issues/1921#issuecomment-1152991694 */
js:
"import{createRequire}from'module';const require=createRequire(import.meta.url);" +
"import{fileURLToPath}from'node:url';import{dirname as __pathDirname}from'node:path';const __filename=fileURLToPath(import.meta.url);const __dirname=__pathDirname(__filename);"
},
charset: "utf8",
plugins: [
esbuildDecorators({
tsconfig: `${projectRoot}/apps/server/tsconfig.json`
}),
esbuildProgressPulgin()
]
} satisfies esbuild.BuildOptions;
await esbuild.build({
...commonBuildOptions,
outdir: `${projectRoot}/apps/server/dist/bundle-minify-nokeepnames-package-external`,
bundle: true,
minify: true,
keepNames: false
external: [
"@fastify/aws-lambda",
"@fastify/cookie",
"@fastify/helmet",
"@nestjs/axios",
"@nestjs/common",
"@nestjs/config",
"@nestjs/core",
"@nestjs/jwt",
"@nestjs/passport",
"@nestjs/platform-fastify",
"@nestjs/typeorm",
"aws-lambda",
"axios",
"class-transformer",
"class-validator",
"fastify",
"joi",
"jsonwebtoken",
"lodash",
"passport",
"passport-jwt",
"pg",
"reflect-metadata",
"rxjs",
"typeorm",
"uuid"
],
} satisfies esbuild.BuildOptions);
์ธ๋ถ ํจํค์ง๋ค์ ๋ฒ๋ค๋์ง ์๋๋ก ํ๊ณ , ์์ค์ฝ๋ ๋ด๋ถ ์ฝ๋๋ง ๋ฒ๋ค๋๋๋ก ์ค์ ํ์๋ค.
ํ ์คํธ ํ๊ฒฝ:
- ํ ์คํธ ๋์ ์ฝ๋๋ฒ ์ด์ค: TypeScript๋ก ์์ฑ๋ Node.js ๋ฐํ์์ฉ ์น ์๋ฒ7
- ๋ฒ๋ค๋ง ์๋จ: esbuild๋ก minified bundle 1ํ ์งํ
- LLM: OpenAI o3-mini ๋ชจ๋ธ 8
๋ฒ๋ค๋ง ์ (์๋ณธ ์ฝ๋๋ฒ ์ด์ค)
- ์ฝ๋ ์ค: ์ฝ 15,000์ฌ์ค์ TypeScript
- ํ์ผ ๊ฐ์: ์ฝ 300์ฌ๊ฐ
- ์์ค ์ฝ๋ ํฌ๊ธฐ: ์ฝ 2MB
- ์ธ๋ถ ํจํค์ง๋ค์ ํฌํจํ ์์ค ์ฝ๋ ํฌ๊ธฐ: ์ฝ 1GB 9
๋ฒ๋ค๋ง ํ (LLM์๊ฒ ์ ๋ฌํ ๋ด์ฉ)
์ฌ์ง: ์ฝ๋๋ฒ ์ด์ค ํ์ผ ์ ์ฒด๋ฅผ JavaScript ํ์ผ 1๊ฐ๋ก ์์ถํ ๊ฒฐ๊ณผ๋ฌผ
- ์ผ์ชฝ ์ฌ์ง: ํ ํฐ ๊ฐ์ ๊ณ์ฐ ๊ฒฐ๊ณผ
- ์ค๋ฅธ์ชฝ ์ฌ์ง: ํ์ผ ์ ๋ณด
๋ฒ๋ค๋ง ํ ์ฝ๋๋ฒ ์ด์ค๋ ๋ค์๊ณผ ๊ฐ์ด ์์ถ๋์๋ค.
- ๋ฌธ์์: 239,143๊ฐ
- ํ ํฐ ๊ฐ์: ์ฝ 76,706๊ฐ
- ํ์ผ ํฌ๊ธฐ: 248KB
- ํ์ผ ๊ฐ์: 1๊ฐ
ํ ์คํธ 1: ChatGPT๋ฅผ ํตํ API ๋ฌธ์ ์์ฑ
์ฝ๋๋ฒ ์ด์ค๋ฅผ ์์ถํ ํ์ผ 1๊ฐ๋ง ์์ด๋, ChatGPT๊ฐ Swagger API ๋ฌธ์๋ฅผ ์์ฑํ ์ ์์๊น?
์ค์จ๊ฑฐ(Swagger)๋ ๊ฐ๋ฐ์๊ฐ REST ์น ์๋น์ค๋ฅผ ์ค๊ณ, ๋น๋, ๋ฌธ์ํ, ์๋นํ๋ ์ผ์ ๋์์ฃผ๋
์คํ ์์ค ์ํํธ์จ์ด ํ๋ ์์ํฌ์ด๋ค.
ํ ์คํธ ์ ์ฐจ
- ๋ฒ๋ค ์์ฑ
- ์์ถ๋ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์๋ ํ๋กฌํํธ ์์ ํ ์คํธ๋ก ์ฒจ๋ถ
- ChatGPT์ ์ ๋ฌ
ํ๋กฌํํธ
Rules:
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF RFC 2119 (https://datatracker.ietf.org/doc/html/rfc2119).
Context:
- [index.mjs] is a bundled JavaScript code of a TypeScript codebase.
- [index.mjs] was generated by esbuild to reduce size and remove unnecessary contents.
- [index.mjs] keeps every business logic that original codebases implements.
Request:
- Create a OpenAPI Specification 3.0 content based on [filename]. And, response the specification's content only.
Requirements:
- The result MUST be in JSON format.
- The result MUST include every HTTP API and it's HTTP Method as path information.
- The result SHOULD include security, schema, response information for each API.
- The result MAY include tag information for each API.
`package.json`'s content:
(์ฝ๋๋ฒ ์ด์ค์์ ์ฐ์ธ ์์กด์ฑ ๋ชฉ๋ก)
`index.mjs`'s content:
(๋ฒ๋ค๋ ์ฝ๋ ๋ด์ฉ)
Response:
ํ ์คํธ 1 ๊ฒฐ๊ณผ: ChatGPT๋ฅผ ํตํ API ๋ฌธ์ ์์ฑ
๋๋ถ๋ถ์ ์๋์์ 21๊ฐ ์๋ํฌ์ธํธ ์ค 19๊ฐ ์ด์์ ์๋ํฌ์ธํธ๋ฅผ ์ ํํ๊ฒ ๋ฌธ์ํํ๋ ๋ฐ ์ฑ๊ณตํ๋ค. ์๋ํฌ์ธํธ๊ฐ ํฌํจ๋ API ๋ฌธ์๋ YAML ํ์ ์ค๋ฅ ์์ด ์์ฑ๋์์ผ๋ฉฐ, URL, Method ์ ๋ณด๊ฐ ์ ํํ๊ฒ ๊ธฐ์ฌ๋์๋ค.
์ฌ์ง: ChatGPT๊ฐ ์์ฑํ Swagger API ๋ฌธ์๋ฅผ https://editor.swagger.io์์ ํ์ธํ ๋ชจ์ต
๋์กฐ๊ตฐ๊ณผ์ ๋น๊ต
ChatGPT๋ฅผ ํตํด ์์ฑํ API ๋ฌธ์๊ฐ ์ผ๋ง๋ ์ฌ์ค์ ๊ฐ๊น์ด์ง ํ์ธํ๊ธฐ ์ํด, ์น ํ๋ ์์ํฌ์์ ์์ฒด์ ์ผ๋ก ์์ฑํ Swagger ๋ด์ฉ๊ณผ ๋น๊ตํ์๋ค.
๋์กฐ๊ตฐ
์น ํ๋ ์์ํฌ์์ ์์ฒด์ ์ผ๋ก ์์ฑํ Swagger ํ์ผ ํ์ธํ๊ธฐ
์น ํ๋ ์์ํฌ์์ ์์ฒด์ ์ผ๋ก ์์ฑํ Swagger ํ์ผ ๋ค์ด๋ก๋ (yaml)
openapi: 3.0.0
paths:
/:
get:
operationId: AppController_root
parameters: []
responses:
'200':
description: ''
tags:
- App
/ads.txt:
get:
operationId: AppController_adsTxt
parameters: []
responses:
'200':
description: ''
tags:
- App
/auth/access-token:
get:
operationId: AccessTokenController_getAccessToken
parameters: []
responses:
'200':
description: ''
tags:
- AccessToken
/auth/logout:
post:
operationId: LocalJwtController_logout
parameters: []
responses:
'201':
description: ''
tags:
- LocalJwt
get:
operationId: LocalJwtController_logoutGet
parameters: []
responses:
'200':
description: ''
tags:
- LocalJwt
/auth/google-oauth/{web}:
get:
operationId: GoogleOAuthController_authUserWithGoogleOauthCode
parameters:
- name: code
required: true
in: query
schema:
type: string
- name: web
required: true
in: path
schema:
type: string
responses:
'200':
description: ''
tags:
- GoogleOAuth
/temp-signup:
post:
operationId: TempSignupController_temporarySignUpUser
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TemporarySignUpDto'
responses:
'201':
description: ''
tags:
- TempSignup
/frontend-error:
post:
operationId: FrontendErrorController_insert
parameters: []
responses:
'201':
description: ''
tags:
- FrontendError
/land-comments:
post:
operationId: UserLandCommentController_registerComment
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Function'
responses:
'201':
description: ''
tags:
- UserLandComment
/land-events:
get:
operationId: LandEventController_getLandEvents
parameters: []
responses:
'200':
description: ''
tags:
- LandEvent
/profile/me:
get:
operationId: PublicProfileController_getProfile
parameters: []
responses:
'200':
description: ''
tags:
- PublicProfile
patch:
operationId: PublicProfileController_updateUserById
parameters: []
responses:
'200':
description: ''
tags:
- PublicProfile
/profile/others:
get:
operationId: PublicProfileController_getOthersProfiles
parameters: []
responses:
'200':
description: ''
tags:
- PublicProfile
/profile/complete-signup:
patch:
operationId: PublicProfileController_completeSignup
parameters: []
responses:
'200':
description: ''
tags:
- PublicProfile
/profile:
delete:
operationId: PublicProfileController_terminateUser
parameters: []
responses:
'200':
description: ''
tags:
- PublicProfile
/user-interaction-web:
post:
operationId: UserInteractionWebController_makeUserInteractionAndGetWebMessageResponse
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserInteractionDto'
responses:
'201':
description: ''
tags:
- UserInteractionWeb
/dice-toss:
post:
operationId: DiceTossController_tossDiceAndGetWebMessageResponse
parameters: []
responses:
'201':
description: ''
tags:
- DiceToss
/recent-skill-logs:
get:
operationId: RecentSkillLogsController_getRecentSkillLogsWeb
parameters:
- name: limit
required: true
in: query
schema:
type: number
responses:
'200':
description: ''
tags:
- RecentSkillLogs
/scenarios/d1/map:
get:
operationId: D1Controller_getAliases
parameters: []
responses:
'200':
description: ''
tags:
- D1
/health/detail:
get:
operationId: HealthController_readiness
parameters: []
responses:
'200':
description: ''
tags:
- Health
/health:
get:
operationId: HealthController_simple
parameters: []
responses:
'200':
description: ''
tags:
- Health
info:
title: Cats example
description: The cats API description
version: '1.0'
contact: {}
tags:
- name: cats
description: ''
servers: []
components:
schemas:
TemporarySignUpDto:
type: object
properties: {}
Function:
type: object
properties: {}
UserInteractionDto:
type: object
properties: {}
o3-mini Generation
ChatGPT๊ฐ ์์ฑํ Swagger ํ์ผ ํ์ธํ๊ธฐ
ChatGPT๊ฐ ์์ฑํ Swagger ํ์ผ ๋ค์ด๋ก๋ (yaml)
openapi: "3.0.0"
info:
title: "Server API"
version: "1.0.0"
servers:
- url: "https://example.com"
description: "Primary server (update with actual URL)"
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
cookieAuth:
type: apiKey
in: cookie
name: refreshToken
schemas:
ContactResponse:
type: string
example: "contact: lifegame2021team@gmail.com"
AdsTxtResponse:
type: string
example: "ADS TXT content from configuration"
TokenResponse:
type: object
properties:
accessToken:
type: string
example: "eyJhbGciOiJIUzI1NiIsInR..."
GenericResponse:
type: object
additionalProperties: true
ErrorResponse:
type: object
properties:
message:
type: string
paths:
/:
get:
tags:
- Root
summary: "Get root contact info"
responses:
"200":
description: "Contact information"
content:
application/json:
schema:
$ref: "#/components/schemas/ContactResponse"
/ads.txt:
get:
tags:
- Root
summary: "Get ads.txt content"
responses:
"200":
description: "ADS TXT content"
content:
text/plain:
schema:
$ref: "#/components/schemas/AdsTxtResponse"
/auth/access-token:
get:
tags:
- Auth
summary: "Obtain a new access token using a valid refresh token"
security:
- cookieAuth: []
responses:
"200":
description: "Access token generated successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/TokenResponse"
"401":
description: "Unauthorized โ invalid or missing credentials"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/auth/logout:
post:
tags:
- Auth
summary: "Logout user (POST)"
security:
- cookieAuth: []
responses:
"200":
description: "User successfully logged out"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
get:
tags:
- Auth
summary: "Logout user (GET)"
security:
- cookieAuth: []
responses:
"200":
description: "User successfully logged out"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
/auth/google-oauth/{web}:
get:
tags:
- Auth
summary: "Authenticate user with Google OAuth"
parameters:
- in: path
name: web
required: true
schema:
type: string
description: "A dynamic segment representing the web redirect path"
- in: query
name: code
required: true
schema:
type: string
description: "The OAuth authorization code returned by Google"
responses:
"200":
description: "Google OAuth callback response"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"400":
description: "Bad Request"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/temp-signup:
post:
tags:
- Temp Signup
summary: "Temporarily sign up a new user with hCaptcha verification"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
hCaptchaSuccessToken:
type: string
username:
type: string
countryCode3:
type: string
required:
- hCaptchaSuccessToken
- username
- countryCode3
responses:
"200":
description: "Temporary signup successful"
content:
application/json:
schema:
type: boolean
example: true
"400":
description: "Bad Request โ invalid hCaptcha token or missing fields"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/land-events:
get:
tags:
- Land Events
summary: "Retrieve a list of recent land events"
parameters:
- in: header
name: timezone
schema:
type: string
required: false
description: "Timezone identifier (e.g., 'Asia/Seoul')"
security:
- bearerAuth: []
responses:
"200":
description: "A list of land event summaries"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/GenericResponse"
"401":
description: "Unauthorized"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/dice-toss:
post:
tags:
- Dice Toss
summary: "Toss dice and receive a gaming response message"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
userId:
type: string
required:
- userId
security:
- bearerAuth: []
responses:
"200":
description: "Dice toss result with game data"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"400":
description: "Bad Request โ invalid input"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/profile/me:
get:
tags:
- Profile
summary: "Retrieve the authenticated user's profile information"
security:
- bearerAuth: []
responses:
"200":
description: "User profile data"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"401":
description: "Unauthorized"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
patch:
tags:
- Profile
summary: "Update the authenticated user's profile"
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
countryCode3:
type: string
required:
- username
- countryCode3
responses:
"200":
description: "Profile updated successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"400":
description: "Bad Request โ validation errors"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/profile/others:
get:
tags:
- Profile
summary: "Retrieve profiles of other users"
security:
- bearerAuth: []
parameters:
- in: query
name: limit
required: false
schema:
type: integer
description: "Maximum number of profiles to return"
- in: query
name: page
required: false
schema:
type: integer
description: "Page number for pagination"
- in: query
name: updatedAfter
required: false
schema:
type: string
format: date-time
description: "Filter profiles updated after this datetime"
responses:
"200":
description: "List of other user profiles"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/GenericResponse"
"401":
description: "Unauthorized"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/profile/complete-signup:
post:
tags:
- Profile
summary: "Complete the authenticated user's signup process"
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
countryCode3:
type: string
username:
type: string
required:
- countryCode3
- username
responses:
"200":
description: "Signup completed successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"400":
description: "Bad Request"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/profile:
delete:
tags:
- Profile
summary: "Terminate (delete) the authenticated user's account"
security:
- bearerAuth: []
responses:
"200":
description: "User account terminated successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"401":
description: "Unauthorized"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/recent-skill-logs:
get:
tags:
- Skill Logs
summary: "Retrieve recent skill logs for the authenticated user"
security:
- bearerAuth: []
parameters:
- in: query
name: limit
required: false
schema:
type: integer
description: "The maximum number of logs to retrieve"
responses:
"200":
description: "A list of recent skill logs"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/GenericResponse"
"401":
description: "Unauthorized"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/land-comments:
post:
tags:
- Land Comments
summary: "Register a comment on a land (game event)"
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
userId:
type: string
comment:
type: string
required:
- userId
- comment
responses:
"200":
description: "Comment registered successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"400":
description: "Bad Request"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/scenarios/d1/map:
get:
tags:
- Scenarios
summary: "Retrieve skill group aliases for scenario D1"
security:
- bearerAuth: []
responses:
"200":
description: "A mapping of skill groups and their aliases"
content:
application/json:
schema:
type: object
additionalProperties: true
/user-interaction-web:
post:
tags:
- User Interaction
summary: "Perform a user interaction call to trigger a skill"
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
callingSkillRoute:
type: string
callingSkillParam:
type: object
required:
- callingSkillRoute
responses:
"200":
description: "Response from the user interaction call"
content:
application/json:
schema:
$ref: "#/components/schemas/GenericResponse"
"400":
description: "Bad Request"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/health/detail:
get:
tags:
- Health
summary: "Detailed health check"
responses:
"200":
description: "Detailed health status"
content:
application/json:
schema:
type: string
example: "OK"
/health:
get:
tags:
- Health
summary: "Simple health check"
responses:
"200":
description: "Simple health status"
content:
application/json:
schema:
type: string
example: "m"
security:
- bearerAuth: []
ํ ์คํธ 2: ChatGPT๋ฅผ ํตํ ๋งค๋ด์ผ ์์ฑ
์ฝ๋๋ฒ ์ด์ค๋ฅผ ์์ถํ ํ์ผ 1๊ฐ๋ง ์์ด๋, ChatGPT๊ฐ ๋น์ฆ๋์ค ๋ก์ง์ ์ดํดํ๊ณ โ๋งค๋ด์ผโ์ ์์ฑํ ์ ์์๊น?
ํ ์คํธ ์ ์ฐจ
- ํธ์๋ฅผ ์ํด ํ ์คํธ 1์์ ์ค๊ฐ ๋ํ๋ฅผ ๊ทธ๋๋ก ์ ์ง
- ํ๋กฌํํธ ์ ๋ฌ
ํ๋กฌํํธ
Generate manual for 'POST /temp-signup' endpoint.
[for non-coder]
1. ELI5 for teammates who cannot code
2. runtime behavior
3. 'how dose it works' explanation - should include technical details
4. business logics
5. possible edge cases
[for coder]
1. ELI5 for teammates who cannot code
2. runtime behavior
3. 'how dose it works' explanation - should include technical details
3.1. technical detail for framework and libraries
3.2. sequence diagram if possible
4. possible design pattern it implements
5. possible improvements
6. possible edge cases
tone: no emoji, professional tone, literacy style
each in markdown format
one in english, one in korean.
ํ ์คํธ 2 ๊ฒฐ๊ณผ: ChatGPT๋ฅผ ํตํ ๋งค๋ด์ผ ์์ฑ
๋น๊ฐ๋ฐ์/๊ฐ๋ฐ์์ฉ ๋งค๋ด์ผ์ ๋์์ ์ฑ๊ณต์ ์ผ๋ก ์์ฑํ ์ ์์๋ค.
์ฌ์ง: ChatGPT๊ฐ ์์ฑํด๋ธ ์ํ์ค ๋ค์ด์ด๊ทธ๋จ์ ํตํ ์์คํ
์ค๋ช
"๋น๊ฐ๋ฐ์๋ฅผ ์ํ ๋งค๋ด์ผ" ์์ฑ๋ฌผ ํ์ธํ๊ธฐ
POST /temp-signup ์๋ํฌ์ธํธ ๋งค๋ด์ผ (Korean)
๋น๊ฐ๋ฐ์๋ฅผ ์ํ ์ค๋ช
1. ELI5 ์ค๋ช (์ฝ๋๋ฅผ ๋ชจ๋ฅด๋ ํ์์ ์ํ ์ค๋ช )
์ด ์๋ํฌ์ธํธ๋ ์์ ์ฌ์ฉ์ ๊ณ์ ์ ์์ฑํฉ๋๋ค. hCaptcha๋ผ๋ ์ฌ๋์์ ํ์ธํ๋ ์ ์ฐจ(๋น๋ฐ ์ฝ๋๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์)๋ฅผ ๊ฑฐ์ณ์, ์ด๋ฆ, ์ด๋ฉ์ผ, ๊ตญ๊ฐ ์ฝ๋ ๋ฑ์ ์ ๋ณด๋ฅผ ์ ์ถํ๋ฉด ์์๋ก ๊ณ์ ์ด ๋ง๋ค์ด์ง๊ณ , ๊ทธ ๊ณ์ ์ผ๋ก ์๋น์ค๋ฅผ ์ด์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
2. ๋ฐํ์ ๋์
์ฌ์ฉ์๊ฐ ํ์๊ฐ์ ์ ๋ณด๋ฅผ ์ ์กํ๋ฉด ์๋ฒ๋ ๋จผ์ hCaptcha ํ ํฐ์ ๊ฒ์ฌํ์ฌ ์ฌ์ฉ์๊ฐ ๋ก๋ด์ด ์๋๋ผ๋ ๊ฒ์ ํ์ธํฉ๋๋ค. ๊ทธ ํ, ์์ ์ฌ์ฉ์ ๊ณ์ ์ ์์ฑํ๊ณ , ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ์ ๋ณด์ ์ฟ ํค(๋ฆฌํ๋ ์ ํ ํฐ)๋ฅผ ์ค์ ํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก, ํ์๊ฐ์ ์ด ์ฑ๊ณตํ์์ true/false ๊ฐ์ผ๋ก ๋ฐํํฉ๋๋ค.
3. ๋์ ๋ฐฉ์ (๋์ ์์ค์ ์ค๋ช )
์ ๋ ฅ ๊ฒ์ฆ: hCaptcha ํ ํฐ, ์ฌ์ฉ์ ์ด๋ฆ, ์ด๋ฉ์ผ, ๊ตญ๊ฐ ์ฝ๋ ๋ฑ ํ์ ํ๋๊ฐ ํฌํจ๋์ด ์๋์ง ํ์ธํฉ๋๋ค.
์ธ๊ฐ ์ฌ๋ถ ํ์ธ: hCaptcha ํ ํฐ์ ์ธ๋ถ hCaptcha ์๋น์ค์ ์ ์กํ์ฌ ์ฌ๋์ด ๋ง๋์ง ํ์ธํฉ๋๋ค.
๊ณ์ ์์ฑ: ๊ฒ์ฆ์ด ์ฑ๊ณตํ๋ฉด, ์์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค(๋๋ ๋ด๋ถ ์ ์ฅ์)์ ์ ์ฅํฉ๋๋ค.
์ฟ ํค ์ค์ : ์์ฑ๋ ๋ฆฌํ๋ ์ ํ ํฐ์ HTTP ์ ์ฉ ์ฟ ํค๋ก ์ค์ ํ์ฌ, ์ดํ ์ฌ์ฉ์๊ฐ ๊ณ์ ์ธ์๋ ์ ์๋๋ก ํฉ๋๋ค.
์๋ต: ํ์๊ฐ์ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ์๋ตํฉ๋๋ค.
4. ๋น์ฆ๋์ค ๋ก์ง
์ฌ์ฉ์ ๊ฒ์ฆ: hCaptcha๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๊ณผ ์๋ ๊ฐ์ ์ ๋ฐฉ์งํฉ๋๋ค.
์์ ๊ณ์ ์์ฑ: ์ฌ์ฉ์๊ฐ ์ฆ์ ์๋น์ค๋ฅผ ์ด์ฉํ ์ ์๋๋ก ์์ ๊ณ์ ์ ๋ง๋ค๋, ์ดํ์ ์ ์ ๊ฐ์ ์ ์ฐจ๊ฐ ์ถ๊ฐ๋ ์ ์์ต๋๋ค.
๋ณด์ ๊ด๋ฆฌ: ๋ฆฌํ๋ ์ ํ ํฐ์ ๋ณด์ ์ฟ ํค๋ก ๋ฐ๊ธํ์ฌ ์ธ์ ๋ณด์์ ๊ฐํํฉ๋๋ค.
5. ๊ฐ๋ฅํ ์ฃ์ง ์ผ์ด์ค
์ ํจํ์ง ์์ hCaptcha ํ ํฐ: hCaptcha ํ ํฐ์ด ์๊ฑฐ๋ ์๋ชป๋ ๊ฒฝ์ฐ ํ์๊ฐ์ ์ด ๊ฑฐ๋ถ๋ฉ๋๋ค.
๋ถ์์ ํ ๋ฐ์ดํฐ: ์ฌ์ฉ์ ์ด๋ฆ, ์ด๋ฉ์ผ, ๊ตญ๊ฐ ์ฝ๋ ์ค ํ๋๋ผ๋ ๋น ์ง ๊ฒฝ์ฐ ์คํจํ ์ ์์ต๋๋ค.
์๋ฒ ์ค๋ฅ: ์ผ์์ ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋๋ ๋คํธ์ํฌ ๋ฌธ์ ๋ก ์ธํด ์๊ธฐ์น ๋ชปํ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์ค๋ณต ๊ฐ์ : ์ด๋ฉ์ผ์ด๋ ์ฌ์ฉ์ ์ด๋ฆ์ด ์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ๊ฒฝ์ฐ ์ถ๊ฐ ๊ฒ์ฆ์ด ํ์ํ ์ ์์ต๋๋ค.
"๊ฐ๋ฐ์๋ฅผ ์ํ ๋งค๋ด์ผ" ์์ฑ๋ฌผ ํ์ธํ๊ธฐ
POST /temp-signup ์๋ํฌ์ธํธ ๋งค๋ด์ผ (Korean)
๊ฐ๋ฐ์๋ฅผ ์ํ ์ค๋ช
1. ELI5 ์ค๋ช (์ฝ๋๋ฅผ ๋ชจ๋ฅด๋ ํ์์ ์ํ ์ค๋ช )
ํ์๊ฐ์ ๊ณผ์ ์ ํฐ์ผ ๋ถ์ค์ ๋น์ ํ๋ค๋ฉด, ์ฌ์ฉ์๋ hCaptcha๋ผ๋ ๋น๋ฐ ์ฝ๋๋ฅผ ์ ์ํ์ฌ ๋ก๋ด์ด ์๋์ ์ฆ๋ช ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ถ์ค์์๋ ์์ ํ์ ์นด๋๋ฅผ ๋ฐ๊ธํ๊ณ , ๋์ค์ ํด๋ฝ์ ๋ค์ ๋ฐฉ๋ฌธํ ์ ์๋๋ก ๋ธ๋ ์ด์ฌ๋ฆฟ(์ฟ ํค)์ ์ ๊ณตํฉ๋๋ค.
2. ๋ฐํ์ ๋์
POST ์์ฒญ์ด /temp-signup ๊ฒฝ๋ก๋ก ์ค๋ฉด, ์๋ฒ๋ JSON ํ์์ ํ์ด๋ก๋๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ ๋ ฅ๊ฐ์ด ๊ฒ์ฆ๋๊ณ , ์ธ๋ถ hCaptcha ์๋น์ค์์ hCaptcha ํ ํฐ์ ํ์ธํ ํ, ์์ ์ฌ์ฉ์ ๋ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค. ์ดํ, ๋ณด์ HTTP ์ ์ฉ ์ฟ ํค์ ๋ฆฌํ๋ ์ ํ ํฐ์ ์ค์ ํ๊ณ , ์ต์ข ์ ์ผ๋ก ๊ฐ์ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ Boolean ๊ฐ์ผ๋ก ์๋ตํฉ๋๋ค.
3. ๋์ ๋ฐฉ์ โ ๊ธฐ์ ์ ์ธ๋ถ์ฌํญ
3.1. ํ๋ ์์ํฌ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ด๋ จ ๊ธฐ์ ์ธ๋ถ์ฌํญ
NestJS ํ๋ ์์ํฌ: ์ด ์๋ํฌ์ธํธ๋ NestJS ์ปจํธ๋กค๋ฌ๋ก ๊ตฌํ๋์ด ์์ผ๋ฉฐ, @Controller(), @Post() ๋ฑ ๋ฐ์ฝ๋ ์ดํฐ์ ์์กด์ฑ ์ฃผ์ (@Injectable())์ ์ฌ์ฉํฉ๋๋ค.
hCaptcha ์ฐ๋: @nestjs/axios์ HttpService๋ฅผ ์ฌ์ฉํ์ฌ "https://hcaptcha.com/siteverify" URL์ POST ์์ฒญ์ ๋ณด๋ด hCaptcha ํ ํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํฉ๋๋ค. ํ๊ฒฝ๋ณ์๋ก ๊ด๋ฆฌ๋๋ hCaptcha ๋น๋ฐ ํค(HCAPTCHA_SECRET_KEY)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋: TypeORM(@nestjs/typeorm)์ ํตํด ์์ ์ฌ์ฉ์ ๋ ์ฝ๋๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํฉ๋๋ค.
์ฟ ํค ๊ด๋ฆฌ: @fastify/cookie ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด์ ์ฟ ํค๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์ฟ ํค๋ HTTP ์ ์ฉ, ๋ณด์, ์๋ช ๋ ์ฟ ํค๋ก ์ค์ ๋ฉ๋๋ค.
๋ฐ์ดํฐ ๊ฒ์ฆ: NestJS์ Validation Pipe ๋ฐ ์ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(class-validator ํน์ Joi)๋ฅผ ์ฌ์ฉํด ์ ๋ ฅ ๋ฐ์ดํฐ์ ์ ํจ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
3.2. Sequence Diagram (ํ ์คํธ ๊ธฐ๋ฐ)
sequenceDiagram
participant Client
participant Controller as POST /temp-signup
participant hCaptchaService
participant UserService
participant RefreshTokenService
Client->>Controller: JSON payload {hCaptchaSuccessToken, username, email, countryCode3}
Controller->>hCaptchaService: Validate hCaptcha token
hCaptchaService-->>Controller: Return true/false
alt hCaptcha valid
Controller->>UserService: Create temporary user record
UserService-->>Controller: Return new user object
Controller->>RefreshTokenService: Generate refresh token
RefreshTokenService-->>Controller: Return token
Controller->>Client: Set HTTP-only cookie and return true
else
Controller->>Client: Return error response (signup failed)
end
4. Possible Design Patterns
์๋น์ค ์งํฅ ์ํคํ ์ฒ: ์ธ์ฆ, ์ฌ์ฉ์ ๊ด๋ฆฌ, ํ ํฐ ๊ด๋ฆฌ ๋ฑ ๊ฐ๊ฐ์ ์ฑ ์์ ๊ฐ๋ณ ์๋น์ค๋ก ๋ถ๋ฆฌํฉ๋๋ค.
์์กด์ฑ ์ฃผ์ : NestJS์ ์ฃผ์ ํน์ง์ ํ์ฉํด ๊ฐ ์๋น์ค๊ฐ ๋ค๋ฅธ ์๋น์ค์ ์์กดํ ์ ์๋๋ก ๊ตฌ์ฑํฉ๋๋ค.
ํ์ฌ๋ ํจํด: ์ปจํธ๋กค๋ฌ๋ ์ฌ๋ฌ ๋ด๋ถ ์๋น์ค(hCaptcha, User, Token ์๋น์ค)๋ฅผ ๋จ์ํํ์ฌ ํด๋ผ์ด์ธํธ์ ์ ๊ณตํ๋ ์ญํ ์ ํฉ๋๋ค.
5. Possible Improvements
๊ณ ๋ํ๋ ๊ฒ์ฆ: class-validator ๋๋ Joi์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ๋ ์์ธํ ์์ฒญ ์คํค๋ง ๊ฒ์ฆ์ ์ํ.
์๋ฌ ํธ๋ค๋ง ๊ฐ์ : ํด๋ผ์ด์ธํธ์ ์ข ๋ ๊ตฌ์ฒด์ ์ธ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํ ์ ์๋๋ก ์๋ฌ ํธ๋ค๋ง ๊ตฌ์กฐ๋ฅผ ๊ฐ์ .
์๋ ์ ํ: ์๋ํฌ์ธํธ ๋จ์ฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์๋ ์ ํ(Rate Limiting) ๊ธฐ๋ฅ ๋์ .
๋ก๊น ๋ฐ ๋ชจ๋ํฐ๋ง: ์ธํฐ์ ํฐ๋ฅผ ํตํ ์์ธ ๋ก๊น ์ ์ถ๊ฐํ์ฌ ์ด์ ๋ฐ ๊ฐ์ฌ์ ๋๋น.
์ค๋ณต ์ฒดํฌ: ๊ธฐ์กด ์ฌ์ฉ์์์ ์ค๋ณต ๊ฐ์ ์ฌ๋ถ๋ฅผ ๋ฏธ๋ฆฌ ํ์ธํ์ฌ ๋ถํ์ํ ๋ฐ์ดํฐ ์์ฑ ๋ฐฉ์ง.
6. Possible Edge Cases
์ ํจํ์ง ์๊ฑฐ๋ ๋ง๋ฃ๋ hCaptcha ํ ํฐ: ์ธ๋ถ hCaptcha ์๋น์ค์์ ์ ํจ์ฑ ๊ฒ์ฆ์ ์คํจํ ๊ฒฝ์ฐ.
ํ์ ์ ๋ ฅ ๋๋ฝ: ์ฌ์ฉ์ ์ด๋ฆ, ์ด๋ฉ์ผ ๋๋ ๊ตญ๊ฐ ์ฝ๋์ ๋๋ฝ.
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฅ์ : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ฅ์ ์ ์์ ๊ณ์ ์์ฑ ์คํจ.
์ฟ ํค ๊ตฌ์ฑ ์ค๋ฅ: ์ฟ ํค ์ค์ ์ต์ (HTTP ์ ์ฉ, ๋ณด์ ๋ฑ)์ด ์ ๋๋ก ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ๋ก ์ธํ ๋ณด์ ์ทจ์ฝ์ฑ.
์์ธ ์ฒ๋ฆฌ ๋ฏธํก: ์ธ๋ถ hCaptcha API ์๋ต์์ ๋นํ์ค ์๋ต์ด ์ฌ ๋ ์ฒ๋ฆฌํ ๋ก์ง์ ๋ถ์ฌ.
์ด ํ ์คํธ์์ ๋๋ ๋ํ์ ์ ๋ฌธ์ ์์นด์ด๋ธ์์ผ ๋์๋ค. ChatGPT ๋ํ ๊ธฐ๋ก์์ ํ์ธํด๋ณผ ์ ์๋ค.
ํ๊ณ์
ChatGPT์์ ํ์ฉ์ ๊ดํ ํ๊ณ์
์ฌ์ง: GPT-4.5 ๋ชจ๋ธ์ด ์๋ต์ ๊ฑฐ๋ถํ๋ ๋ชจ์ต.
๋ฒ๋ค๋ JavaScript ํ์ผ์ ChatGPT ๋ํ์ ์ฒจ๋ถํ ๋, โChatGPT ํ์ผ ์ ๋ก๋โ๋ฅผ ํตํด ์ ๋ก๋ํ๋ ๊ฒ๋ณด๋ค, ํ๋กฌํํธ ์์ ํ์ผ ๋ด์ฉ์ ์ง์ ํฌํจ์ํค๋ ๊ฒ์ด ๋ต๋ณ์ ์ ํ๋๋ฅผ ๊ฑฐ์ ์๋ฒฝํ ์์ค์ผ๋ก ๋์ธ๋ค๋ ์ ์ ๋ฐ๊ฒฌํ๋ค.
๊ธ๋ฒ ํ ์คํธ์์๋ o3-mini ๋ชจ๋ธ์ ์ฌ์ฉํ์๋ค. ํํธ, ๋ค๋ฅธ ๋ชจ๋ธ์ ํตํ ๋ต๋ณ ์์ฑ์ ์๋ํ์ ๋์๋ โ๋ฉ์์ง ๊ธธ์ด ์ ํโ์ ๊ฑธ๋ ค ์๋ต์ ๋ฐ์๋ผ ์ ์์๋ค.
๋ฒ๋ค๋ง์ ๊ดํ ํ๊ณ์
์ฌ์ง: ์์ค ์ฝ๋ ํ์ผ ์์น๋ฅผ ๋ฌป๋ ์ง๋ฌธ์ ์๋ต์ ๊ฑฐ๋ถํ๋ ๋ชจ์ต.
๋ฒ๋ค๋ง์ ํ๊ธฐ ์ํด์๋, ๋ฒ๋ค๋ฌ ๋๊ตฌ ์ฌ์ฉ๋ฒ์ ๊ณต๋ถํด์ผ ํ ๊ฒ์ด๋ค.
์ฝ๋๋ฒ ์ด์ค์ ๋ํ ๋ฒ๋ค๋ง์ ์๋ํ๊ธฐ ์ํด์๋ ๋ฒ๋ค๋ง์ ์คํจํ ๋งํ ๋ฌธ๋ฒ์ ์ค๋ฅ๊ฐ ์์ค์ฝ๋์ ์กด์ฌํด์๋ ์ ๋๋ค.
๋ฒ๋ค๋ง ์ค ์์ค๋๋ ์ ๋ณด๋ LLM์ ์ ๋ฌ๋์ง ์๋๋ค. ๋ณ๋์ RAG๊ฐ ํ์ํ๋ค.
๋ฐ๊ฒฌ
์ ํต์ ์ธ ๋๊ตฌ๋ฅผ ์จ์ RAG๋ฅผ ์ฑ์ทจํ๋ค๋ ์
์ฝ๋๋ฒ ์ด์ค๊ฐ context window์ ํฌํจ๋ ์ ์๊ฒ๋ โ์์ค ์์ถโํ์ฌ๋ ๋์๊ณผ ๊ด๋ จ๋ ์ง์์ ์ ๋ฌํ ์ ์์์ ํ์ธํ์๋ค. ๋ํ, ์ด๋ฏธ ์กด์ฌํ๋ ๋ฒ๋ค๋ง ๋๊ตฌ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ์์์ ์๋ฏธ๊ฐ ์๋ค.
๋ค๋ฅธ ์ธ์ด๋ก ์์ฑ๋ ์ฝ๋๋ฒ ์ด์ค์ ๋ํ ์ผ๋ฐํ ๊ฐ๋ฅ์ฑ
TypeScript/JavaScript ์ฝ๋ ์ง์์์๋ ์ค๋ซ๋์ ๋ฒ๋ค๋ง์ ๋ํ ์ฐ๊ตฌ๊ฐ ์ด๋ฃจ์ด์ง ์ํฉ์ด๋ผ, ๋ฒ๋ค๋ง ์์คํ ์ ๊ตฌ์ฑํ๋ ๋๋๋ ๋น๊ต์ ๋ฎ๋ค.
ํ์ง๋ง ๋ค๋ฅธ ์ธ์ด๋ ์ํฉ์ด ๋ค๋ฅด๋ค. ๋จ์ ์ธ ์๋ก์จ ์ปดํ์ผ ์ธ์ด(C++ ๋ฑ)๋ก ์์ฑ๋๋ ์ฝ๋๋ฒ ์ด์ค์ ๋ํด์๋ ์ด๋ฌํ ๋ฒ๋ค๋ง์ด ๊ฐ๋ฅํ์ง ํ์ธ์ด ํ์ํ ๊ฒ์ด๋ค.
๋ค๋ง, LLM์ด .exe ํ์ผ์ ์ดํดํ๊ณ , ํ์ด์ฌ ํฌํ ํ๋ ๋ฐ ์ฑ๊ณตํ๋ค๋ฉฐ ์ฃผ์ฅํ๋ ์ฌ๋ก๊ฐ ์กด์ฌํ๋ค10. ๋ฐ๋ผ์, ์ฝ๋๋ฒ ์ด์ค์ ๋ํ ์ ์ ํ ์์ถ์ด ์ด๋ฃจ์ด์ง๋ค๋ฉด LLM์ด ์ดํดํ๋ ๋ฐ์๋ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ๋ณผ ์ ์์ ๊ฒ์ด๋ค.
Semantic search์์ ์๋์ง
semantic search์ ๋ฒ๋ค๋ง๋ ์ฝ๋๋ฒ ์ด์ค ์ ๋ณด๋ฅผ ๋์์ RAG์ ํ์ฉํ๋ค๋ฉด, ์๋ก ์ํธ๋ณด์์ ์ผ๋ก ์์ฉํ์ฌ ์์นํจ๊ณผ๋ฅผ ๋ณผ ์ ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค.
ํ์ฌ ์์ฉ ์ฝ๋ฉ AI ์์ด์ ํธ๋ค์ ์ฌ๋ฌ ํ์ผ๋ก ๊ตฌ์ฑ๋ ์ฝ๋๋ฒ ์ด์ค์ ์ ์ฒด์ ์ธ ๋งฅ๋ฝ์ ์จ์ ํ ์ดํดํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ๋ค๋ฐ์ฌ์ด๋ค. ์๋ฅผ ๋ค์ด, โ์ด์์ ๋ก๊ทธ์ธ ๋ก๊ทธ๊ฐ โISMS ๋ก๊ทธ ํ ์ด๋ธโ์ ๊ธฐ๋ก๋๋๋ก ๊ธฐ๋ฅ์ ์ถ๊ฐํ์ฌ ์ฃผ์ญ์์คโ๋ผ๋ ์์ฒญ์ด ์ฃผ์ด์ง๋ฉด, AI ์์ด์ ํธ๋ โ์ด์์ ๋ก๊ทธ์ธโ ๊ธฐ๋ฅ๊ณผ โISMS ๋ก๊ทธ ํ ์ด๋ธโ๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ์์ค ์ฝ๋๋ฅผ ํ์ํ๋ ๊ณผ์ ์์ semantic search(์๋ฏธ ๊ธฐ๋ฐ ๊ฒ์)๋ฅผ ์ํํ๋ค.
Semantic search ๊ธฐ๋ฒ์ ์ ๋ ฅ๋ ํค์๋์ ๊ฐ์ฅ ์ ์ฌํ ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์๋ณํ๋ ๋ฐ ๊ธฐ์ฌํ๋, ๊ฒ์ ๋์์ ํฌํจ๋์ง ์์ ํ์ผ์ ์์ด์ ํธ๊ฐ ์ธ์งํ์ง ๋ชปํ ์ํ์ด ์๋ค.
ํํธ, ๋ฒ๋ค๋ง์ ํตํด ์์ถ๋ ์ฝ๋๋ฒ ์ด์ค๋ฅผ LLM์๊ฒ ์ฌ์ ์ ์ ๊ณตํ๊ณ , ์ฌ๊ธฐ์ semantic search๋ฅผ ๊ฒฐํฉํ๋ค๋ฉด, ์ฝ๋๋ฒ ์ด์ค์ ์ ๋ฐ์ ์ธ ๋งฅ๋ฝ์ ๋ณด๋ค ์ถฉ์คํ ์ดํดํจ๊ณผ ๋์์ ๋ฐ์ดํฐ๋ฒ ์ด์คํ๋ ์๋ณธ ์์ค ์ฝ๋์ ํจ๊ณผ์ ์ผ๋ก ์ ๊ทผํ ์ ์์ด ์ ๋ฆฌํ ์ํฉ์ ๋ง๋ จํ ์ ์๋ค.
๊ฒฐ๋ก
LLM์ ๋ํด ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด๋ฅผ RAGํ๊ธฐ ์ํด, ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด๋ฅผ ํ ํ์ผ๋ก ์์ถํ์ฌ LLM์๊ฒ ์ ๋ฌํ๋ ํ ์คํธ๋ฅผ ์ค๊ณํ๋ค.
ํ์กดํ๋ ๋ฒ๋ค๋ง ํด์ ๊ทธ๋๋ก ์ฌ์ฉํ์ฌ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์์ถํ์์ ๋, LLM์ ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด์ ๋ํ API ๋ฌธ์ํ๋ฅผ ์งํํ๊ฑฐ๋, ํน์ API์ ๋ํ ์์ธํ ๋งค๋ด์ผ์ ์์ฑํ ์ ์์๋ค.
์ฝ๋๋ฒ ์ด์ค ์์ถ์ ์งํํ๋ฉฐ ๋ฐ์ํ๋ ์ ๋ณด ์์ค์ ๋ํด์๋ ์๋ณธ ํ์ผ์ ๋ํ ์ถ๊ฐ์ ์ธ Semantic search๋ฅผ ํตํด ๋ณด์ํ ์ ์์ ๊ฒ์ผ๋ก ์ ๋งํ๋ค.
GeekNews์์ ๋๊ธ์ ๋จ๊ธฐ์ค ์ ์์ต๋๋ค.
Footnotes
-
์ ์ ๋ถ์์ ์ํ๋ ์: ํธ์ถ ๊ทธ๋ํ ์์ฑ์ ํตํ ์ ์ด ํ๋ฆ ํ์ & ์ฐ์ ์์ ํ์ธ, (์น ์๋ฒ์ ๊ฒฝ์ฐ) โ์ปจํธ๋กค๋ฌโ ์ฝ๋๋ฅผ ์์์ผ๋ก ๋ถ์ ์งํ, ์ฝ๋๋ฒ ์ด์ค์ ์ด๋ฏธ ๋์ ๋ ์ํคํ ์ณ ํจํด์ด ๋ฌด์์ธ์ง ํ์ ํ ํ, ์ฐ์ญ์ ์ถ๋ก ์ ํตํ ๋ถ์ ๋ฐฉ๋ฒ ์๋ฆฝ. Wikipedia: Call graph โฉ
-
๋์ ๋ถ์์ ์ํ๋ ์: ํตํฉ ํ ์คํธ ๊ณผ์ ์์ ํธ์ถ๋๋ ์ฝ๋์ ๊ทธ๋ ์ง ์์ ์ฝ๋๋ฅผ ๋ถ๋ฅํ์ฌ ๊ฐ ์ฝ๋๊ฐ ๊ด๊ณ๋ฅผ ํ์ . Wikipedia: Runtime verification โฉ
-
LLM ๋ชจ๋ธ์ ์ง์์ ๋น ๋ฅด๊ฒ ์ถ๊ฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก Retrieval-augmented generation(RAG)๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ค. Wikipedia: Retrieval-augmented generation โฉ
-
์๋ฏธ๋ก ์ ๊ฒ์ ๊ธฐ๋ฒ. Wikipedia: Semantic_search โฉ
-
OpenAI: "How does the new file uploads capability work? " - ChatGPT์ ํ์ผ ์ ๋ก๋(File Upload)๋ ์ ์ฒ๋ฆฌ, ๋ณํ, ์ถ์ถ์ ๊ฑฐ์ณ ์ ๋ณด๋ฅผ ์ ์ ํ๋ค. ์๋ฅผ ๋ค์ด Word ๋ฌธ์๋ฅผ ์ฝ์ ๋์๋ ์๊ณ ๋ฆฌ์ฆ์ ์ผ๋ก ๋ฏธ๋ฆฌ ํด์ํ๊ณ ๋ฌธ์์ ์ ๋ชฉ/๋ถ์ ๋ชฉ๋ค์ ์ถ์ถํ์ฌ ๋ฉํ๋ฐ์ดํฐ๋ก ํ์ฉํ๋ค. โฉ
-
์ด์ ์ ์์ฑํ ์ ์ด ์๋ esbuild ๋น๋ ์ค์ ์ ์กฐ๊ธ ์์ ํ์ฌ ๊ทธ๋๋ก ์ฌ์ฉํ์๋ค. ์๋ณธ์ GitHub์์ ํ์ธ ๊ฐ๋ฅํ๋ค. GitHub: build-option.ts โฉ
-
o3-mini๋ OpenAI์์ ์ ๊ณตํ๋ ๊ฐ์ฅ ์ ๋ ดํ LLM ์ค ํ๋์ด๋ค. OpenAI Pricing โฉ
-
devDependencies์ ์ํ๋ ํจํค์ง ํฌํจ. โฉ
-
GeekNews: 27๋ ๋ EXE ํ์ผ์ Claude 3.7์ ์ ๋ก๋ํ ํ ์ผ์ด๋ ๋๋ผ์ด ์ผ โฉ