백엔드 공부

[CRUD 연습] RestTemplate으로 GET, POST

영재임재영 2023. 1. 11. 19:43

 

ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url,requestDto,Long.class);

진짜 요즘 이 코드 한 줄로 엄청나게 많은 공부를 하고 있다.

책을 보면서 따라쳐볼 때는 몰랐지.. 이렇게까지 많은 것이 담겨 있을 줄이야..

진짜 잼민 펀치가 필요할 것 같다. 옥상,, 아니 카페로 따라와,,,

🥓 RestTemplate 사용해서 객체 GET, POST 해보기

이전 포스팅에서 한 번 다룬 내용이다. 그 때보다 더 구체적으로 공부해보았다!

참고로, 밑에서 사용할 restTemplate은 TestRestTemplate 객체의 인스턴스이다!

class MusicAPIControllerTest {

    @Autowired
    private TestRestTemplate restTemplate;
    
    ...
}
  GET POST
응답 형태 - Object getForObject( ) postForObject( )
응답 형태 - ResponseEntity getForEntity( ) postForEntity( )

위에 작성한 표처럼, 크게 4가지 방식을 사용할 수 있다. 하나하나 살펴보자.

 

1️⃣ GET 방식

// 1. 주어진 URL로 HTTP GET 요청 & Object로 결과를 반환받음
Employee employee = restTemplate.getForObject("http://localhost:8080/employee", Employee.class);

// 2. 주어진 URL로 HTTP GET 요청 & ResponseEntity로 결과를 반환받음
ResponseEntity<Employee> response = restTemplate.getForEntity("http://localhost:8080/employee", Employee.class);

GET 방식은 Deserialize(JSON → Java Object) 과정이라고 할 수 있다! (JSON 데이터 받아오는거니까!)

URI에 매핑된 JSON 형태의 데이터를 어떤 형태로 가져오냐 차이인데, 객체 타입으로 바로 받으면 getForObject 를 사용한다.

 

파라미터의 정보는 ① URL (말 그대로 주소), ② 리턴 타입 (어떤 형태의 그릇에 담을건지 정해라!) 으로 이루어져있다.

 

반면, getForEntity를 사용하면 ResponseEntity<T> 타입으로 받을 수 있는데,

ResponseEntity 객체 인스턴스를 사용해서 HTTP에 대한 추가 정보를 확인할 수 있는 것이 차이점이다.

response.getStatusCode()  // HTTP Status Code를 확인할 수 있다. ex) 200, 201..
Employee newEmployee = response.getBody()  // HTTP Body 부분에 담긴 데이터를 객체로 꺼낼 수 있다.
				    	   // ResponseEntity<타입> 부분에서 지정한 타입과 일치해야 한다!

위 코드처럼 getStatusCode( ) 메서드를 사용해 HTTP Status Code를 확인할 수 있고,

HTTP body 부분에 담긴 데이터를 꺼내서 받아올 수도 있다.

 

또한 getForEntity 에서 지정한 리턴 타입은, getBody( ) 를 했을 때 받을 리턴 타입과 일치해야한다.

쉽게 말해서, ResponseEntity<타입> 부분을 getBody( ) 로 벗겼을 때 나오는 '타입'을 지정한다고 생각하면 된다!

 

사실 getForObject 로 바로 꺼내오나, getForEntity 로 꺼내온 후 getBody( ) 로 꺼내나 똑같은 body 정보가 나온다.

하지만 ResponseEntity는 HTTP에 대한 추가 정보들을 확인할 수 있다는 유용한 점이 있다!

 

2️⃣ POST 방식

List<Employee> employeeList = new ArrayList<>();
employeeList.add(new Employee(3, "Intern"));
employeeList.add(new Employee(4, "CEO"));

// 1. 주어진 URL로 HTTP POST 요청 & Object로 결과를 반환받음
Employee employee = restTemplate.postForObject("http://localhost:8080/employee", employeeList, Employee.class);

// 2. 주어진 URL로 HTTP POST 요청 & ResponseEntity로 결과를 반환받음
ResponseEntity<Long> responseEntity = restTemplate.postForEntity("http://localhost:8080/employee", employeeList, Long.class);

POST 방식은 Serialize(Java Object → JSON) 과정이라고 할 수 있다! (객체 타입 데이터를 올리는거니까!)

파라미터가 하나 늘어났다. 왜냐! 객체 타입의 데이터를 POST 해야하지 않나!

 

파라미터의 정보는 ① URL (주소),② 객체 (데이터), ③ 리턴 타입 (어떤 형태의 그릇에 담을건지 정해라!) 으로 이루어져있다.

 

GET은 객체 타입으로 데이터를 받아와서, 해당 객체를 활용하는 방식이지만, POST는 올리면 끝이지 않나!

postForObject 에서 반환한 데이터는 활용성이 없는 것 같고, postForEntity 는 HTTP 정보라도 들고 있어 이를 활용할 수 있다.

(반환 값에 대해서 그렇게 큰 의미는 없다고 생각한다..! 활용하려면 얼마든지 활용은 가능하나, GET에 비해서는 떨어진다는 뜻)

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MusicAPIControllerTest {

    @LocalServerPort private int port;
    @Autowired private TestRestTemplate restTemplate;
    
    @Test
    void 등록() {
    	// given
    	MusicSaveRequestDto requestDto
            = new MusicSaveRequestDto("Sneakers", "ITZY", "CHECKMATE", "Put my sneakers on!");
        String url = "http://localhost:" + port + "/api/v1/music";
        
        // when
        ResponseEntity<Long> responseEntity
            = restTemplate.postForEntity(url, requestDto, Long.class);
            
        // then
        List<Music> musicList = musicRepository.findAll();
        assertThat(musicList.get(0).getTitle()).isEqualTo(requestDto.getTitle());
        assertThat(responseEntity.getStatusCode()).isEqualTo(OK);
        assertThat(responseEntity.getBody()).isEqualTo(2);
    }

}

위 코드는 등록(POST)에 대한 테스트 코드인데, when 부분만 살펴보면 requestDto 객체를 POST 하였다.

그리고 ResponseEntity<Long> 타입으로 받음으로써, getStatusCode( )를 활용해 Status Code를 확인할 수도 있다.

(여기서 responseEntity.getBody( ) 를 하면 '2' 가 나온다! 타입은 'Long' 으로 지정되었을 것이다!)

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MusicAPIControllerTest {

    @LocalServerPort private int port;
    @Autowired private TestRestTemplate restTemplate;
    
    @Test
    void 조회() {
    	// given
    	Music music = new Music("Loco", "ITZY", "Crazy in Love", "I'm gettin loco");
        musicRepository.save(music); 
        String url = "http://localhost:" + port + "/api/v1/music" + music.getId();
        
        // when
        ResponseEntity<Music> responseEntity
            = restTemplate.getForEntity(url, Music.class);  // 리턴 타입 주의!
        MusicResponseDto responseDto = new MusicResponseDto(responseEntity.getBody());
            
        // then
        assertThat(responseDto.getTitle()).isEqualTo(music.getTitle());
        assertThat(responseEntity.getStatusCode()).isEqualTo(OK);
    }

}

위 코드는 조회(GET)에 대한 테스트 코드이고, when 부분만 살펴보면 url 주소에 매핑된 데이터를 GET 하였다.

그리고 ResponseEntity<Music> 타입으로 받은 것을 getBody( ) 해서 HTTP body 부분을 통해 전달된 데이터를 사용할 수 있다.

getBody( ) 해서 얻은 Entity 데이터(Music 객체)를 DTO에 매핑해서 활용할 수 있도록! 테스트 코드를 작성했다. 😆😆