웹훅 Google Sheets 연동: 운영 환경 테스트 결과
웹훅 Google Sheets 연동: Ai Flowi 자체 작업 공간에서 진행한 내부 시연이며, 고객의 성과가 아닙니다. 8 and 2026년 10월 9일에 실제 HTTP 요청을 보내고 시트를 다시 읽어, 유효한 입력으로 행이 정상적으로 기록된 결과, 잘못된 입력의 거부, 가져오기 후 재테스트와 순차 중복 방지를 기록했습니다. 스프레드시트 쓰기 실패 시 응답 요건은 충족하지 못했습니다.
작성: Ai Flowi · 게시일 · 수정일 . 아래 테스트 날짜는 내부 보고서를 따릅니다. [1]
이 페이지는 모델을 사용하지 않는 워크플로의 테스트 결과를 기록합니다. 노드 연결과 검증 쿼리는 상위 튜토리얼을 참고하세요. 빌더의 사용 맥락은 AI Flowi Workflow 제품 개요에서 확인할 수 있습니다. 테스트 근거는 기록된 구성만 다룹니다.
방법과 환경
실제 HTTP POST 요청을 https://workflow.aiflowi.com/api/v1/webhook/<flow-id>로 보냈으며, 로그인한 브라우저의 Playwright 요청 컨텍스트를 사용했습니다. 이 엔드포인트는 템플릿이며, 비공개 워크플로 식별자는 공개하지 않습니다. 최종 워크플로는 Universal Webhook 및 Platform API Key 인증을 사용했고, 응답 모드는 From Flow로 설정했습니다. 각 요청에는 Content-Type: application/json 헤더를 사용했습니다. 실행마다 임시 인증을 생성했으며, 실행 후 삭제를 확인했습니다. [1] [2] [3]
| 항목 | 기록된 구성 |
|---|---|
| 플랫폼 | workflow.aiflowi.com의 AI Flowi Workflow 1.9.2. 버전 엔드포인트는 2026년 10월 8일에 확인했습니다. |
| 격리 | Ai Flowi 자체 작업 공간에서 앱으로 생성한 합성 데이터 전용 테스트 스프레드시트, 전용 테스트 워크플로, 잘못된 스프레드시트를 지정한 별도 변형과 새로 가져온 사본을 사용했습니다. |
| Google 접근 | 작업 공간에 이미 승인된 Google 연결을 사용했습니다. 연결 값과 Spreadsheet ID는 공개하지 않습니다. |
| 10월 8일 행 추가 워크플로 | 노드 7개, 연결 6개. 검증 → Verification Router → 행 데이터 준비 → Append Rows (Sheet1!A:C, USER_ENTERED) → 200 응답. 검증에서 거부된 입력 → 422 응답. |
| 10월 9일 중복 방지 워크플로 | 노드 8개, 연결 7개. event_id가 필요합니다. 탭(여기서는 DemoEvents라는 별칭 사용)에 Upsert Row를 적용하고, 헤더 행은 1, 키 열은 event_id, 일치 여부는 대소문자를 구분하며 입력 방식은 RAW입니다. 응답 필드 선택을 통해 삽입 또는 중복 상태를 반환합니다. 검증에서 거부된 입력 → 422. |
| 측정 | 각 요청 후 Read Range로 테스트 시트를 읽습니다. HTTP 상태와 요청 전후 행 수를 비교합니다. v2 실행기는 행 배열, 일치하는 이벤트 ID와 응답 본문도 비교합니다. v2 행 수에는 헤더를 포함하지 않습니다. |
[1] [2] [3] 요청은 순차적으로 실행했습니다. 기존 합성 데이터 행이 있어 시작 시에도 행이 존재했습니다. 이 총계는 고객 기록 수가 아닙니다.
2026년 10월 8일: Append Rows와 가져오기 후 재테스트
유효한 입력은 행을 기록했고, 잘못된 입력과 인증 실패는 행을 기록하지 않았습니다. 중복 요청 쌍은 두 번 모두 행을 추가했습니다. 이 초기 워크플로의 “예상” 열은 보고된 워크플로 설계에서 도출한 재현 목표입니다. 제공된 보고서에는 스프레드시트 쓰기 실패 사례의 HTTP 상태가 지정되어 있지 않았습니다. “관찰” 열은 기록된 HTTP 상태와 요청 전 → 후 행 수이며, 괄호 안은 추가된 행 수입니다. [1] [3]
| 테스트 / 요청 본문 | 예상 HTTP / 추가 행 수 | 원본에서 관찰한 HTTP 상태 / 행 수 | 가져온 사본에서 관찰한 HTTP 상태 / 행 수 |
|---|---|---|---|
| T1 유효한 입력과 인증 정보를 포함한 요청 | 200 / +1 | 200 / 3 → 4 (+1) | 200 / 6 → 7 (+1) |
| T2 필수 필드 누락 (email) | 422 / +0 | 422 / 4 → 4 (+0) | 422 / 7 → 7 (+0) |
| T3 잘못된 필드 유형 (name이 숫자) | 422 / +0 | 422 / 4 → 4 (+0) | 422 / 7 → 7 (+0) |
| T3b 잘못된 이메일 형식 | 422 / +0 | 422 / 4 → 4 (+0) | 422 / 7 → 7 (+0) |
| T4 형식이 잘못된 JSON | 422 / +0 | 422 / 4 → 4 (+0) | 422 / 7 → 7 (+0) |
| T5 API 키 누락 | 403 / +0 | 403 / 4 → 4 (+0) | 403 / 7 → 7 (+0) |
| T6 유효하지 않은 API 키 | 403 / +0 | 403 / 4 → 4 (+0) | 403 / 7 → 7 (+0) |
| T7 Google 스프레드시트 접근 실패 (존재하지 않는 시트 ID) | 실패, HTTP 상태 미지정 / +0 | 404 오류 원문 / 4 → 4 (+0) | 재실행하지 않음 |
| T8a 중복 전달 – 첫 번째 | 200 / +1 | 200 / 4 → 5 (+1) | 200 / 7 → 8 (+1) |
| T8b 중복 전달 – 동일한 두 번째 요청 | 200 / +1 | 200 / 5 → 6 (+1) | 200 / 8 → 9 (+1) |
민감 정보를 제거한 JSON을 업로드한 결과 HTTP 201이 반환됐고, 노드 7개와 연결 6개가 유지됐습니다. Google account 필드는 비어 있었고 Spreadsheet ID는 YOUR_SPREADSHEET_ID였습니다. 요청을 다시 보내기 전에 테스트 연결과 시트를 설정했습니다. T7은 이 가져온 사본에서 재실행하지 않음 상태였으며, 별도의 실패 시험용 워크플로가 필요했습니다. [1]
관찰된 응답 예: 원본의 T1 응답에는 updatedRows: 1 및 Sheet1!A4:C4가 포함됐고, 가져온 사본의 응답에는 Sheet1!A7:C7가 포함됐습니다. T2 응답에는 Validation failed 및 email is required and must be a valid address가 포함됐으며, T3 응답에는 name is required and must be text가 포함됐습니다. T4 응답에는 Request body must be a JSON object with name, email and request.가 포함됐습니다. T5와 T6 응답에는 각각 API 키가 필요하다는 오류와 API 키가 유효하지 않다는 오류가 포함됐습니다. [1]
2026년 10월 9일: 순차 중복 방지와 가져오기 후 재테스트
원본과 가져온 사본은 각각 실행 중 데이터 행 여섯 개를 삽입했습니다. 동일한 요청을 순차적으로 재시도했을 때 {"status":"duplicate"}를 반환했고, 두 번째 행을 삽입하지 않고 기존 행을 업데이트했습니다. 이벤트 ID만 다르고 나머지 필드가 동일한 요청은 행 두 개를 삽입했습니다. T9는 해당 이벤트 ID와 일치하는 행이 정확히 하나인지 확인했습니다. 이는 순차 실행에서 관찰한 결과입니다. [1] [2]
| 테스트 / 요청 본문 | 예상 HTTP / 추가 행 수 | 원본에서 관찰한 HTTP 상태 / 행 수 | 가져온 사본에서 관찰한 HTTP 상태 / 행 수 | 관찰된 응답 / 결과 |
|---|---|---|---|---|
| T1 유효한 입력과 인증 정보를 포함한 요청 | 200 / +1 | 200 / 0 → 1 (+1) | 200 / 6 → 7 (+1) | {"status":"inserted"} |
| T2 필수 필드 누락 (email) | 422 / +0 | 422 / 1 → 1 (+0) | 422 / 7 → 7 (+0) | 422; 검증 실패 |
| T3 잘못된 필드 유형 (name이 숫자) | 422 / +0 | 422 / 1 → 1 (+0) | 422 / 7 → 7 (+0) | 422; 검증 실패 |
| T3b 잘못된 이메일 형식 | 422 / +0 | 422 / 1 → 1 (+0) | 422 / 7 → 7 (+0) | 422; 검증 실패 |
| T4 형식이 잘못된 JSON | 422 / +0 | 422 / 1 → 1 (+0) | 422 / 7 → 7 (+0) | 422; 본문이 객체가 아닌 오류 |
| T5 API 키 누락 | 403 / +0 | 403 / 1 → 1 (+0) | 403 / 7 → 7 (+0) | 403; API 키 필요 |
| T6 유효하지 않은 API 키 | 403 / +0 | 403 / 1 → 1 (+0) | 403 / 7 → 7 (+0) | 403; 유효하지 않은 API 키 |
| T7 잘못된 시트: 정해진 형식의 오류 응답 요건 | 정해진 형식의 502 오류 응답 / +0 | 404 오류 원문 / 1 → 1 (+0) | 404 오류 원문 / 7 → 7 (+0) | 미충족: 컴포넌트 오류 원문 |
| T8a 중복 전달 – 첫 번째 | 200 / +1 | 200 / 1 → 2 (+1) | 200 / 7 → 8 (+1) | {"status":"inserted"} |
| T8b 중복 전달 – 두 번째 | 200 / +0 | 200 / 2 → 2 (+0) | 200 / 8 → 8 (+0) | {"status":"duplicate"} |
| T9a 동일한 event_id – 첫 번째 | 200 / +1 | 200 / 2 → 3 (+1) | 200 / 8 → 9 (+1) | {"status":"inserted"} |
| T9b 동일한 event_id – 두 번째 | 200 / +0 | 200 / 3 → 3 (+0) | 200 / 9 → 9 (+0) | {"status":"duplicate"} |
| T10a 다른 event_id, 동일한 나머지 필드 – 첫 번째 | 200 / +1 | 200 / 3 → 4 (+1) | 200 / 9 → 10 (+1) | {"status":"inserted"} |
| T10b 다른 event_id, 동일한 나머지 필드 – 두 번째 | 200 / +1 | 200 / 4 → 5 (+1) | 200 / 10 → 11 (+1) | {"status":"inserted"} |
| T11-0 유효하지 않은 event_id | 422 / +0 | 422 / 5 → 5 (+0) | 422 / 11 → 11 (+0) | 422; event_id 검증 상세 메시지 |
| T11-1 유효하지 않은 event_id | 422 / +0 | 422 / 5 → 5 (+0) | 422 / 11 → 11 (+0) | 422; event_id 검증 상세 메시지 |
| T11-2 유효하지 않은 event_id | 422 / +0 | 422 / 5 → 5 (+0) | 422 / 11 → 11 (+0) | 422; event_id 검증 상세 메시지 |
| T11-3 유효하지 않은 event_id | 422 / +0 | 422 / 5 → 5 (+0) | 422 / 11 → 11 (+0) | 422; event_id 검증 상세 메시지 |
| T11-4 유효하지 않은 event_id | 422 / +0 | 422 / 5 → 5 (+0) | 422 / 11 → 11 (+0) | 422; event_id 검증 상세 메시지 |
| T12 event_id 100자 | 200 / +1 | 200 / 5 → 6 (+1) | 200 / 11 → 12 (+1) | {"status":"inserted"} |
T11-0부터 T11-4까지는 이벤트 ID의 누락, null, 숫자, 빈 문자열, 101자 길이를 각각 시험한 다섯 개의 테스트입니다. 각 실행에서 다섯 개 모두 422를 반환했습니다. T12는 정확히 100자를 사용했고 행 하나를 추가했습니다. 실행기는 T11의 오류 상세 메시지로 event_id is required and must be text between 1 and 100 characters를 요구했습니다. [1] [2]
운영 환경에서 내보내기한 결과 HTTP 200이 반환됐으며, 구성은 노드 8개와 연결 7개였습니다. 민감 정보 제거 후 기록된 비밀 정보 검사에서는 0건이 탐지됐습니다. 민감 정보를 제거한 JSON을 새 워크플로에 업로드한 결과 HTTP 201이 반환됐습니다. Google account는 비어 있었고 Spreadsheet ID는 YOUR_SPREADSHEET_ID였습니다. 두 필드를 모두 설정한 뒤 재테스트했습니다. 원본과 가져온 사본의 실패 시험용 변형 모두 404 오류 원문을 반환했으므로, 정해진 형식의 502 오류 응답 요건은 여전히 충족되지 않았습니다. [1]
합성 입력: 민감 정보를 제거한 정확한 요청 본문
각 사례를 펼치면 요청 본문 전체를 복사할 수 있습니다. 동일한 조건에서 항상 같은 요청 본문이 생성되도록 원본 실행기의 요청을 재구성하고 명시적으로 민감 정보를 제거했습니다. 이름에 포함된 내부 티켓 표시는 Demo로 바꾸었습니다. 생성된 v2 실행 접두사는 원본 실행의 경우 demonstration-01로, 가져온 사본 실행의 경우 demonstration-02로 바꾸었습니다. 다른 모든 페이로드 필드는 유지했습니다. T12에는 x를 다시 채워 정확히 100자를 유지했습니다. v2 근거에는 캡처한 요청 바이트가 아닌 결과가 기록되어 있습니다. 여기 제시된 것은 민감 정보를 제거한 정확한 재현용 본문이며, 원래 생성된 식별자를 공개한다는 의미는 아닙니다. 인증 값은 공개하지 않습니다. [2] [3]
10월 8일 Append Rows 사례
가져온 행 추가 워크플로에서도 T7을 제외한 동일한 본문으로 테스트를 반복합니다. [1] [3]
T1 — 유효한 입력과 인증 정보를 포함한 요청
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":"Demo Test T1","email":"t1@example.com","request":"Synthetic webhook test T1"}T2 — 필수 필드 누락 (email)
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":"Demo Test T2","request":"missing email"}T3 — 잘못된 필드 유형 (name이 숫자)
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":12345,"email":"t3@example.com","request":"wrong type"}T3b — 잘못된 이메일 형식
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":"Demo Test T3b","email":"not-an-email","request":"bad email"}T4 — 형식이 잘못된 JSON
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name": "Demo Test T4", "email": 본문은 콜론과 그 뒤의 공백 하나로 끝납니다. 이 바이트를 텍스트로 보내세요. 내용을 보완하거나 JSON으로 인코딩하지 마세요.
T5 — API 키 누락
POST · Content-Type: application/json · 인증: x-api-key 헤더를 생략합니다. 대상: 테스트 워크플로.
{"name":"Demo Test T5","email":"t5@example.com","request":"Synthetic webhook test T5"}T6 — 유효하지 않은 API 키
POST · Content-Type: application/json · 인증: 의도적으로 유효하지 않은 키 사용 (값은 비공개). 대상: 테스트 워크플로.
{"name":"Demo Test T6","email":"t6@example.com","request":"Synthetic webhook test T6"}T7 — Google 스프레드시트 접근 실패 (존재하지 않는 시트 ID)
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 잘못된 스프레드시트를 지정한 별도 워크플로.
{"name":"Demo Test T7","email":"t7@example.com","request":"Synthetic webhook test T7"}T8a — 중복 전달 – 첫 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":"Demo Test T8","email":"t8@example.com","request":"Synthetic webhook test T8"}T8b — 중복 전달 – 동일한 두 번째 요청
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":"Demo Test T8","email":"t8@example.com","request":"Synthetic webhook test T8"}10월 9일 Upsert Row 사례
가져온 사본을 실행할 때는 모든 이벤트 ID에서 demonstration-01 대신 demonstration-02를 사용하세요. T12는 해당 접두사와 마지막 하이픈 뒤에 x를 채워 정확히 100자로 만듭니다. T8a/T8b와 T9a/T9b는 각 쌍 안에서 동일한 이벤트 ID를 유지해야 합니다. T10a/T10b는 이벤트 ID만 다릅니다. [2]
T1 — 유효한 입력과 인증 정보를 포함한 요청
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T1","name":"Demo Test T1","email":"t1@example.com","request":"Synthetic webhook test T1"}T2 — 필수 필드 누락 (email)
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T2","name":"T2","request":"missing email"}T3 — 잘못된 필드 유형 (name이 숫자)
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T3","name":12345,"email":"t3@example.com","request":"Synthetic webhook test T3"}T3b — 잘못된 이메일 형식
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T3b","name":"Demo Test T3b","email":"not-an-email","request":"Synthetic webhook test T3b"}T4 — 형식이 잘못된 JSON
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name": "T4", "email": 본문은 콜론과 그 뒤의 공백 하나로 끝납니다. 이 바이트를 텍스트로 보내세요. 내용을 보완하거나 JSON으로 인코딩하지 마세요.
T5 — API 키 누락
POST · Content-Type: application/json · 인증: x-api-key 헤더를 생략합니다. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T5","name":"Demo Test T5","email":"t5@example.com","request":"Synthetic webhook test T5"}T6 — 유효하지 않은 API 키
POST · Content-Type: application/json · 인증: 의도적으로 유효하지 않은 키 사용 (값은 비공개). 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T6","name":"Demo Test T6","email":"t6@example.com","request":"Synthetic webhook test T6"}T7 — 잘못된 시트: 정해진 형식의 오류 응답 요건
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 잘못된 스프레드시트를 지정한 별도 워크플로.
{"event_id":"demonstration-01-T7","name":"Demo Test T7","email":"t7@example.com","request":"Synthetic webhook test T7"}T8a — 중복 전달 – 첫 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T8","name":"Demo Test T8","email":"t8@example.com","request":"Synthetic webhook test T8"}T8b — 중복 전달 – 두 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T8","name":"Demo Test T8","email":"t8@example.com","request":"Synthetic webhook test T8"}T9a — 동일한 event_id – 첫 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T9","name":"Demo Test T9","email":"t9@example.com","request":"Synthetic webhook test T9"}T9b — 동일한 event_id – 두 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T9","name":"Demo Test T9","email":"t9@example.com","request":"Synthetic webhook test T9"}T10a — 다른 event_id, 동일한 나머지 필드 – 첫 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T10a","name":"Demo Test T10","email":"t10@example.com","request":"Synthetic webhook test T10"}T10b — 다른 event_id, 동일한 나머지 필드 – 두 번째
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-T10b","name":"Demo Test T10","email":"t10@example.com","request":"Synthetic webhook test T10"}T11-0 — 유효하지 않은 event_id
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"name":"Demo Test T11","email":"t11@example.com","request":"Synthetic webhook test T11"}T11-1 — 유효하지 않은 event_id
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":null,"name":"Demo Test T11","email":"t11@example.com","request":"Synthetic webhook test T11"}T11-2 — 유효하지 않은 event_id
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":123,"name":"Demo Test T11","email":"t11@example.com","request":"Synthetic webhook test T11"}T11-3 — 유효하지 않은 event_id
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"","name":"Demo Test T11","email":"t11@example.com","request":"Synthetic webhook test T11"}T11-4 — 유효하지 않은 event_id
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","name":"Demo Test T11","email":"t11@example.com","request":"Synthetic webhook test T11"}T12 — event_id 100자
POST · Content-Type: application/json · 인증: 유효한 임시 Platform API Key. 대상: 테스트 워크플로.
{"event_id":"demonstration-01-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","name":"Demo Test T12","email":"t12@example.com","request":"Synthetic webhook test T12"}문서화된 한계
버전 1.9.2에서는 Google Sheets 쓰기 실패 시 여전히 플랫폼 오류가 그대로 반환됩니다. v2 T7의 목표 결과는 HTTP 502와 정확히 다음 본문이었습니다: {"error":"Spreadsheet write failed","code":"SHEET_WRITE_FAILED"}. 두 실행 모두 컴포넌트 오류 원문과 HTTP 404를 반환했습니다. 테스트 시트는 변경되지 않았습니다. 근거에서 식별자를 가리기 전에는 오류에 Google API URL과 Spreadsheet ID가 포함되어 있었습니다. 보고서에는 해당 응답에 인증 정보가 없었다고 기록되어 있습니다. 성공 응답의 필드를 선택하는 것만으로는 실패 응답의 민감 정보가 제거되지 않습니다. [1] [2]
Google Sheets 컴포넌트에는 워크플로 내부 실패 분기를 위한 오류 출력이 없습니다. 실패가 발생하면 후속 Webhook Response가 실행되기 전에 그래프가 중단되며, From Flow 응답 템플릿도 이를 처리하지 못합니다. 문서에 명시된 ‘찾을 수 없음’ 오류는 HTTP 404로 반환되지만 다른 오류는 500이 될 수 있습니다. 정해진 형식의 실패 응답 본문을 반환하려면 플랫폼 변경이나 별도로 구현한 게이트웨이가 필요합니다. 여기서는 어느 쪽도 구현됐다고 주장하지 않습니다. [1] [2]
- 동시 중복 요청 실측: 2026년 10월 9일에 하나의
event_id로 다섯 건을 동시에 전달했을 때 모두 200을 반환했고, 시트 행 3개가 추가됐습니다 (15 → 18; 일치하는 이벤트 행 0 → 3). 이 워크플로는 동시 요청에 안전하지 않습니다. 발신자가 순차적으로 전달하도록 하거나 후속 단계에서 중복을 제거하세요. Upsert Row는 원자적 고유성 검사나 요청 간 잠금 없이 읽기와 쓰기를 수행합니다. [4] - 중복 요청은 업데이트입니다. 중복 요청도 Google Sheets에 쓰기를 수행합니다. 같은 이벤트 ID로 변경된 페이로드를 보내면 전달한 필드를 덮어쓰며, 마지막으로 성공한 업데이트가 최종 값이 됩니다. 동일한 본문으로 수행한 런타임 테스트는 최초 전달 내용을 변경 없이 보존하는 처리를 입증하지 않습니다. [1] [2]
- 범위와 보존은 시트에 따라 달라집니다. 대소문자를 구분하고 앞뒤 공백을 제거하지 않은 이벤트 ID가 한 워크시트에 저장됩니다. 해당 워크시트로 보내는 모든 발신자는 같은 키 공간을 공유합니다. 다른 워크시트의 키 공간은 독립적입니다. 만료나 별도의 수신 로그는 없습니다. 키를 삭제하거나 수정하면 이후 요청에서 다시 삽입될 수 있습니다. 기존 중복 행은 병합되지 않습니다. 수동 편집이나 스키마 변경으로 조회가 올바르게 동작하지 않을 수 있습니다. [1] [2]
- 설정이 중요합니다. JQ 쿼리 필드를 표시된 상태로 유지하세요. 이전에 필드를 숨긴 상태로 실행했을 때는
JSON Query is required and cannot be blank오류로 실패했습니다. 최종 행 추가 설계는 Verification Router를 사용합니다. 기록된 편집기 자동 저장 검사에서는 연결 여섯 개가 모두 유지됐습니다. 이전 Condition 라우터에서는 거부 출력의 연결이 사라졌습니다. [1] - 내보낸 파일은 민감 정보 제거가 필요합니다. 일괄 내보내기 결과에는 정리 전 Google 라벨, 연결 및 스프레드시트 식별자, 웹훅 URL과 계정/워크플로 메타데이터가 남아 있었습니다. 기록된 검사에서 비밀 정보가 탐지되지 않았다는 결과는 민감 정보를 제거한 해당 파일에만 적용되며, 앞으로 내보낼 임의의 파일에는 적용되지 않습니다. 행 추가 HTTP 응답에는 실행 ID가 없었고, 플랫폼 트랜잭션 로그에는 컴포넌트 실행이 기록되어 있었습니다. [1]
테스트하지 않은 항목
이번 실행에서는 부하, 성능 벤치마크로서의 지연 시간, 대규모 동시 요청을 테스트하지 않았습니다. 아래 신뢰성 재테스트는 중복 요청 다섯 건을 동시에 보낸 배치 하나를 측정했으며, 대규모 동작을 입증하지 않습니다. 설계에 설명된 오프라인 중첩 읽기 검사는 로컬 Google API 스텁을 사용했으므로 운영 환경의 동시 요청 실측이 아닙니다. External Provider 인증은 테스트하지 않았습니다. 모델을 사용하지 않은 이 테스트 결과는 모델 기반 구성 예제의 런타임 동작, 광범위한 Google 장애 복구 또는 고객 성과를 입증하지 않습니다. [1] [2] [3]
관련 자료: 웹훅 필드 매핑 도구: Google Sheets용.
재현 방법
검증된 Append Rows 워크플로 다운로드 · 순차 중복 방지 워크플로 다운로드. 문서화된 가져오기 후 재테스트에 사용한, 민감 정보를 제거한 워크플로 패키지입니다. 중복 방지 압축 파일에는 ai-flowi-webhook-to-google-sheets-duplicate-protection.json이 포함되어 있습니다. [1] [3] 상위 튜토리얼의 다운로드 및 설정 안내.
- 격리된 합성 데이터 테스트 스프레드시트를 만드세요. Append Rows에는
Sheet1을 사용하고, 열을name,email,request순서로 배치하세요. Upsert Row는 가져온 Upsert Row의 시트 제목을DemoEvents로 바꾸고, 같은 이름의 별도 탭을 추가하세요. 1행은 정확히event_id,name,email,request로 설정하세요. 테스트 대상에 고객 시트를 지정하지 마세요. [1] [2] - 압축을 풀고 선택한 JSON을 새 워크플로에 업로드하세요. 승인된 Google 계정을 설정하고
YOUR_SPREADSHEET_ID를 바꾸세요. 가져온 그래프가 행 추가의 경우 노드 7개 / 연결 6개, 업서트의 경우 8 / 7인지 확인하세요. 상위 튜토리얼의 행 추가 설정 또는 중복 방지 설정을 사용하세요. [1] - Universal Webhook을 POST, Platform API Key, From Flow로 설정하세요. 검증 및 행 데이터 구성용 JQ 필드를 표시된 상태로 유지하고, 성공 응답은 200, 거부 응답은 422로 설정하세요. Upsert Row는 헤더 행을 1로 지정하고,
event_id를 키 열로 사용하며, 대소문자를 구분하는 일치 방식과RAW를 사용하세요. [1] [2] - 초기 시트 행을 기록하세요. 위의 민감 정보를 제거한 본문을 나열된 순서대로 자신의 편집기에 표시된 엔드포인트로 보내세요. 유효한 인증 사례에는 임시
x-api-key헤더를 사용하고, T5에서는 생략하며, T6에서는 의도적으로 유효하지 않은 값을 사용하세요. T4는 잘린 텍스트를 그대로 보내세요. 각 요청 후 시트를 읽고 HTTP 상태, 응답 본문, 요청 전후 행 수와 추가 행 수를 기록하세요. 재실행할 때 새 네임스페이스를 사용하려면 각 쌍 안에서 접두사를 일관되게 바꾸고 T12를 다시 채워 정확히 100자로 만드세요. [2] [3] - T7은 복사한 별도의 실패 시험용 변형에 존재하지 않는 Spreadsheet ID를 지정해서만 실행하세요. 실제 테스트 시트를 다시 읽어 변경되지 않았는지 확인하세요. 응답 원문은 비공개로 기록하고, 근거를 공유하기 전 식별자를 가리세요. 1.9.2에서는 정해진 형식의 오류 응답 요건이 여전히 충족되지 않을 것으로 예상하세요. [1] [2] [3]
- 새로 가져온 사본의 비어 있는 Google 필드와 시트 자리표시자를 설정한 뒤 같은 순서로 반복하세요. v2에는 민감 정보를 제거한 두 번째 네임스페이스를 사용해 원본 실행의 기존 키가 삽입 수에 영향을 주지 않도록 하세요. 문서화된 행 추가 가져오기 테스트는 T7을 건너뛰었고, v2 가져오기 테스트는 이를 반복했습니다. 과거의 절대 행 번호가 아닌 증감량을 비교하세요. [1] [2] [3]
- 테스트 후 임시 인증을 폐기하고 계정에 더 이상 표시되지 않는지 확인하세요. 새로 내보낸 파일은 공유 전에 점검하고, 재현에는 제공된 민감 정보 제거 다운로드 파일을 사용하세요. 테스트 쓰기와 시트 다시 읽기도 워크플로 노드를 실행합니다. [1] [2] [3]
신뢰성 재테스트 (2026년 10월 9일)
수정일: 2026년 10월 9일. 기록된 테스트는 중복 방지 워크플로에서 2026년 10월 9일, 09:12:21–09:13:34 MYT (UTC+8)에 진행됐습니다. 내부 합성 데이터 테스트입니다. 아래 행 수는 시트의 데이터 행 수이며, 이벤트 행 수는 테스트한 event_id에 해당하는 행만 셉니다. [4]
| 사례 | 예상 | 관찰된 상태 | 요청 전 / 후 행 수 | 판정 |
|---|---|---|---|---|
| 유효한 요청 | HTTP 200; +1행; 이벤트 행 1개 | HTTP 200; 삽입됨 | 12 → 13 (+1); 이벤트 행 0 → 1 | 통과 |
| 필드 누락 | HTTP 422; +0행; 이벤트 행 0개 | HTTP 422 | 13 → 13 (+0); 이벤트 행 0 → 0 | 통과 |
| 잘못된 유형 | HTTP 422; +0행; 이벤트 행 0개 | HTTP 422 | 13 → 13 (+0); 이벤트 행 0 → 0 | 통과 |
| 형식이 잘못된 JSON | HTTP 422; +0행; 이벤트 행 0개 | HTTP 422 | 13 → 13 (+0); 이벤트 행 0 → 0 | 통과 |
| 빈 본문 | HTTP 422; +0행; 이벤트 행 0개 | HTTP 422 | 13 → 13 (+0); 이벤트 행 0 → 0 | 통과 |
| 키 누락 | HTTP 403; +0행; 이벤트 행 0개 | HTTP 403 | 13 → 13 (+0); 이벤트 행 0 → 0 | 통과 |
| 유효하지 않은 키 | HTTP 403; +0행; 이벤트 행 0개 | HTTP 403 | 13 → 13 (+0); 이벤트 행 0 → 0 | 통과 |
| 클라이언트 시간 초과 | 클라이언트의 요청 중단과 이후 시트 상태 관찰. 서버 작업 취소는 가정하지 않음 | HTTP 상태 없음: 1,000 ms 후 CLIENT_TIMEOUT; 행 쓰기 관찰됨 | 13 → 14 (+1); 이벤트 행 0 → 1 | 관찰됨 |
| 시간 초과 후 재시도 | HTTP 200; +0행; 이벤트 행 1개 | HTTP 200; 중복 | 14 → 14 (+0); 이벤트 행 1 → 1 | 통과 |
| 순차 중복 요청 (전달 1) | HTTP 200; +1행; 이벤트 행 1개 | HTTP 200; 삽입됨 | 14 → 15 (+1); 이벤트 행 0 → 1 | 통과 |
| 순차 중복 요청 (전달 2) | HTTP 200; +0행; 이벤트 행 1개 | HTTP 200; 중복 | 15 → 15 (+0); 이벤트 행 1 → 1 | 통과 |
| 순차 중복 요청 (전달 3) | HTTP 200; +0행; 이벤트 행 1개 | HTTP 200; 중복 | 15 → 15 (+0); 이벤트 행 1 → 1 | 통과 |
| 동시 중복 요청 | 응답 다섯 개. 목표는 이벤트 행 하나이며, 경합 상황 관찰 | 200 × 5; 삽입됨 × 3, 중복 × 2 | 15 → 18 (+3); 이벤트 행 0 → 3 | 동시 요청에 안전하지 않음 (관찰됨) |
| 큰 페이로드 | 약 50 KB 요청 텍스트의 수락/거부와 실제 쓰기 결과 관찰. 플랫폼 크기 제한은 가정하지 않음. | HTTP 200; 삽입됨; 50,132바이트 본문 / 50,000바이트 요청 텍스트 (~50 KB) 수락 | 18 → 19 (+1); 이벤트 행 0 → 1 | 관찰됨 |
| 상위 시스템 오류 | 2xx가 아닌 응답과 변경되지 않은 합성 데이터 시트. 근거에서 식별자를 가리기 전 실제 오류 원문 노출 확인. | HTTP 404; 플랫폼 오류 원문; 식별자를 가리기 전 스프레드시트 식별자와 오류 상세 정보 원문 노출 | 19 → 19 (+0); 이벤트 행 0 → 0 | 관찰됨 |
클라이언트 시간 초과는 행 쓰기를 막지 못했습니다. 클라이언트는 1,000 ms에 요청을 중단했습니다. 이후 세 번의 스냅숏 모두 이벤트 행 하나를 확인했습니다 (요청 시작 후 2,415, 7,383 및 17,397 ms). 정확한 서버 쓰기 시점은 알 수 없습니다. 따라서 이 검사는 클라이언트 중단에도 행이 기록됐음을 보여 주지만, 중단 시점과 비교해 언제 쓰기가 완료됐는지는 알려 주지 않습니다. 같은 event_id로 순차적으로 재시도했을 때 200과 중복 상태를 반환했고 추가 행은 기록되지 않았습니다. 세 차례 순차 전달에서도 이벤트 행은 하나만 남았습니다.
동시 중복 요청에서 발견된 문제: 2026년 10월 9일에 하나의 event_id로 다섯 건을 동시에 전달했을 때 모두 200을 반환했고, 시트 행 3개가 추가됐습니다 (15 → 18; 일치하는 이벤트 행 0 → 3). 이 워크플로는 동시 요청에 안전하지 않습니다. 발신자가 순차적으로 전달하도록 하거나 후속 단계에서 중복을 제거하세요. 추가된 시트 행 3개는 해당 이벤트의 총 3개 행이며, 목표인 단일 행보다 2개 많습니다. 배치 스냅숏은 공통으로 사용하므로, 응답마다 +3을 다시 더하지 마세요.
상위 시스템 오류: 제공된 변형 워크플로는 잘못된 스프레드시트를 지정한 상태로 플랫폼 오류 원문과 HTTP 404를 반환했고, 시트 행 수는 19 → 19로 유지됐습니다. 식별자를 가린 오류에는 Requested entity was not found.와 Upsert Row 그래프 실패가 보고됐습니다. 식별자를 가리기 전 검사에서는 스프레드시트 식별자와 플랫폼 오류 상세 정보 원문이 기록됐지만, 인증 정보는 없었습니다. 버전 1.9.2에는 워크플로 내부 Google 오류 분기가 없습니다.
검증된 v1 사례: 이번 재테스트에서 실행하지 않음. 비공개 테스트 설정에 해당 워크플로의 명시적인 식별자가 없었습니다. 계획한 12개 사례 모두 여기에는 관찰된 HTTP 상태나 행 수가 없습니다. 위의 이전 v1 결과는 별도의 근거로 유지됩니다. 재테스트는 완료됐고 임시 인증을 삭제했습니다 (HTTP 200; 키 목록에서 사라짐). 그러나 전체 런타임 검증과 필수 검사 상태는 모두 false였습니다. “관찰됨”으로 표시된 행은 관찰 결과를 기록한 것이며, 신뢰성 검증을 통과했다는 보장은 아닙니다. 약 50 KB 요청이 한 번 수락됐다고 해서 최대 페이로드 크기가 입증되지는 않습니다. 시간 초과 검사는 제한된 시간 범위만 다룹니다.
근거 출처
- [1] Ai Flowi 내부 운영 환경 테스트 보고서. 섹션: 설정, 2026년 10월 8일의 최종 원본 워크플로 결과와 새로 가져온 사본, 관찰된 한계, 2026년 10월 9일의 v2 원본/가져온 사본 결과, 스프레드시트 쓰기 실패 처리, v2 다운로드 파일. 운영 환경 관찰 결과의 출처입니다. 내부 테스트 기록이며, 고객의 성과가 아닙니다.
- [2] Ai Flowi 중복 방지 설계 및 운영 환경 테스트 실행기. 설계 섹션: 식별자와 범위, 스프레드시트 쓰기 실패, 정확한 검증, 그래프 필드, 절차와 오프라인 한계. 실행기: 동일한 조건에서 항상 같은 요청 본문을 생성하는 코드, 예상 상태와 행 증감량, 전체 시트 다시 읽기, 응답 검사와 임시 인증 정리. 설계의 초기 “운영 환경에서 검증되지 않음” 상태는 [1]에 기록된 10월 9일 런타임 결과보다 앞선 것입니다. 오프라인 검사만으로는 운영 환경의 성공을 입증하지 않습니다.
- [3] Ai Flowi 검증된 Append Rows 운영 환경 테스트 실행기와 민감 정보를 제거한 워크플로. 실행기: 요청 본문 생성, 누락/유효하지 않은 인증, 형식이 잘못된 JSON, 잘못된 스프레드시트를 지정한 변형 워크플로, 순차 중복 요청 쌍, 시트 다시 읽기와 정리. 런타임 결과는 이전에 실제 실행 없이 수행한 패키지 검사가 아닌 [1]에 근거합니다.
- [4] Ai Flowi 내부 신뢰성 재테스트 근거, 2026년 10월 9일 MYT 기록. 운영 환경 요청 상태, 클라이언트 중단 관찰, 전체 시트 및 이벤트 행 수, 동시 요청 다섯 건 배치, 페이로드 바이트 수, 상위 시스템 오류 노출과 임시 인증 정리. 검증된 v1 사례는 실행하지 않았습니다. 실행 날짜는 근거의 타임스탬프를 따릅니다. 이 페이지는 10월 10일에 업데이트됐습니다.