> For the complete documentation index, see [llms.txt](https://judy-valentine.gitbook.io/judy/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://judy-valentine.gitbook.io/judy/projects/delivery-fee-sharing-platform.md).

# Delivery Fee Sharing Platform

배달 주문 공유 및 배달비 분담 플랫폼

## 1. Overview

사용자 간 배달 주문을 공유하고 배달비를 분담할 수 있는 플랫폼을 설계하고 개발했습니다.

배달 주문 시 참여자를 모집하고, 모집 완료 후 자동으로 채팅방을 생성하여 메뉴 취합/정산까지 이어지는 배달비 공유 플랫폼을 개발했습니다.

***

## 2. Service Highlights

{% tabs %}
{% tab title="회원가입/로그인" %}
![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FQ7q0DAo0uQhsYuZymfSi%2F%E1%84%92%E1%85%AC%E1%84%8B%E1%85%AF%E1%86%AB%E1%84%80%E1%85%A1%E1%84%8B%E1%85%B5%E1%86%B8%E1%84%85%E1%85%A9%E1%84%80%E1%85%B3%E1%84%8B%E1%85%B5%E1%86%AB.gif?alt=media\&token=19c07157-ade8-4ddd-ab16-5675c41d335e)
{% endtab %}

{% tab title="게시글 생성" %}
![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FVjc6d0hIw3XPltuovOF8%2F%E1%84%80%E1%85%A6%E1%84%89%E1%85%B5%E1%84%80%E1%85%B3%E1%86%AF%20%E1%84%89%E1%85%A2%E1%86%BC%E1%84%89%E1%85%A5%E1%86%BC.gif?alt=media\&token=e3254595-3a87-4e0a-9441-ba4d8ab739cf)
{% endtab %}

{% tab title="메인 페이지" %}
![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FirU0AxLGqY5111qkNTb3%2F%E1%84%86%E1%85%A6%E1%84%8B%E1%85%B5%E1%86%AB%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5.gif?alt=media\&token=6be56d79-0765-4162-88ef-949c4d551c1f)
{% endtab %}

{% tab title="채팅 페이지 " %}
![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FFDOOYQxwRo4G6opfPwfq%2F%EC%B1%84%ED%8C%85.gif?alt=media\&token=d5e3c954-bb9c-4e1e-931b-cf77a9f86050)
{% endtab %}

{% tab title="마이 페이지" %}
![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FJZGk70FOORtd2nhEFjaT%2F%E1%84%86%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5.gif?alt=media\&token=1d592587-a8e6-4e5e-9453-a286c2206058)
{% endtab %}
{% endtabs %}

***

## 3. Architecture

<div align="left"><figure><img src="https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FlNKLefEziqSihLXZBUj4%2Fimage.png?alt=media&amp;token=55db5946-a690-4809-88b4-225d2a4ae3eb" alt=""><figcaption></figcaption></figure></div>

***

## 4. Tech Stack

| 영역          | 기술                        |
| ----------- | ------------------------- |
| Backend     | Spring Boot, Java         |
| ORM / Query | Spring Data JPA, QueryDSL |
| Database    | MySQL                     |
| API 문서화     | Swagger                   |
| 인프라         | Docker, AWS EC2           |
| CI/CD       | GitHub Actions            |
| 모니터링        | Prometheus, Grafana       |

***

## 5. Contributions

<table><thead><tr><th width="132.65234375">영역</th><th>기여 내용</th></tr></thead><tbody><tr><td>프로젝트 리드</td><td>2주 단위 스프린트 관리, 역할 분담, PR 규칙·Commit Convention·Code Style 문서화</td></tr><tr><td>모집 게시글 API</td><td>Spring Data JPA 기반 RESTful API 개발, QueryDSL 도입으로 동적 검색·페이징 구현</td></tr><tr><td>API 문서화</td><td>Swagger를 활용한 API 명세 자동화로 협업·테스트 효율 향상</td></tr><tr><td>DevOps</td><td>Docker 컨테이너 환경 구축, GitHub Actions CI/CD 파이프라인 작성, Prometheus/Grafana 모니터링</td></tr></tbody></table>

## 6. Implementation

### 6.1 주문 상태 관리

#### 주문 상태 머신 — 모집부터 정산까지

배달 인원 모집 과정을 3단계 상태 전이로 설계했습니다.

| 상태          | 트리거        | 설명               |
| ----------- | ---------- | ---------------- |
| **OPEN**    | 방 생성 시     | 참여자 모집 중         |
| **MATCHED** | 목표 인원 도달 시 | 모집 완료, 채팅방 자동 생성 |
| **CLOSED**  | 마감 시간 도달 시 | 주문 마감, 정산 진행     |

주문 생성 시 기본 상태를 `OPEN`으로 설정하고, 참여 인원이 목표에 도달하면 자동으로 `MATCHED`로 전환했습니다.

```java
Order order = Order.builder()
    .userId(userId)
    .restaurantId(request.getRestaurantId())
    .maxParticipants(request.getMaxParticipants())
    .status(OrderStatus.OPEN)
    .build();
```

**결과:** 상태 전이를 명확하게 분리하여 각 단계별 비즈니스 로직을 독립적으로 관리할 수 있는 구조를 확보했습니다.

***

### 6.2 동시성 제어 — 비관적 락 기반 참여 정합성 보장

여러 사용자가 동시에 참여할 경우 인원 초과 또는 중복 참여가 발생할 수 있었습니다. 낙관적 락은 충돌 시 재시도 비용이 크고 참여 요청이 짧은 시간에 집중되는 특성상 충돌 빈도가 높다고 판단하여, 비관적 락(Pessimistic Lock)을 선택했습니다.

```java
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT o FROM Order o WHERE o.id = :id")
Optional<Order> findByIdWithLock(@Param("id") Long id);
```

참여 처리 흐름에서 락 획득 → 중복 참여 검증 → 인원 증가 → 상태 전환 순서로 로직을 배치했습니다.

```java
@Transactional
public void joinOrder(Long orderId, Long userId) {
    Order order = orderRepository.findByIdWithLock(orderId)
        .orElseThrow(() -> new OrderNotFoundException(orderId));

    if (order.isFullyBooked()) throw new OrderFullException(orderId);
    if (participantRepository.existsByOrderIdAndUserId(orderId, userId))
        throw new DuplicateParticipantException(orderId, userId);

    participantRepository.save(Participant.of(order, userId));
    order.increaseParticipantCount();

    if (order.isTargetReached()) order.updateStatus(OrderStatus.MATCHED);
}
```

**결과:** 동시 참여 상황에서도 인원 초과·중복 참여 없이 데이터 정합성을 유지했습니다.

<br>

***

### 6.3. QueryDSL 동적 검색 — 모집 게시글 필터링 & 페이징

모집 게시글 목록 조회 시 식당명, 지역, 상태 등 다양한 조건을 조합해 검색해야 했습니다. Spring Data JPA의 쿼리 메서드만으로는 조건 조합마다 메서드를 생성해야 하므로, 동적 쿼리 작성이 가능한 QueryDSL을 도입했습니다.

**결과:** 검색 조건이 추가되더라도 쿼리 메서드를 신규 작성하지 않고 `BooleanExpression` 조합만으로 대응할 수 있는 구조를 확보했습니다.

***

### 6.4 CI/CD & 모니터링 — Docker + GitHub Actions + Prometheus/Grafana

수동 배포로 인한 휴먼 에러와 서버 상태 파악 지연 문제를 해결하기 위해 자동화 파이프라인과 모니터링 환경을 구축했습니다.

**CI/CD 파이프라인:**

1. **Build** — Gradle 빌드 및 Docker 이미지 생성
2. **Push** — Docker Registry에 이미지 푸시
3. **Deploy** — AWS EC2에 컨테이너 배포

**모니터링:**

Prometheus로 JVM 메트릭, HTTP 요청 지표를 수집하고 Grafana 대시보드로 시각화했습니다. EC2 인스턴스의 CPU·메모리 사용량과 API 응답 시간을 실시간으로 확인하여 장애 발생 시 빠르게 대응할 수 있는 환경을 마련했습니다.

***

## 7. Result

* 비관적 락 기반 동시성 제어로 참여 로직의 데이터 정합성 확보
* QueryDSL 도입으로 검색 조건 추가 시 코드 변경 최소화
* GitHub Actions CI/CD 파이프라인 구축으로 수동 배포 제거
* Prometheus/Grafana 모니터링으로 서버 상태 실시간 파악 체계 확립
* Swagger API 문서 자동화로 프론트엔드 팀과의 협업 효율 향상

***

## 8. Lessons Learned

**개선할 점**

* 실시간 참여 상태 공유 미흡 — 현재 클라이언트가 주기적으로 상태를 조회하는 폴링 방식으로, WebSocket을 적용하면 참여 상태를 즉시 반영할 수 있음
* 락 범위 최적화 필요 — 비관적 락이 주문 엔티티 전체에 걸려 있어 참여자가 많아질수록 대기 시간이 증가하므로, 락 범위를 좁히거나 낙관적 락 전환을 검토해야 함
* 비용 분담 로직 미완성 — 참여자 간 배달비 분담 계산은 설계 수준에 머물러 있으며, 결제 연동까지 이어지는 구현이 필요함

<details>

<summary>PPT</summary>

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2Frqkd06qcOdV0ZVN8yq3M%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B31.jpeg?alt=media\&token=33b6b16e-a849-4c33-92dd-294f22fa8dc8)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2F9NDkKr3kJt7IXRaubAC5%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B32.jpeg?alt=media\&token=634320e1-d86e-4b05-a00a-1ae348f24c0a)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FenrJGIO3RggCIB20kK80%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B33.jpeg?alt=media\&token=8baad4b4-1844-47d0-ac05-9cd34b807947)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FqzKCZKjbOCKtdEtNtXWu%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B34.jpeg?alt=media\&token=935ba524-fa2d-491d-b782-2ecf7b1a3787)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FxKf1YkiPvJemj4AzeQgx%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B35.jpeg?alt=media\&token=1e517d1b-7db5-4e35-b74f-3faa85ee3580)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FCUQK3KdM42QYDFY798B7%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B36.jpeg?alt=media\&token=282bd5d7-fbd2-4f38-8ba5-ec309378a454)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FptNOqXbMCOanmXuBLtLz%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B37.jpeg?alt=media\&token=e6164f61-741e-4dad-a29b-976dd6995dfd)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2Fjs9U97z9sXM8Ub0OjqdF%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B38.jpeg?alt=media\&token=d587fe11-b964-4cf6-ac86-64e5f6609f33)

