๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

ํ•™์Šต ๊ธฐ๋ก (Learning Logs)/CS Study

์›นํˆฐ ์ƒ์„ฑ AI(Webtoon Maker)๋ฅผ ์œ„ํ•œ ์„œ๋ฒ„ ์„ค๊ณ„

๐Ÿ“Œ์ „์ฒด ์•„ํ‚คํ…์ฒ˜ 

์›นํˆฐ ์ƒ์„ฑ ์„œ๋น„์Šค๋Š” ํฌ๊ฒŒ 5๊ฐ€์ง€ ํ•ต์‹ฌ ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  1. Frontend (์›น/์•ฑ)
    • ์œ ์ €๊ฐ€ ์›นํˆฐ์„ ๋งŒ๋“ค๊ณ  ์—…๋กœ๋“œํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค
  2. Backend API (Spring Boot)
    • ์œ ์ € ์ธ์ฆ, ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ ์ฒ˜๋ฆฌ, ์›นํˆฐ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
  3. AI Model Server (Python, FastAPI, Flask) ---> ai ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์ง€ ๋ง์ง€
    • AI ๋ชจ๋ธ์„ ํ™œ์šฉํ•ด ์ด๋ฏธ์ง€ ์ƒ์„ฑ, ํŽธ์ง‘ ๋ฐ ์Šคํƒ€์ผ ๋ณ€ํ™˜ ์ˆ˜ํ–‰
  4. Database (PostgreSQL, Redis)
    • ์œ ์ €, ์›นํˆฐ ์ •๋ณด, ์„ค์ • ๊ฐ’ ์ €์žฅ
  5. Storage (S3/MinIO)
    • ์›นํˆฐ ์›๋ณธ ์ด๋ฏธ์ง€ ๋ฐ ์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ ์ €์žฅ
    • S3๋ฅผ ์ง์ ‘ ๊ตฌ์ถ•ํ•ด์„œ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด MinIO

๐Ÿ“Œ SSE๋ฅผ ํ™œ์šฉํ•œ ์„œ๋ฒ„ ์„ค๊ณ„

โœ… SSE(Server-Sent Events)์™€ Kafka๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์›นํˆฐ ์ƒ์„ฑ ์ƒํƒœ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์กฐ ์„ค๊ณ„
โœ… ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ์€ Kafka๋ฅผ ํ†ตํ•ด AI ์„œ๋ฒ„๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, AI ์„œ๋ฒ„๋Š” SSE๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ƒํƒœ ์ „์†ก
โœ… ์ตœ์ข… ์›นํˆฐ ์ด๋ฏธ์ง€๋Š” S3/MinIO์— ์ €์žฅ๋˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๋Š” ์ƒ์„ฑ์ด ์™„๋ฃŒ๋˜๋ฉด ํ•ด๋‹น ์ด๋ฏธ์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Œ

๐Ÿš€ ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋Š” ์›นํˆฐ์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ๊ณผ์ •์„ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ! ๐Ÿ”ฅ

๐Ÿš€ SSE(Server-Sent Events)๋ž€?

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๊ณ , ์„œ๋ฒ„๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” HTTP ๊ธฐ๋ฐ˜์˜ ํ†ต์‹  ๋ฐฉ์‹.
  • ์ฑ„ํŒ…, ์ŠคํŠธ๋ฆฌ๋ฐ, AI ์ž‘์—… ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๊ฐ™์€ ์‹ค์‹œ๊ฐ„ ์‘์šฉ์— ์ ํ•ฉ.
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚         Client (React)        โ”‚
                     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                     โ”‚               โ”‚               โ”‚
                     โ”‚      SSE (์›นํˆฐ ์ƒ์„ฑ ์ƒํƒœ)        โ”‚
                     โ”‚               โ”‚               โ”‚
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                โ”‚
        โ”‚   Webtoon API Server      โ”‚                โ”‚
        โ”‚   (Spring Boot + SSE)     โ”‚                โ”‚
        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                โ”‚
        โ”‚           โ”‚ Kafka         โ”‚                โ”‚
        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                โ”‚
        โ”‚       AI Model Server     โ”‚                โ”‚
        โ”‚       (FastAPI, PyTorch)  โ”‚                โ”‚
        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                โ”‚
        โ”‚      S3 / MinIO (Storage) โ”‚                โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

 

 

(1) ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ

๐Ÿ“Œ ์š”์ฒญ API (POST /api/webtoon/generate)

  • ์œ ์ €๊ฐ€ ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด, ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ๋จ.
  • Kafka๋ฅผ ํ†ตํ•ด AI ๋ชจ๋ธ ์„œ๋ฒ„๋กœ ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ์„ ๋ณด๋ƒ„.
