Edit Profile 페이지를 만들어 본다.
이 페이지를 만들면서 많은 걸 배우게 될거다. 프로필을 바꾸고, form
을 사용하는 연습은 물론이고
유저한테 있었으면 하는 아바타 같은 파일도 업로드 해볼거다.
지금은 깃허브로 로그인 해야지만 아바타가 있다.
그래서 웹사이트에서 생성한 계정에도 아바타를 업로드 할수 있게 할거다.
그리고 Github
로 계정을 만들어도 아바타를 바꿀수 있도로고 해본다.
파일을 바꾸는 방법도 알아봐야 겠다. 모두 파일에 관련된 거다.
생각해보면 비디오에도 파일이 필요 하다. 현재는 uploadVideo
에는 title
, dscription
, hashtags
밖에 없다.
그래서 video file
을 추가 할거다.
지금부터 할것들은 파일 작업을 하기전에 form
, url
, controller
를 연습하는거다.
router
, controller
, template
, form
을 이해했으면 파일을 업로드 하는 부분도 이해하기 쉬울거다.
알다시피 userRouter
에 가보면 /edit
이 있다.
userRouter.get("/edit", edit);
/edit
이 있고 controller(edit)
도 있다. 그리고 get
과 post
두개의 method
가 필요하다.
그래서 이걸 export const getEdit
으로 하고
userController.js
에서
export const getEdit = (req, res) => {
return res.render("edit-profile", { pageTitle: "Edit Profile" });
};
pageTitle
도 필요 해서 넣었다. 나중에 form
으로 data
를 보낼거다.
지금은 이 controller
를 사용해 본다. 그리고 getEdit
을 import
한다.
userRouter.js
에서
import express from "express";
import {
getEdit,
logout,
see,
startGithubLogin,
finishGithubLogin,
} from "../controllers/userController";
userRouter.get("/edit", getEdit);
그리고 edit
을 getEdit
으로 바꿔 준다.
post
도 필요하다.
export const postEdit = (req, res) => {
return res.render("edit-profile");
};
render
가 아니라 redirect
하게 될지도 모른다. 일단 이렇게 하고
edit
을 삭제 해 준다. 이제 getEdit
,postEdit
이 생겼다.
이제 postEdit
을 import
해준다.
import express from "express";
import {
getEdit,
postEdit,
logout,
see,
startGithubLogin,
finishGithubLogin,
} from "../controllers/userController";
userRouter.route("/edit").get(getEdit).post(postEdit);
그리고 route
를 이용하여 이렇게 코드를 해준다.
다음 단계는
/edit url
에 접근 할수 있어야 한다.
그래서 template
를 바꿔 볼거다. template
의 header
에서 링크를 사용하고 있다.
views
로 가서 base.pug
에서
body
header
h1=pageTitle
nav
ul
li
a(href="/") Home
if loggedIn
li
a(href="/users/edit") Edit Profile
사용자가 로그인 돼 있는 경우에만 editProfile
링크를 볼수 있게 한다.
my profile
페이지는 마지막에 다시 만들어 보기로 한다. 지금은 지워 준다.
새로고침하면 로그인이 안되어 있기 때문에 edit profile
, logout
이 안보인다.
loggenIn
이 localsMiddleware
에서 온 변수이기 때문이다.
middlewares.js
에서
export const localsMiddleware = (req, res, next) => {
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.siteName = "Wetube";
res.locals.loggedInUser = req.session.user;
next();
};
여기에 있는 loggenIn
이 session
에 user
가 있는지 확인해 준다.
지금 현재 페이지에서는 session
에는 user
가 없다.
그래서 이런 이유로 loggedIn
이 base.pug
에서 쓰고 있는 거란걸 꼭 기억한다.
그리고 깃허브 계정으로 로그인 해본다. 해주면 Edit Profile
링크가 생겨 있는걸 알수 있다.
현재 Edit Profile
을 클릭하면 views
에 edit-profile
이 없다고 에러가 생긴다.
views
에 가서 edit-profile.pug
를 만들어 준다.
그리고 새로고침을 해보면 일단 에러가 뜨진 않는다. 물론 edit-profile
이 텅 비어 있긴 하다.
그래서 모든 페이지에서 했던대로 적용해 준다.
extends base
block content
form(method="POST")
input(placeholder="Name",name="name", type="text", requeired)
input(placeholder="Email",name="email", type="email", requeired)
input(placeholder="Username",name="username", type="text", requeired)
input(placeholder="Location",name="location", type="text", requeired)
input(type="submit", value="Update Profile
base.pug
를 extend
하고 block content
를 추가한다.
base
만 입력해줘도 잘 작동한다. input
으로 사용 할것을 join.pug
에서 활용해서 쓴다.
비밀번호 변경 페이지는 따로 만들어 줄거다. 왜냐하면 비밀번호가 있는 사용자가 있고
없는 사용자가 있어서 그렇다. 그리고 submit input
의 value="Update Profile"
새로고침을 해주면 Edit Profile
이 생겼다. 그런데 Edit Profile
에 갔을때
form
이 비어 있으면 안된다. 새로 생성하는게 아니라 수정하는 것이기 때문에
현재 프로필을 볼수 있어야 한다. Edit Video
에서 했던 것처럼 말이다.
그럼 이 template
로 user object
를 가져와 본다.
controller
에다가 할수도 있다.
userController.js
에서
export const getEdit = (req, res) => {
return res.render("edit-profile", { pageTitle: "Edit Profile", user: req.session.user });
직접 req.session.user
에 있는 user object
를 줄수도 있다.
이런식으로 유저를 로그인 시켰다.
하지만 middleware
가 있다.
export const localsMiddleware = (req, res, next) => {
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.siteName = "Wetube";
res.locals.loggedInUser = req.session.user;
next();
};
이 middleware
가 현재 로그인된 사용자를 알려준다. 그래서 userController
에 이걸 보낼 필요 조차도 없다.
이미 locals
를 통해서 loggedInUser
를 사용 할수 있다.
이걸 이용해서 로그인 정보를 활용 할수 있는거다. locals
은 자동적으로 views
로 import
된다.
Edit Profile
에서 value
를 추가 할수 있다.
edit-profile.pug
에서
extends base
block content
form(method="POST")
input(placeholder="Name",name="name", type="text", requeired, value=loggedInUser.name)
input(placeholder="Email",name="email", type="email", requeired, value=loggedInUser.email)
input(placeholder="Username",name="username", type="text", requeired, value=loggedInUser.username)
input(placeholder="Location",name="location", type="text", requeired, value=loggedInUser.location)
input(type="submit", value="Update Profile")
그래서 이런식으로 활용 할수 있다. 새로고침 해서 확인해 보면 해당 정보를 보여준다.
loggedInUser
도 user
인걸 기억해야 한다. 그 말은 user model
에 있는 모든걸 template
에서 사용 가능하다는 거다.
const userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
avatar_url: String,
socialOnly: { type: Boolean, default: false },
username: { type: String, required: true, unique: true },
password: { type: String },
name: { type: String, required: true },
location: String,
});
이부분을 얘기 하는 거다. 미리 만들어 놓은 localsMiddelware
덕분이다.
이미 form
, get
,post
는 다 해봤었다.
하지만 loggedInUser
를 form
에 이렇게 사용해 보는건 처음이였다.
만약 이페이지에 로그인 되지 않은 상태로 온다면 어떻게 될까?
당연히 에러가 난다. undefined
의 property
중 name
을 읽을수 없다.
Cannot read properties of undefined (reading 'name')
왜냐하면 name property
를 가져오려는데 loggedInUser
가 undefined
라서 그렇다.
두가지 문제점이 있다.
하나는 loggedInUser
에 접근하려는데 로그인 되어 있지 않으면 생기는 에러
둘째는 로그인 돼 있지 않은 사람들은 해당 URL
로 가지 못하게 해야 한다.
URL
이 작동하지 않고 redirect
시켜줘야 한다.
그러면 몇몇 route
를 보호하는 middleware
가 필요하겠다.
그전에 이 에러는 middleware
에서 쉽게 고칠수 있다.
export const localsMiddleware = (req, res, next) => {
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.siteName = "Wetube";
res.locals.loggedInUser = req.session.user;
next();
};
보다시피 loggedInUser
는 req.session.user
인데 이게 undefined
일수가 있다.
그래서 이뒤에 or(||)
와 빈 object({})
를 추가해주면 된다.
res.locals.loggedInUser = req.session.user || {};
이런식으로 해주면 된다.이렇게 하면 로그인을 안해도 접근 할수는 있다.
loggedInUser
를 사용하려 할때 생기는 문제는 고쳤다. 문제는 누구든지 접근 할수 있다는 거다.