RestTemplate์ด๋ ๋ฌด์์ผ๊น?
Server To Server
- ์ง๊ธ๊น์ง๋ ๋ธ๋ผ์ฐ์ Client๋ก๋ถํฐ ์์ฒญ์ ๋ฐ๋ ์๋ฒ์ ์ ์ฅ์์ ๊ฐ๋ฐ์ ์งํํด์์
- ์๋น์ค ๊ฐ๋ฐ์ ์งํํ๋ค๋ณด๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ๋ง์ผ๋ก๋ ๊ตฌํ์ด ํ๋ ๊ธฐ๋ฅ๋ค์ด ๋ฌด์ํ ๋ง์ด ์กด์ฌํจ
ex) ํ์๊ฐ์ ์ ์งํํ ๋ ์ฌ์ฉ์์ ์ฃผ์๋ฅผ ๋ฐ์์ผ ํ๋ค๋ฉด, ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์๋ ๊ธฐ๋ฅ์ ๊ตฌํํด์ผ ํ๋๋ฐ ์ง์ ๊ตฌํ์ ํ๊ฒ ๋๋ฉด ๋ง์ ์๊ฐ๊ณผ ๋น์ฉ์ด ๋ค์ด๊ฐ - ์ด๋, ์นด์นด์ค์์ ๋ง๋ ์ฃผ์ ๊ฒ์ API๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ํด๋น ๊ธฐ๋ฅ์ ๊ฐํธํ๊ฒ ๊ตฌํํ ์ ์์
- ์ด๋ฌํ ๊ฒฝ์ฐ ์ฐ๋ฆฌ์ ์๋ฒ๋ Client ์ ์ฅ์ด ๋์ด Kakao ์๋ฒ์ ์์ฒญ์ ์งํํด์ผ ํจ

