본문 바로가기
AI / DL/엘리스 SW 코딩 훈련 트랙

[SW 코딩 훈련] Node.js와 Express.js 03. NPM과 모듈

by bri9htstar 2022. 11. 24.

NPM(Node Package Manager)

Package는 어떤 노드, 코드들의 모음이다. Manager는 Package를 관리하는 툴이다. NPM은 Node.js 프로젝트를 관리하는 필수적인 도구라고 보면 된다. NPM은 온라인이 연결된 환경이라면 어디서든 사용할 수 있도록 온라인 저장소가 있고, cmd나 terminal 같은 커맨드라인 도구에서 이를 사용할 수 있다.

NPM 온라인 저장소는 수많은 오픈소스 라이브러리도구들이 업로드되는 저장소다. 이곳에서 필요한 라이브러리나 도구를 손쉽게 검색 가능하다. JS 한계를 넘은 Node.js의 특징 때문에, 웹이 아니라 다양한 분야에서 사용되기 때문에 Node.js의 인기로 거대한 생태계를 보유한다.

cmd나 terminal 같은 커맨드라인 도구는 프로젝트 관리를 위한 다양한 명령어를 제공한다.

 

  • 저장소에서 라이브러리, 도구 설치 : 온라인 환경을 Node.js 환경에서 다운 받아 사용한다.
  • 프로젝트 설정 / 관리 : 진행 중인 프로젝트를 설정을 바꾸고 추가하거나 삭제하는 것이 가능하다.
  • 프로젝트 의존성 관리 : 어떤 프로젝트 사이에 존재하는 의존성을 관리하기 위해 NPM에서 정리해준다.

NPM 사용해보기

NPM을 사용한다는 것은 NPM 커맨드라인 도구의 사용법을 익히는 것이다.

프로젝트 생성하기

$npm init

프로젝트 디렉터리를 생성하고, 해당 디렉터리 안에서 npm init 명령어를 사용하면 몇 번의 질문을 물어본다. 이 과정에서 package.json이라는 파일을 만들어 주고 이 디렉터리는 Node.js 프로젝트가 된다.

터미널이나 cmd에 $ npm init을 입력하면 자동으로 오른쪽과 같은 파일로 만든다.

package.json

생성되는 package.json은 프로젝트 관련 정보들이 저장되는 파일이다. 이 파일을 직접 수정하거나 npm 명령어를 사용하여 프로젝트 정보를 수정할 수 있다. 

package.json의 구성요소

의존성 관리하기

프로젝트 내에서 사용하는 라이브러리를 관리하는 방법이다. 프로젝트가 실행되기 위해 라이브러리에 의존하기 때문에 이러한 라이브러리들을 dependency(의존성)라고 이야기한다. 

 

라이브러리 : 특정 기능을 수행하는 코드의 묶음. 복잡한 기능을 직접 작성하지 않고, 다른 사람이 구현한 것을 사용하는 방법. Node.js에서는 패키지라고도 부름.

npm install 명령어

npm install 명령어를 통해 프로젝트 의존성(프로젝트에서 사용되는 모듈)을 관리할 수 있다. npm install 명령어는 사용 방법에 따라 여러 용도로 사용 가능하다. (npm i를 축약형으로 사용 가능)

 

  • 의존성 추가 : $npm install [package-name]

필요한 패키지를 프로젝트에 추가할 수 있다. 추가된 패키지는 package.json의 dependencies 안에 추가되며, node_modules 라는 이미 생성된 디렉터리에 저장된다.

 

  • 개발용 의존성 분리 : $npm install [package-name] --save-dev

npm은 개발용 의존성을 분리하여 관리할 수 있다. 개발용 의존성이란 배포 전까지만 사용하는 의존성을 말한다 (ex. 유닛 테스트 라이브러리). --save-dev 옵션을 이용하면 개발용 의존성을 추가할 수 있다. 개발용 의존성은 package.json의 devDependencies에 추가된다.

프로젝트에 의존성을 추가하면 package-lock.json이라는 파일이 생성되는데, 프로젝트에 의존성을 추가하면 자동으로 '^최신버전'으로 추가가 되는데, 의존성 버전이 갑자기 변경되지 않도록, 설치된 버전을 고정하는 역할을 한다.
npm install [package-name]@[version] 으로 패키지 버전을 지정할 수 있다.
Ex)
~1.13.0 - 1.13.x 버전 설치
^1.13.0 - 1.x.x 버전 설치, 가장 왼쪽이 0이 아닌 버전을 고정
0.13.0 - 0.13.0 버전만 설치

 

  • 의존성 내려받기 : $npm install

기본적으로 node_modules 디렉터리는 코드 관리나 배포 시에 업로드 하지 않는다. 의존성이 많아지면 용량이 너무 커지는 것과, 운영체제별로 실행되는 코드가 다른 경우가 존재하기 때문이다. npm install 명령어를 아무 옵션 없이 사용하면 package.json에 정의된 dependencies와 devDependencies의 의존성을 node_modules 디렉터리에 내려받는다. 이렇게 되면 기존에 설치가 되었다면 상관없지만 이 파일을 바탕으로 같은 node.js 프로젝트를 개발한다고 헀을 때 편리하게 의존성을 내려받을 수 있다.

