์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ’ป ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด ์™„๋ฒฝ ๊ฐ€์ด๋“œ

๐Ÿ’ป ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด ์™„๋ฒฝ ๊ฐ€์ด๋“œ

CPU์™€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ถ”์ ํ•˜๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด ์†Œ์Šค์ฝ”๋“œ ์™„์ „ ์ •๋ณต! ๐Ÿš€

๐ŸŽฏ ์™œ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์ด ํ•„์š”ํ• ๊นŒ?

์นœ๊ตฌ์•ผ, ์ปดํ“จํ„ฐ๊ฐ€ ๊ฐ‘์ž๊ธฐ ๋А๋ ค์ง€๊ฑฐ๋‚˜ ํ”„๋กœ๊ทธ๋žจ์ด ๋จนํ†ต์ด ๋  ๋•Œ ๋‹ต๋‹ตํ–ˆ๋˜ ๊ฒฝํ—˜ ์žˆ์ง€? ๐Ÿ˜ค
๊ทธ๋Ÿด ๋•Œ ํ•„์š”ํ•œ ๊ฒŒ ๋ฐ”๋กœ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์ด์•ผ!

CPU๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ผํ•˜๊ณ  ์žˆ๋Š”์ง€, ๋ฉ”๋ชจ๋ฆฌ๋Š” ์–ผ๋งˆ๋‚˜ ์‚ฌ์šฉ ์ค‘์ธ์ง€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด
๋ฌธ์ œ์˜ ์›์ธ์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ๊ฑฐ๋“ . ๋งˆ์น˜ ์ž๋™์ฐจ ๊ณ„๊ธฐํŒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ! ๐Ÿš—๐Ÿ’จ

์˜ค๋Š˜์€ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณผ ์ˆ˜ ์žˆ๋Š” ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์•ผ.
์ดˆ๋ณด์ž๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ์นœ์ ˆํ•˜๊ฒŒ ์„ค๋ช…ํ•ด์ค„ ํ…Œ๋‹ˆ ๊ฑฑ์ • ๋งˆ! ๐Ÿ˜Š

CPU Monitor 45% Usage Memory Monitor 70% Total: 16 GB Used: 11.2 GB Free: 4.8 GB ๐Ÿ“Š

๐Ÿ› ๏ธ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์˜ ํ•ต์‹ฌ ๊ตฌ์„ฑ์š”์†Œ

๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์„ ๋งŒ๋“ค๊ธฐ ์ „์— ์–ด๋–ค ๋ถ€ํ’ˆ๋“ค์ด ํ•„์š”ํ•œ์ง€ ์•Œ์•„๋ณด์ž!
๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์„ ์กฐ๋ฆฝํ•˜๋“ฏ์ด, ๊ฐ ๋ถ€๋ถ„์„ ์ดํ•ดํ•˜๋ฉด ์ „์ฒด ๊ทธ๋ฆผ์ด ๋ณด์ผ ๊ฑฐ์•ผ. ๐Ÿงฉ

๐Ÿ“Œ 1. ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ชจ๋“ˆ

์‹œ์Šคํ…œ ์ •๋ณด๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ํ•ต์‹ฌ ์—”์ง„์ด์•ผ.
์šด์˜์ฒด์ œ์™€ ๋Œ€ํ™”ํ•˜๋ฉด์„œ CPU ์‚ฌ์šฉ๋ฅ , ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ ๊ฐ™์€ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•˜์ง€.

Windows Linux macOS
๊ฐ ์šด์˜์ฒด์ œ๋งˆ๋‹ค ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๋‹ค๋Š” ์ ! ๊ธฐ์–ตํ•ด๋‘ฌ. ๐ŸŽฏ

๐Ÿ“Œ 2. ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ๋ถ„์„ ๋ชจ๋“ˆ

์ˆ˜์ง‘ํ•œ ์›์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ๋žŒ์ด ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ํ˜•ํƒœ๋กœ ๊ฐ€๊ณตํ•˜๋Š” ๋ถ€๋ถ„์ด์•ผ.
๋ฐ”์ดํŠธ๋ฅผ ๊ธฐ๊ฐ€๋ฐ”์ดํŠธ๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ํ‰๊ท ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด.
์ด ๊ณผ์ •์ด ์—†์œผ๋ฉด ์ˆซ์ž ๋”๋ฏธ๋งŒ ๋ณด๊ฒŒ ๋  ๊ฑฐ์•ผ! ๐Ÿ˜…

๐Ÿ“Œ 3. ์‹œ๊ฐํ™” ์ธํ„ฐํŽ˜์ด์Šค

๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ž˜ํ”„, ์ฐจํŠธ, ๊ฒŒ์ด์ง€ ๊ฐ™์€ ์‹œ๊ฐ์  ์š”์†Œ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๋ถ€๋ถ„!
์ˆซ์ž๋งŒ ๋ณด๋Š” ๊ฒƒ๋ณด๋‹ค ๊ทธ๋ž˜ํ”„๋กœ ๋ณด๋ฉด ํ›จ์”ฌ ์ง๊ด€์ ์ด์ž–์•„? ๐Ÿ“ˆ
์‹ค์‹œ๊ฐ„์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๋™์ ์ธ UI๊ฐ€ ํ•ต์‹ฌ์ด์•ผ.

๐Ÿ“Œ 4. ์•Œ๋ฆผ ๋ฐ ๋กœ๊น… ์‹œ์Šคํ…œ

CPU๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ์ด ์œ„ํ—˜ ์ˆ˜์ค€์— ๋„๋‹ฌํ•˜๋ฉด ๊ฒฝ๊ณ ๋ฅผ ๋ณด๋‚ด์ฃผ๋Š” ๊ธฐ๋Šฅ!
๋˜ํ•œ ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋กํ•ด์„œ ๋‚˜์ค‘์— ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์ง€.
๋ฌธ์ œ๊ฐ€ ์–ธ์ œ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ์œ ์šฉํ•ด. ๐Ÿ””

๐Ÿ’ก Python์œผ๋กœ ๋งŒ๋“œ๋Š” ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณผ๊นŒ?
Python์€ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง์— ์ตœ์ ํ™”๋œ ์–ธ์–ด์•ผ. ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋งŽ๊ฑฐ๋“ ! ๐Ÿ

๋จผ์ € ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ถ€ํ„ฐ ์„ค์น˜ํ•ด๋ณด์ž.

๐Ÿ’ก TIP: Python์ด ์ฒ˜์Œ์ด๋ผ๋ฉด ์žฌ๋Šฅ๋„ท์—์„œ Python ๊ธฐ์ดˆ ๊ฐ•์˜๋ฅผ ์ฐพ์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ!
๋‹ค์–‘ํ•œ ์ „๋ฌธ๊ฐ€๋“ค์ด ์ดˆ๋ณด์ž๋ฅผ ์œ„ํ•œ ๋งž์ถคํ˜• ๊ฐ•์˜๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ๊ฑฐ๋“ . ๐Ÿ˜Š

๐Ÿ”ง ํ•„์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

# psutil: ์‹œ์Šคํ…œ ์ •๋ณด ์ˆ˜์ง‘์„ ์œ„ํ•œ ํ•ต์‹ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
pip install psutil

# matplotlib: ๊ทธ๋ž˜ํ”„ ์‹œ๊ฐํ™”๋ฅผ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
pip install matplotlib

# tkinter: GUI ์ธํ„ฐํŽ˜์ด์Šค (Python ๊ธฐ๋ณธ ๋‚ด์žฅ)
# ๋ณ„๋„ ์„ค์น˜ ๋ถˆํ•„์š”

psutil์€ ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์•ผ!
CPU, ๋ฉ”๋ชจ๋ฆฌ, ๋””์Šคํฌ, ๋„คํŠธ์›Œํฌ ๋“ฑ ๊ฑฐ์˜ ๋ชจ๋“  ์‹œ์Šคํ…œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด.
ํฌ๋กœ์Šค ํ”Œ๋žซํผ์„ ์ง€์›ํ•ด์„œ Windows, Linux, macOS ๋ชจ๋‘์—์„œ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜์ง€. ๐Ÿ‘

๐Ÿ“ ๊ธฐ๋ณธ ๋ชจ๋‹ˆํ„ฐ๋ง ์ฝ”๋“œ - CPU ์‚ฌ์šฉ๋ฅ 

import psutil
import time

def monitor_cpu():
    """CPU ์‚ฌ์šฉ๋ฅ ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ํ•จ์ˆ˜"""
    print("=== CPU ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์ž‘ ===\n")
    
    try:
        while True:
            # ์ „์ฒด CPU ์‚ฌ์šฉ๋ฅ  (1์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ์ธก์ •)
            cpu_percent = psutil.cpu_percent(interval=1)
            
            # ๊ฐ ์ฝ”์–ด๋ณ„ ์‚ฌ์šฉ๋ฅ 
            cpu_per_core = psutil.cpu_percent(interval=1, percpu=True)
            
            # ํ˜„์žฌ ์‹œ๊ฐ„
            current_time = time.strftime("%H:%M:%S")
            
            # ๊ฒฐ๊ณผ ์ถœ๋ ฅ
            print(f"[{current_time}] ์ „์ฒด CPU ์‚ฌ์šฉ๋ฅ : {cpu_percent}%")
            print(f"์ฝ”์–ด๋ณ„ ์‚ฌ์šฉ๋ฅ : {cpu_per_core}")
            print("-" * 50)
            
            time.sleep(2)  # 2์ดˆ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ
            
    except KeyboardInterrupt:
        print("\n๋ชจ๋‹ˆํ„ฐ๋ง์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")

if __name__ == "__main__":
    monitor_cpu()
๐Ÿ” ์ฝ”๋“œ ํ•ด์„ค: psutil.cpu_percent(interval=1)
โ†’ 1์ดˆ ๋™์•ˆ์˜ ํ‰๊ท  CPU ์‚ฌ์šฉ๋ฅ ์„ ์ธก์ •ํ•ด. interval ๊ฐ’์ด ํด์ˆ˜๋ก ๋” ์ •ํ™•ํ•˜์ง€๋งŒ ์‘๋‹ต์ด ๋А๋ ค์ ธ.

percpu=True
โ†’ ๊ฐ CPU ์ฝ”์–ด๋ณ„๋กœ ์‚ฌ์šฉ๋ฅ ์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜ํ•ด. ๋ฉ€ํ‹ฐ์ฝ”์–ด ์‹œ์Šคํ…œ์—์„œ ์œ ์šฉํ•˜์ง€!

KeyboardInterrupt
โ†’ Ctrl+C๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ํ”„๋กœ๊ทธ๋žจ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ข…๋ฃŒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜. ๐Ÿ›‘

