Azure SQL Database와 함께 Spring Data R2DBC 사용

이 문서에서는 Spring Data R2DBC를 사용하는 샘플 애플리케이션을 만들어 r2dbc-mysql GitHub 리포지토리의 Microsoft SQL 서버용 R2DBC 구현을 사용하여 Azure SQL Database에서 정보를 저장 및 검색하는 것을 보여줍니다.

R2DBC 는 기존의 관계형 데이터베이스에 반응형 API를 제공합니다. Spring WebFlux와 함께 사용하여 비차단 API를 사용하는 완전 반응형 Spring Boot 애플리케이션을 만들 수 있습니다. 클래식 "연결당 하나의 스레드" 접근 방식보다 더 나은 확장성을 제공합니다.

필수 조건

샘플 애플리케이션 참조

이 문서에서는 샘플 애플리케이션을 코딩합니다. 더 빠르게 이동하려는 경우 이 애플리케이션은 이미 코딩되어 있습니다 https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-sql-server.

작업 환경 준비

먼저 다음 명령을 사용하여 몇 가지 환경 변수를 설정합니다.

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_SQL_SERVER_ADMIN_USERNAME=spring
export AZ_SQL_SERVER_ADMIN_PASSWORD=<YOUR_AZURE_SQL_ADMIN_PASSWORD>
export AZ_SQL_SERVER_NON_ADMIN_USERNAME=nonspring
export AZ_SQL_SERVER_NON_ADMIN_PASSWORD=<YOUR_AZURE_SQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

