졸업요건 검사 사이트 PleaseGraduate 회고

Updated: Categories:

나의 인생 프로젝트 이야기

처음해보는 회고

애증의 Please Graduate … 지금까지 운영하며 많은 고난이 함께했기에 내가 느꼈던 점들을 포스팅해보려 한다.
(매우 늦은 감이 있긴함)

글을 쓰는 재능이 없어서 걱정이지만 ㅜ 내가 가장 열정적으로 개발했던 프로젝트의 역사를 써보고 싶어서…ㅋㅋ
그냥 의식의 흐름대로 써봐야겠다 🤯


프로젝트의 시작

우선 PleaseGraduate 사이트는 나 혼자 시작한 프로젝트가 아니다.

이 프로젝트는 21년 1월 계절학기 프로그램인 창의학기제에서부터 시작됐다.

창의학기제는 3주간 자유 주제로 뭐든지 만들어 내는 과목이다.
과 동기,후배와 나까지 총 5명이서 이 과목을 수강했고, 프로젝트 완성까지 3주라는 시간이 주어졌다.
3주라는 기간이 너무 애매해서 다 같이 머리를 꽁꽁 싸매고 어떤 프로젝트를 해볼까 고민하다가 한 후배가 아이디어를 냈다.
학생들의 졸업요건을 자동으로 검사해주는 사이트를 만들어보자는 것이다.

여기서 오!를 외쳤다. 학생들이 필요성을 느끼던 서비스였기 때문이다.

우리 학교는 졸업요건이 매우 까다롭다. (다른 학교보다 우리학교가 복잡한 편이다.. ㅋㅋ..)
졸업하기 위해서 체크해야하는 영역으로 전공필수, 전공선택, 교양필수, 기타 등등… 총 8개나 된다;; 😱
각 영역마다 기준 학점을 채워야하고, 또 영역마다 들어야하는 필수과목들도 정해져 있다.

그 뿐만 아니라 특정 영역의 경우엔 무슨 선택영역(?)도 세 가지 이상을 채워야 하는 등 어려운 하위 기준들이 많다.
근데 가장 불편한 것은 나의 이수현황을 확인할 수 있는 사이트가 영역마다 달라서 일일히 찾아봐야 한다는 것이다.

상황이 이렇다 보니 4학년을 마치고 졸업심사에서 자신도 몰랐던 조건이 부족해 졸업이 미뤄지는 경우가 많이 발생한다.
별것도 아닌것 때문에 졸업을 못한다니… 이게 얼마나 억울한 일인가?

그래서 5명 모두 이거다!라고 생각하고 바로 프로젝트에 착수하게 된다.


프로젝트 설계

우선 학교 커뮤니티에 설문을 돌려서 수요조사를 진행했다.

구글폼 설문 결과

image

설문 결과를 보고 필요한 서비스라는 확신이 들게된다.

그 다음은 아이디어를 마구 던지면서 학생들이 불편함을 겪는 기능들을 구체적으로 생각해보았다.
그렇게 완성된 초기 설계는 다음과 같았다.

  1. 복잡한 수강편람을 뒤져가며 직접 졸업요건을 계산해야함 -> 검사 알고리즘 구현
  2. 여기저기 흩어져 있는 나의 이수현황을 일일히 찾아야함 -> 크롤링으로 한번에 모아주기
  3. 다음 학기에 뭐 듣지? -> 머신러닝을 통한 강의 추천

이제 원하는 기능을 구현하기 위해 어떤 기술을 쓸지 선택해야되는데…


새싹 개발자

프로젝트 당시엔 3학년을 마친 후 겨울방학이었다.
그때까지만 해도 팀원 모두가 웹사이트 하나 제대로 만들어 본 적 없는 새싹 개발자들이었다.

그래서 어떤 기술이나 프레임워크를 선택해야할지 잘 몰랐다.
우선 머신러닝을 파이썬으로 할 것이니 파이썬 기반 프레임워크인 Flask와 Django가 후보에 올랐다.
근데 별 이유 없이 둘 중 Django가 초보자가 사용하기 좀 더 쉽다는 글을 보고 Django를 선택해 개발을 시작하게 된다.

