[사이드 프로젝트] Mongoose의 'populate'를 이용한 타 collection 참조 👀

June hyoung Park·2020년 9월 23일
5

데이터 베이스

목록 보기
1/1
post-thumbnail

NoSQL 데이터 베이스인 MongoDB를 사용하다보면, 컬렉션의 특정 데이터를 기반으로 다른 컬렉션의 데이터를 참조할 일이 생긴다. 그러나 관계형 데이터 베이스처럼 테이블 join을 할 수는 없는 상황에서 이와 비슷한 기능을 가진 'populate'에 대해 정리 해보려한다.

MongoDB의 ObjectId

ObjectId는 하나의 document 내에서 유일함이 보장되는 12 byte binary data다. 또한 MongoDB 자체 에서 자동으로 넣어주는 고유값이기에, ObjectId를 통해 다른 컬렉션에 있는 데이터를 참조할 수 있다. 즉, 특정 collection에서 populate 메소드를 이용하면 ObjectId를 기반으로 다른 collection의 정보들을 함께 담아서 출력할 수 있다.

populate 🕺

예시로 유투브와 비슷한 기능을 하는 동영상 업로드 서비스의 영상 업로드 부분을 생각해보자. 유저가 로그인을 하여 자신의 계정으로 영상을 업로드 한다고 했을때, 업로드한 영상에 대한 데이터를 담을 스키마엔 제목, 영상 길이, 공개 비공개 여부, 썸네일 등등 여러가지가 들어가야 할것이다.

그리고 이 예제에선 작성자(writer)부분에 작성자의 ObjectId와 Mongoose의 populate 메서드를 이용해서 회원가입된 유저들에 대한 데이터가 담겨있는 User 컬렉션을 참조한뒤 업로드된 영상 뿐만이 아닌, 작성자에 대한 정보까지 가져오는 방법에 대해 다룰것이다.

mongoose.Schema 😃

먼저 populate를 사용하기위해선 스키마 정의 시 type을 mongoose.SchemaTypes.ObjectId로 해줘야한다. 또한 ref(레퍼런스)에는 해당 ObjectId를 가지고 어떤 모델을 참조할것인지를 지정해줘야 하기에, 회원가입된 유저들에 대한 데이터가 담겨있는 'User'를 지정해 주었다.

Video upload

Uploadvideo.js

클라이언트(리액트) 측에서 업로드시 서버로 보낼 데이터들을 지정해주는 부분이다. 제목, 길이, 카테고리, 등등을 담은 객체를 만든 뒤 Node js로 만들어둔 /api/video/uploadVideoapi로 post요청을 보내게 된다. 위 객체 내부 'writer'키의 value인user.userData._id는 리덕스의 'useSelector'을 이용하여 가져온 로그인된 유저의 ObjectId이다. (클라이언트 관련 부분이나, 파일 업로드 자체의 대한 부분은 자세히 다루진 않겠다.)

Nodejs Express server (post)

우선 위에서 보낸 post요청을 받은 Express server의 api부분이다. video 모델객체를 만든 뒤 클라이언트에서 보낸 데이터들을 저장해준다.

video 콜렉션을 보면 정상적으로 잘 저장된것을 알 수 있다. 맨 위의 _id부분은 업로드된 영상(게시물) 의
ObjectId이며, writer부분에 업로드한 유저의 ObjectId이다.

Root page

이제 홈페이지 메인에 접속하면, 업로드된 영상(게시물)들을 불러오도록 하자.

이제 LandingPage(root page)에 접속하면 리액트의 useEffect훅을 통해 "/api/video/getVideos"api로 get요청을 보내게되며, 응답으로 서버에서 video 컬렉션에 있는 데이터들을 json형식으로 보내줄것이다.

Nodejs Express server (get)

이 과정에서 populate 메서드가 사용된다. populate의 인자로 참조가 필요한 Document이름을 넣은 뒤exec()메서드의 videos 인자를 통해 받아온 데이터에 접근할 수 있다.

이제 루트 페이지 접속 시 비디오들에 대한 정보를 모두 가져올 수 있게되었으며, 각 항목의 writer 부분을 보면, 업로드한 유저의 objectId뿐만이 아니라 이메일, 이름, 프로필 이미지 등 유저의 모든 정보를 함께 담고 있는것을 알 수 있다!

profile
Take me home~~~~

0개의 댓글