게임을 만들다보니 점점 욕심도 생기고 덩치가 커지면서 '서버'가 필요하게 되었습니다. 예전부터 그냥 C++로 서버 하나 뚝딱 만들면 되겠지... 라고 생각하고 있었는데, 클라우드 서버에서 처리량에 따라 서버의 개수 조절이라던가 여러가지 설정해 줘야 하는 부분들을 생각하니 머리가 아파졌습니다.
그래서 AWS의 Lambda를 이용하여 Serverless Mobile Game 시스템을 구축해보자는 생각으로 AWS를 조금씩 도입하기 시작했습니다.
그 첫번째 단계가 바로 Cognito를 이용한 계정의 인증입니다.
Cognito란 AWS에서 제공하는 계정 인증방식입니다. 기본적으로 Device 정보와 이것저것 조합하여 각 Device별로 고유한 ID를 생성하여 사용자를 인증하고 인증 정보를 토대로 AWS의 기능에 접근하기 위한 접근 권한을 얻어내기 위한 기능입니다. Cognito에서 권한을 얻으면 AWS SDK for Unity를 통해 S3, DynamoDB, Lambda, Notification 등 각종 서비스에 접근할 수 있게 됩니다.
Cognito의 권한은 '비인증 사용자'와 '인증 사용자'로 구분하여 서로 다른 권한을 부여할 수 있습니다. '비인증 사용자'는 말 그대로 어떠한 인증없이 그냥 접속한 Guest 유저를 말합니다. '인증 사용자'란 Facebook, google, twitter, Amazon, OpenID 등을 통해 인증을 받은 유저를 말합니다. Cognito에서 해당 인증 정보에서 뭔가 데이터를 얻어오진 않고 오직 인증을 하는데만 사용한다고 합니다.
이제 Unity에서 사용하기 위한 방법을 순서대로 따라가 보겠습니다.
첫번째 순서는 회원가입입니다. 가입 절차는 생략합니다. 일단 가입하면 무료로 1년간 AWS Free-tier 관련 기능들을 사용할 수 있습니다. 성능이 좀 좋다 싶으면 무료 사용 기간에도 돈을 내야하는 옵션이 있으니 테스트 할 때 무작정 좋은 옵션 선택하지말고 주의해야 합니다.
AWS Console에 접속을 했으면 'Region'을 선택해야 합니다. 최근 Seoul 리전이 생겨서 그걸 사용해 보려고 했으나 Seoul 리전에서는 Cognito 기능을 제공하지 않아서 그나마 가까운 Tokyo 리전을 선택했습니다.
Cognito를 설정해야하니 메뉴중 Cognito를 찾아서 클릭해 줍니다.
이미 만들어둔 Identity가 있어서 화면이 좀 다를 수 있겠으나 Create new Identity pool 버튼이 있을겁니다. 그걸 클릭해 줍니다.
이제 본격적으로 Identity Pool을 생성합니다. 계정의 인증 정보들이 잔뜩 담길 곳이라서 Pool 이라고 하나봅니다. Identity Pool Name 은 적당히 앱의 이름을 적어줍니다.
Unauthenticated Identities 옵션은 앞서 말했던 '비인증 사용자'를 허용할 것인지에 대한 옵션입니다. 체크를 해주면 인증하지 않은 사용자에게도 unique identifier를 생성해 줍니다. 게임 같은 경우에는 guest 입장이 안되면 피쳐드에 지장이 생겼던거 같으니 일단 저는 체크를 해줬습니다.
이제 문제는 Authentication providers에 대한 설정입니다. 위 스크린샷에 나와 있는것 처럼 각종 인증 제공자들에 대한 설정입니다. Facebook developer console, Google Developer Console을 통해서 API 접근을 위한 App ID를 얻어올 수 있습니다.
일단 Google 로그인을 위해 Google+ 의 Client ID를 얻어오는 방법을 알아보겠습니다.
이번에도 가입 절차를 생략하고 Google Developer Console에 접속합니다. 화면 상단에 '프로젝트 선택' -> '프로젝트 생성...' 을 클릭해 줍니다.
프로젝트 이름에 앱 이름을 입력해 줍니다.
그리고 약관에 동의를 하고 만들기를 클릭해 줍니다.
몇 초만 기다리면 프로젝트가 생성됩니다.
이제 내가 만든앱이 구글에 로그인을 하기위한 기본적인 준비가 되었습니다. 이제 로그인을 위한 API에 접근하기 위한 준비를 해야합니다. 붉은 사각형으로 표시된 "API 사용 설정 및 관리" 버튼을 클릭해 줍니다.
Android에서 사용할 클라이언트ID를 만들어 봅니다.
앞서 적은 글에서 Keystore의 SHA-1 finger print를 얻어서 적어줍니다.
패키지 이름은 Unity -> Player Setting -> Other Settings -> Bundle Identifier에 설정한 것을 기록해 줍니다.
이제 OAuth 2.0 클라이언트 ID가 발급되었습니다. 붉은 사각형 영역에 있는 클라이언트 ID를 복사해 줍니다.
이제 인증 사용자와 비인증 사용자 각각을 위한 권한을 설정해 줘야 합니다. 권한 설정은 AWS IAM을 이용하여 설정할 수 있습니다. 기본적으로 Create a new IAM Role이 설정되어 있고 해당 Identity Pool 이름이 붙어 있는 Role이 생성되게 되어 있습니다. 기본 생성되는 권한은 동일하게 인증을 얻는 것이고 '인증 사용자'에게는 Cognito Sync 기능을 사용할 수 있는 권한이 부여됩니다.
이제 Cognito를 사용하여 인증을 진행할 수 있는 준비가 되었습니다.
Unity에서 AWS SDK for Unity를 통해서 인증을 얻어와 봅시다.
http://docs.aws.amazon.com/mobile/sdkforunity/developerguide/
위의 링크에서 AWS SDK for Unity를 다운로드 하고 적당한 곳에 압축을 풀어줍니다.
압축을 풀어보면 unitypackages가 포함되어 있습니다. AWS에서 사용할 기능들에 맞춰서 필요한 package를 로드하면 됩니다. 일단 Lambda를 사용할 예정이므로 Lambda Package를 로드해 줍니다.
열기를 한 후 모든 파일을 import 해 줍니다.
AWSSDK/src/GameObjects/AWSPrefab을 Scene에 올려줍니다. 이 Prefab에 포함된 Unity Initializer 컴포넌트가 AWS SDK를 초기화 해주는 역할을 합니다. 이거 포함하지 않으면 기능이 제대로 동작하지 않습니다.
_credential = new CognitoAWSCredentials( "identity Pool ID", // Identity Pool ID RegionEndpoint.APNortheast1 // Region );
이제 타이밍상 적절한 곳에 위와같은 코드를 추가하여 CognitoAWSCredentials를 생성해 주기만하면 인증을 사용하기 위한 준비가 마무리 되었습니다. 그냥 이상태로 사용하면 비인증 사용자로 인증 권한을 받아옵니다.
IAmazonLambda _lambda; IAmazonLambda LambdaClient { get { if (_lambda == null) { _lambda = new AmazonLambdaClient(Credential, RegionEndpoint.APNortheast1); } return _lambda; } } public void Invoke(string func, string eventText) { LambdaClient.InvokeAsync(new Amazon.Lambda.Model.InvokeRequest() { FunctionName = func, Payload = eventText }, (response) => { if (response.Exception == null) { Debug.Log(Encoding.ASCII.GetString(response.Response.Payload.ToArray())); } else { Debug.Log(response.Exception); } }); }
이제 람다를 사용하기 위해서 위의 코드처럼 AmazonLambdaClient를 생성합니다. 이때 아까 생성한 credential 정보를 인자로 넘겨줍니다.
이렇게 생성한 IAmazonLambda 인터페이스를 통해서 InvokeAsync로 람다 함수를 호출할 수 있습니다. 이제 호출을 위한 람다 함수를 만들어 줘야 합니다.
다시 AWS Console로 돌아갑니다.
이번에는 콘솔 메뉴에서 Lambda를 선택해 줍니다.
간단한 테스트용 함수를 만들거라서 Blueprint 중에 hello world를 선택했습니다. 언어로는 Java, Node.js, Python을 사용할 수 있는데 저는 Python을 선택했습니다. 편하신 언어로 선택하면 됩니다. 각 언어에서 제공하는 라이브러리들도 활용할 수 있습니다.
FunctionName은 호출에 사용될 함수의 이름입니다. 해당 함수명으로 호출하면 이 Python 파일이 실행되고 lambda_handler 함수가 호출됩니다. 테스트만 할꺼라서 함수명도 HelloWorld라고 간단히 지어주고 특별한 코드의 수정없이 Next를 클릭하여 함수를 생성해 줍니다.
이제 스크립트의 적절한 곳에서 아까 만들어둔 Invoke함수를 호출해 줍니다. 저는 Singleton 객체로 만들어두어서 이런식으로 호출했습니다.
AWSManager.instance.Invoke("HelloWorld", "{\"key1\":\"kwon\", \"key2\":\"sang\",\"key3\":\"goo\"}");
이제 Unity에서 게임을 실행하여 정상적으로 동작하는지 확인해봅시다. 아마 이상한 exception들이 나오면서 안될겁니다. 이유는 Identity pool을 생성할 때 자동으로 만들어진 IAM의 권한에 Lambda를 실행하기 위한 권할 설정이 되어 있지 않기 때문일겁니다. 다시 AWS Console로 가서 IAM을 찾아서 클릭해 줍니다.
붉게 사각형으로 표시한 "lambda:*" 를 권한에 추가하면 해당 권한을 얻은 사용자는 AWS의 모든 Lambda를 호출할 수 있는 권한을 얻게 됩니다. 나중에 적절한 수준의 권한으로 조절할 필요가 있겠네요.
이제 Unity에서 인증을 하고 Lambda 호출까지 수행할 수 있게 되었습니다.