태양을 피하고 싶어서 만든 앱

Jiiker·2025년 7월 12일
134

그늘길

목록 보기
1/1
post-thumbnail

배포중인 URL: https://project-g-seven.vercel.app/

프로젝트 개요

날씨가 너무 덥다... 깜빡하고 선크림이라도 안 바른 날에는 태양빛에 닿으면 죽는 뱀파이어 마냥 그늘을 찾아 다닌다. 우리는 어렴풋이 해는 동쪽에서 떠서 서쪽으로 진다고 알고있지만, 중위도 지역에 위치한 대한민국은 다양한 계절만큼이나 태양의 위치도 다양하다. 여름은 북동쪽에서 북서쪽, 겨울은 남동쪽에서 남서쪽, 봄/가을에는 동쪽에서 서쪽으로 계절별로 조금씩 차이가 있다. 나름 지구과학 과목에서 1등급을 받았었지만, '북반구 중위도 지역의 여름이니까 오늘은 태양이 북동쪽에서 북서쪽으로 지겠구나.' 따위의 생각은 하지 않는다. 그리고 이제 나름 개발자로 전직하지 않았는가. 그래서 만들어버렸다. 지도에 그늘을 표시해주는 앱. 일명 그늘길 프로젝트.

아이디어

아이디어의 시작은 건물 부지와 건물의 높이만 알면 대략적인 그림자를 그릴 수 있지 않을까하는 생각에서 출발했다. 그리고 건물 부지와 건물 높이는 여러가지 이유들로 인해 반드시 데이터로 관리될 것 같아서 어떻게든 얻을 수 있는 데이터라고 생각이 들었다. 우선 지도 API도 여러 가지가 있었고, 건물 데이터는 국토교통부에서 제공하는 공공데이터 API도 있었다. 그런데 지도 API 중에 3D 건물 데이터를 제공해주는 API가 있었다. Mapbox API인데, 지도와 건물 데이터 간에 호환성이 가장 좋을 것 같아서 일단 프로토타입을 이 API로 만들어 보기로 결정했다.

그림자를 어떻게 그릴 것인가?

  1. 모든 건물은 밑면부터 천장까지 일정한 모양을 가지는 기둥 형태라고 가정
  2. 태양 빛은 태양 고도의 각도로 평행하게 입사한다고 가정

그림자 길이

그림자의 길이는 간단한 삼각함수 계산을 통해 구할 수 있다.

그림자 모양

그림자 모양을 어떻게 결정해야될지 고민을 많이 했다. 일단 굉장히 가벼운 앱으로 만들고 싶었기 때문에 로직을 복잡하게 가져가고 싶지 않았고, 아주 단순한 계산으로 그리고 싶었다.

[방법1] Turf.js - convex 메서드

자바스크립트 라이브러리 중에 지리 공간 데이터를 처리하는데 사용하는 Turf.js라는 라이브러리가 있었다. 이 라이브러리에 convex라는 메서드가 있는데, 2차원 좌표 평면에 존재하는 점들의 집합을 감싸는 최소 크기의 볼록 다각형을 만들어준다. 이를 이용하면 그림자를 쉽게 만들 수 있지 않을까 생각했다.

아까 그림자 길이를 계산했던 것을 토대로, 건물의 윗면이 바닥에 정사영되는 위치를 알 수 있고, 모든 건물은 기둥 형태라는 가정을 통해 간단하게 밑면을 그림자 길이 만큼 평행이동 시킴으로써 윗면이 정사영 되는 위치를 쉽게 계산할 수 있다. 그리고 기존 밑면을 이루던 점들과 윗면이 정사영 된 점들을 가지고 convex 메서드를 이용하면 그림자와 유사한 형태의 볼록다각형을 얻을 수 있다.

[방법1] 구현 결과

위 방법을 통해 구현한 첫 번째 그림자 지도이다. 일단 대부분의 건물이 기둥 형태이기도 하고, 대부분의 건물 단면이 볼록다각형 형태이기 때문에 사용에는 큰 문제가 없어보였다. 다만, 지도를 넘기다보면 간혹 오목한 형태의 단면을 가진 건물들이 있는데, 이 경우에 그림자 모양에 문제가 생겼다.

