story · how it was built
설명
무엇을 (문제·대상)
산업용 센서를 파는 회사의 영업은 제품 카탈로그가 아니라 사양 문답에서 시작합니다. 압력 범위, 사용 유체, 설치 환경을 듣고 맞는 모델을 골라 주는 일이 먼저입니다. 이 시스템은 그 첫 문답부터 견적, 수주, 구매, 재고, 세금계산서까지를 한 흐름으로 묶은 B2B 세일즈 ERP 입니다.
주요 기능
- 제품 추천 퍼널 — 방문자가 기본 정보를 넣으면 조건에 맞는 제품을 제안하고, 그대로 견적 요청으로 이어집니다. 로그인 없이 접수됩니다.
- 견적·수주 — 견적 항목 관리와 프로젝트 단위 추적.
- 고객·활동 — 고객, 담당자, 활동 이력, 첨부파일.
- 구매·입고 — 거래처, 발주, 발주 항목, 입고.
- 재고·세금계산서 — 재고와 입출고 이력, 세금계산서 발행.
- 이메일 이력 — 보낸 메일과 템플릿을 남깁니다.
어떻게 만들었는가 (과정·도구 활용)
Next.js · Supabase 로 만들었고 AI 는 사양 문답 보조에 씁니다. 권한 설계가 이 시스템의 핵심이었습니다. 외부에 열려 있는 건 견적 요청 접수 하나뿐이고, 나머지 테이블은 전부 로그인한 관리자만 접근할 수 있도록 행 수준 보안으로 막았습니다.
정책을 두 번 감사했습니다. 처음 감사에서 대문자 표기만 검색하는 바람에 실제로는 걸려 있던 정책을 「없다」고 잘못 판정했고, 다시 전수 확인해서 진짜 구멍 하나(대상 역할이 빠져 사실상 전체에 열려 있던 정책 4건)를 찾아 고쳤습니다.
한계·다음
- 정책 이름 표기 방식이 마이그레이션마다 달라 세 가지가 섞여 있습니다. 동작에는 영향이 없어 신규만 통일하기로 했습니다.
- 단일 제품군 기준으로 만들어져 있어, 제품군이 늘면 추천 로직을 일반화해야 합니다.
journey · lessons
과정 · 배운 점
본문 = 무엇·기능·사용법. 여기 = 시간순 여정 + 다음에 남긴 교훈.
「없다」는 진단은 코드로 확인한 뒤에 내려야 합니다. 대문자로만 검색해 놓고 보안 정책이 없다고 판정했는데, 다시 보니 소문자로 걸려 있었습니다. 잘못된 「없음」 판정은 멀쩡히 되는 것을 건드리게 만듭니다.
정책이 존재하는 것과 정책이 올바른 대상에 걸려 있는 것은 다릅니다. 대상 역할 절이 빠진 정책 4건은 문법상 전체 공개였습니다. 실제 데이터베이스에서 적용 역할을 조회해 확인하기 전까지는 통과로 볼 수 없습니다.
익명 접수를 하나 열어 둘 때는, 그게 의도된 구멍이라는 걸 문서에 남겨야 합니다. 안 그러면 다음 감사 때마다 같은 논쟁을 반복합니다.
피드백 원함 · 개선 제안 · 스택·도구 조언 · 질문