개발용 의존성을 제외하고 내려받으려면 $npm install --production
프로젝트를 배포할 때에는 개발용 의존성을 같이 의존성을 같이 포함할 필요가 없다. package.json의 dependencies만 node_modules에 내려받는다.

 

  • 개발용 의존성 추가 
  • 전역 패키지 추가 : $npm install [package-name] --global

전역 패키지는 프로젝트에 종속되지 않는 모든 node.js를 개발하는 것들이다. 패키지를 전역 패키지 디렉터리에 내려받는다. 주로 프로젝트에 종속되지 않는 커맨드라인 도구들을 전역 패키지로 추가해서 사용한다. (Ex. express-generator, pm2)

 

  • 의존성 삭제하기 : $npm remove [package-name]

package.json의 dependencies와 devDependencies에서 삭제하고 node_modules에서도 삭제한다.

 

로컬 패키지와 전역 패키지

  • 로컬 패키지

package.json에 선언되어 있고(어떤 패키지에 종속되었다는 뜻), node_modules에 저장된 패키지이다. 이렇기 때문에 다른 프로젝트에서는 다른 로컬 패키지에 있는 것을 사용하긴 어렵다.

 

  • 전역 패키지

npm install -g 를 통해 내려받아, 전역 패키지 저장소에 저장된 패키지다.

 

전역 패키지도 프로젝트에서 불러 사용하는 것도 좋으나, 프로젝트의 의존성이 package.json 내에 명시적으로 선언돼있는 것이 프로젝트 관리의 좋은 방향이다. 프로젝트를 다른 곳에서 쓸 때 어떤 패키지가 필요한지 드러나있기 때문이다.

 

스크립트 실행하기 : npm run [script-name]

스크립트란 간단한 동작을 수행하는 코드인데, package.json의 scripts에 선언된 스크립트를 해당 명령어로 실행할 수 있다.

key를 입력하면 이에 대응하는 value가 나오게 된다.

npm script를 사용하는 이유는, npm script 내에선 의존성 패키지를 사용할 수 있기 때문이다. 이 말은 일일히 접근하는게 아니라 package.json 안에서 직접 자신에 근접한 의존성 패키지를 직접 사용할 수 있는 것이다.

쉽게 패키지를 접근할 수 있다.

npm 스크립트엔 run을 제외하고 사용할 수 있는 주요 스크립트들이 있다.

 

  • test : 코드 유닛 테스트 등에 사용
  • start : 프로젝트 실행
  • stop : 프로젝트 종료

run을 제외하고 사용할 수 있을 뿐, npm 내부적으로 코드를 제공해 주는 것은 아니다. 단지 npm은 package.json, node_modules에 있는 정보를 바탕으로 특정 명령만 수행해준다고 보면 된다.

 

NPM 요약

 

NPX

npm 패키지를 설치하고 않고 사용할 수 있게 해주는 도구이다. 기본적으로 npm에 패키지를 설치해야 사용할 수 있던 것은 당연하다. npx는 프로젝트에 추가하거나 전역 패키지로 추가하지 않고도 npx를 이용하여 바로 실행할 수 있게 해준다.

npx를 사용하면 Node.js의 특정 버전을 사용하여 js 파일을 실행할 수 있다. 프로젝트의 Node.js 버전 별 실행환경을 확인할 때 유용한다. 여러 컴퓨터에서 작업한다고 했을 때, 다양한 각각의 버전을 확인해볼 수 있다는 게 장점이다.

npx를 활용하면 github gist 코드를 실행할 수 있다. gist는 github에 등록된 간단한 코드다. npx를 이용하면 gist 코드를 다운받지 않고 바로 실행 가능하다. git이 설치되어 있어야 하며, 온라인상의 코드는 어떤 위험이 있을지 모르므로 코드를 잘 확인하고 실행해야 한다.

 

Node.js의 모듈

모듈은 코드를 분리하기 위한 방법이다. 간단한 프로그램이라면 파일 하나로도 가능하다. 프로젝트가 커지면 기능에 맞게 코드를 분리하는 것이 중요하다. 예를 들어 반복되는 기능을 모듈로 분리하여 사용할 수 있다.

앞서 말한 패키지는 모듈의 모음이기도 하다. npm 패키지들은 많은 모듈을 포함하고 있는 코드의 모음이다. Node.js는 다양한 모듈을 기본적으로 제공한다. 기본 제공 모듈은 직접 작성하기 매우 어렵거나 복잡한 로직을 포함한 모듈이 있으므로 자주 사용되는 기본 제공 모듈을 알아두는 것이 필요하다.

Node.js의 기본 제공 모듈 - console

console은 브라우저에서 제공되는 console과 유사한 디버깅 도구이다. 터미널 환경에서 console 모듈을 활용하면 어떤 출력 결과가 해당 터미널에 나타나게 된다. log, warn, error 함수로 로그 레벨을 구분해서 표시한다. time, timeLog, timeEnd 함수로 시간 추적도 가능하다

Node.js의 기본 제공 모듈 - process

