{
  "name": "\uc138\ubbf8\ub098 \ub370\ubaa8 \uc6a9 \uc6cc\ud06c\ud50c\ub85c\uc6b0",
  "nodes": [
    {
      "parameters": {
        "path": "research",
        "responseMode": "lastNode",
        "options": {
          "responsePropertyName": "data"
        }
      },
      "id": "f56d9bad-15c7-4108-8f9e-9da72441771f",
      "name": "Webhook \ud2b8\ub9ac\uac70",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -1400,
        180
      ]
    },
    {
      "parameters": {
        "url": "https://openapi.naver.com/v1/search/news.json",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "={{ $json.query }}"
            },
            {
              "name": "display",
              "value": "20"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Naver-Client-Id",
              "value": "=ukBNYmnsfjlX82JImWyp"
            },
            {
              "name": "X-Naver-Client-Secret",
              "value": "Nz6VHqzBjR"
            }
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "id": "954c9fb7-a25b-42d6-8018-ca679663a5aa",
      "name": "\ub124\uc774\ubc84 \ub274\uc2a4 \uac80\uc0c9 (Naver API)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        -1100,
        180
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://openapi.naver.com/v1/datalab/search",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {}
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Naver-Client-Id",
              "value": "=ukBNYmnsfjlX82JImWyp"
            },
            {
              "name": "X-Naver-Client-Secret",
              "value": "Nz6VHqzBjR"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{ \"startDate\":\"2025-01-01\", \n  \"endDate\":\"2025-07-27\", \n  \"timeUnit\":\"month\", \n  \"keywordGroups\":[   \n    { \"groupName\":\"AI\",\n      \"keywords\":[\"\ucc57GPT\",\"\uc0dd\uc131\ud615AI\"] \n    },   \n    { \"groupName\":\"\ud074\ub77c\uc6b0\ub4dc\", \n      \"keywords\":[\"AWS\",\"Azure\"] } \n  ], \n  \"device\":\"pc\", \n  \"ages\":[\"3\",\"4\",\"5\"] \n\n}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "b726b48e-35c5-41fd-9ec3-b7006dad7739",
      "name": "\ub124\uc774\ubc84 \uac80\uc0c9\uc5b4 \ud2b8\ub80c\ub4dc",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        -1240,
        -60
      ]
    },
    {
      "parameters": {
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "title"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        -780,
        180
      ],
      "id": "0613a216-908f-40c9-ac3c-5215e62b33ff",
      "name": "Aggregate"
    },
    {
      "parameters": {
        "jsCode": "/**\n * n8n Code node\n * \uc785\ub825: HTTP Request \ub178\ub4dc\uac00 \ubc18\ud658\ud55c JSON\n * \ubaa9\uc801: items[] \ubc30\uc5f4\uc744 \uac1c\ubcc4 \uc544\uc774\ud15c\uc73c\ub85c \ubd84\ub9ac\u2006+\u2006\ud0dc\uadf8 \uc81c\uac70\n * \ucd9c\ub825: [{json:{title, link, pubDate, description}}, \u2026]\n */\nconst raw = $json;                     // HTTP \ub178\ub4dc\uc5d0\uc11c \ub118\uc5b4\uc628 \ud55c \ub369\uc5b4\ub9ac\nconst list = raw.items ?? [];          // safety\n\nreturn list.map(i => ({\n  json: {\n    title:       i.title.replace(/<[^>]*>/g, ''),        // <b>\ud0dc\uadf8 \uc81c\uac70\n    link:        i.link,\n    pubDate:     i.pubDate,\n    description: i.description.replace(/<[^>]*>/g, '')\n  }\n}));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -940,
        180
      ],
      "id": "7115aa4b-e3e4-4c19-8a55-bdebb48b9ced",
      "name": "Code"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://hyperclova-x-alpha-helsinki-agent-hotfix-250611.clops-inference.clova.ai/v2/generate",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer clops_7c8807d97ec8780cb11ac98061dc"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "charset",
              "value": "utf-8"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"top_k\": 1,\n  \"stop\": [\"<|stop|>\", \"<|endofturn|>\"],\n  \"max_tokens\": 8154,\n  \"temperature\": 0.5,\n  \"repeat_penalty\": 1.0,\n  \"prompt\": \"<|im_start|>system\\n\ub2f9\uc2e0\uc740 \uacbd\ud5d8 \ub9ce\uc740 \ub274\uc2a4\ub808\ud130 \ud3b8\uc9d1\uc7a5\uc785\ub2c8\ub2e4. \ub3c5\uc790\uc758 \uad00\uc2ec\uc0ac(query)\ub97c \uc815\ud655\ud788 \ud30c\uc545\ud558\uc5ec, \uadf8\ub4e4\uc5d0\uac8c \uac00\uc7a5 \uac00\uce58 \uc788\ub294 \uae30\uc0ac\ub97c \uc120\ubcc4\ud558\ub294 \uac83\uc774 \ub2f9\uc2e0\uc758 \uc5ed\ud560\uc785\ub2c8\ub2e4.\\n\\n\uc791\uc5c5 \uc21c\uc11c:\\n1. \uba3c\uc800 \ub3c5\uc790\uc758 query\ub97c \ubd84\uc11d\ud558\uc5ec \ud575\uc2ec \uad00\uc2ec\uc0ac\uc640 \ud3c9\uac00 \uae30\uc900\uc744 \ub3c4\ucd9c\ud558\uc138\uc694\\n2. \ub3c4\ucd9c\ud55c \uae30\uc900\uc5d0 \ub530\ub77c **\uc81c\uacf5\ub41c \ubaa8\ub4e0 \uae30\uc0ac**\ub4e4\uc758 \uc2e4\uc9c8\uc801 \uac00\uce58\ub97c \ud3c9\uac00\ud558\uc138\uc694\\n3. \ub2e8\uc21c\ud55c \ud0a4\uc6cc\ub4dc \ub9e4\uce6d\uc774 \uc544\ub2cc, \uc2e4\uc81c \ub0b4\uc6a9\uc758 \uae4a\uc774\uc640 \uc2e4\uc6a9\uc131\uc744 \uace0\ub824\ud558\uc138\uc694\\n4. **\ubc18\ub4dc\uc2dc \ubaa8\ub4e0 \uae30\uc0ac\uc5d0 \uc21c\uc704\ub97c \ub9e4\uae30\uc138\uc694 (1\ub4f1\ubd80\ud130 \ub9c8\uc9c0\ub9c9 \ub4f1\uc218\uae4c\uc9c0)**\\n\\n\ubc18\ub4dc\uc2dc \ub2e4\uc74c JSON \ud615\uc2dd\uc73c\ub85c\ub9cc \ucd9c\ub825\ud558\uc138\uc694:\\n{\\n  \\\"query_analysis\\\": {\\n    \\\"main_interest\\\": \\\"\ub3c5\uc790\uc758 \ud575\uc2ec \uad00\uc2ec\uc0ac\\\",\\n    \\\"evaluation_criteria\\\": [\\\"\uae30\uc9001\\\", \\\"\uae30\uc9002\\\", \\\"\uae30\uc9003\\\"],\\n    \\\"total_articles\\\": \ucd1d_\uae30\uc0ac_\uac1c\uc218\\n  },\\n  \\\"rankings\\\": [\\n    {\\\"rank\\\": 1, \\\"title\\\": \\\"\uae30\uc0ac \uc81c\ubaa9\\\", \\\"reason\\\": \\\"\uc120\uc815 \uc774\uc720\\\"},\\n    {\\\"rank\\\": 2, \\\"title\\\": \\\"\uae30\uc0ac \uc81c\ubaa9\\\", \\\"reason\\\": \\\"\uc120\uc815 \uc774\uc720\\\"},\\n    ... \ubaa8\ub4e0 \uae30\uc0ac \ud3ec\ud568 ...\\n  ]\\n}\\n\\nJSON \uc678\uc5d0 \ub2e4\ub978 \ud14d\uc2a4\ud2b8\ub294 \ud3ec\ud568\ud558\uc9c0 \ub9c8\uc138\uc694.<|im_end|>\\n<|im_start|>user\\nquery: AI \uc11c\ube44\uc2a4 \uae30\ud68d\u00b7\uac1c\ubc1c\\n\\n\ub2e4\uc74c 4\uac1c \uae30\uc0ac\ub97c \ubaa8\ub450 \ud3c9\uac00\ud574\uc8fc\uc138\uc694:\\n- \uad6c\uae00, \uc0c8\ub85c\uc6b4 AI \ubaa8\ub378 \ubc1c\ud45c\\n- \ub0a0\uc528 \uc608\ubcf4, \ub0b4\uc77c \ub9d1\uc74c\\n- \uc0bc\uc131\uc804\uc790, AI \uce69 \uac1c\ubc1c \ud22c\uc790\\n- LG\uc804\uc790 CEO, \\\"AI\uac00 \uc911\uc694\ud558\ub2e4\\\" \ubc1c\uc5b8<|im_end|>\\n<|im_start|>assistant\\n{\\n  \\\"query_analysis\\\": {\\n    \\\"main_interest\\\": \\\"AI \uc11c\ube44\uc2a4\uc758 \uc2e4\uc81c \uac1c\ubc1c\uacfc \uad6c\ud604\\\",\\n    \\\"evaluation_criteria\\\": [\\\"\uae30\uc220\uc801 \uad6c\uccb4\uc131\\\", \\\"\uc2e4\ubb34 \uc801\uc6a9 \uac00\ub2a5\uc131\\\", \\\"\uac1c\ubc1c\uc790/\uae30\ud68d\uc790\uc5d0\uac8c \uc8fc\ub294 \uc778\uc0ac\uc774\ud2b8\\\"],\\n    \\\"total_articles\\\": 4\\n  },\\n  \\\"rankings\\\": [\\n    {\\\"rank\\\": 1, \\\"title\\\": \\\"\uad6c\uae00, \uc0c8\ub85c\uc6b4 AI \ubaa8\ub378 \ubc1c\ud45c\\\", \\\"reason\\\": \\\"\uc2e4\uc81c \uc0ac\uc6a9 \uac00\ub2a5\ud55c AI \ubaa8\ub378 \ubc1c\ud45c\ub85c \uac1c\ubc1c\uc5d0 \uc9c1\uc811 \ud65c\uc6a9 \uac00\ub2a5\\\"},\\n    {\\\"rank\\\": 2, \\\"title\\\": \\\"\uc0bc\uc131\uc804\uc790, AI \uce69 \uac1c\ubc1c \ud22c\uc790\\\", \\\"reason\\\": \\\"AI \uc11c\ube44\uc2a4 \uc778\ud504\ub77c \ubc1c\uc804\uc5d0 \uae30\uc5ec\ud558\ub294 \ud558\ub4dc\uc6e8\uc5b4 \uac1c\ubc1c\\\"},\\n    {\\\"rank\\\": 3, \\\"title\\\": \\\"LG\uc804\uc790 CEO, 'AI\uac00 \uc911\uc694\ud558\ub2e4' \ubc1c\uc5b8\\\", \\\"reason\\\": \\\"\uacbd\uc601\uc9c4 \ubc1c\uc5b8\uc740 \ud2b8\ub80c\ub4dc \ucc38\uace0\uc6a9\uc774\uc9c0\ub9cc \uc2e4\ubb34\uc801 \uac00\uce58\ub294 \ub0ae\uc74c\\\"},\\n    {\\\"rank\\\": 4, \\\"title\\\": \\\"\ub0a0\uc528 \uc608\ubcf4, \ub0b4\uc77c \ub9d1\uc74c\\\", \\\"reason\\\": \\\"AI\uc640 \uc804\ud600 \uad00\ub828 \uc5c6\ub294 \uc77c\ubc18 \ub0a0\uc528 \uc815\ubcf4\\\"}\\n  ]\\n}<|im_end|>\\n<|im_start|>user\\nquery: {{ $('query').item.json.query }}\\n\\n\ub2e4\uc74c {{$json.title.length}}\uac1c \uae30\uc0ac\ub97c \ubaa8\ub450 \ud3c9\uac00\ud574\uc8fc\uc138\uc694:\\n\\n{{$json.title}}<|im_end\\n<|im_start|>assistant\\n{\\n  \\\"query_analysis\\\": {\\n    \\\"main_interest\\\":\"\n}",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 20
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -620,
        180
      ],
      "id": "025d705e-8266-46f9-8dc6-926684bcef53",
      "name": "HCX \ub274\uc2a4 \uae30\uc0ac \ub9ac\ub7ad\ud0b9"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://dev-chainer-api.io.naver.com/v1/chat-completions",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Clops-Token",
              "value": "clops_7c8***"
            },
            {
              "name": "X-Chainer-Service-Name",
              "value": "news-summary"
            },
            {
              "name": "X-Clops-Model",
              "value": "https://hyperclova-x-alpha-helsinki-fixed-cand2-re.clops-inference.clova.ai"
            },
            {
              "name": "x-request-id",
              "value": "example1"
            },
            {
              "name": "X-Chainer-Debug",
              "value": "true"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"stream\": false,\n  \"temperature\": 0.5,\n  \"top_k\": null,\n  \"top_p\": 0.6,\n  \"repetition_penalty\": 1.05,\n  \"max_tokens\": 1152,\n  \"max_text_tokens\": 8192,\n  \"stop\": [\"<|im_end|>\", \"<|endofturn|>\"],\n  \"force_assistant_answer\": true,\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"#\ubaa9\ud45c(Objective)\\n\ub2f9\uc2e0\uc740 \uc8fc\uc5b4\uc9c4 \uae30\uc0ac \uc81c\ubaa9\uc744 \ubcf4\uace0 \uc911\uc694\ud55c \uc21c\uc11c\ub300\ub85c title \uc744 \uc7ac\ubc30\uc5f4 \ud569\ub2c8\ub2e4\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"\uae30\uc0ac \uc81c\ubaa9 : {{ $json.title }}\"\n    }\n  ]\n}",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 20
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -1040,
        -60
      ],
      "id": "957bc5a9-302a-4c35-abd1-4b2897f79258",
      "name": "Clova API Call1"
    },
    {
      "parameters": {
        "jsCode": "/******************************************************************\n * n8n Code node   \u2014   HyperCLOVA-X \ub274\uc2a4 \ub7ad\ud0b9 \ud30c\uc11c (Edge-case safe)\n * \uc785\ub825 : $json.choices[0].text (\uc784\uc758 \ud615\uc2dd, <|im_end|> \ud3ec\ud568)\n * \ucd9c\ub825 : [{json:{rank,title,reason}}]  \u2014 rank \uc624\ub984\ucc28\uc21c\n ******************************************************************/\n\nconst raw = $json.choices?.[0]?.text ?? '';\nconst body = raw.split('<|')[0];                 // \uba54\ud0c0 \ud1a0\ud070 \uc81c\uac70\n\n/*---------------------------------------------------------------\n  STEP-1  \uc21c\uc218 JSON \ucc3e\uae30   {...\"rankings\":[ {...}, ... ]}\n----------------------------------------------------------------*/\ntry {\n  const firstBrace = body.indexOf('{');\n  if (firstBrace !== -1) {\n    // JSON.parse \uc5d0\ub7ec \ubc29\uc9c0\ub97c \uc704\ud574 \ub9c8\uc9c0\ub9c9 '}' \uc704\uce58\uae4c\uc9c0 \uc790\ub984\n    const lastBrace = body.lastIndexOf('}');\n    if (lastBrace > firstBrace) {\n      const cleaned = body.slice(firstBrace, lastBrace + 1)\n                           .replace(/,\\s*}/g, '}')         // trailing comma\n                           .replace(/,\\s*]/g, ']');        // trailing comma\n      const obj = JSON.parse(cleaned);\n      if (Array.isArray(obj.rankings)) return obj.rankings\n        .map(({rank,title,reason}) => ({json:{rank,title,reason}}))\n        .sort((a,b)=>a.json.rank-b.json.rank);\n    }\n  }\n} catch (_) { /* \ub69d\u2014\ub2e4\uc74c \ub2e8\uacc4 */ }\n\n/*---------------------------------------------------------------\n  STEP-2  \uac1d\uccb4 \ube14\ub85d \ub2e8\uc704 \ud30c\uc2f1  { \"rank\":n, \"title\":\"...\", ... }\n----------------------------------------------------------------*/\nconst blockRegex = /\\{[^{}]*?\"rank\"\\s*:\\s*\\d+[^{}]*?\"reason\"\\s*:\\s*\"[^\"]+?\"[^{}]*?}/gs;\nconst blocks = [...body.matchAll(blockRegex)].map(m=>m[0]);\nconst results = [];\n\nfor (const blk of blocks) {\n  try {\n    const safe = blk.replace(/,\\s*}/g,'}').replace(/,\\s*]/g,']');\n    const {rank,title,reason} = JSON.parse(safe);\n    results.push({rank,title,reason});\n  } catch {/* skip */}\n}\nif (results.length) {\n  results.sort((a,b)=>a.rank-b.rank);\n  return results.map(r=>({json:r}));\n}\n\n/*---------------------------------------------------------------\n  STEP-3  1-\ub77c\uc778 \ud328\ud134 \ud30c\uc2f1  \"rank\": n , \"title\": \"...\", \"reason\": \"...\"\n----------------------------------------------------------------*/\nconst lineRegex = /\"rank\"\\s*:\\s*(\\d+)[\\s\\S]+?\"title\"\\s*:\\s*\"([^\"]+?)\"[\\s\\S]+?\"reason\"\\s*:\\s*\"([^\"]+?)\"/g;\nlet m; let autoRank = 1;\nwhile ((m=lineRegex.exec(body))!==null) {\n  results.push({\n    rank:   Number(m[1]) || autoRank++,\n    title:  m[2],\n    reason: m[3]\n  });\n}\nif (!results.length) throw new Error('\ub7ad\ud0b9 \uc815\ubcf4\ub97c \ucc3e\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.');\n\nresults.sort((a,b)=>a.rank-b.rank);\n\n// \uc81c\ubaa9 \uc911\ubcf5 \uc81c\uac70(\uccab \ubc88\uc9f8\ub9cc \ub0a8\uae40)\nconst seen = new Set();\nconst unique = results.filter(r=>{\n  if (seen.has(r.title)) return false;\n  seen.add(r.title); return true;\n});\n\nreturn unique.map(r=>({json:r}));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -460,
        180
      ],
      "id": "24dbe932-0239-452f-9296-bd2c3cc45a04",
      "name": "Code1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        -300,
        180
      ],
      "id": "01ed54fd-a06c-48c9-b65e-8e768a4ad607",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "/**\n * n8n Code node\n * INPUT  : \uc11e\uc5ec-\uc788\ub294  items  ( \u2460 rank\u00b7reason \uc804\uc6a9 \u2461 link\u00b7pubDate\u00b7description \uc804\uc6a9 )\n * OUTPUT : \ub450 \uc815\ubcf4\ub97c \ud569\uccd0 \uc644\uc804\ud55c \ub2e8\uc77c JSON \ubc30\uc5f4\n *          {title, link, pubDate, description, rank, reason}\n */\n\nconst THRESHOLD = 0.45;  // \uc81c\ubaa9 \uc720\uc0ac\ub3c4 \uc784\uacc4\uac12(0~1)\u2015\ub0ae\ucd9c\uc218\ub85d \uad00\ub300\ud55c \ubcd1\ud569\n\n/* \uc720\uc0ac\ub3c4: \uacf5\ubc31\u00b7\uad6c\ub450\uc810 \uc81c\uac70 \ud6c4 Jaccard */\nfunction similarity(a, b) {\n  const clean = s => s.toLowerCase().replace(/[^\\p{L}\\p{N}\\s]/gu,'');\n  const A = new Set(clean(a).split(/\\s+/));\n  const B = new Set(clean(b).split(/\\s+/));\n  const inter = [...A].filter(x => B.has(x)).length;\n  return inter / (A.size + B.size - inter || 1);\n}\n\n/* \ub204\uc801 Map  titleKey \u2192 \uac1d\uccb4 */\nconst merged = [];\n\nfor (const { json } of items) {\n  const cur = { ...json };                       // \ubcf5\uc0ac\n  const title = cur.title?.trim();\n  if (!title) continue;\n\n  // \uac00\uc7a5 \uc720\uc0ac\ud55c \uae30\uc0ac \ucc3e\uae30\n  let bestIdx = -1, bestScore = 0;\n  merged.forEach((m, idx) => {\n    const s = similarity(title, m.title);\n    if (s > bestScore) { bestScore = s; bestIdx = idx; }\n  });\n\n  /* \uc0c8 \uadf8\ub8f9 */\n  if (bestScore < THRESHOLD) {\n    merged.push(cur);\n    continue;\n  }\n\n  /* \ubcd1\ud569 \u2013 \ube48 \ud544\ub4dc\ub294 \ucc44\uc6cc \ub123\uae30 */\n  const target = merged[bestIdx];\n  for (const k of ['link','pubDate','description','rank','reason']) {\n    if (target[k] === undefined || target[k] === null) target[k] = cur[k];\n  }\n}\n\n/* \uc815\ub82c: rank \uc788\ub294 \uac74 \uc624\ub984\ucc28\uc21c, \uc5c6\uc73c\uba74 \ub4a4\ub85c */\nmerged.sort((a,b)=> (a.rank??999) - (b.rank??999));\n\nreturn merged.map(j => ({ json: j }));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -140,
        180
      ],
      "id": "8f9eda1b-6667-4eaa-89bf-46e5bcb1295d",
      "name": "Code2"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "fb92b8d6-5fbc-42a1-a9c9-69e08f871bf7",
              "name": "query",
              "value": "AI",
              "type": "string"
            },
            {
              "id": "835bf623-5b18-4a54-b322-983e50956afc",
              "name": "address",
              "value": "kangmj0825@gmail.com",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -1260,
        180
      ],
      "id": "2e2591cb-af34-4e1e-b697-ef466745ebd8",
      "name": "query"
    },
    {
      "parameters": {
        "content": "## \ud0a4\uc6cc\ub4dc \uae30\ubc18 \ub124\uc774\ubc84 \ub274\uc2a4 \ubaa9\ub85d \uc2a4\ud06c\ub7a9",
        "height": 260,
        "width": 460
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1280,
        100
      ],
      "id": "06a62bd4-7a93-4c79-8f39-cf586d597d2c",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## \ub124\uc774\ubc84 \ub274\uc2a4 \uae30\uc0ac Re-ranking\n",
        "height": 260,
        "width": 800
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -800,
        100
      ],
      "id": "14c21d8a-7e24-42b2-b735-de8d900bd9da",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "jsCode": "/* ---------- 0) \uc624\ub298 \ub0a0\uc9dc ---------- */\nconst dateStr = new Date().toLocaleDateString('ko-KR', {\n  year:  'numeric',\n  month: 'long',\n  day:   'numeric',\n});\n\n/* ---------- \uacf5\ud1b5 \uc0c1\uc218 ---------- */\nconst OUTER_WRAP = `\n  width:100%;\n  max-width:600px;\n  border:1px solid #d9d9d9;\n  border-radius:8px;\n  font-family:Arial,Helvetica,sans-serif;\n  overflow:hidden;\n`;\n\n/* ---------- 1) HEADER ---------- */\nconst headerHtml = `\n  <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"\n         style=\"width:100%;margin:0 auto 32px;\">\n    <tr><td align=\"center\">\n      <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" style=\"${OUTER_WRAP}\">\n        <tr><td style=\"background:#61ba7a;padding:24px;text-align:center;\">\n\n          <!-- \uba54\uc778 \ud0c0\uc774\ud2c0 -->\n          <span style=\"display:block;font-size:28px;font-weight:bold;color:#fff;line-height:1.3;\">\n            &nbsp;HyperClova&nbsp;News&nbsp;Letter\n          </span>\n\n          <!-- \uc548\ub0b4 \ubb38\uad6c (\uac1c\uc120\u00b7\ud53c\ub4dc\ubc31 \ubb38\uad6c) -->\n          <span style=\"display:block;margin-top:6px;font-size:13px;color:#e9ffe5;line-height:1.4;\">\n            \ubcf8 \ub274\uc2a4\ub808\ud130\ub294 AI \uae30\uc220\uc744 \ud65c\uc6a9\ud574 \uc790\ub3d9\uc73c\ub85c \uc218\uc9d1\u00b7\uc120\ubcc4\u00b7\uac00\uacf5\ub41c \ucf58\ud150\uce20\uc785\ub2c8\ub2e4.<br/>\n            \ub354 \ub098\uc740 \uc11c\ube44\uc2a4\ub97c \uc704\ud574 \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\uace0 \uc788\uc73c\ub2c8, \uc18c\uc911\ud55c \uc758\uacac\uc744 \ubd80\ud0c1\ub4dc\ub9bd\ub2c8\ub2e4.\n          </span>\n\n        </td></tr>\n      </table>\n    </td></tr>\n  </table>\n`;\n\n/* ---------- 2) \ubcf8\ubb38 ---------- */\nconst bodyPlaceholder = $input.first().json.htmlBlocks;\n\n/* ---------- 3) CTA(\ubc84\ud2bc) ---------- */\nconst ctaHtml = `\n  <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;margin:0 auto 32px auto;\">\n    <tr><td align=\"center\">\n      <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" style=\"${OUTER_WRAP}\">\n        <tr><td style=\"padding:24px;text-align:center;\">\n          <h2 style=\"margin:0 0 18px 0;font-size:24px;color:#333;\">\uc624\ub298\uc758 \ub274\uc2a4\ub97c \ub354 \uc790\uc138\ud788 \uc54c\uace0\uc2f6\ub2e4\uba74?</h2>\n          <a href=\"https://agent.io.naver.com/agent/ai_newsletter\" style=\"\n            display:inline-block;\n            background:#61ba7a;\n            color:#fff;\n            font-size:16px;\n            font-weight:bold;\n            padding:12px 28px;\n            border-radius:24px;\n            text-decoration:none;\n          \">\uc5d0\uc774\uc804\ud2b8\uc5d0\uac8c \ubb3c\uc5b4\ubcf4\uae30 \u2192</a>\n        </td></tr>\n      </table>\n    </td></tr>\n  </table>\n`;\n\n/* ---------- 4) FOOTER ---------- */\nconst footerHtml = `\n  <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;margin:32px auto 0 auto;\">\n    <tr><td align=\"center\">\n      <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" style=\"${OUTER_WRAP}\">\n        <tr><td style=\"background:#222;padding:24px;color:#fff;font-size:12px;line-height:1.6;text-align:left;\">\n          <p style=\"margin:0 0 12px 0;\">\n            \uc704 \uc804\uc790\uc6b0\ud3b8 \ubc0f \uadf8\uc5d0 \ud3ec\ud568\ub41c \uc815\ubcf4\ub294 \uc704\uc5d0 \uae30\uc7ac\ub41c \uc218\uc2e0\uc778\ub9cc\uc744 \uc704\ud574 \ubc1c\uc1a1\ub418\ub294 \uac83\uc73c\ub85c\uc11c \ubcf4\uc548\uc744\n            \uc720\uc9c0\ud574\uc57c \ud558\ub294 \uc815\ubcf4 \ubc0f \ubc95\ub960\uc0c1 \ub610\ub294 \ub2e4\ub978 \uc0ac\uc720\ub85c \uc778\ud558\uc5ec \uacf5\uac1c\uac00 \uae08\uc9c0\ub41c \uc815\ubcf4\uac00 \ub4e4\uc5b4 \uc788\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n            \uadc0\ud558\uac00 \uc774 \uc804\uc790\uc6b0\ud3b8\uc758 \uc9c0\uc815 \uc218\uc2e0\uc778\uc774 \uc544\ub2c8\uba74 \uc774\ub97c \ubb34\ub2e8\uc73c\ub85c \ubcf4\uc720, \ubcf5\uc81c, \uc804\uc1a1, \ubc30\ud3ec, \uacf5\uac1c\ud560 \uc218 \uc5c6\uc73c\uba70,\n            \uc77c\ubd80\uc758 \ub0b4\uc6a9\uc774\ub77c\ub3c4 \ubcf4\uc720, \ubcf5\uc81c, \ubc30\ud3ec, \uacf5\uac1c\ud574\uc11c\ub294 \uc548\ub429\ub2c8\ub2e4. \uc798\ubabb \uc218\uc2e0\ub41c \uacbd\uc6b0\uc5d0\ub294 \uc989\uc2dc\n            <a href=\"mailto:dl_ncloud_privacy@navercorp.com\" style=\"color:#61ba7a;text-decoration:none;\">\ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc \uac1c\uc778\uc815\ubcf4\ubcf4\ud638(dl_ncloud_privacy@navercorp.com)</a>\ub85c\n            \uc5f0\ub77d\ud558\uc5ec \uc8fc\uc2dc\uace0, \uc6d0\ubcf8 \ubc0f \uc0ac\ubcf8\uacfc \uadf8\uc5d0 \ub530\ub978 \ucca8\ubd80 \ubb38\uc11c\ub97c \ubaa8\ub450 \uc0ad\uc81c\ud558\uc5ec \uc8fc\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.\n          </p>\n          <p style=\"margin:0;\">\n            This email and the information contained in this email are intended solely for the recipient(s) addressed above\n            and may contain information that is confidential and/or privileged or whose disclosure is prohibited by law or\n            other reasons. If you are not the intended recipient, any unauthorized storage, duplication, dissemination,\n            distribution or disclosure is strictly prohibited. If you received this email in error, please immediately\n            contact <a href=\"mailto:dl_ncloud_privacy@navercorp.com\" style=\"color:#61ba7a;text-decoration:none;\">NAVER Cloud Privacy</a>\n            and delete this email and any copies/attachments from your system.\n          </p>\n        </td></tr>\n      </table>\n    </td></tr>\n  </table>\n`;\n\n/* ---------- 5) \ucd5c\uc885 HTML ---------- */\nconst finalHtml = headerHtml + bodyPlaceholder + ctaHtml + footerHtml;\n\n/* ---------- 6) \ubc18\ud658 ---------- */\nreturn [\n  { json: { htmlBlocks: finalHtml } }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        180
      ],
      "id": "7a8ab316-92a2-4994-a569-b54d57cd1c34",
      "name": "Header/Footer HTML4"
    },
    {
      "parameters": {
        "fromEmail": "raphael825@naver.com",
        "toEmail": "={{ $node[\"query\"].json.address }}",
        "subject": "=Hyperclova News Letter ",
        "emailFormat": "html",
        "html": "={{ $json.htmlBlocks }}",
        "options": {}
      },
      "id": "1a706b13-4982-4a57-bc3a-5459b3434717",
      "name": "\uc774\uba54\uc77c \ubc1c\uc1a1",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2,
      "position": [
        400,
        180
      ],
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## \ub274\uc2a4\ub808\ud130 \uc804\uc1a1 \n",
        "height": 260,
        "width": 620
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        20,
        100
      ],
      "id": "f8249de6-7017-4784-bd70-6a0b133c4710",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "jsCode": "/**\n * n8n Function \u25b8 \"HTML \uc774\uba54\uc77c \uc0dd\uc131\"\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * \uc778\ud48b: \uac01 \uc544\uc774\ud15c\uc5d0 rank, title, reason, link, pubDate, description \ud544\ub4dc\uac00 \uc874\uc7ac\n * \uc544\uc6c3: [{ json: { htmlBlocks: \u2026 } }]\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n */\n\n/* 0) \uc624\ub298 \ub0a0\uc9dc */\nconst dateStr = new Date().toLocaleDateString('ko-KR', {\n  year: 'numeric', month: 'long', day: 'numeric',\n});\n\n/* 1) \uacf5\ud1b5 \uc2a4\ud0c0\uc77c */\nconst WRAPPER_STYLE = `\n  width:100%;max-width:600px;border:1px solid #d9d9d9;border-radius:8px;\n  font-family:Arial,Helvetica,sans-serif;\n`;\n\n/* 2) \ubbf8\ub9ac\ubcf4\uae30 \ube14\ub85d */\nconst previewTitles = items\n  .slice(0, 5)  // \uc0c1\uc704 5\uac1c\ub9cc \ubbf8\ub9ac\ubcf4\uae30\uc5d0 \ud45c\uc2dc\n  .map((item, idx) => `${idx + 1}. ${item.json.title}`)\n  .join('<br/>');\n\nconst previewHtml = `\n  <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;margin:0 auto 32px;\">\n    <tr><td align=\"center\">\n      <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" style=\"${WRAPPER_STYLE}\">\n        <tr><td style=\"padding:24px;\">\n          <h2 style=\"margin:0 0 16px;font-size:24px;font-weight:bold;color:#61ba7a;\">${dateStr} AI \uc8fc\uc694 \uc18c\uc2dd TOP 5</h2>\n          <p style=\"font-size:16px;line-height:1.6;color:#111;margin:0;\">${previewTitles}</p>\n        </td></tr>\n      </table>\n    </td></tr>\n  </table>\n`;\n\n/* 3) \uae30\uc0ac \uce74\ub4dc + \ud53c\ub4dc\ubc31 \ub9c1\ud06c */\nconst BASE_URL = 'https://hcx-n8n.io.naver.com/webhook/get_score';\n\n// \uc0c1\uc704 10\uac1c \uae30\uc0ac\ub9cc \ud45c\uc2dc\nconst cardsHtml = items.slice(0, 10).map((item, idx) => {\n  const a = item.json;\n\n  /* \u2500\u2500 rank \ub77c\ubca8 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  const rankLabel = a.rank\n    ? `<p style=\"font-size:14px;color:#61ba7a;margin:0 0 4px;text-align:left;font-weight:bold;\">\n         AI \uad00\ub828\ub3c4 ${a.rank}\uc704\n       </p>`\n    : '';\n\n  /* \u2500\u2500 \uc120\uc815 \uc774\uc720 (reason) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  const reasonBlock = a.reason\n    ? `<div style=\"background:#f5f5f5;padding:12px;border-radius:6px;margin:0 0 16px;\">\n         <p style=\"font-size:14px;color:#666;margin:0;font-style:italic;\">\n           \ud83d\udca1 \uc120\uc815 \uc774\uc720: ${a.reason}\n         </p>\n       </div>`\n    : '';\n\n  /* \u2500\u2500 \ubcf8\ubb38 (description) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  const body = a.description\n    ? `<p style=\"font-size:16px;line-height:1.6;margin:0 0 18px;color:#333;\">\n         ${a.description.substring(0, 200)}${a.description.length > 200 ? '...' : ''}\n       </p>`\n    : '';\n\n  /* \u2500\u2500 \ubc1c\ud589\uc77c (pubDate) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  const pubDateLabel = a.pubDate\n    ? `<p style=\"font-size:13px;color:#999;margin:0 0 12px;\">\n         \ud83d\udcc5 ${new Date(a.pubDate).toLocaleDateString('ko-KR', {\n           year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit'\n         })}\n       </p>`\n    : '';\n\n  /* \u2500\u2500 1-5 \uc810\uc218 \ub9c1\ud06c \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  const feedback = Array.from({ length: 5 }, (_, n) => n + 1)\n    .map(n => `\n      <a href=\"${BASE_URL}?url=${encodeURIComponent(a.link || a.url)}&score=${n}\"\n         style=\"display:inline-block;width:24px;font-size:16px;margin:0 4px;\n                text-decoration:none;color:#61ba7a;\">${n}</a>`)\n    .join('');\n\n  /* \u2500\u2500 \uce74\ub4dc HTML \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  return `\n    <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;margin:0 auto 32px;\">\n      <tr><td align=\"center\">\n        <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" style=\"${WRAPPER_STYLE}\">\n          <tr><td style=\"padding:24px;\">\n\n            ${rankLabel}\n\n            <h2 style=\"margin:0 0 16px;font-size:22px;line-height:1.3;\">\n              <a href=\"${a.link || a.url}\" style=\"color:#61ba7a;text-decoration:none;\">${a.title}</a>\n            </h2>\n\n            ${pubDateLabel}\n            ${reasonBlock}\n            ${body}\n\n            <a href=\"${a.link || a.url}\" style=\"color:#61ba7a;font-size:16px;font-weight:bold;text-decoration:none;\">\n              \uc790\uc138\ud788 \ubcf4\uae30 \u2192\n            </a>\n\n            <hr style=\"border:none;border-top:1px solid #d9d9d9;margin:24px 0;\"/>\n\n            <p style=\"font-size:16px;font-weight:bold;text-align:center;margin:0 0 12px;color:#111;\">\n              \uc774 \uae30\uc0ac, \uc5b4\ub560\ub098\uc694?\n            </p>\n            <p style=\"font-size:12px;color:#777;margin:0 0 12px;text-align:center;\">\n              \ubaa8\ubc14\uc77c\uc5d0\uc120 \uc544\uc9c1 \ud3c9\uc810\uc774 \uc9c0\uc6d0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.<br/>\n              \uc6f9 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c \ucc38\uc5ec\ud574 \uc8fc\uc138\uc694.\n            </p>\n\n            <div style=\"text-align:center;\">${feedback}</div>\n\n          </td></tr>\n        </table>\n      </td></tr>\n    </table>\n  `;\n}).join('');\n\n/* 4) \uacb0\uacfc \ubc18\ud658 */\nreturn [{ json: { htmlBlocks: previewHtml + cardsHtml } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        60,
        180
      ],
      "id": "86a48f4b-d03a-476d-a53f-bda389db8d7a",
      "name": "News Block HTML"
    }
  ],
  "connections": {
    "\ub124\uc774\ubc84 \ub274\uc2a4 \uac80\uc0c9 (Naver API)": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "HCX \ub274\uc2a4 \uae30\uc0ac \ub9ac\ub7ad\ud0b9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "HCX \ub274\uc2a4 \uae30\uc0ac \ub9ac\ub7ad\ud0b9": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Code2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "query": {
      "main": [
        [
          {
            "node": "\ub124\uc774\ubc84 \ub274\uc2a4 \uac80\uc0c9 (Naver API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code2": {
      "main": [
        [
          {
            "node": "News Block HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Header/Footer HTML4": {
      "main": [
        [
          {
            "node": "\uc774\uba54\uc77c \ubc1c\uc1a1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "News Block HTML": {
      "main": [
        [
          {
            "node": "Header/Footer HTML4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook \ud2b8\ub9ac\uac70": {
      "main": [
        [
          {
            "node": "query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "81e38421-506c-4ff6-bb58-e54cc39c358b",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "wq4UXGzUmmGSXeB8",
  "tags": []
}