### DEMO

#### GIF ver.

#### Capture ver.

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2Fdo9G0DabixQFhF9bf4QI%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B314.jpeg?alt=media\&token=c92cdce4-a93d-44f9-abdb-2ac0e41b26e4)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2F2J5qNiXhcfQavE1ksYvo%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B315.jpeg?alt=media\&token=dead4e67-3acf-4741-93c8-5f06d88b2ea5)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FZlTs6ZDIn1GF60sHX657%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B316.jpeg?alt=media\&token=2b5b56e7-0ef3-4cc1-a8d0-db53db3ca6ae)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FjaZmco4wnTT3wkVmW89W%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B317.jpeg?alt=media\&token=7ddbfca3-57db-45c5-a834-357bd88990fb)

![Route 53 추](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FjjDfTPoriKfojxUKQStX%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B318.jpeg?alt=media\&token=0dca4eab-94df-4d20-a2e7-c7e12c9fdf36)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FQgw93CvaHaF8t08uYEuG%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B319.jpeg?alt=media\&token=d73c7073-5b60-47e5-9af4-22059e46a2c1)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FVUIuWvYVYHwoa6F6jSA6%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B320.jpeg?alt=media\&token=5f2805e4-94b8-45fc-b281-7e52c2b031d1)

![](https://2669959621-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxncaDDrGpdjhVy86HbwM%2Fuploads%2FOIOHRfLrv0SqsRjJA3bO%2F%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B322.jpeg?alt=media\&token=e529c446-559d-4efe-8940-d97665fd8001)

{% embed url="<https://github.com/team-e-techeer>" %}

</details>
