← λ©”μΈμœΌλ‘œ λŒμ•„κ°€κΈ°

πŸ“Š Jupyterμ—μ„œ AI 데이터 λΆ„μ„ν•˜κΈ°

CLI vs Jupyter 비ꡐ - λͺ¨λ‹ˆν„°λ§ μ•ŒλžŒ 데이터 뢄석을 ν†΅ν•œ 체계적 ν•™μŠ΅

πŸ“š ν•™μŠ΅ 단계

πŸ”Ή 사전 μ€€λΉ„

λͺ©ν‘œ: Jupyter ν™˜κ²½κ³Ό 데이터λ₯Ό μ€€λΉ„ν•©λ‹ˆλ‹€

ν™˜κ²½ μ„€μ •

# Jupyter μ„€μΉ˜ 확인
jupyter --version

# ν•„μš”ν•œ 라이브러리 μ„€μΉ˜
pip install pandas matplotlib numpy

데이터 μ€€λΉ„

πŸ“‹ ν•„μš”ν•œ 파일:
  • Alarm_list_*.csv: μ•ŒλžŒ 데이터 (1,129건)
  • Failure_list_*.csv: μž₯μ•  데이터 (75건)

폴더 ꡬ쑰

your_project/
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ Alarm_list_*.csv
β”‚   └── Failure_list_*.csv
└── notebooks/
    └── monitoring_analysis.ipynb

Jupyter μ‹œμž‘

# ν”„λ‘œμ νŠΈ ν΄λ”μ—μ„œ μ‹€ν–‰
cd your_project
jupyter lab

# μƒˆ λ…ΈνŠΈλΆ 생성: Python 3 선택
πŸ’‘ μ‹€ν–‰ ν™”λ©΄ μ˜ˆμ‹œ: μ•„λž˜μ™€ 같은 Jupyter Lab ν™˜κ²½μ—μ„œ μž‘μ—…ν•˜κ²Œ λ©λ‹ˆλ‹€
Jupyter Lab μ‹€ν–‰ ν™”λ©΄

μ‹€μ œ Jupyter Lab ν™˜κ²½μ—μ„œ λͺ¨λ‹ˆν„°λ§ 데이터 뢄석 쀑인 ν™”λ©΄

πŸ”Ή 1-3단계: κΈ°λ³Έ μ„€μ •

핡심: 뢄석 ν™˜κ²½μ„ μ€€λΉ„ν•˜κ³  데이터λ₯Ό λ‘œλ“œν•©λ‹ˆλ‹€

1단계: 라이브러리 μž„ν¬νŠΈ

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
import re
from datetime import datetime

# ν•œκΈ€ 폰트 μ„€μ • (macOS)
plt.rcParams['font.family'] = 'AppleGothic'
plt.rcParams['axes.unicode_minus'] = False

print("πŸ“š 라이브러리 λ‘œλ“œ μ™„λ£Œ!")

2단계: 데이터 λ‘œλ“œ

⚠️ 주의: data_pathλ₯Ό 본인 ν™˜κ²½μ— 맞게 μˆ˜μ •ν•˜μ„Έμš”
# 데이터 경둜 μ„€μ •
data_path = './data'  # 본인 ν™˜κ²½μ— 맞게 μˆ˜μ •

# CSV 파일 찾기
csv_files = [f for f in os.listdir(data_path) if f.endswith('.csv')]
print(f"πŸ“Š 발견된 파일: {csv_files}")

# μ•ŒλžŒ 데이터 λ‘œλ“œ
alarm_files = [f for f in csv_files if f.startswith('Alarm_list')]
df_alarms = pd.read_csv(os.path.join(data_path, alarm_files[0]))

# μž₯μ•  데이터 λ‘œλ“œ
failure_files = [f for f in csv_files if f.startswith('Failure_list')]
df_failures = pd.read_csv(os.path.join(data_path, failure_files[0]))

print(f"βœ… μ•ŒλžŒ: {df_alarms.shape[0]:,}ν–‰")
print(f"βœ… μž₯μ• : {df_failures.shape[0]}ν–‰")

3단계: 데이터 ꡬ쑰 탐색

# μ•ŒλžŒ 데이터 ꡬ쑰
print("πŸ“„ μ•ŒλžŒ 데이터:")
print(f"컬럼: {list(df_alarms.columns)}")
print(df_alarms.head(3))

print("\nπŸ“„ μž₯μ•  데이터:")
print(f"컬럼: {list(df_failures.columns)}")
print(df_failures.head(3))
πŸ’‘ Jupyter의 μž₯점: 각 λ‹¨κ³„λ³„λ‘œ κ²°κ³Όλ₯Ό ν™•μΈν•˜λ©΄μ„œ λ‹€μŒ 뢄석을 κ³„νšν•  수 μžˆμŠ΅λ‹ˆλ‹€

πŸ”Ή 4-6단계: 데이터 뢄석

