ASP.NET Core 1.2 · 1부. 웹 개발 기초

프로젝트 생성과 구조

Program.cs 와 미들웨어 파이프라인을 읽습니다.

예상 학습 시간 14분 난이도 입문
개념 설명

템플릿을 선택해 만듭니다

웹 프로젝트도 콘솔과 같이 dotnet new 로 만듭니다. 다만 뒤에 적는 이름이 여럿입니다. 무엇을 만들 것이냐에 따라 미리 채워 주는 것이 다르기 때문입니다.

이름만들어 주는 것
web비어 있는 웹입니다. 필요한 것을 직접 추가합니다.
webapi데이터를 돌려주는 API 입니다. 예제 주소가 하나 들어 있습니다.
mvc컨트롤러와 뷰를 갖춘 웹앱입니다.
webappRazor Pages 웹앱입니다.
blazorwasm브라우저 안에서 도는 앱입니다.

이 트랙은 webwebapi 를 주로 사용합니다. 어느 것으로 만들든 안에 들어 있는 파일의 종류는 거의 같습니다. 채워진 내용만 다릅니다. 어떤 것이 있는지 dotnet new list web 으로 볼 수 있습니다.

최소 예제

만들고 돌려 보기

webapi 로 하나 만들어 보겠습니다. 이 트랙이 끝날 때 만들 할일 API 와 이름을 맞춰 두었습니다.

터미널
dotnet new webapi -o TodoApi
cd TodoApi
dotnet run
출력
info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5263 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development

이 단원의 명령은 브라우저가 아니라 여러분의 터미널에서 돌립니다.

찍힌 주소 뒤에 /weatherforecast 를 붙여 열면 템플릿이 넣어 둔 예제가 JSON 을 돌려줍니다. 포트 번호는 만들 때 무작위로 정해지므로 여러분의 것과 다릅니다.

[{"date":"2026-08-30","temperatureC":0,"summary":"Balmy","temperatureF":32}, …]
상세 사용법

만들어진 파일

빌드하기 전의 폴더에는 파일이 여섯 개뿐입니다.

TodoApi/
├─ Program.cs                    // 프로그램이 시작하는 곳
├─ TodoApi.csproj                // 프로젝트 설정
├─ TodoApi.http                  // 편집기에서 요청을 보내 보는 파일
├─ appsettings.json              // 설정값
├─ appsettings.Development.json  // 개발일 때 덮어쓸 설정값
└─ Properties/
   └─ launchSettings.json        // dotnet run 이 읽는 실행 설정

dotnet run 을 하면 binobj 가 생깁니다. 빌드가 만드는 것이라 손대지 않고, 버전 관리에도 넣지 않습니다.

콘솔 프로젝트와 다른 곳

.csproj 의 첫 줄이 다릅니다. 콘솔은 Microsoft.NET.Sdk 인데 웹은 Microsoft.NET.Sdk.Web 입니다. 이 한 글자 차이로 ASP.NET Core 전체가 참조에 들어옵니다. 따로 패키지를 추가하지 않아도 WebApplication 을 사용할 수 있는 까닭입니다.

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

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>

launchSettings.json 은 개발 기계에서만 읽습니다

실행할 때 어느 주소로 띄울지는 여기에 있습니다. 그런데 이 파일은 배포본에 들어가지 않습니다. dotnet publish 한 폴더를 열어 보면 appsettings.json 은 있어도 launchSettings.json 은 없습니다. 개발하는 사람마다 다르게 두는 것이라 그렇습니다.

그래서 운영에서 주소를 정하는 방법은 따로입니다(5.1에서 다룹니다). 그리고 개발 중에는 반대로 이 파일이 --urlsASPNETCORE_URLS 보다 앞섭니다. 주소를 바꿨는데 그대로라면 이 파일을 먼저 보십시오.

// 프로필 이름을 골라 띄웁니다
dotnet run --launch-profile http

// 프로필을 아예 사용하지 않습니다
dotnet run --no-launch-profile --urls http://localhost:5000
상세 사용법

Program.cs 는 두 단계입니다

파일 하나뿐이지만 안이 둘로 나뉩니다. 경계는 builder.Build() 입니다.

