끄적끄적

[VUE+TYPESCRIPT] Vuex 타입스크립환경 스토어 아키텍처 정리 본문

Front-end/Vue.js

[VUE+TYPESCRIPT] Vuex 타입스크립환경 스토어 아키텍처 정리

mashko 2021. 10. 29. 02:07
반응형

뷰에서 타입스크립트를 쓰다보면 스토어에 대한 타입정의가 애매할경우가 많다..
오늘은 뷰와 타입스크립트 환경에서 내가 쓰고 있는 아키텍처에 대해 정리해두려고 한다.

아무래도 호불호가 갈리는 스타일일수도 있겠다란 생각을 한다. 개인적으로는 현재 방식이 마음에 든다..
일단 개인환경은 vue, vuex, vuex-class, vue-property-decorator 를 쓰고있다.
먼저 스토어에 액션쪽에 있는 파일을 하나까보면 이렇게 되어 있다.

// HomeAction.ts
class HomeAction implements HomeActionImpl {
  [HomeType.GET_MOCK_LIST] = ({ commit }: { commit: Commit }, payload: MockListRequest): Promise<MockListResponse[]> => {
    return MockService.getMockList(payload).then((response) => {
      commit(HomeType.SET_MOCK_LIST, response);
      return response;
    });
  };
}
// HomeActionImpl.ts
type HomeActionImpl = Modify<
  HomeActionInterface,
  {
    [HomeType.GET_MOCK_LIST]({ commit }: { commit: Commit }, payload: MockListRequest): Promise<MockListResponse[]>;
  }
>;
// HomeActionInterface.ts
interface HomeActionInterface {
  [HomeType.GET_MOCK_LIST](payload: MockListRequest): Promise<MockListResponse[]>;
}
// HomeType.ts
enum HomeType {
  GET_MOCK_LIST = '/HOME/GET_MOCK_LIST',
  SET_MOCK_LIST = '/HOME/SET_MOCK_LIST'
}
// HomeState.ts
export default class HomeState implements RootState {
  mockList: MockListResponse[] = [];
}
// home/index.ts
const HomeStoreModule: StoreModule<HomeState, RootState> = {
  actions: { ...new HomeAction() },
  getters: { ...new HomeGetter() },
  mutations: { ...new HomeMutation() },
  state: new HomeState()
};
// stores/index.ts
const store: StoreOptions<RootState> = {
  plugins: debug ? [logger] : [],
  state: {
    version: '1.0.0' // a simple property
  },
  modules: {
    HomeStoreModule,
    TemplateStoreModule
  }
};

중간에 Impl라고 붙은 파일은 스토어에서 사용하는 메소드 타입을 두기위한 공간이다.
타입스크립트에서는 같은 메소드에 대한 타입정의를 다형성처럼 구현할 수 없다. 그래서 찾은 방법이다. Modify의 구조는 이렇다

export type Modify<T, R> = Omit<T, keyof R> & R;

이렇게 만들어두고 타입 인터페이스를 재정의하는 작업이 필요한때 가져다가 쓰고있다.
저렇게 만들어두고 어떻게 쓰느냐.. 방법은 같다 사실 그냥 모든 타입들에 대해 외워두고 정의하기 싫었던 거다.

export default class Home extends Vue {
  @Action(HomeType.GET_MOCK_LIST)
  private getMockList!: HomeActionInterface[HomeType.GET_MOCK_LIST];

  @Getter(HomeType.GET_MOCK_LIST)
  private readonly mockList!: HomeGetterInterface[HomeType.GET_MOCK_LIST];
}

이렇게 되면 타입을 굳이 다 외우지 않아도 된다.
처음에 만들땐 상당히 귀찮지만.. 어차피 한번 정의해서 사용할꺼 만들어 두면 나중이 편하다.
그리고 저렇게 정의해두면 액션을 만들때 자동완성으로 만들어 준다. 모든 Getter, Mutation도 마찬가지의 구조로 만들어두었더니 그 다음부턴 스토어에 대한 타입은 신경쓰지 않아도 된다.
자바와 타입스크립트를 같이 개발하다보면 확실히 타입스크립트가 더 어렵다 @..@...
타입 잘 찾아지나 확인해보면

리스트타입으로 잘 찾아서 추천해준다.. 굿

반응형
Comments