백엔드 개발자로 취업을 준비하며, 국비교육 이후 몇 개의 프로젝트들을 진행해 왔지만 "매력 있는 신입 개발자"가 되기에는 모자람을 느꼈다.
이에 백엔드 개발자 커뮤니티와 각종 커피챗에 참여해 현직 미들, 시니어급 개발자분과 이야기를 나눈 후 Spring Framework의 Security와 Oauth2, JPA, Batch 등 실무에서 기본적으로 다룰 기능들이 포함되며 Testcode와 api 명세 자동화에 대한 나만의 고민이 담긴 프로젝트를 취업 준비와 병행하기로 결정해서 진행 중이다.
이미 시작한 지는 조금 되었지만 기존 프로젝트들과 다르게 하나하나 많은 고민들이 담긴 프로젝트이기에 작은 고민까지 하나하나 기록에 남기고 싶어 블로그 연재를 시작한다.
우선, 아키텍처는 멀티모듈 아키텍처를 선정해서 진행 중이다. 다양한 기능을 공부하며 하나씩 추가해가고자 하였기 때문에 기존의 레이어드 아키텍처보다는 멀티모듈 프로젝트가 하나씩 모듈을 추가하고 테스트 하는데에 용이할 것 같아 멀티모듈 프로젝트로 선택했다.
프로젝트를 멀티모듈 프로젝트로 설정하기 위한 과정은 아래와 같다.
1. 일반 프로젝트를 생성한 뒤, 프로젝트 내부에 생성되는 기본 파일들을 삭제한 뒤 "모듈"을 생성했다.
1) 우선은 프로젝트에서 클라이언트와 서버 간의 통신을 담당할 api모듈과, 비즈니스 로직을 처리할 domain 모듈 두 가지로 나누었다.
추후 기능이 추가되면 별도의 모듈로 구분하는 게 맞을지, 아니면 기존의 모듈에 포함되는 게 맞을지 고민 후 정리할 예정이다.
2. settings.gradle에 root 프로젝트에 포함될 모듈을 명시해 줬다
//settings.gradle
rootProject.name = 'playground'
include(
"playground-domain",
"playground-api"
)
3. root 폴더의 build.gradle에 프로젝트 공통으로 받아올 dependency를 설정해 줬다.
//root build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}
allprojects { //root 폴더 포함해서 모든 프로젝트와 모듈에 반영할 내용
repositories {
mavenCentral()
}
}
subprojects {//root 폴더 재외 하위 모듈에 반영할 내용
apply {//상위에서 받아온 plugins를 하위에서는 알 수 없기 때문에 다시 한번 받아와줘야 함
plugin('java')
plugin('org.springframework.boot')
plugin('io.spring.dependency-management')
}
dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
}
4. 각각 모듈별로 필요한 dependency를 [모듈 폴더] - [build.gradle] 파일에 명시해 줬다
// playground-api build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation project(':playground-domain')
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
}
// playground-domain build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.0.4'
runtimeOnly 'com.mysql:mysql-connector-j'
}
5. 모듈마다 필요한 properties를 설정해 주되 [api 모듈 폴더] - [src] - [main] - [resources] - [application.yml] 파일을 두고, 나머지 yml 파일은 개별 모듈에 위치시킨 뒤 include 해주었다.
// [api 모듈 폴더] - [src] - [main] - [resources] - application.yml
server:
port: 8083
spring:
profiles:
active: local
include:
- domain
- SECRET
devtools:
livereload:
enabled: true # 서버 자동 시작
---
spring:
config:
activate:
on-profile: dev
---
spring:
config:
activate:
on-profile: beta
---
spring:
config:
activate:
on-profile: prod
// [domain 모듈 폴더] - [src] - [main] - [resources] - application-domain.yml
spring:
config:
activate:
on-profile: local
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
hibernate:
ddl-auto: create
show-sql: true
---
spring:
config:
activate:
on-profile: dev
---
spring:
config:
activate:
on-profile: beta
---
spring:
config:
activate:
on-profile: prod
이후에는 spring jpa 사용하며 Member의 일부 요소를 @Embeded로 처리하는 과정이나, 커스텀 예외처리를 전역으로 관리하는 과정, DTO를 사용해야 하는지, 사용해야 한다면 어떤 패턴을 가지고 갈 것인지, Mapstruct와 Builder 패턴에 대한 고민 등 프로젝트를 진행하며 만나는 고민들을 정리해보고자 한다.
'Project > playground(java-spring,멀티모듈)' 카테고리의 다른 글
[playground] @Embedable, Dto, Mapstruct, Entity setter 그 사이의 고민들 (0) | 2023.07.03 |
---|---|
[playground] Entity update, 어떤게 최선이지? (0) | 2023.07.03 |
야나의 코딩 일기장 :) #코딩블로그 #기술블로그 #코딩 #조금씩,꾸준히
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!