GPters 과제의 마지막 단계 - 내 페이지에 LLM을 활용한 위키 만들기

오늘 뭘 했나

지난 회고에서 "다음은 위키만 만들면 된다"고 적어뒀던, PRD MVP의 마지막 남은 항목을 끝낸 날이다. 텔레그램 발송은 며칠째 문제없이 잘 오고 있어서, 오늘은 위키만 붙이면 되는 상황이었다.

① 생각보다 설계할 게 많았다 — 처음엔 "기사에서 용어 뽑아서 md 파일로 저장" 정도로 간단할 줄 알았다. 그런데 파고들수록 정할 게 계속 나왔다.

  • 섹터를 어떻게 나눌까 → 텔레그램도 반도체/배터리/AI로 나눠 보내고 있으니 위키도 3페이지로 통일.

  • HBM처럼 주목도 높은 용어는 기사가 여러 개 붙을 텐데 → 정의를 중복시키지 말고 같은 용어 아래 링크만 쌓자.

  • 그런데 1년 쓰면 링크 칸이 너무 길어지지 않나? → 언급 횟수를 숫자로 남기고 링크는 최근 3개만 유지.

  • 링크 나열보다 "왜 지금 이게 뜨는지"가 더 유용하지 않나? → "최근 동향" 칸을 추가해서 한두 문장으로 갱신.

이 왔다 갔다 하는 과정에서 "위키란도 쉬울 줄 알았는데 설계해야 할 것이 많네..."라는 말이 절로 나왔다. 결국 용어 하나당 이런 형태로 정했다:

## 용어명

설명 (처음 등장할 때 한 번만 기록, 이후 안 바뀜)

**최근 동향** (날짜 기준, 언급 N회): 왜 지금 뜨는지 1~2문장

<details><summary>근거 기사</summary>

- 최근 기사 링크 3개까지

</details>

② GitHub 토큰 — 404의 함정 — 토큰을 발급해서 n8n에 넣었는데 계속 404 Not Found가 났다. 경로가 틀린 줄 알고 한참 봤는데, 알고 보니 토큰 발급할 때 Repository access를 Public repositories로 잡아둔 게 원인이었다. 내 저장소는 private인데, GitHub은 권한 없는 private 저장소에 대해 "권한 없음(403)"이 아니라 "그런 거 없음(404)"으로 응답한다. 저장소 존재 자체를 숨기는 보안 설계였다. Only select repositories + Contents: Read and write로 재발급하니 바로 됐다.

③ 노드 6개 붙이기 — 기존에 잘 돌아가는 텔레그램 흐름은 건드리지 않고, Aggregate에서 가지를 하나 더 뻗는 방식으로 갔다.

Aggregate ─┬→ Basic LLM Chain → 텔레그램          (기존, 그대로)

└→ 위키용 LLM → 섹터분리 → GitHub읽기 → 병합 → GitHub쓰기 (신규)

텔레그램용 LLM은 "사람이 읽을 문장"을 만들지만, 위키용은 JSON이 필요해서 별도 LLM 노드를 만들고 Structured Output Parser를 붙여 형식을 강제했다.

④ 버그 4개 — 오늘의 진짜 알맹이 — 여기서부터 계속 걸렸다.

  • 버그1 · 프롬프트가 통째로 무시됐다. 실행하면 세 섹터가 전부 "없음"으로 나왔다. 그런데 똑같은 데이터로 텔레그램은 멀쩡하게 3섹터를 다 채워서 보냈다. 이 대비가 단서였다 — 데이터 문제가 아니라 위키용 LLM만의 문제. 원인은 프롬프트 칸이 Expression이 아니라 Fixed 모드여서, {{ JSON.stringify($json) }}가 기사 목록으로 치환되지 않고 글자 그대로 Claude에게 전달된 것. 기사가 하나도 안 보이니 "없음"이라고 답할 수밖에.

  • 버그2 · 반도체만 저장됐다. 배터리·AI 페이지는 계속 비어 있었다. 병합 코드가 .first()(첫 번째 항목만)를 쓰고 있어서, 섹터 3개가 들어와도 항상 첫 개만 처리하고 나머지를 버린 것이었다. .all()로 받아서 반복문으로 도는 식으로 고쳤다.

  • 버그3 · 같은 용어가 매일 새 항목으로 쌓였다. 실행할 때마다 이렇게 갈라졌다.

    ## 차세대 HBM(High Bandwidth Memory)

    ## 차세대 HBM (Processing-in-Memory) ← 괄호 안이 통째로 바뀜

    LLM이 용어 이름을 매번 조금씩 다르게 쓰는 게 문제였다. 처음엔 띄어쓰기만 무시하도록 고쳤는데 그걸로도 안 잡혔고, 결국 괄호 안 설명을 통째로 잘라내서 차세대 HBM으로 통일했다.

  • 버그4 · GitHub 409 충돌. 3개 파일을 저장하려는데 일부만 성공하고 나머지가 실패했다. 에러 메시지가 결정적이었다: is at ee01942... but expected d5ac83c... — 세 개의 저장 요청이 거의 동시에 날아가면서 서로 자리를 뺏은 것이었다. 파일 자체엔 문제가 없고 순서만 어긋난 상황. Batching(1건씩, 1.5초 간격) + Retry On Fail로 해결했다.