๐Ÿ“ ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋‹ˆํ„ฐ๋ง ์ฝ”๋“œ

import psutil

def monitor_memory():
    """๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ํ˜„ํ™ฉ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ํ•จ์ˆ˜"""
    
    # ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด
    memory = psutil.virtual_memory()
    
    # ์Šค์™‘ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด
    swap = psutil.swap_memory()
    
    # ๋ฐ”์ดํŠธ๋ฅผ GB๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
    def bytes_to_gb(bytes_value):
        return round(bytes_value / (1024**3), 2)
    
    print("=== ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋‹ˆํ„ฐ๋ง ===\n")
    
    # ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด ์ถœ๋ ฅ
    print(f"๐Ÿ“Š ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ: {bytes_to_gb(memory.total)} GB")
    print(f"๐Ÿ“Š ์‚ฌ์šฉ ์ค‘: {bytes_to_gb(memory.used)} GB")
    print(f"๐Ÿ“Š ์‚ฌ์šฉ ๊ฐ€๋Šฅ: {bytes_to_gb(memory.available)} GB")
    print(f"๐Ÿ“Š ์‚ฌ์šฉ๋ฅ : {memory.percent}%")
    print()
    
    # ์Šค์™‘ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด ์ถœ๋ ฅ
    print(f"๐Ÿ’พ ์Šค์™‘ ์ „์ฒด: {bytes_to_gb(swap.total)} GB")
    print(f"๐Ÿ’พ ์Šค์™‘ ์‚ฌ์šฉ: {bytes_to_gb(swap.used)} GB")
    print(f"๐Ÿ’พ ์Šค์™‘ ์‚ฌ์šฉ๋ฅ : {swap.percent}%")
    
    # ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ ํŒ๋‹จ
    if memory.percent > 90:
        print("\nโš ๏ธ ๊ฒฝ๊ณ : ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ์ด ๋งค์šฐ ๋†’์Šต๋‹ˆ๋‹ค!")
    elif memory.percent > 75:
        print("\nโšก ์ฃผ์˜: ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ์ด ๋†’์€ ํŽธ์ž…๋‹ˆ๋‹ค.")
    else:
        print("\nโœ… ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ๊ฐ€ ์–‘ํ˜ธํ•ฉ๋‹ˆ๋‹ค.")

if __name__ == "__main__":
    monitor_memory()

๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋‹ˆํ„ฐ๋ง์—์„œ ์ค‘์š”ํ•œ ๊ฑด available๊ณผ free์˜ ์ฐจ์ด์•ผ!

free๋Š” ์™„์ „ํžˆ ๋น„์–ด์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์˜๋ฏธํ•˜๊ณ ,
available์€ ์บ์‹œ๋‚˜ ๋ฒ„ํผ๋กœ ์‚ฌ์šฉ ์ค‘์ด์ง€๋งŒ ํ•„์š”ํ•˜๋ฉด ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๊นŒ์ง€ ํฌํ•จํ•ด.
์‹ค์ œ๋กœ๋Š” available ๊ฐ’์ด ๋” ์ค‘์š”ํ•˜์ง€! ๐ŸŽฏ

๐ŸŽจ GUI ๊ธฐ๋ฐ˜ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด ๋งŒ๋“ค๊ธฐ

์ฝ˜์†” ์ฐฝ์—์„œ ์ˆซ์ž๋งŒ ๋ณด๋Š” ๊ฑด ์ข€ ์‹ฌ์‹ฌํ•˜์ง€?
์ด์ œ ๋ฉ‹์ง„ ๊ทธ๋ž˜ํ”ฝ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ€์ง„ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์„ ๋งŒ๋“ค์–ด๋ณด์ž! ๐Ÿ–ผ๏ธ

tkinter๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ๊ฐ๋ณด๋‹ค ์‰ฝ๊ฒŒ GUI๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด.

๐Ÿ–ฅ๏ธ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ GUI ๋ชจ๋‹ˆํ„ฐ

import tkinter as tk
from tkinter import ttk
import psutil
import threading
import time

class SystemMonitor:
    def __init__(self, root):
        self.root = root
        self.root.title("์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด v1.0")
        self.root.geometry("600x400")
        self.root.resizable(False, False)
        
        # ๋ชจ๋‹ˆํ„ฐ๋ง ํ™œ์„ฑํ™” ํ”Œ๋ž˜๊ทธ
        self.monitoring = True
        
        # UI ๊ตฌ์„ฑ
        self.setup_ui()
        
        # ๋ชจ๋‹ˆํ„ฐ๋ง ์Šค๋ ˆ๋“œ ์‹œ์ž‘
        self.monitor_thread = threading.Thread(target=self.update_stats, daemon=True)
        self.monitor_thread.start()
    
    def setup_ui(self):
        """UI ๊ตฌ์„ฑ ์š”์†Œ ์„ค์ •"""
        
        # ํƒ€์ดํ‹€ ํ”„๋ ˆ์ž„
        title_frame = tk.Frame(self.root, bg="#667eea", height=80)
        title_frame.pack(fill=tk.X)
        
        title_label = tk.Label(
            title_frame, 
            text="๐Ÿ’ป ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ", 
            font=("Arial", 24, "bold"),
            bg="#667eea",
            fg="white"
        )
        title_label.pack(pady=20)
        
        # ๋ฉ”์ธ ์ปจํ…์ธ  ํ”„๋ ˆ์ž„
        content_frame = tk.Frame(self.root, bg="#f8f9fa")
        content_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # CPU ์„น์…˜
        cpu_frame = tk.LabelFrame(
            content_frame, 
            text="๐Ÿ”ฅ CPU ์‚ฌ์šฉ๋ฅ ", 
            font=("Arial", 12, "bold"),
            bg="#f8f9fa",
            padx=10,
            pady=10
        )
        cpu_frame.pack(fill=tk.X, pady=(0, 10))
        
        self.cpu_label = tk.Label(
            cpu_frame,
            text="์ธก์ • ์ค‘...",
            font=("Arial", 16),
            bg="#f8f9fa"
        )
        self.cpu_label.pack()
        
        self.cpu_progress = ttk.Progressbar(
            cpu_frame,
            length=500,
            mode='determinate'
        )
        self.cpu_progress.pack(pady=5)
        
        # ๋ฉ”๋ชจ๋ฆฌ ์„น์…˜
        memory_frame = tk.LabelFrame(
            content_frame,
            text="๐Ÿ’พ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ",
            font=("Arial", 12, "bold"),
            bg="#f8f9fa",
            padx=10,
            pady=10
        )
        memory_frame.pack(fill=tk.X, pady=(0, 10))
        
        self.memory_label = tk.Label(
            memory_frame,
            text="์ธก์ • ์ค‘...",
            font=("Arial", 16),
            bg="#f8f9fa"
        )
        self.memory_label.pack()
        
        self.memory_progress = ttk.Progressbar(
            memory_frame,
            length=500,
            mode='determinate'
        )
        self.memory_progress.pack(pady=5)
        
        # ์ƒ์„ธ ์ •๋ณด ์„น์…˜
        detail_frame = tk.LabelFrame(
            content_frame,
            text="๐Ÿ“Š ์ƒ์„ธ ์ •๋ณด",
            font=("Arial", 12, "bold"),
            bg="#f8f9fa",
            padx=10,
            pady=10
        )
        detail_frame.pack(fill=tk.BOTH, expand=True)
        
        self.detail_text = tk.Text(
            detail_frame,
            height=6,
            font=("Courier", 10),
            bg="#ffffff",
            relief=tk.FLAT
        )
        self.detail_text.pack(fill=tk.BOTH, expand=True)
    
    def update_stats(self):
        """์‹œ์Šคํ…œ ํ†ต๊ณ„๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ"""
        while self.monitoring:
            try:
                # CPU ์ •๋ณด ์ˆ˜์ง‘
                cpu_percent = psutil.cpu_percent(interval=1)
                cpu_count = psutil.cpu_count()
                
                # ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด ์ˆ˜์ง‘
                memory = psutil.virtual_memory()
                memory_percent = memory.percent
                memory_used = round(memory.used / (1024**3), 2)
                memory_total = round(memory.total / (1024**3), 2)
                
                # UI ์—…๋ฐ์ดํŠธ
                self.root.after(0, self.update_ui, cpu_percent, memory_percent, 
                               cpu_count, memory_used, memory_total)
                
                time.sleep(1)
                
            except Exception as e:
                print(f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
                break
    
    def update_ui(self, cpu_percent, memory_percent, cpu_count, memory_used, memory_total):
        """UI ์š”์†Œ ์—…๋ฐ์ดํŠธ"""
        
        # CPU ์—…๋ฐ์ดํŠธ
        self.cpu_label.config(text=f"{cpu_percent}%")
        self.cpu_progress['value'] = cpu_percent
        
        # ์ƒ‰์ƒ ๋ณ€๊ฒฝ (์‚ฌ์šฉ๋ฅ ์— ๋”ฐ๋ผ)
        if cpu_percent > 80:
            self.cpu_label.config(fg="red")
        elif cpu_percent > 60:
            self.cpu_label.config(fg="orange")
        else:
            self.cpu_label.config(fg="green")
        
        # ๋ฉ”๋ชจ๋ฆฌ ์—…๋ฐ์ดํŠธ
        self.memory_label.config(text=f"{memory_percent}%")
        self.memory_progress['value'] = memory_percent
        
        if memory_percent > 80:
            self.memory_label.config(fg="red")
        elif memory_percent > 60:
            self.memory_label.config(fg="orange")
        else:
            self.memory_label.config(fg="green")
        
        # ์ƒ์„ธ ์ •๋ณด ์—…๋ฐ์ดํŠธ
        detail_info = f"""
CPU ์ฝ”์–ด ์ˆ˜: {cpu_count}๊ฐœ
CPU ์‚ฌ์šฉ๋ฅ : {cpu_percent}%

๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ: {memory_used} GB / {memory_total} GB
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ : {memory_percent}%

์—…๋ฐ์ดํŠธ ์‹œ๊ฐ„: {time.strftime("%H:%M:%S")}
        """
        
        self.detail_text.delete(1.0, tk.END)
        self.detail_text.insert(1.0, detail_info.strip())
    
    def on_closing(self):
        """ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์‹œ ์ฒ˜๋ฆฌ"""
        self.monitoring = False
        self.root.destroy()

def main():
    root = tk.Tk()
    app = SystemMonitor(root)
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    root.mainloop()

if __name__ == "__main__":
    main()
๐ŸŽฏ ํ•ต์‹ฌ ํฌ์ธํŠธ: threading ์‚ฌ์šฉ
โ†’ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋ฉด์„œ UI๋Š” ๊ณ„์† ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜.
threading ์—†์ด while ๋ฃจํ”„๋ฅผ ๋Œ๋ฆฌ๋ฉด UI๊ฐ€ ๋ฉˆ์ถฐ๋ฒ„๋ ค! ๐Ÿ˜ฑ

root.after() ๋ฉ”์„œ๋“œ
โ†’ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ tkinter UI๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ฉด ์•ˆ ๋ผ.
after()๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ด.

daemon=True
โ†’ ๋ฉ”์ธ ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋˜๋ฉด ์Šค๋ ˆ๋“œ๋„ ์ž๋™์œผ๋กœ ์ข…๋ฃŒ๋˜๊ฒŒ ํ•ด์ค˜. ๐Ÿ”š
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: GUI ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ๋ณ„๋„ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ด!
๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋Œ๋ฆฌ๋ฉด UI๊ฐ€ ์‘๋‹ตํ•˜์ง€ ์•Š๊ฒŒ ๋ผ.
๋˜ํ•œ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์‹œ ์Šค๋ ˆ๋“œ๋ฅผ ์ œ๋Œ€๋กœ ์ •๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ข€๋น„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‚จ์„ ์ˆ˜ ์žˆ์–ด. ๐Ÿ‘ป

๐Ÿ“ˆ ๊ทธ๋ž˜ํ”„๋กœ ์‹œ๊ฐํ™”ํ•˜๊ธฐ

์ˆซ์ž์™€ ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋ฐ”๋„ ์ข‹์ง€๋งŒ, ์‹œ๊ฐ„์— ๋”ฐ๋ฅธ ๋ณ€ํ™”๋ฅผ ๋ณด๋ ค๋ฉด ๊ทธ๋ž˜ํ”„๊ฐ€ ์ตœ๊ณ ์•ผ!
matplotlib๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‹ค์‹œ๊ฐ„ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ ค๋ณด์ž. ๐Ÿ“Š

๐ŸŽฏ ์‹ค์‹œ๊ฐ„ ๋ผ์ธ ์ฐจํŠธ ๊ตฌํ˜„

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import psutil
import tkinter as tk
from collections import deque

class RealtimeMonitor:
    def __init__(self, root):
        self.root = root
        self.root.title("์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ")
        self.root.geometry("900x600")
        
        # ๋ฐ์ดํ„ฐ ์ €์žฅ์šฉ deque (์ตœ๋Œ€ 60๊ฐœ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ)
        self.cpu_data = deque([0] * 60, maxlen=60)
        self.memory_data = deque([0] * 60, maxlen=60)
        self.time_data = deque(range(60), maxlen=60)
        
        # ๊ทธ๋ž˜ํ”„ ์„ค์ •
        self.setup_plot()
        
        # ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘
        self.ani = animation.FuncAnimation(
            self.fig,
            self.update_plot,
            interval=1000,  # 1์ดˆ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ
            blit=False
        )
    
    def setup_plot(self):
        """๊ทธ๋ž˜ํ”„ ์ดˆ๊ธฐ ์„ค์ •"""
        
        # Figure ์ƒ์„ฑ
        self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1, figsize=(9, 6))
        self.fig.patch.set_facecolor('#f8f9fa')
        
        # CPU ๊ทธ๋ž˜ํ”„ ์„ค์ •
        self.ax1.set_title('CPU ์‚ฌ์šฉ๋ฅ  (%)', fontsize=14, fontweight='bold')
        self.ax1.set_ylim(0, 100)
        self.ax1.set_xlim(0, 60)
        self.ax1.grid(True, alpha=0.3)
        self.ax1.set_facecolor('#ffffff')
        self.line1, = self.ax1.plot([], [], 'b-', linewidth=2, label='CPU')
        self.ax1.legend(loc='upper right')
        self.ax1.set_ylabel('์‚ฌ์šฉ๋ฅ  (%)')
        
        # ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ์„ค์ •
        self.ax2.set_title('๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ  (%)', fontsize=14, fontweight='bold')
        self.ax2.set_ylim(0, 100)
        self.ax2.set_xlim(0, 60)
        self.ax2.grid(True, alpha=0.3)
        self.ax2.set_facecolor('#ffffff')
        self.line2, = self.ax2.plot([], [], 'r-', linewidth=2, label='Memory')
        self.ax2.legend(loc='upper right')
        self.ax2.set_xlabel('์‹œ๊ฐ„ (์ดˆ)')
        self.ax2.set_ylabel('์‚ฌ์šฉ๋ฅ  (%)')
        
        # ๋ ˆ์ด์•„์›ƒ ์กฐ์ •
        plt.tight_layout()
        
        # tkinter์— ๊ทธ๋ž˜ํ”„ ์‚ฝ์ž…
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
    
    def update_plot(self, frame):
        """๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ"""
        
        # ์‹œ์Šคํ…œ ์ •๋ณด ์ˆ˜์ง‘
        cpu_percent = psutil.cpu_percent(interval=0.1)
        memory_percent = psutil.virtual_memory().percent
        
        # ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
        self.cpu_data.append(cpu_percent)
        self.memory_data.append(memory_percent)
        
        # ๊ทธ๋ž˜ํ”„ ์—…๋ฐ์ดํŠธ
        self.line1.set_data(range(60), list(self.cpu_data))
        self.line2.set_data(range(60), list(self.memory_data))
        
        # ํ˜„์žฌ ๊ฐ’ ํ‘œ์‹œ
        self.ax1.set_title(
            f'CPU ์‚ฌ์šฉ๋ฅ : {cpu_percent:.1f}%',
            fontsize=14,
            fontweight='bold'
        )
        self.ax2.set_title(
            f'๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ : {memory_percent:.1f}%',
            fontsize=14,
            fontweight='bold'
        )
        
        return self.line1, self.line2

