JDC 일자리데이터센터

243개 지자체의 인구, 고용, 산업 통계 데이터를 시각화 / 시각화된 통계 데이터와 해석을 문서 파일로 제공

개요

  • 기간 : 2020년 8월 1일 ~ 2021년 4월 30일

  • 회사 : 미래직업전망연구원

  • 담당 범위 : 전체 (Backend, Frontend, Infrastructure)

주요 기술 스택

Frontend

  • HTML5, CSS3 기본 퍼블리싱

  • Bootstrap + jQuery

  • Javascript 차트 시각화 라이브러리 amCharts 활용

  • Naver Maps API Pin Clustering

  • Wordpress (랜딩 페이지)

Backend & Infrastructure

  • PHP CodeIgniter 3 (PHP 7.4)

  • MariaDB 10.4 (AWS RDS)

  • AWS EC2 (Linux Debian, Apache, php-fpm)

  • AWS Lightsail, PHP 7.4 (랜딩 페이지)

  • Python Flask 프레임워크 (Python 3.7) with AWS EC2 Ubuntu 20.04

Etc.

  • Github에서 버전 관리

  • Git-Flow를 적용해 각 브랜치별로 역할 분리, 브랜치별로 배포 서버 다르게 지정하여 Jenkins에서 각각 서버에 자동 배포.

  • Google Drive, Docs API 연동 : 유튜브 영상의 메타 데이터와 썸네일 추출 목적

  • 결제 연동 (아임포트, KG이니시스)

상세 개발 내용

  • 수동 입력 필요한 데이터들 전체 수집 및 정리

  • 랜딩 페이지 (워드프레스) 제작

  • 메인 페이지 전체 개발 - 프론트엔드 & 백엔드 & 데이터베이스

  • 관리자 페이지 전체 개발 - 프론트엔드 & 백엔드 & 데이터베이스

  • 문서 생성 서버 개발 - 백엔드 (Python Flask)

주요 개발 이슈 및 해결 사례

1) 통계 데이터의 표준화 문제

인원이 부족해 초반에는 고용, 노동, 산업 통계 데이터와 지자체별 데이터를 수집하는데 많은 시간을 할애했습니다. 통계청 국가통계포털과 통계청 Open Api를 활용해 주로 데이터를 수집하였습니다. 당시에 이용하기로 한 Gapminder라는 시각화 툴은 csv 형태로 데이터가 import 되어야해서 국가통계포털에서 여러 종류의 데이터를 csv 파일로 다운받은 후, 엑셀로 후처리 작업을 거쳐 수치를 정리했습니다. 또한 지자체별로 hwp, pdf, xlsx 등 파일 형태로 제공되는 통계 항목은 수작업으로 데이터를 정리해줘야 했습니다. 통계청 API는 JSON 형태로 데이터를 제공해주어 편하나, 통계표별로 지역코드와 단위가 표준화가 되어있지 않아 케이스를 모두 파악하고 인자를 주어 별도로 처리해줘야 했습니다. 약 2~3달동안 243개 지자체, 최장 20년에 걸친 30여종의 통계 항목과 지역일자리 목표 공시제의 각종 데이터를 모두 정리했습니다.

지금 되돌아보면 참 힘들고 고된 작업이었던 것 같지만 이 활동이 데이터 처리, 통계 관련 도메인에 대해 깊이 이해할 수 있는 계기가 되었습니다. 향후에 본 경험과 데이터 사이언스에 대한 학습, 그리고 파이썬을 함께 연계하면 해당 분야(데이터 사이언스)에서도 역량을 발휘할 수 있을 것 같습니다.

2) Git과 Jenkins의 도입

처음으로 회사 자체 플랫폼을 개발하며 비록 지금은 혼자 개발을 하고 있지만, 향후 개발 인력이 충원되고 팀이 형성될 때를 대비해 개발 체계와 시스템을 구축하고자 하였습니다. 그 일환으로 Git과 Jenkins를 도입했습니다. Github Private Repository에서 작업하고, Develop 브랜치와 Main 브랜치를 나눠서 개발 서버와 메인 서버별로 배포 자동화를 했습니다. 비단 개발의 편의성을 향상시키는 것 뿐 아니라, 반복적인 작업에 인적 요인의 개입을 줄여 리스크를 줄이는 효과도 얻었습니다. 이 때 구축된 파이프라인을 기반으로 향후 진행되는 프로젝트에도 동일하게 본 체계를 적용했습니다.