핡심: μ‹œκ°„ 기반 뢄석을 μœ„ν•œ μ „μ²˜λ¦¬μ™€ ERP μ‹œμŠ€ν…œ 집쀑 뢄석

4단계: λ‚ μ§œ μ „μ²˜λ¦¬

# λ‚ μ§œ λ³€ν™˜
df_alarms['일자'] = pd.to_datetime(df_alarms['일자'])
df_alarms['μ›”'] = df_alarms['일자'].dt.month

df_failures['λ°œμƒ 일자'] = pd.to_datetime(df_failures['λ°œμƒ 일자'])
df_failures['μ›”'] = df_failures['λ°œμƒ 일자'].dt.month

print("βœ… λ‚ μ§œ μ „μ²˜λ¦¬ μ™„λ£Œ!")
print(f"κΈ°κ°„: {df_alarms['일자'].min()} ~ {df_alarms['일자'].max()}")

5단계: ERP μ‹œμŠ€ν…œ 뢄석

# 계정그룹별 ν˜„ν™© 확인
print("🏒 계정그룹별 ν˜„ν™©:")
print(df_alarms['AccountGroup'].value_counts())

# ERP 데이터 μΆ”μΆœ
erp_alarms = df_alarms[df_alarms['AccountGroup'] == 'ERP'].copy()
erp_failures = df_failures[df_failures['AccountGroup'] == 'ERP'].copy()

print(f"\n🎯 ERP μ•ŒλžŒ: {len(erp_alarms):,}건")
print(f"🚨 ERP μž₯μ• : {len(erp_failures)}건")
print(f"πŸ“ˆ μ „ν™˜μœ¨: {(len(erp_failures)/len(erp_alarms)*100):.2f}%")

6단계: 월별 νŒ¨ν„΄ 뢄석

# 월별 집계
monthly_alarms = erp_alarms.groupby('μ›”').agg({
    '개수': 'sum',
    'μœ νš¨μ•ŒλžŒ': lambda x: (x == 'O').sum()
})

monthly_failures = erp_failures.groupby('μ›”').size().to_frame('μž₯μ• μˆ˜')

# κ²°ν•© 뢄석
monthly_combined = monthly_alarms.join(monthly_failures, how='outer').fillna(0)
monthly_combined['μž₯μ• μœ¨%'] = (monthly_combined['μž₯μ• μˆ˜'] / monthly_combined['μœ νš¨μ•ŒλžŒ'] * 100).round(2)

print("πŸ“… 월별 ν˜„ν™©:")
print(monthly_combined)

πŸ”Ή 7-10단계: 심화 뢄석

핡심: μ‹œκ°„λŒ€λ³„ νŒ¨ν„΄, μ•ŒλžŒ μœ ν˜•, AWS λ¦¬μ†ŒμŠ€ λ§€ν•‘ 및 μ‹œκ°ν™”

7단계: μ‹œκ°„λŒ€λ³„ 뢄석

# μ‹œκ°„λŒ€λ³„ 집계
hourly = erp_alarms.groupby('μ‹œκ°„').agg({
    '개수': 'sum',
    'μœ νš¨μ•ŒλžŒ': lambda x: (x == 'O').sum()
})

# μ‹œκ°„λŒ€ ꡬ뢄 ν•¨μˆ˜
def get_period(hour):
    if 6 <= hour < 12: return 'μ˜€μ „'
    elif 12 <= hour < 18: return 'μ˜€ν›„'
    elif 18 <= hour < 24: return '저녁'
    else: return 'μƒˆλ²½'

hourly['μ‹œκ°„λŒ€'] = hourly.index.map(get_period)
time_summary = hourly.groupby('μ‹œκ°„λŒ€')['μœ νš¨μ•ŒλžŒ'].sum()

print("⏰ μ‹œκ°„λŒ€λ³„ μ•ŒλžŒ:")
print(time_summary.sort_values(ascending=False))

print("\nπŸ”₯ κ°€μž₯ λ°”μœ μ‹œκ°„ TOP 5:")
top_hours = hourly.sort_values('μœ νš¨μ•ŒλžŒ', ascending=False).head()
for hour, data in top_hours.iterrows():
    print(f"  {hour:2d}μ‹œ: {int(data['μœ νš¨μ•ŒλžŒ'])}건")

8단계: μ•ŒλžŒ μœ ν˜• 뢄석

# μΉ΄ν…Œκ³ λ¦¬λ³„ 뢄석
category_analysis = erp_alarms.groupby('Category').agg({
    '개수': 'sum',
    'μœ νš¨μ•ŒλžŒ': lambda x: (x == 'O').sum()
}).sort_values('μœ νš¨μ•ŒλžŒ', ascending=False)

print("πŸ” μ•ŒλžŒ μœ ν˜•λ³„ ν˜„ν™©:")
print(category_analysis)

# μ£Όμš” 원인 뢄석
print("\nπŸ“‹ μ£Όμš” λ°œμƒ 원인 TOP 5:")
causes = erp_alarms['λ°œμƒ 원인'].value_counts().head()
for i, (cause, count) in enumerate(causes.items(), 1):
    print(f"{i}. ({count}건) {cause[:50]}...")

