나의 개발 기록지

간만에 기록 - db 요청 그리고 node 와 mongoose 본문

NextJs

간만에 기록 - db 요청 그리고 node 와 mongoose

해기97 2025. 3. 25. 11:10

지금 현재 프로젝트를 진행 중 기록하는걸 까먹어서 중간 점검한번 할 겸 복습..?

 


일단 next를 사용할 때 최대한 서버 컴포넌트 상태로 유지하며 필요한 기능에만 클라이언트 컴포넌트를 사용하는 것이

성능에 좋다기에 되도록이면 그렇게 사용해보려 노력중이다.

 

그러면서 알게된 방법들을 메모

 

DB 요청할 때, - useEffect 안써도 된다.

 

이 방법이 조금 신선하게 다가왔다. 리액트를 사용했더라면 useEffect로 데이터를 받아와 다뤘을텐데 지금은 아니다.

 

일단 코드의 예시부터 보면 이렇다

 

const { Category, Game } = require("@/models/game");
const { connectDB } = require("./mongoose");
const mongoose = require("mongoose");
const { serializeDoc, serializeDocs } = require("@/utils/serializeDoc");

const getGamesList = async () => {
  await connectDB();
  const gamesListItem = await Game.find({}).populate("author", "name").lean();

  return serializeDocs(gamesListItem);
};

module.exports = {
  getGamesList,
};

 

// app/game/page.js
import { getGamesList } from "@/lib/db";

export default async function GamePage() {
  const games = await getGamesList();

  return (
    <div>
      {games.map(game => <div>{game.title}</div>)}
    </div>
  );
}

 

이걸 보면 GamePage에서는 useEffect를 사용하지않고 서버에서 필요한 데이터를 먼저 불러온 뒤 그걸 사용하는 구조다.

 

Next의 App Router의 서버 컴포넌트 내부에서 직접 불러오는 방식으로

클라이언트 컴포넌트에서 별도의 API 호출이나 상태 관리 없이 gamesList 또는 상세페이지의 데이터를 불러오는 함수를

서버에서 호출해 데이터를 받아오고 해당 데이터로 HTML을 렌더하는 것이다.

 

이 방식의 장점

  • 클라이언트 컴포넌트로 전환할 필요가 없다.
  • SEO 최적화에 유리하다. - 서버에서 렌더링되어서
  • 초기 렌더링 시 필요한 데이터를 모두 서버에서 처리 가능하다.
  • 구조가 단순하고 빠르다.

이런 구조를 서버 컴포넌트 기반의 데이터 패칭 방식이라 한다는데

꽤나 좋은 방식인 것 같다.

코드도 꽤나 간결해지고 보기가 편하더라.

또한 조회수나 좋아요 같은 업데이트 사항에서도 바로바로 가능하다는 점도 꽤나 만족스러웠다.

 


그리고 node와 mongoose에서 자주 사용되는 메서드를 정리해둬야할 것 같다.

나는 node를 아주 얕게만 배워봐서 메모해두지않으면 나중에 사용할 때 까먹거나 헷갈릴 것 같다.

 

자주 사용되는 메서드와 설명

 

1.find()

 

await Game.find({ category: "quiz" })
  • 다수의 문서 조회
  • 결과는 배열로 반환되며
  • 필터 조건 넣을 수 있다 - {} 넣으면 전체를 조회한다.
  • 일반적으로 리스트 조회할 때 많이 사용한다.

2. findOne()

await User.findOne({ email })

 

  • 조건에 맞는 문서 한개 조회
  • 여러 개가 일치해도 가장 첫 번째 것만 반환한다.

3. findById()

await Game.findById(gameId)
  •  ObjectId 기반으로 특정 문서 1개 조회
  • 내부적으로 findOne({ _id:id})와 같다.

4. findByIdAndUpdate()

await Game.findByIdAndUpdate(gameId, { $inc: { viewCount:1 } })
  • 특정 문서를 찾고 바로 수정
  • 두 가지 인자
    • 첫 번째 : 어떤 문서를 수정할지 (ID)
    • 두 번째 : 어떻게 수정할지 ($inc, $set, 등)

5. $inc

$inc : { lickCount: 1}
  • 숫자 필드 증감소
  • likeCount += 1 과 같은 효과지만 원자적이고 안전하게 처리된다.

6. $set

$set: { title: "새 제목"}
  • 지정한 필드 값을 덮어쓰기
  • 문서의 기존 값을 수정할 때 사용

7. lean()

await Game.find({}).lean()
  • Mongoose Document 대신 순수 자바스크립트 객체로 변환
  • 메모리 가볍고 직렬화 하기 쉽다.
  • 서버 컴포넌트에 넘기기 전에 거의 항상 붙이는 게 좋다

8. populate()

.populate("author", "name")
  • 참조된 ObjectId 필드를 실제 객체로 채워줌
  • 예 : author 필드가 User의 ObjectId > populate("author") 하면 전체 유저 정보 포함
  • "author", "name" 처럼 두 번째 인자로 필드 제한 가능

9. deleteOne()

await Like.deleteOne({ userId,gameId})
  • 조건에 맞는 문서 1개 삭제
  • 보통 토글 긴으에서 좋아요 취소 또는 댓글 삭제 같은 데 자주 쓴다.

10. create()

await Like.create({ userId, gameId })
  • 문서 하나 생성
  • new Like({...}).save() 랑 같지만 더 간단하게 쓴다.

 

✅ 기타 자주 쓰이는 Node.js/서버 문법

메서드설명
require() Node.js의 CommonJS 모듈 불러오기 방식
module.exports 모듈 외부로 함수/객체 내보내기
process.env 환경 변수 접근 (비밀 키, DB 주소 등)
async/await 비동기 코드 처리
try/catch 에러 핸들링

 

📝 요약 메모용 정리 (복사해서 쓰기 좋게)

 

📦 Mongoose 핵심 메서드 정리

- find() : 여러 문서 조회
- findOne() : 조건에 맞는 문서 1개 조회
- findById() : ObjectId 기반 1개 조회
- findByIdAndUpdate() : 특정 문서 찾아서 바로 수정
- create() : 문서 생성
- deleteOne() : 문서 1개 삭제

⚙️ 연산자
- $inc : 숫자 필드 +/-
- $set : 필드 값 덮어쓰기

📎 옵션
- populate() : 참조된 ObjectId 실제 객체로 변환
- lean() : 순수 JS 객체로 변환 (직렬화 용이)

💡 기타
- require(), module.exports : Node 모듈 시스템
- process.env : 환경 변수
- async/await, try/catch : 비동기 및 에러 처리

'NextJs' 카테고리의 다른 글

mongoose - api 작성  (0) 2025.04.06
mongoose 메모 - 스키마  (0) 2025.04.06
스키마와 MongoDB 그리고 몽구스  (0) 2025.03.14
Next.js의 use server란 무엇인가?  (0) 2025.01.28
Next의 지정된 파일 이름  (0) 2025.01.24