Node.js

node>MongoDB에서 데이터 출력하기 (array/object 문법)

연습노트 2024. 7. 25. 04:27

DB에 게시물 한 두개만 저장해보도록 합시다.

- mongodb.com 사이트 들어가서

- collection 버튼 누르면

현재 DB에 저장된 데이터들을 구경해볼 수 있는데

저번시간에 forum이라는 데이터베이스안에 post 라는 컬렉션 (폴더)를 만들어봤습니다. 

 

이제 심심하니까 여기다가 데이터 몇개만 저장해볼건데 

게시판을 만든다고 했으니까 유저 게시물을 post 컬렉션에 임시로 몇개 만들어봅시다. 

insert document 버튼이 어딘가 있을텐데 누르면 데이터를 저장할 수 있습니다.

 

 

title : '어쩌구'
content : '저쩌구' 

이런 형식으로 대충 유저 게시물을 두어개 정도 저장해보도록 합시다. 

document에는 데이터이름 : 데이터값 형식으로 데이터를 저장할 수 있습니다. 

자바스크립트 object 자료형이랑 비슷함 

 

 

 

 

▲ 그래서 이렇게 생긴 document를 두개 정도 만들어봤습니다. 

 

 

Q. 근데 document 하나에 여러 게시물 보관해도 되는거 아님?

그래도 되긴 되는데 

MongoDB쓸 때 중요한 점이 하나 있는데

document는 100만개 있어도 document 1개 찾는건 매우 빠릅니다. 

근데 document 하나 안에 100만개의 문장이 있고 거기서 원하는 문장하나만 찾는건 매우 어렵습니다. 

그래서 각각 document에 게시물 1개 씩만 저장해두는게 나을거같군요.

 

다르게 설명하면 document는 하나의 엑셀 행이라고 생각하면 됩니다

저번엔 파일이라고 했던거같은데 더 정확히 말하면 엑셀 행입니다. 

 

 

 

▲ 하나의 엑셀 행에다가 이렇게 자료 저장하는사람 있어요?

아마 없습니다.

 

 

 

▲ 이렇게 한줄한줄 저장하는게 좋습니다.

document도 마찬가지로 엑셀의 행 하나라고 생각하고 저장하면 나중에 별 문제 없습니다. 

 

 

 

 

_id, ObjectId 가 뭐냐면

 

 

 

▲ document 만들 때 잘 보시면 _id 라는 항목도 자동생성된걸 볼 수 있습니다

_id는 document마다 구분하기 위한 유니크한 번호입니다. 

 

왜냐면 예를 들어 유저 두명이 똑같은 글을 써버리면 구분이 안되기 때문에 

자동으로 유니크한 _id 같은걸 자동으로 부여해줍니다.

그냥 글번호라고 생각해도 될거같습니다. 

 

그리고 _id에는 1, 2, 3 이런 정수가 아니라

기본적으로 ObjectId 라고 부르는 랜덤 문자를 집어넣어줍니다. 

ObjectId의 특징은

- 서로 중복되지 않고 

- 먼저만든 document가 더 빠른, 그니까 숫자가 낮은 ObjectId를 가지고 있습니다.

- 자동부여가 싫으면 ObjectId 대신 직접 1, 2, 3 이렇게 숫자를 넣어도 전혀상관없습니다. 

근데 귀찮으니까 보통은 자동부여된거 그대로 냅둡니다. 

 

 

 

 

 

 

페이지 방문시 DB 데이터 보여주기 

 

예를 들어 /list 페이지에 방문하면 DB에 있던 글을 뽑아서 보여주고 싶으면 어떻게하는지 알아봅시다.

 

 

app.get('/list', (요청, 응답) => {
  응답.send('안녕')
})

유저가 /list 페이지 방문하면 뭔가 보내주고 싶으면 

이런거 코드짜면 된다고 했습니다.

