Unity
AI로 알아보는 내 자세, 신체균형 체험 개발기
김*재·
시작하며
관람객이 카메라 앞에서 네 가지 자세를 취하면, AI가 어깨·골반 기울기, 거북목, 허리 유연성(전굴·후굴)을 분석해 종합 등급과 추천 운동을 알려 주는 전시 콘텐츠입니다.
짧은 체험에서 가장 무서운 것은 관람객이 납득하지 못하는 결과입니다. 이상한 등급이 한 번 나오면 콘텐츠 전체를 믿지 않게 되기 때문입니다. 이 글은 웹캠 한 대로 "그럴듯하고 납득 가능한" 자세 진단을 만들기 위해 쓴 방법을 정리한 기록입니다.
1. 먼저 화면부터 쪼갰습니다
코드를 작성하기 전에 콘텐츠에 들어갈 화면을 모두 나열하고, 어디서부터 어디로 흐르는지를 먼저 정리했습니다.
정리하고 보니 화면은 모두 11개였습니다.
기본 흐름: 메인 화면, 시작 방식 선택, 체험 방법, 스캔 준비
자세 스캔: 정면, 측면, 앞으로 숙이기, 뒤로 젖히기
결과: 분석 중, 결과, 결과 QR

흐름도를 그리고 나니 구조가 단순하다는 것이 보였습니다. 관람객이 직접 버튼을 누르는 곳은 앞쪽 화면들과 결과 화면뿐입니다. 스캔부터 분석까지는 모두 시간이 지나면 자동으로 넘어갑니다.

대신 자동 전환이 많아서 타이머가 꼬이면 화면이 엉뚱한 곳으로 넘어갈 위험이 컸습니다. 그래서 분석 단계에서 다음 두 가지를 원칙으로 정했습니다.
화면 전환은 시나리오 매니저 한 곳만 거칩니다. 버튼도 타이머도 "조건"만 알리고, 다음 화면은 매니저가 정합니다.
측정 단계는 각 10초, 분석은 5초로 고정하고, 단계가 바뀔 때 이전 측정값이 섞이지 않게 처음에 한 번 초기화합니다.
2. 측정 항목을 '각도 하나'로 줄였습니다
포즈 인식은 MediaPipe PoseLandmarker(BlazePose, 랜드마크 33개)를 썼습니다. 처음에는 여러 관절을 조합한 복잡한 지표를 고민했지만, 전시 콘텐츠에 필요한 것은 의료적 정밀도가 아니라 관람객이 바로 이해할 수 있는 결과였습니다.
그래서 다섯 항목을 모두 "두 점을 잇는 선의 각도" 하나로 정의했습니다.
어깨 · 골반 기울기: 좌우 점을 잇는 선이 수평에서 벗어난 각도
거북목: 귀–어깨 선이 수직에서 벗어난 각도
전굴 · 후굴: 몸통(어깨 중심–골반 중심) 선이 수직에서 벗어난 각도

화면 좌표가 아닌 월드 좌표를 씁니다. MediaPipe의 월드 랜드마크는 골반 중심이 원점인 미터 단위 좌표라서, 관람객이 카메라에서 조금 멀거나 가까워도 각도가 크게 흔들리지 않습니다.
측면 자세에서는 인식 신뢰도가 높은 쪽을 고릅니다. 옆으로 서면 한쪽 귀와 어깨가 가려지기 때문에, 좌우 중
visibility값이 높은 랜드마크로 계산합니다.
계산식이 단순하니 기준값을 조정하거나 이상한 결과를 추적하기도 쉬웠습니다.
3. 순간값이 아니라 '10초 동안의 최댓값'을 썼습니다
허리를 숙이고 젖히는 동작은 시작과 끝의 각도가 전혀 다릅니다. 특정 순간의 값을 쓰면 결과가 운에 좌우됩니다. 그래서 전굴·후굴은 측정 시간 동안 나온 가장 큰 각도를 기록합니다. "최대한 숙여 주세요"라는 안내와 결과가 자연스럽게 맞아떨어집니다.
종합 등급은 점수 합산 대신 "나쁨 항목이 몇 개인가"로 정했습니다.
항목별 판정: 좋음 · 보통 · 나쁨 3단계. 기울기는 작을수록, 유연성은 클수록 좋습니다.
종합 등급: 나쁨 0개면 A, 1개면 B, 2개면 C, 3~4개면 D, 5개면 E입니다.

