[파이썬 챗봇] 2. 챗봇 실행 메인(main.py) 구현

지수·2021년 7월 14일
0

플레이데이터

목록 보기
20/50

그렇다. 부분 기능을 구현한 감자는 거기서 멈출 수 없었다.
🥔 "내가 만든 기능을 챗봇에 딱 꽂아서 전체 실행을 돌려봐야겠어..!"

말하는 감자의 네이버 날씨 웹 크롤링이 궁금하다면? [ 1편 보고 오기 ]

💡 아이디어

[ 파이썬 챗봇 ] 을 만들기 위해 팀원 각각 기능을 하나씩 맡아서 개발 중에 있다.
각각 맡은 기능 구현이 끝나면 챗봇을 시작하고 - 기능을 선택하고 - 여러 기능을 연결하여 구동하고 - 챗봇을 종료하는 main.py를 만들어 서로 서로 코드를 합쳐야 한다.
다행히 내가 맡은 네이버 날씨 웹 크롤링 부분이 하루만에 끝나서, 먼저 main 파일을 만드는데 도전해보기로 했다..🔥🥔


main.py에 필요한 함수

  • 챗봇을 시작 여부를 확인하는 함수 ⏩ chatbot()
  • 채팅을 시작하는 함수 ⏩ startChat()
  • 기능을 선택하는 함수 ⏩ choose()
  • 선택한 기능을 실행하는 함수(팀원 코드 연결) ⏩ func()
  • 채팅을 끝내는 함수 ⏩ encChat()

💻 구현

0. 구상

챗봇 구동을 위해 main.py를 아래와 같이 설계했다.

  • chatbot() 함수를 통해 챗봇을 시작할 지 여부(answer)를 확인하고
  • answer 값이 Y이면 startChat() 함수를, N이면 endChat() 함수를 실행한다.
  • startChat() 함수를 실행하고나면, 현재 시간을 확인하여 입실, 퇴실 알림을 보낸다.
  • 이어 choose() 함수를 실행하여 어떤 기능 메뉴를 실행할 지 번호(cnum)를 입력 받는다.
  • 이후 기능 실행을 위해 cnum 값을 전역변수로 받아와 func() 함수를 실행한다.
    1이면 날씨 정보 출력 기능을, 2이면 플레이데이터 시간표 출력 기능을, 3이면 점심 메뉴 고르기 기능을, 4면 미니게임 기능을, 5면 코로나 확진 현황 출력 기능을 실행한다.
    cnum 값이 999이면 endChat() 함수를 실행하여 채팅을 마친다.
  • 6번 메뉴 오늘의 뉴스 정보 출력 기능이 추가되었다!

1. 구현 포인트

main.py에 있는 함수들은 구현 자체가 어렵다기보다
함수와 함수를 순서대로 연결하고, 반복해야할 부분을 반복하고, 반복을 탈출해야할 때 탈출하는 등 부분을 구현하는 것이 까다로웠다.

✅ 이럴 때는 위 과정처럼 필요한 함수들을 리스트업하고, 흐름도를 대략적으로 그려보는 것이 큰 도움이 되었다. (처음부터 위 이미지처럼 정리할 수 있었던 것은 아니지만, 노트에 끄적끄적하면서 정리하였다.)
▶ 나중에 디버깅할 때도 흐름도를 그려보는 것이 큰 도움이 되었다!
▶ 대충 구상만 해두고 코드를 치기 시작하면.. 후에 무한루프와 중도종료 등 엄청난 디버깅의 늪에 빠져버릴지도...(안돼..!)

✅ main.py의 함수들은 메인 기능이랄 것보다 챗봇 기본 메세지를 출력하는 부분이 많다. time.sleep을 활용해서 출력 속도를 조절하는 것이 필수였다.
▶ 글자를 한 글자씩 출력하는 방법도 사용해볼까했지만, 출력하는 문장이 길 때는 다소 번잡스러워보여서 사용하지 않았다.

2. 구현 상 문제점/유의점

main.py 구현에 있어 가장 신경썼던 부분은 아무래도 빈틈없는 흐름이었다.

  • 입력을 받는 부분에서 제시한 보기와 다른 답을 입력해도 에러없이 입력값을 다시 받음
  • 각 기능 메뉴를 실행한 후 다시 기능 메뉴를 선택할 수 있도록 반복함
  • 사용자가 챗봇 종료 옵션을 선택하기 전까지 챗봇을 반복 실행함
  • 반복 실행 중 사용자가 챗봇 종료 옵션을 선택하면 오류없이 반복을 탈출함

🐛 디버깅

출력문 몇 개랑 함수 연결만 하면되니까 금방 끝나겠지?라고 생각한 main.py도 디버깅을 피해갈 수는 없었는데..

