연습 - Quarkus 애플리케이션 만들기

완료됨

이 단원에서는 기본적인 Quarkus 애플리케이션을 만듭니다. Maven을 사용하여 애플리케이션을 부트스트랩하고 원하는 IDE(통합 개발 환경)를 사용하여 코드를 편집합니다. 선택한 터미널을 사용하여 코드를 실행합니다. Docker를 사용하여 로컬 PostgreSQL 데이터베이스를 시작하면 애플리케이션을 로컬에서 실행하고 테스트할 수 있습니다.

Maven을 사용하여 Quarkus 애플리케이션 생성

Quarkus 프로젝트 구조를 생성하는 방법에는 여러 가지가 있습니다. Quarkus 웹 인터페이스, 또는 IDE 플러그 인, Quarkus Maven 플러그 인을 사용할 수 있습니다. Maven 플러그 인을 사용하여 프로젝트 구조를 생성해 보겠습니다.

여러 종속성을 사용하여 애플리케이션을 생성합니다.

  • resteasy 종속성을 사용하여 REST 엔드포인트 노출
  • jackson 종속성을 사용하여 JSON 직렬화 및 역직렬화
  • hibernate 종속성을 사용하여 데이터베이스와 상호 작용
  • postgresql 종속성을 사용하여 PostgreSQL 데이터베이스에 연결
  • docker 종속성을 사용하여 Docker 이미지 빌드

먼저 애플리케이션을 로컬에서 실행한 다음 컨테이너화된 버전을 Azure Container Apps에 배포하므로 Azure 종속성을 지정할 필요가 없습니다.

명령 프롬프트에서 할 일 애플리케이션 생성

mvn -U io.quarkus:quarkus-maven-plugin:3.7.3:create \
    -DplatformVersion=3.7.3 \
    -DprojectGroupId=com.example.demo \
    -DprojectArtifactId=todo \
    -DclassName="com.example.demo.TodoResource" \
    -Dpath="/api/todos" \
    -DjavaVersion=17 \
    -Dextensions="resteasy-jackson, hibernate-orm-panache, jdbc-postgresql, docker"

이 명령은 새 Quarkus 프로젝트를 만듭니다. Maven 디렉터리 구조를 생성합니다(소스 코드의 경우 src/main/java, 테스트의 경우 src/test/java). 일부 Java 클래스, 일부 테스트 및 일부 Dockerfile을 만듭니다. 또한 필요한 모든 종속성(최대 절전 모드, RESTEasy, Jackson, PostgreSQL 및 Docker)이 포함된 pom.xml 파일을 생성합니다.

  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-orm-panache</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-container-image-docker</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-orm</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

참고 항목

pom.xml 파일의 모든 종속성은 Quarkus BOM(제품 구성 정보) io.quarkus.platform:quarkus-bom에 정의되어 있습니다.

애플리케이션 코딩

그런 다음 생성된 MyEntity.java 클래스의 이름을 Todo.java(TodoResource.java 파일과 동일한 폴더에 있음)로 바꿉니다. 기존 코드를 다음 Java 코드로 바꿉니다. Java Persistence API(jakarta.persistence.* 패키지)를 사용하여 PostgreSQL 서버에서 데이터를 저장하고 검색합니다. 또한 Hibernate ORM을 Panache(io.quarkus.hibernate.orm.panache.PanacheEntity에서 상속됨)와 함께 사용하여 지속성 계층을 간소화합니다.

JPA 엔터티(@Entity)를 사용하여 Java Todo 개체를 PostgreSQL Todo 테이블에 직접 매핑합니다. 그런 다음 TodoResource REST 엔드포인트는 새 Todo 엔터티 클래스를 만들고 유지합니다. 이 클래스는 Todo 테이블에서 매핑된 도메인 모델입니다. 테이블은 JPA에 의해 자동으로 만들어집니다.

PanacheEntity를 확장하면 해당 형식에 대한 다양한 제네릭 CRUD(만들기, 읽기, 업데이트 및 삭제) 메서드를 가져올 수 있습니다. 따라서 한 줄의 Java 코드로 Todo 개체를 저장하고 삭제하는 등의 작업을 수행할 수 있습니다.

Todo 엔터티를 다음 코드에 추가

package com.example.demo;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

import jakarta.persistence.Entity;
import java.time.Instant;

@Entity
public class Todo extends PanacheEntity {

    public String description;

    public String details;

    public boolean done;

    public Instant createdAt = Instant.now();

    @Override
    public String toString() {
        return "Todo{" +
                "id=" + id + '\'' +
                ", description='" + description + '\'' +
                ", details='" + details + '\'' +
                ", done=" + done +
                ", createdAt=" + createdAt +
                '}';
    }
}