def main():
    root = tk.Tk()
    app = RealtimeMonitor(root)
    root.mainloop()

if __name__ == "__main__":
    main()

deque๋Š” ์ •๋ง ์œ ์šฉํ•œ ์ž๋ฃŒ๊ตฌ์กฐ์•ผ!
maxlen์„ ์„ค์ •ํ•˜๋ฉด ์ž๋™์œผ๋กœ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฒ„๋ฆฌ๊ณ  ์ƒˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด.
๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ด๋ฉด์„œ๋„ ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง€์ง€! ๐ŸŽฏ

animation.FuncAnimation์€ matplotlib์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ด์•ผ.
์ง€์ •ํ•œ ๊ฐ„๊ฒฉ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ทธ๋ž˜ํ”„๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์ค˜.
์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง์— ๋”ฑ ๋งž๋Š” ๋„๊ตฌ์ง€! โšก

๐Ÿ”” ์•Œ๋ฆผ ์‹œ์Šคํ…œ ๊ตฌํ˜„ํ•˜๊ธฐ

์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค๊ฐ€ ์œ„ํ—˜ ์ˆ˜์ค€์— ๋„๋‹ฌํ•˜๋ฉด ์•Œ๋ ค์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž!
์‚ฌ์šฉ์ž๊ฐ€ ํ™”๋ฉด์„ ๊ณ„์† ๋ณด๊ณ  ์žˆ์ง€ ์•Š์•„๋„ ๋ฌธ์ œ๋ฅผ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฑฐ์•ผ. ๐Ÿšจ

โšก ์ž„๊ณ„๊ฐ’ ๊ธฐ๋ฐ˜ ์•Œ๋ฆผ ์‹œ์Šคํ…œ

import psutil
import time
import winsound  # Windows ์ „์šฉ (๋‹ค๋ฅธ OS๋Š” ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ)
from datetime import datetime
import json

