본문 바로가기
공부

[REST] API 요청, 응답

by 꾸돼지 2025. 6. 12.
320x100

클라이언트에게 받은 요청을 수신해서, 검증하고, 작업을 수행하고, 응답하는 일련의 메커니즘을 API라고 한다.

 

나는 다음의 문서를 참고했다.

https://spec.openapis.org/oas/v3.1.0

 

OpenAPI Specification v3.1.0

Each Media Type Object provides schema and examples for the media type identified by its key. It is common to use multipart/form-data as a Content-Type when transferring request bodies to operations. In contrast to 2.0, a schema is REQUIRED to define the i

spec.openapis.org

 

RFC7231 스펙 문서

https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.1

 

RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content

The Hypertext Transfer Protocol (HTTP) is a stateless \%application- level protocol for distributed, collaborative, hypertext information systems. This document defines the semantics of HTTP/1.1 messages, as expressed by request methods, request header fie

datatracker.ietf.org

 

 

아래의 내용은 구글에서 제공하는 API  설계 가이드

https://cloud.google.com/apis/design?hl=ko

 

API 디자인 가이드  |  Cloud API Design Guide  |  Google Cloud

Google AIP와 일치하는 API를 설계하기 위한 가이드라인 모음입니다.

cloud.google.com

 


1. 리소스 이름

대부분의 API는 사용자가 생성, 검색, 및 조작할 수 있는 리소스(주요 명사)를 노출한다.

 - 여기서 리소스는 RDB 기준으로 테이블과 유사하다. 다만 파일이나 다른 요청일 수도 있으니 장담할 수는 없다.

API에서 정의한 모든 리소스 이름은 해당 API 내에서 고유해야 한다.

 - 동일한 API 요청 주소는 리소스의 변경이 없는 한 동일한 값을 제공해야 한다.

리소스의 이름은 컬렉션(사용자, 이벤트)과 식별자(회원번호, 이벤트번호) 등이 번갈아가며 등장한다.

users/goo/userEvents/birthday-dinner-226

참조되는 하위 요소에선 상위 요소의 이름을 제거해서  사용한다.

users/goo/events/birthday-dinner-226

 

 

2. 표준 메서드 

RFC 7231 스펙의 4.3절부터 메서드 정의가 존재한다.

주로 아래의 5가지를 많이 쓰는 것 같다.

 

4.3.1 GET

 -  대상 자원을 서버에 제공 요청

4.3.3 POST

 - 리소스의 의미에 따라 리소스를 처리

 - 주로 리소스의 생성에 많이 사용했었다.

 - 보안과 관련된 이슈로 로그인 등에도 사용한다.

4.3.4 PUT

 - 대상 리소스의 상태가 요청의 요구대로 변화하거나 생성

4.3.5 DELETE

 - 요청한 리소스에 대해 서버에 삭제를 요청

4.3.7 OPTIONS

 - 서버 또는 중개자에서 대상 리소스에 사용 가능한 통신 옵션에 대한 정보 요청, 서버의 기능 테스트

 

3. 응답 코드

https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml

 

Hypertext Transfer Protocol (HTTP) Status Code Registry

 

www.iana.org

 

대표적인 응답 코드는 다음과 같다.

2xx: 성공

200: OK

201: Created

202: Accepted

204: NoContent

 

304: Not Modified

 

4xx: 요청 문제

400: Bad Request

401: Unauthorized

403: Forbidden

404: Not Found

 

5xx: 서버 문제

500: Internal Server Error

 


    @GetMapping("/push-message/{message}")
    public ResponseEntity<String> pushMessage(@PathVariable(name = "message") String message) {
        log.info("{}", message);
        notificationService.sendNotification(1L, message, "push-message");
        return ResponseEntity.ok(message);
    }

 

Spring-Web은 위와 같은 어노테이션으로 REST Method를 제공한다.

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping...

 

위의 리소스 설계는 이상하긴 한데, 위와 같이 사용된다.

응답은 ResponseEntity를 통해 제공할 수 있다.

위의 코드와 내용에 따라. ok 대신 위의 영어 단어를 입력해서 사용한다.

    @GetMapping("/{id}")
    public ResponseEntity<UserDto> getUserById(@PathVariable Long id) {
        UserDto user = // ... 사용자 조회 로직 ...
        if (user != null) {
            return ResponseEntity.ok(user); // 200 OK
        } else {
            return ResponseEntity.notFound().build(); // .notFound().build()는 404(Not Found) 응답을 생성합니다.
        }
    }

 

Axios를 사용하는 FE에서는 2xx응답이 아닌 경우 Error를 통해 수신할 수 있다.

위의 명세를 잘 이해하는 개발자끼리라면 서로 응답코드만 보고도 어떤 문제가 있는지 확인할 수 있다.

function handleApiError(error) {
    if (error.response) {
        // 서버가 상태 코드를 포함한 응답을 반환한 경우
        const status = error.response.status;
        const data = error.response.data; // 서버가 보낸 에러 메시지

        switch (status) {
            case 400: // Bad Request
                alert(`잘못된 요청입니다: ${data.message || '입력값을 확인해주세요.'}`);
                break;
            case 401: // Unauthorized
                alert('로그인이 필요합니다.');
                // (예: 로그인 페이지로 리다이렉트)
                window.location.href = '/login';
                break;
            case 403: // Forbidden
                alert('접근 권한이 없습니다.');
                break;
            case 404: // Not Found
                alert('요청한 리소스를 찾을 수 없습니다.');
                // (예: "사용자를 찾을 수 없습니다"와 같은 UI 메시지 표시)
                break;
            case 500: // Internal Server Error
            default:
                alert('서버에 문제가 발생했습니다. 잠시 후 다시 시도해주세요.');
                break;
        }
    } else if (error.request) {
        // 요청은 이루어졌으나 응답을 받지 못한 경우 (네트워크 에러 등)
        alert('서버에 연결할 수 없습니다. 네트워크 상태를 확인해주세요.');
    } else {
        // 요청을 설정하는 중에 에러가 발생한 경우
        console.error('Error:', error.message);
        alert('요청 중 에러가 발생했습니다.');
    }
}

 


Rest API 사용의 장점

1. 단순함과 범용성

Restful API는 HTTP 프로토콜의 표준 메서드를 사용하여 데이터를 주고받는다.

이 때문에 다른 복잡한 프로토콜이나 기술을 익힐 필요 없이 배우고 사용하기가 매우 단순하다.

이미 웹브라우저나 다양한 HTTP 클라이언트 도구가 널리 사용되므로, 개발 과정에서 특별한 도구 없이도 쉽게 테스트하고 통합할 수 있어서 범용성이 높다.

 

2. 상태 없음(Stateless)

Restful API는 상태가 없는 통신을 지향한다. 즉, 서버는 클라이언트로부터 들어오는 각 요청을 독립적으로 처리하고 이전 요청에 대한 어떤 정보도 저장하거나 기억하지 않는다. 모든 요청은 그 요청을 처리하기 위해 필요한 모든 정보를 담고 있어야 한다.

이러한 상태 없음은 다음과 같은 장점을 제공한다.

  - 확장성: 서버가 클라이언트의 상태를 관리할 필요가 없으므로, 더 많은 클라이언트 요청을 처리하기 위해 서버 확장이 용이하다. 각 요청을 아무 서버나 처리할 수 있기 때문에 로드 밸런싱에도 유리하다.

 - 신뢰성: 서버에 문제가 발생하더라도 클라이언트의 상태 정보가 손실될 염려가 적다.

 - 효율성: 서버 리소스 사용을 최적화할 수 있다.

 

3. 캐싱 가능

캐싱은 이전에 요청했던 데이터를 임시로 저장해 두었다가, 같은 요청이 들어오면 DB에 다시 요청하지 않고 저장된 데이터를 바로 반환하여 성능을 향상하는 기술이다. GET 요청과 같이 데이터를 조회하는 작업은 캐싱이 효과적으로 적용된다. 이를 통해 네트워크 트래픽을 줄이고, 응답 시간을 단축하여 사용자 경험을 개선할 수 있다.

 

4. 클라이언트 - 서버 분리

Restful API는 클라이언트와 서버의 역할을 명확하게 분리한다. 클라이언트는 사용자 인터페이스와 사용자 상태를 관리하고, 서버는 데이터 저장 및 비즈니스 로직을 처리한다. 이 분리는 서로 독립적으로 개발하고 배포할 수 있게 해 준다.

이러한 분리 덕분에 다음과 같은 이점이 있다.

 - 유지보수성 향상: 각 부분이 독립적이므로, 한쪽의 변경이 다른 쪽에 미치는 영향을 최소화한다.

 - 플랫폼 독립성: 클라이언트는 웹, 모바일 앱, 데스크톱 앱 등 어떤 플랫폼이든 될 수 있으며, 서버의 API를 동일하게 사용할 수 있다.

 

5. 다양한 데이터 형식 지원

Restful API는 특정 데이터 형식에 얽매이지 않는다. 일반적으로 JSON, XML을 많이 사용하지만, 필요에 따라 YAML, CSV 등 다른 형식으로도 데이터를 주고받을 수 있다. 이러한 유연성은 다양한 클라이언트와 시스템 간의 연동을 용이하게 만든다.

 

6. 균일한 인터페이스

REST의 핵심 제약 조건 중 하나는 균일한 인터페이스이다. 이는 리소스에 접근하는 방식이 일관적이어야 함을 의미한다.

예컨대, 특정 리소스에 접근할 때는 항상 동일한 URL 구조와 HTTP 메서드를 사용한다.

(ex) GET : /users/10 : user-seq가 10인 사용자의 정보를 조회한다.

 

균일한 인터페이스는 다음과 같은 이점을 제공한다.

 - 상호운용성: 서로 다른 시스템 간의 통합을 더 쉽게 만든다.

 - 배움의 용이성: 개발자가 새로운 API를 배울 때 이미 익숙한 패턴을 사용하므로 학습 곡선이 낮아진다.

 - 디커플링: 클라이언트와 서버 간의 강한 결합을 피하여 시스템의 유연성을 높인다.

 

 

320x100