|
- 행위(Verb) - HTTP Method (GET, PUT, POST, DELETE 등)
- 표현(Representations) - HTTP Message PayLoad( 전송되는 데이터 )
서버 응답: 클라이언트가 JSON 형식을 원할 때: GET /users/123 Accept: application/json 서버 응답: HTTP/1.1 200 OK Content-Type: application/json { "id": 123, "name": "얼씨구", "email": "esg@example.com" } |
REST API 디자인 가이드
- URI는 Resource를 표현해야 한다. 즉, URI가 리소스의 위치나 이름을 명확히 나타내야 한다. 이를 통해 클라이언트가 정확한 리소스에 접근하거나 해당 리소스를 식별할 수 있게 된다.
- Resource에 대한 행위는 HTTP Method (GET, PUT, POST, DELETE 등)로 표현한다.
CRUD : Software가 가지는 기본적인 데이터 처리 기능을 통칭.
- 생성(Create) : SQL - INSERT
- 읽기(Read) : SQL - SELECT
- 갱신(Update) : SQL - UPDATE
- 삭제(Delete) : SQL - DELETE
URI 설계 시 주의할 점
- 동사보다는 명사를 대문자 보다는 가급적 소문자를 사용하자. 아래 URL은 서로 다른 Resource의 표현이다.
표현1) https://korea.com/Testing -- X
표현2) https://korea.com/test -- O
- 하이픈(-)은 URI 가독성을 높이는데 사용하자. Path에 띄어쓰기가 들어가는 경우 %20이 들어가 가독성이 떨어진다.
하이픈(-)을 사용하여 띄어쓰기를 대체( _는 사용 X) 하고 가독성을 높일 수 있다.
https://korea.com/test_a -- X
https://korea.com/test-a -- O
- 확장자를 사용하지 말자. REST API에서는 확장자를 사용하지 않으면서 Resource를 다루는 데 있어 더 유연해 진다.
https://korea.com/mypic.jpg -- X
https://korea.com/mypic -- O
- 마지막에 슬래시 (/)를 포함하지 않는다.
https://korea.com/test/ -- X
https://korea.com/test -- O
- 행위를 포함하지 않는다.
http://korea.com/delete-post/1 -- x
http://korea.com/post/1 -- O
* REST의 장점 : Open API를 제공하기 쉽다. Mashup이 활발해진 배경에는 REST의 영향을 무시할 수 없다. 멀티 플랫폼(Web, iOS, Android) 지원 및 연동이 용이하다. 원하는 타입(json, xml, rss…)으로 데이터를 주고 받을 수 있다. 기존 웹 인프라(HTTP)를 그대로 활용할 수 있다. (방화벽 문제에서 자유롭고, 로드 밸런서 등의 장비도 그대로 사용 가능하다). Resource가 Unique한 URI로 표현되도록 설계하면 웹 캐시 서버도 이용 가능하다.
* REST의 단점 : 사용할 수 있는 Method가 제한적이다. 즉, CRUD로 표현하기 모호한 작업을 처리하기 애매하며, HTTP 의존적이고 표준이 없어 관리가 어렵다.
REST API 디자인 가이드 https://bcho.tistory.com/914
Spring MVC 로 RESTFul 서비스 개발하기
https://devkingdom.tistory.com/108
html form 태그에서 PUT, DELETE 사용
https://jammdev.tistory.com/157
--------------RESTful 샘플 --------------------
🧑🦱 클라이언트 사이드에서 자바스크립트로 요청
let users = []; // 임시로 사용할 사용자 데이터
// 기본 라우트
app.get('/', (req, res) => {
res.send('Welcome to the RESTful API!');
});
// 사용자 생성
app.post('/users', (req, res) => {
const user = req.body;
user.id = users.length + 1; // 간단한 ID 생성 로직
users.push(user);
res.status(201).send(user);
});
// 모든 사용자 조회
app.get('/users', (req, res) => {
res.send(users);
});
// 특정 사용자 조회
app.get('/users/:id', (req, res) => {
const userId = parseInt(req.params.id, 10);
const user = users.find(u => u.id === userId);
if (user) {
res.send(user);
} else {
res.status(404).send({ message: 'User not found' });
}
});
// 사용자 정보 수정
app.put('/users/:id', (req, res) => {
const userId = parseInt(req.params.id, 10);
const userIndex = users.findIndex(u => u.id === userId);
if (userIndex !== -1) {
users[userIndex] = { ...users[userIndex], ...req.body };
res.send(users[userIndex]);
} else {
res.status(404).send({ message: 'User not found' });
}
});
// 사용자 삭제
app.delete('/users/:id', (req, res) => {
const userId = parseInt(req.params.id, 10);
const userIndex = users.findIndex(u => u.id === userId);
if (userIndex !== -1) {
users.splice(userIndex, 1);
res.status(204).send();
} else {
res.status(404).send({ message: 'User not found' });
}
});
------- 서버를 시작하고 API를 테스트 할 수 있다. --------
1) Node.js 서버인 경우 - express 모듈 사용
node index.js : 서버가 실행 중일 때, 다음과 같은 HTTP 요청을 사용하여 API를 테스트할 수 있다.
* 사용자 생성 (POST /users)
POST http://localhost:3000/users
Content-Type: application/json
{
"name": "John",
"email": "john@example.com"
}
* 모든 사용자 조회 (GET /users)
GET http://localhost:3000/users
* 특정 사용자 조회 (GET /users/ )
GET http://localhost:3000/users/1
* 사용자 정보 수정 (PUT /users/)
PUT http://localhost:3000/users/1
Content-Type: application/json
{
"name": "John"
}
* 사용자 삭제 (DELETE /users/)
DELETE http://localhost:3000/users/1
2) ApachTomcat 서버인 경우 - Spring 사용
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
@GetMapping
public List<User> getUsers() {
return userService.getUsers();
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
Optional<User> user = userService.getUserById(id);
if (user.isPresent()) {
return ResponseEntity.ok(user.get());
} else {
return ResponseEntity.notFound().build();
}
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
User updatedUser = userService.updateUser(id, userDetails);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}