Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
33bd112
feat: init-setting
orkrj Jan 26, 2025
5c06a85
feat: setup for multi-module
orkrj Jan 26, 2025
5edf060
feat: add docker-file and compose.yml
orkrj Jan 26, 2025
31d2303
feat: add entities in domain-module
orkrj Jan 26, 2025
219a273
feat: configure datasource profiles for docker and local environments
orkrj Jan 26, 2025
35b0d86
feat: insert dummy-data
orkrj Jan 26, 2025
e57ffa3
feat: implement querydsl-based search logic for movie
orkrj Jan 27, 2025
62edbd7
feat: add search and transformation logics for filtering currently pl…
orkrj Jan 27, 2025
15cac0f
feat: set controller to search movies-playing
orkrj Jan 27, 2025
d8c6820
chore: update dummy data and configs
orkrj Jan 27, 2025
5078ece
chore: setup for connecting with redis
orkrj Jan 27, 2025
b6dffa5
feat: add logics to cache searched movie details
orkrj Jan 27, 2025
53f9de1
feat: add secondary-index in movie
orkrj Jan 27, 2025
e6ceb72
feat: add member entity and logics, dummy-data for reservation
orkrj Jan 29, 2025
0cfafce
refactor: modify seat logics to find the seat by seatName and scheduleId
orkrj Jan 29, 2025
c611f9e
feat: add logics to find the schedule for reservation
orkrj Jan 29, 2025
0f6935f
chore: move files for clarify
orkrj Jan 29, 2025
2b64805
feat: implement reservation api with test
orkrj Jan 29, 2025
9519af2
chore: update dummy-data generator and entity field
orkrj Jan 30, 2025
e8ed6e5
feat: ✅pessimistic lock 구현
orkrj Jan 30, 2025
db7ba07
feat: add test logic for pessimistic-lock
orkrj Jan 30, 2025
d256a83
feat: ✅optimistic lock 구현 및 테스트
orkrj Jan 30, 2025
f6ce71f
feat: ✅distributed lock 구현 및 테스트
orkrj Jan 31, 2025
d89b94c
chore: update minor changes
orkrj Jan 31, 2025
ea78d73
chore: add k6 test script and result
orkrj Jan 31, 2025
8a90778
chore: update erd image and remove unused test dir in modules
orkrj Jan 31, 2025
4db4fea
Create README.md
orkrj Jan 31, 2025
a9ec5bf
Merge pull request #1 from orkrj/3rdweek
orkrj Jan 31, 2025
27a01ba
Merge remote-tracking branch 'old-origin/dev'
orkrj Jan 31, 2025
157f449
chore: rename root project and erd file
orkrj Jan 31, 2025
75ff8dc
chore: update project settings to match root project name
orkrj Jan 31, 2025
cdf5287
feat: add logic to init writer and updater in base-entity
orkrj Feb 1, 2025
53206cb
refactor: move business logic to domain module following DDD
orkrj Feb 1, 2025
3eb2829
refactor: rename variables and extract constants following DDD
orkrj Feb 1, 2025
a0d241c
refactor: improve reservation service orchestration
orkrj Feb 1, 2025
9e2ea0c
feat: ensure lock is released only by the owning thread
orkrj Feb 1, 2025
5fedce0
feat: apply functional distributed lock and perform load test
orkrj Feb 1, 2025
de924af
Merge pull request #1 from orkrj/refactor-3rdweek
orkrj Feb 1, 2025
eeed9f7
feat: implement rate-limiting for movie queries using redis
orkrj Feb 3, 2025
f1254da
feat: add rate-limiting test
orkrj Feb 3, 2025
5044d86
feat: apply aop-based distributed lock in reserveSeat instead of lambda
orkrj Feb 3, 2025
ad5280b
feat: add rate-limiting to reserveSeat
orkrj Feb 3, 2025
8bf68ca
chore: change blocked time ttl unit from nanoseconds to seconds
orkrj Feb 3, 2025
bb3f22f
feat: add dependency and config for jacoco
orkrj Feb 3, 2025
33f9609
chore: adjust leaseTime based on test results
orkrj Feb 3, 2025
d6fcfcc
chore: update README.md
orkrj Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
157 changes: 157 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/

### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# AWS User-specific
.idea/**/aws.xml

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# SonarLint plugin
.idea/sonarlint/


# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

### Intellij+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.

.idea/*

!.idea/codeStyles
!.idea/runConfigurations

### Gradle ###
.gradle
**/build/
!src/**/build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties

# Cache of project
.gradletasknamecache

# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath

### Gradle Patch ###
# Java heap dump
*.hprof


### volume ###
database
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM openjdk:21-jdk

WORKDIR /app

COPY api/build/libs/*SNAPSHOT.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "/app/app.jar"]
67 changes: 64 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,64 @@
## [본 과정] 이커머스 핵심 프로세스 구현
[단기 스킬업 Redis 교육 과정](https://hh-skillup.oopy.io/) 을 통해 상품 조회 및 주문 과정을 구현하며 현업에서 발생하는 문제를 Redis의 핵심 기술을 통해 해결합니다.
> Indexing, Caching을 통한 성능 개선 / 단계별 락 구현을 통한 동시성 이슈 해결 (낙관적/비관적 락, 분산락 등)
# project-movie
<br>


## 1. API 모듈
- HTTP 요청 처리
- REST API 엔드포인트 제공
- Spring Boot 애플리케이션 시작점

---

## 2. Application 모듈
- 비즈니스 서비스 구현
- 포트(Port) 인터페이스 정의
- 도메인 객체와 외부 인터페이스 간 데이터 변환 및 조율

---

## 3. Domain 모듈
- 엔티티 정의
- 레포지토리 정의
- 엔티티 객체 관계 설정

---

## 4. Infrastructure 모듈
- 더미 데이터 생성
- JPA 레포지토리 인터페이스 정의 및 구현
- 데이터베이스 설정
- 외부 시스템 통합

---

## 모듈 구조 요약

```plaintext
project-movie/
├── api/
├── application/
├── domain/
└── infrastructure/
```
---

## ERD
[movie_app-erd](https://github.com/user-attachments/assets/aa4d568c-948c-4334-bae1-d29ca2602efa)

---

## 분산 락 성능 테스트(AOP)
[reserveAPI_distributed_lock_test-AOP](https://github.com/orkrj/project-movie/blob/main/reserve-distributed-AOP.png)

## 분산 락 성능 테스트(Lamda)
[reserveAPI_distributed_lock_test-Functional](https://github.com/orkrj/project-movie/blob/main/reserve-distributed-Functional.png)

## 결정
#### 1. 분산 락 구현 방식
- vus 100, duration 600s 환경에서 테스트한 결과, AOP 기반 분산 락이 MAX 응답 시간은 크지만 avg, P(90), P(95), TPS에서 더 우수한 성능을 보임.
- 따라서, 함수형 구현 대신 AOP 기반으로 분산 락을 적용하기로 결정.

#### 2. waitTime, leaseTime
- waitTime = 1s : 영화 예매의 경우 대체 선택지가 많아, 대기 시간을 짧게 설정하여 사용자 경험(UX)을 개선함. 불필요한 서버 부하 또한 예방 가능한 결정임.
- leaseTime = 3s : 분산 락 테스트 결과, 응답 시간 P(95) 68ms, 최대 응답 시간 1015ms 가 측정되어 최대 응답의 3배를 지정하여 안정성을 확보하려 함.
---
3 changes: 3 additions & 0 deletions api/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
37 changes: 37 additions & 0 deletions api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/
15 changes: 15 additions & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
bootJar {
enabled = true
mainClass = 'hanghae.api.ApiApplication'
}

dependencies {
implementation project(':domain')
implementation project(':application')
implementation project(':infrastructure')

implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}
Binary file added api/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
7 changes: 7 additions & 0 deletions api/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading