HTTP 통신은 Connectionless(비연결성), Stateless(무상태성)의 특징을 가지고 있어, 응답 이후에 연결을 유지하지 않고 서버는 이전 요청의 상태를 기억하지 않습니다.
즉, 클라이언트가 요청을 보내면 서버는 응답을 반환한 후 연결을 종료하며, 이후의 요청은 이전 요청과 무관하게 독립적으로 처리됩니다.
이로 인해 확장성이 높아지지만, 상태 유지를 위해 쿠키나 세션, JWT와 같은 인증 방식이 사용됩니다.
쿠키는 웹 브라우저에 저장되는 데이터 조각입니다. 서버에서 쿠키를 설정해서 클라이언트로 내려주고, 클라이언트는 해당 쿠키를 서버로 다시 보냄으로써 상태를 유지합니다.
세션은 서버에서 사용자의 상태를 관리하기 위해 주로 사용됩니다. 세션 데이터는 서버에 저장되며, 클라이언트에는 세션의 고유한 ID값을 쿠키로 전달하고, 이후의 요청마다 세션 ID를 쿠키로 서버에 전달하여 상태를 유지합니다.
JWT(Json Web Token)는 무상태성(Stateless) 프로토콜인 HTTP에서 상태 정보를 유지할 수 있는 방법입니다.
JWT는 Header, Payload, Signature로 구성되어있는 문자열이며, 각 부분은 점(.)으로 구분됩니다.
Header
JWT의 메타데이터가 포함되어 있으며, 주로 토큰 타입과 해싱 알고리즘 정보를 담고 있습니다.
// Base64Url로 인코딩됩니다.
{
"alg": "HS256",
"typ": "JWT"
}
Payload
전송 클레임들이 포함되어 있으며, 주로 사용자 정보, 만료 시간, 발급자 등을 포함합니다.
// Base64Url로 인코딩됩니다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"exp": 1516239022
}
Signature
헤더와 페이로드를 합친 후 비밀 키로 서명하여 생성됩니다.
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) //
API 요청 시 AccessToken을 사용하여 HTTP-Header Authorization에 AccessToken 값을 포함시켜 전송합니다. (ex. Authorization: Bearer < AccessToken >)
서버는 HTTP 요청을 수신 후 AccessToken이 유효한지 확인 후, 페이로드에 포함된 정보를 기반으로 사용자의 권한을 확인하고 요청을 처리합니다.
SOP(Same-Origin Policy)는 사용자의 브라우저 측에서 구현된 보안 메커니즘으로, 웹 페이지가 자바스크립트를 통해 다른 출처의 리소스에 접근하는 것을 제한합니다. 이 제한은 웹 페이지 간의 상호작용에서 발생할 수 있는 보안 문제(ex. XSS, CSRF 등)를 방지하기 위해 존재합니다.
SOP는 동일 출처(Origin)가 아닌 다른 출처의 리소스에 접근하는 것을 제한합니다. 예를 들면, 내가 사용하고 있는 웹 브라우저에서 자바스크립트로 다른 출처의 API를 호출하려 할 때, SOP는 이를 차단하고 에러를 발생시킵니다.
CORS(Cross-Origin Resource Sharing)는 사용자의 브라우저에서 SOP의 제한을 일부 완화하기 위해 도입된 메커니즘으로, 웹 페이지가 다른 출처의 리소스에 접근할 수 있도록 서버 측에서 허용하는 방식입니다. CORS 설정에 따라 요청을 허용할지 결정하게 됩니다.
CORS 설정 (HTTP-Header)
Access-Control-Allow-Origin:
서버가 응답할 때 특정 출처에서 온 요청을 허용할 지 지정합니다.
Access-Control-Allow-Methods:
서버가 어떤 HTTP 메서드를 허용할지 지정합니다.
Access-Control-Allow-Headers:
클라이언트가 요청 시 사용할 수 있는 헤더 목록을 지정합니다.
Access-Control-Allow-Credentials:
클라이언트가 요청에 쿠키나 인증 헤더를 포함할 수 있는지를 지정합니다.
Access-Control-Expose-Headers:
클라이언트가 응답에서 사용할 수 있는 헤더 목록을 지정합니다.
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true
REST는 웹 서비스 아키텍처 스타일 중 하나로, HTTP 프로토콜을 기반으로 클라이언트와 서버 간의 상호작용을 정의하는 방식으로 구성 되어있습니다.
REST는 HTTP URI를 활용하여 자원(Resource)을 명시하고, HTTP 메소드를 통해 자원에 대한 CRUD Operation을 적용하는 것을 의미합니다.
HTTP 메서드 사용
URI 설계
URI는 자원을 명확하게 표현합니다.
// Bad
/getUsersData
/getUserData
// Good
/users
/users/10
RESTful API 설계 예시
GET /users // 모든 사용자 목록을 조회
GET /users/123 // id가 123인 사용자의 정보를 조회
POST /users // 새로운 사용자를 생성
PUT /users/123 // id가 123인 사용자의 정보를 업데이트
DELETE /users/123 // id가 123인 사용자를 삭제
클라이언트-서버 아키텍처(Client-Server Architecture)
클라이언트-서버 아키텍처는 클라이언트와 서버 간의 역할을 명확히 분리하는 것을 의미합니다. 클라이언트는 UI/UX를 담당하며, 서버는 데이터 관리 및 보안 관리를 담당합니다.
무상태성 (Stateless)
무상태성은 서버가 각 클라이언트 요청,응답 간의 상태를 저장하지 않는다는 것을 말합니다. 모든 요청은 독립적으로 처리되며, 요청에는 필요한 모든 정보가 포함되어야 합니다.
캐시 가능(Cacheable)
캐시는 클라이언트가 서버의 응답을 캐시할 수 있도록 명시 해야 한다는 제약 조건입니다.
HTTP Header에 cache-control을 사용해서 처리합니다.
일관된 인터페이스(Uniform Interface)
일관된 인터페이스는 시스템의 모든 부분이 동일한 방식으로 상호작용하도록 설계되어야 한다는 것을 말합니다. 이를 통해 복잡성을 줄이고, 상호성을 높일 수 있습니다.
계층화된 시스템(Layered System)
계층화된 시스템은 시스템이 여러 계층으로 구성될 수 있으며, 각 계층은 다른 계층에 대한 정보를 알 필요가 없다는 것을 의미합니다. 예를 들면, 클라이언트는 자신이 직접 서버와 통신하는지, 프록시 서버나 로드벨런서를 통해 서버와 통신하는지 알지 못합니다.
이러한 부분에서 계층화된 시스템은 보안, 성능, 확장성 측면에서 다양한 이점을 제공할 수 있게 됩니다.
코드 온 디멘드(Code on Demand) [Option]
코드 온 디멘드는 선택적 제약 조건으로, 서버가 클라이언트에게 실행할 코드를 전송할 수 있다는 것을 의미합니다. 코드 온 디멘드는 클라이언트의 기능을 확장하여 서버에서 받은 코드를 실행하여 동적으로 기능을 변경하거나 추가할 수 있습니다. 하지만 시스템의 단순성을 떨어뜨리며, 클라이언트 단에서 보안 문제를 유발 할 수 있어 대부분의 RESTful 시스템에서는 해당 제약 조건을 사용하지 않습니다.