process는 컴퓨터 상에서 실행하고 있는 프로그램의 단위라고 보면 된다. 현재 실행 프로세스 관련 기능을 제공한다. arch, argv, env 등 실행 환경 및 변수 관련 값을 제공한다. abort, kill, exit 등 프로세스 동작 관련 함수를 제공한다. 다시 말해 컴퓨터의 환경에 쉽게 접근할 수 있게 해주는 모듈이다.

Node.js의 기본 제공 모듈 - fs

파일 입출력을 하기 위해 사용한다. readFile, writeFile 함수로 JS 코드로 작성한 프로그램에서 나온 파일 읽기, 쓰기 작업을 진행할 수 있다. -Sync 함수 제공하여 동기 동작으로 사용하고, watch로 파일/디렉터리 변경 이벤트를 감지한다.

Node.js의 기본 제공 모듈 - http

http 서버, 클라이언트를 위해 사용한다. 웹브라우저에서 하는 역할을 대신한다고 볼 수 있다. createServer 함수로 버를 생성하고, Request 함수로 http 요청을 생성할 수 있다.

기타 기본제공 모듈. 필요할 때 찾아서 사용하면 된다.

 

모듈의 작성과 사용

모듈의 기본적인 작성법

elice 라는 파일이 불러와질 때, 무엇을 반환할 것인지를 미리 정해준다. 이 경우에는 객체 name, age, nationality를 반환한다. require 키워드는 elice가 불러졌을 때 student라는 객체에 반환값들이 들어가게 해준다.

모듈이 load 될 때 사용될 값을 module.exports로 내보낸다.

변수명으로 export 하는 모듈 작성법

export 키워드로 .name 등을 프로퍼티로 활용하여 elice 모듈을 불러올 수 있다.

모듈을 object로 만들고, 각 key - value를 지정해서 내보낸다. (exports.key= value; 꼴)

함수를 export하는 모듈 작성법

arrow를 활용하여 왼쪽에 매개변수, 오른쪽에 할 일을 중괄호로 지정해준다. return에 object를 적었다는 것은 적은 내용을 그대로 반환하겠다는 뜻이다. 그냥 호출하면 안 되고 매개변수를 위한 정보를 채워주고 반환해야한다.

모듈을 함수로 만들어서 모듈 사용 시에 값을 정할 수 있게 내보낸다.

모듈의 사용 방법 - require 동작의 이해

모듈은 require 함수를 통해 load 할 수 있다. C에서는 include, Java에서 import와 유사하다. 의존성 패키지, 직접 작성한 모듈 모두 사용 가능하다.

require 할 때 모듈 코드가 실행된다. Node.js 모듈은 첫 require 시에 cache(저장됨), 두 번 실행하진 않는다. 모듈 코드를 여러 번 실행하기 위해선 함수 모듈로 작성한다.

모듈의 사용 방법 - npm 패키지

의존성 패키지들은 require('package-name')로 load 할 수 있다. 패키지를 사용하려면 node_modules에 내려받아져 있어야 한다. 그렇지 않다면 npm.install 명령어를 통해 설치를 먼저 해줘야한다.

모듈의 사용 방법 - 직접 작성한 모듈

직접 작성한 모듈은 현재 파일과의 상대 디렉터리로 load한다. my-module이 .js 파일인 경우 해당 파일 load한다. my-module이 디렉터리인 경우 my-module/index.js 파일 load한다.

모듈의 사용 방법 - 함수형 모듈

함수형 모듈의 경우 load 했을 때 모듈이 바로 실행되지 않는다. 왜냐하면 이것은 함수를 선언만 했지 사용한다 명시하지 않았기 때문이다. 필요한 시점에 load된 함수를 실행하여 모듈을 사용할 수 있다.

모듈의 사용 방법 - json 파일

require로 json 파일도 load 가능한데, json 파일은 JS에서 object로 된 {key : value, …}와 같은 파일이다. 이것을 그대로 불러올 수 있다. 이 때 object type으로 자동파싱이 된다. text로 된 json 파일이 있다 했을 때, 이것을 json obejct 자료로 만들어준다.

모듈의 작성과 사용 요약

module.exports를 사용하여 모듈을 작성할 수 있다.

require를 사용하여 의존성 패키지, 모듈, json 파일을 사용할 수 있다.

모듈은 첫 require 시에만 실행하고 cache 되므로 여러 번 실행할 모듈은 함수형으로 작성해야 한다.


다음 지시사항에 맞게 코드를 수정합니다.
require 시 생략 가능한 부분은 전부 생략하도록 합니다.

  1. 같은 디렉터리에 있는 module1을 require 합니다.
  2. ./module2 디렉터리에 있는 index.js를 require 합니다.
  3. data.json 파일을 require 합니다.
  4. 함수형 모듈 funcModule을 require하고 사용해 봅니다.
const module1 = require("./module1");
const module2 = require("./module2/index.js");
const data = require('./data');
const funcModule = require('./funcModule');

console.log(
    module1,
    module2,
    data.name,
    /* funcModule 사용 */
    funcModule()
);

2번째 줄에서 require("./module2") 라고 해야 통과가 된다. 왜일까?

댓글