
Telegram, n8n, AWS Bedrock을 이용한 문서 분류 시스템 구축 — 셀프 호스팅 AI 문서 분석기를 만든 6가지 결정 사항
요약
Telegram, n8n, AWS Bedrock을 활용하여 개인용 문서 분류 및 요약 시스템을 구축하는 과정을 다룹니다. 도메인이 없는 환경에서 셀프 서명 인증서와 Nginx를 사용하여 웹훅을 설정하고 EC2 상에 프로덕션 환경을 구현하는 실무적인 팁을 제공합니다.
핵심 포인트
- 도메인 없이 셀프 서명 인증서와 Nginx로 Telegram 웹훅 구현
- n8n을 활용한 워크플로우 오케스트레이션 및 PDF 텍스트 추출
- AWS Bedrock을 이용한 효율적인 문서 요약 및 분류
- EC2 환경에서의 보안 및 네트워크 구성 트레이드오프 분석
제 모바일로 들어오는 문서의 양은 제가 읽을 수 있는 능력을 앞지르고 있습니다. 연구 논문, 기사, 도서 등 — 여러 채널을 통해 PDF 형태로 공유되는 속도가 개인이 처리할 수 있는 속도보다 빠릅니다. 문제는 '어떻게 더 많이 읽을 것인가?'가 아니라, '어떻게 30분이 아닌 30초 안에 무엇이 내 주의를 끌 가치가 있는지 결정할 것인가?'입니다.
그래서 저는 이 분류 (triage) 시스템을 구축했습니다.
Telegram은 웹훅 (webhook)에 대해 HTTPS를 요구합니다. 하지만 저는 인증서를 연결할 도메인이 없었습니다. 셀프 서명 인증서 (self-signed cert), Nginx 프록시 (proxy), 그리고 역공학된 비밀 토큰 (secret token)을 사용하여, AWS Bedrock이 사고를 담당하고 EC2 위에서 작동하는 PDF 요약 봇을 어떻게 프로덕션 환경에 올렸는지 소개합니다.
요약 (TL;DR): 도메인 없음 → Telegram API에 셀프 서명 인증서 업로드 → Nginx TLS 종단 (termination) → n8n 오케스트레이션 (orchestration) → Bedrock 요약. 액세스 키 (access keys) 없음. 전체 아키텍처는 아래와 같습니다.
목차
- 제약 사항 (Constraints)
- 아키텍처: EC2 상의 Telegram에서 Bedrock까지
- 주요 설계 결정 사항
- 가장 먼저 실패한 것
- 실제로 배포된 구현체
- 다르게 했을 것들
- 설계자를 위한 시사점
제약 사항 (Constraints)
| 제약 사항 | 값 |
|---|---|
| 도메인 | 사용 가능하지 않음 — Route 53 호스팅 영역 없음, ACM 인증서 발급 불가 |
| ... |
아키텍처: EC2 상의 Telegram에서 Bedrock까지
데이터 흐름: 사용자 PDF 전송 → Telegram이 EC2:443으로 웹훅 POST 전달 → Nginx가 TLS를 종단하고 n8n:5678로 프록시 → n8n이 파일을 다운로드하고 텍스트를 추출한 뒤 Bedrock을 호출 → Telegram Bot API를 통해 응답 전송.
주요 설계 결정 사항
모든 아키텍처는 명시적으로 이루어진 트레이드오프 (trade-offs)의 집합입니다. 이 시스템을 형성한 결정 사항들은 다음과 같습니다:
| # | 결정 사항 | 이유 | 수용된 트레이드오프 (Trade-off) |
|---|---|---|---|
| 1 | Self-signed cert + Nginx (도메인 불필요) | Telegram은 setWebhook API를 통해 업로드된 인증서를 수락함; 도메인 의존성을 완전히 제거함 | 브라우저에서 인증서 경고 표시; 웹훅 (webhook) 등록이 수동으로 이루어짐 |
| ... |
가장 먼저 실패한 것들
터널링 서비스 (Tunnel services): 웹훅 전달의 불안정성
로컬 n8n 인스턴스를 노출하기 위해 localhost.run, cloudflared, ngrok을 시도했습니다. 세 가지 모두 SSH를 통해 연결되었으나, HTTP 트래픽이 안정적으로 도착하지 않았습니다. 커스텀 서브도메인(*.lhr.life, *.trycloudflare.com)에 의존하는 터널링 서비스는 통제 범위를 벗어난 의존성을 발생시킵니다. 즉, DNS 해석(resolution), 업타임(uptime), 연결 안정성이 모두 제3자에게 위임됩니다. 24시간 내내 접속 가능해야 하는 웹훅 엔드포인트(endpoint)에 있어, 이는 제가 감수하고 싶지 않은 리스크였습니다.
웹훅 403 에러: 프록시 신뢰 설정 오류 (proxy trust misconfiguration)
Nginx를 n8n 앞에 두고 EC2에 배포한 후, 모든 Telegram 웹훅이 403 Forbidden을 반환했습니다. 해결책은 N8N_PROXY_HOPS=1 설정이었습니다. 이 설정이 없으면 n8n은 Nginx로부터 오는 X-Forwarded-For 헤더를 신뢰하지 않으며, 요청을 스푸핑(spoofed)된 것으로 간주하여 거부합니다.
암호화 키 불일치: 소리 없는 데이터 손실
다른 암호화 키(encryption key)를 사용하여 Docker 컨테이너를 다시 생성했습니다. n8n은 '소유자 계정 설정(Set up owner account)' 화면을 보여주었고, 기존의 모든 워크플로우(workflows)와 자격 증명(credentials)이 사라졌습니다. 암호화 키와 Docker 볼륨(volume)은 한 쌍으로 결합되어 있습니다. 하나를 변경하면서 다른 하나를 유지하지 않으면 모든 것을 잃게 됩니다.
문서화되지 않은 비밀 토큰 (secret token)
n8n v2.22.5는 Telegram 웹훅 요청에 비밀 토큰을 강제합니다. 광범위한 테스트와 소스 코드 분석 끝에, 저는 이 공식이 다음과 같은 패턴을 따른다는 것을 발견했습니다:
secret_token = {workflowId}_{nodeId}
workflowId는 브라우저 URL에서 확인할 수 있습니다. nodeId는 Telegram Trigger 노드를 클릭했을 때 나타납니다. 이는 n8n 문서나 UI에 명시되어 있지 않으며, 경험적인 발견(empirical discovery)이 필요했습니다. 올바른 비밀 토큰이 없으면 Telegram은 모든 전달 시도에 대해 403을 받게 되며, 여러분의 봇은 아무런 반응도 하지 않을 것입니다.
실제 배포된 구현 사항
Docker: IAM 역할(role) 액세스 권한을 가진 n8n
# Secrets Manager에서 암호화 키를 가져옵니다 (절대 하드코딩하지 마세요)
N8N_KEY=$(aws secretsmanager get-secret-value \
--secret-id <your-secret-id> \
...
이 설정에 포함된 주요 결정 사항:
N8N_AWS_SYSTEM_CREDENTIALS_ACCESS_ENABLED=true— 액세스 키(access keys) 없이 EC2 IAM 역할(role)을 사용합니다.N8N_PROXY_HOPS=1— 정확히 하나의 프록시 계층(Nginx)만 신뢰합니다.N8N_ENCRYPTION_KEY는 런타임(runtime) 시 Secrets Manager에서 가져오며, 디스크에 절대 저장되지 않습니다.- 버전을
2.22.5로 고정(pinned)했습니다 — 버전 간에 웹훅(webhook) 비밀 토큰 동작이 변경될 수 있기 때문입니다.
Nginx: TLS 종단(termination)
server {
listen 443 ssl;
server_name _;
...
proxy_request_buffering off 설정이 매우 중요합니다. 이 설정이 없으면 Nginx가 요청 본문(request body)을 버퍼링하여 n8n이 멀티파트 업로드(multipart uploads, 예: PDF)를 파싱하는 데 실패합니다.
웹훅(Webhook) 등록: 자체 서명 인증서(self-signed cert) 트릭
curl -s \
-F "url=https://<your-ec2-public-ip>/webhook/<your-webhook-id>/webhook" \
-F "certificate=@/etc/ssl/certs/n8n.pem" \
...
이 단일 호출에서 세 가지 작업이 수행됩니다:
- Telegram이 웹훅 URL을 학습합니다.
- 자체 서명된 공개 인증서(self-signed public cert)가 업로드됩니다 — Telegram은 향후 전달 시 이 인증서를 신뢰하게 됩니다.
- 비밀 토큰(secret token)이 등록됩니다 — Telegram은 이를 헤더(header)에 포함하며, n8n은 이를 검증합니다.
워크플로우(Workflow) 노드 체인
LLM 프롬프트(prompt):
다음 문서를 분석하여 다음을 제공하세요:
1. 제목/주제
2. 핵심 통찰 (3-5개의 불렛 포인트)
...
시스템 메시지(System message): '당신은 문서 분석가입니다. 명확한 요약을 제공하세요. Telegram 형식에 맞게 작성하세요.'
내가 다르게 했을 부분
도메인을 등록하세요. 자체 서명 인증서 (Self-signed certs)도 작동은 하지만 운영상의 마찰을 초래합니다. 인증서 갱신 후 웹훅 (webhook)을 수동으로 재등록해야 하거나, 에디터 사용 시 브라우저 경고가 나타나는 등의 문제입니다. 도메인은 연간 5달러 정도로 저렴하며, ACM (AWS Certificate Manager)이 무료 인증서를 제공하므로 자체 서명 인증서의 복잡성을 완전히 제거할 수 있습니다. MVP (Minimum Viable Product) 단계에서는 수용 가능한 수준이었으나, 그 이상의 단계로 넘어간다면 가장 먼저 변경할 사항입니다.
n8n의 백엔드로 PostgreSQL을 전환하세요. n8n은 프로덕션 데이터베이스로 PostgreSQL을 공식 지원합니다 (SQLite가 기본값이며, MySQL/MariaDB는 지원이 중단되었습니다). SQLite는 Docker 볼륨 내에 존재하며, 쓰기 작업 시 락 (lock)이 걸리고, 안전한 핫 백업 (hot backup)을 지원하지 않으며, 수평적 확장 (horizontal scaling)을 위한 n8n의 큐 모드 (queue mode)와 호환되지 않습니다. Amazon RDS for PostgreSQL 또는 Aurora Serverless v2를 사용하면 애플리케이션 레이어를 건드리지 않고도 관리형 백업, 시점 복구 (point-in-time recovery), 그리고 멀티 워커 (multi-worker) 배포 경로를 확보할 수 있습니다.
최소값(min)=1인 Auto Scaling Group과 런치 템플릿 (launch template)을 추가하세요. 현재 아키텍처는 단일 EC2 인스턴스로 구성되어 있어, 하나의 가용 영역 (availability zone)에 의존하며 단일 장애점 (single point of failure)을 가집니다. 동일한 사용자 데이터 (user-data) 스크립트를 사용하는 ASG (Auto Scaling Group)를 도입하면, 아키텍처의 복잡성을 추가하지 않고도 자가 치유 (self-healing, 상태 검사 실패 시 자동 교체) 기능을 제공할 수 있습니다. 도메인 및 ACM과 결합하면, 최소한의 추가 비용으로 시스템을 '작동하는 프로토타입'에서 '프로덕션급 (production-grade)'으로 격상시킬 수 있습니다.
아키텍트를 위한 시사점 (Takeaways)
자체 서명 인증서는 유효한 패턴입니다 — 하지만 웹훅 소비자 (webhook consumer)가 인증서 업로드를 명시적으로 지원할 때만 해당됩니다. Telegram은 이를 지원합니다. 하지만 대부분의 서비스 (Stripe, GitHub, Slack 등)는 지원하지 않습니다. 아키텍처를 확정하기 전에 이 부분을 반드시 확인하십시오.
EC2 워크로드에는 액세스 키 (access keys)보다 IAM 역할 (IAM roles)이 엄격하게 우월합니다. 키 로테이션 (rotation)이 필요 없고, 노출 위험이 없으며, 자동으로 갱신됩니다. 여기에는 트레이드오프 (trade-off)가 없습니다. 그냥 사용하십시오.
버전을 고정하세요 (Pin your versions). n8n의 웹훅 비밀값 (webhook secret) 강제 적용 기능은 마이그레이션 경로 없이 버전 사이에 갑자기 나타났습니다. n8n:latest 태그를 사용하는 것은 리스크가 큽니다. 버전을 고정하고, 스테이징 (staging) 환경에서 업그레이드를 테스트하며, 롤백 (rollback) 계획을 유지하십시오.
웹후크 (webhooks) 레이어를 단계별로 디버깅하십시오. 다섯 가지의 뚜렷한 실패 모드가 있습니다: 네트워크 (network), TLS, 인증 (authentication), 애플리케이션 로직 (application logic), 응답 포맷팅 (response formatting). 다음 단계를 테스트하기 전에 각 단계가 반드시 통과되어야 합니다. 레이어를 건너뛰면 순환적인 문제 해결 (circular troubleshooting)의 늪에 빠지게 됩니다.
인프라가 아닌 프롬프트 (prompt)에 지능을 부여하십시오. 이 시스템의 'AI' 부분 전체는 단 5줄의 프롬프트 템플릿에 불과합니다. 나머지 95%의 노력은 인프라 — 인증서 (certificates), 비밀 값 (secrets), 네트워킹 (networking), Docker 볼륨 (Docker volumes)에 투입되었습니다. 모델은 범용 제품 (commodity)입니다. 모델로 데이터를 안정적으로 주고받는 것이 진정한 기술 (craft)입니다.
HTTPS 웹후크가 필요하지만 도메인을 확보할 수 없을 때 여러분은 어떤 방식을 사용하시나요? 다른 분들도 저와 같이 자체 서명 인증서 (self-signed cert) 패턴을 경험했는지, 아니면 더 나은 해결책을 찾았는지 궁금합니다. 아래에 댓글을 남겨주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기