4편 — 트러블슈팅 & ROI 분석
실전에서 마주친 문제 12가지와 해결 전략 + 자동화 도입 성과
1. 들어가며
이 시스템은 단순히 노드를 이어 붙인 자동화가 아니라,
AI – 사람 – 시스템이 함께 작동하는 완전한 CRM 파이프라인이었습니다.
하지만 실제 구축 과정에서는 예상치 못한 문제가 계속 등장했습니다.
Google Sheets, Notion API, OpenAI, n8n이라는 서로 다른 생태계가 만나면서 발생하는 구조적 충돌들이었죠.
이번 글에서는 실제로 부딪혔던 문제들을
5개의 문제 카테고리로 구분하여 구조적으로 정리하고,
마지막에는 자동화의 정량적 성과(ROI)까지 함께 담았습니다.
2. 트러블슈팅
문제의 본질에 따라 5가지 카테고리로 나누어 정리했습니다.
Ⅰ. 상태 관리 & 데이터 무결성 (State Management)
데이터 상태값의 모호함(Null, Empty, False)이 자동화 시스템을 불안정하게 만든 대표 사례들입니다.
🛠 Case 1. 데이터가 엉뚱한 곳에 쌓이는 Ghost Row
문제 (Issue)
Append Row가 시트의 “다음 빈 행”이 아니라,
**아래로 한참 떨어진 위치(예: 1000번째 줄 뒤)**에 추가됨.
기술적 원인 (Root Cause)
Google Sheets는 행에 체크박스가 존재하기만 해도
그 행을 “데이터가 있는 상태(Non-empty Row)”로 인식합니다.
→ Append 기능은 이 행들을 모두 “사용 중”으로 보고,
실제 데이터가 없는 멀리 떨어진 지점에 새 행을 생성해버립니다.
해결 (Fix)
- 정적(Static)으로 행을 미리 구성하는 방식 완전 폐기
- 모든 행은 “데이터 추가 시” 동적으로 생성
- 체크박스 기반의 상태값 의존 설계 자체를 제거
🛠 Case 2. 체크박스의 Null vs False 문제
문제 (Issue)
“처리 안 된 데이터(미체크)”만 가져와야 하는데,
n8n의 필터가 제대로 동작하지 않아 오답이 반복됨.
기술적 원인 (Root Cause)
Google Sheets의 체크박스는 해제 상태를
FALSE가 아닌 null(또는 empty string) 으로 반환합니다.
문제는…
| Google Sheets Trigger | null/"" |
| n8n Get Row/Get Many | false (정상 Boolean) |
→ 같은 셀인데도 모듈마다 해석이 다름.
해결 (Fix)
- 체크박스 상태값 자체를 데이터 기준으로 사용하지 않기
- Null과 False를 모두 제거하는 방향으로 **Dropdown(대기/완료)**으로 상태 재설계
→ 데이터 무결성 100% 확보.
Ⅱ. 식별 & 조회 정합성 (Identification & Query Accuracy)
CRM 데이터는 “누구를 다루고 있는가”가 가장 중요합니다.
따라서 검색/조회 단계에서의 오차는 그대로 중복/누락으로 이어집니다.
🛠 Case 3. Notion 검색이 엉뚱한 고객을 반환하는 문제
문제
이메일이 일부만 비슷해도 다른 고객 페이지가 함께 반환됨.
기술적 원인
Notion Search API는 “정확한 match”가 아니라
유사 검색(Fuzzy Matching) 이 기본값입니다.
이는 검색 엔진으로는 좋지만 CRM 데이터 조회에는 매우 위험합니다.
해결
- Search 노드 완전 제거
- Database Pages → Get Many로 전환
- Build manually 필터로을 직접 정의
-
Email == 입력값
- Always Output Data 옵션 활성화
🛠 Case 4. Notion Update 시 특정 필드가 잠겨 수정되지 않는 문제
문제
Status를 바꾸려는데 입력 UI가 회색으로 잠겨 수정할 수 없음.
기술적 원인
Status를 **Match Key(= 찾기 기준)**로 설정해버린 것이 원인.
Match Key는 “찾는 기준”이지 “변경할 값”이 아닙니다.
기준(Match Key)은 ‘절대 변하지 않는 값’이어야 한다.
해결
- Match Key → 고유식별자(Unique ID, Primary Key) 로 설정
(임시로 Email을 사용할 수도 있지만, 원칙적으로는 ID가 이상적) - Status는 Values To Update 섹션에만 배치
Ⅲ. 데이터 포맷 & 파싱 (Formatting & Parsing)
AI·Notion·Google Sheets가 요구하는 포맷이 다르기 때문에
다양한 포맷 충돌 문제들이 발생했습니다.
🛠 Case 5. AI가 JSON을 마크다운으로 감싸는 문제
문제
OpenAI가
형태로 반환하여 n8n이 문자열로 인식 — 파싱 불가.
기술적 원인
LLM의 기본 학습패턴 때문에
JSON 요청 시 코드블록 제공이 “기본 행동”입니다.
프롬프트만으로는 완전 제어 불가.
해결
- Code Node에서 Markdown 태그 제거
- JSON.parse()로 강제 변환
- 실패 시 fallback 값 반환하는 안전장치 추가
🛠 Case 6. Notion 본문 Append 시 줄바꿈, 날짜 포맷 깨짐
문제
히스토리 로그가
- 줄바꿈이 무시되거나
- Timestamp가 그대로 들어가거나
해서 가독성이 떨어짐.
기술적 원인
Notion 본문은 단일 문자열이 아니라
Rich Text Object 배열 구조입니다.
단순 문자열을 던지면 구조 자체가 깨집니다.
해결
- YYYY-MM-DD 형식으로 날짜 정규화
- 텍스트를 Rich Text Object 형태로 강제 변환
Ⅳ. 입력 흐름 & AI 제어 (Input Flow & Guardrails)
AI는 “대답하려는 성향”이 너무 강하기 때문에
필수값이 없는데도 JSON을 억지로 완성하려는 문제가 있었습니다.
🛠 Case 7. 사용자의 돌발 질문으로 Slot Filling 흐름이 깨지는 문제
문제
“로그인이 안 돼요” → (필수 정보 부족)
AI가 갑자기 “설명 모드”로 넘어가 버림.
또는 임의 값으로 JSON을 만들어 스키마 오류 발생.
기술적 원인
LLM은 빈 필드를 상상(hallucination)으로 채워서라도
“일단 답을 완성”하려는 성향이 있음.
해결
1) Slot Filling 규칙 강화
필수 슬롯이 비어있으면
→ 어떤 질문에도 대답하지 않고 정보 요청만 수행하도록 명령.
2) Code Node 2차 유효성 검사
Slot Filling을 통과하더라도
필수값이 없으면 절대 다음 단계로 넘어가지 않음.
3) Chat 시작 시 “의도 선택 UI” 제공 (대폭 안정화)
예:
사용자가 1/2로 명확히 의도 지정 →
Router AI의 분류 정확도 상승 →
Slot Filling 충돌 사라짐
Ⅴ. 배치 처리 & 성능 최적화 (Batch Processing)
🛠 Case 8. Polling 기반의 Trigger 처리 특성과 Loop 설계
문제
관리자가 1건만 승인해도
여러 승인된 행이 한 번에 묶여 들어오면서
중복 처리나 누락 가능성이 증가함.
기술적 원인
n8n의 Google Sheets Trigger는 Webhook 방식이 아니라
Polling(주기 확인) 기반이며,
주기는 사용자가 직접 지정한다(예: 30초, 1분 등).
Polling은 일정 주기마다 시트를 “전체적으로 스캔”하며,
트리거 타이밍 안에서 변경된 데이터가 배열(Array)로 전달된다.
→ 단일 행이 아닌 여러 행이 한 번에 들어올 가능성이 항상 존재.
해결
1) Polling 트리거는 “알림(Event)” 역할로 축소
트리거: “변경된 것이 있다”까지만 전달.
2) 실제 처리할 데이터는 n8n이 능동적으로 조회
조건:
→ 정확히 필요한 행만 가져옴.
3) Loop는 상황에 따라 기본 설계로 고려
Polling 기반에서 다중 행이 들어올 가능성이 높기 때문에
Loop를 사용해 안정적으로 “1건씩” 처리하도록 설계.
※ 개념 보완
- “Polling은 도구가 아니라 설계 패턴 중 하나”
- “Polling 시스템은 변경된 구간만 반환한다”는 과한 일반화 →
n8n은 “전체를 읽고 변경된 행을 직접 판단”하는 구조 - “Loop가 정답”이 아니라,
Polling에서는 Loop가 필요한 상황이 잦다가 정확한 표현
3. ROI 분석: 자동화가 만들어낸 실제 성과
📈 1) 업무 시간 92% 절감
| 입력 | 3분 | 0초 |
| 중복 검색 | 2분 | 0초 |
| 승인 | - | 20초 |
→ 5분 → 20초
→ 하루 50건 기준: 4시간 10분 → 16분
📉 2) 인건비 절감 효과
- 하루 4시간 절감 × 월 20일 = 80시간
- 최저시급 기준 약 100만 원/월 절감
✔ 3) 데이터 무결성 향상
- 중복 생성 0%
- 오타·누락 제거
- 모든 문의가 타임스탬프 기반 히스토리로 축적
- 조회/분석도 깨끗한 프로덕션 데이터만 사용
🌐 4) 고객 대응 품질 상승
- 과거 문의 히스토리를 즉시 조회 가능
- 상담의 연속성 확보
- 향후 통계·리포트 자동 생성 기반 마련
4. 이번 프로젝트에서 얻은 설계 원칙
🧩 1) 명시성 > 암묵성
Dropdown 형태의 명시적 데이터가 자동화를 안정적으로 만든다.
🧩 2) AI 출력은 반드시 Code Node로 후처리
AI는 확률적이므로, 시스템의 핵심 포맷(JSON)은 결정론적으로 보정한다.
🧩 3) 검색은 유사가 아니라 “정확 일치”
CRM 데이터는 오차허용이 없다.
🧩 4) Polling 기반 트리거는 “여러 행 입력 가능성”을 전제로 설계
필요 시 Loop를 기본 고려.
🧩 5) Match Key는 변하지 않는 불변값(Unique ID)만 사용
상태(Status)처럼 바뀌는 값을 기준으로 검색하면 안 된다.
5. 마무리
이번 4편에서는
- 구축 과정에서 마주친 실제 문제들
- 기술적 원인 분석
- 구조적 해결 방식
- 자동화가 가져온 정량적 효과
까지 모두 다뤘습니다.
이 시리즈가 n8n을 기반으로 한 AI·Human-in-the-loop CRM 구축에 관심 있는
개발자, 기획자, 운영 담당자들에게 하나의 참고 사례가 되었으면 합니다.