개발공부 & 부트캠프/[부트캠프] 회고

[데이터 엔지니어링 부트캠프]11월 4주차 회고

포리셔 2023. 11. 28. 09:05

센터 휴관으로 금요일은 쉬고 월요일에서 목요일까지 4일간만 진행되었습니다. 물론 파이널인데 작업 안 하고 쉴 여유가 있을 리는...

좋았던 점

  • 2차 발표가 끝난 후, 애자일 회고를 진행하면서 앞으로의 진행 방향을 수정할 수 있었습니다. 에러나 버그를 두려워 하지 말고 일단 빠르게 진행해서 만들어보자는 것이었습니다. 그동안 말로만 이런 다짐을 해왔지만 이제부터는 눈에 보이는 성과도 조금씩 나오고 있는 만큼 조금 더 템포를 빠르게 하고자 하는 것에 팀원들의 동의를 얻었습니다.
  • 애자일 회고가 끝난 뒤, 프로젝트와는 별개로 강사님께 요청해 이력서 첨삭을 받을 수 있었습니다.

아쉬웠던 점

  • 그동안 사소한 이슈나 국지적인 에러에 너무 매몰되어서, 한편으로는 그것을 너무 우려해서 제대로 작업을 진행하지 못한 것 같다는 자체 애자일 회고가 있었습니다.
  • 인원 중 한 명이 열심히 하려는 것 같기는 한데, 정작 협업에 가장 중요한 의사소통이나 풀 리퀘 방법에 대해 전혀 모르고 있어서 발목이 잡혔습니다. 아니, 모르는 것은 물어보면서 그렇게 할 수 있다 치는데, 그걸 배우고 보완하려는 의지가 보이지 않았습니다.
  • 프론트엔드 템플릿을 찾아보니 무료로 사용할 수 있으면서도 퀄리티가 좋은 템플릿이 많더군요... 진작에 이런 쪽으로 먼저 찾아볼 것을 그랬습니다.
  • 어찌 보면 사소하고, 어찌 보면 크다고 할 수 있는 흠을 찾아냈습니다. 바로 csv 파일의 위도와 경도 컬럼이 서로 반대로 되어 있었다는 것... 다시 말해 위도 컬럼에 경도 정보가 들어있었고 경도 컬럼에 위도 정보가 들어있었습니다.

배운 점

구글 지도 API

여행 코스 추천을 위해 구글 지도 API를 연동해 웹사이트 아래쪽에 넣는 방안을 추진했습니다. 아래 사진은 프론트엔드 신경 안 쓰고 일단 뜨는지만 체크한 사진입니다.

  • API 키 발급: 여느 대기업이나 기관에서 제공하는 API가 그렇듯 구글 지도 API도 키를 발급받아야 사용할 수 있습니다. 구글 클라우드 사이트로 들어가서 발급받아야 하며, 사용하기 전 자신이 만들고자 하는 프로그램에 대한 프로젝트를 생성해야 합니다. 또한 무료로 사용하는 유저라도 결제 수단을 등록하지 않으면 나중에 지도를 출력했을 때 워터마크가 찍히기 때문에, 이를 막기 위해 결제 수단을 등록해주셔야 합니다. 보통 2만여 건 정도를 넘지 않으면 무료로 사용할 수 있다고 하니, 공부나 프로젝트 용으로 사용하기에는 무리가 없을 듯합니다.
  • API 키를 발급받은 후에는 다음과 같은 태그를 추가했습니다. 스프링 부트 index.html 파일 기준이므로 mustache 등 다른 포맷을 사용할 경우 조금 문법이 달라질 수 있고, 실제로도 이후 작업에서 약간의 수정을 거쳤습니다.
<html>
<!--
    Google Map API 설정 부분
  -->
  <head>
    <!--
      첫 번째 script 요소:
      Google Maps API를 사용하기 위해 로컬에서 작성할 코드를 불러옴.
    -->
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <!-- 
      두 번째 script 요소:
      원격에 있는 구글 서버로부터 Google Maps API의 코드를 내려받음.
    -->
    <script type="text/javascript">
      google.charts.load("current", {
        "packages":["map"],
        // Note: 아래 키에 구글 맵에서 발급받은 API key를 입력해야 합니다.
        // 참고: https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings
        "mapsApiKey": "your_api_key"
      });
      google.charts.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Lat', 'Long', 'Name'],
          [33.5070537, 126.492776, '제주국제공항'],
          [33.5162323, 126.5120637, '용두암']
        ]);

        var map = new google.visualization.Map(document.getElementById('map_div'));
        map.draw(data, {
          showTooltip: true,
          showInfoWindow: true
        });
      }

    </script>
  </head>

  <body>
    <!-- 필수:
      이 부분에서 width와 height를 반드시 CSS 형식에 따라 지정해야 합니다.
      비어있는 div 요소는 기본값이 0인 높이를 가지기 때문에
      구글 지도가 화면 상에 나타나지 않을 겁니다.
    -->
    <div id="map_div" style="width: 1200px; height: 675px"></div>
  </body>
