๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ

[ํ† ์ดํ”„๋กœ์ ํŠธ] ๊ฐ„๋‹จํ•œ ํด๋ฆฝ ์˜์ƒ ํ™”์žฌ ํƒ์ง€ ์›น ์„œ๋น„์Šค ๋งŒ๋“ค์–ด๋ณด๊ธฐ

by kaizen_bh 2025. 5. 18.

 

 

 

์˜ฌํ•ด 3์›”๋ถ€ํ„ฐ 5์›”๊นŒ์ง€ ๋“ฃ๋Š” ICT ์ด๋…ธ๋ฒ ์ด์…˜ ์Šคํ€˜์–ด ์ธ๊ณต์ง€๋Šฅ ๋น„์ „์ปดํ“จํŒ… ๊ณผ์ •์—์„œ ๋งˆ์ง€๋ง‰ 2์ฃผ๊ฐ„ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ์‹œ๊ฐ„์ด ์žˆ๋‹ค

 

์–ด๋–ค๊ฑธ ํ•ด๋ณด๋ฉด ์ข‹์„๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์ด์ „ ์—…๋ฌด์—์„œ ๋งก์•˜๋˜ ํ™”์žฌ ํƒ์ง€๋ฅผ ์›น์— ์˜ฌ๋ ค๋ณด๊ณ  ์›น์˜ ์ „์ฒด์ ์ธ ํ๋ฆ„์„ ํ•œ๋ฒˆ ๊ฒฝํ—˜ํ•ด๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค ์‹ถ์–ด์„œ ์›น์— ์งง์€ ํ™”์žฌ ํด๋ฆฝ ์˜์ƒ์„ ์—…๋กœ๋“œํ•˜๋ฉด ํƒ์ง€ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฐ„๋‹จํ•œ AI๋ฅผ ์˜ฌ๋ฆฐ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ธฐ๋กœ ํ•˜์˜€๋‹ค

์›น, ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ ๋ถ€๋ถ„์€ ์ „ํ˜€ ๋‹ค๋ค„๋ณธ ์ ์ด ์—†์—ˆ๊ธฐ์— ๋ชจ๋“  ๋‚ด์šฉ๋“ค์ด ์ƒˆ๋กœ์› ๋‹ค

 

๋จผ์ € ์ „์ฒด์ ์ธ ๊ณ„ํš์„ ๋จผ์ € ์„ธ์›Œ๋ณด๊ณ  ์‹ค์ œ๋กœ ๊ณ„ํš๋Œ€๋กœ ์ง„ํ–‰๋˜์—ˆ๋Š”์ง€, ์ง„ํ–‰ํ•˜๋ฉด์„œ ์–ด๋А ๋ถ€๋ถ„์ด ๋ง‰ํ˜”๊ณ  ์–ด๋–ค ์ด์Šˆ๋“ค์ด ๋ฐœ์ƒํ–ˆ๋Š”์ง€, ๊ณ„ํš์„ ์กฐ์ •ํ•˜์—ฌ ์–ด๋””๊นŒ์ง€ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ–ˆ๋Š”์ง€ ๋“ฑ ๊ณ„ํš๊ณผ ์‹ค์ œ ์ง„ํ–‰ ๋‚ด์šฉ์„ ๋น„๊ตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค

์ˆ˜์—… ๋‚ด์šฉ ๋ฐ ์ž๋ฃŒ๋“ค์„ ๋ฒ ์ด์Šค๋กœ ํ•˜์—ฌ ๊ธฐ์ค€ ์‚ผ๊ณ  ์›ํ•˜๋Š” ๋ฐฉํ–ฅ์„ฑ์— ๋งž๊ฒŒ ์ปค์Šคํ…€ํ•˜๋Š” ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜์˜€๋‹ค

 

์ง€๊ธˆ ์ ์€ ๊ณ„ํš๋“ค์€ ๊ฑฐ์ฐฝํ–ˆ์œผ๋‚˜..(๋‚ด ๊ธฐ์ค€) ๋ง‰์ƒ ํ•ด๋ณด๋‹ˆ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„๋“ค์ด ์ •๋ง ๋งŽ์•˜๋‹ค

 

 

 


 

 

๐Ÿ“Œ ํ”„๋กœ์ ํŠธ๋ช…

FireClip AI: ํด๋ฆฝ ์˜์ƒ ๊ธฐ๋ฐ˜ ํ™”์žฌ ํƒ์ง€ ์›น์„œ๋น„์Šค

 

 

๐ŸŽฏ 1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

ํ•ญ๋ชฉ ๋‚ด์šฉ
๋ชฉํ‘œ ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋กœ๋“œํ•œ ์‹ค๋‚ด CCTV ํด๋ฆฝ ์˜์ƒ์—์„œ ์—ฐ๊ธฐ ๋˜๋Š” ๋ถˆ๊ฝƒ์„ ์ž๋™ ํƒ์ง€ํ•˜๊ณ , ํƒ์ง€๋œ ๊ฒฐ๊ณผ(๋ฐ”์šด๋”ฉ๋ฐ•์Šค)๋ฅผ ๊ทธ๋ฆฐ ์˜์ƒ์œผ๋กœ ์›นํŽ˜์ด์ง€์— ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ๋Ÿ‰ ์›น์„œ๋น„์Šค ๊ตฌํ˜„
๊ธฐ์ˆ  ์Šคํƒ GCP, Flask, MongoDB, YOLO, OpenCV

 

 

 


