안드로이드만 올리다 갑자기 웬 Spring인가 싶지만... 최근 스쿼드 형태의 팀에서 일하며 든 생각은 내가 백엔드 시스템에 대한 지식이 너무 부족하다는 것이다. 두마리의 토끼를 잡는다는게 쉽지는 않지만 그래도 팀원들과 소통하는데 있어서 어려움은 없어야 한다고 생각해서 틈틈이 Spring 공부도 해보려고 한다.. 😇
다시 java를 하려니 kotlin이 정말 편하다는걸 새삼 느낌...🥹
설명 | Path Variable | Query Parameter | DataBody | |
---|---|---|---|---|
GET | 데이터를 조회하는 요청 | O | O | X |
POST | 새로운 데이터를 생성하는 요청 | O | △ | O |
PUT | 기존 데이터를 수정하는 요청 | O | △ | O |
DELETE | 데이터를 삭제하는 요청 | O | O | X |
Spring에서
Path Variable
,Query Parameter
,DataBody
는 HTTP 요청에서 데이터를 전달하는 방법을 설명하는 개념이다.
- Path Variable : URL 경로의 일부로 데이터를 전달하는 방식
/user/{name}
일 때{name}
이 Path Variable이다.@PathVariable
어노테이션을 사용해 이를 처리한다.- Query Parameter : URL 뒤에
?
를 붙여키-값
쌍으로 데이터를 전달하는 방식이고 여러 개의 파라미터를&
으로 구분한다.
/search?name=subeen
과 같은 형태로 쿼리 파라미터가 전달된다.@RequestParam
어노테이션을 사용해 이를 처리한다.- DataBody(Request Body) : HTTP 요청의 본문에 데이터를 담아 보내는 방식으로 POST, PUT 요청에서 사용되며 데이터를 JSON, XML 등으로 전달할 수 있다.
- 사용자가 입력한 데이터를 서버로 보낼 때 JSON 형식으로 본문에 포함될 수 있다.
@RequestBody
어노테이션을 사용해 이를 처리한다.
@RestController // REST API를 처리하는 컨트롤러임을 의미
@RequestMapping("/api") // "/api"로 시작하는 모든 URL 요청은 이 컨트롤러에서 처리함
public class GetApiController {
@GetMapping(path = "/hello") // "/hello" 주소로 들어오는 GET 요청을 처리함
public String hello() {
// http://localhost:8080/api/hello 로 접속 시 "Hello Spring Boot" 반환
return "Hello Spring Boot";
// HTML 형식으로 응답할 수도 있음
// var html = "<html> <body> <h1> Hello Spring Boot </body> </html>";
// return html;
}
// Path Variable을 사용하여 URL에서 값을 받아오는 방식
// URL에서 "message", "age", "isWoman" 값을 받아 처리
@GetMapping(path = "/echo/{message}/age/{age}/is-woman/{isWoman}")
public String echo(
@PathVariable(name = "message") String msg,
@PathVariable int age, // int 타입은 기본형으로 반드시 값을 가짐
@PathVariable boolean isWoman
) {
System.out.println("echo message: " + msg);
System.out.println("echo age: " + age);
System.out.println("echo isWoman: " + isWoman);
return msg.toUpperCase();
}
// Query Parameter
// 1. URL의 쿼리 스트링을 통해 특정 정보에 대해 필터링을 하는 방식
// http://localhost:8080/api/book?category=IT&issued-year=2025&issued-month=03&issued-day=22
@GetMapping(path = "/book")
public void queryParam(
@RequestParam String category,
@RequestParam(name = "issued-year") String issuedYear,
@RequestParam(name = "issued-month") String issuedMonth,
@RequestParam(name = "issued-day") String issuedDay
) {
System.out.println("book category: " + category);
System.out.println("book issuedYear: " + issuedYear);
System.out.println("book issuedMonth: " + issuedMonth);
System.out.println("book issuedDay: " + issuedDay);
}
// 2. 쿼리 파라미터를 객체로 매핑하여 파싱하는 방식
// http://localhost:8080/api/book2?category=IT&issuedYear=2025&issuedMonth=03&issuedDay=22
@GetMapping(path = "/book2")
public void queryParamDto(
BookQueryParam bookQueryParam // BookQueryParam 객체로 쿼리 파라미터를 받음
) {
System.out.println("bookQueryParam: " + bookQueryParam);
}
}
쿼리 파라미터를 객체 형태로 매핑받기 위한 클래스
Lombok 어노테이션을 사용해 수동으로 Getter/Setter 메소드와 생성자 등을 작성하는 과정을 자동화함
- @Data : 기본적인 Getter/Setter 메서드를 자동 생성해줌
- @NoArgsConstructor : 기본 생성자를 생성함
- @AllArgsConstructor : 모든 필드를 받는 생성자를 자동으로 생성함
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookQueryParam {
private String category;
private String issuedYear;
private String issuedMonth;
private String issuedDay;
}
@RestController
@RequestMapping("/api")
public class PostApiController {
@PostMapping("/post") // "/api/post" URL로 들어오는 POST 요청을 처리
public BookRequest post(
@RequestBody BookRequest bookRequest // HTTP Body로 들어온 JSON 데이터를 BookRequest 객체로 변환
// 클라이언트가 보내는 JSON 데이터를 자동으로 객체로 변환해줌
) {
System.out.println(bookRequest);
return bookRequest;
}
/*
반환값이 String인 경우에는 플레인 텍스트가 반환되고
객체인 경우에는 기본적으로 JSON 형식으로 변환되어 반환됨
- 반환값이 String인 경우
"BookRequest(name=Spring Boot, number=100, category=Java)"
- 반환값이 객체인 경우
{
"name": "Spring Boot",
"number": "100",
"category": "Java"
}
*/
@PostMapping("/user") // "/api/user" URL로 들어오는 POST 요청을 처리
private UserRequest post(
@RequestBody UserRequest userRequest // HTTP Body로 들어온 JSON 데이터를 UserRequest 객체로 변환
) {
System.out.println(userRequest);
return userRequest;
}
}
@JsonNaming은
JSON 변환시 속성 이름 변환 규칙을 지정하는 어노테이션으로 JSON 데이터를 송수신할 때 객체의 필드명이 자동으로 변환 된다.
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
private String userName;
private Integer userAge;
private String email;
private Boolean isKorean;
}
// 클라이언트에서 보내는 JSON이 다음과 같을 때
{
"user_name": "john",
"user_age": 20,
"email": "john@test.com",
"is_korean": false
}
// UserRequest 객체가 위의 JSON 데이터를 받으면 스네이크 케이스로 변환 및 매핑
userName = "John"
userAge = 20
email = "john@test.com"
isKorean = false
@Slf4j
@RestController
@RequestMapping("/api")
public class PutApiController {
private static final Logger log = LoggerFactory.getLogger(PutApiController.class);
@PutMapping("/put")
public void put(
@RequestBody UserRequest userRequest
) {
log.info("Request : {}", userRequest);
}
}
@Slf4j
@RestController
@RequestMapping("/api")
public class DeleteController {
private static final Logger log = LoggerFactory.getLogger(DeleteController.class);
@DeleteMapping(path = "/user/{userName}")
public void delete(
@PathVariable String userName
) {
log.info("user-name : {}", userName);
}
}