Skip to main content
Summary

텍스트 기능을 콘텐츠 파이프라인으로 확장하기

AI 기능은 글을 생성하는 데서 끝나지 않습니다. 하나의 글을 대표 이미지, 카드뉴스 문장, 내레이션 오디오, 짧은 영상 기획으로 바꿀 수 있습니다. 이때 중요한 것은 "여러 API를 한 번에 호출한다"가 아니라, 원본 텍스트를 목적별 산출물로 나누는 구조입니다.

예를 들어 블로그 글 하나를 입력받는다면 서버는 먼저 이미지 프롬프트와 음성 대본을 만듭니다. 그다음 이미지 생성 API로 대표 이미지를 만들고, TTS API로 오디오 파일을 생성합니다. 마지막으로 결과 URL과 메타데이터를 화면에 전달하거나 DB에 저장합니다.

이미지와 음성 API 활용하기AI 생성 이미지

API Key는 여전히 서버에만 둔다

이미지와 음성 API도 텍스트 생성과 같은 원칙을 따릅니다. 클라이언트에서 OpenAI를 직접 호출하지 않습니다. Next.js에서는 app/api/*/route.ts 또는 Server Action에서 요청을 처리하고, OPENAI_API_KEY는 환경변수로만 읽습니다. 서버 전용 헬퍼를 만들어 두면 라우트마다 같은 설정을 반복하지 않아도 됩니다.1

// lib/ai.ts
import OpenAI from "openai";

export function getOpenAIClient() {
  const apiKey = process.env.OPENAI_API_KEY;
  if (!apiKey) throw new Error("Missing OPENAI_API_KEY");
  return new OpenAI({ apiKey });
}

브라우저가 서버에 보내는 값은 글 제목, 본문, 이미지 용도, 음성 톤 정도로 제한합니다. 서버는 길이, 허용된 이미지 크기, 금지 입력을 검증한 뒤 모델을 호출합니다.

이미지 생성 요청 설계하기

이미지 생성 요청에서 결과에 큰 영향을 주는 값은 프롬프트, 크기, 품질, 스타일입니다. 크기가 클수록 활용도는 높지만 비용과 응답 시간이 늘어날 수 있습니다. 품질 옵션도 마찬가지입니다. 그래서 서비스 기본값을 먼저 정해야 합니다.

블로그 대표 이미지는 보통 넓은 비율이 좋고, 카드뉴스는 정사각형, 영상 썸네일은 가로형이 적합합니다. 처음부터 모든 옵션을 사용자에게 열어 두기보다, 용도별 프리셋을 제공하는 편이 안정적입니다.

이미지 프롬프트는 재사용 가능한 템플릿으로 관리합니다.

용도: 블로그 대표 이미지
주제: {title}
핵심 메시지: {summary}
주체: {main_subject}
배경: 단순하고 현대적인 작업 공간
구도: 중앙에 핵심 오브젝트, 넉넉한 여백
색감: 차분한 파란색과 밝은 회색
분위기: 전문적이지만 친근함
제외 요소: 과도한 텍스트, 로고, 왜곡된 손, 복잡한 배경

특히 이미지 안의 글자는 부정확하게 생성될 수 있습니다. 제목, 버튼, 브랜드 문구는 이미지 생성 후 별도 편집 레이어로 넣는 것이 안전합니다.

이미지 생성 Route 예시

// app/api/image/route.ts
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { getOpenAIClient } from "@/lib/ai";

const Schema = z.object({
  prompt: z.string().min(10).max(1200),
  size: z.enum(["1024x1024", "1536x1024", "1024x1536"]),
  quality: z.enum(["low", "medium", "high"]).default("medium"),
});

export async function POST(req: NextRequest) {
  const { prompt, size, quality } = Schema.parse(await req.json());
  const openai = getOpenAIClient();

  const result = await openai.images.generate({
    model: "gpt-image-1",
    prompt,
    size,
    quality,
  });

  return NextResponse.json({ image: result.data?.[0] });
}

실서비스에서는 반환된 이미지를 그대로 오래 믿기보다, 파일 저장소에 저장하고 DB에는 파일 URL, 프롬프트 버전, 크기, 생성 시각을 함께 남깁니다.

TTS로 글을 듣기 좋은 대본으로 바꾸기

TTS는 Text To Speech의 약자로 텍스트를 음성으로 바꾸는 기능입니다. 좋은 음성을 만들려면 원문을 그대로 넣지 않는 것이 중요합니다. 블로그 글은 눈으로 읽는 문장이고, 오디오는 귀로 듣는 문장입니다.

따라서 먼저 음성 대본을 만듭니다. 긴 문장은 짧게 나누고, 어려운 기호와 표는 말로 풀어 씁니다. 문단 사이에는 자연스러운 여백을 넣고, 도입부에는 "이번 글에서는…"처럼 청취자를 안내하는 문장을 추가합니다.

// app/api/speech/route.ts
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { getOpenAIClient } from "@/lib/ai";

const Schema = z.object({
  script: z.string().min(5).max(4000),
  voice: z.enum(["alloy", "verse", "sage"]).default("alloy"),
});

export async function POST(req: NextRequest) {
  const { script, voice } = Schema.parse(await req.json());
  const openai = getOpenAIClient();

  const audio = await openai.audio.speech.create({
    model: "gpt-4o-mini-tts",
    voice,
    input: script,
    format: "mp3",
  });

  const buffer = Buffer.from(await audio.arrayBuffer());

  return new Response(buffer, {
    headers: { "Content-Type": "audio/mpeg" },
  });
}

목소리는 서비스 성격에 맞게 고릅니다. 학습 콘텐츠는 차분한 목소리, 짧은 홍보 영상은 밝고 빠른 목소리가 어울립니다. 속도와 문장 길이를 조정하면 같은 목소리도 훨씬 듣기 좋아집니다.

실습: 글 하나를 이미지와 오디오로 변환하기

최종 흐름은 다음처럼 설계할 수 있습니다.

  1. 사용자가 제목과 본문을 입력한다.

  2. 서버가 입력을 검증한다.

  3. 텍스트 모델이 imagePrompt, audioScript, storyboard를 JSON으로 만든다.

  4. 이미지 Route가 대표 이미지를 생성한다.

  5. Speech Route가 내레이션 오디오를 생성한다.

  6. 클라이언트는 이미지 URL, 오디오 URL, 스토리보드를 렌더링한다.

여기서 핵심은 중간 결과를 분리하는 것입니다. 이미지 생성이 실패해도 음성 대본은 저장할 수 있어야 합니다. 오디오 생성이 늦어도 먼저 대표 이미지를 보여 줄 수 있어야 합니다. 멀티모달 AI 기능은 한 번의 마법 같은 호출이 아니라, 작은 생성 작업을 안전하게 연결한 파이프라인입니다.

참고

1Explain how to integrate OpenAI's API into a Next.js app with practical code examples

책 목록

처음 만나는 AI API 개발: OpenAI API로 서비스 기능 만들기

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기