Spring์์๋ ์๋ฒ์์ ๋ค๋ฅธ ์๋ฒ๋ก ๊ฐํธํ๊ฒ ์์ฒญํ ์ ์๋๋ก RestTemplate ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ์์
Client ์ ์ฅ์ Server(์ด๊ธฐ์ธํ )
- Client ์ ์ฅ์ Server ํฌํธ ๋ฒํธ: 8080
Controller
package com.sparta.springresttemplateclient.controller;
import com.sparta.springresttemplateclient.dto.ItemDto;
import com.sparta.springresttemplateclient.service.RestTemplateService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/client")
public class RestTemplateController {
private final RestTemplateService restTemplateService;
public RestTemplateController(RestTemplateService restTemplateService) {
this.restTemplateService = restTemplateService;
}
@GetMapping("/get-call-obj")
public ItemDto getCallObject(String query) {
return restTemplateService.getCallObject(query);
}
@GetMapping("/get-call-list")
public List<ItemDto> getCallList() {
return restTemplateService.getCallList();
}
@GetMapping("/post-call")
public ItemDto postCall(String query) {
return restTemplateService.postCall(query);
}
@GetMapping("/exchange-call")
public List<ItemDto> exchangeCall(@RequestHeader("Authorization") String token) {
return restTemplateService.exchangeCall(token);
}
}
DTO
package com.sparta.springresttemplateclient.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class ItemDto {
private String title;
private int price;
}
Entity
package com.sparta.springresttemplateclient.entity;
import lombok.Getter;
@Getter
public class User {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
}
Service
package com.sparta.springresttemplateclient.service;
import com.sparta.springresttemplateclient.dto.ItemDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class RestTemplateService {
public ItemDto getCallObject(String query) {
return null;
}
public List<ItemDto> getCallList() {
return null;
}
public ItemDto postCall(String query) {
return null;
}
public List<ItemDto> exchangeCall(String token) {
return null;
}
}
๏นก์์ ํ๋ฆ: Client ์ ์ฅ์ Server์ Controller๋ก ์์ฒญ → Service๋ฅผ ๊ฑฐ์ณ Server ์ ์ฅ์ Server๋ก ์์ฒญ์ด ๋ณด๋ด์ง(RestTemplate์ ์ฌ์ฉ) → ์์ฒญ์ ๊ดํ ๋ก์ง ์ฒ๋ฆฌ ํ ์๋ต ๋ฐํ → ๋ค์ Client ์ ์ฅ์ Server๋ฅผ ํตํด ์ต์ข ์ ์ผ๋ก ์๋ต์ ๋ฐ์
Server ์ ์ฅ์ Server(์ด๊ธฐ์ธํ )
- Server ์ ์ฅ์ Server ํฌํธ ๋ฒํธ: 7070
- ํด๋น ์๋ฒ๋ Client ์ ์ฅ์ Server๊ฐ ๋ณด๋ธ ์์ฒญ์ ๋ฐ๋ Controller
// application.properties
server.port = 7070
Controller
package com.sparta.springresttemplateserver.controller;
import com.sparta.springresttemplateserver.dto.ItemResponseDto;
import com.sparta.springresttemplateserver.dto.UserRequestDto;
import com.sparta.springresttemplateserver.entity.Item;
import com.sparta.springresttemplateserver.service.ItemService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/server")
public class ItemController {
private final ItemService itemService;
public ItemController(ItemService itemService) {
this.itemService = itemService;
}
@GetMapping("/get-call-obj")
public Item getCallObject(@RequestParam String query) {
return itemService.getCallObject(query);
}
@GetMapping("/get-call-list")
public ItemResponseDto getCallList() {
return itemService.getCallList();
}
@PostMapping("/post-call/{query}")
public Item postCall(@PathVariable String query, @RequestBody UserRequestDto requestDto) {
return itemService.postCall(query, requestDto);
}
@PostMapping("/exchange-call")
public ItemResponseDto exchangeCall(@RequestHeader("X-Authorization") String token, @RequestBody UserRequestDto requestDto) {
return itemService.exchangeCall(token, requestDto);
}
}
DTO
package com.sparta.springresttemplateserver.dto;
import com.sparta.springresttemplateserver.entity.Item;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
@Getter
public class ItemResponseDto {
private final List<Item> items = new ArrayList<>();
public void setItems(Item item) {
items.add(item);
}
}
package com.sparta.springresttemplateserver.dto;
import lombok.Getter;
@Getter
public class UserRequestDto {
private String username;
private String password;
}
Entity
package com.sparta.springresttemplateserver.entity;
import lombok.Getter;
@Getter
public class Item {
private String title;
private int price;
public Item(String title, int price) {
this.title = title;
this.price = price;
}
}
Service
package com.sparta.springresttemplateserver.service;
import com.sparta.springresttemplateserver.dto.ItemResponseDto;
import com.sparta.springresttemplateserver.dto.UserRequestDto;
import com.sparta.springresttemplateserver.entity.Item;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
@Service
public class ItemService {
private final List<Item> itemList = Arrays.asList(
new Item("Mac", 3_888_000),
new Item("iPad", 1_230_000),
new Item("iPhone", 1_550_000),
new Item("Watch", 450_000),
new Item("AirPods", 350_000)
);
public Item getCallObject(String query) {
return null;
}
public ItemResponseDto getCallList() {
return null;
}
public Item postCall(String query, UserRequestDto requestDto) {
return null;
}
public ItemResponseDto exchangeCall(String token, UserRequestDto requestDto) {
return null;
}
}
RestTemplate์ Get ์์ฒญ
๊ฐ์ฒด ํ๋๋ง ๊ฐ์ ธ์ค๊ธฐ
Client ์ ์ฅ์ Server
- RestTemplate ์ฃผ์ ๋ฐ์์ ์ฌ์ฉํ๊ธฐ
// RestTemplateService
...
@Slf4j
@Service
public class RestTemplateService {
private final RestTemplate restTemplate;
// RestTemplate์ Spring Boot์์ ์๋ ๋ฑ๋ก์ ์ฒ์์ ์ํํ์ง ์์
// ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ RestTemplate์ ๋ง๋ค ์ ์๋ RestTemplate builder๋ฅผ ๋ฑ๋กํด์ค์ผํจ
public RestTemplateService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
...
}
- Client ์ชฝ GET ์์ฒญ ๋ง๋ค๊ธฐ
// RestTemplateService.java
public ItemDto getCallObject(String query) {
// ์์ฒญ URL ๋ง๋ค๊ธฐ
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070") // ์๋ฒ ์
์ฅ์ ์๋ฒ์ ๋ณด๋ผ ์ค๋น
.path("/api/server/get-call-obj") // ์๋ฒ ์
์ฅ์ ์๋ฒ์ Controller ๋ถ๋ถ
.queryParam("query", query) // ?๊ฒ์์ด
.encode()
.build()
.toUri();
log.info("uri = " + uri);
// GET ๋ฐฉ์์ผ๋ก ํด๋น URI ์๋ฒ์ ์์ฒญ์ด ๋ณด๋ด์ง
// getForEntity(URI, ์์ฒญ์ ํ ๋ค์ ๋ฐ์ ์๋ต DTO);
// :๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ ์๋ฒ์ ์๋ฒ๋ก๋ถํฐ ๋์ด์ค๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค Class ํ์
์ ์ง์ ํ๋ฉด, ์๋์ผ๋ก ์ญ์ง๋ ฌํ๊ฐ ๋์ด์ ๊ฐ์ฒด ํํ๋ก ๋ด๊น
ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);
log.info("statusCode = " + responseEntity.getStatusCode());
return responseEntity.getBody();
}
Server ์ ์ฅ์ Server
// ItemService
// ๊ฒ์์ด์ ํด๋นํ๋ Item ๋ฐํ
public Item getCallObject(String query) {
for (Item item : itemList) {
if(item.getTitle().equals(query)) {
return item;
}
}
return null;
}


