[시즌2] 개인서버 개발/시즌2 설계(완)

Multi-project 구조 설계 (Gradle)

북극곰은콜라 2023. 12. 21. 08:16
반응형


개요

지난 시즌 개발 중 신규 프로젝트 시작할 때 큰 귀찮음이 있었다.
1. 프로젝트마다 중복되는 코드: log 설정, db설정, kafka 설정, 등등..
2. 프로젝트마다 중복되는 작업: github, jenkins CI/CD, docker config 등등..
이런 귀찮음은 결국 신규 프로젝트를 시작할 때 부담으로 작용하게 되었고
간단한 아이디어를 테스트 하기에 좋지 못했다.
이번 시즌에는 이러한 부분을 사전에 방지하고자 한다.
이 글은 Gradle의 Multi-Project 구조를 통해
이러한 문제상황을 해결해보려 한다.

 


Multi-Project 구조 설계

Gradle은 Multi-Project 구조를 지원한다.
이번 프로젝트는 2-depth 이상으로 구성하려 한다.
Root project 'pbear-root'
\--- Project ':pbear-spring'
     +--- Project ':pbear-spring:pbear-lib'
     \--- Project ':pbear-spring:pbear-sample'
Project 구조이다.
전체적으로 java 프로젝트를 대상으로 하며
일단 Spring Project를 1-depth로 잡았다.
2-depth부터 개발이 진행될 프로젝트들이 나열되는데
기본적으로 lib를 두고, spring-project에서 사용될 공통 코드 및 설정을 implementation 해서 사용하고자 한다.

[root] setting.gradle

rootProject.name = 'pbear-root'

include 'pbear-spring'
include 'pbear-spring:pbear-lib'
include 'pbear-spring:pbear-sample'
특이사항은 없으며
하위 프로젝트의 build.gradle을 include 시켰다.

[root] build.gradle

group = 'com.pbear'

subprojects {
    apply plugin: 'java'
    apply plugin: 'java-library'

    sourceCompatibility = 17
    targetCompatibility = 17

    dependencies {
        compileOnly 'org.projectlombok:lombok:1.18.28'
        annotationProcessor 'org.projectlombok:lombok:1.18.28'
    }

    repositories {
        mavenCentral()
    }
}
subprojects를 통해 하위 프로젝트에 적용될 plugin, dependencies 및 repositories를 설정했다.

[pbear-spring] build.gradle

plugins {
    id 'org.springframework.boot' version '3.2.0' apply false
    id 'io.spring.dependency-management' version '1.1.4' apply false
}

ext {
    set('springCloudVersion', "2023.0.0")
}

subprojects {
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }

    test {
        useJUnitPlatform()
    }
}
1-depth의 spring을 주제로 묶은 프로젝트이다.
여기서 spring의 dependencies를 통합해서 관리하고자 한다.
기본적으로 spring의 dependency-management 플러그인을 사용하고, spring boot 및 spring cloud version을 관리할 수 있도록 세팅했다.

[pbear-lib]  build.gradle

version = '0.0.1'

dependencies {
    implementation 'org.springframework.boot:spring-boot-autoconfigure'
}
2-depth의 Library에 해당하는 프로젝트이다.
추후 추가될 예정이며, 여기부터는 project version 관리를 한다.

[pbear-sample] build.gradle

version = '0.0.0'

dependencies {
    implementation project(':pbear-spring:pbear-lib')

    implementation 'org.springframework.boot:spring-boot-starter-webflux'
}
REST echo기능을 하나 넣은 sample project이다.
추후 추가되는 프로젝트는 위처럼 pbear-lib를 implementation을 해서 사용한다.
위 프로젝트 구조를 통해
프로젝트 추가 시 낭비되는 작업들을 최소화시킬 수 있을 것이라 판단된다.
ex) github project 추가, spring dependency 작업, 중복 기능 구현, 설정 등

 


Common logback 설정

[pbear-lib] logback.xml

Root project 'pbear-root'
\--- Project ':pbear-spring'
     +--- Project ':pbear-spring:pbear-lib'
          \--- src/main/resources/logback.xml
     \--- Project ':pbear-spring:pbear-sample'
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty name="APP_NAME" source="spring.application.name"/>

    <springProfile name="local">
        <property name="FILE_PATH" value="/users/xxxxx/workspace/logs"/>
        <property name="FILE_NAME" value="${APP_NAME}"/>
    </springProfile>

    <springProfile name="release">
        <property name="FILE_PATH" value="/logs"/>
        <property name="FILE_NAME" value="${APP_NAME}"/>
    </springProfile>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyyMMdd HH:mm:ss} [%thread] %-5level%logger{5} - %msg %n</pattern>
        </encoder>
    </appender>

    <appender name="RollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${FILE_PATH}/${FILE_NAME}.log</file>

        <encoder>
            <pattern>%d{yyyyMMdd HH:mm:ss} [%thread] %-5level%logger{5} - %msg %n</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${FILE_PATH}/${FILE_NAME}.log.%d{yyyy-MM-dd}_%i.gz</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>1GB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <springProfile name="local">
        <root level="INFO">
            <appender-ref ref="STDOUT" />
        </root>
    </springProfile>

    <springProfile name="release">
        <root level="INFO">
            <appender-ref ref="RollingFileAppender" />
        </root>
    </springProfile>
</configuration>
공통 library에 자주 사용하는 logback을 넣고 다른 project에서 implementation 하면
실제 기동 시 해당 logback이 적용된다.
변수는 모두 spring properties로 받아온다.

이로서 신규 프로젝트는 로깅에 대한 설정을 스킵할 수 있다.
또한 log관련 변동사항이 다 같이 적용되고, log의 형식도 통일할 수 있다.

 


Next..

신규 프로젝트마다. CI / CD설정하고, docker 설정 만드는 것도 많이 귀찮은 작업이었다.
프로젝트 구조를 잡았으니
다음은 Jenkins를 통해 CI / CD를 공통화할 계획이다.

 


REFERENCE

https://docs.gradle.org/current/userguide/multi_project_builds.html

 

 

 

반응형