@PostMapping("/api/webtoon/generate")
public ResponseEntity<String> generateWebtoon(@RequestBody WebtoonRequest request) {
    String taskId = UUID.randomUUID().toString();
    
    // Kafka๋ฅผ ํ†ตํ•ด AI ์„œ๋ฒ„๋กœ ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ
    webtoonProducer.sendMessage("webtoon-tasks", taskId, request);

    return ResponseEntity.ok(taskId);
}

 

 

(2) ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›นํˆฐ ์ƒ์„ฑ ์ƒํƒœ ๊ตฌ๋… (SSE)

๐Ÿ“Œ SSE ์—ฐ๊ฒฐ API (GET /api/webtoon/status/{taskId})

  • ํด๋ผ์ด์–ธํŠธ๋Š” SSE๋ฅผ ํ†ตํ•ด ์›นํˆฐ ์ƒ์„ฑ ์ƒํƒœ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ.
  • AI ๋ชจ๋ธ์ด ์ง„ํ–‰ ์ƒํƒœ๋ฅผ Kafka๋กœ ์ „์†กํ•˜๋ฉด, ์ด๋ฅผ SSE๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌ.
@GetMapping(value = "/api/webtoon/status/{taskId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter subscribeWebtoonStatus(@PathVariable String taskId) {
    SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);

    webtoonStatusService.addEmitter(taskId, emitter);

    emitter.onCompletion(() -> webtoonStatusService.removeEmitter(taskId));
    emitter.onTimeout(() -> webtoonStatusService.removeEmitter(taskId));

    return emitter;
}

 

(3) AI ์„œ๋ฒ„๊ฐ€ ์›นํˆฐ ์ƒ์„ฑ ํ›„ ์ƒํƒœ ์—…๋ฐ์ดํŠธ

๐Ÿ“Œ AI ์„œ๋ฒ„ (FastAPI)

  • AI ๋ชจ๋ธ์ด Kafka์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„ ์›นํˆฐ์„ ์ƒ์„ฑํ•˜๊ณ  ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•จ.
from kafka import KafkaConsumer, KafkaProducer
import json
import time

consumer = KafkaConsumer(
    'webtoon-tasks',
    bootstrap_servers='kafka:9092',
    value_deserializer=lambda x: json.loads(x.decode('utf-8'))
)

producer = KafkaProducer(
    bootstrap_servers='kafka:9092',
    value_serializer=lambda x: json.dumps(x).encode('utf-8')
)

for message in consumer:
    task_id = message.key
    data = message.value

    # 1. ์›นํˆฐ ์ƒ์„ฑ ์‹œ์ž‘
    producer.send('webtoon-status', key=task_id, value={"status": "started"})
    time.sleep(2)

    # 2. AI ๋ชจ๋ธ ์‹คํ–‰ (๊ฐ€์ •)
    producer.send('webtoon-status', key=task_id, value={"status": "generating"})
    time.sleep(5)

    # 3. ์ƒ์„ฑ ์™„๋ฃŒ
    image_url = f"https://s3.bucket.com/{task_id}.png"
    producer.send('webtoon-status', key=task_id, value={"status": "completed", "url": image_url})

 

 

(4) ์„œ๋ฒ„๊ฐ€ SSE๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์— ์ƒํƒœ ์ „๋‹ฌ

//๐Ÿ“Œ Spring Boot์—์„œ Kafka ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„ SSE๋กœ ์ „์†ก
@KafkaListener(topics = "webtoon-status")
public void listenWebtoonStatus(@Payload String message, @Header(KafkaHeaders.RECEIVED_KEY) String taskId) {
    webtoonStatusService.sendUpdate(taskId, message);
}
//๐Ÿ“Œ SSE ์ƒํƒœ ์—…๋ฐ์ดํŠธ ์„œ๋น„์Šค
@Service
public class WebtoonStatusService {
    private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

    public void addEmitter(String taskId, SseEmitter emitter) {
        emitters.put(taskId, emitter);
    }

    public void sendUpdate(String taskId, String status) {
        SseEmitter emitter = emitters.get(taskId);
        if (emitter != null) {
            try {
                emitter.send(SseEmitter.event().data(status));
            } catch (IOException e) {
                emitter.complete();
                emitters.remove(taskId);
            }
        }
    }

    public void removeEmitter(String taskId) {
        emitters.remove(taskId);
    }
}

 

