우당탕탕 백준과 깃헙 연동하기 with Python

Sawol·2021년 3월 15일
11
post-thumbnail

모든 발전은 귀찮음에서 부터 출발한다. -내 생각

❗️ 본 게시글은 백준 알고리즘 문제풀이 사이트에서 작성한 코드를 깃헙에 자동으로 업로드하는 프로젝트에 대한 이야기입니다. 부디 잘못된 부분이 있다면 알려주세요.🙏


💡개발한 계기

최근 들어, 매일 백준 문제를 풀고 있다. 예전에 문제를 풀 때는 항상 내가 제출한 정답 코드를 복사, 붙여넣기를 통해 깃헙에 올렸었다. 이제는 귀찮기도 해서 그냥 풀고 있는데 문득, 깃헙에 내 잔디들이 죽어가는 게 아쉬웠다.

내가 코드를 작성하지 않는 것도 아니고! 매일 코드를 짜는데 내 잔디들이 죽어가고 있다니...
그래서 다시 잔디를 잘 가꾸어 보기로 했다. 그렇다고 예전처럼 수동으로 코드 짜고 -> 복사하고 -> 올리는 이 과정은 너무나도 귀찮다.

난 코드를 짤게. 저장은 누가할래?
그래서 만들었다! 잔디 살리기 프로젝트!! 무럭 무럭 다시 자라렴.😆👨‍🌾


🔧기술 스택

파이썬을 너무나도 애정 하는 나는 세상에 모든 것은 '파이썬' 하나로 다 만들 수 있다고 생각한다.
물론 구글은 디폴트.

  • Python3
  • selenium
  • BeautifulSoup
  • pygithub
  • github (배포)

필요한 배경지식

selenium

웹 브라우저를 컨트롤 할 수 있는 도구의 모음이다. 이때동안 셀레니움이 하나의 도구인 줄 알았는데 그게 아니고 셀레니움 안에는 3가지의 도구가 있다.

  • WebDriver
  • IDE
  • Grid

자세한건 공식 홈페이지를 참고하면 되고, 이 프로젝트에서 사용한 WebDriver에 대해 이야기를 좀 더 하자면 하나의 API로 브라우저를 제어하는 역할을 한다. 즉, 우리가 흔히 "셀레니움으로 크롤러를 만들었어~" 라고 하지만 정확히 말하자면 "셀리니움의 WebDriver로 크롤러를 만들었어~" 가 맞는 표현이다.
셀레니움은 페이지를 방문할 때 가져올 수 있는 모든 리소스를 다 가져오기 때문에 속도가 조금 느리다. 만약 정적이 페이지에서 데이터를 가져올 경우에는 아래에 설명한 bs4를 사용하는 게 좋다.
또한, 셀레니움은 대부분 파이썬을 많이 사용하지만 사실 자바, C#, 코틀린 등 다양한 언어로 사용 가능하다.
아직 셀레니움과 WebDriver에 대해 이해가 안 간다면 여기를 참고하면 된다.

BeautifulSoup

“You didn’t write that awful page. You’re just trying to get some data out of it. Beautiful Soup is here to help.” - Opening lines of Beautiful Soup

bs4(BeautifulSoup4)는 html, xml 같은 언어에서 데이터를 가져오기 위한 python 라이브러리다. 예를 들어 영화 예매 사이트에 영화 제목과 상영 시간 데이터를 갖고 싶다고 하자. 수동으로 영화 제목 복사 -> 붙여넣기, 상영 시간 복사 -> 붙여넣기를 해도 되지만 만약 영화가 몇 십에서 몇 백 개가 된다면? 너무 비효율적이다. 이럴 때 사용하는 게 bs4이다.
정적인 사이트에서는 대부분의 데이터를 들고 올 수 있지만 만약 스크립트가 돌아가는 동적 페이지에서 데이터를 가지고 올 때는 bs4는 스크립트를 동작시키지 못하니, 셀레니움과 함께 사용하는 것이 좋다.
물론 "나는 셀레니움이 느려서 사용하기 싫다!" 라고 한다면 동적인 사이트도 bs4로 데이터를 가져올 수 있다. 이전에 다음 크롤러를 개발했을 때 속도 때문에 셀레니움 없이 bs4로 개발한 적이 있다. 대신 조금 귀찮아진다. 사이트에서 요구하는 쿠키 값이나 토큰 값을 전달하는 관련 api를 찾아 스크립트가 동작하도록 한 뒤, 데이터를 긁으면 된다. 하지만 데이터를 쉽게 가져갈 수 있도록 "이 api를 쓰면 돼~" 하며 OpenAPI를 알려주는 경우도 있지만, 대부분 그렇지 않다. 예전 프로젝트도 안 알려줘서 아~주 고생을... 셀레니움과 bs4의 차이가 궁금하다면 여기를 보면 된다.


