Spring 에서는 서버에서 다른 서버로 간편하게 요청할 수 있도록 RestTemplate 기능을 제공하고 있다.
Servcer To Server로 Client 입장의 서버로 다른 서버의 API를 활용하면 간단하게 기능 구현을 할 수 있게 된다.
실습과정에서 경험했던 가벼운 RestTemplate 개념을 정리하고 넘어가고자 한다.
2개의 프로젝트를 통해 Client 입장의 서버는 8080 포트를 이용, Servcer 입장의 서버는 7070 포트로 동시에 실행을 시켜 보는 과정이다.
Client 입장 서버
- RestTemplateController
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);
}
}
- 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");
}
}
- ItemDto에 받아온 JSONObject를 사용하여 초기화하는 생성자를 추가
- User
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;
}
}
- RestTemplateService
package com.sparta.springresttemplateclient.service;
import com.sparta.springresttemplateclient.dto.ItemDto;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class RestTemplateService {
public ItemDto getCallObject(String query) {
// 요청 URL 만들기
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/get-call-obj")
.queryParam("query", query)
.encode()
.build()
.toUri();
log.info("uri = " + uri);
ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);
log.info("statusCode = " + responseEntity.getStatusCode());
return responseEntity.getBody();
}
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);
log.info("statusCode = " + responseEntity.getStatusCode());
log.info("Body = " + responseEntity.getBody());
return fromJSONtoItems(responseEntity.getBody());
}
public ItemDto postCall(String query) {
// 요청 URL 만들기
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/post-call/{query}")
.encode()
.build()
.expand(query)
.toUri();
log.info("uri = " + uri);
User user = new User("Robbie", "1234");
ResponseEntity<ItemDto> responseEntity = restTemplate.postForEntity(uri, user, ItemDto.class);
log.info("statusCode = " + responseEntity.getStatusCode());
return responseEntity.getBody();
}
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");
RequestEntity<User> requestEntity = RequestEntity
.post(uri)
.header("X-Authorization", token)
.body(user);
ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
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;
}
}
- Spring의 UriComponentsBuilder를 사용하여 URI를 손쉽게 만들 수 있음
- getForEntity는 Get 방식으로 해당 URI의 서버에 요청을 진행
- getCallList : 결과값이 다중 JSON으로 넘어오기 때문에 JSON To Object를 사용하지 않고 일단 String 값 그대로를 가져옴
- exchangeCall : exchange 메서드의 첫 번째 파라미터에 RequestEntity 객체를 만들어 전달해주면 uri, header, body의 정보를 한번에 전달할 수 있음
Server 입장 서버
- ItemController
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);
}
}
- UserRequestDto
package com.sparta.springresttemplateserver.dto;
import lombok.Getter;
@Getter
public class UserRequestDto {
private String username;
private String password;
}
- ItemResponseDto
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);
}
}
- Item
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;
}
}
- ItemService
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) {
for (Item item : itemList) {
if(item.getTitle().equals(query)) {
return item;
}
}
return null;
}
public ItemResponseDto getCallList() {
ItemResponseDto responseDto = new ItemResponseDto();
for (Item item : itemList) {
responseDto.setItems(item);
}
return responseDto;
}
public Item postCall(String query, UserRequestDto userRequestDto) {
System.out.println("userRequestDto.getUsername() = " + userRequestDto.getUsername());
System.out.println("userRequestDto.getPassword() = " + userRequestDto.getPassword());
return getCallObject(query);
}
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();
}
}
- itemList를 조회하여 요청받은 검색어에 맞는 Item을 반환
- getCallList : itemList를 ItemResponseDto에 담아 반환
- exchangeCall : 전달된 header와 body의 정보를 확인할 수 있음
이 과정들을 실습하면서 실제로 User에서 요청하는 값에 따른 값을 반환하고 얻는 과정을 확인할 수 있었고 서버와 서버 간의 통신과정을 기본적으로 이해해볼 수 있는 경험을 가졌다.
'Spring > 백엔드 기초' 카테고리의 다른 글
| [백엔드 기초] 클라우드 개념 이해하기 (보충작성 필요) (1) | 2025.11.11 |
|---|---|
| [백엔드 기초] Validation 개념 정리 (0) | 2025.10.30 |
| [백엔드 기초] Filter, Spring Security (0) | 2025.10.24 |
| [백엔드 기초] 쿠키를 활용한 인증 인가 개념 실습 (0) | 2025.10.23 |
| [백엔드 기초] 백엔드 기초 개념정리 (0) | 2025.10.22 |