class AlertSystem:
    def __init__(self, cpu_threshold=80, memory_threshold=85):
        """
        ์•Œ๋ฆผ ์‹œ์Šคํ…œ ์ดˆ๊ธฐํ™”
        
        Args:
            cpu_threshold: CPU ์‚ฌ์šฉ๋ฅ  ์ž„๊ณ„๊ฐ’ (%)
            memory_threshold: ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ  ์ž„๊ณ„๊ฐ’ (%)
        """
        self.cpu_threshold = cpu_threshold
        self.memory_threshold = memory_threshold
        
        # ์•Œ๋ฆผ ๊ธฐ๋ก
        self.alert_history = []
        
        # ์—ฐ์† ์•Œ๋ฆผ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ์ฟจ๋‹ค์šด (์ดˆ)
        self.cooldown = 60
        self.last_cpu_alert = 0
        self.last_memory_alert = 0
    
    def check_cpu(self):
        """CPU ์‚ฌ์šฉ๋ฅ  ์ฒดํฌ"""
        cpu_percent = psutil.cpu_percent(interval=1)
        current_time = time.time()
        
        if cpu_percent > self.cpu_threshold:
            # ์ฟจ๋‹ค์šด ์ฒดํฌ
            if current_time - self.last_cpu_alert > self.cooldown:
                self.trigger_alert(
                    "CPU",
                    cpu_percent,
                    self.cpu_threshold
                )
                self.last_cpu_alert = current_time
                return True
        
        return False
    
    def check_memory(self):
        """๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ  ์ฒดํฌ"""
        memory = psutil.virtual_memory()
        memory_percent = memory.percent
        current_time = time.time()
        
        if memory_percent > self.memory_threshold:
            if current_time - self.last_memory_alert > self.cooldown:
                self.trigger_alert(
                    "Memory",
                    memory_percent,
                    self.memory_threshold
                )
                self.last_memory_alert = current_time
                return True
        
        return False
    
    def trigger_alert(self, resource_type, current_value, threshold):
        """์•Œ๋ฆผ ๋ฐœ์ƒ"""
        
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        alert_info = {
            "timestamp": timestamp,
            "type": resource_type,
            "value": current_value,
            "threshold": threshold
        }
        
        # ์•Œ๋ฆผ ๊ธฐ๋ก ์ €์žฅ
        self.alert_history.append(alert_info)
        
        # ์ฝ˜์†” ์ถœ๋ ฅ
        print("\n" + "="*50)
        print(f"โš ๏ธ  ๊ฒฝ๊ณ  ์•Œ๋ฆผ!")
        print(f"์‹œ๊ฐ„: {timestamp}")
        print(f"์œ ํ˜•: {resource_type}")
        print(f"ํ˜„์žฌ ๊ฐ’: {current_value:.1f}%")
        print(f"์ž„๊ณ„๊ฐ’: {threshold}%")
        print("="*50 + "\n")
        
        # ์†Œ๋ฆฌ ์•Œ๋ฆผ (Windows)
        try:
            winsound.Beep(1000, 500)  # 1000Hz, 500ms
        except:
            pass  # ๋‹ค๋ฅธ OS์—์„œ๋Š” ๋ฌด์‹œ
        
        # ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋ก
        self.save_to_log(alert_info)
    
    def save_to_log(self, alert_info):
        """์•Œ๋ฆผ์„ ๋กœ๊ทธ ํŒŒ์ผ์— ์ €์žฅ"""
        try:
            with open("system_alerts.log", "a", encoding="utf-8") as f:
                log_entry = json.dumps(alert_info, ensure_ascii=False)
                f.write(log_entry + "\n")
        except Exception as e:
            print(f"๋กœ๊ทธ ์ €์žฅ ์‹คํŒจ: {e}")
    
    def get_alert_summary(self):
        """์•Œ๋ฆผ ์š”์•ฝ ์ •๋ณด ๋ฐ˜ํ™˜"""
        if not self.alert_history:
            return "์•Œ๋ฆผ ๊ธฐ๋ก์ด ์—†์Šต๋‹ˆ๋‹ค."
        
        cpu_alerts = sum(1 for a in self.alert_history if a['type'] == 'CPU')
        memory_alerts = sum(1 for a in self.alert_history if a['type'] == 'Memory')
        
        summary = f"""
๐Ÿ“Š ์•Œ๋ฆผ ์š”์•ฝ
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
์ด ์•Œ๋ฆผ ์ˆ˜: {len(self.alert_history)}๊ฐœ
CPU ์•Œ๋ฆผ: {cpu_alerts}๊ฐœ
๋ฉ”๋ชจ๋ฆฌ ์•Œ๋ฆผ: {memory_alerts}๊ฐœ

์ตœ๊ทผ ์•Œ๋ฆผ:
"""
        # ์ตœ๊ทผ 5๊ฐœ ์•Œ๋ฆผ ํ‘œ์‹œ
        for alert in self.alert_history[-5:]:
            summary += f"\n[{alert['timestamp']}] {alert['type']}: {alert['value']:.1f}%"
        
        return summary
    
    def monitor(self, duration=None):
        """
        ์ง€์†์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์ž‘
        
        Args:
            duration: ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ๊ฐ„(์ดˆ), None์ด๋ฉด ๋ฌดํ•œ ์‹คํ–‰
        """
        print("๐Ÿ” ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค...")
        print(f"CPU ์ž„๊ณ„๊ฐ’: {self.cpu_threshold}%")
        print(f"๋ฉ”๋ชจ๋ฆฌ ์ž„๊ณ„๊ฐ’: {self.memory_threshold}%")
        print("\n์ข…๋ฃŒํ•˜๋ ค๋ฉด Ctrl+C๋ฅผ ๋ˆ„๋ฅด์„ธ์š”.\n")
        
        start_time = time.time()
        
        try:
            while True:
                # ์‹œ๊ฐ„ ์ œํ•œ ์ฒดํฌ
                if duration and (time.time() - start_time) > duration:
                    break
                
                # CPU ์ฒดํฌ
                self.check_cpu()
                
                # ๋ฉ”๋ชจ๋ฆฌ ์ฒดํฌ
                self.check_memory()
                
                # ํ˜„์žฌ ์ƒํƒœ ์ถœ๋ ฅ
                cpu = psutil.cpu_percent(interval=0.1)
                memory = psutil.virtual_memory().percent
                
                print(f"[{datetime.now().strftime('%H:%M:%S')}] "
                      f"CPU: {cpu:.1f}% | Memory: {memory:.1f}%", end='\r')
                
                time.sleep(5)  # 5์ดˆ๋งˆ๋‹ค ์ฒดํฌ
                
        except KeyboardInterrupt:
            print("\n\n๋ชจ๋‹ˆํ„ฐ๋ง์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
            print(self.get_alert_summary())

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    # ์•Œ๋ฆผ ์‹œ์Šคํ…œ ์ƒ์„ฑ (CPU 80%, ๋ฉ”๋ชจ๋ฆฌ 85% ์ž„๊ณ„๊ฐ’)
    alert_system = AlertSystem(cpu_threshold=80, memory_threshold=85)
    
    # ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์ž‘
    alert_system.monitor()
๐Ÿ’ก ๊ฐœ์„  ์•„์ด๋””์–ด: 1. ์ด๋ฉ”์ผ ์•Œ๋ฆผ: smtplib๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฉ”์ผ๋กœ ์•Œ๋ฆผ ์ „์†ก
2. Slack/Discord ์—ฐ๋™: ์›นํ›…์„ ์‚ฌ์šฉํ•ด์„œ ๋ฉ”์‹ ์ €๋กœ ์•Œ๋ฆผ
3. ๋ฐ์Šคํฌํ†ฑ ์•Œ๋ฆผ: plyer ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์‹œ์Šคํ…œ ํŠธ๋ ˆ์ด ์•Œ๋ฆผ
4. SMS ์•Œ๋ฆผ: Twilio API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ž ๋ฉ”์‹œ์ง€ ์ „์†ก

ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ์™€ ํ•„์š”์— ๋”ฐ๋ผ ์„ ํƒํ•˜๋ฉด ๋ผ! ๐ŸŽฏ

๐Ÿ’พ ๋ฐ์ดํ„ฐ ๋กœ๊น… ๋ฐ ๋ถ„์„

์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๋Š” ๊ฒƒ๋„ ๋งค์šฐ ์œ ์šฉํ•ด!
์–ธ์ œ ์‹œ์Šคํ…œ ๋ถ€ํ•˜๊ฐ€ ๋†’์•˜๋Š”์ง€, ์–ด๋–ค ํŒจํ„ด์ด ์žˆ๋Š”์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ . ๐Ÿ“Š

๐Ÿ“ CSV ํŒŒ์ผ๋กœ ๋ฐ์ดํ„ฐ ์ €์žฅํ•˜๊ธฐ

import psutil
import csv
import time
from datetime import datetime
import os

class DataLogger:
    def __init__(self, log_file="system_log.csv"):
        """
        ๋ฐ์ดํ„ฐ ๋กœ๊ฑฐ ์ดˆ๊ธฐํ™”
        
        Args:
            log_file: ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ
        """
        self.log_file = log_file
        self.initialize_log_file()
    
    def initialize_log_file(self):
        """๋กœ๊ทธ ํŒŒ์ผ ์ดˆ๊ธฐํ™” (ํ—ค๋” ์ž‘์„ฑ)"""
        
        # ํŒŒ์ผ์ด ์ด๋ฏธ ์กด์žฌํ•˜๋ฉด ๊ฑด๋„ˆ๋›ฐ๊ธฐ
        if os.path.exists(self.log_file):
            print(f"๊ธฐ์กด ๋กœ๊ทธ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: {self.log_file}")
            return
        
        # ์ƒˆ ํŒŒ์ผ ์ƒ์„ฑ ๋ฐ ํ—ค๋” ์ž‘์„ฑ
        headers = [
            "timestamp",
            "cpu_percent",
            "cpu_count",
            "memory_total_gb",
            "memory_used_gb",
            "memory_percent",
            "disk_usage_percent",
            "network_sent_mb",
            "network_recv_mb"
        ]
        
        with open(self.log_file, 'w', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow(headers)
        
        print(f"์ƒˆ ๋กœ๊ทธ ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: {self.log_file}")
    
    def collect_system_info(self):
        """ํ˜„์žฌ ์‹œ์Šคํ…œ ์ •๋ณด ์ˆ˜์ง‘"""
        
        # CPU ์ •๋ณด
        cpu_percent = psutil.cpu_percent(interval=1)
        cpu_count = psutil.cpu_count()
        
        # ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด
        memory = psutil.virtual_memory()
        memory_total = round(memory.total / (1024**3), 2)
        memory_used = round(memory.used / (1024**3), 2)
        memory_percent = memory.percent
        
        # ๋””์Šคํฌ ์ •๋ณด
        disk = psutil.disk_usage('/')
        disk_percent = disk.percent
        
        # ๋„คํŠธ์›Œํฌ ์ •๋ณด
        network = psutil.net_io_counters()
        network_sent = round(network.bytes_sent / (1024**2), 2)
        network_recv = round(network.bytes_recv / (1024**2), 2)
        
        # ํƒ€์ž„์Šคํƒฌํ”„
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        return {
            "timestamp": timestamp,
            "cpu_percent": cpu_percent,
            "cpu_count": cpu_count,
            "memory_total_gb": memory_total,
            "memory_used_gb": memory_used,
            "memory_percent": memory_percent,
            "disk_usage_percent": disk_percent,
            "network_sent_mb": network_sent,
            "network_recv_mb": network_recv
        }
    
    def log_data(self):
        """๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋ก"""
        
        info = self.collect_system_info()
        
        with open(self.log_file, 'a', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow([
                info["timestamp"],
                info["cpu_percent"],
                info["cpu_count"],
                info["memory_total_gb"],
                info["memory_used_gb"],
                info["memory_percent"],
                info["disk_usage_percent"],
                info["network_sent_mb"],
                info["network_recv_mb"]
            ])
        
        return info
    
    def start_logging(self, interval=60, duration=None):
        """
        ์ฃผ๊ธฐ์ ์ธ ๋กœ๊น… ์‹œ์ž‘
        
        Args:
            interval: ๋กœ๊น… ๊ฐ„๊ฒฉ (์ดˆ)
            duration: ์ด ๋กœ๊น… ์‹œ๊ฐ„ (์ดˆ), None์ด๋ฉด ๋ฌดํ•œ
        """
        print(f"๐Ÿ“ ๋ฐ์ดํ„ฐ ๋กœ๊น…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.")
        print(f"๋กœ๊ทธ ํŒŒ์ผ: {self.log_file}")
        print(f"๋กœ๊น… ๊ฐ„๊ฒฉ: {interval}์ดˆ")
        print("\n์ข…๋ฃŒํ•˜๋ ค๋ฉด Ctrl+C๋ฅผ ๋ˆ„๋ฅด์„ธ์š”.\n")
        
        start_time = time.time()
        log_count = 0
        
        try:
            while True:
                # ์‹œ๊ฐ„ ์ œํ•œ ์ฒดํฌ
                if duration and (time.time() - start_time) > duration:
                    break
                
                # ๋ฐ์ดํ„ฐ ๋กœ๊น…
                info = self.log_data()
                log_count += 1
                
                # ์ง„ํ–‰ ์ƒํ™ฉ ์ถœ๋ ฅ
                print(f"[{info['timestamp']}] "
                      f"๋กœ๊ทธ #{log_count} | "
                      f"CPU: {info['cpu_percent']:.1f}% | "
                      f"Memory: {info['memory_percent']:.1f}%")
                
                time.sleep(interval)
                
        except KeyboardInterrupt:
            print(f"\n\n๋กœ๊น…์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
            print(f"์ด {log_count}๊ฐœ์˜ ๋กœ๊ทธ๊ฐ€ ๊ธฐ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    logger = DataLogger("system_log.csv")
    
    # 60์ดˆ๋งˆ๋‹ค ๋กœ๊น… (๋ฌดํ•œ ์‹คํ–‰)
    logger.start_logging(interval=60)

๐Ÿ“Š ๋กœ๊ทธ ๋ฐ์ดํ„ฐ ๋ถ„์„ํ•˜๊ธฐ

import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime

class LogAnalyzer:
    def __init__(self, log_file="system_log.csv"):
        """๋กœ๊ทธ ๋ถ„์„๊ธฐ ์ดˆ๊ธฐํ™”"""
        self.log_file = log_file
        self.df = None
        self.load_data()
    
    def load_data(self):
        """CSV ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ"""
        try:
            self.df = pd.read_csv(self.log_file)
            self.df['timestamp'] = pd.to_datetime(self.df['timestamp'])
            print(f"โœ… {len(self.df)}๊ฐœ์˜ ๋กœ๊ทธ๋ฅผ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.")
        except FileNotFoundError:
            print(f"โŒ ๋กœ๊ทธ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {self.log_file}")
        except Exception as e:
            print(f"โŒ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์‹คํŒจ: {e}")
    
    def get_statistics(self):
        """๊ธฐ๋ณธ ํ†ต๊ณ„ ์ •๋ณด ์ถœ๋ ฅ"""
        if self.df is None or self.df.empty:
            print("๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
            return
        
        print("\n" + "="*60)
        print("๐Ÿ“Š ์‹œ์Šคํ…œ ์‚ฌ์šฉ ํ†ต๊ณ„")
        print("="*60)
        
        # CPU ํ†ต๊ณ„
        print("\n๐Ÿ”ฅ CPU ์‚ฌ์šฉ๋ฅ ")
        print(f"  ํ‰๊ท : {self.df['cpu_percent'].mean():.2f}%")
        print(f"  ์ตœ๋Œ€: {self.df['cpu_percent'].max():.2f}%")
        print(f"  ์ตœ์†Œ: {self.df['cpu_percent'].min():.2f}%")
        
        # ๋ฉ”๋ชจ๋ฆฌ ํ†ต๊ณ„
        print("\n๐Ÿ’พ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ")
        print(f"  ํ‰๊ท : {self.df['memory_percent'].mean():.2f}%")
        print(f"  ์ตœ๋Œ€: {self.df['memory_percent'].max():.2f}%")
        print(f"  ์ตœ์†Œ: {self.df['memory_percent'].min():.2f}%")
        
        # ๋””์Šคํฌ ํ†ต๊ณ„
        print("\n๐Ÿ’ฟ ๋””์Šคํฌ ์‚ฌ์šฉ๋ฅ ")
        print(f"  ํ‰๊ท : {self.df['disk_usage_percent'].mean():.2f}%")
        
        # ๋„คํŠธ์›Œํฌ ํ†ต๊ณ„
        print("\n๐ŸŒ ๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ๋Ÿ‰")
        total_sent = self.df['network_sent_mb'].iloc[-1] - self.df['network_sent_mb'].iloc[0]
        total_recv = self.df['network_recv_mb'].iloc[-1] - self.df['network_recv_mb'].iloc[0]
        print(f"  ์ „์†ก: {total_sent:.2f} MB")
        print(f"  ์ˆ˜์‹ : {total_recv:.2f} MB")
        
        print("\n" + "="*60 + "\n")
    
    def plot_trends(self):
        """์‹œ๊ฐ„์— ๋”ฐ๋ฅธ ํŠธ๋ Œ๋“œ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ"""
        if self.df is None or self.df.empty:
            print("๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
            return
        
        fig, axes = plt.subplots(2, 2, figsize=(14, 10))
        fig.suptitle('์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํŠธ๋ Œ๋“œ ๋ถ„์„', fontsize=16, fontweight='bold')
        
        # CPU ์‚ฌ์šฉ๋ฅ 
        axes[0, 0].plot(self.df['timestamp'], self.df['cpu_percent'], 
                        color='#667eea', linewidth=2)
        axes[0, 0].set_title('CPU ์‚ฌ์šฉ๋ฅ ', fontweight='bold')
        axes[0, 0].set_ylabel('์‚ฌ์šฉ๋ฅ  (%)')
        axes[0, 0].grid(True, alpha=0.3)
        axes[0, 0].axhline(y=80, color='r', linestyle='--', alpha=0.5, label='์œ„ํ—˜ ์ˆ˜์ค€')
        axes[0, 0].legend()
        
        # ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ 
        axes[0, 1].plot(self.df['timestamp'], self.df['memory_percent'], 
                        color='#f5576c', linewidth=2)
        axes[0, 1].set_title('๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ', fontweight='bold')
        axes[0, 1].set_ylabel('์‚ฌ์šฉ๋ฅ  (%)')
        axes[0, 1].grid(True, alpha=0.3)
        axes[0, 1].axhline(y=85, color='r', linestyle='--', alpha=0.5, label='์œ„ํ—˜ ์ˆ˜์ค€')
        axes[0, 1].legend()
        
        # ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ (GB)
        axes[1, 0].plot(self.df['timestamp'], self.df['memory_used_gb'], 
                        color='#4facfe', linewidth=2)
        axes[1, 0].set_title('๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰', fontweight='bold')
        axes[1, 0].set_ylabel('์‚ฌ์šฉ๋Ÿ‰ (GB)')
        axes[1, 0].grid(True, alpha=0.3)
        
        # ๋””์Šคํฌ ์‚ฌ์šฉ๋ฅ 
        axes[1, 1].plot(self.df['timestamp'], self.df['disk_usage_percent'], 
                        color='#43e97b', linewidth=2)
        axes[1, 1].set_title('๋””์Šคํฌ ์‚ฌ์šฉ๋ฅ ', fontweight='bold')
        axes[1, 1].set_ylabel('์‚ฌ์šฉ๋ฅ  (%)')
        axes[1, 1].grid(True, alpha=0.3)
        
        # ๋ ˆ์ด์•„์›ƒ ์กฐ์ •
        plt.tight_layout()
        plt.show()
    
    def find_peak_usage(self, top_n=5):
        """์ตœ๊ณ  ์‚ฌ์šฉ๋ฅ  ์‹œ์  ์ฐพ๊ธฐ"""
        if self.df is None or self.df.empty:
            print("๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
            return
        
        print("\n" + "="*60)
        print(f"๐Ÿ” CPU ์‚ฌ์šฉ๋ฅ  ์ƒ์œ„ {top_n}๊ฐœ ์‹œ์ ")
        print("="*60)
        
        top_cpu = self.df.nlargest(top_n, 'cpu_percent')[['timestamp', 'cpu_percent']]
        for idx, row in top_cpu.iterrows():
            print(f"{row['timestamp']} - {row['cpu_percent']:.2f}%")
        
        print("\n" + "="*60)
        print(f"๐Ÿ” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ  ์ƒ์œ„ {top_n}๊ฐœ ์‹œ์ ")
        print("="*60)
        
        top_memory = self.df.nlargest(top_n, 'memory_percent')[['timestamp', 'memory_percent']]
        for idx, row in top_memory.iterrows():
            print(f"{row['timestamp']} - {row['memory_percent']:.2f}%")
        
        print("\n")

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    analyzer = LogAnalyzer("system_log.csv")
    
    # ํ†ต๊ณ„ ์ •๋ณด ์ถœ๋ ฅ
    analyzer.get_statistics()
    
    # ์ตœ๊ณ  ์‚ฌ์šฉ๋ฅ  ์‹œ์  ์ฐพ๊ธฐ
    analyzer.find_peak_usage(top_n=5)
    
    # ํŠธ๋ Œ๋“œ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
    analyzer.plot_trends()

pandas๋Š” ๋ฐ์ดํ„ฐ ๋ถ„์„์˜ ํ•„์ˆ˜ ๋„๊ตฌ์•ผ!
CSV ํŒŒ์ผ์„ DataFrame์œผ๋กœ ์ฝ์–ด์˜ค๋ฉด SQL์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด.
๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋„ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ๊ฐ•๋ ฅํ•˜์ง€! ๐Ÿ’ช

๐ŸŒ ์›น ๊ธฐ๋ฐ˜ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ

๋ฐ์Šคํฌํ†ฑ ์•ฑ๋„ ์ข‹์ง€๋งŒ, ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์‹œ๋ณด๋“œ๋Š” ์–ด๋•Œ?
์–ด๋””์„œ๋“  ์ ‘์†ํ•ด์„œ ์‹œ์Šคํ…œ ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์„œ ํŽธ๋ฆฌํ•ด! ๐ŸŒ

Flask๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ์›น ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด.

๐Ÿš€ Flask ๊ธฐ๋ฐ˜ ๋ชจ๋‹ˆํ„ฐ๋ง ์„œ๋ฒ„

from flask import Flask, render_template, jsonify
import psutil
import json
from datetime import datetime

app = Flask(__name__)

@app.route('/')
def index():
    """๋ฉ”์ธ ๋Œ€์‹œ๋ณด๋“œ ํŽ˜์ด์ง€"""
    return render_template('dashboard.html')

@app.route('/api/system-info')
def get_system_info():
    """์‹œ์Šคํ…œ ์ •๋ณด API ์—”๋“œํฌ์ธํŠธ"""
    
    # CPU ์ •๋ณด
    cpu_percent = psutil.cpu_percent(interval=1)
    cpu_count = psutil.cpu_count()
    cpu_freq = psutil.cpu_freq()
    
    # ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด
    memory = psutil.virtual_memory()
    swap = psutil.swap_memory()
    
    # ๋””์Šคํฌ ์ •๋ณด
    disk = psutil.disk_usage('/')
    
    # ๋„คํŠธ์›Œํฌ ์ •๋ณด
    network = psutil.net_io_counters()
    
    # ํ”„๋กœ์„ธ์Šค ์ •๋ณด (์ƒ์œ„ 5๊ฐœ)
    processes = []
    for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
        try:
            processes.append(proc.info)
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass
    
    # CPU ์‚ฌ์šฉ๋ฅ  ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
    processes.sort(key=lambda x: x['cpu_percent'] or 0, reverse=True)
    top_processes = processes[:5]
    
    # JSON ์‘๋‹ต ์ƒ์„ฑ
    response = {
        'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        'cpu': {
            'percent': cpu_percent,
            'count': cpu_count,
            'frequency': {
                'current': cpu_freq.current if cpu_freq else 0,
                'min': cpu_freq.min if cpu_freq else 0,
                'max': cpu_freq.max if cpu_freq else 0
            }
        },
        'memory': {
            'total': round(memory.total / (1024**3), 2),
            'available': round(memory.available / (1024**3), 2),
            'used': round(memory.used / (1024**3), 2),
            'percent': memory.percent
        },
        'swap': {
            'total': round(swap.total / (1024**3), 2),
            'used': round(swap.used / (1024**3), 2),
            'percent': swap.percent
        },
        'disk': {
            'total': round(disk.total / (1024**3), 2),
            'used': round(disk.used / (1024**3), 2),
            'free': round(disk.free / (1024**3), 2),
            'percent': disk.percent
        },
        'network': {
            'bytes_sent': round(network.bytes_sent / (1024**2), 2),
            'bytes_recv': round(network.bytes_recv / (1024**2), 2)
        },
        'top_processes': top_processes
    }
    
    return jsonify(response)

@app.route('/api/cpu-history')
def get_cpu_history():
    """CPU ์‚ฌ์šฉ๋ฅ  ํžˆ์Šคํ† ๋ฆฌ (๊ฐ„๋‹จํ•œ ์˜ˆ์ œ)"""
    # ์‹ค์ œ๋กœ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์บ์‹œ์—์„œ ๊ฐ€์ ธ์™€์•ผ ํ•จ
    history = []
    for i in range(60):
        history.append({
            'time': i,
            'value': psutil.cpu_percent(interval=0.1)
        })
    return jsonify(history)

if __name__ == '__main__':
    print("๐ŸŒ ๋ชจ๋‹ˆํ„ฐ๋ง ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค...")
    print("๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:5000 ์œผ๋กœ ์ ‘์†ํ•˜์„ธ์š”!")
    app.run(debug=True, host='0.0.0.0', port=5000)

๐ŸŽจ HTML ๋Œ€์‹œ๋ณด๋“œ ํ…œํ”Œ๋ฆฟ

<!-- templates/dashboard.html -->
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f5f7fa; }
        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; }
        .container { max-width: 1400px; margin: 30px auto; padding: 0 20px; }
        .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px; }
        .card { background: white; border-radius: 12px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .card-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #333; }
        .metric { font-size: 36px; font-weight: bold; color: #667eea; margin: 10px 0; }
        .progress-bar { width: 100%; height: 20px; background: #e9ecef; border-radius: 10px; overflow: hidden; margin: 10px 0; }
        .progress-fill { height: 100%; background: linear-gradient(90deg, #667eea, #764ba2); transition: width 0.3s ease; }
        .process-list { list-style: none; }
        .process-item { padding: 10px; border-bottom: 1px solid #e9ecef; display: flex; justify-content: space-between; }
        .status-good { color: #28a745; }
        .status-warning { color: #ffc107; }
        .status-danger { color: #dc3545; }
    </style>
</head>
<body>
    <div class="header">
        <h1>๐Ÿ’ป ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ</h1>
        <p>์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค ๋ชจ๋‹ˆํ„ฐ๋ง</p>
    </div>

    <div class="container">
        <div class="grid">
            <div class="card">
                <div class="card-title">๐Ÿ”ฅ CPU ์‚ฌ์šฉ๋ฅ </div>
                <div class="metric" id="cpu-percent">--%</div>
                <div class="progress-bar">
                    <div class="progress-fill" id="cpu-progress" style="width: 0%"></div>
                </div>
                <p>์ฝ”์–ด ์ˆ˜: <span id="cpu-count">--</span>๊ฐœ</p>
            </div>

            <div class="card">
                <div class="card-title">๐Ÿ’พ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ </div>
                <div class="metric" id="memory-percent">--%</div>
                <div class="progress-bar">
                    <div class="progress-fill" id="memory-progress" style="width: 0%"></div>
                </div>
                <p><span id="memory-used">--</span> GB / <span id="memory-total">--</span> GB</p>
            </div>

            <div class="card">
                <div class="card-title">๐Ÿ’ฟ ๋””์Šคํฌ ์‚ฌ์šฉ๋ฅ </div>
                <div class="metric" id="disk-percent">--%</div>
                <div class="progress-bar">
                    <div class="progress-fill" id="disk-progress" style="width: 0%"></div>
                </div>
                <p><span id="disk-used">--</span> GB / <span id="disk-total">--</span> GB</p>
            </div>
        </div>

        <div class="card">
            <div class="card-title">๐Ÿ“Š ์ƒ์œ„ ํ”„๋กœ์„ธ์Šค (CPU ์‚ฌ์šฉ๋ฅ  ๊ธฐ์ค€)</div>
            <ul class="process-list" id="process-list">
                <li class="process-item">๋กœ๋”ฉ ์ค‘...</li>
            </ul>
        </div>
    </div>

    <script>
        function updateDashboard() {
            fetch('/api/system-info')
                .then(response => response.json())
                .then(data => {
                    // CPU ์—…๋ฐ์ดํŠธ
                    document.getElementById('cpu-percent').textContent = data.cpu.percent.toFixed(1) + '%';
                    document.getElementById('cpu-progress').style.width = data.cpu.percent + '%';
                    document.getElementById('cpu-count').textContent = data.cpu.count;
                    
                    // ๋ฉ”๋ชจ๋ฆฌ ์—…๋ฐ์ดํŠธ
                    document.getElementById('memory-percent').textContent = data.memory.percent.toFixed(1) + '%';
                    document.getElementById('memory-progress').style.width = data.memory.percent + '%';
                    document.getElementById('memory-used').textContent = data.memory.used;
                    document.getElementById('memory-total').textContent = data.memory.total;
                    
                    // ๋””์Šคํฌ ์—…๋ฐ์ดํŠธ
                    document.getElementById('disk-percent').textContent = data.disk.percent.toFixed(1) + '%';
                    document.getElementById('disk-progress').style.width = data.disk.percent + '%';
                    document.getElementById('disk-used').textContent = data.disk.used;
                    document.getElementById('disk-total').textContent = data.disk.total;
                    
                    // ํ”„๋กœ์„ธ์Šค ๋ชฉ๋ก ์—…๋ฐ์ดํŠธ
                    const processList = document.getElementById('process-list');
                    processList.innerHTML = '';
                    
                    data.top_processes.forEach(proc => {
                        const li = document.createElement('li');
                        li.className = 'process-item';
                        li.innerHTML = `
                            <span>${proc.name} (PID: ${proc.pid})</span>
                            <span>CPU: ${(proc.cpu_percent || 0).toFixed(1)}%</span>
                        `;
                        processList.appendChild(li);
                    });
                })
                .catch(error => console.error('Error:', error));
        }

        // ์ดˆ๊ธฐ ๋กœ๋“œ
        updateDashboard();
        
        // 2์ดˆ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ
        setInterval(updateDashboard, 2000);
    </script>
</body>
</html>
๐ŸŒŸ ์›น ๋Œ€์‹œ๋ณด๋“œ์˜ ์žฅ์ : 1. ํฌ๋กœ์Šค ํ”Œ๋žซํผ: ์–ด๋–ค ๊ธฐ๊ธฐ์—์„œ๋“  ๋ธŒ๋ผ์šฐ์ €๋งŒ ์žˆ์œผ๋ฉด ์ ‘์† ๊ฐ€๋Šฅ
2. ์›๊ฒฉ ๋ชจ๋‹ˆํ„ฐ๋ง: ๋„คํŠธ์›Œํฌ๋งŒ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์œผ๋ฉด ์–ด๋””์„œ๋“  ํ™•์ธ
3. ๋ฐ˜์‘ํ˜• ๋””์ž์ธ: ๋ชจ๋ฐ”์ผ, ํƒœ๋ธ”๋ฆฟ, ๋ฐ์Šคํฌํ†ฑ ๋ชจ๋‘ ์ง€์›
4. ์‰ฌ์šด ๊ณต์œ : URL๋งŒ ๊ณต์œ ํ•˜๋ฉด ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์ด ๋™์‹œ์— ๋ชจ๋‹ˆํ„ฐ๋ง ๊ฐ€๋Šฅ

๋ณด์•ˆ์ด ์ค‘์š”ํ•˜๋‹ค๋ฉด ์ธ์ฆ ์‹œ์Šคํ…œ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ! ๐Ÿ”

๐Ÿ”ง ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

๊ธฐ๋ณธ์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ๋„˜์–ด์„œ ๋” ์ „๋ฌธ์ ์ธ ๊ธฐ๋Šฅ๋“ค์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž!
์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์˜ ํˆด์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ์•ผ. ๐Ÿš€

๐Ÿ“ฑ ํ”„๋กœ์„ธ์Šค๋ณ„ ์ƒ์„ธ ๋ชจ๋‹ˆํ„ฐ๋ง

import psutil
from datetime import datetime
import time

class ProcessMonitor:
    def __init__(self):
        """ํ”„๋กœ์„ธ์Šค ๋ชจ๋‹ˆํ„ฐ ์ดˆ๊ธฐํ™”"""
        self.process_history = {}
    
    def get_process_info(self, pid):
        """ํŠน์ • ํ”„๋กœ์„ธ์Šค์˜ ์ƒ์„ธ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ"""
        try:
            process = psutil.Process(pid)
            
            # ํ”„๋กœ์„ธ์Šค ๊ธฐ๋ณธ ์ •๋ณด
            info = {
                'pid': pid,
                'name': process.name(),
                'status': process.status(),
                'create_time': datetime.fromtimestamp(process.create_time()).strftime('%Y-%m-%d %H:%M:%S'),
                'username': process.username(),
                'cpu_percent': process.cpu_percent(interval=0.1),
                'memory_info': {
                    'rss': round(process.memory_info().rss / (1024**2), 2),  # MB
                    'vms': round(process.memory_info().vms / (1024**2), 2),  # MB
                    'percent': process.memory_percent()
                },
                'num_threads': process.num_threads(),
                'num_fds': process.num_fds() if hasattr(process, 'num_fds') else 'N/A',
                'io_counters': None
            }
            
            # I/O ์นด์šดํ„ฐ (์ง€์›๋˜๋Š” ๊ฒฝ์šฐ)
            try:
                io = process.io_counters()
                info['io_counters'] = {
                    'read_bytes': round(io.read_bytes / (1024**2), 2),  # MB
                    'write_bytes': round(io.write_bytes / (1024**2), 2)  # MB
                }
            except (psutil.AccessDenied, AttributeError):
                pass
            
            # ์—ฐ๊ฒฐ ์ •๋ณด
            try:
                connections = process.connections()
                info['connections'] = len(connections)
            except (psutil.AccessDenied, psutil.NoSuchProcess):
                info['connections'] = 'N/A'
            
            return info
            
        except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
            return {'error': str(e)}
    
    def get_all_processes(self, sort_by='cpu'):
        """๋ชจ๋“  ํ”„๋กœ์„ธ์Šค ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ"""
        processes = []
        
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status']):
            try:
                info = proc.info
                info['cpu_percent'] = proc.cpu_percent(interval=0.1)
                processes.append(info)
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                pass
        
        # ์ •๋ ฌ
        if sort_by == 'cpu':
            processes.sort(key=lambda x: x['cpu_percent'] or 0, reverse=True)
        elif sort_by == 'memory':
            processes.sort(key=lambda x: x['memory_percent'] or 0, reverse=True)
        
        return processes
    
    def monitor_process(self, pid, duration=60, interval=1):
        """ํŠน์ • ํ”„๋กœ์„ธ์Šค๋ฅผ ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ๋ชจ๋‹ˆํ„ฐ๋ง"""
        print(f"๐Ÿ” ํ”„๋กœ์„ธ์Šค {pid} ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์ž‘")
        print(f"๊ธฐ๊ฐ„: {duration}์ดˆ, ๊ฐ„๊ฒฉ: {interval}์ดˆ\n")
        
        start_time = time.time()
        samples = []
        
        try:
            while (time.time() - start_time) < duration:
                info = self.get_process_info(pid)
                
                if 'error' in info:
                    print(f"โŒ ์˜ค๋ฅ˜: {info['error']}")
                    break
                
                samples.append({
                    'timestamp': datetime.now().strftime('%H:%M:%S'),
                    'cpu': info['cpu_percent'],
                    'memory': info['memory_info']['percent']
                })
                
                print(f"[{samples[-1]['timestamp']}] "
                      f"CPU: {info['cpu_percent']:.1f}% | "
                      f"Memory: {info['memory_info']['percent']:.1f}% | "
                      f"Threads: {info['num_threads']}")
                
                time.sleep(interval)
                
        except KeyboardInterrupt:
            print("\n๋ชจ๋‹ˆํ„ฐ๋ง์„ ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค.")
        
        # ํ†ต๊ณ„ ์ถœ๋ ฅ
        if samples:
            print("\n" + "="*60)
            print("๐Ÿ“Š ๋ชจ๋‹ˆํ„ฐ๋ง ๊ฒฐ๊ณผ ์š”์•ฝ")
            print("="*60)
            
            cpu_values = [s['cpu'] for s in samples]
            memory_values = [s['memory'] for s in samples]
            
            print(f"CPU ์‚ฌ์šฉ๋ฅ :")
            print(f"  ํ‰๊ท : {sum(cpu_values)/len(cpu_values):.2f}%")
            print(f"  ์ตœ๋Œ€: {max(cpu_values):.2f}%")
            print(f"  ์ตœ์†Œ: {min(cpu_values):.2f}%")
            
            print(f"\n๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ :")
            print(f"  ํ‰๊ท : {sum(memory_values)/len(memory_values):.2f}%")
            print(f"  ์ตœ๋Œ€: {max(memory_values):.2f}%")
            print(f"  ์ตœ์†Œ: {min(memory_values):.2f}%")
    
    def find_memory_hogs(self, top_n=10):
        """๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์„ธ์Šค ์ฐพ๊ธฐ"""
        processes = self.get_all_processes(sort_by='memory')
        
        print("\n" + "="*60)
        print(f"๐Ÿ’พ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ƒ์œ„ {top_n}๊ฐœ ํ”„๋กœ์„ธ์Šค")
        print("="*60)
        
        for i, proc in enumerate(processes[:top_n], 1):
            print(f"{i}. {proc['name']} (PID: {proc['pid']})")
            print(f"   ๋ฉ”๋ชจ๋ฆฌ: {proc['memory_percent']:.2f}%")
            print()
    
    def find_cpu_hogs(self, top_n=10):
        """CPU๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์„ธ์Šค ์ฐพ๊ธฐ"""
        processes = self.get_all_processes(sort_by='cpu')
        
        print("\n" + "="*60)
        print(f"๐Ÿ”ฅ CPU ์‚ฌ์šฉ๋Ÿ‰ ์ƒ์œ„ {top_n}๊ฐœ ํ”„๋กœ์„ธ์Šค")
        print("="*60)
        
        for i, proc in enumerate(processes[:top_n], 1):
            print(f"{i}. {proc['name']} (PID: {proc['pid']})")
            print(f"   CPU: {proc['cpu_percent']:.2f}%")
            print()

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    monitor = ProcessMonitor()
    
    # CPU ์‚ฌ์šฉ๋Ÿ‰ ์ƒ์œ„ ํ”„๋กœ์„ธ์Šค
    monitor.find_cpu_hogs(top_n=5)
    
    # ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ƒ์œ„ ํ”„๋กœ์„ธ์Šค
    monitor.find_memory_hogs(top_n=5)
    
    # ํŠน์ • ํ”„๋กœ์„ธ์Šค ๋ชจ๋‹ˆํ„ฐ๋ง (์˜ˆ: PID 1234)
    # monitor.monitor_process(1234, duration=30, interval=2)

๐ŸŒก๏ธ ์˜จ๋„ ๋ชจ๋‹ˆํ„ฐ๋ง (ํ•˜๋“œ์›จ์–ด ์„ผ์„œ)

import psutil

def monitor_temperatures():
    """์‹œ์Šคํ…œ ์˜จ๋„ ๋ชจ๋‹ˆํ„ฐ๋ง"""
    
    # ์˜จ๋„ ์„ผ์„œ๊ฐ€ ์ง€์›๋˜๋Š”์ง€ ํ™•์ธ
    if not hasattr(psutil, "sensors_temperatures"):
        print("โŒ ์ด ์‹œ์Šคํ…œ์€ ์˜จ๋„ ์„ผ์„œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
        return
    
    temps = psutil.sensors_temperatures()
    
    if not temps:
        print("โŒ ์˜จ๋„ ์„ผ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
        return
    
    print("\n" + "="*60)
    print("๐ŸŒก๏ธ  ์‹œ์Šคํ…œ ์˜จ๋„ ์ •๋ณด")
    print("="*60 + "\n")
    
    for name, entries in temps.items():
        print(f"๐Ÿ“ {name}:")
        for entry in entries:
            status = ""
            if entry.current > 80:
                status = " โš ๏ธ ๊ฒฝ๊ณ : ๋†’์€ ์˜จ๋„!"
            elif entry.current > 70:
                status = " โšก ์ฃผ์˜"
            
            print(f"  {entry.label or 'N/A'}: {entry.current}ยฐC{status}")
            if entry.high:
                print(f"    ์ตœ๋Œ€ ์•ˆ์ „ ์˜จ๋„: {entry.high}ยฐC")
            if entry.critical:
                print(f"    ์ž„๊ณ„ ์˜จ๋„: {entry.critical}ยฐC")
        print()

def monitor_fans():
    """ํŒฌ ์†๋„ ๋ชจ๋‹ˆํ„ฐ๋ง"""
    
    if not hasattr(psutil, "sensors_fans"):
        print("โŒ ์ด ์‹œ์Šคํ…œ์€ ํŒฌ ์„ผ์„œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
        return
    
    fans = psutil.sensors_fans()
    
    if not fans:
        print("โŒ ํŒฌ ์„ผ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
        return
    
    print("\n" + "="*60)
    print("๐ŸŒ€ ํŒฌ ์†๋„ ์ •๋ณด")
    print("="*60 + "\n")
    
    for name, entries in fans.items():
        print(f"๐Ÿ“ {name}:")
        for entry in entries:
            print(f"  {entry.label or 'N/A'}: {entry.current} RPM")
        print()

def monitor_battery():
    """๋ฐฐํ„ฐ๋ฆฌ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง (๋…ธํŠธ๋ถ)"""
    
    if not hasattr(psutil, "sensors_battery"):
        print("โŒ ๋ฐฐํ„ฐ๋ฆฌ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
        return
    
    battery = psutil.sensors_battery()
    
    if battery is None:
        print("โŒ ๋ฐฐํ„ฐ๋ฆฌ๊ฐ€ ๊ฐ์ง€๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. (๋ฐ์Šคํฌํ†ฑ?)")
        return
    
    print("\n" + "="*60)
    print("๐Ÿ”‹ ๋ฐฐํ„ฐ๋ฆฌ ์ •๋ณด")
    print("="*60 + "\n")
    
    print(f"๋ฐฐํ„ฐ๋ฆฌ ์ž”๋Ÿ‰: {battery.percent}%")
    print(f"์ „์› ์—ฐ๊ฒฐ: {'์˜ˆ' if battery.power_plugged else '์•„๋‹ˆ์˜ค'}")
    
    if battery.secsleft != psutil.POWER_TIME_UNLIMITED:
        hours = battery.secsleft // 3600
        minutes = (battery.secsleft % 3600) // 60
        print(f"๋‚จ์€ ์‹œ๊ฐ„: {hours}์‹œ๊ฐ„ {minutes}๋ถ„")
    else:
        print("๋‚จ์€ ์‹œ๊ฐ„: ์ถฉ์ „ ์ค‘")
    
    print()

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    monitor_temperatures()
    monitor_fans()
    monitor_battery()
โš ๏ธ ํ•˜๋“œ์›จ์–ด ์„ผ์„œ ์ฃผ์˜์‚ฌํ•ญ: ์˜จ๋„, ํŒฌ ์†๋„ ๊ฐ™์€ ํ•˜๋“œ์›จ์–ด ์„ผ์„œ ์ •๋ณด๋Š” ๋ชจ๋“  ์‹œ์Šคํ…œ์—์„œ ์ง€์›๋˜์ง€ ์•Š์•„.
ํŠนํžˆ ๊ฐ€์ƒ ๋จธ์‹ ์ด๋‚˜ ์ผ๋ถ€ ๋…ธํŠธ๋ถ์—์„œ๋Š” ์ ‘๊ทผ์ด ์ œํ•œ๋  ์ˆ˜ ์žˆ์–ด.

Linux์—์„œ๋Š” lm-sensors ํŒจํ‚ค์ง€๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•˜๊ณ ,
Windows์—์„œ๋Š” ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์–ด. ๐Ÿ”ง

๐ŸŽ“ ์‹ค์ „ ํ™œ์šฉ ํŒ๊ณผ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค

์ด์ œ ์‹ค์ œ๋กœ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์„ ์šด์˜ํ•  ๋•Œ ์•Œ์•„๋‘๋ฉด ์ข‹์€ ํŒ๋“ค์„ ๊ณต์œ ํ• ๊ฒŒ!
๊ฒฝํ—˜์—์„œ ์šฐ๋Ÿฌ๋‚˜์˜จ ๋…ธํ•˜์šฐ๋“ค์ด์•ผ. ๐Ÿ˜Š

๐Ÿ’ก 1. ์ ์ ˆํ•œ ์ƒ˜ํ”Œ๋ง ๊ฐ„๊ฒฉ ์„ค์ •

๋„ˆ๋ฌด ์งง์€ ๊ฐ„๊ฒฉ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋ฉด ์˜คํžˆ๋ ค ์‹œ์Šคํ…œ์— ๋ถ€ํ•˜๋ฅผ ์ค„ ์ˆ˜ ์žˆ์–ด.

๊ถŒ์žฅ ๊ฐ„๊ฒฉ:
โ€ข ์‹ค์‹œ๊ฐ„ ๋Œ€์‹œ๋ณด๋“œ: 1-2์ดˆ
โ€ข ๋กœ๊น…: 30-60์ดˆ
โ€ข ์žฅ๊ธฐ ํŠธ๋ Œ๋“œ ๋ถ„์„: 5-10๋ถ„

์ƒํ™ฉ์— ๋งž๊ฒŒ ์กฐ์ ˆํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด! โฑ๏ธ

๐Ÿ’ก 2. ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

์žฅ์‹œ๊ฐ„ ์‹คํ–‰๋˜๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์€ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ์ฃผ์˜ํ•ด์•ผ ํ•ด.

์ฒดํฌ๋ฆฌ์ŠคํŠธ:
โ€ข ๋ฐ์ดํ„ฐ ๋ฒ„ํผ ํฌ๊ธฐ ์ œํ•œ (deque์˜ maxlen ํ™œ์šฉ)
โ€ข ์ฃผ๊ธฐ์ ์ธ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜
โ€ข ์˜ค๋ž˜๋œ ๋กœ๊ทธ ํŒŒ์ผ ์ž๋™ ์‚ญ์ œ
โ€ข ํ”„๋กœ์„ธ์Šค ์žฌ์‹œ์ž‘ ์Šค์ผ€์ค„๋ง

์•ˆ์ •์ ์ธ ์šด์˜์„ ์œ„ํ•ด ํ•„์ˆ˜์•ผ! ๐Ÿ›ก๏ธ

๐Ÿ’ก 3. ์—๋Ÿฌ ์ฒ˜๋ฆฌ

์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง์€ ์˜ˆ์™ธ ์ƒํ™ฉ์ด ๋งŽ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด.

์ฃผ์š” ์˜ˆ์™ธ:
โ€ข psutil.NoSuchProcess: ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ข…๋ฃŒ๋จ
โ€ข psutil.AccessDenied: ๊ถŒํ•œ ๋ถ€์กฑ
โ€ข psutil.TimeoutExpired: ์‘๋‹ต ์‹œ๊ฐ„ ์ดˆ๊ณผ

๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ์ ์ ˆํžˆ ์ฒ˜๋ฆฌํ•ด์„œ ํ”„๋กœ๊ทธ๋žจ์ด ์ค‘๋‹จ๋˜์ง€ ์•Š๊ฒŒ ํ•ด์•ผ ํ•ด! ๐Ÿšจ

๐Ÿ’ก 4. ์„ฑ๋Šฅ ์ตœ์ ํ™”

๋ชจ๋‹ˆํ„ฐ๋ง ํˆด ์ž์ฒด๊ฐ€ ์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋˜๊ฒ ์ง€?

์ตœ์ ํ™” ํŒ:
โ€ข ํ•„์š”ํ•œ ์ •๋ณด๋งŒ ์ˆ˜์ง‘ (interval ํŒŒ๋ผ๋ฏธํ„ฐ ํ™œ์šฉ)
โ€ข ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ๋ณด๋‹ค๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ณ ๋ ค
โ€ข ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์ตœ์ ํ™”
โ€ข ์บ์‹ฑ ์ „๋žต ์ˆ˜๋ฆฝ

๊ฐ€๋ณ๊ณ  ํšจ์œจ์ ์ธ ํˆด์ด ์ตœ๊ณ ์•ผ! โšก

๐Ÿ’ก 5. ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ

์‹œ์Šคํ…œ ์ •๋ณด๋Š” ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ์•ผ. ๋ณด์•ˆ์— ์‹ ๊ฒฝ ์จ์•ผ ํ•ด!

๋ณด์•ˆ ์ฒดํฌ๋ฆฌ์ŠคํŠธ:
โ€ข ์›น ๋Œ€์‹œ๋ณด๋“œ์— ์ธ์ฆ ์ถ”๊ฐ€
โ€ข HTTPS ์‚ฌ์šฉ
โ€ข ๋กœ๊ทธ ํŒŒ์ผ ๊ถŒํ•œ ์„ค์ •
โ€ข API ์—”๋“œํฌ์ธํŠธ ์ ‘๊ทผ ์ œ์–ด
โ€ข ๋ฏผ๊ฐํ•œ ์ •๋ณด ๋งˆ์Šคํ‚น

๋ณด์•ˆ์€ ์„ ํƒ์ด ์•„๋‹ˆ๋ผ ํ•„์ˆ˜์•ผ! ๐Ÿ”

๐ŸŒŸ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€! ์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ์—ˆ๋‹ค๋ฉด ์ •๋ง ๋Œ€๋‹จํ•ด! ๐Ÿ‘

์šฐ๋ฆฌ๋Š” ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์„ ๋งŒ๋“œ๋Š” ์—ฌ์ •์„ ํ•จ๊ป˜ ํ–ˆ์–ด.
๊ธฐ๋ณธ์ ์ธ CPU, ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋‹ˆํ„ฐ๋ง๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ
GUI ์ธํ„ฐํŽ˜์ด์Šค, ์›น ๋Œ€์‹œ๋ณด๋“œ, ์•Œ๋ฆผ ์‹œ์Šคํ…œ, ๋ฐ์ดํ„ฐ ๋ถ„์„๊นŒ์ง€ ๋‹ค๋ค˜์ง€.

์ด์ œ ๋„ˆ๋งŒ์˜ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ! ๐Ÿš€

๐ŸŽฏ ๋‹ค์Œ ๋‹จ๊ณ„ ์ถ”์ฒœ:

1. ๊ธฐ๋Šฅ ํ™•์žฅ: ๋„คํŠธ์›Œํฌ ๋ชจ๋‹ˆํ„ฐ๋ง, ๋””์Šคํฌ I/O ์ถ”์  ๋“ฑ ์ถ”๊ฐ€
2. ์•Œ๋ฆผ ๊ณ ๋„ํ™”: ์ด๋ฉ”์ผ, Slack, Discord ์—ฐ๋™
3. ๋จธ์‹ ๋Ÿฌ๋‹ ์ ์šฉ: ์ด์ƒ ํƒ์ง€, ์˜ˆ์ธก ๋ถ„์„
4. ํด๋ผ์šฐ๋“œ ์—ฐ๋™: AWS CloudWatch, Azure Monitor ํ†ตํ•ฉ
5. ์ปจํ…Œ์ด๋„ˆ ๋ชจ๋‹ˆํ„ฐ๋ง: Docker, Kubernetes ์ง€์›

๊ฐ€๋Šฅ์„ฑ์€ ๋ฌด๊ถ๋ฌด์ง„ํ•ด! ๐Ÿ’ซ
๐Ÿ’ผ ํ”„๋กœ์ ํŠธ๋ฅผ ๋” ๋ฐœ์ „์‹œํ‚ค๊ณ  ์‹ถ๋‹ค๋ฉด? ์žฌ๋Šฅ๋„ท์—์„œ ์ „๋ฌธ๊ฐ€์˜ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋‚˜ ๋ฉ˜ํ† ๋ง์„ ๋ฐ›์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ!
์‹ค๋ฌด ๊ฒฝํ—˜์ด ํ’๋ถ€ํ•œ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋„ˆ์˜ ์ฝ”๋“œ๋ฅผ ํ•œ ๋‹จ๊ณ„ ์—…๊ทธ๋ ˆ์ด๋“œ์‹œ์ผœ์ค„ ์ˆ˜ ์žˆ์–ด.
ํ˜ผ์ž ๊ณ ๋ฏผํ•˜์ง€ ๋ง๊ณ  ์ „๋ฌธ๊ฐ€์˜ ๋„์›€์„ ๋ฐ›์•„๋ณด๋Š” ๊ฒƒ๋„ ํ˜„๋ช…ํ•œ ์„ ํƒ์ด์ง€! ๐Ÿค

์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง์€ ๋‹จ์ˆœํžˆ ์ˆซ์ž๋ฅผ ๋ณด๋Š” ๊ฒŒ ์•„๋‹ˆ์•ผ.
์‹œ์Šคํ…œ์˜ ๊ฑด๊ฐ• ์ƒํƒœ๋ฅผ ํŒŒ์•…ํ•˜๊ณ , ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•˜๋ฉฐ,
์ตœ์ ์˜ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ํ•„์ˆ˜ ๋„๊ตฌ์ง€.

์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฉ‹์ง„ ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด์„ ๋งŒ๋“ค์–ด๋ด!
๊ทธ๋ฆฌ๊ณ  ๊ณ„์† ๋ฐœ์ „์‹œ์ผœ ๋‚˜๊ฐ€๋ฉด์„œ ๋” ๋งŽ์€ ๊ฒƒ์„ ๋ฐฐ์šฐ๊ฒŒ ๋  ๊ฑฐ์•ผ. ๐Ÿ“š

์ฝ”๋”ฉ์€ ๊ฒฐ๊ตญ ์‹ค์ „์ด์•ผ. ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ณ , ์‹คํŒจํ•˜๊ณ , ๊ฐœ์„ ํ•˜๋ฉด์„œ
์ง„์งœ ์‹ค๋ ฅ์ด ๋Š˜์–ด๋‚˜๋Š” ๊ฑฐ๋‹ˆ๊นŒ ๋ง์ด์•ผ! ๐Ÿ’ช

ํ–‰์šด์„ ๋นŒ์–ด! ํ™”์ดํŒ…! ๐ŸŽ‰

๐Ÿ’ป ๐Ÿ“Š ๐Ÿš€ Happy Monitoring!
๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.