1. 웹 서버란?
- e.g. 음식을 갖다주며 서빙하는 사람을 영어로 서버(server)라 함
서버=== 데이터를 전달해주는 알바생(server, 컴퓨터)웹 서버=== 텍스트, 이미지, 비디오 및 앱 데이터를 요청하는 클라이언트(유저)에게 데이터 전달

웹 서버는 HTTP(Hypertext Transfer Protocol)를 사용하여 웹 브라우저와 통신한다.
- 대부분의 웹 페이지 콘텐츠는 HTML(Hypertext Markup Language)로 인코딩된다.
- 콘텐츠는 정적(e.g. 텍스트 및 이미지) 또는 동적일 수 있다.
- 동적 콘텐츠를 제공하기 위해
- 대부분의 웹 서버는 비즈니스 논리를 통신으로 인코딩하는 서버 측 스크립팅 언어를 지원함
- e.g.) ASP(Active Server Pages), Javascript, PHP, Python 및 Ruby
- 웹 서버는 일반적으로 요청되는 콘텐츠의 전달 속도를 높이기 위해 콘텐츠를 캐시할 수도 있다.
- 이 프로세스를 웹 가속이라고도 함

- 호스팅되는 파일을 필요로 할 때마다 브라우저는 HTTP를 통해 파일을 요청한다.
- 요청이 웹 서버에 도달하면 HTTP 서버는 요청을 수락하고 요청된 문서를 찾아 HTTP를 통해 브라우저로 다시 보낸다.
- (서버가 요청한 문서를 찾지 못하면 대신 404 응답을 반환합니다.)
2. HTTP Requests
2.1 HTTP
- Hypertext Transfer Protocol의 약어
- HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜(약속)
- 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 프로토콜
- 클라이언트-서버 프로토콜이란 수신자 측(e.g. 웹브라우저)에 의해 요청이 초기화되는 프로토콜을 의미
- => 웹 상에서 통신을 할 때 어떤 형식(HTTP)으로 통신을 하자고 정해놓은 약속
2.2 HTTP Method
- 수행할 작업의 종류를 나타내기 위해 서버에 보내는 메시지
- 이러한 방법을 사용하면 브라우저와 서버 간의 더 풍부한 통신이 가능
- 가장 일반적으로 사용되는 방법은 GET 및 POST
- cf. https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
| 메서드 | 설명 |
|---|---|
| GET | 어떠한 데이터를 서버로부터 받아(GET) 올 때 사용하는 Method GET /posts, /posts/2 |
| POST | 일반적으로 무언가를 생성하기 위해 서버에 데이터 블록을 수락하도록 요청POST /posts |
| PUT | 데이터를 업데이트할 때 사용PUT /posts/3 |
| DELETE | 데이터를 서버에서 삭제할 때 사용DELETE /posts/3 |
2.3 GET Method
- GET 메소드는 URL 매개변수를 사용하여 서버에서 데이터를 요청한다.
- 웹에서 가장 일반적으로 사용되는 HTTP 방법
- GET 요청 매개변수는
이름-값쌍으로 형식이 지정됨 - e.g.
www.google.com/search?q=nodejs- 쿼리 매개변수 q를 사용하여 nodejs에 대한 결과를 가져오도록 Google에 지시
- 이에 대한 응답으로 Google은 검색 결과가 포함된 페이지를 반환합니다.
GET 요청은 다음 사항들을 수행할 수 있다.
- 서버에서 데이터 검색 - 일반적으로 웹 페이지
- 길이 제한이 있는 서버로 데이터 보내기
- 브라우저 기록에 남음
- 캐시가 됨
GET 요청은 다음 사항들을 수행할 수 없다.
- 민감한 데이터(예: 비밀번호, 신용 카드 정보)를 처리
- 서버에서 데이터 수정
2.4 POST Method
- POST 메서드는 리소스(종종 데이터베이스 레코드)를 변경하기 위해 서버에 데이터를 보낸다.
- POST 데이터는 사용자가 볼 수 없는 요청 본문으로 전송된다.
- POST 요청의 예시 :
POST /posts/1 HTTP/1.1
POST 요청은 다음을 수행할 수 있다.
-
리소스 데이터, 즉 서버의 데이터 수정
-
민감한 데이터를 처리하는 데 사용
-
길이 제한 없이 데이터 보내기
POST 요청은 다음을 수행할 수 없다.
- 캐시에 저장
- 브라우저 기록에 남기기
2.5 PUT Method vs PATCH Method
(1) 공통점
둘 다 어떠한 데이터를 수정하기 위해서 사용됩니다.
(2) 차이점
PUT: 데이터 전체 교체, 데이터 교체 시 모든 필드 필요PATCH: 데이터의 부분 교체, 데이터 교체 시 일부 필드 필요
1/users/12{3"username": "johnahn",4"email": "johnahn@naver.com"5}
올바르게 이메일만 바꾸는 방법
1PUT /users/12{3"username": "johnahn",4"email": "johnahn@gmail.com" // new email address5}
1PATCH /users/12{3"email": "johnahn@gmail.com" // new email address4}
3. Stateless Protocol
- 사용자가 서버에게 자기가 누군지 밝혀도, 그 이후 다시 서버에게 물어보면 해당 사용자가 누구인지 모릅니다. 왜 그러냐면…
HTTP는 stateless 프로토콜이기 때문이다.- HTTP는 상태를 비저장하는 프로토콜로, 서버에 여러 요청이 오는 동안 각 사용자의 정보나 상태를 갖고 있을 필요가 없다.
- 왜 이렇게 만들었냐면… 성능 문제때문이다.
- 각 요청에 대한 연결을 재설정하는데 드는 시간-대역폭을 최소화하기 위해서
4. HTTP Request, Response 구조
4.1 Request(요청) 구조

-
Starter line:- HTTP method 종류, request target (url), http version 정보를 담고 있다.
- e.g. 위 그림의
GET /test.html HTTP/1.1
-
Headers:Key:Value값으로 해당 request에 대한 추가 정보를 담고 있다. -
Body:- 해당 request가 전송하는 데이터가 담겨있는 부분
- 전송하려는 데이터가 없다면 비어있다.
| Headers Key | 설명 |
|---|---|
| Host | 요청하려는 서버 호스트 이름, 포트번호 |
| User-agent | 클라이언트 프로그램 정보 |
| Referer | 바로 직전에 머물렀던 웹 링크 주소 |
| Accept | 클라이언트가 처리 가능한 미디어 타입 종류 나열 |
| If-Modified-Since | 여기에 쓰인 시간 이후로 변경된 리소스 취득.페이지가 수정되었으면 최신 페이지로 교체. |
| Authorization | 인증 토큰을 서버로 보낼 때 쓰이는 Header |
| Origin | 서버로 Post 요청을 보낼 때 요청이 어느 주소에 시작되었는지 나타내는 값.이 값으로 요청을 보낸 주소와 받는 주소가 다르면 CORS 에러가 발생 |
| Cookie | 쿠기 값 key-value로 표현된다. Set-Cookie 헤더와 함께 서버로부터 이전에 전송됐던 저장된 HTTP 쿠키를 포함 |
4.2 Response(응답) 구조

status line: HTTP version, Status Code, Status Text 을 나타낸다.headers: Request의 headers와 동일.- 하지만 Response Headers에서만 쓰이는 값도 있다.
body: Response의 body와 일반적으로 동일.
| Headers Keys | 설명 |
|---|---|
| Server | 웹서버의 종류 |
| Age | max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려주는 값 |
| Referrer-policy | 서버 referrer 정책을 알려주는 값 ex) origin, no-referrer, unsafe-url |
| WWW-Authenticate | 사용자 인증이 필요한 자원을 요구할 시, 서버가 제공하는 인증 방식 |
| Proxy-Authenticate | 요청한 서버가 프락시 서버인 경우 유저 인증을 위한 값 |
| Set-Cookie | 서버 측에서 클라이언트에게 세션 쿠키 정보를 설정 (RFC 2965에서 규정) |



5. HTTP Status Codes
- HTTP 상태 코드는 브라우저 요청에 따라 서버에서 반환되는 코드이다.
- 이 코드 번호는 요청이 성공했는지 또는 오류가 있었는지 나타낸다.
예를 들어서,
200 OK= 성공적인 HTTP 요청을 위한 코드.404 Not Found= 요청된 페이지에 대한 코드를 찾을 수 없다.
| 코드 | 설명 |
|---|---|
| 100 - 199 | 정보 코드(infomational codes) |
| 200 - 299 | 성공 코드(success codes) |
| 300 - 399 | 리다이렉션 코드(redirection codes) |
| 400 - 499 | 클라이언트 에러 코드(client error codes) |
| 500 - 599 | 서버 에러 코드(server error codes) |
아래 ⭐️가 있는 건 자주 보는 코드란 의미입니다
5.1 100 - 199 정보 코드
요청에 대한 정보 메시지를 반환하는 상태 코드
100 Continue: Server는 요청 헤더를 수신했으며 클라이언트가 요청 본문을 보낼 수 있도록 합니다.101 Switching Protocols: 요청자가 프로토콜의 서버 전환을 요청103 Checkpoint: 중단된 PUT 또는 POST 요청을 재개하기 위한 재개 가능한 요청 옵션을 표시
5.2 200 - 299 성공 코드
성공적인 요청을 나타내는 상태 코드
200 OK: 성공적인 HTTP 요청에 대한 표준 응답.⭐️201 Created: 요청이 성공적이었으며 그 결과로 새로운 리소스가 생성되었습니다. 이 응답은 일반적으로 POST 요청 또는 일부 PUT 요청 이후에 따라옵니다.⭐️202 Accepted: 요청은 처리를 위해 수락되지만 완료되지는 않습니다.203 Non-Authoritative Information: 요청이 성공했지만 다른 소스에서 정보를 반환합니다.204 No Content: 반환된 콘텐츠 없이 요청이 성공했습니다.⭐️205 Reset Content: 요청은 반환된 콘텐츠 없이 성공했으며 요청자가 문서를 새로 고칠 것을 요구합니다.206 Partial Content: 요청자가 보낸 범위 헤더로 인해 서버가 리소스의 일부만 반환하고 있습니다.
5.3 300 - 399 리다이렉션 코드
리디렉션과 관련된 알림인 상태 코드
300 Multiple Choices: 사용자가 링크를 선택하고 해당 위치로 이동할 수 있는 링크 목록을 표시합니다.301 Moved Permanently: 이 응답 코드는 요청한 리소스의 URI가 변경되었음을 의미합니다. 새로운 URI가 응답에서 아마도 주어질 수 있습니다.⭐️302 Found: 요청한 페이지가 일시적으로 새 URL로 이동되었습니다.303 See Other: 요청한 페이지는 다른 URL에서 찾을 수 있습니다.304 Not Modified: 요청된 페이지는 마지막 요청 이후 수정되지 않았습니다.307 Temporary Redirect: 요청한 페이지가 일시적으로 새 URL로 이동되었습니다.308 Resume Incomplete: 중단된 PUT 또는 POST 요청을 재개하기 위한 재개 가능한 요청에 사용됨
5.4 400 - 499 클라이언트 오류 코드
클라이언트로 인해 발생한 오류를 나타내는 상태 코드
400 Bad Request: 이 응답은 잘못된 문법으로 인하여 서버가 요청을 이해할 수 없음을 의미합니다.⭐️401 Unauthorized: 요청은 유효하지만 서버가 응답하지 않습니다. 일반적으로 실패한 인증에 사용됩니다.⭐️403 Forbidden: 클라이언트는 콘텐츠에 접근할 권리를 가지고 있지 않습니다. 예를 들어 그들은 미승인이어서 서버는 거절을 위한 적절한 응답을 보냅니다. 401과 다른 점은 서버가 클라이언트가 누구인지 알고 있습니다.⭐️404 Not Found: 요청한 페이지를 서버에서 찾을 수 없습니다.⭐️405 Method Not Allowed: 요청한 메서드가 페이지에서 지원되지 않습니다.406 Not Acceptable: 서버가 클라이언트가 수락하지 않은 응답을 생성합니다.407 Proxy Authentication: 클라이언트는 요청하기 전에 프록시로 인증해야 합니다.408 Request Timeout: 서버가 요청을 기다리는 시간이 초과되었습니다.409 Conflict: 이 응답은 요청이 현재 서버의 상태와 충돌될 때 보냅니다.⭐️410 Gone: 요청한 페이지를 더 이상 사용할 수 없습니다.411 Length Required: “Content-Length”가 정의되지 않았습니다. 서버는 그것 없이는 요청을 수락하지 않습니다412 Precondition Failed: 서버에서 요청 전제 조건 결과가 거짓413 Request Entity Too Large: 요청 엔터티가 너무 커서 서버가 요청을 수락하지 않습니다.414 Request-URI Too Long: URL이 너무 길어 서버가 요청을 수락하지 않습니다. 이것은 POST 요청이 긴 쿼리를 유발하는 GET 요청으로 변환되는 경우 발생할 수 있습니다.415 Unsupported Media Type: 지원되지 않는 미디어 유형으로 인해 서버가 요청을 수락하지 않습니다.416 Requested Range Not Satisfiable: 요청자가 서버에서 제공할 수 없는 파일의 일부를 서버에 요청했습니다.417 Expectation Failed: 서버가 예상 요청 헤더 필드의 요구 사항을 충족할 수 없습니다
5.5 500 - 599 서버 오류 코드
서버에서 오류가 발생했음을 나타내는 상태 코드
500 Internal Server Error: 특정 오류 메시지를 사용할 수 없을 때 표시되는 일반 오류 메시지⭐️501 Not Implemented: 서버가 요청 방법을 인식하지 못하거나 요청을 완료할 수 없습니다502 Bad Gateway: 서버가 게이트웨이 또는 프록시 역할을 하고 업스트림 서버에서 잘못된 응답을 받았습니다.503 Service Unavailable: 서버가 요청을 처리할 준비가 되지 않았습니다. 일반적인 원인은 유지보수를 위해 작동이 중단되거나 과부하가 걸렸을 때입니다.⭐️504 Gateway Timeout: 서버가 게이트웨이 또는 프록시 역할을 하고 업스트림 서버에서 적시에 응답을 받지 못했습니다.505 HTTP Version Not Supported: 서버가 요청에 사용된 HTTP 프로토콜 버전을 지원하지 않습니다.511 Network Authentication Required: 클라이언트는 네트워크 액세스를 얻기 위해 인증해야 합니다.
6. 웹 서버 생성
1const http = require('http')23const port = 300045const server = http.createServer((req, res) => {6// writeHead는 1번만 호출되야 하며, end()가 호출되기 전에 호출되어야 함7// 상태 코드와 응답 헤더를 클라이언트에 보낸다.8res.writeHead(200, {9'Content-Type': 'text/plain',10})11// 데이터가 로드되었음을 서버에 알림12res.end('Hello')13})1415server.listen(port, hostname, () => {16console.log(`Server running at port : ${port}/`)17}) // 127.0.0.1 => localhost
(1) CreateServer 메소드
- http.createServer() 메소드는 server 객체를 생성한다.
- server 객체는 EventEmitter를 기반으로 만들어졌다.
server.on('request', 콜백 함수);
(2) server 객체
server 객체는 컴퓨터의 포트를 수신하고 요청이 만들어질 때마다 requestListener라는 함수를 실행할 수 있다.
server.listen()=> 서버 실행,server.close()=> 서버 종료- server 객체는 EventEmitter를 기반으로 만들어졌다.
- server.on(‘request’, 콜백 함수), server.on(‘connection’, 콜백 함수) …(close, upgrade…)
- HTTP 서버 객체는 컴퓨터의 포트를 수신하고 요청이 만들어질 때마다 requestListener라는 함수를 실행할 수 있습니다.
(3) RequestListener 함수
- requestListener는 서버가 요청을 받을 때마다 호출되는 함수
- requestListener 함수는 사용자의 요청과 사용자에 대한 응답을 처리한다.
6.1 req
req(request), res(response) 객체는 노드가 전달해준다.request 객체는 IncomingMessage의 인스턴스다.IncomingMessage 객체는 서버에 대한 요청을 나타낸다.
다음은 request(요청) 객체가 가지는 속성 또는 메서드들이다.
| 속성 또는 메서드 | 설명 |
|---|---|
| destroy() | 요청 객체를 해제합니다. |
| headers | 요청 헤더의 키-값 쌍 객체를 반환합니다. |
| httpVersion | 클라이언트가 보낸 HTTP 버전을 반환합니다. |
| method | 요청 방법을 반환합니다. |
| rawHeaders | 요청 헤더의 배열을 반환합니다. |
| rawTrailers | 요청 트레일러의 원시 키와 값 배열을 반환합니다. |
| setTimeout() | 지정된 밀리초 후에 지정된 함수를 호출합니다. |
| statusCode | 응답 상태 코드를 반환합니다. |
| socket | 연결에 대한 Socket 객체를 반환합니다. |
| trailers | 트레일러를 포함하는 객체를 반환합니다. |
| url | 요청 URL 문자열을 반환합니다. |
6,2 res
- ServerResponse 객체는 requestListener 함수의 두 번째 매개변수로 전달됩니다.
- 클라이언트에 웹 페이지를 제공하기 위해 response 객체를 사용합니다.
| 속성 또는 메서드 | 설명 |
|---|---|
| addTrailers() | HTTP 트레일링 헤더 추가 |
| end() | 서버에 응답이 완료된 것으로 간주하도록 알림 |
| finished | 응답이 완료된 경우 true, 그렇지 않으면 false 반환 |
| getHeader() | 지정된 헤더의 값 반환 |
| headersSent | 헤더가 전송된 경우 true, 그렇지 않으면 false 반환 |
| removeHeader() | 지정된 헤더 제거 |
| sendDate | Date 헤더가 응답에 전송되지 않아야 하는 경우 false로 설정합니다. 기본값은 true |
| setHeader() | 지정된 헤더 설정 |
| setTimeout() | 지정된 밀리초 후에 지정된 함수 호출 |
| statusCode | 클라이언트에 전송될 상태 코드 설정 |
| statusMessage | 클라이언트에 전송될 상태 메시지 설정 |
| write() | 텍스트 또는 텍스트 스트림을 클라이언트에 전송 |
| writeContinue() | 클라이언트에 HTTP Continue 메시지 전송 |
| writeHead() | 상태 및 응답 헤더를 클라이언트에 전송 |
💡 서버에서 클라이언트로 텍스트를 보내는 것이 아닌 javascript object 보내려면?
Content Type 을 변경해주시면 된다.
1const server = http.createServer((req, res) => {2// writeHead는 1번만 호출되야 하며, end()가 호출되기 전에 호출되어야 함3// 상태 코드와 응답 헤더를 클라이언트에 보낸다.4res.writeHead(200, {5'Content-Type': 'application/json',6})7// 데이터가 로드되었음을 서버에 알림8res.end(9// res.end에는 문자열을 넣어줘야 함10JSON.stringify({11a: 'a',12b: 'b',13}),14)15})
7. HTTP Routing
- 페이지마다 다른 결과를 보여주기 === 이를 라우팅(routing)이라 부름
- cf. route = 경로, 길 | routing = 길 찾기, 경로 찾기
1const server = http.createServer((req, res) => {2res.statusCode = 20034if (req.url === '/home') {5res.setHeader('Content-Type', 'application/json')6res.end(7JSON.stringify({8a: 'a',9b: 'b',10}),11)12} else if (req.url === '/about') {13res.setHeader('Content-Type', 'text/html')14res.write('<html>')15res.write('<body>')16res.write('<h1>About Page</h1>')17res.write('</body>')18res.write('</html>')19} else {20res.end()21res.statusCode = 40422res.end()23}24})2526server.listen(3000)
8. Post 요청으로 데이터 추가
1const http = require('http')23let dataObject = {4a: 'a',5b: 'b',6}78const server = http.createServer((req, res) => {9if (req.method === 'POST' && req.url === '/home') {10req.on('data', data => {11console.log(data.toString())12const stringifiedData = data.toString()13Object.assign(dataObject, JSON.parse(stringifiedData))14})15} else {16if (req.url === '/home') {17res.statusCode = 20018res.setHeader('Content-Type', 'application/json')19res.end(JSON.stringify(dataObject))20} else if (req.url === '/about') {21res.statusCode = 20022res.setHeader('Content-Type', 'text/html')23res.write('<html>')24res.write('<body>')25res.write('<h1>About Page</h1>')26res.write('</body>')27res.write('</html>')28res.end()29} else {30res.statusCode = 40431res.end()32}33}34})3536server.listen(3000, () => {37console.log('서버 실행!!!')38})