[WebClient] Spring์์ API ํธ์ถํ๊ธฐ
๐น ๋ฐฐ๊ฒฝ
์ธ๋ถ API๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์์ฒญ/์๋ต์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ฐ์ตํฉ๋๋ค.
Spring์์ HTTP ์์ฒญ์ ์ํด ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ RestTemplate, WebClient๋ฑ์ด ์์ต๋๋ค. RestTemplate์ Spring 3.0๋ถํฐ ์ง์ํ๊ธฐ ์์ํ์ผ๋ฉฐ, ๋๊ธฐ์ ์์ฒญ๋ง ์ฒ๋ฆฌ ๊ฐ๋ฅํ ํน์ง์ด ์์ต๋๋ค. ์ต๊ทผ Spring 5.0๋ถํฐ WebClient๋ฅผ ํ์ค์ผ๋ก ์ผ์ ์คํ๋ง์์ ๊ถ์ ํ๊ณ ์์ด ์ด๋ฅผ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
๐น WebClinet๋?
๊ณต์๋ฌธ์: https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-client
์ฐธ๊ณ ๋ฌธ์: https://www.baeldung.com/spring-5-webclient
๊ฐ๋จํ ๋งํด์, WebClient๋ ์น ์์ฒญ์ ์ํํ๊ธฐ ์ํ ์ฃผ์ ์ง์ ์ ์ ๋ํ๋ด๋ ์ธํฐํ์ด์ค์ ๋๋ค.
Spring Web Reactive ๋ชจ๋์ ์ผ๋ถ๋ก ์ ์๋์์ผ๋ฉฐ, ๊ธฐ์กด์ Rest Template๋ฅผ ๋์ฒดํ๊ฒ ๋ฉ๋๋ค.
์ฑ๊ธ ์ค๋ ๋ ๋ฐฉ์์ผ๋ก HTTP/1.1 ํ๋กํ ์ฝ์์ ์๋ํ๋ ๋ฐ์ํ Non-Blocking ์๋ฃจ์ ์ ๋๋ค.
์ด ์๋ฃจ์ ์ Non-Blocking ํด๋ผ์ด์ธํธ์ด๋ฉฐ Spring-webflux ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํ์ง๋ง ๋๊ธฐ์ ์์ ๊ณผ ๋น๋๊ธฐ์ ์์ ์ ๋ชจ๋ ์ง์ํ๋ฏ๋ก Servlet Stack์์ ์คํ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ์๋ ์ ํฉํฉ๋๋ค.
* Non-Blocking?
Blocking๊ณผ Non-Blocking์ ์ฃผ๋ก IO์ ์ฝ๊ธฐ, ์ฐ๊ธฐ์์ ์ฌ์ฉ๋ฉ๋๋ค. Blocking์ ์์ฒญํ ์์ ์ด ๋ง์น ๋๊น์ง ๊ณ์ ๋๊ธฐํ๋ค return ํ๋ค๋ฉด, Non-Blocking์ ์ฆ์ ๊ฒฐ๊ณผ๋ฅผ returnํ์ง ์์ต๋๋ค. Non-Blocking์์ ํ๋์ Thread๊ฐ ์ฌ๋ฌ ๊ฐ์ IO๋ฅผ ์ฒ๋ฆฌ ๊ฐ๋ฅํฉ๋๋ค.
Non-Blocking์ ์์คํ ์ ํธ์ถํ ์งํ์ ํ๋ก๊ทธ๋จ์ผ๋ก ์ ์ด๊ฐ ๋ค์ ๋์์์ ์์คํ ํธ์ถ์ ์ข ๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ค์ ๋์์ ์ํํฉ๋๋ค. ํธ์ถํ ์์คํ ์ ๋์์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋์์ ๋ค๋ฅธ ์์ ์ ์งํํ ์ ์์ด์ ์์ ์ ์๋๊ฐ ๋นจ๋ผ์ง๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
๐น ๊ฐ๋ฐ
Spring Test์์ jsonplaceholder API๋ฅผ ํธ์ถํด๋ณด๊ฒ ์ต๋๋ค.
jsonplaceholder๋ ์๋ฌด๊ฑฐ๋ ์ฌ์ฉํด๋ ๋ฌด๋ฐฉํ๋ฉฐ, ์๋ ์์ ๋ https://jsonplaceholder.typicode.com/๋ฅผ ์ด์ฉํ์ต๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ
Gradle
implementation 'org.springframework.boot:spring-boot-starter-webflux'
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
ํ ์คํธ ์ฝ๋
import org.junit.jupiter.api.Test;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class WebClientTest {
@Test
void doTest() {
WebClient client = WebClient.create();
String url = "https://jsonplaceholder.typicode.com/todos/1";
Mono<String> stringMono = client.get()
.uri(url)
.retrieve()
.bodyToMono(String.class);
System.out.println(stringMono.flux().toStream().findFirst());
System.out.println("์ข
๋ฃ");
}
}
๐น ๊ฒฐ๊ณผ
Optional[{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}]
"์ข
๋ฃ"
API ์์ฒญ ์๋ต์ด ์ ์์ ์ผ๋ก ์จ ๊ฒ์ ํ์ธํ์์ต๋๋ค.
์ค์ ํ๋ก์ ํธ์์ ์ฌ์ฉํ ๋๋ WebClient์ Header, Cookie ๋ฑ ์ ๋ณด๋ฅผ ์ค์ ํ์ฌ ์์ฑํ ์ ์์ผ๋ฉฐ, filter๋ฅผ ์ด์ฉํ ์ธ๋ฐํ ์ค์ ์ ํด์ค์ผ ํฉ๋๋ค.
์ฌ๊ธฐ๊น์ง ์งํํ ์ ์๋ค๋ฉด, ๊ณต์๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ฌ ๊ธฐ๋ฅ์ ๋ํ๋ ๋ฐฉ๋ฒ์ ์ด๋ ต์ง ์์ ๊ฒ์ ๋๋ค.
'Programming > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Fixture Monkey 2ํ] validation ํ ์คํธ ํ๊ธฐ (w/ JPA Repository) (2) | 2023.12.03 |
---|---|
[Fixture Monkey] ํฝ์ค์ณ ๋ชฝํค๋ก ํ ์คํธ ์ฝ๋ ์์ฑํ๊ธฐ (Java Spring) (2) | 2023.11.24 |