--- title: 라인 봇에 AI 에이전트 연결하는 방법과 실수 date: 2026-10-01 model: hermes-agent category: setups summary: Hermes 에이전트를 라인 봇에 붙이려다 실제로 깨진 지점과 해결 과정을 그대로 기록한 삽질담이다. tags: line, bot, hermes, setup, webhook, signature author_type: human --- 텔레그램, 디스코드까지 해보고 나서 라인(LINE)도 연결해 봤다. 결론부터 말하면, 텔레그램·디스코드보다 훨씬 어렵다. 이유가 있다. 텔레그램은 polling이니까 서버에서 물어보면 되지만, 라인은 웹훅만 있고 서명 검증이 있어서 "연결 안 된다"는 문제가 대부분 프록시·서명 쪽에서 발생한다. 아래는 실제로 실패한 것을 포함해 정리한 내용이다. (운영자 환경 측정 기준) ## 1. LINE Developers 콘솔에서 채널 만들기 1. [LINE Developers Console](https://developers.line.biz/console/) 접속 2._provider_ 선택 → `Create a channel` → `LINE Login`이 아닌 **Messaging API** 채널 생성 3. Provider → Channel → Messaging API 탭으로 이동 여기서부터가 첫 함정이다. ### 주의점 1: 채널 종류를 Messaging API로 만들어야 한다 LINE Login 채널을 만들면 봇 토큰 자체가 안 나온다. 처음에 LINE Login으로 만들어서 채널 설정 화면을 헤맸다. Messaging API 채널이어야 `Channel secret`과 `Channel access token`이 발급된다. ## 2. 토큰과 시크릿 발급 Basic settings에서 두 값이 보인다. ```text Channel secret: a1b2c3d4e5f6... Channel access token (long-lived): eyJhbGciOi... ``` Channel access token은 두 종류가 있다. - **단기 토큰**: 유효 기간이 짧다. 보통 30일~몇 시간 단위로 재발급해야 한다. - **장기 토큰**: 채널 설정에서 직접 발급하는 것으로, 이걸 써야 서버가 며칠씩 무중단으로 돌아도 죽지 않는다. ### 주의점 2: 단기 토큰으로 두면 며칠 뒤에 갑자기 죽는다 처음에 발급돼 있던 단기 토큰을 `.env`에 넣어두고 며칠 잘 돌아가는 줄 알았다. 어느 날 아침에 봇이 무응답이 됐는데, 로그를 보니 401이었다. 토큰 만료였다. 지금은 장기 토큰으로 교체했다. 24시간 무중단 목적이면 이걸 반드시 장기 토큰으로 바꿔야 한다. ## 3. 웹훅 등록 LINE Developers Console의 Messaging API 설정에서 Webhook URL을 넣고 `Verify`를 누른다. ```text https://my-domain.example.com/webhook/line ``` 여기서 처음부터 막힌 게, 로컬 개발 환경이었다는 점이다. ### 주의점 3: 라인 웹훅은 공인 HTTPS만 받는다 로컬 주소(`http://localhost:8000`)를 넣으면 `Verify` 버튼 자체가 실패한다. 라인 서버가 외부에서 우리 서버에 접속해야 하는데, `localhost`는 당연히 아무도 못 잡기 때문이다. 나는 ngrok 같은 터널을 붙여 임시로 확인했다. 운영 도메인이 없다면 tunnels.xyz 같은 서비스를 쓰거나, 리버스 프록시로 인증서를 붙여야 한다. ### 주의점 4: 프록시가 X-Forwarded-For를 안 넘기면 차단된다 역방향 프록시(Nginx, Caddy 등) 뒤에 앱을 두면 요청이 프록시 주소(127.0.0.1)에서 온 것으로 보인다. 라인 서버는 allowlist에 등록된 IP에서만 POST를 보내는데, 이 주소가 그대로 잡히면 모든 요청이 조용히 무시된다. 내 경우 `X-Forwarded-For` 헤더를 넘기도록 프록시 설정을 고쳐서 해결했다. ```nginx location /webhook/line { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } ``` ## 4. 서명 검증 이게 라인 연동에서 제일 중요한 부분이다. 라인 서버가 보낸 요청에는 `X-Line-Signature` 헤더에 HMAC-SHA256 서명이 들어있다. ```text X-Line-Signature: base64값 ``` 검증 방법은 이렇다. 1. 요청 바디를 그대로 읽는다 (JSON 파싱하면 순서가 바뀌므로 원본 바이트가 필요) 2. `Channel secret`을 키로, 바디를 메시지로 HMAC-SHA256을 계산한다 3. base64 인코딩한 결과를 `X-Line-Signature`와 상수시간 비교한다 ### 주의점 5: 파싱된 JSON으로 검증하면 무조건 실패한다 파이썬에서는 이렇게 하면 안 된다. ```python body = json.loads(request.data) # 여기서 이미 깨진다 signature = hmac.new(secret, json.dumps(body).encode(), hashlib.sha256) ``` JSON을 파싱했다가 다시 직렬화하면 키 순서, 공백, 인코딩이 원본과 달라진다. 서명이 원문 바이트 기준으로 계산되어 있으므로 반드시 원본을 쓴다. ```python import base64, hashlib, hmac def verify(raw_body: bytes, signature: str, secret: str) -> bool: expected = base64.b64encode( hmac.new(secret.encode(), raw_body, hashlib.sha256).digest() ).decode() return hmac.compare_digest(expected, signature) ``` ### 주의점 6: 서명 검증 실패는 400으로 응답해야 한다 검증을 안 하고 200을 반환하면 아무도 문제가 있다는 걸 모른다. 검증 실패 시 400을 반환하고, 실패한 요청 바디와 헤더를 로그에 남겨놓는 게 디버깅할 때 편하다. 나는 그때 첫 요청 바디를 파일로 떨어뜨려 놓고 라인 콘솔에서 보낸 테스트 바디와 바이트 단위로 비교해서 겨우 원인을 찾았다. ## 5. 에이전트 실행 ```bash hermes gateway start ``` 기존 텔레그램/디스코드와 같이 게이트웨이로 띄운다. ### 주의점 7: 그룹 채팅에서는 멘션해야 한다 라인은 그룹 채팅에서 봇을 멘션하지 않으면 전혀 반응하지 않는다. 텔레그램처럼 봇이 알아서 대화를 읽는 구조가 아니라, 멘션(`@BotName`)이 있어야 메시지가 전달된다. 즉 채널의 잡담이 요금으로 넘어가는 문제는 라인에서는 애초에 발생하지 않는다. 대신 그룹에서 쓰려면 멘션을 빼먹으면 아무 일도 안 한다. ## 6. 설정 파일 ```env # 라인 채널 시크릿 (서명 검증에 사용) LINE_CHANNEL_SECRET=a1b2c3d4e5f6... # 장기 액세스 토큰 LINE_CHANNEL_ACCESS_TOKEN=eyJhbGciOi... # 허용 사용자 (숫자 ID, 필수 권장) LINE_ALLOWED_USERS=U1234567890abcdef... # 웹훅 경로 LINE_WEBHOOK_PATH=/webhook/line ``` ### 주의점 8: 라인 사용자 ID는 `U`로 시작하는 문자열이다 텔레그램은 숫자(`123456789`), 디스코드는 숫자(`123456789012345678`)인데, 라인은 `U4af4980629...`처럼 알파벳이 붙는다. 숫자만 넣는다고 가정하고 파싱하면 값이 잘려서 필터가 통과를 안 시킨다. 문자열 그대로 넣어야 한다. ## 7. 세 플랫폼 비교 | 항목 | 텔레그램 | 디스코드 | 라인 | | --- | --- | --- | --- | | 봇 생성 | BotFather | Developer Portal | Messaging API 채널 | | 수신 방식 | polling (쉬움) | 웹소켓 | 웹훅만 (어려움) | | HTTPS 필요 | 아니오 | 아니오 | 예 (공인 인증서) | | 서명 검증 | 없음 | 없음 | HMAC-SHA256 필수 | | 토큰 수명 | 영구 | 영구 | 단기 토큰은 만료 있음 | | 그룹 반응 | 멘션 불필요 | 접두어 필요 | 멘션 필수 | | 난이도 | 쉬움 | 보통 | 어려움 | ## 정리 1. LINE Developers Console에서 Messaging API 채널 생성 (LINE Login으로 만들면 토큰이 안 나온다) 2. 장기 액세스 토큰 발급 (단기 토큰은 며칠 뒤에 죽는다) 3. 공인 HTTPS 도메인 확보 후 웹훅 등록 (localhost는 Verify가 안 된다) 4. 리버스 프록시에서 `X-Forwarded-For` 전달 (안 하면 요청이 조용히 무시된다) 5. 서명 검증은 원본 바이트 기준 (JSON 재직렬화하면 무조건 실패한다) 6. 검증 실패 시 400 반환, 허용 사용자는 `U`로 시작하는 ID로 등록 솔직히 개인 비서 용도로는 텔레그램이 압도적으로 편하다. 라인은 국내 사용자 대상 서비스 연동이나 카카오 비즈니스 메시지처럼 도메인이 정해진场景에서 비로소 값어치를 한다. Weekend 프로젝트로 해보다가 반나절을 날렸지만, 같은 삽질을 다른 사람이 하지 않도록 남긴 기록이다.