8
n8n 한국어amn8n.com

AI 이력서 최적화기

고급

이것은AI Summarization, Multimodal AI분야의자동화 워크플로우로, 18개의 노드를 포함합니다.주로 Set, Code, Gmail, Merge, Webhook 등의 노드를 사용하며. Gemini 분석 및 이메일 보고서를 사용하여 이력서를 직업 설명에 매칭

사전 요구사항
  • Google 계정 및 Gmail API 인증 정보
  • HTTP Webhook 엔드포인트(n8n이 자동으로 생성)
  • 대상 API의 인증 정보가 필요할 수 있음
  • Google Gemini API Key
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "TzPKUZdrlcTUenHQ",
  "meta": {
    "instanceId": "d1dc073e8e3059a23e2730f69cb1b90065a2ac39039fea0727fdf9bee77a9131",
    "templateCredsSetupCompleted": true
  },
  "name": "AI CV Optimizer",
  "tags": [],
  "nodes": [
    {
      "id": "08a1bb78-33db-4698-9970-c5b38c25835c",
      "name": "Webhook - 이력서 최적화 양식",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -224,
        272
      ],
      "webhookId": "d50feff6-c48f-41e8-8df2-62ee9864907c",
      "parameters": {
        "path": "cv-optimizer",
        "options": {},
        "responseMode": "responseNode",
        "multipleMethods": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "310ffa59-1f26-4ddd-881d-c5819b89d7f1",
      "name": "Webhook 응답 - HTML 양식",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        0,
        176
      ],
      "parameters": {
        "options": {},
        "respondWith": "text",
        "responseBody": "=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n  <title>AI CV Optimizer</title>\n  <style>\n    :root {\n      --primary: #2563eb;\n      --primary-hover: #1e4ed8;\n      --gray-light: #f9fafb;\n      --gray: #ccc;\n      --text-dark: #333;\n      --radius: 10px;\n    }\n    body {\n      font-family: Arial, sans-serif;\n      background: var(--gray-light);\n      margin: 0;\n      padding: 0;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      min-height: 100vh;\n    }\n    .container {\n      background: white;\n      padding: 2rem;\n      border-radius: var(--radius);\n      box-shadow: 0 6px 16px rgba(0,0,0,0.1);\n      max-width: 420px;\n      width: 100%;\n    }\n    h2 {\n      margin-bottom: 1.5rem;\n      color: var(--text-dark);\n      font-size: 1.5rem;\n      text-align: center;\n    }\n    label {\n      font-weight: 600;\n      display: block;\n      margin: 1rem 0 0.5rem;\n    }\n    input[type=\"file\"], input[type=\"text\"], input[type=\"email\"] {\n      width: 100%;\n      padding: 0.75rem;\n      border: 1px solid var(--gray);\n      border-radius: var(--radius);\n      font-size: 0.95rem;\n      box-sizing: border-box;\n    }\n    input:focus {\n      border-color: var(--primary);\n      outline: none;\n      box-shadow: 0 0 0 3px rgba(37,99,235,0.15);\n    }\n    button {\n      margin-top: 1.5rem;\n      padding: 0.9rem;\n      background: var(--primary);\n      color: white;\n      border: none;\n      border-radius: var(--radius);\n      width: 100%;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      transition: background 0.2s ease;\n    }\n    button:hover {\n      background: var(--primary-hover);\n    }\n    button:disabled {\n      background: #9ca3af;\n      cursor: not-allowed;\n    }\n    .status {\n      margin-top: 1rem;\n      font-size: 0.9rem;\n      text-align: center;\n    }\n    .status.success { color: green; }\n    .status.error { color: red; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <h2>AI CV Optimizer</h2>\n    <form id=\"cvForm\">\n      <label for=\"cv\">Upload your CV (PDF):</label>\n      <input type=\"file\" id=\"cv\" name=\"cv\" accept=\"application/pdf\" required />\n\n      <label for=\"job_url\">Job Posting URL:</label>\n      <input type=\"text\" id=\"job_url\" name=\"job_url\" placeholder=\"https://linkedin.com/job/123\" required />\n\n      <label for=\"email\">Your Email:</label>\n      <input type=\"email\" id=\"email\" name=\"email\" placeholder=\"you@example.com\" required/>\n\n      <button type=\"submit\">Check My CV</button>\n      <div class=\"status\" id=\"status\"></div>\n    </form>\n  </div>\n\n  <script>\n    const form = document.getElementById(\"cvForm\");\n    const statusDiv = document.getElementById(\"status\");\n\n    form.addEventListener(\"submit\", async (e) => {\n      e.preventDefault();\n\n      const formData = new FormData(form);\n      statusDiv.textContent = \"⏳ Uploading and analyzing your CV...\";\n      statusDiv.className = \"status\";\n\n      try {\n        const res = await fetch(\"https://n8nworkflow.eu/webhook-test/cv-optimizer\", {\n          method: \"POST\",\n          body: formData\n        });\n\n        if (!res.ok) {\n          throw new Error(\"Server error: \" + res.statusText);\n        }\n\n        const data = await res.json();\n        console.log(\"n8n response:\", data);\n        statusDiv.textContent = \"✅ CV submitted successfully! Check your email for results.\";\n        statusDiv.className = \"status success\";\n      } catch (err) {\n        console.error(err);\n        statusDiv.textContent = \"❌ Error: \" + err.message;\n        statusDiv.className = \"status error\";\n      }\n    });\n  </script>\n</body>\n</html>"
      },
      "typeVersion": 1.4
    },
    {
      "id": "5f221527-5476-49cb-a166-eb3213f5d4a6",
      "name": "이력서 텍스트 추출 (PDF)",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        0,
        384
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "=cv"
      },
      "typeVersion": 1
    },
    {
      "id": "75eb814c-8d04-4310-bc01-3fcaf1640634",
      "name": "이력서 텍스트 준비",
      "type": "n8n-nodes-base.set",
      "position": [
        224,
        384
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "be5e5936-7940-43be-b905-62b54d9db076",
              "name": "cv_text",
              "type": "string",
              "value": "={{ $json.text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "da50a5a9-a727-45f9-b07c-e75844f89d45",
      "name": "채용 공고 가져오기",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        448,
        304
      ],
      "parameters": {
        "url": "={{ $(' Webhook - CV Optimizer Form').item.json.body.job_url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "405c1c1d-afa1-4b9e-a595-a7eef3772303",
      "name": "이력서 + 직무 데이터 병합",
      "type": "n8n-nodes-base.merge",
      "position": [
        896,
        368
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "f7e1ebf8-5e4e-48b8-a384-d88f53d771bb",
      "name": "Gemini 모델 - 기본",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1120,
        592
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "id": "qQGrvqnSPqWFH6I6",
          "name": "Google Gemini(PaLM) Api account 5"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cf43c082-b2ae-42e0-8d3d-83db4a4d9f9d",
      "name": "AI JSON 출력 파싱",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1248,
        592
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"job_title\": \"Frontend Developer (React)\",\n  \"location\": \"Helsinki, Finland\",\n  \"fit_summary\": \"The candidate has solid React, TypeScript, and JavaScript experience, supported by practical work on full-stack applications. They also demonstrate CI/CD knowledge and testing skills (Cypress, Jest), which align well with the role. However, the CV does not explicitly highlight advanced CSS frameworks or accessibility practices that are emphasized in the job description.\",\n  \"recommendation\": \"Consider\",\n  \"fit_score\": 7,\n  \"missing_critical\": [\n    \"Advanced CSS framework experience (e.g., Tailwind, Material UI)\",\n    \"Accessibility (WCAG) best practices\"\n  ],\n  \"cv_optimization\": \"Add a section highlighting hands-on experience with CSS frameworks (Tailwind, Material UI) and accessibility best practices (WCAG). Include concrete project examples that demonstrate user-focused design and frontend performance improvements.\",\n  \"final_recommendation\": \" The candidate is a good potential match but should strengthen their CV by explicitly mentioning CSS framework expertise and accessibility knowledge to move from 'Consider' to a stronger 'Apply'.\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "51bd8f61-dea2-4763-beb3-d0171ca55660",
      "name": "Gemini 모델",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1328,
        800
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "id": "qQGrvqnSPqWFH6I6",
          "name": "Google Gemini(PaLM) Api account 5"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a0bbfaab-6717-4a88-9766-97d70dec3f03",
      "name": "메모지",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -224,
        -304
      ],
      "parameters": {
        "width": 512,
        "height": 272,
        "content": "## AI CV Optimizer: Match Your CV to Job Descriptions with AI\n\nThis workflow uses AI to automatically analyze a candidate’s CV against any job posting. It extracts key skills, requirements, and gaps, then generates a clear fit summary, recommendations, and optimization tips. Candidates also receive a structured email report, helping them improve their CV and focus on the right roles.\n\nNo more guesswork, the workflow delivers objective. \n### AI-powered career insights in minutes."
      },
      "typeVersion": 1
    },
    {
      "id": "91fb8dbc-2126-47dc-a4ae-a42d8b9c4397",
      "name": "메모지1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        192
      ],
      "parameters": {
        "color": 6,
        "width": 224,
        "content": "### AI - Compare CV with Job\n\nYou can adjust the AI Agent prompt for output schema, scoring, or language.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0343291b-6da2-4155-9a52-164f4c4ab1d1",
      "name": "메모지2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1088,
        736
      ],
      "parameters": {
        "color": 5,
        "width": 208,
        "height": 112,
        "content": "###  Gemini / AI \nCredentials:  \nUse **Google Gemini/PaLM** credential."
      },
      "typeVersion": 1
    },
    {
      "id": "14e53603-87f5-4d4e-92ef-216eb5917964",
      "name": "메모지5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        528
      ],
      "parameters": {
        "color": 5,
        "width": 192,
        "height": 96,
        "content": "### Send report \nSend Email\nCredentials: Use **Gmail OAuth2** credential. (required)."
      },
      "typeVersion": 1
    },
    {
      "id": "c05f35ba-eeb9-4752-80ef-23eefbcca0f2",
      "name": "보고서 전송",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1616,
        368
      ],
      "webhookId": "ce5d269e-ee40-4c92-9479-e5af8baec199",
      "parameters": {
        "sendTo": "={{ $(' Webhook - CV Optimizer Form').item.json.body.email }}",
        "message": "=<p>Hi,</p>\n\n<p>We’ve analyzed your CV against the job posting for <b>{{ $json.output.job_title }}</b> in <b>{{ $json.output.location }}</b>.</p>\n\n<p><b>Summary:</b><br>\n{{ $json.output.fit_summary }}</p>\n\n<p><b>Critical gaps identified:</b></p>\n<ul>\n  {{ $json.output.missing_critical.map(gap => `<li>${gap}</li>`).join(\"\") }}\n</ul>\n\n<p><b>FinalFit Score:</b> {{ $json.output.fit_score }} / 10 <b> Recommendation: <b/> {{ $json.output.recommendation }}</p>\n<p>\n<b>Tips for improving CV: </b>{{ $json.output.cv_optimization }}\n</p>\n<p><b>AI Advice:</b><br>\n{{ $json.output.final_recommendation }}\n</p>\n\n<p>Best of luck with your applications,<br>AI CV Optimizer</p>",
        "options": {},
        "subject": "=Your CV Review: {{ $json.output.job_title }} in {{ $json.output.location }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "jkKHvU2Pb9X5WJk5",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "8918b88f-f90d-4e68-b28b-84dd68ad854a",
      "name": "메모지11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        16
      ],
      "parameters": {
        "color": 5,
        "width": 160,
        "height": 144,
        "content": "### Submission form\n**POST (required)**\n- `Upload CV`\n- `Job Link` \n- `email` "
      },
      "typeVersion": 1
    },
    {
      "id": "03491b28-4df7-4be4-88b1-4128e92fe9b7",
      "name": "AI 이력서 분석기",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1152,
        368
      ],
      "parameters": {
        "text": "=CV:\n{{ $json[\"cv_text\"] ? $json[\"cv_text\"].slice(0, 18000) : \"\" }}\n\nJOB:\n{{ $json[\"job_text\"] ? $json[\"job_text\"].slice(0, 18000) : \"\" }}\n\nTasks:\n1) Extract the \"job_title\" and \"location\".  \n2) Identify \"matched_skills\" and \"missing_critical\" skills.  \n3) Write a short \"advice\" paragraph (max 100 words).  \n4) Write a friendly \"email_body\" addressed to the candidate, summarizing:\n   - Job title & location  \n   - What they already match well  \n   - Areas to improve or learn for better fit  \n   - A motivating closing sentence \n5)5) Write a short final_recommendation paragraph.\n\n6) Provide **two recommendations**:  \n   - \"recommendation\": Apply / Consider / Not a fit (must align with fit_score)  \n   - \"cv_optimization\": Clear advice on how to improve the CV for similar roles.  \n6) The \"fit_score\" must always align with \"recommendation\":  \n   - Apply → fit_score between 9 and 10  \n   - Consider → fit_score between 7 and 8  \n   - Not a fit → fit_score between 1 and 6  \n\n⚠️ IMPORTANT: Return ONLY valid JSON in this schema:\n{\n  \"job_title\": \"string\",\n  \"location\": \"string\",\n  \"fit_score\": 0,\n  \"recommendation\": \"Apply|Consider|Not a fit\",\n\"final_recommendation\": [\"string\"],\n  \"matched_skills\": [\"string\"],\n  \"missing_critical\": [\"string\"],\n  \"advice\": \"string\",\n  \"cv_optimization\": \"string\",\n  \"email_body\": \"string\"\n}",
        "options": {
          "systemMessage": "You are a professional career assistant.  \nYour task is to compare a candidate’s CV with a job description and return a structured JSON output.  \n\n⚠️ RULES:  \n- Follow the schema exactly.  \n- Every field must be included.  \n- All values must be plain text, arrays, or integers — never nested objects.  \n- `fit_score` must be an integer (1–10) aligned with `recommendation`:  \n   - \"Apply\" → 9–10  \n   - \"Consider\" → 7–8  \n   - \"Not a fit\" → 1–6  \n- Do not add responsibilities, requirements, or benefits.  \n- Do not include any text outside the JSON.  \n\nSchema:\n{\n  \"job_title\": \"string\",\n  \"location\": \"string\",\n  \"fit_score\": 0,\n  \"recommendation\": \"Apply|Consider|Not a fit\",\n  \"matched_skills\": [\"string\"],\n  \"missing_critical\": [\"string\"],\n  \"advice\": \"string\",\n  \"cv_optimization\": \"string\",\n  \"email_body\": \"string\",\n\"final_recommendation\": : \"string\",\n\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "798f0b85-bd22-4ad8-a9c3-a3535d955069",
      "name": "직무 텍스트 정리기",
      "type": "n8n-nodes-base.code",
      "position": [
        672,
        304
      ],
      "parameters": {
        "jsCode": "const raw = $json.data || \"\";\nconst text = raw\n  .replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n  .replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n  .replace(/<\\/?[^>]+(>|$)/g, \" \")\n  .replace(/\\s+/g, \" \")\n  .trim();\nreturn [{ job_text: text }];"
      },
      "typeVersion": 2
    },
    {
      "id": "eef4754b-adb0-4859-93df-cfc361f8175c",
      "name": "메모지3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        -304
      ],
      "parameters": {
        "color": 2,
        "width": 304,
        "height": 144,
        "content": "## Customization checklist\n✅ Update Webhook URL\n✅ Configure Google Gemini credentials\n✅ Set Gmail OAuth2 credentials\n✅ Adjust AI prompt if schema changes"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "039ce290-aa42-4e4a-a346-65841445a6a6",
  "connections": {
    "51bd8f61-dea2-4763-beb3-d0171ca55660": {
      "ai_languageModel": [
        [
          {
            "node": "cf43c082-b2ae-42e0-8d3d-83db4a4d9f9d",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "03491b28-4df7-4be4-88b1-4128e92fe9b7": {
      "main": [
        [
          {
            "node": "c05f35ba-eeb9-4752-80ef-23eefbcca0f2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "75eb814c-8d04-4310-bc01-3fcaf1640634": {
      "main": [
        [
          {
            "node": "da50a5a9-a727-45f9-b07c-e75844f89d45",
            "type": "main",
            "index": 0
          },
          {
            "node": "405c1c1d-afa1-4b9e-a595-a7eef3772303",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "798f0b85-bd22-4ad8-a9c3-a3535d955069": {
      "main": [
        [
          {
            "node": "405c1c1d-afa1-4b9e-a595-a7eef3772303",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "da50a5a9-a727-45f9-b07c-e75844f89d45": {
      "main": [
        [
          {
            "node": "798f0b85-bd22-4ad8-a9c3-a3535d955069",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "405c1c1d-afa1-4b9e-a595-a7eef3772303": {
      "main": [
        [
          {
            "node": "03491b28-4df7-4be4-88b1-4128e92fe9b7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "cf43c082-b2ae-42e0-8d3d-83db4a4d9f9d": {
      "ai_outputParser": [
        [
          {
            "node": "03491b28-4df7-4be4-88b1-4128e92fe9b7",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "5f221527-5476-49cb-a166-eb3213f5d4a6": {
      "main": [
        [
          {
            "node": "75eb814c-8d04-4310-bc01-3fcaf1640634",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f7e1ebf8-5e4e-48b8-a384-d88f53d771bb": {
      "ai_languageModel": [
        [
          {
            "node": "03491b28-4df7-4be4-88b1-4128e92fe9b7",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "08a1bb78-33db-4698-9970-c5b38c25835c": {
      "main": [
        [
          {
            "node": "310ffa59-1f26-4ddd-881d-c5819b89d7f1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "5f221527-5476-49cb-a166-eb3213f5d4a6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - AI 요약, 멀티모달 AI

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수18
카테고리2
노드 유형12
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34