Search
Duplicate
📒

[Network Study] 02-4. HTTP/1.1

상태
수정중
수업
Network Study
주제
HTTP
연관 노트
3 more properties
참고

HTTP/1.1의 시맨틱스

NOTE
HTTP/1.1은 지속 연결(Persistent Connections)을 통해 요청과 응답이 단일 연결을 통해 가능하며, 추가적인 HTTP 메소드나, 청크 전송, 캐시 제어등이 도입되었습니다.
HTTP 1.0에서는 여러가지 한계가 존재했습니다. request-response가 완료되면 connection이 제거되었고,
HTTP/1.1의 변경사항은 아래와 같습니다.
1.
통신 고속화
Keep-Alive가 기본적으로 유효하다.
파이프라이닝
캐시
2.
TLS를 통한 암호화 통신을 지원한다.
3.
새로운 메서드가 추가되었다.
PUT, DELETE (필수 메서드)
OPTION, TRACE, CONNECT
4.
청크 전송(Chunked Transfer Encoding)
5.
가상 호스트 지원

통신 고속화(Keep-Alive, 파이프라이닝)

NOTE
HTTP/1.1에서는 Keep-Alive, 파이프라이닝 통해서 통신 속도를 향상시켰습니다.

Keep-Alive

HTTP의 아래층인 TCP/IP 통신을 효율화하는 구조이며, Keep-Alive를 사용해 연속된 요청에 기존의 Connection을 다시 사용합니다.
TCP/IP 접속까지의 대기 시간을 줄이고, 통신 처리량이 많아지므로 속도가 올라갑니다.
TLS의 경우 Connection단계에서 핸드셰이크 과정이 걸리는 만큼 Keep-Alive를 통해 핸드셰이크 횟수를 줄이는것이 응답 시간 개선에 큰 도움이 됩니다.
Keepl-Alive를 이용한 통신은 클라이언트, 서버 중 한 쪽이 다음 헤더를 부여해 접속을 끊거나 타임아웃될 때까지 연결이 유지됩니다.
Connection: keep-alive # keep-alive 사용 Connection: Close # 해제 요청 # curl은 복수의 요청으로 keep-alive 활용가능 curl -v http://www.google.com http://www.google.com
Bash
복사
하지만 Keep-Alive 종료를 명시적으로 보내는 것은 간단하지 않고, 실제로는 타임아웃으로 접속이 끊어지기를 기다리는게 일반적입니다.
통신이 지속되는 동안 OS의 자원을 계속 소비하므로, 실제 통신이 이루어지지 않는데 접속을 유지하는건 좋지 않으므로 짧은 시간에 끊는것이 좋습니다.

파이프라이닝

파이프라이닝은 첫 번째 요청이 완료되기 전에 다음 요청을 보내는 기술입니다. 이는 대기 시간을 없애고 네트워크의 효율성을 높이는 데 도움이 됩니다. 그러나 많은 브라우저에서 지원하지 않고, HOL 블로킹과 같은 문제로 인해 성능 향상에 크게 기여하지 못하므로, 이 기술은 잘 사용되지 않았습니다.
파이프라이닝은 자체 기술보다는, HTTP/2에서 스트림으로 재탄생했으며, 통신 순서를 유지해야한다는 제약이 사라졌습니다.
HOL Blocking(Head Of Line Blocking)은 파이프라이닝이 1번째 요청이 완료되기전에 다음 요청을 보내도, 결국 최초의 요청이 병목되면 이후에 들어온 요청들에 대해서도 병목이 생기는 현상입니다.

통신 고속화(Keep-Alive, 파이프라이닝)

NOTE
HTTP/1.1에서 ETag, Expire, Cache-Control은 웹 캐싱을 제어하기 위한 주요 헤더입니다. 이 헤더들은 서버와 클라이언트 간의 데이터 전송 효율성을 높이는데 중요한 역할을 합니다.

Etag

