1. 자원(Resource) 설계
자원은 REST API에서 다루는 데이터나 엔터티를 의미합니다. 자원을 명확히 식별하기 위해 URI를 사용합니다.
핵심 원칙
- 자원 이름은 복수형 명사 사용
- 예시: /users, /posts, /comments
- 자원 계층 구조 명확히 표현
- 예시: /blogs/{blogId}/posts/{postId}
- 직관적이고 이해하기 쉬운 URI 사용
- 예시:
- 모든 사용자 조회: GET /users
- 특정 사용자 조회: GET /users/{id}
- 예시:
URI 설계 시 주의사항
- 슬래시(/)는 계층 구조를 나타냅니다.
- 올바른 예: /blogs/1/posts/100
- 잘못된 예: /blogs/1/posts/100/
- 하이픈(-)을 사용하여 가독성을 높입니다.
- 올바른 예: /blog-members
- 밑줄(_)은 사용하지 않습니다.
- 소문자만 사용합니다. (대소문자 구분됨)
- 올바른 예: /members, 잘못된 예: /Members
- 파일 확장자는 포함하지 않습니다.
- 잘못된 예: /photo.jpg
- 올바른 예: Accept 헤더 사용 (Accept: image/jpeg)
코드 예시 (Spring Boot)
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
// 모든 사용자 조회 (Collection)
@GetMapping
public List<User> getUsers() {
return userService.getAllUsers();
}
// 특정 사용자 조회
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
if(user == null){
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
}
HTTP 메서드 활용
HTTP 메서드는 자원에 대한 행위를 정의합니다.
| 메서드 | 역할 | 의미 |
|--------|-------------------|
| GET | 자원 조회 |
| POST | 자원 생성 |
| PUT | 자원 전체 수정 |
| PATCH | 자원의 일부 수정 |
| DELETE | 자원 삭제 |
각 메서드의 실습 코드 예시 (Spring Boot)
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
// GET: 모든 사용자 조회
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
// GET: 특정 사용자 조회
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
if(user == null){
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
// POST: 새 사용자 생성
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User newUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
}
// PUT: 사용자 전체 정보 수정(덮어쓰기)
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
User existingUser = userService.findById(id);
if(existingUser == null){
return ResponseEntity.notFound().build();
}
user.setId(id);
User updatedUser = userService.save(user);
return ResponseEntity.ok(updatedUser);
}
// PATCH: 사용자 정보 일부 수정
@PatchMapping("/{id}")
public ResponseEntity<User> partialUpdate(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
User updatedUser = userService.partialUpdate(id, updates);
if(updatedUser == null){
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(updatedUser);
}
// DELETE: 사용자 삭제
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
boolean deleted = userService.delete(id);
if(!deleted){
return ResponseEntity.notFound().build();
}
return ResponseEntity.noContent().build();
}
}
상태 코드(Status Codes)
HTTP 상태 코드는 API 응답 결과를 명확히 전달하는 중요한 요소입니다.
주요 상태 코드 정리
| 상태 코드 | 의미 | 상황 |
|-----------|------|
| 200 OK | 요청 성공적으로 처리됨 (주로 GET 요청 성공 시) |
| 201 Created | 새 자원이 성공적으로 생성됨 |
| 204 No Content | 삭제 성공 또는 응답 본문 없음 |
| 400 Bad Request | 클라이언트의 요청이 잘못됨 |
| 401 Unauthorized | 인증되지 않은 요청 |
| 403 Forbidden | 권한 부족으로 접근 불가 |
| 404 Not Found | 리소스를 찾을 수 없음 |
| 405 Method Not Allowed | 허용되지 않은 HTTP 메서드 사용 |
| 409 Conflict | 요청이 서버 상태와 충돌할 때 |
| 500 Internal Server Error | 서버 내부 오류 |
상태 코드 활용 코드 예시
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<?> getUser(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
Map<String, Object> error = new HashMap<>();
error.put("status", "error");
error.put("message", "User not found");
error.put("error_code", 404);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); //404 Not Found
}
return ResponseEntity.ok(user); //200 OK
}
@PostMapping
public ResponseEntity<?> createUser(@RequestBody User user) {
if(user.getEmail() == null) {
Map<String, Object> error = new HashMap<>();
error.put("status", "error");
error.put("message", "Email is required");
error.put("error_code", 400);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
User created = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser); //201 Created
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
boolean deleted = userService.delete(id);
if(!deleted){
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); //204 No Content
}
}
위의 코드에서:
- 성공적인 조회는 200 OK
- 생성 성공은 201 Created
- 삭제 성공은 204 No Content
- 클라이언트 오류는 400 Bad Request, 404 Not Found 등 적절한 상태코드를 반환합니다.
위의 세 가지 챕터(자원 설계, HTTP 메서드 활용, 상태 코드 활용)를 충분히 이해하고 위의 코드들을 실습해보면 REST API의 기본적인 CRUD 작업 구현 및 API 설계를 충분히 이해하고 스스로 구현할 수 있게 됩니다.
'Spring > 10. rest-api' 카테고리의 다른 글
| @PathVariable / @RequesteBody / @RequestParam (0) | 2025.03.16 |
|---|---|
| REST API 예제 (0) | 2025.03.14 |
| HttpMessageConverter (0) | 2025.03.14 |
| rest api 와 서버 사이드 렌더링 / 클라이언트 사이드 렌더링과의 연관성 (0) | 2025.03.08 |
| REST API의 개념 (2) | 2025.03.08 |