
결재 대기 문서가 며칠씩 묵을 때, 알림 한 번으로 부족한 이유
결재함 맨 위에 출장비 정산 문서가 하나 있습니다. 차례가 온 첫날에는 제목 옆에 아무 표시가 없습니다.
다음 날 회색 배지로 '2일째'가 붙습니다. 그다음 날은 '3일째'이고, 그날이 금요일이면 주말을 넘긴 월요일 아침에는 '6일째'가 됩니다.
이 배지를 달기 전에는 그 숫자를 아무도 몰랐습니다. 결재자도 기안자도 확인할 방법이 없었습니다.
제가 만들어 운영하는 사내 그룹웨어는 보험대리점(GA) 지사, 수십 명 규모 조직에서 씁니다. 거기서 올라온 요청은 한 줄이었습니다.
"결재 차례가 와도 알림 한 번이라 며칠씩 잊힌다."
알림이 한 번뿐이던 구조
기존 결재 알림은 차례가 바뀌는 순간에 한 번 나갔습니다. 그날 외근이나 회의가 겹치면 알림은 다른 메시지에 묻힙니다.
그 뒤로는 결재함에 직접 들어가 보지 않는 한 알 길이 없습니다.
더 근본적인 빈칸이 하나 있었습니다. 차례가 언제 왔는지 기록하는 칸이 없었습니다.
상신 시각은 남지만, 두 번째 결재자에게 차례가 넘어간 시각은 어디에도 없었습니다. 그래서 '며칠째 대기'를 셀 수가 없었고, 알림을 다시 보낼 기준도 잡을 수 없었습니다.
요청을 받고 저는 아래 제안을 올렸습니다. 채택 여부는 운영 쪽이 정했습니다.
| 제안 | 결과 |
|---|---|
| 매일 아침 결재 대기 묶음 알림 + 대기 일수 표시 | 만듦 |
| 기안자가 누르는 재촉 버튼 | 승인되지 않아 만들지 않음 |
| 결재자 휴가 경고 + 대결 | 만듦 |
재촉 버튼이 빠지면서 방향이 하나로 모였습니다. 재촉은 시스템이 하루 한 번 하고, 사람이 사람을 재촉하는 기능은 두지 않는 쪽입니다.
시각 한 칸부터
처음 손댄 곳은 데이터였습니다. 결재 단계마다 '차례가 온 시각'을 남기는 칸을 추가했습니다.
까다로운 건 기록 지점이었습니다. 차례가 바뀌는 경로는 상신할 때, 임시저장 문서를 상신할 때, 앞 사람이 승인해 넘길 때, 퇴사자 결재를 정리할 때였습니다.
한 곳이라도 빠지면 그 경로로 들어온 문서는 일수가 비어 보입니다. 그래서 경로를 먼저 다 찾은 뒤 같은 함수 하나로 시각을 찍게 했습니다.
이 함수는 한 차례에 여러 번 불려도 기록이 흐트러지지 않게 만들었습니다.
이미 진행 중이던 문서도 처리해야 했습니다. 운영 DB에서 대기 중인 결재 단계는 11개였고, 그중 지금 차례인 6개에만 시각을 채웠습니다.
나머지 5개는 뒷단계라 아직 차례가 오지 않았습니다. 비워 두는 게 맞는 값입니다.
매일 아침 한 통, 묶어서
묶음 알림은 평일이고 공휴일이 아닌 날, 오전 9시부터 오후 6시 사이 창 안에서만 나갑니다. 한 사람에게 하루 한 통입니다.
제목은 "결재 대기 N건 · 가장 오래된 건 M일째" 형식입니다. 본문에는 문서 5건까지 보여 주고 나머지는 "외 N건"으로 줄입니다.
대상은 어제 이전부터 기다리는 문서입니다. 오늘 차례가 온 문서는 방금 차례 알림이 나갔으니 묶음에서 뺍니다.
메신저 채널이 연결되지 않은 사람에게는 이메일로 갑니다.
새 스케줄러를 두지 않은 이유
정해진 시각에 뭔가를 보내려면 보통 예약 작업(크론)을 하나 새로 둡니다. 저는 두지 않았습니다.
그룹웨어에는 실시간 알림 서버가 이미 10분마다 도는 타이머를 갖고 있었습니다. 이 타이머가 내부 API를 부르도록 한 줄을 얹었습니다.
내부 API는 비밀 헤더를 확인한 뒤에만 움직이고, 비밀값은 기존에 쓰던 것을 재사용했습니다. 새 비밀값을 만들지 않았고, 비밀 헤더가 맞지 않는 호출은 거부합니다.
남은 문제는 중복이었습니다. 타이머는 하루에 수십 번 부르는데 알림은 한 번만 나가야 합니다.
그래서 '사람 + 날짜'를 키로 하는 발송 기록 표를 두었습니다. 발송 전에 이 표에 먼저 한 줄을 넣고, 넣기에 성공한 호출만 보냅니다.
같은 날 두 번째 호출은 넣기에서 막히니 그대로 지나갑니다. 창 안 첫 호출이 그날 발송이 되므로 실제 도착은 09:00~09:10 사이입니다.
| 선택 | 얻은 것 | 내준 것 |
|---|---|---|
| 기존 10분 타이머에 얹기 | 관리할 스케줄러가 늘지 않음 | 최대 10분 늦게 도착 |
| 하루 1회 선점 기록 | 타이머가 몇 번 돌아도 중복 없음 | 기록 표 하나 추가 |
첫 운영 발송은 배포 당일에 나갔습니다. 배포가 업무시간 창 안이었기 때문입니다.
서버 기록으로 11시 13분에 대상 3명에게 3통이 나갔고 실패는 0이었습니다. 하루치 표본이라 이 숫자는 동작 확인 이상의 의미는 없습니다.
알림만으로는 다시 묻힐 수 있어서 화면에도 숫자를 남겼습니다.
결재함 목록에는 'N일째' 배지가 붙습니다. 첫날은 표시하지 않고 2일째부터 보입니다.
문서 상세의 결재 진행 레일에는 'N일째 대기'가, 홈 화면 카드에는 '최장 N일째'가 뜹니다.
결재자가 휴가 가면 문서는 어디로
묶음 알림을 받아도 결재자가 휴가 중이면 소용이 없습니다. 문서는 그 사람이 돌아올 때까지 멈춥니다.
기안자는 상신하고 나서야 그 사실을 알게 됩니다. 기존에는 결재선을 통째로 바꾸는 것 말고 대신 처리할 방법이 없었습니다.
그래서 대결을 넣었습니다. 결재자가 미리 지정해 둔 사람이 그 기간 동안 본인 차례를 대신 처리하는 방식입니다.
휴가 신청 폼에서 대결자를 고르면 그 휴가와 연결됩니다. 휴가가 반려되거나 취소되면 대결도 자동으로 꺼집니다.
결재 화면의 '부재·대결' 패널에서도 직접 지정하고 해제할 수 있습니다. 기간은 시작일과 종료일을 모두 포함하고, 최대 92일입니다.
기간이 겹치는 대결 지정은 거부합니다.
권한이 넓어지는 기능의 경계
대결은 남의 차례를 처리할 수 있게 하는 기능입니다. 권한이 넓어지는 방향이라 경계를 먼저 정했습니다.
| 상황 | 처리 |
|---|---|
| 기안자 본인이 대결자로 지정됨 | 처리 금지(자기 문서 결재 방지) |
| 휴가 반려·취소, 기간 만료, 수동 해제 | 처리 거부 |
| 대결자이지만 다른 사람 차례 | 처리 거부 |
| 결재선 | 바꾸지 않음, 실제 처리자를 따로 기록 |
| 다른 문서의 근거 문서 후보 | 대결로 본 문서는 넣지 않음 |
서명란에는 원래 결재자 칸에 '대결 이름'이 찍힙니다. 나중에 누가 실제로 눌렀는지 문서만 보고 알 수 있습니다.
이 경계는 DB 테스트 10건으로 묶었습니다. 기안자 대결자 거부, 만료·해제·휴가 반려 뒤 거부, 다른 사람 차례 거부가 모두 들어 있습니다.
알림도 같이 손봤습니다. 차례 알림은 결재자와 대결자에게 함께 가고, 아침 묶음 알림에는 "OO 님 대결" 항목으로 따로 들어갑니다.
부재 안내도 이때 붙였습니다. 상신 전에 알 수 있도록 기안 화면과 휴가 신청 화면의 결재선 아래에 결재자 부재 안내를 붙였습니다.
여기서 휴가 종류는 서버가 아예 내려보내지 않습니다. 병가 같은 항목은 건강정보이기 때문입니다.
화면에서만 가리면 브라우저 개발자 도구로 응답을 열었을 때 그대로 보입니다. 그래서 부재 안내 응답에는 휴가 날짜와 대결자 이름만 담았습니다.
세 사람 시점으로 돌린 화면
배포 뒤 시험 환경에서 기안자, 대결자, 부재자 세 사람 계정으로 데스크톱과 모바일 폭 화면을 돌려 봤습니다.
모바일 목록에서 대결 배지가 제목과 함께 잘려 "김부…"처럼 보였습니다. 제목만 줄이고 배지는 크기를 고정해 고쳤습니다.
대결자의 상세 화면에 '내 차례' 표시가 붙었습니다. 차례 판정에 대결이 섞여 들어간 탓이라, 실제 결재자일 때만 붙게 바꿨습니다.
부재 패널의 "· OO 부장 대결"이라는 문구는 맡긴 건지 맡은 건지 헷갈렸습니다. "OO 님이 대결 중"과 "OO 님 대결 맡음"으로 나눴습니다.
아직 확인하지 못한 것도 있습니다. 실제 휴가자의 문서를 대결자가 승인하는 왕복은 실사용 데이터가 생기지 않아 운영에서 본 적이 없습니다.
지금은 DB 테스트로만 묶여 있고, 첫 실사례가 나오면 따로 확인할 계획입니다.
우리 조직에 대입해 보기
결재가 메신저와 엑셀, 메일로 흩어져 도는 조직이라면 결재선과 휴가, 알림을 한 시스템에 모으는 일이 출발점입니다. 그래야 대기 일수를 세고 대결을 휴가에 묶을 수 있습니다.
전자결재 화면이 실제로 어떻게 생겼는지는 사내 그룹웨어 시연 데모에 가상 조직 데이터로 들어 있습니다.
이미 쓰는 시스템에 묶음 알림이나 대결만 붙이고 싶다면 업무 시스템 상담에 지금 결재가 도는 방식을 적어 보내 주세요. 기존 결재 데이터에 시각 한 칸을 더할 수 있는지가 첫 갈림길입니다.
결재 지연 자가진단
아래 질문에 바로 답이 안 나오면 그 칸이 지연이 생기는 자리입니다.
- 각 결재자에게 차례가 온 시각을 기록하고 있습니까? 없다면 '며칠째'는 누구도 셀 수 없습니다.
- 결재 알림은 차례가 바뀔 때 한 번 울리고 끝납니까, 아니면 기다리는 문서를 매일 묶어서 다시 알려 줍니까?
- 결재자가 휴가를 가면 그 기간의 문서는 누가 처리합니까? 기안자는 상신 전에 그 사실을 볼 수 있습니까?
- 오래 묵은 문서를 챙기는 일을 기안자 개인에게 맡기고 있습니까, 시스템이 정해진 시각에 대신하고 있습니까?
- 다른 사람이 대신 승인했을 때, 원래 결재자와 실제로 누른 사람이 문서에 따로 남습니까?
- 휴가 종류 같은 민감한 항목이 화면에서만 가려지고 응답에는 실려 가고 있지 않습니까?
다섯 번째와 여섯 번째는 사고가 나기 전에는 잘 드러나지 않습니다. 결재함 첫 줄의 문서가 오늘 며칠째인지부터 확인해 보세요.
이어서 읽기
정산 프로그램 마진이 실제보다 크게 나올 때, 공식부터 보는 법
정산 앱이 띄운 누적 지사마진이 본사 확정 장부의 약 4.5배였고, 적자인 달 셋을 흑자로 그리고 있었습니다. 장부 항등식은 원 단위까지 맞았는데 화면 공식이 13항목 중 2항목만 보던 사례와 화면을 점검하는 3단계 절차를 적었습니다.

매장 예약 관리, 엑셀 대신 작은 예약 시스템으로 시작하기
담당자별 예약이 메모장과 메신저에 흩어진 매장이라면 업무 전체를 바꿀 필요는 없습니다. 접수와 담당자 일정, 일별 예상 매출만 묶은 예약 화면의 크기를 데모로 짚고 엑셀로 충분한지 가르는 문항과 첫 범위를 적었습니다.

본사 마감 엑셀 양식이 매달 바뀔 때, 업로드가 반만 들어가는 문제
본사가 보내는 월 마감 엑셀은 매달 열이 빠지고 형식이 바뀝니다. 보험대리점 지사의 마감 적재를 다시 만들며 정한 기준, 처음 보는 변화에서 멈추고 넣은 뒤 DB에서 다시 세는 방식을 실제 숫자와 실패까지 함께 적었습니다.