3) 문서 파일 생성 기능 개발

  • 요구사항 파악

    기관에서는 주요 고용, 노동, 산업 통계 데이터에 대해 기초 데이터(표)와 시각화 데이터(차트), 그리고 해석을 주로 필요로 하기에 해당 내용을 담은 리포트를 제작하기로 결정하였습니다. 실제로 주요 수익 모델이 될 서비스이기에 신중하게 개발 방향을 잡아야 했습니다.

  • HWP 파일로 생성 도전... 그리고 보류

    공공기관이 서비스의 주요 타겟층 중 하나이기에 한글 파일로의 생성을 제일 먼저 고려했습니다. 하지만 몇 가지 문제점이 있었습니다. hwp 파일 포맷 공개로 한글 파일을 읽는 라이브러리들은 몇 가지 존재했지만, 한글 파일을 생성하고 작성하는 라이브러리는 대부분 찾기가 어려웠습니다. 자바로 만든 라이브러리가 있어 intellij를 설치하고 테스트를 해봤는데 자바에 익숙하지 않아 추가 개발을 하기가 어려웠습니다. 물론 스터디를 하고 시간을 투자하면 구현 자체는 가능할 것으로 보였으나, 일정과 업무량, 그리고 향후 유지보수 여력 등을 고려했을 때 잠시 보류하고 다른 방안을 먼저 탐색해보기로 결정했습니다.

  • WISIWYG 에디터의 문서 출력 기능 검토.. 그리고 반려

    hwp 파일 외에 다른 포맷으로 파일을 만들기 위해서 제일 먼저 생각했던게 WYSIWYG 에디터의 문서 출력 기능이었습니다. 실제로 구현은 가장 간단하게 이뤄지는데 라이센스와 가격이 가장 큰 문제였습니다. CKEditor 5와 Fraola Editor를 두고 고민을 했는데, CKEditor는 연간 약 $780로 아직 수입이 없는 상황에서 조금 부담스러운 금액으로 작용하였습니다. Fraola 에디터의 경우 영구 구독시 $1299에 기능을 이용할 수 있지만, 생성된 문서 파일을 고객에게 판매하는 것이기 때문에 라이센스 상 상위인 Enterprise가 적용돼 $2999까지 가격이 올라가서 도입이 반려되었습니다. 완전 오픈소스로 관리되는 에디터들보다 기능이 풍부하고 지원이 안정적이어서 서비스 내에 에디터가 필요한 여러 곳에도 사용할 수 있었겠지만 가격과 예산 문제로 인해 다른 방안을 찾아야 했습니다.

  • Google Docs와 Drive API 이용으로 최종 결정!

    그러던 중 Google Docs와 Google Drive 를 이용해 문서 틀을 만들고, 거기에 값을 치환해서 문서로 출력하는 건 어떨까 하는 아이디어를 떠올렸고 Python을 이용해 바로 테스트해봤습니다. 먼저 구글쪽 매뉴얼을 보고 예제 코드를 가져와 인증을 하고, 문서에서 {{TEXT-1}} 과 같이 영역을 만들어두고 값을 치환하는데 성공했습니다. 마지막으로 해당 파일을 API를 통해 다운로드 하는것까지 테스트에 성공해 바로 메인 코드 작성에 들어갔습니다.

    Flask vs AWS Lambda

    구현 방식에 있어 고민이 좀 있었습니다. Flask와 람다 모두 사용해본 경험이 있고, 각각의 장단점이 뚜렷해서 어느 한 쪽이 좋고 안 좋고를 논하기가 어려웠습니다. 다만 람다의 경우 서버리스 특성상 클라우드 서비스 제공업체에 따라 코드가 종속적이게 되어 향후 관리 측면에서는 Flask가 조금 더 유리하다고 판단했습니다. 또한 람다로 테스트를 하던 중 액세스 토큰이 만료되어 리프레시 토큰으로 새로 액세스 토큰을 발급받아 저장하더라도, 람다 자체에서 파일을 저장하지 않아 인증을 위한 절차가 복잡해진다는 문제가 있었습니다. 이외에도 향후 기능 확장을 고려했을 때 Flask가 비교우위에 있다고 판단, Flask를 이용하기로 결정하였습니다.

  • 실제 코드 구동은 다음과 같은 방식으로 이뤄집니다.

    1. 프론트에서 데이터(이미지 : base64 인코딩, 수치 데이터와 해석문 : json)를 담아 Flask 서버로 POST 요청을 보냄

    2. 요청이 유효한지 확인 : 웹서비스 프론트에서 넘어온 토큰이 유효한지, 이용자의 권한이 충분한지, 필요한 파라미터가 모두 넘어왔는지 체크

    3. 문서 형식에 따라 기존에 구글 드라이브에 생성되어있던 템플릿을 복사해서 새 파일로 생성 (Google Drive API)

    4. 문서에 데이터 삽입 : Google Docs API로 지정된 위치에 데이터 치환

    5. 이미지의 경우 base64 Decode하여 이미지 파일로 생성해 서버의 임시위치에 저장, AWS S3 SDK를 이용해 S3에 이미지 파일 업로드 한 후 해당 링크를 받아와 Google Docs API로 이미지 삽입 (이미지가 바로 삽입되지 않고 링크로만 넣을 수 있음). 이후 S3에 업로드한 이미지 삭제, 서버의 임시파일 삭제 처리

    6. 지정한 형식으로 파일 저장 : Google Drive API를 통해 docx, pdf, odt 등 7가지 종류의 형식으로 임시폴더에 파일 저장

    7. S3에 파일 업로드 후 링크 받아온 후 임시폴더 파일 삭제, S3 링크 반환

    8. 프론트에서 반환된 링크값을 통해 사용자가 파일을 다운로드받을 수 있도록 함

