활성화된 모든 파이프라인 단계는 작업에 기록을 하나씩 남기므로, 실제로 무엇이 실행됐는지 추측하지 않고 직접 읽어 확인할 수 있습니다.
몇 가지 pipeline 단계를 켰다고 해보죠. 예를 들어 원문을 다듬는 pre-edit, 의미가 어긋났는지 잡아내는 back-translation 같은 단계들입니다. 그런데 작업이 completed_with_warnings 상태로 돌아왔습니다. 어느 단계에서 문제가 생긴 걸까요? 사람 검토자가 실제로 작업을 맡았을까요, 아니면 시간이 초과됐을까요? 추가 단계에는 비용이 얼마나 들었을까요? 로캘별로 AI 단계와 사람 단계가 여러 개 들어가는 파이프라인은 자칫 블랙박스가 되기 쉽습니다. 결과물은 나오지만, 중간 단계들이 제 역할을 했는지는 믿고 넘어가게 되니까요.
하지만 여기서는 믿고 넘어가게 두지 않습니다. 활성화된 모든 단계는 작업의 steps[] 배열에 기록을 하나씩 남깁니다. 어떤 단계였는지, 상태가 무엇인지, 비용이 얼마였는지, 언제 시작해서 언제 끝났는지까지 모두 남습니다. 각 단계가 실제로 무엇을 했는지 읽어보면 됩니다. 실행됐다고 믿을 필요는 없습니다. 이 페이지는 바로 그 내용을 설명합니다.
파이프라인이 처음이라면 Pipeline overview부터 시작하세요.
이 페이지에서 다루는 내용
기록이 저장되는 위치#
steps[] 배열은 로컬라이제이션 작업의 필드 중 하나입니다. 따로 조회할 필요는 없고, 작업을 읽을 때마다 함께 내려옵니다:
GET /jobs/localization/:jobIdX-API-Key 헤더에 API 키를 넣어 인증하세요. 전체 엔드포인트, job-status 값, 그리고 outputData 페이로드는 단일 작업 페이지에서 다룹니다. 이 페이지는 그 응답의 한 필드인 단계별 실행 기록과, 그 기록이 무엇을 알려주는지에 집중합니다.
규칙은 단순합니다. 조회하는 모든 작업에는 이미 자체 감사 로그가 들어 있습니다. 파이프라인이 활성화되지 않은 작업에도 core localization은 항상 실행되기 때문에 기록이 하나 남습니다. 선택 단계를 두 개 켜면 기록은 세 개가 됩니다. 배열은 파이프라인에 따라 늘어나며, 실행된 순서대로 단계당 항목이 하나씩 추가됩니다.
steps 배열#
steps[]의 각 항목은 한 단계의 실행 기록입니다. 실행을 감사하려면 아래 필드를 읽으면 됩니다. 어떤 단계였는지, 결과가 어땠는지, 비용이 얼마였는지, 언제 실행됐는지를 확인할 수 있습니다:
"steps": [
{
"stepId": "preEdit",
"type": "action",
"status": "completed",
"errorMessage": null,
"costUsd": 0.0012,
"externalRefType": null,
"externalRefId": null,
"externalRefUrl": null,
"createdAt": "2026-03-16T10:30:01.000Z",
"startedAt": "2026-03-16T10:30:01.000Z",
"completedAt": "2026-03-16T10:30:02.000Z"
},
{
"stepId": "localize",
"type": "action",
"status": "completed",
"errorMessage": null,
"costUsd": 0.0184,
"externalRefType": null,
"externalRefId": null,
"externalRefUrl": null,
"createdAt": "2026-03-16T10:30:02.000Z",
"startedAt": "2026-03-16T10:30:02.000Z",
"completedAt": "2026-03-16T10:30:05.000Z"
}
]| 필드 | 설명 |
|---|---|
stepId | 이 기록이 어떤 파이프라인 단계에 해당하는지 나타냅니다. 아래 매핑 표를 참고하세요. |
type | 단계의 유형입니다. 자동화된 단계라면 action입니다. |
status | 이 단계의 상태입니다. completed, failed, 또는 skipped가 들어가며, 작업 전체 상태와는 별개입니다. |
errorMessage | 이 단계가 실패한 이유입니다. status가 failed가 아닌 한 null입니다. |
costUsd | 이 단계에 든 비용(USD)입니다. JSON 숫자이거나 null입니다. |
externalRefType, externalRefId, externalRefUrl | 서드파티로 작업을 넘기는 단계에 대한 외부 기록 포인터입니다. 대표적으로 human review 단계가 그렇습니다. 완전 자동화된 단계라면 null입니다. |
createdAt, startedAt, completedAt | 단계가 생성되고, 작업이 할당되고, 완료된 시점입니다. |
각 기록에는 outputData 필드도 함께 들어 있습니다. 이 필드에는 해당 단계가 만들어낸 콘텐츠가 작업의 outputData와 같은 형태로 담깁니다. 이 페이로드는 감사 기록이 아니라 번역 결과이므로, 작업 수준의 outputData와 함께 단일 작업 페이지에 문서화되어 있습니다. 파이프라인이 실제로 무엇을 했는지 보려면 위 필드들을 읽으면 됩니다.
이 기록은 단일 outputData 블롭으로는 볼 수 없는 두 가지를 보여줍니다. 첫째, 비용이 작업 단위 총액만이 아니라 단계별로도 나뉘어 표시됩니다. 그래서 back-translation을 켠 뒤 청구 금액이 달라졌다면, 정확히 어느 단계가 영향을 줬는지 확인할 수 있습니다. 둘째, 시간 정보도 단계별입니다. humanEdit 기록에서 startedAt와 completedAt 사이가 몇 시간씩 벌어져 있다면, 대기 원인은 엔진이 아니라 사람이었다는 뜻입니다.
steps는 위치가 아니라 stepId로 읽으세요
기록은 실행 순서대로 나타나지만, 배열 위치로 접근하면 안 됩니다. 어떤 단계가 실행됐는지는 무엇을 활성화했는지에 따라 달라지므로, 위치는 작업마다 고정되지 않습니다. 단계는 stepId(steps.find(s => s.stepId === "humanEdit"))로 찾아야 합니다. stepId 값의 집합 자체는 고정되어 있지만, 특정 작업에 실제로 들어오는 값은 사용자가 켠 단계들뿐입니다.
stepId를 단계에 매핑하기#
각 stepId는 하나의 파이프라인 단계를 가리킵니다. 아래 표는 기록에 들어 있는 값이 어떤 단계를 의미하는지, 그리고 그 단계가 무엇을 하는지 설명하는 페이지가 어디인지 보여줍니다:
stepId | 단계 |
|---|---|
preEdit | 로컬라이제이션 전 AI 편집 |
localize | 핵심 로컬라이제이션 |
humanEdit | 로컬라이제이션 후 사람 검토 |
postEdit | 로컬라이제이션 후 AI 평가 |
rephrase | 자연스러운 카피로 다듬기 |
backTranslation | 역번역 검사 |
localize는 파이프라인 사용 여부와 관계없이 모든 작업에 나타나는 유일한 stepId입니다. 이것이 핵심 번역 단계이며, 항상 실행됩니다. 나머지 다섯 개는 엔진 또는 요청에서 해당 단계를 활성화한 경우에만 나타납니다.
단계 상태: completed, failed, skipped#
각 단계는 작업이나 다른 단계들과 별개로 자체 status를 가집니다. 값은 세 가지입니다:
단계 status | 의미 |
|---|---|
completed | 단계가 실행되어 결과를 만들어냈습니다. |
failed | 단계가 실행되다가 오류가 발생했습니다. 이유는 errorMessage에 들어 있습니다. |
skipped | 이 단계는 활성화되어 있었지만, 이번 실행에서는 끝까지 완료되지 않았습니다. |
completed와 failed는 예상대로 이해하면 됩니다. 잠깐 짚고 넘어가야 할 것은 skipped인데, 이것은 "비활성화됨"과는 다릅니다. 애초에 켜지 않은 단계는 기록 자체가 생기지 않습니다. 반면 skipped 기록은 그 단계가 활성화되어 있었지만 파이프라인 규칙에 따라 이번에는 건너뛰어졌다는 뜻입니다. 가장 분명한 예가 human review입니다. 검토 가능 시간이 끝날 때까지 사람이 응답하지 않으면, 그 단계는 skipped로 표시되고 AI 번역이 최종 결과로 이어집니다. 기록은 그대로 남기 때문에, 건너뛰어졌다는 사실이 조용히 묻히지 않고 드러납니다.
단계 상태와 작업 상태는 다릅니다
failed 단계가 있다고 해서 작업이 항상 failed인 것은 아닙니다. 대부분의 선택 단계는 비핵심 단계이기 때문에, 하나가 실패하더라도 해당 기록은 failed로 남고 엔진은 마지막으로 정상적이었던 출력을 이어 받아 작업을 전체 outputData 상태로 마칩니다. 그렇게 결정되는 작업 상태, 즉 completed_with_warnings는 단일 작업 페이지에서 설명합니다. 단계 상태는 한 단계에서 무슨 일이 있었는지를 알려주고, 작업 상태는 결국 번역을 받았는지를 알려줍니다.
단계 실패가 작업 경고로 이어지는 방식#
비핵심 단계가 실패하면, 그 실패는 동시에 두 곳에 나타납니다. 서로 다른 두 뷰이지만 같은 사건을 가리킵니다. steps[] 기록은 errorMessage를 동반한 failed 상태가 되는데, 이것이 상세 보기입니다. 같은 실패는 작업 최상위 warnings 배열에도 항목 하나로 나타나는데, 이것이 상태 처리 코드가 분기할 때 사용하는 요약 보기입니다:
{
"id": "ljb_A1b2C3d4E5f6G7h8",
"status": "completed_with_warnings",
"outputData": { "title": "Hallo" },
"warnings": [
{ "step": "backTranslation", "message": "Back-translation check did not complete" }
],
"steps": [
{ "stepId": "localize", "type": "action", "status": "completed", "errorMessage": null, "costUsd": 0.0184, "completedAt": "2026-03-16T10:30:05.000Z" },
{ "stepId": "backTranslation", "type": "action", "status": "failed", "errorMessage": "Back-translation check did not complete", "costUsd": 0.0031, "completedAt": "2026-03-16T10:30:11.000Z" }
]
}각 warnings 항목은 { step, message }이며, 여기서 step는 실패한 기록에서 볼 수 있는 것과 같은 stepId입니다. 즉, 두 배열은 서로 정확히 대응합니다. warnings는 무엇이 잘못됐는지 빠르게 보여주는 목록이고, steps[]는 각 항목의 세부 내용을 확인하러 가는 곳입니다. 로캘을 사람이 확인해야 할지 판단할 때는 warnings를 읽고, 그에 대응하는 steps[] 기록에서는 그 배경이 되는 errorMessage, 비용, 타이밍을 확인하면 됩니다.
이것이 completed_with_warnings의 의미입니다. 핵심 번역은 성공했기 때문에 사용할 수 있는 outputData는 있지만, 적어도 하나의 비핵심 단계가 failed 기록과 그에 대응하는 경고를 남긴 상태라는 뜻입니다. 출력은 배포 가능한 결과물로 보고, 경고는 노출할 가치가 있는 품질 신호로 취급하세요. 읽을 번역 자체가 없다는 뜻은 작업 status가 failed일 때뿐이며, 그 판단 기준과 전체 작업 상태 표는 단일 작업 페이지에 있습니다.
단계 상태 집계는 별도의 표면에서 확인합니다
steps[]는 "이 작업에서 파이프라인이 무엇을 했는가"에 답합니다. 반면 여러 작업에 걸친 추세, 예를 들어 pre-edit가 얼마나 자주 실패하는지, back-translation이 얼마나 자주 번역을 바로잡는지는 집계 질문입니다. 그런 내용은 작업별 응답이 아니라 Reports 페이지에서 다룹니다. 여기서는 작업별 기록을 보고, 거기서는 집계를 봅니다.