조건문, 반복문이 많은만큼 자잘한 수정이 많이 필요했는데 기억에 남는 것은 아래 세가지이다.
1) 각 기능 실행 이후 종료되지 않고, 다른 기능을 실행하게 하려다가 무한 루프에 빠져버린 경우
2) 사용자가 제시한 보기가 아닌 값을 입력했을 때, 재입력을 요청하게 만드는 부분
3) 여러 함수를 엮어 하나의 흐름을 만드는 부분


먼저, 1)번 문제의 경우,
(아---주)초기 코드에서는 아래와 같이 코드를 짰기 때문에 발생한 문제이다. (너무 허접한 코드라서 까는 밑밥..)

# 초기 코드 A
while(1):
	if cnum == "1":
            time.sleep(1)
            wt.weather()
        elif cnum == "2":
            time.sleep(1)
            ps.print_schedule()
        elif cnum == "3":
            time.sleep(1)
            ms.menu()
        elif cnum == "4":
            time.sleep(1)
            mg.miniGame()
        elif cnum == "5":
            time.sleep(1)
            cn.corona()
        elif cnum == "999":
	    endChat()

위의 코드가 정말 단순하게 while문 안에 계속 넣고 돌리다가 cnum이 999일 때만 채팅을 끝내주면 되겠지?라는 짧은 생각에서 짠 코드인데,
당연하게도 저 코드는 무한루프에 빠진다. break가 없는 while(1)이라니..(절레절레😩)
게다가 저 코드는 원래 생각했던대로 한 기능이 끝나고 다른 기능을 선택하게 되는 식이 아니라 처음 선택한 하나의 기능만 무한대로 재실행한다. 껄껄;

그래서 또 단순하고 짧은 생각으로 break문을 붙여줘봤다.

# 초기 코드 B
while(1):
	if cnum == "1":
            time.sleep(1)
            wt.weather()
            break
        elif cnum == "2":
            time.sleep(1)
            ps.print_schedule()
            break
        elif cnum == "3":
            time.sleep(1)
            ms.menu()
            break
        elif cnum == "4":
            time.sleep(1)
            mg.miniGame()
            break
        elif cnum == "5":
            time.sleep(1)
            cn.corona()
            break
        elif cnum == "999":
            break
	    endChat()

이렇게 되면 무한루프에서는 탈출하지만 모든 경우에 break로 반복문을 탈출하기 때문에 반복문을 쓴 이유가 전혀 없어진다ㅋㅋㅋ
물론 반복문에서 빠져나와 다시 cnum(기능 메뉴 번호) 값을 받는 choose() 함수로 이동하지도 않는다. (초기에는 챗봇 실행 test시 함수와 함수를 연결하지 않고 각각 함수를 순서대로 출력하는 방식을 사용했다. => 3)번 문제에 대한 이야기)

그래서 최종적으로는, 반복문을 사용하지 않고 choose() 함수에서 cnum 값에 따라

  • 기능 메뉴 번호 (1~5)(1~6)일 때만 func() 함수를 이어 호출하고
  • 채팅 종료 옵션 번호일 때는 endChat() 함수를 이어 호출하고
  • 그 외 값을 입력했을 때는 다시 choose() 함수를 호출하도록 한 뒤
  • func() 함수 안에서 각 기능 메뉴 번호에 따라 if-elif 문으로 알맞은 함수를 호출하고
  • if-elif 문이 종료되면 다시 choose() 함수를 실행하도록 만들었다.

    반복문을 사용하지는 않았지만, 자체적인 반복 사이클을 만들었달까..?🤔

다음으로 사용자로부터 입력값을 받는 부분이 포함된만큼 2)번 문제 해결이 중요하다.

입력값을 받는 부분은 총 세 부분이다.
1. chatbot() : 챗봇을 시작할지 종료할지 묻는 부분 Y/N
2. startchat() : 이름을 입력 받는 부분 (이건 정해진 보기가 없으니까 제외)
3. choose() : 실행하고 싶은 기능 메뉴 번호를 입력 받는 부분 1,2,3,4,5, 999

반복문도 써보고, 조건문도 써보고 여러 시도를 해봤지만
오류나 함수 꼬임없이 사용할 수 있었던 방법은 아래와 같다.

  • 입력값에 대한 조건을 설정하고 입력값이 ~이면
  • 각 입력값마다 다음으로 실행해야할 함수를 실행
  • 재입력을 받아야하는 경우,
    잘못 입력했다는 멘트를 출력하고 자기 자신 함수 호출
    (=뱅굴뱅굴 값을 제대로 입력하지 않으면 벗어나지 못하는 제자리걸음)

