김로그 개발 잘 하고 싶다

성공학기 제작기


학교 수강신청현황 크롤링해서 간단한 웹서비스 만든 썰

전국의 대학생들이 모두 똑같을 것이다. 원하는 과목 수강신청에 모두 성공하면 곧 시작될 한 한기가 두근두근 기대하며 시간을 보낼것이고, 한 과목이라도 실패한다면 친구들한테 전체 수강신청 기간에 도와달라고 부탁하거나 곧 졸업하는 선배들한테 형 그거 저 주심 안 돼요ㅠㅠ 애걸하며 개강 첫 주를 누구보다 바쁘게 보낼것이다..

나도 딱 한 번 수강신청에 실패한 적이 있는데 4학년 1학기 수강신청 당일 늦잠 자버려서 한 과목도 수강신청을 못 했다. 수강신청 추가요청서를 열 장쯤 뽑아서 교수님 일일이 찾아뵙고 수강신청좀 부탁드려요 메일을 쓰며 시간을 보냈다. 학교가는 전날에는 혹시라도 교수님이 안 받아주시면 어쩌나 이러다가 졸업 못하는 거 아닌가? 계절학기는 듣기 싫은데… 별별 생각을 다하면서 잠을 설쳤다. 개강이 그리 설래지도 기쁘지도 않았다.

수강신청 실패로 인해 비극이 시작될 것이라는 사실을 잘 아는 학생들은 이런 일이 생기지 않게 하기 위해 학생들은 수강신청에 앞서 실패 피해를 최소화 하기 위해 플랜A, 플랜B 등 여러 전략을 세운다.적을 알고 나를 알면 백전백승이라고 했다. 학생들은 내가 들어야할 과목들은 정확하게 알고 있지만 안타깝게도 학생들이 수강신청에 앞서 전략을 세우는 데 필요한 정보를 얻기 정말 힘들다. 그냥 이렇게 됐으면 좋겠다는 막연한 기대 속에 잘되겠지…하며 신념에 기반한 수강신청 계획을 세운다.

학생들은 수강신청시 학교에서 제공하는 정보를 참고한다.

건국대학교(이하 우리 학교)는 학생들에게 몇가지 정보를 제공한다.

  • 종합강의시간표
    • 과목별 수강인원
    • 과목별 제한인원
  • 장바구니
    • 과목별 담은 인원 수
    • 과목별 해당 학년 수강인원
    • 과목별 해당 학년 과목 신청수

우리 학교(건국대학교)는 한 과목에 수강할 수 있는 학년의 비율이 정해져 있다. 1학년 수업이라면 전체 수강인원의 70%는 1학년이 들을 수 있고 나머지 학년은 각각 전체 수강인원의 10%씩 자리가 할당된다. 문제는 여기서 발생한다. 수강신청 전에 우리 학년 빈자리가 몇 개 있나 알 수 있으면 좋겠지만, 안타깝게도 ㅠㅠ 수강 장바구니 기간이 끝나면 이 정보를 알 방법이 없다. 결국에는 종합강의시간표에 나와 있는 다른 학년 빈자리가 희석된 전체 빈자리 수만 보고 ‘어? 자리 많이 남았네! 들을 수 있겠다!‘안도하며 수강신청했다가 결국 망하게 된다. 흐어엉 물론 이런 경우는 드물다

예1

어찌어찌 하다보니 5학년이 되었고 마지막 학기 수강신청을 기다리며 밤을 새우다가 학년별로 빈자리를 볼 수 있으면 좋겠다고 생각해서 한번 만들어 보게 되었다.

위 그림은 컴퓨터의 이해라는 교양과목(1460)의 4학년 수강신청 현황인데 장바구니 기간에 링크를 복사해 놓았다.

주소는 아래와 같다. http://kupis.konkuk.ac.kr/sugang/acd/cour/aply/CourBasketInwonInq.jsp?ltYy=2016&ltShtm=B01011&sbjtId=1460&promShyr=4&fg=B

주소를 조금만 자세히 바라보면 전달하는 매개변수들은 아래와 같다.

  • ltYy : 수강연도
  • ltShtm : 모르겠음
  • sbjtId : 강의코드
  • promShyr : 아마도 학년
  • fg : 모르겠음

강의코드와 학년을 바꾸니 원하는 정보를 얻을 수 있었다. 웹으로 만들기 전에 어떤 언어와 어떤 웹프레임 워크를 쓸까 잠깐 고민했는데 최근까지 python으로 코딩할 일이 많아서 python + flask로 하려고 했으나 나중에 서버에 올릴 때 조금 귀찮을까 봐 멋쟁이 사자처럼 3기 때 배운 ruby on rails를 복습할 겸 ruby on rails로 개발하기로 했다. 배포는 c9.io에서 하는걸로 하고 꼬딩 고고

