연습 - Azure 리소스 및 Java Spring 애플리케이션 만들기
이 단원에서 기본 Spring Boot 애플리케이션을 만듭니다. Azure CLI 및 선택한 IDE(통합 개발 환경)를 사용하여 코드를 편집하겠습니다. 선택한 터미널을 사용하여 코드를 실행합니다.
작업 환경 준비
다음 명령을 사용하여 몇 가지 환경 변수를 설정합니다.
AZ_RESOURCE_GROUP=azure-spring-workshop
AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
AZ_LOCATION=<YOUR_AZURE_REGION>
AZ_MYSQL_USERNAME=spring
AZ_MYSQL_PASSWORD=<YOUR_MYSQL_PASSWORD>
AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
코드에서 자리 표시자를 다음 표의 값으로 바꿉니다. 해당 값은 이 모듈 전체에서 사용됩니다.
변수 | 설명 |
---|---|
<YOUR_DATABASE_NAME> | MySQL 서버의 이름입니다. Azure에서 고유해야 합니다. |
<YOUR_AZURE_REGION> | 사용할 Azure 지역입니다. 기본적으로 eastus 를 사용할 수 있지만, 거주 장소에 가까운 지역을 사용하는 것이 좋습니다. 사용 가능한 지역의 전체 목록을 보려면 az account list-locations 를 입력합니다. |
<YOUR_MYSQL_PASSWORD> | MySQL 데이터베이스 서버의 암호입니다. 암호 길이는 8자 이상이어야 합니다. 영어 대문자, 영어 소문자, 숫자 0~9, 영숫자가 아닌 문자(!, $, #, % 등) 중 세 범주의 문자를 포함해야 합니다. |
<YOUR_LOCAL_IP_ADDRESS> | Spring Boot 애플리케이션을 실행할 로컬 컴퓨터의 IP 주소입니다. IP 주소를 찾으려면 브라우저에서 whatismyip.akamai.com을 가리킵니다. |
다음으로, 리소스 그룹을 만듭니다.
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
| jq
참고
이 모듈에서는 Azure Cloud Shell에 기본적으로 설치되는 jq
도구를 사용하여 JSON 데이터를 표시하고 읽기 쉽도록 만듭니다.
jq
도구를 사용하지 않으려는 경우 이 모듈에 있는 모든 명령의 | jq
부분을 안전하게 제거할 수 있습니다.
Azure Database for MySQL 인스턴스 만들기
이제 관리형 MySQL 서버를 만들겠습니다.
참고
Azure Database for MySQL에 대해 자세히 알아보려면 이 모듈의 끝에 있는 관련 설명서 링크를 따르세요.
다음 스크립트를 실행하여 Azure Database for MySQL의 작은 인스턴스를 만듭니다. 데이터베이스에는 CPU 1개와 2GB RAM이 있습니다.
az mysql server create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_NAME \
--location $AZ_LOCATION \
--sku-name B_Gen5_1 \
--storage-size 5120 \
--admin-user $AZ_MYSQL_USERNAME \
--admin-password $AZ_MYSQL_PASSWORD \
| jq
이 스크립트는 이전에 설정한 변수를 사용하는 작은 MySQL 서버를 만듭니다.
MySQL 서버에 대한 방화벽 규칙 구성
Azure Database for MySQL은 기본적으로 보호됩니다. 방화벽에서 들어오는 연결을 허용하지 않습니다. 따라서 로컬 IP 주소가 데이터베이스 서버에 액세스할 수 있도록 허용하는 방화벽 규칙을 추가합니다.
다음 명령을 실행하여 웹 서버의 방화벽을 엽니다.
az mysql server firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_NAME-database-allow-local-ip \
--server-name $AZ_DATABASE_NAME \
--start-ip-address $AZ_LOCAL_IP_ADDRESS \
--end-ip-address $AZ_LOCAL_IP_ADDRESS \
| jq
다음 명령을 실행하여 Azure 리소스의 방화벽 액세스를 허용합니다.
az mysql server firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--name allAzureIPs \
--server-name $AZ_DATABASE_NAME \
--start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 \
| jq
MySQL 데이터베이스 구성
이전에 만든 MySQL 서버가 비어 있습니다. Spring Boot 애플리케이션에서 사용할 수 있는 데이터베이스가 없습니다. demo
라는 새 데이터베이스를 만듭니다.
az mysql db create \
--resource-group $AZ_RESOURCE_GROUP \
--name demo \
--server-name $AZ_DATABASE_NAME \
| jq
Spring Initializr를 사용하여 애플리케이션 생성
Spring Initializr는 Spring Boot 프로젝트 구조를 자동으로 생성하는 웹 애플리케이션입니다. Spring Initializr는 애플리케이션 코드를 생성하지 않고 기본적인 프로젝트 구조와 Maven 빌드 사양을 제공합니다.
세 가지 종속성(web
, mysql
, data-jpa
)이 있는 애플리케이션 스캐폴드를 생성합니다.
로컬에서 애플리케이션을 실행하기 때문에 Azure 종속성을 지정하지 않아도 됩니다.
명령 프롬프트에서 애플리케이션을 생성합니다.
curl https://start.spring.io/starter.tgz -d type=maven-project -d dependencies=web,data-jpa,mysql -d baseDir=azure-spring-workshop -d bootVersion=3.1.5.RELEASE -d javaVersion=17 | tar -xzvf -
Azure Database for MySQL을 사용하도록 Spring Boot 구성
src/main/resources/application.properties 파일을 열고 몇 가지 속성을 추가합니다. 두 개의 $AZ_DATABASE_NAME
변수와 $AZ_MYSQL_PASSWORD
변수를 이전에 설정한 값으로 바꾸어야 합니다.
logging.level.org.hibernate.SQL=DEBUG
spring.datasource.url=jdbc:mysql://$AZ_DATABASE_NAME.mysql.database.azure.com:3306/demo?serverTimezone=UTC
spring.datasource.username=spring@$AZ_DATABASE_NAME
spring.datasource.password=$AZ_MYSQL_PASSWORD
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
경고
spring.jpa.hibernate.ddl-auto=create-drop
구성 속성을 사용하면 Spring Boot는 애플리케이션을 시작할 때 데이터베이스 스키마를 자동으로 만들고, 종료할 때 데이터베이스 스키마를 삭제하려고 합니다. 이 속성은 테스트에 유용하지만 프로덕션 환경에서 사용할 수 없습니다.
참고
spring.datasource.url
구성 속성에 ?serverTimezone=UTC
를 추가합니다. 이 설정은 데이터베이스에 연결할 때 UTC(협정 세계시) 날짜 형식을 사용하도록 JDBC(Java Database Connectivity) 드라이버에 지시합니다. 그러지 않으면 Java 서버에서 데이터베이스와 동일한 날짜 형식을 사용하지 않으므로 오류가 발생합니다.
이제 제공된 Maven 래퍼를 사용하여 애플리케이션을 시작하세요.
./mvnw spring-boot:run
이 스크린샷은 처음 실행되는 애플리케이션을 보여 줍니다.
애플리케이션 코딩
다음 Java 코드를 추가합니다. 이 코드는 JPA(Java Persistence API)를 사용하여 MySQL 서버에서 데이터를 검색하고 저장합니다.
JPA 엔터티 클래스를 사용하여 Java Todo
개체를 MySQL Todo
테이블에 직접 매핑합니다.
DemoApplication
클래스 옆에 새 Todo
엔터티 클래스를 만듭니다. 다음 코드를 추가합니다.
package com.example.demo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Todo {
public Todo() {
}
public Todo(String description, String details, boolean done) {
this.description = description;
this.details = details;
this.done = done;
}
@Id
@GeneratedValue
private Long id;
private String description;
private String details;
private boolean done;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Todo)) {
return false;
}
return id != null && id.equals(((Todo) o).id);
}
@Override
public int hashCode() {
return 31;
}
}
이 클래스는 Todo
테이블에서 매핑된 도메인 모델입니다. JPA를 통해 자동으로 생성됩니다.
해당 클래스를 관리하려면 리포지토리가 필요합니다. 동일한 패키지에 새 TodoRepository
인터페이스를 정의합니다.
package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TodoRepository extends JpaRepository<Todo, Long> {
}
이 리포지토리는 Spring Data JPA가 관리하는 JPA 리포지토리입니다. JpaRepository
를 확장하여 해당 형식의 많은 제네릭 CRUD(만들기, 읽기, 업데이트, 삭제) 메서드를 가져옵니다. 따라서 Todo
개체를 저장하고 삭제하는 것처럼 작업을 수행할 수 있습니다.
HTTP를 통해 데이터를 검색하고 저장할 REST 인터페이스를 게시할 수 있는 RestController
를 만들어 애플리케이션을 완료합니다. 동일한 패키지에 TodoController
클래스를 구현합니다. 다음 코드를 추가합니다.
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/")
public class TodoController {
private final TodoRepository todoRepository;
public TodoController(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
@PostMapping("/")
@ResponseStatus(HttpStatus.CREATED)
public Todo createTodo(@RequestBody Todo todo) {
return todoRepository.save(todo);
}
@GetMapping("/")
public Iterable<Todo> getTodos() {
return todoRepository.findAll();
}
}
마지막으로, 다음 명령을 사용하여 애플리케이션을 중지했다가 다시 시작합니다.
./mvnw spring-boot:run
Spring Boot 애플리케이션이 시작되고 데이터베이스에 연결되어야 합니다.
이 스크린샷은 데이터베이스에 연결하는 애플리케이션을 보여 줍니다.
애플리케이션 테스트
애플리케이션을 테스트하기 위해 cURL
을 사용할 수 있습니다.
먼저 데이터베이스에 새 todo 항목을 만듭니다.
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done": "true"}' \
http://127.0.0.1:8080
이 명령은 생성된 항목을 반환합니다.
{"id":1,"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done":true}
다음으로, 새 cURL
요청을 사용하여 데이터를 검색합니다.
curl http://127.0.0.1:8080
이 명령은 직접 만든 항목을 포함하여 todo 항목 목록을 반환합니다.
[{"id":1,"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done":true}]