AI/생성형AI

[Web기반업무자동화](2)GPT API를 이용한 업무 자동화(MacOS/Linux)

CodeMasterSong 2025. 5. 17. 21:42
반응형

macOS/리눅스 사용자를 위한 GPT와 Flask로 AI 키워드 봇 개발

이번 글에서는 macOS 또는 리눅스 환경에서 OpenAI의 GPT API와 Python 웹 프레임워크 Flask를 사용하여, 여러분이 궁금해하는 키워드에 대해 AI가 똑똑하게 설명해주는 웹 애플리케이션을 만드는 방법을 소개합니다. 터미널 사용이 익숙하지 않아도 괜찮아요. 한 단계 한 단계 따라오시면, 어느새 멋진 AI 봇이 여러분 손에서 탄생할 거랍니다. 전반적인 과정은 이전 글인 Windows 기반의 내용과 같으므로 얻어지는 결과는 같으므로 이미지는 생략하고 진행과정의 설명으로 대신합니다.

 

오늘의 개발 목표:

  • 웹 페이지에서 사용자가 특정 키워드를 입력합니다.
  • Flask 백엔드가 이 키워드를 GPT API로 전송합니다.
  • GPT 모델이 해당 키워드에 대한 설명을 생성합니다.
  • 생성된 설명을 웹 페이지에 결과로 표시합니다.

프로젝트 명칭: MyFirstWebWithLLM

필요한 개발 도구 (환경):

  • macOS 또는 Linux 운영체제
  • Python (3.7 이상 권장, 대부분의 macOS/Linux에는 기본 설치되어 있거나 쉽게 설치 가능)
  • Flask (Python 웹 프레임워크)
  • OpenAI Python 라이브러리
  • 가상 환경 (venv) – 프로젝트별 독립적인 개발 환경 구성

[1단계]: 프로젝트 디렉토리 생성 및 가상 환경 설정

먼저, 우리 프로젝트를 위한 전용 공간(디렉토리)을 만들고, 다른 Python 프로젝트와 충돌하지 않도록 격리된 가상 환경을 설정합니다.

  1. 프로젝트 디렉토리 생성 및 이동: 터미널(Terminal)을 실행하세요. (macOS: Launchpad에서 'Terminal' 검색, Linux: 배포판에 따라 다름, 보통 Ctrl+Alt+T) 다음 명령어를 사용하여 원하는 위치에 MyFirstWebWithLLM이라는 디렉토리를 만들고, 그 안으로 이동합니다. (예: 홈 디렉토리 아래 Projects 폴더)(~/Projects는 예시이며, 여러분이 원하는 경로로 변경해도 됩니다.)
  2. mkdir -p ~/Projects/MyFirstWebWithLLM  # -p 옵션은 상위 디렉토리도 필요하면 생성
    cd ~/Projects/MyFirstWebWithLLM
    
  3. 가상 환경 생성: 프로젝트 디렉토리 안에서 다음 명령어를 실행하여 myenv라는 이름의 가상 환경을 만듭니다. macOS나 최신 Linux 배포판에서는 python3를 사용하는 것이 일반적입니다.(만약 python3 명령어가 없다면 python -m venv myenv를 시도해 보세요.) 실행 후, ls 명령어로 확인해보면 myenv라는 하위 디렉토리가 생성된 것을 볼 수 있습니다.
  4. python3 -m venv myenv
    
  5. 가상 환경 활성화: 생성한 가상 환경을 사용하기 위해 다음 명령어로 활성화합니다.명령어를 실행하면, 터미널 프롬프트의 맨 앞에 (myenv)라는 표시가 나타납니다. 이는 현재 가상 환경 내에서 작업 중임을 의미합니다.
  6. source myenv/bin/activate
    

[2단계]: 필수 라이브러리 설치

