1. 개요
Bootique 는 확장 가능한 차세대 마이크로 서비스 구축을 목표로 하는매우 가벼운 오픈 소스 컨테이너리스 JVM 프레임워크입니다. 임베디드 Jetty 서버 위에 구축되었으며 jax-rs 로 REST 핸들러를 완벽하게 지원합니다 .
이 기사에서는 Bootique를 사용하여 간단한 웹 애플리케이션을 구축하는 방법을 보여줍니다 .
2. 메이븐 의존성
다음 의존성을 pom.xml에 추가하여 Bootique 사용을 시작하겠습니다 .
<dependency>
<groupId>io.bootique.jersey</groupId>
<artifactId>bootique-jersey</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.bootique</groupId>
<artifactId>bootique-test</artifactId>
<scope>test</scope>
</dependency>
그러나 Bootique는 몇 가지 BOM(“Bill of Material”) 가져오기를 선언해야 합니다. 그래서 다음 <dependencyManagement> 섹션을 pom.xml에 추가해야 합니다 .
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.bootique.bom</groupId>
<artifactId>bootique-bom</artifactId>
<version>0.23</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
최신 버전의 Bootique는 Central Maven Repository 에서 사용할 수 있습니다 .
실행 가능한 jar를 빌드하기 위해 Bootique는 maven-shade-plugin 에 의존합니다 . 그렇기 때문에 아래 구성도 추가해야 합니다.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>
3. 애플리케이션 시작
Bootique 응용 프로그램을 시작하는 가장 간단한 방법은 기본 메서드에서 Bootique 의 exec() 메서드를 호출하는 것입니다 .
public class App {
public static void main(String[] args) {
Bootique.app(args)
.autoLoadModules()
.exec();
}
}
그러나 이렇게 하면 임베디드 서버가 시작되지 않습니다. 일단 위의 코드가 실행되면 다음 로그가 표시되어야 합니다.
NAME
com.baeldung.bootique.App
OPTIONS
-c yaml_location, --config=yaml_location
Specifies YAML config location, which can be a file path
or a URL.
-h, --help
Prints this message.
-H, --help-config
Prints information about application modules and their
configuration options.
-s, --server
Starts Jetty server.
이들은 Bootique 와 함께 사전 번들로 제공되는 사용 가능한 프로그램 인수에 지나지 않습니다 .
이름은 자명합니다. 따라서 서버를 시작하려면 –s 또는 –server 인수를 전달해야 하며 서버는 기본 포트 8080 에서 실행됩니다 .
4. 모듈
Bootique 애플리케이션은 "모듈" 모음으로 만들어집니다. Bootique 의 용어 에서 "모듈은 일부 코드를 포함하는 Java 라이브러리"입니다. 즉, 모든 서비스를 모듈로 취급합니다. 의존성 주입을 위해 Google Guice를 사용합니다 .
작동 방식을 확인하기 위해 하나의 인터페이스를 만들어 보겠습니다.
public interface HelloService {
boolean save();
}
이제 구현을 만들어야 합니다.
public class HelloServiceImpl implements HelloService {
@Override
public boolean save() {
return true;
}
}
모듈을 로드할 수 있는 두 가지 방법이 있습니다. 첫 번째는 Guice 의 Module 인터페이스를 사용하는 것이고 다른 하나는 auto-loading 이라고도 하는 Bootique 의 BQModuleProvider를 사용하는 것입니다 .
4.1. 사용방법(예제) 모듈
여기에서 Guice 의 Module 인터페이스를 사용하여 인스턴스를 바인딩할 수 있습니다.
public class ModuleBinder implements Module {
@Override
public void configure(Binder binder) {
binder
.bind(HelloService.class)
.to(HelloServiceImpl.class);
}
}
모듈이 정의되면 이 사용자 정의 모듈을 Bootique 인스턴스 에 매핑해야 합니다 .
Bootique
.app(args)
.module(module)
.module(ModuleBinder.class)
.autoLoadModules()
.exec();
4.2. BQModuleProvider (자동 로딩)
여기서 우리가 해야 할 일은 BQModuleProvider를 사용하여 이전에 만든 모듈 바인더를 정의하는 것입니다 .
public class ModuleProvider implements BQModuleProvider {
@Override
public Module module() {
return new ModuleBinder();
}
}
이 기술의 장점은 모듈 정보를 Bootique 인스턴스 와 매핑할 필요가 없다는 것입니다 .
/resources/META-INF/services/io.bootique.BQModuleProvider 에 파일을 생성 하고 패키지 이름을 포함하여 ModuleProvider 의 전체 이름을 작성하면 Bootique가 나머지를 처리합니다.
com.baeldung.bootique.module.ModuleProvider
이제 @Inject 어노테이션을 사용하여 런타임에 서비스 인스턴스를 사용할 수 있습니다.
@Inject
HelloService helloService;
여기서 주목해야 할 한 가지 중요한 점은 Bootique 의 자체 DI 메커니즘을 사용하고 있기 때문에 서비스 인스턴스를 바인딩하기 위해 Guice @ImplementedBy 어노테이션을 사용할 필요가 없다는 것입니다.
5. REST Endpoints
JAX-RS API를 사용하여 REST Endpoints을 만드는 것은 간단합니다.
@Path("/")
public class IndexController {
@GET
public String index() {
return "Hello, baeldung!";
}
@POST
public String save() {
return "Data Saved!";
}
}
엔드포인트를 Bootique 자체 Jersey 인스턴스에 매핑하려면 JerseyModule을 정의해야 합니다 .
Module module = binder -> JerseyModule
.extend(binder)
.addResource(IndexController.class);
6. 구성
YAML 기반 속성 파일에 내장 또는 사용자 지정 구성 정보를 제공할 수 있습니다.
예를 들어 사용자 지정 포트에서 애플리케이션을 시작하고 기본 URI 컨텍스트 'hello'를 추가하려는 경우 다음 YAML 구성을 사용할 수 있습니다.
jetty:
context: /hello
connector:
port: 10001
이제 애플리케이션을 시작하는 동안 config 매개변수에 이 파일의 위치를 제공해야 합니다.
--config=/home/baeldung/bootique/config.yml
7. 로깅
즉시 사용 가능한 Bootique는 bootique-logback 모듈 과 함께 제공됩니다 . 이 모듈을 사용하려면 pom.xml 에 다음 의존성을 추가해야 합니다 .
<dependency>
<groupId>io.bootique.logback</groupId>
<artifactId>bootique-logback</artifactId>
</dependency>
이 모듈은 Custom 로깅을 구현하기 위해 재정의할 수 있는 BootLogger 인터페이스와 함께 제공됩니다.
Bootique.app(args)
.module(module)
.module(ModuleBinder.class)
.bootLogger( new BootLogger() {
@Override
public void trace( Supplier<String> args ) {
// ...
}
@Override
public void stdout( String args ) {
// ...
}
@Override
public void stderr( String args, Throwable thw ) {
// ...
}
@Override
public void stderr( String args ) {
// ...
}
}).autoLoadModules().exec();
또한 config.yaml 파일에서 로깅 구성 정보를 정의할 수 있습니다.
log:
level: warn
appenders:
- type: file
logFormat: '%c{20}: %m%n'
file: /path/to/logging/dir/logger.log
8. 테스트
테스트를 위해 Bootique는 bootique-test 모듈 과 함께 제공됩니다 . Bootique 애플리케이션을 테스트할 수 있는 두 가지 방법이 있습니다 .
첫 번째 접근 방식은 모든 테스트 케이스가 기본 테스트 스레드에서 실행되도록 하는 '포그라운드' 접근 방식입니다.
다른 하나는 테스트 케이스가 격리된 스레드 풀에서 실행되도록 하는 '백그라운드' 접근 방식입니다.
'포그라운드' 환경은 BQTestFactory를 사용하여 초기화할 수 있습니다 .
@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();
'백그라운드' 환경은 BQDaemonTestFactory를 사용하여 초기화할 수 있습니다 .
@Rule
public BQDaemonTestFactory bqDaemonTestFactory = new BQDaemonTestFactory();
환경 팩토리가 준비되면 간단한 테스트 케이스를 작성하여 서비스를 테스트할 수 있습니다.
@Test
public void givenService_expectBoolen() {
BQRuntime runtime = bqTestFactory
.app("--server").autoLoadModules()
.createRuntime();
HelloService service = runtime.getInstance( HelloService.class );
assertEquals( true, service.save() );
}
9. 결론
이 기사에서는 Bootique 의 핵심 모듈을 사용하여 애플리케이션을 빌드하는 방법을 보여주었습니다 . bootique-jooq , bootique-kotlin , bootique-job 등과 같이 사용할 수 있는 여러 다른 Bootique 모듈이 있습니다 . 사용 가능한 모듈의 전체 List은 여기 에서 볼 수 있습니다 .
항상 그렇듯이 전체 소스 코드는 GitHub에서 사용할 수 있습니다.