근데 '안녕' 말고 DB에 있던 글을 뽑아서 보내주고 싶으면요? 

 

 

 

await db.collection('컬렉션명').find().toArray() 

DB에 있던 데이터를 하나 꺼내고 싶으면 이런거 쓰면 됩니다.

그럼 이 자리에 컬렉션에 있던 모든 document가 출력됩니다. 

 

 

 

app.get('/list', async (요청, 응답) => {
  let result = await db.collection('컬렉션명').find().toArray()
  응답.send(result[0].title)
})

그래서 이렇게 코드짜면 유저가 /list 페이지 방문하면 DB에 있던 첫글 제목을 보내줍니다. 

참고로 await 쓰려면 그 전에 async라는걸 콜백함수 왼쪽에 붙여야합니다. 

 

 

await이 뭐임

 

await이 뭐냐면 다음 줄 실행하기 전에 잠깐 기다리라는 뜻입니다.

 

왜 이게 필요하냐면 자바스크립트는 참을성이 없습니다.

자바스크립트에서 처리가 좀 오래걸리는 함수들은

가끔 처리가 완료되기까지 기다리지 않고 바로 다음 줄을 급하게 실행하려고 하기 때문에 (일명 비동기처리)

그걸 막고 싶으면 콜백함수를 쓰거나 await을 쓰거나 .then을 쓰거나 셋 중 하나 쓰면 됩니다.

 

 

app.get('/list', async (요청, 응답) => {
  let result = db.collection('컬렉션명').find().toArray()
  응답.send(result[0].title)
})

그래서 db.collection() 어쩌구 코드들은 처리가 좀 오래걸리기 때문에

그런 코드에 await을 안써버리면 DB에서 데이터 꺼내오기도 전에 응답.send() 를 실행해버립니다. 

그래서 await 붙여야합니다.

 

 

 

실은 그냥 mongodb 라이브러리에서

db.collection().어쩌구() 코드들은 항상 await을 붙이라고 하기 때문에 그렇게 쓴 것이라고 생각해도 됩니다. 

 

 

 

app.get('/list', async (요청, 응답) => {
  db.collection('컬렉션명').find().toArray().then((result)=>{
    응답.send(result[0].title)
  })
})

app.get('/list', async (요청, 응답) => {
  db.collection('컬렉션명').find().toArray((err, result)=>{
    응답.send(result[0].title)
  })
})

예전 버전의 mongodb 라이브러리는 .then() 아니면 콜백함수를 넣어서 작성했었습니다. 

근데 await 쓰면 더 깔끔해보이니까 그걸로 쓰도록 합시다. 

 

참고로 await도 여러분 맘대로 붙이는게 아니라 붙일 수 있는 곳만 붙일 수 있습니다.

정확히 말하면 Promise를 뱉는 곳에다가만 붙일 수 있는데

당연히 mongodb 라이브러리 만든 사람이 여기다가 await 붙일 수 있게 만들어놔서 이게 가능한거니까 참고합시다.

 

[collapse]

 

 

 

 

 

 

array/object 자료형

 

 

array와 object 자료형인데 이런거 미리배워오랬는데

무시하고 그냥 듣는 분들도 있기 때문에 잠깐 설명하자면 

 

자바스크립트에서 여러가지 자료들을 변수하나에 저장하고 싶으면 

array자료형을 사용하면 됩니다

 

let a = [10, 20, 30]

이러면 변수 하나에 여러가지 숫자나 문자를 담아서 보관할 수 있습니다. 

 

let a = [10, 20, 30]
console.log(a[1])

나중에 원하는 자료만 쏙 빼서 사용하고 싶으면 

변수명 뒤에 대괄호 치고 몇번째 자료를 꺼내고 싶은지 써주면 됩니다.

위의 코드에서 [1] 이라고 쓰면 1번째 자료가 나옵니다. 

컴퓨터는 0부터 세기 때문에 아마 20이 출력됩니다. 확인해봅시다. 

 

 

 

 

 

