Unity 게임을 위한 .NET Core 서버 만들기
요약
본 튜토리얼은 Unity 게임과 연동되는 맞춤형 ASP.NET Core 백엔드 서버를 구축하는 방법을 안내합니다. 프로젝트 스캐폴딩부터 시작하여, 서버와 클라이언트 간의 데이터 통신 및 모델 공유 방안을 다룹니다. 특히 모델 복제 방식의 문제점을 지적하고 클래스 라이브러리를 활용한 효율적인 데이터 공유 방법을 제시합니다.
핵심 포인트
- Unity 게임에 연동되는 ASP.NET Core 백엔드 구축 방법 학습
- 서버와 클라이언트 간 API 통신 및 데이터 흐름 이해
- 모델 복제 대신 Shared Library를 사용해 데이터 일관성 유지
안녕하세요, 오늘 여러분께 Unity 게임용 맞춤형 ASP.NET Core 백엔드를 만드는 방법을 보여드릴 거예요. 제 흥분이 느껴지실 겁니다. 제가 가장 좋아하는 두 가지 것, 즉 서버와 게임을 결합하는 거거든요. 즐거우셨으면 좋겠네요. 첫 번째 에피소드에서는 프로젝트를 어떻게 스캐폴딩(scaffolding)하고, 여러분의 서버와 Unity 프로젝트 간에 모델을 공유할 수 있는지 보여드릴 거예요. ASP.NET Core 애플리케이션이 실제로 무엇인지, API가 무엇이고 어떻게 작동하는지 보여드릴게요. 게임에서 데이터를 서버로 가져오고, 서버에서 다시 게임으로 보내는 방법도 보여드릴 겁니다. 파트 2에서는 인증(authentication)과 권한 부여(authorization)를 추가하고 데이터베이스에 연결하는 것도 다룰 거예요. 만약 이 모든 것이 궁금하시다면, 파트 2가 나올 때까지 기다려 주세요. 하지만 일단 시작해 봅시다. 여러분이 새로 시작한다고 가정할게요. 제가 지금 하는 것처럼요. 메인 루트 폴더를 만드세요. 저는 이 프로젝트 이름을 'game server'라고 부를 거예요. 자, 애플리케이션을 만들겠습니다. 저는 Writer IDE를 사용하고 있어요. 여러분은 Visual Studio를 사용할 수도 있는데, 그것도 완벽하게 괜찮습니다. 모든 것이 대략 같은 방식으로 이루어지니까요. 창만 다르게 보일 뿐이지 프로젝트 자체는 완전히 똑같아요. Writer에서는 그냥 새 솔루션(solution)을 만들 거예요. 이름을 'game server'라고 지을게요. 여기가 제 루트 폴더예요. 그래서 여기에 넣을 겁니다. 솔루션을 위한 디렉토리를 만들지는 않을 거예요. 그리고 이렇게 하면 아무 프로젝트도 없는 아주 기본적인 솔루션만 생길 거예요. 모든 IDE에서 이 두 단계를 다 설명할 필요는 없지만, Visual Studio에서는 새 프로젝트를 만들고 '빈 솔루션(blank solution)'을 선택한 다음 솔루션 이름을 지정하면 됩니다. 그러면 끝이에요. 모든 것이 대략 똑같으니, 그냥 접근 방식만 다를 뿐입니다.
아이디어에 따라 이 튜토리얼에는 설명할 내용이 너무 많습니다. 따라서 제가 일부를 건너뛰더라도 직접 구글링 하셔야 합니다. 그렇지 않으면 25개 부분으로 구성된 튜토리얼이 될 것이고, 저는 그렇게 하고 싶지 않습니다. 자, 시작하기 위해 솔루션 안에 새 프로젝트를 만듭니다. '새 프로젝트 추가'를 할 건데, 첫 번째는 ASP.NET Core 웹 애플리케이션을 사용해야 합니다. 반드시 Core를 사용하고 있는지 확인하세요. Core라는 것은 크로스 플랫폼(cross-platform)이라는 의미이므로 Windows, Linux, Mac에서 사용할 수 있습니다. 오래된 .NET Standard 버전은 절대 사용하지 마세요. 그건 오직 Windows 전용입니다. 그러니까 Net Core를 사용해야 합니다. Visual Studio나 여기서 유형을 선택할 수 있는데, 저는 Web API를 할 겁니다. 이건 애플리케이션의 초기 스캐폴드(scaffold)와 같아서, 대략 어떻게 하는지 보여주는 샘플 코드를 제공해 줄 뿐입니다. C# 인증은 넣지 않을 겁니다. 직접 구현할 거예요. 이름은 'Server'로 하고 여기에 넣겠습니다. 그리고 폴더 루트에 두고 '만들기'를 누릅니다. 다음으로 Unity와 서버 간에 데이터를 공유해야 합니다. 초보적인 방법은 모델(model)을 복제하는 것입니다. 즉, 서버와 Unity 양쪽에 같은 모델을 두는 것이죠. 사실 이것이 C# 백엔드와 JavaScript 프론트엔드를 다룰 때 많은 사람들이 하는 방식인데, 모델을 복제하면 매우 지저분하고 오류가 발생하기 쉽습니다. 그래서 이를 완화하기 위해 저희는 새 프로젝트를 만들 건데, 이건 클래스 라이브러리(class library)가 될 겁니다. 이름은 'Shared Library'라고 하겠습니다. 원래는 'Library'라고 부르는 게 일반적이지만, Unity 자체에 이미 'Library' 폴더가 있기 때문에 충돌이 생길 수 있습니다. 그래서 'Shared Library'로 하겠습니다. 이 프로젝트를 빌드하면 단순히 바이너리(binary) 파일만 생성되고 그 안에 모든 클래스들이 들어있습니다. 예를 들어, 첫 번째 클래스를 이름은 'Player'로 바꾸고 몇 가지 속성(property)을 만들겠습니다. 음, 레벨(level) 같은 것과 플로트(float)가 필요할 수 있는데, 이건 체력(health)이 될 수 있습니다. 여기 라이브러리가 있고 여기에 Player가 들어있습니다. 그리고 이것이...
그게 뭐냐면 API가 뭔지, 그리고 특히 ASP.NET Core API가 무엇인지입니다. 우리가 RESTful 서비스라고 부르는 것입니다. 기본적으로 이 모든 엔드포인트를 열어두는데, 아무도 접속하지 않으면 그냥 유휴 상태로 있습니다. 누군가 접속하는 즉시 로직을 실행하고 데이터를 반환하거나, 데이터를 게시(post)하거나 데이터베이스에 데이터를 넣거나, 무엇이든 합니다. 그저 요청을 받고 응답을 보내는 것만 하는 겁니다. 간단하죠? 그리고 실제로 짜증 나는 부분은 샘플 컨트롤러가 너무 장황하다는 것입니다. 이렇게 복잡하고 무서울 필요가 없습니다. 그러니 이 날씨 예보(weather forecast) 컨트롤러와 날씨 예보를 삭제합시다. 그냥 삭제하고 훨씬 더 간단한 우리만의 것을 만듭시다. 플레이어 컨트롤러 이제 '컨트롤러'는 단순히 관례일 뿐만 아니라, 이 프레임워크에서 인식되고 자동 매핑되려면 필수적입니다. 그리고 우리는 ControllerBase를 상속받을 것입니다. ControllerBase는 이것을 실제로 컨트롤러로 만들 수 있게 해주고, 우리가 필요로 하는 많은 컨트롤러 기능을 제공합니다. 몇 가지 다른 것들이 더 필요합니다. 첫 번째는 API Controller이고, 마지막으로 라우트(routes)입니다. 이는 우리가 컨트롤러에 대한 어떤 종류의 수동 매핑도 할 필요가 없게 해주어, 그것들이 실제로 활성화되려면 자동으로 존재하게 합니다. 그래서 그냥 대괄호 안에 넣고 Controller라고 작성하면 됩니다. 이것이 우리가 사용하는 관례입니다. 자, 이제 컨트롤러를 설정했고, 컨트롤러에 대해 생각하는 좋은 방법은 단순히 엔드포인트 그룹이라는 것입니다. 그리고 이 컨트롤러 안에서 실제로 우리의 엔드포인트를 작성합니다. 예를 들어, 지금 플레이어를 반환할 곳을 하나 작성해 보겠습니다. 아하, 우리는 현재 이 플레이어에 접근할 수 없습니다. 왜냐하면 공유 라이브러리에 있기 때문입니다. 따라서 이 프로젝트를 이 프로젝트에 참조 추가하는 몇 가지 방법이 있습니다. Visual Studio에서 Rider나 ReSharper를 사용한다면 자동으로 찾을 수 있어야 합니다. 비록 누가 알겠어요, 아마도 새로운 버전의 Visual Studio에서도 그렇게 할 수 있을지 모르지만요. 만약 그것이 작동하지 않는다면 서버에서 마우스 오른쪽 버튼을 클릭하고 추가하세요.
참조를 추가하고 공유 라이브러리를 여기에 클릭하기만 하면 이 프로젝트가 이를 종속성으로 갖게 됩니다. 그리고 여기서는 누락된 참조를 포함할 것이고, 죄송하지만 이 함수는 플레이어를 반환할 것입니다. 그냥 get이라고 부르겠습니다. 그런 다음 여기에서 새 플레이어를 만들고, 아래에서는 그 플레이어를 반환할 것입니다. 정말 쉽습니다. 또 해야 할 한 가지가 있는데, 이것이 마지막 보일러플레이트 코드라고 약속합니다. 단지 이것이 post나 patch, put 같은 것이 아니라 실제로 get 요청이라고 말만 하면 됩니다. get 요청은 페이로드 없이 호출할 수 있는 엔드포인트이며 데이터를 받을 수 있다는 것입니다. 좋습니다. 그래서 첫 번째 get 요청을 설정하는 데는 사실상 이 모든 것이 필요합니다. 자, 실행해 보겠습니다. 그러면 이 swagger 인터페이스가 보일 것이고, swagger는 API 문서 자동 생성 플러그인 같은 것입니다. 모든 엔드포인트를 볼 수 있게 해줍니다. 저는 실제로 이것을 끄는 편인데, 나중에 어떻게 하는지 보여드리겠습니다. 네, 제 애플리케이션이 제 플레이어 엔드포인트, 제 플레이어 컨트롤러를 찾았습니다. 올바른 규칙(convention)을 사용하고 이 속성들로 장식했기 때문에 가능합니다. 실제로 시도해 볼 수 있습니다. 실행해 보겠습니다. 그리고 우리 플레이어가 응답했습니다. 좋습니다. 다음은 만약 우리가 서버에 데이터를 실제로 post하고 싶다면 어떨까요? 그것은 똑같이 쉽게 달성됩니다. http post public을 하고, 여전히 플레이어를 반환하도록 하겠습니다. 예를 들어 그들이 플레이어를 생성했고, 실제로 그들에게 플레이어를 반환할 때 데이터베이스에 의해 할당된 실제 ID가 포함되어 있는 경우입니다. 그래서 post를 하도록 합시다. 이것은 플레이어 객체를 수락하고, 여기에서 '플레이어가 데이터베이스에 추가되었습니다'라고 말만 하면 됩니다. 그리고 플레이어가 데이터베이스에 추가되었다고 가정합시다. 아마도 고유한 ID가 주어졌을 것입니다. 그래서 우리는 실제로 그 플레이어를 반환할 것입니다. 좋습니다. 이제 실행하면 두 개의 엔드포인트, get과 post가 있는 것을 볼 수 있습니다. 여기에서 post로 이동하여 이 엔드포인트를 시도해 볼 수 있고, 예를 들어 레벨 7이라고 합시다.
터무니없기 때문입니다. 실제로 아무것도 하지 않을 것이기 때문에요. 하지만 네, 우리가 방금 보낸 모델을 반환하고 있습니다. 그래서 POST와 GET이 있습니다. 하지만 쿼리하는 내용에 대해 조금 더 제어할 수 있어야 한다면 어떨까요? 예를 들어 ID가 100인 플레이어를 원한다면요. 실제로 여기에는 ID가 없으니, 그냥 ID를 추가해 봅시다. ID요. 데이터를 전송하는 방법은 몇 가지가 있습니다. 쿼리 문자열(query strings)을 통해 할 수 있습니다. 그렇게 해봅시다. 쿼리에서 이 값은 int id가 될 것이고, 여기서는 그냥 속이는 방식으로 우리가 요청한 ID라고 말합시다. 마치 데이터베이스에서 얻은 것처럼요. 만약 이것을 시도하면, 이것은 쿼리에서 온 것입니다. 그래서 플레이어 엔드포인트로 가서 쿼리 문자열을 사용하고 물음표(?)를 넣고, 예를 들어 속성으로 호출하는 것이 우리가 'id'라고 말한다고 가정합시다. 그리고 그것이 'equals' 100이라고 합시다.
보시다시피 100 레벨로 전달되고 있습니다. 이것은 쿼리 문자열을 사용하여 하는 한 가지 방법입니다. 참고로, 만약 더 많은 쿼리 문자열이 필요하다면, 예를 들어 'name'이라는 문자열이 있다고 가정해 봅시다. 그러면 이렇게 할 것입니다. 첫 번째 것 뒤에는 물음표만 있고, 두 번째 것부터는 앰퍼샌드(&)가 필요합니다. 그리고 거기에 이름(name)을 넣으면 됩니다. 좋아요. 다음은 라우트(route)를 통해 하는 방법입니다. 단순한 쿼리를 수행할 때는 아마도 이 방법이 더 좋을 것입니다. 이렇게 할 수 있고, ID를 사용할 수 있습니다. 그리고 이것을 쿼리에서 라우트로 변경할 수 있습니다. 이제 플레이를 누르면 이렇게 얻습니다. 'player/150'으로 갑니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 YouTube Tarodev (Unity 팁)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기