๐Ÿงฑ 2. ๋ฐ์ดํ„ฐ ๊ตฌ์ถ• ๋ฐ ๋ชจ๋ธ ํ•™์Šต 

 

ํ•ญ๋ชฉ ๋‚ด์šฉ
์‚ฌ์šฉ ๋ฐ์ดํ„ฐ ํ˜•์‹ CCTV ํ˜•์‹์˜ ํด๋ฆฝ ์˜์ƒ ๋ฐ ์ด๋ฏธ์ง€
๋ผ๋ฒจ ํ•ญ๋ชฉ ์ˆ˜ ์—ฐ๊ธฐ/๋ถˆ๊ฝƒ 2๊ฐœ ํด๋ž˜์Šค ํฌํ•จ
๊ตฌ์ถ• ์ „๋žต (์ˆ˜์ง‘ ๊ฒฝ๋กœ) โœ… ๊ณต๊ฐœ ํ™”์žฌ/์—ฐ๊ธฐ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์…‹ ํ™œ์šฉ (AIhub, kaggle, Roboflow)
โœ… ํ•„์š”์‹œ ํฌ๋กค๋ง ๋˜๋Š” YouTube ํด๋ฆฝ์œผ๋กœ ๋ณด์™„
โœ… ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๋ฐ YOLO ํฌ๋งท์œผ๋กœ ๋ผ๋ฒจ๋ง

์ˆ˜์ง‘๋Ÿ‰ ์ตœ์†Œ 1000์žฅ ์ด๋ฏธ์ง€ (๋ผ๋ฒจ ํฌํ•จ)
์ด๋ฏธ์ง€ ํ•ด์ƒ๋„ 640×480 ~ 1920×1280 (1280x1080 ์ด์ƒ ๊ถŒ์žฅ)
๋ฐ์ดํ„ฐ๋‹น ํ‰๊ท  ์šฉ๋Ÿ‰ ์•ฝ 500 ~ 1,000KB
๋ผ๋ฒจ๋ง ๋„๊ตฌ Roboflow
๋ชจ๋ธ ์‚ฌ์šฉ ์ „๋žต ๐Ÿ“Œ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์„ ํƒ
โ‘  ์‚ฌ์ „ ํ•™์Šต๋œ YOLOv8 ๋ถˆ๊ฝƒ/์—ฐ๊ธฐ ๋ชจ๋ธ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
โ‘ก ๊ฒฝ๋Ÿ‰ ์ปค์Šคํ…€ ๋ฐ์ดํ„ฐ๋กœ ํŒŒ์ธํŠœ๋‹

 

 

๐Ÿงฑ 2-1. ๋ผ๋ฒจ๋ง ๊ธฐ์ค€ ๋ฐ ํ’ˆ์งˆ ๊ด€๋ฆฌ

ํ•ญ๋ชฉ  ๊ธฐ์ค€
๋ฐ”์šด๋”ฉ ๋ฐ•์Šค ์ตœ์†Œ ํฌํ•จ ์˜์—ญ, ํด๋ž˜์Šค๋ช… ํฌํ•จ
๋ถ„๋ฅ˜ ๋ผ๋ฒจ ๊ณ ์œ  ํด๋ž˜์Šค ID + ์„ค๋ช…
๊ฒ€์ˆ˜ ์ƒ˜ํ”Œ ๊ฒ€์ˆ˜ 20%
  • ์ €์žฅ ๋ฐ ๊ด€๋ฆฌ
    • ํ˜•์‹: YOLO TXT
    • ์ €์žฅ์†Œ: Google Drive
    • ๊ด€๋ฆฌํˆด: Roboflow
  • ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• ๊ณ„ํš
    • Noise, saturation, hue, hori flip, brightness

 

๐Ÿ’ป ์ผ๋ฐ˜ํ™” ์„ฑ๋Šฅ ๊ฒ€ํ† 

  • ํ•™์Šต๋ฐ์ดํ„ฐ์— ํฌํ•จ๋˜์ง€ ์•Š์€ ํƒ์ง€ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ 20์žฅ ์ด์ƒ์— ๋Œ€ํ•œ ํƒ์ง€๋Šฅ๋ ฅ ํ‰๊ฐ€
  • mAP ์„ฑ๋Šฅ์„ ์‚ฐ์ถœํ•˜์—ฌ 0.7 ์ด์ƒ์ด ๋˜๋„๋ก ํ•™์Šต ๋ฐ์ดํ„ฐ ์กฐ์ •

 

 

 

 

๐Ÿงฑ 2-2. ๋ฐ์ดํ„ฐ ๊ตฌ์ถ• ์ง„ํ–‰

์‚ฌ์šฉ ๋ฐ์ดํ„ฐ Roboflow,  AIํ—ˆ๋ธŒ,  Kaggle
๋ผ๋ฒจ๋ง ํˆด Roboflow

 

