[2021.09.13 ~ 2021.09.17]
드디어 첫 프로젝트가 끝이 났다
지금까지 JAVA를 공부해서 Spring으로 프로젝트를 해왔었는데
flask로 프로젝트를 한 건 처음이다
첫 날에 계획했던 화면과 나름 비슷하게 구현이 되었다
https://velog.io/@donggun130/hanghae993%EA%B8%B0-15%EC%A1%B0
[프로젝트 이름 및 사용 기술]
이름은 '연수구 가치봉사' 이다!
팀원이 인천광역시 연수구에 살고 있기도 하고
연수구에서 할 수 있는 봉사활동이 그렇게 많지 않아서 크롤링하기 적당해보였다
1~3기 통해서 봉사를 주제로 진행한 프로젝트가 없어서 이걸로 선택했다
사용한 기술은 Python3.8, flask, bs4, requests, pymongo, pyJWT 1.7.1, charset-nomalizer 2.0.4 이다
[프로젝트 설명]
1. 로그인 페이지
회원가입을 통해 계정을 새로 만들고, 로그인을 한다
2. 목록 조회 페이지
인천 연수구에서 할 수 있는 봉사활동 목록을 보여준다
하트를 눌러 좋아요를 표시할 수 있고, 취소도 할 수 있다
좋아요를 표시하면 마이페이지에서 확인 가능하다
3. 상세 페이지
봉사활동의 제목을 눌러 상세내용을 확인한다
4. 마이페이지
마이페이지에서 좋아요를 누른 봉사활동 정보가 출력된다
하트를 눌러 좋아요 취소를 하면 봉사예정 부분에서 사라진다
완료하기 버튼을 눌러 봉사 완료 부분으로 이동한다
현재까지 봉사를 완료한 총 시간을 확인할 수 있다
소스코드: https://github.com/Ldonggun/hanghae99-3-15
5. 구현한 기능
기능 | Method | URL | request | response |
로그인 페이지 이동 | GET | / | ||
목록 조회 페이지 이동 | GET | /mainpage | 토큰["id"] | 봉사활동 정보 리스트 |
목록 조회 페이지 좋아요 누르기 |
POST | /mainpage/like | {"volunteer_no": volunteer_no, "subject": subject, "recruit_period": recruit_period, "hour": hour, "href": href} |
메시지 "좋아요를 눌렀습니다!" |
목록 조회 페이지 좋아요 취소 |
POST | /mainpage/cancel | {"volunteer_no": volunteer_no} | 메시지 "좋아요를 취소했습니다!" |
마이페이지 이동 | GET | /mypage | 토큰["id"] | 봉사활동 정보 리스트, 총 봉사시간, 마감일로부터 남은 날 |
마이페이지 좋아요 취소 | POST | /mypage/delete | {"volunteer_no": volunteer_no} | 메시지 "봉사활동 삭제됨!" |
수행한 봉사활동 완료 | POST | /mypage/done | {"volunteer_no": volunteer_no} | 메시지 "봉사활동 완료됨!" |
회원가입 | POST | /sign_up/save | {"username_give": username, "password_give": password} |
{'result': 'success'} |
아이디 중복확인 | POST | /sign_up/check_dup | {"username_give": username} | {'result': 'success', 'exists': exists} |
로그인 | POST | /sign_in | {"username_give": username, "password_give": password} |
{'result': 'success', 'msg': '연결됨.'} |
[어려웠던 점]
1. 1365 페이지가 크롤링이 안 된다
1365의 봉사활동 조회 페이지에서 지역을 선택하는 부분이 있는데
인천광역시 -> 연수구 로 선택을 한 상태에서 URL을 가져와 크롤링을 했다
근데 전 지역을 조회한 상태에서 크롤링을 해오는 것이였다
계속 생각해보니까 쿼리스트링이 생각났다
쿼리스트링으로 인천광역시, 연수구, 현재 페이지 에 대한 데이터를 같이 보냈더니 해결되었다
2. 인천광역시 연수구에 대한 봉사활동들을 조회했는데 페이지가 여러개다
총 페이지 개수를 계산하려면 인천광역시 연수구에 있는 봉사활동 총 개수가 필요했다
1365 페이지에서 먼저 총 개수를 크롤링해온 뒤 한 페이지에서 확인할 수 있는 봉사활동 개수(10개)로 나누어
총 페이지 개수를 계산했다
정확히는 올림 함수를 썼다
page_count = math.ceil(page_count / 10)
그래서! 총 페이지 개수를 구한 뒤 for문을 사용했다
쿼리스트링의 cPage의 값을 페이지 개수대로 반복문으로 바꿔가며 그 페이지를 크롤링했다
3. 1365 페이지에 있는 데이터들을 가져오는 방법
이건 한번 해봤기 때문에 다행히도 크게 어렵지 않았다
크롬의 개발자도구의 'copy selector' 기능을 이용해 크롤링 대상 태그의 선택자를 가져왔다
크롤링 대상의 태그를 전체 다 가져와 태그를 걸러내 데이터만 뽑아내고, 필요한 형태로 가공했다
4. 크롤링 속도가 너무 느리다
심각하게 너무 느렸다..누가 웹 페이지를 1분 이상 기다리겠는가..ㅠㅠ
무조건 개선해야했다
멘토님과의 1:1 상담이 있었는데, 그 때 '크롤링 성능 개선'이라고 검색해보라고 알려주셨다
구글링을 해서 아래의 페이지를 찾았다
https://geniyong.github.io/2019/11/06/Python-Crawler-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0.html
멀티쓰레드를 이용하는 것이다
해야 할 일을 n명이 나눠가져서 하는 원리이다
그래서 1분 넘게 걸리는 것을 17초 정도로 줄였다
내 방 컴퓨터가 인터넷 상태가 좋지 않아 느린 편이다
인터넷 상태가 좋다면 이것보다 더 빠를 것이다
5. 마이페이지에서 목록 조회 페이지로 이동했을 때, 데이터가 중복되어 화면에 보인다
코드를 아무리 이래저래 바꿔봐도 원인을 못 찾았다
그래서 봉사활동 정보들이 담겨있는 리스트에서 중복된 데이터는 삭제했다
하지만 프로젝트를 완성하고 다시 생각해보니 크롤링할 때마다 데이터를 담고있는 리스트를
초기화해줘야했었다
초기화를 안한 상태로 계속 크롤링을 하니 중복되는 데이터가 있는 게 당연하지..
왜 그 당시에는 생각 못했을까..
6. 마이페이지에서 계정마다 좋아요 누른 봉사활동 목록을 보여주는 것을 다르게 해야 한다
기본적인 기능을 다 구현하고 보니, 큰 비중을 차지하는 기능을 넣지 않았던 것이다
그래서 로그인을 할 때 브라우저에 토큰을 저장하는데, 그 토큰에서 아이디값을 가져오는 게 필요했다
나는 JWT를 전혀 몰랐다. 공부를 해보니까
JWT는 JSON Web Token의 줄임말로, JSON 객체를 사용해 정보를 안정성 있게 전달하는 웹표준이고,
사용자가 로그인하면 서버에서 회원임을 인증하는 토큰을 넘겨줌으로써
이후 회원만 접근할 수 있는 서비스 영역에서 신분을 확인하는 데 쓰일 수 있다고 한다.
https://tansfil.tistory.com/58?category=255594
위의 글은 http 요청에서부터 cookie/session ~ JWT 내용까지 있어 자세해서 좋다
JWT에 대한 내용만 있는건 https://velopert.com/2389
JWT는 "." 구분자로 헤더(header), 내용(payload), 서명(signature) 세 부분으로 되어있다
그 중 payload에 아이디와 암호화된 비밀번호를 저장해서
목록 조회 페이지로 이동할 때 payload에서 아이디값을 가져왔다
좋아요를 눌러 DB에 봉사활동 정보를 저장할 때 좋아요를 누른 계정 아이디도 같이 저장했다
마이페이지에서 좋아요를 누른 봉사활동들을 DB에서 조회할 때
현재 로그인한 계정이 좋아요를 누른 것을 조회해오도록 했다
7. 1365 페이지에서 모집 마감한 봉사활동을 마이페이지에서 안 떠야 한다
이 부분은 메인페이지에서 크롤링해온 데이터를 가져와
DB에 저장되어있는 데이터와 비교를 했다
크롤링해온 봉사활동 목록에서
DB에 저장되어있는 봉사활동이 없으면 DB에서 삭제했다
마감된 봉사활동은 크롤링해온 목록에 없을거기 때문에
이런 로직으로 만들었다
마감일이 정해져 있어도 이미 모집되었기 때문에 게시물을 올린 사람이 게시물을 내릴 수도 있다
이 경우를 생각해서 위의 로직으로 짰다
[배운 것]
협업하는 과정을 경험했다
특히 Github에 대해 익숙해지기 위해 다같이 공부했다
Flask라는 프레임워크를 배웠다
Django를 잠깐 써본 적이 있는데, 나한테는 Flask가 더 쉬웠다
뭔가 Spring 프레임워크랑 비슷한 느낌이라 좀 더 익숙하게 사용했던 것 같다
그리고 MongoDB라는 것을 처음 사용해 봤다
이제 보니까 MongoDB는 NoSQL이였다
NoSQL은 JSON 형태로 데이터가 저장되는 것 같았다
Oracle과 MySQL과 다른 형태였다
[아쉬웠던 것]
Github를 조금이라도 잘 다뤘더라면 시간을 좀 더 효율적으로 사용했지 않았을까 싶다
그리고 프로젝트에 DB를 제대로 사용하지 못했던 것 같다
마이페이지에서만 사용되고, 메인페이지에서는 크롤링해온 데이터로 보여주기 때문에
데이터베이스가 거의 쓰이지 않았다
[소감]
처음 만난 사람들과 바로 프로젝트를 시작해야되니 너무 어색했다
숨 막힐 정도로 어색했는데 그래도 어찌어찌 진행되었다
우리 조는 git을 제대로 써 본 사람이 없어서
코드를 카톡으로 주고받으면서 프로젝트를 했다
프로젝트를 어느정도 마무리 한 다음에는 다같이 git에 대해 공부했다
github에서 clone하는 것 부터 commit, push하는 것 까지 공부하고 각자 돌아가면서 이 과정을 직접 해봤다
같이 공부해나가니까 머리에 더 잘 들어왔다
참 좋은 경험이였다
'항해99 3기' 카테고리의 다른 글
[TIL] 2021.09.25 - 개인 프로젝트 요구 기능 완성 (0) | 2021.09.25 |
---|---|
[TIL] 2021.09.24 - Spring 강의 마무리, 개인 프로젝트 시작 (0) | 2021.09.24 |
[TIL] 2021.09.23 - Spring 3-4주차 강의 듣기 (0) | 2021.09.23 |
[TIL] 2021.09.22 - Spring 강의 2주차 듣기 (0) | 2021.09.23 |
SpringBoot 에러) cannot deserialize from object value (0) | 2021.09.22 |