1. 개요

Jooby 는 가장 많이 사용되는 NIO 웹 서버 위에 구축된 확장 가능하고 빠른 마이크로 웹 프레임워크 입니다. 매우 간단하고 모듈식이며 현대 웹 아키텍처에 맞게 명확하게 설계되었습니다. Javascript Kotlin 도 지원합니다.

기본적으로 Jooby 는 Netty, Jetty 및 Undertow 를 훌륭하게 지원합니다 .

이 기사에서는 전반적인 Jooby 프로젝트 구조와 Jooby를 사용하여 간단한 웹 애플리케이션을 빌드하는 방법에 대해 알아봅니다 .

2. 애플리케이션 아키텍처

간단한 Jooby 애플리케이션 구조는 다음과 같습니다.

├── public
|   └── welcome.html
├── conf
|   ├── application.conf
|   └── logback.xml
└── src
|   ├── main
|   |   └── java
|   |       └── com
|   |           └── baeldung
|   |               └── jooby
|   |                   └── App.java
|   └── test
|       └── java
|           └── com
|               └── baeldung
|                   └── jooby
|                       └── AppTest.java
├── pom.xml

여기서 주목할 점은 공용 디렉토리에 css/js/html 등과 같은 정적 파일을 넣을 수 있다는 것입니다. conf 디렉토리에는 logback.xml 또는 application.conf 등과 같이 애플리케이션에 필요한 모든 구성 파일을 넣을 수 있습니다 .

3. 메이븐 의존성

pom.xml 에 다음 의존성을 추가하여 간단한 Jooby 애플리케이션을 만들 수 있습니다 .

<dependency>
    <groupId>org.jooby</groupId>
    <artifactId>jooby-netty</artifactId>
    <version>1.1.3</version>
</dependency>

Jetty 또는 Undertow 를 선택하려는 경우 다음 의존성을 사용할 수 있습니다.

<dependency>
    <groupId>org.jooby</groupId>
    <artifactId>jooby-jetty</artifactId>
    <version>1.1.3</version>
</dependency>
<dependency>
    <groupId>org.jooby</groupId>
    <artifactId>jooby-undertow</artifactId>
    <version>1.1.3</version>
</dependency>

Central Maven Repository 에서 최신 버전의 Jooby 프로젝트를 확인할 수 있습니다 .

Jooby 에는 전용 Maven 원형도 있습니다. 이를 사용하여 필요한 모든 의존성이 미리 빌드된 샘플 프로젝트를 만들 수 있습니다.

다음 스크립트를 사용하여 샘플 프로젝트를 생성할 수 있습니다.

mvn archetype:generate -B -DgroupId=com.baeldung.jooby -DartifactId=jooby 
-Dversion=1.0 -DarchetypeArtifactId=jooby-archetype 
-DarchetypeGroupId=org.jooby -DarchetypeVersion=1.1.3

4. 애플리케이션 구축

4.1. 서버 시작

임베디드 서버를 시작하려면 다음 코드 스니펫을 사용해야 합니다.

public class App extends Jooby {
    public static void main(String[] args) {
        run(App::new, args);
    }
}

일단 시작되면 서버는 기본 포트 8080 에서 실행됩니다 .

사용자 정의 포트 및 사용자 정의 HTTPS 포트 로 백엔드 서버를 구성할 수도 있습니다 .

{
    port( 8081 );
    securePort( 8443 );
}

4.2. 라우터 구현

Jooby 에서 경로 기반 라우터를 만드는 것은 매우 쉽습니다 . 예를 들어 다음과 같은 방법으로 ' /login ' 경로에 대한 라우터를 만들 수 있습니다 .

{
    get( "/login", () -> "Hello from Baeldung");
}

비슷한 방식으로 POST, PUT 등과 같은 다른 HTTP 메서드를 처리하려는 경우 아래 코드 스니펫을 사용할 수 있습니다.

