n8n AI 워크플로우에서 데이터 유출을 방지하는 5가지 방법
요약
n8n AI 워크플로우 실행 시 발생할 수 있는 개인정보(PII) 유출 문제를 방지하기 위한 5가지 기술적 접근 방식을 소개합니다. 코드 노드를 활용한 수동 토큰화부터 n8n의 내장 Guardrails 노드 활용법까지 구체적인 구현 방법과 트레이드오프를 다룹니다.
핵심 포인트
- n8n 실행 로그와 외부 LLM API로의 PII 노출 위험성 경고
- Code 노드를 이용한 수동 토큰화 방식의 장단점 분석
- n8n v1.113.3 이상에서 지원하는 내장 Guardrails 노드 소개
- 워크플로우 설계 시 데이터 보안을 위한 단계별 솔루션 제시
만약 여러분이 이메일, 전화번호, 계정 ID, 건강 기록과 같은 실제 고객 데이터에 접근하는 n8n AI 워크플로우를 실행하고 있다면, 해당 데이터는 거의 확실하게 평문(plain text) 상태로 외부 LLM API에 전달되고 있습니다. n8n 실행 기록(execution history)은 기본적으로 모든 노드의 입력과 출력을 저장하므로, 인스턴스 접근 권한이 있는 사람이라면 누구나 로그에서 가공되지 않은 개인정보(PII)를 읽을 수 있습니다.
이 포스트에서는 의존성 없는 빠른 해결책부터 프로덕션급 솔루션까지, 실제 도구, 설치 지침, 그리고 각 방법의 솔직한 트레이드오프(tradeoffs)를 포함한 다섯 가지 구체적인 접근 방식을 다룹니다.
시작하기 전에 이것이 중요한 이유
전형적인 n8n AI 워크플로우는 다음과 같습니다:
Webhook → 고객 기록 가져오기 → 프롬프트 생성 → OpenAI → 응답 전송
해당 프롬프트가 OpenAI에 도달할 때쯤이면 다음과 같은 내용이 포함되어 있을 수 있습니다:
john.doe@company.com의 지원 사례를 요약하세요,
SSN 999-88-7777, 계정 #48291, 전화번호 555-304-8821.
문제: {{ $json.description }}
거기에 있는 모든 필드는 개인정보(PII)입니다. 이는 OpenAI의 인프라로 전송됩니다. 또한 여러분의 n8n 실행 로그에 그대로 남아 있습니다. 이를 방지하기 위한 구체적인 조치를 취하지 않는 한, 이 과정은 조용히 계속될 것입니다.
옵션 1: Code 노드를 이용한 수동 토큰화 (Manual tokenization)
개념: LLM 노드 이전에 n8n Code 노드에서 JavaScript를 작성하여 민감한 필드를 토큰(token)으로 교체한 다음, 이후에 이를 다시 되돌리는 방식입니다.
설정: 별도의 설치가 필요하지 않습니다. LLM 노드 앞에 Code 노드를 추가하세요.
// "Tokenize" Code node — Run Once for All Items
const map = {};
let counter = 1;
...
그 후 LLM 노드 다음에 값을 복구하기 위한 두 번째 Code 노드를 배치합니다:
// "Detokenize" Code node
let response = $input.first().json.message.content;
const map = $('Tokenize').first().json._pii_map;
...
실제로 보호되는 범위:
- 코드에 명시적으로 나열한 필드
- 최종 프롬프트 문자열 내의 PII
보호되지 않는 범위:
- 누락된 모든 항목 — 새로운 워크플로우를 만들 때마다 처음부터 다시 작성해야 함
- 암시적인 민감 정보(독점 프로젝트 이름, M&A 맥락 등)를 감지하지 못함
- 주의하지 않으면 실행 로그(
execution logs)에_pii_map이 여전히 나타남 - 실행별 감사 추적(Audit trail) 기능 없음
- 데이터 스키마(Data schema)가 변경되면 즉시 작동이 중단됨
가장 적합한 경우: 프로토타이핑(Prototyping). 어떤 2~3개 필드에 PII(개인 식별 정보)가 포함되어 있는지 정확히 알고 있으며, 스키마가 변경될 때 코드를 업데이트하는 것을 잊지 않을 일회성 워크플로우.
옵션 2: n8n의 내장 Guardrails 노드
정의: 데이터와 LLM(대규모 언어 모델) 노드 사이에 위치하는 n8n 네이티브 노드(2025년 11월, v1.113.3부터 사용 가능)입니다. 패턴 기반 검사를 위해 외부 서비스가 필요하지 않습니다.
설정: n8n을 최소 v1.113.3 이상으로 업데이트하세요. Guardrails 노드는 노드 검색에서 바로 나타나며 별도의 설치는 필요하지 않습니다.
이 노드에는 두 가지 모드가 있습니다:
텍스트 위반 검사 (Check Text for Violations) — 선택한 정책에 따라 텍스트를 스캔하고, 무언가 트리거되면 Fail 브랜치로 경로를 지정합니다. 그 후 워크플로우 중단, 시도 로그 기록, 안전한 대체값(Fallback) 반환 중 무엇을 할지 결정할 수 있습니다.
텍스트 정화 (Sanitize Text) — 감지된 콘텐츠를 제자리에서 삭제(Redact)하고 [EMAIL_ADDRESS] 또는 [PHONE_NUMBER]와 같은 플레이스홀더(Placeholder)로 대체합니다. 워크플로우는 정화된 텍스트를 가지고 계속 실행됩니다.
전형적인 패턴:
Webhook → Guardrails (Sanitize) → OpenAI → Response
사용 가능한 가드레일(Guardrails)에는 다음이 포함됩니다: PII 감지(20개 이상의 엔티티 유형: 이메일, 전화번호, 신용카드, SSN, IBAN, 여권, 운전면허증, 의료 면허 및 국가별 형식), 비밀 키(Secret Keys), 키워드(Keywords), URL, 사용자 정의 정규식(Custom Regex), 탈옥(Jailbreak) 감지 (LLM 기반), NSFW 감지 (LLM 기반), 그리고 주제 일치성(Topical Alignment).
특히 PII의 경우, 정화(Sanitize) 모드는 패턴 매칭을 통해 구조화된 엔티티를 포착하므로 API 호출이 필요하지 않고 지연 시간(Latency)이 추가되지 않습니다. 탈옥 및 NSFW 감지는 연결된 LLM 노드가 필요하며 검사당 한 번의 API 호출이 추가됩니다.
실제로 보호되는 범위:
- 사용자가 설정한 단일 텍스트 필드 내의 구조화된 개인정보 (Structured PII)
- API 키 패턴, 일반적인 자격 증명 (Credential) 형식
- 사용자 대상 입력값에 대한 탈옥 (Jailbreak) 및 인젝션 (Injection) 시도
- 패턴 기반 검사를 위한 외부 서비스 의존성 없음
탐지하지 못하는 부분:
- 디토큰화 (Detokenization) 불가 — 한 번 마스킹(Redacted)되면 해당 값은 사라집니다. 사용자에게 반환되는 응답에는 원본 대신
[EMAIL_ADDRESS]가 포함됩니다. LLM 호출 이후 실제 값을 복구해야 하는 워크플로우의 경우, 추가적인 로직이 필요합니다. - 노드 간 가시성 (Cross-node visibility) 부재 — 지정된 텍스트 필드만 확인하며, 여러 상위 노드(Upstream nodes)를 거치며 누적된 데이터는 확인하지 못합니다.
- 외부 시스템에 대한 감사 추적 (Audit trail) 부재
- 문서화된 한 가지 제한 사항: 일관된 디토큰화 (동일한 엔티티 → 긴 세션 동안 동일한 토큰 유지)를 위해서는 추가적인 워크플로우 로직이 필요하며, 노드가 이를 자동으로 처리하지는 않습니다.
가장 적합한 용도: 사용자 대상 챗봇 및 접수(Intake) 워크플로우에 첫 번째 보호 계층을 추가하는 데 적합합니다. 탈옥을 차단하고 입력 시 구조화된 PII를 잡아내는 데 탁월합니다. 하지만 워크플로우가 여러 노드에서 가져온 데이터를 조합하여 프롬프트를 구성하는 경우, 이것만으로는 충분하지 않습니다.
옵션 3: n8n-nodes-rehydra (커뮤니티 노드)
개요: Rehydra SDK를 기반으로 구축된 오픈 소스 n8n 커뮤니티 노드입니다 (GitHub, npm). 익명화 (Anonymization)와 재수화 (Rehydration)를 모두 처리하며, 이는 LLM이 응답한 후 원본 값을 복구할 수 있음을 의미합니다.
설정 방법:
Self-hosted n8n → Settings → Community Nodes → Install → n8n-nodes-rehydra 입력.
또는 CLI를 통해 설치:
npm install n8n-nodes-rehydra
패키지에 포함된 세 가지 노드:
Rehydra: Anonymize — 탐지된 PII를 XML 스타일의 태그인 <PII type="EMAIL" id="1"/>로 교체합니다. 가명화 (Pseudonymize) 모드 (가역적, 기본값)와 익명화 (Anonymize) 모드 (비가역적, 값을 다시 사용할 필요가 없는 경우)를 지원합니다. 출력값: anonymizedText, piiMap (암호화됨), entities.
Rehydra: Rehydrate — 이전 Anonymize (익명화) 단계의 piiMap을 가져와 원래 값을 복원합니다. 동일한 암호화 키가 필요합니다.
Rehydra: Inspect — 드라이 런 (dry run) 모드입니다. 텍스트를 수정하지 않고 감지된 엔티티 (entities)를 반환합니다. 프로덕션에 적용하기 전, 무엇이 탐지될지 테스트하는 데 유용합니다.
설정 옵션:
- NER Mode (개체명 인식 모드): 비활성화 (정규 표현식 (regex)만 사용, 빠름), 양자화 (Quantized, ~280 MB ONNX 모델, 첫 실행 시 자동 다운로드), 또는 표준 (Standard, ~1.1 GB 모델). ONNX 모델은 로컬에서 실행됩니다 — API 호출이 없으며, 오프라인에서 작동하고, PII (개인정보)는 절대 사용자의 기기를 떠나지 않습니다.
- PII Types (PII 유형): 이메일, 전화번호, IBAN, 이름, 조직 등 — 탐지할 항목을 선택합니다.
- Locale (로캘): 국가별 형식에 따른 탐지 패턴에 영향을 미칩니다.
전형적인 워크플로우:
데이터베이스 (Database) → Rehydra: Anonymize → Claude → Rehydra: Rehydrate → 결과 저장
실제 포함 범위:
- NER 모드가 활성화된 경우 구조화된 PII + 소프트 PII (이름, 조직)
- 가역적 가명화 (Reversible pseudonymization) — LLM은 안정적인 플레이스홀더 (placeholders)를 사용하여 작업하고, 응답 시 실제 값이 복원됩니다.
- NER 모드 사용 시 완전히 로컬에서 작동 — 탐지를 위한 외부 API 호출 없음
- 설정된 모든 텍스트 필드에서 작동
누락되는 부분 (한계점):
- NER 모드는 첫 실행 시 ~280 MB 모델 다운로드(양자화 버전) 또는 ~1.1 GB(표준 버전)가 필요합니다 — 첫 실행 시 시작 지연 시간이 발생합니다.
- 노드 간 데이터 이동에 대한 가시성 없음 — 처리할 필드를 직접 구성해야 합니다.
- 감사 추적 (audit trail) 또는 대시보드 없음
- 검증되지 않은 커뮤니티 노드 —
N8N_COMMUNITY_PACKAGES_ENABLED=true설정이 적용된 셀프 호스팅 n8n이 필요하며, n8n Cloud에서는 사용할 수 없습니다.
가장 적합한 대상: 외부 서비스 의존성 없이 가역적인 PII 마스킹이 필요하며, 특히 정규 표현식만 사용하는 방식 이상의 이름/조직 탐지가 필요한 셀프 호스팅 팀.
옵션 4: HTTP Request 노드를 통한 Microsoft Presidio
개요: Microsoft에서 제작한 프로덕션용 오픈 소스 PII 탐지 및 익명화 엔진입니다. 로컬 서비스로 배포한 후 n8n의 HTTP Request 노드를 통해 호출하여 사용합니다.
설정 (Setup):
Docker로 배포:
docker pull mcr.microsoft.com/presidio-analyzer
docker pull mcr.microsoft.com/presidio-anonymizer
...
n8n에서 HTTP Request 노드를 추가합니다:
POST http://localhost:5001/analyze
Body: {
"text": "{{ $json.prompt }}",
...
이렇게 하면 위치 정보와 함께 탐지된 엔티티 (entities)가 반환됩니다. 이를 익명화 (anonymizer) 엔진으로 보냅니다:
POST http://localhost:5002/anonymize
Body: {
"text": "{{ $json.prompt }}",
...
Presidio는 50개 이상의 엔티티 유형 (entity types), 사용자 정의 인식기 (custom recognizers), 그리고 다양한 익명화 연산자 (replace, redact, hash, encrypt, mask)를 지원합니다. 이는 많은 기업용 PII 파이프라인의 기초가 되며, 영어와 더불어 점차 늘어나고 있는 다른 언어들을 지원합니다.
실제 포함 범위:
- 광범위한 엔티티 탐지 (기본적으로 50개 이상의 유형 제공)
- 도메인 특화 엔티티를 위한 사용자 정의 인식기 (custom recognizers)
- 엔티티 유형별 다양한 익명화 전략
- 완전한 로컬 실행 — 인프라 외부로 데이터가 나가지 않음
- 가역적 (reversible) 워크플로우를 위한 암호화 기반 익명화
한계점:
- 별도의 Docker 서비스를 실행하고 유지 관리해야 함
- 네이티브 n8n 노드가 없음 — HTTP Request 노드들을 직접 연결해야 하므로, 워크플로우 복잡도가 높아지고 에러 처리 (error handling) 로직을 직접 구축해야 함
- 전송된 텍스트 필드만 확인 가능 — 노드 간 데이터 흐름에 대한 가시성 없음
- n8n 전용 감사 추적 (audit trail) 기능 없음
- 가역성이 필요한 경우 익명화/비익명화 (anonymization/deanonymization) 매핑 저장에 대한 책임이 사용자에게 있음
가장 적합한 대상: 엔티티 탐지에 대해 최대한의 제어권을 원하고, 산업별 특화된 PII를 위한 사용자 정의 인식기가 필요하며, 제3자 SaaS에 의존하고 싶지 않은 DevOps 역량을 갖춘 팀.
옵션 5: n8n-nodes-privent (커뮤니티 노드)
개요: 외부 프록시가 아닌 워크플로우 그래프 내부에서 실행되는 네이티브 n8n 커뮤니티 패키지 (npm, privent.ai)입니다. npm에서 2,000회 이상의 설치를 기록했습니다.
위에서 언급한 모든 것들과의 구조적 차이점은 다음과 같습니다. Privent 노드는 다른 모든 n8n 노드와 동일한 방식으로 **노드 입력/출력 JSON 및 노드 간 데이터 이동 (cross-node data movement)**을 직접 읽습니다. 즉, 단순히 지정된 최종 텍스트 필드만 보는 것이 아니라, 프롬프트가 구성되기 전 전체 워크플로우 전체에 걸쳐 축적된 데이터를 확인합니다.
설정 (Setup):
Self-hosted (자체 호스팅):
N8N_COMMUNITY_PACKAGES_ENABLED=true
그 다음 Settings → Community Nodes → Install → n8n-nodes-privent를 진행합니다.
n8n Cloud Pro/Enterprise: 동일한 UI 경로를 사용하며, 환경 변수 설정이 필요하지 않습니다.
pv_live_… 키를 사용하여 Privent API 자격 증명 (credential)을 생성합니다 (vault 백엔드는 배포 유형에 따라 자동으로 구성됩니다).
패키지에는 6개의 노드가 포함되어 있습니다:
Privent Session — sessionId를 생성하고 인메모리 vault (in-memory vault)를 예열합니다. 하나의 세션 내에서 여러 노드에 동일한 값이 나타날 때 토큰 매핑을 일관되게 유지합니다.
Privent Tokenize — 감지된 민감 데이터를 결정론적인 [KIND_NNN] 플레이스홀더 (placeholder)로 교체합니다. EMAIL, SSN, CREDIT_CARD, IBAN, AWS_KEY, JWT, API_KEY 등 10가지 카테고리를 감지합니다. 감지 엔진 (ACARS)은 단순한 패턴 매칭 (pattern-matching) 대신 엔티티 민감도 (entity sensitivity), 의미론적 위험 (semantic risk), 문맥적 증폭 (contextual amplification), 목적지 위험 (destination risk), 행동 속도 (behavioral velocity), 정책 재정의 (policy overrides) 등 6가지 가중치 신호를 동시에 평가합니다.
Privent Detokenize — 플레이스홀더를 실제 값으로 다시 복원하지만, 신뢰할 수 있다고 선언한 싱크 (sinks)에서만 수행합니다. strict: true 설정 시, 다운스트림 싱크 URL을 해싱하여 사용자의 trustedSinks 접두사 목록과 대조합니다. 알 수 없는 엔드포인트를 대상으로 하는 HTTP 노드는 플레이스홀더를 그대로 유지하며, 다운스트림 로직이 어떻게 작동하든 상관없이 평문 값은 vault에 안전하게 보관됩니다.
Privent Risk Check — 프롬프트가 모델에 도달하기 전에 실행당 전체 ACARS 분석 결과와 함께 점수를 매깁니다.
Privent Handoff — 한 에이전트가 다른 에이전트에게 권한을 위임할 때 agent_handoff 감사 이벤트 (audit events)를 발생시킵니다. 승인되지 않은 범위 확장 (scope expansions)을 플래그로 표시합니다.
Privent Audit Event — Privent 대시보드로 사용자 정의 관측성 이벤트 (observability events)를 전송합니다.
일반적인 워크플로우:
Webhook → [사용자 노드] → Session → Tokenize → OpenAI → Detokenize → Response
워크플로우 JSON:
{
"nodes": [
{ "name": "Webhook", "type": "n8n-nodes-base.webhook" },
...
실제로 포함되는 기능:
- 동적 런타임 PII (개인정보) + 구조화된 엔티티 (structured entities) + 암시적 민감 콘텐츠 (시맨틱 리스크 스코어링 (semantic risk scoring)을 통해 독점적 컨텍스트, M&A 관련 언어 등을 포착)
- 노드 간 데이터 이동 — 그래프 내부에서 실행되므로, 단순히 유출 지점(egress point)뿐만 아니라 노드 사이를 흐르는 데이터를 감지
- 볼트(vault) 수준의 유출 게이팅 (Egress gating) — 엄격 모드(strict mode)를 통해 다운스트림 워크플로우 로직이 데이터를 전송하려고 시도하더라도 평문(cleartext)이 신뢰할 수 없는 목적지에 도달하는 것을 방지
- 세션 전반에 걸친 일관된 토큰 매핑 (token mapping)
- Privent 대시보드 내 실행별 전체 감사 추적 (audit trail)
- 자격 증명 및 API 키 탐지 (AWS_KEY, JWT, API_KEY)
- Handoff 노드를 통한 멀티 에이전트 위임 감사 (Multi-agent delegation auditing)
필요 사항:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기