한 줄 요약: 매일 텔레그램으로만 받고 흘려보내던 뉴스 키워드를, n8n이 GitHub API로 직접 커밋해서 위키에 쌓도록 만들었다. 같은 용어가 다시 나오면 새 항목을 만들지 않고 “언급 횟수”와 “최근 동향”만 갱신되는 구조라, 1년을 써도 페이지가 지저분해지지 않는다.
이런 분께 도움이 돼요: AI가 뽑아준 결과를 매번 복사·붙여넣기로 저장하고 있는 분, n8n에서 GitHub API를 쓰고 싶은 분, 그리고 “에러는 안 나는데 결과만 이상한” 자동화 버그에 발목 잡혀본 분.
Before — 어제까지의 문제
매일 오후에 텔레그램으로 반도체·배터리·AI 키워드가 잘 도착하고 있었다. 문제는 거기서 끝난다는 것이었다.
- 메시지는 스크롤에 묻혀 사라진다. 2주 전에 뭘 받았는지 다시 찾기 어렵다.
- “HBM이 요즘 왜 자주 나오지?”라는 감각이 안 쌓인다. 매번 처음 보는 것처럼 읽게 된다.
- 이직 포트폴리오로 보여줄 게 텔레그램 캡처밖에 없다.
PRD에도 뽑힌 키워드를 위키 개념 페이지에 자동 저장이 MVP 기능으로 적혀 있었는데, 이게 마지막까지 남은 항목이었다.
설계부터 오래 걸렸다 (쉬울 줄 알았다)
처음엔 “용어 뽑아서 md 파일로 저장” 정도로 생각했다. 그런데 막상 정하려니 계속 질문이 나왔다.
| 고민 | 결정 |
|---|---|
| 섹터를 어떻게 나누지? | 텔레그램도 3섹터로 보내니 위키도 3페이지로 통일 |
| HBM처럼 자주 나오는 용어는 기사가 여러 개 붙을 텐데? | 정의를 중복시키지 말고 같은 용어 아래 링크만 추가 |
| 1년 쓰면 링크 칸이 너무 길어지지 않나? | 언급 횟수를 숫자로 남기고, 링크는 최근 3개만 유지 |
| 링크 나열보다 “왜 지금 뜨는지”가 더 유용하지 않나? | ”최근 동향” 칸 추가 |
이 왔다 갔다 하는 과정에서 “위키란도 쉬울 줄 알았는데 설계할 게 많네…” 소리가 절로 나왔다. 하지만 이걸 먼저 정해둔 덕분에 실제 구현은 오히려 빨랐다. 최종 형태는 이렇다.
## 차세대 HBM
HBM(고대역폭 메모리)은 GPU 옆에 붙어 데이터를 빠르게 전달하는 메모리인데,
차세대 HBM은 여기서 한 발 더 나아가 메모리 안에서 직접 연산까지 처리하는 기술입니다.
**최근 동향** (2026-08-24 기준, 언급 1회): 삼성전자가 GPU 없이도 메모리 칩 자체에서
AI 연산을 수행할 수 있는 차세대 HBM을 공개하며 반도체 업계의 주목을 받았습니다.
<details><summary>근거 기사</summary>
- 2026-08-24: [기사 보기](https://...)
</details>
핵심은 “설명은 한 번만, 동향은 매번” 이다. 처음 등장할 때 쓴 설명은 그대로 두고, 그 용어가 다시 나오면 언급 횟수가 올라가고 최근 동향만 새로 갱신된다. 이러면 페이지 길이는 용어 개수에만 비례하고, 개별 항목은 1년을 써도 항상 6~7줄로 고정된다.
어떻게 만들었나 (따라 하실 수 있게)
0. 원칙 — 잘 되는 건 건드리지 않는다
이미 매일 잘 돌아가는 텔레그램 흐름이 있었다. 여기에 손대면 멀쩡한 게 망가질 수 있으니, Aggregate에서 가지를 하나 더 뻗는 병렬 구조로 갔다.
┌→ Basic LLM Chain → 텔레그램 (기존, 그대로)
RSS 3개 → Merge → 중복제거 → Aggregate
└→ 위키용 LLM → 섹터분리 → GitHub읽기 → 병합 → GitHub쓰기 (신규)
📷 여기에 n8n 캔버스 전체 스크린샷을 넣으면 구조가 한눈에 보여요
1. GitHub 토큰 발급 (여기서 첫 번째로 막혔다)
n8n이 내 저장소에 글을 쓰려면 열쇠가 필요하다. GitHub 토큰 발급 페이지에서 만든다.
- Token name:
n8n-wiki-writer - Expiration:
90 days - Repository access:
Only select repositories→ 내 저장소 선택 - Repository permissions → Contents:
Read and write
n8n에서는 GitHub 노드가 아니라 **HTTP Request의 Generic Credential Type → Bearer Auth**로 등록한다.
2. 위키 저장용 LLM 노드 (JSON으로 받기)
텔레그램용 LLM은 “사람이 읽을 문장”을 만들지만, 파일에 저장하려면 기계가 읽을 JSON이 필요하다. 그래서 별도 Basic LLM Chain을 만들고 프롬프트를 이렇게 넣었다.
아래는 오늘 수집된 기사 목록입니다 (JSON):
{{ JSON.stringify($json) }}
이 중에서 반도체/배터리/AI 3개 섹터 각각에서 가장 중요한 기사를 하나씩 골라
아래 형식의 JSON으로만 답하세요.
- 용어: 그 기사의 핵심 키워드/용어
- 설명: 그 용어가 무엇인지 처음 보는 사람도 이해할 수 있게 쉬운 설명 (1~2문장)
- 사례: 오늘 이 용어가 왜 뉴스에 나왔는지 (1~2문장)
- 원문: 그 기사의 링크
해당 섹터에 기사가 없으면 용어에 "없음", 나머지는 빈 문자열로 답하세요.
출력 규칙: 설명 문장이나 마크다운 코드블록 없이, JSON 객체 하나만 출력하세요.
여기에 Require Specific Output Format 토글을 켜고 Structured Output Parser를 연결해서 형식을 강제했다. 이러면 AI가 형식을 어길 여지가 줄어든다.
⚠️ 두 가지 함정
Source for Prompt가 기본값Connected Chat Trigger Node로 되어 있다 →Define below로 바꿔야 직접 쓴 프롬프트가 들어간다.- 그러면 아래에 빈
Prompt 1이 자동으로 생기는데, 이걸 삭제하지 않으면 실행 에러가 난다.
3. GitHub에서 읽고 → 합치고 → 다시 쓰기
GitHub API로 파일을 수정하려면 읽기 → 수정 → 쓰기 세 단계가 필요하다. 그냥 덮어쓸 수 없고, “내가 본 버전이 이거였다”는 증표(sha)를 같이 보내야 한다.
읽기 (HTTP Request, GET)
https://api.github.com/repos/{내계정}/{저장소}/contents/{{ $json.path }}
헤더 2개: Accept: application/vnd.github+json, X-GitHub-Api-Version: 2022-11-28
쓰기 (HTTP Request, PUT) — 같은 URL에 Body 3개를 보낸다.
| 필드 | 값 |
|---|---|
message | 커밋 메시지 (예: 위키 자동 업데이트) |
content | 새 파일 내용을 base64로 인코딩한 것 |
sha | GET에서 받은 값 (이게 없으면 거절당한다) |
사이의 병합 Code 노드가 실제 로직을 담당한다. 기존 내용을 풀어서 같은 용어가 있는지 찾고, 있으면 언급 횟수를 올리고 링크를 밀어내고, 없으면 새 섹션을 맨 아래 붙인다.
막힘 → 해결: 조용히 틀리는 버그 4개
여기서부터가 오늘의 진짜 알맹이였다. 네 개 다 에러 메시지가 안 뜨거나, 떠도 엉뚱한 걸 가리켰다.
버그 1 — n8n은 초록불인데 GitHub엔 아무것도 없다
PUT 노드가 성공(초록 체크)했는데 커밋이 안 올라갔다. 원인은 Method가 아직 GET이었던 것. GET 노드를 복제해서 PUT을 만들었는데 Method 바꾸는 걸 깜빡했다. 요청 자체는 성공하니 n8n은 성공으로 표시하고, 실제로는 파일을 읽기만 한 것이다.
💡 구분법: PUT 노드 출력에
commit항목이 있으면 진짜 커밋된 것.content/sha만 있으면 GET처럼 읽기만 한 것이다.
버그 2 — 프롬프트가 통째로 무시됐다
실행하면 세 섹터가 전부 없음으로 나왔다. 기사가 51건이나 들어왔는데도.
결정적 단서는 똑같은 데이터로 텔레그램은 멀쩡하게 3섹터를 다 채워서 보냈다는 것이었다. 데이터 문제가 아니라 위키용 LLM만의 문제로 좁혀졌다.
원인은 프롬프트 칸이 Expression이 아니라 Fixed 모드였던 것. n8n에서 {{ }}는 Expression 모드일 때만 실제 값으로 바뀐다. Fixed면 {{ JSON.stringify($json) }}라는 글자 그대로 AI에게 전달된다. 기사가 하나도 안 보이니 “없음”이라고 답할 수밖에 없었던 것이다.
💡 이게 제일 무서운 종류의 버그다. 에러가 안 나고 조용히 이상한 결과만 나온다.
버그 3 — 반도체만 저장되고 배터리·AI는 계속 비어 있었다
병합 코드가 $input.first()(첫 번째 항목만)를 쓰고 있었다. 섹터 3개가 들어와도 항상 첫 개만 처리하고 나머지를 버린 것. .all()로 받아서 반복문으로 도는 구조로 바꿨다.
버그 4 — 같은 용어가 매일 새 항목으로 쌓였다
실행할 때마다 이렇게 갈라졌다.
## 차세대 HBM(High Bandwidth Memory)
## 차세대 HBM (Processing-in-Memory) ← 괄호 안이 통째로 바뀜
AI는 같은 용어를 매번 똑같이 쓰지 않는다. 처음엔 띄어쓰기만 무시하도록 고쳤는데 그걸로도 안 잡혔고, 결국 괄호 안 설명을 통째로 잘라내서 차세대 HBM으로 통일했다.
용어: d.용어.replace(/\s*[((].*?[))]\s*/g, '').trim(),
버그 5(보너스) — GitHub 409 충돌
3개 파일을 저장하는데 일부만 성공했다. 에러 메시지가 결정적이었다.
409 - "is at ee01942... but expected d5ac83c..."
세 개의 저장 요청이 거의 동시에 날아가면서 서로 자리를 뺏은 것이다. 세 명이 같은 노트에 동시에 쓰려는데 각자 “내가 본 마지막 페이지 다음에 쓸게”라고 해서 충돌한 상황. 파일 자체엔 문제가 없고 순서만 어긋난 것이라, 하나씩 간격을 두고 보내면 해결된다.
- PUT 노드 → Options →
Batching: Items per Batch1, Batch Interval1500 - PUT 노드 → Settings 탭 →
Retry On Fail: Max Tries3, Wait3000
덤 — RSS 소스도 3개로 늘렸다
“배터리 섹터가 자주 빈다”는 문제도 같이 잡았다. RSS Read 노드 3개를 만들고 Merge 노드(Mode: Append, Number of Inputs: 3)로 합쳐서 기존 중복제거 노드에 넘겼다.
여기서도 하나 막혔다. 비즈니스포스트를 넣으려는데 403이 났다. 확인해보니 User-Agent(접속 프로그램 이름)가 비어 있으면 차단하는 사이트였는데, n8n의 RSS Read 노드는 옵션이 SSL 관련 하나뿐이라 이걸 바꿀 수가 없었다.
우회하려면 노드 4개(HTTP Request → XML → Split Out → Limit)를 붙여야 했다. 잠깐 고민하다 한경 IT로 갈아탔다. 대신 디일렉(THE ELEC)을 추가했는데 — 반도체·배터리 전문 매체라 오히려 더 잘 맞았고, 실제로 그날 배터리 항목(LFP 배터리)이 여기서 잡혔다.
💡 완벽하게 뚫는 것만이 답은 아니다. 우회 비용이 크면 대체재를 찾는 게 합리적일 때가 있다.
After — 결과
마지막 실행에서 커밋 3개가 올라가고 세 페이지가 전부 채워졌다.
| 페이지 | 들어온 용어 | 출처 |
|---|---|---|
| 반도체 | 차세대 HBM | 한국경제 |
| 배터리 | LFP 배터리 | 디일렉 |
| AI | AI 에이전트 | 한국경제 |
| Before | After | |
|---|---|---|
| 저장 | 텔레그램 메시지 (스크롤에 묻힘) | 위키에 영구 누적 |
| 반복 용어 | 매번 처음 보는 것처럼 | 언급 N회로 추이가 보임 |
| 손이 가는 정도 | 복붙해서 정리 | 0 — 완전 자동 |
| 사이트 반영 | 수동 배포 | GitHub 커밋 → Vercel 자동 재배포 |
n8n이 커밋하면 Vercel이 자동으로 재배포까지 해줘서, n8n → GitHub → 사이트가 전부 하나로 이어진다. 이걸로 PRD에 적어둔 MVP 4개가 사실상 다 끝났다.
가져가실 것 — 자동화 버그 자가진단 체크리스트
오늘 겪은 걸 정리하면, “에러는 없는데 결과가 이상할 때” 이 순서로 보면 빠르다.
- 결과가 전부 비어 있다 →
{{ }}가 들어간 칸이 Expression 모드인지 확인. Fixed면 글자 그대로 전달된다. - 여러 개 중 하나만 처리된다 → 코드에
.first()가 있는지 확인..all()+ 반복문으로 바꾼다. - 성공했다는데 결과물이 없다 → 요청 Method가 맞는지, 출력에 기대한 항목(
commit같은)이 있는지 확인. - 같은 항목이 자꾸 새로 생긴다 → AI가 만든 이름으로 매칭하고 있다면, 표기 흔들림을 정리하는 장치가 필요하다.
- 여러 개 중 일부만 실패한다 → 동시 요청 충돌을 의심. 하나씩 간격을 두고(Batching) 보낸다.
- 뒤쪽 노드가 아예 안 돈다(
Node was not executed) → 앞에서 데이터가 0건이 된 것. 중복제거 노드가 범인인 경우가 많다.
솔직한 후기
답답했다. 쉬울 줄 알았던 게 설계부터 오래 걸렸고, 그다음엔 버그가 하나 잡으면 또 하나 나왔다. 특히 “성공했다” 싶을 때마다 확인해보면 실제로는 반쯤만 된 상태였던 게 제일 힘 빠졌다 — n8n은 초록불인데 GitHub엔 커밋이 없다든가, 반도체만 저장돼 있다든가.
그래도 마지막에 세 페이지가 다 채워진 걸 보고 위안이 됐다. 초록불이 곧 성공은 아니라는 것, 그리고 끝을 직접 열어서 눈으로 확인해야 한다는 것 — 오늘 제일 크게 배운 건 이거였다.