[근황]
프로젝트의 기능 구현도 마무리 되어가고 인턴 생활의 끝이 다가오면서 남은 연차를 소진하여 일본으로 2박3일 여행을 다녀왔다. 자유로운 회사 분위기 덕분에 눈치 안 보고 제대로 푹 쉬고 왔다! 인턴을 시작하고 월급을 받아 별다른 것을 사지는 않고 항상 모아두고 있었는데, 모아둔 돈으로 이번에 여행 다녀오며 먹을 것과 옷 사는 것에 탕진해서 다시 통장 잔고는 텅장으로 돌아왔다. 그래도 인턴쉽 기간 동안 주말에도 쉼 없이 공부를 해왔는데 덕분에 잠시 개발은 멈추고 확실히 리프레시 할 수 있었다.
[관리자 별로 메뉴 권한 부여하기]
관리자 페이지 리뉴얼 프로젝트 개발을 하면서 중요한 기능 중 하나가 바로 관리자별로 각각 다른 메뉴 접근 권한을 부여하는 것이었다. 메뉴와 관리자 모델은 이미 생성이 되어있는 상태이므로, 두 모델 간의 관계를 어떻게 정의를 할 것인지가 중요했다. 우선 DB 관계를 정의하기 전 요구사항 먼저 파악하는 것이 중요했다.
기능의 요구사항은 다음과 같았다.
1. 관리자의 권한에 따라 접근할 수 있는 메뉴가 다르다.
2. 하나의 관리자가 여러개 의 메뉴에 대해 접근 권한을 가질 수 있으며, 한 메뉴에 대한 접근 권한을
여러 명이 가질 수 있다.
관리자가 다수의 메뉴에 접근할 수 있으며 반대로 하나의 메뉴에 여러 사용자가 접근 가능함을 고려하면 M:N의 관계로 표현하는 것이 적절해 보였다. 이를 구현하기 위해선 맵핑 테이블이 필요했는데 이를 위해 UserMenuPermission 모델을 생성하였다. 이 모델은 각각의 사용자와 메뉴를 연결해 주어 메뉴 접근 권한을 관리자별로 부여할 수 있게 해준다. 이런 방식을 이용하면 사용자나 메뉴가 추가/변경/삭제 되더라도 UserMenuPermission을 업데이트 함으로써 쉽게 권한을 조정할 수 있게 된다.
그렇다면 관리자 별로 메뉴 권한을 부여한 뒤 이것을 어떻게 접근 제어할까?
이 문제는 DRF(Django Rest Framework)의 Permissions을 활용함으로써 간단히 해결할 수 있었다. DRF의 권한 시스템은 view가 시작되기 전에 먼저 요청의 권한 여부를 확인하며 해당 접근 권한이 있으면 요청의 접근을 허용한다. 이는 API의 다른 부분들을 사용자에 따라 접근을 허용할지 거부할지 결정하는 기능을 제공한다. DRF에서 기본적으로 제공하는 Permissions들이 있지만 기본 기능만으로는 부족한 감이 있었다. 따라서 우리 프로젝트의 요구 사항에 맞게 Permissions를 커스텀하여 구현하였다.
[PrviateRouter 구현하기]
관리자 사이트의 경우 보안 때문에 로그인한 사용자만 페이지를 볼 수 있어야 한다. 맨 처음에는 굉장히 단순하게 생각했다.
1. 관리자 사이트에 접속한다.
2. 접속한 사용자의 로그인 상태를 체크한다.
3. 로그인 상태가 아니라면 , 로그인 페이지로 redirect 시킨다.
위와 같은 흐름으로 진행한다면 매우 간단하게 기능을 구현할 수 있을 거라고 생각했다.
그러나 해당 방식으로 구현을 하면, 위에 영상처럼 관리자 페이지가 렌더링 되는 문제가 발생하는 것을 확인할 수 있었다. 리뷰 시간에 이에 대해 질문을 하였는데 useEffect때문에 해당 문제가 발생한다는 것을 알게 되었다. 그 이후 공식문서를 확인해보니 useEffect의 동작 방식 때문에 생기는 문제였다.
useEffect의 경우, 렌더링이 끝난 이후에 함수가 동작하는데 이 때문에 로그인 상태를 확인하기 전 먼저 페이지 렌더링이 된 뒤 그 다음 로그인 상태를 확인 후 리디렉트 되는 거였다. 즉 다음과 같은 순서로 진행이 됐다.
접속 → 컴포넌트 렌더링 → useEffect에서 checkAuthenticationApi를 통해 권한 확인 → redirect
이는 보안에 문제가 될 수도 있고 쓸데없이 자원을 낭비하는 문제를 야기할 수도 있다. 따라서 인증된 사용자만 렌더링 된 화면을 볼 수 있도록 접근 제어를 따로 구현해 줘야 했다.
이를 위해 별도의 PrivateRouter 컴포넌트를 만든 뒤 로그인 상태를 확인한 후 페이지를 렌더링 할 수 있도록 구현했다.
PrivateRoute 컴포넌트는 ContextAPI을 통해 저장되어 있는 loginState에서 로그인 여부를 확인한 후 로그인되어있지 않은 상태라면 로그인 페이지로 리디렉션을, 로그인 상태라면 자식 컴포넌트를 렌더링 할 수 있도록 구현했다.
자식 컴포넌트를 PrivateRoute로 싸면 된다.
[약 4개월간의 인턴생활을 돌아보며]
3월 2일 첫 출근이 너무나도 생생하게 기억난다. 사실 출근하기 전날 내가 제대로 인턴 생활을 마칠 수 있는지에 대한 걱정에 새벽까지 잠을 못 잤었다. 그래서 그런지 첫 출근 날 아침이 유독 쌀쌀하고 공기가 차갑게 느껴졌다. 하지만 인턴 생활 동안 데일리언 분들의 배려 덕분에 지금은 따뜻함으로 인턴 생활을 채울 수 있었던 것 같다. 특히 Kero님께서 많이 도와주셨으며 심지어 진로에 대한 상담도 흔쾌히 들어주셨다. 일하느라 바쁘셨을 텐데 진지하게 고민을 들어주시고 상담해 주셔서 너무 감사하다. 덕분에 방향성을 잡았을 뿐만 아니라 향후 어떤 서비스를 구현하고 싶다는 결심까지 생겨 내가 할 일은 그저 앞으로 나아가기만 하면 된다.
4개월 동안 너무 많은 것을 얻어만 가는 것 같아 염치가 없다는 생각을 했다. 이런 은혜를 어떻게 갚아야 하나 생각을 하다 문득, 예전에 해우님께서 전사스크럼 시간에 해주셨던 이야기가 기억이 났다. 약 2달 전이라서 정확하게 기억은 나지 않지만 데일리언들이 더 좋은 곳으로 이직을 해서 데일리 출신들이 일을 잘하더라 이런 얘기를 들으면 기분이 좋을거라고 말씀하셨던 것 같다. 나도 앞으로 누군가 나에게 개발을 잘하게 된 계기가 무엇이냐 물어본다면, 데일리펀딩에서의 인턴생활이 좋은 밑거름이 되었다고 말할 수 있도록 훌륭한 개발자가 되기 위한노력을 다짐하며 끝을 맺는다. 인턴일 뿐인 저에게 잘해주신 모든 데일리언분들에게 정말 감사드립니다 !!!