토이프로젝트/선착순 이벤트 쿠폰 시스템

2. 프로젝트 환경 설정

feel2 2024. 4. 6. 16:31
반응형

멀티모듈 구성

 

 

좀 더 효율적인 관리를 위해 멀티모듈로 구성해 볼 예정이다.

 

 

 

 

dependecy는 필요할 때 그때 추가하기로 한다.

create를 누르면 다음과 같이 프로젝트가 생성될 것이다.

 

 

제일 바깥의 디렉토리는 src 폴더가 필요없으니 삭제해주도록 하자.

 

루트 디렉토리(mycoupon)에서

우클릭 > new > Module… 선택하면 새로운 모듈을 만들 수 있다.

 

 

위의 타이틀에 New Module을 꼭 확인하자!!

 

 

아까와 동일하게 dependency를 나중에 넣어줄 예정이기에 그냥 바로 craete를 해주자.

총 3가지 모듈로 구성될 것이다.

  • mycoupon-api
  • mycoupon-consumer
  • mycoupon-core

 

 

보통 멀티모듈로 구성할 때는 공통으로 가져다 쓰는 모듈을 core로 두고, 나머지 모듈에서 build.gradle에서 implementation 하여 가져다 쓴다.

참고로 gradle에서는 dependency에 추가할 때 전이 의존성의 범위에 따라 implementation or api로 추가하여 해당 모듈에서 사용할 수 있다.

해당 내용에 대해서는 추후에 포스팅을 하여 자세히 정리할 예정이다.

그러면 각 모듈별로 build.gradle에 설정 내용을 넣어보자.

  • mycoupon

제일 바깥 루트 디렉토리의 build.gradle 설정 내용이다.

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.3'
    id 'io.spring.dependency-management' version '1.1.4'
}

bootJar.enabled = false

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

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}
subprojects {
    apply plugin: "java"
    apply plugin: "io.spring.dependency-management"
    apply plugin: "org.springframework.boot"

    repositories {
        mavenCentral()
    }

    // 관리하는 모듈에 공통 dependencies
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        compileOnly "org.projectlombok:lombok"
        annotationProcessor "org.projectlombok:lombok"
        implementation "org.springframework.boot:spring-boot-starter"
        annotationProcessor "jakarta.annotation:jakarta.annotation-api"
        annotationProcessor "jakarta.persistence:jakarta.persistence-api"
        testImplementation "org.springframework.boot:spring-boot-starter-test"

    }

}

tasks.named('test') {
    useJUnitPlatform()
}
  • mycoupon-api

디렉토리 mycoupon-api build.gradle 설정 내용이다.

dependencies {
    implementation project(":coupon-core")
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation "org.springframework.boot:spring-boot-starter-web"
}

tasks.named('test') {
    useJUnitPlatform()
}
  • mycoupon-consumer

디렉토리 mycoupon-consumer build.gradle 설정 내용이다.

dependencies {
    implementation project(":coupon-core")
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation "org.springframework.boot:spring-boot-starter-web"
}

tasks.named('test') {
    useJUnitPlatform()
}
  • mycoupon-core

디렉토리 mycoupon-core build.gradle 설정 내용이다.

bootJar { enabled = false }

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

}

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

이렇게 모든 모듈에 build.depedency를 설정해주었다.

여기서 마지막으로 제일 바깥 루트 디렉토리에서 모듈 전체의 빌드를 관리하기 위해 settings.gradle 에 다음과 같이 추가해줘야 한다.

rootProject.name = 'mycoupon'
include("mycoupon-core","mycoupon-api","mycoupon-consumer" )

 

이렇게 build.gradle 의 설정이 끝났으면 꼭 저기 Reload 버튼을 눌러 동기화를 한번 해주자.

원래는 각 모듈들이 바깥에 하나씩 더 있었을텐데 마우스 우클릭하여 unlinked 를 하면 안 쓰는 모듈들은 사라지니 참고하자.

 

