# 아키텍처 가이드

# API 호출 및 상태관리

  • 기본적으로는 MVVM 형태
  • api는 rest 서버 호출을 캡슐화 합니다.
  • store는 ViewModel에 해당하며 클라이언트의 비지니스 로직을 캡슐화 합니다.

# rest.js

api 호출의 공통적인 처리 루틴을 라이브러리로 만든 것입니다.

import axios from "axios";
import {useMainStore} from '@/store/main'
import {useEtcStore} from '@/store/etc'
import errorLog from "./errorLog";

const mainStore = useMainStore();
const etcStroe = useEtcStore();

const instance = axios.create({
    baseURL: process.env.VUE_APP_API_BASEURL,
});

instance.interceptors.request.use(function (config) {
    etcStroe.setLoading(true);

    if (mainStore.token !== null) {
        config["headers"] = {
            Authorization: `Bearer ${mainStore.token}`,
        };
    }
    return config;
});

instance.interceptors.response.use(
    function (response) {
        etcStroe.setLoading(false);
        return Promise.resolve(response);
    },

    function (error) {
        etcStroe.setLoading(false);
        errorLog.sendMessage(0, JSON.stringify(error));
        return Promise.reject(error);
    }
);

export default instance;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  • 14, 26, 31: API 호출 후 응답이 늦어지면 로딩 중 아이콘 표시하기
  • 16-20: 토큰 정보가 있으면 헤더에 자동으로 포함 시켜서 전송하기
  • 32: 에러가 발생하면 에러 로그 서버로 메시지 자동으로 전송하기

# api

import rest from "@/utils/rest";

export default {
    async getPosts() {
        return rest.get("/posts");
    },
}
1
2
3
4
5
6
7

# store

import { defineStore } from "pinia";
import apiPost from "@/api/post";

export const usePostStore = defineStore("post",  {
    id: "post",

    state: () => ({
        posts: [],
    }),

    actions: {
        async fetchPosts() {
            try {
                const response = await apiPost.getPosts();
                this.posts = response.data;
            } catch (error) {
                this.posts = [];
            }
        }
    },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# view

<template>
    <div v-for="post in postStore.posts" :key="post.id">
        <PostDetailComponent :post="post" />
        <CommentComponent :post="post" />
    </div>
</template>

<script>
import { usePostStore } from '@/store/post'
import PostDetailComponent from '@/components/PostDetailComponent.vue'
import CommentComponent from '@/components/CommentComponent.vue'

export default {
    components: {
        PostDetailComponent,
        CommentComponent,
    },

    setup() {
        const postStore = usePostStore()
        return { postStore }
    },

    mounted() {
        this.postStore.fetchPosts()
    },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28