종량제 -- 쓰레기봉투 물류시스템 (jongryangje)
종량제 개발목록 (엑셀 다운로드) -- 로컬 복제 후에는 assets/종량제_개발목록_20260127.xlsx
지자체/지정판매소 등을 대상으로 하는 종량제 쓰레기봉투 물류/업무 웹 애플리케이션입니다.
백엔드는 CodeIgniter 4 기반입니다.
저장소: wixon-associates/jongryangje
| 구현 화면 스크린샷 | Notion 진행상황 | 서버/배포 가이드 |
운영 환경
기술 스택
| 항목 |
기술 |
| Framework |
CodeIgniter 4.7+ |
| Language |
PHP 8.2+ (strict types) |
| Database |
MySQL / MariaDB (MySQLi) |
| 의존성 관리 |
Composer 2.x |
| E2E 테스트 |
Playwright (Chromium) |
| 세션 |
파일 기반 (writable/session/) |
| 프론트엔드 |
Tailwind CSS (CDN), Vanilla JS |
프로젝트 구조
데이터베이스 (25개 테이블)
회원/인증
| 테이블 |
용도 |
member |
회원 (mb_id, mb_level, mb_state, PII 암호화, 로그인 실패 lock) |
member_log |
로그인/로그아웃 감사 로그 (IP, User-Agent) |
member_approval_request |
회원가입 역할 승인 요청 (pending/approved/rejected) |
지자체/판매소
| 테이블 |
용도 |
local_government |
지자체 (테넌트 루트, lg_code 기반) |
designated_shop |
지정판매소 (지자체별, 판매소번호 자동생성) |
메뉴 시스템
| 테이블 |
용도 |
menu_type |
메뉴 유형 (admin, site) |
menu |
메뉴 항목 (트리 구조, 역할별 노출, 지자체별) |
기본코드 마스터
| 테이블 |
용도 |
code_kind |
코드 종류 (A~T, 20종) |
code_detail |
세부코드 (행정구역, 봉투구분, 재질, 용량 등) |
단가/포장
| 테이블 |
용도 |
bag_price |
봉투 단가 (발주/도매/소비자가, 적용기간) |
bag_price_history |
단가 변경 이력 |
packaging_unit |
포장 단위 (박스/팩/낱장) |
packaging_unit_history |
포장 단위 변경 이력 |
업체/담당자/대상자
| 테이블 |
용도 |
sales_agency |
판매 대행소 |
company |
업체 (manufacturer/association/collector) |
manager |
담당자 (소속/직위) |
free_recipient |
무료용 대상자 (생보자/시설/수훈자) |
발주/입고/재고
| 테이블 |
용도 |
bag_order |
발주 (UUID, LOT번호, SHA-256 해시) |
bag_order_item |
발주 품목 (봉투코드별 수량/금액) |
bag_receiving |
입고 (발주 연계, 박스/낱장 수량) |
bag_inventory |
재고 현황 (봉투코드별 현재 재고) |
판매/주문/불출
| 테이블 |
용도 |
bag_sale |
판매/반품 (판매소, 봉투코드, 수량/금액) |
shop_order |
주문 접수 (배달일, 결제/입금/수령 상태) |
shop_order_item |
주문 품목 (박스/팩/낱장 단위) |
bag_issue |
무료용 불출 (연도/분기, 불출처, 상태) |
역할 체계 (RBAC)
| Level |
역할 |
설명 |
| 4 |
Super Admin |
전체 시스템 관리, 작업 지자체 선택 필수 |
| 3 |
지자체관리자 |
소속 지자체 범위 내 관리 |
| 2 |
지정판매소 |
봉투 판매/재고 관리 |
| 1 |
일반 사용자 |
기본 조회 (시민) |
- 역할 상수:
Config\Roles -- LEVEL_SUPER_ADMIN(4), LEVEL_LOCAL_ADMIN(3), LEVEL_SHOP(2), LEVEL_CITIZEN(1)
AdminAuthFilter가 로그인 + 레벨 3/4 + 지자체 선택 여부 검증
멀티테넌시
local_government.lg_idx가 테넌트 루트
- 관리자 필터에서
admin_effective_lg_idx() 기반 테넌트 분리
- Super Admin은
/admin/select-local-government에서 작업 지자체 선택
- 지자체관리자는 소속
mb_lg_idx 자동 적용
라우트 구조
공개 페이지
| 경로 |
설명 |
/ |
홈 (비로그인: 환영, 로그인: 대시보드) |
/login, /logout |
로그인/로그아웃 |
/register |
회원가입 (역할 승인 플로우) |
/dashboard/* |
대시보드 시안 (classic/modern/dense/charts) |
사이트 메뉴 (/bag/*)
| 경로 |
설명 |
기능 |
/bag/basic-info |
기본정보관리 |
코드/단가/포장단위 조회 + 관리 링크 |
/bag/purchase-inbound |
발주 입고 관리 |
발주/입고 목록 + 등록 버튼 |
/bag/issue |
불출 관리 |
불출 목록 + 처리/취소 |
/bag/inventory |
재고 관리 |
봉투별 현재 재고 조회 |
/bag/sales |
판매 관리 |
주문/판매/반품 + 등록 |
/bag/sales-stats |
판매 현황 |
기간별 판매 데이터 |
/bag/flow |
봉투 수불 관리 |
봉투코드별 입출고 수불 요약 |
/bag/analytics |
통계 분석 관리 |
Phase 6 예정 |
/bag/window |
창 |
Phase 6 예정 |
/bag/help |
도움말 |
시스템 안내 |
관리자 (/admin/*, adminAuth 필터)
시스템 관리
| 경로 |
기능 |
/admin |
관리자 대시보드 |
/admin/users/* |
회원 관리 (CRUD) |
/admin/access/login-history |
로그인 이력 |
/admin/access/approvals |
회원 승인 대기 처리 |
/admin/roles |
역할 목록 |
/admin/menus/* |
메뉴 관리 (트리 CRUD) |
/admin/local-governments/* |
지자체 관리 (CRUD) |
/admin/select-local-government |
작업 지자체 선택 (Super Admin) |
/admin/password-change |
비밀번호 변경 |
/admin/designated-shops/* |
지정판매소 관리 (CRUD) |
기본정보관리 (Phase 2)
| 경로 |
기능 |
/admin/code-kinds/* |
기본코드 종류 (CRUD) |
/admin/code-details/* |
세부코드 (CRUD) |
/admin/bag-prices/* |
봉투 단가 (CRUD + 이력) |
/admin/packaging-units/* |
포장 단위 (CRUD + 이력) |
/admin/sales-agencies/* |
판매 대행소 (CRUD) |
/admin/managers/* |
담당자 (CRUD) |
/admin/companies/* |
업체 (CRUD) |
/admin/free-recipients/* |
무료용 대상자 (CRUD) |
발주/입고/재고 (Phase 3)
| 경로 |
기능 |
/admin/bag-orders/* |
발주 관리 (등록/상세/취소/삭제) |
/admin/bag-receivings/* |
입고 관리 (등록, 재고 자동 반영) |
/admin/bag-inventory |
재고 현황 조회 |
판매/주문/불출 (Phase 4)
| 경로 |
기능 |
/admin/shop-orders/* |
주문 접수 (등록/취소) |
/admin/bag-sales/* |
판매/반품 (등록) |
/admin/bag-issues/* |
무료용 불출 (등록/취소, 재고 연동) |
리포트 (Phase 5)
| 경로 |
기능 |
/admin/reports/sales-ledger |
판매 대장 (일자별/기간별) |
/admin/reports/daily-summary |
일계표 (일계 + 월간 누계) |
/admin/reports/period-sales |
기간별 판매현황 |
/admin/reports/supply-demand |
봉투 수불 현황 |
모델 (25개)
| 모델 |
테이블 |
용도 |
| MemberModel |
member |
회원 계정 |
| MemberLogModel |
member_log |
로그인 이력 |
| MemberApprovalRequestModel |
member_approval_request |
승인 요청 |
| LocalGovernmentModel |
local_government |
지자체 |
| DesignatedShopModel |
designated_shop |
지정판매소 |
| MenuModel |
menu |
메뉴 항목 |
| MenuTypeModel |
menu_type |
메뉴 유형 |
| CodeKindModel |
code_kind |
코드 종류 |
| CodeDetailModel |
code_detail |
세부코드 |
| BagPriceModel |
bag_price |
봉투 단가 |
| BagPriceHistoryModel |
bag_price_history |
단가 변경 이력 |
| PackagingUnitModel |
packaging_unit |
포장 단위 |
| PackagingUnitHistoryModel |
packaging_unit_history |
포장 단위 이력 |
| SalesAgencyModel |
sales_agency |
판매 대행소 |
| CompanyModel |
company |
업체 |
| ManagerModel |
manager |
담당자 |
| FreeRecipientModel |
free_recipient |
무료 대상자 |
| BagOrderModel |
bag_order |
발주 |
| BagOrderItemModel |
bag_order_item |
발주 품목 |
| BagReceivingModel |
bag_receiving |
입고 |
| BagInventoryModel |
bag_inventory |
재고 |
| BagSaleModel |
bag_sale |
판매/반품 |
| ShopOrderModel |
shop_order |
주문 접수 |
| ShopOrderItemModel |
shop_order_item |
주문 품목 |
| BagIssueModel |
bag_issue |
무료 불출 |
보안
| 항목 |
구현 |
| 인증 |
세션 기반 로그인, AdminAuthFilter로 관리자 접근 제어 |
| RBAC |
4단계 역할 (Config\Roles), 메뉴별 역할 노출 |
| PII 암호화 |
pii_encryption_helper (AES, ENC: prefix) - 이메일/전화번호 |
| 비밀번호 |
password_hash() + password_verify() (bcrypt) |
| 로그인 보호 |
5회 실패 시 계정 잠금 (mb_login_fail_count, mb_locked_until) |
| CSRF |
CodeIgniter 내장 CSRF 필터 |
| 멀티테넌시 |
lg_idx 기반 데이터 격리, 세션에서 테넌트 관리 |
빠른 시작
1) 저장소 복제 및 의존성 설치
2) 환경 설정
.env에서 설정:
| 항목 |
설명 |
app.baseURL |
예: http://localhost:8045/ |
database.default.* |
DB 호스트/DB명/사용자/비밀번호 |
encryption.key |
PII 암호화용 64자리 hex |
3) 데이터베이스 준비
SQL 스크립트 실행 순서:
| 순서 |
파일 |
용도 |
| 1 |
init_jongryangje_dev.sql |
DB/사용자 생성 |
| 2 |
login_tables.sql |
회원/로그인/지자체/지정판매소 테이블 |
| 3 |
member_approval_request_add.sql |
승인 요청 테이블 |
| 4 |
member_login_lock_add.sql |
로그인 잠금 컬럼 |
| 5 |
menu_tables.sql |
메뉴 시스템 + 시드 |
| 6 |
menu_type_add_site.sql |
사이트 메뉴 타입 |
| 7 |
local_government_init_daegu.sql |
대구 8개 구군 지자체 |
| 8 |
code_master_init_daegu.sql |
기본코드 마스터 (20종) |
| 9 |
bag_price_tables.sql |
단가 + 단가 이력 테이블 |
| 10 |
packaging_unit_tables.sql |
포장 단위 + 이력 테이블 |
| 11 |
sales_agency_tables.sql |
판매 대행소 테이블 |
| 12 |
manager_tables.sql |
담당자 테이블 |
| 13 |
company_tables.sql |
업체 테이블 |
| 14 |
free_recipient_tables.sql |
무료 대상자 테이블 |
| 15 |
order_tables.sql |
발주/발주품목 테이블 |
| 16 |
sales_tables.sql |
판매/입고/재고/불출/주문 테이블 |
| 17 |
seed_test_accounts.sql |
테스터 계정 4개 |
| 18 |
seed_realistic_data.sql |
실제형 시범 데이터 |
4) 개발 서버 실행
5) 시드 데이터 (선택)
E2E 테스트 (Playwright)
테스터 계정 (비밀번호: test1234!)
| ID |
역할 |
Level |
tester_admin |
Super Admin |
4 |
tester_local |
지자체관리자 (중구청) |
3 |
tester_shop |
지정판매소 |
2 |
tester_user |
일반 사용자 |
1 |
테스트 파일 (84개 테스트)
| 파일 |
테스트 수 |
대상 |
| auth.spec.js |
9 |
로그인/로그아웃/회원가입 |
| admin.spec.js |
10 |
관리자 패널 접근 |
| public.spec.js |
4 |
공개 페이지 |
| bag-site.spec.js |
11 |
사이트 메뉴 /bag/* |
| code-management.spec.js |
7 |
기본코드 CRUD |
| bag-price.spec.js |
6 |
봉투 단가 |
| packaging-unit.spec.js |
3 |
포장 단위 |
| phase2-entities.spec.js |
8 |
대행소/담당자/업체/무료대상자 |
| phase2-extra.spec.js |
4 |
지자체 수정/비밀번호/로그인 lock |
| phase3-order.spec.js |
8 |
발주/입고/재고 |
| phase4-sales.spec.js |
10 |
주문/판매/불출 |
| phase5-reports.spec.js |
4 |
리포트 |
기본코드 체계
A~T 총 20종의 코드 체계 (code_kind + code_detail):
| 코드 |
코드명 |
코드 |
코드명 |
| A |
도/특별시/광역시 구분 |
K |
반품사유 |
| B |
특별시/광역시/시/군코드 |
L |
지정판매소 변경사유 |
| C |
구코드 |
M |
수불구분 |
| D |
동코드 |
N |
동판종류 |
| E |
봉투구분 |
O |
봉투명 (상세 봉투코드) |
| F |
봉투재질 |
P |
작업권한 |
| G |
용량별 |
Q |
예산과목 |
| H |
무상지급 대상 |
R |
은행목록 |
| I |
판매형태 |
S |
소속 |
| J |
반품형태 |
T |
직위 |
개발 진행 현황
Phase별 완료 현황
| Phase |
내용 |
상태 |
| Phase 1 |
프로젝트 초기 세팅, 로그인/회원가입, RBAC, 멀티테넌시, 메뉴 관리, PII 암호화 |
완료 |
| Phase 2 |
기본정보관리 (코드/단가/포장/대행소/담당자/업체/무료대상자/지자체수정/비밀번호/로그인lock) |
완료 |
| Phase 3 |
발주/입고/재고 (발주등록/LOT/취소/삭제/현황/입고처리/재고현황) |
완료 |
| Phase 4 |
주문/판매/불출 (주문접수/판매/반품/불출처리/취소) |
완료 |
| Phase 5 |
리포트 (판매대장/일계표/기간별현황/수불현황) |
완료 |
| Phase 6 |
모바일앱 + 고급기능 (바코드/통계/엑셀/인쇄) |
대기 |
Phase 6 이후 대기 작업
- 지정판매소 다조건 조회 + 엑셀 + 인쇄 + 바코드 출력
- 지정판매소 지도 표시 / 현황 (신규/취소)
- 카카오 주소 검색 API 연동
- 년 판매 현황 (월별/분기별)
- 지정판매소별 판매현황
- 홈택스 세금계산서 엑셀 생성
- 반품/파기 현황, LOT 수불 조회
- 바코드 스캐너 연동 (Electron + serialport)
- 실사 선별/등록/조회
- 페이지네이션/엑셀/인쇄 공통 컴포넌트
- CRUD 로깅 (전체 데이터 변경 이력)
- 2차 인증 적용
- 대시보드 실 데이터 연동
- 모바일앱 (15개 기능)
SQL 스크립트 목록 (writable/database/)
| 파일 |
용도 |
init_jongryangje_dev.sql |
DB/사용자 생성 |
login_tables.sql |
member, member_log, local_government, designated_shop |
member_approval_request_add.sql |
승인 요청 테이블 |
member_login_lock_add.sql |
로그인 실패 잠금 컬럼 |
menu_tables.sql |
menu_type, menu + admin/site 시드 |
menu_type_add_site.sql |
사이트 메뉴 타입 추가 |
menu_add_lg_idx.sql |
메뉴에 지자체 컬럼 추가 |
menu_site_seed_from_csv.sql |
사이트 네비게이션 시드 |
local_government_init_daegu.sql |
대구 8개 구군 지자체 |
code_master_init_daegu.sql |
기본코드 20종 + 세부코드 |
bag_price_tables.sql |
bag_price, bag_price_history |
packaging_unit_tables.sql |
packaging_unit, packaging_unit_history |
sales_agency_tables.sql |
sales_agency |
manager_tables.sql |
manager |
company_tables.sql |
company |
free_recipient_tables.sql |
free_recipient |
order_tables.sql |
bag_order, bag_order_item |
sales_tables.sql |
bag_sale, bag_receiving, bag_inventory, bag_issue, shop_order, shop_order_item |
seed_test_accounts.sql |
테스터 계정 4개 |
seed_realistic_data.sql |
실제형 시범 데이터 (대구 남구청 기준) |
fix_double_encoding.sql |
UTF-8 이중인코딩 수정 |