12 min read

퓨전 개발팀의 파워 앱 개발 실사례

Justin Yoo

얼마전 Microsoft에서는 퓨전 개발팀을 위한 무료 학습 모듈을 공개했다. 더불어 이를 위한 전자책도 함께 공개했는데, 이를 통해 조직내 퓨전 개발팀의 작동 방식에 대한 아이디어가 실제 어떤 식으로 구현이 되는지를 살펴볼 수 있다.

가트너에서는 퓨전 개발팀을 "교차 기능 조직(cross-functional team)으로서 비지니스 가치를 수행하기 위해 다양한 데이터와 기술을 사용한다"라고 정의한다. 동시에 이 퓨전 개발팀은 대체로 기술적인 의사결정을 IT 조직 외부에서 내리기도 하고, 이 결정의 방향은 IT 조직에서 권장하는 방향과 다르게 가는 경우도 잦다. 그리고 이러한 퓨전 개발팀의 리더는 IT 조직 외부에서 오는 경우가 많다고도 한다. 즉, 기존의 IT 조직 관점에서 흔히 보이는 전문 개발자의 시각보다는 좀 더 넓은 비니지스 관점에서 가치를 충족시키는 서비스 개발이 이루어져야 하는 셈이다. 그렇다면 실제로 이러한 퓨전 개발팀에서 어떤 제품 혹은 서비스를 개발하고 배포할까?

이 포스트에서는 Mallee Bulls Fitness 라는 가상의 피트니스 센터에서 회원들이 운동 일지 작성에 사용할 모바일 앱을 파워 앱으로 개발하는 일련의 과정에 대해 시리즈로 다루도록 한다.

이 포스트에 사용한 백엔드 API 샘플 코드는 이곳 GitHub 리포지토리에서 다운로드 받을 수 있다.

시나리오

몰리불스 피트니스 센터의 퍼스널 트레이너인 안지민쌤은 자신이 관리하는 회원들에게 운동일지를 항상 수기로 작성해서 줬다. 하지만, 굳이 쌤이 관리하는 일지 내용을 다시 수기로 작성해서 건네주는 것이 비효율적이라는 생각에 센터에서 도입한 파워 앱을 이용해서 회원과 공유해보고자 하는 계획을 세웠다. 이미 회원의 운동 일지를 저장하는 전산 시스템은 구축이 되어 있는 상태이므로, 이를 파워 앱에서 사용할 수 있게끔 사용자 지정 커넥터를 만들어 파워 앱에서 사용하기만 하면 된다. 파워 앱을 통해 회원의 운동 일지 데이터를 입력 받아 데이터베이스에 저장하는 일련의 과정은 대략 아래와 같은 구조이다.

GymLog Architecture

  • 백엔드에서 사용하는 애저 펑션OpenAPI 확장 기능을 설치해서 검색용이성(discoverability)을 높인다.
  • OpenAPI 문서를 이용해 사용자 지정 커넥터를 만든다.
  • 사용자 지정 커넥터를 통해 파워 앱에서 운동 데이터를 백엔드로 보낸다.
  • 백엔드는 비동기식으로 데이터를 다루는 Pub/Sub 패턴을 구현한다.
  • 백엔드 API에서 받아온 데이터는 퍼블리셔 쪽에 계속 쌓이다가 운동이 다 끝나는 시점에 모두 합산(Aggregate)한 데이터를 애저 서비스 버스로 보낸다.
  • 서비스 버스로 보낸 데이터는 섭스크라이버 쪽의 애저 펑션에서 받아 최종적으로 애저 코스모스 DB로 저장한다.

백엔드 API 개선

안지민쌤은 퍼스널 트레이너 팀장이기도 해서 피트니스 센터의 여러 가지 업무에 대한 자동화 아이디어를 퓨전 개발팀에 제공하고 있다. 같은 퓨전 개발팀 내 전문 개발자인 권수빈쌤에게 API 검색이 가능하게끔 해달라는 요청을 했고, 이를 받아들여 권수빈쌤은 애저 펑션에 OpenAPI 기능을 추가했다. 이를 위해 가장 먼저 NuGet 패키지 라이브러리를 애저 펑션 프로젝트에 추가했다.

