본문으로 건너뛰기

Seoul Meari

시민의 일상이 도시의 미래가 되는 MR 소셜 플랫폼

개요

기간

2025.08 ~ 2025.09

개요

팀 프로젝트

역할

유니티, 프론트엔드, 백엔드, AR/VR 활용, AWS 서버 구축

🏆

2025 서울 AI 해커톤 - 서울특별시장상(대상 - 1등)

주요 기능

공간 메아리(AR 방명록), 시간 탐험(VR 역사 체험), AI 도시 진단

사용 기술

ReactNest.jsFastAPIUnityC#AR/VRAWSPostgreSQLPostGIS

구현 기능 및 개발 과정

공간 메아리 (AR 방명록)

앱 기반 AR 카메라에서 남기는 위치 고정 소셜 시스템
격자 내 메시지 호출ID 등록언로드사용자 이동현재 GPS 격자 판정생성 큐오브젝트 스폰해시 테이블 관리격자 이탈
격자 단위로 메시지를 호출하고 큐로 스폰해 해시 테이블로 관리함.

GPS 영역을 격자로 나누고, 사용자 이동 시 해당 격자의 메시지를 불러옴. 진입 격자와 이탈 격자를 큐로 전달함. 생성된 오브젝트는 해시 테이블로 관리함.

시간 탐험 (장소 인식형 역사 VR)

GPS 기반 과거 풍경/3D 오브젝트 렌더링
에셋 번들메타데이터패키지 메타데이터 조회병렬 다운로드매니페스트 → 의존성 → 타겟 순관리자CDN서버클라이언트로컬 캐시인게임 로드
번들과 메타데이터를 CDN·서버에 나눠 올리고, 클라이언트가 병렬 다운로드와 로컬 캐시를 거쳐 순서대로 로드함.

GPS에 기반하여 특정 랜드마크의 근처에 있으면, 해당 장소의 과거 이미지/3D 오브젝트/해설을 VR 세계에 생성. 다양한 기업과 이벤트형 공간 생성 가능

관리자는 에셋 번들과 메타데이터를 각각 CDN과 서버에 업로드. 클라이언트는 패키지(예: gyeongbokgung_v1) 메타데이터 조회 → CDN 병렬 다운로드 → 로컬 캐시 → 인게임에서 매니페스트/의존성/타겟 번들 순으로 로드.

AR 도슨트

사진, GPS 기반의 멀티 모달 자료 설명
주변 환경·맥락 해석AR 오버레이사용자 촬영 사진AI 도슨트위치 정보역사·사건·공간 특징직관적 안내
사진과 위치를 입력으로 AI 도슨트가 맥락을 해석해 AR로 안내함.

사용자가 촬영한 사진과 위치 정보를 기반으로, AI 도슨트가 주변 환경과 맥락을 설명함. 건물의 역사, 사건의 의미, 공간적 특징 등을 AR로 직관적으로 안내함.

AI 도시 진단 엔진 (팀원 담당)

촬영 데이터의 배경을 비동기 분석해 이상 탐지
익명화 원본Presigned URL 업로드위험 요소 감지·분류중복 보고 통합사용자 촬영Yolo 태깅분석 파이프라인클러스터링신뢰도 리포트대시보드 시각화
촬영 데이터가 Yolo 태깅 → 분석 → 클러스터링을 거쳐 신뢰도 점수와 함께 대시보드로 시각화됨.

사용자 촬영 데이터의 원본(익명화)을 Yolo가 포트홀/균열/기울어진 간판/녹슨 가로등 등을 태깅함. 태깅한 정보를 바탕으로 서버에 업로드하면, 비전 모델이 위험 요소를 감지·분류함. 반복 탐지/중복 보고를 클러스터링으로 통합해 신뢰도 점수와 함께 리포트를 생성함.

Presigned URL 기반 업로드 → 분석 파이프라인 → 클러스터링/중복 통합 → 대시보드 시각화(히트맵/증거 이미지/처리 상태)로 구성함.

위치 데이터 저장·조회 서버 (PostGIS)

