반응형

package-lock.json은 왜 생성될까?


우리가 기존에 사용하는 package.json 만으로는 정보가 부족하기 때문입니다.

package.json 에서는 버전정보를 저장할 때 version range 를 사용합니다.

“내가 사용할 패키지의 버전은 1.2.7버전이다.” 라고 말하는 대신 “나는 1.2.7버전 이상의 패키지를 사용할거다.”처럼 말하는 방식인데요. (전자처럼 버전정보를 명시하는 것도 가능합니다.)

협업을 하기위해 같은 package.json 을 사용해 각자의 컴퓨터에 같은 패키지들을 설치해서 같은 개발환경을 구성하게됩니다.

하지만 몇가지 조건이 들어맞아버리는 불행한(..) 상황이 오게되면, 같은 package.json 을 사용해서 npm install 을 진행하더라도 서로 다른 node_modules를 생성하는 경우가 발생합니다.

  • npm의 버전이 다른 경우, npm의 알고리즘이 조금씩 다르기 때문에 서로 다른 node_modules 트리가 생성될 수 있습니다.
  • 콕찝어서 버전명을 명시하지않고 version range 를 사용하기 때문에, 새로운 버전의 패키지가 배포된 이후 설치를 진행할 경우 최신 버전으로 설치될 수 있습니다.
  • 내가 사용하고 있는 패키지가 의존하고 있는 패키지가 새로운 버전으로 배포되었을 경우, 다른 node_modules 트리가 생성될 수 있습니다.

 

첫번째 상황 같은 경우에는 협업하는 멤버들이 npm --version 으로 버전을 확인한 뒤, npm 버전을 일치시킨 후 작업하면 예방할 수 있는 상황입니다.

하지만 다른 상황들에서는 다음과같은 일들이 발생할 수 있습니다.

개발자1: 테스트가 계속 실패해.

개발자2: 어제 내가 테스트할 땐 잘 됐는데??

개발자1: 왜이러지..

.. 몇 시간 후

개발자1: 아직도 안돼..

개발자2: 뭐가 문제인 것 같아?

개발자1: range-parser문제인 것 같아.

개발자2: range-parser 버전 몇이야?

개발자1: 2.0.1

개발자2: 나랑 버전이 다르네; 오늘 아침에 새로운 버전으로 릴리즈되었나본데?

난감하죠.

이런 불행한 상황을 피해가기위해 태어난 것이 package-lock.json 입니다.

package.json 에는 "~3.3.8" 으로 적혀있지만, package-lock.json 에는 "3.3.16"으로 정확한 버전명이 적혀있습니다.

package-lock.json  node_modules 구조나 package.json 이 수정되고 생성될 때 당시 의존성에 대한 정확하고 구체적인 정보를 품고 자동으로 생성됩니다.

npm install 명령어를 입력하면 태어난다고 생각하면 되겠네요.

또한 package-lock.json 이 존재할 때에는 npm install 의 동작방식이 조금 변하는데요.

package.json 을 사용하여 node_modules 를 생성하지않고 package-lock.json 을 사용하여 node-modules 를 생성합니다.

정리를 해보자면, package-lock.json 은 개발자들이 동일한 node_module 트리를 생성해서 같은 의존성을 설치할 수 있도록 보장해주는 고마운 녀석이라고 할 수 있겠습니다.

결론은.

 package-lock.json 을 레포지토리에 같이 커밋하자. ”

 

포스팅 끝!

.

.

.

..을 내려고했지만 궁금했던 점.

 package.json  package-lock.json 으로 나눠둔 걸까요?


애초에 package.json 에 정확한 버전명을 적어놓으면 해결되는 문제 아닐까? 라는 의문점이 들어서 찾아봤습니다.

앞서 package.json 에서는 version range 를 사용한다고 했습니다.

version range 는 다음과 같이 사용하는데요.

  • 1.4.0: 정확하게 1.4.0버전
  • >1.4.0 : 넘버링이 1.4.0보다 큰 버전
  • <1.4.0: 넘버링이 1.4.0보다 작은 버전
  • >=1.4.0 : 넘버링이 1.4.0보다 크거나 같은 버전
  • <=1.4.0 : 넘버링이 1.4.0보다 작거나 같은 버전
  • 1.4.0 || >= 2.4.0 : 정확하게 1.4.0버전이거나, 넘버링이 2.4.0보다 같거나 큰 모든 버전

 

만약 package.json 에 패키지 버전을 콕 찝어 정해놓는다면,

프로젝트에서 사용하고 있는 패키지의 중요한 버그 수정이 이루어질 때 마다 프로젝트의 package.json 에 적혀있는 버전도 수정해주어야하기 때문입니다.

모든 크고 작은 패키지들의 릴리즈에대해 항상 추적하고 수정해야하는 엄청난 귀찮음과 수고스러움을 version range 가 해결해주고 있었습니다.