{
    post( "/save", req -> {
        Mutant token = req.param( "token" );
        return token.intValue();
    });
}

여기에서는 요청에서 요청 매개변수 이름 토큰을 가져옵니다. 기본적으로 모든 요청 매개변수는 JoobyMutant 데이터 유형으로 유형 변환됩니다. 기대에 따라 지원되는 기본 데이터 유형으로 변환할 수 있습니다.

다음과 같은 방법으로 모든 URL 매개변수를 확인할 수 있습니다.

{
    get( "/user/{id}", req -> "Hello user : " + req.param("id").value() );
    get( "/user/:id", req -> "Hello user: " + req.param("id").value() );
}

우리는 위의 것을 사용할 수 있습니다. 고정 콘텐츠로 시작하는 매개변수를 찾는 것도 가능합니다. 예를 들어 다음과 같은 방법으로 ' uid:' 로 시작하는 URL 매개변수를 찾을 수 있습니다.

{
    get( "/uid:{id}", req -> "Hello User with id : uid" + 
        req.param("id").value());
}

4.3. MVC 패턴 컨트롤러 구현

엔터프라이즈 애플리케이션의 경우 Jooby 는 Spring MVC와 같은 다른 MVC 프레임워크와 마찬가지로 MVC API와 함께 제공됩니다.

예를 들어 ' /hello ' 라는 경로를 처리할 수 있습니다 .

@Path("/hello")
public class GetController {
    @GET
    public String hello() {
        return "Hello Baeldung";
    }
}

매우 유사하게 @POST , @PUT, @DELETE 등의 어노테이션 을 사용하여 다른 HTTP 메서드를 처리하는 핸들러를 만들 수 있습니다 .

4.4. 정적 콘텐츠 처리

HTML, Javascript, CSS, 이미지 등과 같은 정적 콘텐츠를 제공하려면 해당 파일을 공용 디렉터리에 배치해야 합니다.

배치되면 라우터에서 모든 URL을 다음 리소스에 매핑할 수 있습니다.

{
    assets( "/employee" , "form.html" );
}

4.5. 취급 양식

기본적으로 Jooby의 요청 인터페이스는 수동 유형 캐스팅을 사용하지 않고 모든 양식 개체를 처리합니다.

양식을 통해 직원 세부 정보를 제출해야 한다고 가정해 보겠습니다. 첫 번째 단계에서 데이터를 보유하는 데 사용할 Employee 빈 객체를 생성해야 합니다.

public class Employee {
    String id;
    String name;
    String email;

    // standard constructors, getters and setters
}

이제 양식을 만들기 위해 페이지를 만들어야 합니다.

<form enctype="application/x-www-form-urlencoded" action="/submitForm" 
    method="post">
    <input name="id" />
    <input name="name" />
    <input name="email" />
    <input type="submit" value="Submit"/>
</form>

다음으로 이 양식을 처리하고 제출된 데이터를 가져오는 포스트 핸들러를 생성합니다.

post( "/submitForm", req -> {
    Employee employee = req.params(Employee.class);
    // ...
    return "empoyee data saved successfullly";
});

여기서 주목해야 할 점 은 동적 양식 바인딩을 지원하려면 양식 enctypeapplication/x-www-form-urlencoded 로 선언해야 한다는 것 입니다.

Request.file(String filename)통해 업로드된 파일을 검색할 수 있습니다.

post( "/upload", req -> {
    Upload upload = req.file("file");
    // ...
    upload.close();
});

4.6. 필터 구현

즉시 사용 가능한 Jooby 는 전역 필터와 경로 기반 필터를 정의할 수 있는 유연성을 제공합니다.

Jooby 에서 필터를 구현 하는 것은 URL 경로를 필터에 대해 한 번, 핸들러에 대해 다시 한 번, 두 번 구성해야 하기 때문에 약간 까다롭습니다 .

예를 들어 ' /filter' 라는 URL 경로에 대한 필터 를 구현해야 하는 경우 이 경로에 명시적으로 필터를 구현해야 합니다.

