VDA5050 instantActions와 표준 액션 총정리: 상태·blockingType·실무 패턴
이 글의 핵심
instantActions는 진행 중인 order와 별개로 지금 바로 실행할 액션을 보내는 토픽입니다. 표준이 정의한 액션마다 반대 동작, 멱등 여부, 연결된 state 필드, 사용할 수 있는 위치(instant, node, edge)가 정해져 있고, 실행 상태는 actionStates에서 WAITING부터 FINISHED·FAILED까지 전이합니다. 표준 문서의 정의와, libVDA5050++ 기반 어댑터에서 실제로 보낸 메시지의 결과를 나눠 정리합니다.
instantActions는 VDA5050에서 가장 짧은 메시지인데, 운영 중 가장 자주 문제가 되는 토픽이기도 합니다. 멈추고, 재개하고, 취소하고, 위치를 다시 잡고, 충전을 시작하는 일이 모두 여기를 지나갑니다. 이 글은 VDA5050 2.0.0 문서(공식 저장소의 2.0.0 태그, VDA5050_EN_V1.md)에서 instantActions와 액션에 관한 부분을 키워드별로 정리하고, 그 동작을 libVDA5050++(v2.11.3) 위에 만든 어댑터에서 실제로 보내 본 결과를 덧붙입니다. 표준 문서의 머리말은 이 버전을 “RELEASE CANDIDATE, FOR REVIEW”로 적고 있으므로, 이후 버전과 다른 부분이 있을 수 있습니다.
실무에서 어떻게 쓰이는지에 대해서는 특정 업체의 도입 사례를 확인하지 못했습니다. 아래 “실무 패턴”은 표준 문서가 직접 든 예시, 표준이 정한 의무 사항, 그리고 시뮬레이터에서 확인한 동작에서 도출한 것이며, 그렇게 구분해서 적었습니다. order와 node·edge 규칙은 order 수명주기, pick 액션의 상태 머신은 pick 액션 처리, 라이브러리 사용법은 libVDA5050++ 어댑터 만들기에서 다룹니다.
instantActions 토픽
표준은 instantActions를 “즉시 수행해야 하는 액션을 AGV에 보낼 때 쓰는 토픽”으로 정의합니다. 관제 시스템이 발행하고 AGV가 구독하며, 토픽 이름은 <interface>/<버전>/<manufacturer>/<serialNumber>/instantActions입니다. 구현 필수 토픽입니다. 표준의 QoS 규정(6.2절)은 order, state, visualization에 QoS 0(최대 한 번), connection에 QoS 1을 정하고 있고, instantActions의 QoS는 그 절에 따로 적혀 있지 않습니다.
메시지 구조는 공통 헤더(headerId, timestamp, version, manufacturer, serialNumber)와 actions 배열이 전부입니다. headerId는 토픽마다 따로 세고, 메시지를 보낼 때마다 1씩 올립니다.
{
"headerId": 7,
"timestamp": "2026-10-31T00:41:12.000Z",
"version": "2.0.0",
"manufacturer": "sim",
"serialNumber": "blog001",
"actions": [
{ "actionType": "startPause", "actionId": "p1", "blockingType": "NONE" }
]
}
표준이 정한 규칙은 두 가지입니다.
- AGV는 instantAction을 받으면
state.actionStates배열에 해당 액션의actionState를 추가하고, 진행에 따라actionStatus를 갱신해야 합니다. - instantAction은 현재 order의 내용과 충돌하면 안 됩니다. 표준이 든 예는 order가 포크를 올리라고 하는데 내리라는 instantAction을 보내는 경우입니다.
표준이 instantActions의 용도로 직접 든 예시는 “order를 바꾸지 않고 AGV를 일시정지”, “일시정지 뒤 order 재개”, “신호(광학, 음향 등) 켜기”입니다.
action 객체의 키워드
instantActions의 actions 항목과 order의 node·edge에 붙는 actions 항목은 같은 구조입니다.
| 필드 | 의미 |
|---|---|
actionType | 액션의 이름. 표준 액션 표의 첫 열 값이거나, 제조사가 정의한 이름 |
actionId | 액션을 식별하고 state의 actionStates와 연결하는 고유 ID. 표준은 UUID 사용을 제안 |
actionDescription | 선택. 액션에 대한 추가 설명 |
blockingType | NONE, SOFT, HARD 중 하나. 주행·다른 액션과의 병행 가능 여부 |
actionParameters | {"key": ..., "value": ...} 객체의 배열. 액션별 파라미터 |
actionParameters가 키-값 쌍 배열인 것은 8.2절에서 “구현을 일반적으로 유지하기 위한” 설계라고 설명합니다. 예를 들어 stationType과 loadType을 넘길 때는 [{"key":"stationType","value":"floor"},{"key":"loadType","value":"pallet_eu"}] 모양입니다. 표준은 필요하면 표에 없는 파라미터를 추가로 정의해도 된다고 허용하지만, 의미가 맞는 표준 파라미터가 있으면 반드시 써야 한다고 적고 있습니다. 표에 없는 액션도 제조사가 정의해 쓸 수 있으며, 이 경우 관제 시스템이 그 정의를 따라야 합니다.
표준이 정의한 액션 표
6.8.1절의 표는 액션마다 다섯 가지를 정합니다. 반대 동작(counter action), 멱등 여부, 파라미터, 연결된 state 필드, 사용할 수 있는 위치(instant, node, edge)입니다.
| 액션 | 반대 동작 | 멱등 | 파라미터 | 연결된 state | instant | node | edge |
|---|---|---|---|---|---|---|---|
| startPause | stopPause | yes | 없음 | paused | yes | no | no |
| stopPause | startPause | yes | 없음 | paused | yes | no | no |
| startCharging | stopCharging | yes | 없음 | batteryState.charging | yes | yes | no |
| stopCharging | startCharging | yes | 없음 | batteryState.charging | yes | yes | no |
| initPosition | 없음 | yes | x, y, theta(float64), mapId, lastNodeId(string) | agvPosition.x/y/theta/mapId, lastNodeId | yes | yes(엘리베이터) | no |
| stateRequest | 없음 | yes | 없음 | 없음 | yes | no | no |
| logReport | 없음 | yes | reason(string) | 없음 | yes | no | no |
| pick | drop(자동화된 경우) | no | lhd, stationType, stationName, loadType, loadId, height, depth, side | loads | no | yes | yes |
| drop | pick(자동화된 경우) | no | lhd, stationType, stationName, loadType, loadId, height, depth(모두 선택) | loads | no | yes | yes |
| detectObject | 없음 | yes | objectType(선택) | 없음 | no | yes | yes |
| finePositioning | 없음 | yes | stationType, stationName(선택) | 없음 | no | yes | yes |
| waitForTrigger | 없음 | yes | triggerType | 없음 | no | yes | no |
| cancelOrder | 없음 | yes | 없음 | 없음 | yes | no | no |
각 열의 의미를 짚습니다.
- 연결된 state: startPause와 stopPause는
paused가 연결돼 있어야 하는 이유를 표가 직접 적습니다. 많은 AGV가 하드웨어 스위치로도 일시정지되기 때문에, 관제가 보낸 instantAction뿐 아니라 스위치로 바뀐 상태도 같은 필드로 보여야 한다는 뜻입니다. 같은 이유로 stopPause는 하드웨어 버튼으로 멈춘 차량도 (그렇게 설정돼 있다면) 다시 출발시킬 수 있다고 표가 적습니다. - instant, node, edge 열: 같은 액션이 어디에 붙을 수 있는지를 정합니다. 충전은 order의 노드에도 붙일 수 있고(충전소 노드에서 충전), instantAction으로도 보낼 수 있습니다. cancelOrder와 pause는 노드나 엣지에 붙을 수 없습니다. 표를 읽을 때 한 가지 주의할 점은 finePositioning의 설명이 “instantAction: AGV가 정확히 목표에 맞추기 시작”이라고 적으면서 instant 열은 no라는 것입니다. 문서 안에서 서로 맞지 않으므로, 이 액션을 instantAction으로 쓰려면 제조사의 factsheet를 확인해야 합니다.
- 멱등: 표의 열 이름대로, 같은 액션을 다시 받아도 결과가 같은 액션이 yes입니다. pick과 drop만 no입니다. 표준이 이 열을 어디에 쓰라고 직접 적지는 않았습니다. 재전송 정책을 정할 때 참고하는 값으로 읽는 것이 자연스럽습니다.
- 반대 동작: pick과 drop은 “자동화된 경우” 서로의 반대이고, 나머지는 pause와 charging이 짝입니다. node에 붙는 액션은 스스로 끝나거나(예: 5초짜리 경고음, 집기가 끝나면 종료되는 pick) 짝을 이뤄야 한다(예: activateWarningLights와 deactivateWarningLights)고 6.8절이 적습니다.
액션 설명에서 눈여겨볼 문장들입니다.
- startPause: 이동은 멈추지만 “다음 노드에 도달할 필요는 없고”, 액션은 계속될 수 있으며, order는 재개 가능한 상태로 남습니다.
- startCharging과 stopCharging: 충전은 서 있는 충전 자리에서도, 이동 중인 충전 차선에서도 할 수 있습니다. 과충전 방지는 차량의 책임입니다. 충전이 충전기나 차량에 의해 중간에 끝날 수도 있으므로(배터리가 가득 찼을 때), stopCharging의
charging은 AGV가 새 order를 받을 준비가 됐을 때만 false여야 합니다. - initPosition: 차량의 자세를 주어진 값으로 덮어씁니다. 표준이 적은 것은 이 정의까지이고, 어떤 상황에서 쓰는지는 따로 설명하지 않습니다.
- logReport: 차량이 로그 리포트를 만들어 저장하도록 요청하고, 완료되면 로그 이름이 상태로 보고됩니다.
- waitForTrigger: 차량에서 일어나는 트리거(버튼 입력, 수동 적재 등)를 기다리고, 타임아웃 처리는 관제의 책임이며 필요하면 order를 취소해야 합니다.
- cancelOrder: 가능한 한 빨리 멈춥니다(즉시일 수도 있고 다음 노드일 수도 있음). 그 뒤 order는 삭제되고 모든 액션이 취소됩니다.
actionStatus와 상태 전이
6.11절은 AGV가 받은 모든 액션(node·edge에 붙은 것이든 instantAction이든)을 actionStates의 항목으로 나타내야 한다고 정합니다. actionStatus의 값은 여섯 가지입니다.
| 값 | 의미 |
|---|---|
| WAITING | 액션은 받았지만 트리거되는 노드에 아직 도달하지 못했거나 엣지에 아직 진입하지 않음 |
| INITIALIZING | 트리거됨, 준비 작업을 시작함 |
| RUNNING | 실행 중 |
| PAUSED | pause instantAction이나 외부 트리거(차량의 일시정지 버튼)로 멈춤 |
| FINISHED | 끝남. 결과는 resultDescription으로 보고 |
| FAILED | 어떤 이유로든 끝내지 못함 |
6.8.2절은 액션별로 이 상태가 무엇을 뜻하는지를 정합니다. 차량이 즉시 전환할 수 있는 액션(예: 일시정지)은 INITIALIZING과 RUNNING을 건너뛰고 바로 FINISHED가 되어도 됩니다. 몇 가지만 옮깁니다.
- startPause의 FINISHED: 차량이 서 있고 모든 액션이 일시정지되며,
paused: true를 보고합니다. FAILED는 하드웨어 스위치가 우선하는 것처럼 일시정지 모드를 켤 수 없는 경우입니다. - startCharging의 FINISHED: 충전이 시작되고
batteryState.charging: true를 보고합니다. FAILED는 충전기에 정렬되지 않은 것 같은 이유이며, 표준은 충전 문제가 오류(errors)와 짝을 이뤄야 한다고 적습니다. - initPosition의 FINISHED: 자세가 리셋되고
agvPosition과lastNodeId가 요청한 값을 보고합니다. FAILED는 자세가 유효하지 않거나 리셋할 수 없는 경우입니다. - stateRequest의 FINISHED: 상태를 보냈다는 뜻입니다.
- pick과 drop: INITIALIZING은 아직 필요한 사전 작업(예: 높이 조정), PAUSED는 안전 필드가 침범된 경우처럼 일시적으로 멈춘 상태이고 해소되면 이어서 진행됩니다. FINISHED는 적재물이 AGV에 들어왔거나(pick) 나갔고(drop) AGV가 새 load state를 보고한 상태입니다.
- waitForTrigger: order가 취소되면 FAILED가 됩니다.
blockingType
6.12절은 여러 액션이 있을 때 실행 순서는 목록의 순서가, 병행 실행은 blockingType이 정한다고 적습니다.
| blockingType | 의미 |
|---|---|
| NONE | 다른 액션과 병행 가능하고, 차량이 달리는 동안에도 실행 가능 |
| SOFT | 다른 액션과 병행 가능하지만 차량은 움직이면 안 됨 |
| HARD | 단독 실행. 다른 액션과 병행 불가, 차량도 움직이면 안 됨 |
한 노드에 서로 다른 blockingType의 액션이 섞여 있을 때의 처리는 문서의 그림 15가 정합니다(이 글에는 옮기지 않았습니다). 표의 설명으로 보면 pause 같은 instantAction은 NONE으로 보내는 것이 자연스럽지만, 표준 문서 자체가 액션마다 어떤 blockingType을 써야 하는지를 표로 정하지는 않습니다. 이 규칙은 구현마다 정해집니다. 예를 들어 libVDA5050++ v2.11.3 위의 어댑터에서는 stateRequest를 HARD로 보내면 거부됐고 NONE만 허용한다는 메시지가 돌아왔습니다. cancelOrder는 HARD로 보내 정상 처리됐습니다(뒤의 실행 결과 참고).
cancelOrder
6.6.3절이 가장 길게 정의한 instantAction입니다. 규칙을 순서대로 옮깁니다.
- order의 base 노드가 계획 밖으로 바뀌었을 때는 order를 취소해야 합니다.
- 받으면 차량이 능력에 따라 멈춥니다(그 자리에서, 또는 다음 노드에서).
- 예정된 액션은 취소되고
failed를 보고해야 합니다. 실행 중이던 액션도 취소하고 failed를 보고합니다. 중단할 수 없는 액션은 끝날 때까지running을 보고하다가 결과(finished 또는 failed)를 보고합니다. - 액션이 실행되는 동안 cancelOrder 자신도
running을 보고하고, 모든 이동과 액션이 멈춘 뒤에finished를 보고합니다. orderId와orderUpdateId는 유지됩니다.
취소 뒤 새 order를 받을 수 있는 상태여야 하며, 어디서 시작하는지는 차량 종류에 따라 갈립니다. 태그로 노드에서 자기 위치를 잡는 차량이면 새 order는 지금 서 있는 노드에서 시작해야 합니다. 노드 사이에서 멈출 수 있는 차량이면 관제가 선택하되 차량은 두 방법 모두 받아야 합니다.
- 첫 노드를 차량이 지금 서 있는 위치의 임시 노드로 두는 order를 보낸다. 차량은 이 노드가 이미 도달한 것과 같다고 인식해야 합니다.
- 첫 노드를 이전 order의 마지막 통과 노드로 두되 허용 오차를 차량이 그 안에 들어올 만큼 크게 잡는다.
취소할 order가 없을 때(6.6.3.2): 차량은 cancelOrder를 failed로 보고하고, errorLevel이 warning인 noOrderToCancel 오류를 보고해야 합니다. 이때 instantAction의 actionId를 errorReference로 넘겨야 합니다.
오류와 order 거절
state의 errors에는 두 단계가 있습니다. WARNING은 필드 침범처럼 스스로 해소되는 오류이고, FATAL은 사람의 개입이 필요한 오류입니다. 각 오류는 errorReferences(headerId, orderId, actionId 같은 키-값)로 원인을 가리킬 수 있습니다. 8.1절은 order 때문에 생긴 오류라면 headerId, 토픽(order 또는 instantAction), orderId와 orderUpdateId, 액션 때문이면 actionId, 파라미터가 틀렸다면 그 파라미터 목록을 레퍼런스에 담으라고 권고합니다. “적재물이 있어야 할 자리에 없다” 같은 외부 요인으로 액션이 끝나지 못할 때도 actionId를 참조해야 합니다.
6.6.4절은 order가 거절되는 세 경우의 처리를 정합니다. 표준 문서에 오류 이름으로 등장하는 것은 validationError(형식이 잘못된 order, 새 order를 받을 때까지 계속 보고), orderError(차량이 수행할 수 없는 액션이나 쓸 수 없는 필드가 있는 order, 잘못된 필드를 레퍼런스로), orderUpdateError(같은 orderId인데 orderUpdateId가 낮은 order, 이전 order를 유지하고 계속 실행)와 취소할 order가 없을 때의 noOrderToCancel입니다. 같은 orderId와 orderUpdateId를 두 번 받으면 두 번째는 무시되는데, 표준은 관제가 state 응답이 늦어서 order를 다시 보낸 경우를 이유로 듭니다.
관제가 어떤 액션을 쓸 수 있는지 알아내기: factsheet
표준의 factsheet 토픽(구현 필수)에서 protocolFeatures.agvActions가 이 AGV가 지원하는 액션 목록입니다. 표준 액션과 제조사 정의 액션이 모두 들어가며 항목마다 actionType, actionScopes(INSTANT, NODE, EDGE 중 허용되는 것), actionParameters(키, valueDataType, isOptional, 설명), resultDescription이 있습니다. 관제 시스템은 이 목록으로 “이 차량에 이 액션을 instantAction으로 보낼 수 있는가”를 미리 판단할 수 있습니다. 표에서 본 instant, node, edge 열이 차량마다 실제로 어떻게 정해졌는지가 여기서 확정됩니다. 지원하지 않는 optional 파라미터는 optionalParameters에 없으면 지원하지 않는 것으로 간주합니다.
실행해 본 결과
아래는 libVDA5050++ v2.11.3 위에 만든 시뮬레이터(Ubuntu 24.04 aarch64 컨테이너, eclipse-mosquitto:2)에 instantActions를 직접 보내 state를 관찰한 것입니다. 표준이 아니라 이 라이브러리와 이 어댑터의 동작이라는 점을 구분해서 읽어야 합니다. 차량은 order가 없는 상태에서 시작했고, 충전소는 노드 n0에 있습니다.
| 보낸 것 | 관찰된 state |
|---|---|
cancelOrder(HARD), order 없음 | 액션이 FINISHED, errors 비어 있음 |
startPause | 액션 FINISHED, paused: true |
stopPause | 액션 FINISHED, paused: false |
stateRequest + doBackflip(알 수 없는 액션)을 한 메시지에 | 알 수 없는 액션만 FAILED, unknownActionType 오류. 같은 메시지의 stateRequest는 state에 나타나지 않음 |
stateRequest를 HARD로 | 액션 FAILED, instantActionError: BlockingType "HARD" is not allowed, expected one of {NONE} |
initPosition(x 3.0, y 2.0, lastNodeId n2) | 액션 FINISHED, agvPosition (3.0, 2.0), lastNodeId: n2 |
startCharging(n0에서, HARD) | 액션 FINISHED, batteryState.charging: true |
stopCharging | 액션 FINISHED, charging: false |
이 결과에서 표준 문서와 대조해 볼 지점은 다음입니다.
- 표준 6.6.3.2는 order가 없을 때의 cancelOrder를 FAILED와
noOrderToCancel경고로 보고하라고 정합니다. 이 환경에서는 FINISHED로 끝나고 오류도 없었습니다. 이 어댑터가 cancelOrder를 라이브러리의 기본 처리에 맡기고 있어서 라이브러리의 동작이라고 보이지만, 라이브러리 소스에서 이 분기를 직접 확인한 것은 아니므로 단정하지는 않습니다. 관제 쪽에서 cancelOrder 결과로 order 유무를 판단하고 있다면 이 차이를 확인해야 합니다. unknownActionType과instantActionError는 2.0.0 문서의 오류 이름 목록에 없습니다. 라이브러리가 붙인 이름이므로, 관제가 오류 이름 문자열에 의존한다면 차량 제조사마다 이름이 다를 수 있습니다.errorReferences와errorDescription을 함께 보는 편이 안전합니다.factsheetRequest는 이 2.0.0 문서의 액션 표에 없습니다. 라이브러리가 factsheet 발행을 요청하는 instantAction으로 제공하는 확장이며 blockingType은 NONE만 허용합니다.startPause는 이동 중에 보내면 차량이 그 자리에서 멈췄고(이전 실행에서 위치가 약 1.75m 지점에서 정지),stopPause로 다시 달렸습니다.cancelOrder를 이동 중에 보내면orderId가 유지된 채nodeStates와edgeStates가 비었고lastNodeSequenceId는 0으로 돌아갔으며 위치는 엣지 중간에 남았습니다. 표준이 “orderId와 orderUpdateId는 유지”라고 한 부분과 맞습니다.
실무 패턴
특정 업체의 사례가 아니라, 위의 표준 규칙과 실행 결과에서 도출한 운영 방식이고, 내 해석이 들어간 부분이 있습니다.
일시정지: 현장 작업자가 하드웨어 스위치로 차량을 세우는 경우를 표준이 전제합니다. 그래서 관제 화면의 “정지 중” 표시는 보낸 instantAction이 아니라 state의 paused 값으로 판단해야 하고, 관제가 stopPause로 재개시킬 수 있는지는 차량 설정에 달려 있습니다. 재개가 실패하면 액션이 FAILED가 되고 이유는 errors에 있어야 합니다.
취소와 복구: 취소는 order 삭제와 같은 뜻입니다. 취소 직후 차량이 엣지 중간에 서 있을 수 있으므로, 표준이 말한 두 가지 중 하나로 다음 order를 만듭니다. 임시 노드 방식은 차량의 현재 좌표를 알아야 하고, 허용 오차를 키우는 방식은 지나치게 키우면 다른 노드와 구분이 안 됩니다. 표준 문구대로 cancelOrder가 모든 이동과 액션이 멈춘 뒤에 FINISHED를 보고하므로, 새 order는 그 뒤에 보내는 것이 자연스럽습니다.
위치 재설정: 차량을 수동으로 옮겼거나 엘리베이터로 층(맵)이 바뀐 직후에는 initPosition으로 현재 자세와 mapId, lastNodeId를 알려 줍니다. 표의 node 열에는 괄호로 “엘리베이터”만 적혀 있는데, 층 이동 노드에서 쓰는 경우를 뜻하는 것으로 읽힙니다. 위치를 잘못 알려 주면 이후 order가 거절되거나 엉뚱한 곳으로 가므로, 관제는 FINISHED 뒤 state의 agvPosition을 확인합니다.
충전: 충전소 노드에 도착한 뒤 startCharging을 보내고, 가득 찬 뒤에는 차량이 스스로 충전을 끝낼 수 있으므로 stopCharging을 보내기 전에 batteryState.charging을 먼저 봅니다. 충전 시작 실패는 액션 FAILED와 오류가 함께 오는 것이 표준의 기대입니다. 충전이 끝난 차량이 새 order를 받을 수 있는지는 charging: false가 기준입니다.
state 재동기화: order, state, visualization은 QoS 0이라 메시지가 사라질 수 있습니다. 관제가 차량 상태를 못 받았다고 의심되면 stateRequest로 즉시 state를 요청할 수 있고, 액션은 멱등입니다. 이 방법은 표준이 직접 권한 패턴은 아니고, stateRequest가 “state를 다시 보내라”는 정의를 가진 데서 나온 사용법입니다.
차량 능력 사전 확인: 새 차량을 붙일 때 factsheet의 agvActions와 actionScopes를 먼저 읽어, 쓰려는 instantAction이 목록에 있고 INSTANT 범위인지 확인합니다. 제조사 정의 액션은 이 목록 말고는 관제가 알 방법이 없습니다.
재전송 정책: 멱등 열이 yes인 instantAction은 응답이 늦을 때 다시 보내도 같은 결과가 되도록 정의돼 있습니다. 같은 actionId로 다시 보낼 때 차량이 중복을 어떻게 다루는지는 표준에 적혀 있지 않으므로, 실제 재전송 로직을 만든다면 차량과 맞춰야 합니다. order는 같은 orderId와 orderUpdateId를 두 번 받으면 두 번째를 무시하는 규칙이 있어서, 재시도할 때 orderUpdateId를 올리지 않아야 합니다.
한계
표준 부분은 2.0.0 문서(릴리스 후보 표기)를 기준으로 했고, 그림 9(cancelOrder 이후의 기대 동작), 그림 14(actionStatus 전이도), 그림 15(blockingType 혼합 처리)는 이미지라서 글에 옮기지 않았습니다. 이후 버전(2.1, 3.0)에서 액션 표나 instantAction 이름이 바뀌었는지는 확인하지 않았습니다. 실행 결과는 로컬 컨테이너의 가상 차량에서 얻은 것이며 실제 장비의 응답 시간, 하드웨어 스위치, 안전 필드와의 상호작용은 다루지 않았습니다. 업체별 도입 사례나 통계는 확인하지 못해서 싣지 않았습니다.