우당탕탕 제작과정

1. 크롬은 시크릿모드!🕶

일단 나는 Chrome을 사용하기에 WebDriver Chrome를 다운했다. 그리고 시크릿모드 성애자라서 시크릿모드로 사용할 수 있도록 옵션 값도 집어넣었다.

chrome_options = webdriver.ChromeOptions()  
chrome_options.add_argument("--incognito")

2. 앗, 캡챠!😫

일단 자동 로그인부터 만들었다. 로그인 하는것 부터가 귀찮으니까...

그런데 캡챠가 떴다. 이걸 우회해야겠는데 싶어서 pyperclip 을 사용해 ID와 PW를 복사 -> 붙여넣기 형식으로 바꿨는데도 우회를 실패했다.😭
이 방법, 저 방법 찾다가 캡챠의 늪에 빠져 이제는 내가 그냥 로그인해도 100%로 캡챠가 뜬다. 심지어 소화전을 찾아라->버스를 찾아라->횡단보도를 찾아라 기타 등등 6문제 정도는 풀어야 통과가 된다. 이미 늦었지만 그냥 좀 귀찮게 로그인은 직접하자로 결론냈다.

3. 너, 뭐하고 있니?👀

백준 문제를 풀 때, 나의 상황은 대략 이렇다.

  1. 문제를 찾는다.
  2. 문제를 읽는다.
  3. 문제를 풀고 제출한다.
  4. 문제의 결과를 본다.

1-4를 반복하는 패턴이다. 여기서 크롤링을 사용해야 하는 경우는 4번이다. 문제를 제출한 결과가 정답일 경우 해당 코드를 크롤링하고 정답이 아닐 경우에는 답을 맞출 때까지 기다려야 한다.
일단, 내가 뭘 하고 있는지 크롤러가 알아야 하기 때문에 url를 통해 나의 상태에 대해 코드를 짜봤다.

간접적으로 감시당하는 기분을 느끼게 되었다.

4. 난 네가 금방 제출한 코드를 알고있다.🕵️‍♂️

내가 제출한 결과를 보고 있을 때, "맞았습니다!!"라는 문구가 뜬다면 그 코드를 가지고 와야한다.

처음에는 셀레니움으로 하면 속도도 느리고 소스를 보기 위해 한 번 더 들어가야 한다는 점이 싫어서 bs4로 해결하려고 했었다. 그런데 코드 부분이 api를 사용해서 디비에서 불러오는 방식이어서 bs4로는 코드를 짜기 복잡해졌다.
생각해 보면 코드 하나 읽어오는 것이기 때문에 bs4나 셀레니움이나 큰 차이가 없을 거고, 코드를 보기 위해 한 번 더 들어가는 것도 크게 신경이 쓰이지 않을 거라 합리화했다. 사실 API를 만들 시간에 알고리즘 한 문제 더 푸는 게 나한테 이득일 거 같기도 하고.

셀레니움을 사용하니 간단한 코드로 제출한 코드를 깔끔하게 불러올 수 있었다.

5. 넌 답을 맞춰, 코드는 내가 저장할테니😉

코드를 깃헙에 저장하기 위해서 두 가지 생각을 했다.

  1. 파일을 저장해 git으로 push 한다.
  2. git API를 사용해서 바로 github에 업로드한다.

두 방법 중 아무래도 2번이 가장 간단하고 깔끔한 방법인 거 같아 git API를 사용하기로 했다. 파이썬에서 git API를 간편하게 사용할 수 있도록 도와주는 pygithub 이라는 라이브러리가 존재한다. git API에서 지원하는 모든 기능을 지원하는 파이썬을 사용할 때는 이 라이브러리를 사용하는 것이 효율적일 것이다. 또한 Documents도 잘 정리되어 있어 사용이 어렵지 않다.
git API를 쓰기 위해서 토큰을 깃헙에서 발급받은 뒤, 해당 토큰으로 로그인을 한다. 그리고 원하는 repository에 파일을 생성하면 끝이다.

