현재 브라우저가
uploads
폴더에 있는 내용을 볼수 있게 해야한다.
브라우저가 서버에 있는 파일에 접근할수 없으니까 그렇다. 브라우저한테 어디로 가야 하는지 얘기해줘야 한다.
그리고 브라우저가 서버의 어떤 폴더로든 갈수 있는건 보안상 좋지 않다.
그래서 브라우저가 어떤 페이지와 폴더를 볼수 있는지 알려줘야 한다.
그러기 위해 static files serving
이라는걸 활성화 해준다.
폴더 전체를 브라우저에게 노출시킨다는 의미이다. 폴더를 만들고 그 폴더를 브라우저에게 노출 시키는 거다.
먼저 /uploads route
를 만들어야 한다.
server.js
에서
app.use("/uploads", express.static("uploads"));
app.use
를 써서 "/uploads"
로 간다면 그리고 폴더를 노출시킨다.
노출시키는 방법은 express.static()
이다.
static()
에는 노출시키고 싶은 폴더의 이름을 쓰면 된다.
vsc
에서 정의를 보면 디렉토리 내부의 파일을 제공한다고 명시되어 있다.
그래서 "uploads"
를 입력해 주면 된다. 새로고침을 하면 이미지가 안나오던데
서버는 잘 받고 있는데 서버에서 에러가 나던데 서버를 껐다 다시 재시작 해주니 잘 작동한다.
새탭에서 이미지를 열면 확장가 없어서 다운로드 할려고 한다.
확장자는 없지만 컴퓨터는 이해하고 있다. 브라우저도 이해하고 있다는 말이다.
다시 한번 말하자면 처음 원했던건 파일을 업로드 하는거였다.
서버로 파일을 보내고 싶었다. 먼저 views
의 edit-profile
에 파일을 받는 input
을 만들었다.
img(src="/" + loggedInUser.avatarUrl, width="100",height="100")
그리고 다른 파일은 필요 없으니 이미지만 받는다고 설정했다.
파일 input
을 만들었고 원하는건 서버에 이미지를 저장하고 그 이미지에 대한 정보를 얻는거였다.
그래서 multer
라는 middelware
를 사용했다.
export const uploadFiles = multer({ dest: "uploads/" });
form
으로 보낸 파일을 업로드 해주고, 그 파일에 관한 정보도 제공해주고 다른 기능도 있다.
예를 들면 파일명을 완전히 랜덤으로 생성해준다는 거다.
만약 두명의 유저가 selfile
라는 같은 이름의 파일을 업로드 해도 multer
가 이름을 바꿔 주기 때문에 아무 문제 없다.
그리고 그 파일을 지정한 폴더에 저장해준다.
그리고 다음 순서의 controller
에 파일에 관한 정보를 제공한다.
routers
에서 multer
를 먼저 사용해주고
userRouter.js
에서
userRouter
.route("/edit")
.all(protectorMiddleware)
.get(getEdit)
.post(uploadFiles.single("avatar"), postEdit);
그 다음 postEdit controller
를 사용하면 multer
가 시작된다.
파일이 업로드 되고 파일명이 바뀌고 파일이 uploads
폴더에 저장되고
그 파일에 관한 정보를 받아서 postEdit
에 전달해 주는 거다.
userController.js
에서
export const postEdit = async (req, res) => {
const {
session: {
user: { _id, avatarUrl },
},
body: { name, email, username, location },
file,
} = req;
const exists = await User.exists({
_id: { $ne: { _id } },
$or: [{ username }, { email }],
});
그리고 postEdit
에서 req.file
을 사용할수 있다.
postEdit
에서는 avatarUrl
을 업데이트 할수 있는데 때로는 유저가 파일을 보내지 않을수도 있다.
그래서 꼭 확인해야 한다. form
에 file
이 있다면 req
에 있는 file object
를 사용 할수 있다는거고 그말은 file.path
가 존재한다는 거다.
그런데 form
에 file
이 없다면 user
의 avatarUrl
은 기존의 것이랑 같다.
기존의 avatarUrl
은 어디서 오는거냐면 req.session.user.avatarUrl
에서 오는 거다.
기존 avatarUrl
을 현재 로그인된 유저로 부터 가져오는 거다.
그리고 avatarUrl
이 생기긴 했지만 그걸로는 충분하지 않다.
브라우저가 아직 이 파일이 존재하는지 모르기 때문이다.시도해봤지만 404
에러가 뜨고 작동하지 않았다.
작동하지 않은 이유는 서버가 /uploads/랜덤값
라는url
을 이해하도록 설정되지 않아서 그랬다.
그래서 server.js
에서
app.use("/uploads", express.static("uploads"));
Express
에게 만약 누군가 /uploads
로 가려고 한다면 uploads
폴더의 내용을 보여주라고 했다.
uploads
폴더는 multer
가 파일을 저장하는 곳이다.
만약 다른 사진을 새로 아바타로 설정한다면 폴더에 또 새로운 이미지 파일이 생기는거다.
사이트가 활성화 되었을때 트래픽량이나 여러 모로 안 좋을것 같다.
이 방법의 문제점을 해결해 보도록 한다.
첫번째 문제점은 파일을 서버에 저장한다는거다. 좋은 생각이 아니다. 서버는 계속 종료되고 다시 시작하는걸 반복한다.
뭔가를 업데이트하면 새로운 서버를 만들어서 다시 시작하는거다.
그 전 서버에 저장 돼있던 파일들은 날아가는거다.
그렇다면 서버가 두개 필요하다면 어떨까? 하나의 백엔드를 만들더라도 서버 두개가 필요할때가 있다.
방문자가 너무 많으면 그럴수도 있다. 그럼 두개의 서버에서 uploads
폴더를 공유해야 하나? 그건 너무 이상하다.
서버가 죽으면 어떻게 될까?
서버가 죽으면 서버를 시작할수 있는 코드를 가지고 다른 서버에서 다시 시작하면 된다.
그런데 서버가 죽었을때 코드와 업로드된 파일들이 있다면 파일은 날리는 거다.
그래서 나중에 이방법을 바꿀 건데 파일을 서버에 저장하는게 아니라 다른곳에 저장하는거다.
서버가 사라졌다 다시 돌아와도 파일은 그대로 있도록 말이다. 파일을 안전하게 저장하는거다.
이건 나중에 실제 서버에 배포할때 해본다.
한가지 꼭 기억할게 있다.
DB
에 절대 파일을 저장하면 안된다.
DB
에는 파일 자체가 아니라 파일의 위치를 저장하는거다.
그래서 파일 원본은 Amazon
의 하드드라이브 같은데 저장하면된다.
DB
에는 url
을 저장하면 된다.
다음 파트에서는 배운걸 연습하고 video model
에 한가지를 추가할거다.
video model
에는 video file
이 없다.
아바타에 했던걸 활용해서 video file url
을 만들어 본다.