자습서: DocumentDB를 사용하여 TypeScript 앱 빌드 및 Azure DocumentDB에 배포

이 자습서에서는 Docker 컨테이너에서 DocumentDB를 로컬 개발 데이터베이스로 사용하고 MongoDB 드라이버로 TypeScript 애플리케이션을 빌드한 다음 연결 문자열 교환하여 Azure DocumentDB로 마이그레이션합니다.

이 자습서에서는 다음을 수행합니다.

  • Docker 컨테이너에서 DocumentDB 시작
  • TypeScript 애플리케이션 만들기
  • 로컬 데이터베이스에 애플리케이션 연결
  • Azure DocumentDB 클러스터 만들기
  • Azure DocumentDB에 애플리케이션 배포

사전 요구 사항

컨테이너 시작

DocumentDB용 Docker 컨테이너 이미지를 사용하여 로컬 개발 데이터베이스를 만듭니다.

  1. DocumentDB 컨테이너 이미지를 끌어오세요.

    docker pull ghcr.io/documentdb/documentdb/documentdb-local:latest
    
  2. 사용자 이름 및 암호로 컨테이너를 시작합니다.

    docker run --detach --publish 10260:10260 --name documentdb ghcr.io/documentdb/documentdb/documentdb-local:latest --username <admin-username> --password <admin-password>
    

    중요합니다

    <admin-username><admin-password>를 사용자 고유의 자격 증명으로 대체하십시오.

  3. 컨테이너가 실행 중인지 확인합니다.

    docker ps --filter "name=documentdb"
    

    중요합니다

    DocumentDB 게이트웨이 엔드포인트는 포트 10260에서 사용할 수 있습니다. 다음 연결 문자열 형식을 사용하여 연결합니다.

    mongodb://<admin-username>:<admin-password>@localhost:10260/?tls=true&tlsAllowInvalidCertificates=true
    
    설정 가치
    엔드포인트 https://localhost:10260
    사용자 이름 <admin-username>
    암호 <admin-password>
    TLS true
    TLS에서 잘못된 인증서 허용 true

    <admin-username><admin-password>를 사용자 고유의 자격 증명으로 대체하십시오.

애플리케이션 만들기

Next.js 애플리케이션을 만들고 로컬 데이터베이스에 연결합니다.

  1. 빈 폴더에 새 Next.js 애플리케이션을 만듭니다.

    npx create-next-app .
    
  2. Node.js MongoDB 드라이버를 설치합니다.

    npm install --save mongodb
    
  3. 다음 코드로 명명된 app/data.tsx 새 파일을 만듭니다. 이 파일에는 데이터베이스와 상호 작용하는 서버 작업이 포함되어 있습니다.

    "use server";
    
    import { MongoClient, ObjectId } from "mongodb";
    import { revalidatePath } from "next/cache";
    
    const connectionString = "<documentdb-connection-string>";
    
    const client = new MongoClient(connectionString);
    const db = client.db("work-management");
    const collection = db.collection("tasks");
    
    export type Todo = {
      id: string;
      title: string;
      completed: boolean;
    };
    
    export async function getTodos(): Promise<Todo[]> {
      const docs = await collection.find().sort({ _id: -1 }).toArray();
      return docs.map((doc) => ({
        id: doc._id.toString(),
        title: doc.title,
        completed: doc.completed,
      }));
    }
    
    export async function addTodo(formData: FormData) {
      const title = formData.get("title") as string;
      if (!title?.trim()) return;
      await collection.insertOne({ title: title.trim(), completed: false });
      revalidatePath("/");
    }
    
    export async function toggleTodo(formData: FormData) {
      const id = formData.get("id") as string;
      const doc = await collection.findOne({ _id: new ObjectId(id) });
      if (doc) {
        await collection.updateOne(
          { _id: new ObjectId(id) },
          { $set: { completed: !doc.completed } }
        );
      }
      revalidatePath("/");
    }
    
    export async function deleteTodo(formData: FormData) {
      const id = formData.get("id") as string;
      await collection.deleteOne({ _id: new ObjectId(id) });
      revalidatePath("/");
    }
    

    중요합니다

    연결 문자열 자리 표시자를 컨테이너를 시작할 때 이 자습서의 앞부분에서 지정한 자격 증명으로 바꿉다.

  4. 기존 app/page.tsx 파일을 삭제하고 다음 코드로 바꿉다.

    import { getTodos, addTodo, toggleTodo, deleteTodo } from "./data";
    
    export default async function Home() {
      const todos = await getTodos();
    
      return (
        <div className="min-h-screen bg-black text-zinc-50 font-sans">
          <main className="max-w-lg mx-auto py-16 px-8">
            <h1 className="text-2xl font-semibold tracking-tight mb-8">Todo App</h1>
    
            <form action={addTodo} className="flex gap-2 mb-8">
              <input
                name="title"
                placeholder="Add a todo..."
                required
                className="flex-1 rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-600"
              />
              <button type="submit" className="rounded-md bg-zinc-100 px-4 py-2 text-sm font-medium text-zinc-900 hover:bg-zinc-300 transition-colors">
                Add
              </button>
            </form>
    
            <ul className="space-y-2">
              {todos.map((todo) => (
                <li key={todo.id} className="flex items-center gap-3 rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2">
                  <form action={toggleTodo}>
                    <input type="hidden" name="id" value={todo.id} />
                    <button type="submit" className="text-lg leading-none">{todo.completed ? "✅" : "⬜"}</button>
                  </form>
                  <span className={`flex-1 text-sm ${todo.completed ? "line-through text-zinc-500" : "text-zinc-100"}`}>{todo.title}</span>
                  <form action={deleteTodo}>
                    <input type="hidden" name="id" value={todo.id} />
                    <button type="submit" className="text-sm text-red-400 hover:text-red-300 transition-colors">✕</button>
                  </form>
                </li>
              ))}
            </ul>
    
            {todos.length === 0 && <p className="text-center text-sm text-zinc-500 mt-4">No todos yet.</p>}
          </main>
        </div>
      );
    }
    
  5. 애플리케이션을 로컬로 실행합니다.

    npm run dev
    
  6. 브라우저에서 열어 http://localhost:3000 애플리케이션이 실행 중이고 로컬 데이터베이스에 연결되어 있는지 확인합니다.

    여러 항목이 데이터베이스에 유지된 웹 브라우저에서 실행되는 새 애플리케이션의 스크린샷.

    팁 (조언)

    Visual Studio Code의 DocumentDB 확장을 사용하여 DocumentDB 컨테이너에 연결하면 이 애플리케이션이 생성하는 데이터를 볼 수 있습니다. 데이터베이스의 이름이 지정 work-management 되고 컬렉션의 이름이 지정 tasks됩니다.

  7. 애플리케이션을 중지합니다.

