Google Sheets 행 상태 업데이트

Google Sheets 행 상태 업데이트를 위해 웹훅으로 이벤트 ID와 상태를 받아 입력을 검증하고, 기존 행을 찾아 상태 셀에 기록합니다. ID를 찾지 못하면 쓰기 작업 없이 별도의 응답 경로로 처리합니다. 이 템플릿은 AI 모델을 사용하지 않습니다.

상태: 2026년 10월 9일에 AI Flowi Workflow 1.9.2에서 운영 환경 테스트 완료(34개 중 34개 사례 통과)

작성: Ai Flowi · 게시일 . 수정일 2026년 10월 9일. 운영 환경 테스트 날짜: 2026년 10월 9일 (MYT).

작업

{event_id,status}가 포함된 인증된 HTTP POST 요청을 받습니다. 기존 행에서 대소문자를 구분하여 event_id와 정확히 일치하는 값을 검색합니다. 테스트에서는 상태를 기록한 뒤 HTTP 200과 {"status":"updated"}를 반환했고, 조회 결과 일치하는 행이 없으면 HTTP 404와 {"status":"not-found"}를 반환했습니다. 행을 찾지 못했을 때의 분기에는 쓰기 컴포넌트가 없습니다.

대상 사용자

스프레드시트에 이벤트나 작업 기록을 보관하고, 요청을 보내는 측에서 기존 기록을 대기 중, 진행 중 또는 완료로 표시해야 하는 팀에 적합합니다. 상태는 요청을 보내는 측에서 제공합니다. 이 워크플로는 자유 형식의 상태 텍스트를 받으며, 상태를 추론하거나 업무상 상태 전환 규칙을 강제하지 않습니다.

입력 예시

{"event_id":"demo-event-001","status":"complete"}

두 필드 모두 유니코드 코드 포인트 1–100개로 이루어진 문자열이어야 하며, 공백이 아닌 문자가 하나 이상 있어야 합니다. 공백은 그대로 유지됩니다. ID는 대소문자를 구분하며, 001과 1은 다릅니다. 요청에 포함된 추가 필드는 검증 과정에서 제거됩니다.

설정

  1. 가상 테스트 데이터가 담긴 비공개 스프레드시트와 접근 권한이 부여된 Google 연결을 사용합니다.
  2. YOUR_TAB 탭을 만듭니다. 테스트를 위해 A1을 event_id, B1을 status, C1을 note로 설정합니다. 업데이트 요청을 보내기 전에 기록을 미리 넣어 둡니다. 일반적인 사용에서는 일반 텍스트 형식의 ID, 텍스트가 입력된 셀, 고유한 ID를 사용합니다.
  3. Universal Webhook을 POST, Platform API Key 인증, From Flow 응답 모드로 설정합니다. 요청을 보내는 측의 키는 비공개로 유지합니다.
  4. Search Row의 Key Column을 event_id, Header Row를 1, Sheet Name을 YOUR_TAB으로 설정하고 Case Sensitive Key Match를 활성화합니다. Update Range를 RAW로 설정하고 Include Object Headers를 비활성화합니다.
  5. 아래에 나온 노드를 연결합니다. JSON Operations에서 선택한 작업과 JQ 필드가 보이도록 유지합니다. Combine 노드의 JSON 입력은 목록을 받도록 설정합니다. 요청 처리 중에는 시트 행을 이동, 정렬, 삽입 또는 삭제하지 않습니다.
  6. 비공개 탭에서 문서에 설명된 테스트를 다시 실행합니다. 실제 기록에 워크플로를 사용하기 전에 각 요청의 응답과 시트 전체를 확인합니다.

노드 연결 및 필드 매핑

이 그래프에는 13개 노드가 있습니다. Universal Webhook, 검증용 JSON Operations, 유효한 입력을 처리하는 Verification Router, Search Row, Combine 작업을 사용하는 JSON Operations, 조회 결과를 평가하는 JSON Operations, 찾은 행을 처리하는 Verification Router, Data to Message, Update Range, 성공 응답용 JSON Operations, 그리고 200·404·422 응답을 위한 Webhook Response 노드 3개입니다.

