-
private npm registry 구축 :: 마이구미Nodejs 2020. 3. 28. 00:41반응형
이 글은 "private npm registry" 를 의미하는 사내 npm 저장소를 다룬다.
이를 위해 Verdaccio 를 이용하는데, 전반적인 이해와 사용 방법을 알아본다.
본인은 실제로 우리가 사용하는 npm 에 대해 조금 더 알게 된 계기가 되었다.
사내 npm 저장소를 구축할 일이 없어도 유용한 글이 될것이라 생각한다.
Verdaccio - https://github.com/verdaccio/verdaccioprivate npm registry 는 무엇인가?
우리는 현재 npm 을 통해 많은 모듈들을 이용한다.
npm 에서 많은 모듈을 우리는 그저 편하게 install 하여 사용하고 있다.
우리가 이렇게 사용할 수 있는 건, npm 은 public 하게 제공해주기 때문이다.
반대로 private 이라면, 의미 그대로 외부적으로 노출되지 않는 npm registry 를 뜻한다.
private npm registry 은 왜 필요한가?
정확히는 private package 를 원하는 것이다.
회사 사내에서 많은 프로젝트를 진행하다보면, 재사용할 수 있는 모듈이 많을 것이다.
팀 내부 또는 다른 팀에서도 충분히 사용할 수 있을거라 판단된다면, 많은 곳에서 쓰이길 바랄 것이다.
우리는 이러한 모듈들을 npm 에 통해 패키지화해서 공유할 수 있다.
하지만 보안상 외부에 노출하기 어려운 것들도 있고, 너무 오픈되어 있어 관리 이슈가 좋지 못하다.
이를 위해, 오직 본인이 속한 조직을 위한 npm registry 를 구축하는 것을 private npm registry 라고 할 수 있다.
private npm registry 은 어떻게 구축하는가?
역시나 이미 누군가 잘 만들어주셨다.
verdaccio 라는 것을 활용하면 된다.
이전에는 sinopia 를 많이 사용했고, 현재는 이를 기반으로 발전해온 verdaccio 를 사용한다.
우리가 아는 create-react-app, storybook, angluar cli, babel 등 많은 곳에서 이를 활용하고 있다.
하지만 이들이 사용하는 목적은 완전히 private npm 을 위함은 아니다.
즉, verdaccio 또한 이를 위해서만 존재하는 것은 아니다.
유스케이스 중 private npm 을 포함하고 있을 뿐이다.
문서에서 명시된 이점은 다음과 같다.
- Use private packages
- Cache npmjs.org registry
- Link multiple registries
- Override public packages
- E2E Testing
간략히 설명하겠고, 자세한 건 공식 문서를 참고하길 바란다.
Use private packages
위에서 언급한 내용이자 이 글의 주제이다.
Cache npmjs.org registry
만약 npmjs.org 서버가 느리거나, 죽게 되면 어떻게 될까?
이러한 이슈를 방지하기 위해 미리 필요한 패키지들을 캐시하여 대비할 수 있다.
Link multiple registries
하나의 프로젝트에서 여러 개의 registry 의 모듈을 가져올 수 있다.
verdaccio 에서 제공하는 기능인 uplinks 를 참고하면 된다.
Override public packages
본인의 프로젝트에 오픈 소스를 사용하고 있었는데, 버그를 발견하여 PR 를 날렸지만 승인되지 않거나 지연되고 있을 경우가 존재한다.
이러한 경우 본인이 구축한 npm 서버에 반영된 코드를 올려놓고 사용할 수 있다.
E2E Testing
여기서 E2E 테스트는 publish 하는 패키지들에 대해 체크를 의미한다. *publish - npm 서버에 업로드 하는 행위
local npm registry 를 통해 publish 를 시뮬레이션 할 수 있다.
위에서 언급한 create-react-app, storybook 등에서 사용하고 있는 방식이다.
CRA 에서 사용된 히스토리를 참고해보면 좋을 것이다.
여기서부터는 사용 방법에 대해 알아본다.
$ npm install -g verdaccio
로컬에서 global 로 설치한 후, verdaccio 명령어를 실행하면 된다.
로컬 서버가 실행되는 것을 볼 수 있다.
http://localhost:4873 으로 접속하면 아래와 같은 페이지가 보여진다.
그리고 다음과 같은 로그를 확인할 수 있다.
warn --- config file - /Users/mygumi/.config/verdaccio/config.yaml
warn --- Verdaccio started
warn --- Plugin successfully loaded: verdaccio-htpasswd
warn --- Plugin successfully loaded: verdaccio-audit
warn --- http address - http://localhost:4873/ - verdaccio/4.5.1우선 주의깊게 봐야하는 건 2가지이다.
- config.yaml
- verdaccio-htpasswd
우선 config.yaml 은 verdaccio 의 전반적인 설정 파일이다.
우리가 원하는 기능의 대부분은 config.yaml 파일을 통해 제공되어진다.
파일을 확인해보면 디폴트값은 대략 다음과 같다.
storage: ./storage
auth:
htpasswd:
file: ./htpasswd
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
..........더 길지만 여기서 언급하거나 다룰 것들만 설명한다.
storage
publish 되는 패키지들 존재하는 디렉토리가 된다.
즉, 모든 패키지들은 ./storage 경로에 저장되는 것이다.
직접 publish 하고 저 경로를 확인해보면, 새로 추가된 것을 확인할 수 있다.
만약 폴더를 삭제하면, local npm 에도 사라지게 된다.
auth
사용자 인증에 대한 데이터를 의미한다.
verdaccio 는 기본 인증을 htpasswd 기반으로 한다.
관련된 데이터 파일이 ./htpasswd 에 저장된다는 것을 의미한다.
실제로 사용자 등록을 하면 username 과 암호화된 패스워드가 파일에 추가된다.
아래에서 확인해볼 것이다.
uplinks
유스케이스에서도 언급했었다.
디폴트 값은 실제 npmjs.org 서버로써, 만약 npm install 하는 패키지가 local npm 에 없다면, npmjs.org 에서 내려받게 된다.
packages
각 패키지들에 대한 권한을 부여한다.
'@*/*' 는 verdaccio 에서 private 패키지에는 prefix 를 @ 로 권장한다. ex) @samsung/module, @tistory/module1
@ 로 시작되는 패키지는 접근은 누구나 가능하다는 것이고, publish 의 경우에는 인증된 사용자만이 가능하다는 의미이다.
*prefix 를 활용해야하는 이점과 인증된 사용자에 대해서는 아래에서 계속 설명할 것이다.
우선 하나의 패키지를 publish 해보자.
위에서 언급했듯이, 만약 패키지 권한이 $authenticated 라면 인증이 필요하다.
인증을 위해 사용자 등록을 해야한다.
npm adduser 명령어를 통해 할 수 있다.
이건 실제 npm 서버를 사용하는 것과 동일하다.
다만, 사용자를 등록할 서버의 경로만 다시 설정해준 것이다.
Username, Password, Email 을 등록하면 "~ logged in ~" 로그를 확인할 수 있다.
위에서 언급한대로 htpasswd 파일을 열어보면 관련 데이터가 들어가있는 모습을 볼 수 있다.
혹시나 로그인된 상태를 확인해보고 싶으면 npm whoami 로 확인할 수 있다.
이제 publish 가 가능한 상태가 되었다.
publish 를 위해 빈 프로젝트에 index.js 와 package.json 을 생성한다.
// index.js console.log("Hi"); // package.json { "name": "@tistory/module1", "version": "1.0.0", "main": "index.js", "dependencies": {}, "devDependencies": {}, "keywords": [], "author": "mygumi", "license": "ISC", "description": "" }
그 후 npm publish 명령어를 통해 업로드한다.
성공적으로 완료되었다면, 관련 패키지를 볼 수 있을 것이다.
이로써, 패키지는 원하는 곳에서 npm install 을 통해 내려받을 수 있다.
권한이 $all 이라면, 누구나 install 할 수 있을 것이고, $authenticated 라면, 로그인을 해야한다.
여기까지 기본적인 기능들을 사용할 수 있다.
하지만 한가지 문제가 존재한다.
우리가 원하는 건 말 그대로 Private 한 것이다.
하지만 사실 npm adduser 는 누구나 가능하다는 점이 private 하지않다.
결과적으로는 npm adduser 를 막아야한다.
이는 config.yaml 에서 제공해준다.
auth:
htpasswd:
file: ./htpasswd
# Maximum amount of users allowed to register, defaults to "+inf".
# You can set this to -1 to disable registration.
max_users: -1max_users 에 대해 주석처리를 풀고 값을 -1 로 지정해주면 된다.
그러면 서버는 npm adduser 는 요청을 거부하게 된다.
그리고 서버에 있는 htpasswd 파일에 직접 접근하는 방식으로 사용자 관리를 private 하게 할 수 있다.
자세한 건 다음 링크를 참고하면 된다. (https://hostingcanada.org/htpasswd-generator/)
마지막으로 private 패키지에는 prefix 를 권장하는 이유를 알아본다.
우리는 여지껏 npm 명령어에 --registry http://localhost:4873 를 같이 작성해야했다.
여러 개의 registry 를 사용한다면, npm 명령어에 --registry 옵션을 매번 경우에 따라, 다르게 지정해줘야한다.
이건 조금 번거러운 작업일 수도 있고, 사용자에게는 혼란을 줄 수 있다.
$ npm install react
$ npm install --registry http://localhost:4873 @tistory/module1이것을 쉽게 해결할 수 있는 방법이 prefix 이다.
prefix 를 통해 registry 를 암묵적으로 정하는 것이다.
@tistory/* 의 이름을 가진 패키지는 private npm 서버를 바라보는 것이고, 이외에는 실제 npm 을 바라본다고 가정한다.
그러면 우리는 npm config 명령어를 통해 registry 를 명시해줄 수 있다.
$ npm config set @tistory:registry http://localhost:4873
명령어를 입력하면 .npmrc 파일에 저장된다.
또는 아래와 같이 .npmrc 파일에 직접 셋팅해줄 수도 있다.
.npmrc
@tistory:registry=http://localhost:4873
이제는 여지껏 npm 명령어에서 --registry 를 명시한 거를 생략해도 된다.
@tistory 로 시작하는 패키지는 local private 서버를 바라보고, 이외에는 npmjs.org 서버를 바라보게 된다.
// before
$ npm install react
$ npm install --registry http://localhost:4873 @tistory/module1
// after
$ npm install react
$ npm install @tistory/module1prefix 은 단순히 가독성뿐만 아니라 이러한 방식으로 편의성을 높혀줄 수 있다.
이로써, 사용자는 혼란 없이 사용할 수 있게 된다.
반응형'Nodejs' 카테고리의 다른 글
Sequelize.js 에서 Class 도입하기 :: 마이구미 (0) 2018.01.01 일렉트론 자동 새로고침(Eletron reload) :: 마이구미 (0) 2017.12.16 Node.js vs Java 구조적 차이 :: 마이구미 (9) 2017.04.30 Ready check failed 오류 해결 [Redis] :: 마이구미 (2) 2017.03.23 async 모듈을 통한 비동기 제어 :: 마이구미 (0) 2017.03.18