
SOFTMOA TECHNOLOGY
구내식당 식수 신청 마감과 배식 집계 시스템 구축 방법
소프트모아가 정리한 기술 기록입니다.
Contents
구내식당 식수 신청 인원과 배식 집계가 다를 때는 신청, 마감 확정, 수령 기록을 나눠 관리해야 합니다. 마감 뒤 들어온 신청까지 조리 수량에 바로 더하거나 단말기의 입력 횟수를 식사 인원으로 세면 숫자가 맞아 보여도 기준은 틀릴 수 있습니다. 이 글은 실제 고객 사례가 아닌, 직원이 점심 한 끼를 신청하는 가상 시스템의 설계 예입니다.
조리 담당자가 보는 숫자를 먼저 정합니다
예시 사업장은 당일 오전 10시를 신청 마감으로 정합니다. 직원은 식사일, 사업장, 점심 메뉴를 고르고 1식을 신청합니다. 같은 직원이 같은 날 같은 끼니에 두 번 신청하지 못하게 하며, 취소 후 재신청도 기존 신청의 변경 이력으로 남깁니다. 여러 끼니나 사업장을 운영한다면 신청번호 외에 날짜·끼니·사업장 식별자를 반드시 저장하는 설계입니다.
마감 화면에는 '확정 3식, 추가 승인 대기 1식'처럼 두 수량을 따로 보여줍니다. 아래 예에서 M01~M03은 CONFIRMED, M04는 마감 전 취소한 CANCELLED, M05는 마감 후 신청한 LATE_PENDING입니다. 신청 행은 5개지만 조리 담당자에게 넘기는 최초 확정 수량은 3식입니다. 이 수치는 예제 입력이며 실제 운영 실적이 아닙니다.
- 직원 화면: 본인 신청과 취소 결과, 마감 시각, 추가 신청의 승인 여부를 표시합니다.
- 총무 화면: 마감본을 확정하고 추가 신청을 승인하거나 반려합니다. 조리 담당자가 추가 준비 가능 수량을 확인한 뒤 승인하도록 정합니다.
- 조리·배식 화면: 메뉴별 확정 수량과 승인된 증감을 조회하고, 배식 시 해당 신청의 수령을 기록합니다. 직원 전체의 신청 이력은 노출하지 않습니다.
마감 시각은 화면을 누른 시간이 아니라 서버가 신청을 접수한 시각으로 판정하는 설계입니다. 예컨대 09:59:59 접수는 마감 전, 10:00:00 접수는 마감 후로 정하고 시간대도 Asia/Seoul로 고정합니다. 이 경계와 승인 담당자는 회사가 정할 운영 규칙이지 모든 식당에 적용되는 기준은 아닙니다.
입력 3건이 수령 3식을 뜻하지 않는 예
배식 단말기에 M01, M01, M02가 들어왔다고 가정합니다. 같은 신청의 중복 입력 때문에 원시 기록은 3건이지만, 서로 다른 확정 신청에 연결된 수령 기록은 2건입니다. 다음 SQL은 SQLite에서 별도 테이블을 만들지 않고 이 차이만 조회합니다. WITH로 예제 행을 구성하고 count(*)로 행 수를 셉니다.[1][5] 실행 환경은 SQLite 3.54.0이며 업무 DB는 변경하지 않았습니다.
WITH booking(id,status) AS (
VALUES ('M01','CONFIRMED'),('M02','CONFIRMED'),
('M03','CONFIRMED'),('M04','CANCELLED'),
('M05','LATE_PENDING')
), receipt(booking_id) AS (
VALUES ('M01'),('M01'),('M02')
), eligible AS (
SELECT id FROM booking WHERE status='CONFIRMED'
), received AS (
SELECT DISTINCT r.booking_id
FROM receipt r JOIN eligible e ON e.id=r.booking_id
)
SELECT
(SELECT count(*) FROM eligible) AS confirmed,
(SELECT count(*) FROM receipt) AS raw_events,
(SELECT count(*) FROM received) AS recorded_meals,
(SELECT count(*) FROM eligible)
- (SELECT count(*) FROM received) AS unconfirmed,
(SELECT count(*) FROM booking
WHERE status='LATE_PENDING') AS late_pending;
위 내용을 meal-check.sql로 저장한 뒤 다음 명령을 실행합니다. 메모리 DB에서 예제 SELECT만 수행합니다.
sqlite3 :memory: -header -column < meal-check.sql
confirmed raw_events recorded_meals unconfirmed late_pending
3 3 2 1 1
확정은 3식, 원시 입력은 3건, 수령 기록은 2식, 수령 미확인은 1식, 추가 승인 대기는 1식입니다. 수령 미확인 M03을 곧바로 '먹지 않은 직원'으로 표시하지 않습니다. 직원이 받았는데 단말기 기록이 누락됐을 수도 있기 때문입니다. 수령 기록 2식 역시 실제 섭취량이나 잔반량을 증명하지 않습니다.
마감본은 남기고 변경분을 전달합니다
M05를 승인하면 최초 마감본 3식을 덮어쓰지 않고 '추가 승인 +1식'과 조리 담당자의 확인을 남깁니다. 변경 후 확정 수량은 4식입니다. SQL의 M05 상태만 CONFIRMED로 바꾼 복사본에서는 결과가 4, 3, 2, 2, 0으로 달라집니다. 추가 승인은 수령 기록을 만들지 않으므로 미확인이 2식이 됩니다. 원래 예제의 취소 신청 M04는 그대로 제외됩니다.
마감 이후 취소도 요청을 받자마자 확정 수량에서 빼지 않는 편이 낫습니다. 이미 조리가 시작됐는지 확인한 뒤 담당자가 변경분을 승인하도록 설계합니다. 직원에게는 '취소 요청 중'과 '취소 확정'을 구분해 보여주고, 승인자·시각·사유·변경 전후 수량을 저장합니다. 식대 정산에 반영할지는 별도 사내 기준으로 정합니다.
조회용 중복 제거와 현장 배식 통제는 다릅니다
이 SQL은 이미 들어온 기록을 집계할 뿐, 중복 배식을 막지 않습니다. 운영 시스템은 수령 확정 저장 시 신청번호의 중복을 검사하고, 여러 단말기가 동시에 처리해도 한 번만 확정되는 저장 규칙을 별도로 구현해야 합니다. 취소·미승인 신청이나 다른 날의 신청번호는 일반 배식 처리에서 제외하고 담당자 확인 대상으로 보냅니다.
통신 장애 중에는 저장 성공 여부를 화면에 분명히 표시합니다. 수기 배식은 임시 기록번호와 담당자를 남겨 온라인 기록과 대조하고, 재전송 때문에 기록이 두 배가 되지 않게 합니다. 잘못 등록한 수령을 정정할 때도 원본을 지우지 않고 정정 사유를 연결합니다. SQL 예제에는 이런 저장·권한·정정 기능이 없으므로 화면과 API 검증은 별도 개발 범위입니다.
구축 범위를 정할 때는 신청 달력보다 먼저 마감본, 추가 승인, 수령 미확인의 의미를 합의하는 것이 좋습니다. softmoa.com에서는 이런 업무 규칙을 반영한 관리자 시스템을 상담할 수 있습니다.
SQL 확인 자료: [1] SQLite WITH, [5] SQLite 집계 함수.
소프트모아는 해당 시스템을 구축합니다. 문의하기