Unity 앱서버주변 5×5 · 이동 시 새 줄만없는 격자만 · 동시 5건ST_Y·ST_X 범위 조건격자 안 메시지주변 3×3 격자위도·경도·고도Point로 변환해 저장앱 시작·격자 이동격자 캐시격자 조회 APIPostGIS 좌표 열메시지 스폰AR 메시지 작성·VR장면 등록저장 API
AR 메시지와 VR 장면은 같은 PostGIS 좌표 열에 저장되고, 앱은 캐시에 없는 격자만 서버에 요청해 받은 메시지를 주변 3×3 격자에만 띄움.

저장 형식: AR 메시지와 VR 역사 장면 번들의 위치를 모두 PostGIS geography(PointZ, 4326) 열에 저장하고 공간 인덱스를 선언함. 좌표는 GeoJSON 순서(경도·위도·고도)로 저장하고, 응답할 때 위도·경도·고도 객체로 바꿔 반환함.

AR 메시지 조회 순서: ① 앱이 시작되면 현재 GPS 좌표를 0.0001도(약 10m) 단위 격자 좌표로 변환하고, 주변 5×5 격자를 요청 큐에 넣음. ② 큐의 격자를 동시에 최대 5건까지 GET /echo/nearby로 요청함. 이미 캐시에 있는 격자는 요청하지 않음. ③ 서버는 격자 기준점부터 격자 간격만큼의 위도·경도 범위를 ST_Y·ST_X 조건으로 조회해, 해당 격자 안의 메시지만 반환함. ④ 응답은 격자 정수 좌표를 키로 캐시에 저장하고, 주변 3×3 격자의 메시지만 화면에 스폰함. ⑤ 사용자가 다른 격자로 이동하면 새로 포함된 줄의 격자만 다시 요청함.

AR 메시지 작성 순서: ① 사진을 Presigned URL로 S3에 먼저 업로드함. ② 메시지 저장 요청이 오면 서버가 S3에 해당 이미지 키가 있는지 확인함. ③ 위도·경도·고도를 GeoJSON Point로 변환해 메시지와 함께 저장함.

VR 장면 등록 순서: ① 관리자가 레이아웃 JSON을 올리면 관리자 웹이 mainLocation의 위도·경도·고도를 입력칸에 자동으로 채움. ② 서버가 업로드 세션을 만들고 번들 파일마다 5분간 유효한 Presigned URL을 발급함. 관리자 웹은 이 URL로 번들 파일을 S3에 직접 업로드함. ③ 업로드 완료 요청이 오면 서버가 레이아웃 JSON 구조와 좌표 값을 검사함. ④ 트랜잭션 안에서 업로드 세션에 비관적 잠금을 걸어 같은 업로드가 두 번 처리되지 않게 함. 이후 위치를 Point로 변환해 번들과 함께 저장하고, 세션을 완료 상태로 바꿈.

트러블슈팅

GPS 튐으로 메시지 위치 튐

ID값 기반의 Equal 메소드 오버라이드
활성화된 메시지 딕셔너리의 ID 값 조회를 통한 불필요한 렌더링 방지
smoothingFactor 0.1 보간보이는지 판단스폰 순간만 최신 GPSID·해시 테이블 렌더보정 전 GPS보정 좌표스폰 결정오브젝트 생성위치 유지
보정 전 GPS를 보간해 얻은 보정 좌표로 보이는지 판단하고, 스폰 순간만 최신 GPS로 보완함.
문제

실제로 이동하지 않아도 GPS 좌표가 수 미터씩 변동함. 이에 따라 화면에 표시된 메시지가 다른 위치로 이동함.

분석

보정 전 GPS 값을 좌표로 사용하면 측정 오차가 화면 이동에 그대로 반영됨. 값의 변동을 완화하고 이미 생성된 오브젝트를 재생성하지 않는 처리가 모두 필요함.

해결

보정 좌표를 이전 값과 새 값 사이에서 0.1의 비율로 이동시켜 급격한 위치 변화를 줄임.

해결

보정 좌표를 기준으로 메시지가 보이는지 판단해 스폰하며, 실제 스폰 시점은 최신 GPS로 보완함.

