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

Amazon VPC

Amazon VPC Architecture ์ดํ•ดํ•˜๊ธฐ

์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐํšํ•˜๋ฉฐ, ๊ฐœ๋ฐœ์—์„œ ๋ฌด์—‡์„ ๊ฐ€์žฅ ๋จผ์ € ๊ณ ๋ฏผํ•ด์•ผ ํ•˜๋Š”์ง€ ๋‹ค์‹œ ๋Œ์•„๋ณด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.ํ•œ๋•Œ๋Š” ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ๋ชจ๋“  ์„ค๊ณ„์˜ ์ถœ๋ฐœ์ ์ด๋ผ๊ณ  ๋ฏฟ์—ˆ์Šต๋‹ˆ๋‹ค. ์œ ์ €๊ฐ€ ๋ฌด์—‡์„ ๋ณด๊ณ , ์–ด๋–ค ํ๋ฆ„์—์„œ ๋จธ๋ฌด๋ฅด๊ณ  ์ดํƒˆํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์ดํ•ด ์—†์ด ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ ๋‹ค๋Š” ๊ฑด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ

'์›์‚ฌ์ดํŠธ'

ํ”„๋ก ํŠธ์—”๋“œ ๊ด€์ ์œผ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ดํ•ดํ•˜๊ธฐ

์˜ค๋žœ๋งŒ์— ๋ฐฉ๋ฒ•๋ก ์— ๊ด€ํ•œ ๊ธ€์„ ์“ฐ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ตœ๊ทผ ์ƒํ™ฉ์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค. SSAFY์—์„œ๋Š” ํ•˜๋ฃจ์— ์—„์ฒญ๋‚œ ์–‘์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ๋“ค์„ ๊ณผ์ œ๋กœ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ, '๊ตฌํ˜„๋ ฅ'์ด ๋งค์šฐ ๋–จ์–ด์ง„๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์™„์ „ํžˆ ์–ด๋ ค์šด ๋ฌธ์ œ๋ผ๋ฉด '์•„์‰ฌ์›€'์ด๋ผ๋Š” ๊ฐ์ •์กฐ์ฐจ ๋А๋ผ์ง€

Subnet

VPC ์„ค๊ณ„์˜ ์‹œ์ž‘: IP์™€ Subnet

๋ฐ˜๋ณต๋˜๋Š” ๋ฃจํ‹ด ์†์—์„œ ์–ป์€ ์•ˆ์ •๊ฐ์„ ๋ฐœํŒ ์‚ผ์•„, ์ด์ œ๋Š” ๊ธฐ์ˆ ์  ์ŠคํŽ™ํŠธ๋Ÿผ์„ ๋„“ํžˆ๊ธฐ ์œ„ํ•œ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์— ์ฐฉ์ˆ˜ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์˜ ๋ชฉํ‘œ๋Š” ๋‹จ์ˆœํ•œ ํฌํŠธํด๋ฆฌ์˜ค ๊ตฌ์ถ•์„ ๋„˜์–ด, ์‹ค์ œ ์„œ๋น„์Šค ์ˆ˜์ค€์˜ ๋ธ”๋กœ๊ทธ ์‹œ์Šคํ…œ ๊ตฌํ˜„๊ณผ ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ ์ ์šฉ ๋“ฑ ์‹ค๋ฌด์— ๊ฐ€๊นŒ์šด ์—ญ๋Ÿ‰์„ ํ•œ ๋‹จ๊ณ„