Project
MaPPPing의 비하인드 스토리 - 개발자 편
안녕하세요. SDP 5기 이길원, 6기 윤여경, 장윤설입니다. 이번 테크 인사이트에서는
Failure Map의 서버 구동 방법과 구현 방법을 소개하려고 합니다.
[사진: https://failuremap.sdpglobal.org/]
서버 구동
방법
기술 스택을 나열하면 EC2(Elastic
Computing Cloud) + node.js + NGINX로 서버가 구동되고 있습니다. Failure
Map 페이지의 url인
failuremap.sdpglobal.org 의 경우, 미리 구매한 sdpglobal.org 의 서브 도메인을 사용하기에 따로 비용이
청구되고 있지 않습니다.
EC2는 AWS에서 제공하는 기능으로, 간단하게 컴퓨터를 하나 대여하는 것이라고 생각할 수 있습니다. 정식 명칭은 Elastic Computing Cloud 입니다. 특히, 리눅스 운영체제를 활용해 흔히 서버라고 부르는 컴퓨터를 사용하는데 최적화된 것들이 많습니다.
이러한 EC2 컴퓨터에서 해당 컴퓨터로 접근할
수 있는 다양한 포트가 존재합니다. 이 때, 포트는 통신의 종단점이라고도
불립니다. http의 443, ssh의
22 등 이미 기능이 정해져 있는 포트가 존재합니다. 다음으로, 해당
포트로 들어오는 ip주소를 제한할 수 있습니다. 우리 서버의 경우 현재 public 으로 열려 있는 상태기 때문에 443, 22 등의 포트로 요청을 보내는 ip는 외부적인 오류가 없다면 정상적인
응답을 받을 수 있습니다.
그러나 이것만으로는 충분하지 않습니다. 사용자가
보낸 요청에 대해 서버에서 어떤 응답을 보내야 할지 정확히 정해지지 않았기 때문입니다. 이런 응답은 Node.js에서 담당하고 있습니다. Node.js를 활용하여 사용자가 요청을
보냈을 때 어떤 응답을 보낼지, 즉 페이지에 어떤 내용을 띄워줄지 구현되어 있습니다.
마지막으로 보안을 위해 NGINX를 사용하고
있습니다. 우리 컴퓨터의 크롬, IE 같은 브라우저를 통해 Failure Map 페이지로 요청을 보내면, 실제로는 NGINX 라는 서버를 감싸는 껍질이 먼저 그 요청을 확인합니다. 그리고 우리의
요청을 타인이 가로채도 해당 내용을 확인할 수 없게 내용을 암호화하여 보안성을 높입니다. 또한 NGINX 역시 하나의 서버로 동작하기 때문에 여러 포트를 가지고 있는데, 실제 EC2 서버에서 열린 포트가 무엇인지 알려주지 않고 NGINX의 80번 포트로만 접근하게 하여 서버 보안성을 높일 수 있습니다.
구현 방법
기본적으로 Failure Map의 웹 매핑(Web
Mapping)을 위해 오픈 소스 자바 스크립트 라이브러리인 Leaflet을 사용했습니다. Leaflet은 지리 정보의 저장 포맷 중 하나인 GeoJSON 형식을 지원하여 GeoJSON Layer을 제공합니다. 아래는
Leaflet에서 제공하는 GeoJSON 데이터의 예시입니다.
var geojsonFeature = {
"type":
"Feature",
"properties": {
"name":
"Coors Field",
"amenity": "Baseball Stadium",
"popupContent": "This is where the Rockies play!"
},
"geometry":
{
"type":
"Point",
"coordinates": [-104.99404, 39.75621]
}
};
아래 코드에서 볼 수 있듯이, GeoJSON 레이어가
제공하는 옵션을 사용하여 Failure Map의 필터, 팝업창, 마커 등을 구현했습니다.
let geoLayer = L.geoJson(json, {
onEachFeature:
addPopup,
filter:
geoJson_filter,
pointToLayer:
geoJson_pointToLayer
});
주요 라이브러리
Leaflet 외에 필터 기능 구현에 사용된 주요 라이브러리를 소개합니다.
●
jQuery - javascript 코드를 간단하게 만들어주는 라이브러리
●
Select2 - jQuery Select box용 라이브러리
(검색 기능, 그룹형 옵션, 테마 등의 기능 제공)
●
Ion.RangeSlider - jQuery 반응형 범위 필터(Responsive Range Filter)
구체적인 구현 방법은 지도 구현에 사용된 함수와 변수를 소개하며 살펴보도록 하겠습니다.
변수 소개
var
customOption; // 사용자가 필터바에서
설정한 Country, Sector, FC_Year 등의 속성값을 저장하는 배열
함수
소개
데이터 불러오기
- function
load_data(customOption)
jQuery에서 제공하는 Ajax 함수를 활용하여
서버의 Mongo DB에 저장되어 있는 GeoJSON 형식의 데이터를 API로 접근합니다. 만약 데이터를 불러오는 과정이 에러 없이 성공한다면
data_process에
미처리 데이터(raw data)인 json 데이터를 파라미터로 넘겨
데이터 정제 과정을 거치게 하고, 정제된 데이터를 options_to_html 함수에 넘겨 데이터를
기반으로 필터의 옵션을 생성합니다. 다음으로 load_map 함수의
파라미터로 전달합니다.
- function
data_process(json)
각 속성값의 명칭을
통일시키기 위해 대소문자 및 결측값을 확인하고 수정합니다.
맵 세팅하기
- function
load_map(json, customOption)
Leaflet에서 제공하는 기능을 활용하여 기본 좌표와 확대/축소
정도(zoom level)를 세팅합니다. 이후 앞서 소개한 geoLayer를 이용하여 데이터(json)를 불러오고 팝업창 (addPopup), 필터 기능(geoJson_filter), 마커 기능(geoJson_pointToLayer)을 각각
onEachFeature, filter,
pointToLayer 옵션에 추가하여 해당 기능들을 지도에서 구현할 수 있도록 합니다.
- function
addPopup(feature, layer)
데이터의 feature값에서 팝업창에
들어갈 내용을 불러와 넣어주고, 마커를 클릭했을 때 레이어(layer) 위에서
팝업창이 열리도록 합니다.
- function
geoJson_filter(feature)
변수 customOption 에서 각각의 필터에 대해 사용자가 설정한 옵션이 있는지 살펴보고, 사용자가
아무런 필터를 적용하지 않은 경우 마커의 해당 조건값을 true로 설정하여 지도에 보여줍니다. 설정된 조건이 있는 경우, 데이터의 feature값과 비교하여
해당 조건을 포함하고 있는 마커만 지도에 띄워 보여줍니다.
- function
geoJson_pointToLayer(feature, latlng, layer)
각 마커의 feature값을 불러와 sector별로 색상을
지정하고, subsector별로 아이콘을 지정해줍니다. 이렇게 설정된
마커를 각각의 좌표(latlng)에 맞게 레이어(layer)에 추가해줍니다.
필터 구현하기
- function
options_to_html(data)
load_data 에서 선언된 함수로, 정제된 데이터를 기반으로 페이지에 옵션을 생성합니다. JSON형식인 데이터에서 properties 계층에 있는 각각의 value값을 array로 정리한 후, 오름차순으로
정렬한 Set로 변환시켜줍니다.
- function
updateStates(customOption)
사용자가 데이터의 각각의 속성에 대해 조건을 걸었을 때 이 변화를 감지하고
customOption 배열에
추가합니다.
- function
reloadMap(json)
customOption에 변화가 감지될 때마다 지도에 필터링된 값을 보여주기 위해 레이어를 새로고침합니다.
- function
yearIsincluded(feature, yearOp)
FC Year의 슬라이드형 범위 필터(Range
filter)에 대한 함수로, 해당 데이터의 feature값이 슬라이드로
설정한 조건(yearOp)에 포함되는지 확인하고, 결측값(N/A) 포함여부를
결정하는 체크박스의 조건에 따라 마커를 보여줍니다.
+) 자세한 코드는 Github(https://github.com/sdp-tech/Visualization)를 참고해주세요!
몇 달간 많은 수정을 거쳐 (아직도 작업중인) 약 700줄의 코드를 이렇게 간단하게 글로 정리하니 느낌이 새롭습니다. 코드를 찬찬히 다시 읽어보니 이상한 로직이나 함수 명들이 눈에 띄어 코드를 수정하는 시간도 가질 수 있었습니다. 리서치팀으로부터 받은 피드백을 바탕으로 저희 페이지가 좀 더 풍성해지고, 정기적인
코드 리팩토링을 통해 저희 Failure Map이 더욱 단단해지는 것 같아 마음이 든든합니다. Phase 4의 본격적인 작업을 앞두고, 현재에는 모바일 사용자가 더욱 편리하게
사용할 수 있도록 모바일 웹 작업에 힘쓰고 있습니다.
[사진: https://failuremap.sdpglobal.org/inner-page]
현재 시각화가 어느 정도 완성된 단계이며, 여기서 더
나아가 더욱 유익한 지도를 사용자들에게 전달하기 위해 각 프로젝트의 see also 기능을 개발 중입니다. 이 기능은 프로젝트들의 유사도를 측정해서 사용자들이 관련된 프로젝트를 추천 받을 수 있는 시스템입니다. 저희는 군집화 (Clustering)를 통해 사한 데이터를 여러 기준에 따라 그룹화할 예정이며 대표적인 알고리즘을 설명하겠습니다. 군집화란
비지도 학습의 대표적인 분석입니다. 비슷한 특성을 가진 데이터를 같이 묶는 방법이며 어떤 기준으로 데이터를
분류하는지에 따라 다른 관점을 얻을 수 있습니다.
K-means Algorithm
가장 흔히 사용되는 클러스터링 알고리즘은 K-means 방법입니다. 이 알고리즘은 이해하기 쉽고 구현하는 것도 간단해서 대중적으로 사용되고 있습니다. 또한, 일반적으로 괜찮은 결과가 나오기 때문에 군집 분석에 적합합니다. K-평균 알고리즘은
다음과 같은 방식으로 구현됩니다.
- 데이터 세트에서 특정함의 점 k개를
중심점으로 선택합니다.
- 각 데이터를 k개의 점과 거리를
측정해 가장 가까운 점끼리 분리합니다.
- 모든 데이터가 k개 그룹으로
나누고 나면, 각 그룹의 중심점을 다시 계산합니다.
- 이전 단계에서 계산한 중심점을 이용해서
2, 3단계를 반복합니다. 이 과정에서 모든 그룹의 벡터 평균이 많이 바뀌지 않으면
프로세스를 종료합니다.
[사진: https://bangu4.tistory.com/98]
K-평균 알고리즘은 속도가 아주 빠르며 대용량
데이터 처리에 매우 유리합니다. 또한, 계산량도 적고 각 유형의 특성을
파악하기 적합한 방법입니다. 하지만 이 알고리즘은 아웃라이어에 민감해서 초기에
k 값을 선택하는 게 어렵습니다.
Hierarchy Clustering
K-평균 알고리즘과 달리 계층 (hierarchy) 클러스터링은
텍스트 형식의 데이터를 분류하여 분석할 수 있습니다. 이 알고리즘은 각 데이터 텍스트의 유사도를 먼저 찾고
유사도가 높은, 즉 동의어가 많은 데이터를 먼저 묶으면서
하위 계층 구조부터 상위 계층까지 만들어 나갑니다. 계층 알고리즘은 다음과 방식으로 진행됩니다.
- 모든 단어를 고유의 클러스터로 지정합니다.
- 문자열 매칭 알고리즘을 통해 단어나 문장 간의 유사도를 계산합니다.
- 병합했을 때 최고 품질의 조합을 만드는 두 군집을 합병합니다. 이때 먼저 합쳐진 군집의 유사도가 나중에 합쳐진 그룹의 유사도보다 더 높습니다.
- 한 군집만 남았을 때까지 3단계를
반복합니다.
[사진: https://towardsdatascience.com/a-friendly-introduction-to-text-clustering-fa996bcefd04]
계층 알고리즘은 모든 데이터의 유사도를 측정할 수 있는 장점을 갖고 있습니다. K-평균 알고리즘과는 달리 군집 간의 거리를 계산할 수 없는 데이터도 분류할 수 있습니다. 그러나 계산량이 많아 속도는 그리 빠른 편은 아니며 대용량 데이터에 적용하기 힘듭니다.
이처럼 여러 군집 분석이 존재합니다. Failure Map
Phase 4에는 최대한 다양하고 유의미한 인사이트를 얻기 위해 적합한 알고리즘을 신중히 선택해야 합니다.
마지막으로
SDP 부원이자 테크팀원으로서 전세계 유일무이한 SDP의 Failure Map제작을 맡게 되어 영광스러운 마음을 지니고 있습니다. 앞으로도 Failure Map이 더욱 나은 모습을 갖출 수 있도록 열심히 작업해보도록 하겠습니다.
많은 관심 부탁드립니다!
[출처]
https://brunch.co.kr/@gimmesilver/40
https://towardsdatascience.com/a-friendly-introduction-to-text-clustering-fa996bcefd04
https://failuremap.sdpglobal.org/
Comments
Post a Comment