ETag는 웹 객체(HTML, 이미지 등)의 버전을 고유하게 식별하는 문자열이며, 각 리소스에 대해 Etag값을 생성하고 HTTP 응답에 포함시킵니다.
# 1. JSONPlaceholder(가짜 데이터 제공하는 무료 REST API) curl --http1.1 -i https://jsonplaceholder.typicode.com/posts/1 # 2. 응답 HTTP/1.1 200 OK Cache-Control: max-age=43200 Etag: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU" Age: 12368 # 3. Etag값이 변경되지 않았다면 304 코드반환 curl --http1.1 -i \ -H 'If-None-Match: "124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"' \ https://jsonplaceholder.typicode.com/posts/1 # 4. 304 반환 HTTP/1.1 304 Not Modified Cache-Control: max-age=43200
Bash
복사
E-Tag 흐름

Expires

Expires 헤더는 클라이언트가 리소스를 캐시할 수 있는 유효기간을 명시합니다. 이 기간이 지난다면 서버에서 리소스를 다시 요청해야 합니다.
HTTP/1.1 200 OK Expires: Wed, 21 Oct 2021 07:28:00 GMT
Bash
복사

Cache-Control

Cache-Control 헤더는 클라이언트와 서버 간의 캐시 정책을 보다 세부적으로 제어할 수 있게 해줍니다.
HTTP/1.1 200 OK Cache-Control: max-age=3600, must-revalidate
Bash
복사
max-age: 리소스의 유효시간
no-cache: 캐시된 복사본을 사용하기 전에 서버에 재검증 요청
no-store: 응답이 어떠한 경우에도 캐시되어선 안된다.
must-revalidate: 캐시된 응답이 만료된 후에는 서버 재검증 없이 사용되어서는 안된다.
Cache-Control 흐름

전송 계층 보안(TLS)

NOTE
TLS는 네트워크에서 보안 통신을 제공하는 프로토콜로 기밀성과 데이터 무결성을 보장하며 민감한 정보의 안전한 전송을 도와줍니다.
TLS와 관련된 이야기는 매우 중요하고, 분량이 커서 다른 페이지에서 따로 설명한다.

HTTP 메서드 추가

NOTE
HTTP/1.0에서 옵션이었던 PUT, DELETE 메서드가 필수 메서드로 추가되었으며, OPTIONS, TRACE, CONNECT 메서드가 새롭게 추가되었습니다.

PUT, DELETE

기존의 GET, POST와 더불에 이제 4개의 메서드가 갖추어져 HTTP는 데이터를 취급하는 프로토콜로도 이용할 수 있게 되었습니다. PUT, DELETE의 경우에는 HTML 폼으로 보낼 수 없고 XMLHttpRequest를 사용해야 합니다.
하지만 실제로는 HTTP는 고수준 API이고, CRUD는 프리미티브한 조작이라는 차이가 있습니다.
실제로 CRUD를 대응시켜 HTTP를 사용하는건 비현실적이며, 하나의 POST로 CRUD가 여러번 실행되는 경우나, 트랜잭션과 같은 차이점이 있기 떄문입니다.

OPTIONS, TRACE, CONNECT

OPTIONS: 서버가 받아들일 수 있는 메서드 목록 반환 (CORS에 사용)
TRACE: 서버는 Content-Typemessage/http를 설정하고 200을 붙여 헤더와 바디를 그대로 반환합니다.
현재 XSS, XST 취약성이 대두되면서 이 방식은 거의 사용되지 않습니다.
XSS를 통해 임의의 스크립트를 실행할 수 있게 되고, 삽입된 악의적인 스크립트를 사용하여 일반적으로 얻을 수 없는 HttpOnly의 쿠키 정보를 획득할 수 있습니다.
현재 브라우저에서는 XMLHttpRequest로 TRACE를 보내는 것이 허용되지 않지만, 활성화할 필요는 없습니다.
CONNECT: HTTP 프로토콜상에 다른 프로토콜의 패킷을 흘릴 수 있게 한다.
주로 https 통신을 중계하는 용도로 사용합니다.

가상 호스트 지원

