@RestController 요청 매핑 데이터 받기 응답 REST 큰그림 📝 문제풀이
◀ 이전 📋 목차 CH 08 ▶
🎮 CHAPTER 07 · 중급

웹 요청을 받아 JSON으로 답하는 컨트롤러

HTTP 과목에서 배운 REST·메서드·상태코드가 스프링에서 어떻게 코드로 살아나는지 봐요. 프론트(리액트)가 호출하는 API의 입구가 바로 이 컨트롤러예요.

🎯 이 장을 끝내면
🎮
@RestController
@RestController란?
웹 요청을 받아 데이터를 돌려주는 입구예요.

@RestController는 웹 요청을 받아서 JSON 데이터를 반환하는 컨트롤러예요. 화면(HTML 뷰)을 그려서 돌려주는 게 아니라, 순수한 데이터를 응답으로 내보내요. 그래서 리액트 같은 프론트엔드나 모바일 앱이 이 데이터를 받아 화면을 그리죠.

🔤
어노테이션(Annotation) — 클래스나 메서드 위에 붙이는 @로 시작하는 표시(이름표)예요. 코드에 "이건 이런 용도야"라고 쪽지를 붙여 두면, 스프링이 그 표시를 읽고 알아서 일을 처리해줘요. 앞으로 나올 @RestController·@GetMapping이 전부 어노테이션이에요.
🔤
REST API — 웹 주소(URL)와 HTTP 메서드로 데이터를 주고받도록 정한 규칙이에요. API는 프로그램끼리 대화하는 창구(입구)를 뜻하고, JSON은 그때 오가는 데이터를 { "name": "kim" }처럼 적는 가벼운 텍스트 형식이에요.
🍔
왜 REST라는 약속이 필요할까요? 여러 사람이 함께 쓰는 식당에 정해진 주문 방식이 없다면 주방은 뒤죽박죽이 되겠죠. REST는 "어떤 주소로, 어떤 동작(GET·POST 등)을 보내면 무슨 일이 일어난다"를 미리 정해 둔 약속이에요. 이 약속을 잘 지키면 프론트(리액트)와 서버가 서로 말이 척척 통하죠. 이 약속을 잘 따른 API를 RESTful하다고 불러요.
🧩 @RestController = @Controller + @ResponseBody 원래 @Controller뷰(HTML 화면)의 이름을 돌려주는 게 기본이에요. 여기에 @ResponseBody를 붙이면 "반환값을 뷰가 아니라 응답 본문(데이터) 그 자체로 보내라"는 뜻이 돼요. @RestController는 이 둘을 합쳐 놓은 어노테이션이에요. 클래스에 한 번만 붙이면 그 안의 모든 메서드가 데이터(JSON)를 응답해요. REST API를 만들 땐 이걸 씁니다.
🎛️
@Controller
뷰(화면) 이름을
돌려주는 기본
+
📤
@ResponseBody
반환값을 데이터
그 자체로 내보냄
=
🎮
@RestController
JSON 데이터를
돌려주는 API 입구
@RestController @Controller @ResponseBody JSON REST API @RequestMapping
🧭
뷰 vs 데이터. @Controller는 "화면을 그려 돌려주는" 전통적 방식, @RestController는 "데이터만 돌려주는" API 방식이에요. 요즘처럼 프론트와 백엔드가 분리된 구조에선 @RestController가 표준이에요.
🔗
요청 매핑
HTTP 메서드+경로를 메서드에 연결
HTTP 과목의 GET·POST·PUT·DELETE가 그대로 살아나요.
🔤
HTTP 메서드 — 브라우저가 서버에 보내는 요청의 "동작 종류"예요. 같은 주소라도 GET은 조회, POST는 생성, PUT은 수정, DELETE는 삭제를 뜻해요. 아래 매핑 어노테이션이 이 메서드와 짝을 이뤄요.
어노테이션HTTP 메서드역할
@GetMappingGET조회 — 데이터를 읽어옴
@PostMappingPOST생성 — 새 데이터를 만듦
@PutMappingPUT수정 — 기존 데이터를 바꿈
@DeleteMappingDELETE삭제 — 데이터를 지움

클래스 위에 @RequestMapping("/users")공통 경로(prefix)를 걸어두면, 각 메서드는 그 뒤에 이어지는 경로만 적으면 돼요. 아래 컨트롤러의 조회 메서드는 결국 GET /users에 연결돼요.

@RestController
@RequestMapping("/users")   // 공통 경로: 모든 메서드 앞에 /users
public class UserController {

    @GetMapping             // GET /users  (전체 조회)
    public List<User> list() {
        return userService.findAll();
    }

