Docs Menu
Docs Home
/ /

튜토리얼: Spring Boot와 통합

Spring Boot는 프로덕션용 애플리케이션 개발을 간소화하는 오픈 소스 Java 프레임워크 입니다.Spring Data MongoDB 와 결합된 이 프레임워크 MongoDB 데이터베이스와 효율적으로 상호 작용 수 있는 방법을 제공합니다.

이 튜토리얼에서는 Spring Data MongoDB 사용하여 MongoDB database 에서 작업을 수행하는 반응형 Spring Boot 애플리케이션 빌드 방법을 보여줍니다. 이 샘플 현금 잔액 애플리케이션 사용하여 다음 작업을 수행하는 REST API를 호출할 수 있습니다.

  • 계정 만들기 또는 가져오기

  • 한 계정에서 또는 두 계정 간에 거래 수행

Spring Data MongoDB MongoDB 에 대한 리포지토리 지원 제공하여 데이터베이스 와 상호 작용 하는 두 가지 프라이머리 방법을 제공합니다.

  • ReactiveMongoRepository: 일반적인 데이터베이스 작업에 대한 액세스 제공하는 상위 수준 추상화입니다.

  • ReactiveMongoTemplate: MongoDB 작업 및 쿼리 구성에 대한 더 많은 제어를 제공하는 하위 수준 추상화입니다.

MongoDB 다중 문서 ACID 트랜잭션을 지원하므로 원자성, 일관성, 격리 및 내구성 보장 충족하는 여러 작업을 수행할 수 있습니다. Spring Data MongoDB @Transactional 주석 또는 TransactionalOperator 클래스를 통해 트랜잭션에 대한 내장 지원 제공합니다. 이 튜토리얼의 샘플 애플리케이션 데이터베이스 작업의 원자성을 보장하기 위해 트랜잭션 지원 구성합니다.

MongoDB 트랜잭션에 대해 자세히 학습 MongoDB Server 매뉴얼의 트랜잭션을 참조하세요.

이 튜토리얼에서는 간소화된 현금 잔액 시스템을 구현하는 예시 애플리케이션 다운로드 방법을 보여줍니다. 이 애플리케이션 사용하면 은행 계좌 잔액을 생성, 조회 및 업데이트 할 수 있습니다. 전체 애플리케이션 보려면 mdb-spring-boot-reactive GitHub 리포지토리 참조하세요.

튜토리얼을 완료하여 다음 조치를 수행하는 방법을 학습 .

  • 예시 Spring Boot 애플리케이션 다운로드

  • MongoDB 에 연결하도록 애플리케이션 구성

  • 애플리케이션 구조 및 주요 구성 요소 이해

  • 애플리케이션을 실행합니다.

  • 은행 계좌를 생성하고 트랜잭션을 수행하기 위해 POST 요청을 보냅니다.

1

이 튜토리얼을 시작하기 전에 다음 구성 요소가 준비되어 있는지 확인하십시오.

2

다음 명령을 실행 하여 MongoDB 개발자 GitHub 리포지토리 에서 예시 애플리케이션 복제합니다.

git clone git@github.com:mongodb-developer/mdb-spring-boot-reactive.git

이 리포지토리 Spring Data MongoDB 사용하여 MongoDB database 와 상호 작용 반응형 Spring Boot 애플리케이션 포함되어 있습니다.

3

예시 애플리케이션 디렉토리 에서 src/main/resources/application.properties 파일 로 이동합니다. 이 파일 에서 다음 코드와 같이 spring.data.mongodb.uri 속성 Atlas 연결 URI로 설정하다 .

spring.data.mongodb.uri=<connection URI>

<connection URI> 자리 표시자를 Atlas 연결 URI로 바꿉니다.

4

루트 디렉토리 에서 다음 명령을 실행 애플리케이션 에 대한 스키마 유효성 검사 설정하다 합니다.

mongosh "<connection URI>" --file setup.js

이 명령은 은행 계좌 잔액이 0 미만이 되지 않도록 하는 제약 조건을 생성합니다. <connection URI> 자리 표시자를 Atlas 연결 URI로 바꿉니다.

1

AccountController.java 파일 계정을 만들고 가져오기 위한 REST API 엔드포인트가 포함되어 있습니다. 이 파일 txn-demo.accounts 컬렉션 에 문서 삽입하는 POST 메서드 엔드포인트와 accountNum 값을 기반으로 문서 찾는 GET 메서드 엔드포인트를 정의합니다. 다음 코드는 이러한 메서드를 보여줍니다.

