1. 학습내용
16:00 ~ 17:00 스탠다드반 특강 ( 김재연 튜터님 )
응답 데이터
Server에서 Client로 Data를 전달하는 방법
[1] 정적 리소스
- 정적인 HTML, CSS, JS, Image 등을 변경 없이 그대로 반환한다.
[2] View Template
- SSR(Server Side Rendering)을 사용할 때 View가 반환된다.
📌 View Template
- View Template은 Model을 참고하여 HTML 등이 동적으로 만들어지고 Client에 응답된다.
- Spring Boot는 기본적으로 View Template 경로(src/main/resources/templates)를 설정한다.
- build.gradle에 Thymeleaf 의존성을 추가하면 ThymeleafViewResolver와 필요한 Spring Bean들이 자동으로 등록된다.
- @Controller의 응답으로 String을 반환하는 경우
@ResponseBody가 없으면 View Resolver가 실행되며 View를 찾고 Rendering한다.- @ResponseBody 가 있으면 HTTP Message Body에 return 문자열 값이 입력된다.
- 반환 타입이 void인 경우
- 잘 사용하지 않는다.
- @Controller + (@ResponseBody, HttpServletResponse, OutputStream)과 같은 HTTP Message Body를 처리하는 파라미터가 없으면 RequestMapping URL을 참고하여 View Name으로 사용한다.
[3] HTTP Message Body
- 응답 데이터를 직접 Message Body에 담아 반환한다.
▶ HTTP Message Body(응답)
[1] HttpServletResponse 사용
@Controller
public class ResponseBodyController {
@GetMapping("/v1/response-body")
public void responseBodyV1 (
HttpServletResponse response
)
throws IOException {
response.getWriter().write("data");
}
}
[2] ResponseEntity<> 사용
@GetMapping("/v2/response-body")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("data", HttpStatus.OK);
}
- Response Body에 data라는 문자열과 HttpStatus.OK에 해당하는 상태 코드를 반환한다. ★
- ResponseEntity는 HttpEntity 를 상속받았다.
- HttpEntity는 HTTP Message의 Header, Body 모두 가지고 있다.
[3] @ResponseBody(TEXT, JSON) 사용
@Data
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 전체 필드를 인자로 가진 생성자
public class Tutor {
private String name;
private int age;
}
Tutor 클래스
// TEXT 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-text")
public String responseBodyText() {
return "data"; // HTTP Message Body에 "data"
}
// JSON 데이터 통신
@ResponseStatus(Httpstatus.OK)
@ResponseBody
@GetMapping("/v3/response-body-json")
public Tutor responseBodyJson() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor; // HTTP Message Body에 Tutor Object -> JSON
}
- View를 사용하는 것이 아닌 HTTP Message Converter를 통해 HTTP Message Body를 직접 입력할 수 있다. → ResponseEntity와 같음(==)
- @ResponseStatus 를 사용하여 상태 코드를 지정할 수 있다
[4] ResponseEntity<Object>(JSON) ★ ★
@ResponseBody
@GetMapping("/v5/response-body")
public ResponseEntity<Tutor> responseBody() {
Tutor tutor = new Tutor("wonuk", 100);
return new ResponseEntity<>(tutor, HttpStatus.OK);
}
- ResponseEntity<> 두 번째 파라미터에 Enum을 사용하여 상태 코드를 바꿀 수 있다.
- HTTP Message Converter를 통하여 JSON 형태로 변환되어 반환된다.
- 동적으로 응답 코드를 변경할 수 있다.
정리
Client에서 Server로 Data를 전달하는 세가지 방법
[1] GET - Query Param, Query String
ex) http://localhost:8080/tutor?name=wonuk&age=100
- 사용하는 어노테이션
- @RequestParam, @ModelAttribute
[2] POST - HTML Form(x-www-form-urlencoded)
Server(Spring)에서 HTTP 응답을 Client에 전달하는 세가지 방법
- 정적 리소스
- 정적인 HTML, CSS, JS, Image 등을 변경없이 그대로 반환한다.
- View Template
- SSR(Server Side Rendering)을 사용할 때 View가 반환된다.
- 사용하는 어노테이션
- @Controller
- HTTP Message Body
- 응답 데이터를 직접 Message Body에 담아 반환한다.
- 사용하는 어노테이션
- @ResponseBody, ResponseEntity<Object>