해당 클래스를 관리하려면 TodoResource를 업데이트하여 HTTP를 사용하여 데이터를 저장하고 검색하는 REST 인터페이스를 게시할 수 있도록 합니다. TodoResource 클래스를 열고, 코드를 다음과 같이 바꾸기

package com.example.demo;

import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;

import java.util.List;

@Path("/api/todos")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public class TodoResource {

    @Inject
    Logger logger;

    @Inject
    UriInfo uriInfo;

    @POST
    @Transactional
    public Response createTodo(Todo todo) {
        logger.info("Creating todo: " + todo);
        Todo.persist(todo);
        UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder().path(todo.id.toString());
        return Response.created(uriBuilder.build()).entity(todo).build();
    }

    @GET
    public List<Todo> getTodos() {
        logger.info("Getting all todos");
        return Todo.listAll();
    }
}

애플리케이션 실행

개발 모드에서 애플리케이션을 실행하려면 Docker가 실행되고 있어야 합니다. 이는 Quarkus가 pom.xml 파일에 선언된 PostgreSQL 종속성 quarkus-jdbc-postgresql로 인해 PostgreSQL 데이터베이스가 필요하다는 것을 감지하고, PostgreSQL Docker 이미지를 다운로드하고, 데이터베이스로 컨테이너를 시작하기 때문입니다. 그런 다음 데이터베이스에 Todo 테이블을 자동으로 만듭니다.

Docker가 컴퓨터에서 로컬로 실행되고 있는지 확인하고 다음 명령을 사용하여 할 일 애플리케이션을 실행합니다.

cd todo
./mvnw quarkus:dev    # On Mac or Linux
mvnw.cmd quarkus:dev  # On Windows

Quarkus 애플리케이션이 시작되고 데이터베이스에 연결되어야 합니다. 다음과 같은 출력이 표시됩니다.

[io.qua.dat.dep.dev.DevServicesDatasourceProcessor] Dev Services for the default datasource (postgresql) started.
[io.qua.hib.orm.dep.HibernateOrmProcessor] Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000

[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) table "todo" does not exist, skipping
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) sequence "hibernate_sequence" does not exist, skipping
[io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus) started in 4.381s. Listening on: http://localhost:8080
[io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
[io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, vertx]

--
Tests paused
Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

애플리케이션을 테스트할 때 cURL을 사용할 수 있습니다.

별도의 터미널에서 다음 명령을 사용하여 데이터베이스에 새 할 일 항목을 만듭니다. Quarkus 콘솔에 로그가 표시됩니다.

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done": "true"}' \
    http://127.0.0.1:8080/api/todos

이 명령은 생성된 항목(식별자와 함께)을 반환해야 합니다.

{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true,"createdAt":"2022-12-30T15:17:20.280203Z"}

다음 cURL 명령을 사용하여 두 번째 할 일을 만듭니다.

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done": "false"}' \
    http://127.0.0.1:8080/api/todos

다음으로, 새 cURL 요청을 사용하여 데이터를 검색합니다.

curl http://127.0.0.1:8080/api/todos

이 명령은 직접 만든 항목을 포함하여 할 일 항목 목록을 반환합니다.

[ 
  {"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true},
  {"id":2,"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done":false}
]

애플리케이션 테스트

애플리케이션을 테스트하려면 기존 TodoResourceTest 클래스를 사용할 수 있습니다. REST 엔드포인트를 테스트해야 합니다. 엔드포인트를 테스트하기 위해 RESTAssured를 사용합니다. TodoResourceTest 클래스의 코드를 다음 코드로 바꿉니다.

package com.example.demo;

import io.quarkus.test.junit.QuarkusTest;
import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import org.junit.jupiter.api.Test;

@QuarkusTest
class TodoResourceTest {

    @Test
    void shouldGetAllTodos() {
        given()
                .when().get("/api/todos")
                .then()
                .statusCode(200);
    }

    @Test
    void shouldCreateATodo() {
        Todo todo = new Todo();
        todo.description = "Take Quarkus MS Learn";
        todo.details = "Take the MS Learn on deploying Quarkus to Azure Container Apps";
        todo.done = true;

        given().body(todo)
                .header(CONTENT_TYPE, APPLICATION_JSON)
                .when().post("/api/todos")
                .then()
                .statusCode(201);
    }
}

애플리케이션을 테스트할 때 Quarkus는 테스트를 위해 PostgreSQL 데이터베이스가 필요하다는 것을 감지하므로 Docker Desktop을 실행해야 합니다. 다음 명령을 사용하여 애플리케이션을 테스트합니다.

./mvnw clean test    # On Mac or Linux
mvnw.cmd clean test  # On Windows

다음과 같이 유사한 출력이 표시됩니다.

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.TodoResourceTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------