๊ฐ์ฒด ์ฌ๋ฌ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
Client ์ ์ฅ์ Server
- JSON์ ๋ค๋ฃจ๊ธฐ ์ํด dependencies์ ์๋ ์ฝ๋ ์ถ๊ฐ
// json
implementation 'org.json:json:20230227'
- RestTemplateService์ ๊ฐ์ฒด ์ฌ๋ฌ๊ฐ ๊ฐ์ ธ์ค๋ ๋น์ฆ๋์ค ์ฝ๋ ์ถ๊ฐ
- ์ฌ๋ฌ๊ฐ ๋ฐ์์ค๊ธฐ ์ํด String ๊ฐ์ฒด๋ก ๊ฐ์ ธ์ค๊ธฐ
package com.sparta.springresttemplateclient.service;
...
@Slf4j
@Service
public class RestTemplateService {
...
public List<ItemDto> getCallList() {
// ์์ฒญ URL ๋ง๋ค๊ธฐ
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/get-call-list")
.encode()
.build()
.toUri();
log.info("uri = " + uri);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class); // ์ฌ๋ฌ๊ฐ๋ฅผ ๋ฐ์์ค๊ธฐ ์ํด String์ผ๋ก ๋ฐ์์ค๊ธฐ
log.info("statusCode = " + responseEntity.getStatusCode());
log.info("Body = " + responseEntity.getBody());
return fromJSONtoItems(responseEntity.getBody());
}
...
// ๋์ด์ค๋ JSON ํํ(์ค์ฒฉ JSON)
// {
// "items": [
// {"title":"Mac", "price": 3888000},
// {"title":"iPad", "price": 1230000},
// {"title":"iPhone", "price": 1550000},
// {"title":"Watch", "price": 450000},
// {"title":"AirPods", "price": 350000}
// ]
// }
public List<ItemDto> fromJSONtoItems(String responseEntity) {
// JSONObject์ getJSONArray ๋ฉ์๋์ key๊ฐ์ ์ฃผ๊ธฐ
JSONObject jsonObject = new JSONObject(responseEntity);
JSONArray items = jsonObject.getJSONArray("items");
List<ItemDto> itemDtoList = new ArrayList<>();
for (Object item : items) {
ItemDto itemDto = new ItemDto((JSONObject) item);
itemDtoList.add(itemDto);
}
return itemDtoList;
}
}
- ItemDto์ ์์ฑ์ ์ถ๊ฐ
package com.sparta.springresttemplateclient.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.json.JSONObject;
@Getter
@NoArgsConstructor
public class ItemDto {
private String title;
private int price;
public ItemDto(JSONObject itemJson) {
this.title = itemJson.getString("title");
this.price = itemJson.getInt("price");
}
}
Server ์ ์ฅ์ Server
// ItemService.java ๋ด ์๋ ์ฝ๋ ์ถ๊ฐ
public ItemResponseDto getCallList() {
ItemResponseDto responseDto = new ItemResponseDto();
for (Item item : itemList) {
responseDto.setItems(item);
}
return responseDto;
}


RestTemplate์ Post ์์ฒญ
Client ์ ์ฅ์ Server
// RestTemplateService.java
public ItemDto postCall(String query) {
// ์์ฒญ URL ๋ง๋ค๊ธฐ
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/post-call/{query}") // Path Variable ๋ฐฉ์
.encode()
.build()
.expand(query)
.toUri();
log.info("uri = " + uri);
User user = new User("Robbie", "1234");
// postForEntity(URI, HttpBody์ ๋ฃ์ด์ค ๋ฐ์ดํฐ, ์ ๋ฌ๋ฐ์ ๋ฐ์ดํฐ์ mappingํ ๊ฒ)
// ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ RestTemplate์ด ์๋์ผ๋ก JSON์ผ๋ก ๋ณ๊ฒฝํด์ค
ResponseEntity<ItemDto> responseEntity = restTemplate.postForEntity(uri, user, ItemDto.class);
log.info("statusCode = " + responseEntity.getStatusCode());
return responseEntity.getBody();
}
Server ์ ์ฅ์ Server
// ItemService.java
public Item postCall(String query, UserRequestDto userRequestDto) {
System.out.println("userRequestDto.getUsername() = " + userRequestDto.getUsername());
System.out.println("userRequestDto.getPassword() = " + userRequestDto.getPassword());
return getCallObject(query);
}



