뉴스 카테고리(2) 웹 만들기

정원석·2024년 9월 23일

프로젝트

목록 보기
2/3

머신러닝을 웹에서 사용하는 방법

머신러닝 프로그램도 일반적인 Python 프로그램입니다. 따라서 필요에 따라 실행할 수 있습니다.
하지만 프로그램을 실행할 때마다 프로세스를 다시 실행하는 것은 굉장히 비효율적인 일입니다.
TensorFlow 라이브러리를 읽어 들이는 것만으로도 시간이 꽤 들기 때문입니다.

그래서 이번에서 머신러닝하는 프로그램을 서버(프로세스)로 실행해두고 웹 애플리케이션을 통해 머신러닝 학습 결과를 얻는 형태로 프로그램을 구현합니다.

웹에서 카테고리를 분류하는 모델 사용하기

이전에 소개한 그림에서는 웹 서버와 머신러닝 서버가 따로 동작하는 형태였습니다. 하지만 포트 번호 의 충돌만 발생하지 않으면 두 개의 프로그램이 같은 머신(컴퓨터) 위에서 동작할 수 있습니다.
또한 대량의 접근이 없는 경우라면 웹 서버에 머신러닝 시스템을 직접 넣어도 됩니다. 이번 절에서는 실행 환경 편의성을 고려해 가장 쉬운 방법이라고 할 수 있는 '웹 서버 내부에 머신러닝 시스템을 직접 넣는 방법'을 사용하겠습니다.
즉 다음과 같이 웹 서버와 머신러닝 서버를 하나의 프로그램으로 구현하겠습니다.

그림에서 알 수 있는 것처럼 사용자가 웹 서버에 접속하면 일단 HTML/자바스크립트 애플리케이션을 제공합니다. 애플리케이션이 실행된 뒤 사용자가 텍스트 상자에 텍스트를 입력하고 '판정'버튼을 누르면 판정 결과를 출력하게 구현해 봅시다.

머신러닝 기능을 가진 웹 서버 만들기

그럼 카테고리를 판정하는 API를 포함한 웹 서버 프로그램을 Python으로 만들어 봅시다. 참고로 'APT 는 애플리케이션 프로그래밍 인터페이스(Application Programming Interface)의 약자로, 외부의 애플리케이션에서 사용하기 쉬운 형태로 기능을 제공하는 것을 의미합니다.

다음 웹 서버는 앞에서 만든 사전 데이터, MLP 가중치 데이터, tfidf.py 모듈과 my_text.py 파일을 사용하므로 'genre' 디렉터리 내부에 있는 프로그램과 데이터가 있는 디렉터리에 파일을 생성하고 실행 하면 됩니다.

import json
import flask
from flask import request
import my_text

# 포트 번호 --- (*1)
TM_PORT_NO = 8085
# HTTP 서버 실행하기
app = flask.Flask(__name__)
print("http://localhost:" + str(TM_PORT_NO))

# 루트에 접근할 경우 --- (*2)
@app.route('/', methods=['GET'])
def index():
    with open("index.html", "rb") as f:
        return f.read()

# /api에 접근할 경우
@app.route('/api', methods=['GET'])
def api():
    # URL 매개 변수 추출하기 --- (*3)
    q = request.args.get('q', '')
    if q == '':
      return '{"label": "내용을 입력해주세요", "per":0}'
    print("q=", q)
    # 텍스트 카테고리 판별하기 --- (*4)
    label, per, no = my_text.check_genre(q)
    # 결과를 JSON으로 출력하기
    return json.dumps({
      "label": label, 
      "per": per,
      "genre_no": no
    })
    
if __name__ == '__main__':
    # 서버 실행하기
    app.run(debug=False, port=TM_PORT_NO)

프로그램 내부에서 웹 서버를 간단하게 만들 수 있는 Flask 프레임워크를 사용했습니다.

python tm_server.py

명령어를 입력하고 서버를 켜 봅시다.

이제 주소창에
http://localhost:8085/api?q=(판정하고 싶은 텍스트)
입력해봅시다.

