우리가 사용하는 모든 어플리케이션에서는 서버가 따로 운영이 된다. 그렇다면 서버란 무엇일까? 만약 어플리케이션으로 무언가를 할 때, 가령 쇼핑을 할 때라든지 어떤 온라인 게임을 할 경우에도 마찬가지로 모든 정보가 어플리케이션 안에 내장되어 운영되는 경우라면 무언가 정보가 바뀌어야 하는 상황마다 어플리케이션의 업데이트가 필요할 것이다. 하지만 우리가 어플리케이션을 사용할 때 그런 경우는 만나본 적이 없었을 것이다. 서버라는 것이 존재하기 때문이다.
이렇게 정보(리소스)들이 존재하는 곳과 정보를 이용하여 동작하는 어플리케이션을 분리시킨 것을 클라이언트-서버 아키텍쳐, 다른 말로 2티어 아키텍처라고 한다. 여기서 리소스를 제공하는 곳이 영단어 그대로 server(서버)이고 제공받은 리소스를 사용하는 곳이 client(클라이언트)이다.
클라이언트와 서버는 요청과 응답을 주고 받는 관계이다. 요청을 하지도 않았는데 응답을 주는 경우는 없다. 일반적으로 서버는 리소스를 전달하는 역할만을 수행하는데, 데이터베이스 공간에서 리소스를 저장하는 일을 수행한다. 이렇게 데이터베이스까지 합쳐진 형태를 3티어 아키텍처라고 한다.
클라이언트와 서버가 요청과 응답을 주고 받기 위해서는 통신을 위한 여러가지 과정이 필요할 것이다. 그중에 먼저 통신 규약인 프로토콜에 대해 알 필요가 있다. 웹 어플리케이션 아키텍처에서는 클라이언트와 서버가 HTTP라는 프로토콜을 이용해서 통신을 수행한다.
우리가 어플리케이션을 사용할 때, 처음 쓰는 어플리케이션을 사용한다하더라도 어떤 사용설명서 없이도 잘 사용할 수가 있다. 그것은 우리가 서버에서 리소스를 어떻게 다루는지 알고 있어서는 절대 아닐 것이다. 그 이유는 바로 서버에서 클라이언트에게 리소스를 잘 활용할 수 있도록 인터페이스를 제공해주기 때문이다. 그 인터페이스가 바로 API(Application Programming Interface) 이다.
보통 인터넷에 있는 데이터를 요청할 때는 HTTP 프로토콜을 사용하여 주소 (URL, URI)에 접근한다. 브라우저의 주소창에 입력한 URL은 서버가 제공되는 환경에 존재하는 파일의 위치를 나타낸다.
위의 URL 주소는 구글 검색창에 '코로나'를 검색한 후의 주소이다. 이 주소로 이야기를 해보면 google.com 이라는 것이 서버의 기본 폴더를 뜻한다. terminal에서 폴더를 구분할 때 처럼 URL도 / 를 이용하여 폴더에 진입할 수가 있다.
URL(Uniform Resource Locator)은 scheme, hosts, url-path로 구분할 수 있다. scheme은 통신 방식을 결정하고 일반적인 웹 브라우저에서는 http(s)를 사용한다. hosts는 웹 서버의 이름이나 도메인, IP를 사용하며 주소를 나타낸다. url-path는 웹 서버에서 지정한 루트 디렉토리부터 시작하여 웹 페이지, 이미지, 동영상 등이 위치한 경로와 파일명을 나타낸다.
URI(Uniform Resource Identifier)은 URL의 기본 요소에 query, bookmark를 포함하여 나타낸다. query는 웹 서버에 보내는 추가적인 질문이다.
https:// =============> scheme
google.com =============> hosts
/search =============> url-path
?q=코로나 =============> query
네트워크에 연결된 특정 PC의 주소를 나타내는 체계를 IP address라고 한다. IPv4(Internet Protocol version 4)는 .(dot)으로 구분된 네 덩이를 가졌는데 각 덩이마다 0~255의 숫자로 나타낼 수 있다. 이 구조를 따르면 약 43억(2의 32제곱) 개의 주소를 표현할 수가 있는데 몇 가지는 아래 예시처럼 이미 정해진 쓰임새가 있다.
127.0.0.1 : localhost
0.0.0.0 , 255.255.255.255 : broadcast address
전 세계적으로 PC 사용량이 늘어나면서 43억개의 IP도 그 한계를 맞이하게 되었다. 그로 인해 등장한 것이 IPv6인데 2의 128제곱 개만큼의 주소를 표현할 수 있게 됐다.
앞서 IP주소에 대해 설명하였고 그 주소에 진입할 수 있는 정해진 통로를 PORT라고 한다. 터미널에서 리액트를 실행하면 IP주소 뒤에 :3000 과 같은 숫자가 나타나는데 이 숫자가 port number이다. 포트번호는 0~65535번까지 사용할 수 있는데 0~1024번까지는 다음과 같이 이미 정해진 번호가 있다.
웹 브라우저를 통해 특정 사이트에 접근할 때, IP주소를 대신하여 사용하는 주소를 도메인이라고 한다.
nslookup google.com
터미널 창에서 위와 같은 명령어를 입력하면 위 사진과 같은 결과를 받을 수가 있다. 여기서 Ip주소는 172.217.31.143가 되고 google.com은 도메인 이름이 된다.
네트워크 상의 모든 PC가 IP주소를 가지지만 모든 IP주소가 도메인 이름을 가지는 것은 아니다. localhost를 제외한 모든 도메인 이름은 일정 기간 동안 대여를 하여 사용한다. 이것을 관리하는 시스템이 DNS(Domain Name System) 이다. 호스트의 도메인 이름을 IP주소로 변환하거나 반대의 경우를 수행하도록 개발된 데이터베이스 시스템이다.
원래 웹 페이지에서는 어떤 버튼을 누르면 그 버튼이 동작한 후의 페이지를 새로 렌더해서 페이지가 깜빡하고 새로운 페이지를 불러왔다. 이런 부분을 개선하여 원하는 부분만 따로 동작하는 웹으로, 서버와 자유롭게 통신할 수 있고 페이지 깜빡임 없이 작동하는 dynamic web page(web app)가 등장하였다.
서버를 자유롭게 통신할 수 있는 기술인 XMLHttpRequest(XHR)와 Javascript와 DOM을 이용하여 페이지 깜빡임 없이 seamless하게 작용하는 기술을 합쳐 AJAX(Asynchronous Javascript and XML)이 등장하였다.
처음에는 XMLHttpRequest를 이용하여 서버와 통신을 하였고 다소 어려운 코드를 개선하여 JQuery를 활용하여 코드를 작성했으나 보다 쓰기 쉬운 API를 만들고자 함에 따라 fetch API가 등장했다.
fetch('http://~~~')
.then((res) => {
return res.json();
})
.then((json) => {
// json 형태로 전달받은 서버로부터 응답
});
SSR은 웹 페이지를 서버에서 렌더링한다. 브라우저가 서버의 URI로 GET 요청을 보내면 서버는 정해진 웹 페이지 파일을 브라우저로 전송한다. 그리고 서버의 웹 페이지가 브라우저에 도착하면 완전히 렌더링된다. 서버에서 웹 페이지를 보내기 전에 완전히 렌더링했기 때문에 Server Side Rendering이라고 한다. 웹 페이지의 내용에 데이터베이스의 데이터가 필요한 경우, 서버는 데이터베이스의 데이터를 불러온 다음 웹 페이지를 완전히 렌더링 된 페이지로 변환한 후에 브라우저에 응답으로 보낸다.
SEO(Search Engine Optimization)가 우선순위인 경우 일반적으로 SSR을 사용하고, 웹 페이지의 첫 화면 렌더링이 빠르게 필요한 경우에도 단일 파일 용량이 작은 SSR이 적합하다. 그밖에 웹 페이지가 사용자와 상호작용이 적은 경우도 마찬가지이다.
CSR은 클라이언트에서 페이지를 렌더링한다. 웹 개발에서 사용하는 대표적인 클라이언트는 웹 브라우저이다. 브라우저의 요청을 서버로 보내면 서버는 웹 페이지를 렌더링하는 대신, 웹 페이지의 골격이 될 단일 페이지를 클라이언트에 보낸다. 이때 서버는 웹 페이지와 함께 js파일을 보내는데 클라이언트가 웹 페이지를 받으면 웹 페이지와 함께 전달된 js 파일은 브라우저에서 웹 페이지를 완전히 렌더링 된 페이지로 바꾼다. 웹 페이지에 필요한 내용이 데이터베이스에 저장된 경우, 브라우저는 데이터베이스에 저장된 데이터를 가져와서 웹 페이지에 렌더링해야한다.
HTTP는 HyperText Transfer Protocol의 줄임말로, HTML과 같은 문서를 전송하기 위한 어플리케이션 계층 프로토콜이다. HTTP는 웹 브라우저와 웹 서버의 소통을 위해 디자인되어서, 전통적인 클라이언트-서버 모델에서 클라이언트가 HTTP messages 양식에 맞춰 요청을 보내면 서버도 HTTP messages 양식에 맞춰 응답을 한다. HTTP는 특정 상태를 유지하지 않는 무상태성(Stateless)이라는 특성을 가졌단 것을 기억하자.
HTTP messages는 클라이언트와 서버 사이에 데이터가 교환되는 방식으로 요청(Request), 응답(Response)의 두 유형이 존재한다.
위의 사진처럼 Request와 Response는 유사한 구조를 가진다.
- start-line : 요청이나 응답의 상태를 나타냄. 항상 첫 줄에 위치. 응답에서는 status line이라 칭함.
- HTTP headers : 요청을 지정하거나, 메시지에 포함된 본문을 설명하는 헤더의 집합
- empty line : 헤더와 본문을 구분하는 빈 줄
- body : 요청과 관련된 데이터나 응답과 관련된 데이터 또는 문서를 포함. 요청과 응답의 유형에 따라 선택적으로 사용
- start line과 HTTP headers를 묶어 요청이나 응답의 헤드라고 하고, payload는 body라고 함.
Http 요청은 클라이언트가 서버에 보내는 메시지.
Start line에는 세 가지 요소가 있다.
수행할 작업(GET, POST 등)이나 방식(HEAD or OPTIONS)을 설명하는 HTTP method를 나타냄.
요청 대상(URL/URI) 또는 프로토콜, 포트, 도메인의 절대 경로는 요청 컨텍스트에 작성된다. 이 요청 형식은 HTTP method 마다 다름.
Origin 형식 : ?와 쿼리 문자열이 붙는 절대 경로. POST, GET, HEAD, OPTIONS 등의 method와 함께 사용.
POST / HTTP 1.1
GET /background.png HTTP/1.0
HEAD /test.html?query=alibaba HTTP/1.1
OPTIONS /anypage.html HTTP/1.0
absolute 형식 : 완전한 URL 형식. 프록시에 연결하는 경우 대부분 GET method와 함께 사용
GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1
authority 형식 : 도메인 이름과 포트 번호로 이루어진 URL의 authority component. HTTP 터널을 구축하는 CONNECT와 함께 사용
CONNECT developer.mozilla.org:80 HTTP/1.1
asterisk 형식 : OPTIONS와 함께 별표(*)하나로 서버 전체를 표현
OPTIONS * HTTP/1.1
HTTP 버전은 메시지의 다른 구조를 결정. 이를 위해 버전을 함께 입력.
Request의 Headers는 기본 구조를 따름. 대소문자 구분 없는 문자열과 콜론, 값을 입력. 값은 헤더에 따라 다름.
Request의 본문은 Http messages 구조의 마지막에 위치. 모든 요청에 body가 필요하지는 않음. GET, HEAD, DELETE, OPTIONS처럼 서버에 리소스를 요청하는 경우에는 본문이 필요하지 않음.
Response의 첫 줄. 다음 정보를 포함
HTTP/1.1 404 Not Found.
Response에 들어가는 HTTP headers는 Request 요청 헤더와 동일한 구조를 가짐.
Response의 본문은 HTTP messages 구조의 마지막에 위치. 모든 응답에 body가 필요하진 않음. 201, 204와 같은 상태 코드를 가지는 응답에는 본문이 필요하지 않음.
상태를 가지지 않는다는 HTTP의 가장 큰 특성. HTTP로 클라이언트와 서버가 통신을 주고 받는 과정에서 HTTP가 클라이언트나 서버의 상태를 확인하지 않는다.