• 수행 시기: 2026년 7월
  • 진행 상태: 진행 중. 주문·입금 확인·배송 상태 관리 흐름은 구현했고, 실제 배포와 카카오 로그인·푸시 알림 연동이 남아 있습니다.
  • 소스 코드: https://github.com/anjinsung-debug/apple

활동 목적

농장에서 사과를 직접 파는 판매자가 주문을 받고 배송 상태를 관리하는 과정을 웹 앱에서 처리할 수 있게 하는 것이 목표입니다. 구매자는 주소와 품목만 고르면 주문할 수 있고, 판매자는 입금 확인 → 주문 접수 → 배송 시작 → 배송 완료 순서로 주문을 처리하며, 상태가 바뀔 때마다 구매자가 진행 상황을 확인할 수 있게 하려고 합니다.

또한 별도 앱을 설치하지 않아도 쓸 수 있도록, 구매자 앱과 판매자 앱을 PWA(Progressive Web App) 형태의 웹 앱으로 만드는 것도 목표입니다.

내 역할

개인 프로젝트로, 기획부터 구현까지 혼자 수행했습니다.

  • 기획: 구매자·판매자의 주문 흐름과 화면 구성 정리
  • 백엔드: Express API 서버, Prisma 데이터베이스 설계(ERD), 주문 상태 전이 규칙, 테스트 코드
  • 프론트엔드: React 구매자 앱(web-buyer)과 판매자 앱(web-seller), 두 앱의 공통 코드(shared)

수행 과정

  1. 주문 흐름 정의: 주문 전송 → 입금 확인 → 주문 접수 → 배송 시작 → 배송 완료의 상태와 알림 시점을 정했습니다.
  2. 데이터 설계: 사용자·배송지·상품·주문·주문 상태 기록을 나눈 ERD를 만들고 Prisma 스키마로 옮겼습니다.
  3. API 서버 구현: 요청이 routes → controllers → services → models 한 방향으로만 흐르도록 계층을 나눴습니다.
  4. 구매자·판매자 앱 구현: 두 앱을 별도로 만들고 API 호출·로그인·주문 상태 표시는 shared에서 함께 쓰게 했습니다.
  5. 테스트 작성: 주문번호 생성과 상태 전이 규칙은 단위 테스트로, 로그인 API는 통합 테스트로 검증했습니다.

방법을 선택한 이유

  • 상태 전이 규칙을 서버에서 강제: 허용된 전이 목록(STATUS_FLOW)을 서버 상수로 두고 그 밖의 요청은 400으로 거부합니다. 화면에서만 막으면 잘못된 요청으로 배송 완료된 주문이 다시 접수 상태로 돌아갈 수 있기 때문입니다.
  • 주문에 배송지를 복사해 저장(스냅샷): 주문이 배송지를 참조만 하면, 구매자가 나중에 주소를 고치거나 지웠을 때 과거 배송 기록까지 바뀝니다. 주문 시점의 주소를 주문에 복사해 이력을 보존했습니다.
  • 결제 대행 없이 계좌 이체 + 입금 확인: 판매자 계좌로 직접 입금받고, 판매자가 입금을 확인해야만 주문을 접수할 수 있게 했습니다.
  • 구매자 앱과 판매자 앱 분리: 사용하는 사람과 화면이 완전히 다르므로 앱을 나누고, 역할 검사는 화면(라우트)과 API 양쪽에서 해서 판매자 화면을 구매자가 쓰지 못하게 했습니다.
  • PWA로 구현: 앱 스토어 설치 없이 휴대폰 브라우저에서 바로 쓰게 하려고, 두 앱에 웹 앱 매니페스트 (manifest.webmanifest, display: standalone)와 서비스 워커(sw.js)를 넣어 홈 화면에 추가하면 앱처럼 열리게 했습니다.

산출물과 결과

산출물무엇을 구현·확인했는가
README실행 방법, 전체 주문 흐름, 폴더 구조, ERD, API 목록 정리
구매자 앱품목 선택 → 주소 입력 → 입금자명 입력 → 주문 전송, 주문 내역과 배송 진행 타임라인
판매자 앱상태별 주문 탭, 입금 확인 → 주문 접수 → 배송 처리, 판매 품목·입금 계좌 관리
API 서버로그인·배송지·상품·주문·알림 API와 주문 상태 전이 규칙
테스트 코드주문번호 형식, 상태 전이 허용·거부 규칙(단위), 로그인 API(통합)

로컬에서 서버와 두 앱을 실행하면 개발용 로그인으로 구매자 주문부터 판매자 배송 완료까지 전체 흐름을 확인할 수 있습니다.

실행 화면

로컬에서 실행한 화면입니다. 주문자 이름·연락처·주소는 테스트용 값이며, 화면 아래쪽 문의 연락처는 가렸습니다.

사과랑 구매자 앱 첫 화면. '진안 고원, 농장부터 안방까지' 제목 아래 부사 사과 5kg 29,000원, 홍로 사과 3kg 21,000원, 못난이 사과 10kg 32,000원 상품 카드 3개와 재고, '주문하러 가기' 버튼이 있다.

그림 1. 구매자 앱 첫 화면: 판매 중인 사과의 가격·재고를 보여 주고 주문 화면으로 이어진다.

사과랑 판매자 앱의 들어온 주문 화면. 접수 대기·접수 완료·배송 중·배송 완료 탭 중 접수 대기 탭에 주문 AP261017-0001이 있고, 입금자명과 '입금 확인 전' 표시, 87,000원, '입금 확인'과 '거절' 버튼이 보인다.

그림 2. 판매자 앱 주문 관리: 입금을 확인해야 주문을 접수할 수 있도록 ‘입금 확인’ 버튼이 먼저 나온다.

사과랑 구매자 앱의 주문 상세 화면. 주문 AP261017-0001이 배송 완료 상태이고, 배송 진행에 접수 대기·주문 접수·배송 중·배송 완료 네 단계가 시각과 함께 표시되며, 아래에 배송지와 주문 품목 부사 사과 5kg 3개 합계 87,000원이 있다.

그림 3. 구매자 주문 상세: 판매자가 상태를 바꿀 때마다 배송 진행 타임라인에 단계와 시각이 쌓인다.

배운 점

백엔드와 프론트엔드를 이어 주는 흐름에 대해 공부할 수 있는 기회가 되었습니다. 화면에서 주문 버튼을 누르면 shared/api/client.js가 로그인 토큰을 붙여 /api/orders로 요청을 보내고, 서버가 routes → controllers → services → models 순서로 처리한 결과가 다시 화면의 주문 상태로 표시되기까지의 과정을 직접 구현하면서 따라가 볼 수 있었습니다. 또 카카오 로그인 같은 외부 API로 사용자를 확인하고, 인증 미들웨어(auth middleware)로 로그인한 사용자만 API를 쓸 수 있게 하는 방법을 배웠습니다.

한계와 다음 개선 방향

한계다음 개선 방향
푸시 알림이 연결되지 않아 화면이 15~20초마다 주문 상태를 다시 불러옵니다.Firebase 푸시를 연동해 상태가 바뀔 때만 알림을 받게 합니다.
README는 데이터베이스를 SQLite로 설명하지만 schema.prisma는 이미 PostgreSQL로 바뀌어 문서와 코드가 다릅니다.배포 설정을 정리하면서 README의 데이터베이스·실행 방법을 실제 코드에 맞게 고칩니다.