한 장의 2D 이미지로 만드는 2.5D 상품 뷰어 대표 이미지

한 장의 2D 이미지로 만드는 2.5D 상품 뷰어

2025. 12. 20.

X에서 우연히 흥미로운 글을 발견했다. Google의 AI 이미지 생성 모델인 나노바나나 프로로 2D 이미지에서 텍스처를 생성하고, 이를 Three.js에 적용해 입체감 있는 모델링을 만드는 글이었다.

https://x.com/tkm_hmng8/status/1996037744305570235

이 글을 보며 문득 아이디어가 떠올랐다. AI를 활용하여 전문 3D 디자이너가 아니어도 그래픽스에 필요한 리소스를 쉽게 생성할 수 있다면, 전자 상거래(E-Commerce)에서도 새로운 사용자 경험을 만들어낼 수 있을 것 같았다. 그래서 실제로 2D 상품 이미지를 AI로 필요한 텍스처 이미지를 생성하고, 이를 2.5D 모델에 적용해 입체감 있는 상품 뷰어를 만드는 실험을 해보았다. 이 글에서는 그 실험 과정과 결과를 공유하고자 한다.

그래픽스의 필요성

"전자 상거래에 왜 그래픽스가 필요한가?" 하는 의문이 들 수 있다. 사실 그래야만 하는 이유는 없다. 하지만 사람들은 더 현실적이고 생생한 경험을 선호하는 경향이 있다. 더 예쁘고 멋진 것을 좋아하는 것은 인간의 본능이라고 생각한다.

최근 수년간 하드웨어 발달로 일반 사용자 기기의 스펙이 향상되면서, 3D 게임을 넘어서 일반적인 영역에서도 웹과 네이티브를 구별하지 않고 그래픽스를 활용한 UI/UX가 점점 늘어나고 있다.

예를 들어, Apple은 새로운 디자인 언어인 리퀴드 글래스를 운영체제 전반에 도입하면서, 셰이더 효과를 활용한 실제 유리 느낌의 UI를 제공하고 있다. 도입 전에는 성능 문제를 우려했지만, 도입 후 가시성 이슈는 있어도 성능 이슈는 크게 두드러지지 않았다. 이것이 가능한 이유는 Apple의 A 시리즈와 M 시리즈 칩셋의 GPU 성능 향상이 뒷받침된 덕분이다.

국내에서도 일반 사용자 대상의 서비스에서 그래픽스를 활용하는 사례가 점점 늘어나고 있다. 주로 디자인을 중시하는 서비스에서 보이고 있는데, 토스에서는 어느 시점부터 다양한 사용자 인터랙션에 2D 셰이더 효과가 보이기 시작했다. 페이스 페이를 소개할 때도 3D 모델링을 활용했다. 우아한 형제들에서도 최근 우아콘 2025 행사에서 Three.js를 활용한 UI 사례를 소개했다.

물론 예전부터 3D 그래픽스가 기술적으로 필요해서 도입한 사례는 있다. 하지만 내가 예시로 든 사례들은 일반 사용자가 반복적으로 실행하는 환경에서 굳이 도입할 필요 없지만, 더 멋지고 예쁜 사용자 경험을 제공하기 위해 도입한 경우다. 일상에서 자연스럽게 더 나은 경험을 제공하는 사례가 앞으로 더 늘어날 것이라 생각한다.

본론에 들어가기에 앞서 이 글에서 '그래픽스'는 셰이더 효과를 사용하는 작업으로 의미를 한정한다. 그래픽스 지식을 어느 정도 필요로 하지만, 완전한 3D 모델링이나 렌더링까지는 포함하지 않는다. 2.5D 정도의 개념으로 생각하면 된다.

텍스처는 그래픽스에서 모델의 표면에 효과를 입히기 위한 리소스를 의미하며, 모델의 색상과 질감, 반사율 등을 정의하는 데 사용된다. 이 글에서는 알베도 맵과 노멀 맵, 깊이 맵을 사용한다.

  • 알베도 맵(Albedo Map)은 물체의 기본 색상 정보를 담은 이미지로, 조명이나 그림자 효과 없이 순수한 표면 색상만 표현한다.
  • 노멀 맵(Normal Map)은 표면의 미세한 굴곡과 세부 묘사를 표현하는 텍스처로, 빛이 표면에 닿는 반사 방향을 변경하여 입체감을 더한다.
  • 깊이 맵(Depth Map)은 표면의 높낮이 정보를 담은 이미지로, 밝은 부분이 높고 어두운 부분이 낮음을 나타내어 입체감을 표현한다.

실험 방법과 결과

전자 상거래에서 상품 이미지를 보는 경험을 향상시키기 위해, 앞서 말했듯 AI를 활용해 2D 상품 이미지로부터 텍스처 이미지를 생성하고, 이를 그래픽스 기술과 결합하여 입체감 있는 제품 표현을 시도했다.

