[Spring-legacy] 이거 @RequestBody Map으로 받아도 되나요?

2025. 8. 27. 21:26·공부일기../Spring

인트로~

오늘 회사에서 신입사원이 화면단에서 데이터를 data: JSON으로 넘기는데 뒤에 있던 일부 객체 필드를 누락시켰더니 서버에서 전체 JSON이 그대로 받아졌다고 했다. 그럴 수밖에 없는 게 @RequestBody는 말 그대로 HTTP 요청의 바디(body)를 그대로 긁어서 Java 객체로 매핑해주는 방식이기때문이다.
 
하지만 문제는… 회사 프로젝트가 레거시라서 요청을 @RequestBody Map<String, Object>로 받고 있다는 거였다. 이러면 JSON 구조가 조금만 달라도 바로 400 Bad Request 터지는 구조다ㅋㅋ
 
@RequestParam으로 바꾸면안되냐고 말하길래 그럼 이제는 JSON 객체를 제대로 묶어서 받지도 못하고 필드 하나하나 전부 파라미터로 풀어서 받아서 다시 조립할거냐구.. ㄹㅈㄷ 비효율
 
그래서 생각난김에 `@RequestParam`과 `@RequestBody`의 차이 그리고 왜 DTO로 받아야 하는지 정리해보려고 한다.
 
 
 


 

1. @RequestParam과 @RequestBody 차이

 
둘 다 클라이언트에서 데이터를 받아오는 방식이지만 어디에 데이터를 담아서 보내느냐에 따라 처리 방식이 완전히 달라진다.
 
 

1-1. @RequestParam

  • 주로 URL의 쿼리 파라미터나 폼 데이터를 처리할 때 사용한다.
  • 간단한 검색 조건이나 필터값, 페이지 번호 등을 받을 때 적합하다.

요청 : 

POST /greet?name=승민&age=30

 
Controller :

@PostMapping("/greet")
public String greet(@RequestParam String name, @RequestParam int age) {
    return "안녕 " + name + ", 나이는 " + age;
}

 

 

1-2. @RequestBody

  • HTTP 요청 본문(Body) 에 담긴 JSON 데이터를 처리할 때 사용한다.
  • 회원가입, 게시글 등록, 주문 생성 등 구조화된 객체 전체를 받아야 할 때 쓰인다.
  • 이때는 보통 프론트엔드에서 `application/json` 형식으로 복잡한 구조의 데이터를 보낸다.

요청 :

POST /greet
Content-Type: application/json

{
  "name": "승민",
  "age": 30
}

 
DTO클래스 :

public record GreetRequest(String name, int age) {}

 
Controller : 

@PostMapping("/greet")
public String greet(@RequestBody GreetRequest request) {
    return "안녕 " + request.name() + ", 나이는 " + request.age();
}

 
 


 
 

2.  동작 방식은 어떻게 다를까?

 
`@RequestParam`은 스프링은 내부적으로 WebDataBinder를 사용해서 파라미터 값을 타입에 맞게 변환해서 매핑해준다.
 
`@RequestBody`는 JSON 파서를 이용해서 HTTP Body를 읽고 그걸 자바 객체로 변환한다.
여기엔 Jackson의 ObjectMapper가 사용된다.
 
`@RequestParam`은 URL이나 폼데이터 → 자바 변수
`@RequestBody`는 JSON → 자바 객체 
 
 


3. DTO를 써야 하는 이유

 
간단한 필터, 검색, 페이지네이션 등엔 `@RequestParam`을 쓰고 
데이터 생성/수정 요청은 거의 대부분 `@RequestBody + DTO 조합`으로 처리한다.
 
무작정 Map<String, Object>로 받거나 Entity 객체를 그대로 @RequestBody에 쓰는 건 실무에서 안티패턴이니 주의해야 한다.
 
 

3-1. DTO 사용이유

  • 타입 안정성 확보 → 컴파일 시점에 오류 잡힘
  • 유효성 검증 가능 → @Valid, @NotNull 등 활용 가능
  • Swagger 연동 용이 → 문서 자동 생성
  • 도메인 모델과 분리 → 보안상 안전 (Entity 직접 노출 금지)
