## 여기서 다루게 될 내용 - npm에 배포하는 법 - Lint, Prettier, Jest 등 배포 환경 구축하기 ## 다루지 않는 내용 - Typescript 문법 및 내용 - 자동 배포 환경 구축 - 테스트 코드 작성법 등 --- ## 기본 개념 ### NPM이란 무엇인가 npm(Node Package Manager)는 소프트웨어 저장소이자 해당 저장소에 등록된 라이브러리들을 설치 및 관리를 도와주는 도구이다. 여기서 Node란 Node.js를 뜻하는 말로 한마디로 자바스크립트로 작성된 소스들이 등록되어 있다. npm을 통해 필요한 라이브러리들을 설치하고 버전 관리를 할 수 있으며 작성된 소스를 npm 에 배포하여 다른 곳에서 다운 받아 사용할 수도 있다. npm 외에도 페이스북에서 개발한 yarn 이나 brew같은 패키지 관리 도구가 있으나 npm이 가장 대표적인 도구이다. 당연한 말이지만 npm에 패키지를 등록하기 위해서는 npm 과 Node.js가 설치되어 있어야 한다. Node.js가 설치되어 있지 않다면 [공식 사이트](https://nodejs.org/en/)에서 쉽게 설치할 수 있다. LTS는 안정화된 버전 Current는 최신 버전을 나타낸다. Node.js를 설치하면 npm은 같이 설치가 된다. npm이 설치되어있는지 확인하기 위해선 간단하게 버전 확인으로 할 수 있다. ``` shell $ npm -version ``` Node.js는 버전에 영향을 받으므로 배포 환경 등에서는 버전을 올리는 것에 대해서 안전하지 확인이 필요하지만 npm은 주기적으로 업데이트 하기를 권장한다. npm을 업데이트하는 방법은 간단하게 npm이 npm을 글로벌하게 설치해 주면 된다. ``` shell $ npm i -g npm ``` npm에 등록된 패키지를 설치하기 위해서는 아래와 같은 명령어로 설치를 할 수 있으며 관련 패키지를 관리하기 위해서는 `package.json` 파일이 필요하다. ``` shell $ npm i PACKAGE_NAME ``` `package.json`은 `npm init` 명령어로 생성 가능하며 초기에 관련된 정보를 입력해야 하는데 기본 값으로 넣고 싶다면 `-y`를 붙여주면 된다. ``` shell $ npm init -y ``` 이하 npm에 관련된 내용은 이미 알고있다고 가정하고 진행하도록 하겠다. npm에 패키지를 등록하려면 우선 로그인을 해야한다. ``` shell $ npm login ``` 가입이 되어있지 않다면 아래와 같이 명령을 통해 쉽게 가입할 수 있다. ``` shell $ npm adduser ``` ### Typescript 란 Typescript는 javascript의 superset으로 쉽게 말하자면 javascript에 타입을 적용한 언어라고 할 수 있다.(Typescript를 하나의 언어로 분류하는지에 대해서는 의견차이가 있는것 같다.) Typescript는 javascript를 한번더 감쌌기 때문에 당연히 브라우저에서는 인식을 할 수 없으므로 컴파일을 해주는 과정이 필요하다. 해당 과정을 통해 javascript 버전을 지정할 수 있어 babel 같은 도구를 사용하지 않아도 되는 장점이 있다. 또한 타입 명시로 인해 추후 유지보수나 코드 관리등이 용이하므로 많은 사랑을 받고 있는 언어이다. 타입스크립트로 배포하게 될 경우 자바스크립트 환경과 타입스크립트 환경 모두 사용가능하므로 점점 타입스크립트로 패키지를 배포하고 있는 추세이다. ---- ## #1 패키지 명 정하기 개발의 시작은 항상 이름을 정하는 것부터 이다. 이름을 정하는게 뭐가 중요한가 싶지만 본 프로그램의 기능을 잘 설명하는 이름을 정해야 사람들이 관련 라이브러리를 찾을때 유용할 것이라고 생각이 든다. npm은 유명한 도구인 만큼 이미 해당 저장소에는 약 120만개의 패키지들이 등록되어 있다.(2020년 05월 기준) 그만큼 프로젝트 명으로 생각하고 있는 이름은 이미 등록되어 있을 확률이 높다. 패지키명이 유효한지 확인하는 방법은 npm 공식 페이지에서 검색으로도 가능하지만 간단하게 해당 패키지 명으로 설치를 시도해 봄으로서 확인할 수 있다. 만약 404에러가 뜬다면 패키지명이 등록되어 있지 않은 것이니 안심하고 사용해도 된다 ``` shell $ npm i uzihoon-awesome-package npm ERR! code E404 npm ERR! 404 Not Found - GET https://registry.npmjs.org/uzihoon-awesome-package - Not found ``` 이름을 지정하고 나면 폴더를 생성해 준다. ``` shell $ mkdir uzihoon-awesome-package && cd uzihoon-awesome-package ``` ## #2 Git 설정하기 폴더를 생성하고 나면 코드 관리를 위해 git을 설정해 준다. 여기서는 Github으로 설정하도록 하겠다. ![](https://uzilog-upload.s3.ap-northeast-2.amazonaws.com/private/ap-northeast-2%3Ab6c10628-1f45-492c-a9eb-f54020bc8014/1590307170950-image.png) ``` shell echo "# uzihoon-awesome-pacakge" >> README.md git init git add README.md git commit -m "first commit" git remote add origin https://github.com/Uzihoon/uzihoon-awesome-pacakge.git git push -u origin master ``` ## #3 Package 설정하기 npm package 초기 설정을 해준다. ``` shell $ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help init` for definitive documentation on these fields and exactly what they do. Use `npm install ` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (uzihoon-awesome-package) version: (1.0.0) 0.0.1 description: awesome package entry point: (index.js) test command: git repository: keywords: author: uzihoon license: (ISC) MIT About to write to /Users/jiwoohong/study/uzihoon-awesome-package/package.json: { "name": "uzihoon-awesome-package", "version": "0.0.1", "description": "awesome package", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "uzihoon", "license": "MIT" } Is this OK? (yes) yes ``` 위의 과정을 생략하고 싶으면 `-y`를 붙여주면 된다. ``` shell $ npm init -y ``` ## #4 필요한 패키지 설치 및 설정하기 개발에 필요한 패키지 설치와 설정을 해준다. 이번 글에서는 타입스크립트를 기준으로 하기 때문에 우선 타입스크립트 관련 패키지를 설치한다. ``` shell $ npm i --save-dev typescript ``` `--save-dev`는 devDependecy로 설치된다. dependency와 devDependency의 차이점은 devDependency는 해당 패키지 개발에서만 필요한 파일로서 패키지를 배포한 후 사용자가 다운받을때는 같이 포함되지 않는다. 이는 빌드를 돌려서 어플리케이션을 배포할때도 마찬가지로서 개발에서만 필요한 파일과 배포에 포함되어야 할 파일을 분리해야 배포시 패키지의 용량을 줄일 수 있게 된다. 이제 개발에 도움을 주는 `prettier`와 `tslint`를 설치해 준다. ```shell $ npm i --save-dev prettier tslint tslint-config-prettier ``` 마지막으로 테스트를 위한 `jest`를 설치해준다. ```shell $ npm i --save-dev jest ts-jest @types/jest ``` 이제 개발에 필요한 패키지들을 설치하는 것은 모두 끝이났다! 이후 배포하고자 하는 패키지 개발에 필요한 모듈들이 추가로 있을 경우 설치하면 된다. 설치가 끝났으니 관련 설정들을 해줄 차례이다. 우선 git 배포하고싶지 않은 파일들을 `.gitignore`파일을 생성하여 설정해준다. ### .gitignore ``` shell # package node_modules # typescript compile /build ``` .npmignore은 npm 배포 시에 포함시키지 않을 폴더를 설정하는 파일이다. ### .npmignore ``` shell src tsconfig.json tslint.json .prettierrc ``` jest를 사용하기 위한 설정을 해준다. ### jestconfig.json ```json { "transform": { "^.+\\.(t|j)sx?$": "ts-jest" }, "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"] } ``` `tslint` 설정을 위한 `tslint.json`파일을 생성하고 아래와 같이 설정해 준다. ### tslint.json ``` json { "extends": ["tslint:recommended", "tslint-config-prettier"] } ``` `prettier` 설정은 아래와 같이 `.prettierrc`에 설정해 준다. ### .prettierrc ```json { "printWidth": 120, "trailingComma": "all", "singleQuote": true } ``` 가장 기본적인 설정만 해주었는데 별도로 탭 사이즈 같은 추가 문법 규칙을 설정하고 싶을 경우 여기서 설정하면 된다. 마지막으로 가장 중요한 타입스크립트 설정을 해준다. ### tsconfig.json ``` json { "compilerOptions": { "target": "es5", "module": "commonjs", "declaration": true, "outDir": "./build", "strict": true }, "include": ["src"], "exclude": ["node_modules", "**/__tests__/*"] } ``` typescript 설정은 타입스크립트가 컴파일 할때 필요한 설정들을 해주는 것이다. 우선 `compilerOptions`는 컴파일할때 필요한 문법 설정을 해주는 것이다. - `target`은 컴파일을 적용할 자바스크립트 문법을 설정한 것으로 ES5라고 설정할 경우 ES5 문법에 맞춰 컴파일 된다. 타입스크립트를 활용시 얻는 이점 중 하나로서 해당 문법에 맞춰서 컴파일이 되므로 바벨 같은 별도의 라이브러리를 사용할 필요가 없다. 기본값은 ES3 이고 최신 문법을 적용하고 싶을 경우 ESNEXT 값을 주면 된다. - `module`은 모듈 타입을 지정하는 것이다. 여기서는 `commonjs`로 지정하였다. - `declaration`은 패키지를 배포하고자 할때 필수로 필요한 설정이다. 해당 옵션은 `true`라고 할 경우 타입 정의 파일이 같이 빌드되어서 생성된다. 타입스크립트에서 패키지를 다운받아서 사용할 경우 타입이 정의되어 있어야 하므로 필수로 체크해야한다. - `outDir`은 빌드 후 생성되는 파일들을 저장할 폴더 이름이다. 여기서는 `build` 폴더에 빌드된 파일이 생성하도록 지정하였고, `.gitignore` 파일에서 해당 폴더는 git에 포함시키지 않도록 설정하였다. - `strict`는 `stric` 모드를 사용하지 설정하는 부분이다. - `include`는 빌드를 돌릴 타겟 폴더이며 여기서는 `src` 폴더에 있는 파일은 전부 포함시킨다고 설정했다. - `exclude`는 제외시킬 폴더로서 `node_modules`와 추후 생성할 테스트 폴더는 제외하였다. ## #5. 빌드 설정하기 개발 환경 셋팅이 끝났으면 이제 배포와 테스트에 필요한 설정들을 할 차례이다. 해당 설정들은 `package.json` 파일의 `scripts` 안에 설정해 준다. ### 빌드 설정 ``` json "build": "tsc" ``` 타입스크립트로 빌드를 돌리겠다는 뜻이며 `tsconfig.json`에서 설정한 대로 빌드가 실행된다. ### lint 설정 ```json "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", "lint": "tslint -p tsconfig.json" ``` 코드 포맷과 린트 설정을 적용해 준다. ### Test 설정 ```json "test": "jest --config jestconfig.json" ``` 테스트를 위한 명령어 설정이며 jestconfig.json에 설정을 적용하여 테스트를 실행한다. ### NPM 배포 스크립트 설정 이제 마지막으로 NPM에 배포할때 사용할 스크립트 명령들을 설정해 준다. ```json "prepare" : "npm run build" ``` `prepare`은 publish 되거나 로컬에서 `npm install`을 수행하기 전에 수행되는 명령어 이다. ```json "prepublishOnly" : "npm test && npm run lint" ``` `prepublishOnly`는 npm에 배포할때 사용하는 명령어 `npm publish`이전에 실행되는 명령으로 테스트와 린트를 수행 한 후 결과가 통과되면 배포하도록 설정하는 부분이다. ```json "preversion" : "npm run lint" ``` `preversion`은 패키지의 버전을 높이기 전에 수행되는 명령이다. 당연히 버전을 올리기 전 코드 를 한번 더 검사하고 진행하도록 한다. ```json "version" : "npm run format && git add -A src" ``` 위 `preversion`에서 수행한 `lint`가 통과되고 나면 수행되는 작업으로 git에 추가로 포함시키기 위한 작업이 들어있다. ```json "postversion" : "git push && git push --tags" ``` 마지막으로 git에 추가 및 태그 설정 작업이 들어간다. 해당 명령을 실행하고 github에서 확인을 해 보면 태그가 버전별로 추가되는 것을 확인할 수 있다. 최종적으로 완성된 package.json의 scripts 부분은 아래와 같다. ### package.json ```json "scripts": { "test": "jest --config jestconfig.json", "build": "tsc", "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", "lint": "tslint -p tsconfig.json", "prepare": "npm run build", "prepublishOnly": "npm test && npm run lint", "preversion": "npm run lint", "version": "npm run format && git add -A src", "postversion": "git push && git push --tags" } ``` `src` 폴더안에서 코드 작성과 테스트 코드를 작성하고 `npm publish` 명령을 수행하면 npm에 배포되는 것을 확인할 수 있다. ```shell npm publish ``` 최초로 배포된 이후 버전을 올리고 싶다면 버전 패치 명령을 날리고 `lint` 명령을 통과한 후 버전을 올라가는 것을 확인 할 수 있다. ```shell npm version patch ``` 이후 다시 publish 하면 된다. ```shell npm publish ``` ## 마무리 NPM에 모듈을 배포하는 작업은 흔히 하는 작업은 아니다. 오픈소스 코드를 배포하거나 사내망에서 사용할 패키지들을 배포하는 경우를 제외하고는 굳이 경험을 해보지는 않는 것 같다. 그러나 배포하는 과정이나 환경을 셋팅하는 작업등은 개발 환경과 유사하니 진행을 하면서 많은 도움이 되었다. 특히 `package.json`의 `scripts` 부분을 설정하는 것이 생각보다 다양한 명령어 들이 있고 prefix로 활용을 하면 자동배포 환경에서 작업 순서를 쉽게 셋팅할 수 있다는 장점이 있다. 패키지 배포는 [GeoKo](https://uzihoon.github.io/GeoKo/) 프로젝트를 수행하면서 경험하였고 이제 남은 것은 코드를 다듬고 테스트 작업을 추가 수행하는 것이다.