발대식이 끝난후 7/12일 첫번째 워크샵을 진행하게 되었다.
워크샵을 준비하기 위한 개발환경이 필요하였다.
원래 발대식때 개발환경을 다같이 맞춰서 진행하려고 했는데
발대식때 설명하는 시간이 너무 길어져서 개발환경은 세팅하지 못하여 수업전에 미리 해오기로 했습니다!
M365 개발자 계정 : https://study.fusiondev.kr/m365/m365-dev-setup
파워 플랫폼 개발자 계정 : https://study.fusiondev.kr/pp/pp-dev-setup
NHN 클라우드 계정 : https://toast.com/
이후 다음과 같이 .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
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파일들이 하나의 클래스만을 담을 수 있도록 디렉토리 및 파일을 생성하고 수정하였습니다.
또한, 각각의 클래스들이 강하게 결합되어 의존하지 않는 것이 권장됩니다. 따라서 종속성 주입을 해주었습니다.
터미널을 통해 패키지를 추가합니다.
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 로 접속하면 아래와 같은 화면이 나타납니다.