NOTE
가상 호스트는 하나의 서버에서 여러 도메인 또는 웹사이트를 운영할 수 있도록 하는 기술입니다. 서버의 하드웨어적 리소스를 공유하면서도, 각각의 웹사이트가 독립적인 도메인을 가지고 별개로 운영될 수 있게 합니다.
server { listen 80; server_name www.example.com example.com; # 도메인 1 root /www/example; index index.html; } server { listen 80; server_name www.anotherexample.com; # 도메인 2 root /www/anotherexample; index index.html; }
Bash
복사
nginx.conf

청크

NOTE
HTTP/1.1에서는 데이터 전체를 한번에 전송하지 않고 작게 나눠 전송하는 청크 방식이 있습니다.
청크를 사용하면 데이터 전송을 여러 청크로 나누어 시간을 단축시킬 수 있습니다. 이를 통해 용량이 큰 요청을 나눠서 전송할 수 있습니다. 따라서, 1GB짜리 영상 파일을 전송하더라도 메모리 1GB를 소비하지 않게 됩니다.
package main import ( "fmt" "net" "os" ) func main() { // 9999포트 열기 listener, err := net.Listen("tcp", "localhost:9999") if err != nil { fmt.Println("Error creating listener:", err) os.Exit(1) } defer listener.Close() fmt.Println("Server is listening on localhost:9999") // 연결 성공여부 및 동작 for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } go handleConnection(conn) } } // 전송 데이터 func handleConnection(conn net.Conn) { defer conn.Close() // 전송할 전체 데이터 msg := "Hello from server. This data will be sent in chunks. Each chunk has its own part of the whole message." data := []byte(msg) // 청크 사이즈 정의 chunkSize := 5 // 데이터를 청크로 나누어 전송 for i := 0; i < len(data); i += chunkSize { end := i + chunkSize if end > len(data) { end = len(data) } _, err := conn.Write(data[i:end]) if err != nil { fmt.Println("Error writing to connection:", err) return } } }
Go
복사
client.go
package main import ( "fmt" "io" "net" "os" ) func main() { conn, err := net.Dial("tcp", "localhost:9999") if err != nil { fmt.Println("Error connecting to server:", err) os.Exit(1) } defer conn.Close() var receivedData []byte buf := make([]byte, 1024) // 1024 바이트 크기의 버퍼 for { n, err := conn.Read(buf) if err != nil { if err != io.EOF { fmt.Println("Error reading from connection:", err) } break } receivedData = append(receivedData, buf[:n]...) // 수신된 청크 출력 fmt.Printf("Received chunk: %s\n", string(buf[:n])) } fmt.Println("Received message:", string(receivedData)) }
Go
복사
server.go
Received chunk: Hello Received chunk: from server. This data will be sen Received chunk: t in chunks. Each ch Received chunk: unk has its own Received chunk: part of the wh Received chunk: ole messag Received chunk: e. Received message: Hello from server. This data will be sent in chunks. Each chunk has its own part of the whole message.
Go
복사
결과

HTTP/1.1의 사용

파일 다운로드 후 로컬에 저장

NOTE
브라우저는 기본적으로 MIME에 따라 파일처리를 결정한다 만약 MIME이 image/png라면 이미지 파일로 보고 브라우저에 표시한다.
// 파일 보존해더 : Content-Disposition // filename.xlsx 다운로드 Content-Disposition: attachment; filename=filename.xlsx
Go
복사
서버의 응답에 Content-Disposition 헤더가 있다면, 브라우저는 다운로드 대화상자를 표시하고 파일을 저장한다.
# --remote-name(-O): Content-Disposition 헤더에 지정된 파일이름 저장 curl --remote-name https://downloads.apache.org/httpd/httpd-2.4.46.tar.gz
Bash
복사

다운로드 중단/재시작

NOTE
파일 다운로드를 중단/재시작 하는 기능은 Range 요청 헤더Content-Range 응답 헤더를 사용하는 범위 요청기능을 활용할 수 있습니다. (RFC 7233)
HTTP Range의 기능은 대용량 파일을 다운로드할 때 매우 유용하며, 서버가 이를 지원한다면 Accept-Ranges: bytes 헤더를 통해 알려줍니다.
Range 요청: Range: bytes=1000-1999는 1000~1999번째 바이트까지만 요청한다.
Accept-Range 응답: 서버가 범위 요청을 지원할 경우 응답 헤더에 Accept-Ranges: bytes를 포함해서 알려준다.
206 Partial Conent 응답: 서버가 요청된 범위의 데이터만 반환할때 사용하는 상태코드 입니다.
package main import ( "io" "log" "net/http" "os" "strconv" ) func main() { url := "https://dlcdn.apache.org/httpd/httpd-2.4.59.tar.bz2" // 대용량 파일 URL outputFile := "complete_largefile.zip" // 완성될 파일 이름 partSize := 1024 * 1024 // 다운로드할 각 파트의 크기 (1MB) client := &http.Client{} outFile, err := os.Create(outputFile) if err != nil { log.Fatalf("Error creating file: %v", err) } defer outFile.Close() // 파일 나눠서 순차 다운로드 for i := 0; ; i++ { start := i * partSize end := start + partSize - 1 // Range 헤더 설정 rangeHeader := "bytes=" + strconv.Itoa(start) + "-" + strconv.Itoa(end) log.Printf("Requesting bytes from %d to %d", start, end) req, err := http.NewRequest("GET", url, nil) if err != nil { log.Fatalf("Error creating request: %v", err) } req.Header.Add("Range", rangeHeader) req.Header.Set("User-Agent", "curl/7.64.1") // 요청 실행 resp, err := client.Do(req) if err != nil { log.Fatalf("Error executing request: %v", err) } defer resp.Body.Close() // 응답 상태 로그 log.Printf("Received status code: %d for range %d-%d", resp.StatusCode, start, end) if resp.StatusCode == http.StatusRequestedRangeNotSatisfiable { log.Println("Reached the end of the file.") break } // 파일의 일부분 쓰기 written, err := io.Copy(outFile, resp.Body) if err != nil { log.Fatalf("Error writing to file: %v", err) } log.Printf("Written %d bytes for range %d-%d", written, start, end) // 206 Partial Content 이외의 응답 처리 if resp.StatusCode != http.StatusPartialContent { log.Fatalf("Expected status 206, got %d", resp.StatusCode) } } log.Println("Download completed successfully!") }
Go
복사
2024/05/13 09:15:15 Requesting bytes from 0 to 1048575 2024/05/13 09:15:15 Received status code: 206 for range 0-1048575 2024/05/13 09:15:15 Written 1048576 bytes for range 0-1048575 2024/05/13 09:15:15 Requesting bytes from 1048576 to 2097151 2024/05/13 09:15:15 Received status code: 206 for range 1048576-2097151 # ... 2024/05/13 09:15:16 Reached the end of the file. 2024/05/13 09:15:16 Download completed successfully!
Bash
복사

XMLHttpRequest(XHR)

NOTE
XMLHttpRequest는 웹 브라우저와 웹 서버 간에 데이터를 비동기적으로 교환하고 조작하기 위한 웹 API이며, AJAX(Asynchronous Javascript and XML)의 핵심 기술입니다.
var xhr = new XMLHttpRequest(); xht.open("GET", "/json", true); xht.onload = function() { // 응답이 들어왔을 때 호출되는 메서드 if (xhr.status == 200) { // JSON 파싱해서 표시 console.log(JSON.parse(xhr.responseText)); } }; xhr.setRequestHeader("MyHeader", "HeaderValue"); xhr.send(); // curl -H "MyHeader=HaderValue" /json 과 동일한 의미
JavaScript
복사

XMLHttpRequest와 HTTP 요청의 차이

XMLHttpRequest는 웹 브라우저에서 제공하는 객체로, JavaScript를 통해 서버로부터 비동기적으로 데이터를 요청하거나 수신할 수 있는 기능을 제공합니다.
XMLHttpRequest는 페이지를 새로 고치지 않고도 백그라운드에서 HTTP 요청을 보낼 수 있습니다. 일반적인 HTTP 요청은 비동기 처리가 기본적으로 내장되어 있지 않습니다.

코멧(Comet)

CometXMLHttpRequest를 이용해 서버로부터 클라이언트로 데이터를 실시간으로 푸시하는 웹 기술입니다.
단방향 통신을 이용해 양방향 통신을 하는 방법은 크게 폴링 / 롱 폴링 기법이 있습니다.
HTTP/2부터는 웹소켓이나 SSE와 같은 고급 기술을 사용합니다.
폴링
이 방식에서 클라이언트는 주기적으로 서버에 새로운 값이 있는지 요청합니다.
이로 인해 서버에 불필요한 부하가 발생할 수 있으며, 실시간 처리에도 지연이 발생할 수 있습니다.
롱 폴링
클라이언트가 요청을 보낼 때, 서버는 즉시 응답하지 않습니다. 대신, 통신을 종료하거나 요청이 타임아웃되기 전까지 응답을 보류합니다.
이 방법은 실시간 정보를 효과적으로 제공할 수 있으나, 서버 자원의 사용이 비효율적일 수 있습니다.
클라이언트가 계속해서 새로운 값이 있는지 주기적으로 요청하는 방식입니다.
서버에 불필요한 부하를 발생시킬 수 있으며, 실시간 처리에는 여전히 지연이 발생합니다.

XMLHttpRequest의 보안

XMLHttpRequest의 기능은 굉장히 광력해서, 악의적인 스크립트가 포함되면 생각지 못하게 데이터 변조나 탈취가 일어날 수 있어 엄격하게 제한됩니다. XMLHttpRequest의 정보 제한은 크게 2가지가 있습니다.
1.
정보제한: 쿠키에서 httpOnly속성의 쿠키값은 접근이 불가능하다.
2.
전송제한: 도메인, 메서드 헤더 3종류
a.
도메인 제한: 동일-출처 정책으로 보낼 수 있는 도메인이 제한된다. (CORS)
b.
메서드 제한: CONNECT, TRACE의 메서드 제한 (SecurityError 예외발생)
c.
헤더: SET-, Proxy-로 시작되는 키 금지

지오로케이션

NOTE
지오로케이션 API는 자신의 위치를 알려주는 기능이며, 사생활과 직결되므로 사용자가 허가한 경우에만 활성화한다.
스마트폰이면 내장 GPS, PC의 경우에는 와이파이 등을 활용해서 대략적인 위치를 제공한다.
와이파이 액세스 포인트의 고유 ID(BSSID)와 위도/경도 정보를 사전에 구축한다

X-Powred-By 헤더

NOTE
X- 로 시작하는 HTTP 헤더는 비표준 헤더를 의미하며 일반적으로 RFC 문서에 정의된 표준 헤더가 아닙니다.
X-Powered-By 역시 공식 RFC에는 없는 헤더이지만, 많은 서버에서 시스템 이름을 반환하는데 사용하고 있어 사실상 표준이 됐습니다.

원격 프로시저 호출

NOTE
프로시저는 각 언어가 제공하는 함수, 클래스와 같은것을 의미하며 원격 프로시저 호출(RPC)란 것은 다른 컴퓨터에 있는 기능을 마치 자신의 컴퓨터 안에 있는 것처럼 호출하고, 필요에 따라 반환값을 받는 구조입니다.
RPC에는 다양한 방식이 있습니다.
XML-RPC
SOAP
JSON-RPC

SOAP

SOAPXML-RPC를 확장해서 만들어진 규격이며, 2016년 웹의 아키텍쳐로서 자주 쓰인 구조이다.
POST /Reservations HTTP/1.1 Host: travelcompany.example.org Content-Type: application/soap+xml; charset="utf-8" Content-Length: nnnn <?xml version='1.0' ?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" > <env:Header> <t:transaction xmlns:t="http://thirdparty.example.org/transaction" env:encodingStyle="http://example.com/encoding" env:mustUnderstand="true" >5</t:transaction> </env:Header> <env:Body> <m:chargeReservation env:encodingStyle="http://www.w3.org/2003/05/soap-encoding" xmlns:m="http://travelcompany.example.org/"> <m:reservation xmlns:m="http://travelcompany.example.org/reservation"> <m:code>FT35ZBQ</m:code> </m:reservation> <o:creditCard xmlns:o="http://mycompany.example.com/financial"> <n:name xmlns:n="http://mycompany.example.com/employees"> Åke Jógvan Øyvind </n:name> <o:number>123456789099999</o:number> <o:expiration>2005-02</o:expiration> </o:creditCard> </m:chargeReservation </env:Body> </env:Envelope>
XML
복사
SOAP 구조

JSON-RPC

JSON-RPCXML-RPC의 XML 대신 JSON을 이용한 원격 프로시져 호출입니다. SOAP와 대조적으로 단순하게 하는것에 초점을 맞추었습니다.
POST /jsonrpc HTTP/1.1 Host: api.example.com Content-Type: application/json Content-Length: 94 Accept: application/json { "jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3 }
Bash
복사
HTTP/1.1 200 OK Content-Type: application/json Content-Length: 41 { "jsonrpc": "2.0", "result": 19, "id": 3 }
Bash
복사
XML-RPC는 항상 200 상태코드이지만, JSON-RPC는 여러 상태코드를 지정했다.
200 : 성공
204: Notification 시의 반환값
307: 리다이렉트
405: 메서드 지원예외

Go언어의 JSON-RPC

package main import ( "log" "net" "net/http" "net/rpc" "net/rpc/jsonrpc" ) // Calculator 타입 정의, 이를 통해 메서드 제공 type Calculator int // Multiply 메서드 정의, Args 인수를 받아 결과를 result에 저장 func (c *Calculator) Multiply(args Args, result *int) error { // 곱하기 연산 로그 출력 log.Printf("곱하기 연산: %d, %d\n", args.A, args.B) // 곱셈 결과를 result 포인터에 저장 *result = args.A * args.B return nil } // Args 구조체 정의, 두 개의 정수 인수 A와 B 포함 type Args struct { A, B int } func main() { // Calculator 인스턴스 생성 calculator := new(Calculator) // 새로운 RPC 서버 생성 server := rpc.NewServer() // Calculator 타입의 인스턴스를 서버에 등록 server.Register(calculator) // 기본 RPC 경로에 서버 핸들러 설정 http.Handle(rpc.DefaultRPCPath, server) // 서버 시작 로그 출력 log.Println("start http listening : 18888") // TCP 리스너 생성, 포트 18888에서 수신 대기 listener, err := net.Listen("tcp", ":18888") if err != nil { panic(err) } // 클라이언트 연결 수락을 위한 루프 for { // 클라이언트 연결 수락 conn, err := listener.Accept() if err != nil { panic(err) } // 새로운 고루틴에서 연결 처리 go server.ServeCodec(jsonrpc.NewServerCodec(conn)) } }
Go
복사
package main import ( "log" "net/rpc/jsonrpc" ) // Args 구조체 정의, 두 개의 정수 인수 A와 B 포함 type Args struct { A, B int } func main() { // JSON-RPC 클라이언트 생성, localhost:18888에 연결 client, err := jsonrpc.Dial("tcp", "localhost:18888") if err != nil { panic(err) } // 결과를 저장할 변수 선언 var result int // Args 구조체 인스턴스 생성, 값 4와 5 설정 args := &Args{4, 5} // Calculator.Multiply 메서드 호출, 결과를 result에 저장 err = client.Call("Calculator.Multiply", args, &result) if err != nil { panic(err) } // 곱셈 결과 로그 출력 log.Printf("4 x 5 = %d\n", result) }
Go
복사

Rest API vs JSON-RPC

NOTE
Rest API와 JSON-RPC는 웹 서비스와 서버 간의 통신을 위한 접근 방식입니다.

REST API

REST(Representational State Transfer)는 분산 시스템 설계를 위한 아키텍처 스타일입니다. 이는 자원(resource)의 상태를 전달하는 데 초점을 맞추며, 일반적으로 HTTP 프로토콜을 사용합니다.
리소스 지향: REST는 웹의 리소스(예: 사용자, 페이지, 객체)를 URL로 표현하고, 이 리소스에 대한 다양한 동작을 HTTP 메소드 (GET, POST, PUT, DELETE 등)로 정의합니다.
스테이트리스: 각 요청은 독립적이며, 요청 간에 클라이언트의 상태 정보를 저장하지 않습니다.
표현 형식: JSON, XML 등 여러 형식을 사용할 수 있으며, 클라이언트가 Accept 헤더를 통해 원하는 형식을 요청할 수 있습니다.
단순성과 일반성: REST는 웹 표준을 사용하며, 이해하기 쉽고 사용하기 편리합니다.
확장 가능성: 다양한 서비스에 쉽게 통합될 수 있습니다.

JSON-RPC

JSON-RPC는 원격 프로시저 호출(Remote Procedure Call) 프로토콜의 하나로, JSON을 사용하여 정보를 인코딩합니다. 이는 함수나 프로시저 호출을 중심으로 설계되었습니다.
프로시저 호출 중심: 서버에 정의된 메소드를 직접 호출하며, 이 메소드는 파라미터를 받아 결과를 반환합니다.
트랜스포트 중립적: JSON-RPC는 HTTP뿐만 아니라 다른 통신 프로토콜(Sockets, WebSockets 등)에서도 사용할 수 있습니다.
간결한 메시징: JSON 객체를 사용하여 메소드 이름, 파라미터, 그리고 고유한 ID를 포함하는 메시지를 구성합니다.
비상태성: REST와 마찬가지로 상태 정보를 저장하지 않으며 각 호출은 독립적입니다.
언어 독립성: JSON 형식은 다양한 프로그래밍 언어에서 지원되므로 언어에 구애받지 않습니다.

주요 차이점

1.
접근 방식: REST는 자원 중심의 상태 관리에 초점을 맞춘 반면, JSON-RPC는 서비스의 특정 기능을 호출하는 방식에 중점을 둡니다.
2.
메시지 구조: REST는 HTTP의 표준 메소드와 URI를 사용하여 자원을 조작하는 반면, JSON-RPC는 메소드 호출 정보를 포함하는 단순한 JSON 객체를 사용합니다.
3.
유연성과 확장성: REST는 아키텍처 스타일로서의 유연성과 확장성을 제공하는 반면, JSON-RPC는 프로시저 호출의 명확성과 간결함을 제공합니다.
4.
프로토콜 및 데이터 포맷: REST는 HTTP 프로토콜에 종속적이지만 다양한 데이터 포맷을 지원할 수 있으며, JSON-RPC는 프로토콜에 종속적이지 않고 JSON 포맷을 사용합니다.

웹사이트 간 공통 인증 및 허가 플랫폼

NOTE
웹 사이트 간의 공통 인증 및 권한 부여 플랫폼은 인터넷의 확산과 함께 다양한 온라인 서비스의 보안 요구 사항을 충족시키기 위해 개발되었습니다. 이 플랫폼들은 사용자가 여러 서비스에 대한 동일한 인증 정보(사용자 이름 및 비밀번호)를 반복해서 입력하는 불편함을 줄이고, 보안 리스크를 최소화하는 데 중점을 두고 있습니다.
1.
싱글 사인온(Single Sign-On, SSO): 한 번의 로그인으로 여러 시스템이나 애플리케이션에 접근할 수 있게 해주는 기술입니다. 사용자는 한 번의 인증 절차를 통해 여러 관련 서비스를 이용할 수 있습니다.
2.
커베로스(Kerberos): 네트워크 인증 프로토콜로서, 사용자가 서비스에 안전하게 접속할 수 있도록 해줍니다. 커베로스는 티켓 기반의 인증 메커니즘을 사용하여 통신 양 당사자의 신원을 보장합니다.
3.
SAML (Security Assertion Markup Language): 사용자 인증 및 권한 부여 데이터를 교환하기 위한 XML 기반 표준입니다. SAML은 주로 엔터프라이즈 신원 공급자와 서비스 공급자 간의 인증 및 권한 부여 정보를 주고받는 데 사용됩니다.
4.
오픈아이디(OpenID): 사용자가 여러 서비스에서 동일한 신원을 재사용할 수 있게 해주는 분산 신원 인증 시스템입니다. 사용자는 오픈아이디 공급자를 통해 다양한 웹 서비스에 로그인할 수 있습니다.
5.
OAuth: 인터넷 사용자가 비밀번호를 제공하지 않고도, 다른 웹 사이트의 자신의 정보에 접근할 수 있는 권한을 제3의 서비스에 부여할 수 있는 개방형 표준입니다. 주로 API 접근 권한을 안전하게 위임할 때 사용됩니다.
6.
오픈아이디 커넥트(OpenID Connect): OAuth 2.0을 기반으로 하는 인증 계층입니다. 이는 JSON 기반의 ID 토큰을 사용하여 사용자의 신원 정보를 전달합니다.