1주일간 1개의 과제를 8명이서 진행했습니다. 하나의 홈페이지에서 로그인, 회원가입, 관리자 페이지를 만드는 것이 목표였고, 이 외에도 계정별 접근 가능한 페이지 허가 등 세부적인 사항들을 만들어야 했습니다. 이것은 그에 관한 리뷰입니다.
매일 오전 10시, 혹은 2시에 만나 진행상황, 앞으로 필요한 부분, 인원 분배를 했습니다. 먼저 해야 할 부분이 있었고, 나중에 해도 되는 부분이 있었기 때문에 그때마다 필요한 부분에 담당을 정해가며 처리했습니다. 저녁 7시마다 중간 점검을 하고 풀리지 않는 부분은 함께 고민하면서 속도가 더뎌지지 않도록 했습니다.
금요일 오전에 거의 모든 형태가 완성이 되었고, 마지막 날에는 모두가 모여 파일 구조, 내부 구조, 함수명 등등 많은 컨벤션들을 다시 맞추며 최대한 한 사람이 작업한 것처럼 보이도록 형태를 변경했습니다.
기능별 상세 페이지를 만들어 그때마다 어떤 값들이 들어오고 나가며, 처리되는지 기록을 남겼습니다. 이를 통해 나중에 유지보수를 할 때 근거자료가 될 수 있도록 했습니다.
여기에서 저는 관리자 페이지의 계정 리스트를 Pagination을 통해 불러오고, 검색기능을 통해 입력된 keyword에 맞춰 실시간으로 정보를 가져오도록 했습니다. 그리고 각 계정 별 Menu 권한을 설정하는 checkbox 로직을 구현해봤습니다.
또한 팀장으로서 회의주도와 일정 관리, 시간적, 인적 자원 배분을 통해 효율적인 프로젝트가 될 수 있도록 노력했습니다. 그리고 팀원 중에 로직이 잘 풀리지 않거나 아이디어가 떠오르지 않을 때, 계속해서 페어 프로그래밍을 진행하면서 문제를 해결해나갔습니다.
const getUserInfo = (pages, limit, searchWord) => {
const originalData = LOCAL_STORAGE.get('userData');
const filteredUserInfo = [];
const nonFilteredUserInfo = [];
const paginationInfo = [];
originalData?.map((user) => {
if (
user.userId.search(searchWord) >= 0 ||
user.name.search(searchWord) >= 0
) {
filteredUserInfo.push({
userId: user.userId,
password: user.password,
name: user.name,
age: user.age,
role: user.role,
address: user.address,
menubar: user.menubar,
creditCard: {
CVC: user.creditCard.CVC,
cardNumber: user.creditCard.cardNumber,
expired: user.creditCard.expired,
holderName: user.creditCard.holderName,
},
});
}
nonFilteredUserInfo.push({
userId: user.userId,
password: user.password,
name: user.name,
age: user.age,
role: user.role,
address: user.address,
menubar: user.menubar,
creditCard: {
CVC: user.creditCard.CVC,
cardNumber: user.creditCard.cardNumber,
expired: user.creditCard.expired,
holderName: user.creditCard.holderName,
},
});
return;
});
const data =
filteredUserInfo.length !== 0 ? filteredUserInfo : nonFilteredUserInfo;
const maxPage =
Math.ceil(data.length / limit) > 0 ? Math.ceil(data.length / limit) : 1;
data.map((user, idx) => {
if (idx >= (pages - 1) * limit && idx < pages * limit) {
paginationInfo.push({
userId: user.userId,
password: user.password,
name: user.name,
age: user.age,
role: user.role,
address: user.address,
menubar: user.menubar,
creditCard: {
CVC: user.creditCard.CVC,
cardNumber: user.creditCard.cardNumber,
expired: user.creditCard.expired,
holderName: user.creditCard.holderName,
},
});
}
return;
});
return { userData: paginationInfo, maxPage: maxPage };
};
keyword를 통해 검색을 한 후, 필터링 된 정보를 가지고 pagination을 진행했습니다. 한개의 응답마다 maxPage를 같이 보내서, 클라이언트 단에서 이 단어를 가지고 몇 페이지까지 볼 수 있는지 확인할 수 있도록 했습니다. keyword로 필터링하는 과정에서 else문을 넣었다면 filteredUserInfo 혹은 nonfilteredUserInfo 둘 중 한 곳에만 데이터를 처리하기 때문에 효율적인 면에서 더 낫지 않았을까 하는 생각도 듭니다.
로그인 버튼을 누를 때 어떤 로직을 통해야 로그인이 정상적으로 될 지, 이를 위해 token 발급은 언제 이루어져야 할 지, 아이디와 비밀번호는 언제 유효성 검사가 되어야 할 지 등등 로그인에서 이루어지는 로직을 함께 구상했습니다.
로그인 버튼을 누르면 정규 표현식을 통해 아이디와 비밀번보의 유효성 검사를 실시하고, 통과가 되면 userdb에 접근하여 회원가입 유무를 알아본 후, token(id, role)을 발급하여 전달하면 이를 localStorage에 저장하고 role에 따라 관리자 혹은 메인 페이지로 이동합니다. (여기서 token은 현재 db를 따로 사용하지 않아 localStorgage를 db처럼 사용하고 있어 이곳에 저장했습니다.)
홈페이지에는 로그인을 하거나 일정 role 이상이 되어야 보일 수 있는 페이지가 있을 수 있습니다. 1차적으로는 gnb에 페이지를 보이지 않거나 클릭을 닫아서 접근을 막을 수 있습니다. 하지만 주소를 통해 직접 접근을 할 때는 로직상으로 접근 권한을 제어할 필요가 있습니다.
이를 위해 Router에서 클라이언트가 인가된 대상인지 확인 후 검증이 된다면 페이지로 이동, 제한된 대상이라면 메인 페이지로 리다이렉트 시키는 방법으로 해결할 수 있습니다.
layout컴포넌트를 만들고, 이곳에 기본적인 css를 선언해서 다른 모든 Component의 최상단에 컴포넌트로 선언을 해주면 모든 양식이 그 틀 안에서 적용되게 됩니다.
이 때, ThemeProvider를 사용해서 styled-component를 통해 만들어지는 모든 컴포넌트에 적용하는 전역적인 값을 설정합니다.
이를 통해 협업 과정에서 화면의 틀이 무너지지 않고 일관적인 형태를 유지해 나갈 수 있게 됩니다.
협업을 하다보니 부족한 부분에 대해서 많이 배우게 됩니다. 프론트엔드를 시작한 지 얼마 안 된 저에게 다양한 곳에서 경험을 쌓고 온 동료들은 최고의 선생님이 되어주고 있습니다. 특히 css와 틀을 잡아가는 방법이 많은 도움이 되었습니다.
또한 42Seoul에서 많은 정보들을 Parsing하고 다양한 로직을 구현했던 시간들이 문제를 해결하는데 많은 도움이 되었습니다.
컨벤션을 맞추는 게 초반에 이뤄져야 했던 것이었지만 8명이 작업하는 것은 처음이어서 마지막에 모든 것이 완성되고 함께 수정했습니다. 이를 통해 앞으로의 과제에서는 이 컨벤션에 계속 맞추어 진행하거나, 각 팀마다 컨벤션을 새로 만들어나갈 수 있을 것 같습니다.
중간에 메뉴를 조절하는 기준이 role별로 할 것인지, 계정별로 할 것인지에 대해서 의견이 달라졌었고, 계정별로 바꾸는 것으로 최종 결정이 됐습니다. 처음에 정한 방향과 실제로 가능한 방향이 다를 수 있고, 소통과 고민을 통해 맞춰갈 수 있다는 경험을 얻었습니다.