-
RestFul 하다?카테고리 없음 2024. 5. 4. 15:44
이 글은
- RestFul 하다 라는게 뭔지 설명하기 앞서서 Rest api가 뭔지 알아 보자
REST API
- Representational State Transfer의 약자
- 소프트웨어 프로그램 아키텍처의 한 형식이다
- www 와 같은 분산 하이퍼미디어 시스템을 위한 스포트웨어 개발 아키텍처의 한 형식
- 기본적으로 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하기 때문에 웹의 장점을 최대한 활용할 수 있는 아키텍처 스타일 이다
- HTTP URI를 통해 자원을 명시하고 HTTP Method를 통해 해당 자원에 대한 CRUD OPERATION을 적용하는 것을 의미한다
- REST는 자원 기반의 구조 설계의 중심에 Resource가 있고 HTTP Method를 통해 Resource를 처리하도록 설계된 아키텍쳐를 의미한다
HTTP Method
- POST - 리소스를 생성
- GET - 리소스를 조회
- PUT - 리소스를 수정
- DELETE - 리소스를 삭제
REST의 구성
- Resource(자원) - URL
- Verb(행위) - Http Method
- Representations(표현)
RESTful 하다?
- 일단 예제 코드이다
- 잘못 된 코드들이다
- 매핑 어노테이션에서 URI 부분을 수정해야한다
@RestController @RequestMapping("/task") public class TaskController { private final TaskService taskService; public TaskController(TaskService taskService) { this.taskService = taskService; } @GetMapping("/list") public ResponseEntity<List<TaskInfoResponseDTO>> taskDtoList(@RequestParam("projectId") Long projectId) { List<TaskInfoResponseDTO> taskListByProject = taskService.findTaskListByProject(projectId); return ResponseEntity.ok().body(taskListByProject); } @GetMapping("/{taskId}") public ResponseEntity<TaskDto> findTaskDto(@PathVariable("taskId") Long taskId) { Optional<TaskDto> info = taskService.findTask(taskId); return info.isPresent() ? ResponseEntity.ok().body(info.get()) : ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } @PostMapping("/register") public ResponseEntity<Void> createTask(@Valid @RequestBody TaskRequest taskRequest) { boolean isProcessed = taskService.registerTaskAndTaskTag(taskRequest); return isProcessed ? ResponseEntity.status(HttpStatus.CREATED).build() : ResponseEntity.status(HttpStatus.CONFLICT).build(); } @PutMapping("/{taskId}/modify") public ResponseEntity<Void> modifyTask(@PathVariable("taskId") Long taskId, @Valid @RequestBody TaskRequest taskRequest) { boolean isProcessed = taskService.modifyTask(taskId, taskRequest); return isProcessed ? ResponseEntity.status(HttpStatus.OK).build() : ResponseEntity.status(HttpStatus.CONFLICT).build(); } @DeleteMapping("/{taskId}/delete") @ResponseStatus(HttpStatus.OK) public void deleteTask(@PathVariable("taskId") Long taskId) { taskService.deleteTask(taskId); } }
1. 각 메소드의 기능은 HTTP 메소드에서 정의 되어 있다
- 이미 저장하는 기능은 POST, 조회 GET, 수정 PUT, 삭제 DELETE 인데 URI 에 각각의 기능을 중복해서 적어 줄 필요가 없다
- RESTful 정의에서 각 리소스에 대한 기능을 HTTP 메소드를 이용하여 일관되게 정의할 수 있어야 한다 의 의미가 이런 의미이다
2. 객체명이 URI에 포함된다면 가급적이면 복수형을 사용해야한다
- 관례적으로 객체명을 복수로 써 주는것이 좋다
- 예를들어 위의 코드에서는 task -> tasks 이렇게 해야한다
수정 코드
@RestController @RequestMapping("/tasks") public class TaskController { private final TaskService taskService; public TaskController(TaskService taskService) { this.taskService = taskService; } @GetMapping("/list") public ResponseEntity<List<TaskInfoResponseDTO>> taskDtoList(@RequestParam("projectId") Long projectId) { List<TaskInfoResponseDTO> taskListByProject = taskService.findTaskListByProject(projectId); return ResponseEntity.ok().body(taskListByProject); } @GetMapping("/{taskId}") public ResponseEntity<TaskDto> findTaskDto(@PathVariable("taskId") Long taskId) { Optional<TaskDto> info = taskService.findTask(taskId); return info.isPresent() ? ResponseEntity.ok().body(info.get()) : ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } @PostMapping public ResponseEntity<Void> createTask(@Valid @RequestBody TaskRequest taskRequest) { boolean isProcessed = taskService.registerTaskAndTaskTag(taskRequest); return isProcessed ? ResponseEntity.status(HttpStatus.CREATED).build() : ResponseEntity.status(HttpStatus.CONFLICT).build(); } @PutMapping("/{taskId}") public ResponseEntity<Void> modifyTask(@PathVariable("taskId") Long taskId, @Valid @RequestBody TaskRequest taskRequest) { boolean isProcessed = taskService.modifyTask(taskId, taskRequest); return isProcessed ? ResponseEntity.status(HttpStatus.OK).build() : ResponseEntity.status(HttpStatus.CONFLICT).build(); } @DeleteMapping("/{taskId}") @ResponseStatus(HttpStatus.OK) public void deleteTask(@PathVariable("taskId") Long taskId) { taskService.deleteTask(taskId); } }
하지만
- 기준이 다 다르고 확실하게 정의해 놓은 것 이 없다
- RESTful 의 가장 중요한 것은 URI의 명확한 정의를 통해 실무에서 API 사용에 있어 원할한 소통이 가능해야 한다는 것이다
이것 이외의 규칙들
- "/" 슬래시를 통해 계층 관계를 표시하여 구분
- "_ " 밑줄 사용 금지
- URI 경로는 소문자
- 파일 확장자는 포함 금지
- 이미 HTTP METHOD 어노테이션을 사용함으로써 URI에 명시하지 않아도 된다 즉, CRUD 기능을 나타내는 것은 URI에 사용 X
- 프로그래밍 언어의 Method명을 이용 금지
- 명사 단수형 보단 복수형 ex) task -> tasks
-
- API에 있어서 서브 도메인은 일관성있게 사용해야함
결론
- 이러한 규칙들이 있지만 항상 잊지 않고 생각해야 하는건 URI의 명확한 정의를 통해 실무에서 API사용에 있어서 원할한 소통이 가능 해야한다
- 이러한 규칙들이 있지만 그 팀이나 조직의 규칙에 맞게 따라야 한다