역시 괜히 이렇게 나눠둔 것이 아니었네요!

 

포스팅 끝!

.

.

.

을 내려고했지만 하나만 더.

npm ci 명령어


npm ci 는 npm@5.7.1 부터 지원되는 명령어입니다.

package-lock.json 이 존재하면 package.json 대신, package-lock.json 을 이용해서 패키지들을 설치하는 명령어입니다.

“아니 걍 npm install로 설치해도 package-lock.json있으면 lock으로 설치하는거 아닌가”

npm blog{:target=”_blank”} 에 따르면 node_modules 가 없으면, npm install 보다 npm ci  2배 이상 더 빠르다고 합니다.

오오..

그래서 저도 사용해봤는데요.

npm install 명령어로 설치

npm ci 명령어로 실행

작은 프로젝트임에도 설치 시간이 차이가 나네요.

production으로 빌드할때 node_modules가 항상 비워져있는 환경이라면, npm ci 명령어를 사용하는 것도 좋을 듯 합니다!

반응형
반응형
이 글은 "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 은 단순히 가독성뿐만 아니라 이러한 방식으로 편의성을 높혀줄 수 있다.

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



출처: https://mygumi.tistory.com/371 

반응형
반응형

JavaScript와 HTML, CSS등에 대해서는 일체 다루지 않는다.

기초지식은 다른 강의를 참조하도록 하라.

 

참고:

[Package]Bower(Front End Pacakage 관리) 설치

[Package]Vue.js

 

https://vuex.vuejs.org/kr/

http://vuejs.kr/update/2017/01/08/using-vue-with-vuex-vue-rotuer/

 

vue에서 vuex를 붙혀서 사용하는 방법은 여러분들도 이제 알았다.

조금 더 깔끔하게 사용하는 방식이 있는데 바로 핼퍼를 사용하는 것이다.

결합도를 조금 더 낮추는 효과가 있으며 전역을 사용하는 vuex를 좀 더 컴포넌트적인 관점으로 보게해준다.

그리고 마크업 관점에서 코드가 길어지는걸 대비할 수 있다.

 

이를 이용하는게 바로 helper들이고 vuex map함수라고 부르는 경우도 있다.

뭐라고 부르건 여러분들의 마음이다.

 

helper 함수 종류

 

mapState - state를 연결해주는 함수

mapGetters - getters를 연결해주는 함수

mapMutations - mutations를 연결해주는 함수

mapActions - actions를 연결해주는 함수

 

엄청 당연한 말만 써놨는데 생각해 보니까 당연하다.

 

예제는 기존 코드를 변경하는 방식으로 진행할 생각이다.

 

https://github.com/justkukaro/vue-test-server/tree/master/testserver

ajax콜을 받는 백엔드 서버이다. 없으면 없는대로 진행해도 무리는 없다.

 

https://github.com/justkukaro/vue-test-server/tree/master/vuex-actions

이것이 저번까지 했던 helper를 쓰지 않는 코드이다.

 

https://github.com/justkukaro/vue-test-server/tree/master/vuex-helper

이 코드가 핼퍼를 사용하는 코드이다.

 

/* store.js */
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        count: 0,
        weight: 2,
        random: 0,
    },
    mutations: {
        increment(state) {
            state.count++;
        },
        decrement(state) {
            state.count--;
        },
        successGenerateRandomNumber(state, payload){
            state.random = payload.num;
        },
        failGenerateRandomNumber(/*state, payload*/){
            console.log('ERROR!');
        }
    },
    getters:{
        count(state, getters){
            return Math.pow(state.count, getters.weight);
        },
        weight(state, /*getters*/){
            return state.weight;
        },
        random(state, /*getters*/){
            return state.random;
        }
    },
    actions:{
        generateRandomNumber({commit, /*state*/}, /*payload*/) {
            axios.get(`http://localhost:4321/`)
                .then((res) => {
                    commit('successGenerateRandomNumber', res.data);
                })
                .catch((res) => {
                    commit('failGenerateRandomNumber', res);
                });
        }
    }
})

저번에 사용했던 store가 딱 적당한 예제인데 모든 부분이 조금씩 사용되고 있다.

 

<!--HelloWorld.vue-->
<template>
<div class="hello">
<b>count : {{$store.state.count}}</b><br>
<b>count^2 : {{$store.getters.count}}</b><br>
<b>random : {{$store.getters.random}}</b><br>
<input type="button" @click="increment()" value="increment"/>
<input type="button" @click="decrement()" value="decrement"/>
<input type="button" @click="randomNumber()" value="random"/>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data() {
return {}
},
created: function () {
},
methods: {
increment: function () {
this.$store.commit('increment')
},
decrement: function () {
this.$store.commit('decrement')
},
randomNumber: function () {
this.$store.dispatch('generateRandomNumber', /*100*/);
}
}
}
</script>