머리박기

개발은 쉽지만은 않았다. 다들 처음 겪어보는 MTV 패턴과 같은 프레임워크의 규칙을 공부해야 했다.
하지만 이때까진 시간에 쫓겨 동작원리도 모른 채 ‘사용법’만 익혀 무작정 구현했다.

게다가 당시 merge, rebase, PR 등 협업을 위한 Git 사용법을 전혀 몰랐기에 그저 커밋 용도로만 사용했다.
지속적 통합을 하지 않고 머지데이를 정해서 다같이 모여 confict를 해결하는… 원시적인 방법으로 협업했다.

그저 머리박기식 개발이었지만, 지금 생각해보니 이런 불편한 경험들이 모두 성장을 위한 발판이 되었던 것 같다.
잘못된 방식을 경험해봤기에 다시 그 길을 가지 않을 수 있는 것이다.

개발의 재미

어느정도 기능이 완성되어 테스트가 필요한 시점이 오게 됐는데, 저학년들은 아는 사람이 없어 테스트를 하지 못했다. (아싸였다)
그래서 과실에서 대가타다가 후배가 들어오면 한번 검사해보라고 계속 영업을 했고, 여러명이 테스트를 해줬다.

이 때가 내가 개발한 서비스를 다른 사람이 사용하는 순간이었다.
검사 결과는 꽤나 정확했고, 검사해본 사람들은 신기해하고 정말 유용하다고 칭찬을 해줬다.

이 경험이 엄청난 동기부여가 됐고, 처음으로 개발에 재미를 느꼈다.
내 서비스를 누군가 사용하고 도움을 받는다는 것의 성취감이 정말 컸던 것 같다.
이때부터 난 이 프로젝트에 애정을 가지게 된다 ㅋㅋㅋ

완성

밤샘 코딩하던 추억의 공간

시간은 흘러흘러 3주가 지나간다.
막판엔 시간이 부족해서 다같이 모여 밤까지 새가며 코딩한 결과, 어느정도 동작하는 웹사이트가 탄생하게 된다.

  1. 사용자가 학교 ID/PW 입력
  2. 학교 성적 사이트와 다른 졸업요건 사이트들을 크롤링 후 사용자의 이수 정보를 취합
  3. 저장해놓은 졸업요건과 비교하여 검사
  4. 머신러닝 후 강의 추천

사용자가 학교 아이디와 비밀번호만 입력하면 자동으로 모든 것을 검사해주는 목표하고자 했던 기능은 완성했다.
하지만 야속하게도 3주라는 시간은 짧았고, 배포까지는 어림도 없었다.

또한 검사 가능한 학과가 우리 학과 단 하나 뿐인… 데모 수준으로 프로젝트가 마무리된다.

데모 버전 홈페이지 (추억)

image


끝까지 간다

팀 프로젝트의 결과물은 개발 기간이 끝나면 잊혀지기 마련이다.

하지만 난 여기서 끝내지 않고 전교생이 검사 가능한 서비스를 만들어보고 싶었다.
구현하기만 하면 쓰지 않을 이유가 없는 서비스였기 때문에 사용자는 이미 확보되어 있다고 생각했다.

그렇게 나는 혼자 개발을 이어나갔다. 과제로 하는 수동적인 코딩이 아닌, 자발적인 코딩을 하게 된 것이다.
우선 기존 코드의 미흡했던 부분을 고쳤다. 미처 고치지 못한 버그들을 수정하고, 다른 팀원이 작성한 코드에 주석을 달면서 이해하고, 프론트엔드도 직접 디자인하면서 손을 봤다.
이젠 많은 사람들에게 내 서비스를 선보인다고 생각하니, 어느 부분 하나 대충 할 수가 없었다.
악의적인 사용자가 할 행동을 예상하여 검증로직을 추가하는 등 모든 부분을 꼼꼼하게 체크했다.