RestTemplate์ exchange
Header์ ๋ฐ์ดํฐ๋ฅผ ๋ด์์ ์์ฒญํ๋ ๋ฐฉ๋ฒ
Client ์ ์ฅ์ Server
// RestTemplateService
public List<ItemDto> exchangeCall(String token) {
// ์์ฒญ URL ๋ง๋ค๊ธฐ
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/exchange-call")
.encode()
.build()
.toUri();
log.info("uri = " + uri);
User user = new User("Robbie", "1234"); // Body์ ๋ณด๋ผ ๋ฐ์ดํฐ
RequestEntity<User> requestEntity = RequestEntity
.post(uri) // Method ์ง์
.header("X-Authorization", token) // Header ์ถ๊ฐ
.body(user); // body ๋ถ๋ถ
// exchange(RequestEntity ๊ฐ์ฒด, ๋ฐ์์ฌ ๊ฐ์ฒด)
ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
return fromJSONtoItems(responseEntity.getBody());
}
Server ์ ์ฅ์ Server
// ItemService.java
public ItemResponseDto exchangeCall(String token, UserRequestDto requestDto) {
System.out.println("token = " + token);
System.out.println("requestDto.getUsername() = " + requestDto.getUsername());
System.out.println("requestDto.getPassword() = " + requestDto.getPassword());
return getCallList();
}



Naver Open API
๋ค์ด๋ฒ๊ฐ ์ ๊ณตํ๋ API ๋ชฉ๋ก
1. ์ ํ๋ฆฌ์ผ์ด์ ๋ฑ๋ก


1-1) Postman์ผ๋ก Naver API ์์ฒญํด๋ณด๊ธฐ
- Client ID์ Client Secret ๊ฐ ๋ฃ์ด์ค์ผํจ


2. Client ์ ์ฅ์ ์๋ฒ์ Naver ์ํ ๊ฒ์ API ๊ธฐ๋ฅ ๋ถ์ด๊ธฐ

DTO ์์ฑ

package com.sparta.springresttemplateclient.naver.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.json.JSONObject;
@Getter
@NoArgsConstructor
public class ItemDto {
private String title;
private String link;
private String image;
private int lprice;
public ItemDto(JSONObject itemJson) {
this.title = itemJson.getString("title");
this.link = itemJson.getString("link");
this.image = itemJson.getString("image");
this.lprice = itemJson.getInt("lprice");
}
}
Controller ๊ตฌํ
package com.sparta.springresttemplateclient.naver.controller;
import com.sparta.springresttemplateclient.naver.dto.ItemDto;
import com.sparta.springresttemplateclient.naver.service.NaverApiService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api")
public class NaverApiController {
private final NaverApiService naverApiService;
public NaverApiController(NaverApiService naverApiService) {
this.naverApiService = naverApiService;
}
@GetMapping("/search")
public List<ItemDto> searchItems(@RequestParam String query) {
return naverApiService.searchItems(query);
}
}
Service ๊ตฌํ

package com.sparta.springresttemplateclient.naver.service;
import com.sparta.springresttemplateclient.naver.dto.ItemDto;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@Slf4j(topic = "NAVER API")
@Service
public class NaverApiService {
private final RestTemplate restTemplate;
public NaverApiService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
public List<ItemDto> searchItems(String query) {
// ์์ฒญ URL ๋ง๋ค๊ธฐ
URI uri = UriComponentsBuilder
.fromUriString("https://openapi.naver.com")
.path("/v1/search/shop.json")
.queryParam("display", 15) // 15๊ฐ์ฉ ๊ฐ์ ธ์ค(Default: 10)
.queryParam("query", query)
.encode()
.build()
.toUri();
log.info("uri = " + uri);
RequestEntity<Void> requestEntity = RequestEntity
.get(uri)
// ํค๋ ์ถ๊ฐ
.header("X-Naver-Client-Id", "Client-Id")
.header("X-Naver-Client-Secret", "Client-Secret")
.build();
ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
log.info("NAVER API Status Code : " + responseEntity.getStatusCode());
return fromJSONtoItems(responseEntity.getBody());
}
public List<ItemDto> fromJSONtoItems(String responseEntity) {
JSONObject jsonObject = new JSONObject(responseEntity);
JSONArray items = jsonObject.getJSONArray("items");
List<ItemDto> itemDtoList = new ArrayList<>();
for (Object item : items) {
ItemDto itemDto = new ItemDto((JSONObject) item);
itemDtoList.add(itemDto);
}
return itemDtoList;
}
}


๏นก ํ์ํ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์ค๊ธฐ ์ํด ๊ฐ๊ณตํด์ ๋ฐํํ ์ ์์!