์‹ค์ œ CCTV์™€ ์œ ์‚ฌํ•œ 720p (1280 x 720) / 1080p(1920 x 1080 ) ํฌ๊ธฐ๋ฅผ ๊ฐ€์ง„ ์‹ค๋‚ด์˜ ์ด๋ฏธ์ง€๋ฅผ ๊ตฌํ•˜๊ธฐ๋Š” ์‰ฝ์ง€ ์•Š์Œ

  • ํŠนํžˆ CCTV ํ™”์žฌ ์ด๋ฏธ์ง€๋Š” ๋”๋”์šฑ ๊ตฌํ•˜๊ธฐ ์–ด๋ ต๋‹ค (๋ณด์•ˆ ๊ด€๋ จ ์ด์Šˆ ๋“ฑ ๊ณต์œ  ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋‹ค์ˆ˜)
  • Roboflow Kaggle ์—์„œ ๊ตฌํ•œ ์ด๋ฏธ์ง€๋“ค์€ ํ™”์งˆ์ด ๋‚ฎ์€ ์นด๋ฉ”๋ผ๋กœ ์ฐํžŒ ์˜์ƒ๋“ค์„ 640x640 ํฌ๊ธฐ๋กœ ๋ฆฌ์‚ฌ์ด์ฆˆํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„ ์ด๋ฏธ์ง€์˜ ํ€„๋ฆฌํ‹ฐ๊ฐ€ ๋งŽ์ด ๋–จ์–ด์ง
  • AIHub์˜ ๊ฒฝ์šฐ 1920x1080 ํฌ๊ธฐ์˜ ๊ณ ํ™”์งˆ ์ด๋ฏธ์ง€์ด์ง€๋งŒ ์•ผ์™ธ ์ดฌ์˜ ์ด๋ฏธ์ง€

 

1์ฐจ ๋ฐ์ดํ„ฐ์…‹ 

์›๋ณธ 730์žฅ ๋ผ๋ฒจ๋ง ๋ฐ ์ด๋ฏธ์ง€ ์ฆ๊ฐ• ์ ์šฉ ํ›„ ์ด 1810์žฅ

 

ํด๋ž˜์Šค๋ณ„ ๊ฐ์ฒด ๊ฐœ์ˆ˜

  • fire : 894 ๊ฐœ
  • smoke : 250 ๊ฐœ

Preprocessing

  • Auto-Orient: Applied
  • Resize: Stretch to 640x640

Augmentations

  • Outputs per training example: 3
  • 90° Rotate: Clockwise, Counter-Clockwise, Upside Down
  • Saturation: Between -25% and +25%
  • Brightness: Between -15% and +15%
  • Blur: Up to 2.5px
  • Noise: Up to 0.1% of pixels

๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

  • Train Set : 90%, 1620 ์žฅ
  • Valid Set : 8%, 146์žฅ
  • Test Set : 2%, 44์žฅ

 


 

 

 

2์ฐจ ๋ฐ์ดํ„ฐ์…‹ 

280์žฅ ์ถ”๊ฐ€ ๋ผ๋ฒจ๋ง ๋ฐ ์ด๋ฏธ์ง€ ์ฆ๊ฐ• ์ ์šฉ ํ›„ ์ด 2524์žฅ

 

ํด๋ž˜์Šค๋ณ„ ๊ฐ์ฒด ๊ฐœ์ˆ˜

  • fire : 1,134 ๊ฐœ
  • smoke : 518 ๊ฐœ

Preprocessing

  • Auto-Orient: Applied
  • Resize: Stretch to 640x640

Augmentations

  • Outputs per training example: 3
  • 90° Rotate: Clockwise, Counter-Clockwise, Upside Down
  • Saturation: Between -25% and +25%
  • Brightness: Between -15% and +15%
  • Blur: Up to 2.5px
  • Noise: Up to 0.1% of pixels
  • Shear: ±10° Horizontal, ±10° Vertical

๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

  • Train Set : 91%, 2286 ์žฅ
  • Valid Set : 7%, 187์žฅ
  • Test Set : 2%, 51์žฅ

 

 

๋ฐ์ดํ„ฐ ์ถœ์ฒ˜

 

 

 


 

 

๐Ÿงฑ 2-3. ๋ชจ๋ธ ํ•™์Šต ๊ฒฐ๊ณผ

 

ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ ๋ฐ ๋ชจ๋ธ ํŠœ๋‹

ํ™˜๊ฒฝ : Colab 

 

 

์ผ๋ฐ˜ ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ

from ultralytics import YOLO

# ๋ชจ๋ธ ์ดˆ๊ธฐํ™” (๊ฐ€๋ณ๊ฒŒ ์‹œ์ž‘: yolov8n.pt)
model = YOLO('yolov8n.pt')  # ๋˜๋Š” yolov8s.pt, yolov8m.pt ๋“ฑ

# ํ•™์Šต ์‹œ์ž‘
model.train(
    data='/content/data/data.yaml',
    epochs=50,
    imgsz=640,
    batch=16,
    project='yolov8_fire_detection',
    name='exp',
    exist_ok=True
)

 

  • 1,2์ฐจ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ํ•™์Šต
  • ๋” ๋‹ค์–‘ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์œผ๋กœ ์ž๋™์œผ๋กœ ์ตœ์ ์˜ ์กฐํ•ฉ ์ฐพ๋„๋ก wandb์˜ sweep ๊ธฐ๋Šฅ ์‚ฌ์šฉ 

 

 

 

 

Wandb Sweep๋กœ ๋ชจ๋ธ ์ž๋™ ํŠœ๋‹

!pip install -U ultralytics
!wandb login <api key>
!yolo settings wandb=True

import wandb
from wandb.integration.ultralytics import add_wandb_callback
from ultralytics import YOLO

# ํ”„๋กœ์ ํŠธ๋ช… ์ง€์ • (์ž๋™ ์ƒ์„ฑ๋„ ๊ฐ€๋Šฅ)
wandb.init(project="fire_clip_project", job_type='training')
  • wandb ์—ฐ๊ฒฐ ๋ฐ sweep ์„ค์ •

 

