Home 잉여 프로젝트 개발 일지 - 3
포스트
취소

잉여 프로젝트 개발 일지 - 3

중간 점검

  • SideBar 추가

Untitled

Screen Shot 2022-03-14 at 8.20.14 PM.png

  • 복무 기간 페이지 (’/army’) 완성
    • vue-chart-3 사용
    • vue-chartjs를 사용하려 했으나 vue 3 를 지원하지 않는 관계로 feature가 적으나 호환이 되는 vue-chart-3를 선택

Untitled

  • 로그인 페이지 구현

Untitled

백엔드 개발

백엔드는 유일하게 사용할 줄 아는 django rest framework를 사용하기로 했다. 웹에서 새로운 걸 공부하기 위해 vue를 사용한 것과는 별개로 기존에 아는 것을 사용하기로 했는데 가장 큰 이유는 학습 곡선의 문제였다. 프론트가 html + js + css 의 큰 틀을 유지하면서 사용 방법만 차이가 있는 것과는 달리 백엔드 프레임워크들은 그 구성부터가 차이가 났기 때문이다. 따라서 새로운 프레임워크를 공부하며 개발을 하는 것 보다는 기존에 많이 사용해왔던 django를 사용하는 것이 더 효율적이라고 판단하였다.

가장 먼저 백엔드에서 진행했던 부분은 user 저장과 관련된 부분이었다. Username을 닉네임으로 사용하고자 했기 때문에 CustomUser을 만드는 방식을 채택했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.db import models
from django.utils import timezone

from .managers import CustomUserManager

class CustomUser(AbstractBaseUser, PermissionsMixin):
    user_id = models.CharField(max_length=30, unique=True, null=False)
    username = models.TextField(max_length=30, blank=False, unique=True)
    introduction = models.TextField(max_length=500, blank=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    date_joined = models.DateTimeField(default=timezone.now)

    USERNAME_FIELD = 'user_id'
    REQUIRED_FIELDS = ['username']

    objects = CustomUserManager()

    def __str__(self):
        return f'User {self.user_id}'

위와 같이 AbstractBaseUser을 상속해서 CustomUser 클래스를 생성해주고, admins.py, managers.py 등 여러 파일을 적절히 수정한 뒤, settings.py 에서

1
AUTH_USER_MODEL = 'user.CustomUser'

와 같이 설정해주었다.

유저 인증 방식은 Token Authentication 방식을 사용했다. 서버에서는 로그인 시, Response body에 token을 포함시켜서 response하면 되며, 클라이언트에서는 Request를 보낼 때 Header에 token을 포함시키는 방식으로 작동한다.

1
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

이후 적절히 views.py 를 건드려서 로그인과 회원가입을 완성시켜 주었다.

Frontend + Backend

이제 프론트엔드와 백엔드가 잘 연결되는지를 확인해볼 시간이다.

Proxy 설정

먼저 Vue 선에서 proxy를 설정해주어야 하는데 기본적으로 vue 개발 서버에서 request를 보낼 때, 따로 설정하지 않으면 localhost:8080으로 request를 보내게 된다. 우리의 백엔드 서버는 localhost:8000에서 돌아가고 있으므로 vue project의 최상단에 vue.config.js 파일을 만들어 다음과 같이 설정해주었다.

1
2
3
4
5
6
7
8
9
module.exports = {
  devServer: {
      proxy: {
          '/api': {
              target: 'http://127.0.0.1:8000'
          }
      }
  }
}

이와 같이 설정하면 클라이언트에서 api로 시작하는 요청이 localhost:8080이 아니라 localhost:8000으로 리다이렉트되어 요청된다.

axios

통신을 위해서 axios를 사용하였다. axios는 vuex와 연동하여 그 구조를 깔끔하게 만들어줄 수 있다.

vuex는 크게 state, getters, mutations, actions로 나눌 수 있다. 통신의 control flow를 글로 적어보면, 첫 번째로 Vue의 Component에서 actions 내의 async fuction(axios 포함)을 dispatch 한다. 이 async function은 axios를 활용하여 통신을 진행하게 되고, 그 결과를 가지고 mutation 내의 function을 commit 한다. 이후 mutation 내의 function이 state를 변경하게 되는 것이다.

실제 코드를 통해 간단하게 살펴보면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Login.vue
export default {
  name: 'Login',
  data() {
    return {
      userId: '',
      password: '',
    }
  },
  methods: {
    onClickLogin() {
      const userData = {
        user_id: this.userId,
        password: this.password,
      }
      this.$store.dispatch('user/login', userData)
    }
  }
}

onClickLogin에서 userIdpassword 정보를 userData로 묶어주고, dispatch를 통해 action을 불러온다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// store/user.js
const actions = {
  async login({ commit }, loginData) {
    axios.post('user/login/', loginData)
      .then((res) => {
        console.log(res.data);
        const userData = {
          user_id: res.data.user_id,
          username: res.data.username,
          introduction: res.data.introduction,
        }
        commit('updateUserData', userData);
        commit('updateAccessToken', res.data.token);
      })
  }
}

이후 action은 axios를 통해 post request를 백엔드에 보내게 되고, 받은 result를 가지고 local storage에 있는 userDataaccessToken을 갱신시키는 mutation을 commit을 통해 불러온다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store/user.js
const state = () => ({
  userData: {},
  accessToken: '',
})

const mutations = {
  updateUserData(state, userData) {
    state.userData = userData;
  },
  updateAccessToken(state, accessToken) {
    state.accessToken = accessToken;
  }
}

결과적으로 mutation이 state를 변경시키면서 login flow가 끝이 난다.

이후 이렇게 저장된 userDataaccessToken을 활용하여 원하는 기능을 구현하면 된다.

결과

Untitled

성공적으로 프론트엔드와 백엔드를 연결한 모습을 확인할 수 있다.

회원가입 페이지, 게시판 페이지 등 다양하게 할 일이 많이 남았다. 게시판부터 만든다고 해놓고 뭐가 이렇게 오래 걸리는지 모르겠다. 그래도 하나하나 새로운 것들을 배우며 진행하고 있기 때문에 큰 시간낭비라고 생각하진 않는다. 다음 게시물에선 진짜 게시판을 완성해야겠다…

이 게시물은 저작권자의 CC BY 4.0 라이센스를 따릅니다.

잉여 프로젝트 개발 일지 - 2

-