RESTful APIRESTful API 사용 예제REST APIRESTful API 란rest api 모범사례

효율적인 RESTful API 설계와 구현 가이드

KUKJIN LEE
KUKJIN LEE
2024년 6월 11일
178

RESTful API는 현대 웹 개발의 중요한 요소입니다. 효율적으로 설계된 RESTful API는 애플리케이션의 확장성과 유지보수성을 크게 향상시킵니다.

 

1. RESTful API란?

REST(Representational State Transfer)는 웹의 설계 원칙 중 하나로, HTTP 프로토콜을 통해 데이터를 주고받는 아키텍처 스타일입니다. RESTful API는 이러한 REST 원칙을 따르는 API를 의미합니다. 주요 특징으로는 자원의 명확한 URI, HTTP 메소드 사용, 상태 비저장성 등이 있습니다.

 

2. RESTful API 설계 원칙

  • 자원(Resource) 기반 URI: 자원은 URI를 통해 명확하게 식별됩니다. 예를 들어, /users는 사용자 자원을 나타냅니다.

  • HTTP 메소드 사용: GET, POST, PUT, DELETE 등의 HTTP 메소드를 사용하여 자원에 대한 CRUD(생성, 읽기, 업데이트, 삭제) 작업을 수행합니다.

  • 상태 비저장성: 서버는 클라이언트의 상태를 저장하지 않으며, 모든 요청은 독립적으로 처리됩니다.

  • 표현(Representation): 클라이언트와 서버 간 데이터 교환은 JSON, XML 등의 표현 형식을 사용합니다.

 

3. RESTful API Best Practices

  • 명확하고 일관된 네이밍: URI와 메소드 사용을 일관성 있게 유지합니다.

  • HTTP 상태 코드 사용: 적절한 HTTP 상태 코드를 반환하여 요청 결과를 명확하게 나타냅니다.

  • 페이징, 필터링, 정렬: 대량의 데이터를 효율적으로 처리하기 위해 페이징, 필터링, 정렬 기능을 제공합니다.

  • 보안: 인증 및 권한 부여 메커니즘을 사용하여 API를 보호합니다. 예를 들어, JWT(Json Web Token)를 이용한 인증.

 

Node.js를 이용한 RESTful API 구현

물론 아키텍처 패턴(디자인 패턴)으로 설계하면 아래 코드의 유지보수성을 높이고, 재사용성을 높일 수 있습니다. 예시를 위해 작성했습니다.

const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
let users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
];
// 모든 사용자 조회
app.get('/users', (req, res) => {
    res.json(users);
});
// 특정 사용자 조회
app.get('/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).send('사용자를 찾을 수 없습니다.');
    res.json(user);
});
// 사용자 생성
app.post('/users', (req, res) => {
    if (!req.body.name) return res.status(400).send('이름이 필요합니다.');
    const newUser = {
        id: users.length + 1,
        name: req.body.name
    };
    users.push(newUser);
    res.status(201).json(newUser);
});
// 사용자 업데이트
app.put('/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).send('사용자를 찾을 수 없습니다.');
    if (!req.body.name) return res.status(400).send('이름이 필요합니다.');
    user.name = req.body.name;
    res.json(user);
});
// 사용자 삭제
app.delete('/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).send('사용자를 찾을 수 없습니다.');
    users = users.filter(u => u.id !== parseInt(req.params.id));
    res.status(204).send();
});
app.listen(port, () => {
    console.log(`서버가 http://localhost:${port} 에서 실행 중입니다.`);
});

 

Java (Spring Boot)를 이용한 RESTful API 구현

Java의 예시 또한 아키텍처 패턴(디자인 패턴)으로 설계하면 아래 코드의 유지보수성을 높이고, 재사용성을 높일 수 있습니다. 예시를 위해 작성했습니다.

(어노테이션을 사용하면 아래 코드는 훨씬 간단하게 작성할 수 있기 때문에, RESTful API 이해 용도로만 봐주세요!)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@SpringBootApplication
public class RestfulApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(RestfulApiApplication.class, args);
    }
}
@RestController
@RequestMapping("/users")
class UserController {
    private List<User> users = new ArrayList<>();
    public UserController() {
        users.add(new User(1, "Alice"));
        users.add(new User(2, "Bob"));
    }
    @GetMapping
    public List<User> getUsers() {
        return users;
    }
    @GetMapping("/{id}")
    public User getUser(@PathVariable int id) {
        Optional<User> user = users.stream().filter(u -> u.getId() == id).findFirst();
        if (!user.isPresent()) {
            throw new UserNotFoundException("사용자를 찾을 수 없습니다.");
        }
        return user.get();
    }
    @PostMapping
    public User createUser(@RequestBody User newUser) {
        newUser.setId(users.size() + 1);
        users.add(newUser);
        return newUser;
    }
    @PutMapping("/{id}")
    public User updateUser(@PathVariable int id, @RequestBody User updatedUser) {
        User user = getUser(id);
        user.setName(updatedUser.getName());
        return user;
    }
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable int id) {
        User user = getUser(id);
        users.remove(user);
    }
}
class User {
    private int id;
    private String name;
    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }
    // getters and setters
}
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "사용자를 찾을 수 없습니다.")
class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

 

 

관련 글

[SQL 입문] 필요한 데이터만 콕 집어 가져올 수 있는 WHERE 절

사용자는 테이블에 있는 모든 데이터를 다 보고 싶어 하지는 않습니다. 오히려 특정 항목에 대한 데이터만 가져오고 싶을 때가 훨씬 많습니다. 예를 들어, 어떤 사용자의 이메일이나 ID는 알고 있는데, 그 사람이 언제 우리 앱에 가입했는지 확인하고 싶다고 가정해 봅시다...

2026년 1월 27일10

SQL에서 SELECT란 무엇인가?

데이터베이스를 거대한 서류 보관함이라고 생각하면 됩니다. 보관함 안에는 수많은 데이터가 차곡차곡 쌓입니다. SELECT는 이 보관함에서 "내가 원하는 정보를 찾아줘!"라고 요청하는 명령어입니다. 이 과정을 전문 용어로 '쿼리(Query)'라고 부릅니다. &amp;nbs...

2026년 1월 26일10

[SQL 기초] "언제 하나씩 다 넣어?" 데이터 한 번에 넣기

개발을 하다 보면 데이터베이스(DB)에 샘플 데이터를 대량으로 넣어야 할 때가 있습니다. 메뉴 100개를 추가해야 하는데 INSERT 문을 100번 쓰고 있다면? 너무 비효율적이죠! 오늘은 SQL에서 여러 데이터를 한 번에 넣는 '다중 삽입(Multiple Inse...

2026년 1월 21일13

SQL 데이터 삽입하기

데이터가 없는 데이터베이스는 연료 없는 로켓과 같습니다. 이제 'Missions' 테이블에 새로운 행(row)을 추가하는 방법을 알아보겠습니다. "삽입(Inserting)"은 '데이터 추가'를 의미합니다. 기존 Missions 테이블 ...

2026년 1월 20일12