Node.js
Rest API 실습
REST API 란?
REST(Representational State Transfer)는
월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식으로,
엄격한 의미로 REST 는 네트워크 아키텍처 원리의 모음입니다.
여기서 ‘네트워크 아키텍처 원리’란 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반을 일컫습니다.
간단한 의미로는, 웹 상의 자료를 HTTP 위에서 SOAP 이나 쿠키를 통한 세션 트랙킹 같은
별도의 전송 계층 없이 전송하기 위한 아주 간단한 인터페이스를 말합니다.
이 두 가지의 의미는 겹치는 부분과 충돌되는 부분이 있습니다.
API 를 제공하는 사이트로 부터 API 를 제공받을 떄 필요한 부분을 필요에 맞게 가져다가 씀으로
웹 어플리케이션을 좀 더 강력하게 만들 수 있습니다.
// yts(영화서비스를 하는 곳) api를 받아와서 다운로드 수대로 정렬 (이처럼 원하는 정보를 알맞게 사용할 수 있습니다.)
_callApi = () => {
return fetch("https://yts.am/api/v2/list_movies.json?sort_by=download_count")
.then(potato => potato.json())
.then(json => json.data.movies)
.catch(err => console.log(err));
};
Node.js 실습
Node.js 는 언어가 아닌 JavaScript 런타임의 일종입니다.
JavaScript Runtime
JavaScript Runtime 은 JS 를 구동하기 위해 필요한 실행환경입니다.
- Chrome 이 제공하는 웹 브라우저용 런타임
- Node.js 가 제공하는 서버용 런타임
- MongoDB 가 제공하는 데이터 처리용 런타임
- Photoshop 이 제공하는 전용 런타임
V8 JavaScript Engine
-
JIT(Just-In-Time) compilation
- JIT 컴파일(just-in-time compilation) 또는 동적 번역(dynamic translation)은 프로그램을
실제 실행하는 시점에 기계어로 번역하는 컴파일 기법으로 이 기법은 프로그램의 실행 속도를 빠르게 하기 위해 사용됩니다.
- JIT 컴파일(just-in-time compilation) 또는 동적 번역(dynamic translation)은 프로그램을
-
Code Optimization (코드 최적화)
-
Used in
- Google Chrome
- Node.js
- MongoDB
Event-driven Programming
프로그램의 흐름이 외부 요인에 의해 일어나는 사건에 의해 결정되는 프로그래밍 방식으로
약속된 방식으로 이벤트 핸들러를 작성함으로써 외부 이벤트가 일어났을 때 코드를 실행합니다.
- 마우스 입력
- 키보드 입력
- 다른 프로그램 / 컴퓨터로부터의 통신
Node.js Module
// module.exports에 저장한 값은 다른 모듈에서 불러올 수 있습니다.
module.exports = {
familyName: "이",
givenName: "근환",
fullName: function() {
return this.familyName + this.givenName;
}
};
// exports로도 참조 가능합니다.
exports.add = (x, y) => x + y;
exports.sub = (x, y) => x - y;
// node.js에 내장되어 있는 것을 불러오고 싶을 때 이렇게 사용합니다.
const os = require("os");
console.log(os.platform());
console.log(os.freemem());
// node.js에서 내가 작성한 것을 불러오고 싶을 때 이렇게 사용합니다.
const m = require("./module.js");
// require('../module');
console.log(m.name);
NPM
Node.js 패키지 관리 도구 + 클라우드 패키지 저장소
- 의존 패키지 관리
- 스크립트 실행
- 패키지 설정
- NPM 에 패키지 배포
- Node.js 종합 작업 도구
package.json
패키지 정보를 담고 있는 파일입니다.
dependencies
‘npm install –save’ 명령으로 설치한 패키지가 기록됩니다.
scripts
원래 목적은 패키지 생명주기마다 자동으로 실행되는 명령을 등록하기 위함이나,
개발자의 편의를 위해 자주 사용되는 명령을 등록하는 용도로 더 많이 사용됩니다.
// 패키지 이름, 버전, 설명등을 할 수 있습니다.
// package.json이란 파일은 npm이 관리합니다.
{
"name": "hello-npm",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
// 자주 쓰는 명령어를 이렇게 해놓으면 간편히 사용가능합니다.
// npm start라고 하면 바로 실행되게끔!
// parcel, webpack등에도 사용가능합니다.
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
.gitignore
git 을 이용하는 모든 명령에서 예외 처리를 할 수 있습니다.
.gitignore 파일을 생성하고 안에 예외 처리할 폴더 및 파일의 이름을 적어주면 됩니다.
HTTP
-
웹 브라우저와 웹 서버 간의 통신을 위해 개발된 통신규약
-
최근에는 REST API 의 부상과 함께 다른 용도로도 널리 사용됩니다.
- 모바일 앱 - 서버 간 통신
- 서버 - 서버 간 통신
-
80 번 포트를 기본으로 사용합니다.
-
클라이언트의 요청(Request)과 서버의 응답(Response)으로 이루어집니다.
일반 홈페이지의 대다수가 이러한 HTTP 로 시작됩니다.
HTTP 역사
- 1991 년 : HTTP 초기버전 발표, 텍스트만 전송할 수 있는 극도로 단순한 프로토콜, 인터넷 붐을 일으켰습니다.
- 1996 년 : 여러 인터넷 서비스 업체들이 자체적으로 사용하던 HTTP 구현들을 모아서 HTTP 1.0 발표
- 1999 년 : 1.0 문제 해결, 여러가지 기능 추가한 1.1 을 발표, 지금까지 사용되고 있는 버전
HTTPS
- HTTP over SSL(Secure Socket Layer)
- HTTP 통신을 암호화해 주고받는 내용을 중간에서 가로챌 수 없도록 합니다. (클라이언트 - 공개키, 서버 - 개인키)
- 443 번 포트를 기본으로 사용합니다.
주로 은행, 쇼핑몰, 정부사이트등 보안이 중요한 곳에서 사용합니다.
HTTP 와 HTTPS 의 차이
HTTP 와 HTTPS 의 장단점
-
HTTP
-
장점
- 접속 도중 끊기더라도 처음부터 다시 시작할 필요가 없어 시간을 낭비하지 않습니다.
-
단점
- HTTP 는 클라이언트가 요청한 페이지를 암호화 되지 않은 상태로 주고 받을 수 있어
HTTP 로 만든 홈페이지는 클라이언트와 서버의 네트워크에 침입 해 중간에서 정보를 가로챌 수 있는 위험이 상존합니다.
- HTTP 는 클라이언트가 요청한 페이지를 암호화 되지 않은 상태로 주고 받을 수 있어
-
-
HTTPS
-
장점
- 즉 이용자(클라이언트)가 사이트에 접속하게 되면 서버가 공개키를 이용자에게 보내게 되고
이를 통해서 이용자의 암호화된 정보를 서버는 개인키로 볼 수 있어 네크워크에 침입한 해커는 아무것도 볼 수 없게 됩니다.
쉽게 말하면 보안성이 우수합니다.
- 즉 이용자(클라이언트)가 사이트에 접속하게 되면 서버가 공개키를 이용자에게 보내게 되고
-
단점
- 암호화된 정보를 교환하기 때문에 서버가 과부하에 걸리는 경우가 발생합니다.
- 접속이 끊기게 되면 다시 처음부터 시작해야 하는 불편함이 따릅니다
-
HTTP/2
- 구글의 SPDY 프로토콜을 기반으로 2015 년에 확정된 새로운 HTTP 표준입니다.
- 속도 개선에 중점을 두고 개발되었습니다.
- 반드시 HTTPS 를 사용해야 합니다.
- 현재 전체 웹사이트 중 26% 이상이 사용중입니다.
HTTP 1.1 과 HTTP/2 와 차이점
TCP (Transmission Control Protocol)
웹 브라우저들이 웹에서 서버에 연결할 때 사용되며, 이메일 혹은 파일 전송시에도 사용됩니다.
Request & Response
- 웹 브라우저(또는 다른 클라이언트)는 웹 서버에 요청(Request)를 보냅니다.
- 그에 따라 서버는 클라이언트에 응답(Response)를 보냅니다.
- 웹 브라우저의 경우, HTML 문서 형태의 응답이 오면 해당 문서를 분석한 후,
문서에 포함된 모든 자원에 대한 요청을 각각 추가로 보냅니다.(이미지, CSS, JS 등..)
Request Method
- HTTP 명세에는 8 종류가 등록되어 있고, 각각의 역할과 충족해야 하는 성질이 명시되어 있습니다.
- 웹 브라우저는 특정 상황에서 특정 메소드를 요청을 보내도록 만들어져 있습니다.
- Ajax 와 같이 요청을 보내는 코드를 직접 짤 때는 요청 메소드를 선택할 수 있습니다.
- 자료의 본문을 요청하는 GET 메소드와 새로운 자료를 등록하는 POST 메소드가 가장 많이 쓰입니다.
HTTP URL Anatomy
[주의]
위의 주소(도메인)은 절대적인 주소가 아닙니다.
사람들이 이용하기 쉽게 문자 혹은 숫자로 구성된 주소(도메인)은
우리가 해당 주소로 요청을 보냈을 때 DNS 서버에 질의를 통해 해당 주소의 웹서버 IP 를 제공받게 되고,
그 해당 주소의 웹서버 IP 에 요청을 하여 응답을 받게 되는 것입니다.
Percent Encoding
-
URL 은 ASCII 문자(128 개의 영문자+특수문자+제어문자)밖에 사용되지 못하기 때문에,
non-ASCII 문자를 위한 표현방법이 필요합니다. -
Percent encoding 은 non-ASCII 문자를 위한 웹 표준 인코딩 방법으로,
JavaScript 에 관련 기능이 포함되어 있습니다.
encodeURIComponent("한글");
// "%ED%95%9C%EA%B8%80"
decodeURIComponent("%ED%95%9C%EA%B8%80");
// "한글"
Response Status
-
Status Category
-
2xx : 성공
- 200 OK : 성공
- 201 Created : 자료가 성공적으로 생성되었습니다.
-
3xx : 추가 작업이 필요함
- 301 Moved Permanently (Redirection) : 자료가 완전히 다른 곳으로 이동했습니다.
- 302 Found (Redirection) : 자료가 일시적으로 다른 곳에 있습니다.
- 304 Not Modified (Cache) : 클라이언트가 이미 가지고 있던 자료가 수정되지 않았습니다. (그대로 사용하면 됩니다.)
-
4xx : 실패 - 클라이언트 책임
- 400 Bad Request : 요청의 형태가 잘못되어 응답할 수 없습니다.
- 401 Unauthorized : 인증이 되지 않았습니다.
- 403 Forbidden : 요청한 자료에 접근할 권한이 없습니다. (인가가 되지 않았습니다.)
- 404 Not Found : 요청한 자료가 없습니다.
-
5xx : 실패 - 서버 책임
- 500 Internal Server Error : 요청을 처리하던 중에 예상치 못한 오류가 발생했습니다.
- 503 Service Unavailable : 서버가 일시적으로 응답을 할 수 없습니다.
-
Header
- 요청과 응답에 대한 추가 정보를 표현하는 데 사용됩니다.
-
인증, 캐싱, 쿠키, 보안, 내용협상, 프록시 등 웹 표준에 정의된 많은 기능을 제어하는 데 사용됩니다.
-
Header 의 종류
- Authorization : 요청의 인증 정보
- User-Agent : 요청 중인 클라이언트의 정보
- Location : 301, 302 응답에서 자료의 위치
- Accept : 요청이 어떤 형태의 자료를 원하는지 나타냅니다.
-
Content-Type : 요청 혹은 응답이 어떤 형태의 자료인지 나타냅니다. [ex] content-type : application/json;charset=UTF-8
- Accept, Content-Type 에서 사용되는 Mime Type
Content Negotiation
요청의 Accept, Accept-Language 등의 헤더를 보고 서버가
그에 맞는 형태의 자료를 응답하는 절차를 Content-negotiation 이라 합니다.
chrome Devtools
-
network : 웹 페이지와 관련된 네트워크 요청들을 확인할 수 있는 패널
-
element : 로딩된 사이트의 DOM 요소와 CSS 속성보기와 변경이 가능합니다.
워크 스페이스에 별도로 추가하지 않는 한 새로고침하면 변경된 내역이 사라집니다. -
console : 웹 페이지의 로그를 확인할 수 있는 패널
자바스크립트 코드 실행이 가능합니다. -
source : 로딩한 웹 페이지의 자바스크립트를 디버깅 할 수 있는 채널
-
timeline : 사이트 로딩, 화면 렌더링 등 모든 활동들의 기록을 측정할 수 있는 패널
-
profile : 페이지 성능과 관계된 메모리 릭(leak)등의 이슈를 진단할 수 있는 패널
-
application : 웹 스토리지, 쿠키, 세션 등의 저장소와 PWA 의 주요 기능들을 확인할 수 있는 패널
-
security : 개인정보 보안이나 인증서와 관계된 사항을 확인할 수 있는 패널
Express
Glitch 실습
Glitch 는 웹 브라우저 위에서 Node.js 기반 앱을 만들고, 복제하고,
편집하고, 공동 작업하고, 호스팅할 수 있는 환경을 제공합니다.
https://glitch.com/
Express
- Node.js 생태계에서 가장 널리 쓰이는 웹 프레임워크
- 내장하고 있는 기능은 매우 적으나, 미들웨어를 주입하는 방식으로 기능을 확장하는 생태계를 가지고 있습니다.
// Express 앱의 기본 구조
// Express 인스턴스 생성
const app = express();
// 미들웨어 주입
app.use(sessionMiddleware());
app.use(authenticationMiddleware());
// 라우터 핸들러 등록
app.get("/", (request, response) => {
response.send("Hello World");
});
// 서버 구동
app.listen(3000, () => {
console.log("Example app listening on port 3000!");
});
Routing
// HTTP 요청 메소드 (GET, POST, ...)와 같은 이름의 메소드를 사용합니다.
app.get("/articles", (req, res) => {
res.send("Hello Routing!");
});
// 특정 경로에만 미들웨어를 주입하는 것도 가능합니다.
app.post("/articles", bodyParserMiddleware(), (req, res) => {
database.articles.create(req.body).then(() => {
res.send({ ok: true });
});
});
// 경로의 특정 부분을 함수의 인자처럼 입력 받을 수 있습니다.
app.get("/articles/:id", (req, res) => {
database.articles
.find(req.params.id) // 'req.params'에 저장됨
.then(article => {
res.send(article);
});
});
Request 객체
- req.body : 요청 바디를 적절한 형태의 자바스크립트 객체로 변환하여 이곳에 저장됩니다.
(body-parser 미들웨어에 의해 처리됩니다.) - req.ip : 요청한 쪽의 IP
- req.params : route parameter
- req.query : query string 이 객체로 저장됩니다.
Reponse 객체
- res.status(…) : 응답의 상태 코드를 지정하는 메소드
- res.append(…) : 응답의 헤더를 지정하는 메소드
- res.send(…) : 응답의 바디를 지정하는 메소드
인자가 텍스트면 text/html, 객체면 application/json 타입으로 응답
Express 실습 - glitch 사용
onst express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.enable('trust proxy');
app.use(bodyParser.json());
// GET method
app.get('/', (req, res) => {
res.send('Hello, Express!')
});
// POST method
app.post('/', (req, res) => {
/*
Mission:
요청의 바디에 실려 온 JSON에 name이라는 속성이 있으면 해당 값을 이용해 응답하고, 없으면 400 Bad Request를 응답한다.
응답 형태는 'Hello, <name>!' 으로 한다.
*/
if (req.body.name) {
res.send(`Hello, ${req.body.name}!`);
} else {
res.status(400);
res.send('400 Bad Request');
}
});
// query parameter, res.status
app.get('/add', (req, res) => {
/*
Mission:
query parameter에 x와 y라는 이름을 가진 두 값을 정수로 바꾸어서 더한 후 응답한다.
값을 정수로 바꿀 수 없다면 400 Bad Request로 응답한다.
*/
req.query.x = parseInt(req.query.x);
req.query.y = parseInt(req.query.y);
if (Number.isInteger(req.query.x) && Number.isInteger(req.query.y)) {
res.send({sum: req.query.x+ req.query.y});
} else {
res.status(400);
res.send('400 Bad Request')
}
})
// req.ip
app.get('/ip', (req, res) => {
/*
Mission:
요청한 쪽의 ip를 응답한다.
*/
res.send(req.ip);
});
// req.get, res.set, res.end
app.get('/header', (req, res) => {
/*
Mission:
요청의 X-Custom-Header 헤더를 그대로 응답에 포함시켜 응답한다.
응답에는 바디를 포함시키지 않도록 한다.
hint 1: req.get 메소드는 요청에 포함된 특정 헤더의 값을 가져온다.
예) req.get('X-Custom-Header')
hint 2: res.set 메소드는 응답에 새로운 헤더를 지정한다.
예) res.set('X-Custom-Header', value)
hint 3: res.end 메소드는 응답을 보낸다. res.send와 비슷하지만, 아무런 인자도 받지 않는다.
*/
res.set('X-Custom-Header', req.get('X-Custom-Header'));
res.end();
});
const listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
Template Language
- 템플릿과 데이터를 결합해 문서를 생성하는 프로그램 혹은 라이브러리
- 템플릿을 작성할 때 사용하는 언어를 템플릿 언어라고 합니다.
EJS (Embedded JavaScript Template)
- Node.js 생태계에서 가장 많이 사용되는 템플릿 엔진
- JavaScript 코드를 템플릿 안에서 그대로 쓸 수 있음
EJS Syntax
-
템플릿 태그
- <%…%> : 템플릿의 구조를 제어하기 위해 사용하며, 문자열을 내놓지 않습니다.
- <%=…%> : 내부의 식을 문자열로 변환해 HTML 문서 안에 삽입합니다.
- <%#…%> : EJS 주석입니다. HTML 주석과는 다르게 아예 HTML 문서에 포함되지 않습니다.
-
HTML Escaping
데이터를 HTML 에 삽입하는 <%= … %> 템플릿 태그는 <, > 두 문자를 각각 <, >로 변환하여 HTML 에 삽입합니다.
결과적으로 HTML 태그를 직접 템플릿에 삽입하지 못하게 막습니다.
이렇게 하는 이유는 보안 때문으로, XSS(Cross-site Scripting)를 당할 위험을 줄여줍니다.
<%- … %> 템플릿 태그를 이용하면 HTML escape 를 생략할 수 있으나,
아주 특별한 경우가 아니면 <%= … %> 태그를 사용하기를 권장합니다.
<%# 주석입니다 %>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/index.css">
</head>
<body>
<% if (name) { %>
<p>당신의 이름은 <%= name %>입니다.</p>
<% } else { %>
<p>이름이 주어지지 않았습니다. query parameter에 name을 추가해보세요.</p>
<% } %>
<hr>
<h1>List</h1>
<ul>
<% items.forEach(item => { %>
<li><%= item %></li>
<% }) %>
</ul>
<% if (showSecret) { %>
<p>my secret is: <%= secret %></p>
<% } %>
</body>
</html>
파일을 그대로 제공하기
// 'public' 폴더에 있는 파일을 '/static' 경로 아래에서 제공
app.use("/static", express.static("public"));
<!--템플릿 파일에서 참조할 수 있음-->
<link rel="stylesheet" href="/static/index.css">
<script type="text/javascript" src="/static/index.js"></script>
HTML Form
-
HTML Form 을 전송하면, 입력된 정보가 기본적으로 percent encoding 되어 요청됩니다.(GET, POST 모두 다 해당됩니다.)
- GET method - 주소에 정보가 포함되어 전송됩니다. (보안에 다소 취약한 부분이 있습니다.)
GET /search?query=%EA%B0%9C&sort=latest HTTP/1.1
- POST method - 요청바디에 포함되어 전송됩니다.
POST /form HTTP/1.1 Content-Type: application/x-www-form-urlencoded ... home=Cosby&favorite+flavor=files
HTML Form Example
-
UUID
인터넷 상의 수많은 자료를 구분하기 위해 각 자료에 식별자(identifier)를 부여하는 일은 아주 중요합니다.
식별자를 부여하는 가장 쉬운 방법은 자료가 생성된 순서대로 번호를 붙이는 것입니다.
실제로 많은 데이터베이스에서 이런 방법을 사용하고 있습니다.
하지만 환경에 따라 자료가 생성되는 순서를 알 수 없는 경우도 있습니다.
UUID 는 식별자로 사용하기 위해 고안된 수 형식이며, 아래와 같은 형식으로 표현됩니다.
424e19f5-f330-4be1-889f-4a9f7da75b69
UUID 는 표현할 수 있는 경우의 수가 무지무지무지무지 많습니다.
(128bit = 2 의 128 제곱) UUID 난수를 생성하는 표준적인 방법(UUID version 4)을 사용하면,
언제 어디서 UUID 를 생성해도 정확히 같은 UUID 가 생성될 수 있는 확률이매우매우매우매우 작기 때문에 안심하고 식별자로 사용할 수 있습니다. -
Redirection after submission
순수한 HTML form 을 이용해 POST 메소드로 자료를 전송한 후에는 꼭 리디렉션을 통해 응답해야 합니다.
특히 302 상태 코드를 사용해 응답해야 합니다.
POST 메소드 요청에 일반적인 응답(2xx)을 하게 되면,
해당 페이지를 새로고침을 했을 때 이전에 보냈던 요청을 그대로 다시 보내게 되기 때문에,
자료가 이중으로 전송되게 됩니다.
server.js 에서 주석을 해제해서 테스트해볼 수 있습니다.
단, 이는 순수 HTML form 을 사용했을 때만 해당되며,
Ajax 를 통해 자료를 전송하는 방식이라면 2xx 상태코드의 일반적인 응답을 해도 괜찮습니다.
(사용자가 Ajax 를 새로고침할 수 있는 방법은 없기 때문입니다.)
301 상태코드(Moved Permanently)를 사용하면 안되는 이유는 브라우저 캐시 때문입니다.
브라우저가 한 번 301 응답을 받게 되면, 그 결과를 저장해두었다가 사용자가 같은 요청을 보내려고 할 때
서버에 요청을 보내지 않고 미리 저장해둔 응답을 대신 보여줍니다.
만약 사용자의 폼 전송에 대해 한 번 301 상태코드로 응답하게 되면,
사용자가 나중에 같은 내용으로 폼을 전송하려고 했을 때 제대로 전송되지 않을 것입니다. -
Form validation
사용자가 입력하는 자료는 개발자가 기대하는 형식과는 영 딴판일 수 있습니다.
필요한 필드가 없을 수도 있고, 자료의 형식을 서버가 이해할 수 없는 경우도 있습니다.
이런 자료를 데이터베이스에 그냥 집어넣게 되면 데이터베이스가 뒤죽박죽이 되고 말 것입니다.
그래서, 사용자에게 입력받은 자료는 처리를 하기 전에 항상 올바른 형태인지 검증해야 합니다.
이런 검증 과정을 form validation 이라고 합니다.
form validation 을 구현하는 전형적인 방법은 다음과 같습니다.
사용자가 폼을 작성합니다.
사용자가 폼을 서버에 전송합니다.
서버는 기대한대로 데이터가 들어왔는지 검사합니다.
서버는 데이터가 기대한 대로 잘 들어왔으면 다음 단계를 진행하고,
데이터에 문제가 있다면 어떤 문제가 있는지를 사용자에게 알려줍니다.
서버 측에서 하는 form validation 은 꼭 필요하지만,
사용자가 자료를 서버에 전송해야만 데이터에 어떤 문제가 있는지를 알 수 있다는 단점이 있습니다.
서버 측 validation 을 잘 구현해서 사용자가 덜 불편하게끔 만드는 방법도 있지만
폼을 서버에 전송해야 피드백을 받을 수 있다는 점은 변하지 않습니다.
더 나은 사용자 경험을 위해 클라이언트 측 validation 을 하는 것을 고려해볼 수 있습니다.
클라이언트 측 validation 은 사용자가 폼을 작성하는 도중에 피드백을 받을 수 있다는 점에서
서버 측 validation 보다 훨씬 나은 사용자 경험을 제공할 수 있습니다.
대신 서버 측 코드에서 하는 데이터 검사 로직을 클라이언트 측 코드에도
중복 구현해야 한다는 어려운 점이 있습니다.
다행히 HTML5 에 추가된 form validation 기능을 이용하면
간단한 validation 은 자바스크립트 코드를 하나도 짜지 않고도 구현할 수 있습니다.
HTML5 form validation 을 시험해 보려면, HTML 문서에 Form > Input 필드에 required 속성을 추가하면 됩니다.
HTML5 form validation 은 사용하기 간편하고,
브라우저에 내장되어 있다는 점에서 (특히 모바일에서) 일관성있는 사용자 경험을 제공할 수 있다는 장점이 있습니다.
하지만 HTML5 를 지원하지 않는 구형 브라우저에서는 사용할 수 없고,
또 복잡한 형태의 validation 은 지원하지 않는다는 단점이 있습니다.
(여러 필드의 자료를 합쳐서 validation 을 한다거나, validation 을 하기 위해 서버에 요청을 해야 하는 등)
주의! 클라이언트 측 validation 을 하더라도 서버 측에서는 반드시 validation 을 따로 해주어야 합니다.
사용자가 언제나 우리가 제공하는 클라이언트를 사용한다는 보장은 없기 때문입니다.
multipart/form-data
- 기본 설정으로는 폼으로 파일을 업로드하는 것은 불가능합니다.
- (클라이언트 측) form 태그에 enctype=”multipart/form-data” 속성을 적용하면 파일 업로드 가능합니다.
- (서버 측) body-parser 미들웨어는 multipart/form-data 형태의 요청을 지원하지 않습니다.(multer 필요)
URL shortener 구현 실습
- 긴 URL 은 비밀 키를 알아야만 만들 수 있습니다.
- 짧은 URL 은 누구나 이용할 수 있습니다.
2. Today I Found Out
통신에 대해서 기대를 갖고 있었고 기대에 상당부분 만족할 수 있는 공부였습니다.
REST API가 무엇인지 알아보고 실습을 통해 이런 것들이구나 하고 깨달을 수 있었습니다.
배우면서도 어서 써먹어보고 싶다는 생각이 가득할 정도로 좋았습니다.
또한 Node.js를 배워봄으로써 런타임에 대해서 알아볼 수 있었고,
평소에 궁금했던 것들을 상당수 체험해서 궁금증을 해결할 수 있었습니다.
3. refer
https://fds9.github.io/fds-nodejs-http/
https://developer.github.com/v3/
https://www.slideshare.net/GihyoJoshuaJang/ss-71668518