본문 바로가기
Study/Spring

[Spring] 멀티 모듈 프로젝트 만들기

by 오늘만 사는 여자 2023. 3. 10.
728x90
반응형

❗️ 멀티 모듈 프로젝트가 필요한 이유

예를 들어서 회원 프로그램을 개발한다고 했을 때 여러 개의 서버가 필요하다.
① batch 서버
② API 서버
등등

하지만 해당 서버들을 단일 프로젝트로 만들게 되면 다음과 같은 문제가 생긴다.

첫번째, 공통적으로 처리해야하는 코드의 처리
: 아예 분리되어 있는 프로젝트이다 보니 공통되는 코드들은 각 프로젝트에 복붙해서 사용할 수 밖에 없고, 한 파일의 코드가 수정되는 경우 다른 프로젝트의 코드도 수정해줘야 한다.

두번째, 접근성 문제
: 프로젝트 수에 따라 IDE 를 실행시켜야 하고 ,, 프로젝트 수가 많아지면 많아 질 수록 개발하는데 어려움이 동반 될 수 밖에 없다.

이런 문제를 해결하기 위해선 멀티 모듈 프로젝트를 사용하면 된다.

❓ 멀티 모듈 프로젝트의 구성


위에서 예시를 들었던 회원 프로그램을 예시로 들자면 위의 그림과 같다.
batch-server module 엔 배치 서버 관련 코드
api-server module 엔 API 관련 코드들이 있다.

두 모듈에서 공통되는 코드는 commons 모듈에 있고 batch-server module 과 api-server module 에서 의존성을 설정해서 사용하는 방식으로 멀티 모듈 프로젝트를 구성할 수 있다.

🏃‍♂️ 멀티 모듈 프로젝트 시작하기

1. 프로젝트 생성


예제에서는 Gradle, 자바 버전은 1.8 로 프로젝트를 생성해주겠다.


프로젝트 생성을 하게 되면 위와 같은 구조가 되는데 우리는 하나의 프로젝트에 여러개의 모듈이 위치해 있고 공통 코드 같은 경우도 따로 모듈에 들어갈 거기 때문에 src 폴더는 삭제해준다.

➡️ 루트 프로젝트는 하위 모듈을 관리하는 역할 만 하 때문에 src 폴더를 삭제해도 괜찮다.

2. 모듈 추가

가장 상위 프로젝트에서 마우스 오른쪽 클릭을 하고, New > Module 을 선택 후, 모듈 이름을 입력해서 모듈을 만들어준다.

해당 프로젝트에서는 velog-api-server, velog-batch-server, velog-core 로 총 3개를 만들어줬다.

velog-api-server : API 관련 모듈
velog-batch-server : Batch 성 관련 모듈
velog-core : velog-api-server, velog-batch-server 에서 사용하는 공통 모듈

setting.gradle 에 새로 만들어진 모듈에 대해서 코드를 추가해줘야 하는데, New > Module 을 통해서 모듈을 만든 경우에는 인텔리제이가 자동으로 코드를 넣어준다.

만일 코드가 없는 경우에는 include #{모듈명} 으로 추가해주자.

3. 프로젝트 세팅

build.gradle 설정

buildscript {
    ext {
        springBootVersion = '2.6.2'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
        classpath "io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE"
    }
}

// 하위 모든 프로젝트 공통 세팅
subprojects {
    apply plugin: 'java'
    apply plugin: 'idea'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    group 'org.example'
    version '1.0-SNAPSHOT'

    sourceCompatibility = '1.8'
    targetCompatibility = '1.8'
    compileJava.options.encoding = 'UTF-8'

    repositories {
        mavenCentral()
    }

    // 하위 모듈에서 공통으로 사용하는 세팅 추가
    dependencies {
        compileOnly 'org.projectlombok:lombok'

        annotationProcessor 'org.projectlombok:lombok'
        annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
        testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
    }

    test {
        useJUnitPlatform()
    }
}

project(':velog-core') {
    // 공통 코드

    bootJar { enabled = false } // core 은 bootJar 로 패키징 할 필요 없음
    jar { enabled = true }

    dependencies {
    }
}

project(':velog-api-server') {
    bootJar { enabled = true }
    jar { enabled = false }

    dependencies {
        compile project(':velog-core') // 컴파일 시 velog-core project 로딩
        implementation 'org.springframework.boot:spring-boot-starter-web'
    }
}