public class SignupRequest {
    @NotBlank
    private String email;

    @Size(min = 6)
    private String password;
}
@PostMapping("/signup")
public ResponseEntity<?> signup(@Valid @RequestBody SignupRequest request) {
    return ResponseEntity.ok("회원가입 완료");
}

 
 

3-2. @RequestBody Map<String, Object>의 위험성

  • 보안 취약: {"role":"ADMIN"} 같은 데이터 조작 가능
  • 유효성 검증 불가(@Valid, @NotNull 등)
  • 문서화 불가 (Swagger 문서화 자동 연동불가)
  • 실수 방지 어려움, 구조 예측 불가
@PostMapping("/hack")
public ResponseEntity<?> hack(@RequestBody Map<String, Object> payload) {
    // JSON 전체를 그대로 받음
    ...
}

 
 
 


 
 

4. 결론

`@RequestParam`은 말 그대로 URL이나 폼에서 파라미터처럼 전달되는 데이터를 받을 때 쓰인다.
그에 반해 `@RequestBody`는 요청의 본문에 담긴 JSON 데이터를 읽어올 때 사용된다.
 
단순 값 몇 개 받을 때는 @RequestParam으로 충분하지만 
회원가입, 게시글 작성처럼 여러 필드가 있는 경우에는 DTO 객체를 정의해서 `@RequestBody`로 받는 것이 타입 안정성, 문서화, 유효성 검증 등에서 훨씬 유리하다.
 
클라이언트가 보낸 데이터를 신뢰하지 말고 명확하게 구조화된 DTO를 통해 안전하게 처리하는 것이 가장 중요하다~ 
안전하고 유지보수 가능한 API 설계를 위해서는 @RequestBody + DTO + 유효성 검증 조합이 필수당
 

불필요한 JSON 필드는 받지도~ 믿지도 말자~

끘~ 

'공부일기.. > Spring' 카테고리의 다른 글

[Spring] Spring Boot MySQL 설정 (커넥션 풀, OSIV, SQL 로깅)  (0) 2025.09.18
[Spring Boot] application.yml 설정파일 마스타~~  (0) 2025.09.14
[Redis] Redis 동작원리 : 속도 빠른이유  (4) 2025.08.21
Redis 활용시 직렬화/역직렬화를 해야하는 이유 (ObjectMapper)  (4) 2025.08.17
Redis 캐시1 - RedisCacheManager (@Cacheable) 사용하기  (3) 2025.08.16
'공부일기../Spring' 카테고리의 다른 글
  • [Spring] Spring Boot MySQL 설정 (커넥션 풀, OSIV, SQL 로깅)
  • [Spring Boot] application.yml 설정파일 마스타~~
  • [Redis] Redis 동작원리 : 속도 빠른이유
  • Redis 활용시 직렬화/역직렬화를 해야하는 이유 (ObjectMapper)
s0-0mzzang
s0-0mzzang
공부한것을 기록합니다...
  • s0-0mzzang
    승민이의..개발일기..🐰
    s0-0mzzang
  • 전체
    오늘
    어제
    • 전체~ (108)
      • 마음가짐..! (10)
      • 공부일기.. (76)
        • weekly-log (6)
        • Spring (19)
        • Java (18)
        • DataBase (10)
        • git (2)
        • JPA (6)
        • kafka (1)
        • Backend Architecture (3)
        • Troubleshooting (삽질..ㅋ) (2)
        • Cloud (1)
        • Docker (2)
        • 알고리즘 (1)
        • 리액트 (2)
        • Infra (3)
      • 하루일기.. (22)
        • 그림일기 (8)
        • 생각일기 (14)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    ADC 환경
    리팩토링
    StringTokenizer
    다짐
    자바
    spring
    swagger
    인프라 기초
    spring boot
    JPA
    스프링부트
    SpringBoot
    항해플러스
    TDD
    ERD
    Paging
    항해99
    React
    MySQL
    BufferedReader
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
s0-0mzzang
[Spring-legacy] 이거 @RequestBody Map으로 받아도 되나요?
상단으로

티스토리툴바