그리고 한번에 전교생을 대상으로 배포하기엔 조금 쫄려서(?) 일단 소프트웨어융합 단과대학 6개학과를 대상으로 1차배포하는 것을 목표로 세웠다. 수강편람을 뒤져가며 다른 학과의 졸업요건까지 조사해 DB에 기준을 채워넣었다. 이게 리얼 노가다 작업이고 시간이 오래걸렸지만, 사람들이 서비스를 사용하는 걸 상상하며 악으로 깡으로 버텼다.

첫 배포

어느정도 준비가 되었다고 생각이 들었을 때 드디어 처음으로 배포를 공부했다.
그 땐 정말 아무것도 몰랐고 그냥 구글에 ‘Django 배포하기’를 검색해 나오는 블로그들을 싹 다 본 것 같다.
처음으로 AWS에 가입하고, Linux 문법을 공부하고, nginx도 써보고, 도메인을 붙여보는 등 무작정 따라했다.

그때부터 내가 적용했던 것들은 모두 기록하고 싶어서 개발일지를 썼다.
그렇게 처음으로 클라우드 환경에 올라간 내 사이트를 봤을 때의 감정은… 이루 말할 수가 없었다.
(너무 신나서 동기들한테 동네방네 자랑했었다 ㅋㅋㅋ)

잘 동작하는 것을 확인한 후 커뮤니티에 달려가서 홍보를 했다.
생각보다 많은 사람들이 사용했고, 5시간만에 150명 정도가 접속했다.
싱글벙글하며 모니터링하고 있던 와중 문제가 발생하게 된다…

민감정보 노출한 썰

흑역사

홍보글을 올리면서 깃허브 주소도 함께 올렸었는데, 커뮤니티 사람들이 급하게 DB 정보가 노출된 것을 알려줬다.
자칫하면 사용자들의 정보가 모두 해킹당할 수도 있었던 것이다.

당시엔 초보 개발자였기 때문에 민감정보를 노출해서는 안된다는 걸 전혀 몰랐고, 급하게 레포지토리를 Private으로 변경했다.
근데 커밋 히스토리에 정보가 다 남겨져 있었기에… 그냥 레포지토리를 초기화 시켜버렸다.
그리고 DB 정보를 다 수정 후 .gitignore로 모두 숨겨 다시 배포했다. 커밋 백개 정도를 날려먹어서 슬퍼했던 기억이 난다 😇

그리고 https를 적용하라는 조언도 들었다. 나는 당연히 그게 뭔지 몰랐었고 https에 대해서 공부했다.
지금 생각하면 사용자 정보를 입력받는 서비스에서 보안 레이어는 필수였고, 나중에 Route53을 사용해서 적용시켰다.

(그 당시 내게 조언해줬던 착한 선배 개발자들에게 다시 한번 감사함을 느낀다!)

IP 차단당한 썰

사용자가 150명 쯔음이 될때 갑자기 서버에 오류가 생겼다. 학교 성적 홈페이지 크롤링이 차단된 것이었다.
이게 뭔일인가 싶어서 로컬환경에서 테스트했을 땐 잘되고, 원격서버에서 크롤링했을 땐 IP가 차단됐다는 메시지를 뱉었다.

그렇다… 원격 서버의 동일한 IP로 홈페이지에 150회 이상 접속하니 악의적 접근이라 생각해 해당 IP를 차단해버린 것이다.
배포 첫날인데 바로 밴을 먹여버리니 이 때의 상실감이 너무 컸던 것 같다.

크롤링에도 허가가 필요하다는 것을 이 때 알았고, 나는 전산실에 메일을 보낸다.

이후 아래와 같은 답변이 오게 된다.

전산실 답변

답장을 받고 좀 허탈했다. 열심히 만든 프로그램을 중단하라니…
물론 학교 성적 사이트는 휴학, 제적 등 많은 치명적인 기능이 있기에 이런 우회적인 접속을 차단하는게 당연하다고 생각했다.

포기못해

하지만 나는 여기서 포기할 수 없었다.
반드시 전교생을 대상으로 배포해서 학교의 전설적인 개발자가 되고 싶었다.