현장 운영자가 관람객에게 "빨간 항목이 두 개라서 C등급이에요"라고 한 문장으로 설명할 수 있다는 점이 가장 큰 장점이었습니다.
4. MediaPipe 결과는 메인 스레드로 넘겨서 처리했습니다
LIVE_STREAM 모드에서 MediaPipe의 결과 콜백은 Unity 메인 스레드가 아닌 곳에서 호출됩니다. 여기서 UI나 Transform을 바로 건드리면 간헐적으로 예외가 나는데, 재현이 잘 되지 않아 현장에서 가장 잡기 어려운 버그가 됩니다.
그래서 역할을 둘로 나눴습니다.
콜백: 랜드마크 33개를
lock안에서 버퍼에 복사하고, "새 데이터 있음" 플래그만 세웁니다.Update: 메인 스레드에서 플래그를 확인하고, 버퍼를 꺼내 각도 계산과 UI 갱신을 합니다.
계산 로직(PostureAnalyzer)도 MediaPipe 타입에 의존하지 않는 가벼운 구조체로 분리했습니다. 덕분에 카메라 없이 좌표 값만 넣어도 계산을 검증할 수 있었습니다.
5. 화면 흐름은 시나리오 JSON으로 관리했습니다
앞에서 쪼갠 11개 화면의 흐름은 코드에 직접 쓰지 않고 StreamingAssets의 시나리오 JSON에 정의했습니다.
화면 문구: 각 화면의 제목 · 설명 · 버튼 문구가 JSON에 들어 있습니다.
전환 조건: "조건 = 다음 화면" 형식으로 적습니다. 버튼 오브젝트 이름이 곧 조건 이름이라서, 버튼을 누르면 그 조건이 충족되고 매니저가 다음 화면으로 넘깁니다.
자동 전환: 스캔과 분석 단계는 타이머가 조건을 충족시킵니다.
현장 설치 중에 "문구를 조금 바꿔 주세요" 같은 요청이 와도, 다시 빌드하지 않고 JSON만 고치면 됩니다. 전시 콘텐츠에서는 이 차이가 큽니다.
6. 현장에서 카메라가 안 켜질 때
개발 PC에서 잘 되던 웹캠이 전시장 PC에서 안 켜지는 일이 가장 많았습니다. 원인은 대부분 코드가 아니라 환경이었습니다.
윈도우 카메라 권한: "데스크톱 앱에서 카메라에 액세스"가 꺼져 있으면 Unity 빌드에서는 카메라 목록이 비어 있습니다. 가장 흔한 원인입니다.
다른 앱이 카메라를 점유: Teams, Zoom, OBS가 백그라운드에서 카메라를 잡고 있으면 프레임을 받지 못합니다.
Visual C++ 런타임 누락: MediaPipe는 네이티브 DLL을 쓰기 때문에, 재배포 패키지가 없는 PC에서는 초기화부터 실패합니다.
엉뚱한 카메라가 0번으로 잡힘: 가상 카메라나 IR 카메라가 첫 번째 장치로 잡힐 수 있습니다.
이 항목들을 운영 매뉴얼의 체크리스트로 만들어 두었더니, 현장 문의가 와도 원격으로 빠르게 해결할 수 있었습니다.
마치며
깊이 센서 없이 웹캠 한 대였지만, 관람객이 납득할 수 있는 자세 진단 콘텐츠를 만들 수 있었습니다. 돌아보면 복잡한 알고리즘보다, 단순하게 정하고 현장을 먼저 생각한 결정들이 콘텐츠를 지켜 주었습니다.
화면 분석을 먼저: 11개 화면과 전환 조건을 먼저 정리하니 구현할 범위가 분명해졌습니다.
측정은 단순하게: 다섯 항목을 모두 각도 하나로 정의하니 기준 조정과 검증이 쉬워졌습니다.
결과는 설명 가능하게: 최댓값 측정과 "나쁨 개수" 등급으로 관람객과 운영자 모두 결과를 바로 이해할 수 있었습니다.
현장을 먼저 생각하기: 스레드 분리, JSON 시나리오, 카메라 체크리스트가 설치 이후의 시간을 줄여 주었습니다.
전시 콘텐츠는 설치하는 순간부터가 진짜 운영입니다. 개발할 때부터 현장에서 고치기 쉬운 구조를 함께 설계해 두시길 권합니다.
읽기 도구
약 7분 읽기
이 글이 도움이 되었나요?
Work with GIWorks
프로젝트에 GIWorks의 경험이 필요하신가요?
전시·콘텐츠·엔지니어링 프로젝트의 아이디어와 고민을 들려주세요. 필요한 기술과 실행 방법을 함께 찾겠습니다.
문의하기