React

[TIL/React] 2025/01/26

Google AI Studio ์ ์šฉํ•˜๊ธฐ ๐Ÿ”ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ด€๋ จ Q&A ์‚ฌ์ดํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉฐ ์ƒ๊ฒจ๋‚œ ์ถ”๊ฐ€์ ์ธ ์งˆ๋ฌธ์„, ์„œ๋น„์Šค ๋‚ด์—์„œ AI์—๊ฒŒ ์งˆ๋ฌธํ•  ์ˆ˜ ์žˆ๋„๋ก, ๊ด€๋ จ ํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ฐœํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.Google AI Studio๋ฅผ ํ™œ์šฉํ–ˆ๋‹ค.Get API Key ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ ๋’ค, AP

2025๋…„ 1์›” 26์ผ2min read

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 ๐ŸŒฟ

code
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 ๐ŸŒฟ

code
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 ๐ŸŒฟ

code
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. ๋””ํ…Œ์ผํ•œ ํ”„๋ก ํŠธ์—”๋“œ ์ฒ˜๋ฆฌ๊ฐ€ ์•„์ง ๋ถ€์กฑํ•จ

More to read

REST API

ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ์‚ฌ์ด

HTTP ์ƒํƒœ ์ฝ”๋“œ๋Š” ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐฑ์—”๋“œ๋กœ ๋ณด๋ƒˆ๋˜ ์š”์ฒญ์˜ ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์˜๋ฏธํ•˜๋Š” ์ผ์ข…์˜ ์•ฝ์†์ด๋ฉฐ, API๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ•ต์‹ฌ ์š”์†Œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ƒํƒœ ์ฝ”๋“œ์™€ ๊ด€๋ จํ•˜์—ฌ, ๋ฐฑ์—”๋“œ๋Š” ์ž˜ ๋ชจ๋ฅด๋Š” ํ”„๋ก ํŠธ์—”๋“œ์˜ ์Šฌํ”ˆ ์‚ฌ์ •์ด ์žˆ์Šต๋‹ˆ๋‹ค.์•„๋ž˜๋Š” ์š”์ฒญ์ด ์‹คํŒจํ–ˆ์Œ์—๋„, ๋ฐฑ์—”๋“œ์—์„œ ์ƒํƒœ ์ฝ”๋“œ

JWT

ํ† ํฐ ๊ด€๋ฆฌ ๋ฐฉ์‹ ํ†บ์•„๋ณด๊ธฐ

0. ๋“ค์–ด๊ฐ€๋ฉฐ ๐ŸŽฏ ์„œ๋น„์Šค์— ์ ‘๊ทผํ•˜๋ ค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ ์‚ฌ์šฉ์ž ์ธ์ฆ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฃผ์–ด์ง„ ๊ถŒํ•œ์„ ํ™•์ธํ•˜๋Š” ์ž‘์—…์€ ์ธ๊ฐ€๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ธ๊ฐ€๋Š” ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ธ์ฆ์—๋Š” ๋งŽ์€ ๋ฐฉ์‹์ด ์žˆ์ง€๋งŒ, ์˜ค๋Š˜์€ ์„ธ์…˜ ์ธ์ฆ ๋ฐฉ

A2A

A2A / MCP ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜

0. ๋“ค์–ด๊ฐ€๋ฉฐ โœ๏ธ Google for Developers์—, ๋ ˆ์Šคํ† ๋ž‘ ๊ณต๊ธ‰๋ง ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ ์—ฎ์€ 6๋Œ€ ํ”„๋กœํ† ์ฝœ(MCP, A2A, UCP, AP2, A2UI, AG-UI)์— ๋Œ€ํ•œ ๊ฐ€์ด๋“œ๊ฐ€ ๊ฒŒ์‹œ๋œ ์ดํ›„, MCP์™€ A2A๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•ด ๋ณด๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