1. 개요
Cloud Spanner는 가용성이 높고 수평적으로 확장 가능한 멀티 리전 RDBMS입니다. 이 Codelab에서는 가장 작은 Cloud Spanner 인스턴스를 사용하지만 작업이 끝나면 종료하는 것을 잊지 마세요.
학습할 내용
- Spring Boot에서 Cloud Spanner를 사용하여 데이터를 저장하고 검색하는 방법
필요한 항목
본 가이드를 어떻게 사용하실 계획인가요?
귀하의 Google Cloud Platform 서비스 사용 경험을 평가해 주세요.
<ph type="x-smartling-placeholder">2. 설정 및 요구사항
자습형 환경 설정
- Cloud Console에 로그인하고 새 프로젝트를 만들거나 기존 프로젝트를 다시 사용합니다. (Gmail 또는 G Suite 계정이 없으면 만들어야 합니다.)
모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID
라고 부릅니다.
- 그런 후 Google Cloud 리소스를 사용할 수 있도록 Cloud Console에서 결제를 사용 설정해야 합니다.
이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 가이드를 마친 후 비용이 결제되지 않도록 리소스 종료 방법을 알려주는 '삭제' 섹션의 안내를 따르세요. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.
Cloud Shell 활성화
- Cloud Console에서 Cloud Shell 활성화를 클릭합니다.
이전에 Cloud Shell을 시작하지 않았으면 설명이 포함된 중간 화면(스크롤해야 볼 수 있는 부분)이 제공됩니다. 이 경우 계속을 클릭합니다(이후 다시 표시되지 않음). 이 일회성 화면은 다음과 같습니다.
Cloud Shell을 프로비저닝하고 연결하는 데 몇 분 정도만 걸립니다.
가상 머신은 필요한 모든 개발 도구와 함께 로드됩니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab에서 대부분의 작업은 브라우저나 Chromebook만 사용하여 수행할 수 있습니다.
Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 해당 프로젝트 ID로 이미 설정된 것을 볼 수 있습니다.
- Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list
명령어 결과
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
명령어 결과
[core] project = <PROJECT_ID>
또는 다음 명령어로 설정할 수 있습니다.
gcloud config set project <PROJECT_ID>
명령어 결과
Updated property [core/project].
3. Cloud Spanner 초기화
gcloud CLI를 사용하여 Cloud Spanner API를 사용 설정합니다.
gcloud services enable spanner.googleapis.com
Cloud Spanner 인스턴스를 만듭니다.
gcloud spanner instances create spanner-instance \ --config=regional-us-central1 \ --nodes=1 --description="A Spanner Instance"
인스턴스 내에 데이터베이스를 만듭니다.
gcloud spanner databases create orders \ --instance=spanner-instance
데이터 스키마를 설명하는 schema.ddl
파일을 만듭니다.
cat << EOF > schema.ddl CREATE TABLE orders ( order_id STRING(36) NOT NULL, description STRING(255), creation_timestamp TIMESTAMP, ) PRIMARY KEY (order_id); CREATE TABLE order_items ( order_id STRING(36) NOT NULL, order_item_id STRING(36) NOT NULL, description STRING(255), quantity INT64, ) PRIMARY KEY (order_id, order_item_id), INTERLEAVE IN PARENT orders ON DELETE CASCADE; EOF
Cloud Spanner 데이터베이스에 스키마를 적용합니다.
gcloud spanner databases ddl update orders \ --instance=spanner-instance \ --ddl="$(<schema.ddl)"
4. 새 Spring Boot Java 애플리케이션 부트스트랩
Cloud Shell 환경에서 다음 명령어를 사용하여 새 Spring Boot 애플리케이션을 초기화하고 부트스트랩합니다.
$ curl https://start.spring.io/starter.tgz \ -d packaging=jar \ -d dependencies=cloud-gcp,web,lombok \ -d baseDir=spanner-example \ -d type=maven-project \ -d bootVersion=3.2.6 | tar -xzvf - $ cd spanner-example
이렇게 하면 새 Maven 프로젝트와 Maven의 pom.xml
, Maven 래퍼, 애플리케이션 진입점이 있는 새 spanner-example/
디렉터리가 생성됩니다.
pom.xml
파일에서 Spring Data Cloud Spanner 시작 조건을 추가합니다.
spanner-example/pom.xml
<project>
...
<dependencies>
...
<!-- Add Spring Cloud GCP Spanner Starter -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
</dependency>
...
</dependencies>
...
</project>
application.properties에서 Spanner 데이터베이스 연결 정보를 구성합니다.
spanner-example/src/main/resources/application.properties
spring.cloud.gcp.spanner.instance-id=spanner-instance spring.cloud.gcp.spanner.database=orders
JAVA_HOME
이 올바른 버전으로 설정되어 있는지 확인합니다.
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/
앱을 다시 빌드하여 Maven 구성이 올바른지 확인합니다.
./mvnw package
5. 항목 만들기
Spring Cloud GCP의 Spring Data Spanner 지원으로 Spring Data를 통해 쉽게 Java 객체를 만들고 Spanner 테이블에 대한 관용적인 ORM 매핑을 만들 수 있습니다.
먼저 주문 항목 클래스를 만듭니다.
spanner-example/src/main/java/com/example/demo/OrderItem.java
package com.example.demo;
import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;
@Table(name="order_items")
@Data
class OrderItem {
@PrimaryKey(keyOrder = 1)
@Column(name="order_id")
private String orderId;
@PrimaryKey(keyOrder = 2)
@Column(name="order_item_id")
private String orderItemId;
private String description;
private Long quantity;
}
Spanner의 상위/하위 관계의 경우 복합 기본 키를 사용해야 합니다. 이 예에서 복합 키는 order_id
와 order_item_id
입니다.
다음으로 Order 클래스를 만듭니다.
spanner-example/src/main/java/com/example/demo/Order.java
package com.example.demo;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.Interleaved;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;
@Table(name="orders")
@Data
public class Order {
@PrimaryKey
@Column(name="order_id")
private String id;
private String description;
@Column(name="creation_timestamp")
private LocalDateTime timestamp;
@Interleaved
private List<OrderItem> items;
}
이 클래스는 @Interleaved
주석을 사용하여 주문 항목과 일대다 관계를 만듭니다.
6. OrderRepository 인터페이스 만들기
다음 콘텐츠로 OrderRepository
클래스를 만듭니다.
spanner-example/src/main/java/com/example/demo/OrderRepository.java
package com.example.demo;
import com.google.cloud.spring.data.spanner.repository.SpannerRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface OrderRepository extends SpannerRepository<Order, String> {
}
인터페이스는 SpannerRepository<Order, String>
를 확장합니다. 여기서 Order
는 도메인 클래스이고 String
는 기본 키 유형입니다. Spring Data는 이 인터페이스를 통해 자동으로 CRUD 액세스를 제공하므로 추가 코드를 만들 필요가 없습니다.
7. 기본 작업을 위한 REST 컨트롤러 만들기
기본 애플리케이션 DemoApplication
클래스를 열고 다음과 같이 수정합니다.
spanner-example/src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;
import java.time.LocalDateTime;
import java.util.UUID;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@RestController
class OrderController {
private final OrderRepository orderRepository;
OrderController(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@GetMapping("/api/orders/{id}")
public Order getOrder(@PathVariable String id) {
return orderRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, id + " not found"));
}
@PostMapping("/api/orders")
public String createOrder(@RequestBody Order order) {
// Spanner currently does not auto generate IDs
// Generate UUID on new orders
order.setId(UUID.randomUUID().toString());
order.setTimestamp(LocalDateTime.now());
order.getItems().forEach(item -> {
// Assign parent ID, and also generate child ID
item.setOrderId(order.getId());
item.setOrderItemId(UUID.randomUUID().toString());
});
Order saved = orderRepository.save(order);
return saved.getId();
}
}
8. 애플리케이션 실행
애플리케이션을 다시 빌드하고 실행합니다.
./mvnw spring-boot:run
그러면 제대로 시작되고 포트 8080에서 수신 대기해야 합니다.
엔드포인트에 주문 레코드를 게시할 수 있습니다.
curl -H"Content-Type: application/json" -d'{"description": "My orders", "items": [{"description": "Android Phone", "quantity": "1"}]}' \ http://localhost:8080/api/orders
주문의 UUID
로 응답해야 합니다.
그런 다음 UUID
를 사용하여 주문을 검색할 수 있습니다.
curl http://localhost:8080/api/orders/REPLACE_WITH_ORDER_UUID
Cloud Spanner 데이터가 저장되는 방식을 확인하려면 Cloud 콘솔로 이동하여 Spanner → Spanner 인스턴스 → 주문 데이터베이스 → 주문 테이블 → 데이터로 이동합니다.
9. 삭제
삭제하려면 더 이상 요금이 발생하지 않도록 Spanner 인스턴스를 삭제하세요.
gcloud spanner instances delete spanner-instance -q
10. 축하합니다.
이 Codelab에서는 Cloud Spanner에서 데이터를 저장하고 검색할 수 있는 대화형 CLI 애플리케이션을 만들었습니다.
자세히 알아보기
- Cloud Spanner: https://cloud.google.com/spanner/
- GCP의 Spring 프로젝트: https://googlecloudplatform.github.io/spring-cloud-gcp/reference/html/
- GCP의 Spring GitHub 저장소: https://github.com/spring-cloud/spring-cloud-gcp
- Google Cloud Platform의 자바: https://cloud.google.com/java/
라이선스
이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.