VGOLF F&B
주방 프린터부터 디지털 사이니지까지, 매장을 돌리는 F&B 시스템
Role: Frontend Developer · F&B 제품 전반 단독 개발
Overview
골프장 F&B 플랫폼의 주문·관리자·주방 영수증 출력·매장 사이니지 서브시스템을 초기 보일러플레이트 위에서 설계·구현했습니다. 앱 로직을 넘어 매장 하드웨어 연동, 오프라인·실시간 견고성, 상태별 조건 렌더링처럼 실제 배포 현장에서 깨지는 지점들을 붙잡아 해결한 것이 핵심입니다. 초기 인프라(axios·recoil·SSE 훅·login shell)와 일부 모듈은 선행 팀원 기반이며, 2025년 12월 합류 이후 F&B 제품 전반을 맡아 개발했습니다.
이 프로젝트의 핵심
10개월 · 520커밋
Next.js App Router 정적 export, TypeScript strict
ESC/POS 열전사 프린팅 직접 구현
80mm 주방 영수증 바이트열 생성 + EUC-KR 인코딩, CJK를 폭 2로 계산하는 고정폭 레이아웃 엔진
클라우드→LAN 브릿지 설계
정적 배포 앱과 매장 사설망 프린터가 서로 닿지 못하는 구조를, 로컬 프린트 에이전트를 경유해 raw TCP로 해결
오프라인 부팅 사이니지(DID)
망분리 미니 PC가 네트워크 없이 부팅해도 화면이 뜨도록 서비스워커 문서 프리캐시 설계
나머지 3개 더 보기접기
WYSIWYG 사이니지 편집기
편집 화면과 실제 표출이 동일하게 렌더되도록 %오프셋 저장 + container-query 폰트 자동 스케일
이중 실시간 전략
사이니지는 SSE 구독, 주문 화면은 폴링 + 야간모드 상태머신 + 연속에러 서킷브레이커로 24시간 무인 운영
다축 조건 렌더링 설계
주문 상태·ERP·권한·화면 분할·네트워크·운영 시간대 6개 축을 독립 분기해 조합 폭발을 관리
Screens














실제 운영 화면입니다. 손님·직원의 이름과 CCTV에 잡힌 이용객은 알아볼 수 없게 처리했고, 내부 접속 주소는 잘라냈습니다.
자세히
하드웨어 연동 — ESC/POS 주방 영수증5
80mm 열전사 프린터용 ESC/POS 바이트열을 직접 생성하고, 프린터가 이해하는 EUC-KR로 인코딩
CJK 문자를 폭 2로 계산하는 고정폭 레이아웃 엔진으로 한/영 혼용 표 정렬을 맞춤
빌지번호 클라이언트 채번 + IndexedDB 일자 단위 중복방지
재시작해도 같은 영수증이 다시 출력되지 않음
구조가 가장 큰 난점
앱은 클라우드 정적배포인데 프린터는 매장 사설망(192.168.x.x)이라 서로 닿지 못함
브라우저가 로컬 프린트 에이전트(127.0.0.1:9110)로 명령을 보내고, 에이전트가 raw TCP:9100으로 프린터에 쏘는 브릿지로 해결
디지털 사이니지(DID) — 오프라인 우선4
망분리 미니 PC가 네트워크 없이 부팅해도 화면이 뜨도록 서비스워커 캐싱을 설계
문서 프리캐시를 빌드ID revision과 함께 주입
CDN 폰트가 오프라인에서 누락되는 문제를 자체 호스팅으로 해결
PDF는 브라우저 기본 뷰어를 피하고 canvas 직접 렌더 + 로컬 워커로 처리해 오프라인에서도 표출
배경이 지정되지 않은 경우 템플릿 fallback으로 빈 화면이 뜨지 않게 방어
WYSIWYG 사이니지 편집기4
1~4분할 레이아웃을 grid-template-areas로 구성해 분할 수가 바뀌어도 같은 렌더 경로를 씀
텍스트 세트 드래그 위치를 중앙 기준 % 오프셋으로 저장
편집 해상도와 표출 해상도가 달라도 위치가 유지됨
container-query 기반 폰트 자동 스케일로 화면 크기에 따라 글자가 함께 커지고 작아짐
정렬·폰트·크기·색상·PDF 오버레이·전체화면 미리보기까지 편집기와 실제 표출이 동일하게 렌더
실시간 · 무인 운영 견고성5
사이니지는 SSE 채널을 구독해 콘텐츠 변경만 수신
불필요한 폴링 트래픽 제거
주문 화면은 React Query 폴링에 야간모드 상태머신(off / idle 30s / active 5s)을 얹어 영업 시간대별로 주기를 조정
연속에러 서킷브레이커 가드로 백엔드 장애 시 폴링을 자동 중단, 24시간 무인 환경에서 요청이 쌓이지 않게 함
visibilitychange 연동으로 화면이 보이지 않을 때의 동작을 분리
캐시 무효화는 ERP 연동 여부를 아는(ERP-aware) 중앙집중 방식으로 관리
실시간 골퍼 코스진행 관제 바3
각 홀의 실제 너비·간격 비율로 트랙을 구성해 코스 형태가 바 위에 그대로 반영되게 함
골퍼를 progress·gap 기반으로 배치
홀 내부 진행률과 홀 사이 이동 구간을 구분해 표시
정방향·역방향 진행 순서까지 계산해 한눈에 코스 상황을 읽을 수 있게 구성
매장 배치도 캔버스 에디터3
pan / zoom과 페이지 간 드래그 이동(포인터 히트테스트)을 지원하는 캔버스 편집기
회전 시 w/h 스왑까지 반영한 AABB 충돌검출로 테이블이 겹치지 않게 배치
근사정사각 멀티페이지 그리드 구성, 좌표는 "x,y,r" · "1920,1080,page" 형태로 인코딩해 저장·복원
조건별 렌더링 설계6
하나의 화면이 여러 축의 상태를 동시에 만족해야 해, 상태를 형태(칩·컬러·레이아웃)로 인코딩하고 각 축을 독립 분기해 조합 폭발을 관리
주문 상태
접수(R) · 재주문(RN) · 수락(P) · 취소(N) · 완료(Y)에 따라 카드/즉석조리/알림 분기
ERP 연동
연동 시 공급가·VAT·전표 컬럼을 조건부 주입하고 orderErp가 있는 행만 필터
화면 분할
1~4분할, 일반 ↔ PDF, 텍스트 오버레이 조합
네트워크
online(최신) / offline(캐시본) / connecting(백오프 재시도)
권한
canPrintBill · canManageGoods · canCancelOrder 기반 RBAC와 역할별 랜딩 라우팅
정산 · ERP3
ExcelJS로 서식·병합·테두리를 적용한 매출 시트 export
ERP 연동 시 공급가·VAT·전표 컬럼을 조건부로 주입하고, orderErp가 있는 행만 필터링
그룹 행 forward-fill로 회계 대사에 바로 쓸 수 있는 형태로 정리