방법은 간단하다. 나노바나나 프로로 원본 이미지에서 필요한 텍스처 이미지를 생성한 뒤 이를 2.5D 모델에 적용해 사용자가 상품을 입체적으로 볼 수 있게 만드는 것이다.

우선, 결과부터 공유해보겠다.

실험에 사용된 원본 이미지는 네이버 스마트 스토어에서 제공하는 AirPods 3 Pro 상품 이미지이다.

이를 바탕으로 나노바나나 프로를 활용하여 노멀 맵 텍스처와 깊이 맵 텍스처로 사용할 이미지를 생성했다. 원본 이미지는 알베도 맵 텍스처로 사용했다.

이를 바탕으로 자체 제작한 그래픽스 엔진을 활용하여 2.5D 모델을 만들고, 사용자가 마우스 움직임을 통해 제품을 입체적으로 볼 수 있도록 구현했다.

구현된 결과는 다음 영상과 같다.

네이버 스마트 스토어와 유사한(?) 프리뷰 화면을 자체 제작하여 적용해본 모습이다. 2D의 원본 이미지 한 장만으로도 꽤 자연스럽고 입체감 있는 모델을 만들 수 있었다. 사용자 움직임에 따라 자연스럽게 빛이 반사되는 모습을 볼 수 있으며, 원본 이미지에는 없는 디테일한 부분도 어느 정도 표현되는 것을 확인할 수 있다.

물론 완벽하지는 않다. 특히, 복잡한 형태의 제품은 깊이 맵 텍스처 생성이 어려워서 입체감이 떨어지는 경우가 있다. 실험에 사용된 에어팟 프로 이미지의 경우 비교적 단순하고 매끄러우며, 빛이 반사되어도 크게 어색하지 않은 형태라서 좋은 결과를 얻을 수 있었다.

그리고 Three.js 등 검증된 그래픽스 라이브러리를 활용했다면 텍스처 품질을 더 향상시킬 수 있었을 것이다. 다만, 이번 실험에서는 자체 제작한 그래픽스 엔진을 활용해보았다. 스스로도 정말 될까 하는 마음에 시도해본 것이었는데, 의외로 괜찮은 결과가 나와서 놀랐다.

실험 구현 과정

프롬프트 작성

나노바나나 프로를 활용하여 원본 이미지를 텍스처 이미지로 변환하려면, 적절한 프롬프트를 작성하는 것이 중요하다. 글 도입부에서 소개했던 X에서 보았던 글에서 일본어로 작성된 프롬프트를 참고하여, 이를 필자의 환경에 맞게 변형했다. 아래는 실험에 사용한 노멀 텍스처 맵 생성을 위한 프롬프트이다.

Markdown
첨부한 이미지를 기반으로 표면 노말 맵(Surface Normal Map) 이미지를 생성하세요.
 
출력은 RGB 이미지 한 장이며 각 픽셀은 표준 탄젠트 공간(Tangent Space) 형식의 표면 노말 방향을 다음과 같이 인코딩합니다:
 
- R = X 방향
- G = Y 방향
- B = Z 방향
 
요구사항:
 
- 입력 이미지와 동일한 해상도와 종횡비를 유지할 것
- 붓터치, 명암, 윤곽 등에서 자연스럽게 추론되는 표면의 굴곡을 기준으로 노말 방향을 생성할 것
- 새로운 요소를 추가하거나 재해석한 그림을 만들지 말 것
- 가능한 미세한 표면 형태와 방향만 합리적으로 추론할 것
- 노이즈 없이 부드럽고 일관된 노말 변화를 유지할 것

이 프롬프트를 사용하여 생성한 노멀 맵 텍스처 이미지는 다음과 같다.

프롬프트는 영문과 한글 모두 시도해보았는데, 생성 결과에 체감되는 차이는 없었다.

그래픽스 지식이 없는 상태라면, 프롬프트에 생소한 용어가 많아 이해하기 어려울 수 있다. 노멀 맵 텍스처의 경우, 핵심은 AI 모델에게 표면의 방향 정보를 RGB 값으로 인코딩하는 방식을 설명하는 것이 중요하다.

특히, 텍스처의 경우 2D 이미지인데, 이를 3D 모델에 적용해야 하므로 2D 공간을 3D 공간으로 매핑하는 방법을 명확히 이해해야한다. 이를 위해 탄젠트 공간(Tangent Space) 개념을 활용했다.

