일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 코딩테스트
- 코딩테스트준비
- HTML
- 방송대
- 코드잇
- 꿀단집
- 파이썬프로그래밍기초
- presignedurl
- 유노코딩
- redis
- 방송대컴퓨터과학과
- 항해99
- Python
- 개발자취업
- MySQL
- node.js
- aws
- 파이썬
- 99클럽
- Cookie
- nestjs
- 중간이들
- SQL
- 데이터베이스시스템
- Git
- JavaScript
- CSS
- TiL
- 프로그래머스
- 엘리스sw트랙
- Today
- Total
배꼽파지 않도록 잘 개발해요
[코드잇] Node.js 기본기 ② - 웹서버 제작, 서드파티 모듈과 npm 본문
◆ 초간단 웹 서버 만들기
◆ 서드파티 모듈과 npm 제대로 배우기
초간단 웹 서버 만들기
서버와 클라이언트
클라이언트 : 서비스에 대한 요청을 보내는 프로그램 또는 컴퓨터
서버 : 요청을 받은 서버는 그에 알맞은 응답을 해줌
// http 모듈을 로드했을 때 리턴되는 객체를 같은 이름인 http라는 상수로 받음.
const http = require('http');
let server = http.createServer();
// 서버 객체가 외부 요청을 받을 수 있도록 해줌
// 서버 객체가 포트번호 3000번을 갖고 외부 요청을 기다리도록 함.
server.listen(3000);
서버에서 외부의 요청을 기다리며 실행되고 있는 프로그램에는 포트번호라는 숫자값이 할당됨.
이 포트번호는 프로그램마다 다름.
클라이언트는 포트번호를 잘 지정하면 원하는 요청을 보낼 수 있음.
127.0.0.1 ( localhost ): 자신의 컴퓨터를 나타내도록 특별히 정해진 주소
테스트용으로 사용되는 IP 주소
무한로딩만 되고, 서버로부터 응답이 오지 않고 있음.
그 이유는 서버 객체가 클라이언트로 요청 받았을때 어떤 응답을 해줘야 하는지 설정하지 않았기 때문임.
request : 클라이언트의 요청에 관한 객체
response : 서버 객체가 할 응답에 관한 객체
Ctrl + C : 서버 종료
const http = require('http');
// 클라이언트 요청 들어올 때마다 응답을 보내줌
let server = http.createServer(function (request, response) {
response.end('<h1>Hello world!</h1>');
});
server.listen(3000);
http://127.0.0.1:3000
- 나의 컴퓨터에서(127.0.0.1)
- 3000번 포트 번호를 가지고 실행되고 있던(:3000) 서버 프로그램과
- http라는 프로토콜로 통신을 시작하겠다는 뜻
URL 구조
URL (Uniform Resource Locator)
웹 상의 특정 자원(HTML, CSS, JS, 이미지, 영상 등)의 위치를 나타낸 문자열
http://example.com/business/mart/item?category=14&id=2965
http | 스킴(scheme) | 프로토콜 이름 프로토콜 : 클라이언트와 서버 간의 통신 규약 (주로 http나 https) |
example.com | 호스트(host) | 특정 서버를 나타냄 |
/business/mart/item | 경로(path) | 원하는 자원의 위치를 나타냄 Path는 의미를 나타내기 위한 용도 디렉토리 구조 안에 item 파일이 없어도 됨 서버 개발자들이 원하는대로 정할 수 있음 |
category=14&id=2965 | 쿼리(query) | 서버에 요청할 때 원하는 것을 상세하게 표현하기 위해 사용 물음표 뒷부분 / 쿼리의 각 항목은 &표시로 구분함. |
포트 번호를 입력하지 않아도 접속되는 이유
- 특정 프로토콜로 통신을 하는 서버 프로그램은 특정 포트 번호를 사용하도록 정해져 있기 때문
- https://www.google.com도 이렇게 써야 정확함.
- 포트번호는 http : 80, https: 443
Domain Name Resolution (DNS 서비스, Name Server)
- 외우기 쉬운 도메인 네임을 IP 주소로 변환하는 작업
라우팅 (URL 라우팅)
· 요청이 들어온 URL에 따라 서버가 다르게 처리하는 것
· 클라이언트의 요청에 대해 서버가 그 URL을 보고 적절하게 분기하여 처리하여 주는 것
url 정보는 request 객체의 속성으로 들어옴.
127.0.0.1:3000/
→ 이 부분은 출력이 안 된다.
보통 한 사이트 내에서 돌아다니면 URL에서 호스트 부분은 그대로이고, path부터 그 뒷부분이 다양하게 변함.
그 뒷부분이 달라질 때마다 보게 되는 페이지도 달라짐.
→ 각 path마다 해야할 응답이 서버 프로그램에 미리 설정되어 있기 때문에 가능한 것임.
url 중에서도 특히 path부터가 중요하기 때문에
지금 속성 이름은 url이지만 실제로는 path이후부터의 문자열만 있음.
URL에 따라서 다른 응답을 주도록 코드를 수정
const http = require('http');
users = ['Tom', 'Andy', 'Jessica', 'Paul'];
let server = http.createServer(function (request, response) {
if (request.url === '/') { // '직접 입력' 또는 '호스트부분만 입력'
response.end('<h1>Welcome!</h1>'); // 메인 페이지인것처럼
} else if (request.url === '/users') { // /users 입력
response.end('<h1>' + users + '</h1>');
} else { // 나머지 path
response.end('<h1>Page Not Available</h1>');
}
});
server.listen(3000);
http 모듈로 라우팅할 때의 불편함
split 메소드를 활용하여 나눌 수 있음.
console.log('/users/1'.split('/'))
// [ '', 'users', '1' ]
내장된 http 모듈을 사용하여 간단한 Node.js HTTP 서버를 생성
const http = require('http');
users = ['Tom', 'Andy', 'Jessica', 'Paul'];
/*
users/1 = Tom
users/2 = Andy
이런식으로 회원 이름이 응답되도록 함
*/
let server = http.createServer(function (request, response) {
if (request.url === '/') {
response.end('<h1>Welcome!</h1>');
} else if (request.url === '/users') {
response.end('<h1>' + users + '</h1>');
} else if (request.url.split('/')[1] === 'users') {
// url: /users/1, /users/2, ...
let userIdx = request.url.split('/')[2];
let userName = users[userIdx - 1];
response.end('<h1>' + userName + '</h1>');
} else {
response.end('<h1>Page Not Available</h1>');
}
});
server.listen(3000);
권장되는 스타일의 코드로 개선해보기
const http = require('http'); // etc
const users = ['Tom', 'Andy', 'Jessica', 'Paul']; // const
const server = http.createServer((request, response) => { // Arrow Function, const
if (request.url === '/') {
response.end('<h1>Welcome!</h1>');
} else if (request.url === '/users') {
response.end(`<h1>${users}/h1>`); // Template String
} else if (request.url.split('/')[1] === 'users') {
// url : /users/1, /users/2, .. // etc
const userIdx = request.url.split('/')[2];
const userName = users[userIdx - 1]; // etc
response.end(`<h1>${userName}</h1>`); // Template String
} else {
response.end('<h1>Page Not Available</h1>');
}
});
server.listen(3000);
https://google.github.io/styleguide/jsguide.html
Google JavaScript Style Guide
Google JavaScript Style Guide 1 Introduction This document serves as the complete definition of Google’s coding standards for source code in the JavaScript programming language. A JavaScript source file is described as being in Google Style if and only i
google.github.io
express 모듈로 하는 더 세련된 라우팅
서드파티 모듈인 Express를 사용하면 더 간편하게 라우팅이 가능함.
express 모듈 설치
npm install express
express 모듈을 활용하여 요청에 따라 다른 응답을 보냄
const http = require('http');
const express = require('express');
const app = express();
const users = ['Tom', 'Andy', 'Jessica', 'Paul'];
app.get('/', (request, response) => {
response.end('<h1>Welcome!</h1>');
});
app.get('/users', (request, response) => {
response.end(`<h1>${users}</h1>`);
});
app.get('/users/:id', (request, response) => {
const userName = users[request.params.id - 1];
response.end(`<h1>${userName}</h1>`);
});
app.get('*', (request, response) => {
response.end('<h1>Page Not Available</h1>');
});
app.listen(3000);
app객체의 get메소드
· express로 만든 객체는 보통 app이라는 이름을 붙임
· app객체의 get메소드는 특정 path에 대해서 그 요청과 응답을 다루는 함수를 하나씩 설정
· 첫번째 인자 : '/' , 두번째 인자 : 콜백함수
→ 첫번째 인자가 들어올 때 두번째 인자인 함수가 실행됨.
app.get('/', (request, response) => {
response.end('<h1>Welcome!</h1>');
});
:id의 의미
· 'id'라는 문자열 의미 X
· 해당 위치에 오는 값을 id라는 속성에 담으라는 express만의 표기법임.
· request 객체의 params 객체의 id속성
http://127.0.0.1:3000/users/2
app.get('/users/:id', (request, response) => {
console.log(request.params);
//const userName = users[request.params.id - 1];
//response.end(`<h1>${userName}</h1>`);
});
* 의 의미
위에 나온 path의 경우를 제외한 모든 path를 의미함.
특성상 맨 마지막에 써야 함.
app.get('*', (request, response) => {
response.end('<h1>Page Not Available</h1>');
});
실무에서는 Express 같은 서드 파티 모듈을 사용해서 라우팅하는 것이 정석임.
서드파티 모듈과 npm 제대로 배우기
모듈이 파일 혹은 디렉토리인 이유
: Node.js에서 모듈이 검색되는 순서 때문임.
서드파티 모듈인 경우
경로표시 유무 판단하고, 없는 경우
→ '서드파티 모듈' or '코어모듈'로 판단
→ node_modules 디렉토리 내에 해당 파일이 있으면 로드, 아니면 디렉토리를 찾음
→ pakage.json 파일을 찾음
→ 'main 필드에 적힌 파일' or 'index.js 파일' 로드
서드파티 모듈은 'pakage.json'이라는 파일을 가진 디렉토리 형태로 존재함.
pakage.json 파일 내용 중 main 필드가 없으면 index.js 파일을 로드함.
package.json 파일
·node_modules디렉토리 안에 실제로 서드파티 모듈이 설치됨.
디렉토리 하나가 서드파티모듈 하나임.
서드파티모듈을 설치할 때 필요한 다른 서드파티 모듈(dependency)이 같이 설치됨.
dependency : 하나의 패키지가 의존하는 다른 패키지
서드파티모듈의 디렉토리를 살펴보면 pakage.json이 있음.
- pakage.json이라는 파일을 가진 디렉토리가 패키지다.
- 하나의 서드 파티 모듈은 하나의 패키지다.
- 서드 파티 모듈을 관리할 때 쓰는 npm은 node package manager의 줄임말이다.
package.json 필드의 의미
name | 패키지 이름 |
version | 패키지 버전 |
description | 패키지에 대한 설명, 검색에 반영됨. |
keywords | 패키지에 대한 키워드, 검색에 반영됨. |
homepage | 패키지 관련 커뮤니티 주소 |
bugs | 패키지 사용하다 발생하는 버그 신고할 수 있는 URL이나 이메일 |
license | 패키지 라이센스 |
author | 패키지를 만든 사람의 정보 |
contributors | 패키지를 만드는데 기여한 사람의 정보 |
main | require('패키지이름')을 로드했을 때 실제로 로드되는 파일 이름 목록 |
repository | 패키지 코드가 관리되고 있는 레포지토리 주소 |
scripts | npm으로 간편하게 실행할 수 있는 스크립트 파일들의 정보 길이가 긴 명령어를 즐겨찾기해두고 좀 더 편하게 호출하기 위해 사용하는 필드 "scripts" : { "test" : "실행할 커맨드 A" } npm run test |
dependencies | express 패키지가 필요로 하는 다른 패키지의 이름과 버전 정보 |
https://docs.npmjs.com/cli/v10/configuring-npm/package-json
package.json | npm Docs
Specifics of npm's package.json handling
docs.npmjs.com
Sementic Version과 Version Range Syntax
Sementic Version
dependencies 필드에 있는 각 패키지 이름 옆의 버전
Major Version . Minor Version . Patch Version
- 메이저 버전 : 이전 버전의 API와 호환되지 않는 API 상의 변화가 발생한 경우 (기존 API 삭제, 이름 변경 등)
- 마이너 버전 : 이전 버전의 API와 호환되는 API 상의 변화가 발생한 경우 (새로운 API추가)
- 패치 버전 : API에 변화를 주지 않는 범위 내에서 변화가 이루어진 경우 (코드 버그 해결 등)
Version Range Syntax
"codeit" : "2.3.1" | 정확히 2.3.1 버전 |
"codeit" : ">2.3.1" | 2.3.1보다 높은 버전 |
"codeit" : "2.3.1 || ≥2.5.0 <3.1.2" | 2.3.1 버전 또는 2.5.0 버전 이상이면서 3.1.2 버전 미만 |
"codeit" : "2.3.1 - 3.1.2" | 2.3.1 버전 이상 3.1.2 버전 이하 |
"codeit" : "2.3.1 - 3" | 2.3.1 버전 이상 4 미만 |
"codeit" : "*" | 어느 버전이든 상관없음 |
"codeit" : "3.x" | 3.0이상 4 미만 |
"codeit" : "3.1.x" | 3.1.0이상 3.2.0 미만 |
"codeit" : "~3.1.2" | 3.1.2 이상 3.2.0 미만 |
"codeit" : "~3" | 3.0.0 이상 4.0.0 미만 |
"codeit" : "^1.2.3" | 메이저버전 (1) 그대로인 범위 내에서의 업데이트만 허용 1.2.3 이상 2.0.0 미만 |
"codeit" : "^0.2.3" | 0.2.3 이상 0.3.0 미만 |
내 모듈을 패키지로 만들어보기
현재 디렉토리를 하나의 패키지로 만들때 쓰는 명령어
npm init
모든 필드의 값을 기본값으로 설정하고 싶은 경우
npm init -y
보통 다른 패키지들도 entry point에는 main.js를 씀.
test command : 코드를 테스트할 때 사용할 명령어를 지정
내 패키지를 npm 공개 저장소에 올려보기
npm 공식 홈페이지에 회원가입 후 로그인
npm login
현재 사용자 확인
npm whoami
npm 공개 저장소에 업로드
npm publish
[패키지 이름]@[버전] 형식으로 뜸.
패키지 버전 업데이트
npm version
npm publish
공개된 패키지 내리기
npm unpublish [패키지 이름]@[버전] // 특정 버전만
npm unpublish [패키지 이름] --force // 모든 버전
package.json과 package-lock.json의 차이
- package.json : 어떤 버전의 패키지들이 설치되어야 하는지 기록되어 있음
- package-lock.json : 실제로 설치된 패키지들의 정확한 버전이 기록되어 있음
패키지를 공유할 때는 보통 그 안의 node_modules 디렉토리를 제외하고 공유한다.
이때 패키지 안의 package.json 파일 내용 중 dependencies 필드의 정보가
공유받는 측에서 node_modules 디렉토리를 재생성(npm install)하는 데 사용되며
이때 공유해준 사람과 공유받은 사람 간에 node_modules 디렉토리 내부의 차이가 발생하지 않도록 방지하려면(완전히 똑같은 실행환경을 공유해야할 경우) package-lock.json 파일도 package.json 파일과 함께 공유해줘야 함.
패키지 간 의존 관계의 위험성
• 악성코드 문제
• 패키지 내 코드의 취약점
최신 버전의 패키지들이 보통 보안상 더 안전하기 때문에 npm outdated, npm update 정기적으로 실행하기
특정 패키지의 버전만 지정해서 업데이트할 수 있음.
npm update [패키지명]@[버전]
내 패키지 안에 설치된 패키지들 중 취약점 확인하기
npm audit
취약점 고치기
npm audit fix
아니면 More info에 있는 URL에 들어가기
• 패키지의 가용성(Availability) 문제
패키지가 갑자기 사라져버리거나 관리되지 않고 방치될 수도 있음.
nodemon 패키지를 전역 설치해보기
코드 수정할 때마다 서버 중지하고 브라우저 새로고침하는 일이 번거로움.
이런 경우 nodemon 패키지를 사용하여 작업의 효율성을 높일 수 있음.
nodemon 패키지 : 파일의 코드 변화를 알아서 감지해서 자동으로 재실행해주는 패키지
nodemon 패키지 전역 설치
npm install -g nodemon
-g : 글로벌 모드로 설치 (전역설치)
패키지를 하나의 실행파일처럼 사용할 수 있음
관리자 권한으로 설치
sudo npm install -g nodemon
비밀번호 : 컴퓨터 관리자 비밀번호
보안 오류 때문에 nodemon 설치 후 실행 불가능한 경우
Windows PowerShell을 관리자 권한으로 들어가서 로컬로 생성된 스크립트를 실행할 수 있도록 설정
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
nodemon 정상 실행됨.
파일 변화 생기면 main 모듈을 자동으로 재실행해줌.
새로고침하면 변화확인 가능함.
https://www.npmjs.com/package/nodemon
nodemon
Simple monitor script for use during development of a Node.js app.. Latest version: 3.0.3, last published: 6 days ago. Start using nodemon in your project by running `npm i nodemon`. There are 5093 other projects in the npm registry using nodemon.
www.npmjs.com
전역 설치의 원리
설치 방법
- local mode 설치 : node_modules 디렉토리에 설치
- global mode 설치 (전역 설치) : {prefix}/lib/node_modules에 설치
npm이 참조하는 설정값 확인
npm config list --json
전역 설치한 패키지도 require 함수로 로드할 수 있음.
const nodemon = require('C:\\Users\\airyt\\AppData\\Roaming\\npm\\node_modules\\nodemon');
node로 실행해야 한다는 의미
#!/usr/bin/env node
nodemon 실행
→ $PATH 변수 참조해서 /usr/local/bin/nodemon 파일 실행
→ 원본 파일인 /user/local/lib/node_modules/nodemon.js을 실행
→ 가장 맨 윗 줄의 #!/usr/bin/env node를 확인하고
시스템이 자동으로 node /user/local/lib/node_modules/nodemon.js 실행
그밖의 npm 명령어
express라는 단어가 이름에 있거나 설명, 검색 키워드에 있는 패키지들이 전부 출력됨.
npm search express
해당 패키지의 정보가 출력됨
npm info express
내 패키지가 의존하고 있는 다른 패키지 확인
npm list
의존하고 있는 패키지 삭제
cat package.json
npm uninstall (패키지명)
공식 홈페이지에서 패키지에 대한 내용 검색 가능함.
npm | Home
Bring the best of open source to you, your team, and your company Relied upon by more than 17 million developers worldwide, npm is committed to making JavaScript development elegant, productive, and safe. The free npm Registry has become the center of Java
www.npmjs.com
npm의 중요성과 Yarn
프론트엔드 개발 작업과 도구
testing 작업 | 코드가 잘 작동하는지를 검사 | Mocha |
code formatting 작업 | 자바스크립트 코드가 가독성 좋은 포맷으로 잘 작성되었는지를 검사하고 수정 | ESLint |
transpiling 작업 | 작성한 자바스크립트 코드가 자바스크립트 최신 표준을 지원하지 않는, 오래된 브라우저(특히, 인터넷 익스플로러 등)에서도 문제없이 동작할 수 있도록 변환 자바스크립트의 단점을 보완한 언어(Typescript 등)로 작성한 코드를 다시 자바스크립트로 변환 |
Babel |
bundling 작업 | 여러 자바스크립트 파일들과 CSS 파일 등을 하나의 파일로 묶는 번들링 작업 | Webpack |
minifying 작업 | 번들링된 결과를 더 작은 용량으로 압축해주는 작업 | Uglify-JS |
Task Runner | 이런 작업들을 한 번에 자동으로 실행할 수 있도록 설정하는 작업 | Gulp |
Yarn : 2016년 페이스북에서 출시한 패키지 관리 프로그램, npm의 느린 속도 보완하였음.
사용 전 설치가 필요함
npm install -g yarn
패키지 설치
yarn add [패키지명]
패키지 삭제
yarn remove [패키지명]
'코드잇 Codeit > Back-End' 카테고리의 다른 글
[코드잇] 관계형 데이터베이스를 활용한 자바스크립트 서버 만들기 (0) | 2024.06.25 |
---|---|
[코드잇] Express 기본기 - ② ORM으로 하는 데이터베이스 작업, 배포하기 (0) | 2024.02.01 |
[코드잇] Express 기본기 - ① Express 기본 익히기 (0) | 2024.01.23 |
[코드잇] Node.js 기본기 ① - Node.js 시작하기 및 기본 개념 (0) | 2024.01.22 |
[코드잇] SQL 데이터베이스 - 데이터베이스 모델링 (1) | 2023.05.24 |