@RestController
public class AccountController {
//...
@PostMapping("/account")
public Mono<Account> createAccount(@RequestBody Account account) {
return accountRepository.save(account);
}
@GetMapping("/account/{accountNum}")
public Mono<Account> getAccount(@PathVariable String accountNum) {
return accountRepository.findByAccountNum(accountNum)
.switchIfEmpty(Mono.error(new AccountNotFoundException()));
}
//...
}

각 엔드포인트는 기본 Java Reactive Streams 운전자 에서 추상화 역할을 하는 ReactiveMongoRepository 인터페이스인 AccountRepository에서 Mono<Account> 유형을 반환합니다.

2

AccountController 클래스에는 다음 트랜잭션 엔드포인트도 포함되어 있습니다.

  • 계정 잔액에 추가되는 .../debit 엔드포인트

  • 계정 잔액에서 차감하는 .../credit 엔드포인트

  • 한 계정에서 다른 계정으로 전송을 수행하는 .../transfer 엔드포인트

이러한 엔드포인트에는 다음과 같은 정의가 있습니다.

@RestController
public class AccountController {
//...
@PostMapping("/account/{accountNum}/debit")
public Mono<Txn> debitAccount(@PathVariable String accountNum,
@RequestBody Map<String, Object> requestBody) {
//...
txn.addEntry(new TxnEntry(accountNum, amount));
return txnService.saveTransaction(txn).flatMap(txnService::executeTxn);
}
@PostMapping("/account/{accountNum}/credit")
public Mono<Txn> creditAccount(@PathVariable String accountNum,
@RequestBody Map<String, Object> requestBody) {
//...
txn.addEntry(new TxnEntry(accountNum, -amount));
return txnService.saveTransaction(txn).flatMap(txnService::executeTxn);
}
@PostMapping("/account/{from}/transfer")
public Mono<Txn> transfer(@PathVariable String from,
@RequestBody TransferRequest transferRequest) {
//...
txn.addEntry(new TxnEntry(from, -amount));
txn.addEntry(new TxnEntry(to, amount));
return txnService.saveTransaction(txn).flatMap(txnService::executeTxn);
}
//...
}

하나의 TxnEntry 객체 단일 계정에 대한 변경 사항을 나타내며, Txn 는 하나 또는 여러 개의 TxnEntry 객체로 구성될 수 있습니다. 샘플 코드에서 차변 및 크레딧 엔드포인트는 하나의 새 TxnEntry 객체 생성하고 전송 엔드포인트는 두 개의 TxnEntry 객체를 생성합니다.

3

AccountRepository 인터페이스는 ReactiveMongoRepository 을 확장하고 다음 쿼리 메서드를 정의합니다.

public interface AccountRepository extends ReactiveMongoRepository<Account, String> {
@Query("{accountNum:'?0'}")
Mono<Account> findByAccountNum(String accountNum);
@Update("{'$inc':{'balance': ?1}}")
Mono<Long> findAndIncrementBalanceByAccountNum(String accountNum, double increment);
}

이 코드는 MongoDB 쿼리 때 메서드 인수로 동적으로 대체되는 자리 표시자를 사용할 수 있도록 하는 다음 주석을 사용합니다.

  • @Query: findByAccountNum() 메서드에 주석을 달고 문서를 찾기 위한 쿼리 기준을 지정합니다. ?0 자리 표시자는 accountNum 매개 변수 값으로 대체됩니다.

  • @Update: findAndIncrementBalanceByAccountNum() 메서드에 주석을 달고 일치하는 문서에 수행할 업데이트 작업을 지정합니다. ?1 자리 표시자가 increment 매개 변수 값으로 대체되어 MongoDB의 $inc 연산자 사용하여 잔액을 늘릴 수 있습니다.

참고

이전 단계에서 설명한 POST 엔드포인트는 메서드를 사용하지만 accountRepository.save() 이 메서드를 정의할 필요는 없습니다.save() 메서드 및 기타 많은 기본 메서드는 의 상속 체인에 있는 인터페이스에 의해 이미 선언되어 있습니다.ReactiveMongoRepository

4

TxnService 클래스는 트랜잭션 실행을 처리합니다. 이 클래스에는 다음 코드가 포함되어 있습니다.

@Service
public class TxnService {
//...
public Mono<Txn> saveTransaction(Txn txn) {
return txnTemplate.save(txn);
}
public Mono<Txn> executeTxn(Txn txn) {
return updateBalances(txn)
.onErrorResume(DataIntegrityViolationException.class
/*lambda expression to handle error*/)
.onErrorResume(AccountNotFoundException.class
/*lambda expression to handle error*/)
.then(txnTemplate.findAndUpdateStatusById(txn.getId(), TxnStatus.SUCCESS));
}
public Flux<Long> updateBalances(Txn txn) {
Flux<Long> updatedCounts = Flux.fromIterable(txn.getEntries()).concatMap(
entry -> accountRepository.findAndIncrementBalanceByAccountNum(
entry.getAccountNum(), entry.getAmount())
);
return updatedCounts.handle(/*...*/);
}
}