dotnet add package Microsoft.Azure.WebJobs.Extensions.OpenApi --prerelease

그리고 기존의 API에 몇 가지 데코레이터만 추가해서 API 엔드포인트를 OpenAPI 문서에 포함시켰다. 아래는 맨 처음 운동 루틴을 시작할 때 사용하는 API이다. 아래 코드는 OpenAPI와 상관없는 부분은 제외시켰으므로, 만약 해당 API의 전체 코드를 보고 싶다면 이 링크를 클릭한다.

// Decorators for OpenAPI
[OpenApiOperation(operationId: "CreateRoutine", tags: new[] { "publisher", "routine" }, Summary = "Create a new routine", Description = "This creates a new routine", Visibility = OpenApiVisibilityType.Important)]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "x-functions-key", In = OpenApiSecurityLocationType.Header, Description = "API key to execute this endpoint")]
[OpenApiRequestBody(contentType: ContentTypes.ApplicationJson, bodyType: typeof(RoutineRequestMessage), Required = true, Example = typeof(RoutineRequestMessageExample), Description = "The request message payload for a routine")]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: ContentTypes.ApplicationJson, bodyType: typeof(RoutineResponseMessage), Example = typeof(RoutineResponseMessageExample), Summary = "200 response", Description = "This returns the response of 'OK'")]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.InternalServerError, contentType: ContentTypes.ApplicationJson, bodyType: typeof(ErrorResponseMessage), Example = typeof(ErrorResponseMessageExample), Summary = "500 response", Description = "This returns the response of 'Internal Server Error'")]
// Decorators for OpenAPI
[FunctionName(nameof(RoutineHttpTrigger.CreateRoutineAsync))]
public async Task<IActionResult> CreateRoutineAsync(
[HttpTrigger(AuthorizationLevel.Function, HttpVerbs.Post, Route = "routines")] HttpRequest req,
ExecutionContext context,
ILogger log)
{
...
}

위와 같이 OpenAPI 설정을 추가하고 난 후 배포해 보면 아래와 같이 Swagger UI 화면이 나타난다.

Publisher Swagger UI

위에 추가한 확장 기능 라이브러리는 OpenAPI 스펙 V2 (Swagger)와 V3를 모두 지원하므로, https://<function_app_name>.azurewebsites.net/api/swagger.json 으로 접속하면 설정에 따라 V2 문서 혹은 V3 문서를 렌더링한다. 위 그림은 V3 문서를 렌더링하는 것으로 되어 있다.

사용자 지정 커넥터 생성

이제 서버리스 API는 OpenAPI 확장 기능에서 제공하는 실시간 OpenAPI 문서 생성 기능을 통해 검색용이성을 높였으니, 이를 통해 파워 앱 쪽에서 사용자 지정 커넥터를 이용해 API에 접근할 수 있게 해야 한다. 파워 앱은 로우코드 플랫폼이므로 퓨전 팀 안에서 굳이 전문 개발자인 권수빈쌤이 이 사용자 지정 커넥터를 만들어 주지 않더라도 시민 개발자인 안지민쌤도 충분히 작업이 가능하다. 아래와 같이 파워 앱 스튜디오의 좌측 사용자 지정 커넥터 링크를 클릭한 후 우측 상단의 ➕ 새 사용자 지정 커넥터 버튼을 눌러 URL에서 OpenAPI 가져오기 메뉴를 선택한다.

Import OpenAPI from URL

아래와 같이 공개 API의 URL에 붙여넣기 필드에 애저 펑션에서 자동 생성해 주는 OpenAPI 문서 URL을 붙여넣는다. 참고로 사용자 지정 커넥터는 현재 OpenAPI v2 스펙으로 작성된 문서만 인식한다. 따라서, https://<function_app_name>.azurewebsites.net/api/openapi/v2.json과 같은 형태의 URL을 호출하면 곧바로 V2 형식의 OpenAPI 문서를 생성해 주기 때문에 이를 이용하면 된다.

