카테고리 없음

유리볼 구현하기

elaus 2026. 6. 30. 12:47

0. 개요

이번에 디프만 18기 활동을 하면서 개발 과정에서 겪은 시행 착오에 대해서 회고를 남기고자 합니다. 비록 안드로이드 파트로서 디프만에 참여하기는 했습니다만, iOS 제가 담당했었기에 이 글은 iOS 기준으로 작성 하였습니다.

 

사실 AI의 발전으로 인해 웬만한 화면은 AI로도 쉽게 구현할 수 있게 되었습니다. 특히 Figma에 잘 구조화된 디자인이 있다면, 화면 구현 자체는 더 이상 아주 어려운 일이 아닐지도 모릅니다. 그럼에도 UI 구현을 회고로 남기고자 하는 이유는 세 가지입니다.

첫째, Figma 디자인 만으로 드러나지 않는 디자이너의 의도를 반영하는 것은 AI가 할 수 없는 일이고 둘째, Figma의 블렌드 효과나 기타 효과를 코드단에서 1대1로 반영이 불가능한 경우에는 개발자의 실험이 필요하며 셋째로, 반응형을 고려하거나 디자인의 디테일한 요소를 잡는 것은 시각적 확인과 꼼꼼함이 필요한 영역이기 때문입니다.

 

이 글에서는 제가 겪은 시행착오를 정리하고, 적어도 아직은 AI가 대신하기 어려운 화면 구현 단계에서의 인간 개발자의 역할에 대해서도 이야기해보고자 합니다.

 

1. 문제정의

저희 팀이 만든 앱은 소모품 관리를 체계적으로 도와주는 obrit입니다. (플레이스토어와 앱스토어에서 다운로드 가능합니다!)

이 앱의 특징이라고 한다면, 소모품을 등록했을 때 등록된 소모품이 홈 화면의 유리볼에 노출이 되고, 그 유리볼에 인터렉션을 넣어서 재미요소를 더했다는 점일텐데요, 이 유리볼을 구현하는 것이 중요한 도전과제였습니다. 

 

디자이너의 figma 디자인 원본

저는 이번에 기획자가 아닌 개발자로 동아리에 참여했기 때문에, 기획을 맡은 디자이너의 의도를 최대한 반영하는데 집중했습니다. 아래는 당시 정리했던 요구사항들인데요, 실제로 이 모든 요구사항을 한 번에 전달받았다기보다는, 제가 구현 과정에서 세부 요구사항으로 나누어 정리한 내용에 가깝습니다. 제가 아이디어를 내서 추가한 부분도 있고요.

요구사항
1. 유리볼처럼 보여야 한다
2. 유리볼 안의 물품들이 들어간다
3. 유리볼 안에 들어간 물품을 손으로 움직일 수 있어야 한다
4. 유라볼 안의 물품들은 쌓인 느낌을 주어야 한다
5. 유리볼 외곽에 상태를 표시하는 링이 있어야 한다
6. 해당 링의 색이 유리볼 표면에 비쳐보여야 한다
7. 유리볼의 그림자가 하단에 표현되어야 한다
8. 유리볼 좌우에 상태 문구가 표시되고, 해당 문구 뒤에 그라데이션으로 위험도에 따른 색이 표시되어야 한다
9. 유리볼 안의 물품 표면에 링의 색이 비쳐보여야 한다
10. 폰을 기울임에 따라 안의 물품들이 움직여야 한다
11. 전반적으로 Glassmorphic한 느낌이 나야 한다.

 

이렇게 정리하니 꽤 많아 보이지만, 실제 구현 과정에서는 고려해야 할 사항이 더 많았습니다.

 

예를 들어 유리볼 안에 들어가는 물품들의 크기는 어떻게 정할 것인지, 물품들이 서로 충돌했을 때는 어떻게 처리할 것인지, 물품들은 어느 정도 깊이감 있게 겹쳐야 하는지, 물품들이 유리볼 끝에 닿았을 때는 어떻게 보여야 하는지 등을 고민해야 했습니다. 그 자리에서 멈춰야 하는지, 아니면 부딪힌 뒤 다시 튕겨 나와야 하는지처럼 세부적인 이슈도 많았습니다.

 

2. 구현과 시행착오

구현하는 과정과 그 방식에 있어서도 시행착오가 있었습니다.

 

처음에는 다른 화면들처럼 Figma MCP를 활용해서 구현을 하고자 했습니다. 그렇게 초안을 잡아두고, 실제 디자인과의 차이를 눈으로 확인하며 수정하는게 다른 화면들 구현하는게 빠르면서도 정확했었거든요. 그런데, 이 경우는 결과가 좀 달랐습니다. 몇번을 프롬프팅을 다시해서 돌려봐도, 제가 원하는 결과물이 잘 나오지 않더라구요. 

시도해본 구현 방식
- Figma 디자인을 AI에게 던져주고 알아서 구현해보라고 하기
- 요구사항을 명확히 정의한뒤, Figma 디자인과 함께 AI에게 구현시키기
- Figma 레이어 분석해서 직접 구현하기

 