⑤ RSS 소스 3개로 확장 — 지난 회고에 적어뒀던 "배터리 섹터가 자주 빈다" 문제도 오늘 같이 잡았다.

  • 비즈니스포스트를 넣으려 했는데 403이 났다. 확인해보니 User-Agent(접속 프로그램 이름)가 비어 있으면 차단하는 사이트였는데, n8n의 RSS Read 노드는 옵션이 SSL 관련 하나뿐이라 이걸 바꿀 수가 없었다. 우회하려면 노드 4개(HTTP Request → XML → Split Out → Limit)가 필요해서, 깔끔하게 한경 IT로 대체했다.

  • 대신 **디일렉(THE ELEC)**을 넣었다. 반도체·배터리 전문 매체라 딱 맞았고, 실제로 오늘 배터리 항목(LFP 배터리)이 여기서 잡혔다.

  • 세 피드를 합치려고 Merge 노드(Append, 입력 3개)를 Remove Duplicates 앞에 끼웠다.

⑥ 결과 — 마지막 실행에서 커밋 3개가 올라가고 세 페이지가 전부 채워졌다.

페이지

오늘 들어온 용어

출처

반도체

차세대 HBM

한국경제

배터리

LFP 배터리

디일렉

AI

AI 에이전트

한국경제

GitHub에 커밋되면 Vercel이 자동으로 재배포까지 해줘서, n8n → GitHub → 사이트 반영이 전부 자동으로 이어진다는 것도 오늘 확인했다.

그때그때 느낀 것

  • 솔직히 답답했다. 쉬울 줄 알았던 게 설계부터 오래 걸렸고, 그다음엔 버그가 하나 잡으면 또 하나 나왔다.

  • 특히 "성공했다" 싶을 때마다 확인해보면 실제로는 반쯤만 된 상태였던 게 힘 빠졌다 — n8n은 초록불인데 GitHub엔 커밋이 없다든가, 반도체만 저장돼 있다든가.

  • 그래도 마지막에 세 페이지가 다 채워진 걸 보고 위안이 됐다.

배운 것 (누적)

  • private 저장소는 권한이 없으면 403이 아니라 404가 뜬다. GitHub이 일부러 저장소 존재 자체를 숨기는 설계다. "경로가 틀렸나?" 하고 헤매기 쉬운데, 토큰 권한부터 의심하는 게 빠르다.

  • fine-grained 토큰은 Repository access를 Only select repositories로 잡아야 private 저장소에 접근된다. Public repositories로 두면 내 저장소인데도 안 보인다.

  • n8n에서 {{ }}를 쓰려면 그 칸이 Expression 모드여야 한다. Fixed 모드면 글자 그대로 전달된다. 에러가 안 나고 조용히 이상한 결과만 나오기 때문에 더 위험하다.

  • 이럴 때 **"같은 데이터로 다른 노드는 잘 되는가"**를 비교해보면 원인이 빠르게 좁혀진다. 오늘은 텔레그램이 멀쩡한 걸 보고 "데이터 문제 아님"이 바로 확정됐다.

  • LLM은 같은 용어를 매번 똑같이 쓰지 않는다. 이름으로 뭔가를 매칭하는 구조라면, 표기 흔들림을 정리하는 장치(괄호 제거·공백 무시 같은)를 반드시 넣어야 한다.

  • GitHub API로 같은 저장소에 여러 파일을 연달아 저장하면 409가 난다. 각 요청이 "내가 본 마지막 상태 다음에 쓸게"라고 하는데 이미 다른 요청이 써버려서 생기는 충돌. 하나씩 간격을 두고 보내면(Batching) 해결된다.

  • n8n에서 노드를 Deactivate하면 입력이 그대로 출력으로 흘러나간다. 완전히 끊기는 게 아니라 통과(pass-through)라서, 엉뚱한 데이터가 뒤로 넘어갈 수 있다.

  • 테스트할 때 Remove Duplicates가 오늘 기사를 이미 다 처리했으면 뒤쪽 노드가 아예 안 돈다(Node was not executed). 잠깐 꺼두고 테스트한 뒤 다시 켜는 걸 잊지 말 것.

  • RSS 사이트마다 접근 정책이 다르다. User-Agent가 비어 있으면 막는 곳이 있는데, RSS Read 노드로는 이걸 못 바꾼다. 우회 비용이 크면 다른 매체로 갈아타는 게 합리적이다.

다음 계획

  • 내일 예약 실행에서 세 페이지에 새 용어가 실제로 하나씩 쌓이는지 확인한다.

  • "최근 동향"을 지금은 그날 뽑은 문장으로 통째로 덮어쓰는데, 원래 설계는 기존 동향 + 새 기사를 LLM이 다시 요약하는 것이었다. 여유가 생기면 업그레이드한다.

  • 아직 못 한 것: 실패 알림(Error Trigger → 텔레그램).

오늘 나온 개념: HBM / LFP 배터리 / AI 에이전트 / fine-grained PAT / base64 / sha / 409 Conflict / Batching

1
1개의 답글
밀어주고 끌어주는

온·오프라인 AI 스터디

AI로 어디까지 할 수 있는지
직접 확인하실 분만 신청하세요.