project(':velog-batch-server') {
    bootJar { enabled = true }
    jar { enabled = false }

    dependencies {
        compile project(':velog-core') // 컴파일 시 velog-core project 로딩
    }
}

subprojects
: setting.gradle 에 include 된 프로젝트를 전부 관리한다.
: rootproject 까지 적용시키고 싶은 경우 allprojects 로 등록하면 된다.

project
: 하위 프로젝트의 의존성 관리한다.
: velog-core 의 경우 공통 모듈이기 때문에 velog-api-server, velog-batch-server 에 의존성을 주입해준다.

위와 같이 설정을 해준다음 velog-api-server 가 velog-core 에 대한 의존성을 가지고 있는지 확인하려면 Gradle > Dependencies > compileClasspath 를 확인해주면 된다.

velog-api-server 와 velog-batch-server 에 velog-core 를 정상적으로 의존성을 가지고 있는 걸 확인할 수 있다 🙂

4. 모듈 설정

 velog-api-server :: API 서버 모듈
api 서버 모듈 에 아래 파일을 생성해준다.

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

resources > application.yml

server:
  port: 8000

: 서버 포트번호를 8000 으로 설정해준다.
: 원하는 포트번호가 있는 경우 해당 포트 번호로 설정해주면 된다.

com.soyeon.velog > ApiApplication.java

package com.soyeon.velog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }
}

: 패키지를 만들고 ApiApplication 파일을 만들어준다.
: @SpringBootApplication 어노테이션을 통해 웹 어플리케이션이 실행 될 수 있도록 한다.

Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package. 오류가 발생하는 경우
➡️ 패키지를 지정하지 않아 발생하는 오류로 패키지를 만들고 그 안에 Application 코드를 넣어주자.

 velog-batch-server :: 배치 서버 모듈
build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

resources > application.yml

server:
  port: 8001

: 포트 번호를 8081로 설정해준다.
: 원하는 포트 번호가 있다면 그걸로 지정해주되, velog-api-server 와는 다르게 지정해준다.

com.soyeon.velog > BatchApplication

package com.soyeon.velog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BatchApplication {
    public static void main(String[] args) {
        SpringApplication.run(BatchApplication.class, args);
    }
}

: 패키지를 만들고 BatchApplication 파일을 만들어준다.
: @SpringBootApplication 어노테이션을 통해 웹 어플리케이션이 실행 될 수 있도록 한다.

 서버 정상작동 확인
ApiApplication 혹은 BatchApplication 을 실행시켜준다.

velog-api-server url 👉 localhost:8000
velog-batch-server url 👉 localhost:8001

예제 그대로 따라했다면 위의 url로
혹은 포트를 수정했다면 수정한 포트로 접속하면 정상 작동을 확인 할 수 있다.

아직 만든 API 가 없기 때문에 각각의 url 로 접속했을 때 아래와 같은 화면이 뜬다면 서버가 정상적으로 실행된 것이다.

5. 공통 모듈 (velog-core) 의존성 테스트

velog-core 에 com.soyeon.velog.entity 라는 패키지를 만들고 가상으로 Member entity 를 만들어보자. 코드는 아래와 같다.

com.soyeon.velog.entity > Member.class

package com.soyoen.velog.entity;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Member {
    String name;
    int age;
}

: Member 는 이름과 나이를 가지고 있다고 가정한다.
: @Getter, @Setter, @ToString 은 롬복 어노테이션으로 get 메서드, set 메소드, toString 메서드를 자동 생성해준다.

velog-api-server 에 ApiController 를 만들어주고 Member 객체를 사용해보자.
velog-api-server 는 velog-core 에 의존성을 가지고 있기 때문에 Member 객체를 사용할 수 있다.

package com.soyeon.velog.controller;

import com.soyoen.velog.entity.Member;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ApiController {

    @GetMapping("/test")
    public String test() {
        Member member = new Member();
        member.setAge(10);
        member.setName("이름");
        return member.toString();
    }
}


: import 된 값인 import com.soyoen.velog.entity.Member; 와 위의 사진을 보면 velog-core 에 있는 클래스를 import 해서 사용하고 있다는 걸 확인할 수 있다.


API 로 접속해봤을 때에도 정상적으로 결과가 나오는 걸 확인할 수 있다.

 

출처 : https://velog.io/@soyeon207/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%EB%A9%80%ED%8B%B0-%EB%AA%A8%EB%93%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0

728x90
반응형

댓글