기존엔 두개의 사이트를 크롤링했었다.
성적 사이트에서는 성적표 엑셀 + 영어인증 여부를 가져오고, 독서인증 사이트에서는 인증현황을 가져오는 방식이다.
여기서 ID/PW만 입력 후 검사해주는 방식을 사용자가 직접 성적표 엑셀 + 영어점수를 입력하도록 하면 성적 사이트를 크롤링하지 않아도 됐다.

이 시점부터 기존의 모든 기능을 갈아 엎게 된다.


Version 2.0.0

많은 기능을 바꿔야했기에 버전업을 하기로 생각했다.
버전업을 하는 김에 다른 기능도 추가해야겠다고 생각하고, 또 한달동안 개발을 진행하게 된다.

우선 학생인증, 회원가입, 로그인과 같은 기본 기능을 추가했다.
그리고 회원 기능이 추가됐으니, 직접 미래에 들을 강의를 추가해서 검사해볼 수 있는 커스텀 기능도 추가할 수 있었다.
마지막으로 사용자들이 많이 들은 강의 통계를 뽑아낼수도 있으니 꿀교양을 추천해주는 기능도 추가했다.

추천 알고리즘 수정

그렇게 개발하고 있었는데, 이전보다 검사 속도가 느려진 느낌을 받았다.
프로젝트 초기에는 1초 이내로 검사가 완료됐는데, 사용자가 생기고 나서부터 갑자기 2~3초씩 걸렸다.
알고보니 머신러닝 강의추천 기능에서 검사를 할때마다 머신러닝이 돌아가기 때문에 발생한 현상이었다.
고작 백여명의 사용자 데이터가 추가됐다고 시간이 배로 뛰어버렸으니, 사용자가 천명, 이천명이 된다면?

나는 고민에 빠진다. 주기적으로 모델을 학습시키고 완성된 모델로 검사를 해야하는 것인가?
인공지능을 운영하는 방법에는 자신이 없었고, 사실 몇백, 몇천명의 데이터로 정확도 있는 모델을 만들기도 어려웠다.
따라서 그냥 학생들이 많이 들은 강의순으로 추천하도록 알고리즘을 변경하는 선택을 했다.

최종 배포

기능이 완성되고 마지막으로 모든 학과의 졸업요건을 조사해서 DB에 넣는 과정만 남게됐다.
여기서 정말 포기하고 싶었다. 68개 학과 7개 학번의 졸업요건은 각자 다르고 이해하기도 어려웠다.

기존 검사 알고리즘을 변경해야하는 조건도 있었고, 수강편람만 읽고 알기 힘든 기준도 있었다.
진짜 배포만 바라보면서 악착같이 학교 커뮤니티와 학적과에 물어보며 조사했고, 결국 모든 졸업요건을 완성시켰다.

그렇게 2021년 7월 26일 최종배포를 완료하고 커뮤니티에 홍보를 하게 된다.

반응

당시 홍보글

image

커뮤니티의 반응은 생각보다 뜨거웠다! 홍보 게시글은 바로 Best 게시글로 선정됐다.
난생 처음 겪어보는 관심이라 기분이 좋았던 기억이 난다. ㅋㅋㅋ

급하게 찍었던 동시접속자 수

동접자

동시접속자 수는 142명까지 기록했고, 일일 방문자수는 900명까지 기록했다.
근데 동접자 백명이라 해도 서버에 문제가 생기진 않았다. (아무일도 없는 것처럼 평온했다)

감사한 댓글들

afdse

가장 뿌듯했던 건 댓글들이었다. 그 동안의 삽질을 모두 보상받는 기분이었다.
내가 만든 서비스가 누군가에게 도움이 된다는게 너무 기쁘고 행복했다.
이전까진 내가 개발에 흥미가 없다고 생각했는데, 무언가 시도하지 않았기에 흥미가 생길수 없었던 것 뿐이었다.
이 경험을 통해 나는 개발의 매력을 느끼고 서비스 개발자를 꿈꾸게 되었다.

세종대 홍보과 게시물

afdse