<style scoped>
</style>

모든 요소들을 사용하는 것을 볼 수 있다.

먼저 state부터 바꿔보자.

 

mapState

 

import {mapState} from 'vuex'

상단에는 당연히 위처럼 선언해준다.

 

computed: {
    ...mapState([
        'count'
    ])
}

mapState는 state를 끌어와서 사용할 수 있다.

만약 여러분이 적은게 store내에 존재하지 않다면 당연히 아무것도 출력하지 않는 빈문자열이 출력된다. === 아무것도 출력안됨.

이 state는 computed에 선언해주어야한다.

반드시 computed여야하는건 아니지만 권장된다.

 

<b>count : {{count}}</b><br>

그러면 여러분은 이렇게 사용할 수 있게 된다.

마크업적으로 훨씬 깔끔하게 되었다.

 

...mapState({
    cnt: 'count',
})

여러분은 무조건 배열만 써야하는것은 아니다.

만약 이름을 정하고 싶다면 object를 사용해도 무방하다.

 

<b>count : {{cnt}}</b><br>

당연하게 호출하는 방식도 바뀌게 된다.

 

mapGetters

 

...mapGetters({
    count: 'count'
}),

사용방식 역시 똑같다. 당연히 배열로도 사용가능하다.

 

computed: {
    ...mapState({
        cnt: 'count',
    }),
    ...mapGetters({
        count: 'count'
    }),
}

이 Getters는 computed에 선언해주어야한다.

반드시 computed여야하는건 아니지만 권장된다.

 

<b>count^2 : {{count}}</b><br>

위 처럼 사용할 수 있다.

 

mapMutations

 

increment: function () {
    this.$store.commit('increment')
},
decrement: function () {
    this.$store.commit('decrement')
},

이 두녀석을 통째로 바꿔보자.

 

import {mapState, mapGetters, mapMutations} from 'vuex'

일단 당연히 선두에 선언해줘야한다.

 

methods: {
    ...mapMutations({
        increment: 'increment',
        decrement: 'decrement'
    }),
    randomNumber: function () {
        this.$store.dispatch('generateRandomNumber', /*100*/);
    }
},

이 녀석들은 methods에 선언해줘야한다.

그리고 store에 있는 변수들과 연결시켜준다.

 

<input type="button" @click="increment()" value="increment"/>
<input type="button" @click="decrement()" value="decrement"/>

그러면 놀랍게도 함수가 직접 store와 연결된다.

이는 장점과 단점이 함께 있어서 필자생각에는 좀 주의를 요하긴 하는거 같다.

 

mapActions

 

randomNumber: function () {
    this.$store.dispatch('generateRandomNumber', /*100*/);
}

이번엔 이녀석을 바꿔보자.

 

import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'

이제 helper 4총사를 모두 선언하였다.

 

methods: {
    ...mapMutations({
        increment: 'increment',
        decrement: 'decrement'
    }),
    ...mapActions({
        randomNumber: 'generateRandomNumber'
    }),
},

이 녀석역시 methos에 선언해줘야한다.

 

<input type="button" @click="randomNumber()" value="random"/>

코드 하나 수정없이 직접 actions과 연결하였다.

 

helper의 사용유무의 장점과 단점

 

이 개념은 react포스팅 react-redux에도 똑같이 존재하는 개념이다.

물론 둘 다 써본 필자의 입장에서는 개념은 똑같지만 vuex가 좀더 세련되 보인다, 다만 큰 작업을 하거나 자유도 측면에서는 redux가 좀더 낫다.

 

다만 react-redux나 vuex helper같은 개념이 왜 필요하냐는 것이다.

사실 없이 쓰는 사람들도 굉장히 많다.

 

이를 이해하기위해서는 원자 디자인을 이해해야한다.

필자도 한번 포스팅 할 생각이고 필자가 포스팅을 완료하면 이 항목이 수정 될?수도 있을것이다.

그러나 아직 개념을 모르는 사람들이 있다면 이 포스팅을 보시면 도움이 될 것이다.

 

간단히 말하자면 모든 컴포넌트에는 data와 methods가 없고 외부만 존재하고 데이터는 store에서 처리한다는 개념이다.

즉 모든 데이터는 store에서 일괄처리한다는 것인데 아주 여러가지 단점과 아주 여러가지 장점을 함께 가진다.

그래서 뭐가 좋다라고 말하기는 힘들다. 그러니 여러분들은 알아보고 잘 생각해서 사용하는 것이 좋다.

 

출처: https://kamang-it.tistory.com/entry/Vue18vuex%EC%97%90%EC%84%9C-helper%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0mapState-mapMutations-mapActions-mapGetters

반응형
반응형