사실 주사용 목적 자체가 고층 빌딩으로 인해 생기는 그림자를 이용하려고 만든 앱이라 내가 사용하기엔 큰 문제는 없었다. 하지만... 누군가에게 소개했을 때 이런 것들이 하나 보일 때마다 이 앱의 신뢰도에 문제가 생길 수 있겠다고 생각했다. 그래서 조금 복잡해질 수는 있지만, 더욱 정교한 그림자를 그려보기로 했다.

[방법2] 건물의 모든 면에 대해 그림자 생성

사실 이게 그림자를 그리는 정석적인 방법일 것 같다. 원래는 햇빛이 닿는 면에 대해서만 그림자를 그려주면 되지만, 햇빛이 닿는 면인지 계산하는 로직이 훨씬 더 복잡할 것 같아서, 단순하게 모든 옆면과 윗면에 대해 생기는 그림자를 다 그리도록 했다.

제공되는 건물 3D 데이터에는 건물 밑면의 폴리곤 데이터와 높이만 있었기 때문에 건물 밑면에서 연속한 두 개의 점과 높이를 통해 한 면의 그림자를 생성했다.

[방법2] 구현 결과

이로써 그림자가 더욱 정교해졌다. 다만 조금 아쉬운건 여러 그림자를 Turf.js의 union 메서드를 이용해서 하나의 그림자로 합치고 싶었는데, 이 부분에서 계속 에러가 발생해 일단 보류중이다. 그래서 일단 각 면마다 각각의 그림자가 그려지고, 많이 겹쳐진 부분은 좀 더 어두운 색을 띄고, 그렇지 않은 부분은 연한 색을 띈다.

기존에 이상하게 그려졌던 오목한 형태의 건물도 꽤나 그림자다워진 모습을 볼 수 있다.

  • 변경 전 INP

  • 변경 후 INP

비록 변경 후에 INP 속도가 두 배 이상으로 느려지긴 했지만... 기존 속도가 워낙에 빨랐고, 지금도 크게 느리게 느껴지지는 않아서 성능을 포기하고 미학을 선택했다. 하지만, 화면을 빠르게 이동했을 때 변경 전에 비해 끊기는 느낌이 생긴 것은 사실이다. 이런 부분은 디바운스 처리를 하거나 로드한 건물 3D 레이어나 그림자 레이어를 캐싱할 수 있는지 등등 다른 방법으로 최적화를 할 수 있지 않을까 생각한다. 그리고 Turf.js의 union 메서드 에러를 해결하면 조금은 나아지지 않을까 싶다.

  • (✅추가 작업) 디바운스 설정 이후 INP

이후에 추가적으로 디바운스 유틸 함수를 만들어서, 위도, 경도, 줌, 각도 값들이 변할 때마다 계속 요청을 보내는 것이 아닌, 100ms 간격 이내의 연속적인 요청에 대해서는 기존 요청을 클리어 후 새로운 요청을 보내도록 설정했다. 디바운스 설정 후에 성능이 비약적으로 상승한 것을 확인할 수 있었다. 그런데, INP 지표가 의미하는 것이 인터렉션 이후 처음으로 무언가 다시 그려지기까지의 시간을 측정하는 것 같은데, 그림자는 분명 늦게 로드되고 있지만 3D 건물 레이어가 로드되는 시점을 기준으로 측정되어 빠르게 나온 것 같다는 느낌이 들었다. 이 부분에 대해서는 추가적으로 찾아봐야 할 것 같다.

사용 후기

요즘 부트캠프 오프라인 출석차 강남으로 가는데, 솔직히 특정 목적지를 가기 위해 이 앱을 사용하지는 않는다. 아무리 덥다고 한들 1초라도 빨리 목적지에 도착하는 게 좋기 때문에 무조건 최단거리로만 간다. 다만, 가기 전에 카페를 들러야 하는 경우 사용하고 있다. 강남역 인근은 어디로 가든 카페 하나쯤은 있기 마련이다. 그래서 맵을 켜서 그늘 위치를 확인한 후 그늘이 많은 쪽에 있는 카페를 경유하여 목적지를 가고 있다.

사실 카카오맵이나 네이버지도 등의 너무 친절한 UI를 보다가 이 Mapbox의 투박한 UI를 보고 있으면 어디가 어딘지 헷갈리긴 한다. 그래서 이 앱을 블로그에 소개할까 망설이기도 했다.