9단계: AWS λ¦¬μ†ŒμŠ€ λ§€ν•‘

# AWS μ„œλΉ„μŠ€ νŒ¨ν„΄ μ •μ˜
aws_patterns = {
    'ALB': r'\[ALB\]',
    'EC2': r'\[EC2\]|i-[0-9a-f]+',
    'FSx': r'\[FSx\]|FSx ONTAP',
    'RDS': r'\[RDS\]|database',
    'S3': r'\[S3\]|bucket'
}

# μ„œλΉ„μŠ€λ³„ μ•ŒλžŒ μΆ”μΆœ
service_alarms = {}
for service, pattern in aws_patterns.items():
    matches = erp_alarms[erp_alarms['λͺ¨λ‹ˆν„°λ§ λ©”μ‹œμ§€'].str.contains(pattern, case=False, na=False)]
    if len(matches) > 0:
        service_alarms[service] = {
            'μ•ŒλžŒμˆ˜': len(matches),
            'μœ νš¨μ•ŒλžŒ': (matches['μœ νš¨μ•ŒλžŒ'] == 'O').sum()
        }

if service_alarms:
    service_df = pd.DataFrame(service_alarms).T
    print("πŸ” AWS μ„œλΉ„μŠ€λ³„ μ•ŒλžŒ:")
    print(service_df.sort_values('μœ νš¨μ•ŒλžŒ', ascending=False))
else:
    print("AWS μ„œλΉ„μŠ€ κ΄€λ ¨ μ•ŒλžŒμ΄ λ°œκ²¬λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")

10단계: μ‹œκ°ν™”

# μ’…ν•© μ‹œκ°ν™”
plt.figure(figsize=(15, 10))

# 1. 월별 νŠΈλ Œλ“œ
plt.subplot(2, 3, 1)
monthly_combined[['μœ νš¨μ•ŒλžŒ', 'μž₯μ• μˆ˜']].plot(kind='bar', ax=plt.gca())
plt.title('Monthly Trend')
plt.xticks(rotation=0)
plt.legend()

# 2. μ‹œκ°„λŒ€λ³„ 뢄포
plt.subplot(2, 3, 2)
time_summary.plot(kind='bar', color='orange', ax=plt.gca())
plt.title('Alarms by Time Period')
plt.xticks(rotation=45)

# 3. μΉ΄ν…Œκ³ λ¦¬λ³„ 뢄포
plt.subplot(2, 3, 3)
category_analysis['μœ νš¨μ•ŒλžŒ'].head(5).plot(kind='pie', autopct='%1.1f%%', ax=plt.gca())
plt.title('Top 5 Categories')
plt.ylabel('')

# 4. μ‹œκ°„λ³„ 뢄포
plt.subplot(2, 3, 4)
hourly['μœ νš¨μ•ŒλžŒ'].plot(kind='bar', color='lightblue', ax=plt.gca())
plt.title('Hourly Distribution')
plt.xlabel('Hour')

# 5. AWS μ„œλΉ„μŠ€λ³„ (μžˆλŠ” 경우)
if service_alarms:
    plt.subplot(2, 3, 5)
    service_df['μœ νš¨μ•ŒλžŒ'].plot(kind='bar', color='lightcoral', ax=plt.gca())
    plt.title('AWS Services')
    plt.xticks(rotation=45)

plt.tight_layout()
plt.show()

print("πŸ“Š μ‹œκ°ν™” μ™„λ£Œ!")

🎯 ν•™μŠ΅ μ™„λ£Œ

βœ… Jupyter의 μž₯점을 μ²΄ν—˜ν–ˆμŠ΅λ‹ˆλ‹€:
  • 단계별 μ‹€ν–‰μœΌλ‘œ 쀑간 κ²°κ³Ό 확인
  • μ¦‰μ„μ—μ„œ μΆ”κ°€ 뢄석 κ°€λŠ₯
  • μ‹œκ°ν™” κ²°κ³Όλ₯Ό λ°”λ‘œ 확인
  • 뢄석 과정이 λ¬Έμ„œλ‘œ 보쑴
πŸ“Š CLI vs Jupyter 차이점:
  • CLI: 슀크립트 전체 μ‹€ν–‰ β†’ κ²°κ³Ό 확인
  • Jupyter: 단계별 μ‹€ν–‰ β†’ 탐색적 뢄석
πŸš€ λ‹€μŒ 단계 μ œμ•ˆ:
  • λ‹€λ₯Έ AccountGroup (μ΄λ§ˆνŠΈμ•±, κ³΅μš©κ³„μ •) 뢄석
  • 예츑 λͺ¨λΈλ§μœΌλ‘œ μž₯μ•  예츑
  • Streamlit으둜 μ‹€μ‹œκ°„ λŒ€μ‹œλ³΄λ“œ ꡬ좕
사전 μ€€λΉ„
1-3단계
4-6단계
7-10단계