Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### VS Code ###
.vscode/
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
## [본 과정] 이커머스 핵심 프로세스 구현
[단기 스킬업 Redis 교육 과정](https://hh-skillup.oopy.io/) 을 통해 상품 조회 및 주문 과정을 구현하며 현업에서 발생하는 문제를 Redis의 핵심 기술을 통해 해결합니다.
> Indexing, Caching을 통한 성능 개선 / 단계별 락 구현을 통한 동시성 이슈 해결 (낙관적/비관적 락, 분산락 등)
# JM 항해 시네마소개

## 프로젝트 소개
- 해당과정은 [단기 스킬업 Redis 교육 과정](https://hh-skillup.oopy.io/) 을 하면서 진행한 프로젝트이다.
- 영화목록을 조회할수 있는 서비스 프로젝트
- 향후 진행하면서 README파일은 계속 업데이트

## API
### Get
|#|API|내용|비고|
|---|------|---|---|
|1|/api/movies|서버가 가지고 있는 영화목록 리턴| |
|1|/api/movies/title?title=|특정 title의 영화 정보를 리턴| |
|1|/api/movies/genre?genre=|특정 genre의 영화목록을 리턴| |

### Post
|#|API|내용|비고|
|---|------|---|---|
|1|/api/movies|서버에 영화목록을 입력| |

## Architecture
- 해당과제는 Controller, Service, domain으로 나누어져있는 Layered Architecture를 기본으로한다.
- 구현을 진행하면서, 필요시 Layered Architecture를 기반으로 Module을 분리예정
<img width="375" alt="image" src="https://github.com/user-attachments/assets/98b55ce4-fea4-46ef-9525-fe0485645097" />

## TABLE
- 현재 DB에 저장되는 Data는 아래와 같다.
- 구현 진행하면서, 필요시 변경예정
<img width="118" alt="image" src="https://github.com/user-attachments/assets/70e62ad9-923f-4fee-96ac-3e145d91982f" />

## TODO
- 메인페이지 추가 구현
- /api/movie, /api/movie/title, /api/movie/genre API 합치기
3 changes: 3 additions & 0 deletions app/.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
40 changes: 40 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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/

### etc ###
volumes/
127 changes: 127 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
id "jacoco"
}

group = 'com.movie'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.redisson:redisson-spring-boot-starter:3.43.0'
implementation 'com.google.guava:guava:33.4.0-jre'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-docker-compose'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
useJUnitPlatform()
finalizedBy 'jacocoTestReport'
}

// jacoco 정보
jacoco {
toolVersion = "0.8.11"
layout.buildDirectory.dir("reports/jacoco")
}

// jacoco Report 생성
jacocoTestReport {
dependsOn test // test 종속성 추가

reports {
xml.required = true
csv.required = false
html.required = true
}

def QDomainList = []
for (qPattern in '**/QA'..'**/QZ') { // QClass 대응
QDomainList.add(qPattern + '*')
}

afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/dto/**',
'**/event/**',
'**/*InitData*',
'**/*Application*',
'**/exception/**',
'**/service/alarm/**',
'**/aop/**',
'**/config/**',
'**/MemberRole*'
] + QDomainList)
}))
}

finalizedBy 'jacocoTestCoverageVerification' // jacocoTestReport 태스크가 끝난 후 실행
}

// jacoco Test 유효성 확인
jacocoTestCoverageVerification {
def QDomainList = []
for (qPattern in '*.QA'..'*.QZ') { // QClass 대응
QDomainList.add(qPattern + '*')
}

violationRules {
rule {
enabled = true // 규칙 활성화 여부
element = 'CLASS' // 커버리지를 체크할 단위 설정

// 코드 커버리지를 측정할 때 사용되는 지표
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.30
}

limit {
counter = 'BRANCH'
value = 'COVEREDRATIO'
minimum = 0.30
}

excludes = [
'**.dto.**',
'**.event.**',
'**.*InitData*',
'**.*Application*',
'**.exception.**',
'**.service.alarm.**',
'**.aop.**',
'**.config.**',
'**.MemberRole*'
] + QDomainList
}
}
}
24 changes: 24 additions & 0 deletions app/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
services:
mysql:
image: 'mysql:latest'
environment:
MYSQL_DATABASE: redis1st
MYSQL_PASSWORD: PASSWORD
MYSQL_ROOT_PASSWORD: PASSWORD
MYSQL_USER: redis1st
volumes:
- ./volumes/db/mysql/data:/var/lib/mysql
- ./volumes/db/mysql/init:/docker-entrypoint-initdb.d
ports:
- '3306:3306'
redis:
image: redis:latest
labels:
- "name=redis"
- "mode=standalone"
command: redis-server /usr/local/conf/redis.conf
volumes:
- ./volumes/db/redis/data:/data
- ./volumes/db/redis/conf/redis.conf:/usr/local/conf/redis.conf
ports:
- '6379:6379'
Binary file added app/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
7 changes: 7 additions & 0 deletions app/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