Azure DocumentDB 클러스터 만들기

클라우드에서 애플리케이션 데이터를 호스트하는 Azure DocumentDB 클러스터를 만듭니다.

  1. 클러스터 이름 및 대상 리소스 그룹 이름에 대한 변수를 만듭니다.

    RESOURCE_GROUP_NAME="<resource-group-name>"
    CLUSTER_NAME="<cluster-name>"
    ADMIN_USERNAME="<admin-username>"
    ADMIN_PASSWORD="<admin-password>"
    

    중요합니다

    자리 표시자 값을 사용자 고유의 값으로 바꿉니다. 클러스터 이름은 전역적으로 고유해야 합니다.

  2. Azure DocumentDB 클러스터를 만듭니다.

    az cosmosdb mongocluster create \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --location "eastus" \
      --administrator-login $ADMIN_USERNAME \
      --administrator-login-password $ADMIN_PASSWORD \
      --server-version "8.0" \
      --shard-node-tier "M30" \
      --shard-node-ha false \
      --shard-node-disk-size-gb 128 \
      --shard-node-count 1
    
  3. 현재 IP 주소에서의 액세스를 허용하는 방화벽 규칙을 만듭니다.

    MY_IP=$(curl -s ifconfig.me)
    
    az cosmosdb mongocluster firewall rule create \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --rule-name "allow-my-ip" \
      --start-ip-address $MY_IP \
      --end-ip-address $MY_IP
    
  4. 클러스터에 대한 연결 문자열 가져옵니다.

    az cosmosdb mongocluster show \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --query "connectionString" \
      --output tsv
    
  5. 연결 문자열 값을 기록합니다. 다음 단계에서 사용합니다.

Azure DocumentDB에 애플리케이션 연결

로컬 컨테이너 대신 Azure DocumentDB에 연결하도록 애플리케이션을 업데이트합니다.

  1. app/data.tsx의 로컬 연결 문자열을 Azure DocumentDB 연결 문자열으로 바꿉니다.

    const connectionString = "<azure-documentdb-connection-string>";
    

    중요합니다

    <azure-documentdb-connection-string>를 이전 단계에서 기록한 연결 문자열로 교체합니다. 포털에서 제공된 연결 문자열에는 암호가 포함되어 있지 않습니다. 연결 문자열 <password> 자리 표시자를 클러스터를 만들 때 지정한 암호로 바꿉다.

  2. 애플리케이션을 다시 시작합니다.

    npm run dev
    
  3. http://localhost:3000을(를) 브라우저에서 여세요. 이제 애플리케이션은 데이터를 읽고 Azure DocumentDB 클러스터에 씁니다.

자원을 정리하세요

이 자습서에서 만든 리소스가 더 이상 필요하지 않은 경우 요금이 발생하지 않도록 삭제합니다.

  1. Azure DocumentDB 클러스터를 삭제합니다.

    az cosmosdb mongocluster delete \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --yes
    
  2. DocumentDB 컨테이너를 중지하고 제거합니다.

    docker stop documentdb
    docker rm documentdb
    

다음 단계:

빠른 시작: Node.js를 사용하여 Azure DocumentDB