Next.js에서 iframe을 활용해 유니티 빌드 파일을 렌더링하던 중 배포 환경인 gitlab에 유니티 빌드 파일을 저장할 수 없는 문제가 발생했다.(파일 크기 문제)
물론 lfs와 같이 대용량 파일을 gitlab에 저장하는 방식도 있겠으나, 시간이 없었던 관계로 빠르게 해결할 수 있는 방안을 찾아야했다.
결론(시도한 방법)
1. Next.js를 일종의 proxy 서버로 활용하여 s3에 접근 : 속도가 매우 느려짐
2. Docker 이미지 생성시 S3에 저장된 유니티 빌드 파일을 public에 끼워 넣기 : 채택
1번 방식
iframe을 통해 S3에 있는 유니티 빌드 파일에 직접 접근시 CORS 오류 발생
- nity WebGL 빌드 파일은 index.html이 S3에 저장되어 있고, 브라우저가 이를 직접 요청하면 CORS 헤더(Access-Control-Allow-Origin)가 없으면 요청이 차단됩니다.
- 특히, Unity WebGL은 여러 파일(.js, .json, .css, .wasm)을 요청하기 때문에 CORS가 제대로 설정되지 않으면 전체 프로젝트가 로드되지 않습니다.
위와 같은 이유로 iframe에서 S3에 직접 접근할 수 없었습니다.
해결 방식
Next.js API 라우트를 프록시로 사용하여 S3에서 Unity WebGL 파일을 가져온 뒤, 브라우저에 전달하는 방식을 사용했습니다. 브라우저가 S3에 직접 접근하지 않도록 하고, Next.js 서버를 통해 S3의 파일을 가져옵니다. Next.js 서버는 동일 출처(origin)로 작동하므로, 브라우저는 CORS 문제 없이 파일을 로드할 수 있습니다.
쉽게 말하면 브라우저가 S3에 직접 접근하지않고 Next.js가 접근할 수 있도록 코드를 수정했습니다.
Next.js API 라우트로 요청 프록시
- 브라우저가 /api/proxy/index.html에 요청을 보냅니다. 이 요청은 Next.js 서버에서 처리됩니다.
- Next.js 서버는 내부적으로 S3에 요청을 보내 Unity 파일을 가져옵니다.
- 요청은 서버 측에서 이루어지기 때문에 CORS 정책의 영향을 받지 않습니다.
- 브라우저 → Next.js 서버(동일 출처) → S3
2. Next.js 서버와 브라우저는 동일 출처
- 브라우저는 Next.js 서버에서 전달받은 데이터를 동일 출처로 인식합니다.
- 이 방식은 브라우저가 S3로 직접 요청하지 않고 Next.js 서버를 통해 데이터를 중계받기 때문에 브라우저의 CORS 제약이 적용되지 않습니다.
현재 코드 동작 방식
1. handler API 라우트:
- /api/proxy/[...file] 경로를 처리하며, 요청된 파일 이름을 S3 경로로 변환합니다.
- S3에 요청을 보내 파일을 가져옵니다.
- 가져온 파일을 Next.js 서버가 브라우저로 반환합니다.
- 브라우저는 Next.js 서버에서 데이터를 전달받기 때문에 동일 출처로 간주합니다.
API 코드 흐름:
- 브라우저가 /api/proxy/index.html 요청.
- Next.js가 S3 URL에 요청.
- S3에서 받은 데이터를 브라우저에 반환.
- 브라우저는 반환된 데이터를 동일 출처에서 온 것으로 처리.
2. UnityViewer 컴포넌트:
- iframe이 Next.js API(/api/proxy/index.html)를 통해 Unity의 index.html을 요청.
- index.html이 로드되면서 추가로 필요한 Unity 리소스 파일들을 /api/proxy/ 경로를 통해 요청.
- 모든 파일 요청은 Next.js 서버에서 S3로 프록시 요청되므로, CORS 문제를 피합니다.
추가 문제사항 해결방법(속도 저하)
위의 방식을 사용하여 S3에 저장된 유니티 빌드파일을 화면에 띄우는데는 성공했습니다.
다만 문제는 속도가 너무 느려 다른 방법을 찾아야 했습니다.
기존처럼 Public 폴더 밑에 유니티 빌드 파일이 있는 것처럼 사용하기
가장 안전한 방법은 기존처럼 Public 폴더 밑에 유니티 빌드 파일이 있는 방식이라고 생각했습니다.
현재 문제는 배포에 엮여있는 레파지토리에 필요한 유니티 파일을 올릴 수 없다는 문제였고(파일 크기 문제),
이를 해결하기 위해 빌드할 때만 public에 저장할 수 있을까에 대해 고민하며 빌드할 때 S3에 저장된 유니티 빌드 파일을 public에 옮겨 담는 방식을 채택했습니다.
따라서 도커가 프론트 코드를 도커 이미지로 생성하기전에 public에 유니티 빌드 파일을 끼워넣자! 라는 방식으로 접근했습니다.
결과
- public에 유니티 빌드 파일을 올리는 것과 같은 효과로 구현되었습니다.
- localhost에서 개발할 때는 public에 유니티 빌드 파일을 저장해놓고 사용하되 gitignore를 활용해 유니티 빌드 파일이 원격 레파지토리에 저장되지 않도록 주의하면 될거라 생각됩니다.