본문 바로가기
Spring

Spring Response/Request 어노테이션

by CodingMasterLSW 2025. 4. 16.

@RequestParam

- URL / Form 에서 오는 값을 읽을 때 사용한다.

 

ex) ?name=jenson&age=20 이라는 쿼리 파라미터가 있고, 해당 URL을 통해 값을 가져오고 싶다면?

@GetMapping
public void read(
	@RequestParam("name") String name,
	@RequestParam("age") int age
) { ... }

 


위와 같이 가져오려는 모든 매개변수에 @RequestParam 어노테이션을 붙여줘야 한다. 단, 파라미터 이름이 변수 이름과 같다면, @RequestParam 값은 생략 가능하다.

@GetMapping
public void read(
	@RequestParam String name,
	@RequestParam int age
) { ... }

 

@RequestBody

- HTTP 요청 바디를 읽는다.

- RequestParam과 같이 값을 읽어올 때 사용되지만, Json 처럼 요청 Body 전체를 자바 객체로 바꿀 때 사용한다.

@GetMapping
public void read(@RequestBody Person person) {
	String name = person.getName();
	int age = person.getAge();
}

 

 

궁금했던 점

 

1) Json은 위와 같은 형식으로 데이터를 제공해줄텐데 String, int 값을 누가 Person 객체로 만들어주는걸까?

{
  name : "jenson",
  age : 20
}

 

- @RequestBody를 사용하면 Json -> 객체로 변경해준다. 이를 역직렬화라고 한다. (+ 반대로 객체 -> Json으로 변경은 직렬화라고 한다).

 

주의사항 

- HTTP 요청은 Body를 한 번만 읽을 수 있다. 하지만 Form 데이터는 request.getParameter()를 통해 읽게 된다 (이를 통해 body를 자동으로 읽어버림). 이후에 @RequstBody로 body를 다시 읽으려고 할 때 에러가 날 수 있다.

스프링 공식 문서에 적혀있는 내용

 

즉, Form데이터를 사용할 때는 @RequestParam을 사용하자.

(+ 쿼리파라미터를 통해 URL를 읽는 방법에는 애초에 HTTP 요청 바디가 없다. 즉 이 경우에는 @RequestParam을 사용해야 한다.)

 

@PathVariable

- URL 자체에 포함된 값을 가져온다.

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
	// ...
}

 

@RequestParam과의 차이점

- owners?ownerId=42 -> @RequestParam

- onwers/42 -> @PathVariable

 

경로에 값이 들어있다면 @PathVariable / 쿼리스트링에 들어있다면 @RequestParam

 

@PathVariable은 누구(what)를, @RequestParam은 어떻게(how)를 표현할 때 사용한다.

 

예시 코드

@GetMapping("/users/{userId}/posts")
public List<Post> getPosts(
    @PathVariable Long userId,
    @RequestParam int page,
    @RequestParam int size
)

 

  • userId → 어떤 유저의 글인지 (자원 식별)
  • page, size → 어떻게 가져올지 (옵션/필터)

 

@ResponseBody

주로 Json값을 반환할 때 사용한다. 해당 어노테이션을 붙인 후 객체를 반환하면, Spring의 Jackson 이 직렬화를 해 Json으로 반환해준다. 메서드가 성공한다면, 기본적으로 상태코드를 200으로 반환한다.

 

예시코드

class Member {
	private final String name;
	private final int age;
}

@ResponseBody
public Member findMember() {
	Member member = getMember();
	return member;
}

 

member 객체를 반환하지만 @ResponseBody를 사용한다면

{
	name : "Jenson",
	age : 25
}

 

위와 같은 Json 값이 반환된다.

 

 

@ResponseEntity

@ResponseBody와 같지만, 명시적으로 Http의 Header와 상태 코드를 지정할 수 있다.

class Member {
	private final String name;
	private final int age;
}

public ResponseEntity<Member> findMember() {
	Member member = getMember();
	return ResponseEntity.ok(member);
}

 

ok()는 상태코드 200을 반환하지만, 보다 유연하게 관리할 수 있다.

noContent(), notFound(), accepted() ...

 

ResponseEntity.status(400) 과 같이 직접 상태 코드를 관리할 수도 있다.

하지만, @ResponseBody 또한 @ResponseStatus 를 통해 상태 코드를 관리할 수도 있다. 

 

class Member {
	private final String name;
	private final int age;
}

@ResponseBody
@ResponseStatus(HttpStatus.OK) // 해당 어노테이션을 통해 상태 코드 조작 가능
public Member findMember() {
	Member member = getMember();
	return member;
}

 

그러면 둘 다 똑같아 보이는데... 어떤 차이점이 있을까?

 

아래의 예시 코드를 통해 이해해보자.

class Member {
	private final String name;
	private final int age;
}

public ResponseEntity<Member> findMember() {
	Member member = getMember();
	if (member == null) {
		return ResponseEntity.noContent().build();
	}
	return ResponseEntity.ok(member);
}

 

member가 존재하지 않는다면 상태코드 400을 반환하고, 존재한다면 200을 반환하려고 한다.

@ResponseEntity 를 사용한다면 동적으로 상태코드를 반환할 수 있지만, @ResponseStatus를 사용했다면 정적으로 반환할 수 밖에 없다.

 

결론: @ResponseEntity를 사용하면 보다 유연하게 반환값을 관리할 수 있다. 다만, @ResponseBody를 사용할 때 보다 코드의 양이 조금 늘어날 수 있다.

 

 

추가 공부

 

Controller vs RestController

 

@RestController의 경우 어노테이션 내부를 확인해보면 Controller + @ResponseBody 인 것을 확인할 수 있다.

 

방탈출 미션에서의 코드를 보며 어떤 문제가 생기는 지 알아보자.

 

@RestController
public class RoomescapeController {

    @GetMapping("/admin")
    public String admin() {
        return "admin/index";
    }

 

내가 의도한 코드는 admin/index.html이 렌더링 되어 /admin 페이지로 반환이다. 예상대로 동작할까?

이상한 결과값이 나온다.

이상한 결과값이 나온다. 이유가 뭘까?

 

@RestController 내부에 @ResponseBody 어노테이션이 존재하기 때문이다. 해당 어노테이션이 붙어있기에 반환할 때 html 페이지가 렌더링 되지 않고,  문자열인 "admin/index"가 반환되는 것이다. 

 

정리하자면 HTML View를 리턴하고 싶다면 @ResponseBody 어노테이션이 없는 @Controller를 사용해야 한다.

 

어떤 값은 HTML View를 반환해야 하고 어떤 값은 Json을 반환해야 한다면,  Controller를 사용하며, Json 값이 필요한 메서드에 @ResponseBody를 일일히 붙여주자.

 

만약, HTML View를 반환해야 할 일이 없다면 그냥 @RestController를 쓰자.

'Spring' 카테고리의 다른 글

Spring HTTP 처리 과정  (0) 2025.06.29
Spring Core 꼬리 질문 해보기  (0) 2025.04.28