4. ๐Ÿ“Œ SSE๋ฅผ ํ™œ์šฉํ•œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ (React)

//๐Ÿ“Œ React์—์„œ SSE๋ฅผ ํ†ตํ•ด ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋ฐ›๊ธฐ
import { useState, useEffect } from "react";

const WebtoonGenerator = ({ taskId }) => {
    const [status, setStatus] = useState("Waiting...");

    useEffect(() => {
        const eventSource = new EventSource(`/api/webtoon/status/${taskId}`);

        eventSource.onmessage = (event) => {
            const data = JSON.parse(event.data);
            setStatus(data.status);

            if (data.status === "completed") {
                console.log("์›นํˆฐ ์ƒ์„ฑ ์™„๋ฃŒ:", data.url);
                eventSource.close();
            }
        };

        return () => eventSource.close();
    }, [taskId]);

    return <div>์›นํˆฐ ์ƒํƒœ: {status}</div>;
};

๐Ÿ“Œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜ (MSA)

โœ… Spring Boot API + FastAPI AI ์„œ๋ฒ„ ๋ถ„๋ฆฌํ•˜์—ฌ ํ™•์žฅ์„ฑ ์žˆ๋Š” ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„

โœ… Kafka ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์›นํˆฐ ์ƒ์„ฑ ์ฒ˜๋ฆฌ

โœ… Redis ์บ์‹ฑ ๋ฐ JWT ์ธ์ฆ ์ ์šฉ

โœ… S3 / MinIO๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ €์žฅ

โœ… Kubernetes ๊ธฐ๋ฐ˜ AI ์„œ๋ฒ„ ๋ฐฐํฌ (GPU ์Šค์ผ€์ผ๋ง)

๐Ÿš€ ์›นํˆฐ ์ƒ์„ฑ AI ์„œ๋น„์Šค๊ฐ€ ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ณ , ๋Œ€๋Ÿ‰์˜ ์›นํˆฐ ์š”์ฒญ๋„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ! ๐Ÿš€

                         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                         โ”‚         FRONTEND (React)     โ”‚
                         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                        โ”‚
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ”‚      API GATEWAY (Spring Cloud Gateway)   โ”‚
                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                               โ”‚
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚                                                  โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Webtoon API (Spring) โ”‚                     โ”‚ AI Model Server     โ”‚
โ”‚  - ์œ ์ € ์ธ์ฆ (JWT)     โ”‚                     โ”‚ (FastAPI, PyTorch)  โ”‚
โ”‚  - ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ       โ”‚                     โ”‚ - ์›นํˆฐ ์Šคํƒ€์ผ ์ ์šฉ      โ”‚
โ”‚  - DB ์ €์žฅ            โ”‚                     โ”‚ - AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ       โ”‚
โ”‚  - ์ž‘์—… ์ƒํƒœ ๊ด€๋ฆฌ       โ”‚                     โ”‚ - Task Queue ๊ด€๋ฆฌ    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚                                           โ”‚
           โ”‚                                           โ”‚
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚   PostgreSQL      โ”‚                       โ”‚    S3             โ”‚
    โ”‚  (์œ ์ € & ์›นํˆฐ ์ •๋ณด)  โ”‚                       โ”‚   (์ด๋ฏธ์ง€ ์ €์žฅ)      โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
์‚ฌ์šฉ์ž โ†’ Gateway โ†’ API ์„œ๋ฒ„ โ†’ AI ์„œ๋ฒ„ (ML ๋ชจ๋ธ) โ†’ Storage
 

์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด Kafka๋ฅผ ํ†ตํ•ด AI ์„œ๋ฒ„๋กœ ์ „๋‹ฌ 

AI ์„œ๋ฒ„๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด Webtoon API ์„œ๋ฒ„์—์„œ ์ตœ์ข… ๊ฒฐ๊ณผ ์ €์žฅ

 
 

๊ฐ ์„œ๋น„์Šค ์—ญํ• 

  • Gateway (Spring Cloud Gateway)
    • API ๋ผ์šฐํŒ… ๋ฐ ์ธ์ฆ ์ฒ˜๋ฆฌ
  • Webtoon API (Spring Boot)
    • ์œ ์ € ์ธ์ฆ, ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ ์ฒ˜๋ฆฌ, DB ์—ฐ๋™
  • AI Model Server (Python, FastAPI)
    • ์›นํˆฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฐ ํ•„ํ„ฐ ์ ์šฉ
  • File Storage (S3 / MinIO)
    • ์›นํˆฐ ์ด๋ฏธ์ง€ ์ €์žฅ ๋ฐ ์บ์‹ฑ

 

