- 수행 시기: 2026년 7월
- 진행 상태: 진행 중. 주문·입금 확인·배송 상태 관리 흐름은 구현했고, 실제 배포와 카카오 로그인·푸시 알림 연동이 남아 있습니다.
- 소스 코드: https://github.com/anjinsung-debug/apple
활동 목적
농장에서 사과를 직접 파는 판매자가 주문을 받고 배송 상태를 관리하는 과정을 웹 앱에서 처리할 수 있게 하는 것이 목표입니다. 구매자는 주소와 품목만 고르면 주문할 수 있고, 판매자는 입금 확인 → 주문 접수 → 배송 시작 → 배송 완료 순서로 주문을 처리하며, 상태가 바뀔 때마다 구매자가 진행 상황을 확인할 수 있게 하려고 합니다.
또한 별도 앱을 설치하지 않아도 쓸 수 있도록, 구매자 앱과 판매자 앱을 PWA(Progressive Web App) 형태의 웹 앱으로 만드는 것도 목표입니다.
내 역할
개인 프로젝트로, 기획부터 구현까지 혼자 수행했습니다.
- 기획: 구매자·판매자의 주문 흐름과 화면 구성 정리
- 백엔드: Express API 서버, Prisma 데이터베이스 설계(ERD), 주문 상태 전이 규칙, 테스트 코드
- 프론트엔드: React 구매자 앱(
web-buyer)과 판매자 앱(web-seller), 두 앱의 공통 코드(shared)
수행 과정
- 주문 흐름 정의: 주문 전송 → 입금 확인 → 주문 접수 → 배송 시작 → 배송 완료의 상태와 알림 시점을 정했습니다.
- 데이터 설계: 사용자·배송지·상품·주문·주문 상태 기록을 나눈 ERD를 만들고 Prisma 스키마로 옮겼습니다.
- API 서버 구현: 요청이 routes → controllers → services → models 한 방향으로만 흐르도록 계층을 나눴습니다.
- 구매자·판매자 앱 구현: 두 앱을 별도로 만들고 API 호출·로그인·주문 상태 표시는
shared에서 함께 쓰게 했습니다. - 테스트 작성: 주문번호 생성과 상태 전이 규칙은 단위 테스트로, 로그인 API는 통합 테스트로 검증했습니다.
방법을 선택한 이유
- 상태 전이 규칙을 서버에서 강제: 허용된 전이 목록(
STATUS_FLOW)을 서버 상수로 두고 그 밖의 요청은 400으로 거부합니다. 화면에서만 막으면 잘못된 요청으로 배송 완료된 주문이 다시 접수 상태로 돌아갈 수 있기 때문입니다. - 주문에 배송지를 복사해 저장(스냅샷): 주문이 배송지를 참조만 하면, 구매자가 나중에 주소를 고치거나 지웠을 때 과거 배송 기록까지 바뀝니다. 주문 시점의 주소를 주문에 복사해 이력을 보존했습니다.
- 결제 대행 없이 계좌 이체 + 입금 확인: 판매자 계좌로 직접 입금받고, 판매자가 입금을 확인해야만 주문을 접수할 수 있게 했습니다.
- 구매자 앱과 판매자 앱 분리: 사용하는 사람과 화면이 완전히 다르므로 앱을 나누고, 역할 검사는 화면(라우트)과 API 양쪽에서 해서 판매자 화면을 구매자가 쓰지 못하게 했습니다.
- PWA로 구현: 앱 스토어 설치 없이 휴대폰 브라우저에서 바로 쓰게 하려고, 두 앱에 웹 앱 매니페스트
(
manifest.webmanifest,display: standalone)와 서비스 워커(sw.js)를 넣어 홈 화면에 추가하면 앱처럼 열리게 했습니다.
산출물과 결과
| 산출물 | 무엇을 구현·확인했는가 |
|---|---|
| README | 실행 방법, 전체 주문 흐름, 폴더 구조, ERD, API 목록 정리 |
| 구매자 앱 | 품목 선택 → 주소 입력 → 입금자명 입력 → 주문 전송, 주문 내역과 배송 진행 타임라인 |
| 판매자 앱 | 상태별 주문 탭, 입금 확인 → 주문 접수 → 배송 처리, 판매 품목·입금 계좌 관리 |
| API 서버 | 로그인·배송지·상품·주문·알림 API와 주문 상태 전이 규칙 |
| 테스트 코드 | 주문번호 형식, 상태 전이 허용·거부 규칙(단위), 로그인 API(통합) |
로컬에서 서버와 두 앱을 실행하면 개발용 로그인으로 구매자 주문부터 판매자 배송 완료까지 전체 흐름을 확인할 수 있습니다.
실행 화면
로컬에서 실행한 화면입니다. 주문자 이름·연락처·주소는 테스트용 값이며, 화면 아래쪽 문의 연락처는 가렸습니다.

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

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

그림 3. 구매자 주문 상세: 판매자가 상태를 바꿀 때마다 배송 진행 타임라인에 단계와 시각이 쌓인다.
배운 점
백엔드와 프론트엔드를 이어 주는 흐름에 대해 공부할 수 있는 기회가 되었습니다.
화면에서 주문 버튼을 누르면 shared/api/client.js가 로그인 토큰을 붙여 /api/orders로 요청을 보내고,
서버가 routes → controllers → services → models 순서로 처리한 결과가 다시 화면의 주문 상태로 표시되기까지의
과정을 직접 구현하면서 따라가 볼 수 있었습니다.
또 카카오 로그인 같은 외부 API로 사용자를 확인하고, 인증 미들웨어(auth middleware)로 로그인한 사용자만
API를 쓸 수 있게 하는 방법을 배웠습니다.
한계와 다음 개선 방향
| 한계 | 다음 개선 방향 |
|---|---|
| 푸시 알림이 연결되지 않아 화면이 15~20초마다 주문 상태를 다시 불러옵니다. | Firebase 푸시를 연동해 상태가 바뀔 때만 알림을 받게 합니다. |
README는 데이터베이스를 SQLite로 설명하지만 schema.prisma는 이미 PostgreSQL로 바뀌어 문서와 코드가 다릅니다. | 배포 설정을 정리하면서 README의 데이터베이스·실행 방법을 실제 코드에 맞게 고칩니다. |