[실무 강의] Python과 ChatGPT API로 엑셀(CSV) 데이터 5분 만에 자동 분류 & 핵심 요약하기 완벽 마스터 튜토리얼

학습 목표: AI 기반 데이터 자동화의 혁신

2026년 현재, 기업의 데이터 양은 기하급수적으로 늘어났으며 단순 반복적인 엑셀 작업은 더 이상 인적 자원의 낭비가 되어서는 안 됩니다. 본 강의의 목표는 파이썬(Python)과 최신 ChatGPT API(GPT-4o 및 이후 모델)를 결합하여 수천 줄에 달하는 엑셀(CSV) 데이터를 단 5분 만에 자동으로 분류하고 핵심 내용을 요약하는 시스템을 구축하는 것입니다. 이 과정을 통해 여러분은 단순 사무직에서 데이터 자동화 전문가로 거듭날 수 있는 실무 기술을 습득하게 될 것입니다.

본 튜토리얼에서는 실제 고객 상담 로그나 상품 리뷰 데이터를 가정하여, AI가 텍스트의 감정을 분석하고 카테고리를 분류하며 짧은 문장으로 요약하는 전체 프로세스를 다룹니다. 코딩 초보자도 단계별로 따라올 수 있도록 설계되었습니다.

사전 준비 사항

실습을 시작하기 전에 아래의 환경이 구성되어 있는지 확인하십시오. 2026년 표준 개발 환경을 기준으로 작성되었습니다.

1. 운영체제(OS) 및 개발 환경

  • OS: Windows 11 이상, macOS Sequoia 이상 또는 Linux(Ubuntu 24.04 LTS 권장)
  • IDE: Visual Studio Code (VS Code) 최신 버전

2. 파이썬(Python) 버전

  • Python 3.12.x 이상: 최신 라이브러리 호환성을 위해 3.12 이상의 버전을 권장합니다.

3. 필수 라이브러리 설치

터미널(Terminal) 또는 명령 프롬프트(CMD)를 열고 아래 명령어를 입력하여 필요한 라이브러리를 설치하십시오.

pip install openai pandas openpyxl python-dotenv
  • openai: ChatGPT API 서버와 통신하기 위한 공식 라이브러리입니다.
  • pandas: 엑셀 및 CSV 데이터를 효율적으로 처리하기 위한 데이터 분석 도구입니다.
  • openpyxl: 엑셀 파일(.xlsx) 형식을 읽고 쓰기 위한 엔진입니다.
  • python-dotenv: API 키와 같은 보안 정보를 .env 파일에서 관리하기 위해 사용합니다.

1단계: API 키 설정 및 프로젝트 구조 잡기

가장 먼저 OpenAI API 키를 안전하게 관리해야 합니다. 프로젝트 루트 폴더에 .env 파일을 생성하고 다음과 같이 입력합니다.

OPENAI_API_KEY=your_api_key_here

이후 프로젝트의 폴더 구조를 다음과 같이 구성합니다.

  • main.py: 파이썬 메인 실행 코드
  • data.csv: 분석할 원본 데이터 파일
  • .env: 환경 변수 파일

2단계: 데이터 로드 및 전처리 로직 설계

먼저 판다스(Pandas)를 사용하여 CSV 데이터를 불러옵니다. 데이터는 ‘ID’, ‘Content(내용)’ 컬럼을 포함하고 있다고 가정합니다.

import pandas as pd
import os
from dotenv import load_dotenv
from openai import OpenAI

# 환경 변수 로드
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

# 데이터 불러오기
def load_data(file_path):
    try:
        df = pd.read_csv(file_path, encoding='utf-8-sig')
        print(f"성공: {len(df)}개의 행을 로드했습니다.")
        return df
    except Exception as e:
        print(f"오류 발생: {e}")
        return None

3단계: ChatGPT API 연동 및 자동 분류 파이썬 코드 구현

이제 핵심 로직인 AI 분석 함수를 작성합니다. 이 함수는 각 행의 텍스트를 읽어 GPT에게 전달하고, 지정된 형식(JSON 등)으로 결과를 반환받습니다.

def analyze_text(text):
    prompt = f"""
    다음 텍스트를 분석하여 두 가지 항목을 응답하세요.
    1. 카테고리 (불만, 문의, 칭찬, 기타 중 하나)
    2. 요약 (10자 내외의 짧은 요약)

    텍스트: {text}
    형식: 카테고리 | 요약
    """
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "당신은 데이터 분류 전문가입니다."},
            {"role": "user", "content": prompt}
        ],
        temperature=0
    )
    
    result = response.choices[0].message.content.strip()
    return result

# 전체 데이터 적용
def process_automation(df):
    results = []
    for index, row in df.iterrows():
        print(f"{index+1}번째 행 분석 중...")
        analysis = analyze_text(row['Content'])
        results.append(analysis)
    
    # 결과 파싱하여 컬럼 분리
    df[['Category', 'Summary']] = pd.DataFrame([r.split('|') for r in results])
    return df

