
https://soso-hyeon.tistory.com/83
멀티 모듈 프로젝트에서 하나의 레포지토리 안에 여러 모듈을 두고, 각 모듈에 대해 별도의 실행 파일(JAR)을 만들 수 있다.
이를 통해 각 모듈을 독립적으로 배포하거나 도커 컨테이너로 나눠서 배포하는 방식으로 운영할 수 있다.
각각의 모듈(cs25-common, cs25-services, cs25-batches)은 별도의 JAR 파일로 빌드

이렇게 돼서 배치와 서비스를 분리하는것이 주 목적이다.
배치는 하루에 한번~두번 정도만 돌아가고, 돌아갈 때 리소스를 많이먹는다
서비스는 24시간 돌아가면서 ai 벡터 db인 크로마를 쓰기 때문에 기본 리소스가있다.
그래서 배치돌아가는 성능에 다른 상관없는 서비스들이 꽁으로 돌아가지않게 그냥 분리해버리려고한다.
저렇게 나누게되면 cs25-services, cs25-batches 는 서로서로가 내부에 대해서 알 필요가없음 있는지도모르게됨 (의도!!)
docker-compse.yml 최종형
배치배포하는 쪽에서는 common + batches 이미지 pull받고
써비스 하는 쪽에서는 common + services 이미지 pull받아서 쓰면되게끔version: '3' services: cs25-common: image: cs25-common:latest build: context: ./cs25-common ports: - "8081:8080" cs25-services: image: cs25-services:latest build: context: ./cs25-services ports: - "8082:8080" depends_on: - cs25-common cs25-batches: image: cs25-batches:latest build: context: ./cs25-batches ports: - "8083:8080" depends_on: - cs25-common

공통 적용에 프로메테우스 추가
global같은 경우는 batch까지 적용되는 것만 남겨서 common 형식으로 빠지고,
jwt나 로그인 인증 필터 이런것들은 도메인→서비스 패키지 이름 바꿔서 안으로 넣으면될듯
cs25-common: 공통 모듈, 다른 서비스와 배치에서 공유되는 코드 (이미지 생성x)cs25-service: 서비스 모듈 (비즈니스 로직)cs25-batch: 배치 모듈 (일괄 처리 작업)global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: [ 'prometheus:9090' ]
- job_name: 'cs25-service'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: [ 'cs25-service:8080' ]
- job_name: 'cs25-batch'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: [ 'cs25-batch:8080' ]
구조는 아래처럼 설정해야한다
├── cs25-common # 공통 모듈 (예: 유틸리티, 예외 처리 등)
│ └── build.gradle # 공통 모듈의 Gradle 설정
├── cs25-services # 서비스 모듈 (예: 비즈니스 로직)
│ └── build.gradle # 서비스 모듈의 Gradle 설정
├── cs25-batches # 배치 모듈 (예: 일괄 처리 작업)
│ └── build.gradle # 배치 모듈의 Gradle 설정
└── build.gradle # 상위 프로젝트의 Gradle 설정 (모든 모듈)

루트에 있던 src를 각 모듈에 맞는위치로 나눠서 넣어줬따
그리고 src 삭~ 제~ 속이 시원하다 ^^
root파일의 setting.gradle