</html>

파이썬 haversine 패키지

위도(latitude)와 경도(longitude) 정보를 기반으로 두 지점 사이의 거리를 계산해주는 패키지입니다. 하버사인(Haversine) 공식에 기반해 거리 계산을 해줍니다.

from haversine import haversine

# 위경도 입력
Seoul = (37.541, 126.986)  #Latitude, Longitude
Toronto = (43.65, -79.38)

# 거리 계산
haversine(Seoul, Toronto, unit = 'km')

이 패키지를 이용하면 현재 구축해놓은 여행지 정보 csv 파일로부터 여러 지점의 위도와 경도를 구해와서 직선 거리를 구할 수 있을 것으로 기대됩니다.

최단 경로 알고리즘

임의의 개수의 추천 여행지를 뽑아내서 그 정보를 바탕으로 각 지점 사이의 거리를 얻어낸 뒤 최적의 경로를 설계하는 알고리즘을 개발 중입니다. 다익스트라(Dijkstra) 알고리즘과 기본적인 그리디 알고리즘에 기반하여 설계 중이고, 다른 조원이 만들어놓은 테스트 데이터(전국에서 다섯 개 명소를 임의로 뽑아내서 출력)를 바탕으로 거리와 경로를 계산했습니다. 지역 단위로 좁혀서 제대로 동작하는지 테스트했습니다.

  • 다익스트라 알고리즘: 최적 경로 알고리즘의 대명사로 꼽히는 알고리즘으로 그래프 이론에 기반하고 있습니다. 각 노드(여기서는 여행지에 해당)와 노드를 잇는 간선(edge)에 대해 가중치(여기서는 여행지 사이의 거리에 해당)를 계산하고, 최적의 가중치 조합을 갖는 노드 순서를 반환합니다. 즉, 최적의 거리를 갖는 여행지 방문 순서를 전달받을 수 있습니다. 기본적으로 성능 측면에서는 힙 자료구조를 이용하는 개선된 다익스트라 알고리즘을 사용하는 것이 좋지만, 현재 개발 중인 알고리즘은 많아봐야 10개 정도의 여행지에 대한 코스를 짜주는 부분이라 우선은 힙 자료구조를 사용하지 않는 간단한 다익스트라 알고리즘에 기반해서 개발했습니다.
import numpy as np
from haversine import haversine

def dijkstra(similar_tags, start=0):
    """
     '간단한 다익스트라' 알고리즘
    ==============================================
    Variables
     - similar_tags: Dictionary type.
                     메인 스크립트에 해당하는 app.py에서 미리 코사인 유사도를 기준으로 정렬하여 입력받습니다.
     - start: Integer.
              여행 중 처음으로 방문할 장소의 인덱스입니다. 기본값은 0입니다.
    ==============================================
    Return
    - visited_nodes: List. 방문할 여행지의 순서.
    - distances: ndarray. 한 여행지로부터 다른 여행지까지의 거리. 자기자신에 해당하는 거리는 0으로 저장됩니다.
    """
    # 다익스트라 알고리즘은 시작하기 전 모든 노드 간의 거리(또는 가중치)를 무한대로 설정하고 시작합니다.
    # INF = np.inf

    # 노드의 개수, 간선의 개수(노드 n개, 간선은 nC2 = (n * (n-1) / 2)개로 설정)
    n = len(similar_tags)
    m = n * (n - 1) / 2

    # 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
    graph = [[] for i in range(n + 1)]
    # 최단 거리 테이블을 모두 무한으로 초기화
    distances = np.zeros((n, n))

    # 모든 간선 정보 입력받기 - 거리를 입력
    # 각 노드로부터 다른 노드까지의 거리 입력(자기 자신에 해당하는 거리는 0으로 설정)
    for i in range(n):
        for j in range(n):
            if i == j: # 자기 자신
                pass
            else: # 그 외의 다른 노드들
                # 여행 장소 위도, 경도(출발지)
                start_location = (similar_tags[i]['lon'], similar_tags[i]['lat'])
                # 여행 장소 위도, 경도(다른 노드)
                other_location = (similar_tags[j]['lon'], similar_tags[j]['lat'])
                distance = haversine(start_location, other_location, unit='km')
                distances[i, j] = distance

    visited_nodes = greedy(distances, start_node=start)
    return visited_nodes, distances