그리고 교내 홍보과와 인터뷰도 하고 홍보 게시글도 올라가게 되었다.
이 때 내가 뭐라도 된것 같았다. (사실은 걍 뉴비 개발자였을 뿐…ㅎ)


1년간의 운영

아무리 꼼꼼하게 개발한다 해도 수많은 버그들을 피해갈 수 없었다.
따라서 운영을 위해선 사용자와의 소통창구가 필요했고, 나는 구글폼을 사용해 문제 발생시 피드백을 보낼 수 있도록 했다.

피드백용 구글폼

image

1년동안 생각보다 많은 피드백을 받았다. 지금까지 146명이나 피드백을 주었다.
사용자의 적극적인 피드백 덕분에 서비스의 문제점을 빠르게 파악하고 꾸준히 발전시켜 나갈 수 있었다.

리팩토링

앞서 말했듯 새싹 개발자일 때 시작했던 프로젝트인 만큼 결과물이 완벽하지 않았다.
가장 심각했던건 veiw.py라는 하나의 파일에 서버의 모든 로직이 포함되어 있어 코드가 거의 3천줄이 넘어간다는 것이었다.
유지보수하면서 이건 너무 불편했기에 함수를 기능별로 분리하여 결합도를 조금이나마 낮췄다.

하지만 레거시 코드는 생각보다 강력했다.
클린코드를 몰랐기에 의미를 알 수 없는 코드에 주석을 남발했고, OOP는 전혀 사용되지 않았다.
유지보수성이 너무 떨어져서 뒤늦게 이걸 해결하자니 거의 다시 시작하는 수준이었기에 아직까지 모두 해결하지 못했다 ㅜㅜ
모든 개발자들이 왜 클린코드와 객체지향을 강조하는지 뼈저리게 느낀 경험이 되었다.

서버 이전

1년간의 운영끝에 AWS EC2 프리티어의 수명은 다하게 되었고, 새로운 서버로 이전을 해야했다.
그동안 CI/CD 개념을 몰라 매번 수동으로 배포하고… 도메인을 적용하는 방법도 몰랐기에 매달 돈 내가면서 Route53을 썼었다.

하지만 1년이 지나고 배포실력이 성장했기에, 서버 이전을 하면서 배포 구조를 싹 바꿔야겠다고 마음 먹었다.
그렇게 변경된 아키텍처는 아래와 같다.

image

Spring 프로젝트 CI/CD하는 것보다 Django가 훨씬 어려워서 삽질 좀 했지만 결국 해내긴 했다.

수동배포하다가 자동배포되니까 진짜 살것같았고, 무엇보다 Route53 기능을 nginx로 대체해서 돈도 안내고 http2도 적용했다.
그리고 매일 정각마다 사용자 통계를 보내주는 기능을 추가했는데, 운영에 큰 도움이 되었다.

현재

image

1년간 운영해온 결과, 현재는 사용자가 4300명을 넘었다. 전교생의 40%가 사용하고 있는 것이다.
평소 일일 방문자수는 3~50명이고, 누적 방문자 수는 약 27,000명이 되었다.
누군가에게는 적은 수일 수 있지만 내겐 정말 큰 숫자다. 꾸준히 사용해주는 학생들에게 감사한 마음을 남긴다.


마무리

PleaseGraduate는 짧은 개발인생 최대 업적이라고 생각한다.
개발에 재미를 느끼게 해줬고, 나의 터닝포인트가 된 효자같은 프로젝트이기 때문이다.

그래서 꼭 한번 회고하고 싶었다. (막상 하고 나니까 너무 길어지긴 했다;;)

내 멘토님은 개발자의 길을 걷기 위해선 개발이 재밌어야 한다고 항상 말씀하셨다.

나도 전적으로 이 말에 동감한다. 개발에 재미를 느끼면 성장은 자연스레 따라오기 때문이다.
그리고 일에 재미가 없으면 전문직에서 어떻게 살아남겠는가.
자신이 만들어보고 싶은 것을 만들고, 그걸 사용하는 사람이 있다면 반드시 동기부여를 얻을 수 있다.
나는 그것을 추진력 삼아 앞으로 나아가고자 한다.