이때까지만 해도 주변 몇 사람한테만 보여주고 우아앙 하려고 했다. 디자인 같은 거 신경쓸 시간이 없었기도 하고 당장 내일이 수강신청인데 완성도 있게 만들 자신 없었다.

일단 c9.io에 프로젝트를 만들고 위 주소를 크롤링했다. 소스코드를 보니 테이블의 <td> 태그의 table_bg_white클래스를 가진 문자열만 가지고 오는것이 첫 목표였다. ruby에는 Nokogiri라는 훌륭한 젬이 있기 때문에 이 젬을 사용해서 크롤링했다.

예1

우아앙 글씨가 깨진다. 물론 가장 처음에 크롤링한 결과라서 숫자는 없지만 이후에 td만을 긁어 왔을 때는 한글로 된 텍스트는 모두 깨지고 숫자는 남아있어서 숫자만 가지고 왔다. 보통 utf-8로 되어있는 문자열을 크롤링한 경험이 있어서 처음에 이 결과를 봤을때 무척당황했던 기억이 난다. 소스코드를 살펴보니 KSC5601라는 걸로 인코딩 되어있었는데 아무리 구글링해도 KSC5601에서 utf-8로 바꾸는 내용이 있긴있던데 이해를 잘 못해서 넘어갔다.

나중에 시간이 지나서 알게된 사실이지만

KSC5601 한글 완성형 표준(한글 2,350자 표현) 한국공업표준 정보처리분야(C)의 5601번 표준안

KSC5636 영문자에 대한 표준 한국공업표준 정보처리분야(C)의 5636번 표준안 기존 ASCII Code에서 역슬래쉬()를 원() 표시로 대체

EUC-KR Bell Laboratories에서 유닉스 상에서 영문자 이외의 문자를 지원하기 위해 제안한 확장 유닉스 코드(Extend UNIX Code)중 한글 인코딩 방식 영문은 KSC5636으로 처리하고 한글은 KSC5601로 처리 EUC-KR = KSC5601 + KSC5636

출처 http://okky.kr/article/44287

라고 한다.

Nokogiri는 기본설정으로 UTF-8 문자열로 저장을 하는데 아마 이 과정에서 깨지지 않았나 생각한다. Nokogiri:encoding문서에 나온데로 EUR-KR로 엔코딩하니 깨지지 않더라… 나중에 python이랑 beautiful soup4로 크롤링해봤는데 python에서는 알아서 인코딩을 해주는지 깨지지 않았다. 왜 그런걸까

사실 이게 이번 서비스를 만드는 데 필요한 정보 전부이다….

일단은 원하는 정보는 가져오는데 성공해서 종합강의시간표 소스를 봤다.

종합강의시간표 http://kupis.konkuk.ac.kr/sugang/acd/cour/time/SeoulTimetableInfo.jsp

아마도 수강신청 기간에 가장 많이 보는 페이지일 것이다. 매년 이 페이지를 사용하면서 느낀 불편한 점은 과목코드, 과목명으로 수업을 찾을 때 항상 년 도와 학기를 입력해줘야 한다는 점 어짜피 해당연도 해당 학기만 볼 건데 ㅂㄷㅂㄷ, 그리고 교양과목 찾으려면 너무 많은 입력이 필요하다는 점이다. 사실 이 부분에 대해서 좀 개선을 해보려고 했지만 다음 학기에 서비스를 만들어서 런칭할 때 해보려고 한다. 졸려서 포기함

소스코드를 보면 변수에 대한 정보를 알 수 있는데 정리하면

  • ltYy 년도 2016, 2017 등등
  • ltShtm 학기
    • B01011 1학기
    • B01012 2학기
    • B01014 하계 계절수업
    • B01015 동계 계절수업
  • openSust 학과 코드
    • 006751 전체대학
    • 105371 전자공학부
    • 나머지 소스코드 참조
  • pobtDiv구분
    • B04044 전필
    • B04045 전선
    • B0404O 전기
    • B04043 지교
    • B04046 일선
    • B04047 교직
    • B0404P 기교
    • B0404Y 핵교
    • B0404Z 일교
    • B04054 심교
    • ALL 전체

교양과목 개편에 따라 핵교가 없어졌다고 한다. 아마 이전 수업 조회용으로 남겨놓은 듯

  • cultCorsFld 선택교양 구분
    • B52001 외국어
    • B52002 글쓰기
    • 나머지 소스코드참조

가 된다. 이를 바탕으로 2016년도 1학기 전자공학부 전필과목을 조회하려면

http://kupis.konkuk.ac.kr/sugang/acd/cour/time/SeoulTimetableInfo.jsp?ltYy=2016&ltShtm=B01011&openSust=105371&pobtDiv=B04044 를 입력하면 된다.

보통 수강신청이 망하면 자신이 가진 과목과 원하는 과목을 교환한다. 사이트를 방문한 사람들끼리 이런 정보를 주고 받으면 좋을 것 같아서 disqus를 달았다.