우리 AI 봇을 구동하기 위해 웹 개발 도구인 Flask와 GPT API와 통신할 openai 라이브러리를 설치해야 합니다.

  1. requirements.txt 파일 생성: 프로젝트 디렉토리(MyFirstWebWithLLM) 내에 requirements.txt라는 파일을 만들고, 필요한 라이브러리 목록을 작성합니다. 터미널에서 텍스트 편집기(예: nano, vim, code)를 사용하거나 GUI 편집기를 사용해도 됩니다. 예시 (nano 사용):편집기가 열리면 다음 두 줄을 입력하고 저장 후 닫습니다. (nano의 경우: Ctrl+O 저장, Enter, Ctrl+X 종료)
    Flask
    openai
    
  2. nano requirements.txt
    
  3. 라이브러리 설치: 가상 환경이 활성화된 터미널((myenv) 표시가 있는 상태)에서 다음 명령어를 실행하여 requirements.txt 파일에 명시된 라이브러리들을 설치합니다.(만약 pip 대신 pip3를 주로 사용한다면 pip3 install -r requirements.txt를 사용하세요. 가상 환경 내에서는 보통 pip이 해당 환경의 Python 버전에 맞춰져 있습니다.)
  4. pip install -r requirements.txt
    

[3단계]: OpenAI API 키 발급 및 안전한 환경 변수 설정

GPT 모델을 사용하려면 OpenAI에서 제공하는 API 키가 필요합니다. 이 키는 매우 중요한 정보이므로 안전하게 관리해야 합니다.

  1. OpenAI API 키 발급:
    • OpenAI API 키 페이지로 이동하여 OpenAI 계정으로 로그인하거나 새로 만듭니다.
    • API 키 관리 섹션에서 "Create new secret key" 버튼을 클릭하여 새 API 키를 생성합니다.
    • 매우 중요: 생성된 API 키는 해당 창에서만 전체 내용을 볼 수 있습니다. 즉시 안전한 곳(예: 암호 관리 프로그램)에 복사하여 보관하세요. 창을 닫거나 벗어나면 다시는 전체 키를 볼 수 없습니다.
  2. API 키 환경 변수 설정 (보안 강화): API 키를 코드에 직접 작성하는 것은 보안상 매우 위험합니다. 대신, 운영체제의 환경 변수로 설정하여 코드에서는 이 변수를 참조하도록 합니다.
    • 현재 터미널 세션에 임시로 설정하기: (터미널을 닫으면 설정이 사라집니다) 터미널에 다음 명령어를 입력하세요. "여러분의_API_키_여기에_붙여넣으세요" 부분을 실제 발급받은 키로 대체합니다.
      export OPENAI_API_KEY="여러분의_API_키_여기에_붙여넣으세요"
      
    • 영구적으로 설정하기 (권장): 매번 터미널을 열 때마다 API 키를 자동으로 로드하려면, 쉘(Shell)의 설정 파일에 위 export 명령어를 추가해야 합니다.
      1. 사용하는 쉘의 종류를 확인합니다 (보통 Bash 또는 Zsh). 터미널에서 echo $SHELL 명령어로 확인할 수 있습니다.
      2. 해당 쉘의 설정 파일을 엽니다:
        • Bash 쉘: nano ~/.bashrc 또는 nano ~/.bash_profile
        • Zsh 쉘 (macOS 최신 버전 기본값): nano ~/.zshrc
      3. 파일 맨 아래에 다음 줄을 추가합니다 (API 키는 실제 키로 변경). export OPENAI_API_KEY="여러분의_API_키_여기에_붙여넣으세요"
      4. 파일을 저장하고 편집기를 닫습니다.
      5. 변경사항을 즉시 적용하려면 다음 명령어를 실행하거나 (해당 쉘 설정 파일명으로 변경), 터미널을 새로 여세요.
        source ~/.zshrc  # 또는 source ~/.bashrc 등
        

[4단계]: 웹 페이지 구조 설계 (HTML 템플릿)

