Rookies 15일차: Python - LLM, Langchain, RAG 3
학습 내용 요약 (2025-11-12)
오늘은 LLM(대형 언어 모델)과 파이썬 생태계를 활용한 보안 로그 분석 대시보드 구축 과정을 집중적으로 학습하였습니다. 특히 LLM의 자동화 능력, 데이터 전처리 및 정규표현식 활용, 그리고 지도 시각화까지 실제 실무에서 활용할 수 있는 다양한 기술을 단계별로 익혔습니다. 각 개념이 어떻게 유기적으로 연결되는지, 그리고 실무에서 발생할 수 있는 문제와 그 해결 방법까지 구체적으로 다루었습니다.
1. LLM 기반 보안 로그 분석의 필요성과 준비
1.1. 보안 로그 분석에서 LLM이 중요한 이유
현대의 보안 환경에서는 방대한 로그 데이터를 신속하게 분석하는 능력이 필수적입니다. 사람이 직접 모든 로그를 검토하는 것은 비효율적이므로, LLM을 활용하면 로그 데이터의 요약, 분류, 위험도 평가를 자동화할 수 있습니다. 이를 통해 보안 담당자는 빠르게 위협을 식별하고 대응할 수 있습니다.
중요: LLM을 통한 자동화는 반복적이고 대량의 데이터 처리에 강점을 보입니다. 그러나, LLM의 응답 형식이 항상 일관적이지 않을 수 있으므로, 후처리 과정이 반드시 필요합니다.
1.2. 프로젝트 환경 및 주요 라이브러리
보안 로그 분석 대시보드 구축을 위해 다음과 같은 파이썬 라이브러리를 사용합니다.
- os, dotenv: 환경 변수 및 API 키 관리
- openai: OpenAI LLM API 호출
- streamlit: 웹 대시보드 구현
- pandas, numpy: 데이터 처리 및 분석
- plotly.express: 데이터 시각화(특히 지도 시각화)
환경 변수 관리 코드 예시:
from dotenv import load_dotenv # .env 파일에서 환경 변수 불러오기
import os # 운영체제 관련 기능 제공
load_dotenv() # .env 파일을 읽어서 환경 변수로 등록
api_key = os.getenv("OPENAI_API_KEY") # 환경 변수에서 API 키 가져오기
- 위 코드는 API 키와 같은 민감 정보를 코드에 직접 노출하지 않고 안전하게 관리하는 방법입니다.
주의: API 키를 코드에 직접 입력하지 않도록 하십시오. 깃허브 등의 저장소에 노출되면 보안 사고로 이어질 수 있습니다.
2. LLM 프롬프트 설계 및 활용
2.1. LLM 프롬프트 엔지니어링의 핵심
LLM에게 원하는 결과를 얻으려면, 명확하고 구체적인 프롬프트 설계가 필수입니다. 특히, 보안 로그 분석에서는 출력 형식(json)과 예시를 반드시 포함해야 하며, 불필요한 텍스트가 포함되지 않도록 강하게 지시해야 합니다.
프롬프트 설계 예시 코드:
system_content = """
너는 아주 멋진 사이버 보안 전문가야.
내가 업로드한 로그데이터를 기반으로 공격 유형, 국가, 위험도 등을 분석해줘.
출력 예시)
- ip : 공격 IP
- country : 공격 발생 국가명(영문)
- status : 'Blocked' or 'Allowed'
- risk_level : 1~10 사이의 정수
- latitude : 해당 국가의 대략적인 위도(중심값)
- longitude : 해당 국가의 대략적인 경도(중심값)
json 형식 이외의 다른 텍스트는 절대 포함하지마(**매우 중요**).
예시)
[
{"ip" : "1.2.3.4", "country" : "South Korea", "attack_type" : "SQL Injection", "status": "Blocked", "risk_level" : 8, "latitude": 37.5665, "longitude": 126.9780},
{"ip" : "5.6.7.8", "country" : "China", "attack_type" : "DDoS", "status": "Allowed", "risk_level" : 5, "latitude": 39.9042, "longitude": 116.4074}
]
"""
- 출력 형식과 예시를 명확히 제시하면 LLM이 일관된 결과를 반환할 확률이 높아집니다.
중요: LLM의 응답이 항상 json 형식이 되도록 프롬프트에서 강하게 요구하십시오. 그렇지 않으면 파싱 오류가 발생할 수 있습니다.
3. LLM 호출 및 데이터 전처리
3.1. LLM 호출 함수 설계
LLM에게 로그 데이터를 전달하고 분석 결과를 받아오는 함수는 다음과 같이 구현합니다.
제목: LLM 호출 함수(ask_llm) 예시
from openai import OpenAI # OpenAI API 사용
def ask_llm(frm):
client = OpenAI(api_key=api_key) # OpenAI 클라이언트 생성
response = client.chat.completions.create(
model="gpt-4o-mini", # 사용할 모델명
messages=[
{"role": "system", "content": system_content}, # 시스템 프롬프트
{"role": "user", "content": f'로그분석\n{frm.head(20).to_dict()}'}
],
max_tokens=1500, # 최대 응답 토큰 수
temperature=0.8, # 창의성(무작위성) 조절(0~1)
)
return response # LLM 응답 객체 반환
max_tokens는 응답의 최대 길이를,temperature는 창의성을 조절합니다.
3.2. LLM 응답 파싱과 정규표현식 활용
LLM의 응답에는 종종 마크다운 코드 블록(```)이나 불필요한 텍스트가 포함될 수 있습니다. 이때 정규표현식을 사용하여 필요한 부분만 추출합니다.
제목: 정규표현식으로 마크다운 제거
import re # 정규표현식 모듈 임포트
csv_text = """
```json
[
{"ip": "1.2.3.4", "country": "South Korea", "risk_level": 8}
]
””” # LLM 응답 예시
코드 블록 시작 부분 제거
csv_text = re.sub(r”^[a-zA-Z]*\n?", "", csv_text) #json 또는 ``` 제거
코드 블록 끝 부분 제거
csv_text = re.sub(r”$", "", csv_text).strip() # 닫는 제거
print(csv_text)
출력:
[
{“ip”: “1.2.3.4”, “country”: “South Korea”, “risk_level”: 8}
]
> **중요:** LLM의 응답 형식이 일관되지 않을 때, 정규표현식은 불필요한 부분을 신속하게 제거하는 데 매우 유용합니다.
---
## 4. 데이터프레임 변환 및 필터링
### 4.1. LLM 응답을 데이터프레임으로 변환
LLM이 반환한 JSON 데이터를 파이썬의 딕셔너리로 파싱한 후, 판다스 데이터프레임으로 변환하여 분석에 활용합니다.
#### 제목: JSON 문자열 → 데이터프레임 변환
```python
import json # JSON 파싱 모듈
import pandas as pd # 데이터프레임 처리
json_str = '[{"ip": "1.2.3.4", "country": "South Korea", "risk_level": 8}]' # 예시 JSON 문자열
data = json.loads(json_str) # JSON 문자열을 딕셔너리로 변환
df = pd.DataFrame(data) # 데이터프레임으로 변환
print(df)
# 출력:
# ip country risk_level
# 0 1.2.3.4 South Korea 8
4.2. 데이터 필터링 실습
보안 분석에서는 위험도가 높은 IP만 추출하는 것이 중요합니다. 판다스의 조건 필터링을 활용하여 손쉽게 구현할 수 있습니다.
제목: 위험도 기준 데이터 필터링
# 데이터프레임에서 위험도(risk_level)가 7 이상인 행만 추출
high_risk_df = df[df['risk_level'] >= 7] # 조건에 맞는 데이터만 추출
print(high_risk_df)
# 출력:
# ip country risk_level
# 0 1.2.3.4 South Korea 8
팁: 조건에 맞는 데이터가 없으면 결과가 비어 있을 수 있으므로, 필터 조건과 데이터 자체를 반드시 점검해야 합니다.
5. Streamlit 대시보드 및 지도 시각화
5.1. Streamlit 대시보드 구조
Streamlit을 활용하면 복잡한 웹 개발 없이도 데이터 분석 대시보드를 쉽게 만들 수 있습니다. 주요 흐름은 다음과 같습니다.
- 페이지 설정 및 제목 출력
- CSV 파일 업로드
- 로그 데이터 표시
- LLM 분석 버튼 및 결과 처리
- 분석 결과 시각화(공격 유형, 국가, 위험도)
- 고위험 IP 필터링 및 표시
- 지도 시각화(Plotly)
제목: Streamlit 대시보드 주요 코드 흐름
import streamlit as st # 웹 대시보드 라이브러리
import pandas as pd # 데이터 처리
import plotly.express as px # 시각화
def view():
st.set_page_config(page_title='보안로그분석 AI', layout='wide') # 페이지 설정
st.title('LLM 기반 관리자 대시보드') # 대시보드 제목
file = st.file_uploader('보안 로그 CSV 파일 업로드', type=['csv']) # 파일 업로드 위젯
if file:
frm = pd.read_csv(file) # 업로드된 CSV 파일 읽기
st.dataframe(frm.head()) # 데이터프레임 상위 5개 행 표시
if st.button('로그 분석 시작'):
with st.spinner('로그 데이터를 분석하고 있습니다...'):
response = ask_llm(frm) # LLM 분석 함수 호출
# LLM 응답 파싱 및 데이터프레임 변환
import json
data = json.loads(response.choices[0].message.content.strip())
resultFrm = pd.DataFrame(data)
st.dataframe(resultFrm) # 분석 결과 표시
# 지도 시각화
fig = px.scatter_geo(
resultFrm,
lat='latitude',
lon='longitude',
hover_name='ip',
hover_data=['country', 'attack_type', 'risk_level'],
color='risk_level',
color_continuous_scale='Reds',
size='risk_level',
size_max=20,
projection='natural earth',
title='공격 IP 국가별 분포 지도'
)
st.plotly_chart(fig, use_container_width=True)
5.2. Plotly를 활용한 지도 시각화
Plotly의 scatter_geo 함수를 사용하면, 위도/경도 정보를 바탕으로 공격 IP의 분포를 세계 지도에 시각화할 수 있습니다.
제목: Plotly 지도 시각화 예시
import plotly.express as px # Plotly 임포트
import pandas as pd # 데이터프레임 처리
# 예시 데이터프레임 생성
data = {
'latitude': [37.5665, 35.1796], # 위도 정보
'longitude': [126.9780, 129.0756], # 경도 정보
'risk_level': [8, 5], # 위험도 점수
'ip': ['1.2.3.4', '5.6.7.8'],
'attack_type': ['DDoS', 'Malware']
}
df = pd.DataFrame(data)
# 지도 시각화
fig = px.scatter_geo(
df,
lat='latitude', # 위도 컬럼
lon='longitude', # 경도 컬럼
color='risk_level', # 위험도에 따라 색상
size='risk_level', # 위험도에 따라 점 크기
hover_name='ip', # 마우스 오버 시 IP 표시
hover_data=['attack_type'], # 공격 유형 표시
projection='natural earth', # 지도 투영 방식
title='공격 IP 지도 시각화'
)
fig.show() # 차트 표시
- 지도 시각화에서 점이 표시되지 않거나 색상이 적용되지 않는 경우, 데이터의 위도/경도 값과 컬럼 타입(숫자형인지)도 반드시 확인해야 합니다.
6. 정규표현식(Regex)과 데이터 전처리
6.1. 정규표현식의 기본 개념과 활용
정규표현식은 문자열에서 특정 패턴을 찾거나, 추출하거나, 치환하는 데 사용하는 강력한 도구입니다. 로그 데이터, LLM의 자유로운 출력 결과 등에서 필요한 정보만 추출할 때 매우 유용합니다.
제목: 이메일, 전화번호, 숫자 추출 예시
import re # 정규표현식 모듈
txt = '문의 이메일은 jslim9413@naver.com 입니다. 연락처는 010-1234-5678입니다.'
# 이메일 추출
email_pattern = r'\w+@\w+\.\w+'
emails = re.findall(email_pattern, txt)
print(emails) # 출력: ['jslim9413@naver.com']
# 전화번호 추출
phone_pattern = r'\d{3}-\d{4}-\d{4}'
phones = re.findall(phone_pattern, txt)
print(phones) # 출력: ['010-1234-5678']
# 숫자만 추출
numbers = re.findall(r'\d+', txt)
print(numbers) # 출력: ['010', '1234', '5678']
팁: 정규표현식 패턴이 복잡해질수록 가독성이 떨어질 수 있으므로, 변수명과 주석을 활용하여 관리하는 것이 좋습니다.
6.2. LLM 결과의 전처리와 정규표현식 결합
LLM의 출력이 항상 예측 가능한 형식이 아니므로, 정규표현식과 예외 처리를 통해 필요한 정보만 추출하는 후처리 로직이 필수적입니다.
제목: LLM 응답에서 JSON 부분만 추출
import re # 정규표현식 모듈
import json # JSON 파싱 모듈
llm_response = '''
여러 안내문구
{
"name": "홍길동",
"email": "hong@example.com",
"phone": "010-1234-5678"
}
추가 안내문구
'''
# 중괄호로 감싸진 JSON 부분만 추출
pattern = r'(\{[\s\S]*?\})'
match = re.search(pattern, llm_response)
if match:
json_str = match.group(1) # JSON 문자열 추출
data = json.loads(json_str) # 딕셔너리로 변환
print(data)
# 출력: {'name': '홍길동', 'email': 'hong@example.com', 'phone': '010-1234-5678'}
7. 데이터 전처리 실무 팁 및 주의사항
- API 키 노출 방지:
.env파일을 반드시.gitignore에 추가하여 깃허브 등에 노출되지 않도록 하십시오. - LLM 응답 파싱 오류: 프롬프트에서 출력 형식을 명확히 요구하지 않으면, LLM이 설명 문구를 추가할 수 있습니다. 이 경우 JSON 파싱이 실패할 수 있습니다.
- 파일 인코딩 문제: CSV 파일을 읽을 때 인코딩 오류가 발생하면,
encoding='utf-8'또는encoding='cp949'등으로 지정하십시오. - 데이터프레임 변환: LLM 응답을 바로 데이터프레임으로 변환하기 전에 반드시 JSON 파싱이 정상적으로 이루어졌는지 확인해야 합니다.
- 지도 시각화: 위도/경도 정보가 정확하지 않으면 지도 시각화가 왜곡될 수 있으므로, 국가 중심값을 사용하는 것이 대략적인 분포 파악에 유용합니다.
전체 흐름 요약
오늘 학습한 내용은 LLM을 활용한 보안 로그 분석 자동화의 전체 흐름을 다룹니다. 환경 설정과 프롬프트 설계, LLM 호출 및 응답 전처리, 데이터프레임 변환, 조건 필터링, 그리고 지도 시각화까지 실무에서 바로 활용할 수 있는 기술을 단계별로 익혔습니다. 특히 정규표현식을 통한 데이터 전처리와 Streamlit 대시보드 구현 방법을 중점적으로 다루었습니다.
주요 개념 요약표
| 개념 | 설명 | 예시/비고 |
|---|---|---|
| LLM | 대형 언어 모델로, 자연어 처리 및 데이터 분석 자동화에 활용 | OpenAI GPT-4, GPT-3.5 등 |
| 프롬프트 엔지니어링 | LLM에게 원하는 결과를 얻기 위해 지시문을 명확히 설계하는 기법 | 출력 예시, 형식, 필수 항목 명시 |
| 환경 변수 관리 | 민감 정보(API 키 등)를 안전하게 관리하는 방법 | dotenv, os 모듈 활용 |
| 판다스 필터링 | 조건에 맞는 데이터만 추출하는 데이터프레임 연산 | df[df[‘risk_level’] >= 7] |
| 정규표현식(Regex) | 문자열에서 패턴을 추출·치환하는 도구 | 이메일, 전화번호, JSON 추출 등 |
| Streamlit | 파이썬 기반 웹 대시보드 프레임워크 | st.file_uploader, st.dataframe, st.plotly_chart |
| Plotly | 데이터 시각화 라이브러리(특히 지도 시각화에 강점) | px.scatter_geo |
| JSON 파싱 | 문자열 형태의 JSON 데이터를 파이썬 객체로 변환 | json.loads() |
| 데이터 전처리 | 분석 전 데이터 정제, 형식 통일, 결측치 처리 등 | 정규표현식, 데이터 타입 변환 등 |
| 지도 시각화 | 위도/경도 정보를 활용해 데이터의 지리적 분포를 시각화 | Plotly, pydeck 활용 |
공부 후기
오늘은 LLM과 파이썬 생태계를 활용한 보안 로그 분석 자동화의 전체 흐름을 실무 관점에서 체계적으로 학습하였다. 특히 LLM의 프롬프트 설계와 응답 전처리, 그리고 정규표현식의 실전 활용법을 구체적으로 익힐 수 있었다. Streamlit과 Plotly를 활용한 대시보드 및 지도 시각화 구현 과정도 매우 실용적이었다. 앞으로 실제 데이터로 다양한 실습을 반복하며, 데이터 전처리와 시각화 역량을 더욱 강화하고 싶다.
댓글 남기기