n8n 웹훅 CORS 에러 원인과 3가지 해결 방법

n8n 웹훅 CORS 에러, 왜 발생하고 어떻게 해결할까?

n8n으로 자동화 워크플로우를 구성하다 보면, 특히 웹훅(Webhook)을 외부 서비스나 프론트엔드 JavaScript와 연동할 때 ‘CORS 에러’를 자주 만나게 됩니다. 브라우저에서 n8n 웹훅 URL로 Ajax 요청을 보냈을 때 No 'Access-Control-Allow-Origin' header is present on the requested resource 같은 에러 메시지가 표시되면, 요청이 브라우저 보안 정책에 막힌 상황입니다.

이 글에서는 n8n 웹훅 CORS 에러가 발생하는 근본적인 원리를 이해하고, 실제 운영 환경에 적용해 볼 수 있는 3가지 해결 방법을 단계별로 정리했습니다. 아래 핵심 요약과 비교표를 먼저 확인하면 전체 흐름을 빠르게 파악할 수 있습니다.

🚀 핵심 요약
1. 원인: 브라우저의 CORS 정책이 n8n 웹훅 도메인과 호출 페이지 도메인의 차이를 감지해 요청을 차단합니다.
2. 가장 안정적인 해결책: n8n 서버에서 허용 도메인을 명시하거나 리버스 프록시로 CORS 헤더를 처리하는 방법이 권장됩니다.
3. 주의사항: ‘Respond to Webhook’ 응답 헤더만으로는 Preflight 요청을 처리할 수 없으므로, 부분적인 해결에 그칠 수 있습니다.

1. n8n 웹훅 CORS 에러의 원인: 브라우저의 보안 정책

CORS(Cross-Origin Resource Sharing)는 웹 브라우저가 보안상의 이유로 다른 출처(도메인, 프로토콜, 포트)의 리소스 요청을 제한하는 정책입니다. 예를 들어 호출 페이지가 https://myblog.com이고 n8n 웹훅 URL이 https://your-n8n.com/webhook/123이라면, 출처가 서로 다르기 때문에 브라우저는 요청을 안전하지 않은 것으로 판단합니다. 즉 n8n 서버 자체가 요청을 거부하는 것이 아니라, 브라우저가 응답을 확인하고 차단하는 구조입니다.

n8n 웹훅 엔드포인트가 외부에서 접근 가능한 Production URL로 생성되어 있어도, 기본적으로 CORS 허용 헤더가 포함되어 있지 않은 경우가 많습니다. 따라서 별도 설정 없이 프론트엔드에서 직접 호출하면 CORS 에러가 발생할 수 있습니다. 실제 프로젝트에서는 https://your-n8n.com/webhook/... 형태의 URL을 호출하기 전에, 브라우저 개발자 도구 Network 탭에서 Preflight(OPTIONS) 요청과 실제 요청의 헤더를 함께 확인하는 습관이 도움이 됩니다.

2. 해결책 1: ‘Respond to Webhook’ 응답 헤더 추가

인터넷에서 가장 쉽게 찾을 수 있는 방법은 n8n 웹훅 이후에 연결한 ‘Respond to Webhook’ 노드에서 Response Headers를 설정하는 것입니다. 예를 들어 Key를 Access-Control-Allow-Origin, Value를 https://myblog.com으로 입력하면, n8n이 정상적으로 응답할 때 브라우저가 CORS 정책을 통과할 수 있습니다. 개발 중에는 *를 사용할 수 있지만, 보안을 고려해 운영 환경에서는 허용 도메인을 명시하는 것이 좋습니다.

다만 이 방법은 한계가 뚜렷합니다. 브라우저는 본 요청을 보내기 전에 Preflight 요청(OPTIONS 메서드)을 먼저 전송하는데, ‘Respond to Webhook’ 노드는 이 Preflight 요청 자체를 처리하지 못하는 경우가 많습니다. 따라서 n8n 웹훅까지 요청이 도달하기 전에 브라우저 단계에서 차단될 수 있으며, GET 방식의 단순 요청이 아니라면 완전한 해결책으로 보기 어렵습니다.

이 방식은 테스트 목적이나 같은 출처에서 간단한 GET 요청을 보낼 때만 제한적으로 활용하는 것을 추천합니다.

3. 해결책 2: n8n 서버에 CORS 환경 변수 설정하기

