1. RESTful API๋?
RESTful API๋ REST(Representational State Transfer) ์ํคํ ์ฒ ์คํ์ผ์ ๋ฐ๋ฅด๋ API๋ฅผ ์๋ฏธํ๋ค.
REST๋ 2000๋ ๋ก์ด ํ๋ฉ(Roy Fielding)์ด ๋ ผ๋ฌธ์์ ์๊ฐํ ๊ฐ๋ ์ผ๋ก,
์น์ ์ฅ์ ์ ๊ทน๋ํํ๋ ๋คํธ์ํฌ ์ํคํ ์ฒ ์์น์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ค.
RESTful API๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ํต์ ์ REST์ ์์น์ ๋ง๊ฒ ์ค๊ณํ API๋ฅผ ์๋ฏธํ๋ค.
์ฝ๊ฒ ๋งํด, RESTful API๋ "๊ท์น์ ์งํค๋ HTTP API"๋ผ๊ณ ๋ณผ ์ ์๋ค.
๊ท์น์ ๋ฐ๋ฅด์ง ์์ผ๋ฉด RESTfulํ์ง ์์ API๊ฐ ๋ ์ ์๋ค.
2. REST์ ๊ธฐ๋ณธ ์์น
RESTful API๋ฅผ ์ค๊ณํ๊ธฐ ์ํด์๋ REST์ ๊ธฐ๋ณธ ์์น์ ์ดํดํด์ผ ํ๋ค.
REST๋ ๋ค์๊ณผ ๊ฐ์ ์ฃผ์ ์์น์ ๋ฐ๋ฅธ๋ค.
1) ํด๋ผ์ด์ธํธ-์๋ฒ ๊ตฌ์กฐ (Client-Server)
- ํด๋ผ์ด์ธํธ์ ์๋ฒ๋ ์๋ก ๋ ๋ฆฝ์ ์ผ๋ก ๋์ํด์ผ ํ๋ค.
- ํด๋ผ์ด์ธํธ๋ UI์ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ด๋นํ๊ณ , ์๋ฒ๋ ๋ฐ์ดํฐ ์ ์ฅ ๋ฐ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๋ค.
- ์๋ก์ ์ญํ ์ด ๋ช ํํ๊ฒ ๋ถ๋ฆฌ๋์ด์ผ ํ์ฅ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ์ข์์ง๋ค.
2) ๋ฌด์ํ์ฑ (Stateless)
- ์๋ฒ๋ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ์ฅํ์ง ์๋๋ค.
- ๊ฐ ์์ฒญ์ ๋ ๋ฆฝ์ ์ด๋ฉฐ, ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ์์ฒญ์ ํฌํจํด์ผ ํ๋ค.
- ์๋ฅผ ๋ค์ด, ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ๋ ค๋ฉด ํด๋ผ์ด์ธํธ๋ ๋งค ์์ฒญ๋ง๋ค ์ธ์ฆ ์ ๋ณด๋ฅผ ํฌํจํด์ผ ํ๋ค.
3) ์บ์ ๊ฐ๋ฅ (Cacheable)
- ํด๋ผ์ด์ธํธ๋ ์๋ต์ ์บ์ฑํ ์ ์์ด์ผ ํ๋ค.
- ์๋ต์๋ ์บ์ฑ ๊ด๋ จ ์ ๋ณด๋ฅผ ๋ด์์ผ ํ๋ฉฐ, Cache-Control, ETag ๋ฑ์ HTTP ํค๋๋ฅผ ํ์ฉํ๋ค.
- ๋ถํ์ํ ์๋ฒ ์์ฒญ์ ์ค์ฌ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ค.
4) ๊ณ์ธตํ๋ ์์คํ (Layered System)
- ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ ์ง์ ํต์ ํ๋ ๊ฒ์ด ์๋๋ผ **์ค๊ฐ ๊ณ์ธต(ํ๋ก์, ๋ก๋ ๋ฐธ๋ฐ์ ๋ฑ)**์ ๊ฑฐ์น ์ ์๋ค.
- ์ด๋ฅผ ํตํด ๋ณด์, ๋ก๋ ๋ฐธ๋ฐ์ฑ, ์ฑ๋ฅ ์ต์ ํ ๋ฑ์ ํ ์ ์๋ค.
5) ์ผ๊ด๋ ์ธํฐํ์ด์ค (Uniform Interface)
- RESTful API๋ ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ์ค๊ณ๋์ด์ผ ํ๋ค.
- ๋ชจ๋ ๋ฆฌ์์ค๋ ๋ช ์ฌ ๊ธฐ๋ฐ URL์ ์ฌ์ฉํ๊ณ , HTTP ๋ฉ์๋๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ฌ์ฉํด์ผ ํ๋ค.
- ์๋ฅผ ๋ค์ด, GET /users๋ ์ฌ์ฉ์ ๋ชฉ๋ก์ ์กฐํํ๊ณ , POST /users๋ ์๋ก์ด ์ฌ์ฉ์๋ฅผ ์ถ๊ฐํ๋ค.
6) ์ฝ๋ ์จ ๋๋งจ๋ (Code on Demand, ์ ํ ์ฌํญ)
- ํด๋ผ์ด์ธํธ๊ฐ ์คํํ ์ ์๋ ์ฝ๋๋ฅผ ์๋ฒ๊ฐ ์ ๊ณตํ ์ ์๋ค.
- ์๋ฅผ ๋ค์ด, JavaScript ํ์ผ์ ํด๋ผ์ด์ธํธ๋ก ์ ์กํ์ฌ ๋์ ์ผ๋ก ์คํํ๊ฒ ํ๋ ๋ฐฉ์์ด ๊ฐ๋ฅํ๋ค.
์์ ์์น ์ค "์ฝ๋ ์จ ๋๋งจ๋"๋ ํ์ ์์๊ฐ ์๋๋ฉฐ, ๋๋จธ์ง ๋ค์ฏ ๊ฐ์ง๋ ๋ฐ๋์ ์ง์ผ์ผ ํ๋ค.
3. RESTful API ์ค๊ณ ์์น
RESTful API๋ ๋ฆฌ์์ค๋ฅผ ์ค์ฌ์ผ๋ก ์ค๊ณํด์ผ ํ๋ค. API์์ ๋ค๋ฃจ๋ ๋ฐ์ดํฐ๋ "๋ฆฌ์์ค(Resource)"์ด๋ฉฐ,
์ด๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ช ํํ URL ๋ฐ HTTP ๋ฉ์๋๋ฅผ ์ ์ํ๋ ๊ฒ์ด ์ค์ํ๋ค.
1) ๋ฆฌ์์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ URL ์ค๊ณ
- ๋ฆฌ์์ค๋ ๋ช ์ฌ๋ฅผ ์ฌ์ฉํ์ฌ ํํํ๋ค.
- URL ๊ฒฝ๋ก์๋ ๋์ฌ๊ฐ ํฌํจ๋์ง ์๋๋ค.
- ์์:
- GET /users (๋ชจ๋ ์ฌ์ฉ์ ์กฐํ)
- GET /users/1 (ID๊ฐ 1์ธ ์ฌ์ฉ์ ์กฐํ)
- POST /users (์๋ก์ด ์ฌ์ฉ์ ์์ฑ)
- PUT /users/1 (ID๊ฐ 1์ธ ์ฌ์ฉ์ ์ ๋ณด ์์ )
- DELETE /users/1 (ID๊ฐ 1์ธ ์ฌ์ฉ์ ์ญ์ )
2) HTTP ๋ฉ์๋ ํ์ฉ
RESTful API์์๋ HTTP ๋ฉ์๋๋ฅผ ์ผ๊ด๋๊ฒ ์ฌ์ฉํด์ผ ํ๋ค.
HTTP ๋ฉ์๋์๋ฏธ์์
GET | ๋ฐ์ดํฐ ์กฐํ | GET /users/1 (1๋ฒ ์ฌ์ฉ์ ์กฐํ) |
POST | ์๋ก์ด ๋ฆฌ์์ค ์์ฑ | POST /users (์ ์ฌ์ฉ์ ์ถ๊ฐ) |
PUT | ๊ธฐ์กด ๋ฆฌ์์ค ์ ์ฒด ์์ | PUT /users/1 (1๋ฒ ์ฌ์ฉ์ ์ ๋ณด ์์ ) |
PATCH | ๊ธฐ์กด ๋ฆฌ์์ค ๋ถ๋ถ ์์ | PATCH /users/1 (1๋ฒ ์ฌ์ฉ์์ ์ผ๋ถ ์ ๋ณด ์์ ) |
DELETE | ๋ฆฌ์์ค ์ญ์ | DELETE /users/1 (1๋ฒ ์ฌ์ฉ์ ์ญ์ ) |
3) ์๋ต ์ํ ์ฝ๋ ์ฌ์ฉ
์ฌ๋ฐ๋ฅธ HTTP ์ํ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด API์ ๊ฐ๋ ์ฑ์ด ์ข์์ง๊ณ , ํด๋ผ์ด์ธํธ๊ฐ ์๋ต์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
์ํ ์ฝ๋์๋ฏธ
200 OK | ์ ์ ์๋ต |
201 Created | ์๋ก์ด ๋ฆฌ์์ค ์์ฑ ์ฑ๊ณต |
204 No Content | ์์ฒญ ์ฑ๊ณต, ํ์ง๋ง ๋ฐํํ ๋ฐ์ดํฐ ์์ |
400 Bad Request | ์๋ชป๋ ์์ฒญ (์ ํจ์ฑ ๊ฒ์ฌ ์คํจ ๋ฑ) |
401 Unauthorized | ์ธ์ฆ ์คํจ (๋ก๊ทธ์ธ ํ์) |
403 Forbidden | ๊ถํ ์์ |
404 Not Found | ๋ฆฌ์์ค๋ฅผ ์ฐพ์ ์ ์์ |
500 Internal Server Error | ์๋ฒ ์ค๋ฅ |
4. RESTful API ์์ (Spring Boot)
์๋๋ Spring Boot๋ฅผ ํ์ฉํ RESTful API ์์ ์ด๋ค.
1) REST ์ปจํธ๋กค๋ฌ
@RestController
@RequestMapping("/users")
public class UserController {
private final List<User> users = new ArrayList<>();
// ์ฌ์ฉ์ ๋ชฉ๋ก ์กฐํ (GET /users)
@GetMapping
public List<User> getUsers() {
return users;
}
// ํน์ ์ฌ์ฉ์ ์กฐํ (GET /users/{id})
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable int id) {
return users.stream()
.filter(user -> user.getId() == id)
.findFirst()
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// ์ฌ์ฉ์ ์ถ๊ฐ (POST /users)
@PostMapping
public ResponseEntity<User> addUser(@RequestBody User user) {
user.setId(users.size() + 1);
users.add(user);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}
// ์ฌ์ฉ์ ์ ๋ณด ์์ (PUT /users/{id})
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable int id, @RequestBody User newUser) {
for (User user : users) {
if (user.getId() == id) {
user.setName(newUser.getName());
user.setEmail(newUser.getEmail());
return ResponseEntity.ok(user);
}
}
return ResponseEntity.notFound().build();
}
// ์ฌ์ฉ์ ์ญ์ (DELETE /users/{id})
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable int id) {
if (users.removeIf(user -> user.getId() == id)) {
return ResponseEntity.ok().build();
}
return ResponseEntity.notFound().build();
}
}
2) User ๋ชจ๋ธ
public class User {
private int id;
private String name;
private String email;
// Getter, Setter, ์์ฑ์ ์๋ต
}
5. ๊ฒฐ๋ก
RESTful API๋ ์น์ ์์น์ ๋ฐ๋ฅด๋ HTTP API๋ก,
๋ฆฌ์์ค๋ฅผ ์ค์ฌ์ผ๋ก URL์ ์ค๊ณํ๊ณ HTTP ๋ฉ์๋๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ฌ์ฉํด์ผ ํ๋ค.
์ฌ๋ฐ๋ฅธ ์ค๊ณ๋ฅผ ์งํค๋ฉด ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ด ๋ฐ์ด๋ API๋ฅผ ๋ง๋ค ์ ์๋ค.
Spring Boot๋ฅผ ํ์ฉํ๋ฉด RESTful API๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ผ๋ฉฐ,
์ํ ์ฝ๋์ JSON์ ํ์ฉํด ๋ช ํํ API ์๋ต์ ์ ๊ณตํ ์ ์๋ค.
'๐ Web' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Git Flow ์๋ฒฝ ์ ๋ฆฌ: ํ์ ๊ณผ ๋ฐฐํฌ๋ฅผ ์ํ Git ๋ธ๋์น ์ ๋ต (0) | 2025.02.28 |
---|---|
JWT (JSON Web Token)๋? ์ฝ๊ฒ ์ดํดํ๊ธฐ (0) | 2025.02.27 |