sweep_config = {
    'method': 'random',
    'metric': {'goal': 'maximize', 'name': 'metrics/mAP50-95(B)'},
    'parameters': {
        'batch_size': {'values': [16, 32, 64]},
        'learning_rate': {
            'distribution': 'uniform',
            'min':0.0001,
            'max':0.001
            }
    }
}


sweep_config = {
    'method': 'bayes',
    'metric': {'goal': 'maximize', 'name': 'metrics/mAP50-95(B)'},
    'parameters': {
        'batch_size': {'values': [16, 32]},
        'learning_rate': {'distribution': 'uniform', 'min': 0.0001, 'max': 0.001},
        'optimizer': {'values': ['SGD', 'Adam', 'AdamW']},
        'label_smoothing': {'distribution': 'uniform', 'min': 0.0, 'max': 0.1}
    }
}
  • ํŠœ๋‹ํ•  ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์ง€์ •
  • mAP50-95๊ฐ€ ์ตœ๋Œ€ํ™”๋˜๋Š” ๊ฒƒ์„ ๊ธฐ์ค€์œผ๋กœ ์‚ผ์Œ
  • ๋ฐฐ์น˜ ์‚ฌ์ด์ฆˆ์™€ ํ•™์Šต๋ฅ ์„ ์—ฌ๋Ÿฌ ์กฐํ•ฉ๋ณ„๋กœ ํ•™์Šต ์ง„ํ–‰
  • ์ด ์™ธ์—๋„ ๋” ๋งŽ์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
  • sweep config ์„ค์ • ํ›„ ํ•™์Šต ๋Œ๋ฆฌ๋ฉด ์กฐํ•ฉ๋“ค์„ ์ž๋™์œผ๋กœ ํ•™์Šต ๋ฐ wandb์— ์„ฑ๋Šฅ ๋กœ๊น…

 

 

sweep_id = wandb.sweep(sweep=sweep_config, project='fire_clip_project')

def yolo_train():
    with wandb.init() as run:
        config = wandb.config

        # ๋ชจ๋ธ ์ •์˜ ๋ฐ ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ
        model = YOLO('yolov8n.pt')
        add_wandb_callback(model, enable_model_checkpointing=True)
        results = model.train(
            data='/content/data/data.yaml',
            name='exp3',
            plots=True,
            batch=config.batch_size,
            epochs=50,
            imgsz=640,
            cos_lr=True,
            lrf=0.01,
            lr0=config.learning_rate,
            project='yolov8_fire_detection'
        )

        metrics = results.metrics

        wandb.log({
            'epoch': 50,  # ๋˜๋Š” run.step ๋“ฑ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
            'val_loss': results.loss,  # ๋˜๋Š” ๋‹ค๋ฅธ ์ ์ ˆํ•œ loss ์‚ฌ์šฉ
            'metrics/mAP50': metrics.get('metrics/mAP50(B)', None),
            'metrics/mAP50-95': metrics.get('metrics/mAP50-95(B)', None)
        })

 

 

 

 

 

 

 


 

 

 

๐Ÿ› ๏ธ 3. ๊ตฌํ˜„ ๋ฒ”์œ„ ๋ฐ ๊ธฐ๋Šฅ ์ •์˜

๋ถ„๋ฅ˜ ๊ธฐ๋Šฅ ์„ค๋ช…
๐ŸŽฅ ์˜์ƒ ์ž…๋ ฅ 10~30์ดˆ ์˜์ƒ ํด๋ฆฝ ์—…๋กœ๋“œ (mp4) ์›น UI์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์—…๋กœ๋“œ
๐Ÿง  ํ™”์žฌ ํƒ์ง€ YOLOv8 ๊ธฐ๋ฐ˜ ์—ฐ๊ธฐ/๋ถˆ๊ฝƒ ํƒ์ง€ Flask API ๋‚ด๋ถ€์—์„œ ํ”„๋ ˆ์ž„ ์ถ”์ถœ ํ›„ ํƒ์ง€ ์ˆ˜ํ–‰
๐Ÿ–ผ๏ธ ๊ฒฐ๊ณผ ํ‘œ์‹œ ํƒ์ง€๋œ ํ”„๋ ˆ์ž„ ์ธ๋„ค์ผ + ์‹œ๊ฐ„์ •๋ณด ํ‘œ์‹œ MongoDB์— ๊ฒฐ๊ณผ ์ €์žฅ
๐Ÿ“ ๊ฒฐ๊ณผ ์ €์žฅ ํƒ์ง€ ๊ฒฐ๊ณผ ์˜์ƒ๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ ํƒ์ง€ ์˜์ƒ ํŒŒ์ผ : GCP VM Server
๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ : MongoDB

 

๐Ÿ› ๏ธ 3-1. ์‚ฌ์šฉ ๊ธฐ์ˆ  ์Šคํƒ

ํŒŒํŠธ ๊ธฐ์ˆ 
์›น ์„œ๋ฒ„ Flask (GCP Cloud Run ๋ฐฐํฌ)
DB MongoDB
ํด๋ผ์ด์–ธํŠธ HTML (+CSS)
์˜์ƒ ์ฒ˜๋ฆฌ OpenCV, FFmpeg
ํƒ์ง€ ๋ชจ๋ธ YOLOv8s/n 

 

๐Ÿ› ๏ธ 3-2. ์ „์ฒด ๊ตฌ์กฐ

 

