이전 글: 2022.03.21 - [분류 전체보기] - [reactive] 7. CompletableFuture
[reactive] 7. CompletableFuture
이전 글: 2022.03.21 - [개발/reactive] - [reactive] 6. refactoring [reactive] 6. refactoring 이전 글: 2022.03.18 - [개발/reactive] - [reactive] 5. 비동기 RestTemplate과 비동기 MVC/Servlet [reactive..
bangpurin.tistory.com
저번 시간에 작성한 application을 webflux로 바꿔보는 작업을 진행한다.
springboot2.6.4로 진행하였기 때문에 유튜브와 다르게 아래의 의존성을 추가했다.
implementation 'org.springframework.boot:spring-boot-starter:2.6.4'
// implementation 'org.springframework.boot:spring-boot-starter-web:2.6.4'
implementation "org.springframework.boot:spring-boot-starter-webflux:2.6.4"
spring-webflux는 기본 서버가 netty라서 모두 네티로 작업하였다.
그리고 설정명이 달라서 수정하였다. 아래 소스를 참고!
@Slf4j
@EnableAsync
@SpringBootApplication
public class Application {
@RestController
public static class MyController{
@Autowired
MyService myService;
WebClient client = WebClient.create();
static final String URL1 = "http://localhost:8081/service?req={req}";
static final String URL2 = "http://localhost:8081/service2?req={req}";
@GetMapping("/rest")
public Mono<String> rest(int idx) {
//이것만으로는 api 쏘지 않음
Mono<ClientResponse> r = client.get()
.uri(URL1, idx)
.exchange();
//container안의 원소를 받아서 변환해서 다시 container(모노) 담아서 리턴 Mono<Mono<String>>
//이중으로 감싸주는 것은 원하는 결과가 아니니 flatmap으로 작업해서 하나로 합쳐야 함
Mono<String> body = r
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class)) //Mono<String>
.doOnNext(c -> log.info(c))
.flatMap(res1 -> client.get().uri(URL2, res1).exchange()) //Mono<ClientResponse>
.flatMap(c -> c.bodyToMono(String.class)) //Mono<String>
.doOnNext(c -> log.info(c))
.flatMap(res2 -> Mono.fromCompletionStage(myService.work(res2))) //completable<String> -> mono<String>
.doOnNext(c -> log.info(c))
;
//return 시 모노면 그때 subscribe 수행함
//mono subscribe 를 spring이 실행해줌
return body;
}
}
@Service
public static class MyService{
//또다른 스래드 비동기 작업 시 async
@Async
public CompletableFuture<String> work(String req){
return CompletableFuture.completedFuture(req + "/asyncwork");
}
}
public static void main(String[] args) {
System.setProperty("reactor.netty.ioWorkerCount", "1");
System.setProperty("reactor.netty.pool.maxConnections", "2000");
SpringApplication.run(Application.class, args);
}
}
참고로 위 코드는 아래 코드를 수정한 것이다.
소스를 살펴보면 mono의 map과 flatmap의 사용 차이를 느낄 수 있을 것이다.
@GetMapping("/rest")
public Mono<String> rest(int idx) {
Mono<ClientResponse> r = client.get()
.uri(URL1, idx)
.exchange();
Mono<String> body = r
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class)) //Mono<String>
.flatMap(res1 -> client.get().uri(URL2, res1).exchange()) //Mono<ClientResponse>
.flatMap(c -> c.bodyToMono(String.class)) //Mono<String>
.map(res2 -> myService.work(res2))
;
return body;
}
////////////////////////
@Service
public static class MyService{
public String work(String req){
log.info("myservice {}" , req);
return req + "/asyncwork";
}
}
map과 flatmap의 차이는 아래 링크에서 자세히 확인 가능하다. 스트림으로서의 차이는 이해했는데 동기/비동기에 대해서는 아직 잘 모르겠다.
https://www.geeksforgeeks.org/difference-between-map-and-flatmap-in-java-stream/
Difference Between map() And flatMap() In Java Stream - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
www.geeksforgeeks.org
https://luvstudy.tistory.com/95
Reactor map, flatMap method는 언제 써야할까?
webflux로 서비스를 만들어보면서 map과 flatMap을 언제 써야 할지 헷갈릴 때가 있어 공부한 내용을 정리함. map과 flatMap은 둘 다 스트림의 중간에 값을 변환해주는 역할을 한다. map은 1 : 1로 반환을 보
luvstudy.tistory.com
'개발 > reactive' 카테고리의 다른 글
[reactive] 10. Flux (0) | 2022.03.25 |
---|---|
[reactive] 9. Mono (0) | 2022.03.23 |
[reactive] 7. CompletableFuture (0) | 2022.03.21 |
[reactive] 6. refactoring (0) | 2022.03.21 |
[reactive] 5. 비동기 RestTemplate과 비동기 MVC/Servlet (0) | 2022.03.18 |