[TIL/React] 2025/01/26

์›๋ฏผ๊ด€ยท2025๋…„ 1์›” 26์ผ

[TIL]

๋ชฉ๋ก ๋ณด๊ธฐ
167/201
post-thumbnail

Google AI Studio ์ ์šฉํ•˜๊ธฐ ๐Ÿ”

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ด€๋ จ Q&A ์‚ฌ์ดํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉฐ ์ƒ๊ฒจ๋‚œ ์ถ”๊ฐ€์ ์ธ ์งˆ๋ฌธ์„, ์„œ๋น„์Šค ๋‚ด์—์„œ AI์—๊ฒŒ ์งˆ๋ฌธํ•  ์ˆ˜ ์žˆ๋„๋ก, ๊ด€๋ จ ํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ฐœํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

Google AI Studio๋ฅผ ํ™œ์šฉํ–ˆ๋‹ค.

1. ์ดˆ๊ธฐ ์„ค์ • โš™๏ธ

1-1. Get API Key ๐ŸŒฟ

Get API Key ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ ๋’ค, API ํ‚ค ๋งŒ๋“ค๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ API Key๋ฅผ ๋ฐœ๊ธ‰๋ฐ›๋Š”๋‹ค.

๊ฒฐ์ œ ์„ค์ •์„ ๋”ฐ๋กœ ํ•˜์ง€ ์•Š์•˜๊ธฐ์—, ๊ธฐ๋ณธ์š”๊ธˆ์ œ๋Š” '๋ฌด๋ฃŒ'๋กœ ์ ์šฉ๋œ๋‹ค.

1-2. Gemini SDK Initialization ๐ŸŒฟ

SDK ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•œ๋‹ค. ํ–ฅํ›„ ํ•ด๋‹น SDK ํŒจํ‚ค์ง€๋ฅผ ํ†ตํ•ด genAI ๋ชจ๋ธ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ๊ตฌํ˜„ ํ๋ฆ„ โš™๏ธ

2-1. Overall Flow ๐ŸŒฟ

๊ธฐ๋ณธ์ ์œผ๋กœ AskAIPage์—์„œ ์งˆ๋ฌธํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด, ์„œ๋ฒ„ ์ฃผ์†Œ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ prompt์— ๋Œ€ํ•œ POST ์š”์ฒญ์ด ์ง„ํ–‰๋œ๋‹ค.

์š”์ฒญ์„ ๋ฐ›๋Š” ์„œ๋ฒ„์˜ ๊ฒฝ๋กœ๋Š” controller ์ƒ์— ๋ช…์‹œ๋˜์–ด ์žˆ๊ณ , controller์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์„ธ๋ถ€ ๋กœ์ง์ธ generateContent ํ•จ์ˆ˜ ์ฝ”๋“œ๋Š” service์— ์ž‘์„ฑ๋˜์–ด ์žˆ๋‹ค.

์ตœ์ข…์ ์œผ๋กœ controller์—์„œ ์ฒ˜๋ฆฌ๋œ response ๊ฐ’์„ state์— ์ €์žฅํ•˜์—ฌ front-end์—์„œ ๋ Œ๋”๋ง ํ•œ๋‹ค.

2-2. gemini.module.ts ๐ŸŒฟ

import { Module } from '@nestjs/common';

import { GoogleGenerativeAIService } from './gemini.service';
import { GoogleGenerativeAIController } from './gemini.controller';

@Module({
  controllers: [GoogleGenerativeAIController],
  providers: [GoogleGenerativeAIService],
})
export class GeminiModule {}

์ปจํŠธ๋กค๋Ÿฌ์™€ ์„œ๋น„์Šค๋ฅผ ๋ชจ๋“ˆ ๋‹จ์œ„๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด gemini.module.ts ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ๋‹ค. ์ด ํŒŒ์ผ์€ ์ตœ์ƒ๋‹จ app.module.ts์— ๋“ฑ๋ก๋˜์–ด์•ผ ํ•œ๋‹ค.

2-3. gemini.controller.ts ๐ŸŒฟ

import { Controller, Post, Body } from '@nestjs/common';
import { GoogleGenerativeAIService } from './gemini.service';