해결

이미 생성된 메시지 오브젝트는 ID 및 해시 테이블을 기반으로 렌더링됨.

결과

급격한 GPS 변화에도 렌더링된 위치를 유지함.

XR 카메라 충돌

Cesium의 Dynamic Camera(BG Camera)를 XR Origin 아래로 이동
Dynamic Camera에 카메라의 이동을 포착하는 Track Pose Driver 부착
Dynamic Camera 를 XR Origin 아래로 이동메인 카메라 제거Tracked Pose Driver 부착XR Origin 메인카메라카메라 요구 충돌Cesium Georeference카메라메인 카메라가 계속화면 점유Dynamic 카메라일원화기기 자세 추적 정상화
XR Origin과 Cesium Georeference의 카메라 요구가 충돌해, 메인 카메라를 제거하고 Dynamic 카메라에 Tracked Pose Driver를 붙여 기기 자세 추적을 일원화함.
문제

카메라가 가상 세계를 비추지만 휴대폰을 움직여도 화면이 함께 움직이지 않음.

분석

XR Origin과 Cesium Georeference가 각각 카메라를 요구해 충돌함. 두 카메라 중 어느 쪽이 기기 자세를 받는지 확인해야 했음.

분석

XR Origin과 Cesium Georeference가 각각 카메라를 요구해 충돌함.

분석

Tracked Pose Driver는 기기 자세를 카메라에 전달하는 컴포넌트임. XR Origin의 메인 카메라에 이 컴포넌트가 붙어 있었음.

분석

Dynamic Camera를 XR Origin 아래로 옮겼으나, 메인 카메라가 실제 화면을 계속 비추고 에러도 남았음.

해결

메인 카메라를 제거하고 Dynamic 카메라에 해당 컴포넌트를 적용해 충돌을 해결함.

Cesium 월드에서 비정상 이동

Anchor/Transform 상호작용과 Origin Shift
AR·VR 충돌1차: Detect Transform Change 해제Georeference가 플레이어를 못 따라옴GPS 초기 위치를 Georeference 원점으로GPS 10초 갱신Globe Anchor 반영제자리 위치 튐Anchor GPS 갱신 중단한계 확인기준점 고정안정된 이동
AR·VR 충돌로 튀던 위치를 GPS 초기값을 Georeference 원점으로 고정해 해결하기까지의 단계.
문제

GPS 갱신 때마다 위치가 갱신되면서 가만히 있어도 위치가 튀는 문제가 발생함. 10초마다 갱신되는 것으로 보아 GPS와 관련된 문제일 것이라 추측함.

분석

GPS의 값이 과도하게 Cesium Globe Anchor에 반영되었다고 생각하여 Anchor 값과 Transform 값을 모두 로그로 출력해 원인을 확인함

분석

AR과 VR의 충돌이 원인으로 드러남.

해결

초기에는 Cesium Globe Anchor에서 Detect Transform Change를 해제하여 해결함

문제

카메라 transform 변화에도 날아다니진 않지만, Anchor의 GPS 값은 갱신되지 않음

분석

CesiumOriginShift는 플레이어가 멀리 이동할 때 부동소수점 정밀도 문제를 막기 위해 Georeference 기준점을 주기적으로 플레이어 근처로 옮겨주는 역할을 함

문제

하지만 이렇게 하면 Cesium Georeference가 플레이어를 따라오지 않음

해결

따라서 GPS의 초기 위치를 Cesium Georeference 기준으로 설정함

결과

결과

Unity 2022.3 LTS 환경에서 AR/VR 통합을 시도하며 GPS, SLAM, VPS, Cesium Georeference 등 다양한 위치 맞춤 기술을 학습함.

GPS 튐 현상을 Lerp 기반 스무딩으로 보정하는 방법을 적용하고, XR Origin과 Cesium Dynamic Camera의 충돌 문제를 해결하며 카메라 시스템의 구조를 이해함.

대용량 JSON은 한 번에 읽지 않고 스트리밍으로 처리해야 함을 확인함.

라이선스