큰 설정은 필요xxx
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.0'
id 'io.spring.dependency-management' version '1.1.7'
}
ext {
set('queryDslVersion', "5.0.0")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'jakarta.mail:jakarta.mail-api:2.1.0'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
//queryDSL
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta"
annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//Monitoring
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
settings.gradle 꼭 삭제하게!!!!

plugins {
id 'java'
id 'org.springframework.boot' version '3.5.0'
id 'io.spring.dependency-management' version '1.1.7'
}
ext {
set('queryDslVersion', "5.0.0")
}
dependencies {
implementation project(':cs25-common')
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
...
}
bootJar {
enabled = true
}
jar {
enabled = false
}
bootJar, jar 파일 설정값을 추가해줘야하고
implementation project(':cs25-common') 의존 받아야할 대상 추가도해줘야함
settings.gradle 꼭 삭제하게!!!!
주입 받아야할 대상 (service, batch 모듈에서 Config 파일 추가가 필요함!!)
@Configuration// 공통 모듈의 entity, repository, component를 인식하기 위한 스캔 설정
@EntityScan(basePackages = "com.example.cs25common.global")
@EnableJpaRepositories(basePackages = "com.example.cs25common.global")
@ComponentScan(basePackages = {
"com.example.cs25batch", // 자기 자신
"com.example.cs25common" // 공통 모듈
})
public class JPAConfig {
}
이런식으로 추가 해준다.
어디의 엔티티/레포지토리 받을것인지, 컴포넌트 스캔범위를 어디로 할것인지 설정해줘야함
참고!!!
@Configuration// 공통 모듈의 entity, repository, component를 인식하기 위한 스캔 설정 @EntityScan(basePackages = { "com.example.cs25common.global", "com.example.cs25service.domain" }) @EnableJpaRepositories(basePackages = { "com.example.cs25common.global", "com.example.cs25service.domain" }) @ComponentScan(basePackages = { "com.example.cs25service", // 자기 자신 "com.example.cs25common" // 공통 모듈 }) public class JPAConfig { // 추가적인 JPA 설정이 필요하면 여기에 추가 }이렇게 여러개 봐야하는 경우도 쓸 수있음

모듈 안에다가 적어줘야한다!!
application.properties도 모듈마다 작성해줘야함 !!
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: [ 'prometheus:9090' ]
- job_name: 'cs25-service'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: [ 'cs25-service:8080' ]
- job_name: 'cs25-batch'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: [ 'cs25-batch:8080' ]
츄츄가 츄츄가 츄가츄가
'/actuator/prometheus' 여기서 같이볼 수 있게 path 설정도 같이해준다
services:
cs25-service:
container_name: cs25-service
build:
context: .
dockerfile: cs25-service/Dockerfile
depends_on:
- mysql
- redis
- chroma
ports:
- "8080:8080"
networks:
- monitoring
cs25-batch:
container_name: cs25-batch
build:
context: .
dockerfile: cs25-batch/Dockerfile
depends_on:
- mysql
- redis
ports:
- "8081:8080"
networks:
- monitoring
mysql:
container_name: mysql
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: cs25
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
networks:
- monitoring
redis:
container_name: redis
image: redis:7.2
ports:
- "6379:6379"
volumes:
- redis-data:/data
networks:
- monitoring
chroma:
container_name: chroma
image: ghcr.io/chroma-core/chroma
ports:
- "8000:8000"
restart: unless-stopped
volumes:
- chroma-data:/data
networks:
- monitoring
jenkins:
container_name: jenkins
image: jenkins/jenkins:lts
user: root
ports:
- "9000:8080"
- "50000:50000"
volumes:
- jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
restart: always
networks:
- monitoring
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./prometheus:/etc/prometheus
ports:
- "9090:9090"
networks:
- monitoring
grafana:
image: grafana/grafana
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- prometheus
networks:
- monitoring
volumes:
chroma-data:
grafana-data:
jenkins_home:
mysql-data:
redis-data:
networks:
monitoring:
상당히 길어졌다..

배치는 이제 aws 람다로 올라가니깐 나중에 받아올 이미지 골라서 받아오면 되겠지??? 배포는 나중에또 팀원들이랑 상의해봐야한다
그리고 튜터님과 1차 MVP 시연을 준비하면서 팀원들과 배포 형식을 상의해봤다.


ㅍ프론트는 정적리소스가 많다보니 클라우드 프론트 기능써서 보내버리고 이렇게 멀티모듈로 프로젝트를 나눠서
배치는 람다, 백엔드는 EC2로 올라갈 것 같다.
서브넷도 그림은 퍼블릭에 EC2두개 올라간걸로 보이는데 전부 PRIVATE으로 돌릴 것 같음
튜터님이 문제없어보인다고 도장도찍어주심 쾅쾅
하.. 이제 팀원들이 수정하던 코드들을 모아서 이쪽에 얹어줘야한다....
이게 정말 고민이 많다.
common 쪽에서 거의 디비도 같이 저장하고있어서 모듈을 하나더 나눠서 db로 할 것인지 !!! 쓰으읍
츄츄가 츄츄가 츄가츄가
할 것들이 정말 많네요. 오늘도 잘 보고 갑니다. 🫡