최근에 팀장님이 도커를 이용한
자동 배포 로직을 만들고 보일러 플레이트를 제공하여 주셨습니다.
드디어 첫번째 구현시간이라
서버를 세팅하고 로그인, 회원가입 컨트롤러를 만들었습니다.
강의 공부에서 스택이 크게 변하지않았는데 고민할것이 많은거같습니다.
1. 라우팅 설계
처음에 팀원분이 만들어주신 라우터를 토대로
express에 get과 post를 처리하는 함수를 만들고 있었습니다.
그런데 팀원분이 이것은 임시로 만든 거라 단지 참고자료로 삼자고 했습니다.
rootRouter
/ -> Home
/join -> Join
/login -> Login
/logout -> Log Out
/search -> Search User
/accounting -> Accounting
userRouter
/user/upload -> Upload User
/user/edit -> Edit User
/user/remove -> Remove User
/user/attend -> User Attendance
/user/lockers -> User Lockers
programRouter
/program -> See Programs
/program/upload -> Upload programs
/program/edit -> Edit Programs
/program/remove -> Remove Programs
3. 유저 로그인유지 관리
브라우저가 로그인 상태를 유지하도록 하는 기능이 필요합니다.
유튜브 강의 코드에선 클라이언트 쪽 로그인 유저의 정보관리를
pug engine
이 제공해주는 res.locals
객체를 통해 했었습니다.
로그인 시 req.session
에 유저 정보를 저장하고res.locals
에 req.session
의 데이터를 옮겨줍니다.
이렇게 req.locals
의 프로퍼티에 정보를 삽입하는 미들웨어를
라우팅 전에 실행시켜 주면
해당 데이터들을 pug
에서 그냥 가져다 쓸 수 있습니다.
이해를 돕기 위한 유튜브 강의코드
// 1. 세션에 유저정보 저장
export const postLogin = async (req, res) => {
//중략.. 로그인성공
req.session.loggedIn = true;
req.session.user = user;
return res.redirect("/")
}
// 2. res.locals에 필요한 변수 저장
export const localsMiddleware = (req, res, next) => {
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.siteName = "NotThatShorts";
res.locals.loggedInUser = req.session.user || {};
next();
};
// server.js 에서 라우팅 전에 실행
app.use(localsMiddleware);
// 3. pug 엔진에서 해당 변수 사용
a(href=`/users/${loggedInUser._id}`) #{loggedInUser.username}
그런데 react 에선 저런 res.locals
가 없습니다.
일단 똑같이 로그인 시 req.session
에 유저정보를 저장하게 했습니다.
그리고 apiRouter
에 해당 정보를 요청받을 시 전송하는 코드도 만들었습니다.
// 세션에 유저정보 저장
const postTrainerLogin: customMiddleware = async (req, res) => {
//중략 로그인 성공
req.session.loggedIn = true;
req.session.user = user;
return;
}
// apiRouter 코드: 클라이언트 요청시 data 객체 전송
apiRouter.get('/data', (req, res) => {
const data = {
//@ts-ignore
loggedIn: Boolean(req.session.loggedIn),
//@ts-ignore
loggedInUser: req.session.user || {},
};
res.json(data);
});
// server.ts 코드
app.use("/api", apiRouter);
문제가 있다면, 페이지에서 로그인정보를 유지하려면
유저 정보를 포함하는 모든 컴포넌트가 전부다 /api/get
에 요청을 보내야 한다는 점입니다.
- 모든 컴포넌트가 아래의 코드를 가져야 한다면 엄청난 성능저하가 예상됩니다.
const [loggedIn, setLoggedIn] = useState("false");
const [user, setUser] = useState({});
const handleUserData = () => {
const response = await axios.get("/api/get")
const [loggedIn, user] = response.data;
setLoggedIn(loggedIn);
setUser(user)
}
- axios 함수는 잘 모릅니다. 일단 임시로 보여주기 위해 작성했습니다.
하지만 redux-store
에 정보를 저장하는 방식을 이용하면,
요청을 반복할 필요가 없다는 결론이 나왔습니다.
redux강의를 듣고 todo-list: redux 버전을 구현해 보아서 다행입니다.
3. csr + backend
저희는 express
로 백엔드 로직을 처리하고rendering
은 react-router-dom
으로 해주기로 했습니다.
// 백엔드 데이터 로직 처리하는 라우터들
app.use("/", rootRouter);
app.use("/api", apiRouter);
//react가 build한 html 파일이 react-router-dom 으로 랜더링 로직을 처리한다
app.get('*', (req, res) => {
res.sendFile(path.join('./client/build/index.html'));
});
그렇다면 백엔드 로직 라우터들이 response
를 끝내버리면안됍니다.
app.get('*') 부분이 실행되기 전에 상단의 라우터들에서 통신이 종료되면
화면을 랜더링이 실행되지 않으니까요.
따라서 중간에 있는 라우터의 컨트롤러(미들웨어)에res.send
, res.render
, res.sendFile
등 통신을 종료하는 메서드 사용이 없어야 합니다.
모델 설계
브라우저에 전달되는 user
객체에서 어떤 칼럼을 이용해서 권한을 부여할지,
admin
이나 trainer
의 권한별로 아예 다른 페이지로 갈지,
동일 컴포넌트 내부에서 다른 화면을 그려주게 할지 이런 것들을 선택해야 합니다.
그래서 어떤 칼럼을 집어넣어야 하나 많이 고민하면서
boiler plate내부에 User모델의 칼럼을 조작하고 있었습니다.
그런데 팀원분이 지난달에 팀장님이 노션에 작성한 임시 모델에서
필요한 값만 조금 조작하자고 제안해 주셨습니다.
https://www.notion.so/a3133ab07d2f4e14b4c8d9f0835cdf3c
그래서 백엔드가 할 것
trainer가 회원가입 시 기본적으로 authorized
칼럼값이 false
가 되게 설정합니다.
회원가입 시 자동으로 admin 계정에게 권한 허가 요청을 보냅니다.
만약 허가를 누른다면, trainer 모델 내부에 authorized 값을 true로 바꿔주는 로직을 만드려고 합니다
아직 해당 권한으로 무엇을 할지는 정하지 않았습니다.
클라이언트분이 원하시는 방식대로 간단히 권한을 표시하게만 해주시면 될 거 같습니다.
ex)
권한 허가받은 계정과 대기 중인 계정에게 보여주는
화면의 색상을 달리한다던가, 그냥 권한을 텍스트로 표시해 준다거나
여러가지 다양한 방법이 있습니다.
리액트 공부를 하고 있어서 그런가 클라이언트부분도 생각해보니 재밌는거같습니다.
읽어주셔서 감사합니다
오타나 질문, 조언은 댓글로 남겨주세요.
'프로젝트 기록 및 회고 > 고객관리 프로그램' 카테고리의 다른 글
CRM 프로젝트 시작! - 회원가입/권한부여 (0) | 2023.06.16 |
---|