잠깐 좌표 체계에 대해 설명하자면, 2D인 텍스처 이미지를 3D 모델에 입히려면 크게 세 가지 좌표 체계를 거친다. 귀여운 스티커를 스타벅스 텀블러에 붙인다고 상상해보자.

  • UV 좌표계는 2D 텍스처 이미지의 위치를 표현한다. 스티커 내부의 각 픽셀이 텀블러 표면의 어느 위치에 붙을지를 나타낸다.
  • 월드 좌표계는 3D 공간에서 물체의 절대 위치를 나타낸다. 스타벅스 텀블러가 화면의 어디 있고, 어떤 각도로 회전되어 있는지 등을 표현한다.
  • 탄젠트 공간은 모델 표면의 각 점마다 존재하는 상대적인 좌표계로, 스타벅스 텀블러 표면의 특정 지점이 어느 방향을 향하든 그 표면에 딱 붙어서 함께 움직인다.

프롬프트 결과로 제공되는 이미지의 RGB 값을 통해, 각 픽셀의 표면이 가리키는 방향(노말 방향 혹은 노말 벡터)을 탄젠트 공간에서 표현할 수 있다. R 채널은 X 방향, G 채널은 Y 방향, B 채널은 Z 방향을 나타낸다. 이를 통해 그래픽스 엔진이 빛의 반사 방향을 계산하여 입체감을 표현할 수 있다.

실제 셰이더 코드에서는 이 과정을 TBN 행렬(Tangent-Bitangent-Normal Matrix)을 통해 구현한다. TBN 행렬은 노말 맵 이미지의 RGB 값으로 표현된 탄젠트 공간의 방향 정보를 월드 좌표계로 변환하는 역할을 한다. 아래는 WebGPU 셰이더 언어(WGSL)로 작성한 TBN 행렬 생성 함수에서 핵심만 정리한 코드이다.

WGSL
fn buildTBN(normal: vec3f, tangent: vec3f) -> mat3x3f {
  let N = normalize(normal);
  let T = normalize(tangent);
  let B = normalize(cross(N, T));
  return mat3x3f(T, B, N);
}

이 함수의 normal은 모델 표면이 바깥쪽을 향하는 수직 방향을 의미한다. 스타벅스 텀블러 표면에 수직으로 꽂힌 화살표를 떠올리면 된다. tangent는 그 표면을 따라 수평으로 흐르는 방향이다. 텀블러 표면을 따라 가로나 세로로 그어진 선이라고 생각하면 쉽다.

입력받은 normaltangent를 각각 정규화(Normalize)해서 N과 T를 만들고, 이 둘에 수직인 비탄젠트 벡터(B)를 외적(Cross Product)으로 계산한다. 세 벡터로 구성된 3x3 행렬이 바로 TBN 행렬이다.

이 행렬을 사용하면 노말 맵에서 읽어온 RGB 값을 실제 3D 공간에서 의미 있는 방향 정보로 변환할 수 있고, 그 결과로 빛이 표면에 닿았을 때 어느 방향으로 반사되는지 계산하여 사실적인 입체감을 만들어낼 수 있다.

다음으로 깊이 맵 텍스처의 경우, 노멀 맵과 유사한 방식으로 프롬프트를 작성했다. 깊이 맵은 표면의 높낮이 정보를 담고 있으므로, 밝은 부분이 카메라에 가깝고 어두운 부분이 멀어짐을 나타내도록 지시했다. 아래는 깊이 맵 생성을 위한 프롬프트이다.

Markdown
첨부한 이미지를 기반으로 깊이 맵(Depth Map) 이미지를 생성하세요.
 
출력은 다음을 의미하는 단일 그레이스케일 이미지입니다:
 
- 흰색 = 카메라에 가까움
- 검은색 = 멀어짐
 
요구사항:
 
- 입력 이미지와 동일한 해상도와 종횡비를 유지할 것
- 깊이는 부드럽고 연속적이며 물리적으로 타당해야 함
- 원본 명화에서 합리적으로 존재할 수 있는 기하학적 깊이만 추론할 것
- 새로운 객체나 디테일을 추가하지 말 것
- 스타일화하거나 재해석하지 말 것
- 질감 노이즈를 피하고 깊이 구조에만 집중할 것

이 프롬프트를 사용하여 생성한 깊이 맵 텍스처 이미지는 다음과 같다.

깊이 맵을 활용할 때는 패럴럭스 매핑(Parallax Mapping)이라는 기법을 사용하는데, 셰이더 코드를 소개하려면 카메라 방향 계산과 UV 좌표 변환 등 추가 개념 설명이 필요해서 이 글에서 다루지는 않겠다.

어드민 데모 구현

프롬프트는 완성했지만, 판매자에게 일일이 제미나이에 접속해서 텍스처 맵을 생성하도록 요구하는 것은 매우 비현실적이다. 전자상거래는 하루에도 수십, 수백 개의 상품이 등록되는 환경이다. 실무에서는 이러한 작업을 자동화하여 상품 판매자가 쉽게 사용할 수 있도록 기능을 제공할 수 있어야 한다.

