05. 표현식으로 데이터 잇기¶
앞 노드가 만든 값을 뒤 노드가 쓰는 방법입니다. 이음새에서 가장 자주 쓰고, 가장 자주 틀리는 부분이니 이 문서만큼은 한 번 훑어두시길 권합니다.
문법은 하나입니다.
어디서 값을 가져올 수 있나¶
| 쓰는 법 | 가져오는 값 |
|---|---|
${nodes.<노드id>.response.body.<필드>} |
앞 노드의 출력 — 가장 많이 씁니다 |
${nodes.<노드id>.request.data.<필드>} |
그 노드가 받았던 입력 |
${input.<필드>} |
엣지가 넘겨준 값 (조건 노드에서도 이 범위를 씁니다) |
${secrets.<키>} |
워크스페이스 시크릿 (API 키 등) |
${vars.<키>} |
워크스페이스 일반 변수 |
${connections.<제공사>.<필드>} |
연결된 서비스의 토큰 등 |
${item} / ${item.<필드>} |
반복 중인 현재 원소 (루프 안에서만) |
${index} |
반복 회차 번호 (0부터) |
${loops.<LOOP_START id>.item} |
바깥쪽 반복의 현재 원소 (반복이 겹칠 때) |
${loops.<LOOP_START id>.index} |
바깥쪽 반복의 회차 번호 |
${datasets.<제목>.count} |
데이터셋 행 개수 |
${datasets.<제목>.latest} |
데이터셋 최근 행 전체 |
${datasets.<제목>.latest.<필드>} |
최근 행의 특정 필드 |
앞 노드 출력 가져오기 (핵심)¶
노드 id에 하이픈이 있어도 됩니다. 중첩 필드는 점으로 계속 파고들면 됩니다.
${nodes.fetch.response.body.data.customer.name} # 중첩 객체
${nodes.fetch.response.body.items.0.name} # 배열 첫 번째 원소 — 숫자는 인덱스
${nodes.fetch.response.body.items.2.price} # 세 번째 원소
시크릿·변수 가져오기¶
시크릿과 일반 변수는 서로 접근할 수 없습니다. ${vars.*}로 시크릿을 꺼낼 수 없고 그 반대도 안 됩니다.
→ 08. 변수와 시크릿
| raw — 구조를 그대로 넘기기¶
이음새에서 가장 흔한 실수가 여기서 나옵니다. 꼭 읽어주세요.
표현식 결과는 기본적으로 문자열로 바뀝니다. 숫자나 짧은 텍스트는 문제없지만, 배열이나 객체를 다음 노드에 넘길 때는 이게 문제가 됩니다.
# ❌ 배열이 문자열로 뭉개짐
data: "${nodes.fetch-orders.response.body.data}"
# → "[{id=1, amount=1000}, {id=2, amount=2000}]" 같은 이상한 문자열이 됩니다
# ✅ 배열 그대로 전달
data: "${nodes.fetch-orders.response.body.data | raw}"
| raw가 필요한 곳¶
| 상황 | 예 |
|---|---|
| Transform 노드에 데이터 넘길 때 | data: "${nodes.fetch.response.body.items \| raw}" |
| 루프에 반복할 배열 넘길 때 | items: "${nodes.fetch.response.body.data \| raw}" |
| 객체 통째로 넘길 때 | payload: "${nodes.build.response.body \| raw}" |
| raw의 규칙¶
값 전체가 표현식 하나일 때만 씁니다. 문장 중간에 끼워 넣을 수 없습니다.
# ✅ 값 전체가 표현식 하나
data: "${nodes.fetch.response.body.items | raw}"
# ❌ 문장 안에 섞음 — 동작하지 않습니다
text: "주문 목록: ${nodes.fetch.response.body.items | raw}"
문장 안에 넣고 싶다면 그건 애초에 문자열이어야 하는 값입니다. | raw 없이 쓰세요.
| "기본값" — 값이 없을 때 대신 쓸 값¶
값이 null일 때 쓸 기본값을 정해둘 수 있습니다. 선택 입력 필드처럼 "있으면 쓰고 없으면 넘어가는"
자리에 씁니다.
text: "안녕하세요 ${input.name | \"고객\"}님" # name 이 null 이면 → "안녕하세요 고객님"
body:
memo: "${input.memo | \"\"}" # 빈 문자열로
count: "${input.count | 0}" # 숫자로
쓸 수 있는 기본값은 "문자열" · 정수 · 실수 · true · false · null 입니다.
⚠️ 경로가 아예 없으면 fallback도 실패합니다¶
fallback은 값이 null일 때만 동작합니다. 경로 자체가 없으면 (오타·존재하지 않는 키)
기본값이 있어도 그대로 실패합니다.
${input.userId | "unknown"} # userId 가 null 이면 → "unknown"
${input.usreId | "unknown"} # 오타 — 그런 필드가 없으므로 실행 실패
일부러 이렇게 되어 있습니다. 오타를 기본값으로 덮어버리면 잘못된 값이 조용히 흘러가기 때문입니다.
⚠️ 0으로 시작하는 값은 따옴표로 감싸세요¶
기본값의 숫자는 숫자로 해석되므로 앞자리 0이 사라집니다. 전화번호·주문번호처럼 0으로 시작하는 값은 반드시 문자열로 적으세요.
${input.phone | "01012345678"} # ✅ 그대로 01012345678
${input.phone | 01012345678} # ❌ 숫자로 해석되어 1012345678
| raw 와 함께 쓰기¶
| 는 파이프로 이어 붙일 수 있고, raw가 앞입니다.
| null 만 쓰면 문자열 자리에서는 빈 문자열이 됩니다. JSON null로 넘기려면 | raw | null 입니다.
기본값 문자열 안에는
}를 넣을 수 없습니다 — 표현식을 닫는 문자이기 때문입니다.|는 기본값 안에서는 구분자로 보지 않으므로 그대로 써도 됩니다.
객체를 입력으로 넘기는 두 가지 방법¶
방법 1 — 구조를 직접 적고 값만 표현식으로 (권장)
input:
body:
orderId: "${nodes.trigger.response.body.orderId}"
amount: "${nodes.aggregate.response.body.총액}"
status: "confirmed"
방법 2 — 통째로 | raw
객체를 | raw 없이 통째로 넘기는 것만 피하면 됩니다.
엣지 매핑 vs 직접 참조¶
같은 일을 하는 두 가지 스타일이 있습니다. 하나를 골라 일관되게 쓰세요.
스타일 A — 직접 참조 (간단)¶
nodes:
- id: notify
type: CALL
integration: http_request
input:
body:
orderId: "${nodes.trigger.response.body.orderId}"
edges:
- from: trigger
to: notify
노드가 "어디서 오는 값인지"까지 직접 압니다. 짧고 읽기 쉽습니다.
스타일 B — 엣지 매핑 + ${input.*}¶
nodes:
- id: notify
type: CALL
integration: http_request
input:
body:
orderId: "${input.orderId}"
edges:
- from: trigger
to: notify
request:
data:
orderId: "${nodes.trigger.response.body.orderId}"
노드는 "orderId가 필요하다"만 알고, 그 값을 어디서 가져올지는 선이 압니다.
언제 B를 써야 하나¶
조건 노드(CONDITIONAL)로 이어질 때는 B가 필수입니다.
조건식은 ${input.*} 범위에서 평가되므로, 엣지로 값을 넘겨주지 않으면 조건이 아무것도 못 봅니다.
→ 06. 흐름 제어
자주 겪는 문제¶
표현식이 그대로 문자로 나와요¶
${...} 안의 경로가 틀렸을 때 실행이 ExpressionResolveException으로 실패합니다.
실행 이력에서 그 노드를 열고 바로 앞 노드의 실제 출력을 확인한 뒤 경로를 맞추세요.
표현식은 저장할 때 검사하지 않습니다. 실행할 때 비로소 확인됩니다. GUI에서 중간중간 저장할 수 있도록 일부러 이렇게 되어 있습니다.
JOINT 노드 값을 가져올 수 없어요¶
JOINT는 자기 출력이 없습니다. 합류만 시키는 노드입니다.
JOINT 다음 노드에서는 JOINT 이전 노드를 직접 참조하세요.
# ❌ JOINT는 출력이 없음
${nodes.join.response.body.value}
# ✅ JOINT 앞 노드를 직접 참조
${nodes.fetch-a.response.body.value}
{{ }} 는 표현식이 아닙니다¶
{{key}} 는 레시피 기능의 자리표시자입니다. 직접 작성하는 워크플로우 YAML에는 절대 넣지 마세요.
표현식은 언제나 중괄호 하나 + $ — ${...} 입니다.
스케줄 트리거인데 windowStart가 없어요¶
lookback을 설정해야만 생깁니다. → 03. 트리거 설정하기
빠른 참조표¶
# 앞 노드 출력
${nodes.fetch.response.body.data}
${nodes.fetch.response.body.items.0.name} # 배열 인덱스
${nodes.fetch.response.body.data | raw} # 구조 보존
# 트리거
${nodes.trigger.response.body.orderId} # 웹훅 본문
${nodes.trigger.response.body.windowStart} # 스케줄 lookback
# 워크스페이스 자원
${secrets.MY_API_KEY}
${vars.BASE_URL}
${connections.slack.accessToken}
${datasets.처리이력.count}
${datasets.처리이력.latest.주문번호}
# 엣지가 넘긴 값 / 조건식
${input.orderId}
# 루프 안
${item}
${item.orderId}
${index}
${loops.each-order.item} # 겹친 루프의 바깥쪽 원소
${loops.each-order.index}
# 값이 없을 때 기본값
${input.name | "고객"}
${input.count | 0}
${nodes.fetch.response.body.data | raw | null}
다음 → 06. 흐름 제어