이제 거의 다 왔다… 조금만 더 힘내자!!

 

스프링 부트로 넘어오면서 부트에서 디펜던시 관리를 편하게 해주기에 이정도에서 그치는 것이지 부트가 없었을 때는 설정만 일주일 걸렸다고 한다….(스프링 부트 최고!)

 

이제 코어 모듈(mycoupon-core)에서 @SpringBootApplication 달려있는 파일을 삭제해주자. 왜 삭제해주어야 할까?

@SpringBootApplication 의 구성 계층을 잠깐 살펴보면

@SpringBootApplication
----> @SpringBootConfiguration
    ---------->@Configuration

 

이런식으로 구성되어 있다.

 

스프링 공식 홈페이지에서 찾아보면 @SpringBootConfiguration한 애플리케이션에 1개만 존재해아 한다고 명시되어 있다.

스프링은 @SpringBootConfiguration 통해서 스프링 구성 정보를 가져온다고 한다. 구성을 자동으로 찾는 부분은 @SpringBootTest 를 통해서 확인이 가능하다고 한다.

 

대신 다음과 같은 파일을 추가해 주자.

package com.example.mycouponcore;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan
public class MyCouponCoreConfiguration {
}

 

 

 

@SpringBootApplication 을 없앴기 때문에 mycoupon-core 에서는 @SpringBootTest 가 제대로 동작을 안할 것이다. (위에서 언급했듯이 @SpringBootConfiguration 정보를 @SpringBootTest 가 참고하기 때문에)

mycoupon-core 모듈에서의 테스트를 위해 기존에 있던

 

MycouponCoreApplicationTests 파일을 삭제하고 TestConfig 파일을 추가해주자.

 

package com.example.mycouponcore;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;

@ActiveProfiles("test")
@TestPropertySource(properties = "spring.config.name=application-core")
@SpringBootTest(classes = MyCouponCoreConfiguration.class)
public class TestConfig {

}

 

 

 

 

 

진짜 마지막으로 각 module의 application.propertiesapplication.yml 로 변경해 주고, 설정 정보를 넣어주자.

  • mycoupon-api

디렉토리 mycoupon-api application-api.yml설정 내용이다.

//applicaiton-api.yml

spring:
  application:
    name: mycoupon-api
server:
  port: 8080
  • mycoupon-consumer

디렉토리 mycoupon-consumer application-consumer.yml 설정 내용이다.

//applicaiton-consumer.yml

spring:
  application:
    name: mycoupon-consumer
server:
  port: 8081
  • mycoupon-consumer

디렉토리 mycoupon-core application-core.yml 설정내용이다.

//application-core.yml

spring:
  config:
    activate:
      on-profile: local

더 자세한 설정은 다음 글에서 mysql과 연동하면서 같이 넣어주겠다.

 

 

 

 

 

 

한가지 더 빼먹은 것만 하고 이번 글은 마무리 하겠다.

각 모듈 안에 @SpringBootApplication 붙어 있는 서비스 진입점에 다음과 같은 설정을 추가해주자.

  • mycoupon-api

package com.example.mycouponapi;

import com.example.mycouponcore.MyCouponCoreConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@Import(MyCouponCoreConfiguration.class)
@SpringBootApplication
public class MycouponApiApplication {

    public static void main(String[] args) {
        System.setProperty("spring.config.name", "application-core, application-api");
        SpringApplication.run(MycouponApiApplication.class, args);
    }

}
  • mycoupon-consumer

package com.example.mycouponconsumer;

import com.example.mycouponcore.MyCouponCoreConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@Import(MyCouponCoreConfiguration.class)
@SpringBootApplication
public class MycouponConsumerApplication {

    public static void main(String[] args) {
        System.setProperty("spring.config.name", "application-core, application-consumer");
        SpringApplication.run(MycouponConsumerApplication.class, args);
    }

}

 

드디어 앱을 한번 기동해보면 다음과 같이 잘 기동되는 것을 알 수 있다!!!!!

 

참조

반응형