좀 더 확실한 방법은 n8n이 실행되는 서버 자체에서 CORS를 허용하는 설정을 적용하는 것입니다. n8n은 Node.js 기반이므로 서버 환경 변수에 허용 오리진을 지정하면, Preflight 요청까지 서버 레벨에서 처리되어 GET, POST, PUT 등 다양한 메서드와 커스텀 헤더를 사용할 수 있습니다. 단, n8n 버전과 실행 방식에 따라 환경 변수가 적용되는 범위가 다를 수 있으므로, 공식 문서 또는 현재 버전의 설정 값을 함께 확인해야 합니다.

3-1. Docker로 실행 중인 경우

docker-compose.yml 파일이나 docker run 명령에 다음 환경 변수를 추가합니다.

N8N_CORS_ORIGIN=https://myblog.com
# 여러 도메인을 허용해야 한다면 쉼표로 구분: N8N_CORS_ORIGIN=https://myblog.com,https://admin.myblog.com
# 테스트 용도로 모든 출처를 허용하려면: N8N_CORS_ORIGIN=*

환경 변수를 추가한 뒤에는 docker-compose restart n8n 또는 docker restart n8n 명령으로 컨테이너를 재시작해야 적용됩니다. 변경 후에는 브라우저 개발자 도구에서 응답 헤더에 Access-Control-Allow-Origin이 포함되었는지 확인하는 것을 권장합니다. 와일드카드(*)는 모든 출처를 허용하므로 민감한 API 키나 개인정보를 다루는 운영 환경에서는 피하는 것이 안전합니다.

3-2. npm 또는 소스 코드로 실행 중인 경우

도커를 사용하지 않는다면 n8n 프로세스를 실행할 때 환경 변수를 직접 지정할 수 있습니다. 예를 들어 Linux 서버에서 N8N_CORS_ORIGIN=https://myblog.com n8n start 형태로 실행하거나, 시스템 서비스 파일에 환경 변수를 등록한 뒤 재시작하면 됩니다. 이 경우에도 실행 로그에 CORS 관련 오류가 있는지 함께 확인하는 것이 좋습니다.

4. 해결책 3: 리버스 프록시(Nginx)로 CORS 헤더 우회하기

만약 n8n 서버 설정을 직접 변경하기 어렵거나, 더 안전하게 웹훅 URL을 숨기고 싶다면 리버스 프록시를 활용할 수 있습니다. 프론트엔드와 n8n 사이에 Nginx와 같은 중간 서버를 두고, 해당 서버에서 CORS 관련 헤더를 추가하거나 경로를 재작성하는 방식입니다. 이 방법은 n8n 웹훅 URL을 외부에 직접 노출하지 않으므로 보안성도 함께 높아집니다.

클라우드 환경이라면 Cloudflare Workers 같은 서버리스 함수를 이용하는 방법도 있습니다. 아래는 Nginx의 간단한 location 블록 예시입니다. 실제 운영 환경에서는 SSL 설정과 허용 도메인을 필요한 범위로 제한해야 합니다.

location /webhook/ {
    proxy_pass https://your-n8n.com;
    add_header Access-Control-Allow-Origin https://myblog.com always;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
    add_header Access-Control-Allow-Headers 'Authorization, Content-Type' always;
    if ($request_method = OPTIONS) { return 204; }
}

5. 3가지 해결 방안 비교 분석표

비교 항목 응답 헤더 추가 CORS 환경 변수 리버스 프록시
설정 난이도 매우 쉬움 보통 어려움
Preflight 대응 불가능 가능 가능
보안 수준 낮음 중간 (도메인 지정 시) 높음
특이 사항 재시작 불필요, 부분 해결 서버 재시작 필수 n8n URL 숨김 가능

6. 마치며: CORS 에러에 대비하는 실전 습관

n8n 웹훅 CORS 에러가 발생했을 때는 먼저 호출 환경을 확인하는 것이 좋습니다. 로컬 개발 환경이라면 n8n을 --tunnel 모드로 실행했는지, 서버가 예상한 포트에 정확히 바인딩되어 있는지 점검해 보세요. 브라우저 개발자 도구의 Network 탭에서 OPTIONS 요청과 응답 헤더를 확인하면 어떤 단계에서 막혔는지 빠르게 진단할 수 있습니다.

운영 환경이라면 가장 안정적인 조합은 n8n 서버에 CORS 설정을 적용하거나, 리버스 프록시를 통해 웹훅 URL을 숨기면서 허용 도메인을 제한하는 방법입니다. 이 글에서 소개한 3가지 방법을 자신의 인프라에 맞게 선택하고, 변경 후 반드시 실제 브라우저 환경에서 테스트해 보시기 바랍니다.

이 글이 도움이 되었다면 댓글로 어떤 방법을 적용했는지 알려주세요. 같은 문제를 겪는 다른 독자에게도 유용한 정보가 됩니다.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다