
마이크로서비스 아키텍처(MSA)에서 REST API는 클라이언트와 서버 간의 원활한 데이터 통신을 위한 중요한 수단입니다. 이번 포스트에서는 GET 및 DELETE 메소드의 매핑 방법을 상세히 설명하고, 호텔 정보 조회 API를 구현하는 방법을 다루겠습니다.
아래는 이해를 돕기 위해 '호텔 관리 시스템'을 기준으로 기본 기능에 대해 설명하겠습니다.
호텔 정보 조회 API 명세서
GET API 명세
- API Endpoint:
/hotels/{id} - HTTP Method: GET
- 설명: 특정 ID를 가진 호텔의 정보를 조회합니다
URI 패턴
- 필수 값: id: 호텔의 고유 식별자 (정수형)
응답 메시지
- 성공 시: 200 OK와 함께 호텔 정보 반환 (JSON)
- 실패 시: 404 Not Found (호텔이 존재하지 않는 경우)
DELETE API 명세
- API Endpoint:
/hotels/{id} - HTTP Method: DELETE
- 설명: 특정 ID를 가진 호텔을 삭제합니다
URI 패턴
- 필수 값: id: 삭제할 호텔의 고유 식별자 (정수형)
응답 메시지
- 성공 시: 204 No Content (삭제 성공)
- 실패 시: 404 Not Found (호텔이 존재하지 않는 경우)
Controller 클래스 구현
스프링 부트에서 REST API의 컨트롤러 클래스를 구현하여 사용자 요청을 처리합니다. @RestController 어노테이션을 사용하여 HTTP 요청과 응답을 처리하는 클래스를 정의합니다.
HotelController 클래스
package com.example.controller;
import com.example.model.Hotel;
import com.example.service.HotelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api/v1/hotels")
@Validated
public class HotelController {
@Autowired
private HotelService hotelService;
// 모든 호텔 조회
@GetMapping
public ResponseEntity> getAllHotels(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String location) {
List hotels = hotelService.getAllHotels(page, size, location);
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(Duration.ofMinutes(5)))
.body(hotels);
}
// 특정 호텔 정보 조회
@GetMapping("/{id}")
public ResponseEntity getHotelById(@PathVariable Long id) {
Optional hotel = hotelService.getHotelById(id);
return hotel.map(h -> ResponseEntity.ok()
.eTag(String.valueOf(h.getVersion()))
.body(h))
.orElse(ResponseEntity.notFound().build());
}
// 호텔 삭제
@DeleteMapping("/{id}")
public ResponseEntity deleteHotel(@PathVariable Long id) {
try {
hotelService.deleteHotel(id);
return ResponseEntity.noContent().build();
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
// 쿼리 파라미터를 활용한 호텔 검색
@GetMapping("/search")
public ResponseEntity> searchHotels(
@RequestParam(required = false) String name,
@RequestParam(required = false) String location,
@RequestParam(required = false) Integer minPrice,
@RequestParam(required = false) Integer maxPrice) {
List hotels = hotelService.searchHotels(name, location, minPrice, maxPrice);
return ResponseEntity.ok(hotels);
}
}@GetMapping 어노테이션
설명
@GetMapping: 이 어노테이션은 HTTP GET 요청을 처리하는 메소드를 매핑하는 데 사용됩니다. URL과 메소드의 매핑을 간편하게 설정할 수 있습니다.
사용법
- 메소드 선언부에만 적용 가능하며, path 속성을 사용하여 URI를 지정합니다
- params, headers 속성을 추가하여 조건부 매핑이 가능합니다
고급 사용 예시
// 조건부 매핑 - 특정 파라미터가 있을 때만 매핑
@GetMapping(value = "/{id}", params = "active=true")
public ResponseEntity getActiveHotelById(@PathVariable Long id) {
Hotel hotel = hotelService.getActiveHotelById(id);
return ResponseEntity.ok(hotel);
}
// 헤더 조건부 매핑
@GetMapping(value = "/{id}", headers = "X-API-Version=v2")
public ResponseEntity getHotelByIdV2(@PathVariable Long id) {
Hotel hotel = hotelService.getHotelByIdWithExtendedInfo(id);
return ResponseEntity.ok(hotel);
}
// Content-Type 지정
@GetMapping(value = "/{id}", produces = "application/json")
public ResponseEntity getHotelAsJson(@PathVariable Long id) {
Hotel hotel = hotelService.getHotelById(id);
return ResponseEntity.ok(hotel);
}@PathVariable 어노테이션
설명
@PathVariable: URI 패턴에서 동적으로 변하는 부분의 값을 메소드 인자에 주입하는 데 사용됩니다.
사용법
메소드의 매개변수로 선언하며, 기본값은 required=true로 필수입니다.
다양한 활용 예시
// 기본 사용법
@GetMapping("/{id}")
public ResponseEntity getHotelById(@PathVariable Long id) {
Hotel hotel = hotelService.getHotelById(id);
return ResponseEntity.ok(hotel);
}
// 변수명이 다른 경우
@GetMapping("/{hotelId}")
public ResponseEntity getHotel(@PathVariable("hotelId") Long id) {
Hotel hotel = hotelService.getHotelById(id);
return ResponseEntity.ok(hotel);
}
// 다중 PathVariable
@GetMapping("/{hotelId}/rooms/{roomId}")
public ResponseEntity getRoom(
@PathVariable Long hotelId,
@PathVariable Long roomId) {
Room room = hotelService.getRoom(hotelId, roomId);
return ResponseEntity.ok(room);
}
// 정규식 패턴 사용
@GetMapping("/{id:[0-9]+}")
public ResponseEntity getHotelByNumericId(@PathVariable Long id) {
Hotel hotel = hotelService.getHotelById(id);
return ResponseEntity.ok(hotel);
}@RequestParam 어노테이션
설명
@RequestParam: 쿼리 파라미터를 메소드 인자에 주입하는 데 사용됩니다. 요청 URL에 포함된 파라미터를 처리할 수 있습니다.
사용법
메소드 매개변수로 선언하며, 기본값은 required=true입니다. 선택적 파라미터로 설정할 수 있습니다.
실전 활용 예시
// 기본 사용법 - 선택적 파라미터
@GetMapping
public ResponseEntity> getHotelsByLocation(
@RequestParam(required = false) String location) {
List hotels = hotelService.getHotelsByLocation(location);
return ResponseEntity.ok(hotels);
}
// 기본값 설정
@GetMapping
public ResponseEntity> getHotels(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "name") String sortBy) {
List hotels = hotelService.getHotels(page, size, sortBy);
return ResponseEntity.ok(hotels);
}
// 다중 값 처리
@GetMapping
public ResponseEntity> getHotelsByAmenities(
@RequestParam List amenities) {
List hotels = hotelService.getHotelsByAmenities(amenities);
return ResponseEntity.ok(hotels);
}
// Map으로 모든 파라미터 받기
@GetMapping("/filter")
public ResponseEntity> filterHotels(
@RequestParam Map filters) {
List hotels = hotelService.filterHotels(filters);
return ResponseEntity.ok(hotels);
}@DeleteMapping 어노테이션
설명
@DeleteMapping: HTTP DELETE 요청을 처리하는 메소드를 매핑하는 데 사용됩니다. GET 메소드와 사용 방법이 유사합니다.
Spring Boot 2025년 최신 설정
application.properties 설정 (필수):
spring.mvc.hiddenmethod.filter.enabled=true또는 application.yml:
spring:
mvc:
hiddenmethod:
filter:
enabled: true실전 구현 예시
// 기본 삭제
@DeleteMapping("/{id}")
public ResponseEntity deleteHotel(@PathVariable Long id) {
try {
hotelService.deleteHotel(id);
return ResponseEntity.noContent().build();
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
// 조건부 삭제
@DeleteMapping("/{id}")
public ResponseEntity deleteHotelWithValidation(
@PathVariable Long id,
@RequestParam(required = false) boolean force) {
try {
boolean deleted = hotelService.deleteHotel(id, force);
if (deleted) {
return ResponseEntity.ok(new ApiResponse("Hotel deleted successfully"));
} else {
return ResponseEntity.badRequest()
.body(new ApiResponse("Cannot delete hotel with active bookings"));
}
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
// 대량 삭제
@DeleteMapping
public ResponseEntity deleteMultipleHotels(
@RequestParam List ids) {
int deletedCount = hotelService.deleteHotels(ids);
return ResponseEntity.ok(
new ApiResponse(deletedCount + " hotels deleted successfully"));
}예외 처리 및 응답 최적화
전역 예외 처리
@RestControllerAdvice
public class HotelControllerAdvice {
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity handleNotFound(EntityNotFoundException e) {
ErrorResponse error = new ErrorResponse("HOTEL_NOT_FOUND", e.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(ValidationException.class)
public ResponseEntity handleValidation(ValidationException e) {
ErrorResponse error = new ErrorResponse("VALIDATION_ERROR", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
}응답 DTO 활용
// 응답 전용 DTO
public class HotelResponse {
private Long id;
private String name;
private String location;
private List rooms;
// 생성자, getter, setter...
}
@GetMapping("/{id}")
public ResponseEntity getHotelById(@PathVariable Long id) {
Hotel hotel = hotelService.getHotelById(id);
HotelResponse response = HotelMapper.toResponse(hotel);
return ResponseEntity.ok(response);
}결론
이번 포스트에서는 REST API에서 GET 및 DELETE 메소드를 매핑하는 방법에 대해 설명했습니다. 호텔 정보 조회 및 삭제 API를 구현하며, 다양한 어노테이션(@GetMapping, @DeleteMapping, @PathVariable, @RequestParam)의 사용법을 살펴보았습니다.
핵심 포인트:
- @GetMapping과 @DeleteMapping의 올바른 사용법 이해
- @PathVariable과 @RequestParam의 차이점과 활용법 숙지
- Spring Boot 2025년 최신 설정을 통한 DELETE 메소드 지원
- 예외 처리와 응답 최적화를 통한 안정적인 API 구현
- RESTful 설계 원칙을 따른 명확한 API 구조
이러한 원리를 바탕으로 더 복잡한 API를 개발하고 확장할 수 있습니다. MSA 환경에서 서비스 간 통신의 기초가 되는 REST API 설계를 통해 확장 가능하고 유지보수하기 쉬운 시스템을 구축할 수 있습니다.
'IT기술 > MSA (with. springboot)' 카테고리의 다른 글
| Spring Boot DTO 패턴 완벽 가이드: MSA 환경에서의 효율적인 데이터 전송 객체 활용 (4) | 2025.07.11 |
|---|---|
| Spring Boot REST API 완벽 구현 가이드: 스테레오타입 어노테이션을 활용한 호텔 관리 시스템 (4) | 2025.07.10 |
| REST API 완벽 가이드: MSA 환경에서의 효율적인 서비스 간 통신 설계 (0) | 2025.07.09 |
| Spring Web MVC 프레임워크 완벽 가이드: MSA 환경에서의 웹 애플리케이션 구축 (0) | 2025.07.08 |
| Spring Boot DTO 패턴 완벽 가이드: MSA 환경에서의 효율적인 데이터 전송 객체 활용 (2) | 2025.07.07 |