FireClip AI ํ”„๋กœ์ ํŠธ ์ตœ์ข… ๊ธฐํš์„œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ, ์›น์„œ๋น„์Šค์˜ ์ „์ฒด ํ๋ฆ„์„ ๊ณ ๋ คํ•œ ๋ฐฑ์—”๋“œ ๋ฐ ์›น ๊ตฌ์กฐ(์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜)

GCP + Flask + MongoDB + YOLO ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™

 

 

 

 

์‚ฌ์šฉ์ž(๋ธŒ๋ผ์šฐ์ €)
      โ”‚
      โ–ผ
[Frontend] (HTML+CSS)
  - ์˜์ƒ ์—…๋กœ๋“œ
  - ํƒ์ง€ ๊ฒฐ๊ณผ ํ™•์ธ
      โ”‚
      โ–ผ
[Flask Backend API Server] (GCP Cloud Run)
  - ์š”์ฒญ ์ฒ˜๋ฆฌ (REST API)
  - YOLOv8 ์ถ”๋ก  ์—ฐ๋™
  - Cloud Storage & MongoDB ์—ฐ๋™
      โ”‚
      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
      โ–ผ                โ–ผ                โ–ผ
[YOLOv8 Inference]   [GCS]           [MongoDB]
(๋กœ์ปฌ or Cloud)    (์˜์ƒ ์ €์žฅ)    (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ)

 

 

โžก๏ธ ์›๋ž˜๋Š” ์—…๋กœ๋“œํ•œ ์˜์ƒ, ํƒ์ง€ ๊ฒฐ๊ณผ ์˜์ƒ์„ ๊ตฌ๊ธ€ ํด๋ผ์šฐ๋“œ ๋ฒ„์ผ“์— ์ €์žฅํ•˜๋ ค ํ–ˆ์œผ๋‚˜ ์ด ๋ถ€๋ถ„๊นŒ์ง€๋Š” ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค

 

 


 

 

๐Ÿ”™ ๋ฐฑ์—”๋“œ ๊ตฌ์กฐ (Flask)

 

๐Ÿ”น ์ฃผ์š” ์ฒ˜๋ฆฌ ํ๋ฆ„

  1. ์‚ฌ์šฉ์ž๊ฐ€ ์˜์ƒ ์—…๋กœ๋“œ 
  2. Flask ์„œ๋ฒ„์—์„œ ์˜์ƒ ์ž„์‹œ ์ €์žฅ
  3. ์ €์žฅ๋œ ์˜์ƒ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜์œผ๋กœ OpenCV๋ฅผ ํ†ตํ•ด ํ”„๋ ˆ์ž„ ๋‹จ์œ„๋กœ YOLO ์ถ”๋ก  ์‹คํ–‰
  4. ์ถ”๋ก  ๊ฒฐ๊ณผ(ํ”„๋ ˆ์ž„ + ๋ฐ•์Šค ์ขŒํ‘œ + ํด๋ž˜์Šค)๋ฅผ ์˜์ƒ์œผ๋กœ ๋งŒ๋“ค๊ณ  ์ €์žฅ ๋ฐ ์›น ํŽ˜์ด์ง€์— ์›๋ณธ๊ณผ ๊ฐ™์ด ๋„์šฐ๊ธฐ
  5. MongoDB์— ํ•ด๋‹น ์˜์ƒ/๊ฒฐ๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ธฐ๋ก (ํŒŒ์ผ ๊ฒฝ๋กœ, ํƒ์ง€๊ฒฐ๊ณผ ๋“ฑ)

 

 


 

๐ŸŒ ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์กฐ (HTML + CSS)

 

๐Ÿ”น ์›นํŽ˜์ด์ง€ ํ™”๋ฉด

 

ํด๋ฆฝ ์˜์ƒ์„ ์—…๋กœ๋“œ ํ•˜๊ธฐ ์ „์— ์ด๋ฏธ์ง€๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ง„ํ–‰ํ•ด๋ณด์•˜๋‹ค

 

์ดˆ๊ธฐ ํ™”๋ฉด. ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์„œ ์›๋ณธ๊ณผ ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ๋„์–ด์ฃผ๋Š” ์ •๋ง ๊ฐ„๋‹จํ•œ ํ˜•ํƒœ์ด๋‹ค

๋ณด๋ฉด ๊ฒฐ๊ณผ๊ฐ€ BGRํ˜•์‹์— ์‹œ๊ฐ„๋„ UTC ํƒ€์ž„์œผ๋กœ ๋˜์–ด์žˆ๋Š” ๋“ฑ ์†Œ์†Œํ•œ ์ด์Šˆ๋“ค์ด ์žˆ์—ˆ๋‹ค

 

 

๊ทธ ๋‹ค์Œ์—” ๊ฐ„๋‹จํ•œ ํด๋ฆฝ ์˜์ƒ์„ ์—…๋กœ๋“œ ๋ฐ ์›น์—์„œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋˜๋Š”์ง€๊นŒ์ง€ ์ง„ํ–‰, ์•„๋ž˜์ฒ˜๋Ÿผ ๋‚˜์˜จ๋‹ค

 

 

 

 

 

 

๐Ÿ”น ์ด์Šˆ ์‚ฌํ•ญ

 