Gateway (Spring Cloud Gateway)

  • JWT ์ธ์ฆ ์ ์šฉ (X-User-Id, X-User-Role ํ—ค๋” ์ „๋‹ฌ)
  • API ์š”์ฒญ์„ ์ ์ ˆํ•œ ์„œ๋ฒ„๋กœ ๋ผ์šฐํŒ… (/api/** โ†’ Webtoon API, /ml/** โ†’ AI ์„œ๋ฒ„)

Webtoon API (Spring Boot)

๐Ÿ“Œ ์ฃผ์š” ๊ธฐ๋Šฅ

  • ์œ ์ € ์ธ์ฆ ๋ฐ ์„ธ์…˜ ๊ด€๋ฆฌ (JWT)
  • ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ ๊ด€๋ฆฌ (๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ)
  • ์ƒ์„ฑ๋œ ์›นํˆฐ ์ €์žฅ ๋ฐ ์กฐํšŒ
  • Redis ์บ์‹ฑ ์ ์šฉ (์ž์ฃผ ์กฐํšŒ๋˜๋Š” ๋ฐ์ดํ„ฐ)

 

Webtoon API ๋ช…์„ธ์„œ

Method Endpoint  
POST /api/webtoon ์ƒˆ๋กœ์šด ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ
GET /api/webtoon/{id} ํŠน์ • ์›นํˆฐ ์ƒ์„ธ ์กฐํšŒ
GET /api/webtoon/list ์‚ฌ์šฉ์ž์˜ ์›นํˆฐ ๋ฆฌ์ŠคํŠธ
DELETE /api/webtoon/{id} ํŠน์ • ์›นํˆฐ ์‚ญ์ œ

 


AI Model Server (FastAPI)

๐Ÿ“Œ ์—ญํ• 

  • ์›นํˆฐ ์Šคํƒ€์ผ ๋ณ€ํ™˜ ๋ฐ AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ
  • ์›นํˆฐ ์ƒ‰๊ฐ ๋ณด์ •, ์Šคํƒ€์ผ ๋ณ€ํ™” ๋“ฑ ์ถ”๊ฐ€ ๋ชจ๋ธ ์ œ๊ณต ๊ฐ€๋Šฅ

AI API ๋ช…์„ธ์„œ

Method Endpoint  
POST /ml/generate ์›นํˆฐ ์ƒ์„ฑ ์š”์ฒญ
POST /ml/style/{id} ์Šคํƒ€์ผ ๋ณ€ํ™˜
POST /ml/status/{taskId} ์ž‘์—… ์ƒํƒœ ์กฐํšŒ

 


๊ทธ๋ฆผ AI ๋ชจ๋ธ

https://modulabs.co.kr/blog/controlnet-stable-diffusion

 

ControlNet ์œผ๋กœ ์ด๋ฏธ์ง€์ƒ์„ฑ (feat. Stable Diffusion)

Stable Diffusion์€ ๋†€๋ผ์šด ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ์—ˆ์œผ๋‚˜ ๋”์šฑ ์„ธ๋ถ€์ ์ธ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•จ์„ ์•Œ๊ฒŒ ๋˜์–ด ControlNet ์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์ด ์ œ์•ˆ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ControlNet ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์„ฑ ๊ณผ์ •์„ ๋”์šฑ ์„ธ๋ถ€์ ์œผ๋กœ ์ œ์–ด

modulabs.co.kr

 


Database (PostgreSQL + Redis)

  • PostgreSQL โ†’ ์œ ์ € ์ •๋ณด, ์›นํˆฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ
  • Redis โ†’ ์ž‘์—… ์ƒํƒœ, ์บ์‹ฑ, ์„ธ์…˜ ๊ด€๋ฆฌ
CREATE TABLE webtoon (
    id UUID PRIMARY KEY,
    user_id UUID NOT NULL,
    title VARCHAR(255) NOT NULL,
    status VARCHAR(50) CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
    image_url TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);

 

 

Storage (S3)

AI ๋ชจ๋ธ์ด ์ƒ์„ฑํ•œ ์›นํˆฐ ์ด๋ฏธ์ง€๋ฅผ S3์— ์ €์žฅ

s3://webtoon-images/{userId}/{webtoonId}/cover.jpg
s3://webtoon-images/{userId}/{webtoonId}/page1.jpg

 


 

'ํ•™์Šต ๊ธฐ๋ก (Learning Logs) > CS Study' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€