필자는 실험을 하는 입장이라서 그에 필요한 간단한 어드민을 구현해 보았다.

우선, 사용자가 상품 이미지를 업로드하면, 사전 정의된 시스템 프롬프트를 이용하여 나노바나나 프로 API로 노멀 맵과 깊이 맵 텍스처를 생성할 수 있도록 구현했다. 생성된 텍스처 이미지는 별도 저장소에 보관된다.

이렇게 저장한 텍스처 이미지를 실제 플랫폼에 적용했을 때, 어떤 모습일지 미리보기 기능도 추가했다. 사용자는 업로드한 상품 이미지와 생성된 텍스처 이미지를 바탕으로 2.5D 모델을 실시간으로 확인할 수 있다.

제품마다 형태와 재질이 다르기 때문에 생성된 텍스처 이미지의 품질도 천차만별일 수밖에 없다. 빛의 세기나 텍스처 품질, 2.5D 모델을 바라보는 카메라 위치 등을 조정할 수 있는 기능도 추가하여 적절한 결과물이 나오도록 조정했다.

다음은 실패 사례다. 파스쿠치 케이크를 원본 이미지로 사용해봤는데, 이번에는 텍스처 효과가 생각만큼 효과적이지 않았다. 케이크의 복잡한 질감이 AI가 이해하기 어려웠던 걸까?

오히려 원본 이미지를 사용하는 것이 더 나아보이는 퀄리티다. 이처럼 상품 이미지의 특성에 따라 텍스처 효과 품질이 달라질 수 있다는 점은 해결해야 할 과제다. 판매자가 업로드한 원본 이미지에 따라 AI가 생성한 텍스처 이미지의 품질이 일정하지 않을 수 있기 때문이다. 그리고 파스쿠치 케이크 이미지처럼 배경과 물체를 분리하는 전처리 작업이 필요할 수도 있겠다.

실무 적용 전제 조건

현재 기준으로 실무에 적용하기에는 어려운 점이 많다고 생각한다. 필자가 생각하기에 이 방법을 적용하려면, 몇 가지 사전 조건이 필요하다.

첫 번째로 일반 사용자의 네트워크 환경이 지금보다 훨씬 좋아져야 한다. 텍스처 이미지를 불러오는 데 시간이 걸리기 때문이다. 어설픈 텍스처 이미지를 불러오면 오히려 사용자 경험이 나빠질 수 있다.

안 그래도 페이지 하나에 불러와야 할 이미지가 많은 전자 상거래 환경에서, 추가로 텍스처 이미지를 불러오려면 네트워크 속도가 빨라야 한다. 다운로드 속도 기준으로 최소한 유선 환경에서 1GB 이상이 보편화되어야 한다고 생각한다. 하지만 여전히 100MB 인터넷 요금제를 사용하는 사용자가 압도적이다. 또한 모바일 환경에서 현재 5G의 속도(약 30~40MB)로는 더더욱 부족하다.

두 번째로 AI 이미지 모델의 토큰 비용이 지금보다 훨씬 저렴해져야 한다. 현재 나노바나나 프로의 경우, 토큰 비용이 상당히 높아서 기업 입장에서 텍스처 이미지 생성 도구를 일반 판매자 대상으로 무료 제공하기에는 부담이 크다.

세 번째로 일반 사용자의 기기가 WebGPU를 사용해도 무리가 없을 정도로 성능이 좋아져야 한다. WebGL도 충분히 가능하지만, WebGPU가 더 나은 품질을 제공할 수 있기 때문이다. 두 셰이더 파이프라인의 학습 차이는 있지만, 추상화된 라이브러리를 사용하게 될 것이므로 WebGPU 지원이 보편화되는 것이 중요하다.

이러한 조건들이 충족되는 날이 온다면, 언젠가 가능하지 않을까?

마치며

이 실험은 실무에서 적용 가능한 상용 솔루션을 만들기 위한 것은 아니었다. 다만 "가능할까?"라는 질문에 "가능할 지도 모르겠다."는 생각을 하게 됐다.

여전히 앞서 말한 실무 적용을 위한 장벽과 함께 상품 판매자가 원본 이미지를 업로드 했을 때, AI가 생성한 텍스처 이미지의 품질이 일정하지 않을 수 있다는 점도 해결해야 한다. 판매자가 텍스처 이미지를 생성했더라도 상품에 어울리는 셰이더 효과를 적절하게 적용되도록 기능을 제공하는 것도 쉽지 않은 문제다.

해결해야 할 문제들이 많지만, 언젠가 사용자들이 온라인 쇼핑몰에서 제품을 볼 때, 단순 2D 이미지가 아닌 입체적이고 생동감 있는 모습을 당연하게 받아들이는 날이 올 것이라 생각한다.