ํƒ์ง€ ๊ฒฐ๊ณผ ์˜์ƒ์ด ์›น์—์„œ ์‹คํ–‰์ด ์•ˆ๋˜๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ

 

  • ์›๋ณธ ์˜์ƒ ์—…๋กœ๋“œ ๋ฐ ํƒ์ง€ ํ›„ ๋ฐ”์šด๋”ฉ๋ฐ•์Šค๋ฅผ ํ”„๋ ˆ์ž„์— ๊ทธ๋ ค์„œ ์˜์ƒ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ๋„ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘
  • ๋งŒ๋“ค์–ด์ง„ ํƒ์ง€ ๊ฒฐ๊ณผ ์˜์ƒ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋‚˜ ๋‹ค์šด๋ฐ›์•„ ํ™•์ธํ•ด๋ณด๋‹ˆ ๋ฌธ์ œ ์—†์Œ
  • ์˜์ƒ๊ณผ html, ์›น ๋ถ€๋ถ„์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์œ ์ถ”

โžก๏ธ ๋งŒ๋“ค์–ด์ง„ ์˜์ƒ๊ณผ ๋ธŒ๋ผ์šฐ์ € ๊ฐ„์˜ ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๋กœ ์›น์—์„œ ์˜์ƒ ์žฌ์ƒ์ด ์•ˆ๋จ

 

 

์ฝ”๋“œ ์ค‘ OpenCV๋ฅผ ํ†ตํ•ด mp4 ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

 

์ด๋ ‡๊ฒŒ OpenCV๋กœ mp4, ์˜์ƒ ํŒŒ์ผ์„ ๋งŒ๋“ค๋•Œ ์ด๋ ‡๊ฒŒ ์ƒ์„ฑ๋œ mp4 ํŒŒ์ผ์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์ฝ”๋ฑ์ผ ์ˆ˜๋„ ์žˆ๋‹ค

mp4๋Š” ํŒŒ์ผ, ์˜์ƒ์„ ๋‹ด์€ ์ปจํ…Œ์ด๋„ˆ์ด๋ฉฐ ๊ฐ™์€ mp4๋ผ๋„ ๋‚ด๋ถ€ ์ธ์ฝ”๋”ฉ ๋ฐฉ๋ฒ•, ์ฝ”๋ฑ์€ ์„œ๋กœ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค

์•„๋ž˜ ๋ธ”๋กœ๊ทธ์—์„œ ๋น„์Šทํ•œ ์ด์Šˆ ๋ฐ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ž˜ ๋‹ค๋ฃจ๊ณ  ์žˆ๋‹ค

 

https://omoknooni.tistory.com/134

 

[GAMST] VideoWriter์™€ fourCC, ์ฝ”๋ฑ

ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ์ค‘ input ์˜์ƒ ์ŠคํŠธ๋ฆผ์—์„œ ์œ„ํ—˜ ๊ตฌ๊ฐ„์„ ํƒ์ง€ํ•ด ์ƒˆ๋กœ์šด ๋น„๋””์˜ค Clip ํŒŒ์ผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ตฌ๊ฐ„์ด ์žˆ์—ˆ๋‹ค.์ด ๋ถ€๋ถ„์—์„œ๋Š” OpenCV์˜ VideoWriter ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•ด ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ๋‹ค. # VideoWriter

blog.omoknooni.me

 

 

โžก๏ธ ffmpeg๋ฅผ ํ†ตํ•ด ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ˜ธํ™˜ํ•˜๋Š” ์ฝ”๋ฑ์œผ๋กœ ์˜์ƒ์„ ๋ณ€ํ™˜

  • opencv๋กœ mp4 ์˜์ƒ ์ƒ์„ฑ -> ffmpeg๋กœ ์ฝ”๋ฑ ๋ณ€ํ™˜ ๋ฐ ์ €์žฅํ•˜๋Š” ์ผ๋ จ์˜ ๊ณผ์ •์€ ๋ณ€ํ™˜ํ•˜๋Š” ์‹œ๊ฐ„ ๋•Œ๋ฌธ์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ์˜์ƒ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค
  • ์ด ์›นํŽ˜์ด์ง€๋Š” ์‹ค์‹œ๊ฐ„ ์˜์ƒ์€ ์•„๋‹ˆ๊ธฐ์— ffmpeg๋ฅผ ์ด์šฉํ–ˆ์œผ๋‚˜ ๋” ๊ณ ๋„ํ™”ํ•œ๋‹ค๋ฉด ์ด ๋ถ€๋ถ„์€ ์ƒ๋žตํ•  ๊ฒƒ์ด๋‹ค

 

์›๋ณธ ๋ฐ ํƒ์ง€ ๊ฒฐ๊ณผ ์˜์ƒ

 

 

 

โ˜๏ธ MongoDB ๊ตฌ์„ฑ

 

 