Vue.js의 Vuex Store 패턴에서 Vue.js Component에 Store를 바인딩 시키는 여러가지 방법을 알아보자. Vuex의 Store를 Component에 바인딩하는 방법에는 여러가지가 있으며 상황에 따라 그 쓰임이 다르다. 그 중에서 가장 실무에 적합하고 가독성이 좋은 방법이 무엇인지 알아보고 활용해보자.

해당 포스트에서는 Vuex의 설명과 사용법에 대해서는 언급하지 않았으며, 오로지 Vuex Store를 컴포넌트에 바인딩하는 방법을 설명한다.

프로젝트의 규모가 크거나 작든 Vuex를 사용할 때는 Store를 Module 별로 분리하는 것이 바람직하다. 그렇지 않으면 각 컴포넌트마다 바인딩 된 Store의 state들이 다른 컴포넌트의 루틴에 의해 오염될 가능성과 코드의 복잡성이 높아지게 되어 있다.

이번 포스트에서는 모듈별로 분리된 Store를 각 컴포넌트에서 효율적으로 바인딩시키는 여러 가지 방법들과 코드 스타일을 알아보자.

Basic

Vue 공식 API에서는 명시된 기본 Store 바인딩 방법이다.

 

위 내용은 mapState라는 Helper를 이용하여 객체의 형태로 count를 바인딩 한 형태이고 아래처럼 state의 이름을 그대로 상속받아 정의할 수도 있다.

 

기본적인 바인딩 방법은 가장 단순한 구조를 가진 Store를 바인딩하였을 때이다. 하지만 Store가 여러 모듈별로 분리되어 있고 하나의 컴포넌트에서는 여러 Store 모듈을 바인딩해야 한다면 매우 복잡해질 것이다.

아래 가정을 가지고 각 바인딩 Style을 살펴보자.

각각 User, Book 이라는 Store 모듈이 존재하고, User A/B 경로에 있으며, Book A/B/C 경로에 위치한다.

프로젝트 구조는 다음과 같다.

 

Style 1 - Vuex Helper

 

또는

 

특정 경로에 포함된 Store 모듈을 사용하기 위해서는 해당 경로를 모두 명시해줘야 한다. 이렇게 사용을 한다면 어느 경로에 있든 서로 다른 Store 모듈을 하나의 컴포넌트 또는 여러 컴포넌트에서 바인딩하여 사용이 가능하다. 하지만 위 예제에서 A/B/C의 단순하고 짧은 명칭이지만 폴더나 Store 모듈의 명칭이 꽤나 길다면 역시나 가독성이 좀 떨어질 것이다. 그래서 우리는 Vuex에서 제공하는 Namespace Helper를 생성할 수 있는 createNamespacedHelpers 이용하여 바인딩하는 것을 가장 인상적으로 볼 수 있다.

Style 2 - createNamespacedHelpers 1

 

또는

 

모듈의 이름이 길고 구조가 복잡하다면 createNamespacedHelpers를 사용하여 바인딩한다면 computed 또는 methods가 간결하고 뛰어난 가독성을 보이는 것을 알 수 있다.

Store 모듈들의 경로를 computed와 methods에 정의를 안 했을 뿐이지 무엇이 다르겠냐고 한다면 생각해보자. 우리는 개발을 하면서 코드를 살펴볼 때나 구현을 할 때 가장 상단에 삽입하거나 명시해 놓은 구현체는 자주 보지 않는다. 오히려 data, computed, methods를 가장 많이 볼 것이다. 이러한 상황에서 수많은 모듈의 경로가 명시되어 있다면 state나 mutation, action의 개체들을 찾기 어려울 것이다.

Style 3 - createNamespacedHelpers 2

그러면 여기서 좀 더 깊이 한번 보자.

만약 createNamespacedHelpers를 사용을 한다고 하지만 만약 하나의 컴포넌트에 서로 다른 경로에 있는 Store 모듈을 여러 개 바인딩할 경우에는 어떻게 해야 할까?
지금까지 Book이라는 모듈만을 가지고 예제를 보았지만, 여기에서 User 모듈을 추가해보자.

 

아래처럼 정의도 가능하다.

 

이렇게 한다면 하나의 컴포넌트에서도 많은 모듈을 바인딩하기가 쉬우며, 코드의 가독성 역시 좋아진다.


각 개발자마다 코드 스타일은 모두 다르고 해당 포스트에 언급한 내용 이외에 더 좋은 방법이 있을 수 있다. 다만 중요한 것은 개발하기 전 또는 하면서 어느 방법이 가장 좋은지 몸소 느끼며 차근차근 수정해 나아가는 것이 중요하다고 본다. 어느 스타일이든 결과는 같겠지만 업무/개발의 속도는 확연히 차이가 날 것이다.

 

출처: https://kdydesign.github.io/2019/04/06/vuejs-vuex-helper/

반응형

+ Recent posts