    @PostMapping            // POST /users (생성)
    public User create(@RequestBody User user) {
        return userService.save(user);
    }
}
💡
매핑 어노테이션은 곧 HTTP 메서드예요. "조회면 @GetMapping, 생성이면 @PostMapping" — HTTP 과목에서 배운 메서드의 의미를 그대로 어노테이션으로 옮기면 됩니다.
📥
데이터 받기
요청에 담긴 값을 파라미터로 받기
경로·쿼리스트링·본문, 세 곳에서 값이 들어와요.
📍 @PathVariable — 경로 변수 URL 경로 안에 들어 있는 값을 받아요. /users/{id}{id}처럼 경로의 일부가 곧 값이에요.
// 요청: GET /users/42
@GetMapping("/{id}")
public User get(@PathVariable Long id) {  // id = 42
    return userService.findById(id);
}
🔎 @RequestParam — 쿼리스트링 URL 뒤 ?name=kim&age=20 같은 쿼리 파라미터를 받아요. 주로 검색·필터·페이징 조건에 써요.
🔤
쿼리스트링(Query String) — URL 뒤에 ?를 붙여 ?name=kim&age=20처럼 추가 조건을 실어 보내는 부분이에요. 여러 개일 땐 &로 이어 붙여요. 쇼핑몰에서 조건을 걸고 검색하면 주소창 끝에 붙는 그 값들이죠.
// 요청: GET /users/search?name=kim
@GetMapping("/search")
public List<User> search(@RequestParam String name) {  // name = "kim"
    return userService.findByName(name);
}
📦 @RequestBody — 요청 본문(JSON) 요청 본문(body)에 담긴 JSON을 자바 객체로 자동 변환해서 받아요. 주로 생성(POST)·수정(PUT)에서 전달되는 데이터를 받을 때 써요.
// 요청 본문: { "name": "kim", "age": 20 }
@PostMapping
public User create(@RequestBody User user) {  // JSON → User 객체
    return userService.save(user);
}
🔑
세 개만 구분하면 끝. 값이 경로에 있으면 @PathVariable, URL 뒤 ?에 있으면 @RequestParam, 본문 JSON이면 @RequestBody예요.
📤
응답
객체를 반환하면 JSON이 되고, 상태코드도 제어
HTTP 과목의 200·201·404가 여기서 등장해요.
🔤
상태코드(HTTP status code) — 응답이 어떻게 됐는지 서버가 숫자로 알려주는 약속이에요. 200은 성공, 201은 새로 만들어짐, 404는 찾는 자원이 없음을 뜻해요.
🔄 객체 반환 → JSON 자동 변환 @RestController의 메서드가 객체를 반환하면, 스프링이 그 객체를 JSON으로 자동 변환해서 응답 본문에 담아 보내요. 개발자가 직접 JSON 문자열을 만들 필요가 없어요. 내부적으로 메시지 컨버터(Jackson)가 자바 객체 ↔ JSON 변환을 처리해줘요.
🔤
직렬화(Serialize) · 역직렬화(Deserialize) — 자바 객체를 네트워크로 보내기 좋게 JSON 문자열로 포장하는 것이 직렬화예요. 택배 보낼 물건을 상자에 담아 포장하는 것과 같죠. 반대로, 받은 JSON을 다시 자바 객체로 풀어내는 것이 역직렬화예요. 이 포장·개봉을 스프링(Jackson)이 자동으로 해줘서 우리는 객체만 다루면 돼요.
🎚️ ResponseEntity — 상태코드 세밀 제어 그냥 객체를 반환하면 상태코드는 기본 200 OK예요. 하지만 "생성됐으니 201 Created"처럼 상태코드를 세밀하게 정하고 싶으면 ResponseEntity로 감싸서 반환해요.
@PostMapping
public ResponseEntity<User> create(@RequestBody User user) {
    User saved = userService.save(user);
    return ResponseEntity
            .status(201)   // 201 Created
            .body(saved);  // 본문에 JSON
}
💡
상태코드는 약속이에요. 조회 성공 200, 생성 성공 201, 없는 자원 404 — HTTP 과목에서 배운 그 코드들을 ResponseEntity로 정확히 실어 보낼 수 있어요.
🌐
REST 큰그림
프론트가 호출하는 API — 큰 그림
HTTP 과목과 리액트가 여기서 하나로 이어져요.

우리가 만든 @RestControllerREST API의 입구예요. 브라우저의 리액트가 fetch로 이 API를 호출하면, 컨트롤러가 요청을 받아 서비스·레포지토리로 넘겨 처리하고, 결과를 JSON으로 돌려줘요. 프론트는 그 JSON을 받아 화면을 그려요.

🔤
클라이언트 · 서버 — 클라이언트는 요청을 보내는 쪽(브라우저의 리액트, 모바일 앱), 서버는 그 요청을 받아 처리해서 응답하는 쪽(우리가 만든 스프링 앱)이에요. 손님(클라이언트)이 주문하면 주방(서버)이 만들어 내주는 관계라고 생각하면 쉬워요.
⚛️
리액트(프론트)
fetch로 API 호출
GET /users/42
🎮
@RestController
요청 받아 처리
JSON 반환
🖥️
화면 렌더
받은 JSON으로
UI 그리기
🔗
과목이 이어져요. HTTP 과목의 메서드·경로·상태코드·JSON이 이 컨트롤러의 어노테이션과 반환값으로 그대로 나타나요. 그리고 리액트 과목에서 이 API를 실제로 호출하게 됩니다. CH 06의 계층 구조(컨트롤러 → 서비스 → 레포지토리)에서 컨트롤러가 바로 이 REST 컨트롤러예요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 네 가지 유형(객관식 · O/X · 빈칸 · 개념)을 섞어 두었어요.
CH 08 🗄️ 데이터 접근 (JPA) — 컨트롤러가 받은 데이터를 DB에 저장하기