자리 표시자를 이 문서 전체에서 사용되는 다음 값으로 바꿉 있습니다.

  • <YOUR_DATABASE_NAME>: Azure에서 고유해야 하는 Azure SQL Database 서버의 이름입니다.
  • <YOUR_AZURE_REGION>: 사용할 Azure 지역. 기본적으로 eastus를 사용할 수 있지만 거주지와 더 가까운 지역을 구성하는 것이 좋습니다. 를 사용하여 az account list-locations사용 가능한 지역의 전체 목록을 볼 수 있습니다.
  • <AZ_SQL_SERVER_ADMIN_PASSWORD><AZ_SQL_SERVER_NON_ADMIN_PASSWORD>: 최소 8자여야 하는 Azure SQL Database 서버의 암호입니다. 문자는 영어 대문자, 영어 소문자, 숫자(0-9) 및 영숫자가 아닌 문자(!, $, #, % 등) 중 세 가지 범주에 속해야 합니다.
  • <YOUR_LOCAL_IP_ADDRESS>: Spring Boot 애플리케이션을 실행할 로컬 컴퓨터의 IP 주소입니다. 이를 찾는 편리한 방법 중 하나는 whatismyip.akamai.com을 여는 것입니다.

다음으로, 다음 명령을 사용하여 리소스 그룹을 만듭니다.

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    --output tsv

Azure SQL Database 인스턴스 만들기

다음으로, 다음 명령을 실행하여 관리되는 Azure SQL Database 서버 인스턴스를 만듭니다.

참고 항목

MS SQL 암호는 특정 조건을 충족해야 하며 비규격 암호로 설정이 실패합니다. 자세한 내용은 Password Policy을 참조하세요.

az sql server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --admin-user $AZ_SQL_SERVER_ADMIN_USERNAME \
    --admin-password $AZ_SQL_SERVER_ADMIN_PASSWORD \
    --output tsv

Azure SQL Database 서버용 방화벽 규칙 구성

Azure SQL Database 인스턴스는 기본적으로 보호됩니다. 들어오는 연결을 허용하지 않는 방화벽이 있습니다. 데이터베이스를 사용하려면 로컬 IP 주소가 데이터베이스 서버에 액세스할 수 있도록 하는 방화벽 규칙을 추가해야 합니다.

이 문서의 시작 부분에서 로컬 IP 주소를 구성했기 때문에 다음 명령을 실행하여 서버의 방화벽을 열 수 있습니다.

az sql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    --output tsv

Windows 컴퓨터의 WSL(Linux용 Windows 하위 시스템)에서 Azure SQL Database 서버에 연결하는 경우 WSL 호스트 ID를 방화벽에 추가해야 합니다.

WSL에서 다음 명령을 실행하여 호스트 머신의 IP 주소를 가져옵니다.

cat /etc/resolv.conf

용어 nameserver 다음에 IP 주소를 복사한 다음, 다음 명령을 사용하여 WSL IP 주소에 대한 환경 변수를 설정합니다.

export AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

그런 다음, 다음 명령을 사용하여 WSL 기반 앱에 대한 서버의 방화벽을 엽니다.


az sql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip-wsl \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --output tsv

Azure SQL 데이터베이스 구성

이전에 만든 Azure SQL Database 서버가 비어 있습니다. Spring Boot 애플리케이션에서 사용할 수 있는 데이터베이스가 없습니다. 다음 명령을 실행하여 호출 demo 되는 새 데이터베이스를 만듭니다.

az sql db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server $AZ_DATABASE_NAME \
    --output tsv

SQL Database 비관리자 사용자 만들기 및 권한 부여

이 단계에서는 관리자가 아닌 사용자를 만들고 데이터베이스에 대한 demo 모든 권한을 부여합니다.

관리 사용자가 아닌 사용자를 만들기 위해 create_user.sql이라는 SQL 스크립트를 만듭니다. 다음 콘텐츠를 추가하고 로컬에 저장합니다.

cat << EOF > create_user.sql
USE demo;
GO
CREATE USER $AZ_SQL_SERVER_NON_ADMIN_USERNAME WITH PASSWORD='$AZ_SQL_SERVER_NON_ADMIN_PASSWORD'
GO
GRANT CONTROL ON DATABASE::demo TO $AZ_SQL_SERVER_NON_ADMIN_USERNAME;
GO
EOF

그런 다음, 다음 명령을 사용하여 SQL 스크립트를 실행하여 관리자가 아닌 사용자를 만듭니다.

sqlcmd -S $AZ_DATABASE_NAME.database.windows.net,1433  -d demo -U $AZ_SQL_SERVER_ADMIN_USERNAME -P $AZ_SQL_SERVER_ADMIN_PASSWORD  -i create_user.sql

참고 항목

SQL 데이터베이스 사용자를 만드는 방법에 대한 자세한 내용은 CREATE USER(Transact-SQL)를 참조하세요.


반응형 Spring Boot 애플리케이션 만들기

반응형 Spring Boot 애플리케이션을 만들기 위해 Spring Initializr를 사용합니다. 여기서 만들 애플리케이션은 다음을 사용합니다.

  • Spring Boot 2.7.11.
  • 다음 종속성: Spring Reactive 웹(Spring WebFlux라고도 함) 및 Spring Data R2DBC.

Spring Initializr를 사용하여 애플리케이션 생성

다음 명령을 실행하여 명령줄에서 애플리케이션을 생성합니다.

curl https://start.spring.io/starter.tgz -d dependencies=webflux,data-r2dbc -d baseDir=azure-database-workshop -d bootVersion=2.7.11 -d javaVersion=17 | tar -xzvf -

반응형 Azure SQL Database 드라이버 구현 추가

생성된 프로젝트의 pom .xml 파일을 열어 r2dbc-mssql GitHub 리포지토리의 반응형 Azure SQL Database 드라이버를 추가합니다.

spring-boot-starter-webflux 종속성 후에 다음 텍스트를 추가합니다.

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-mssql</artifactId>
    <scope>runtime</scope>
</dependency>

Azure SQL Database를 사용하도록 Spring Boot 구성

src/기본/resources/application.properties 파일을 열고 다음 텍스트를 추가합니다.

logging.level.org.springframework.data.r2dbc=DEBUG

spring.r2dbc.url=r2dbc:pool:mssql://$AZ_DATABASE_NAME.database.windows.net:1433/demo
spring.r2dbc.username=nonspring@$AZ_DATABASE_NAME
spring.r2dbc.password=$AZ_SQL_SERVER_NON_ADMIN_PASSWORD

두 개의 $AZ_DATABASE_NAME 변수와 $AZ_SQL_SERVER_NON_ADMIN_PASSWORD 변수를 이 문서의 시작 부분에서 구성한 값으로 바꿉니다.

참고 항목

성능을 향상시키려면 spring.r2dbc.url r2dbc-pool을 사용하여 연결 풀을 사용하도록 속성이 구성됩니다.

이제 제공된 Maven 래퍼를 사용하여 다음과 같이 애플리케이션을 시작할 수 있습니다.

./mvnw spring-boot:run

처음으로 실행 중인 이 애플리케이션의 스크린샷은 다음과 같습니다.

Screenshot of the running application.

데이터베이스 스키마 만들기

기본 DemoApplication 클래스 내에서 다음 코드를 사용하여 데이터베이스 스키마를 만드는 새 Spring bean을 구성합니다.

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.r2dbc.connectionfactory.init.ConnectionFactoryInitializer;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;

import io.r2dbc.spi.ConnectionFactory;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
        ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
        initializer.setConnectionFactory(connectionFactory);
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
        initializer.setDatabasePopulator(populator);
        return initializer;
    }
}