여기서 끝내도 좋겠지만, 한 가지 상황에 대해 처리를 해야 한다. 나는 보통 문제를 풀 때, 맞추면 넘어가기도 하지만 좀 더 간결하고 파이썬스러운 코드로 짜기 위해 수정한 코드를 재제출한다. 이러한 상황에서 코드를 불러오는 것은 문제가 되지 않지만 저장할 때 에러가 발생한다. 똑같은 이름을 가진 파일을 생성하니 발생하는 문제인데, 아래의 방법으로 해결 가능하다.

  1. 파일 제목 끝에 숫자를 붙인다. (file name_1.py...)
  2. 깃헙에서 제공하는 버전 관리를 이용한다.

버전 관리를 사용하는 게 가장 깔끔할 거 같아, 리포지토리에 똑같은 이름이 존재하면 그 파일을 업데이트하는 형식으로 코드를 수정했다.

커밋한 History를 보면 정상적으로 업데이트된 코드를 볼 수 있다.

6. 기다림의 미약🕑

프로젝트가 다 완성되어간다는 기쁨에 사로잡혀있을 무렵, 내가 한 가지 사실을 간과하고 있었음을 깨달았다.
그것은 바로, 백준에서는 '채점 중'이라는 결과가 존재한다는 사실이다.

'채점 중' 일때는 채점이 끝날 때까지 기다리는 코드를 넣어줘야한다.

'채점 중' 일때는 기다리다가 채점 결과가 "맞았습니다!!"가 되면 코드를 불러온다. 글로 적으면 이렇게 간단한데, 이거 하나 놓쳐서 짰던 코드들을 다시 뜯어고쳤다. 역시 바로 개발한다고 코드 작성부터 하는 게 아니라 계획부터 완벽하게 세워야 한다. 이렇게 놓치는 거 하나 없이..


실행 모습

배포도 했다! 이름은 고민을 많이 했지만, 난 네이밍 센스 따위 없는 걸...😔


회고

이걸 만드는 3일동안 잔디가 다시 살아났다!😁

기능을 살리는 거는 하루 만에 뚝딱했지만, 파이썬 코드를 더 파이썬스럽게 디자인하는 것에 시간을 많이 투자했다. 아직 개발 경험이 적어서이겠지만 효율적인 코드, 파이썬스러운 코드로 작성하는 것은 너무 어렵다. 혼자서 하려니까 더 어려운 거 같다.
처음으로 배포라는 것을 해보고 싶어서 혼자 끙끙대며 리팩토링하고 pypi도 가입해봤다. 내가 짠 코드가 다른 오픈 소스처럼 pip install로 설치가 된다는 게 진짜 아주아주 재미난 경험이고 너무 신기했다. 그래도... 클린코드의 세계는 너무 어렵다. 솔직히 배포하기에 많이 망설였다. 다른 사람들에게 보여주기 너무 부끄러운 수준이라...😥

재미, 보람 그리고 내가 부족한 점 등 다양한 것들을 알게 되었다. 배포는 했지만 처음이다 보니 허점도 많았다. 시간이 조금 흘러 내가 다시 이 코드를 봤을 때 '어휴, 누가 코드를 이딴 식으로 짰어?!' 라는 말이 나오길 간절히 바란다. 그때까지 열심히 공부해서 발전해야지. 그리고 깃헙에 올려놨으니 누군가 보고 알려주지 않을까..?

모든 코드는 여기서 볼 수 있습니다.

3개의 댓글

comment-user-thumbnail
2021년 5월 26일

오.. 처음부터 끝까지 구현한 내용 잘 읽었습니다! 멋지시네요!

답글 달기
comment-user-thumbnail
2021년 6월 12일

오 대단합니다! 만드신 패키지 유용하게 쓸 수 있을 것 같습니다!

답글 달기
comment-user-thumbnail
2021년 11월 28일

저도 저런계기로 할 수 있는방법을 찾다가 여기왔습니다 ㅎㅎ 그런데 제가 자바만 사용하고 파이썬을 잘 몰라서 이렇게 좋은 방법을 찾았는데도,, 활용을 못하고있네요 ㅠㅠ 완전 멋지세요!!

답글 달기