[OCA] 파워플랫폼 챌린저스 - 1주차

오경찬·2022년 7월 30일
0

내용

발대식이 끝난후 7/12일 첫번째 워크샵을 진행하게 되었다.
워크샵을 준비하기 위한 개발환경이 필요하였다.
원래 발대식때 개발환경을 다같이 맞춰서 진행하려고 했는데
발대식때 설명하는 시간이 너무 길어져서 개발환경은 세팅하지 못하여 수업전에 미리 해오기로 했습니다!

준비 사항

계정 생성

  1. M365 개발자 계정 : https://study.fusiondev.kr/m365/m365-dev-setup

  2. 파워 플랫폼 개발자 계정 : https://study.fusiondev.kr/pp/pp-dev-setup

  3. NHN 클라우드 계정 : https://toast.com/

개발 환경 설정

  1. .NET 6 SDK : http://dot.net
  2. Visual Studio : http://visualstudio.com
  3. Visual Studio Code : http://visualstudio.com
  4. Azure CLI : http://docs.microsoft.com/cli
  5. PowerShell : http://docs.microsoft.com/powershell
  6. Azure Function Core Tools : https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=v4%2Clinux%2Ccsharp%2Cportal%2Cbash

이후 다음과 같이 .NET 및 Azure Function 버전을 확인합니다.


dotnet --version
// 6.0.301

func --version
// 4.0.4629

which func
// /usr/local/bin/func

which dotnet
// /usr/local/share/dotnet/dotnet

Azure Function 생성(CLI)

func init

후에 터미널에 나오는 옵션중
1. dotnet 선택 -> 1
2. C# 선택 -> 1

func new

후에 터미널에 나오는 옵션중
1. HttpTrigger 선택 -> 1
2. 함수 이름 설정 -> 원하는 함수이름(실습에는 PingHttpTrigger 로 설정)

이후 디렉토리를 보면 새로운 파일들이 생성 되었습니다.
.csproj 파일을 열어 <TargetFramework>, <AzureFunctionsVersion> 태그 안의 값을 확인합니다.
<TargetFramwork> - net6.0
<AzureFunctionsVersion> - v4

네임 수정

.csproj 파일에 추가합니다.
<AzureFunctionsVersion> 태그 뒤에 추가합니다.

<AssemblyName>OCAProject</AssemblyName>
<RootNamespace>OCAProject</RootNamespace>

이후 PingHttpTrigger.cs 파일을 열어 소스코드 최상단의 namespace를 수정합니다.

namespace OCAProject

오류줄은 터미널에

dotnet build
func start

을 입력합니다.
정상적으로 동작을 한다면 http://localhost:7071/api/ping 에 접속하여 아래의 문구가 나타나는지 확인합니다.

This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.

이후 http://localhost:7071/api/ping?name=OCA 에 접속하여, 위의 문구가 다음과 같이 변경되는지 확인합니다.

Hello, OCA. This HTTP triggered function executed successfully.

클래스 수정

PingHttpTrigger 클래스를 다음과 같이 수정합니다.

[FunctionName(nameof(PingHttpTrigger))] 
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "ping")] HttpRequest req,
ILogger log)

그리고 다음의 코드를 삭제합니다.

string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;

다시 dotnet build 을 통해 다시 한번 빌드하고,

func start 를 통해 어플리케이션을 실행하면, http://localhost 환경에서 responseMessage 변수의 값이 출력되는 것을 확인할 수 있습니다.

http://localhost 주소 뒤에 query string ex)?name=emong 을 추가하여 요청을 보내면, 쿼리 스트링 값이 포함된 문자열 응답을 확인할 수 있습니다.

응답 객체 생성

Models라는 디렉토리를 생성후 내부에 ResponseMessage.cs 파일을 생성하고 아래와 같이 내용을 작성합니다.

public class ResponseMessage {
    [JsonProperty("response_message")] // Json 응답 객체의 key 를 변경. 기본적으로는 파스칼 케이싱을 캐멀 케이싱으로 변환.
    public string Message { get; set; }
}

그후 Services라는 디렉토리를 생성후 내부에 IMyService.cs라는 인터페이스 파일과 해당 인터페이스를 상속받아 구현하는 MyService.cs라는 파일을 생성하고 아래와 같이 내용을 작성합니다.

public interface IMyService {
        string GetMessage(string name);
}

public class MyService : IMyService {
    public string GetMessage(string name) {
        string responseMessage = string.IsNullOrEmpty(name)
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
            : $"Hello, {name}. This HTTP triggered function executed successfully.";

        return responseMessage;
    }
}

이후 PingHttpTrigger.cs 파일의 Run method 수정합니다.

var service = new MyService();
var result = service.GetMessage(name);

var res = new ResponseMessage() { Message = result };

결합도를 낮추기 위해 다음과 같은 읽기 전용 멤버 변수와 생성자를 PingHttpTrigger 클래스 최상위에 생성합니다.

private readonly IMyService _service;

public PingHttpTrigger(IMyService service) {
    this._service = service ?? throw new ArgumentNullException(nameof(service));
}

그후 코드를 다음과 같이 수정합니다.

var result = this._service.GetMessage(name);

var res = new ResponseMessage() { Message = result };

패키지 추가 설치

dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.Extensions.Http

설치후 <ItemGroup>태그를 .csproj 파일에서 확인하여 추가 패키지가 설치되었는지 확인합니다.

그후 Startup.cs란 파일을 프로젝트 루트 디렉토리에 생성하고 작성합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(OCAProject.Startup))]
namespace OCAProject
{
    public class Startup: FunctionsStartup {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddScoped<IMyService, MyService>();
        }
    }
}

Models, Services 디렉토리를 만드는 등 갑자기 너무 많은 것을 생성 및 수정하였는데요.

이는 객체 지향 프로그래밍의 원칙들을 준수하기 위함입니다.

우선, 객체 지향 프로그래밍에서는 하나의 클래스가 하나의 기능만을 담당하도록 하는 것이 권장됩니다.

따라서 각각의 cs파일들이 하나의 클래스만을 담을 수 있도록 디렉토리 및 파일을 생성하고 수정하였습니다.

또한, 각각의 클래스들이 강하게 결합되어 의존하지 않는 것이 권장됩니다. 따라서 종속성 주입을 해주었습니다.

OpenApi 등록

터미널을 통해 패키지를 추가합니다.

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

.csproj 파일에서 패키지가 잘 설치되었는지 확인합니다.
다음과 같이 PingHttpTrigger 클래스를 수정합니다.
OpenApi에 등록하기위해 attribute 를 추가해줍니다.

[FunctionName(nameof(PingHttpTrigger))]

// OpenApi에 등록합니다.
[OpenApiOperation(operationId: "Ping", tags: new[] { "greeting" })]
// OpenApi credential을 설정합니다.
[OpenApiSecurity(schemeName: "function_key", schemeType: SecuritySchemeType.ApiKey, Name = "x-functions-key", In = OpenApiSecurityLocationType.Header)]
// OpenApi parameter를 설정합니다.
[OpenApiParameter(name: "name", In = ParameterLocation.Query, Required = true, Description = "Name of the person")]
// OpenApi response를 설정합니다.
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(ResponseMessage), Description = "response description")]

namspace가 소스 파일에 있는지 확인합니다.

그후 다시 빌드를 진행합니다.

dotnet build
func start

http://localhost:7071/api/swagger/ui 로 접속하면 아래와 같은 화면이 나타납니다.

profile
코린이 입니당 :)

0개의 댓글