array자료형이 못생겨서 싫으면 object 자료형도 있습니다.

object자료형도 똑같이 여러 자료를 변수하나에 쑤셔박아두고 싶을 때 씁니다.

 

 

let b = { name : 'kim', age : 20 }

{ } 열고 자료들을 콤마로 구분해서 넣으면 되는데

차이점이 하나 있는게 object는 자료마다 왼쪽에 이름을 지어줘야합니다.

그래서 저는 이름과 나이를 한번 저장해봤습니다. 

 

 

let b = { name : 'kim', age : 20 }
console.log(b.name)
console.log(b['name'])

나중에 자료하나만 쏙 꺼내고 싶으면 object 자료 오른쪽에 점찍고 자료이름 집어넣으면 됩니다.

그럼 그 자료만 쏙 뽑아낼 수 있습니다.

점찍기 싫으면 ['자료이름'] 넣어도 됩니다.

 

 

 

 

 

저는 첫 글의 제목만 꺼내고 싶은데요 

 

DB에서 가져온 결과를 result 변수같은 것에 담아서 출력해보면 

대괄호랑 중괄호가 이상하게 섞여있습니다.

 

 

[
  {
    _id : new ObjectId('어쩌구'),
    title : '첫게시물',
    content : '내용임 111'
  },
  {
    _id : new ObjectId('어쩌구'),
    title : '두번째글임',
    content : '안녕'
  },
]

DB에서 출력한 자료도 array와 object를 활용해서 데이터를 보여줍니다. 

이상하고 복잡하게 생겼지만 쉽게 설명하면 array 안에 object 몇개를 넣어뒀을 뿐입니다.

[ { }, { } ] 대충 이렇게 생긴 자료입니다. 

실은 array 안에 object 맘대로 넣을 수 있습니다. 

 

 

 

 

그럼 result 변수에 저렇게 글들이 저장되어있는데

거기서 첫 글의 제목만 뽑고 싶으면 어떻게 코드짜면 될까요?

-> 아무리 복잡하게 생긴 자료도 시작 괄호만 잘 보면 원하는 내용만 쉽게 뽑을 수 있습니다.

 

result 출력해보면 시작괄호가 뭐죠? 

각진 [ ] 대괄호죠? 

그럼 무조건 array 자료라서 array에서 자료뽑는 문법부터 쓰면 됩니다. 

 

 

app.get('/list', async (요청, 응답) => {
  let result = db.collection('컬렉션명').find().toArray()
  console.log(result[0])
})

그래서 이거 실행해보면 (/list 페이지 방문해보면)

 

 

{
  _id : new ObjectId('어쩌구'),
  title : '첫게시물',
  content : '내용임 111'
}

이런게 터미널에 출력됩니다. 

이 자료는 { } 중괄호로 시작하죠?

그럼 대부분 object 자료라서 object 자료에서 자료 뽑는 문법 쓰면 됩니다. 

 

 

 

app.get('/list', async (요청, 응답) => {
  let result = db.collection('컬렉션명').find().toArray()
  console.log(result[0].title)
})

그래서 이거 실행해보면 첫 글의 제목만 잘 출력되는군요. 

심심하면 둘째 글제목도 한번 뽑아서 출력해보시길 바랍니다 

 

 

 

 

오늘 배운거 정리하자면 

1. 컬렉션에 있던 document 전부 꺼내고 싶으면 db.collection('컬렉션명').find().toArray()

2. array자료에서 자료뽑고 싶으면 array자료[자료순서] 

3. object자료에서 자료뽑고 싶으면 object자료.자료이름 

4. 일부 늦게 동작하는 코드들은 await 안붙이면 그 다음줄부터 실행됨 

 

다음 시간엔 이 데이터들을 html 웹페이지에 집어넣는 방법을 알아보도록 합시다 

그래야 유저가 볼 수 있을거아닙니까