extends Document {}

henry·2025년 2월 2일

extends Document {}TypeScript에서 Mongoose 모델과 함께 사용할 때,
내가 정의한 데이터 구조(예: IUser)에 Mongoose가 제공하는 기본 속성 및 메서드를 추가하기 위해 사용됩니다.
즉, 내 데이터 타입을 확장하여 Mongoose의 기능을 안전하고 효율적으로 사용할 수 있도록 만드는 작업입니다.

TypeScript와 Mongoose를 함께 사용할 때, 사용자 정의 데이터 타입(IUser)
Mongoose가 제공하는 기본 문서 타입(Document)을 결합하여 타입 안정성을 높이기 위한 확장


📌 왜 사용하는가?

1. Mongoose 기본 기능 사용

  • Mongoose Document는 MongoDB 데이터를 다룰 때, 자동으로 제공하는 속성메서드를 포함하는데, extends Document를 사용하면 이 기능들을 내가 정의한 타입과 함께 사용할 수 있습니다.

    • 속성 : _id, __v
    • 메서드 : save(), remove()

2. 타입 안정성 보장

  • TypeScript는 내가 정의한 데이터와 Mongoose의 기본 속성을 결합할 때 타입 충돌을 방지합니다.
  • 코드 작성 시 자동완성을 지원하며, 잘못된 사용을 컴파일 시점에 알려줍니다.


📌 어떻게 사용하는가?

✅ 1. 설정

1. 먼저, 내가 원하는 데이터 구조를 정의합니다.

export interface IUser {
  user_id: string;
  social_id: string;
  social_provider: string;
  email?: string;
  nickname: string;
  profile_image?: string;
}

2. 데이터 구조에 Document를 확장합니다.

  • Mongoose의 기능을 추가하기 위해 Document를 확장한 새로운 타입을 만듭니다.
import { Document } from "mongoose";

export interface IUserDocument extends IUser, Document {}

3. 내가 만든 모델과 연결합니다.

  • Mongoose 모델 정의 시, 확장된 타입을 적용합니다.
import mongoose, { Schema } from "mongoose";
import { IUserDocument } from "./IUserDocument";

const UserSchema: Schema<IUserDocument> = new Schema({
  user_id: { type: String, required: true },
  social_id: { type: String, required: true },
  social_provider: { type: String, required: true },
  email: { type: String },
  nickname: { type: String, required: true },
  profile_image: { type: String },
});

export default mongoose.model<IUserDocument>("User", UserSchema);

✅ 2. 적용


2-1. Mongoose 제공 기본 속성 및 메서드 사용

import UserModel from "./models/User";

const createUser = async () => {
  const user = new UserModel({
    user_id: "123",
    social_id: "456",
    social_provider: "google",
    nickname: "JohnDoe",
  });

  await user.save(); // Mongoose의 `save` 메서드 사용 가능
  console.log(user._id); // Mongoose가 자동 생성한 `_id` 속성 사용 가능
};

2-2. 내가 정의한 데이터에 접근하기

const findUser = async (social_id: string, social_provider: string) => {
  const user = await UserModel.findOne({ social_id, social_provider });

  if (user) {
    console.log(user.nickname); // 내가 정의한 데이터 접근
    console.log(user._id);      // Mongoose 기본 속성 접근
  }
};
  • 출력 결과
    JohnDoe
    123

2-3. Document 변환 (toObject, toJSON)

const transformUser = async (userId: string) => {
  const user = await UserModel.findById(userId);

  if (user) {
    const userObject = user.toObject(); // 일반 객체로 변환
    console.log(userObject);
  }
};
  • 응답 결과

    {
      user_id: "123",
      social_id: "456",
      social_provider: "google",
      nickname: "JohnDoe",
      _id: "641e1234abc5678901234567",
      __v: 0
    }

2-4. Document 수정 후 저장 (save 메서드 사용)

const updateNickname = async (userId: string, newNickname: string) => {
  const user = await UserModel.findById(userId);

  if (user) {
    user.nickname = newNickname; // 닉네임 수정
    await user.save(); // 수정된 데이터를 저장
    console.log("닉네임이 수정되었습니다:", user.nickname);
  } else {
    console.log("사용자를 찾을 수 없습니다.");
  }
};

2-5. 관계형 데이터 조회 (populate)

  • RDBMS의 JOIN과 비슷한 개념
  • populate()를 사용하면 다른 컬렉션(collection)에 저장된 연관된 데이터를 조회할 수 있습니다.
const findPostWithAuthor = async (postId: string) => {
  const post = await PostModel.findById(postId).populate("author");

  if (post) {
    console.log("게시글 제목:", post.title);
    console.log("작성자 닉네임:", post.author.nickname); // 참조된 User 데이터
  }
};

0개의 댓글