- 요청
- @RequestParam, @ModelAttribute, @RequestBody
- 응답
- 정적 리소스, View Template(@Controller), @ResponseBody, ResponseEntity<Object>
메모장 만들기 (실습)
[1] 요구사항 분석 및 설계
- 메모장 API 요구사항
- 통신 데이터 형태는 JSON이다.
- 각각의 메모는 식별자(id), 제목(title), 내용(contents)으로 구성되어 있다.
- 응답을 각각의 API에 알맞게 해야 한다.
- 메모를 생성할 수 있다. (CREATE)
- 메모 생성 시 제목, 내용이 필요하다.
- 생성된 데이터(식별자, 제목, 내용)가 응답된다.
- 메모 전체 목록을 조회할 수 있다. (READ)
- 여러 개의 데이터를 배열 형태로 한번에 응답한다.
- 데이터가 없는 경우 비어있는 배열 형태로 응답한다.
- 메모 하나를 조회할 수 있다. (READ)
- 조회할 memo에 대한 식별자 id값이 필요하다.
- 조회된 데이터가 응답된다.
- 조회될 데이터가 없는 경우 Exception이 발생한다.
- 메모 하나를 전체 수정(덮어쓰기)할 수 있다. (UPDATE)
- 수정할 memo에 대한 식별자 id값이 필요하다.
- 수정할 요청 데이터(제목, 내용)가 꼭 필요하다.
- 수정된 데이터가 응답된다.
- 수정될 데이터가 없는 경우 Exception이 발생한다.
- 메모 하나의 제목을 수정(일부 수정)할 수 있다. (UPDATE)
- 수정할 memo에 대한 식별자 id값이 필요하다.
- 수정할 요청 데이터(제목)가 꼭 필요하다.
- 수정된 데이터가 응답된다.
- 수정될 데이터가 없는 경우 Exception이 발생한다.
- 메모를 삭제할 수 있다. (DELETE)
- 삭제할 memo에 대한 식별자 id값이 필요하다.
- 삭제될 데이터가 없는 경우 Exception이 발생한다.

== 메모장 다루는 기능관련은 ( 생략 )==
♣ 일반 void와 Void타입 차이점
- void: 반환값이 없는 메서드를 정의할 때 사용되는 키워드
- Void: 반환 타입이지만 실제로는 값이 없는 상황에서 사용되는 클래스, 주로 제네릭 타입에서 사용
문제점
- Controller에 책임이 너무 많다.(요청, 비지니스 로직, 응답, 예외 처리 등)
- 서버가 종료된 후 다시 켜지면 데이터가 모두 초기화 된다. ( DB가 없기 때문 )
{ 스탠다드반 }
예외처리
자바의 예외처리
예외 자체를 의미하는 Exception 클래스, 그리고 예외를 핸들링하기 위한 try-catch가 있다.
자바에서 Exception은 다시 2가지로 나뉩니다.
Checked Exception
- 반드시 try-catch나 상위 메소드로 throws 처리를 해야 하는 예외를 말합니다. 처리를 하지 않고 컴파일을 시도하면 오류가 발생하며 실패 합니다.
UnChecked Exception
- Exception을 처리하지 않아도 컴파일이 가능하고 프로그램 실행도 정상적으로 됩니다.

