왜 이 글을 쓰나
리눅스가 낯선 사람들은 Windows 서버로 시작하는 경우가 많다. AWS EC2도 Windows 인스턴스를 선택하면 익숙한 GUI가 나온다. 그런데 막상 IIS를 처음 열면 뭐가 뭔지 모른다. "사이트"가 뭔지, "애플리케이션 풀"이 뭔지, PHP는 어떻게 연결하는지. XAMPP는 설치 자체는 쉬운데, 포트 충돌이나 외부 접속 설정에서 막힌다.
이 글은 Windows 서버 환경을 처음 세팅하는 사람 기준으로, 헷갈리는 부분을 중심으로 정리했다.
IIS 설치 및 기본 설정
IIS 활성화
IIS는 기능을 켜야 쓸 수 있다. 제어판이나 서버 관리자에서 활성화한다.
Windows 10/11 (개발 환경):
- 제어판 → 프로그램 → Windows 기능 켜기/끄기
- "인터넷 정보 서비스" 체크
- 하위 항목에서 "CGI", "ISAPI 확장", "ISAPI 필터" 추가 체크
Windows Server:
- 서버 관리자 → 역할 및 기능 추가
- "웹 서버(IIS)" 역할 선택
- 역할 서비스에서 CGI 포함 여부 확인 (PHP 연동 필수)
설치 후 http://localhost에 접속하면 IIS 기본 페이지가 뜬다.
사이트 추가
IIS 관리자 실행 (inetmgr):
컴퓨터명
└── 사이트
└── Default Web Site ← 기본 사이트 (포트 80)
새 사이트 추가:
- "사이트" 우클릭 → 웹 사이트 추가
- 사이트 이름 입력 (예:
myapp) - 물리적 경로 설정 (예:
C:\inetpub\wwwroot\myapp) - 바인딩 설정 (포트, 도메인)
바인딩 설정
한 서버에서 여러 사이트를 운영할 때 바인딩으로 구분한다.
| 방법 | 예시 | 설명 |
|---|---|---|
| 포트 구분 | :8080, :8081 |
개발 환경에서 자주 씀 |
| 도메인 구분 | app1.example.com, app2.example.com |
실서버에서 주로 씀 |
| IP 구분 | 서버에 IP 여러 개 할당 | 드물게 사용 |
HTTPS를 쓰려면 바인딩 타입을 "https"로 선택하고 인증서를 연결한다. Let's Encrypt는 IIS에서 Win-ACME로 처리한다.
애플리케이션 풀 설정
애플리케이션 풀은 사이트가 어떤 권한과 프로세스로 실행되는지를 결정한다. 기본값은 DefaultAppPool.
중요한 설정:
- .NET CLR 버전: PHP만 쓰면 "관리 코드 없음"으로 설정
- ID: 기본값
ApplicationPoolIdentity. 파일 업로드 권한 문제가 생기면 여기서 계정을 바꾼다
IIS 관리자 → 애플리케이션 풀 → [풀 이름] 우클릭 → 고급 설정
→ 프로세스 모델 → ID → 사용자 지정 계정 설정
PHP + IIS 연동
PHP 설치
IIS에서 PHP를 쓰려면 Windows용 PHP를 따로 설치해야 한다.
- windows.php.net/download 에서 Non-Thread Safe 버전 다운로드
C:\php에 압축 해제php.ini-development를php.ini로 복사- 환경 변수
PATH에C:\php추가
FastCGI 핸들러 매핑
IIS에서 PHP를 실행하려면 FastCGI 방식으로 연결한다.
IIS 관리자 → 서버 수준(또는 사이트 수준) → "처리기 매핑" → "모듈 매핑 추가":
요청 경로: *.php
모듈: FastCgiModule
실행 파일: C:\php\php-cgi.exe
이름: PHP_via_FastCGI
이후 C:\inetpub\wwwroot\test.php 파일을 만들어 확인:
<?php
phpinfo();
?>
http://localhost/test.php에 접속해서 PHP 정보 페이지가 뜨면 연동 성공이다.
php.ini 주요 항목
; 에러 표시 (개발 중에는 On, 운영에서는 Off)
display_errors = On
error_reporting = E_ALL
; 업로드 크기 제한
upload_max_filesize = 50M
post_max_size = 50M
; 실행 시간 제한
max_execution_time = 300
; 타임존
date.timezone = Asia/Seoul
; 주요 확장 활성화 (앞의 ; 제거)
extension=curl
extension=gd
extension=mbstring
extension=mysqli
extension=pdo_mysql
extension=openssl
확장 경로도 맞게 지정해야 한다:
extension_dir = "C:\php\ext"
XAMPP 설정
기본 구조
XAMPP는 Apache + MySQL(MariaDB) + PHP + phpMyAdmin을 한 번에 설치해주는 패키지다. IIS 없이 PHP 개발 환경을 빠르게 구성할 때 쓴다.
설치 후 기본 경로:
| 항목 | 경로 |
|---|---|
| 웹 루트 | C:\xampp\htdocs\ |
| Apache 설정 | C:\xampp\apache\conf\httpd.conf |
| PHP 설정 | C:\xampp\php\php.ini |
| MySQL 설정 | C:\xampp\mysql\bin\my.ini |
| 로그 | C:\xampp\apache\logs\ |
서비스 자동 시작 설정
XAMPP 컨트롤 패널에서 Apache, MySQL 옆 "Svc" 체크박스를 클릭하면 Windows 서비스로 등록된다. 이후 부팅 시 자동 시작된다.
수동으로 서비스 등록하려면 관리자 권한 CMD:
"C:\xampp\apache\bin\httpd.exe" -k install -n "Apache2.4"
"C:\xampp\mysql\bin\mysqld.exe" --install MySQL
포트 충돌 해결
XAMPP 설치 후 Apache가 시작되지 않으면 대부분 포트 80 충돌이다.
충돌 확인:
netstat -ano | findstr :80
netstat -ano | findstr :3306
PID를 확인하고 작업 관리자에서 해당 프로세스를 찾는다. Skype, IIS, 다른 웹 서버가 원인인 경우가 많다.
Apache 포트 변경 (httpd.conf):
# 기존
Listen 80
# 변경
Listen 8080
MySQL 포트 변경 (my.ini):
[mysqld]
port=3307
[client]
port=3307
외부 접속 허용 설정
기본 설치 상태에서는 localhost만 접속할 수 있다. 외부에서 접속하려면 설정을 바꿔야 한다.
Apache 외부 접속 허용 (httpd.conf):
# 기존 (localhost만)
<Directory "C:/xampp/htdocs">
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require local
</Directory>
# 변경 (모든 IP 허용)
<Directory "C:/xampp/htdocs">
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require all granted
</Directory>
phpMyAdmin 외부 접속 허용 (C:\xampp\phpMyAdmin\config.inc.php 또는 C:\xampp\apache\conf\extra\httpd-xampp.conf):
<Directory "C:/xampp/phpMyAdmin">
AllowOverride AuthConfig
Require all granted
</Directory>
MySQL/MariaDB (XAMPP 내장)
루트 비밀번호 설정
기본 설치 상태에서 root 비밀번호는 없다. 외부 접속 허용 전에 반드시 설정한다.
XAMPP 컨트롤 패널 → MySQL "Shell" 클릭:
ALTER USER 'root'@'localhost' IDENTIFIED BY '새비밀번호';
FLUSH PRIVILEGES;
또는 mysqladmin 사용:
C:\xampp\mysql\bin\mysqladmin -u root password "새비밀번호"
비밀번호 설정 후 phpMyAdmin 설정도 업데이트해야 한다 (config.inc.php):
$cfg['Servers'][$i]['password'] = '새비밀번호';
원격 접속 허용
특정 IP에서 원격 접속을 허용하는 방법:
-- 특정 IP만 허용
GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.1.100' IDENTIFIED BY '비밀번호';
-- 모든 IP 허용 (운영 환경에서는 비추천)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '비밀번호';
FLUSH PRIVILEGES;
my.ini에서 bind-address 확인:
[mysqld]
# 외부 접속 허용하려면 아래 줄 주석 처리 또는 0.0.0.0으로 변경
bind-address = 0.0.0.0
Windows 방화벽 설정
서비스를 아무리 잘 설정해도 방화벽이 막혀 있으면 외부에서 접속이 안 된다.
인바운드 규칙 추가
PowerShell (관리자 권한):
# HTTP
netsh advfirewall firewall add rule name="HTTP 80" dir=in action=allow protocol=TCP localport=80
# HTTPS
netsh advfirewall firewall add rule name="HTTPS 443" dir=in action=allow protocol=TCP localport=443
# MySQL
netsh advfirewall firewall add rule name="MySQL 3306" dir=in action=allow protocol=TCP localport=3306
# RDP
netsh advfirewall firewall add rule name="RDP 3389" dir=in action=allow protocol=TCP localport=3389
GUI로 추가하려면: 제어판 → Windows Defender 방화벽 → 고급 설정 → 인바운드 규칙 → 새 규칙
RDP 포트 변경 (보안 권장)
기본 RDP 포트 3389는 자동화된 공격 대상이 된다. 포트를 변경하면 스캐닝 공격을 줄일 수 있다.
레지스트리 수정:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
→ PortNumber 값 변경 (예: 55389)
PowerShell로도 가능:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name PortNumber -Value 55389
변경 후 방화벽에서 새 포트도 허용하고, 기존 3389 규칙은 비활성화한다.
FTP 설정 (IIS FTP 서버)
FTP 기능 설치
IIS FTP 서버를 쓰려면 FTP 기능을 먼저 설치해야 한다.
Windows 기능 켜기/끄기에서 "인터넷 정보 서비스" → "FTP 서버" 체크.
FTP 사이트 추가
IIS 관리자 → 사이트 → FTP 사이트 추가:
- FTP 사이트 이름, 실제 경로 설정
- 바인딩: IP 주소, 포트(21), SSL 없음(또는 허용)
- 인증: 기본(사용자 이름/암호)
- 권한: 읽기/쓰기 허용
사용자 격리 설정
여러 사용자가 FTP를 쓸 때, 각 사용자가 자기 폴더에만 접근하도록 격리할 수 있다.
IIS 관리자 → FTP 사이트 선택 → "FTP 사용자 격리":
격리 옵션: "사용자 이름 디렉터리(전역 가상 디렉터리 사용 안 함)"
폴더 구조:
C:\inetpub\ftproot\
├── LocalUser\
│ ├── user1\ ← user1 접속 시 이 폴더가 루트
│ └── user2\ ← user2 접속 시 이 폴더가 루트
FileZilla로 연결
| 항목 | 값 |
|---|---|
| 호스트 | 서버 IP |
| 포트 | 21 |
| 프로토콜 | FTP |
| 암호화 | 명시적 FTP over TLS (보안 설정 시) |
| 로그온 유형 | 일반 |
방화벽에서 21번 포트와 패시브 모드용 포트 범위(예: 49152-65535)를 허용해야 한다.
IIS vs XAMPP 비교
| 항목 | IIS | XAMPP |
|---|---|---|
| 주 용도 | 실서버 운영, 엔터프라이즈 환경 | 로컬 개발, 빠른 테스트 환경 |
| 설치 | Windows 기능 활성화 | 독립 패키지 설치 |
| PHP 연동 | FastCGI 수동 설정 필요 | PHP 포함, 바로 사용 가능 |
| 관리 도구 | IIS 관리자 (GUI) | XAMPP 컨트롤 패널 |
| 성능 | 높음 (기업 환경 최적화) | 개발 환경 수준 |
| 보안 설정 | 세밀한 제어 가능 | 기본 설정이 느슨함 |
| 비용 | Windows Server 라이선스 필요 | 무료 오픈소스 |
Windows 서버 vs Linux 서버
| 항목 | Windows Server | Linux (Ubuntu/CentOS) |
|---|---|---|
| 웹 서버 | IIS (기본), Apache 가능 | Apache, Nginx |
| GUI | 기본 제공 (RDP) | 선택적 (대부분 CLI) |
| PHP 설정 | FastCGI 핸들러 매핑 | apt/yum + 모듈 설정 |
| 학습 난이도 | 친숙한 GUI, 하지만 설정 위치가 분산 | CLI 진입 장벽, 하지만 문서 풍부 |
| 비용 | 라이선스 비용 발생 | 대부분 무료 |
| 호스팅 지원 | AWS, Azure에서 지원 | 대부분의 클라우드 지원 |
삽질 기록
포트 80 충돌 — IIS + Skype
IIS를 켰는데 Apache가 포트 80을 못 잡는 경우가 있다. netstat -ano | findstr :80 을 실행하면 Skype가 잡고 있는 걸 발견한다. 예전 Skype는 80, 443 포트를 HTTP 대안 포트로 사용했다. Skype 설정 → 고급 → 연결에서 "80, 443 포트 대체 사용" 해제하면 해결된다.
IIS 자체도 설치하면 자동으로 시작된다. XAMPP Apache랑 IIS가 같이 켜져 있으면 당연히 충돌한다. 둘 중 하나만 80 포트를 쓰게 해야 한다.
PHP 확장을 못 찾는 문제
phpinfo()는 뜨는데 특정 확장이 비활성화 상태인 경우, php.ini에서 주석을 해제했는데도 안 되는 경우가 있다. 원인은 대부분 extension_dir 경로 문제다.
; 이렇게 하면 안 됨 (상대 경로)
extension_dir = "ext"
; 이렇게 절대 경로로 써야 함
extension_dir = "C:\php\ext"
IIS 재시작 후 phpinfo()에서 Loaded Configuration File이 실제로 내가 편집한 php.ini를 가리키는지도 확인해야 한다. php.ini가 여러 개 있으면 의도한 파일이 로드되지 않을 수 있다.
파일 업로드 권한 문제
PHP로 파일 업로드 기능을 만들었는데 계속 실패하는 경우. 코드 문제가 아니라 IIS 애플리케이션 풀 계정 권한 문제인 경우가 많다.
기본 ApplicationPoolIdentity는 시스템 계정이라 파일 쓰기 권한이 없다. 업로드 대상 폴더에 IIS 애플리케이션 풀 계정 권한을 줘야 한다.
폴더 속성 → 보안 → 편집 → 추가:
IIS AppPool\{애플리케이션 풀 이름}
예: IIS AppPool\DefaultAppPool
쓰기 권한 체크 후 적용하면 해결된다.
마무리
IIS와 XAMPP는 목적이 다르다. XAMPP는 빠른 로컬 개발 환경, IIS는 실제 서버 운영에 적합하다. 처음에는 XAMPP로 PHP 개발을 익히고, 서버 배포가 필요해지면 IIS로 넘어가는 흐름이 자연스럽다.
헷갈리는 지점은 대부분 권한 문제와 포트 충돌이다. 뭔가 안 될 때 netstat -ano로 포트 확인하고, 이벤트 뷰어에서 로그를 보는 습관을 들이면 디버깅 시간을 크게 줄일 수 있다.
환경: Windows Server 2019 / Windows 11
IIS 버전: 10.0
XAMPP 버전: 8.2.x (PHP 8.2 기준)
'개발 팁' 카테고리의 다른 글
| Docker로 개발 환경 통일하기 — '내 컴퓨터에선 되는데'를 없애는 법 (0) | 2026.03.18 |
|---|---|
| 클라우드 & 공유호스팅 기본 세팅 — AWS, Railway, Vercel, 카페24 (0) | 2026.03.18 |
| Linux 서버 초기 세팅 — 처음 서버 받으면 이것부터 (0) | 2026.03.18 |
| 백업 없이 MySQL/MariaDB 데이터 복구하기 (0) | 2026.03.18 |
| 정규식 실전 치트시트 — 개발자가 자주 쓰는 패턴 모음 (0) | 2026.03.18 |