출발 노드.output → 대상 노드.input
출발 노드 출력대상 노드 입력매핑
Universal Webhook.request_dataValidation.data.body를 읽고, 입력이 유효하면 verified, event_id, status만 출력합니다.
Validation.data_outputValid router.verification_result최상위 verified 불리언 값을 사용합니다.
Valid router.verifiedSearch Row.row_dataevent_id를 조회합니다. 이 컴포넌트는 쓰기 작업을 하지 않습니다.
Valid router.verifiedCombine.data입력으로 받은 status와 event_id를 유지합니다.
Search Row.resultCombine.data유지한 입력에 found, key_value, row_number를 추가합니다.
Combine.data_outputLookup JSON Operations.datafound는 불리언 값이어야 합니다. 일치하는 행이 있으면 row_number와 values:[[status]]를 준비합니다.
Lookup.data_outputFound router.verification_resultverified는 조회 결과를 나타냅니다. 행을 찾지 못한 경우에는 응답 정의를 포함합니다.
Found router.verifiedData to Message.data템플릿: 'YOUR_TAB'!B{row_number}.
Data to Message.textUpdate Range.range_nameMessage로 정확한 상태 셀 범위를 전달합니다.
Found router.verifiedUpdate Range.values상태 값 하나가 담긴 values 래퍼를 사용합니다.
Update Range.resultSuccess JSON Operations.dataupdatedCells == 1이어야 합니다. {status:"updated"}만 추출합니다.
Success.data_output200 response.body_dataHTTP 200 application/json.
Found router.rejected404 response.response_definition{status_code:404,body:{status:"not-found"}}. 쓰기 작업을 하지 않습니다.
Valid router.rejected422 response.body_data검증 오류를 반환합니다. 조회나 쓰기 작업을 하지 않습니다.

Combine 노드는 필드 이름이 서로 다른 JSON 객체 두 개를 받습니다. 조회 결과를 추출하는 과정에서 일치한 행의 번호와 키를 검증한 뒤 분기합니다. 검색에는 event_id 헤더를 사용하고, 쓰기에는 상태 열 B를 사용합니다. 열 순서를 바꾸면 범위 템플릿도 수정해야 합니다. Update Range는 셀 하나만 변경하며, 이벤트 ID, 메모와 해당 범위 밖의 다른 셀은 그대로 유지합니다.

JSON Operations 설정

검증, 조회, 성공 처리에는 JQ Expression을 선택합니다. 입력이 두 개인 Combine 노드에서만 Combine을 선택합니다. 선택한 필드가 보이도록 유지합니다.

검증 쿼리

def valid_text: if type == "string" then length >= 1 and length <= 100 and test("\\S") else false end;
.body as $b | if ($b|type) != "object" then
{verified:false,error:"Request body must be a JSON object with event_id and status."}
else [ (if ($b.event_id|valid_text) then empty else "event_id must be non-blank text between 1 and 100 characters" end),
       (if ($b.status|valid_text) then empty else "status must be non-blank text between 1 and 100 characters" end) ] as $errors
| if ($errors|length) > 0 then {verified:false,error:"Validation failed",details:$errors}
else {verified:true,event_id:$b.event_id,status:$b.status} end end

조회 쿼리

if (.found|type) != "boolean" then error("Unexpected search result")
elif .found == false then {verified:false,status_code:404,body:{status:"not-found"}}
elif (.row_number|type) != "number" then error("Invalid matched row")
elif .row_number < 2 or (.row_number|floor) != .row_number or .key_value != .event_id then error("Invalid matched row")
else {verified:true,row_number:.row_number,values:[[.status]]} end

성공 처리 쿼리

if .updatedCells == 1 then {status:"updated"} else error("Unexpected update result") end

관련 자료: Google Sheets 자동 기록: 예약 실행으로 상태 행 저장하기.

민감 정보를 제거한 요청 및 응답 예시

아래 응답 예시는 가상 데이터를 사용한 운영 환경 테스트 결과와 일치했습니다.

POST <production-webhook-url>
Content-Type: application/json
x-api-key: <private-platform-api-key>

{"event_id":"demo-event-001","status":"complete"}

Expected: HTTP 200
{"status":"updated"}
{"event_id":"demo-event-absent","status":"complete"}

Expected: HTTP 404; sheet unchanged
{"status":"not-found"}
{"event_id":"demo-event-001"}

Expected: HTTP 422; sheet unchanged
{"verified":false,"error":"Validation failed","details":["status must be non-blank text between 1 and 100 characters"]}

검증 및 실패 시 동작