4) 메인 페이지 로딩 속도 개선

  • 문제점 파악

    기본적으로 메인 페이지에 로딩 속도에 영향을 끼치는 무거운 컴포넌트가 많습니다. Gapminder 그래프 16개가 iframe 형식으로 호출되어야하는 특성상 호출에 소요되는 시간이 길고, Naver Maps API로 그리는 지도의 개수가 9개, amCharts로 호출되는 Map Chart 2개 등 전체적으로 자바스크립트쪽 부하가 많습니다. 따라서 기존에는 화면이 처음 보이는데까지 걸리는 시간이 5초 이상으로 길고, 페이지가 완전히 로딩되는 데는 30초 이상이 소요되었습니다. 분명 개선이 필요했고 시간을 조금 들여 여러 최적화 과정을 거쳤습니다.

  • 소스코드 최적화

    우선 자바스크립트 로딩 순위를 다르게 설정하여 첫 화면이 뜨는데까지 걸리는 소요시간을 1초 이내로 줄이고, 대부분의 자바스크립트 파일을 minify했습니다. 네이버 지도의 경우 처음 화면에 뜨는 1개만 먼저 로딩하고, 지도 관련 다른 버튼 조작이 발생할 경우 나머지 8개의 지도를 로딩시켰습니다. amCharts의 Map Chart도 동일하게 1개만 먼저 로딩하고, 다른 지도를 선택하면 로딩되도록 수정하였습니다. 이 외에 Gapminder 차트의 경우, 기존에 화면에 보이는 iframe 6개는 모두 lazy loading을 걸어주었고, 버튼을 클릭해야 볼 수 있는 나머지 10개의 차트의 경우 버튼 선택시 iframe이 로딩되도록 작업해주었습니다.

  • 로딩속도 개선

    작업 결과 첫 화면이 뜨는데까지는 1초 미만, 5초정도면 모든 요소들이 다 로딩될 수 있도록 개선에 성공했습니다. 이 외에도 사이트 내에 로딩이 오래 걸리는 페이지들에 대한 리팩토링도 진행하였습니다.

성장

  • 스타트업 특성상 지속적으로 기획 방향이 바뀔 수 있음을 이해하고, 변경된 기획에 대해 다방면의 기술적 검토를 거쳐 프로젝트가 더 나은 방향으로 나아갈 수 있도록 참여하는 경험을 갖게 되었습니다

  • 사이드 프로젝트로 코드이그나이터를 한 번 써보고 바로 실제 프로젝트에서 이용하며 보안이나 개발 편의성 면에서 확실한 개선점을 얻었고 코드 컨벤션 유지도 용이해졌습니다. 초반에 MVC 패턴을 이해하는데 약간 어려움이 있었으나 금방 이해하고 적응하여 실제 이용상 불편함은 없었습니다.

Last updated