플레이데이터 최종프로젝트를 마치고 나서 쓰는 회고록입니다. 역할 별로 글을 다 쓰면 너무 길어질 것 같아서, 제 파트 위주로 게시합니다! 더 궁금하신 사항이 있으시다면, 맨 하단에 git 주소를 참고해주세요!
1. 프로젝트 소개
서울시 발생 사고로 인한 혼잡도에 대한 관심 급증으로 인해서, 안전성과 여가·문화 생활을 결합한 종합 정보 제공 웹 서비스를 제공하고 싶었습니다. 따라서 저희 팀은 다양한 소스에서 온 데이터를 통합하고, 분석하고, 예측하는 일련의 과정을 웹서비스에 전부 담았습니다.
(1) 팀원별 역할
- 우상욱(팀장) : 데이터엔지니어링
- (1) 데이터베이스 설계 및 구축
- (2) 맛집, 명소 데이터 크롤링
- (3) Airflow 활용 운영 데이터 파이프라인 설계 및 구축
- (4) Aws Lambda 활용, 딥러닝 모델(Tensorflow)을 활용한 별점 업데이트 파이프라인 설계 및 구축
- (5) 데이터웨어하우스 설계 및 구축(Aws Redshift)
- (6) Superset 데이터 시각화 서버 구축 및 DB, DW 연동
- (7) 머신러닝 API 서버 구현(FastAPI)
- (8) Airflow 활용 ML 모델 자동화 배포 파이프라인 설계 및 구현
- (9) 로그 데이터 수집 및 가공 파이프라인 설계
- 김호영 : 데이터분석, 머신러닝
- (1) 데이터 가공/전처리/시각화
- (2) 지하철 승하차 인원, 장소 혼잡도 모델 설계 및 구축
- (3) Aws Lambda 활용, 딥러닝(Tensorflow) 모델을 활용한 별점 업데이트 파이프라인 설계 및 구축
- (4) 대시보드 구축 및 데이터 분석(Superset)
- (5) 머신러닝 API 서버 구현(FastAPI)
- (6) 웹 사이트 로그 데이터 가공 및 분석
- 민병창 : 백엔드
- (1) 데이터베이스 설계 및 연동
- (2) Spring Boot와 JWT를 활용한 회원가입/로그인 구현
- (3) Spring Boot Interceptor request 로그 데이터 수집 api 구현
- (4) Fast api loggers를 활용한 로그 데이터 수집 api 구현
- (5) 실시간 지도 기반 추천 알고리즘
- (6) AWS EC2를 활용한 spring, react 연동 및 배포
- (7) AWS IAM을 사용한 spring, s3 통신 구현
- 김민수 : 백엔드
- (1) Spring Boot와 React 개발환경 설정
- (2) Spring Boot를 활용한 실시간 혼잡도 api 구현
- (3) Spring Boot를 활용한 실시간 혼잡도 장소 api 구현
- (4) Spring Boot를 활용한 사용자 마이페이지 api 구현
- (5) AWS EC2를 활용한 spring, react 연동 및 배포
- 김경목 : 프론트엔드
- (1) 웹 디자인 설계 및 구현
- (2) 사용자 인터페이스 개발
- (3) 웹 애플리케이션 개발 환경 설정
- (4) Responsiveness(반응형) 개발
- (5) UI/UX 개선
- (6) 프론트엔드 프레임워크와 라이브러리 활용
- (7) 테스팅과 디버깅
(2) 사용 기술
- 개발 언어 : Python, Java, JavaScript, HTML, CSS
- 프론트엔드 : HTML, CSS, ReactJS
- 백엔드 : Spring, SpringBoot, FastAPI
- 데이터 : Tensorflow, Scikit-Learn, Airflow, Pandas, Superset
- 데이터베이스 : MySQL(AWS RDS), AWS Redshift
- 테스팅툴 : Selenium, Postman
- 클라우드 : AWS(EC2, S3, RDS, Redshift, ECR, Lambda)
- 데브옵스 : Git, GitHub, GitKraken, Docker
- 협업툴 : Notion, Slack, Canva
2. 시스템 구성도
웹 구현에는, React와 Spring boot를 사용했습니다. 머신러닝 전용 API 개발은, 파이썬 환경에서 진행하기 위해서 FastAPI를 활용하였습니다. 그리고 데이터 분석 대시보드를 웹에 임베딩하기 위해서, Superset을 사용했습니다. 이 외에 모든 데이터 파이프라인은 Airflow로 구현하였으며, 분석용 데이터를 수집하기 위해서, 데이터웨어하우스로 aws redshift를 활용했습니다.
3. ERD
장소를 기준으로 데이터베이스를 설계하고 구축했습니다. 워낙 다양한 소스에서 온 데이터가 많아서, 관계를 주기 위해, 지역구, 지하철역 등이 사용되었습니다. 또한 정규화를 통해서 데이터 중복을 방지하고, 데이터의 일관성 유지를 했습니다. 다만 백엔드에서 처리할 로직이 조금 복잡해졌어서, 개발 기간이 조금 더 길어진 면이 있었습니다. 분명히 장단점이 있었어서, 나중에 한번 더 프로젝트를 한다면, 모든 사항을 고려한 뒤에 반정규화할 테이블은 골라놓고 시작할 것 같기도 합니다. 또 프로젝트 하다가 알게 된 사항인데, 컬럼 값으로 배열이나, json을 쓰는 방식도 고려된다고 합니다.
4. 데이터 수집
망고 플레이트와, 한국관광공사의 데이터를 1차적으로 크롤링 했습니다. 크롤링할 대는 beautiful soup과 selenium을 모두 사용했는데, 한 링크에 있는 url을 모두 따는 작업을 selenium을 활용했습니다(동적 페이지). 그리고 해당 url에 들어갔을 때, beautiful soup을 활용해서 관련 정보를 크롤링했습니다(정적페이지).
웹사이트를 이쁘게 만드는건, 사진에 의해 좌지우지 된다는... 생각이 있어서 관련된 이미지를 전부 S3에 넣어두고 RDS에 객체 URL을 넣어두는 방식으로, 백엔드에서 사용하게끔 하였습니다. 그리고 다른 데이터는 한 정규화된 테이블에 넣어두는 방식으로 구현하였습니다.
5. 데이터 파이프라인
이번 프로젝트에는 다양한 파이프라인을 사용하였습니다. 파이프라인 각각 소개 드리겠습니다.
(1) 수집용 데이터 파이프라인
수집용 데이터 파이프라인입니다. 서울 실시간 도시 데이터를 30분 간격으로 S3에 저장한뒤, 가공해서 DB의 세 개 테이블에 나눠서 적재하였습니다. 또한 문화 행사 정보 데이터는 하루 간격으로 DB에 적재하였습니다.
중간에 실시간 도시 데이터 API가 왕창 업데이트 되면서, 2일 정도 문제가 있었지만, 이후로는 문제 없이 잘 가동했습니다. 외부적 요인도 고려해야한다고 느꼈었는데, 당시 주무관님께 직접 통화를 걸어서 업데이트 일정을 알아보기도 했습니다 ㅋㅋ.ㅋ.ㅋ
S3에 먼저 저장한 이유는, Backfill을 위함인데, 혹시 transform, load 단계에서 혹시 모를 에러가 발생할 수 있어, s3에 먼저 적재하였습니다. s3에는 다음과 같은 구조로 적재하였습니다.
(2) 리뷰 -> 별점 환산 파이프라인
하루에 한번, 맛집, 명소 리뷰 테이블에 있는 리뷰 데이터를 가지고 와서, LSTM 모델로 긍정 확률을 산출한 뒤, 집계하여 특정 로직을 거친 후 맛집 테이블의 별점 컬럼을 업데이트하는 파이프라인입니다. 해당 파이프라인을 구현한 이유는, 실제로 사용자가 별점을 매긴 수치보다는, 시스템에서 설계된 방식대로 딥러닝을 활용해서 점수를 산출하는 방식을 구현해보고 싶었고, 또한 최근 별점 관련 신뢰성 문제 또한 개선해보고자, 이렇게 구현하였습니다.
해당 LAMBDA 함수는 AWS의 event bridge를 통해서, 맛집, 명소 각각 매일 00시 10분, 00시 15분에 작동합니다.
https://dataengineerstudy.tistory.com/193
(3) MySQL -> Redshift COPY 파이프라인
저희는 간단한 MLOPS 구현과, 분석용 대시보드 및 다양한 데이터 분석을 위해 MySQL 데이터를 Redshift로 하루에 한번 copy하는 과정을 거쳤습니다. 이 때 저희의 웹사이트 운영에 필요한 데이터를 제외하고는 MySQL의 부하를 줄이기 위해서 어떤 방법을 쓸까 고민했었습니다. 특히 30분에 한번씩 운영 DB로 적재되는 Population, Weather 테이블은 일주일치 데이터만 가지고 있으면 됐기에, mysql의 이벤트 트리거를 활용해서 하루에 한번씩 일주일치 데이터만 남기고 삭제하는 것 또한 자동화하였습니다.
하지만, Airflow에서 S3RedshiftOperator를 사용할 때, Copy 관련 식별자 문제가 있었는데, 관련해서는 Airflow의 소스코드를 바꿔서 수정했습니다. 아직까지도 해당 식별자 관련 문제는 정확히 알려진 바가 없어서, 소스코드는 바꾼 채 유지 중입니다. 관련 포스팅 첨부드립니다.
https://dataengineerstudy.tistory.com/194
(4) 로그 분석 파이프라인 설계
로그 데이터를 Springboot와 Fastapi에서 추출해서 가공하고 redshift에 적재하는 파이프라인입니다. restAPI를 활용해서, FASTAPI와 스프링서버에 get 요청을 주면, 특정 기능이 동작하면서 s3에 로그 파일을 뱉습니다. 해당 파이프라인이 돌면서 데이터웨어하우스에 하루에 한번씩 적재되고, 분석가는 이런 대시보드를 superset을 통해 생성합니다.
여기서 apache superset은 운영 DB를 바라보고, 작동하는 대시보드 또한 있습니다. 리액트 임베딩, 동적 쿼리 방식은 하단 포스팅에 작성해두었습니다!
https://dataengineerstudy.tistory.com/190
(5) 모델 배포 자동화 파이프라인(MLops)
매일 새로운 데이터를 학습해서 새로운 모델을 배포하는 파이프라인입니다. 하이퍼파라미터 튜닝 같은 부분들은, 초기에 설정해둔 옵션으로 진행했습니다. 처음에는 aws sagemaker나 EC2 서버를 따로 열려고 했으나, 데이터의 사이즈나, 비용, 시간 면에서 굳이 사용할 필요가 없겠다고 판단한 후 구현된 파이프라인입니다. 학습 후에 테스트 값들은 모니터링할 수 있게 슬랙으로 전 팀원이 볼 수 있고, 매일 FastApi 서버로 배포되어서, FastApi 서버에선 해당 모델을 예측에 사용합니다.
아쉬웠던 점으로는 KubeFlow 같은 오픈소스를 사용했다면, 분석가의 노트북 파일들을 좀 더 유기적으로 적용할 수 있었을 것 같습니다. 쿠버네티스를 처음부터 사용해봤다면, 고려해봤을 것 같습니다. 이렇게 생성된 모델은 FastAPI에서 다음과 같은 구조로 사용되었습니다.
Fastapi에서 사용된 간단한 알고리즘 구현도입니다.
6. 웹 구현(시연 영상)
https://www.youtube.com/watch?v=xOqyAW4Hq0Y
웹 관련 설명은 병창님 블로그에 자세히 써있어서, 참고 링크 첨부드립니다:)
https://mbspear.tistory.com/112
7. 발표영상
https://www.youtube.com/watch?v=2tBL4qRNx7w
8. 아쉬웠던 점
1. SPARK을 사용하지 못했다!
데이터의 크기가 SPARK을 사용할 정도는 아니여서, 억지로 SPARK을 사용하진 않았습니다. 기회가 된다면 EMR을 활용해서, SPARK을 돌려봤을 것 같은데 아쉬움이 남습니다. 아마 이 부분은 토이프로젝트 정도로 가볍게 진행해볼 것 같습니다.
2. 기획의 아쉬움
발표 당시 피드백 받았던 건데, 우리가 사용하는 서비스로 인해서 해당 장소가 혼잡해질 경우, 그거에 대한 대처방안은 있느냐?라는 말씀을 들었습니다. 솔직하게 거기까진 생각하지 못했다고 말씀 드렸으나, 나중에 생각해보니 혼잡도와 맛집, 그리고 문화행사를 엮는 일련의 이 과정에 조금 더 세밀한 기획이 필요했을 것 같다고 생각이 들었습니다.
3. 모델링
다양한 시도를 해보지 못했던 것 같습니다. 모델이 추가가 되기도 했고, 데이터가 워낙 적기도하다보니, 더 많은 판단이 필요했을 것 같지만, 생각보다 많은 판단하에 한 작업은 모델링에선 없었습니다. 일단 적어도 일년의 데이터는 확보하고 진행이 되었으면 좋았을텐데, 라는 생각이 들지만 이 부족함 때문에 MLops를 조금이나마 체험해볼 수 있지 않았나 싶기도합니다.
4. 데이터베이스 설계
DB 설계 단에서 백엔드와 충분한 이야기를 했다고 생각하고 설계를 했는데, 나중에 되서 고칠게 꽤 많았습니다. 그러다보니 개발기간도 조금 지연이 되는 문제도 보였습니다. 데이터베이스 설계에서 조금 더 어떤 기능을 어떤 테이블이 담당할지를 구체적으로 설계했다면 백엔드 분들도 조금 덜 고생하지 않았을까 싶습니다.
9. 후기
팀원들간의 의사소통도 좋았고, 문서를 남겨두는 과정, Git에서 칸반보드 기반으로 커밋하는 방식 등 너무나도 배울게 많았던 프로젝트였습니다. 특히 Dag만 10개 정도 작성했고, 데이터 관련 부분을 거의 도맡아서 했었는데 확실히 레벨업한게 느껴집니다. 이젠 데이터 가공 단계를 뛰어 넘었다라는 생각이 들 때, 조금 짜릿했던 것 같습니다.
또 웹 구현해주신 팀원 분들, 경목이, 병창이, 민수형 너무 다들 잘해줘서 고마웠고, 호영이랑은 데이터분석가와 데이터엔지니어의 협업을 해보면서 너무나도 좋았습니다. 서로 의견이 왔다갔다 하는 과정에서, 새로운 것들도 시도 해보고, 에러에 걸리고, 밤을 새서하던 그 때가 추억으로 남았습니다....
무언가를 만드는 사람의 입장으로, 또 무언가를 기획해보는 입장으로 이번 프로젝트는 저에게 있어서 엄청난 성장 단계가 되었을 거라고 생각합니다. 팀원과의 협업도, 컴퓨터 공학적인 지식도, 너무나도 많은 걸 배울 수 있는 프로젝트였습니다. 감사합니다:)
깃허브 : https://github.com/sangwookWoo/Stand_Up_Seoul
다음 플젝은 스파크로.... 반드시...!