운영 환경 테스트에서는 필드 누락, null 값, 잘못된 타입, 빈 문자열, 공백만 있는 문자열, 유니코드 코드 포인트가 100개를 초과하는 문자열이 조회나 쓰기 전에 422를 반환했습니다. 객체가 아닌 본문과 형식이 잘못된 JSON도 운영 환경 테스트에서 422와 {"verified":false,"error":"Request body must be a JSON object with event_id and status."}를 반환했습니다. 플랫폼 키가 없거나 유효하지 않으면 403을 반환했습니다. 인증 응답 본문의 정확한 내용은 플랫폼에서 결정합니다.

Search Row가 성공적으로 실행되어 found:false를 반환한 경우에만 not-found가 생성됩니다. Google 접근 오류는 워크플로를 중단시키며, 플랫폼 오류가 원문 그대로 노출될 수 있습니다. 설정된 컴포넌트 중 이러한 예외를 처리하는 컴포넌트는 없습니다. 조회 결과 형식이 예상과 다르거나 업데이트 결과에서 변경된 셀이 하나가 아니면, 업데이트되었다고 응답하는 대신 오류가 발생합니다.

테스트 결과

운영 환경 HTTP 테스트 34개가 모두 통과했으며, 각 테스트에서 탭 전체를 다시 읽어 검증했습니다. 테스트 내내 시트에는 데이터 행 7개가 유지되었습니다. 성공한 업데이트는 처음 일치한 상태 셀만 변경했고, 일치하는 행이 없거나 입력이 거부된 경우에는 모든 값이 그대로 유지되었습니다. 동일한 요청을 반복했을 때도 값은 변하지 않았습니다. 임시 API 키가 삭제된 것도 확인했습니다.

운영 환경 결과 — 2026년 10월 9일 MYT
사례HTTP 결과시트에 미친 영향판정
T1 — 유효한 기존 행200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T2a — status 누락422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T2b — event_id 누락422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T3a — 숫자형 status422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T3b — 숫자형 event_id422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T4 — 형식이 잘못된 JSON422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T5 — API 키 누락403데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T6 — 유효하지 않은 API 키403데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T7 — 일치하는 event_id 없음404데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T8a — 동일한 업데이트 반복200데이터 행 7 -> 7개. 업데이트를 반복했으며, 값은 그대로 유지되었습니다.통과
T8b — 상태 다시 변경200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T9a — 대소문자 불일치404데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T9b — 앞쪽 공백 불일치404데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T9c — 앞에 0이 있는 텍스트 ID200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T10 — 추가 필드 무시200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T11a — null인 status422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T11b — 빈 status422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T11c — 공백만 있는 status422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T11d — null인 event_id422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T11e — 빈 event_id422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T11f — 공백만 있는 event_id422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T12a — 100자 status200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T12b — 101자 status422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T12c — 미리 등록한 100자 ID200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T12d — 101자 ID422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T13a — 배열 본문422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T13b — null 본문422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T13c — 문자열 본문422데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T14 — RAW로 처리한 수식 형태의 status200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T15 — 공백 유지200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T16 — 중복 키에서 첫 번째 일치 행만 업데이트200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T17a — 공백이 포함된 ID 미리 등록200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과
T17b — 공백을 제거하지 않아 불일치404데이터 행 7 -> 7개. 모든 값이 그대로 유지되었으며, 쓰기 작업이 없었습니다.통과
T18 — 유니코드 status 길이 경계200데이터 행 7 -> 7개. 처음 일치한 상태 셀만 업데이트하고, 다른 셀은 그대로 유지했습니다.통과

테스트한 플랫폼 버전: AI Flowi Workflow 1.9.2. 테스트 날짜: 2026년 10월 9일 (MYT). 경로별로 관찰한 노드 실행 횟수: 측정하지 않음. 가져오기 및 재테스트 결과: 제공된 자료에 따르면 수행되지 않음.

다운로드

워크플로 가져오기 파일 다운로드: 제공되지 않음. 가져온 복사본 테스트를 수행하지 않음. 민감 정보를 제거하여 내보낸 뒤 가져온 복사본 테스트를 완료한 경우에만 공개 가져오기 파일을 추가합니다. 노드 설정은 위에 설명되어 있습니다.

필수 설정

  • 두 Sheets 컴포넌트에 접근 권한이 부여된 Google 연결과 Spreadsheet ID를 설정합니다.
  • YOUR_TAB 탭을 사용하며, 1행의 헤더는 event_id이고 상태는 B열에 있어야 합니다.
  • 텍스트 ID를 미리 등록하고 실행 중에는 행 배치를 변경하지 않습니다.
  • 운영 환경 웹훅 URL과 요청을 보내는 측의 Platform API Key가 필요합니다.
  • 입력이 두 개인 Combine 설정, 조회 결과 분기, 별도의 200·404·422 응답이 필요합니다.