ํ•„๋“œ๋ช… ๋ฐ์ดํ„ฐ ํƒ€์ž… ์„ค๋ช…
_id ObjectId MongoDB๊ฐ€ ์ž๋™ ์ƒ์„ฑํ•˜๋Š” ๊ณ ์œ  ID
original_filename String ์—…๋กœ๋“œ๋œ ์›๋ณธ ์˜์ƒ์˜ ํŒŒ์ผ๋ช… (UUID ๋“ฑ์œผ๋กœ ๊ด€๋ฆฌ)
uploaded_at String ์˜์ƒ ์—…๋กœ๋“œ ์‹œ๊ฐ„ (์˜ˆ: "2025-05-07 23:41:39"). KST ๊ธฐ์ค€ ์‹œ๊ฐ„์œผ๋กœ ๊ธฐ๋ก
video_length_sec Float ์˜์ƒ์˜ ์ด ๊ธธ์ด (์ดˆ ๋‹จ์œ„, ์˜ˆ: 29.91)
fps Float ์ดˆ๋‹น ํ”„๋ ˆ์ž„ ์ˆ˜ (Frames Per Second)
resolution Object ์˜์ƒ ํ•ด์ƒ๋„ ์ •๋ณด. width์™€ height๋ฅผ ํฌํ•จ
โ”œโ”€ width Integer ์˜์ƒ ๊ฐ€๋กœ ํ•ด์ƒ๋„
โ””โ”€ height Integer ์˜์ƒ ์„ธ๋กœ ํ•ด์ƒ๋„
summary Object ๊ฐ์ง€ ๊ฒฐ๊ณผ ์š”์•ฝ ์ •๋ณด
โ”œโ”€ fire_count Integer ์ด Fire ๊ฐ์ฒด ๊ฐ์ง€ ํšŸ์ˆ˜
โ”œโ”€ smoke_count Integer ์ด Smoke ๊ฐ์ฒด ๊ฐ์ง€ ํšŸ์ˆ˜
โ”œโ”€ fire_segments Array[String] Fire๊ฐ€ ๊ฐ์ง€๋œ ์ฃผ์š” ๊ตฌ๊ฐ„. ์ง€์† ๊ฐ์ง€ ๋˜๋Š” ๋‹จ๋ฐœ ๊ฐ์ง€ ํฌํ•จ
โ”œโ”€ smoke_segments Array[String] Smoke๊ฐ€ ๊ฐ์ง€๋œ ์ฃผ์š” ๊ตฌ๊ฐ„. ์ง€์† ๊ฐ์ง€ ๋˜๋Š” ๋‹จ๋ฐœ ๊ฐ์ง€ ํฌํ•จ
โ”œโ”€ avg_confidence Float ์ „์ฒด ๊ฐ์ง€์˜ ํ‰๊ท  ์‹ ๋ขฐ๋„ (0 ~ 1)
โ””โ”€ max_confidence Float ๊ฐ์ง€๋œ ๊ฐ์ฒด ์ค‘ ๊ฐ€์žฅ ๋†’์€ ์‹ ๋ขฐ๋„
detection_details Array[Object] ๊ฐ ๊ฐ์ง€ ๊ฐ์ฒด์˜ ์ƒ์„ธ ์ •๋ณด ๋ชฉ๋ก
โ”œโ”€ label String ๊ฐ์ง€๋œ ๊ฐ์ฒด ํด๋ž˜์Šค (์˜ˆ: "fire", "smoke")
โ”œโ”€ timestamp String ๊ฐ์ง€๋œ ์‹œ์  (์˜ˆ: "00:29" ํ˜•์‹์˜ ํƒ€์ž„์ฝ”๋“œ)
โ”œโ”€ confidence Float ํ•ด๋‹น ๊ฐ์ฒด ๊ฐ์ง€์˜ ์‹ ๋ขฐ๋„ (0~1)
โ””โ”€ bbox Array[Int] ๋ฐ”์šด๋”ฉ ๋ฐ•์Šค ์ขŒํ‘œ: [x1, y1, x2, y2] (์™ผ์ชฝ ์œ„, ์˜ค๋ฅธ์ชฝ ์•„๋ž˜)
result_video_path String ๊ฐ์ง€ ๊ฒฐ๊ณผ๊ฐ€ ์ ์šฉ๋œ ์˜์ƒ ํŒŒ์ผ ๊ฒฝ๋กœ
original_video_path String ์›๋ณธ ์—…๋กœ๋“œ ์˜์ƒ์˜ ๊ฒฝ๋กœ
processed Boolean ํ•ด๋‹น ์˜์ƒ์ด ํƒ์ง€ ํ›„ ์ €์žฅ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€ (True = ์ฒ˜๋ฆฌ ์™„๋ฃŒ)

 

 

fireclip_db> db.video_detections.find()
[
  {
    _id: ObjectId('681b71234ca3e6db95f8500c'),
    original_filename: '9dd8a6ff3c05414687bc8724e539015d.mp4',
    uploaded_at: '2025-05-07 23:41:39',
    video_length_sec: 29.91,
    fps: 29.985945703568117,
    resolution: { width: 854, height: 480 },
    summary: {
      fire_count: 583,
      smoke_count: 72,
      fire_segments: [
        '00:06–00:13 (์ง€์†์ ์œผ๋กœ ๊ฐ์ง€)',
        '00:19–00:25 (์ง€์†์ ์œผ๋กœ ๊ฐ์ง€)',
        '00:27–00:29 (์ง€์†์ ์œผ๋กœ ๊ฐ์ง€)',
        '๋‹จ๋ฐœ์„ฑ ๊ฐ์ง€: 00:15, 00:16'
      ],
      smoke_segments: [
        '00:00–00:04 (์ง€์†์ ์œผ๋กœ ๊ฐ์ง€)',
        '๋‹จ๋ฐœ์„ฑ ๊ฐ์ง€: 00:10, 00:18, 00:19, 00:22, 00:28'
      ],
      avg_confidence: 0.5914,
      max_confidence: 0.9154
    },
    detection_details: [
      {
        label: 'smoke',
        timestamp: '00:00',
        confidence: 0.6521,
        bbox: [ 0, 75, 79, 470 ]
      },
      ...
      ...
      {
        label: 'fire',
        timestamp: '00:29',
        confidence: 0.8521,
        bbox: [ 314, 103, 563, 325 ]
      },
      {
        label: 'fire',
        timestamp: '00:29',
        confidence: 0.8308,
        bbox: [ 309, 86, 561, 330 ]
      },
      {
        label: 'fire',
        timestamp: '00:29',
        confidence: 0.8217,
        bbox: [ 309, 136, 561, 329 ]
      },
      {
        label: 'fire',
        timestamp: '00:29',
        confidence: 0.7908,
        bbox: [ 305, 155, 581, 328 ]
      }
    ],
    result_video_path: 'static/results/result_9dd8a6ff3c05414687bc8724e539015d.mp4',
    original_video_path: 'static/uploads/9dd8a6ff3c05414687bc8724e539015d.mp4',
    processed: true
  }
]

 

 

 

 

 

 


 

