chap 12 - JAVA-JIKIMI/SPRING-IN-ACTION-5 GitHub Wiki
์ด์ ์๋ ์คํ๋ง WebFlux๋ฅผ ์ฌ์ฉํด์ ๋ฆฌ์กํฐ๋ธํ๊ณ ๋ธ๋กํน์ด ์๋ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์๋ค.
๊ทธ๋ฌ๋ ๊ฐ์ด ์๋๋๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ ๋ธ๋กํน์ด ์์ด์ผ ์ง์ ํ ๋ธ๋กํน ์๋ ์ปจํธ๋กค๋ฌ๊ฐ ๋ ์ ์๋ค.
๋ง์ผ ๋ธ๋กํน ๋๋ ๋ฆฌํผ์งํฐ๋ฆฌ์ ์์กดํ๋ ์คํ๋ง WebFlux ๋ฆฌ์กํฐ๋ธ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ๋ค๋ฉด, ์ด ์ปจํธ๋กค๋ฌ๋ ํด๋น ๋ฆฌํผ์งํฐ๋ฆฌ์ ๋ฐ์ดํฐ ์์ฑ์ ๊ธฐ๋ค๋ฆฌ๋๋ผ ๋ธ๋กํน๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์ปจํธ๋กค๋ฌ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ด๋ฅด๊ธฐ๊น์ง ๋ฐ์ดํฐ์ ์ ์ฒด flow๊ฐ ๋ฆฌ์กํฐ๋ธํ๊ณ ๋ธ๋กํน๋์ง ์๋ ๊ฒ์ด ์ค์ํ๋ค.
์คํ๋ง ๋ฐ์ดํฐ๋ Kay ๋ฆด๋ฆฌ์ฆ ํธ๋ ์ธ๋ถํฐ Reactvie Repository์ ์ง์์ ์ ๊ณตํ๊ธฐ ์์ํ๋ค.
Reactvie Repository๋ ์นด์ฐ๋๋ผ, ๋ชฝ๊ณ DB, ์นด์ฐ์น๋ฒ ์ด์ค, Redis ๋ฑ์ ์ง์ํ๋ค.
ํ์ง๋ง RDB๋ JPA๋ ์ง์ํ์ง ์๋๋ฐ, ์ด๋ค์ ํ์คํ๋ ๋น๋๊ธฐ API๋ฅผ ์ ๊ณตํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ผ์ ์์ผ๋ก ์นด์ฐ๋๋ผ์ ๋ชฝ๊ณ DB๋ฅผ ์ด์ฉํ์ฌ ์คํ๋ง ๋ฐ์ดํฐ ๋ฆฌ์กํฐ๋ธ๋ฅผ ์ฌ์ฉํด๋ณผ ๊ฒ์ด๋ค.
์คํ๋ง ๋ฐ์ดํฐ ๋ฆฌ์กํฐ๋ธ ๊ฐ์
Reactvie Repository๋ ๋๋ฉ์ธ ํ์ ์ด๋ ์ปฌ๋ ์ ๋์ , Mono๋ Flux๋ฅผ ์ธ์๋ก ๋ฐ๊ฑฐ๋ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ๊ฐ๋๋ค.
๋ฆฌ์กํฐ๋ธ์ ๋ฆฌ์กํฐ๋ธ๊ฐ ์๋ ํ์ ๊ฐ์ ๋ณํ
๊ธฐ์กด์ RDB๋ฅผ ์ฌ์ฉ์ค์ผ ๋๋ Reactive Programming์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉํ ์ ์๋ค.
RDB๊ฐ ๋ธ๋กํน ์๋ Reactive Query๋ฅผ ์ง์ํ์ง ์๋๋ผ๋, ์ฐ์ ๋ธ๋กํน ๋๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ๊ฐ๋ฅํ ๋นจ๋ฆฌ ๋ฆฌ์กํฐ๋ธ ํ์ ์ผ๋ก ๋ณํํ์ฌ ์์ ์ปดํฌ๋ํธ๋ค์ด Reactive์ ์ฅ์ ์ ํ์ฉํ๊ฒ ํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, RDB์ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํด๋ณด์. ์ด ๊ฒฝ์ฐ OrderRepository๋ ๋ค์๊ณผ ๊ฐ์ ์๊ทธ๋์ฒ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง ์ ์๋ค.
List<Order> findByUser(User user);
์ด findByUser()๋ ๋ธ๋กํน ๋ฐฉ์์ผ๋ก ๋์ํ๋ค. ์๋ํ๋ฉด List๊ฐ Reactive ํ์ ์ด ์๋๋ฏ๋ก ์ด๋ค Reactive ์คํผ๋ ์ด์ ๋ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ฒ๋ค๊ฐ ์ปจํธ๋กค๋ฌ๊ฐ findByUser()๋ฅผ ํธ์ถํ๋ค๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ์กํฐ๋ธํ๊ฒ ์ฌ์ฉํ ์ ์์ด ํ์ฅ์ฑ์ ํฅ์์ํฌ ์ ์๋ค.
์ด ๊ฒฝ์ฐ์ ๊ฐ๋ฅํ ๋นจ๋ฆฌ Reactive๊ฐ ์๋ List๋ฅผ Flux๋ก ๋ณํํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๋ค.
List<Order> orders = repo.findByUser(someUser);
Flux<Order> orderFlux = Flux.fromIterable(orders);
Mono๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ์๋์ ๊ฐ์ด ์์ฑํ๋ฉด ๋๋ค.
Order order = repo.findById(id);
Mono<Order> orderFlux = Mono.just(order);
์ด์ฒ๋ผ Mono์ just()๋ Flux์ fromIterable(), fromArray(), fromStream()์ ์ฌ์ฉํ๋ฉด Repository์ Reactive๊ฐ ์๋ ๋ธ๋กํน ์ฝ๋๋ฅผ ๊ฒฉ๋ฆฌ์ํค๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋์๋ Reactive ํ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ฒ ํ ์ ์๋ค.
์ด๋ฒ์ ์ ์ฅํ๋ ๊ฒฝ์ฐ์ ๋ํด์ ์ดํด๋ณด์. Mono๋ Flux ๋ชจ๋ ์์ ๋ค์ด ๋ฐํํ๋ ๋ฐ์ดํฐ๋ฅผ ๋๋ฉ์ธ ํ์ ์ด๋ Iterable ํ์ ์ผ๋ก ์ถ์ถํ๋ ์คํผ๋ ์ด์ ์ ๊ฐ์ง๊ณ ์๋ค.
Taco taco = tacoMono.block();
tacoRepo.save(taco);
Iterable<Taco> tacos = tacoFlux.toIterable();
tacoRepo.saveAll(tacos);
Mono์ block()์ด๋ Flux์ toIterable()์ ์ถ์ถ ์์ ์ ํ ๋ ๋ธ๋กํน์ด ๋๋ค. ๋ฐ๋ผ์ ์ด๋ฐ์์ Mono์ Flux๋ฅผ ์ฌ์ฉ์ ์ต์ํ ํด์ผ ํ๋ค.
๋ธ๋กํน๋๋ ํ์ ์ ๋ Reactiveํ๊ฒ ์ถ์ถ ํ ์๋ ์๋ค. Mono๋ Flux๋ฅผ ๊ตฌ๋ ํ๋ฉด์ ๋ฐํ๋๋ ์์ ๊ฐ๊ฐ์ ๋ํด ์ํ๋ ์คํผ๋ ์ด์ ์ ์ํํ๋ ๊ฒ์ด๋ค.
tacoFlux.subscribe(
taco -> {
tacoRepo.save(taco);
}
);
tacoRepo์ save๋ ์ฌ์ ํ ๋ธ๋กํน ์คํผ๋ ์ด์ ์ด๋ค.
๊ทธ๋ฌ๋ Flux๋ Mono๊ฐ ๋ฐํํ๋ ๋ฐ์ดํฐ๋ฅผ ์๋นํ๊ณ ์ฒ๋ฆฌํ๋ Reactive ๋ฐฉ์์ subscribe()๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ๋ธ๋กํน ๋ฐฉ์์ ์ผ๊ด์ฒ๋ฆฌ๋ณด๋ค๋ ๋ ๋ฐ๋์งํ๋ค.
NoSql ์ค ํ๋์ธ ๋ชฝ๊ณ DB๋ ๋ฌธ์ํ DB๋ค. ๋ชฝ๊ณ DB๋ BSON(Binary JSON) ํ์์ ๋ฌธ์๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฉฐ, ๋ค๋ฅธ DB์์ ๋ฐ์ดํฐ๋ฅผ ์ฟผ๋ฆฌํ๋ ๊ฒ๊ณผ ๊ฑฐ์ ์ ์ฌํ ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์๋ฅผ ์ฟผ๋ฆฌํ๊ฑฐ๋ ๊ฒ์ํ ์ ์๋ค.
๋ชฝ๊ณ DB๋ฅผ ์คํ๋ง ๋ฐ์ดํฐ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ JPA๋ฅผ ์คํ๋ง ๋ฐ์ดํฐ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์๋ค.
์ฆ, ๋๋ฉ์ธ ํ์ ์ ๋ฌธ์ ๊ตฌ์กฐ๋ก ๋งคํํ๋ ์ ๋ ธํ ์ด์ ์ ๋๋ฉ์ธ ํด๋์ค์ ์ง์ ํ๋ค.
๊ทธ๋ฆฌ๊ณ JPA์ ๋์ผํ ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ์ ๋ฐ๋ฅด๋ Repository Interface๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
์คํ๋ง ๋ฐ์ดํฐ ๋ชฝ๊ณ DB ํ์ฑํํ๊ธฐ ๋ฆฌ์กํฐ๋ธ ์คํ๋ง ๋ฐ์ดํฐ ๋ชฝ๊ณ DB ์คํํฐ ์์กด์ฑ์ ์ถ๊ฐํ์.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
์ด๋ ๊ฒ ๋น๋์ ์์กด์ฑ์ ์ถ๊ฐํ๋ฉด ์คํ๋ง ๋ฐ์ดํฐ ๋ฆฌ์กํฐ๋ธ ๋ชฝ๊ณ DB ์ง์์ ํ์ฑํํ๋ ์๋-๊ตฌ์ฑ์ด ์ํ๋๋ค. (Repository Interface ์๋ ๊ตฌํ)
์คํ๋ง ๋ฐ์ดํฐ ๋ชฝ๊ณ DB๋ ๊ธฐ๋ณธ์ ์ผ๋ก 27017 ํฌํธ๋ฅผ ๋ฆฌ์ค๋ํ๋ค.
๊ทธ๋ฌ๋ ํ ์คํธ์ ๊ฐ๋ฐ์ ํธ๋ฆฌํ๋๋ก in-memory ๋ด์ฅ ๋ชฝ๊ณ DB๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค. ์๋์ ๊ฐ์ด Flapdoodle ์์กด์ฑ์ ๋น๋์ ์ถ๊ฐํ๋ค.
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
</dependency>
๋๋ฉ์ธ ํ์ ์ ๋ฌธ์๋ก ๋งคํํ๊ธฐ ์คํ๋ง ๋ฐ์ดํฐ ๋ชฝ๊ณ DB๋ ๋ชฝ๊ณ DB์ ์ ์ฅ๋๋ ๋ฌธ์ ๊ตฌ์กฐ๋ก ๋๋ฉ์ธ ํ์ ์ ๋งคํํ๋ ๋ฐ ์ ์ฉํ ์ ๋ ธํ ์ด์ ๋ค์ ์ ๊ณตํ๋ค.
๊ทธ ์ค ์๋ 3๊ฐ๊ฐ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ค.
@Id : ์ง์ ๋ ์์ฑ์ ๋ฌธ์ ID๋ก ์ง์ ํ๋ค. Serializable ํ์
์ธ ์ด๋ค ์์ฑ์๋ ์ง์ ํ ์ ์๋ค.
@Document : ์ง์ ๋ ๋๋ฉ์ธ ํ์
์ ๋ชฝ๊ณ DB์ ์ ์ฅ๋๋ ๋ฌธ์๋ก ์ ์ธํ๋ค.
@Field : ๋ชฝ๊ณ DB์ ๋ฌธ์์ ์์ฑ์ ์ ์ฅํ๊ธฐ ์ํด ํ๋ ์ด๋ฆ(๊ณผ ์ ํ์ ์ผ๋ก ์์)์ ์ง์ ํ๋ค.
@Field๊ฐ ์ง์ ๋์ง ์์ ๋๋ฉ์ธ ํ์
์ ์์ฑ๋ค์ ํ๋ ์ด๋ฆ๊ณผ ์์ฑ ์ด๋ฆ์ ๊ฐ์ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋๋ค.
์ด ์ ๋ ธํ ์ด์ ๋ค์ ์ด์ฉํ์ฌ Ingredient ํด๋์ค๋ฅผ ์์ฑํ๋ค.
package tacos;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
@Data
@RequiredArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
@Document
public class Ingredient {
@Id
private final String id;
private final String name;
private final Type type;
public static enum Type {
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}
๋ค์์ Taco์ ๋ชฝ๊ณ DB ๋งคํ์ ์์๋ณด์.
package tacos;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.rest.core.annotation.RestResource;
import lombok.Data;
@Data
@RestResource(rel = "tacos", path = "tacos")
@Document
public class Taco {
@Id
private String id;
@NotNull
@Size(min = 5, message = "Name must be at least 5 characters long")
private String name;
private Date createdAt = new Date();
@Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;
}
ID๋ก String ํ์ ์ ์์ฑ์ ์ฌ์ฉํ๋ฉด ์ด ์์ฑ๊ฐ์ด DB์ ์ ์ฅ๋ ๋ ๋ชฝ๊ณ DB๊ฐ ์๋์ผ๋ก ID ๊ฐ์ ์ง์ ํด์ค๋ค. (null์ผ ๊ฒฝ์ฐ์ ํํจ)
๋ชฝ๊ณ DB ์ ๋ ธํ ์ด์ ์ด ์ง์ ๋ ๋ค์์ Order ํด๋์ค๋ฅผ ์ดํด๋ณด์.
package tacos;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Field;
@Data
@Document
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String id;
private Date placedAt = new Date();
@Field("customer")
private User user;
private String deliveryName;
private String deliveryStreet;
private String deliveryCity;
private String deliveryState;
private String deliveryZip;
private String ccNumber;
private String ccExpiration;
private String ccCVV;
private List<Taco> tacos = new ArrayList<>();
public void addDesign(Taco design) {
this.tacos.add(design);
}
}
customer ์ด์ ๋ฌธ์์ ์ ์ฅํ๋ค๋ ๊ฒ์ ๋ํ๋ด๊ธฐ ์ํด์ user ์์ฑ์ @FIeld๋ฅผ ์ง์ ํ์๋ค.
๋ค์์ผ๋ก User ๋๋ฉ์ธ ํด๋์ค๋ฅผ ์์ฑํ์.
package tacos;
import java.util.Arrays;
import java.util.Collection;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.
SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
@Data
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
@RequiredArgsConstructor
@Document
public class User implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
private String id;
private final String username;
private final String password;
private final String fullname;
private final String street;
private final String city;
private final String state;
private final String zip;
private final String phoneNumber;
private final String email;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
์ด์ ๋ Repository Interface๋ฅผ ์์ฑํ์. ** ๋ฆฌ์กํฐ๋ธ ๋ชฝ๊ณ DB ๋ฆฌํผ์งํฐ๋ฆฌ ์ธํฐํ์ด์ค ์์ฑํ๊ธฐ ์คํ๋ง ๋ฐ์ดํฐ ๋ชฝ๊ณ DB๋ ์คํ๋ง ๋ฐ์ดํฐ JPA๊ฐ ์ ๊ณตํ๋ ๊ฒ๊ณผ ์ ์ฌํ ์๋ Repository ์ง์์ ์ ๊ณตํ๋ค.
๋ชฝ๊ณ DB์ Reactvie Repository๋ฅผ ์์ฑํ ๋๋ ReactiveCrudRepository๋ ReactiveMongoRepository๋ฅผ ์ ํํ ์ ์๋ค.
ReactiveCrudRepository๋ ์๋ก์ด ๋ฌธ์๋ ๊ธฐ์กด ๋ฌธ์์ save() ๋ฉ์๋์ ์์กดํ๋ ๋ฐ๋ฉด, ReactiveMongoRepository๋ ์๋ก์ด ๋ฌธ์์ ์ ์ฅ์ ์ต์ ํ๋ ์์์ ํน๋ณํ insert() ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
์ฐ์ , Ingredient ๊ฐ์ฒด๋ฅผ ๋ฌธ์๋ก ์ ์ฅํ๋ Repository๋ฅผ ์ ์ํ์.
์์ฌ๋ฃ๋ฅผ ์ ์ฅํ ๋ฌธ์๋ ์ด๊ธฐ์ ์์ฌ๋ฃ ๋ฐ์ดํฐ๋ฅผ DB์ ์ถ๊ฐํ ๋ ์์ฑ๋๋ฉฐ, ์ด์ธ์๋ ๊ฑฐ์ ์ถ๊ฐ๋์ง ์๋๋ค.
๋ฐ๋ผ์ ์๋ก์ด ๋ฌธ์์ ์ ์ฅ์ ์ต์ ํ๋ ReactiveMongoRepository ๋ณด๋ค๋ ReactiveCrudRepository๋ฅผ ํ์ฅํด์ผ ํ๋ค.
package tacos.data;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.web.bind.annotation.CrossOrigin;
import tacos.Ingredient;
@CrossOrigin(origins="*")
public interface IngredientRepository extends ReactiveCrudRepository<Ingredient, String> {
}
IngredientRepository๋ ReactiveRepository์ด๋ฏ๋ก ์ด๊ฒ์ ๋ฉ์๋๋ ๊ทธ๋ฅ ๋๋ฉ์ธ ํ์ ์ด๋ ์ปฌ๋ ์ ์ด ์๋ Flux๋ Mono ํ์ ์ผ๋ก ๋๋ฉ์ธ ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํ๋ค.
์๋ฅผ ๋ค์ด, findAll() ๋ฉ์๋๋ Iterable ๋์ Flux๋ฅผ ๋ฐํํ๋ค.
๊ทธ๋ฆฌ๊ณ findById() ๋ฉ์๋๋ Optional ๋์ Mono๋ฅผ ๋ฐํํ๋ค.
๋ฐ๋ผ์ ์ด Reactive Repository๋ ์๋-to-์๋ Reactive flow์ ์ผ๋ถ๊ฐ ๋ ์์๋ค.
๋ค์์ ๋ชฝ๊ณ DB์ ๋ฌธ์๋ก Taco ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ Repository๋ฅผ ์ ์ํ์.
์์ฌ๋ฃ ๋ฌธ์์๋ ๋ค๋ฅด๊ฒ ํ์ฝ ๋ฌธ์๋ ์์ฃผ ์์ฑ๋๋ค.
๋ฐ๋ผ์ ReactiveMongoRepository์ ์ต์ ํ๋ insert() ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
package tacos.data;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Flux;
import tacos.Taco;
public interface TacoRepository extends ReactiveMongoRepository<Taco, String> {
Flux<Taco> findByOrderByCreatedAtDesc();
}
ReactiveCrudRepository์ ๋นํด ReactiveMongoRepository๋ฅผ ์ฌ์ฉํ ๋์ ์ ์ผํ ๋จ์ ์ ๋ฐ๋ก ๋ชฝ๊ณ DB์ ํนํ๋์ด ์๋ค๋ ์ ์ด๋ค.
๊ทธ๋์ ๋ค๋ฅธ DB์๋ ์ฌ์ฉํ ์ ์๋ค. ๋ฐ๋ผ์ ์ด ๋จ์ ์ ๊ฐ์ํ๊ณ ์ฌ์ฉํด์ผ ํ๋ค.
TacoRepository์๋ ์๋ก์ด ๋ฉ์๋๊ฐ ์๋ค. ์ด ๋ฉ์๋๋ ์ต๊ทผ ์์ฑ๋ ํ์ฝ๋ค์ ๋ฆฌ์คํธ๋ฅผ ์กฐํํ์ฌ ๋ฐํํ๋ค.
findByOrderByCreatedAtDesc()๋ Flux๋ฅผ ๋ฐํํ๋ค.
๋ฐ๋ผ์ take() ์คํผ๋ ์ด์ ์ ์ ์ฉํ์ฌ Flux์์ ๋ฐํ๋๋ ์ฒ์ 12๊ฐ์ Taco ๊ฐ์ฒด๋ง ๋ฐํํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, ์ต๊ทผ ์์ฑ๋ ํ์ฝ๋ค์ ๋ณด์ฌ์ฃผ๋ ์ปจํธ๋กค๋ฌ์์๋ ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค.
Flux<Taco> recents = repo.findByOrderByCreatedAtDesc().take(12);
์ด๋ฒ์ OrderRepository ์ธํฐํ์ด์ค๋ฅผ ์์๋ณด์.
package tacos.data;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import tacos.Order;
public interface OrderRepository extends ReactiveMongoRepository<Order, String> {
}
Order ๋ฌธ์๋ ์์ฃผ ์์ฑ๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ReactiveMongoRepository๋ฅผ ํ์ฅํ๋ค.
package tacos.data;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Mono;
import tacos.User;
public interface UserRepository extends ReactiveMongoRepository<User, String> {
Mono<User> findByUsername(String username);
}