특히 유리볼은 여러 레이어가 겹쳐져 있고, 특수 효과가 많이 필요한 UI였습니다. 그래서 AI에게 한 번에 맡기는 방식만으로는 원하는 수준의 결과를 얻기 어려웠습니다. 결국 Figma 레이어를 직접 분석해 구현하는 과정이 필요했습니다.

유리볼 디자인. 이 디자인을 최대한 구현하는 것이 프론트 개발자의 덕목이지 않을까.

처음에는 3D 라이브러리를 활용해봤어요. 안의 아이템들도 3D 아이템 에셋 형식으로 받아서 렌더링하는 방식으로요. 그런데 그렇게 하다보니 두 가지 문제점이 있었는데, 하나는 너무 무거워져서 렌더링에 시간이 상당부분 소요된다는 것이었고, 다른 하나는 그에 비해 드라마틱한 Glassmorphic한 효과가 나오지 않는 다는 것이었습니다. 그래서 이 방법은 포기하게 되었죠. 이후에 Codex와 함께 어떻게 구현하면 좋을지 논의 했고, 시각적으로는 3D틱하게 보이지만, 실제로는 2D로 구현해서 시각적 착각을 주기로 결정했습니다. 

유리볼 Figma 컴포넌트

먼저 유리볼의 시각적 구현부터 진행했습니다.

Figma 디자인의 레이어 단계를 분석해보았을 때, 가장 아랫단에는 상태를 보여주는 링이 있었고 그 위에는 유리볼의 그림자를 표현한 그라데이션 레이어가 있었습니다. 그리고 그 윗단에는 링에 빛이 비쳐서 안에 아이템들에 반사되는 효과를 표현한 레이어가 있었습니다. 가장 윗 레이어가 물품들이 들어있는 유리볼이었죠. 그리고 blend효과를 통해 하위 레이어에도 상위 레이어의 효과가 적용되고 있었습니다. 이를 그대로 코드로 구현했고, 시각적으로 거의 유사하게 만들 수 있었습니다. 

 

이후에 물리 엔진을 적용했습니다. 이 때, 각 아이템들을 두 개의 노드로 나눴습니다. 하나는 충돌만 담당하는 물리 노드이고, 다른 하나는 실제 이미지를 보여주는 스프라이트 노드입니다. 두 개로 나눈 이유는 미세 떨림 효과 보정와 3D 효과를 보여주기 위함이었습니다.

 

처음에 별도의 분리 없이 이미지에 바로 물리 엔진을 적용하다보니 제대로 안정화되지 못하고 물품이 쌓이는 과정에서 미세하게 떨리는 현상이 발생했습니다. 또한 당초 요구사항은 물품이 어느정도 겹치면서 쌓이는 것이었기 때문에 2D 이미지가 그대로 반영되는게 아닌, 어떤 것은 앞으로 오고 어떤것은 뒤로가는 모습이어야 했죠.

 

게다가 아이템 이미지마다 투명 여백과 비율이 달랐기 때문에, 보이는 크기에 맞춰 충돌 반경을 잡으면 큰 오브젝트가 너무 빨리 밀려나거나, 가장자리에서 잘리는 문제가 발생했습니다. 반대로 충돌 반경을 크게 잡으면 물건들이 자연스럽게 쌓이지 않는 문제가 있었습니다. 여러 실험을 해보며 가장 안정적으로 동작하는 비율을 찾기 위해 노력했고, 최종적으로는 시각 크기보다 작은 원형 물리 반경을 쓰고, 아이템 수가 많아지더라도 안정적으로 쌓일 수 있도록 반경 상한을 조절했습니다. 또한 유리볼 자체의 경계도 보이는 유리 테두리보다 살짝 안쪽에 만들어서 아이템에 유리볼 밖을 벗어나는 것처럼 보이는 일이 발생하지 않도록 했습니다.

 

다만 이 과정에서 일부 시각적 효과는 포기해야 했습니다. 바로 유리볼 외곽 링에 표현된 현재 상태가 아이템에 반사되어 보이는 효과가 구현되지 못한 것인데요, 시각 노드를 SwiftUI기반이 아닌, SpriteKit의 Shader로 구현하다보니 SwiftUI단에서 구현된 blend효과가 적용되지 않았습니다. 이걸 해결하기 위해서 각 아이템에 대해서 표면에 빛이 반사되는 효과를 적용해보려고 하기도 했었는데요, 아쉽게도 만족할만한 성과는 거두지 못했습니다.

 

결론

실제 구현된 유리볼

 

AI가 없었다면 애초에 도전하기 어려웠을 과제였지만, 동시에 AI의 한계를 확인할 수 있었던 과제이기도 했습니다. 물론 AI의 한계라기보다는 제 한계일 수도 있겠지요. 여하튼 이 유리볼 덕분에 좋은 평가를 받은 부분도 있다고 생각을 해서 개인적으로는 꽤나 만족할 수 있던 결과인 것 같습니다.

 

항상 글 쓸때마다 느끼지만, 처음 시작하는게 어렵고 또 끝내는게 어렵네요. 이 글은 여기서 마무리짓겠습니다.

 

끝!