주현영
주현영
🎻 루키 파트너
🏡 내집마련 찐친

금, 외환 데일리 시장분석 뉴스레터 자동화

소개

금, 외환 거래 시장은 24/5 멈추지 않죠?

기본적 분석이 필수인데 매일 이걸 직접 찾아보는 건 매우매우 귀찮습니다.

그래서 n8n과 chatGPT를 통해 데일리 시장분석 결과를 메일로 자동화 해보았습니다!

진행 방법

Tip: 어떤 도구를 사용했고, 어떻게 활용하셨나요?

  • n8n과 chatGPT

Tip: 활용 이미지나 캡처 화면을 꼭 남겨주세요.

  • n8n 노드 화면

프로세스 흐름을 보여주는 웹 페이지의 스크린 샷
  • 뉴스레터 입력 화면

한국 지불 페이지의 스크린 샷
  • 뉴스레터 전송화면

    한국어 텍스트가 포함 된 웹 사이트의 스크린 샷

Tip: 코드 전문은 코드블록에 감싸서 작성해주세요. (n8n 코드블록 전문)

{
  "nodes": [
    {
      "parameters": {
        "formTitle": "뉴스레터 주제 입력",
        "formDescription": "뉴스레터 자동화를 위한 주제 입력",
        "formFields": {
          "values": [
            {
              "fieldLabel": "주제를 입력하세요",
              "requiredField": true
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.2,
      "position": [
        -420,
        60
      ],
      "id": "93d7d491-9c7b-45ed-b5d4-6389c122a90b",
      "name": "On form submission",
      "webhookId": "dc382f51-1df1-4f59-9075-4a09d9da8fb4"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "chatgpt-4o-latest",
          "mode": "list",
          "cachedResultName": "CHATGPT-4O-LATEST"
        },
        "messages": {
          "values": [
            {
              "content": "=주제: {{ $json['주제를 입력하세요'] }}\n주제에 대한 뉴스레터 내용을 만들어\n한국어로, 친절한 말투. MZ용어 사용.\n\nJSON으로 응답\ntitle 15자\nintro 100자\nbody1 200자\nbody2 200자\nbody3 200자\nconclusion 150자\n\n"
            }
          ]
        },
        "jsonOutput": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        -220,
        60
      ],
      "id": "25de602a-f3cd-45f0-83c6-a0a359850d2e",
      "name": "Message a model1",
      "credentials": {
        "openAiApi": {
          "id": "rAYzmRwO2GffwIte",
          "name": "Japan AI"
        }
      }
    },
    {
      "parameters": {
        "sendTo": "={{ $json['이메일주소'] }}",
        "subject": "={{ $('Message a model1').item.json.message.content.title }}",
        "message": "=<!DOCTYPE html> <html lang=\"ko\"> <head>     <meta charset=\"UTF-8\">     <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">     <title>{{ $('Message a model1').item.json.message.content.title }}</title> </head> <body style=\"margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f8fafc; color: #334155;\">          <!-- Main Container -->     <div style=\"max-width: 600px; margin: 0 auto; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\">                  <!-- Header -->         <div style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 30px; text-align: center;\">             <h1 style=\"color: #ffffff; font-size: 28px; font-weight: 700; margin: 0; letter-spacing: -0.5px;\"> {{ $('Message a model1').item.json.message.content.title }}</h1>             <div style=\"width: 60px; height: 2px; background-color: #ffffff; margin: 20px auto 0; opacity: 0.8;\"></div>         </div>                  <!-- Content Container -->         <div style=\"padding: 40px 30px;\">                          <!-- Intro Section -->             <div style=\"margin-bottom: 40px;\">                 <div style=\"display: inline-block; background-color: #f1f5f9; color: #475569; padding: 8px 16px; border-radius: 20px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 20px;\">                     Intro                 </div>                 <p style=\"font-size: 16px; line-height: 1.6; color: #475569; margin: 0;\">            {{ $('Message a model1').item.json.message.content.intro }}                </p>             </div>                          <!-- Body Section 1 -->             <div style=\"margin-bottom: 40px; padding: 25px; background-color: #f8fafc; border-radius: 12px; border-left: 4px solid #667eea;\">                 <div style=\"display: inline-block; background-color: #667eea; color: #ffffff; padding: 6px 12px; border-radius: 16px; font-size: 11px; font-weight: 600; margin-bottom: 15px;\">             첫번째            </div>                 <p style=\"font-size: 15px; line-height: 1.7; color: #475569; margin: 0;\">   {{ $('Message a model1').item.json.message.content.body1 }}           </p>             </div>                          <!-- Body Section 2 -->             <div style=\"margin-bottom: 40px; padding: 25px; background-color: #fef7ff; border-radius: 12px; border-left: 4px solid #a855f7;\">                 <div style=\"display: inline-block; background-color: #a855f7; color: #ffffff; padding: 6px 12px; border-radius: 16px; font-size: 11px; font-weight: 600; margin-bottom: 15px;\">                     두번째             </div>                 <p style=\"font-size: 15px; line-height: 1.7; color: #475569; margin: 0;\">    {{ $('Message a model1').item.json.message.content.body2 }}              </p>             </div>                          <!-- Body Section 3 -->             <div style=\"margin-bottom: 40px; padding: 25px; background-color: #f0fdf4; border-radius: 12px; border-left: 4px solid #22c55e;\">                 <div style=\"display: inline-block; background-color: #22c55e; color: #ffffff; padding: 6px 12px; border-radius: 16px; font-size: 11px; font-weight: 600; margin-bottom: 15px;\">    세번째    </div>                 <p style=\"font-size: 15px; line-height: 1.7; color: #475569; margin: 0;\">               {{ $('Message a model1').item.json.message.content.body3 }}            </p>             </div>                          <!-- Conclusion Section -->             <div style=\"background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); padding: 30px; border-radius: 12px; text-align: center; margin-bottom: 30px;\">                 <div style=\"display: inline-block; background-color: rgba(255, 255, 255, 0.3); color: #92400e; padding: 8px 16px; border-radius: 20px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 20px;\">                     결론                 </div>                 <p style=\"font-size: 16px; line-height: 1.6; color: #92400e; margin: 0; font-weight: 500;\">                {{ $('Message a model1').item.json.message.content.conclusion }}          </p>             </div>                          <!-- Footer -->             <div style=\"border-top: 1px solid #e2e8f0; padding-top: 30px; text-align: center;\">                 <p style=\"font-size: 14px; color: #64748b; margin: 0; line-height: 1.5;\">                     이 뉴스레터가 도움이 되셨나요?<br>                     <a href=\"#\" style=\"color: #667eea; text-decoration: none; font-weight: 500;\">피드백 남기기</a> |                      <a href=\"#\" style=\"color: #667eea; text-decoration: none; font-weight: 500;\">구독 취소</a>                 </p>                 <div style=\"margin-top: 20px;\">                     <span style=\"font-size: 12px; color: #94a3b8;\">© 2025 뉴스레터. All rights reserved.</span>                 </div>             </div>                      </div>              </div>      </body> </html>",
        "options": {}
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        440,
        60
      ],
      "id": "f96dd5b0-c44d-494e-ae03-641fd3f708f2",
      "name": "Send a message1",
      "webhookId": "c43f3096-6921-44be-9418-f2797938d2a4",
      "credentials": {
        "gmailOAuth2": {
          "id": "YNfvEpyxHUC03rFg",
          "name": "허세임 업무자동화 실습"
        }
      }
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "1xWGxnYoOED_H0VD8LV8LAaLmaqTa4coCBSIsNHOy6xI",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "주소록",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xWGxnYoOED_H0VD8LV8LAaLmaqTa4coCBSIsNHOy6xI/edit#gid=0"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.6,
      "position": [
        140,
        60
      ],
      "id": "89808c99-2406-48d8-b43e-2a0e2b401836",
      "name": "Get row(s) in sheet1",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "02q69CEdeHxZPYwg",
          "name": "업무자동화 실습 허세임"
        }
      }
    }
  ],
  "connections": {
    "On form submission": {
      "main": [
        [
          {
            "node": "Message a model1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model1": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet1": {
      "main": [
        [
          {
            "node": "Send a message1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "25a9dffef9e60220aad3523f1e08dffced1eef7c8de65fa698b54fd39a495364"
  }
}

결과와 배운 점

내 계정의 Google API를 연동하려고 하는데, 50번의 실패 끝에...

허세임님이 줌수업 때 알려준 계정을 사용했습니다 🙌

역시 모방은 창조의 어머니!👍

사실 오늘의 사례는 n8n과 친해지기 실습이었구요!

정말 필요한 문제는 따로 있는데요.

퇴근하면 차트에 손도 대기 싫은 투자자들을 위해 고민 중인 것이 있습니다!

외환 거래 소프트웨어의 스크린 샷

문제점

  1. 현재의 Monitoring Account 노션페이지는 계좌 ID, PW 리스트업 형식임.

해결방법

  1. 노션 페이지에 Web 형식 계좌화면을 임베딩한 후, 핸드폰에서도 PC 화면을 보는 것처럼 자세하게 시각화하기 (MTS에서 HTS 화면을 보게 만든다고 보면됨)

  2. 매일 VPS 화면을 캡처해서 뉴스레터 혹은 카톡 혹은 텔레그램으로 보내주기

과연 가장 효율적인 방법은 무엇일지 고민해봐야겠습니다ㅎㅎ

To be continued~~

도움 받은 글 (옵션)

참고한 지피터스 글이나 외부 사례를 알려주세요.

(내용 입력)

👉 이 게시글도 읽어보세요