Vue Web API 디자인 패턴 (Repository Pattern) ver.2
Repository Pattren 이란?
비지니스 로직과 API로 데이터를 취득하는 부분을 분리 시키기 위한 디자인 패턴이다.
그리고 서버와의 통신(api request)을 하기위해 개발할 때 고민해야 할 사항들을 해결해 줄 수 있다.
- api 재사용? 매번 URL을 다시 적어야 하나?
- 엔드포인트가 바뀌었을 때는 어떻게 됩니까?
- 다른 프로젝트에서 API 호출 처리를 재사용하고 싶은 경우는 어떻게 됩니까?
- 코드를 리팩터하거나 Vux의 actions로 이동하는 경우는 어떻게 됩니까?
- 여러 개의 리소스가 있는데, 네 개의 다른 엔드포인트를 정의해야 합니까?
- 테스트를 mock의 엔드포인트를 어떻게 다룰 수 있습니까?
기존에 썼던 repository pattern에서 조금 더 수정해서 더 좋은 pratice가 나올 수 있는 방법을 적어보고자 한다.
repositories/posts/index.ts
posts의 Repository를 작성한다($axios는 나중에 plugin에서 주입받을것이다.)
import { NuxtAxiosInstance } from '@nuxtjs/axios';
const resource = '/posts';
export const PostsRepository = ($axios: NuxtAxiosInstance) => ({
get() {
return $axios.get(`${resource}?lastId=1&limit=10`);
},
});
repositories/index.ts
위에서 작성한 repo를 plugins에서 쉽게 주입받기 위해서 Factory를 작성해준다.
import { PostsRepository } from './posts';
export interface Repositories {
posts: typeof PostsRepository;
}
const repositories: Repositories = {
posts: PostsRepository,
};
export const RepositoryFactory = {
get: (key: keyof Repositories) => repositories[key],
};
plugins/axios.ts
이번 주제에서 조금 벗어나지만 axios의 기본설정은 이 플러그인에서 작성하면 좋을꺼 같다.
import { Plugin } from '@nuxt/types';
const baseURL = 'http://localhost:5000';
const initAxios: Plugin = ({ $axios }) => {
$axios.setBaseURL(baseURL);
$axios.onRequest(config => {
console.log(config);
});
$axios.onResponse(config => {
console.log(config);
});
$axios.onError(e => {
console.log(e.response);
});
};
export default initAxios;
plugins/repositories.ts
커스텀 플러그인이기 때문에 type을 declare merge로 정의해주고
해당하는 도메인의 repositories가 불리는 시점에서 repo를 생성해서 반환해주는 플러그인이다.
import { Plugin } from '@nuxt/types';
import { RepositoryFactory, Repositories } from '@/repositories';
declare module '@nuxt/types' {
interface NuxtAppOptions {
// root or this 부분
$repositories: Repositories;
}
interface Context {
// context 부분
$repositories: Repositories;
}
}
const initRepositories: Plugin = ({ $axios }, inject) => {
const repositories = (name: keyof Repositories) => {
return RepositoryFactory.get(name)($axios);
};
inject('repositories', repositories);
};
export default initRepositories;
nuxt.config.js
export default {
...
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: ['~/plugins/repositories', '~/plugins/axios'],
// axios
modules: ['@nuxtjs/axios'],
...
};
usage
components/sample.vue
export default defineComponent({
setup() {
const { $repositories } = useContext()
onMounted(async () => {
const result = await $repositories('posts').get()
console.log(result)
})
},
})
store/action.js
// Test
export const actions = {
async get_selections({ commit }) {
const res = await this.$repositories('posts').get()
console.log('action', res)
},
}
소감
또또, store에서 쓸 때 타입이 문제가 될꺼 같다.
vuex-module-decorator를 쓰는 사람들에게는 이전의 방법이 조금더 쉽게 타입스크립트를 쓸 수 있지 않을까 라는 생각이 든다.
https://heewon26.tistory.com/343
Vue Web API 디자인 패턴 (Repository Pattern)
Repository Pattren 이란? 비지니스 로직과 API로 데이터를 취득하는 부분을 분리 시키기 위한 디자인 패턴이다. 그리고 서버와의 통신(api request)을 하기위해 개발할 때 고민해야 할 사항들을 해결해
heewon26.tistory.com
참고한 곳
https://medium.com/js-dojo/consuming-apis-in-nuxt-using-the-repository-pattern-8a13ea57d520