코드 상세 설명

위 코드에서 temperature=0 설정은 AI의 응답을 일관되게 유지하기 위함입니다. 실무 데이터 처리에서는 창의성보다 정확성과 일관성이 중요하기 때문입니다. 또한 gpt-4o 모델을 사용하여 처리 속도와 비용 효율성을 동시에 잡았습니다.

4단계: 코드 실행 및 결과 데이터 확인

모든 함수가 준비되었다면 이제 메인 로직을 실행하여 최종 결과물을 엑셀 파일로 저장합니다.

if __name__ == "__main__":
    input_file = "data.csv"
    output_file = "analyzed_result.xlsx"
    
    # 1. 데이터 로드
    raw_df = load_data(input_file)
    
    if raw_df is not None:
        # 2. AI 분석 진행
        final_df = process_automation(raw_df)
        
        # 3. 결과 저장
        final_df.to_excel(output_file, index=False)
        print(f"분석 완료! 결과가 {output_file}에 저장되었습니다.")

실행 결과, 기존의 텍스트 데이터 옆에 AI가 자동으로 판단한 ‘카테고리’와 ‘핵심 요약’ 컬럼이 추가된 것을 확인할 수 있습니다. 수작업으로 진행했을 때 몇 시간이 걸릴 분량을 단 몇 초 만에 정확하게 처리해냅니다.

마치며: 실무 적용 팁

본 강의에서 다룬 기술은 단순히 분류와 요약에 그치지 않습니다. API 호출 시 프롬프트를 수정하여 감성 점수(Sentiment Score)를 매기거나, 특정 키워드를 추출하는 등 무궁무진하게 활용할 수 있습니다. 주의할 점은 대량의 데이터를 처리할 경우 API 비용이 발생하므로, 전체 데이터를 처리하기 전에 반드시 상위 5~10개의 샘플 데이터로 테스트를 진행하여 프롬프트의 정확도를 검증하시기 바랍니다.

이제 여러분은 파이썬과 AI를 활용해 업무 효율을 극대화할 수 있는 강력한 무기를 갖게 되었습니다. 지금 바로 실무 데이터에 적용해 보십시오!

댓글 남기기


Warning: getimagesize(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/media.cls.php on line 1158

Warning: getimagesize(https://img1.daumcdn.net/thumb/R1280x0.fwebp/?fname=http://t1.daumcdn.net/brunch/service/user/i41K/image/c_jcDJuwr_NMLg-R3Vdw0Z6YLDk): Failed to open stream: no suitable wrapper could be found in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/media.cls.php on line 1158

Warning: getimagesize(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/media.cls.php on line 1158

Warning: getimagesize(https://d2v80xjmx68n4w.cloudfront.net/members/portfolios/FCy8Z1734331233.jpg): Failed to open stream: no suitable wrapper could be found in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/media.cls.php on line 1158

Warning: getimagesize(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/media.cls.php on line 1158

Warning: getimagesize(https://cdn.maily.so/zqth3sqf8n9svcrr4zlwyq5nvbvy): Failed to open stream: no suitable wrapper could be found in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/media.cls.php on line 1158

Warning: file_put_contents(): Only 4096 of 4369 bytes written, possibly out of free disk space in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/file.cls.php on line 177

Fatal error: Uncaught ErrorException: md5_file(/hosting/apdldk/html/wp-content/litespeed/css/fa9f8a78db5a82cc83b59a833541084d.css.tmp): Failed to open stream: No such file or directory in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimizer.cls.php:148 Stack trace: #0 [internal function]: litespeed_exception_handler() #1 /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimizer.cls.php(148): md5_file() #2 /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimize.cls.php(845): LiteSpeed\Optimizer->serve() #3 /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimize.cls.php(338): LiteSpeed\Optimize->_build_hash_url() #4 /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimize.cls.php(265): LiteSpeed\Optimize->_optimize() #5 /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimize.cls.php(226): LiteSpeed\Optimize->_finalize() #6 /hosting/apdldk/html/wp-includes/class-wp-hook.php(341): LiteSpeed\Optimize->finalize() #7 /hosting/apdldk/html/wp-includes/plugin.php(205): WP_Hook->apply_filters() #8 /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/core.cls.php(464): apply_filters() #9 [internal function]: LiteSpeed\Core->send_headers_force() #10 /hosting/apdldk/html/wp-includes/functions.php(5481): ob_end_flush() #11 /hosting/apdldk/html/wp-includes/class-wp-hook.php(341): wp_ob_end_flush_all() #12 /hosting/apdldk/html/wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters() #13 /hosting/apdldk/html/wp-includes/plugin.php(522): WP_Hook->do_action() #14 /hosting/apdldk/html/wp-includes/load.php(1308): do_action() #15 [internal function]: shutdown_action_hook() #16 {main} thrown in /hosting/apdldk/html/wp-content/plugins/litespeed-cache/src/optimizer.cls.php on line 148