테스트한 버전 및 날짜

테스트한 버전: AI Flowi Workflow 1.9.2. 테스트 날짜: 2026년 10월 9일 (MYT). 제공된 증거는 이 운영 환경 그래프와 가상 테스트 데이터에 해당하며, 가져온 복사본의 결과를 입증하지는 않습니다.

사용량 및 비용 가정

요금제: Go 연간 결제 시 월 USD8부터(월간 USD10), Plus 월 USD16부터(월간 USD20), Pro 100 월 USD80부터(월간 USD100), Pro 200 월 USD160부터(월간 USD200), Pro 500 월 USD400부터(월간 USD500). 매월 5,000~250,000 Flowi Tokens가 제공되며 충전도 가능합니다. 노드 실행 1회당 1토큰, 타사 API 및 모델 사용 요금은 포함되지 않습니다.

이 설계는 AI 또는 LLM 컴포넌트를 사용하지 않으며, 타사 유료 API도 사용하지 않습니다. Google 계정과 시트 접근 권한이 필요하며, 서비스 할당량 제한이 적용됩니다. 아래 추정치는 통과하는 노드마다 한 번씩 실행하고, 라우터 분기 하나만 선택하며, 재시도와 다시 읽어 검증하는 흐름이 없다는 가정에 기반합니다. 운영 환경의 사용량 집계는 아직 확인되지 않았습니다.

설계상 추정치이며, 관찰된 과금 내역이 아닙니다
경로요청당 노드 수요청 100회요청 1,000회요청 10,000회
행 업데이트111,10011,000110,000
행을 찾지 못함88008,00080,000
검증 거부44004,00040,000
그래프 실행 전 인증 거부예상 0예상 0예상 0예상 0

검증을 위해 다시 읽을 때마다 노드 실행이 한 번 추가됩니다. 같은 요청이 반복 전달되면 워크플로가 다시 실행됩니다. 상태가 동일해도 쓰기 작업은 수행됩니다. 실패한 시도와 재시도는 추가 토큰을 소모할 수 있습니다. 타사 API 및 모델 사용량은 요금제에 포함되지 않습니다.

제한 사항

  • 조회와 쓰기는 별개의 호출입니다. 두 호출 사이에 행을 정렬, 삽입 또는 삭제하면 저장된 행 번호가 다른 행을 가리킬 수 있습니다. 행 배치를 변경하지 않습니다. 동시에 구조를 변경해야 한다면 트랜잭션을 지원하는 데이터 저장소를 사용합니다.
  • 검색은 처음 일치한 행을 선택합니다. 중복 ID는 그대로 남습니다. 일반적인 사용에서는 ID를 고유하게 유지해야 합니다.
  • 상태를 동시에 기록하면 서로 덮어쓸 수 있습니다. 충돌 감지나 상태 전환 정책은 없습니다.
  • 상태 열은 B열로 유지해야 합니다. RAW는 수식처럼 보이는 상태 텍스트를 문자 그대로 저장하며, 해당 텍스트를 수식으로 실행하지 않습니다.
  • Google 오류에 대해 민감 정보를 제거한 워크플로 내부 응답은 제공되지 않습니다. 응답이 유실되어도 쓰기 작업은 성공했을 수 있습니다. 전달 결과가 불확실하면 재시도 전에 시트를 확인합니다.
  • 운영 환경 테스트 34개는 통과했지만, 노드 사용량 집계와 민감 정보를 제거한 복사본을 가져와 실행하는 테스트는 아직 검증되지 않았습니다. 다시 읽기 검증은 값을 비교하며, 시트 서식이나 권한은 비교하지 않습니다.

다음 단계

각자의 비공개 설정에서 모든 사례를 다시 실행하고 행 전체 내용을 확인합니다. 동시에 발생하는 행 변경과 원문 그대로 노출되는 Google 오류를 검토합니다. 가져온 복사본을 테스트한 뒤 민감 정보를 제거한 가져오기 파일 다운로드를 추가합니다. Universal Webhook, Google 연결 설정, 일반적인 오류를 참고하세요. 웹훅과 Google 연결 설정의 배경 설명은 웹훅에서 Google Sheets로 연결하는 튜토리얼을 참고하세요.

관련 자료: Google Sheets 이메일 조회: 이메일로 행 찾기.