@Controller('api/ask-ai')
export class GoogleGenerativeAIController {
  constructor(
    private readonly googleGenerativeAIService: GoogleGenerativeAIService,
  ) {}

  @Post()
  async askAI(@Body('prompt') prompt: string): Promise<{ result: string }> {
    try {
      const result =
        await this.googleGenerativeAIService.generateContent(prompt);
      return { result };
    } catch (error) {
      console.error('Error in GoogleGenerativeAIController:', error);
      return { result: 'Failed to generate content from Google Generative AI' };
    }
  }
}

์š”์ฒญ์˜ body์—์„œ prompt๋ฅผ ๋ฐ›์•„์™€์„œ, ์„œ๋น„์Šค ํŒŒ์ผ์— ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š” generateContent ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•œ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜์˜ return ๊ฐ’์„ result์— ์ €์žฅํ•œ ๋’ค ์ตœ์ข…์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

2-4. gemini.service.ts ๐ŸŒฟ

import { Injectable } from '@nestjs/common';
import { GoogleGenerativeAI } from '@google/generative-ai';

@Injectable()
export class GoogleGenerativeAIService {
  private genAI: GoogleGenerativeAI;

  constructor() {
    const apiKey = process.env.GEMINI_API_KEY;
    if (!apiKey) {
      throw new Error('API Key is required');
    }
    this.genAI = new GoogleGenerativeAI(apiKey);
  }

  async generateContent(prompt: string): Promise<string> {
    try {
      const model = this.genAI.getGenerativeModel({ model: 'gemini-pro' });

      const result = await model.generateContent(prompt);
      const response = await result.response;
      const text = await response.text(); 

      return text;
    } catch (error) {
      console.error('Google Generative AI Error:', error);
      throw new Error('Failed to generate content from Google Generative AI');
    }
  }
}

env ํŒŒ์ผ์— ๋ฏธ๋ฆฌ ์ž‘์„ฑํ•ด๋†“์€ apiKey๋ฅผ GoogleGenerativeAI ํ•จ์ˆ˜์— ์ „๋‹ฌํ•ด์„œ genAI๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์ดํ›„ ํ•ด๋‹น ํด๋ž˜์Šค์— getGenerativeModel์„ ํ†ตํ•ด gemini-pro ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ๋ช…์‹œํ•œ๋‹ค.

model.generateContent(prompt)๋ฅผ ํ†ตํ•ด prompt์— ๋Œ€ํ•œ ์ฝ˜ํ…์ธ ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. prompt๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ์ „๋‹ฌ๋œ ํ…์ŠคํŠธ๋กœ, Google Generative AI ๋ชจ๋ธ์ด ํ•ด๋‹น ํ…์ŠคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋œ๋‹ค.

์ตœ์ข…์ ์œผ๋กœ response.text()๋ฅผ ํ†ตํ•ด ์‘๋‹ต์œผ๋กœ๋ถ€ํ„ฐ ํ…์ŠคํŠธ๋ฅผ ์ถ”์ถœํ•œ๋‹ค.

3. ๊ตฌํ˜„ ํ™”๋ฉด โš™๏ธ

3-1. Light Mode ๐ŸŒฟ

3-2. Dark Mode ๐ŸŒฟ

4. ๋ณด์•ˆ์  โš™๏ธ

  1. ๊ตฌํ˜„์— ์ง‘์ค‘ํ•ด์„œ Gemini ๋ฌธ์„œ๋ฅผ ์•„์ง ์ •๋…ํ•˜์ง€๋Š” ์•Š์Œ
  2. ๋ชจ๋ธ ์ด๋ฆ„์ด ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ๋Š”๋ฐ, ์œ ์—ฐ์„ฑ์„ ์žƒ์„ ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ฆ
  3. ๋””ํ…Œ์ผํ•œ ํ”„๋ก ํŠธ์—”๋“œ ์ฒ˜๋ฆฌ๊ฐ€ ์•„์ง ๋ถ€์กฑํ•จ
profile
Write a little every day, without hope, without despair โœ๏ธ

0๊ฐœ์˜ ๋Œ“๊ธ€