TxnService 클래스에는 다음 메서드가 포함되어 있습니다.

  • saveTransaction(): Txn 문서 transactions 컬렉션 에 저장합니다.

  • executeTxn(): updateBalances() 메서드를 호출한 다음 Txn 문서 에서 트랜잭션 상태를 업데이트합니다.

  • updateBalances(): 각 TxnEntry 를 반복하고 각 account 문서 에 해당하는 업데이트를 수행합니다.

5

이전 단계에서 설명한 saveTransaction()executeTxn() 메서드는 모두 TxnTemplate 클래스에 정의된 메서드를 사용합니다. 이러한 메서드에는 다음과 같은 정의가 있습니다.

@Service
public class TxnTemplate {
//...
public Mono<Txn> save(Txn txn) {
return template.save(txn);
}
public Mono<Txn> findAndUpdateStatusById(String id, TxnStatus status) {
Query query = query(where("_id").is(id));
Update update = update("status", status);
FindAndModifyOptions options = FindAndModifyOptions.options().returnNew(true);
return template.findAndModify(query, update, options, Txn.class);
}
//...
}

이러한 메서드는 ReactiveMongoTemplate를 사용하여 MongoDB 와 상호 작용 .

6

계정 간에 돈을 이체할 때 다중 문서 트랜잭션 사용할 수 있습니다. 두 계정에 대한 업데이트는 원자적이어야 하며 트랜잭션은 데이터 원자성을 보장합니다.

Spring의 트랜잭션 지원 액세스 위해 샘플 애플리케이션 ReactiveMongoConfig.java 파일 에 ReactiveMongoTransactionManager 빈을 추가합니다.

@Configuration
public class ReactiveMongoConfig extends AbstractReactiveMongoConfiguration {
//...
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
}

TransactionalOperator 객체 또는 @Transactional 주석을 사용하여 트랜잭션 의 범위를 정의할 수 있습니다. TxnService 클래스는 두 가지 접근 방식을 모두 보여줍니다.

Spring 데이터 트랜잭션

Spring Data MongoDB 의 트랜잭션 및 세션에 대해 자세히 학습 Spring Data 문서에서 세션 & 트랜잭션을 참조하세요.

1

애플리케이션 시작하려면 프로젝트의 루트 디렉토리 에서 다음 명령을 실행 .

mvn spring-boot:run

애플리케이션 시작한 후 http://localhost:8080에서 액세스 할 수 있습니다. 그런 다음 REST API 엔드포인트를 사용하여 계정을 생성하고 트랜잭션을 수행할 수 있습니다.

2

계정 번호가 12345인 새 은행 계좌를 만들려면 셸 에서 다음 명령을 실행 .

curl --location 'localhost:8080/account' \
--header 'Content-Type: application/json' \
--data '{
"accountNum": "12345"
}'

이 명령은 /account 엔드포인트에 POST 요청 전송하여 accounts 컬렉션 에 새 은행 계좌 문서 생성합니다.

3

이전 단계에서 만든 계정에 금액을 입금하려면 셸 에서 다음 명령을 실행 .

curl --location 'localhost:8080/account/12345/debit' \
--header 'Content-Type: application/json' \
--data '{
"amount": 1000
}'

이 명령은 해당 account 문서 의 amount 값을 1000만큼 늘리라는 요청 .../debit 엔드포인트로 보냅니다.

4

한 계정에서 다른 계정으로 돈을 이체하려면 계정 번호가 67890인 새 계정을 만듭니다.

curl --location 'localhost:8080/account' \
--header 'Content-Type: application/json' \
--data '{
"accountNum": "67890"
}'

그런 다음 다음 명령을 실행 하여 500 달러를 이 새 계정으로 이체합니다.

curl --location 'localhost:8080/account/12345/transfer' \
--header 'Content-Type: application/json' \
--data '{
"to": "67890",
"amount": 500
}'

이 명령은 잔액 이체를 완료하기 위해 .../transfer 엔드포인트에 요청 보냅니다.

Spring Data MongoDB 에 대해 자세히 학습 Spring Data MongoDB 참고 문서를 참조하세요.

전체 예시 애플리케이션 보려면 mdb-spring-boot-reactive GitHub 리포지토리 참조하세요.

돌아가기

사용 중 암호화

이 페이지의 내용