첫날 주변 친구들에게만 배포를 했는데 반응이 꽤 좋아서 우리학교 커뮤니티인 ku-kung이랑 DC건국대학교 갤러리, 우리학교 전자공학부 클럽, 내 페이스북 타임라인에 링크를 올렸다. 늦은시간에 올린지라 사람들이 많이 오려나 싶었지만 4학년 수강신청 당일 총 이용자수는 217명에 달했다.

이후에 과 동기인 준현이가 자기 블로그에 링크를 달아주면서 Naver를 통해 유입도 많이 되었다. google analytic를 이용하면 웹사이트 유입경로를 확인 할 수 있는데 2학년 수강신청 때 부터 기이한 현상이 일어났다. direct유입경로가 급증했는데 도메인을 따로 구입하지 않은 상태여서 direct로 접근할 일이 거의 없다고 생각했다. 주변에 들리는 이야기가 링크가 카카오톡을 통해서 퍼지게 되었고 결과적으로 direct유입이 급증했다. 초반에는 desktop사용자가 많아 모바일뷰를 생각하지않고 메인페이지를 짯는데 시간이 지날수록 모바일과 데스크탑 이용자의 총 비율이 1:1에 근접했다.

예1

전교생이 약 17,000명이라고 할 때, 전교생의 20%가 넘는 학우들이 웹페이지를 찾아주었다. 지금도 생각하면 신기하다.


피드백

서비스는 전체수강신청 첫날인 목요일 오후에 종료하였다. 서비스를 종료하며 두가지 문항으로 설문을 받았다.

  • 좋은점은 무엇이었는지
  • 나쁜점은 무엇이었는지

좋은 점을 통해 왜 학생들이 이 서비스를 이용하게 되었지는지와 학교 시스템의 문제점을 알고싶었고 나쁜점을 통해서 추후에 희박하지만 이 서비스를 다시 런칭하게 될 때 반영되어야 할 사항들을 알고 싶었다.

좋은점

예1

원래 개발의도대로 학교 시스템상에서 학년별 자리를 볼 수 없는점을 해소했기 때문에 사용자들이 좋다고 평가해줬다. 운 좋게사용자의 니즈를 파악한듯. 마지막 답변에서 과목코드에 대한 강의계획서 링크를 만들어줬는데 이 기능이 편하다고 답변해 준 사용자가 있다. 세심한것 하나에도 사용자는 이에 대한 경험이 생긴다. ㅇㅇ…

나쁜점

예1

애초에 태생이 재미로 한 코딩이었고 여러 사항을 고려하지 않은채 기획도 없이 개발해서 야기된 문제들이 많았다. 예상한바대로 모바일뷰를 감안하지 않은것, 느렸던것, c9에 올려서 서버가 일정시간마다 내려간것 등등…

예상했지만 미리 고치지 않고 방치한 나를 비난해야 마땅하다.


문제점

  • c9.io 무료 계정을 이용해서 배포를 할 경우 다른 무료 사용자들의 이용을 위해서 주기적으로 서버를 내린다. 이 때문에 접속하지 못한 학생들이 많았다.
  • 전체 수강신청 기간에는 학년별 장바구니에 나와있는 정보를 보여주면 안될 것 같다.
    • 전체 빈자리와 정보가 다르게 보여지는 경우가 있었다.
  • 학교 서버가 뻗으면 같이 뻗는다.(크롤링 요청 응답없음)
  • 모바일 이용자가 많을줄 몰랐다.

  • Disqus로 과목교환하기를 만들었는데 전체이용자수에 비해 저조하지만 30개의 댓글이 달렸다.(이점은 뿌듯하다.)
    • 보통 과목을 교환할 때는 익명으로 하거나 비밀댓글로 카톡아이디 주고 받고하는데
    • disqus는 그런거 없다. 소셜로그인 얼굴이 뜬다.
    • 익명으로 하려면 이메일 인증 받아야한다.

전체 수강신청 때에는 반드시 수강신청현황을 크롤링해서 보여줘야한다.


느낀점

기술도 중요하고 코딩을 잘하는 것도 중요하지만 가장 중요한건 사람을 이해하고 원래 있던 서비스를 분석하는 능력이 아닐까 생각한다. 인문학 전공이 코딩을하면 무서워진다.

  • 자랑스럽게도 우리학교 수강신청 페이지는 IE 6.0에 최적화되어있다.

번외

수강신청 로그인 페이지 소스코드 view-source:http://kupis.konkuk.ac.kr/sugang/login/loginTop.jsp 를 보면 28행에 제적생에 대한 수강신청 불가 처리라는 내용이 있다. 주석상으로 2007년에 작성된 내용같은데 해당 학생들이 아직 학교에 다니고 있는지 아닌지 잘 모르겠지만 우리 학교 학생으로서 내 아이디가 다른 사람들에게 노출된다고 하니 마음이 아프다.


예1

도와준 친구 장준현, 유진욱

감사합니다.