1. 문제점
pandas
와 requests
를 사용한 데이터 수집 및 처리 스크립트에서 18분 이상 실행이 멈추는 등 심각한 성능 저하 현상이 발생했다. 분석 결과, 원인은 ①네트워크 요청의 timeout
부재, ②반복문 내에서의 비효율적인 DataFrame 직접 수정으로 파악되었다.
2. 기존 코드와 문제점 분석
2.1. 원본 코드 (Before)
# 원본 문제 코드
# ... (설정 부분 생략) ...
for idx, row in result_df.iterrows():
urls = row["사고 관련 url모음"]
field_values = { "수위": [], "수온": [], "EC": [] }
for url in urls:
success = False
for attempt in range(3):
try:
# 문제 1: timeout이 없음
res = requests.get(url)
# ... (데이터 처리) ...
success = True
break
except Exception as e:
# ... (에러 처리) ...
# ... (실패 및 길이 보정 처리) ...
# 문제 2: 루프 내에서 DataFrame을 직접, 반복적으로 수정
for label in field_values:
for i, month in enumerate(month_names):
result_df.at[idx, f"{month} {label}"] = field_values[label][i]
# ... (통계 계산 및 저장) ...
# ... (결과 저장 및 출력) ...
2.2. 문제점 상세 분석
① 네트워크 요청의 timeout
부재
requests.get()
함수는 기본적으로 서버의 응답을 무기한 대기한다. 요청 URL 중 하나라도 응답 불가능한 상태일 경우, 해당 요청에서 전체 프로세스가 멈추는 '행(Hang)' 현상이 발생한다.② 반복문 내 DataFrame 직접 수정의 비효율성
.iterrows()
루프 내에서 .at[]
접근자를 사용하여 DataFrame의 셀 값을 하나씩 수정하고 있다.3. 최적화된 코드와 개선 사항
3.1. 수정 코드 (After)
# 최적화된 코드
# ... (설정 부분 생략) ...
all_rows_data = [] # 임시 데이터 저장용 리스트
total_rows = len(result_df)
for idx, row in result_df.iterrows():
print(f"--- 처리 중: {idx+1} / {total_rows} 번째 행 ---") # 개선점 3
# ... (데이터 처리) ...
for url in urls:
try:
# 개선점 1: timeout=10 설정
res = requests.get(url, timeout=10)
# ... (데이터 처리) ...
# ... (예외 처리) ...
# 개선점 2: 처리 결과를 딕셔너리로 취합
new_data_row = {}
for label in field_values:
# ... (길이 보정 및 월별/통계 데이터 new_data_row에 저장) ...
all_rows_data.append(new_data_row)
# 루프 종료 후, 리스트를 DataFrame으로 일괄 변환
new_cols_df = pd.DataFrame(all_rows_data, index=result_df.index)
# 기존 DataFrame과 일괄 병합
result_df = pd.concat([result_df, new_cols_df], axis=1)
# ... (결과 저장 및 출력) ...
3.2. 주요 개선 사항
① timeout
파라미터 추가
requests.get(url, timeout=10)
② "선수집, 후처리" 패턴 적용
all_rows_data
)에 딕셔너리 형태로 수집(Collect)만 한다. 루프가 모두 종료된 후, 이 리스트를 pd.DataFrame()
으로 한 번에 변환하고 pd.concat
으로 기존 DataFrame에 병합(Process)한다.③ 진행 상황 로깅 추가
print()
문을 통해 전체 진행률을 표시했다.4. 결론
외부 네트워크와 통신하는 I/O 작업에는 반드시 timeout
을 명시하여 예기치 않은 대기 상태를 방지해야 한다.
Pandas DataFrame의 반복적인 수정 작업은 성능에 큰 부담을 주므로, 처리할 데이터를 메모리(리스트 등)에 모두 준비한 뒤 일괄적으로 생성 및 결합하는 방식이 훨씬 효율적이다.