def greedy(distances, start_node):
    num_nodes = distances.shape[0]      # 노드의 수( = n)
    visited_nodes = [start_node]        # 방문한 노드 목록
    current_node = start_node           # 현재 위치한 노드

    INF = np.inf

    while len(visited_nodes) < num_nodes:
        min_distance = INF
        for node in range(num_nodes):
            if node not in visited_nodes and distances[current_node, node] < min_distance:
                min_distance = distances[current_node, node]
                next_node = node
        visited_nodes.append(next_node)
        current_node = next_node

    return visited_nodes

이력서 첨삭 관련

예전에 우리 반 공유 폴더에 올려놓은 이력서가 있는데, 이 이력서를 어떻게 고쳐야 할 지, 타 전공이라는 경력 상의 약점을 어떻게 보완할 것인지 등의 조언을 구했습니다. 아래 사항들을 정리해서 이력서 V2를 만들어 수정해보기로 했습니다.

  • 현재 이력서 상에서 고쳐야 할 부분이라면, 질문의 여지를 둬야 한다는 부분이었습니다. 아무래도 IT가 아니라 기계공학 전공인지라 연구실에서 했던 연구들을 최대한 풀어쓴다고 표현도 쉽게 바꾸고 중간중간 생략된 부분이 많았는데, 이러면 실제로 현업에 계신 분들인 면접관들이 뭔가를 궁금해 할 여지가 없다고 하십니다. 조금 더 이 사람에 대해서 궁금해할만한 표현으로 바꿔보는 게 좋을 것 같다고 하셨습니다.
  • 사실 면접은 운칠기삼의 면이 커서 10개 써서 3개 긍정적이면 성공이라고 한다고 합니다(심지어 강사님 본인도 지금 면접을 보게 되면 상황이 똑같을 거라고 하십니다). 면접은 결국 사람 대 사람 사이에 있는 과정인지라 단순히 면접관 개인의 의견과 나의 궁합이 잘 안 맞아서 떨어지는 경우도 있다나요. 더군다나 면접에서 이 사람을 뽑아야 되겠다/이 사람을 뽑으면 안 되겠다에서 제대로 인재를 걸러내는 비율은 사실 절반도 안 되는 것으로 보여진다는 개인 의견이 있었습니다.
  • 제 전공이었던 항공과 소프트웨어를 결합한 회사든, 아니면 일반 소프트웨어 회사든 큰 상관 없이 기회가 주어진다면 가 보겠다는 의견을 말씀드렸습니다. 그랬을 때 향후 커리어가 어떻게 발전할 수 있을지도 생각해 볼 문제라고 했습니다. 예를 들어주신 한 기업(기업 이름을 강사님도 기억 못 하심...)은 국내 대학교 연구실에 실험 장비와 계측 장비를 공급한다고 했는데, 이런 회사에 들어간다면 기계과 전공으로써는 참 괜찮을 수는 있겠으나, 향후에 다른 IT 기업으로 이직하는 것은 경력 상 조금 어려울 수도 있을 것 같다고 했습니다. 같은 맥락에서 네이버에서 근무하실 적에 타 기업이나 부서로 잘 이직하지 못하는 부서가 다름 아닌 지도 그리고 검색 엔진 개발 부서라고 합니다. 너무 특화된 분야라 다른 분야로 이직하기 어렵다는 것이 그 요지.
  • 원티드 이력서 완성도가 40%에 머물러 있는 것은 크게 개의치 말라고 하셨습니다. 분량도 지금 버전 정도면 충분하다고 하시는군요.
  • 항공 분야만이 알아볼 수 있는 기업들의 리스트도 뽑아보는 것이 좋겠다고 했습니다. 비록 연구실을 떠나긴 했지만 지나온 경력을 버릴 생각은 없다고 하니 그 쪽으로 장점을 살리는 차원에서 제안하신 내용입니다.
  • 결정적으로 지금까지 해 온 것만으로도 강점을 충분해보이니 너무 주눅들 필요 없다고 하셨습니다. 소프트웨어공학과 이외의 이공계 분야에서도 프로그램을 만드는 시점이니 만큼 지금 가지고 있는 기계과로서의 연구 성과와 전공 지식을 강점으로 삼아서 준비하면 생각보다는 빠른 시기에 취업이 가능할 수 있을 것 같다는 응원을 들었습니다.

앞으로 바라는 점

  • 데이터 엔지니어링이라는 필드를 너무 쉽게 봤던 것인지 사전 계획보다 너무 할 일이 많고 지연되어 구현하고자 했던 기능의 절반 정도만 간신히 구현했던 것 같습니다. 1주일 남짓 밖에 안 남은 데다가 최종 발표 전인 목요일까지 사전에 기획서와 ppt 파일 및 실행 파일을 보내달라고 하니 실질적인 개발은 화요일에서 수요일 정도까지만 할 수 있을 것 같습니다. 많이 아쉽긴 하지만 이제는 실제 구현에 오류가 없을 정도로 다듬고 발표에 집중해 유종의 미를 거둘 수 있도록 해야겠습니다.