http://localhost:8085/api?q=이번 주에는 미세먼지가 많을 것으로 예상되므로 노약자는 외출을 자제하는 것이 좋습니다.

입력을 해봅시다.


그럼 프로그램을 살펴봅시다. 기본적으로는 my_text.py의 check_genre() 함수를 웹 서버를 통해 제 공하게 만들었을 뿐입니다. Flask 웹 프레임워크를 사용해 굉장히 간단한 코드로 HTTP 서버를 구현했습니다.

프로그램의 (※1)에서는 8085번 포트를 사용해 HTTP 서버를 실행하게 지정합니다. 만약 다른 프로그램에서 8085번 포트를 사용하고 있다면 다른 번호로 변경하면 됩니다. (*2)의 index() 함수에서는 루트에 접근할 경우 'index.html'을 응답하게 합니다.

이어서 (※3) 부분의 api() 함수는 '/api'에 접근할 경우에 호출됩니다. 함수 내부에서는 request.args.get() 메서드를 사용해 URL 매개변수를 추출합니다. (※4) 부분에서는 my_text 모듈의 check_genre() 함수를 호출하고 결과를 JSON 형식으로 응답하게 합니다.

이 서버 프로그램에서는 앞에서 만든 머신러닝 프로그램을 모듈로 사용합니다. 모듈을 읽어 들이는 시점에서 TensorFlow와 Keras가 실행되며 학습 데이터 등을 읽어 들입니다. 그리고 /api에 접근했을 때 카테고리를 판정합니다.

API를 호출하는 웹 애플리케이션 만들기

이어서 HTML5와 자바스크립트를 사용해 웹 애플리케이션을 만들어 봅시다. 이전의 tm_server.py와 같은 디렉토리에 'index.html'이라는 이름으로 저장합니다.

<DOCTYPE html>
<html>
  <meta charset="utf-8">
  <body>
      <h1>텍스트 카테고리 판별하기</h1>
      <div>
          <textarea id="q" rows="10" cols="60"></textarea>
          <br>
          <button id="qButton">판정</button>
          <div id="result"></div>
      </div>
      <script>
          const qs = (q) => document.querySelector(q)
          window.onload = () => {
              const q = qs('#q')
              const qButton = qs('#qButton')
              const result = qs('#result')
              // 판정 버튼을 눌렀을 때 --- (1)
              qButton.onclick = () => {
                  result.innerHTML = "..."
                  // URL 생성하기 --- (2)
                  const api = "/api?q=" + encodeURIComponent(q.value)
                  // API에 접근하기 --- (3)
                  fetch(api).then((res) => {
                      return res.json() // JSON 응답
                  }).then((data) => {
                      // 결과를 화면에 출력하기 --- (4)
                      result.innerHTML =
                          data["label"] +
                          "<span style='font-size:0.5em'>(" + data["per"] + ")</span>"
                  })
              }
          }
      </script>
      <style>
          #result {
              padding: 10px;
              font-size: 2em;
              color: red;
          }
          
          #q {
              background-color: #fffff0;
          }
      </style>
  </body>
</html>

웹 브라우저로 'http://localhost:8085/'에 들어가 봅시다. 적당한 문장을 입력하고 '판정' 버튼을 클릭해봅시다.
참고로 Ajax를 위해 fetch를 사용했습니다.


문장이 너무 짧으면 제대로 판정하지 못하는 경우도 있지만, 대체로 올바른 결과를 얻을 수 있습니다.

그럼 프로그램을 확인해 봅시다. 버튼을 누르면 텍스트 박스에 적혀있는 텍스트를 API 서버에 전달하고 JSON 결과를 응답받은 뒤 이를 HTML에 출력하는 형태입니다.

프로그램의 (1)에서는 판정 버튼을 클릭했을 때의 동작을 지정합니다. (2) 부분에서는 API 서버에 전송할 URL을 생성합니다. (3) 부분에서는 fetch를 사용해 서버에 접근합니다. 결과를 응답 받으면 (4) 부분에서 HTML로 출력합니다.

profile
이기적이타주의자

0개의 댓글