var builder = WebApplication.CreateBuilder(args);

// ① 무엇을 갖출지 — 서비스를 등록합니다
builder.Services.AddOpenApi();

var app = builder.Build();

// ② 요청이 어떤 길로 지날지 — 미들웨어를 놓습니다
if (app.Environment.IsDevelopment()) {
    app.MapOpenApi();
}

app.UseHttpsRedirection();

app.MapGet("/weatherforecast", () => Results.Ok(forecast));

app.Run();

이 경계는 지켜야 합니다. Build() 는 그때까지 등록된 것으로 완성된 앱을 만들고, 서비스 목록을 읽기 전용으로 잠급니다. 뒤에서 추가하면 실행할 때 예외가 발생합니다.

Program.cs
var app = builder.Build();

builder.Services.AddSingleton<TimeProvider>(TimeProvider.System);
출력
Unhandled exception. System.InvalidOperationException: The service collection cannot be modified because it is read-only.

② 에 놓는 것들이 요청을 어떻게 지나보내는지는 ASP.NET Core 1.3 요청과 응답 파이프라인 에서 다룹니다.

버전 배지

Startup.cs 가 있는 예제를 만나면

.NET 6 부터

위의 두 단계는 원래 Startup.cs 라는 파일에 ConfigureServicesConfigure 두 메서드로 나뉘어 있었습니다. .NET 6 에서 최상위 문이 들어오면서 그 파일이 사라지고 Program.cs 하나로 합쳐졌습니다.

합쳐졌을 뿐 하는 일과 순서는 그대로입니다. 옛 예제를 옮길 때는 ConfigureServices 안의 것을 Build() 앞으로, Configure 안의 것을 뒤로 옮기면 됩니다.

실습 문제

직접 해보기

1. 빈 템플릿과 비교하기 난이도 하

web 템플릿으로 하나 더 만들어, webapi 로 만든 것과 Program.cs 가 어떻게 다른지 보세요.

템플릿 이름만 바꾸면 됩니다. 빈 것은 예제 주소와 OpenApi 등록이 없습니다.
dotnet new web -o EmptyWeb # EmptyWeb/Program.cs 는 네 줄입니다. TodoApi 쪽에는 # AddOpenApi 등록과 /weatherforecast 예제가 더 있습니다.
2. 실행 주소 바꾸기 난이도 중

http://localhost:5000 으로 뜨게 해보세요. 두 가지 방법이 있습니다.

--urls 만 붙이면 프로필이 앞서서 듣지 않습니다. 프로필을 고치거나, 프로필을 사용하지 않도록 해야 합니다.
# 방법 1 — launchSettings.json 의 applicationUrl 을 고칩니다 "applicationUrl": "http://localhost:5000" # 방법 2 — 프로필을 사용하지 않습니다 dotnet run --no-launch-profile --urls http://localhost:5000
3. 경계를 넘겨 보기 난이도 상

서비스 등록 한 줄을 builder.Build() 뒤로 옮겨 실행하고, 어떤 예외가 발생하는지 확인해보세요. 그리고 그 예외 문구가 왜 그렇게 적혀 있는지 생각해보세요.

예외 문구에 "read-only" 가 나옵니다. 무엇이 읽기 전용이 되었는지 보세요.
System.InvalidOperationException: The service collection cannot be modified because it is read-only. // Build() 가 서비스 목록을 잠급니다. 앱이 이미 만들어진 뒤에 // 목록이 바뀌면, 먼저 만들어진 것과 나중에 등록된 것이 서로 // 다른 것을 보게 되기 때문입니다.
요약
  • dotnet new 뒤의 이름이 무엇을 채워 줄지 정합니다. 파일의 종류는 어느 것이나 거의 같습니다.
  • .csprojSdk="Microsoft.NET.Sdk.Web" 가 ASP.NET Core 를 참조에 들입니다.
  • launchSettings.json개발 기계에서만 읽고 배포본에 들어가지 않습니다. 개발 중에는 --urls 보다 앞섭니다.
  • Program.csBuild() 를 경계로 서비스 등록미들웨어 배치로 나뉩니다.