| 장점 | 단점 | |
| Checked Exception | - 예외 처리 강제 → 코드 안정성 향상 - 예외 발생 가능성을 명확히 문서화 |
- 가독성이 떨어짐 → 코드 생산성 하락 - 불필요한 예외 처리로 코드 복잡성 증가 |
| UnChecked Exception | - 단순하고 가독성 높은 코드 작성 가능 - 필요할 때만 예외 처리 |
- 예외를 누락할 가능성 존재 - 시스템의 신뢰도 하락 |
Spring Boot의 예외처리
- Exception을 발생시킨다
- 유효성 검증을 한다
Spring Boot 예외처리 방법
- try-catch (Spring은 자바 기반이므로 자바와 동일한 try-catch를 씁니다)
- @ExceptionHandler, @ControllerAdvice
- @Valid, @Validated
- 그 외 유용한 유효성 어노테이션
@ExceptionHandler, @ControllerAdvice ★
- @ExceptionHandler : 하나의 Controller 만 예외 핸들링
- @ControllerAdvice : 모든 Controller에서 발생하는 예외 핸들링
/* @ExceptionHandler */
@RestController
public class SampleController {
@GetMapping("/test")
public String test() {
throw new IllegalArgumentException("Invalid input!");
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
return ResponseEntity.badRequest().body("Error: " + ex.getMessage());
}
}
@RestController
public class DemoController {
@GetMapping("/demo")
public String demo() {
throw new IllegalArgumentException("Invalid input!");
}
}
/* @ControllerAdvice */
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
return ResponseEntity.badRequest().body("Global Error: " + ex.getMessage());
}
}
@RestController
public class SampleController {
@GetMapping("/test")
public String test() {
throw new IllegalArgumentException("Invalid input!");
}
}
@RestController
public class DemoController {
@GetMapping("/demo")
public String demo() {
throw new IllegalArgumentException("Invalid input!");
}
}
@Valid, @Validated ★
데이터를 검증하기 위한 어노테이션 입니다.
이를 활성화 하기 위해서는 아래 의존성을 추가 해야 합니다.
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation
implementation 'org.springframework.boot:spring-boot-starter-validation:3.3.5'

@Valid 예시
@RestController
public class UserController {
@PostMapping("/user")
public ResponseEntity<String> createUser(@RequestBody @Valid UserDto userDto){
return ResponseEntity.ok("User is valid!");
}
}
@Getter
public class UserDto {
private Long id;
@Min(20)
private Long age;
@Override
public String toString() {
return "UserDto{id=" + id + ", age=" + age + '}';
}
}
@Validated 예시
@Validated
@RestController
public class ValidatedController {
@PostMapping("/test-validated/number")
public String testValid(@Min(10) Integer number, @RequestBody @Valid UserDto userDto) {
return number + " : " + userDto.toString();
}
}
@Getter
public class UserDto {
private Long id;
@Min(20)
private Long age;
@Override
public String toString() {
return "UserDto{id=" + id + ", age=" + age + '}';
}
}

보통 클래스내 필드위에 선언한다. 이 외에도 많이 존재 @Notnull 등
- 새롭게 알게 된 점 ★
요청 값들은 매개변수로 응답 값은 반환타입으로 주로 쓰인다.
@RequestBody는 거의 j문자열, JSON (90%이상) 형태의 데이터들이 무수히 반환되는 값이며,
@RequestParam은 QueryParameter (?name=kim&age=20) 나 Form x-www-form-urlencoded
@ResponseEntity<{객체}>는 상태코드를 나타낼떄 많이 쓰임 Httpstatus.OK(200) , Httpstatus.NOT_FOUND(404) 등.
2. 내일 학습 할 것: 스프링 입문(6주차) , 알고리즘, 일정관리 앱 과제 명세서 만들기
'[내일배움캠프-Sparta] > Spring 6기' 카테고리의 다른 글
| TIL 25 [ Spring 일정 관리 앱 과제 ( 필수 . . . JDBC..??) + 미니세션 ( API, ERD ) ] (0) | 2025.03.24 |
|---|---|
| TIL 24 [ Spring ( 3 Layer 아키텍처, DB, SQL, JDBC, SQL Mapper ) ] (0) | 2025.03.21 |
| TIL 22 [ Spring ( 어노테이션II, Request Mapping, 요청 데이터) ] (0) | 2025.03.19 |
| TIL 21 [ Spring( 어노테이션, lombok, 프레임워크, 빌드 도구, 웹 기술 역사 + 스탠다드반 (Spring MVC) ] (0) | 2025.03.18 |
| TIL 20 [ Spring( 네트워크, 용어, HTTP, Rest API ) ] (0) | 2025.03.17 |