get( "/filter", ( req, resp, chain ) -> {
    // ...
    chain.next( req, resp );
});

구문은 Servlet 필터와 매우 유사합니다. 요청을 제한하고 Response.send(Result result) 메서드 를 호출하여 필터 자체에서 응답을 다시 보낼 수 있습니다.

필터가 구현되면 요청 핸들러를 구현해야 합니다.

get("/filter", (req, resp) -> {
    resp.send("filter response");
});

4.7. 세션

Jooby 에는 두 가지 유형의 세션 구현이 있습니다. 인 메모리 및 쿠키 기반.

메모리 내 세션 관리를 구현하는 것은 매우 간단합니다. EhCache, Guava, HazleCast, Cassandra, Couchbase, Redis, MongoDBMemcached 와 같이 Jooby 에서 사용할 수 있는 처리량이 많은 세션 저장소를 선택할 수 있는 옵션이 있습니다 .

예를 들어 Redis 기반 세션 저장소를 구현하려면 다음 Maven 의존성을 추가해야 합니다.

<dependency>
    <groupId>org.jooby</groupId>
    <artifactId>jooby-jedis</artifactId>
    <version>1.1.3</version>
</dependency>

이제 아래 코드 조각을 사용하여 세션 관리를 활성화할 수 있습니다.

{
    use(new Redis());
    session(RedisSessionStore.class);

    get( "/session" , req -> {
        Session session = req.session();
        session.set("token", "value");
        return session.get("token").value();
    });
}

여기서 주목할 점 은 application.conf 에서 Redis url을 'db' 속성 으로 구성할 수 있다는 것 입니다.

쿠키 기반 세션 관리를 활성화하려면 cookieSession() 을 선언해야 합니다 . 쿠키 기반 접근 방식을 선택한 경우 application.conf 파일 에서 application.secret 속성 을 선언해야 합니다. 서명되는 각 쿠키는 이 비밀 키로 서명되므로 항상 긴 임의 문자열 조각을 비밀 키로 사용하는 것이 좋습니다.

인 메모리 및 쿠키 기반 접근 방식 모두에서 application.conf 파일에 필요한 구성 매개 변수를 선언해야 합니다. 그렇지 않으면 응용 프로그램이 시작할 때 IllegalStateException 이 발생합니다.

5. 테스트

경로가 일부 클래스의 전략에 바인딩되어 있기 때문에 MVC 경로를 테스트하는 것은 실제로 쉽습니다. 이렇게 하면 모든 경로에 대해 단위 테스트를 쉽게 실행할 수 있습니다.

예를 들어 기본 URL에 대한 테스트 사례를 빠르게 만들 수 있습니다.

public class AppTest {
 
    @ClassRule
    public static JoobyRule app = new JoobyRule(new App());

    @Test
    public void given_defaultUrl_expect_fixedString() {
 
        get("/").then().assertThat().body(equalTo("Hello World!"))
          .statusCode(200).contentType("text/html;charset=UTF-8");
    }
}

여기서 주목해야 할 점은 @ClassRule 어노테이션을 사용하면 모든 테스트 사례에 대해 하나의 서버 인스턴스만 생성된다는 것입니다. 모든 테스트 케이스에 대해 별도의 서버 인스턴스를 구축해야 하는 경우 정적 수정자 없이 @Rule 어노테이션을 사용해야 합니다.

또한 Jooby의 MockRouter 를 사용 하여 동일한 방식으로 경로를 테스트할 수 있습니다.

@Test
public void given_defaultUrl_with_mockrouter_expect_fixedString() 
  throws Throwable {
 
    String result = new MockRouter(new App()).get("/");
 
    assertEquals("Hello World!", result);
}

6. 결론

이 예제에서는 Jooby 프로젝트와 그 필수 기능을 살펴보았습니다.

항상 그렇듯이 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .

res – REST with Spring (eBook) (everywhere)