프로그래밍/C#, .NET

[.NET] 응용프로그램(WinForm, WPF...)에서 웹호스팅 하기(Self Host)

당근천국 2021. 9. 1. 15:30

이 포스팅에서는 응용프로그램(WinForm, WPF...)에서 ASP.NET를 포함한 웹 서비스를 제공하는 방법을 다룹니다.

퍼블리싱된 파일을 서비스하는 것이 아닙니다.

 

웹서버를 구현한다고도 볼 수 있는데.....

IIS나 Kestrel처럼 퍼블리싱된 파일을 읽어서 서비스하는 방식은 아닙니다.

(그렇다고 구현방식이 다른 건 아닙니다 ㅎㅎㅎㅎ)

 

 

1. 프로젝트 생성

프로젝트는 ".Net 5 WinForm 애플리케이션"으로 생성합니다.

여기서는 "웹 응용 프로그램 MVC (모델-뷰-컨트롤러)"로 생성합니다.

 

'Form1'의 이름을 'MainForm'으로 바꿉니다.

폼을 다음과 같이 구성합니다.

 

버튼을 누르면 브라우저가 열리도록 코드를 넣습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void btnChrome_Click(object sender, EventArgs e)
{
    //https://stackoverflow.com/questions/58846709/process-start-in-core-3-0-does-not-open-a-folder-just-by-its-name
    var psi = new ProcessStartInfo
    {
        FileName = "chrome.exe",
        Arguments = this.txtUrl.Text,
        UseShellExecute = true
    };
    Process.Start(psi);
}
 
private void btnMsEdge_Click(object sender, EventArgs e)
{
    //https://stackoverflow.com/questions/58846709/process-start-in-core-3-0-does-not-open-a-folder-just-by-its-name
    var psi = new ProcessStartInfo
    {
        FileName = "msedge.exe",
        Arguments = this.txtUrl.Text,
        UseShellExecute = true
    };
    Process.Start(psi);
}
cs

 

 

2. 웹 SDK로 변경하기

이제 프로젝트를 'Web SDK'로 변경해야 합니다.

 

솔루션 탐색기에서 프로젝트를 더블클릭해서 '*.csproj' 파일을 열어줍니다.

<Project Sdk="Microsoft.NET.Sdk">

이것을

<Project Sdk="Microsoft.NET.Sdk.Web">

이렇게 바꿔줍니다.

그러면 프로젝트를 다시 로드하라고 합니다.

다시 로드해줍니다.

 

프로젝트의 아이콘이 '웹 응용프로그램'으로 바꿔있습니다.

 

3. ASP.NET 만들기

이제 "웹 응용프로그램 프로젝트"에서 파일을 복사해서 사용하면 됩니다.

 

 

3-1. 파일 생성

"웹 응용프로그램 프로젝트"에서 다음 파일을 복사해서 사용해도 됩니다.

단, 레이저는 제가 테스트를 해보지 않아서 모르겠네요.

아마도 참조 같은 것들을 더 건릴 여야 할 겁니다.

 

Properties

wwwroot

Controllers

Models

Views

appsettings.json

Startup.cs

 

3-2. 'launchSettings.json'파일 수정

이 파일은 웹서버를 실행할 때 사용될 설정을 가지고 있는 파일입니다.

 

이 파일을 아래와 같이 수정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "profiles": {
    "PBAutoWinServer": {
      "commandName""Project",
      "dotnetRunMessages""true",
      "launchBrowser"true,
      "applicationUrl""http://localhost:5000;https://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT""Development"
      }
    }
  }
}
cs

 

이렇게 설정하면 'http://localhost:5000/'에서 웹서버가 실행됩니다.

 

 

3-3. 'Program.cs' 수정

프로그램이 시작되면 웹서버가 동작하도록 'Program.cs'에 다음 코드를 추가합니다.

1
2
3
4
5
6
public static IHostBuilder CreateHostBuilder() =>
    Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
    webBuilder.UseStartup<Startup>();
});
cs

 

 

'static void Main()'

에 'CreateHostBuilder()'를 호출하는 코드를 추가합니다.

1
CreateHostBuilder().Build().RunAsync();
cs

 

 

 

3-4. 'Startup.cs' 생성 혹은 수정

'Startup.cs'파일을 생성하거나 복사하고 다음 코드를 넣습니다.

기존 코드를 그대로 써도 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
 
    public IConfiguration Configuration { get; }
 
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }
 
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }
 
        app.UseStaticFiles();
 
        app.UseRouting();
 
        app.UseAuthorization();
 
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}
cs

 

'env'오류

버전에 따라 다음과 같은 오류가 날 수 있습니다.

'IWebHostEnvironment'에는 'IsDevelopment'에 대한 정의가 포함되어 있지 않고, 가장 적합한 확장 메서드 오버로드 'HostingEnvironmentExtensions.IsDevelopment(IHostingEnvironment)'에는 'IHostingEnvironment' 형식의 수신기가 필요합니다.

'IWebHostEnvironment' does not contain a definition for 'IsDevelopment' and the best extension method overload 'HostingEnvironmentExtensions.IsDevelopment(IHostingEnvironment)' requires a receiver of type 'IHostingEnvironment'

 

'IWebHostEnvironment'의 네임스페이스가 변경되면서 발생하는 문제입니다.

 

코드에 아래 두 개를 추가해줍니다.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

 

 

3-5. 'wwwroot'를 출력 폴더에 복사하기

'wwwroot'는 자동 출력이 되지 않습니다.

배포 설정을 해서 출력하는 방법과

해당 파일들의 '출력 디렉터리로 복사' 옵션을 설정하는 방법,

수작업으로 출력 폴더에 파일을 저장하는 방법이 있습니다.

 

테스트할 때는 'Debug' 폴더에 복사해서 사용합니다.

 

 

4. 테스트하기

디버깅을 돌리면 자동으로 웹 페이지가 표시되지만

릴리즈한 파일로 실행하면 자동으로 웹페이지가 열리지 않습니다.

 

프로그램을 실행하고 웹 페이지를 열어 봅시다.

 

마무리

프로젝트 셈플 소스 : https://github.com/dang-gun/DotNetSamples/tree/master/SelfHost

참고 : https://github.com/tonysneed/Demo.DotNetSelfHost

 

한참 웹 프로젝트로 만들어놨더니 응용프로그램으로 바꿔 달라고 해서 찾은 자료입니다 ㅎㅎㅎㅎ

닷넷은 이런 게 쉽게 쉽게 구현된다는 게 큰 장점입니다.

 

이렇게 구현된 웹서버는 포트만 열어두면 외부에서도 접속이 가능합니다.

그 말은 윈도우 홈 버전과 같이 IIS가 동작하지 않는 운영체제에서도 웹서버 운영이 가능하다는 소리죠.