Unity로 모바일 앱을 만들면 업데이트가 필요해진다. 마켓의 애플리케이션 용량 제한과 심사기간, 유저의 업데이트 설치 유도 등이 문제가 되며, 이러한 문제로 인해 애플리케이션의 문제 해결에 시간을 써버리면 유저는 기다리기보다는 삭제를 선택한다.

따라서, 클라이언트 애플리케이션의 라이브 업데이트는 선택이 아니라 필수다.

요구사항

  1. 마켓을 거치지 않고 클라이언트를 업데이트 해야 한다.
  2. 이미 있는 캐시 시스템을 사용할 수 있어야 한다.

1번은 기본이다. 그리고 이것은, 업데이트 파일을 다운로드 할 수 있는 서버와, 다운로드해야 하는 파일 목록이 필요하다는 의미이다. 아는 사람에겐 하나마나 한 소리지만, 이걸 모르는 사람도 꽤 된다. 기본이니 짚고 넘어간다. 그리고 만약 주변에 이걸 모르는 사람이 있다면, 아마도 무시할 수 없는 중요한 어떤 일을 맡고 있는 사람일 가능성이 높다.

2번은 Unity AssetBundle의 캐시 시스템을 사용한다는 뜻이다. 그리고 여기에서 귀찮은 문제가 생긴다.

문제

1번 문제는 비교적 쉽게 해결할 수 있다. 그저 업데이트 파일이 있는 디렉토리에 들어가서, 하위 디렉토리를 포함해 파일 목록을 파일로 출력하면 된다. 파일 목록이 있는 파일 이름이 고정이라면, 클라이언트를 손댈 필요 없이 새로운 파일 목록을 클라이언트에게 줄 수 있다.

2번은 조금 더 나가야 한다. 유니티의 애셋 번들 캐시는 URL과 정수형 버전을 사용하기 때문이다. URL과 버전의 쌍을 동적으로, 그러니까 서버에서 다운로드 할 수 있는 형태로 만들어야 한다.

해결

http(s)://[호스트]/[클라이언트가 아는 URI]의 애셋번들버전목록(이하 목록)에 다음의 내용을 넣어둔다.

[AssetBundle A의 URL],  [버전]
[AssetBundle B의 URL],  [버전]
...(생략)...

간단하게 CSV 포맷으로 만들 수 있다.

새로운 문제와 해결

Q1 : 새 버전의 애플리케이션이 심사 들어가야 하는데 새 버전용 애셋번들 버전 목록 만들어주세요.

A1 : 그럼 목록 URL을 http(s)://[호스트]/1.0.0 형식으로 만들게요.

Q1-1 : 애셋 번들은 OS마다 따로 만들어야 하는데요?

A1-1 : 그럼 목록 URL을 http(s)://[호스트]/1.0.0.[OS] 형식으로 만들게요.

더 새로운 문제(들)

Q2 : 그렇게 하면 누구나 목록을 볼 수 있잖아요. 다음 업데이트용 리소스를 공개도 안했는데 볼 수 있는 건 안됩니다. 앱을 마켓에 공개할 때까진 리소스도, 리소스 목록도 볼 수 없게 해주세요.

A2 : 로그인한 앱만 리소스를 볼 수 있도록 로그인 한 다음에 목록을 읽을 수 있도록 인증 로직을 추가할게요.

Q3 : 컨텐츠 추가하고 점검 끝나면 리퀘스트가 피크 치는데 인증후에 다운로드하면 트래픽까지 피크 칠텐데? IDC(애플리케이션 서버)는 그거 못 버텨요. 업데이트 파일 다운로드는 CDN(스태틱 파일 서버)으로 처리해야죠. 서버 대수도 문제고 비용은 어쩔 생각이에요?

A3 : …(로직이 없는 파일 서버로 보안을 확보하는 방법이 뭐가 있지?)

Q4 : 점검할 땐 어떻게 하죠? 가끔이지만 IDC가 점검도 하고 이사도 하는데.

A4 : 점검 공지나 약정은 CDN에서 서비스 할게요(어떻게든).

문제의 의미

Q1, Q1-1

  • 운영중인 현재 버전과 테스트 버전을 동시에 운영할 수 있어야 한다.
  • 애플리케이션 버전마다 서로 다른 목록을 사용할 수 있어야 한다.

Q2

  • 특정 버전의 애플리케이션만 목록의 URL을 알 수 있어야 한다. 즉, 예측할 수 없어야 한다.
  • 목록 뿐만 아니라 애셋 번들의 URL도 예측할 수 없어야 한다.

Q3

  • 로그인 등의 권한 확인 로직을 사용할 수 없다.
  • 애플리케이션 서버(로직 서버)와 도메인이 다르다.

Q4

  • 애셋 번들의 목록 외의 정보도 있어야 한다.
  • 에셋 번들과 상관없이 다른 경로(프로세스, 담당자, 담당팀)의 리소스 배포가 있다.

예상 가능한 문제

  • 목록을 손으로 관리하면 반드시 문제가 생긴다.
  • 유니티의 애셋번들 캐시는 롤백이 없다.
  • 여러 애셋번들 사이에 의존성이 있을 경우, 잘못된 캐시 업데이트는 재설치만이 답인 경우도 있다.
  • HTTPS를 쓴다해도 보안은 확실한가? 중간자 공격 기법을 사용하면 목록과 각 애셋 번들의 URL이 노출된다.

결론

  • 무작위 대입 공격(brute force attack)에 대응하기 위해 해시를 사용한다.
  • 애플리케이션과 목록 사이에 하나의 계층을 추가하고 네트워크를 분리한다. 추가한 중간 계층에서 분리한 네트워크 정보를 제공한다.
  • 단순한 애셋 번들의 URL과 버전 외의 정보도 제공하기 쉽도록 CSV 대신에 JSON 포맷을 사용한다.

참고

  • https://github.com/JustBurrow/urs
  • http://docs.unity3d.com/kr/current/Manual/DownloadingAssetBundles.html
  • http://docs.unity3d.com/ScriptReference/WWW.LoadFromCacheOrDownload.html