위 2)번 문제 해결 중 각 입력마다 다음으로 실행해야할 함수를 실행이 잘 작동하기 위해서는 전체 함수 흐름을 잘 잡아주어야 한다.

1번) 문제 해결 파트에서 잠깐 언급했듯이,
아주 초기에는 챗봇 실행시

  • 가장 먼저 호출되는 함수가 chatbot()이 아니라 startChat()이었고,
  • 테스트 시에 필요한 함수를 순서대로 주르륵 호출했었다.

그런데 그렇게되면 main.py 내부 함수 흐름이
챗봇을 시작해서 계속 굴리는 사이클, 종료하는 사이클로 깔끔하게 나눠지지더 않고,
테스트 시에 임의로 사이클을 만들어주는거라 챗봇을 종료해야할 때 오류없이 종료가 되지 않았다.

이게 무슨 소리냐면 초기에는 test할 때
임의로 함수가 호출되는 사이클을 아래와 같이 만들어주었다.

startChat()
choose()
func()

위의 초기 코드는 채팅 시작하고, 기능 메뉴 번호 받고, 기능 실현하고하면 되겠지?라는 짧은 생각에서 짠 코드이다.
그런데 위 코드를 실행하면 채팅 종료를 선택해서 startChat()에서 endChat()으로 이동한 후에도 choose() 함수와 func() 함수를 실행하려고해서 오류가 난다.
+) 팀원분이 짜신 코드리뷰를 하면서 발견한 것인데 이렇게 진행했을 경우 endChat() 안에 exit()을 넣어주면 뒷 코드를 진행하지 않고 탈출이 가능하다!!

그래서 순서도를 그려보고 아래와 같이 수정하였다.

chatbot() 함수를 실행하면 채팅을 시작할 지 여부(Y/N)를 결정하는 입력값에 따라
1) startChat() 함수를 실행하여 채팅 시작
2) endChat() 함수를 실행하여 채팅 종료
3) 그 외의 값은 다시 chatbot() 실행하여 재입력

starChat() 함수가 이어 실행되면 사용자 이름 값을 입력받고,
현 시간에 따라 입실, 퇴실 알람을 출력하고
startChat() 함수 안 마지막 줄에서 choose() 함수를 호출한다.(이어서 호출)

choose() 함수가 이어 실행되면 기능 메뉴 번호를 입력받고, 입력값에 따라
1) 각 기능 구현 함수를 실행시키는 func() 함수 호출
2) endChat() 함수를 실행하여 채팅 종료
3) 그 외의 값은 다시 choose() 실행하여 재입력

func() 함수가 이어 실행되면 choose() 함수에서 받아오 기능 메뉴 번호에 따라 각 기능 구현 함수 실행


📄 코드

main.py 함수는 위에서 말한 흐름, 예외처리가 다라서 특별히 더 설명할 것이 없다.
자세한 코드 내용은 깃허브로!


💬 리뷰

한 줄 요약 : 빠르게 올 수 있는 길을 돌고 돌아 왔지만..그 과정 또한 학습..😐💡

프로젝트를 진행하면서 초기 구상 모델보다 점점 확장되는 경향이 있어서 main 함수를 계속 수정해야했다.

처음에 흐름을 잘 짜두었다면, 후루룩 완성될 코드를 잘못된 길로 들어서 계속 조금씩 추가하다보니 너무 멀리 와버렸다는 생각이 들 때가 가끔 있었다.
성격이 급한 편이라 뭘 찬찬히 준비하고 시작하기보다 일단 시작해보고 생각을 하는 게 역풍으로 통수를 딱 때렸달까..ㅎ 차분해지자 지수..

흐름도를 정리하면서, 과정을 벨로그에 리뷰하면서 코드 짜는 과정을 정리할 수 있었고, 논리적으로 이상한 부분을 찾아낼 수 있었다 굿굿

팀원분들이 다들 엄청 열심히 해주셔서 프로젝트가 순식간에 완성 단계에 가까워졌다! 대박!
남은 시간동안 디벨롭 진행하면 좋은 결과물이 나올 것 같다.

이번에 처음 git add, commit, branch도 만들어서 push도 해봤다..! 완전 대박
(나에게 git은 그냥 git-hub이랑 비슷한 애..git-hub는 git 없이 블로그처럼 코드 올리는 곳이었는데...ㅋㅋㅠㅠ)

다음 기회에 git을 더 공부해서 프로젝트 협업 때 더 제대로 사용해보고 싶다!

아쉬운 점

이번 포스팅 내내 아쉬운 점, 어려웠던 점 써놔서 이건 패-스

profile
사부작 사부작

0개의 댓글