.NET 개발을 시작하면 반드시 마주치는 것이 바로 IIS(Internet Information Services) 이다. 처음에는 visual studio에서 "그냥 F5 누르면 실행되는데 이게 왜 필요하지?"라는 생각이 들 수 있다. 하지만 실제 서비스를 배포하려면 IIS에 대한 이해가 필수다.
이 글에서는 IIS가 무엇인지, 왜 필요한지, 그리고 실제로 어떻게 사용하는지를 정리하고자 한다.
IIS(Internet Information Services) 는 Microsoft에서 만든 웹 서버 소프트웨어 이다. 쉽게 말해 "내가 만든 웹 애플리케이션을 인터넷에 공개해주는 프로그램" 이라고 생각하면 된다.
내가 만든 .NET 웹 애플리케이션 = 음식
IIS = 식당 (손님에게 음식을 제공)
브라우저(클라이언트) = 손님
[사용자 브라우저]
↓ 요청 (HTTP) ↓
[IIS]
↓ 전달 ↓
[.NET 애플리케이션]
↓ 처리 결과 ↓
[IIS]
↓ 응답 (HTTP) ↓
[사용자 브라우저]
개발 중에는 IIS Express 나 Kestrel 이라는 내장 서버가 자동으로 실행된다. 하지만 이것과 실제 운영 환경은 다르다.
| 구분 | 개발 환경 (Kestrel/IIS Express) | 운영 환경 (IIS) |
|---|---|---|
| 용도 | 로컬 테스트 | 실제 서비스 |
| 보안 | 기본적인 수준 | 강력한 보안 기능 |
| 성능 | 단일 사용자 | 다수 동시 접속 처리 |
| 기능 | 최소한 | SSL, 압축, 캐싱, 로깅 등 |
개발할 때는 내장 서버로 충분하지만, 실제 서비스 배포는 IIS를 통해 하는 것이 일반적이다.
IIS를 이해하려면 반드시 알아야 할 개념 3가지가 있다.
하나의 웹사이트 단위 이다. 도메인이나 포트로 구분한다.
http://mysite.com → 사이트 A
http://mysite.com:8080 → 사이트 B
http://another.com → 사이트 C
하나의 IIS 서버에서 여러 개의 사이트를 동시에 운영할 수 있다.
애플리케이션을 실행하는 독립된 작업 공간 이다.
[애플리케이션 풀 A] → 사이트 1, 사이트 2
[애플리케이션 풀 B] → 사이트 3
위 그림에서 만약 사이트 3에서 심각한 오류가 발생해서 풀 B가 죽어도, 풀 A에 있는 사이트 1, 2는 전혀 영향을 받지 않는다. 이것이 애플리케이션 풀을 분리하는 이유이다.
중요한 서비스는 반드시 별도의 애플리케이션 풀에 배치해서 장애를 격리해야 한다.
어떤 주소로 들어온 요청을 받을지 설정하는 것이다.
| 항목 | 설명 | 예시 |
|---|---|---|
| IP 주소 | 특정 IP만 받을지, 전체 받을지 | *, 192.168.0.1 |
| 포트 | 어떤 포트로 받을지 | 80, 443, 8080 |
| 호스트 이름 | 어떤 도메인으로 받을지 | myapp.com |
같은 서버에서 여러 사이트를 운영할 때 바인딩으로 구분한다.
Visual Studio에서 기본 제공하는 경량 IIS 이다.
특징:
Visual Studio → 프로젝트 속성 → 디버그 → IIS Express 선택
IIS Express는 개발/테스트 용도로만 사용하고, 실제 서비스에는 절대 사용하지 않는다.
실제 서비스 배포에 사용하는 전체 기능의 IIS이다.
IIS는 Windows에 기본 포함되어 있지만, 기본적으로 꺼져 있다. 활성화 방법은 다음과 같다.
1. Windows 키 + R → "optionalfeatures" 입력
2. 또는 제어판 → 프로그램 → Windows 기능 켜기/끄기
체크해야 할 항목:
☑ 인터넷 정보 서비스 (Internet Information Services)
☑ World Wide Web 서비스
☑ 응용 프로그램 개발 기능
☑ .NET Extensibility 4.x
☑ ASP.NET 4.x
☑ 일반적인 HTTP 기능
☑ 기본 문서
☑ 정적 콘텐츠
☑ 웹 관리 도구
☑ IIS 관리 콘솔
서버 관리자 → 역할 및 기능 추가 → 웹 서버(IIS) 선택
.NET Core 이상 버전을 사용한다면 ASP.NET Core 호스팅 번들 을 반드시 설치해야 한다.
1. https://dotnet.microsoft.com/download/dotnet 접속
2. 사용하는 .NET 버전 선택
3. Hosting Bundle 다운로드 및 설치
4. IIS 재시작
실제로 ASP.NET 애플리케이션을 IIS에 배포하는 전체 과정을 정리한다.
필자가 사내 프로젝트를 진행하며 학습한대로 작성한 것이니 다를 수 있다.

