AI 자동화 오류로 인한 사고를 막는 Human-in-the-Loop(실무자 승인) 안전 설계
100% 무인화의 치명적 리스크를 통제하는 슬랙/카카오톡 인터랙티브 승인 버튼 아키텍처
이지웍스랩 보안센터 · 2026-08-17 · B2B 업무 자동화 · 읽는 데 9분
자동화의 목표는 "사람을 없애는 것"이 아니라 "사람에게 최종 검토 권한만 남겨두고 지루한 반복 작업을 없애는 것"입니다. 100% 무인화보다 실무자 승인(HITL) 체계가 왜 더 성공률이 높은지 설명합니다.
1. 자율 주행 레벨 4 방식의 업무 자동화
AI가 고속도로를 주행하듯 데이터 파싱과 단가 검증을 99% 진행하고, 마지막 인터체인지(출금 승인, 세금계산서 전송)에서만 운전자(실무자)에게 핸들을 넘기는 방식이 가장 안전합니다.
완전 무인화를 목표로 삼는 순간 리스크가 급격히 커집니다. 자동화의 오류율이 0.1%라도, 그 0.1%가 자금 이체나 세금계산서 발행이라면 단 한 건으로 조직 전체가 흔들립니다. 되돌릴 수 있는 작업과 되돌릴 수 없는 작업을 구분하는 것이 설계의 출발점입니다.
실무 기준은 단순합니다. ① 외부로 나가는가, ② 금액이 움직이는가, ③ 법적 효력이 발생하는가. 이 중 하나라도 해당하면 사람의 승인 게이트를 두십시오. 나머지는 전부 자동으로 두어도 무방합니다.
| 작업 유형 | 자동화 수준 | 판단 근거 |
|---|---|---|
| 문서 파싱·데이터 정제 | 완전 자동 | 결과가 틀려도 재실행으로 복구 가능 |
| 단가 대조·이상치 탐지 | 완전 자동 | 탐지 결과는 제안일 뿐 확정이 아님 |
| 거래처 메일·알림 발송 | 승인 필요 | 외부로 나간 메시지는 회수 불가 |
| 세금계산서 발행·자금 이체 | 승인 필수 | 법적 효력 발생, 취소 시 별도 절차 필요 |
2. 슬랙 인터랙티브 승인 게이트 구현
승인 절차가 번거로우면 실무자는 결국 우회합니다. 별도 시스템에 로그인해서 승인하게 만들면 한 달 안에 '일괄 승인' 습관이 생기고, 게이트는 형식만 남습니다.
따라서 승인은 실무자가 이미 하루 종일 켜두는 도구 안에서 끝나야 합니다. 슬랙 메시지에 [승인] [수정 후 승인] [반려] 버튼을 넣어 3초 만에 의사결정을 마치게 하는 것이 현실적인 최선입니다.
승인 요청 메시지에는 판단에 필요한 정보를 모두 담아야 합니다. 금액, 거래처, 대조 결과, 이상 징후, 원본 문서 링크가 한 화면에 없으면 결국 다른 창을 열어봐야 하고 그만큼 승인이 지연됩니다.
import { WebClient } from '@slack/web-api'
const slack = new WebClient(process.env.SLACK_BOT_TOKEN)
export async function requestApproval(task: {
id: string
partner: string
amount: number
anomalies: string[]
sourceUrl: string
}) {
await slack.chat.postMessage({
channel: '#settlement-approval',
text: `승인 요청: ${task.partner} ${task.amount.toLocaleString()}원`,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text:
`*승인 요청* — ${task.partner}\n` +
`• 금액: *${task.amount.toLocaleString()}원*\n` +
`• 이상 징후: ${task.anomalies.length ? task.anomalies.join(', ') : '없음'}\n` +
`• <${task.sourceUrl}|원본 명세서 보기>`,
},
},
{
type: 'actions',
elements: [
// value에 taskId를 실어 콜백에서 대상 식별
{ type: 'button', style: 'primary', action_id: 'approve',
text: { type: 'plain_text', text: '승인' }, value: task.id },
{ type: 'button', action_id: 'edit',
text: { type: 'plain_text', text: '수정 후 승인' }, value: task.id },
{ type: 'button', style: 'danger', action_id: 'reject',
text: { type: 'plain_text', text: '반려' }, value: task.id },
],
},
],
})
}
3. 감사 추적(Audit Trail) 설계
승인 기록은 '누가 승인했다'만으로 부족합니다. 승인 당시 화면에 표시됐던 데이터의 스냅샷을 함께 남겨야, 나중에 문제가 생겼을 때 승인자가 무엇을 보고 판단했는지 재구성할 수 있습니다.
최소 기록 항목은 승인자 ID, 승인 시각, 작업 ID, 승인 당시 금액과 대조 결과, 그리고 승인 이후 실제 실행 결과입니다. 이 다섯 가지가 있으면 대부분의 내부 감사 질의에 답할 수 있습니다.
기록은 애플리케이션 DB와 분리된 append-only 저장소에 두는 편이 안전합니다. 운영 DB에 함께 두면 데이터 정리 작업 중에 함께 삭제되거나 수정될 여지가 남습니다.
4. 미승인 건 에스컬레이션과 병목 관리
승인 게이트의 최대 부작용은 병목입니다. 승인자가 휴가이거나 알림을 놓치면 자동화된 파이프라인 전체가 그 지점에서 멈춰버립니다.
따라서 미승인 상태의 대기 시간을 반드시 모니터링하고, 일정 시간 초과 시 2차 승인자에게 자동 에스컬레이션되도록 구성해야 합니다. 실무 기준으로 2시간 후 팀장, 4시간 후 부서장 정도의 단계가 무난합니다.
또한 승인 대기 건수 자체를 지표로 관리하십시오. 대기 건이 계속 쌓인다면 승인 대상 범위가 지나치게 넓다는 신호이며, 저위험 작업을 자동 승인으로 내려주는 조정이 필요합니다.
자주 막히는 지점
같은 건이 두 번 승인되어 이중 처리되었습니다.
원인: 여러 담당자가 동시에 버튼을 눌렀고 상태 갱신에 동시성 제어가 없었습니다.
해결: 승인 처리 시 상태가 '대기'인 경우에만 갱신되는 조건부 업데이트(WHERE status = 'pending')를 사용하고, 갱신 행 수가 0이면 이미 처리된 건으로 안내하십시오. 처리 완료 후에는 슬랙 메시지의 버튼을 즉시 제거해야 합니다.
승인 요청 알림이 채널에 묻혀 며칠간 방치됩니다.
원인: 일반 대화 채널에 알림을 보내고 에스컬레이션 규칙이 없습니다.
해결: 승인 전용 채널을 분리하고, 승인자에게 직접 멘션을 걸며, 대기 시간 초과 시 상위 담당자로 자동 에스컬레이션되는 스케줄러를 별도로 운영하십시오.
핵심 요약
- 중요 트랜잭션에는 반드시 Human-in-the-Loop 승인 단계를 설계해야 합니다.
- '외부 발송·금액 이동·법적 효력' 세 가지 기준으로 승인 대상을 판별하면 설계가 단순해집니다.
- 승인은 실무자가 이미 쓰는 도구(슬랙) 안에서 3초 안에 끝나야 우회되지 않습니다.
- 승인 당시 데이터 스냅샷까지 남겨야 감사 대응과 품질 개선에 실제로 쓸 수 있습니다.
자주 묻는 질문
승인 단계를 두면 자동화 효과가 반감되지 않나요?
전체 작업 중 승인이 필요한 건은 보통 5% 미만입니다. 나머지 95%가 자동으로 처리되므로 체감 효과는 거의 그대로이며, 오히려 사고 위험이 사라져 자동화 범위를 더 과감하게 넓힐 수 있습니다.
승인 권한은 어떻게 설계해야 하나요?
금액 구간별로 승인자를 나누는 방식이 일반적입니다. 기존 사내 결재 규정의 전결 기준을 그대로 가져오면 별도 합의 없이 도입할 수 있어 정착이 빠릅니다.
모바일에서도 승인할 수 있나요?
슬랙 모바일 앱에서 블록킷 버튼이 그대로 동작하므로 외근 중에도 승인이 가능합니다. 다만 금액 등 핵심 정보가 모바일 화면에서 잘리지 않도록 메시지 구성을 간결하게 유지하십시오.