하지만, 한 지인 분께서 잠깐 써보시더니 새로운 사용처를 발견해주셨다. 이 얘길 듣고, 뭐 일단 만들어 놓은거고, 열어놓으면 누군가 또 예상치 못한 사용법을 발견해 줄 수도 있지 않겠나 싶었다. 그리고 그림자 그리는 로직을 좀 더 최적화 하고 싶은데, 누군가 조언해 줄 수도 있지 않을까 싶어 블로그에 소개하게 됐다.

마지막으로 배포중인 URL 링크를 한 번 더 공유하면서 글을 마치도록 하겠다.

배포중인 URL: https://project-g-seven.vercel.app/

profile
Hello, world!

37개의 댓글

comment-user-thumbnail
2025년 7월 13일

어머 너무 신기하다 ^^ 우리 아들보여줘야갰어요 ㅎㅎ

1개의 답글
comment-user-thumbnail
2025년 7월 13일

아이디어 너무 좋습니다! 이렇게 더운날 걸어다닐 때 양산이라도 없으면 진짜 그늘길 찾아 다녀야겠네요~ 더 발전시키면 주소 검색도 생기면 좋을 것 같아요.

1개의 답글
comment-user-thumbnail
2025년 7월 15일

잘 봤습니다! 새롭게 지어진 건물들은 아직 지도에 반영이 안되고 있는 것 같아요!

1개의 답글
comment-user-thumbnail
2025년 7월 15일

와 아이디어도 좋고 생각보다 실제 화면으로 봤을때 잘 보여서 좋네요!
재미있게 잘 읽었습니다!

1개의 답글
comment-user-thumbnail
2025년 7월 15일

와 너무 신박해요 ㅋㅋㅋ 재미있게 보고 갑니다 :)

1개의 답글
comment-user-thumbnail
2025년 7월 16일

재밌는 프로젝트네요 ㅋㅋ

1개의 답글
comment-user-thumbnail
2025년 7월 18일

집 밖에 나갈때마다 너무 더워서 그늘 지도 만들고 싶었는데 3D + 삼각함수로 만드는건 생각도 못했네요. 고등학교 수학으로 소프트웨어를 만들 수 있는게 정말 신기하네요. 아이디어 정말 좋은 것 같습니다. (근데 제가 주로 다니는 길에는 그늘이 없네요 ㅠㅠ) 그늘을 최대한 많이 지나는 길 찾기 기능도 있었으면 좋겠어요😁

1개의 답글
comment-user-thumbnail
2025년 7월 18일

아이디어라는게 여기까지 미칠 수 있는 거군요.... 너무 재밌어요 ㅋㅋㅋㅋㅋ

1개의 답글
comment-user-thumbnail
2025년 7월 19일

잘봤습니다! 재미있는 프로젝트네요! 있을 법한 서비스인거 같은데 단계적으로 구현하는 아이디어가 신선했어요!

1개의 답글
comment-user-thumbnail
2025년 7월 21일

ㅋㅋㅋ 너무 재밌는 아이디어네요!

1개의 답글
comment-user-thumbnail
2025년 7월 21일

우와.. 신기하네요!
프론트 프레임워크 뭐 사용하셨나요 ~_~

1개의 답글
comment-user-thumbnail
2025년 7월 21일

cursor는 매우 유용합니다

1개의 답글
comment-user-thumbnail
2025년 7월 22일

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 벨로그 작성하면서 댓글 처음달아봅니다
아이디어 진짜 신박하네요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

1개의 답글
comment-user-thumbnail
2025년 7월 22일

벨로그 시작하고 처음 댓글 답니다! 아이디어 진짜 재밌어요

1개의 답글
comment-user-thumbnail
2025년 7월 23일

정말 잘 만들으셨네요 ! 투박하다 하셨지만 제가 느끼기에는 미니멀해서 편안합니다 ㅎㅎ
좋은 인사이트 감사합니다

1개의 답글
comment-user-thumbnail
2025년 7월 23일

좀 상스러운 표현일 수 있지만 진짜 '개멋있다'.

1개의 답글
comment-user-thumbnail
2025년 7월 25일

아이디어 대박인데요ㅋㅋㅋㅋ
이걸 직접 구현한 것도 대단...

1개의 답글
comment-user-thumbnail
2025년 7월 26일

와 아이디어에 감탄하고 갑니다 진짜 신박하네요

1개의 답글