๐Ÿ“‘ 4. ๊ฒฐ๊ณผ๋ฌผ

  • ์˜ˆ์ƒ ์‚ฐ์ถœ๋ฌผ
    • Flask ๊ธฐ๋ฐ˜ ์„œ๋ฒ„ ์ฝ”๋“œ
    • YOLOv8 ํƒ์ง€ ์Šคํฌ๋ฆฝํŠธ (์ปค์Šคํ…€ or ๊ธฐ์กด)
    • MongoDB ๊ฒฐ๊ณผ ์Šคํ‚ค๋งˆ ๋ฐ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ
    • ํƒ์ง€ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ƒ˜ํ”Œ
    • ๋ฐœํ‘œ์šฉ ์Šฌ๋ผ์ด๋“œ ๋ฐ ์‹œ์—ฐ ์˜์ƒ

 

 

๐Ÿ“‘ 4-1. ์›นํŽ˜์ด์ง€ ํ™”๋ฉด ๋ฐ ๊ฒฐ๊ณผ

 

ํด๋ฆฝ ์˜์ƒ ์—…๋กœ๋“œ ๋ฐ ํƒ์ง€ ๊ฒฐ๊ณผ ์ถœ๋ ฅ



 

 

๐Ÿ“‘ 4-2. ๊ตฌํ˜„ ์—ฌ๋ถ€ ์ •๋ฆฌ ๋ฐ ๋งˆ๋ฌด๋ฆฌ

๊ตฌํ˜„ ํ•ญ๋ชฉ ์‹ค์ œ ์ง„ํ–‰
์›น ์˜์ƒ ์ž…๋ ฅ ๋ฐ ์—…๋กœ๋“œ โœ…
Yolo ํ™”์žฌ ํƒ์ง€ โœ…
๊ฒฐ๊ณผ ํ‘œ์‹œ ๋ฐ DB ์ €์žฅ โœ…
๊ตฌ๊ธ€ ํด๋ผ์šฐ๋“œ ๋ฒ„์ผ“ ์—ฐ๋™ โŒ
ํƒ์ง€ ๊ฒฐ๊ณผ ์กฐํšŒ ๊ธฐ๋Šฅ ์›น์— ์ถ”๊ฐ€ โŒ
์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง ๋ฐ ๊ณ ๋„ํ™” โŒ

 

 

๊ณ„ํš ์ƒ์œผ๋กœ๋Š” ์—…๋กœ๋“œํ•œ ์˜์ƒ์— ๋Œ€ํ•ด ํƒ์ง€ ํ›„ ์›๋ณธ๊ณผ ํƒ์ง€ ๊ฒฐ๊ณผ ์˜์ƒ์„ ๊ตฌ๊ธ€ ํด๋ผ์šฐ๋“œ์— ์ €์žฅํ•˜๊ณ  ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ๋Š” MongoDB์— ์ €์žฅํ•œ๋‹ค

์›น์—๋Š” ์กฐํšŒ ๋ฆฌ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋Ÿฐ ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค

์ฝ”๋“œ๋„ ํ”Œ๋ผ์Šคํฌ ๋™์ž‘ ์ฝ”๋“œ์ธ app.py์—์„œ ๋ชจ๋ธ ์ถ”๋ก , ์ด๋ฏธ์ง€ ์ „ํ›„์ฒ˜๋ฆฌ, ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋“ฑ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์„ ํ•˜๋‚˜์˜ py์— ๋„ฃ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ผ์šฐํŠธ๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ๊ธฐ๋Šฅ๋ณ„๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•œ๋‹ค

์ตœ์ข…์ ์œผ๋กœ๋Š” ์นด๋ฉ”๋ผ์˜ RTSP๋ฅผ ๋ฐ›์•„์™€ ์‹ค์‹œ๊ฐ„ ์ถ”๋ก ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ–ˆ์—ˆ๋‹ค

์•ฑ์ด๋‚˜ ์บ  ๋“ฑ์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์˜์ƒ์— AI ์ถ”๋ก ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋…ธํ‹ฐ๋ฅผ ์ฃผ๋Š” ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๊ฐ€ ๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค

 

์ด๋ฒˆ์—๋Š” ๋งŽ์€ ๋ถ€๋ถ„๋“ค๊นŒ์ง€ ๋‹ค๋ฃจ๊ณ  ๊ตฌํ˜„ํ•ด๋ณด์ง„ ๋ชปํ–ˆ์œผ๋‚˜ ํ”Œ๋ผ์Šคํฌ๋ฅผ ์ด์šฉํ•ด ์›น์˜ ์ „๋ฐ˜์ ์ธ ํ๋ฆ„์„ ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ์œ ์ตํ–ˆ๋‹ค

๋‹ค์Œ์—๋Š” ์ด ๊ฒฝํ—˜๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ ๋” ๋งŽ์€ ๋ถ€๋ถ„๋“ค์„ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด๋ด์•ผ๊ฒ ๋‹ค