사용자가 키워드를 입력하고 AI의 답변을 확인할 수 있는 웹 페이지의 기본 구조(HTML)를 만듭니다.

  1. templates 디렉토리 생성: MyFirstWebWithLLM 프로젝트 디렉토리 내에 templates라는 이름의 새 디렉토리를 만듭니다. Flask는 이 디렉토리에서 HTML 템플릿 파일을 찾습니다.
  2. mkdir templates
    
  3. 키워드 입력 페이지 (index.html) 생성: MyFirstWebWithLLM/templates/ 디렉토리 안에 index.html 파일을 생성하고 다음 코드를 작성하여 저장합니다.
    <!doctype html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>AI 키워드 검색봇 (macOS/Linux)</title>
        <style>
            body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; margin: 20px; background-color: #f8f9fa; color: #212529; display: flex; flex-direction: column; align-items: center; min-height: 90vh; text-align: center;}
            h1 { color: #007bff; margin-bottom: 30px; }
            form { background-color: #ffffff; padding: 30px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); width: 100%; max-width: 500px; }
            label { display: block; margin-bottom: 10px; font-weight: 500; font-size: 1.1em; color: #495057; }
            input[type="text"] { width: calc(100% - 24px); padding: 12px; margin-bottom: 25px; border: 1px solid #ced4da; border-radius: 4px; font-size: 1em; box-sizing: border-box; }
            button { background-color: #28a745; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 1.1em; width: 100%; transition: background-color 0.2s ease-in-out; }
            button:hover { background-color: #218838; }
        </style>
    </head>
    <body>
        <h1>AI에게 질문하기</h1>
        <form action="/search" method="post">
            <label for="keyword">궁금한 키워드를 입력하세요:</label>
            <input type="text" id="keyword" name="keyword" required placeholder="예: 인공지능이란?">
            <button type="submit">AI에게 질문하기!</button>
        </form>
    </body>
    </html>
  4. 결과 표시 페이지 (result.html) 생성: MyFirstWebWithLLM/templates/ 디렉토리 안에 result.html 파일을 생성하고 다음 코드를 작성하여 저장합니다.
    <!doctype html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>AI 답변: {{ keyword }}</title>
        <style>
            body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; margin: 20px; background-color: #e9ecef; color: #343a40; }
            .container { background-color: #ffffff; padding: 25px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); margin-bottom: 25px; max-width: 800px; margin-left: auto; margin-right: auto;}
            h1 { color: #007bff; border-bottom: 2px solid #dee2e6; padding-bottom: 15px; font-size: 1.8em; }
            .keyword-highlight { color: #dc3545; font-weight: 500; }
            .content-box { white-space: pre-wrap; /* AI 답변의 줄바꿈과 공백을 유지 */ line-height: 1.7; background-color: #f8f9fa; padding: 20px; border: 1px solid #dee2e6; border-radius: 4px; margin-top: 20px; font-size: 1.05em;}
            .back-link-container { text-align: center; margin-top: 30px; }
            .back-link { display: inline-block; background-color: #17a2b8; color: white; text-decoration: none; font-weight: 500; padding: 10px 20px; border-radius: 4px; transition: background-color 0.2s ease-in-out; }
            .back-link:hover { background-color: #138496; }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>AI의 답변 <br>검색어: <span class="keyword-highlight">{{ keyword }}</span></h1>
            <div class="content-box">
                {{ content }}
            </div>
        </div>
        <div class="back-link-container">
            <a href="/" class="back-link">다른 키워드로 다시 검색</a>
        </div>
    </body>
    </html>
  5. {{ keyword }}와 {{ content }} 부분은 나중에 Python(Flask) 코드에서 동적으로 채워질 값들입니다.

[5단계]: GPT 연동 로직 구현 (search.py)

사용자가 입력한 키워드를 받아 OpenAI의 GPT 모델에 전달하고, 그 응답을 받아오는 Python 스크립트를 작성합니다.

MyFirstWebWithLLM 프로젝트 디렉토리 내에 search.py 파일을 생성하고 다음 코드를 작성하여 저장합니다.

import os
from openai import OpenAI

def get_content_from_gpt(keyword):
    """
    OpenAI GPT 모델을 사용하여 주어진 키워드에 대한 설명을 생성합니다.
    API 키는 'OPENAI_API_KEY' 환경 변수에서 가져옵니다.
    """
    api_key = os.environ.get("OPENAI_API_KEY") # 환경 변수에서 API 키 읽기
    if not api_key:
        print("중요: OpenAI API 키가 환경 변수에 설정되지 않았습니다!")
        return "오류: OpenAI API 키를 설정해주세요. (환경 변수 OPENAI_API_KEY 확인 필요)"

    try:
        # OpenAI API 클라이언트 초기화 (최신 openai 라이브러리 스타일)
        client = OpenAI(api_key=api_key)

        # GPT 모델에 채팅 형식으로 요청
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",  # 또는 "gpt-4o" 등 최신 고성능 모델
            messages=[
                {"role": "system", "content": "당신은 사용자의 질문에 대해 명확하고, 논리적이며, 이해하기 쉽게 설명해주는 AI 전문가입니다. 모든 답변은 한국어로 제공하며, 핵심 내용을 잘 요약해주세요."},
                {"role": "user", "content": f"'{keyword}'에 대해 초보자도 쉽게 이해할 수 있도록 자세히 설명해주십시오."}
            ],
            temperature=0.65, # 답변의 창의성/일관성 조절 (0.0~2.0, 낮을수록 일관적)
            max_tokens=1800   # 최대 응답 길이 (토큰 단위)
        )
        # AI가 생성한 답변 텍스트 반환
        return response.choices[0].message.content.strip()
    except Exception as e:
        error_message = f"GPT API 호출 중 오류 발생: {str(e)}"
        print(error_message) # 서버 로그에 오류 기록
        user_friendly_error = "죄송합니다, AI로부터 답변을 가져오는 중 예기치 않은 문제가 발생했습니다. 잠시 후 다시 시도해주세요."
        # API 키 인증 오류 시 좀 더 명확한 안내
        if "authentication" in str(e).lower() or "api key" in str(e).lower():
            user_friendly_error = "OpenAI API 키 인증에 문제가 있는 것 같습니다. API 키가 정확한지, 환경 변수 설정이 올바르게 되었는지 다시 한번 확인해주십시오!"
        return user_friendly_error

if __name__ == '__main__':
    # search.py 파일을 직접 실행하여 테스트할 수 있습니다.
    # 테스트 전에 반드시 터미널에서 OPENAI_API_KEY 환경 변수를 설정해야 합니다!
    # (예: export OPENAI_API_KEY="여러분의_API_키")
    test_keyword = "도커(Docker) 컨테이너 기술의 장점은 무엇인가요?"
    print(f"--- '{test_keyword}'에 대한 GPT 응답 테스트 ---")
    gpt_answer = get_content_from_gpt(test_keyword)
    print(gpt_answer)
    print("--- GPT 응답 테스트 완료 ---")

 

주요 코드 설명 (search.py):

  • os.environ.get("OPENAI_API_KEY"): 3단계에서 설정한 OPENAI_API_KEY 환경 변수 값을 가져옵니다.
  • OpenAI(api_key=api_key): API 키를 사용하여 OpenAI 서비스에 연결할 클라이언트 객체를 생성합니다.
  • client.chat.completions.create(...): GPT 모델에 채팅 기반의 요청을 보냅니다.
    • model: 사용할 AI 모델을 지정합니다 (예: "gpt-3.5-turbo", "gpt-4o").
    • messages: AI와의 대화 내용입니다.
      • role: "system": AI의 전반적인 역할이나 행동 지침을 설정합니다.
      • role: "user": AI에게 전달할 사용자의 실제 질문입니다.
    • temperature, max_tokens: AI 응답의 다양성과 최대 길이를 제어하는 파라미터입니다.
  • response.choices[0].message.content.strip(): AI의 응답 중에서 실제 텍스트 내용만 추출하고 불필요한 공백을 제거합니다.
  • try...except 블록: API 호출 중 발생할 수 있는 오류(잘못된 API 키, 네트워크 문제 등)를 감지하고, 프로그램이 비정상적으로 종료되지 않도록 처리하며 사용자에게 친절한 오류 메시지를 반환합니다.

[6단계]: 웹 서비스의 컨트롤 타워 - Flask 앱 (app.py)

사용자의 웹 요청을 받아 처리하고, search.py의 AI 기능을 호출하여 그 결과를 웹 페이지로 다시 전달하는 Flask 애플리케이션의 핵심 로직(app.py)을 작성합니다.

MyFirstWebWithLLM 프로젝트 디렉토리 내에 app.py 파일을 생성하고 다음 코드를 작성하여 저장합니다.

import os
from flask import Flask, render_template, request, redirect, url_for
from search import get_content_from_gpt # 5단계에서 작성한 search.py의 함수 임포트

# Flask 애플리케이션 인스턴스 생성
app = Flask(__name__)

# Flask 세션 관리 등을 위한 시크릿 키 설정 (보안상 중요)
# 실제 운영 환경에서는 예측 불가능한 강력한 키를 사용해야 합니다.
app.secret_key = os.urandom(32)

# 메인 페이지 (키워드 입력 폼) 라우팅
@app.route('/')
def home_page():
    """사용자가 웹사이트 루트 URL에 접속했을 때 호출됩니다."""
    print("사용자가 메인 페이지('/')에 접근했습니다.")
    return render_template('index.html') # index.html 템플릿을 사용자에게 보여줌

# 키워드 검색 처리 및 결과 페이지 라우팅
@app.route('/search', methods=['POST']) # HTTP POST 요청만 처리
def handle_search_request():
    """사용자가 'index.html'에서 폼을 제출했을 때 호출됩니다."""
    if request.method == 'POST':
        # 폼 데이터에서 'keyword' 값을 가져옴. 값이 없으면 빈 문자열 반환 후 공백 제거.
        user_keyword = request.form.get('keyword', '').strip()

        if not user_keyword:
            print("경고: 사용자로부터 빈 키워드가 입력되었습니다. 메인 페이지로 리다이렉트합니다.")
            # 키워드가 입력되지 않았으면, 다시 메인 페이지로 보냄
            return redirect(url_for('home_page'))

        print(f"사용자가 검색한 키워드: '{user_keyword}' (GPT에게 전달 예정)")
        
        # search.py의 get_content_from_gpt 함수를 호출하여 AI의 설명을 가져옴
        ai_generated_content = get_content_from_gpt(user_keyword)
        
        # 디버깅을 위해 AI 응답 일부를 서버 콘솔에 출력
        # print(f"AI로부터 받은 응답 (첫 150자): {ai_generated_content[:150]}...")

        # result.html 템플릿에 사용자가 입력한 키워드와 AI가 생성한 내용을 전달하여 렌더링
        return render_template('result.html', keyword=user_keyword, content=ai_generated_content)
    
    # POST 요청이 아닌 다른 방법으로 '/search' URL에 접근한 경우, 메인 페이지로 리다이렉트
    return redirect(url_for('home_page'))

# 이 스크립트 파일(app.py)이 직접 실행될 때 Flask 개발 서버를 시작
if __name__ == '__main__':
    print("Flask 웹 애플리케이션 서버를 시작합니다. 종료하려면 Ctrl+C를 누르세요.")
    # host='0.0.0.0'은 로컬 머신 외부에서도 (같은 네트워크상에서) 접근 가능하게 함
    # port=5000은 웹 서버가 사용할 포트 번호
    # debug=True는 개발 중에 유용 (코드 변경 시 자동 재시작, 상세 오류 정보 제공)
    # 실제 서비스 배포 시에는 debug=False로 변경하고, Gunicorn 같은 WSGI 서버 사용 권장
    app.run(host='0.0.0.0', port=5000, debug=True)

 

주요 코드 설명 (app.py):

  • app = Flask(__name__): Flask 애플리케이션 객체를 생성합니다. 이 객체가 웹 서버의 역할을 합니다.
  • @app.route('/'): 웹사이트의 루트 URL(예: http://localhost:5000/)로 사용자가 접속하면 home_page 함수가 실행되도록 지정합니다.
  • render_template('index.html'): templates 디렉토리에서 index.html 파일을 찾아 그 내용을 웹 브라우저에 표시합니다.
  • @app.route('/search', methods=['POST']): /search URL로 HTTP POST 요청이 들어오면 (주로 HTML 폼 제출 시 사용됨) handle_search_request 함수가 실행되도록 지정합니다. index.html의 폼 태그에서 action="/search" method="post"로 설정했기 때문입니다.
  • request.form.get('keyword', '').strip(): 사용자가 index.html의 폼에 입력한 keyword 값을 가져옵니다.
  • get_content_from_gpt(user_keyword): search.py에 정의된 함수를 호출하여 AI에게 설명을 요청합니다.
  • render_template('result.html', keyword=user_keyword, content=ai_generated_content): result.html 템플릿을 렌더링하면서, keyword와 content라는 변수명으로 각각 사용자가 입력한 키워드와 AI가 생성한 설명을 전달합니다. HTML 템플릿 내에서는 {{ keyword }}와 {{ content }} 형식으로 이 값들을 사용할 수 있습니다.
  • app.run(host='0.0.0.0', port=5000, debug=True): Flask 개발 서버를 시작합니다.
    • host='0.0.0.0': 로컬 머신뿐만 아니라 동일 네트워크상의 다른 기기에서도 이 서버에 접속할 수 있게 합니다 (예: 스마트폰으로 내 PC IP 주소:5000 접속).
    • port=5000: 서버가 사용할 포트 번호를 지정합니다.
    • debug=True: 개발 모드로 실행합니다. 코드가 변경될 때마다 서버가 자동으로 재시작되며, 오류 발생 시 웹 브라우저에 상세한 디버깅 정보를 표시해줍니다. 실제 서비스 배포 시에는 보안을 위해 False로 변경해야 합니다.

[7단계]: 애플리케이션 실행 및 AI 봇 테스트

모든 코드가 준비되었습니다! 이제 직접 만든 AI 키워드 설명 봇을 실행하고 테스트해볼 시간입니다.

  1. 가상 환경 활성화 확인: 터미널 프롬프트 맨 앞에 (myenv) 표시가 있는지 다시 한번 확인하세요. 만약 없다면 source myenv/bin/activate 명령어로 가상 환경을 활성화합니다.
  2. OpenAI API 키 환경 변수 설정 확인: macOS/Linux 3단계에서 설명한 대로 API 키가 현재 터미널 세션의 환경 변수로 올바르게 설정되어 있는지 확인합니다. (터미널을 새로 열었다면, 임시 설정은 사라졌을 수 있으므로 영구 설정을 했거나 export 명령어를 다시 실행해야 합니다.)
  3. Flask 애플리케이션 실행: 프로젝트 디렉토리(MyFirstWebWithLLM)로 이동된 터미널에서 다음 명령어를 입력하여 app.py를 실행합니다. (Python 3 사용 권장)(또는 시스템 설정에 따라 python app.py)
  4. python3 app.py
    
  5. 웹 브라우저에서 접속 및 테스트: 터미널에 다음과 유사한 메시지가 출력되면 Flask 서버가 성공적으로 실행된 것입니다.
     * Serving Flask app 'app' (lazy loading)
     * Environment: production
       WARNING: This is a development server. Do not use it in a production deployment.
       Use a production WSGI server instead.
     * Debug mode: on
     * Running on http://0.0.0.0:5000 (Press CTRL+C to quit)
     * Restarting with stat
     * Debugger is active!
     * Debugger PIN: xxx-xxx-xxx
    
    이제 웹 브라우저(Safari, Chrome, Firefox 등)를 열고 주소창에 다음 주소 중 하나를 입력한 후 엔터 키를 누르세요:
    • http://127.0.0.1:5000
    • http://localhost:5000
    "AI 키워드 설명봇 (macOS/Linux Ver.)" 페이지가 나타나면 성공입니다! 입력창에 궁금한 키워드를 넣고 "AI에게 질문하기!" 버튼을 클릭해 보세요. 잠시 후, AI가 생성한 설명이 담긴 결과 페이지를 확인할 수 있을 것입니다.
  6. 웹 서버 실행을 중지하려면, 터미널 창에서 Ctrl 키와 C 키를 함께 누르세요.
반응형