오늘 한 일
코딩테스트 연습
숫자 문자열과 영단어
문자열 내 마음대로 정렬하기
1. HTTP 메시지
HTTP 메시지는 서버와 클라이언트 간에 데이터가 교환되는 방식이다. 메시지 타입은 두 가지가 있다. 요청(request)은 클라이언트가 서버로 전달해서 서버의 액션이 일어나게끔 하는 메시지고, 응답(response)은 요청에 대한 서버의 답변이다.
HTTP 메시지는 ascii로 인코딩된 텍스트 정보이며, 여러 줄로 되어있다. HTTP 프로토콜 초기 버전과 HTTP/1.1에서는, 클라이언트와 서버 사이의 연결을 통해 공개적으로 전달되었습니다. 이렇게 한 때 사람이 읽을 수 있었던 메시지는 HTTP/2에서는 최적화와 성능 향상을 위해 HTTP 프레임으로 나누어진다.
웹 개발자 또는 웹 마스터가 손수 HTTP 메시지를 텍스트로 작성하는 경우는 드물다. 대신에 소프트웨어, 브라우저, 프록시, 또는 웹 서버가 그 일을 한다. HTTP 메시지는 설정 파일(프록시 또는 서버의 경우), API(브라우저의 경우), 혹은 다른 인터페이스를 통해 제공된다.
HTTP/2의 이진 프레이밍 메커니즘(binary framing mechanism)은 사용 중인 API나 설정 파일 등을 변경하지 않아도 되도록 설계 되었기 때문에, 사용자가 보고 이해하기 쉽다.
HTTP 요청과 응답의 구조는 서로 닮았으며, 그 구조는 아래와 같다.
- 시작 줄(start-line)에는 실행되어야 할 요청, 또는 요청 수행에 대한 성공 또는 실패가 기록되어 있다. 이 줄은 항상 한 줄로 끝난다.
- 옵션으로 'HTTP 헤더' 세트가 들어간다. 여기에는 요청에 대한 설명, 혹은 메시지 본문에 대한 설명이 들어간다.
- 요청에 대한 모든 메타 정보가 전송되었음을 알리는 빈 줄(blank line)이 삽입된다.
- 요청과 관련된 내용(HTML 폼 컨텐츠 등)이 옵션으로 들어가거나, 응답과 관련된 문서가 들어간다. 본문의 존재 유무 및 크기는 첫 줄과 HTTP 헤더에 명시된다.
HTTP 메시지의 시작 줄과 HTTP 헤더를 묶어서 '요청 헤드(head)' 라고 부르며, 이와 반대로 HTTP 메시지의 페이로드는 '본문(body)'이라고 한다.
2. HTTP 요청
시작 줄
HTTP 요청은 서버가 특정 동작을 취하게끔 만들기 위해 클라이언트에서 전송하는 메시지다. 시작 줄은 다음과 같이 세 가지 요소로 이루어져 있다.
- 'HTTP 메서드'로, 영어 동사(GET, PUT, POST) 혹은 명사(HEAD, OPTIONS)를 사용해 서버가 수행해야 할 동작을 나타낸다.
- '요청 타겟'은 주로 URL, 또는 프로토콜, 포트, 도메인의 절대 경로로 나타낼 수도 있으며 이들은 요청 컨텍스트에 의해 특정지어 진다. 요청 타겟 포맷은 HTTP 메소드에 따라 달라진다. 포맷에는 다음과 같은 것들이 있다.
- 가장 일반적인 형식이고 'origin 형식'으로 알려진 절대 경로. 이 형식은 끝에 ?와 쿼리 문자열이 따라온다. GET, POST, HEAD, OPTIONS 메서드와 함께 사용한다.
- 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과 함께 사용된다.
- 'authority 형식'으로 알려지고 도메인 이름 및 옵션 포트(:)로 이루어진 URL의 인증 컴포넌트. HTTP 터널을 구축하는 경우에만 CONNECT와 함께 사용할 수 있다.
- CONNECT developer.mozilla.org:80 HTTP/1.1
- OPTIONS와 함께 별표(*) 하나로 서버 전체를 나타내는 'asterisk 형식'
- OPTIONS * HTTP/1.1
- 가장 일반적인 형식이고 'origin 형식'으로 알려진 절대 경로. 이 형식은 끝에 ?와 쿼리 문자열이 따라온다. GET, POST, HEAD, OPTIONS 메서드와 함께 사용한다.
- 메시지의 남은 구조를 정의하는 HTTP 버전은 응답 메시지에서 써야 할 HTTP 버전을 알려주는 역할을 한다.
헤더
요청에 들어가는 HTTP헤더는 HTTP헤더의 기본 구조를 따른다. 대소문자 구분없는 문자열 다음에 콜론(:)이 붙으며, 그 뒤에 오는 값은 헤더에 따라 달라진다. 헤더는 값까지 포함해 한 줄로 구성되지만 꽤 길어질 수 있다.
다양한 종류의 요청 헤더가 있는데, 이들은 다음과 같이 몇몇 그룹으로 나눌 수 있다.
- Via와 같은 General 헤더는 메시지 전체에 적용된다.
- User-Agent, Accept와 같은 Request 헤더는 요청의 내용을 좀 더 구체화 시키고(Accept-Language), 컨텍스를 제공하기도 하며(Referer), 조건에 따른 제약 사항을 주기도 하면서(If-None) 요청 내용을 수정한다.
- 메시지 데이터의 원래 형식과 적용된 인코딩을 설명하는 Content-Type과 같은 Representation 헤더(메시지에 본문이 있는 경우에만 존재한다).
본문
본문은 요청의 마지막 부분에 들어간다. 모든 요청에 본문이 들어가지는 않는다. GET, HEAD, DELETE, OPTIONS처럼 리소스를 가져오는 요청은 보통 본문이 필요가 없다. 일부 요청은 업데이트를 하기 위해 서버에 데이터를 전송한다. 보통 (HTML 폼 데이터를 포함하는) POST 요청일 경우에 그렇다.
넓게 보면 본문은 두 종류로 나뉜다.
- 헤더 두 개(Content-Type과 Content-Length)로 정의된 단일 파일로 구성되는 단일-리소스 본문(single-resource bodies)
- 각각 서로 다른 정보를 담고 있는 멀티파트 본문으로 구성되는 다중 리소스 본문
3. HTTP 응답
상태 줄
HTTP 응답의 시작 줄은 '상태 줄(status line)'이라고 불리며, 다음과 같은 정보를 가지고 있다.
- 프로토콜 버전(보통 HTTP/1.1)
- 요청의 성공 여부를 나타내는 '상태 코드'. 일반적인 상태 코드는 200, 404 혹은 302이다.
- 사람이 HTTP메시지를 이해할 때 도움이 되는 상태 코드에 대한 짧고, 순전히 정보 제공 목적의 '상태 텍스트'
상태 줄은 일반적으로 HTTP/1.1 404 Not Found. 와 같이 표현된다.
헤더
응답에 들어가는 HTTP 헤더는 다른 헤더와 동일한 구조를 따른다. 대소문자를 구분하지 않는 문자열 다음에 콜론(:)이 오며, 그 뒤에 오는 값은 구조가 헤더에 따라 달라진다. 헤더는 값을 포함해 전체를 한 줄로 표시한다.
다양한 종류의 응답 헤더가 있는데, 이들은 다음과 같이 몇몇 그룹으로 나눌 수 있다.
- Via와 같은 General 헤더는 메시지 전체에 적용된다.
- Vary와 Accept-Ranges와 같은 Response 헤더는 상태 줄에 포함되지 않는 서버에 대한 추가 정보를 제공한다.
- 메시지 데이터의 원래 형식과 적용된 인코딩을 설명하는 Content-Type과 같은 Representation 헤더(메시지에 본문이 있는 경우에만 존재한다)
본문
본문은 응답의 마지막 부분에 들어간다. 모든 응답에 본문이 들어가지는 않는다. 해당 페이로드 없이도 요청에 충분히 응답하는 201 Created, 204 **No Content** 와 같은 상태 코드를 가진 응답에는 보통 본문이 없다.
넓게 보면 본문은 세가지 종류로 나뉜다.
- Content-Type과 Content-Length라는 두 개의 헤더로 정의하는 길이가 알려진 하나의 파일로 구성된 단일-리소스 본문(Single-resource bodies)
- Transfer-Encoding이 chunked로 설정된 청크로 나뉘어 인코딩되는 길이를 모르는 하나의 파일로 구성된 단일-리소스 본문
- 서로 다른 정보를 담고 있는 멀티파트 본문으로 이루어진 다중 리소스 본문. 이 경우는 상대적으로 위의 두 경우에 비해 보기 힘들다.
4. Express.js로 간단한 API 작성해보기
- 서버 시작하기
// 1. Express.js의 서버를 엽니다.
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
- 라우터 등록
import goodsRouter from './routes/goods.js';
import newsRouter from './routes/news.js';
// 2. 라우터를 등록 합니다.
app.use('/api', [goodsRouter, newsRouter]);
- API 정의
// routes/news.js
/** 뉴스 목록 조회 API **/
// 3. HTTP Method와 URL을 지정한 API를 정의합니다.
// 만약, localhost:3000/api/news 라는 URL로 GET 요청이 들어온다면 해당 코드를 실행합니다.
router.get('/news', (req, res) => {
...
});
- 결과 반환(send 메서드)
router.get('/news', (req, res) => {
// 4. 사용자의 요청에 맞는 데이터를 반환합니다.
return res // Express.js의 res 객체를 반환합니다.
.status(200) // API의 상태 코드를 200번으로 전달합니다.
.send('뉴스 목록 조회 API 입니다.'); // API의 결과값을 '뉴스 목록 조회 API 입니다.'로 전달합니다.
});
- 결과 반환(json 메서드)
/** 뉴스 세부 조회 API **/
// 3. HTTP Method와 URL을 지정한 API를 정의합니다.
// 만약, localhost:3000/api/news/:newsId 라는 URL로 GET 요청이 들어온다면 해당 코드를 실행합니다.
router.get('/news/:newsId', (req, res) => {
// 클라이언트가 전달한 Path Params 데이터를 받아옵니다.
const params = req.params;
// Path Params 데이터 중 newsId를 추출합니다.
const newsId = params.newsId;
// 서버 콘솔에 클라이언트가 전달한 newsId를 출력합니다.
console.log('클라이언트로 부터 전달받은 뉴스 ID:', newsId);
// 4. 사용자의 요청에 맞는 데이터를 json 형태로 반환합니다.
return res.status(200).json({
data: '뉴스 세부 조회 API 입니다.',
});
});
참고: https://developer.mozilla.org/ko/docs/Web/HTTP/Messages
5. 미들웨어(Middleware)
미들웨어는 시스템의 일부가 데이터를 통신하고 관리할 수 있도록 하는 모든 소프트웨어 또는 서비스에 대한 (느슨하게 정의된) 용어다. 컴포넌트와 입력/출력 간의 통신을 담당하는 소프트웨어이므로, 개발자는 어플리케이션의 특정 목적에 집중할 수 있다.
서버 사이트 웹 어플리케이션 프레임워크에서, 미들웨어라는 용어는 데이터베이스 접근과 같은 작업을 처리하기 위해 프레임워크의 요청 및 응답 처리를 하고, 파이프라인에 추가할 수 있도록 미리 구축되어 있는 소프트웨어 컴포넌트를 가리키는데 더 구체적으로 사용되는 경우가 대부분이다.
참고: https://developer.mozilla.org/ko/docs/Glossary/Middleware