Import OpenAPI from URL Pop-up

그런데, 만약 아래와 같은 에러가 발생하면서 사용자 지정 커넥터 생성에 실패할 수도 있는데, 이는 파워 앱 스튜디오와 애저 펑션 API 인스턴스 사이에 CORS 설정이 빠져 있기 때문이다.

Import OpenAPI from URL CORS Error

따라서, 애저 펑션 인스턴스 쪽에서 https://flow.microsoft.com 사이트에 대한 CORS 설정을 아래와 같이 해 주면 된다.

Azure Functions App CORS

CORS 설정이 끝난 후 파워 앱 스튜디오로 돌아와서 다시 사용자 지정 커넥터를 생성하면 이번에는 오류 없이 바로 생성 가능하다. 이 이후 과정은 일반적인 사용자 지정 커넥터 생성 과정과 동일하므로 여기서는 생략하기로 한다. 마침내 아래와 같이 사용자 지정 커넥터가 만들어졌다.

Custom Connector Created

인증을 통한 커넥션 생성

안지민쌤이 이 사용자 지정 커넥터를 활용할 수 있으려면, 먼저 인증 절차를 통해서 커넥션을 만들어 놓아야 한다. 애저 펑션 API 엔드포인트는 API 키로 보호받고 있으므로 이를 이용해 인증하고 커넥션을 만든다. 아래와 같이 버튼을 클릭한다.

New Connection

애저 펑션에서 제공하는 API 인증 키 값을 입력한 후 만들기 버튼을 클릭한다.

API Key Auth

그러면, 아래와 같이 커넥션이 만들어졌고, 이제 파워 앱 안에서 이 사용자 지정 커넥터를 자유자재로 사용할 수 있게 된다.

Connection Created

파워 앱에서 사용자 지정 커넥터 사용

이제 안지민쌤은 본인이 관리하는 회원들의 운동 일지를 수기로 작업하는 대신 파워 앱을 이용해 작성할 수 있게 됐다! 아래와 같이 파워 앱 캔버스 화면에서 사용자 지정 커넥터를 추가하면 된다.

Custom Connector in Power Apps

그리고 앱을 개발해서 회원들의 운동일지를 앱으로 관리할 수 있게 됐다! 아래는 파워 앱을 모바일에서 사용할 때의 스크린샷이다.

Power Apps in Action #1 Power Apps in Action #2

마지막으로 이렇게 기록한 운동 일지는 애저 코스모스 DB에 비동기식으로 저장된다.

Gym Logs in Cosmos DB

안지민쌤의 회원들은 이제 좀 더 손쉽게 스스로 운동 일지를 작성할 수 있게 되었다.

만약 이 GymLogs 앱을 사용해 보고 싶다면 이 링크에서 다운로드 받아 자신의 파워 앱 환경에 업로드해서 사용하면 된다.


지금까지 퓨전 개발팀에서

  • 현장 전문가는 시민 개발자로서 파워 앱을 개발하고,
  • 전문 개발자는 이 파워 앱의 기능을 풍부하게 해 주는 커스텀 커넥터를 위한 백엔드 API를 OpenAPI 형식으로 공개하는 형태로

협업을 하는 과정에 대해 알아 보았다. 이를 통해 결국 몰리불스 피트니스 센터의

  • 고객들은 좀 더 체계적인 운동 일지를 작성할 수 있게 되었고,
  • 이 데이터를 바탕으로 트레이너들은 좀 더 회원별로 개인화된 운동 루틴을 작성할 수 있게 되었다.

이렇게 함으로써 회원과 피트니스 센터 모두에게 좀 더 나은 서비스를 제공할 수 있는 기반이 다져진 셈이다. 다음 포스트에서는 애저 모니터 서비스를 이용해 파워 앱에서 데이터 저장소까지 데이터가 이동하면서 거쳐가는 경로들을 추적하는 과정에 대해 알아보기로 한다.