• private npm registry 구축 :: 마이구미
    Nodejs 2020. 3. 28. 00:41
    이 글은 "private npm registry" 를 의미하는 사내 npm 저장소를 다룬다.
    이를 위해 Verdaccio 를 이용하는데, 전반적인 이해와 사용 방법을 알아본다.
    본인은 실제로 우리가 사용하는 npm 에 대해 조금 더 알게 된 계기가 되었다.
    사내 npm 저장소를 구축할 일이 없어도 유용한 글이 될것이라 생각한다.
    Verdaccio - https://github.com/verdaccio/verdaccio

     

    private 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 에서 사용된 히스토리를 참고해보면 좋을 것이다.

    https://github.com/facebook/create-react-app/compare/99c14e710ffb01d1c4a1124fc3ed2172bf58afbd...1098a4a177521f06febb1fcf7da94791febb19ba

     

    여기서부터는 사용 방법에 대해 알아본다.

     

    $ 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 adduser --registry http://localhost:4873

     

    이건 실제 npm 서버를 사용하는 것과 동일하다.

    다만, 사용자를 등록할 서버의 경로만 다시 설정해준 것이다.

    Username, Password, Email 을 등록하면 "~ logged in ~" 로그를 확인할 수 있다.

    위에서 언급한대로 htpasswd 파일을 열어보면 관련 데이터가 들어가있는 모습을 볼 수 있다.

    혹시나 로그인된 상태를 확인해보고 싶으면 npm whoami 로 확인할 수 있다.

     

    $ npm whoami --registry http://localhost:4873
    $ npm login --registry http://localhost:4873 // 로그인
    $ npm logout --registry http://localhost:4873 // 로그아웃

     

    이제 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 publish --registry http://localhost:4873

     

    성공적으로 완료되었다면, 관련 패키지를 볼 수 있을 것이다.

    이로써, 패키지는 원하는 곳에서 npm install 을 통해 내려받을 수 있다.

     

     npm install --registry http://localhost:4873 @tistory/module1

     

    권한이 $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: -1

     

    max_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/module1

     

    prefix 은 단순히 가독성뿐만 아니라 이러한 방식으로 편의성을 높혀줄 수 있다.

    이로써, 사용자는 혼란 없이 사용할 수 있게 된다.

     

    댓글 1

    • dayrain 2020.08.05 11:37

      안녕하세요, 제 환경에선
      $ npm config set @tistory:registry http://localhost:4873 명령 전에
      $ npm login --registry=http://localhost:4873 --scope=@tistory 명령으로 계정 설정을 해줘야 prefix가 올바르게 작동하더군요.
      혹시 저처럼 헤매시는분들 있을까봐 댓글로 남깁니다.

Designed by Tistory.