Visual Studio → 프로젝트 우클릭 → 게시(Publish)
→ 폴더 선택 → 새 폴더 생성 → 게시
게시 후 생성되는 파일 구조:
📁 publish/
├── MyApp.dll
├── MyApp.exe
├── web.config
├── appsettings.json
└── wwwroot/
├── css/
├── js/
└── ...
원격 데스크톱 연결
→ IP 주소 입력
→ "다른 계정 사용" 선택
→ 서버 계정 ID/PW 입력
IIS Manager 실행 (inetmgr)
→ Sites 우클릭 → Add Website
입력 항목:
| 항목 | 설명 | 예시 |
|---|---|---|
| Site name | 사이트 구분 이름 | MyWebApp |
| Physical path | 배포 파일 경로 | C:\inetpub\MyWebApp |
| Host name | 접속할 도메인 | myapp.local |
로컬에서 게시한 파일들을 서버의 Physical path에 복사한다.
로컬: C:\publish\*
↓ 복사
서버: C:\inetpub\MyWebApp\
실제 도메인이 없을 때, 가상 도메인처럼 사용할 수 있게 해준다.
경로:
C:\Windows\System32\drivers\etc\hosts
추가 내용:
127.0.0.1 www.dev.myapp.com
hosts 파일 수정이 안된다면 Notepad로 관리자 권한 으로 열어 수정해보자.
브라우저에서 www.dev.myapp.com 입력
↓
hosts 파일 확인: myapp.local → 127.0.0.1
↓
127.0.0.1:80 으로 요청
↓
IIS가 Host name이 myapp.local인 사이트 찾음
↓
해당 사이트 응답
IIS의 동작 방식이 버전에 따라 다르다.
| 구분 | .NET Framework | .NET Core/5+ |
|---|---|---|
| IIS 역할 | 직접 실행 | 리버스 프록시 |
| 호스팅 번들 | 불필요 | 필수 |
| 실제 실행 | IIS 워커 프로세스 | Kestrel |
| web.config | 상세 설정 | 최소 설정 |
[사용자] → [IIS] → [Kestrel] → [.NET 앱]
↑
리버스 프록시
(보안, SSL 처리)
최신 .NET에서는 IIS가 앞단에서 보안 처리만 하고, 실제 앱 실행은 Kestrel이 담당 한다.
원인: web.config 파일 문법 오류 또는 권한 문제
해결:
1. web.config 문법 확인
2. 사이트 폴더에 IIS_IUSRS 읽기 권한 부여
원인: .NET 런타임 없음 또는 버전 불일치
해결:
1. 호스팅 번들 설치 확인
2. 앱과 런타임 버전 일치 확인
원인: 폴더 접근 권한 부족
해결: 사이트 폴더에 IIS_IUSRS 권한 추가
에러가 발생하면 이벤트 뷰어(eventvwr) 에서 Windows 로그 → 응용 프로그램을 확인하면 상세 원인을 알 수 있다.
| 개념 | 한 줄 설명 |
|---|---|
| IIS | Windows용 웹 서버, .NET 앱을 인터넷에 공개하는 역할 |
| 사이트 (Site) | 하나의 웹사이트 단위, 도메인/포트로 구분 |
| 애플리케이션 풀 | 앱 실행 환경, 분리하면 장애 격리 가능 |
| 바인딩 | 어떤 IP/포트/도메인으로 접근할지 설정 |
| IIS Express | 개발용 경량 IIS |
| Kestrel | .NET 내장 웹 서버 |
| hosts 파일 | 도메인 없이 가상 도메인처럼 사용하게 해주는 설정 |
IIS는 .NET 웹 개발에서 피할 수 없는 존재이다. 핵심만 정리하면 다음과 같다.
처음에는 복잡해 보이지만, 한 번 직접 배포해보면 금방 익숙해진다.