이 Spring bean은 schema.sql이라는 파일을 사용하므로 src/기본/resources 폴더에 해당 파일을 만들고 다음 텍스트를 추가합니다.

DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id INT IDENTITY PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BIT);

다음 명령을 사용하여 실행 중인 애플리케이션을 중지하고 다시 시작합니다. 이제 애플리케이션이 이전에 생성된 demo 데이터베이스를 사용하고 내부에 todo 테이블을 만듭니다.

./mvnw spring-boot:run

생성되는 데이터베이스 테이블의 스크린샷은 다음과 같습니다.

Screenshot of the creation of the database table.

애플리케이션 코딩

다음으로, R2DBC를 사용하여 Azure SQL Database 서버에서 데이터를 저장하고 검색하는 Java 코드를 추가합니다.

다음 코드를 사용하여 클래스 옆에 DemoApplicationTodo Java 클래스를 만듭니다.

package com.example.demo;

import org.springframework.data.annotation.Id;

public class Todo {

    public Todo() {
    }

    public Todo(String description, String details, boolean done) {
        this.description = description;
        this.details = details;
        this.done = done;
    }

    @Id
    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;
    }
}

이 클래스는 이전에 만든 테이블에 매핑된 todo do기본 모델입니다.

해당 클래스를 관리하려면 리포지토리가 필요합니다. 다음 코드를 사용하여 동일한 패키지에 새 TodoRepository 인터페이스를 정의합니다.

package com.example.demo;

import org.springframework.data.repository.reactive.ReactiveCrudRepository;

public interface TodoRepository extends ReactiveCrudRepository<Todo, Long> {
}

이 리포지토리는 Spring Data R2DBC에서 관리하는 반응형 리포지토리입니다.

데이터를 저장하고 검색할 수 있는 컨트롤러를 만들어 애플리케이션을 완료합니다. TodoController 동일한 패키지에서 클래스를 구현하고 다음 코드를 추가합니다.

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/")
public class TodoController {

    private final TodoRepository todoRepository;

    public TodoController(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @PostMapping("/")
    @ResponseStatus(HttpStatus.CREATED)
    public Mono<Todo> createTodo(@RequestBody Todo todo) {
        return todoRepository.save(todo);
    }

    @GetMapping("/")
    public Flux<Todo> getTodos() {
        return todoRepository.findAll();
    }
}

마지막으로, 다음 명령을 사용하여 애플리케이션을 중지하고 다시 시작합니다.

./mvnw spring-boot:run

애플리케이션 테스트

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

먼저 다음 명령을 사용하여 데이터베이스에 새 "todo" 항목을 만듭니다.

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done": "true"}' \
    http://127.0.0.1:8080

이 명령은 다음과 같이 만든 항목을 반환해야 합니다.

{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}

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

curl http://127.0.0.1:8080

이 명령은 다음과 같이 만든 항목을 포함하여 "todo" 항목 목록을 반환합니다.

[{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}]

다음은 이러한 cURL 요청의 스크린샷입니다.

Screenshot of the cURL test.

축하합니다! R2DBC를 사용하여 Azure SQL Database에서 데이터를 저장하고 검색하는 완전한 반응형 Spring Boot 애플리케이션을 만들었습니다.

리소스 정리

이 빠른 시작 중에 사용되는 모든 리소스를 클린 다음 명령을 사용하여 리소스 그룹을 삭제합니다.

az group delete \
    --name $AZ_RESOURCE_GROUP \
    --yes

다음 단계

Spring Data 애플리케이션을 Azure Spring Apps에 배포하고 관리 ID를 사용하는 방법에 대한 자세한 내용은 자습서: Azure 데이터베이스에 암호 없는 연결을 사용하여 Azure Spring Apps에 Spring 애플리케이션 배포를 참조하세요.

Spring 및 Azure에 대해 자세히 알아보려면 Spring on Azure 설명서 센터를 계속 진행하세요.

참고 항목

Spring Data R2DBC에 대한 자세한 내용은 Spring의 참조 설명서를 참조하세요.

Java와 함께 Azure를 사용하는 방법에 관한 자세한 정보는 Java 개발자를 위한 AzureAzure DevOps 및 Java 사용하기를 참조하세요.