이 섹션의 다중 페이지 출력 화면임. 여기를 클릭하여 프린트.

이 페이지의 일반 화면으로 돌아가기.

Network

네트워크

1 - 인터넷

1.1 - 인터넷 개요

인터넷이란?

인터넷(Internet)이란 전세계에 걸처 수많은 컴퓨터들이 연결된 네트워크들의 집합체를 말한다. 인터넷에 연결된 컴퓨터들은 TCP/IP(Transmission Control Protocol/Internet Protocol)라는 통신 프로토콜을 사용하여 연결되어 있다. 인터넷을 이루는 각 컴퓨터들은 IP 주소라고 부르는 고유의 컴퓨터 주소를 가지고 있으며, 케이블 또는 인공 위성 등의 통신 수단을 통해 서로 연결되어 있다.

이로 인해 전세계의 컴퓨터 사용자들은 인터넷을 통해서 언제 어디서나 필요한 정보를 쉽게 얻을 수 있다.

인터넷의 역사

인터넷의 시작은 미국 국방성의 ARPANet(알파넷, Advanced Research Project Agency Network)이 처음으로 등작한 1969년으로 거슬러 올라간다. 초기의 ARPANet은 핵전쟁 발발 시 어느 한 시스템이 파괴되어도 다른 시스템들을 통하여 완벽하게 연결하여 보완할 수 있는 네트워크로서 미국 4개 대학교(스텐포드, UCLA, UC 산타바바라, 유타주립대)의 컴퓨터 시스템을 연결하는 것으로부터 시작되었다. 그 후 미국의 주요 정부 기관과 교육 기관들을 연결하면서 점차 확대되어 았고, 1983년 ARPANet은 군사적인 목적으로 사용되던 부분이 MILNet으로, 민간용도 부분이 인터넷으로 분리되었다.

인터넷의 주소 체계

인터넷에서 정보를 교환하기 위해서는 각각의 컴퓨터에서 주소나 이름을 부여하여 구분할 필요성이 있다. 인터넷에서 제공하는 주소 체계로는 IP 주소와 도메인네임이 있다.

인터넷을 유지하기 위해서는 인터넷 주소를 관리해야 하며 새로운 인터넷 기술과 표준화를 담당할 기관이 필요한데, NIC(Network Information Center)는 IP 주소와 도메임네임과 같은 네트워크와 컴퓨터들으 주소를 등록하고 관리하는 국제적인 기관으로서 우리 나라에서는 NIC의 산하 기관인 KRNIC가 인터넷 주소와 관리르 담당한다.

IP 주소

IP 주소는 컴퓨터의 주소를 숫자로 나타내는 방식이다. 그 구성은 최상의 주소로 부터 ‘.‘으로 구별하여 4개의 영역을 차례로 나열하는 방식이다. 예를 들어 구글의 IP 주소는 ‘172.217.174.100’과 같이 나타낸다. 그러나 이 방식은 외우거나 사용하기에 불편하여 통상 도메인네임을 사용한다.

도메인네임 시스템

도메인네임은 통산 ‘호스트.서버도메인(기관 이름).서브도메인(기관 성격).최상위 도메인’의 순서로 나타낸다. 예를 들어 청화대의 경우에는 ‘www.president.go.kr’이다.

최상위 도메인은 기관이나 국가를 약어로 나타내는데 미국의 경우에는 국가명을 생략하는 대신 아래 표의 왼쪽에 있는 도메인으로 끝나는 경우가 많다. 예를 들어, 백악관의 도메인네임은 ‘www.whitehouse.gov’ 이다.

최상위 도메인의 종류

도메인 기관명 도메인 국가명
edu 교육기관 kr 대한민국(Korea, South)
com 회사(사업체) jp 일본(Japan)
gov 정부 기관 cn 중국(China)
int 국제 기구 ca 캐나다(Canada)
org 비영리 공공 기관 de 독일(Germany)
net 네트워크 관려 기관 uk 영국(United Kingdom)
mil 미국 국방성 관련 기관 fr 프랑스(Korea, South)

더 많은 국가 코드 최상위 도메인

서브 도메인은 최상위 도메인과 호스트 이름 사이에 있는 영역으로 아래 표와 같이 기관의 이름과 성격을 의미한다. 기관의 성격을 나타내는 서브도메인은 ac, re, co, go, ne 등으로 각각 학교, 연구소, 회사, 정부 기관, 네트워크 관련 기관을 나타낸다.

서브 도메인의 종류

서브도메인 기관명 도메인 예제
ac Academy 교육/학술 기관 https://www.snu.ac.kr
re Research 연구소 https://etri.re.kr
co Company 회사 https://samsung.co.kr/
go Goverment 정부 기관 http://www.president.go.kr/
ne 비영리 공공 기관 네트워트나 게이트웨이

더 많은 .kr

1.2 - OSI 7 계층

OSI 참조 모델(OSI 7 Layer)

네트워크 분야에서 표준화 문제를 거론할 때 빼놓을 수 없는 것중 하나가 “개방형 시스템 상호접속(OSI:Open System Interconnect)“이라는 용어이다. OSI는 세계표준화 기구(ISO)가 1977년 타 기종 컴퓨터 통신을 위한 구조개발에 의해 탄생된 규정으로 어떠한 경로와 방식으로 데이터가 송수신되는가를 보여주는「네트워크 모델」이다. 이를 이해함으로써 라우터, 브릿지, 스위치, 카드 등 각종 장비들이 데이터를 다루는 방식을 파악할 수 있다. OSI는 네트워크 분야 종사자들에게는 일종의 바이블이라고 할 수 있다. OSI가 프로토콜의 집합으로 불리는 것은 OSI 모델을 구성하는 계층들이 각각 프로토콜 역할을 담당한다는 의미에서라고 할 수 있다. OSI 모델은 총 7개의 계층으로 구성된다.

4번째 전송계층부터 7번째 어플리케이션 계층은 일반적으로 상위계층으로 불리는데 네트워크 장비보다는 응용 소프트웨어와 더 관련이 많다.

물리계층

기계적인 측면(케이블 및 접속장치)과 전기적인 측면(전압, 신호를 변조) 컴퓨터와 네트워크 사이의 물리적인 연결 정의. 네트워크 토폴로지 정의. 네트워크 매체에서 사용할 신호 방법을 정의.

테이터 링크 계층

컴퓨터가 메시지를 주고 받기 위한 프로토콜 정의.

물리적인 연결을 통하여 두 장치간의 신뢰성 있는 정보 전송.

네트워크 계층

패킷이 어느 경로로 전송되는지 정의(routing).

네트워크 상의 노드에 전송되는 패킷 흐름을 통제하고 상태 메시지가 네트워크 노드로 전송되는가를 정의.

전송계층

네트워크 상에서 물리적인 위치를 찾는 방법과 노드간의 연결을 확립하고 인증과 패킷 배열.

패킷을 적절한 순서로 모으고, 에러를 검사하고, 패킷을 세션 계층으로 보내는 역할 담당.

세션계층

애플리케이션에 대해 전송계층에 개념적인 인터페이스 제공.

장비들이 네트워크 주소 대신 이름으로 인식되도록 제공.

네트워크 상의 두 노드 사이의 세션, 혹은 연결을 유지.

표현계층

애플리케이션이 네트워크로 들어가는 방법과 네트워크 상에서 데이터를 전송하고 소비되는 형태를 번역하는 방법 정의.

압축과 암호화가 사용된다면 이것도 역시 표현계층에서 처리된다.

응용계층

네트워크 가능 애플리케이션이 네트워크에 접근하기 위해 사용하는 인터페이스.

네트워크 애플리케이션을 정의.

전자우편 및 네트워크 유틸리티가 존재하는 계층.

애플리케이션이 네트워크에 접근하는 것을 제어하고, 네트워크 에러가 발생할 때 애플리케이션에게 그 사실을 알려주는 역할 담당.

계층 프로토콜을 개발한 이유

복잡한 네트워크를 각 역할 영역별로 분리하여 논리적으로 이해하기 쉽게 하기 위해. 또 네트워크 기능간의 표준화된 인터페이스를 제공하며, 네트워크 내의 각 노드에서 수행되는 기능들이 대칭성을 제공하고 네트워크의 설계자, 관리자, 판매업자, 사용자 등이 네트워크의 기능을 논의할 때 표현을 명료하게 해주기 위해.

OSI 7계층

어플리케이션 계층 (최상위 계층)

사용자들과 응용업무를 지원하는 서비스를 규정하는 층이다. FTP, DB, 원격접속(TELNET), 전자메일 등을 관리한다.

프리젠테이션 계층

위의 윗 계층인 어플리케이션 계층에서 보내오는 데이터를 아스키 코드나 EBCDIC 등 기본 코드로 포맷하는 기능을 수행한다.

세션 계층

LAN 사용자가 서버에 접속할 때 이를 관리하는 기능(연결설정,유지, 종료등)을 갖고 있다.

전송 계층

TCP, SPX 등 프로토콜과 관련된 층으로 데이터 전송,에러복구 및 흐름제어, 네트워크 어드레싱 등과 관련되어 있다.

네트워크 계층

데이터에 목적지 주소를 지정하고 전송경로를 결정하는데 필요한 조건을 담고 있다. IP, IPX 등 각종 전송 프로토콜이 활동하는 지역이다. 시스템 접속 장비관리나 패킷관리등을 한다.

데이터 링크 계층

데이터 패킷을 형성하고 전송하는 것을 규정해놓고 있다. 예를 들어 편지를 운송트럭에 적재하고 각 트럭을 고속도로로 보내며 그들이 안전하게 도착하도록 하는 역할을 담당한다.

물리 계층

상위계층인 데이터링크 계층에서 형성된 데이터 패킷을 전기신호나 광 신호로 바꾸어 송수신하는 역할을 담당한다.이 계층은 편지를 각지로 배달하는 트럭과 고속도로 등 편지를 운송하는데 필요한 수단으로 비유할 수 있다.

1.3 - 웹(Web)

웹이란?

인터넷 사용시에 가장 자주 접하는 용어는 월드 와이드 웹(World Wide Web, WWW)일 것이다. 웹은 영어 단어 첫 글자만 따사 WWW 또는 웹(Web)이라고도 부른다. 웹은 거미줄이라는 뜻을 가진 웹을 상징한다.

웹은 그래픽으로 구현되어 있기 때문에 정보 검색이 편리하다는 것이 가장 큰 장점 중의 하나이며, 화면에 텍스트와 그래픽을 동시에 표현할 수 있고, 뛰어난 사용자 인터페이스의 덕분으로 텍스트, 그래픽, 사운드, 동영상 등을 브라우저 상에서 쉽게 처리할 수 있게 되었다.

웹 브라우저

웹 브라우저(Web Browser)란 사용자 인터넷을 이용하여 웹 서버의 하이퍼테스트 문서를 볼 수 있도록 해주는 클라이언트 프로그램으로서 문자뿐만 아니라 멀티미디어 자료를 처리할 수 있는 하이이퍼미디어의 기능도 가지고 있다. 사용자가 음성이나 영상 정보를 원할 때 필요한 프로그램들을 불러와 실행함으러써 웹의 다양한 자원들을 다룰 수 있다.

웹 브라우저가 제공하는 기본적인 기능들에는 웹 페이지 열기, 최근 방문한 URL(Uniform Resource Locator)의 목록 제공, 자주 방문하는 URL의 기억과 관리. 웬 페이지의 저장과 인쇄 등이 있다. 이 웹 브라우저가 없다면 아무리 인터넷에 연결되어 있어도 인터넷에 있는 홈페이지들을 볼 수가 없다.

웹 브라우저의 종류

  • Google Chrome.
  • Mozilla Firefox.
  • Chromium Microsoft Edge.
  • Opera 브라우저
  • Vivaldi 브라우저
  • 네이버 웨일
  • Brave 브라우저

WEB 동작 방식

WEB 동작 방식
이미지 출처: http://tcpschool.com/webbasic/works

  1. 사용자가 브라우저에 URL을 입력한다.
  2. 브라우저는 DNS를 통해 서버의 IP 주소를 찾는다.
  3. HTTP 프로토콜을 사용하여 HTTP 요청 메세지를 생성한다.
  4. TCP/IP 연결을 통해 HTTP 요청 메세지를 생성한다.
  5. 서버는 HTTP 프로토콜을 활용해 HTTP 응답 메세지를 생성한다.
  6. TCP/IP 연결을 통해 요청한 컴퓨터로 전송한다.
  7. 도착한 HTTP 응답 메세지는 웹 페이지 데이터로 반환되고, 웹 브라우저에 의해 출력되어 사용자가 볼 수 있게 된다.

웹 접근성의 국제 표준

  • 웹 접근성을 높이기 위해 고안된 웹 표준은 표준적으로 사용되는 기술이나 규칙을 의미한다.
  • 웹 표준을 정하기 위하여 W3C(World Wide Web Consortium)이 설립되었다.
  • 웹 표준으로 구조 언어인 HTML, 표현 언어인 CSS, 동작 언어인 Script를 지정하였다.

1.4 - FTP (File Transfer Protocol)

FTP

FTP는파일 전송 프로토콜(File Transfer Protocol)의 약자로 TCP/IP 네트워크 상에서 컴퓨터들이 파일을 교환하기 위해 1971년에 최초로 공개된 통신 규약이다.
인터넷에서 파일을 전송하기 위해 사용하는 서비스이다. Telnet이 다른 컴퓨터를 사용하기 위해 접속하는 서비스인데 비해, FTP는 서버 컴퓨터로 파일을 전송하거나 서버 컴퓨터의 파일을 전송하거나 서버 컴퓨터의 파일을 내 컴퓨터로 받아 오기 위해 사용한다.

FTP의 경우 빠르고 안정적으로 파일을 전송할 수 있기 때문에 요즘에도 많이 쓰이고 있으며, Telnet 사용시와 같이 모든 명령어를 익혀야 하는 담점을 극복하기 위해 FTP 전용 프로그램들이 등장하여 편리하게 사용할 수 있게 되었다.

FTP의 원리

FTP는 클라이언트-서버 프로토콜이다. 클라이언트가 파일을 요청하면 서버가 요청된 파일을 제공한다. 따라서 FTP의 연결 설정을 위해서는 2개의 기본 채널이 필요하다.

  • 채널 하나는 명령을 내리고 어떤 파일에 액세스할 수 있는지 등의 기본 정보를 전달하는 명령 채널이다.
  • 또 하나의 채널은 2개의 장치 간에 파일 데이터를 전송하는 데이터 채널이다.

연결을 설정하려면 사용자는 FTP 서버로의 로그인 정보를 제공해야 하며, FTP는 일반적으로는 21번 포트를 기본 통신 모드로 사용한다.

FTP의 연결 모드

FTP의 연결 모드에는 능동 모드, 수동 모드 2가지가 있다.

  • 능동 모드(액티브 모드)
    • 서버가 데이터 요청을 승인하는 능동적인 역할을 한다.
    • 능동 모드에서는 방화벽으로 인한 문제가 종종 발생한다. 제3자가 권한이 없는 세션에 액세스하려고 하면 해당 세션이 차단된다.
  • 수동 모드(패시브 모드)
    • 수동 모드에서는 제3자가 권한이 없는 세션에 액세스하려고 하면, 서버가 능동적으로 연결을 유지하지 않는다.
    • 즉, 사용자가 데이터 채널과 명령 채널 모두를 설정한다. 서버는 기본적으로 ‘듣기만’할 뿐, 적극적으로 관여하지 않음으로써 다른 장치가 대부분의 작업을 처리하도록 한다.

FTP 접속 클라이언트

  • FileZilla : 제일 많이 쓰이고, Windows, MacOS용이 제공되는 무료 프로그램이다.
  • WinSCP : Windows용으로 개발된 무료 프로그램이다.

FTP의 장단점

  • 장점
    • 여러 개의 파일을 동시에 전송할 수 있다.
    • 연결이 끊긴 경우 전송을 다시 시작할 수 있다.
    • 전송 일정을 예약할 수 있다.
  • 단점
    • 보안에 취약하다.

SFTP란?

FTP는 오늘날 우리가 사용하는 대부분의 사이버 보안 조치가 개발된 시기보다 앞선 1970년대에 개발되었다. 보안 프로토콜로 설계된 것이 아니기 때문에 FTP 전송은 파일을 암호화하지 않는다. 그래서 데이터 패킷에 대한 패킷 캡처 공격을 통해 비교적 쉽게 비밀번호, 사용자명, 그 외 기타 민감한 데이터를 읽을 수 있다.

SFTP(SSH 파일 전송 프로토콜)란 시큐어 셸(SSH) 데이터 스트림을 통해 보안 등급이 높은 파일 전송을 실현하는 별도의 프로토콜을 말한다. 21번 포트를 사용하는 FTP 클라이언트와는 달리 SFTP는 22번 포트를 사용한다. FTP의 취약한 보안으로 인해 많은 사람이 보안 기능을 기본으로 제공하고 SSH 연결을 사용하는 SFTP를 선호한다.

참조

1.5 - Telnet

Telnet

인터넷의 Telnet 서비스란 다른 컴퓨터 특히 UNIX 운영 체제를 쓰는 컴퓨터에 접속하여 마치 그 컴퓨터에 직접 키보드와 모니터를 연결한 것과 같이 사용할 수 있도록 해주는 서비스를 말한다.

  • 인터넷을 통하여 원격지의 호스트 컴퓨터에 접속할 때에 지원되는 인터넷 표준 프로토콜이다/
  • TCP/IP 기반의 프로토콜이다.
  • 원격 터미널 접속 서비스이다.
  • TCP 포트 번호는 23번을 기본으로 사용한다.

그래픽 화면이 아닌 텍스트 화면만을 표시할 수 있지만 단순하게 빠른 속도에다 직접 UNIX를 사용할 수 있다는 장점으로 아직까지 많이 사용되고 있다. 그러나 Telnet을 잘 사용하기 위해서는 UNIX의 명령어를 익혀야 하고, 단지 텍스트 화면만을 사용할 수 있기 때문에 특별한 지식이 없이는 사용하기에는 어렵다는 단점이 있다.

Telnet 특징

  • Telnet은 일종의 터미널 에뮬레이션 프로토콜로 NVT(Network Virtual Terminal) 라고 불리는 가상 터미널의 개념 사용한다.
  • 터미널과 호스트와의 일대일 대칭적인 관계이다.
  • 추가적인 옵션 협상 가능하다.

NVT(Network Virtual Terminal) 란 ?

  • Telnet 프로토콜의 가장 기본으로 접속하고자 하는 원격지 시스템과 로컬 시스템의 버전이 상이할 경우 데이터 형식이 다르므로 원활한 통신을 위해 데이터를 변환시켜주는 가상장치이다.
  • NVT 는 기본적인 터미널 제어 문자들 정의한다.

NVT(Network Virtual Terminal)

Telnet 동작 방식

Telnet 동작 방식

  1. 클라이언트는 원격 로그인을 통해 원격지 시스템(서버)에 TCP 연결을 한다.(기본 포트 23번)
  2. 원격지 시스템은 연결된 클라이언트에게 가상의 터미널 제공한다.
  3. 클라이언트는 실제 터미널인 것처럼 원격지 시스템에 명령어를 실행한다.
  4. 원격지 시스템은 클라이언트의 명령을 수행하여 결과를 다시 클라이언트에서 전송한다.

Telnet 접속용 클라이언트

  • Windows에 기본으로 내장된 서버 및 클라이언트
    • 보안적으로 문제로 기본적으로 기능이 비활성화 되어 있다. 사용하려면 설정으로 활성화를 시켜 줘야 한다.
  • Putty, SecureCRT, Xshell 등등 이용하여 편히라게 사용 가능

참조

1.6 - E-Mail

이메일

이메일은 인터넷을 시용하여 편지를 주고 받을 수 잇는 서비스를 말하는데, Web기반 이메일과 POP3를 사용하는 이메일로 나눌 수 있다.

Web 기반 이메일

Web 기반 이메일로는 gmail, naver 등이 있으며, 이런 메일은 별로의 프로그램 없이 인터넷에서 해당 사이트에 접속한 후, 그 곳에서 메일을 관리하고 수신할 수 있는 방식이다.

  • 장점 : 별도의 프로그램을 쓰지 않기 때문에 여러 사람들이 하나의 컴퓨터를 공유하거나 별도의 프로그램을 설치하기 곤란한 곳에서 쉽게 사용할 있다.
  • 단점 : 해당 회사에서 제공하는 인터페이스를 반드시 사용해야 하고, 그 웹 사이트에 접속을 해야 한다.

POP3

POP3 서버의 경우는 Outlook Expresss와 같은 POP3 지원 이메일 클라이언트를 이용하여 메일을 주고 받을 수 있다.

  • 장점 : 단지 편지를 전해 주는 것이므로 POP3을 지원하는 프로그램을 쓰더라도 가능하기 때문에 자신에 편리한 프로그램을 쓸 수 있다.
  • 단점 : 프로그램을 설치해야만 이메일 내용 확인이 가능하다.

1.7 - CDN (Content Delivery Network)

CDN

  • Contents Delivery Network 또는 Content Distribution Network
  • CDN(콘텐츠 전송 네트워크)은 서버와 사용자 사이의 물리적 거리를 줄여 웹 페이지 콘텐츠 로드 지연을 최소화하는, 촘촘히 분산된 서버로 이루어진 플랫폼이다.
  • 지리, 물리적으로 덜어져 있는 사용자에게 보다 빠르고 안정적으로 컨텐츠를 제공하는 기술이다.
  • 사용자에게 느린 응답 속도 및 다운로드 타임을 개설하기 위한 서비스이다.
  • 원격지(Origin-Server)에 있는 컨텐츠를 CDN 내 캐싱 서버를 통해 캐싱하여 컨텐츠를 제공하는 서비스이다.
  • 이를 통해 전 세계 사용자들이 로딩 시간을 늦추지 않고 동일한 고품질 콘텐츠를 볼 수 있다.
  • CDN은 콘텐츠에 대한 요청이 발생하면 사용자와 가장 가까운 위치에 존재하는 서버로 매핑시켜, 요청된 파일의 캐싱된(사전 저장된) 버전으로 요청을 처리한다. 서버가 파일을 찾는 데 실패하는 경우 CDN 플랫폼의 다른 서버에서 콘텐츠를 찾은 다음 엔드유저에게 응답을 전송한다.

Content Delivery Network

이미지 출처 : https://en.wikipedia.org/wiki/Content_delivery_network

2 - HTTP

2.1 - HTTP 입문

HTTP 개요

HTTP(HyperText Transfer Protocol)는 WWW에서 웹 서버와 클라이언트(브라우저)간에 데이터(웹페이지 등)를 송수신하기 위한 프로토콜이다. 기본적으로 텍스트 메시지 리소스를 교환하고, 그 밖에 다양한 리소스(.jpeg 등)도 교환 가능하다.

  • HTTP는 애플리케이션 레벨의 프로토콜로 TCP/IP로 구성된 프로토콜이다.
  • HTTP는 상태를 가지고 있지 않는 Stateless 프로토콜이다.
  • Method, Path, Version, Headers, Body 등으로 구성된다.

HTTP 버전에 따라에 아래의 사양서가 공개되어 있다.

HTTP Messages

HTTP 메시지에는 두 가지 유형이 있다.

  • HTTP 요청 메시지: 클라이언트가 서버에 리소스를 요청한다.
  • HTTP 응답 메시지: 서버가 클라이언트에 HTTP 요청의 결과를 응답한다.

HTTP, HTTPS

  • HTTP
    • HTTP는 텍스트 교환이고 HTML 페이지도 텍스트이다.
    • 바이너리 테이터로 되어 있는 것도 아니고, 단순 텍스트를 주고 받기 때문에 누군가 네트워크에서 신호를 가로채어 본다면 내용이 노출된다. 이런 보안상의 문제를 해결해주기 위해 생긴 것이 HTTPS이다.
  • HTTPS
    • HTTPS는 인터넷 상에 정보를 암호화하는 SSL(Secure Soket Layer) 프로토콜을 이용하여 클라이언트와 서버가 데이터를 주고 받는 통신규약이다.
    • HTTPS는 HTTP 텍스트를 암호화 하는 것이다.
    • HTTPS의 S는 Secure Socket, 보안 통신망을 의마한다.
    • HTTP의 암호화 원리의 핵식은 공개키 암호화 방식이다.
      • 인증서를 발급하여 보내는 메세지를 공개키로 암호화하도록 하고 있다.
      • 암호화된 메세지는 개인키를 가지고 있어야만 가능하기 때문에, 중간에 누구도 원본 데이터를 얻을 수 없다.

2.2 - HTTP Request (요청)

HTTP Requset messages (요청 메시지)

브라우저에서 웹 페이지를 열게 되면, 브라우저는 서버에 다음과 같은 요청 메시지를 보낸다.

GET / HTTP/1.1
Accept: image/gif, image/jpeg, */*
Accept-Language: ko
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (Compatible; MSIE 6.0; Windows NT 5.1;)
Host: www.xxx.zzz
Connection: Keep-Alive

요청 메시지는 다음과 같은 구문으로 구성된다.

HTTP Request line(요청 라인)

GET / HTTP/1.1

HTTP Request Header(요청 헤더)

Accept: image/gif, image/jpeg, */*
Accept-Language: ko
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (Compatible; MSIE 6.0; Windows NT 5.1;)
Host: www.xxx.zzz
Connection: Keep-Alive

HTTP Body(본문)

메세지 본문(POST 메소드 등을 사용)

Start line (요청 시작 라인)

HTTP 요청의 시작 줄에는 다음 세 가지 요소가 있다.

  • HTTP 메소드
  • 요청 대상(경로 이름)
  • HTTP 프로토콜 버전

요청 라인은 다음 형식으로 표시된다.

요청 라인

[HTTP 메소드] [요청 대상] [HTTP 프로토콜 버전]

경로명은 보통 “/aaa/bbb/ccc.html"와 같고, 슬래시로 시작되는 패스명이나, “http://“으로 시작되는 URL가 지정된다. 버전은 현재 1.1이 보통 사용된다.

HTTP Method (메소드)

HTTP/1.0, HTTP/1.1에서 지원되는 메소드는 아래와 같다.

메소드 HTTP/1.0 HTTP/1.1 설명
GET 가장 일반적으로 사용되는 메소드이다. 브라우저는 서버에 페이지를 검색하도록 요청한다.
HEAD 헤더 전용 정보를 요청한다. 서버는 GET 메소드와 HEAD 메소드는 반드시 지원해야 한다.
POST method="POST"를 지정한 폼에 입력한 데이터를 서버에 전송할 때 사용된다.
PUT
DELETE 지정된 자원을 삭제할 것을 서버에 요구한다.
CONNECT × 프록시 서버를 경유해 SSL 통신할 때 등에 사용한다.
OPTIONS × 서버가 서포트하고 있는 메소드나 옵션을 조회할 때에 이용한다.
TRACE × HTTP 요청이 어느 프록시 서버를 경유해 송신되는지 등, HTTP의 동작을 추적할 때에 이용한다. 이 메시지를 받은 마지막 서버는 요청 메시지에 포함된 엔티티(일반적으로 헤더 + 메시지 본문)를 그대로 반환한다.
LINK × 지정한 URL과 리소스에 링크 관계를 연결한다. HTTP/1.1에서는 더 이상 사용되지 않는다.
UNLINK × 지정된 URL과 자원 간의 링크 관계를 해제한다. HTTP/1.1에서는 더 이상 사용되지 않는다.

(◎: 필수, ○: 서포트, ×: 미지원)

Apache는 위 이외에도 PATCH, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK 등의 메소드를 지원하고 있다.

GET

GET 요청 방식은 URI(URL)가 가진 정보를 검색하기 위해 서버 측에 요청하는 형태이다.

전송 형태

GET [request-uri]?query_string  
HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n   

POST

POST 요청 방식은 요청 URI(URL)에 폼 입력을 처리하기 위해 구성한 서버 측 스크립트(ASP, PHP, JSP 등) 혹은 CGI 프로그램으로 구성되고 Form Action과 함께 전송되는데, 이때 헤더 정보에 포함되지 않고 데이터 부분에 요청 정보가 들어가게 된다.

전송 형태

POST [request-uri]?query_string  
HTTP/1.1\r\n  
HOST:[Hostname] 혹은 [IP] \r\n  
Content-Lenght:[Lenght in Bytes] \r\n  
\r\n  
[query-string] 혹은 [데이터]

HEAD 요청 방식은 GET과 유사한 방식이나 웹 서버에서 헤더 정보 이외에는 어떤 데이터도 보내지 않는다.
웹 서버의 다운 여부 점검(Health Check)이나 웹 서버 정보(버전 등)등을 얻기 위해 사용될 수 있다.

전송 형태

HEAD [request-uri] HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n 

OPTIONS

rfc2616
해당 메소드를 통해 시스템에서 지원되는 메소드 종류를 확인할 수 있다.

전송 형태

OPTIONS [request-ri]  
HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n 

PUT

POST와 유사한 전송 구조를 가지기 때문에 헤더 이외에 메시지(데이터)가 함께 전송된다.
원격지 서버에 지정한 콘텐츠를 저장하기 위해 사용되며 홈페이지 변조에 많이 악용되고 있다.

전송 형태

PUT [request-uri] HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n  
Content-Lenght:[Length in Bytes] \r\n  
Content-Type:[Content Type] \r\n  
\r\n  
[데이터] 

PATCH

PUT과 유사하게 요청된 자원을 수정(UPDATE)할 때 사용한다.
PUT의 경우 자원 전체를 갱신하는 의미지만, PATCH는 해당자원의 일부를 교체하는 의미로 사용된다. 즉, 리소스를 부분적으로 변경한다.

전송 형태

PATCH [request-uri] HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP]\r\n  
Content-Lenght:[Length in Bytes]\r\n  
Content-Type:[Content Type]\r\n  
\r\n  
[데이터] 

DELETE

원격지 웹 서버에 파일을 삭제하기 위해 사용되며 PUT과는 반대 개념의 메소드이다.

전송 형태

DELETE [request-uri] HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n  
\r\n 

TRACE

원격지 서버에 Loopback(루프백) 메시지를 호출하기 위해 사용된다.

전송 형태

TRACE [request-uri] HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n  
\r\n 

CONNECT

웹 서버에 프락시 기능을 요청할 때 사용된다.

전송 형태

CONNECT [request-uri] HTTP/1.1\r\n  
Host: [Hostname] 혹은 [IP] \r\n  
\r\n 

요청 대상(경로 이름)

요청 대상은 URL, 경로, 쿼리 문자열 등을 포함한다.

이하의 굵은 문장이 “요청 대상"에 해당한다.

요청 대상 형식 형식 예 설명
origin form - POST / HTTP/1.1
- GET /background.png HTTP/1.0
- HEAD /test.html?query=alibaba HTTP/1.1
- OPTIONS /anypage.html HTTP/1.0
일반적인 형식
absolute form GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1 프록시로 GET 할 때 사용
authority form CONNECT developer.mozilla.org:80 HTTP/1.1 CONNECT에서 사용
asterisk form OPTIONS * HTTP/1.1 OPTIONS에서 사용

HTTP 프로토콜 버전

HTTP 버전을 나타낸다. 일반적으로 HTTP/1.1 or 2.0 이다.

HTTP Header (요청 헤더)

요청 헤더에는 세 가지 유형이 있다.

헤더 유형 설명
응답 헤더 요청 본문의 데이터와 관련이 없는 헤더 - Host
- User-Agent
- Accept -
- If-

- Referer
일반 헤더 검색할 리소스 - Date
- Cache-Control
엔티티 헤더 요청 본문에 적용 - Content-Type
- Content-Length
- Expires

HTTP Body (요청 본문)

HTTP 요청 본문은 요청에서 보낼 데이터이다.
일반적으로 ‘GET’, ‘HEAD’, ‘DELETE’, ‘OPTIONS’에는 요청 본문이 없다. (리소스를 조회하거나 삭제하는 경우에만 사용한다.)
요청 본문은 POST, PUT 등으로 리소스에 데이터를 전송하는 경우에 이용한다.

요청 본문 확인

% curl --trace-ascii - http://www.devkuma.com/ -XPOST -d 'user=kimkc,password=1234'
=> Send data, 24 bytes (0x18)
0000: user=kimkc,password=1234

2.3 - HTTP Response (응답)

HTTP Response messages (응답 메시지)

서버는 요청이 들어오면 다음과 같은 응답 메시지를 반환한다.

HTTP/1.1 200 OK
Date: Sun, 11 Jan 2014 16:06:23 GMT
Server: Apache/1.3.22 (Unix) (Red-Hat/Linux)
Last-Modified: Sun, 07 Dec 2013 12:34:18 GMT
ETag: "1dba6-131b-3fd31e4a"
Accept-Ranges: bytes
Content-Length: 4891
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html

<!DOCTYPE html>
<html>
  :
</html>

응답 메시지는 다음 구문으로 구성된다.

응답 행(Response line) 또는 상태 행(Status line)

HTTP/1.1 200 OK  

HTTP 응답 헤더 (HTTP Response Header)

Date: Sun, 11 Jan 2014 16:06:23 GMT
Server: Apache/1.3.22 (Unix) (Red-Hat/Linux)
Last-Modified: Sun, 07 Dec 2013 12:34:18 GMT
ETag: "1dba6-131b-3fd31e4a"
Accept-Ranges: bytes
Content-Length: 4891
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html

빈 라인(blank line) : (헤더의 끝을 의미함)

CR LF

HTTP 본문 (HTTP Body)

<!DOCTYPE html>
<html>
  :
</html>

줄 바꿈 코드는 Windows 형식의CR LF("\r\n")이다. 첫 번째 라인에는 요청 행 또는 응답 행이 있고, 헤더는 여러 라인이 있고, 빈 라인은 한 라인이 있고, 메시지 바디는 여러 라인이다.

Start line (응답 시작 라인)

HTTP 응답의 시작 라인(상태 라인)에는 다음 세 가지 요소가 있다.

  • HTTP 프로토콜 버전 (HTTP 요청 메시지와 동일)
  • Response Status Code (응답 상태 코드)
  • 상태 문자열

이후에는 특히 중요한 “HTTP 응답 상태 코드"와 “상태 문자열"에 대해 설명한다.

응답 시작 라인은 다음 형식으로 표시된다.

시작 라인:

[HTTP 프로토콜 버전] [응답 상태 코드] [상태 문자열]

상태 문자열는 OK 및 Not Found와 같은 상태 번호의 의미와 세부 정보를 보완하는 메시지를 반환한다.

실제 예제로 시작 라인을 확인해 보자.

시작 라인 확인:

% curl http://google.com/ --head
HTTP/1.1 301 Moved Permanently
  • HTTP 프로토콜 버전 : HTTP/1.1
  • 응답 상태 코드 : 301
  • 상태 문자열 : Moved Permanently

HTTP 프로토콜 버전

HTTP 요청 메시지와 동일하게 HTTP 버전을 나타낸다. 일반적으로 HTTP/1.1 or 2.0 이다.

Response Status Code(응답 상태 코드)와 상태 문자열

HTTP/1.1 상태 코드 정의는 RFC 2616에 규정되어 있는데 간단히 정리하면 다음과 같다.

응답 코드 의미 설명
1xx Informational 정보 제공
2xx Successful 성공 응답
3xx Rediection 추가작업(리디렉션)
4xx Client Error 클라이언트측 오류
5xx Server Error 서버측 오류

1xx, 2xx, 3xx 코드는 서버와 User Agent간의 상태를 표시한 것이기 때문에 일반 사용자가 그 내용을 볼 수 없지만, 4xx, 5xx 코드는 일반 사용자도 흔히 볼 수 있는 내용이다.

어떤 이유로든 웹 페이지가 브라우저 상에 정상적으로 뜨지 않는다면 이는 3xx, 4xx 오류에 해당한다. 때문에 오류의 원인을 이해하고 이를 복구하기 위해서는 오류코드가 의미하는 바를 잘 대충이라도 알아야 한다.

응답 코드 의미 설명
100 Continue 클라이언트로 부터 일부 요청을 받았으며 나머지 정보를 계속 요청한다.
101 Switching protocols 프로토콜 전환. 요청자가 서버에 프로토콜 전환을 요청했으며 서버는 이를 승인하는 중이다.
200 OK 요청이 성공적으로 수행되었다.
201 Created 성공적으로 요청되었으며, 서버가 새 리소스를 작성하였다.
202 Accepted 웹 서버가 요청을 접수했지만 아직 처리하지 않았다.
203 Non-authoritative information 신뢰할 수 없는 정보, 서버가 요청을 성공적으로 처리되었지만 다른 소스에서 수신된 정보를 제공하고 있다.
204 No content 콘텐츠 없음. 서버가 요청을 성공적으로 처리했지만 콘텐츠를 제공하지 않았다.
205 Reset Content 콘텐츠 재설정. 서버가 요청을 성공적으로 처리했지만 콘텐츠를 제공하지 않았다.
206 Partial content 일부 콘텐츠. 서버가 GET요청의 일부만 성공적으로 처리했다.
300 Multiple Choices 컨텐츠를 얻는 방법에 대한 여러 가지 옵션이 있다.
301 Moved permanently 요구한 데이터를 변경된 타 URL에 요청하였다.
302 Not temporarily 요구한 데이터를 변경된 임시 URL에서 찾았음
304 Not modified 업데이트되지 않았고, 컴퓨터 로컬의 캐시 정보를 이용하였다. 보통 gif 등은 웹 서버에 요청하지 않았다. If-Modified-Since 헤더를 사용했을 경우에 반환된다.
305 Use Proxy Location 헤더에 지정된 프록시를 사용한다.
306 (Unused) 미사용.
307 Temporary Redirect 다른 위치로 일시적으로 이동 중이다.
400 Bad request 요청이 잘못되었다. 사용자의 잘못된 요청을 처리할 수 없다.
401 Unauthorized 인증되지 않았다. 인증이 필요한 페이지를 요청한 경우에 발생한다.
402 Payment required 예약됨. 지불이 필요하다.
403 Forbidden 액세스가 허용되지 않는다. 접근 금지(디렉터리 리스팅 요청 및 관리자 페이지 접근 등을 차단).
404 Not found 요청한 페이지가 없다. 찾을 수 없습니다.
405 Method not allowed 허용되지 않는 HTTP Method 사용하였다. 지정한 메소드는 지원되지 않는다.
407 Proxy authentication required 프록시 인증이 필요하다.
408 Request timeout 요청이 시간 초과 되었다.
410 Gone 영구적으로 사용 금지. 요청한 콘텐츠가 사라졌다.
411 Length Required Content-Length 헤더를 추가하여 요청해라.
412 Precondition failed 전체 조건 실패. If-… 헤더에 지정된 조건에 부합하지 않았다.
414 Request-URI too long 요청 URL 길이가 긴 경우임
415 Unsupported Media Type 지원되지 않는 미디어 유형이다.
416 Requested Range Not Satisfiable 요청한 범위가 잘못되었다.
417 Expectation Failed Expect 헤더에 지정된 확장 요청이 실패했다.
500 Internal server error 내부 서버 오류. 서버에서 예기치 않은 오류가 발생하였다.
501 Not implemented 웹 서버가 처리할 수 없다.
502 Bad Gateway 게이트웨이가 잘못되었다.
503 Service unnailable 서비스 제공 불가. 서비스는 사용할 수 없다.
504 Gateway timeout 게이트웨이가 시간 초과되었다.
505 HTTP version not supported 해당 HTTP 버전 지원되지 않는다.

HTTP Header (응답 헤더)

응답 헤더에는 다음 세 가지 유형이 있다

헤더 유형 설명
응답 헤더 응답 본문의 데이터와 관련이 없는 헤더 - Location
일반 헤더 검색할 리소스 - Date
- Cache-Control
엔티티 헤더 응답 본문에 적용 - Content-Type
- Content-Length
- Expires

HTTP Body (응답 본문)

리소스(파일)의 내용을 포함한다.

% curl http://www.devkuma.com
<!DOCTYPE html>
<html lang="ko">
<head>

2.4 - HTTP Header (헤더)

HTTP Header (헤더)

카테고리 요청 응답 헤더
일반 헤더 Cache-Control, Connection, Date, Pragma, Trailer,Transfer-Encoding, Upgrade, Via, Warning
요청 헤더 × Accept, Accept-Charset, Accept-Encoding, Accept-Language, Authorization, Expect, From, Host, If-Match,
If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Max Forwards, Proxy-Authorization, Range,
Referer, TE, User-Agent
응답 헤더 × Accept-Ranges, Age, ETag, Location, Proxy-Authenticate, Retry-After, Server, Vary, WWW-Authenticate
요소 헤더 Allow, Content-Encoding, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range,
Content-Type, Expires, Last-Modified, extension-header

Accept (요청)

브라우저가 수신할 수 있는 데이터 형식(MIME 타입)을 서버에 전달한다. 별표(*)는 “모두"를 의미한다. 다음은 브라우저가 GIF, JPEG 및 기타 모든 형식의 데이터를 수신할 수 있음을 보여준다. (→ Content-Type)

Accept: image/gif, image/jpeg, */*

Accept-Charset (요청)

브라우저가 수신 가능한 문자 세트를 서버에 전달한다. 다음은 브라우저가 iso-8859-5, euc-kr만 수신할 수 있다를 뜻한다. (→ Content-Type)

Accept-Charset: iso-8859-5, euc-kr

Accept-Encoding (요청)

브라우저가 수신 가능한 인코딩 방식을 서버에 전달한다. 예를 들어, 브라우저가 gzip 형식을 서포트하고 있는 것을 서버에 전하면, 서버는 메세지 본문을 자동적으로 gzip 압축해 브라우저에 보내서 브라우저에 이를 자동적으로 해제하여 화면에 표시한다. 이러한 기능으로 의해, 통신 부하를 저감하는 것이 가능하다. (→ Content-Encoding )

Accept-Encoding: gzip, deflate

Accept-Language (요청)

브라우저가 수신 가능한 언어를 서버에 전달한다. 아래는 브라우저가 한국어만 수신할 수 있음을 의미한다. (→ Content-Language )

Accept-Language: ko

Accept-Ranges (응답)

Range 요청에서 사용 가능한 단위를 클라이언트에 전달한다. 현재 정의되어 있는 것은 bytes 뿐이다. (→ Range, Content-Range )

Accept-Ranges: bytes

Age (응답)

엔티티가 생성된 이후의 예상 경과 시간(초)을 나타낸다. 아래의 예에서는, 이 엔티티가 아마, 프록시 서버로 30초간 유지된 것, 즉, 30초 정도 오래된 데이터인 것을 나타낸다.

Age: 30

Allow (요청/응답)

요청 URL에 표시된 리소스에 사용할 수 있는 메서드 목록을 제공한다. 다음 예제에서는 이 리소스에 대해 GET, HEAD, PUT 메서드를 사용할 수 있음을 보여 준다.

Allow: GET, HEAD, PUT

Authorization (요청)

인증이 필요한 자원에 대한 인증 정보를 전달한다. 예를 들어, BASIC 인증의 경우는, Basic 의 문자와, 유저명과 패스워드를 콜론(:)으로 연결한 것을 BASE64 형식에 encode 한 것을 전송한다. (→ WWW-Authenticate )

Authorization: Basic dGFuYWthOmhpbWl0c3U=

Cache-Control (요청/응답)

캐시에 관한 지시를 나타낸다. 다음 예제는 프록시 서버와 클라이언트가 이 리소스를 캐시해서는 안 됨을 보여줍니다. HTTP/1.0에서는 Pragma: no-cache가 사용됩니다. (→ Pragma )

Cache-Control: no-cache

Connection (요청/응답)

HTTP/1.1에서 지원되는 지속 연결 기능을 브라우저가 지원하는 경우, 그 취지를 상대에게 알립니다. 지속적인 연결을 사용하면 단일 연결에서 여러 요청/응답을 발행할 수 있다.

Connection: Keep-Alive

지속 연결을 완료하면 서버는 close를 반환한다.

Connection: close

그 외에도 서버 프록시 간, 프록시 클라이언트 간과 같은 직접 연결에만 유효한 헤더 목록을 표시하는 데 사용됩니다. 프록시 서버는 이 헤더로 지정된 헤더 정보를 삭제해, 전송하지 않으면 안된다.

Connection: Upgrade

Content-Encoding (요청/응답)

콘텐츠 인코딩 방법을 나타낸다. 다음은 콘텐츠가 gzip 형식으로 압축되었음을 나타낸다. (→ Accept-Encoding )

Content-Encoding: gzip

Content-Language (요청/응답)

컨텐츠의 언어를 en(영어), ko(한국어) 등으로 나타낸다.

Content-Language: ko

Content-Length (요청/응답)

컨텐츠(=메시지 본체)의 길이를 바이트 단위로 나타낸다. 헤더와 메시지 본문 사이의 줄 바꿈 바이트 수는 제외한다.

Content-Length: 4891

Content-Location (요청/응답)

컨텐츠가 다른 URL에서도 액세스 가능할 때, 그 엔티티의 URL를 절대 URL 또는 상대 URL 로 나타낸다. (→ Location )

Location: http://xxx.yyy.zzz/index.htm

Content-MD5 (요청/응답)

콘텐츠가 통신 도중에 변경되지 않았는지 확인하기 위해 콘텐츠에 대한 체크 데이터(128비트 MD5 다이제스트를 BASE64로 인코딩)를 나타낸다.

Content-MD5: GitH4qFa4GasgWxJs8ha5Q==

Content-Range (요청/응답)

상대에게 보낼 콘텐츠의 범위를 나타낸다. 아래 예에서는 전체 콘텐츠가 12345바이트이고 그 안의 0바이트부터 999바이트까지의 부분을 전송하고 있음을 보여줍니다. (→ Range , Accept-Ranges )

Content-Range: bytes 0-999/12345

Content-Type (요청/응답)

Content-Type 를 MIME 타입으로 나타낸다. MIME 타입은 리소스(파일) 유형을 말한다.

다음은 콘텐츠의 내용이 텍스트(HTML) 형식임을 나타낸다.

Content-Type: text/html

또한 문자 코드 (euc-kr, ISO-2022-KR, UTF-8 등)를 나타낼 수도 있다.

Content-Type: text/html; charset=euc-kr

응답 헤더을 실제 확인해 보도록 하자.
Content-Type 응답 헤더

$ curl http://google.com/ --head
...
Content-Type: text/html; charset=UTF-8

문자 코드가 UTF-8인 HTML을 응답했다는 것을 의믜한다.

Date (요청/응답)

응답을 반환하는 시간을 나타낸다. 요일(Sun,)은 선택 사항입니다. 날짜는 1 또는 01일 수 있다. 연도는 2자리 또는 4자리일 수 있지만 4자리가 권장됩니다. 초(:23)는 선택 사항입니다. 시간대는 GMT(그리니치 표준시)를 이용하는 경우가 많습니다.

Date: Sun, 04 Jan 2004 16:06:23 GMT

ETag (응답)

엔티티와 그 버전을 고유하게 식별하는 식별자를 나타낸다. 식별자는 파일 식별자, 크기, 갱신 시간 등의 정보로부터 계산됩니다. (→ If-Match , If-None-Match , If-Range )

ETag: "1dba6-131b-3fd31e4a"

Expect (요청)

다양한 목적으로 사용된다.

Expect: 100-continue

Expires (요청/응답)

엔티티의 만료 날짜를 표시한다. 만료일이 지난 엔티티는 캐시에서 삭제된다.

Expires: Thu, 01 Dec 2021 16:00:00 GMT

From (요청)

이 요청을 한 사람의 이메일 주소를 지정한다. 검색 엔진이 로봇으로 탐색하는 경우에, 검색에 관한 문의처의 메일 주소를 통지할 때 등에 이용된다.

From: aaa@xxx.yyy.zzz

Host (요청)

Host 요청 헤더는 요청이 전송되는 서버의 호스트 이름과 포트 번호를 지정한다.

HTTP/1.1에서 유일한 필수 헤더이다. 브라우저에서 서버로 서버 이름을 보낸다. 서버가 이름 베이스의 가상 호스트를 지원하고 있다면 그 이름으로 어느 서버로서 동작할지 결정된다.
예를 들어, http://aaa.devkuma.comhttp://bbb.devkuma.com 는 실은 같은 서버(IP 주소: 183.111.100.230)이지만, Host 헤더로 호스트명을 지정하는 것으로, 가상 두 개의 서버로 작동 할 수 있다.

Host 요청 확인

% curl www.devkuma.com -v
> Host: www.devkuma.com

포트 번호를 지정하지 않으면 요청한 서비스의 기본 포트(예: HTTPS URL이면 443, HTTP URL인 경우 80)로 간주된다.

Host - HTTP | MDN

If-Match (요청)

지정된 ETag와 일치하는 경우에만 메소드를 실행하도록 서버에 요청한다. (→ ETag , If-None-Match)

If-Match: "1dba6-131b-3fd31e4a"

If-Modified-Since (요청)

클라이언트측이 벌써 캐쉬를 가지고 있는 경우, 캐쉬의 일자를 서버에 통지해, 「이 일자보다 새로운 것이 있으면 전송해 주세요」라고 요구한다. 업데이트되지 않은 경우 서버는 304 (not modified) 상태를 반환하고 브라우저는 캐시 된 데이터를 표시한다. (→ If-Unmodified-Since)

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

If-None-Match (요청)

지정한 ETag와 일치하지 않는 경우에만 메소드를 실행할 것을 서버에 의뢰한다. (→ ETag , If-Match)

If-None-Match: "1dba6-131b-3fd31e4a"

If-Range (요청)

클라이언트가 엔티티의 일부를 이미 보유하고있는 경우, “이 ETag에 지정된 엔티티의 일부가 최신이면 나머지 모든 것을, 그렇지 않으면 전체를 보냅니다. ‘의 의미로 요구한다. Range 헤더와 함께 사용한다. (→ ETag , Range)

Range: bytes=0-1023
If-Range: "1dba6-131b-3fd31e4a"

If-Unmodified-Since (요청)

엔티티가, 지정된 일자보다 나중에 갱신되어 있지 않은 경우, 요구를 처리한다. 업데이트된 경우 서버는 412(Precondition Failed) 상태를 반환한다. (→ If-Modified-Since)

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Last-Modified (요청/응답)

엔티티가 마지막으로 업데이트된 시간을 나타낸다. (→ If-Modified-Since )

Last-Modified: Sun, 07 Dec 2003 12:34:18 GMT

Location (응답)

Location 응답 헤더는 리디렉션 대상 URL을 나타낸다.

엔티티 위치가 이동 했을 때, 브라우저가 요구한 URL 과는 다른 URL로 이동시키고 싶은 경우에 사용한다.
URL은 http:// 또는 https://로 시작하는 절대 URL을 지정한다. (→ Content-Location )

Location: [URL]

Location 응답 헤더

% curl http://google.com/ --head
...
Location: http://www.google.com/

위에 예제는 ‘http://google.com/' 대신에 ‘http://www.google.com/'을 접근해 달라는 것을 뜻한다.

Max-Forwards (요청)

OPTIONS 및 TRACE 메소드으로 프록시 서버의 통신 상대에게 도달할 때까지 경유하는 전송·중계 설비의 최대 수를 지정한다. 프록시 서버는 이 값을 하나씩 빼가면서, 다음의 프록시 서버에 전송 한다. 이 값이 0이 되면, 프록시 서버는 마지막 수신자로서 응답을 돌려준다.

Max-Forwards: 16

Pragma (요청/응답)

다양한 목적으로 사용된다. 예를 들어, 다음은 캐시를 사용하지 않겠다고 프록시 서버나 클라이언트에 전달한다. (→ Cache-Control )

Pragma: no-cache

Proxy-Authenticate (응답)

프록시 서버와 클라이언트 간에 인증이 필요함을 나타낸다. (→ Proxy-Authorization , WWW-Authenticate )

Proxy-Authenticate: Basic realm="XXXXXX"

Proxy-Authorization (요청)

프록시 서버와 클라이언트 사이의 자격 증명을 전달한다. (→ Proxy-Authenticate , Authorization)

Proxy-Authorization: Basic dGFuYWthOmhpbWl0c3U=

Range (요청)

클라이언트에서 서버로 엔티티의 일부만 요청한다. 아래 예제에서는 페이지의 처음 1000바이트(0바이트에서 999바이트째)만 요청한다. (→ Accept-Ranges , Content-Range , If-Range)

Range: bytes=0-999

Referer (요청)

이 요청의 원본이 된 페이지의 URL(일반적으로 링크 소스 URL)을 전달한다.

Referer: http://xxx.yyy.zzz/index.html

Retry-After (응답)

몇 초 후에 다시 요청해 준다는 의미에서 503(Service Unavailable)이나 3xx(Redirection) 상태와 함께 반환된다. 아래는 120초 후에 다시 요청해 주는 의미를 가집니다. Date: 형식의 절대 시간을 반환할 수도 있다.

Retry-After: 120

Server (응답)

서버로부터 브라우저에 서버 정보를 돌려즌다. 형식은 특별히 규정되지 않는다.

Server: Apache/1.3.22 (Unix) (Red-Hat/Linux)

TE (요청)

브라우저가 처리 가능한 확장 전송 코딩 방식 (chunked 등)이나 청크 전송시의 trailer 필드를 해석 가능한가 어떤가를 서버에 전달한다.

TE: trailers

Trailer (요청/응답)

헤더 정보를 컨텐츠의 선두가 아니고, 청크 형식으로 분할 송신된 컨텐츠의 뒤에 부가하는 경우, 거기에 부가된 헤더의 일람을 나타낸다. 이는 CGI가 데이터를 전송한 후 Content-Length 헤더를 추가하려는 경우에 유용한다.

Trailer: Content-Length

Transfer-Encoding (요청/응답)

전송에 사용되는 인코딩 형식을 나타낸다.

Transfer-Encoding: chunked

Upgrade (요청/응답)

다른 프로토콜을 사용할 것을 권장한다는 것을 상대에게 알립니다. 클라이언트 프록시 간과 같은 직접 연결에만 유효한다.

Upgrade: HTTP/2.0, SHTTP/1.3

User-Agent (요청)

User-Agent는 클라이언트의 응용 프로그램 이름, OS 이름 등을 나타낸다.
브라우저(=사용자 에이전트)의 정보를 서버에 전달한다. 형식은 특별히 규정되지 않는다. 브라우저 유형, 버전, 플랫폼 등의 정보가 포함된다.

% curl www.devkuma.com -v
> User-Agent: curl/7.77.0

Mac OS에 Chrome으로 요청을 하면 아래와 같이 표시된다. (→ 서버 )

user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36

Vary (응답)

Accept , Accept-Charset , Accept-Language 등, 서버 주도형 네고시에이션으로 사용된 헤더 정보를 나타낸다. 이것은 캐시의 유효성을 결정하는 데 유용한다. 예를 들어, 다음 예제에는 Accept-Language가 포함다. 이는 브라우저가 Accept-Language : ko를 전송했기 때문에 서버가 일본어 콘텐츠를 반환했을 수 있으며 Accept-Language : en에서 요청하면 다른 콘텐츠가 반환 될 수 있다. 있음을 나타낸다.

Vary: Accept-Charset, Accept-Language

Via (요청/응답)

메시지의 전달 경로를 나타낸다. 다음 예는 메시지가 aaa → bbb → ccc라는 프록시를 라우트하여 전달되었음을 보여준다. 1.1은 프로토콜 버전이다.

Via: 1.1 aaa, 1.1 bbb, 1.1 ccc

Warning (요청/응답)

상태 행에 추가되는 경고 코드와 메시지를 전달한다.

Warning: 110 xxxsv "Response is stale"

WWW-Authenticate (응답)

인증이 필요함을 나타낸다. 다음 예제는 이 리소스가 BASIC 인증이라는 HTTP에서 가장 기본적인 방식으로 보호됨을 보여준다. XXXXXX 부분에는 이 인증에 대한 설명문이 들어 있다. (→ Authorization )

WWW-Authenticate: Basic realm="XXXXXX"

extension-header (요청/응답)

이외에도, 서버의 구현에 의해 다양한 헤더가 구현되고 있다.

가상 호스트

HTTP/1.1에서는 가상 호스트가 지원된다. HTTP/1.1 의 클라이언트는 Host 헤더로 호스트명을 송신하지 않으면 안된다. 서버는 가상 호스트에 해당하는 컨텐츠를 응답한다. 이를 통해 한 서버에서 여러 웹 사이트를 지원할 수 있다.

요청

GET / HTTP/1.1
Host: www.devkuma.com

지속적인 연결 (Keep-Alive)

초기의 HTTP는 HTTP 요청을 보낼 때 마다 새로운 소켓 연결이 맺어졌었다. 이 방법은 효율적이지 못하다.

지속성 있는 연결(Persistent Connections)은 이렇게 같은 서버에 여러 개의 소켓 연결을 맺는 비효율 문제를 해결하기 위해 HTTP/1.0의 Keep-Alive가 나와 표준이 되었다.

즉, 하나의 연결 안에 여러 개의 요청을 보내는 것이다. 클라이언트는 아래와 같이 1회의 TCP 접속으로 복수의 컨텐츠를 요구하는 것으로, 통신 퍼포먼스를 향상시킬 수 있다. 지속 접속을 계속하는 경우에는 통상 Connection 헤더로 Keep-Alive 를, 마지막의 요구에는 close 를 지정한다.

브라우저와 서버는 헤더의 Connetion 속성에 Keep-alive 값을 지정할 수 있다. HTTP/1.1에서는 필요하지 않지만 대부분의 브라우저와 서버는 이 값을 계속 포함하고 있다.

요청

GET /aaa.html HTTP/1.1
Host: www.devkuma.com.com
Connection: Keep-Alive

GET /bbb.html HTTP/1.1
Host: www.devkuma.com.com
Connection: close

이에 대해 서버는 Content-Length나 청크(후술)등으로 복수의 컨텐츠의 경계가 명시된 컨텐츠를 돌려준다. timeout 에는 다음의 요구가 오지 않는 경우에 타임 아웃을 발생시키는 시간(초), max 에는 이 지속 접속으로 요구 가능한 요구의 남은 횟수가 지정된다.

응답

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
Keep-Alive: timeout=5, max=100 
Connection: Keep-Alive

(aaa.html 콘텐츠)
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
Keep-Alive: timeout=5, max=99 
Connection: close

(bbb.html 콘텐츠)

청크 (chunked)

CGI 결과 반환에서 콘텐츠를 생성할 때 콘텐츠의 길이를 모르는 경우와 같이 서버는 청크 형식의 데이터를 반환할 수 있다. 청크 형식의 데이터에서 연속 데이터의 바이트 수는 16진수로 표시된다. 0은 데이터의 끝을 의미한다.

응답

HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked

1234년
(16진수로 1234바이트 데이터)
9ab
(16진수로 9ab 바이트의 데이터)
0
(콘텐츠 종료)

BASIC 인증

HTTP 베이직 인증을 사용하면 서버는 클라이언트의 요청에 대해 WWW-Authenticate 헤더를 반환한다.

응답

HTTP/1.1 200 OK
WWW-Authenticate: Basic realm="HIMITSU No PAGE"

클라이언트는 WWW-Authenticate 헤더를 받으면 로그인명과 패스워드의 입력을 촉구하는 다이얼로그를 표시해, 유저가 입력한 로그인명과 패스워드를 encode 하여 다시 컨텐츠 요청을 한다.

요청

HTTP/1.1 200 OK
Host: www.devkuma.com
Authorization: Basic abcdEFGhiJklM==

2.5 - HTTP Cookie (쿠키)

Cookie(쿠키)는 다음과 같은 기능을 만들기 위해 사용한다.

  • 방문자가 그 페이지에 몇 번 방문했는지 기록해 표시한다.
  • 웹서비스에서 방문자의 최근에 방문한 페이지를 기록해 두고, 다음 번 방문시에 그 해당 페이지를 보여주기 위한 용도로 사용한다.
  • 게시판이나 채팅으로 입력한 사용자명을 기록해 두고, 다음 번 방문시에 사용자명의 입력을 생략한다.
  • 로그인으로 세션을 유지한다.

아래의 사양서가 공개되어 있다.

위와 같은 데이터는 CGI 등을 이용하여 서버 측에 기록하기 도 하지만, 쿠키를 이용함으로써 클라이언트측(브라우저를 기동하는 측)의 하드 디스크에 쿠키 정보 데이터를 기록을 하기도 한다.

쿠키 정보가 저장되는 파일은 OS나 브라우저의 버전에 따라 다르다.

예를 들면, Windows와 같은 경우는 다음과 같은 폴더나 파일에 기록된다.

- C:\Document and Settings\(UserName)\Cookies
- C:\Program Files\Netscape\Users\(UserName]\cookies.txt
- C:\Program Files\Netscape\Navigator\cookies.txt
- C:\Windows\Cookies\~.txt

Mac OS에 Chrome인 경우에는 아래 저장된다.

- ~/Library/Application Support/Google/Chrome/Default/Cookies

JavaScript를 사용하여 쿠키를 설정할 때는 다음을 수행한다.

자바스크립트

document.cookie = "~";

HTML로 지정하려면 다음을 수행한다. 이 방법은 추천하지 않는 방식이다.

HTML

<meta http-equiv="Set-Cookie" content="~">

~ 부분에는 다음과 같은 문자열을 지정한다.

형식

NAME=값; expires=값; domain=값; path=값; secure

NAME=값; 이외는 선택 사항이다. 각각 다음과 같은 의미가 있다.

매개변수 의미
NAME=값 원하는 이름에 원하는 값을 지정한다. 세미콜론(;), 쉼표(,), 공백 문자( ) 또는 한글을 사용할 때는 각각 어떤 형식으로 인코딩해야 한다. 인코딩에는 %3B, %2C, %20 등의 URL 형식의 인코딩이 자주 사용된다.
expires=값 클라이언트 측에 기록되는 쿠키의 만료일을 Thu, 1-Jan-2030 00:00:00 GMT와 같은 형식으로 지정한다. 표준 시간대는 항상 GMT로 지정된다. 생략하면 브라우저를 종료 할 때까지 만료된다. 과거 값을 지정하면 쿠키가 삭제된다.
domain=값 쿠키를 게시할 웹 서버의 이름을 지정한다. 생략하면 웹서버 이름(예 : www.devkuma.com)으로 된다.
path=값 여기에서 지정한 경로 이름과 일치하는 페이지를 탐색할 때 브라우저는 저장된 쿠키 정보를 서버로 보낸다. 예를 들어, path=/docs를 지정하면 /docs와 일치하는 모든 페이지에 쿠키 정보가 전송된다. 기본적으로 쿠키가 설정된 페이지의 경로 이름 부분이다.
secure 이 변수를 넣으면, 서버와의 연결이 안전한 경우에만 쿠키 정보가 전송된다.

가장 간단한 쓰기의 예는 다음과 같다. 이것은 브라우저가 끝날 때까지 유효하며, 설정한 페이지와 같은 폴더에 있는(혹은 하위층에 있는) 페이지에 송신된다. HTTP Header

Set-Cookie: NAME=devkuma;

만료일을 지정은 다음과 같이 한다. 브라우저를 종료하든 OS를 다시 시작하든, 만료일까지 디스크에 계속 저장된다. HTTP Header

Set-Cookie: NAME=devkuma; Tue, 31-Dec-2030 23:59:59;

JavaScript를 사용하여 쿠키 값을 읽으려면 document.cookie 값을 참조한다. 값에 대한 설명은 위를 참조하길 바란다.

자바스크립트

alert(document.cookie);

2.6 - CORS

개요

현재의 Web 브라우저에서는 하나의 Web 사이트가 가진 정보가 다른 악의적인 Web 사이트에 악용되는 것을 방지하기 위해 Same-Origin Policy(동일 출처 정책)이 적용된다.

예를 들어, 각각 다른 도메인으로 된 백 엔드 API와 프런트 엔드 간에 통신하여 자원을 요청하게 되면 Origin(도메인, 프로토콜, 포트 번호)이 다르므로 에러가 발생한다는 것이다. 즉, Web 사이트 https://api.devkuma.com/ 를 브라우저에서 표시 할 때, 이 Web 페이지에서 XMLHttpRequest(이하 XHR)와 Fetch API에서 다른 Web 사이트 https://www.devkuma.com/ 에서 HTTP(S)에서 데이터를 읽으려고 하면 오류가 발생한다.

그런데, 사용자가 액세스한 악의적인 Web 사이트라면 몰라도 데이터 연계를 하는 상대로서 신뢰 관계 수있는 Web 사이트까지 제한을 걸어 버리면 불편하므로 데이터 액세스를 허용 할 수 있는 Web 사이트에 대해서는 Origin이 달라도 액세스를 가능하게 하기 위해 CORS(Cross-Origin Resource Sharing) 라는 것이 필요하다.

CORS는?

  • Cross-Origin Resource Sharing 약자로 오리진 간의 자원 공유의 의미한다.
  • 브라우저는 서로 다른 출처간에 통신을 원칙적으로 금지하고 있다. 그러나 Cors 설정을 하여 다른 오리진 간에도 통신할 수 있게 된다.
  • 브라우저에서 보고있는 페이지와는 다른 도메인에서 데이터의 받아오는 것을 허가하는 방식이다.
  • 브라우저는 보안 크로스 사이트 스크립팅을 방지하기 위해 사용된다.
  • 오리진 도메인의 서버와만 통신 할 수 없는 제약이 있다.

Origin(오리진)?

CORS에 대해서 좀 더 정확하게 이해하려면 오리진에 대해 이해하고 있어야 한다. 웹 콘텐츠의 오리진(Origin)은 웹 콘텐츠에 액세스 하는데 사용되는 URL의 스키마(프로토콜), 호스트(도메인), 포트에 의해 정의된다. 스키마, 호스트, 포트가 모두 일치하는 경우에만 두 개체는 같은 오리진이라고 할 수 있다.

Web에서는 같은 오리진 콘텐츠 작업에만 한정되며 (동일 출처 정책)이 제약은 CORS를 사용하여 완화 할 수있다.

동일한 오리진 예

스키마(http) 및 호스트(www.devkuma.com)이 동일하므로 동일한 오리진

http://www.devkuma.com/app1/index.html
http://www.devkuma.com/app2/index.html

서버는 기본적으로 80번 포트이고, HTTP 콘텐츠를 제공하므로 동일한 오리진

http://www.devkuma.com:80
http://www.Devkuma.com

다른 오리진 예

스키마가 다르다.

http://devkuma.com/app1
https://devkuma.com/app2

호스트가 다르다. (서브 도메인이 다르다.)

http://devkuma.com
http://www.devkuma.com
http://blog.example.com

포트가 다르다.

http://www.devkuma.com
http://www.devkuma.com:8080

왜 CORS가 필요한가?

브라우저는 보안상의 이유로 동일한 오리진 정책을 채택하고 있다. 다른 출처에서 내 자원에 마음대로 접근 할 수 없도록 하기 위해 사용한다.

만약 내가 서비스하지 않는 사이트에서 세션의 요청이 얻을 수 있다면 그 사이트는 내 세션 탈취되면 해당 세션에서 나쁜 짓을 할지도 모른다. 그래서 브라우저는 이러한 요청을 막아주고 있다.

피싱 사이트가 대표적인 공격의 사례에서 이런 공격은 멈추고 내가시켰다 오리진 만 요청할 수 있도록하기 위해 필요한다.

CORS는 어떻게 작동 하는가

브라우저가 리소스를 요청할 때 추가적인 헤더에 정보를 담는다. 내 origin은 무엇이고 어떤 메소드를 사용해서 요청을 할 것이고 어떤 헤더들을 포함할 것인지를 담아서 서버에 전송한다. 서버는 서버가 응답할 수 있는 origin들을 헤더에 담아서 브라우저에게 보낸다. 브라우저가 이 헤더를 보고 해당 origin에서 요청할 수 있다면 리소스 전송을 허용하고 만약 불가능하다면 에러를 발생시킨다.

CORS preflight 요청

HTTP 헤더의 전송로 구성된 시스템이며, 브라우저가 오리진을 넘은 요구에 대한 응답에 프런트 엔드 JavaScript 코드가 접근하는 것을 차단할지 여부를 결정한다.

Request Header 목록

  • Origin

    • 어떤 오리진에서 접근하고 있는지를 보여준다.
  • Access-Control-Request-Method

    • preflight 요청을 할 때 실제 요청에서 어떤 메서드를 사용할 것인지 서버에게 알리기 위해 사용된다.
  • Access-Control-Request-Headers

    • preflight 요청을 할 때 실제 요청에서 어떤 header를 사용할 것인지 서버에게 알리기 위해 사용된다.

Response Header 목록

  • Access-Control-Allow-Origin

    • 브라우저가 해당 origin이 자원에 접근할 수 있도록 허용합니다. 혹은 *은 credentials이 없는 요청에 한해서 모든 origin에서 접근이 가능하도록 허용한다.
  • Access-Control-Expose-Headers

    • 응답의 일부로 어떤 헤더를 공개해도 좋은지를 헤더 이름을 열거하여 보여준다.
    • 브라우저가 액세스할 수있는 서버 화이트리스트 헤더를 허용한다.
  • Access-Control-Max-Age

    • preflight 요청 결과를 캐시 할 수있는 시간을 나타낸다.
  • Access-Control-Allow-Credentials

    • Credentials가 true 일 때 요청에 대한 응답이 노출될 수 있는지를 나타낸다.
    • preflight요청에 대한 응답의 일부로 사용되는 경우 실제 자격 증명을 사용하여 실제 요청을 수행 할 수 있는지를 나타낸다.
    • 간단한 GET 요청은 preflight 되지 않으므로 자격 증명이 있는 리소스를 요청하면 헤더가 리소스와 함께 반환되지 않으면 브라우저에서 응답을 무시하고 웹 콘텐츠로 반환하지 않는다.
  • Access-Control-Allow-Methods

    • preflight 요청에 대한 대한 응답으로 허용되는 메서드들을 나타냅니다.
  • Access-Control-Allow-Headers

    • preflight 요청에 대한 응답으로 사용되어 실제 요청을 할 때 사용할 수있다 HTTP 헤더를 나타낸다.요청에 대한 대한 응답으로 실제 요청 시 사용할 수 있는 HTTP 헤더를 나타냅니다.

CORS 사용 예제

여기에 하나의 Web 사이트 https://api.devkuma.com 대해 다른 Web 사이트 https://www.devkuma.com 에 대한 HTTP(S)에 대한 액세스를 허용할 경우를 예제로 설명한다.

간단하게 데이터로드를 허용할 경우

단순히 XHR 나 Fetch API에서 GET과 POST를 허용하려면 다음과 같이한다. 먼저 클라이언트 측에서 XHR의 경우는 특별한 연구가 필요없이 Fetch API의 경우 옵션에 따라 CORS를 사용하는 것을 선언한다.

클라이언트 JavaScript (XHR)

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.devkuma.com');
xhr.addEventListener('load', onLoadFunc, false);
xhr.send(null);

클라이언트 JavaScript (Fetch)

fetch('https://api.devkuma.com', {
  mode: 'cors'
}).then(onLoadFunc);

그리고, Web 서버 쪽에서는 Origin이 달라도 액세스를 허용하도록 브라우저에 명시적으로 알리기 위해 HTTP 응답 헤더에 적절한 정보를 추가한다.

먼저 브라우저에서 서버로 전송되는 HTTP 요청 헤더는 다른 Origin 액세스인 경우에 Origin는 필드가 포함된다.

GET /api HTTP/1.1
Origin: https://www.devkuma.com

만약 Origin 내용이 신뢰할 수 있는 Web 사이트 Origin 경우 HTTP 응답 헤더에

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com

와 같은 내용을 추가하면 브라우저로 액세스가 허용되는 것이다. 또한, 이러한 간단한 예제에만 어떤 Web 사이트에 다른 Origin 액세스를 허용하도록 와일드 카드로 지정할 수 있다 (하위 도메인 등의 부분 지정은 할 수 없다).

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *

Cookie를 허용하려면

HTTP(S) 통신시에 Cookie의 송수신을 허용하려면 브라우저와 서버 모두에서 조금만 조작해야 한다. 먼저 브라우저의 JavaScript에서는 다음과 같이 작성한다. 아래 예제에서는 Access-Control-Allow-Origin에 와일드 카드 지정이 허용되지 않기에 주의가 필요하다.

클라이언트 JavaScript (XHR)

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.devkuma.com');
xhr.withCredentials = true;
xhr.addEventListener('load', onLoadFunc, false);
xhr.send(null);

클라이언트 JavaScript (Fetch)

fetch('https://api.devkuma.com', {
  mode: 'cors',
  credentials: 'include'
}).then(onLoadFunc);

이에 서버 측에서 HTTP 응답 헤더에 다음과 같은 내용을 추가한다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com
Access-Control-Allow-Credentials: true

정교한 HTTP 통신을 사용하려면

CORS 사양 은 다음 조건에 하나라도 해당하는 경우 실제 HTTP 요청 (GET과 POST)를 수행하기 전에 Preflight request 로 OPTIONS 요청을 할 정해져 있다. 이 경우 서버 측에서 GET 및 POST 이외에 OPTIONS에서도 같은 CORS 대응이 필요하게 되므로 주의가 필요하다.

HTTP 요청 메소드가 GET, POST, HEAD 이외이다. HTTP 요청 헤더에 Accept, Accept-Language, Content-Language 이외의 필드가 포함되어 있거나, Content-Type 필드에 application/x-www-form-urlencoded, multipart/form-data, text/plain 이외의 내용이 지정되어 있다. Preflight request 다음과 같은 HTTP 요청 헤더가 포함되어 있다.

OPTIONS /api HTTP/1.1
Access-Control-Request-Method: {요청 HTTP 메소드 (GET, POST 등)}

이 Preflight request에 대한 응답으로 예를 들어, 적어도 다음과 같은 요령으로 Origin을 넘는 액세스로 허용하는 HTTP 요청 메소드를 지정해야 한다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com
Access-Control-Allow-Methods: GET,POST,HEAD,OPTIONS

요청에 자신의 HTTP 요청 헤더를 추가하려면

예를 들어, 브라우저 측에서 X-MyRequestX-MyOption라는 헤더를 추가했다고 하자.

클라이언트 JavaScript (XHR)

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.devkuma.com');
xhr.withCredentials = true;
xhr.setRequestHeader('X-MyRequest', 'this-is-cors-test');
xhr.setRequestHeader('X-MyOption', 'my-option');
xhr.addEventListener('load', onLoadFunc, false);
xhr.send(null);

클라이언트 JavaScript (Fetch)

fetch('https://api.devkuma.com', {
  method: 'GET',
  mode: 'cors',
  credentials: 'include',
  headers: {
    'X-MyRequest': 'this-is-cors-test',
    'X-MyOption': 'my-option'
  }
}).then(onLoadFunc);

이 경우 먼저 다음과 같은 HTTP 요청 헤더를 포함하여 Preflight request가 브라우저에서 서버로 전송된다.

OPTIONS /api HTTP/1.1
Origin: https://www.devkuma.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: X-MyRequest,X-MyOption

서버 측에서는 이러한 요청 헤더에 표시된 메소드와 헤더를 허용할지 여부를 판단하여 응답 헤더를 반환한다. Access-Control-Allow-Methods로 지정된 메소드와 Access-Control-Allow-Headers에서 지정된 헤더가 이 후에는 브라우저에서 전송하는 HTTP 요청이 허용된다. (해당 헤더는 preflight과 실제 요청을 모두 필요하다.)

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,HEAD,OPTIONS
Access-Control-Allow-Headers: X-MyRequest,X-MyOption

응답에 자신의 HTTP 응답 헤더를 추가하고 브라우저에서 읽어 내려면

다른 Origin에 액세스하는 경우, 예를 들어, 브라우저 측의 코드는 아래와 같다.

클라이언트 JavaScript (XHR)

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.devkuma.com');
xhr.withCredentials = true;
xhr.setRequestHeader('X-MyRequest', 'this-is-cors-test');
xhr.setRequestHeader('X-MyOption', 'my-option');
xhr.addEventListener('load', onLoadFunc, false);
xhr.send(null);

function onLoadFunc() {
  var myResponse = xhr.getResponseHeader('X-MyResponse');
  var myOption = xhr.getResponseHeader('X-MyOption');
}

클라이언트 JavaScript (Fetch)

fetch('https://api.devkuma.com', {
  method: 'GET',
  mode: 'cors',
  credentials: 'include',
  headers: {
    'X-MyRequest': 'this-is-cors-test',
    'X-MyOption': 'my-option'
  }
}).then(onLoadFunc);

function onLoadFunc(response) {
  var myResponse = response.headers.get('X-MyResponse');
  var myOption = response.headers.get('X-MyOption');
}

이에 대해 서버 측에서 아래와 같이 응답한다.

HTTP/1.1 200 OK
X-MyResponse: this-is-successful-response
X-MyOptions: good-result

같은 고유 응답 헤더를 브라우저에 반환하려고 하는 경우, 브라우저는 이러한 응답 헤더의 내용을 받으려고 하면 비보안 헤더에 액세스하려고 한 것으로 간주되어 액세스가 허용되지 않도록 되어 있다. (액세스가 허용되는 응답 헤더는 Cache-Control, Content-Language, Content-Type, Expires Last-Modified, Pragma인거 같다.)

이러한 고유 응답 헤더에 액세스 브라우저 허용하려면 허용할 응답 헤더를 Access-Control-Expose-Headers로 지정한다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,HEAD,OPTIONS
Access-Control-Allow-Headers: X-MyRequest,X-MyOption
Access-Control-Expose-Headers: X-MyResponse,X-MyOption

또한 당연히 Set-CookieSet-Cookie2Access-Control-Expose-Headers로 지정해도 XHR나 Fetch API으로 읽을 수 없다.

그런데 Preflight request는 매번 진행 되는가?

Preflight request는 서버 측에서 브라우저 캐시하는 유효 기간을 지정할 수 있다. 이 기간이 있으면 첫 번째 Preflight request가 이 후에는 같은 URL에 대한 HTTP 요청에도 적용이 된다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.devkuma.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,HEAD,OPTIONS
Access-Control-Allow-Headers: X-MyRequest,X-MyOption
Access-Control-Expose-Headers: X-MyResponse,X-MyOption
Access-Control-Max-Age: 864000

Access-Control-Max-Age에는 유효 기간을 초 단위로 지정한다. 위의 예에서는 10일(10(일) × 24(시간) × 60(분) × 60(초) = 864,000 (초))으로 되어 있다.

참조

3 - Apache

Apache

많이 이용되는 Web 서버 중 하나인 Apache 사용법에 대해서 설명한다. 여기에서는 로컬 환경에 Apache를 설치하는 방법, Apache를 사용하여 Web 사이트를 인터넷에 공개하기까지의 절차, 접근 제어 및 로그 파일의 보는 방법 등 기본적인 사용법과 각종 설정 방법 등에 대해 직접 실습하면서 설명한다.

3.1 - Apache | Apache 설치

Apache의 다운로드 및 설치 방법에 대해 설명한다. 설치를 한 후에 Apache를 시작하는 방법과 Apache 기술 문서를 참조하는 방법도 함께 설명한다.

3.1.1 - Apache | Apache 설치 | Apache 다운로드 및 설치

Apache의 다운로드 및 설치 방법에 대해 설명한다. 2019 년 11월 현재 최신 버전은 Apache2.4.41이다. 여기선 설치하려는 환경은 Windows10(64bit)이다.

Apache 다운로드

Apache 다운로드을 한다. Apache의 공식 웹 사이트는 다음과 같다.

httpd.apache.org

최신 버전인 ‘Apache httpd 2.4.41 Released 2019-08-14"블록에 있는"Download “를 클릭한다.

apache_download

이번에는 Windows10(64bit) 환경에 설치하기에 “Files for Microsoft Windows"라고 작성된 링크를 클릭한다.

http://httpd.apache.org/download.cgi#apache24
apache_download

Files for Microsoft Windows를 클릭했을 때, 한글이 표시된다면 상단으로 올리면 “이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.“라는 경고문이 표시되어 있는 것을 볼 수 있을 것이다. 그렇다면 en를 눌려서 영문을 표시하도록 하자.

http://httpd.apache.org/docs/current/ko/platform/windows.html
apache_download

Apache의 공식 사이트에서는 소스 코드만 제공되고, Windows 용 바이너리는 제공하지 않는다고 안내를 하고 있다. 대신에 배포를 해주고 있는 사이트를 몇 가지 알려주고 있기에 이 중에서 여기에서는 “Apache Lounge” 를 클릭한다.

http://httpd.apache.org/docs/current/en/platform/windows.html
apache_download

Apache Lounge 사이트가 표시된다. https://www.apachelounge.com/download/
apache_download

32bit 버전과 64bit 버전이 있는데 여기에서는 64bit 환경에 설치하기 때문에 “Apache 2.4.41 Win64"아래에 표시되는 “httpd-2.4.41-win64-VC16.zip"을 클릭한다.

apache_download

다운로드가 완료되면, 임의의 장소에 보관해 하면 Apache 다운로드는 이것으로 완료되었다.

Visual C ++ 재배포 가능 패키지 설치

Visual Studio를 사용하여 빌드된 Visual C++ 응용 프로그램을 실행하는 경우에는 필요한 런타임 구성 요소가 설치되어 있어야 한다. Window용 Apache 바이너리도 Visual Studio를 사용하여 구축되어 있기 때문에 런타임이 필요하다.

다른 응용 프로그램에서 사용하기 위해 이미 설치되어있는 경우가 많지만, 런타임 구성 요소가 설치가 되지 않으면 아래와 같이 “VCRUNTIME140.dll이(가) 없어 코드 실행할 수 없습니다. 프로그램을 다시 설치하면 이 문제가 해결될 수 있습니다.“와 같은 오류가 표시된다.

그러면 아래 페이지로 가서 Visual C++ 런타임을 설치한다. 여기에서는 Visual Studio 2019 용이 필요하다.

vs_download

이제 준비는 완료되었다. 다음은 Apache 설치에 대해 설명하도록 하겠다.

Apache 설치

Apache의 설치는 다운로드한 압축 파일 “httpd-2.4.41-win64-VC16.zip"를 적당한 폴더에 압축을 풀어 놓기면 하면 된다.

apache_folder

여기에서는 “C:\dev\Apache24"에 저장하였다.

3.1.2 - Apache | Apache 설치 | 설정 파일(http.conf)의 초기 설정하기

Apache에 대한 설정은 http.conf 파일에서 설정한다. Apache를 설치 한 후에 설치한 디렉토리이나 사용하는 포트 번호에 맞게 설정 파일을 변경을 해야 한다. 여기에서는 Apache 설치 직후에 실시 초기 설정에 대해 설명한다.

설치 디렉토리 수정

Apache 설정 파일인 http.conf 파일은 설치 디렉토리에서 “/Apache24/conf/“에 들어 있다.

MacOS은 /etc/apache2/httpd.conf 에 있다.

수정하기 전에 http.conf 파일을 만약을 위해 복사하여 백업으로 따로 저장하도록 하자. (구지 할 필요가 없다고 생각된다면 안해도 된다.)

그러면 http.conf 파일을 편집하도록 하겠다. http.conf 파일은 텍스트 파일이므로 텍스트 편집기에서 열면 열린다. (예를 들면, 윈도우 메모장도 편집이 가능하다.)

먼저 파일에서 “ServerRoot“을 검색한다. 그러면 다음과 같이 작성되어 있는 것을 찾을 수 있다.

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path.  If you point
# ServerRoot at a non-local disk, be sure to specify a local disk on the
# Mutex directive, if file-based mutexes are used.  If you wish to share the
# same ServerRoot for multiple httpd daemons, you will need to change at
# least PidFile.
#
Define SRVROOT "c:/Apache24"

ServerRoot "${SRVROOT}"

ServerRoot에 Apache 서버의 디렉토리를 설정한다. 기본적으로 “c:/Apache24"로 되어 있는 부분을 실제로 Apache를 설치한 디렉토리로 변경하면 된다. 구체적으로는 SRVROOT 변수에 설치한 디렉토리 설정하고 있고, ServerRoot에 SRVROOT 변수을 사용하여 설정하고 있다. 여기에서는 다음과 같이 변경하였다.

Define SRVROOT "C:/apache/Apache24"

ServerRoot "${SRVROOT}"

위에서 설정한 SRVROOT 변수는 아래와 같이 다른 설정 부분에서 사용하여 동일한 디렉토리가 설정된다.

#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "${SRVROOT}/htdocs"

<Directory "${SRVROOT}/htdocs">

 ...생략...

</Directory>
<IfModule alias_module>

 ...생략...

    #
    # ScriptAlias: This controls which directories contain server scripts. 
    # ScriptAliases are essentially the same as Aliases, except that
    # documents in the target directory are treated as applications and
    # run by the server when requested rather than as documents sent to the
    # client.  The same rules about trailing "/" apply to ScriptAlias
    # directives as to Alias.
    #
    ScriptAlias /cgi-bin/ "${SRVROOT}/cgi-bin/"

</IfModule>

#
# "${SRVROOT}/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "${SRVROOT}/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>

포트 번호 설정

다음 포트 번호 설정을 확인한다. 파일에서 “Listen“을 검색한다.

#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80

Listen는 Apache가 어떤 포트 번호와 IP 주소를 listen 할 것인지를 설정한다. 일반적으로 Web 서버와 브라우저와의 통신은 80번 포트를 사용하여 실행되기에 기본 설정에도 80번이 설정되어 있다. 일반적으로 변경할 필요는 없지만, 여러 Web 서버가 동일한 서버 컴퓨터에서 실행하는 경우에는 포트 번호가 중복되지 않게 여기에서 설정을 변경하면 된다.

ServerName 설정

마지막으로 ServerName 설정이다. 설정 파일에서 “ServerName“을 검색한다.

#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80

ServerName은 서버 자체를 나타내는 호스트명과 포트 번호를 설정한다. 초기 설정은 주석으로 되어 있고 설정하려면 “www.example.com:80"와 같이 호스트명 + 포트 번호로 설정한다. (포트 번호를 생략하면 서버에 요청을 할 수 있는 기본 포트 번호인 80을 사용한다.)

여기에서는 Apache는 로컬 환경에 설치되어 있기 때문에 ServerName 앞에 “#“을 제거하고 다음과 같이 변경하였다.

#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName localhost:80

설정 파일의 수정이 끝나면 설정 파일을 저장한다.

3.1.3 - Apache | Apache 설치 | Apache 시작 (콘솔에서 부팅과 서비스 등록)

Apache를 시작하는 방법에 대해 설명한다. Windows 환경에서 사용하는 경우에는 시작하는 방법으로는 크게 두 가지가 있다. 콘솔 응용 프로그램을 이용하여 수동으로 시작하는 방법과 Windows 서비스로 Apache를 등록 및 설정을 하여 자동으로 시작하도록 하는 방법이다.

Apache를 간단히 시작

우선 탐색기에서 Apache를 시작하는 방법이다. 실행 파일(httpd.exe)의 위치는 “(Apache 설치 디렉토리)\Apache24\bin\httpd.exe"에 있다.

시작하려면 “(Apache 설치 디렉토리)\Apache24\bin" 폴더에 있는 “httpd.exe"를 “관리자 권한으로 실행"하면, Apache를 시작된다.

httpd.exe

Apache를 시작되면, 콘솔 응용 프로그램이 뜨고 시작하는 동안 다음과 같은 상태가 된다.

그러면 Apache가 실행되고 있는지 확인해 보자. 브라우저를 시작하여 “http://localhost/“라고 입력하면 다음과 같이 표시된다면 Apache 성공적으로 시작되었다.

It works!

만약 다음과 같이 연결할 수 없다는 에러 표시가 되었다면 Apache의 시작에 실패한 것이다.

It works! Failed

에러가 발생하면 명령 프롬프트에서 httpd.exe를 실행 보면 친절하게 에러의 원인을 표시해 준다

다음은 ServerRoot이 제대로 설정이 되지 않았을 경우에 발생한다.

C:\apache\Apache24\bin>httpd.exe
httpd.exe: Syntax error on line 39 of C:/Apache24/conf/httpd.conf: ServerRoot must be a valid directory

다음은 ServerName이 제대로 설정이 되지 않았을 경우에 발생한다.

C:\apache\Apache24\bin>httpd.exe
AH00558: httpd.exe: Could not reliably determine the server's fully qualified domain name, using fe80::3179:bb2:de42:8a63. Set the 'ServerName' directive globally to suppress this message

시작된 Apache를 중지하려면 콘솔 응용 프로그램을 꺼버리면 된다. 명령 프룸프트로 실행을 하였다면 “Ctrl + c"를 누른다. 다음과 같이 표시되면 Apache가 중지되어 있다.

C:\apache\Apache24\bin>httpd.exe

C:\apache\Apache24\bin>

Apache를 서비스에 등록

다음 Apache를 서비스로 시작하는 방법이다. 우선 서비스로 등록을 한다. Apache가 실행중인 경우 중지하라. 명령 프롬프트를 관리자로 시작하고 “(Apache 설치 디렉토리)\Apache24\bin"디렉토리로 이동하여 “httpd -k install"라고 명령어를 실행한다.

C:\>cd apache\Apache24\bin

C:\apache\Apache24\bin>httpd -k install
Installing the 'Apache2.4' service
The 'Apache2.4' service is successfully installed.
Testing httpd.conf....
Errors reported here must be corrected before the service can be started.

C:\apache\Apache24\bin>

위와 같이 표시되면 서비스로 등록이 완료되었다.

등록된 여부를 확인하려면 Windows10의 “서비스"화면에서 확인할 수 있다. 바탕 화면 왼쪽 하단의 시작 메뉴를 마우스 오른쪽 버튼을 클릭하여 표시되는 메뉴 중에서 “컴퓨터 관리"를 클릭한다.

컴퓨터 관리

“컴퓨터 관리"화면이 나타나면 왼쪽 메뉴에서 “서비스 및 응용 프로그램"에있는 “서비스"를 클릭한다. 화면 오른쪽에 등록되어 있는 서비스 목록이 표시되며,이 가운데 Apache2.4가 포함되어있는 것을 확인할 수 있다.

컴퓨터 관리-서비스

Apache 시작

이어서 Apache를 시작한다. 명령 프롬프트에서 “httpd -k start"고 실행한다.

C:\apache\Apache24\bin>httpd -k start

C:\apache\Apache24\bin>

서비스"의 화면을 확인해 보면 Apache2.4 서비스의 상태가 “실행 중"으로 되어 있다.

컴퓨터 관리-서비스-시작

확인을 위해 브라우저에서 “http://localhost/“라고 입력하면 다음과 같이 표시가 되면 Apache 성공적으로 시작되었다.

Apach 시작

Apache 중지

서비스로 실행중인 Apache 명령 프롬프트에서 중지하려면 “httpd -k stop” 또는 “httpd -k shutdown"라고 실행한다.

C:\apache\Apache24\bin>httpd -k stop
The 'Apache2.4' service is stopping.
The 'Apache2.4' service has stopped.

C:\apache\Apache24\bin>

Apache 재시작

Apache가 실행된 상태에서 재시작을 위해 “httpd -k restart"라고 실행한다.

C:\apache\Apache24\bin>httpd -k restart

C:\apache\Apache24\bin>

Apache를 서비스에서 삭제

서비스로 등록된 Apache를 서비스에서 삭제하려면 “httpd -k uninstall“라고 실행한다.

C:\apache\Apache24\bin>httpd -k uninstall
Removing the 'Apache2.4' service
The 'Apache2.4' service has been removed successfully.

C:\apache\Apache24\bin>

서비스로 어떻게 Apache를 시작할지 여부를 설정

Apache를 서비스로 등록한 경우에는 Windows 서비스 관리 기능을 사용하여 Apache를 시작하거나 PC 부팅시 자동으로 시작하도록 설정할 수 있다. “서비스"화면에서 Apache2.4를 더블 클릭한다.

컴퓨터 관리-서비스

Apache2.4 서비스에 대한 속성이 표시된다.

컴퓨터 관리-서비스

“시작 유형"은 현재 “자동"으로 설정되어 있기에 Windows가 시작될 때 자동으로 Apache도 시작된다. 자동이 아닌 수동으로 Apache 시작을 수행하려면 “시작 유형"을 “수동"으로 변경한다.

컴퓨터 관리-서비스

그리고 먼저번에 명령 프롬프트로 Apache를 시작 및 중지를 하였지만, 화면의 “시작”, “중지”, “일시 중지”, “다시 시작"버튼을 클릭하여 Apache를 기동하거나 중지할 수도 있다.

컴퓨터 관리-서비스

이와 같이 서비스의 관리 화면에서도 Apache를 시작 및 중지를 제어할 수 있다.

3.1.4 - Apache | Apache 설치 | Apache 문서 참조하기

Apache 설정을 할 때 참조가 되는 것은 공식 사이트에 공개되고 있는 Apache 문서이다. 여기에서는 한국어 및 영어로 Apache 문서를 참조하는 방법에 대해 설명한다.

한국어로 작성된 Apache 문서 참조하기

문서를 참조하려면 다음 URL에 접근한다.

httpd.apache.org

왼쪽 메뉴에서 “Documentation"에 속해 있는 “Version 2.4” 링크를 클릭한다.

Apache Documentation

클릭하면 페이지가 열리면 한국어로 된 Apache2.4 시스템에 대한 문서를 볼 수 있다.

Apache Documentation

일부 영어로 된 부분도 있긴 하지만, 한국어로 작성된 상세한 문서가 준비되어 있다. 공식 문서로 매우 알기 쉽게 설명되어 있기에 모르는 것이 있으면 수시로 방문하도록 하자.

영어 버전의 문서 참조하기

한국어 버전의 문서에서는 “이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.“라고 표시되어 있듯이 내용이 조금 오래된 경우도 있는 것 같다. 만약 영어 버전으로 참조되고 싶다면 문서 페이지의 오른쪽 상단에 표시되는 “en"을 클릭한다.

Apache Documentation

클릭하면 영어 버전의 문서가 표시된다.

Apache Documentation

영어 문서를 어느정도 볼 수 있고, 최신의 내용을 확인하고 싶은 경우에 여기를 참조하면 좋을거 같다.

3.1.5 - Apache | Apache 설치 | 80이 아닌 다른 포트 번호 사용하여 Web 접근하기

Apache뿐만 아니라 다른 Web 서버에서도 일반적으로 포트 번호로 80번을 사용한다. 혹시 이미 같은 서버에서 80번을 사용하는 응용 프로그램이 기동되어 있다면, 다른 포트 번호를 사용하도록 설정해야 한다. 여기에 포트 번호로 80번가 아닌 다른 번호를 사용하여 Web 서버에 브라우저에서 접근하는 방법에 대해 설명한다.

Apache에서 사용하는 포트 번호를 변경하기

설정 파일(http.conf)의 초기 설정하기 > 포트 번호 설정“에서 설명했듯이 Apache에서 사용하는 포트 번호 지정은 http.conf 파일에서 지정한다. 기본적으로 Listen 지시어를 사용하여 다음과 같이 80번이 지정되어 있다.

#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80

같은 서버에서 다른 Web 서버가 기동되어 80번 포트가 이미 사용되고 있는 경우에는 다른 포트 번호(예: 8080)를 지정한다. 무엇이든 원하는 번호를 지정할 수 있는 것은 아니고, 같은 서버에서 실행되는 다른 응용 프로그램(메일 서버와 DNS 서버 등)를 사용하지 않는 번호를 지정해야 한다. 여기에서는 예로 8080을 사용하도록 하겠다.

#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 8080

설정을 적용하려면 http.conf 파일을 저장한 후 Apache를 다시 시작한다.

브라우저에서 포트 번호를 지정하여 Apache에 접근하기

브라우저에서 Apache와 같은 웹 서버에 접근하는 경우에느 다음 형식에 따라 접근한다.

http://(Web 서버의 호스트 이름):(Web 서버에서 사용하는 포트 번호)/...

예를 들어, 8080번으로 지정된 Web 사이트에 접근하려면 “http://www.devkuam.com:8080/"과 같이 접근한다.

포트 번호로 80번을 사용하는 경우에는 예외로 포트 번호를 생략하면 80번이 지정된 것으로 간주된다. 따라서 원래 대로라면 “http://www.devkuam.com:80"와 같이 접근하는 대신에 “http://www.devkuam.com"와 같이 포트 번호를 생략하고 접근할 수 있다.

포트 번호가 80번의 경우에는 생략할 수 있으므로 다음의 2개는 동일하다.

http://www.example.com/
http://www.example.com:80/

이번 Apache는 포트 번호 8080을 사용하고 있기에, 이 Web 서버에 접근하려면 http://localhost/ 가 아닌 http://localhost:8080과 같이 포트 번호를 지정하여 접근해야 한다. 그럼 브라우저를 열어서 연결을 해보자.

It works

성공적으로 접속이 되었다. 80이 아닌 다른 포트 번호를 사용하는 경우에는 Web 서버에 접근할 때 포트 번호를 지정하여 접근해야 한다는 것을 잊지 말도록 하자.

3.2 - Apache | Apache 기본 설정

Apache 설정 중에서도 기본적인 항목에 대한 설정 방법에 대해 설명한다. Apache에서는 http.conf 파일을 사용하여 설정한다.

3.2.1 - Apache | Apache 기본 설정 | 설정 파일(httpd.conf) 위치와 보조 설정 파일 읽기

Apache의 설정은 http.conf 파일에서 하는데, 다른 파일에 설정을 작성하고 이를 http.conf 파일에 포함시킬 수도 있다. 여기에서는 http.conf 파일의 위치와 별도로 준비한 보조 설정 파일을 포함 시키는 방법을 대해 설명한다.

http.conf 파일의 위치

Apache를 설치하면 파일 구성은 다음과 같다.

C:\apache\Apache24>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXX

 C:\apache\Apache24 디렉터리

2019-11-26  오후 10:39    <DIR>          .
2019-11-26  오후 10:39    <DIR>          ..
2015-04-16  오전 05:53            13,740 ABOUT_APACHE.txt
2019-11-26  오후 10:39    <DIR>          bin
2019-11-26  오후 10:39    <DIR>          cgi-bin
2019-08-09  오후 11:37                59 CHANGES.txt
2019-11-26  오후 10:39    <DIR>          conf
2019-11-26  오후 10:39    <DIR>          error
2019-11-26  오후 10:39    <DIR>          htdocs
2019-11-26  오후 10:39    <DIR>          icons
2019-11-26  오후 10:39    <DIR>          include
2016-05-18  오전 02:59             3,869 INSTALL.txt
2019-11-26  오후 10:39    <DIR>          lib
2019-08-09  오후 11:38            44,480 LICENSE.txt
2019-11-28  오후 12:30    <DIR>          logs
2019-11-26  오후 10:39    <DIR>          manual
2019-11-26  오후 10:39    <DIR>          modules
2019-08-09  오후 11:38             2,865 NOTICE.txt
2019-08-09  오후 11:50            41,993 OPENSSL-NEWS.txt
2019-08-09  오후 11:50             4,545 OPENSSL-README.txt
2014-01-24  오전 01:33             4,752 README.txt
               8개 파일             116,303 바이트
              13개 디렉터리  459,275,866,112 바이트 남음

C:\apache\Apache24>

Apache 설정 파일은 http.conf 파일은 “(설치 디렉토리)\Apache24\conf"디렉토리에 들어 있다.

C:\apache\Apache24\conf>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXX

 C:\apache\Apache24\conf 디렉터리

2019-11-26  오후 10:39    <DIR>          .
2019-11-26  오후 10:39    <DIR>          ..
2019-08-09  오후 11:50             1,820 charset.conv
2019-11-26  오후 10:39    <DIR>          extra
2019-11-28  오후 12:30            20,555 httpd.conf
2019-08-09  오후 11:50            13,449 magic
2019-08-09  오후 11:50            62,702 mime.types
2019-05-28  오후 10:12            11,259 openssl.cnf
2019-11-26  오후 10:39    <DIR>          original
               5개 파일             109,785 바이트
               4개 디렉터리  459,279,749,120 바이트 남음

C:\apache\Apache24\conf>

설정 변경을 하기 전에 백업으로 http.conf 파일을 다른 이름으로 복사하여 저장해 둔다. 설정을 변경하려면 http.conf 파일은 텍스트 파일이므로 텍스트 편집기를 사용하여 파일을 불러온다.

보조 설정 파일을 포함시키는 방법

현재 버전에서는 일부 설정 항목에 대해서는 별도의 파일로 분리하고, 필요에 따라 httpd.conf 파일에서 가져 올 수 있게 되어 있다. 기본적으로 제공되는 보조 설정 파일은 “(설치 디렉토리)\Apache24\conf\ext "디렉토리에 저장되어 있다.

http.conf 파일에서 다른 설정 파일을 가져 오려면 Include 지시어를 사용한다. 구체적인 예로 http.conf 파일의 마지막 부분을 보면, 다음과 같은 내용이 있다.

# Supplemental configuration
#
# The configuration files in the conf/extra/ directory can be 
# included to add extra features or to modify the default configuration of 
# the server, or you may simply copy their contents here and change as 
# necessary.

# Server-pool management (MPM specific)
#Include conf/extra/httpd-mpm.conf

# Multi-language error messages
#Include conf/extra/httpd-multilang-errordoc.conf

# Fancy directory listings
#Include conf/extra/httpd-autoindex.conf

# Language settings
#Include conf/extra/httpd-languages.conf

# User home directories
#Include conf/extra/httpd-userdir.conf

# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf

# Virtual hosts
#Include conf/extra/httpd-vhosts.conf

# Local access to the Apache HTTP Server Manual
#Include conf/extra/httpd-manual.conf

# Distributed authoring and versioning (WebDAV)
#Include conf/extra/httpd-dav.conf

# Various default settings
#Include conf/extra/httpd-default.conf

# Configure mod_proxy_html to understand HTML4/XHTML1
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>

지금은 모두 “#“이 맨 앞에 있어 주석이서서, 실제로는 보조 설정 파일을 가져 오지 않고 있다. 여기서 사용자 디렉토리에 대한 보조 설정 파일을 가져 오고 싶다면 문장의 앞에 있는 “#“을 삭제하고 다음과 같이 작성한다.

# User home directories
Include conf/extra/httpd-userdir.conf

이제 보조 설정 파일인 “conf/extra/httpd-userdir.conf"파일이 포함된다. Include 지시어 사용에 대한 자세한 내용은 “설정 파일 가져오기 (Include)“를 참조한다.

3.2.2 - Apache | Apache 기본 설정 | 도메인명과 포트 번호 (ServerName, Listen)

Apache의 설정에서 도메인명과 포트 번호 (ServerName, Listen)를 설정하는 방법에 대해 설명한다.

ServerName 지시어(directive) - 도메인 지정

ServerName 지시어(directive)는 Apache 서버가 자신의 도메인명을 나타내는 이름을 지정한다. 예를 들어, Apache가 오류 표시를 할 때, 자신을 나타내는 도메인명도 함께 표시할 때 등에 여기서 설정한 도메인명이 사용된다.

일반적으로 IP 주소에 대해 할당된 도메인명이지만, 따로 이름을 할당하고 그것을 공식 도메인명으로 원하는 경우에 사용한다. “ServerName"가 지정되어 있지 않은 경우는 Apache에 할당된 IP 주소를 역으로 도메인명을 가져온다.

형식은 다음과 같다.

ServerName [스키마://]도메인명|IP 주소[:포트 번호]

“ServerName"의 지정은 보통 “도메인명: 포트 번호"형식으로 지정한다.

그러면 “httpd.conf"파일에서 “ServerName"를 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80

기본적으로 앞에 ‘#‘을 있어서 주석처리 되어 있다.

이번에는 Apache를 로컬 환경에서 이동하고 있기 때문에 위와 같이되어 있지만 외부에 공개되는 Web 서버의 경우 예를 들어 “www.example.com"와 같이 지정 될 거라고 생각합니다 .

ServerName www.example.com:80

포트 번호는 생략할 수 있지만선택 사항이지만, 생략된 경우는 http 포트 번호를 사용한다. 포트 번호도 지정하는 것을 추천하고 있다.

Listen 지시어(directive) - 요청을 받을 포트 번호 지정

Listen 지시어(directive)는 Apache가 외부에서 요청을 받아들이는 포트 번호를 지정한다. 형식은 다음과 같다.

Listen [IP 주소:] 포트 번호 [프로토콜]

그러면 “httpd.conf"파일에서 “Listen"으로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80

요청을 받는 포트 번호로 80 번이 지정되어 있는 것을 확인할 수 있다.

받을 수 있는 포트 번호는 여러 개를 지정할 수 있는데 Listen 지시어를 여러 개를 작성한다. 아래와 같이 하면 80번 포트와 8080번 포트에서 요청을 받게 된다.

Listen 80
Listen 8080

포트 번호만 지정하게 되면 모든 인터페이스에서 지정한 포트 번호의 요청을 받는데, Apache가 실행되는 서버에 여러 개의 인터페이스가 연결되어 특정 인터페이스에서만 요청을 받기를 원한다면 그 인터페이스의 IP 주소를 지정한다.

Listen 192.170.2.1:80
Listen 192.170.2.5:8000

프로토콜는 포트 번호 443를 사용하는 경우에는 https, 그 외의 포트 번호에는 http가 기본적으로 설정된다. 만약 443 이외의 포트 번호로 받으려면 https를 사용하려면 지정을 해야 한다. 예를 들면, 아래와 같이 지정하면 포트 번호 8443를 사용하면서 프로토콜 https를 사용하게 된다.

Listen 192.170.2.1:8443 https

참조

3.2.3 - Apache | Apache 기본 설정 | 연락처 이메일 주소 (ServerAdmin)

Apache 설정에서 연락처 이메일 주소(ServerAdmin) 설정에 대해 설명한다.

ServerAdmin 지시자

“ServerAdmin"는 Apache가 에러가 발생하였을 때 표시되는 질의를 실행하는 연락처 이메일 주소를 표시 할 때 사용된다.

ServerAdmin 이메일 주소 | URL

관리자 이메일 주소보다는 연락처 이메일 주소이다. 또한 이메일 주소 외에 URL을 작성할 수 있다.

그러면 “httpd.conf"파일에서 “ServerAdmin"로검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.  This address appears on some server-generated pages, such
# as error documents.  e.g. admin@your-domain.com
#
ServerAdmin admin@example.com

만약 URL을 지정하는 경우에는 다른 서버의 URL을 작성한다. Apache에 장애가 발생한 경우에 연락처 URL이 동일한 Apache 서버라면 결국 연락을 할 수 없게 되어 버릴 수 있다는 것을 주의하자.

참조

3.2.4 - Apache | Apache 기본 설정 | 서버 위치 디렉토리 (ServerRoot)

Apache의 설정에서 서버의 위치 디렉토리 (ServerRoot)의 설정에 대해 설명한다.

ServerRoot 지시어

“ServerRoot"는 Apache가 설치되어있는 디렉토리이다.

ServerRoot 디렉토리

그러면 “httpd.conf"파일에서 “ServerRoot"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path.  If you point
# ServerRoot at a non-local disk, be sure to specify a local disk on the
# Mutex directive, if file-based mutexes are used.  If you wish to share the
# same ServerRoot for multiple httpd daemons, you will need to change at
# least PidFile.
#
Define SRVROOT "c:/Apache24"

ServerRoot "${SRVROOT}"

SRVROOT라는 변수로 디렉토리를 지정하고, ServerRoot에서 사용되었다. 기본으로 “c:/Apache24"되어 있는데, 변경하려면 새 디렉토리를 지정한다. (마지막에 “/“는 붙이지 않도록 주의하자.)

Apache의 각종 설정에서 절대 경로가 아닌 상대 경로로 작성되면 ServerRoot에 지정된 디렉토리로부터의 상대 경로이다. 예를 들어 “ErrorLog"설정 부분을 보도록 하자.

#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog "logs/error.log"

이와 같이 상대 경로로 작성된 경우 “ServerRoot"값이 “c:/Apache24"이거 이므로, “c:/Apache24/logs/error.log"가 실제로 가리키는 파일이 된다.

3.2.5 - Apache | Apache 기본 설정 | 설정 파일 포함 (Include)

Apache 구성에서 Include 지시어를 사용하여 다른 설정 파일 포함시키는 방법에 대해 설명한다.

 

Include 지시어

“Include"는 다른 설정 파일를 포함시킬 때 사용한다.

Include 파일 이름

파일 이름은 절대 경로로 지정하거나 “ServerRoot"에 대한 상대 경로로 지정한다.

그러면 “httpd.conf"파일에서 “Include"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

# Supplemental configuration
#
# The configuration files in the conf/extra/ directory can be 
# included to add extra features or to modify the default configuration of 
# the server, or you may simply copy their contents here and change as 
# necessary.

# Server-pool management (MPM specific)
#Include conf/extra/httpd-mpm.conf

# Multi-language error messages
#Include conf/extra/httpd-multilang-errordoc.conf

# Fancy directory listings
#Include conf/extra/httpd-autoindex.conf

# Language settings
#Include conf/extra/httpd-languages.conf

# User home directories
#Include conf/extra/httpd-userdir.conf

# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf

# Virtual hosts
#Include conf/extra/httpd-vhosts.conf

# Local access to the Apache HTTP Server Manual
#Include conf/extra/httpd-manual.conf

# Distributed authoring and versioning (WebDAV)
#Include conf/extra/httpd-dav.conf

# Various default settings
#Include conf/extra/httpd-default.conf

# Configure mod_proxy_html to understand HTML4/XHTML1
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>

# Secure (SSL/TLS) connections
#Include conf/extra/httpd-ssl.conf

현재는 모든 주석으로 되어 있지만 “httpd.conf” 이외에 준비된 설정 파일을 “httpd.conf"에 포함하고 싶은 경우에는 주석을 해제하고 “Include"를 사용한다.

3.2.6 - Apache | Apache 기본 설정 | 접근 허용 범위 설정 (섹션 컨테이너)

Apache에서는 접근을 허용하는 적용 범위를 디렉토리 단위와 파일 단위로 제한할 수 있다. 여기에서는 구성 적용 범위를 지정하는 방법에 대해 설명한다.

구성 적용 범위를 제한

“httpd.conf"파일을 보면 다음과 같은 내용을 볼 수 있다.

<Directory />
    AllowOverride none
    Require all denied
</Directory>

<Directory "${SRVROOT}/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<Files ".ht*">
    Require all denied
</Files>

유사한 설정이 반복적으로 이루어지고 있다. 실제 설정이 영향을 받는 범위를 지정하고, 그 범위마다 설정을 되고 있다. 이 범위를 지정하기 위한 작성을 섹션 컨테이너라고 하는 <Directory>, <Files> 등을 이용하여 작성한다.

영향 범위 지정은 (1) 디렉토리 단위로 지정하는 방법, (2) 파일 단위로 지정하는 방법, (3) URL의 경로명 단위로 지정하는 방법의 3 가지로 지정할 수 있다. 예를 들어, 디렉토리에 있는 파일을 보기 위해서는 인증이 필요하도록 설정하는 것이 가능하다.

간단히 작성하는 방법을 살펴 보겠다.

디렉토리 단위로 지정

디렉토리 단위로 범위를 지정하는 경우에는 섹션 컨테이너로 “<Directory>“를 사용한다.

<Directory 경로>
    ...
    설정 지시어
    ...
</ Directory>

디렉토리를 나타내는 경로는 전체 경로를 지정한다. Windows의 경우 드라이브에서 지정된다. 별표(*) 및 물음표(?)와 같은 와일드 카드를 사용한 지정도 가능하다.

<Directory />
    ...
</ Directory>


<Directory "${SRVROOT}/htdocs">
    ...
</ Directory>

위에서는 경로로 “/“와 “${SRVROOT}/htdocs"두 가지가 지정되어 있다. 디렉토리로 지정되면 지정된 디렉토리와 그 디렉토리에 포함된 모든 하위 디렉토리 전체가 포함된다. “${SRVROOT}/htdocs"라고 지정되어 이 디렉토리 아래에 있는 모든 파일 및 하위 디렉토리 모두가 대상이 된다.

${SRVROOT}는 아래와 같이 지정되어 있기에 실제 경로는 “${SRVROOT}/htdocs"의 실제 경로는 “C:/apache/Apache24/htdocs” 이렇게 된다.

Define SRVROOT "C:/apache/Apache24"

경로 이름 “/“라고 작성된 부분은 특별하다. 앞에서 작성한 대로 디렉토리로 지정된 경우에는 모든 하위 디렉토리가 대상이 된다. “/“는 루트 디렉토리를 나타내기에 경로를 “/“로 지정하면 모든 파일이 적용된다. 즉, 여기에서 작성된 설정은 개별로 설정이 되지 않는 모든 디렉토리의 기본 설정이 될 것이다.

별도의 디렉토리에 설정을 작성하고, 그 하위 디렉토리 대해 별도의 설정을 할 수 있다. 이 경우 2개의 설정 (정확하게는 루트에 대한 설정도 포함하면 3개의 설정)이 대상 디렉토리에 대해 작성될 수 있지만, 디렉터리로 지정하는 경우에는 루트에서 길이가 가장 짧은 순(경로가 가장 짧은 순)으로 적용되어 같은 설정 항목에 대한 설정은 덮어쓰여 진다.

파일 단위로 지정

파일 단위로 범위를 지정하는 경우에는 섹션 컨테이너로 <Files>를 사용한다.

<Files 파일명>
    ...
    설정 지시어
    ...
</ Files>

파일 이름을 지정하는 경우 해당 파일이 존재하는 디렉토리에 관계없이 특정 파일 이름의 파일이나 특정 확장자를 가진 파일 전반에 설정을 하고 싶은 경우에 이용하면 편리한다. 파일명도 별표(*) 및 물음표(?)와 같은 와일드 카드를 사용한 지정도 가능하다.

“httpd.conf"파일에 작성된 예를 보면 다음과 같이 기술되어 있다.

<Files ".ht*">
    ...
</Files>

위에서는 “.ht*“라고 지정되어서 이 와일드 카드와 일치하는 파일명은 모두 적용된다. 예를 들면, “a.html"와 파일명이 모두 적용된다.

그리고 아래와 같이 파일명의 정규표현식으로도 사용 가능하다. 정규표현식으로 작성되어 있으면 이 정규표현식과 일치하는 파일명이 모두 적용된다

<Files ~ "\.(htm|html|css|js|php)$">
   ...
</Files>

위에 예는 htm, html, css, js, php가 모두 적용된다. 이와 동일하게 <FileMatch>를 사용해서도 정규표현식이 가능하다. <Files>와 다른 점은 " ~“를 붙히지 않아도 정규표현식이 적용된다.

<FilesMatch "\.(htm|html|css|js|php)$">
    ...
</ FilesMatch>

파일명으로 범위 지정된 설정이 여러개가 작성되었다면, 작성된 순서대로 설정이 활성화되어 간다. 디렉토리의 경우 경로가 가장 짧은 이었지만, 파일명의 경우는 작성된 순서대로 적용되어가는 점에 주의하도록 한다.

URL 경로 단위로 지정

URL 경로 단위로 범위를 지정하는 경우에는 섹션 컨테이너로 <Location>를 사용한다.

<Location URL경로>
    ...
    설정 지시어
    ...
</ Location>

실제 파일의 존재 위치와는 다르게 어떻게 호출되는지의 URL 경로(및 해당 URL 경로로 시작하는 전체 URL)에 설정이 적용된다. 경로는 URL이 “http://호스트/aaa/bbb"라면 “/aaa/bbb"부분을 지정한다.

<Location /aaa/bbb>
    ...
</ Location>

“Location"는 데이터베이스으로 부터 동적으로 URL을 생성하는 경우에 사용하면 편리하다.

실제 설정 방법

3개의 섹션 컨테이너가 작성되었다면 “디렉토리”, “파일명”, “URL 경로"의 순서로 설정이 적용되어 가고 이후 설정은 덮어쓰기를 하게 된다.

여기서 실제 파일에 대해 하나의 액세스 작성 방법으로 “Location"의 URL 표기에 대한 설정을 설명하고 있는데, 이는 어디까지나 파일에 접근 방식의 작성 방법에 대한 제한이지 실제 파일에 대한 범위 설정은 아니다. 문제 없을 수도 있겠지만, 존재하는 파일에 대한 설정은 되도록이면 “Directory"와 “Files"를 사용하여 작성하도록 한다.

참조

3.2.7 - Apache | Apache 기본 설정 | 호스트 접근 설정 (hosts 파일)

hosts 파일을 사용 호스트로 접근 설정하는 방법에 대해 설명한다.

hosts 파일을 사용한 접근 설정

Apache를 로컬 환경에 설치한 경우 브라우저에서 접근하는 경우에는 자신을 나타내는 “localhost"가 사용된다. 또한 “localhost"이외에도 “127.0.0.1"에서도 접근이 가능하다.

“127.0.0.1"은 로컬 루프백((Local Loopback) 주소라고 하는 자신을 가리키는 특별한 IP 주소이다. 로컬 호스트에 IP 주소를 설정하는 경우에도 “127.0.0.1"는 항상 자신을 나타낸다.

그래서 Apache 등을 클라이언트와 동일한 컴퓨터에서 실행하는 경우에는 “127.0.0.1"로 접근하면 자신의 PC에 액세스하는 것이기에, 결과적으로 같은 컴퓨터에서 실행중인 Apache에 접근할 수 있다.

그럼 “localhost"이란? IP 주소 “127.0.0.1"에 설정되어 있는 호스트명이다. 그러기에 “localhost"에 접근하면 “127.0.0.1"에 접근하게 되어, 결과적으로 자신에게 접근하게 된다.

이 호스트명과 IP 주소에 대해 정의하는 곳이 “hosts” 파일이다. 호스트명과 IP 주소를 정의하기 위해서는 DNS 서버 등을 사용하는 방법도 있지만, 로컬에 “hosts” 파일에 작성하여 DNS 서버 등을 참조하지 않고 IP 주소에 대한 호스트명을 등록할 수 있다.

hosts 파일의 위치

Windows의 경우에 “hosts"파일은 “C:\Windows\System32\drivers\etc"에 위치한다.

C:\Windows\System32\drivers\etc>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\Windows\System32\drivers\etc 디렉터리

2019-03-19  오후 01:53    <DIR>          .
2019-03-19  오후 01:53    <DIR>          ..
2019-03-19  오후 01:49               824 hosts <<<<<<<<<<<<<<<<< 여기 존재한다.
2019-03-19  오후 01:49             3,683 lmhosts.sam
2019-03-19  오후 01:49               407 networks
2019-03-19  오후 01:49             1,358 protocol
2019-03-19  오후 01:49            17,635 services
               5개 파일              23,907 바이트
               2개 디렉터리  458,572,058,624 바이트 남음

C:\Windows\System32\drivers\etc>

“hosts"는 텍스트 파일이므로 텍스트 편집기으로 열어 볼 수 있다.

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost

“hosts"파일은 IP 주소에 대한 호스트명을 등록 할 수 있다. 형식은 다음과 같다.

IP주소		호스트명

기본 설정으로 “127.0.0.1"에 “localhost"가 호스트로 등록되어 있다. 여기에 등록이 되어 있기에 “localhost"를 입력하면 해당 호스트명의 IP 주소가 “127.0.0.1"임을 알 수 있으며, 결과적으로 “127.0.0.1"에 접근할 수 있는 것이다 .

여기서 127.0.0.1은 IPv4 주소이고, ::1는 IPv6 주소이다.

Windows 환경에서 확인한 결과 모두 코멘트로 되어 있었다. 그대로 하면 여러가지 불편이 나오는 경우가 있으므로 다음과 같이 “#“을 제거하도록 한다.

# localhost name resolution is handled within DNS itself.
127.0.0.1           localhost
#	::1             localhost

Windows의 경우 관리자 권한으로 실행한 텍스트 에디터가 아닌 편집할 수 없을 수도 있기에 주의하도록 한다.

3.3 - Apache | 콘텐츠의 설치

Web 서버로 클라이언트에 공개하는 콘텐츠의 설치 방법이나 외부에서의 접근 방법에 설명한다.

3.3.1 - Apache | 콘텐츠의 설치 | 도큐먼트 루트 (Document Root)

Apache는 WWW 서버이기에 클라이언트에서 콘텐츠 요청에 대응하는 콘텐츠를 반환한다. 그 내용을 배치해 두는 위치는 “DocumentRoot"로 지정한다.

DocumentRoot 디렉토리

디렉토리는 절대 경로 또는 ServerRoot에 상대 경로로 지정한다. 마지막에 슬래시(/)는 작성하지 않는다.

그러면 “httpd.conf"파일에서 “DocumentRoot"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "${SRVROOT}/htdocs"

이것으로 WWW 서버로 공개하는 콘텐츠는 “${SRVROOT}/htdocs” 디렉토리 아래에 위치하는 것을 의미한다. 여기서 ${SRVROOT}는 앞 페이지(설정 파일(http.conf)의 초기 설정하기)에 의해 아래와 같이 지정했다면 경로는"C:/dev/Apache2.2/htdocs"이 디렉토리가 된다.

Define SRVROOT "C:/apache/Apache24"

위치된 파일과 클라이언트의 요청의 관계는 다음과 같다.

브라우저에서 요청 URL 클라이언트에 반환되는 실제 파일
http : //localhost/index.html C:/apache/Apache24/htdocs/index.html
http : //localhost/sub/index.html C:/apache/Apache24/htdocs/sub/index.html
http : //localhost/img/image.gif C:/apache/Apache24/htdocs/ img/image.gif

현재 Apache에 브라우저에서 액세스하면 다음과 같은 화면이 표시된다.

Apache

이 화면은 “C:/apache/Apache24/htdocs/index.html” 파일이 표시된 것이다.

C:\dev\Apache24\htdocs>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\dev\Apache24\htdocs 디렉터리

2019-11-26  오후 10:39    <DIR>          .
2019-11-26  오후 10:39    <DIR>          ..
2007-06-12  오전 03:53                46 index.html <<<<<<<<<<<<<<< 표시된 파일
               1개 파일                  46 바이트
               2개 디렉터리  458,576,863,232 바이트 남음

C:\dev\Apache24\htdocs>

실습

그럼 다음과 같은 간단한 HTML 파일을 작성하여 문서 루트 디렉토리에 넣어보자.

hello.html

<html>
<head><title>Apache</title></head>
<body>
<h1>Hello World devkuma!</h1>
</body>
</html>

브라우저를 시작하여 다음 URL에 접근한다.

http://localhost/hello.html

3.3.2 - Apache | 콘텐츠의 설치 | 디렉토리 인덱스 (DirectoryIndex)

Apache는 파일에 접근 시에 디렉토리만 지정될 경우에 기본으로 반환하는 파일을 “DirectoryIndex"로 지정한다.

디렉토리 인덱스 (DirectoryIndex)

클라이언트의 요청이 있을 때, 파일명을 지정하지 않고 디렉토리만 지정될 경우가 있다. 파일명이 생략된 경우에 어떤 파일을 반환할까를 “DirectoryIndex"로 지정한다.

DirectoryIndex 파일명 [파일명 [...]]

파일명은 하나 이상을 지정할 수 있다.

그러면 “httpd.conf"파일에서 “DirectoryIndex"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

기본 설정으로 “index.html"이 지정되어 있다. 그러므로 “http://localhost/“로 클라이언트에서 요청하면 실제로는 “http://localhost/index.html"가 존재하는지 여부를 확인하고 있는 경우에 그 파일을 보내준다.

디렉토리 인덱스에는 여러 파일을 지정할 수 있다. 파일은 공백으로 구분하여 이어서 작성한다. 여러 파일을 작성되면, 앞에서부터 순서대로 작성된 파일이 존재하는지 확인하고 있다면 경우에는 그 파일을 표시한다.

DirectoryIndex index.html index.htm index.php

이와 같은 경우는 “index.html”, “index.htm”, “index.php"를 순서대로 검색하여 찾아서 존재하는 파일을 클라이언트에 반환한다.

실습

그럼 다음과 같은 간단한 HTML 파일을 작성하여 문서 루트 디렉토리에 넣어보자.

hello.html

<html>
<head><title>Apache</title></head>
<body>
<h1>Hello World devkuma!</h1>
</body>
</html>

그리고 “DirectoryIndex"을 다음과 같이 작성한다. 혹시 이미 Apache가 켜져 있다면 재기동해야 변경된 내용이 반영된다.

#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
    DirectoryIndex hello.html index.html
</IfModule>

브라우저를 시작하여 다음 URL에 접근한다.

http://localhost/

“DirectoryIndex"에 “hello.html” 파일이 가장 앞에 작성이 되어 있기에 디렉토리만 지정했을 때 먼저 “hello.html “를 검색하고 파일이 존재하여 그 파일이 표시되었다.

그럼 “DirectoryIndex"은 그대로 두고 “hello.html"를 문서 루트에서 다른 곳으로 이동하려고 한다. 도큐먼트 루트( \htdocs)에 bak 디렉토리를 만든고 거기로 이동시킨다. 그리고 다시 브라우저로 “http://localhost/“에 접근한다.

이번 경우는 “hello.html"를 먼저 찾고 파일이 존재하지 않기에 다음 후보인 “index.html"을 찾는다. 그리고 “index.html"이 존재하여 파일을 내용을 클라이언트에 반환한다.

그럼 “DirectoryIndex"은 그대 두고 “index.html"문서 루트에서 다른 곳으로 이동하려고 한다. 이 파일 역시 bak디렉토리를 이동시킨다. 그리고 다시 브라우저로 “http://localhost/“에 접근한다.

“DirectoryIndex"에 지정된 파일이 전부 찾을 수 없는 경우는 그 디렉토리에 포함된 파일 및 디렉토리 목록을 표시한다. 단, 파일 목록이 표시되는 것은 보안 상 문제도 있기 때문에 일반적으로 파일 목록이 표시되지 않도록 설정되어 것이 좋다. (설정 방법은 다른 페이지에서 확인한다)

3.3.3 - Apache | 콘텐츠의 설치 | 앨리어스 (Alias)

Apache는 앨리어스(Alias)을 사용하면 도큐먼트 루트(\htdocs)가 아닌 디렉토리를 외부에서 접근할 수 있다.

앨리어스 (Alias)

클라이언트에 공개하는 콘텐츠는 도큐먼트 루트(\htdocs) 아래의 디렉토리에 위치해야 하지만, 앨리어스(Alias)을 사용하여 전혀 다른 디렉토리에 있는 파일을 도큐먼트 루트 아래에 위치된 것처럼 보이게 할 수 있다.

Alias URL-path file-path|directory-path

클라이언트의 요청에 포함된 URL 경로가 서버의 실제 어느 디렉토리에 대응될 것인가를 지정한다.

그러면 “httpd.conf"파일에서 “Alias"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

<IfModule alias_module>
    #
    # Redirect: Allows you to tell clients about documents that used to 
    # exist in your server's namespace, but do not anymore. The client 
    # will make a new request for the document at its new location.
    # Example:
    # Redirect permanent /foo http://www.example.com/bar

    #
    # Alias: Maps web paths into filesystem paths and is used to
    # access content that does not live under the DocumentRoot.
    # Example:
    # Alias /webpath /full/filesystem/path
    #
    # If you include a trailing / on /webpath then the server will
    # require it to be present in the URL.  You will also likely
    # need to provide a <Directory> section to allow access to
    # the filesystem path.

    #
    # ScriptAlias: This controls which directories contain server scripts. 
    # ScriptAliases are essentially the same as Aliases, except that
    # documents in the target directory are treated as applications and
    # run by the server when requested rather than as documents sent to the
    # client.  The same rules about trailing "/" apply to ScriptAlias
    # directives as to Alias.
    #
    ScriptAlias /cgi-bin/ "${SRVROOT}/cgi-bin/"

</IfModule>

Alias를 사용하지 않는 경우를 생각해 보겠다. 도큐먼트 루트가 “${SRVROOT}/htdocs"이었다면 클라이언트에서 “http://localhost/sub/index.html"와 같은 요청은 다음과 같다.

http://localhost/sub/index.html
${SRVROOT}/htdocs/sub/index.html

이에 대응되게 다음과 같이 “Alias"를 설정하려고 한다.

Alias /sub/ "C:/apache/data"

이렇게 되면 클라이언트에서 “http://localhost/sub/index.html"와 같은 요청은 다음과 같다.

http://localhost/sub/index.html
C:/apache/data/index.html

“Alias"를 설정하여 Apache 도큐먼트 루트 아래에 한정되지 않고 (Apache가 포함되어 있는 디렉토리 이외에서도) 문서를 위치시킬 수 있다.

실습

그럼 실습으로 “C:/apache/data” 디렉토리를 만들고, 그 디렉토리 안에 아래 HTML 파일을 넣어보자.

hello.html

<html>
<head><title>Apache Alias</title></head>
<body>
<h1>Hello World Alias devkuma!</h1>
</body>
</html>

그리고 “Alias"에 대한 설정을 추가합니다.

<IfModule alias_module>
    #
    # Redirect: Allows you to tell clients about documents that used to 
    # exist in your server's namespace, but do not anymore. The client 
    # will make a new request for the document at its new location.
    # Example:
    # Redirect permanent /foo http://www.example.com/bar

    #
    # Alias: Maps web paths into filesystem paths and is used to
    # access content that does not live under the DocumentRoot.
    # Example:
    # Alias /webpath /full/filesystem/path
    #
    # If you include a trailing / on /webpath then the server will
    # require it to be present in the URL.  You will also likely
    # need to provide a <Directory> section to allow access to
    # the filesystem path.

    Alias /data/ "C:/apache/data/"
    <Directory "C:/apache/data">
        Require all granted
    </Directory>

    #
    # ScriptAlias: This controls which directories contain server scripts. 
    # ScriptAliases are essentially the same as Aliases, except that
    # documents in the target directory are treated as applications and
    # run by the server when requested rather than as documents sent to the
    # client.  The same rules about trailing "/" apply to ScriptAlias
    # directives as to Alias.
    #
    ScriptAlias /cgi-bin/ "${SRVROOT}/cgi-bin/"

</IfModule>

※ 디렉토리에 대한 권한이 필요하기 때문에 “Require all granted"를 설정하고 있다.

브라우저를 시작하여 다음 URL에 접근한다.

http://localhost/data/hello.html

apache alias

도큐먼트 루트 이외의 디렉토리에 설치된 파일에 대해 앨리어스(Alias)을 사용하여 외부에서 접근할 수 있게 되었다.

참조

3.3.4 - Apache | 콘텐츠의 설치 | MIME 타입 추가 (AddType)

Web 서버에 공개되는 파일은 텍스트 파일이나 HTML 파일만 가능한 것이 아니다. 이미지나 동영상 등 다양한 파일을 처리할 수 있다. 클라이언트에서 요청하는 파일에 대해 WWW 서버는 파일의 내용을 요청된 파일이 어떤 종류의 파일인지를 맞춰서 클라이언트에 반환을 하게 된다. 그에 따라 클라이언트는 받은 데이터를 적절한 표시 방법으로 처리를 하게 된다.

기본 MIME 타입 및 확장자의 조합은 기본적으로 ‘mime.types’파일에 등록되어 있다. 이 파일 이름과 설치 디렉토리는 “TypesConfig"로 설정되어 있다.

그러면 “httpd.conf"파일에서 “TypesConfig"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

<IfModule mime_module>
    #
    # TypesConfig points to the file containing the list of mappings from
    # filename extension to MIME-type.
    #
    TypesConfig conf/mime.types

... 생략 ...

</ IfModule>

상대 경로로 지정되어 있기에 “ServerRoot"에 대한 상대 경로로 되어 있어, 실제의 파일은 “${SRVROOT}\conf\mime.types"이 된다.

C:\apache\Apache24\conf>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\conf 디렉터리

2019-11-26  오후 10:39    <DIR>          .
2019-11-26  오후 10:39    <DIR>          ..
2019-08-09  오후 11:50             1,820 charset.conv
2019-11-26  오후 10:39    <DIR>          extra
2019-12-01  오후 11:41            20,686 httpd.conf
2019-08-09  오후 11:50            13,449 magic
2019-08-09  오후 11:50            62,702 mime.types <<<<<<<<<<<<<< 여기 있다.
2019-05-28  오후 10:12            11,259 openssl.cnf
2019-11-26  오후 10:39    <DIR>          original
               5개 파일             109,916 바이트
               4개 디렉터리  456,097,648,640 바이트 남음

C:\apache\Apache24\conf>

‘mime.types’는 텍스트 파일이므로 텍스트 편집기에서 열어 일부분만 발췌해 보면 다음과 같다.

# MIME type (lowercased)			Extensions
# ============================================	==========
application/json				json
text/css					css
text/csv					csv
text/html					html htm
text/plain					txt text conf def list log in

MIME 타입에 해당하는 확장자가 등록되어 있다. 예를 들어 “.html” 및 “.htm"확장자를 가진 파일은 MIME 형식이 “text/html"이 되고, “. txt” 및 “.log” 확장자를 가진 파일은 MIME 유형은 “text/plain"이 된다.

MIME 타입을 추가

이미 등록되어 있는 확장자 외에 다른 확장자에 대한 MIME 형식을 추가로 등록할 수 있다. 이 경우 “mime.types” 에 추가로 작성하는 대신에 “httpd.conf “파일에서 “AddType"를 사용하여 작성하는 것을 추천하고 있다.

AddType MIME 유형 확장명 MIME 타입 및 확장자를 세트로 지정다.

그러면 “httpd.conf"파일에서 “AddType"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

<IfModule mime_module>

... 생략...

    #
    # AddType allows you to add to or override the MIME configuration
    # file specified in TypesConfig for specific file types.
    #
    #AddType application/x-gzip .tgz
    #
    # AddEncoding allows you to have certain browsers uncompress
    # information on the fly. Note: Not all browsers support this.
    #
    #AddEncoding x-compress .Z
    #AddEncoding x-gzip .gz .tgz
    #
    # If the AddEncoding directives above are commented-out, then you
    # probably should define those extensions to indicate media types:
    #
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
		
... 생략...

</IfModule>

예를 들면, PHP 파일 인 “.php” 및 “.phps"에 대한 MIME 타입 설정하려면 다음과 같이 작성한다.

<IfModule mime_module>

... 생략 ...

    #
    # AddType allows you to add to or override the MIME configuration
    # file specified in TypesConfig for specific file types.
    #
    #AddType application/x-gzip .tgz
    #
    # AddEncoding allows you to have certain browsers uncompress
    # information on the fly. Note: Not all browsers support this.
    #
    #AddEncoding x-compress .Z
    #AddEncoding x-gzip .gz .tgz
    #
    # If the AddEncoding directives above are commented-out, then you
    # probably should define those extensions to indicate media types:
    #
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz

    AddType application/x-httpd-php .php
    AddType application/x-httpd-php-source .phps

... 생략 ...

</IfModule>

참조

3.4 - Apache | 액세스(Access) 권한

Apache에서 공개된 콘텐츠에 대한 액세스(Access) 제한을 설정하는 방법에 대해 설명한다.

3.4.1 - Apache | 액세스(Access) 권한 | 액세스 권한 설정 (Require)

액세스(Access) 권한 설정에 대해 설명한다.

액세스 권한 설정(Require)

Apache에서 사용되는 모든 파일을 대상으로 접근 제한을 설정할 수 있다. 접근 제한 구역 컨테이너 등을 사용하여 디렉토리 단위와 파일 단위로 설정할 수 있다.

※ 섹션 컨테이너에 대해서는 “접근 허용 범위 설정 (섹션 컨테이너)“를 참조한다.

예를 들어 다음과 같이 작성한다.

<Directory "${SRVROOT}/htdocs">
    Require all granted
    Require not ip 10.252.46.165
</ Directory>

액세스 제한은 Require로 작성을 한다. all를 사용하여 모두 허용(granted) 하거나 모두 거부(denied)할 수 있다. 그리고 host, ip 를 사용하여 특정 호스트나 IP 주소에 대해 허용 및 거부할 수 있다.

형식 의미
Require all granted 모든 액세스 허용
Require all denied 모든 액세스 거부
Require ip IP-주소 해당 IP 주소 허용
Require not ip IP-주소 해당 IP 주소 거부
Require host 호스트 해당 호스트 허용
Require not host 호스트 해당 호스트 거부

all

“all"을 지정하면 모든 액세스가 적용된다. “Require all granted"이면 모든 액세스가 허용된다. “Require all denied"이면 모든 액세스가 거부된다.

IP 주소

IP 주소를 지정하는 경우 해당 IP 주소만 클라이언트에서 접근할 수 있다. “Require ip 192.168.1.1"이면 IP 주소 “192.168.1.1"에서의 접근만 허용된다.

IP 주소를 작성하는 방법은 다음과 같다.

192.168.1.2
192.168.1
192.168.1.0/255.255.255.0
192.168.1.0/24

1번째는 개별 IP 주소를 지정한다. 2번째로 작성하는 경우는 “192.168.1.0/24"에 해당한다. 세 번째와 네 번째는 넷 마스크를 사용한 작성 방식으로 “192.168.1.0 ~ 192.168.1.255"주소가 대상이 된다. (※ IP 주소에 대한 설명은 생략하겠다.)

호스트

호스트 또는 도메인로 지정할 수 있다. 접근한 IP 주소로부터 호스트를 가져온다. 호스트과 대상에 지정된 호스트나 도메인이 뒷부분이 일치하는 항목이 대상이 된다.

Require host devkuma.com

예를 들어, 위와 같이 작성한 경우에는 사용자가 접근한 IP 주소로 구한 호스트의 뒷부분이 “devkuma.com"와 일치하면 허용된다. 일치하는 예로는 “host1.devkuma.com” 라든가 “www.sub.devkuma.com” 등과 같이 뒤부분이 일치하는 것이다.

설정의 우선 순위

<Directory>를 사용한 디렉토리에 대한 액세스 제한 설정하면 지정된 디렉토리 및 모든 하위 디렉토리가 대상이 된다. 예를 들어 하위 디렉토리에 대해 다른 액세스 제한 설정한 경우에는 하위 디렉토리에 대한 설정에 의해 덮어 쓰여 진다.

그럼 기본 설정이 어떻게 되어 있는지를 “httpd.conf"파일에서 살펴 보자. 액세스 제한된 일부분만 발췌하면 다음과 같다.

<Directory />
    AllowOverride none
    Require all denied
</Directory>

<Directory "${SRVROOT}/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<Files ".ht*">
    Require all denied
</Files>

<Directory "${SRVROOT}/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>

먼저 루트 디렉토리 “/“에 대해 모든 액세스를 거부하도록 설정되어 있다. 앞에서 설명했듯이 디렉토리에 대한 권한 설정은 모든 하위 디렉토리도 포함되어 있기에 루트 디렉토리에 대한이 설정은 Apache에 포함된 모든 파일에 대한 액세스가 거부로 설정된다.

다음 도큐먼트 루트인 “${SRVROOT}/htdocs” 디렉토리에 모든 액세스가 허용으로 설정되어 있다. 도큐먼트 루트의 디렉토리 및 하위 디렉토리는 외부에 공개되기에 액세스를 허용해 두어야 한다.

그리고 먼저 작성한 대로 하위 디렉토리에 대한 설정에 의해 덮어 쓰여져서 루트 디렉토리에 설정된 “모두 거부” 설정은 도큐먼트 루트의 하위 디렉토리에 대해 “모든 권한"에 덮어 쓰여 진다.

또한 “cgi-bin"디렉토리도 모든 액세스가 허용되고 있다. 이 디렉토리는 CGI 등이 위치하는 디렉토리이다.

Files를 사용하여 “.ht*“로 와이드카드에 해당되는 모든 파일에 대한 모든 액세스가 거부되어 있다. 이는 위치되어 있는 디렉토리에 관계없이 “.htaccess"라고 파일은 외부에서 접근할 수 없도록하기 위한 것이다. “.htaccess” 액세스 제한을 작성한 특별한 파일로별도로 다른 페이지에서 자세히 살펴 보겠다.

참조

3.4.2 - Apache | 액세스(Access) 권한 | 링크 제한 (SetEnvIf, Referer)

링크 제한 (SetEnvIf, Referer)

클라이언트의 요청 헤더에는 “Referer"라는 정보가 포함되어 있는 경우가 있다. 이것은 어디서 링크가 되었는지에 대한 URL에 대한 정보가 포함되어 있다.

직접 URL를 입력하여 액세스하여 Referer 정보가 포함되지 않은 경우에는 액세스 제한을 걸 수 있다.

먼저 “SetEnvIf"를 사용하여 환경 변수를 설정한다. 이번에는 “Referer"를 체크하고 조건을 충족하는 경우에 설정하는 환경 변수를 정의한다.

SetEnvIf Referer 링크가-발생한-정보 설정하는-환경-변수

헤더에 포함된 “Referer"를 확인하여 올바르게 링크가 되었는지 비교한다. 올바른 경우에는 환경 변수를 설정한다. 구체적인 예를 들면 아래와 같다.

SetEnvIf Referer "http://localhost" local_referal

이 경우에는 해당 파일에 대한 액세스 Referer를 체크하고 “http://localhost"에서 링크로 액세스가 있었는지 여부를 확인한다. 만약 맞다면 환경 변수에 “check"라는 이름의 환경 변수를 설정한다. (check는 예이다. 임의로 환경 변수를 설정할 수 있다.)

그리고 “Require"으로 환경 변수가 설정되어 있는지를 확인하도록 한다.

Require env check

위에서는 IP 주소 등의 정보 대신에 환경 변수 “check"가 설정되어 있으면 허용한다는 설정이 된다.

실습

그럼 실습으로 사용해 보도록 하자. 먼저 “img"디렉토리에 포함된 파일에 대해 “http://localhost"로 시작하는 파일에서 링크를 통해 요청이 있을 경우에만 액세스를 허용하도록 설정하려고 한다.

우선 다음과 같이 HTML 파일을 도큐먼트 루트에 생성한다.

referer.html

<html>
<body>
<h1>Referer Test</h1>
<img src="./img/devkuma.png">
</body>
</html>

그리고 도큐먼트 루트에 “img” 디렉토리를 생성하고 그 안에 “devkuma.png"라는 파일명으로 아무 이미지 파일을 넣는다.

아무 설정을하지 않은 경우에는 “http://localhost/referer.html"를 입력한 경우와 “http://localhost/img/referer.png"라고 이미지 파일을 직접 URL을 입력한 경우에도 아무 문제없이 표시가 된다.

그럼 직접 링크하는 경우를 제한하기 위해 “httpd.conf"파일의 마지막 부근에 아래와 같이 내용을 추가한다.

SetEnvIf Referer "^http://localhost" local_referal
<Directory "${SRVROOT}/htdocs/img">
    Require all denied
    Require env local_referal
</Directory>

도큐먼트 루트 아래에 있는 “img” 디렉토리에 대한 액세스 제한을 하고 있다. Referer를 확인하고 Referer의 앞부분이 “http://localhost"인 경우에만 액세스를 허용한다.

“http://localhost/referer.html"를 입력하면 HTML 파일 중에 “img” 디렉토리에 있는 이미지 파일이 요청된다. 이 경우 이미지 파일의 Referer는 “http://localhost/referer.html"가 되므로 액세스가 허용된다.

그러고 “http://localhost/img/devkuma.jpg"를 직접 URL을 입력하면 Referer가 설정되지 않기 때문에 액세스가 허용되지 않아 표시되지 않는다.

이것으로 Referer를 사용하여 액세스 제한을 어느 정도의 링크 제한을 걸 수 있게 되었다. 어느 정도는 Referer를 원래 보내 오지 않는 브라우저도 있고, 보안 소프트웨어에 따라 Referer를 끄는 경우도 있다. 이와 같은 경우는 클라이언트에서 액세스할 수 없게 된다. 또한 Referer를 위조 할 수 있는 것도 있으므로 Referer에 의한 액세스 제한은 절대적이라고는 할 수 없다.

이와 관련하여 보안 소프트웨어 대응으로 Referer가 없는 경우에도 액세스를 허용하려면 다음과 같이 작성한다.

SetEnvIf Referer "^http://localhost" local_referal
SetEnvIf Referer "^$" local_referal
<Directory "${SRVROOT}/htdocs/img">
    Require all denied
    Require env local_referal
</Directory>

이렇게 작성되면 직접 URL을 입력한 경우에도 허용되긴 하지만, 다른 서버에 있는 HTML 파일에서 직접 이미지에만 링크를 붙여 표시하는 것을 제한할 수 있다 .

참조

3.4.3 - Apache | 액세스(Access) 권한 | 기본 인증 설정 (AuthType)

인증 설정

특정 디렉토리에 있는 파일이나 URL에 사용자 이름 및 비밀번호에 의한 기본 인증을 구성하는 방법을 설명한다. 인증 설정은 많은 설정이 필요하므로 하나 하나 설명하도록 하겠다.

AuthType 인증-방식
AuthName 인증-영역
AuthUserFile 암호-파일

Apache에서 사용 가능한 인증 방법은 기본 인증(Basic) 또는 다이제스트 인증 (Digest)이다. 먼저 어느 인증 방식을 사용할지를 “AuthType"으로 설정한다. 기본 인증을 사용하는 경우의 설정은 다음과 같다.

AuthType Basic

다음은 인증 영역 이름을 지정한다. 이것은 인증을 구별하기 위한 것으로 인증시 영역 이름이 같으면 브라우저 같은 “Authorization” 헤더를 보낸다. (자세한 내용은 별도로 설명한다.)

이 영역 이름에 작성한 문자열이 인증 대화 상자에 표시되는 문자열이다. “사용자명과 비밀번호를 입력하세요.“라고 표시할 경우에는 다음과 같이 작성한다. (비록 이렇게 작성을 하긴 하지만, 본래의 의미는 영역 이름이기에 인증에 대해 서로 다른 문자열로하는 것이 바람직하다고 생각된다.) 단, 브라우저에 따라 표시가 되지 않을 수도 있다.

AuthName "사용자명과 비밀번호를 입력하세요."

다음은 사용자 인증을 위한 사용자 이름과 암호가 등록되어있는 파일을 “AuthUserFile"로 지정한다. 이번 비밀번호 파일을 “C:\apache\passwd\passfile"로 한다.

AuthUserFile "C:/apache/password/pw"

허가하는 사용자 지정

인증을 통과한 모든 사용자에게 액세스를 허용할 수도 있으며, 허가하는 사용자를 지정할 수도 있다 (인증을 통과하고 권한이 있는 사용자와 일치해야 한다.) 허가된 사용자 설정에 “Require"를 사용한다.

Require 옵션 사용자명1 사용자명2 ...

먼저 옵션은 “user” 또는 “group"을 지정한다. 허가의 대상이 사용자 단위이면 “user"를 그룹 단위이면 “group"을 지정한다. (그룹에 대해서 다른 페이지에서 설명하도록 하겠다.)

그리고 부여할 사용자명을 공백으로 구분한다. 예를 들어 수있는 사용자를 “devkuma”, “kimkc”, “araikuma"의 3개로 하려면 다음과 같다.

Require user devkuma kimkc araikuma

그리고 인증을 통과한 모든 사용자의 액세스를 허용하려면 다음과 같이 작성한다.

Require valid-user

이와 같이 사용자명이나 그룹에 액세스를 허용하기위한 비밀번호 파일 전체에서 하나만 생성 해두고, 그 위에 별도의 디렉토리별로 접근을 허용할 사용자와 그룹을 지정할 수 있다 .

인증 대화 상자 표시

그러면 비밀번호 파일 작성하기 전에 인증 대화 상자가 표시되는 것까지 확인해 보자.

먼저 도큐먼트 루트에 “admin"란 디렉토리를 만들고 admin.html 을 생성한다.

<html>
<body>
<h1>Admin</h1>
This is Admin page.
</body>
</html>

그리고 기본 인증을 설정한다. 아래 내용을 “httpd.conf” 어딘가에 추가한다.

<Directory "${SRVROOT}/htdocs/admin">
    AuthType Basic
    AuthName "사용자명과 비밀번호를 입력하세요."
    AuthUserFile "C:/apache/passwd/passfile"
    Require valid-user
</Directory>

그러면 Apache를 다시 시작하여 “http://localhost/admin/admin.html"에 액세스한다.

크롬에서 접속한 경우

Microsoft Edge에서 접속한 경우

사용자명과 비밀번호를 입력을 요구하는 인증 대화 상자가 표시되었다.

그럼 다음 페이지에서 사용자명과 비밀번호를 등록하는 비밀번호 파일 작성에 대해 설명하겠다.

3.4.4 - Apache | 액세스(Access) 권한 | 비밀번호 파일 생성 (htpasswd)

사용자 인증시 참조되는 비밀번호 파일을 생성하고, 거기에 새로 사용자도 추가해 본다.

비밀번호 파일 생성 실행 명령어

사용자 인증시 참조되는 파일이 비밀번호 파일이다. 사용자 이름과 비밀번호가 쌍으로 등록되어 있다. 비밀번호 파일은 실제로 텍스트 파일인데 작성하려면 Apache에서 제공되는 “htpasswd.exe"를 사용하여 만든다.

“htpasswd.exe"파일은 “(Apache가 설치되어 있는 디렉토리)\Apache24\bin"에 포함되어 있다.

C:\apache\Apache24\bin>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\bin 디렉터리

2019-11-26  오후 10:39    <DIR>          .
2019-11-26  오후 10:39    <DIR>          ..
2019-08-09  오후 11:47            97,280 ab.exe
2019-08-09  오후 11:47           109,056 abs.exe
2019-08-09  오후 11:47            41,984 ApacheMonitor.exe
2019-08-09  오후 11:47            18,432 apr_crypto_openssl-1.dll
2019-08-09  오후 11:47            31,232 apr_dbd_odbc-1.dll
2019-08-09  오후 11:47            14,848 apr_ldap-1.dll
2019-08-09  오후 11:50             9,192 dbmmanage.pl
2019-08-09  오후 11:47           100,352 htcacheclean.exe
2019-08-09  오후 11:47           123,392 htdbm.exe
2019-08-09  오후 11:47            84,992 htdigest.exe
2019-08-09  오후 11:47           117,760 htpasswd.exe <<<<<<<<<<<<<<<<<<<<<<< 여기 있다.
2019-08-09  오후 11:50            29,696 httpd.exe
2019-08-09  오후 11:47            65,024 httxt2dbm.exe

... 생략 ...

2019-04-05  오후 07:30            86,016 zlib1.dll
              30개 파일           9,142,248 바이트
               3개 디렉터리  453,122,154,496 바이트 남음

C:\apache\Apache24\bin>

Windows에서 실행하려면 명령 프롬프트에서 실행해야 한다. 실행 형식은 아래와 같다.

htpasswd 옵션 비밀번호-파일 사용자명

생성하려는 비밀번호 파일을 지정하고, 추가할 사용자명을 지정한다. 비밀번호 파일을 새로 만들려면 옵션 “-c"를 지정한다. 기존에 있는 비밀번호 파일에 사용자를 추가하는 경우에는 옵션에 아무것도 지정하지 않는다.

비밀번호 신규 생성하는 경우:

htpasswd -c "C:\apache\passwd\passfile" devkuma

사용자 추가하는 경우 :

htpasswd "C:\apache\passwd\passfile" kimkc

새 비밀번호 파일 생성

그럼 새 비밀번호 파일 생성해 보자. 먼저 명령 프롬프트를 열어 “(Apache가 설치되어있는 디렉토리)\Apache24\bin"로 이동하고, “htpasswd -c “C:\apache\passwd\passfile” devkuma” 명령어를 입력하여 실행한다.

명령어를 실행 전 생성하는 파일의 디렉토리가 생성되어 있어야 한다. 디렉토리가 없으면 아래와 같이 에러가 발생한다.

C:\apache\Apache24\bin>htpasswd -c "C:\apache\passwd\passfile" devkuma
htpasswd: cannot create file C:\apache\passwd\passfile

명령어를 실행해서 문제가 없다면 아래와 같이 비밀번호를 입력란이 표시된다.

C:\apache\Apache24\bin>htpasswd -c "C:\apache\passwd\passfile" devkuma
New password: 

추가할 사용자의 신규 비밀번호를 입력을 한다. 그러면 확인을 위해 다시 비밀번호 입력란이 표시된다.

C:\apache\Apache24\bin>htpasswd -c "C:\apache\passwd\passfile" devkuma
New password: ****
Re-type new password: 

신규 비밀번호와 동일한 비밀번호를 입력한다.

C:\apache\Apache24\bin>htpasswd -c "C:\apache\passwd\passfile" devkuma
New password: ****
Re-type new password: ****
Adding password for user devkuma

C:\apache\Apache24\bin>

확인까지 제대로 입력이 되었다면, 이제 새 비밀번호 파일이 생성되고 계정 하나가 추가되었다.

사용자 추가

이미 생성된 비밀번호 파일에 사용자를 추가하기 위해 “-c"를 붙이지 않고 실행한다. “-c"을 붙이면 새 암호 파일을 새로 생성되어, 기존에 등록된 사용자 정보가 없어지기에 주의하도록 하자.

C:\apache\Apache24\bin>htpasswd "C:\apache\passwd\passfile" kimkc
New password: ****
Re-type new password: ****
Adding password for user kimkc

C:\apache\Apache24\bin>

명령어를 입력하는 방법은 새로 비밀번호 파일 생성하는 방법과 동일하다.

암호 파일 확인

그러면 생성된 암호 파일의 내용을 확인해 보자. 텍스트 파일이므로 텍스트 편집기으로 열어 볼 수 있다.

devkuma:$apr1$H.4gZ1un$LTl9FvfcbxRrRKfqZ4Txy0
kimkc:$apr1$/P6swipC$60iAhelYy/0i6bVbhPHy5/

현재 “devkuma"와 “kimkc” 이렇게 2개의 계정이 생성되어 있다. 비밀번호는 암호화되어 저장되어 있기에 내용은 알 수 없다.

사용자 삭제

사용자 삭제는 다른 암호 파일에서 해당 행을 삭제해도 되지만, “- D” 옵션으로 실행하여 사용자의 삭제가 가능하다. 실행 형식은 아래와 같다.

htpasswd -D 비밀번호-파일 사용자명

그럼 kimkc 계정을 삭제해 보도록 하겠다.

htpasswd -D "C:\apache\passwd\passfile" kimkc
C:\apache\Apache24\bin>htpasswd -D "C:\apache\passwd\passfile" kimkc
Deleting password for user kimkc

C:\apache\Apache24\bin>

“kimkc"가 삭제되었다. 확인을 위해 비밀번호 파일을 열어 본다.

devkuma:$apr1$H.4gZ1un$LTl9FvfcbxRrRKfqZ4Txy0

“kimkc"행이 삭제된 것을 확인할 수 있다.

이것으로 비밀번호 파일이 준비되었다. 다음 페이지에서 인증을 실행해 보도록 하자.

3.4.5 - Apache | 액세스(Access) 권한 | 인증 실행

인증 실행

인증이 필요한 페이지에 접근하려고 하면 서버 측은 “Authorization"라는 헤더가 브라우저의 요청에 포함되어 있는지 확인한다. 처음 접근할 때에는 “Authorization” 헤더가 없기 때문에 브라우저에 인증이 필요하다고 알린다.

알림를 받은 브라우저는 인증 대화 상자를 표시하고 입력된 사용자명과 비밀번호로 “Authorization” 헤더를 만들고 다시 Web 서버에 “Authorization” 헤더가 포함하여 요청을 보낸다.

서버 측에서는 보내온 “Authorization” 헤더를 인증하고, 인증을 통과하면 페이지를 표시하고, 인증을 통과하지 못하면 브라우저 측에 다시 인증이 필요함을 알린다. 즉, 인증 대화 상자는 서버가 표시하는 것이 아니라, 서버로 부터 알림을 받은 브라우저가 “Authorization” 헤더를 생성하기 위해 표시하고 있는 것이다.

그러면 실제로 인증 대화에 등록한 사용자명과 암호를 입력해 본다. “http://localhost/admin/admin.html"에 액세스한다. (인증의 설정에 대해서는 “기본 인증 설정 (AuthType)“를 참조한다).

인증 실행

인증 대화 상자가 열리므로, 비밀번호 파일에 등록된 사용자와 암호를 입력한다. 입력된 값이 암호 파일에 등록된 사용자명과 비밀번호가 맞다면 인증을 통과하고 페이지가 표시된다.

인증 실행

브라우저는 다른 인증이 필요한 페이지에 대한 요청을 서버에 보내는 경우에도 “AuthName"이 같다면 브라우저가 닫힐 때까지 같은 “Authorization” 헤더로 Web 서버에 요청을 하도록 되어 있다.

그러기에 동일한 영역 이름이 설정되어 인증이 필요한 페이지를 이동하게 하면 처음부터 “Authorization” 헤더가 포함되어 있어 그 인증이 통과된다. 그래서 일단 인증이 통과하면 동일한 인증이 필요한 다른 페이지를 다시 인증할 수 없음을 확인할 수 있다.

인증 실행

위에 페이지는 먼저 인증을 통과한 페이지와 같은 디렉토리에 있는 다른 페이지이다. 이 페이지도 같은 디렉토리에 대한 인증이 필요하지만, 이미 인증이 통과되어 “Authorization” 헤더가 포함된 상태이기에 인증을 다시 하지 않는다.

인증에 실패했을 경우

인증 대화 상자가 열려 사용자와 비밀번호를 입력하였을때, 입력이 잘못되었거나 입력된 값이 비밀번호 파일에 등록되어 있지 않는 경우에는 서버 측에서 브라우저로 다시 인증이 필요하다고 알린다. 이는 처음에 “Authorization” 헤더가 없었을 때와 동일한 동작이다. 그래서 다시 인증 대화 상자를 브라우저가 열려 새로운 “Authorization” 헤더를 포함해서 서버에 요청을 하려고 한다.

인증에 성공할 때까지 반복되지만 결국 인증을 포기하고, 대화 상자에 “취소"버튼을 클릭하면 브라우저는 인증이 필요하다는 오류 메시지를 표시하고 Web 서버에 페이지 조회 요청을 보내는 것을 포기하게 된다.

인증 실행

3.4.6 - Apache | 액세스(Access) 권한 | 그룹 단위로 인증

“Require"를 사용하여 접근할 수 있는 사용자를 설정할 시에 사용자가 적은 경우는 나열을 해도 상관 없지만, 미리 사용자를 그룹에 등록해 고, 그룹 단위로 접근을 허용할 수 있다. 그러면 그룹에 포함된 사용자는 인증이 통과하면 접근이 허용되는 것이다.

먼저 그룹명과 그룹에 속한 사용자를 작성하는 그룹 파일을 만든다.

그룹 파일 생성

비밀번호 파일의 경우는 Apache에서 “htpasswd.exe"라고 도구가 준비되어 있지만, 그룹 파일에는 그러한 도구는 준비되어 있지 않다. 그룹 파일은 단순한 텍스트 파일이기에 텍스트 편집기에서 작성을 한다.

그룹명1: 사용자명1 사용자명2 사용자명3 ...
그룹명2: 사용자명1 사용자명4 ...

그룹 파일에 등록하는 그룹마다 한 줄로 작성한다. 그룹명 뒤에 콜론(:)으로 구분하여 그룹에 등록하는 사용자 이름을 작성한다. 사용자명은 공백으로 구분하여 이어서 작성한다.

여기서는 그룹 파일명은 “C:\apache\passwd\ group"라고 지정하겠다. 이번에 생성하는 그룹 파일은 다음과 같다.

group

admin: devkuma kimkc
user: araikuma
other: happykuma

AuthGroupFile을 지정

다음은 “httpd.conf” 파일에 “AuthGroupFile"를 사용하여 그룹 파일명을 지정한다.

AuthGroupFile 그룹명

앞에서 생성한 그룹 파일을 지정은 다음과 같이 하면 된다.

AuthGroupFile "C:/apache/passwd/group"

httpd.conf에 작성 방법

그룹 파일는 어디까지나 사용자를 한번에 관리하는 위한 것이므로, 인증은 사용자 단위로 이루어진다. 그러므로 “AuthGroupFile"는 사용자 인증을 위한 설정 중에 하나로서 작성이 된다.

<Directory "${SRVROOT}/htdocs/admin">
    AuthType Basic
    AuthName "사용자명과 비밀번호를 입력하세요."
    AuthUserFile "C:/apache/passwd/passfile"
    AuthGroupFile "C:/apache/passwd/group"
    Require group admin user
</Directory>

“Require"에 대한 옵션에 “group"을 지정하고, 이어서 접근를 허용할 그룹을 공백으로 구분하여 작성한다.

※ 사용자의 경우에는 모든 사용자를 허용하는 “valid-user"라고 작성을 하였지만, 그룹의 경우는 그렇지 않기에 하나 하나 작성할 수 밖에 없다.

그럼 그룹을 사용한 인증을 해보도록 하겠다. 그러면 인증이 설정되어 있는 디렉토리에 포함된 “http://localhost/admin/admin.html"에 브라우저로 접근한다.

그룹을 사용한 인증

그룹명에 의해 인증을 설정된 경우에도 브라우저에 표시되는 인증 대화 상자는 동일하다. 권한이 설정되어 있는 그룹에 포함된 사용자명으로 인증을 통과하면 해당 페이지가 표시된다.

그룹을 사용한 인증

3.4.7 - Apache | 액세스(Access) 권한 | IP 주소 제한 및 사용자 인증의 조합

“Require"를 사용하여 IP 주소 및 도메인의 제한을 설정하는 방법과 사용자명과 비밀번호를 사용하는 사용자 인증을 수행하는 방법을 하나의 디렉토리에 모두 지정할 수 있다.

<Directory "${SRVROOT}/htdocs/admin">
    Require all granted
    Require ip 192.168.1.0/24
		
    AuthType Basic
    AuthName "사용자명과 비밀번호를 입력하세요."
    AuthUserFile "C:/apache/passwd/passfile"
    Require valid-user
</Directory>

이렇게 두 방식으로 액세스 제한이 설정되어 있으면, 기본적으로 두 조건을 모두 만족하는 경우에만 액세스가 허용된다. 즉, IP 주소도 지정 주소에서 접근이면서, 사용자 인증을 통과한 경우를 말한다.

Apache에서는 어느 하나의 조건만 맞다면 액세스를 허용하도록 설정하는 것도 가능하다. 즉, IP 주소가 조건에 맞는다면 무조건 접근을 허용하고 지정된 IP 주소가 아니라면 사용자 인증해야 한다. 이는 사내에서 자유롭게 볼 수 있지만, 외부에서 볼 경우에 액세스 인증이 해야만 하는 경우를 생각할 수 있다.

설정하려면 “<RequireAny>“으로 설정한다.

<RequireAny>
....
</RequireAny>

그리고 “<RequireAll>“로 설정하면, 특별히 아무것도 지정되지 않은 경우와 동일하게 두 조건이 충족된 경우에만 액세스가 허용된다.

<RequireAll>
...
</RequireAll>

이는 다음과 같이 작성한다.

<Directory "${SRVROOT}/htdocs/admin">
    <RequireAll>
    Require all granted
    Require ip 192.168.1.0/24
		
    AuthType Basic
    AuthName "사용자명과 비밀번호를 입력하세요."
    AuthUserFile "C:/apache/passwd/passfile"
    Require valid-user
    </RequireAll>
</Directory>

3.4.8 - Apache | 액세스(Access) 권한 | 다이제스트 인증 설정 (htdigest)

기본(basic) 인증은 거의 모든 브라우저에서 사용할 수 있지만, 사용자명과 비밀번호 정보를 서버에 전송할 때 일반(Plain) 텍스트로 전송되므로 만약 통신 내용을 중간에 가로채면 사용자명과 비밀번호를 노출이 되어 버린다.

그래서 브라우저와 서버간에 이루어지는 통신에서 흐르는 정보를 MD5로 암호화하고 통신하는 방식이 다이제스트 인증이다.

설정 방법은 기본 인증의 경우와 비슷하다. 순서대로 살펴 보도록 하자.

비밀번호 파일 생성

먼저 비밀번호 파일을 작성한다. 기본 인증의 경우에는 Apache에서 제공되는 “htpasswd.exe"를 사용했지만, 다이제스트 인증의 경우에는 “htdigest.exe"를 사용한다. 이 파일이 놓여있는 위치는 “htpasswd"와 동일하게 “(Apache 설치 디렉토리)/Apache24/bin"에 있다.

실행시의 형식은 다음과 같습니다.

htdigest 옵션 비밀번호-파일 영역명 사용자명

생성한 비밀번호 파일을 지정하고 추가하는 사용자명을 지정한다. 비밀번호 파일을 새로 만들려면 옵션 “-c"를 지정한다. 기존의 비밀번호 파일에 사용자를 추가하는 경우에는 옵션에 아무것도 지정하지 않는다.

기본 인증의 경우와 다른 점은 “영역명"을 맞게 지정한다. 이 영역명은 “AuthName"로 지정하는 영역명과 동일해야 한다.

htdigest -c "C:/apache/passwd/digestpass" "Digest Auth" devkuma

위에서는 비밀번호 파일은 “C:/apache/passwd/digestpass"으로 하고, 영역명은 “Digest Auth"으로 하였으며, 사용자명은 “devkuma"로 지정하여 새 암호 파일을 만들고 있다. 생성할 때는 설정 비밀번호를 두 번 입력해야 하다.

C:\apache\Apache24\bin>htdigest -c "C:/apache/passwd/digestpass" "Digest Auth" devkuma
Adding password for devkuma in realm Digest Auth.
New password: ****
Re-type new password: ****

C:\apache\Apache24\bin>

생성된 비밀번호 파일은 텍스트 파일이므로 텍스트 편집기으로 열어 볼 수 있다.

devkuma:Digest Auth:511a7e57972fad36f7687cf36cd57d6e

“사용자명:영역명:비밀번호"의 형식으로 사용자 1명에 1줄로 작성된다.

httpd.conf 설정

“httpd.conf” 설정은 기본 인증의 경우와 거의 동일하다.

“AuthType"에는 “Basic” 대신에 “Digest"을 지정하고, “AuthName"는 비밀번호 파일을 만들 때 지정한 것과 동일한 영역명을 지정한다. 비밀번호 파일의 지정은 이전 버전에서는 “AuthDigestFile"를 사용한 것 같은데 Apache2.2 이후부턴"AuthUserFile “이다.

<Directory "${SRVROOT}/htdocs/admin">
    AuthType Digest
    AuthName "Digest Auth"
    AuthUserFile "C:/apache/passwd/digestpass"
    Require valid-user
</Directory>

모듈 추가

다이제스트 인증을 사용하는 경우에는 “auth_digest_module"모듈을 로드해야 한다. 디폴트로는 로드하지 않도록 되어있다. “httpd.conf"파일에서 “auth_digest_module"로 검색 해보세요. 71 번째 줄 부근에 설명이 있다.

LoadModule allowmethods_module modules/mod_allowmethods.so
LoadModule asis_module modules/mod_asis.so
LoadModule auth_basic_module modules/mod_auth_basic.so
#LoadModule auth_digest_module modules/mod_auth_digest.so <--------- 디폴트로 로드하지 않도록 주석으로 되어 있다.
#LoadModule auth_form_module modules/mod_auth_form.so
#LoadModule authn_anon_module modules/mod_authn_anon.so

“auth_digest_module"에 대한 “LoadModule"의 앞에 “#“이 작성 되어있다면 “#“을 제거한다. 이것으로 다음부터는 “auth_digest_module” 모듈을 로딩이 될 것이다.

LoadModule asis_module modules / mod_asis.so
LoadModule auth_basic_module modules / mod_auth_basic.so
LoadModule auth_digest_module modules / mod_auth_digest.so  <--------- '#'를 제거하여 주석을 풀었다.
#LoadModule authn_anon_module modules / mod_authn_anon.so
#LoadModule authn_dbm_module modules / mod_authn_dbm.so

다이제스트 인증을 시도

그럼 문서 루트 아래의 “admin” 디렉터리에서 다이제스트 인증을 설정한다. 사용되는 비밀번호 파일은 앞에서 작성한 것을 그대로 사용한다.

<Directory "${SRVROOT}/htdocs/admin">
    AuthType Digest
    AuthName "Digest Auth"
    AuthUserFile "C:/apache/passwd/digestpass"
    Require valid-user
</Directory>

그러면 브라우저에서 “http://localhost/admin/admin.html"에 액세스하면 다음과 같이 인증 대화 상자가 표시된다.

크롬에서 접속한 경우

다이제스트 인증

Microsoft Edge에서 접속한 경우

다이제스트 인증

인증 대화 화면의 기본 인증의 경우와는 약간 차이가 있지만 기본적으로 동일하다. 올바른 사용자명과 비밀번호를 입력하고 인증을 통과하면 해당 페이지가 표시된다.

다이제스트 인증

인증 대화 화면에서 “취소"버튼을 클릭하면 다음과 같은 오류 표시가 행해지고 요청은 종료된다.

다이제스트 인증

덧붙여서 비밀번호 파일을 만들 때 사용자에게 설정한 영역명과 “AuthName"에서 설정한 영역명이 다른 경우에는 사용자명과 비밀번호가 일치하여도도 인증은 되지 않는다.

3.5 - Apache | PHP 사용을 위한 설정

Apache에서 PHP를 사용하는 경우에 필요한 설정에 대해 설명한다. 구체적으로는 “httpd.conf” 파일에 PHP에 대한 설정을 추가하는 방법에 대해 설명한다.

3.5.1 - Apache | PHP 사용을 위한 설정 | 모듈(php7_module) 추가와 확장(.php) 등록

Apache 통해서 PHP를 사용하기 위해 필요한 모듈 (php7_module)의 추가와 확장(.php) 등록하는 방법에 대해 설명한다.

모듈 추가

먼저 PHP를 사용하기위한 모듈을 추가해야 한다. Apache 설정 파일인 “Apache24/conf/httpd.conf” 파일을 텍스트 편집기로 열어 “Dynamic Shared Object (DSO) Support"를 검색하면, 다음과 같은 내용을 찾을 수 있다.

#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
#LoadModule access_compat_module modules/mod_access_compat.so
LoadModule actions_module modules/mod_actions.so

.. (중간 생략) ..

#LoadModule watchdog_module modules/mod_watchdog.so
#LoadModule xml2enc_module modules/mod_xml2enc.so

동적으로 추가할 모듈이 작성되어 있다. Apache2.4를 이용하고 있는 경우에는 이 블록의 맨 끝에 다음 행을 추가한다. (PHP7를 이용하는 경우이다.)

#LoadModule watchdog_module modules/mod_watchdog.so
#LoadModule xml2enc_module modules/mod_xml2enc.so
LoadModule php7_module C:/apache/php-7.4.0-Win32-vc15-x64/php7apache2_4.dll

추가하는 DLL 파일의 경로는 PHP를 설치한 각자의 환경에 맞게 변경한다.

PHP를 설치한 디렉토리를 확인하면 앞에서의 DLL 파일이 존재하는 것을 확인할 수 있다.

C:\apache\php-7.4.0-Win32-vc15-x64>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: 4E53-ECB8

 C:\apache\php-7.4.0-Win32-vc15-x64 디렉터리

2019-12-05  오후 11:06    <DIR>          .
2019-12-05  오후 11:06    <DIR>          ..
2019-11-27  오후 08:24           119,808 deplister.exe
2019-12-05  오후 11:06    <DIR>          dev
2019-12-05  오후 11:06    <DIR>          ext
2019-12-05  오후 11:06    <DIR>          extras
2019-11-27  오후 08:24         1,374,720 glib-2.dll
2019-11-27  오후 08:24            18,432 gmodule-2.dll
2019-11-27  오후 08:24        27,980,288 icudt65.dll
2019-11-27  오후 08:24         2,632,192 icuin65.dll
2019-11-27  오후 08:24            61,440 icuio65.dll
2019-11-27  오후 08:24         1,890,304 icuuc65.dll
2019-12-05  오후 11:06    <DIR>          lib
2019-11-27  오후 08:24         3,422,208 libcrypto-1_1-x64.dll
2019-11-27  오후 08:24            47,616 libenchant.dll
2019-11-27  오후 08:24           282,624 libpq.dll
2019-11-27  오후 08:24           108,544 libsasl.dll
2019-11-27  오후 08:24           300,544 libsodium.dll
2019-11-27  오후 08:24         1,301,504 libsqlite3.dll
2019-11-27  오후 08:24           225,792 libssh2.dll
2019-11-27  오후 08:24           679,424 libssl-1_1-x64.dll
2019-11-27  오후 08:24             3,272 license.txt
2019-11-27  오후 08:24            18,782 news.txt
2019-11-27  오후 08:24           197,120 nghttp2.dll
2019-11-27  오후 08:30                43 phar.phar.bat
2019-11-27  오후 08:30            53,231 pharcommand.phar
2019-11-27  오후 08:24            72,704 php-cgi.exe
2019-11-27  오후 08:24            36,864 php-win.exe
2019-11-27  오후 08:24           128,512 php.exe
2019-11-27  오후 08:24            74,599 php.ini-development
2019-11-27  오후 08:24            74,904 php.ini-production
2019-11-27  오후 08:24            35,840 php7apache2_4.dll <------------ 여기 있다.
2019-11-27  오후 08:24           890,770 php7embed.lib
2019-11-27  오후 08:24           344,064 php7phpdbg.dll
2019-11-27  오후 08:24         9,496,064 php7ts.dll
2019-11-27  오후 08:24           346,112 phpdbg.exe
2019-11-27  오후 08:24            30,257 readme-redist-bins.txt
2019-11-27  오후 08:24             4,846 README.md
2019-12-05  오후 11:06    <DIR>          sasl2
2019-11-27  오후 08:24             2,224 snapshot.txt
              33개 파일          52,255,648 바이트
               7개 디렉터리  450,575,360,000 바이트 남음

C:\apache\php-7.4.0-Win32-vc15-x64>

이것으로 PHP 모듈을 Apache 시작할 때에 추가로 불려오게 된다.

확장자 (.php) 등록

PHP에서 사용하는 확장자 (.php)과 PHP를 연결한다. 등록을 함으로써 확장자 (.php)의 파일에 액세스가 있었을 때에 PHP를 사용하여 실행된 결과를 클라이언트에 반환된다. “httpd.conf” 파일의 맨 아래 부분에 다음과 같이 작성한다.

<FilesMatch "\.php$">
  AddHandler php7-script .php
  AddType application/x-httpd-php .php
</FilesMatch>

이렇게 하면 확장자가 등록 되었다.

php.ini의 위치 지정 (PHPIniDir)

PHP 설정 파일인 “php.ini"가 설치되어 있는 경로를 지정한다. “httpd.conf” 파일을 열고 이번에는 맨 마지막에 다음과 같이 작성한다.

PHPIniDir "C:/apache/php-7.4.0-Win32-vc15-x64"

위에 “php.ini” 파일이 “C:/apache/php-7.4.0-Win32-vc15-x64” 디렉토리에 설치가 되어 경우이다. 자신의 환경에 맞게 변경하도록 한다. 처음 설치했다면 “php.ini"는 존재하지 않는다면, php.ini-development 파일이나 php.ini-production 파일를 복사하여 확장자를 ini로 변경한다.

이것으로 지정된 위치에있는 “php.ini"파일을 참조 할 수 있다.

“httpd.conf” 파일의 변경이 되면 Apache를 다시 시작하여 새 설정을 반영한다.

3.5.2 - Apache | PHP 사용을 위한 설정 | PHP 동작 여부 확인

Apache에서 성공적으로 PHP를 사용할 수 있도록 설정되어 있는지 여부를 확인하기 위해 phpinfo 함수를 사용한 간단한 스크립트를 작성하고 테스트해 본다.

목차

phpinfo 함수를 사용한 샘플 스크립트

텍스트 편집기를 열고 다음과 같이 작성한다.

<?php
phpinfo();
?>

그리고 예를 들어 “phpinfo.php"라는 파일명으로 저장한다. 저장된 파일은 Apache 문서 루트에 넣는다.

C:\apache\Apache24\htdocs>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\htdocs 디렉터리

2019-12-05  오후 11:32    <DIR>          .
2019-12-05  오후 11:32    <DIR>          ..
2007-06-12  오전 03:53                46 index.html
2019-12-05  오후 11:25                21 phpinfo.php
               2개 파일                  67 바이트
               2개 디렉터리  450,570,784,768 바이트 남음

C:\apache\Apache24\htdocs>

브라우저를 열고 “http://localhost/phpinfo.php"에 액세스한다.

phpinfo

위와 같이 PHP에 대한 정보가 표시되었다면, 이제 Apache에서 PHP를 사용할 수 있게 되었다.

3.6 - Apache | 로그 파일

Apache 액세스가 있을 경우 또는 오류가 발생하는 경우에 저장되는 로그에 대해 로그의 저장 방법과 순환 방법에 대해 설명한다.

3.6.1 - Apache | 로그 파일 | 로그 파일의 위치 (CustomLog, ErrorLog)

액세스 및 오류 로그의 위치는 “httpd.conf"에 정의되어 있다. 먼저 액세스 로그에서 살펴 보겠다.

액세스 로그 : CustomLog

액세스 로그 파일의 위치는 “CustomLog"로 지정한다. “httpd.conf"에서 “CustomLog"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    CustomLog "logs/access.log" common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    #CustomLog "logs/access.log" combined
</IfModule>

액세스 로그 파일을 지정하는 “CustomLog” 형식은 다음과 같다.

CustomLog 로그-파일-위치 로그-형식-이름

로그 파일 위치는 “ServerRoot"의 위치에서 상대 위치로 지정한다. ServerRoot에 대해서는 “서버 위치 디렉토리 (ServerRoot)“를 참조한다.

로그 형식 이름은 “LogFormat"으로 정의된 어떤 로그를 기록할 것에 대한 정의를 지정한 것이다. “LogFormat"의 맨 뒤에 작성되어 있는 문장이 포멧명이 된다. 포멧 내용에 대한 자세한 내용은 다른 페이지에서 설명하겠다.

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common

따라서 첫번째 줄의 LogFormat 이름은 “combined"이고, 두번째 줄의 LogFormat 이름은 “common"이다.

기본적으로 활성화되어 있는 액세스 로그는다음과 같이 정의되어 있다.

 CustomLog "logs/access.log" common

이 설정은 로그 파일명은 “access.log"이고, 로그 포멧은 “common"으로 되어 있다.

에러 로그 : ErrorLog

에러 로그 파일의 위치는 “ErrorLog"로 지정한다. “httpd.conf"에서 “ErrorLog"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog "logs/error.log"

에러 로그 파일의 위치도 “ServerRoot"의 위치에서 상대 위치로 지정된다.

로그 파일 확인

액세스 로그와 에러 로그를 텍스트 파일로 되어 있어 텍스트 편집기에서 열어 볼 수 있다.

C:\apache\Apache24\logs>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\logs 디렉터리

2019-12-05  오후 11:29    <DIR>          .
2019-12-05  오후 11:29    <DIR>          ..
2019-12-05  오후 11:25            17,108 access.log
2019-12-05  오후 11:29            60,733 error.log
2019-12-05  오후 11:29                 7 httpd.pid
2019-08-09  오후 11:50             3,146 install.log
               4개 파일              80,994 바이트
               2개 디렉터리  450,580,013,056 바이트 남음

C:\apache\Apache24\logs>

access.log

127.0.0.1 - - [03/Dec/2019:01:21:23 +0900] "GET /referer.html HTTP/1.1" 304 -
127.0.0.1 - - [03/Dec/2019:01:21:23 +0900] "GET /img/devkuma.jpg HTTP/1.1" 403 199
::1 - - [03/Dec/2019:01:21:32 +0900] "GET /referer.html HTTP/1.1" 304 -
::1 - - [03/Dec/2019:01:21:32 +0900] "GET /img/devkuma.jpg HTTP/1.1" 304 -
127.0.0.1 - - [03/Dec/2019:01:21:51 +0900] "GET /img/devkuma.jpg HTTP/1.1" 200 5168
::1 - - [03/Dec/2019:01:22:43 +0900] "-" 408 -
::1 - - [03/Dec/2019:01:22:43 +0900] "-" 408 -
127.0.0.1 - - [03/Dec/2019:01:22:51 +0900] "-" 408 -
127.0.0.1 - - [03/Dec/2019:01:53:07 +0900] "GET /admin/admin.page HTTP/1.1" 401 381
127.0.0.1 - - [03/Dec/2019:01:53:34 +0900] "GET /admin/admin.html HTTP/1.1" 401 381
127.0.0.1 - - [03/Dec/2019:01:54:12 +0900] "GET / HTTP/1.1" 200 99

error.log

[Thu Dec 05 23:27:14.834393 2019] [mpm_winnt:notice] [pid 5788:tid 580] AH00364: Child: All worker threads have exited.
[Thu Dec 05 23:27:14.852887 2019] [mpm_winnt:notice] [pid 11848:tid 576] AH00430: Parent: Child process 5788 exited successfully.
[Thu Dec 05 23:29:01.662578 2019] [mpm_winnt:notice] [pid 10168:tid 668] AH00455: Apache/2.4.41 (Win64) PHP/7.4.0 configured -- resuming normal operations
[Thu Dec 05 23:29:01.662578 2019] [mpm_winnt:notice] [pid 10168:tid 668] AH00456: Apache Lounge VS16 Server built: Aug  9 2019 16:46:32
[Thu Dec 05 23:29:01.662578 2019] [core:notice] [pid 10168:tid 668] AH00094: Command line: 'httpd.exe -d C:/apache/Apache24'
[Thu Dec 05 23:29:01.665949 2019] [mpm_winnt:notice] [pid 10168:tid 668] AH00418: Parent: Created child process 7372
[Thu Dec 05 23:29:02.063030 2019] [mpm_winnt:notice] [pid 7372:tid 664] AH00354: Child: Starting 64 worker threads.

기록되는 포맷의 세부 사항 및 에러 로그에 기록되는 에러 레벨 설정 등에 대해서는 다음 페이지에서 설명하도록 하겠다.

3.6.2 - Apache | 로그 파일 | 액세스 로그 포멧 (LogFormat)

액세스 로그로 저장하는 데이터는 직접 커스텀마이징하여 형식을 지정할 수 있다.

로그 형식 : LogFormat

로그 형식은 “LogFormat"으로 지정한다. 문법은 다음과 같다.

LogFormat "포맷" 로그-형식-이름

기본적으로 “httpd.conf” 파일에 작성되어 있는 로그 형식으로는 다음의 두 가지가 정의되어 있다.

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common

로그 형식 이름으로 “common"과 “combined"의 두 가지가 있다. 형식은 여러 항목의 조합에 의해 정의되었고, 설정 가능한 주요 항목은 다음과 같다.

설정값 의미
%a 액세스한 IP 주소
%A 서버 (Apache)의 IP 주소
%B 전송된 바이트 수 (헤더는 제외)
%b 전송된 바이트 수 (헤더는 제외), 0바이트인 경우는 ‘-‘이 표시된다.
%f 요청된 파일 이름
%h 원격 호스트 이름
%H 요청 프로토콜 이름
%l 클라이언트 식별자
%m 요청 메소드명
%q 요청에 포함된 쿼리 문자열, 공백 이외는 “?“가 붙는다.
%r 요청의 첫 번째 행의 값
%s 응답 상태
%>S 마지막 응답의 상태
%t 시간
%T 처리하는데 걸린 시간
%u 인증 사용자명
%U 요청의 URL 경로
%v 요청에 대한 가상 호스트 이름
%V UseCanonicalName 따른 서버명.
%X 연결 상태
%{쿠키명}C 요청에 포함된 쿠키 값
% {환경변수명}e 환경 변수명의 값
%{헤더명}i 요청에 포함된 헤더명의 값
%{헤더명}o 응답에 포함된 헤더명의 값
%{메모}n 모듈에서 반환한 메모의 값
%{포맷}t 포맷된 시간

이러한 항목을 열거하고 쌍따움표( “)로 감싸서 지정한다. 포맷 중에 쌍따움표을 작성하는 경우는 역슬레쉬(”")으로 이스케이프하여 작성한다.

항목 중에는 중괄호({})로 감싸서 작성하는 항목이 있는데, 예를 들어, “%{헤더명}i"는 헤더 중에서 헤더명에 지정한 값을 받아와서 기록한다. “%{User-Agent}i"라고 지정할 경우에는 헤더에서 “User-Agent"의 값을 기록한다.

액세스 로그 포맷 변경 테스트

기본으로 활성화되어 있는 액세스 로그는 “common"이다. 하나 더 준비어 있는 “combined"으로 변경해보도록 하자. “httpd.conf” 파일의 내용중에 다음과 같이 작성된 부분이 있다.

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    CustomLog "logs/access.log" common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    #CustomLog "logs/access.log" combined

“CustomLog logs / access.log common"앞에 “#“를 붙이고, 대신에 “CustomLog logs / access.log combined"이전 “#“을 제거한다.

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    #CustomLog "logs/access.log" common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    CustomLog "logs/access.log" combined

이것으로 액세스 로그는 “combined” 이름으로 정의된 형식으로 저장될 수 있다. Apache를 재시작한 후 Apache에 적당히 액세스 로그를 확인해 보자.

::1 - - [06/Dec/2019:00:48:42 +0900] "GET /admin/admin.html HTTP/1.1" 404 196 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
127.0.0.1 - - [06/Dec/2019:00:49:03 +0900] "GET / HTTP/1.1" 200 46 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
127.0.0.1 - - [06/Dec/2019:00:49:03 +0900] "GET /favicon.ico HTTP/1.1" 404 196 "http://127.0.0.1/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
127.0.0.1 - - [06/Dec/2019:00:49:24 +0900] "GET /phpinfo HTTP/1.1" 404 196 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
127.0.0.1 - - [06/Dec/2019:00:49:34 +0900] "GET /phpinfo.php HTTP/1.1" 200 72966 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"

위 내용이 새로운 포맷으로 기록된 로그이다. 더 자세한 정보가 기록이 된 것을 볼 수 있다.

3.6.3 - Apache | 로그 파일 | 특정 로그를 다른 파일에 기록

액세스 로그은 오직 1개의 파일에만 저장되는 것은 아니다. 로그 형식을 여러개를 정의하여 별도의 액세스 로그로 여러 파일에 저장할 수도 있다.

기본적으로 “httpd.conf” 파일에 작성되어 있는 로그 포맷에 “User-Agent"만 따로 기록하는 형식을 추가한다.

LogFormat "%{User-Agent}i" agent

그리고, 로그 파일 지정에서 새로운 “CustomLog"를 지정한다.

CustomLog logs/agent.log agent

실제 적용이 된다면 아래와 같을 것이다.

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    LogFormat "%{User-Agent}i" agent <--------------------------- 여기 추가하였다.

    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    #CustomLog "logs/access.log" common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    #CustomLog "logs/access.log" combined
		
    CustomLog logs/agent.log agent <--------------------------- 여기 추가하였다.
		
</IfModule>

이것으로 “User-Agent"만 다른 액세스 로그 파일 “agent.log"에 기록되게 되었다.

그러면 “httpd.conf” 파일을 편집한 후에 Apache를 재시작한 후 Apache에 적당히 액세스 로그를 확인해 본다.

기존 액세스 로그를 기록했던 “access.log” 파일과는 별도로 새롭게 “agent.log"라는 파일이 새로 생성되고, 파일에 액세스한 브라우저에 대한 정보만 기재되어 있는 것을 확인할 수 있다.

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363

위 로그는 “Internet Explorer”, “Edge”, “Chrome” 3개의 브라우저에서 각각 Apache에서 공개되는 HTML 파일을 열람한 경우이다.

3.6.4 - Apache | 로그 파일 | 에러 로그에 기록되는 레벨 설정 (LogLevel)

에러 로그는 어느 레벨까지의 에러를 기록할지 여부를 8단계로 지정할 수 있다. 지정하려면 “LogLevel"로 사용하여 설정한다.

LogLevel 기록하는-레벨

설정 가능한 레벨은 다음과 같다.

레벨 의미
emerg 서버가 가동 할 수 없을 정도의 심각한 오류
alert crit보다 심각한 오류
crit 치명적인 오류
error 오류
warn 경고
notice 알림 메시지
info 서버 정보
debug 디버깅을위한 정보

레벨은 위에서 부터 심각하고, “error"로 설정하면 “error” 위의 “crit”, “alert”, “emerg” 에러도 모두 기록된다.

보다 낮은 수준으로 설정하면 많은 정보를 로그로 남길 수 있지만, 그 만큼 로그 파일 크기가 커지게 되므로 필요에 따라 설정을 변경한다.

“httpd.conf” 파일에 대한 “LogLevel"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn

기본으로 LogLevel가 “warn"으로 설정되어 있다. 변경하려면 “warn"부분을 다른 수준의 값으로 변경하면 된다.

3.6.5 - Apache | 로그 파일 | 로그에 IP 주소를 호스트명으로 변환 (logresolve)

액세스 로그에 기록되는 액세스한 정보는 IP 주소로 기록된다. 기록되는 시점에 IP 주소를 호스트명으로 변환하고 기록하기 위한 설정(HostnameLookups)도 있지만, 이는 액세스할 때마다 DNS 참조가 발생하여 부하가 높아지기 때문에 일반적으로 로그에 기록된 후 호스트명으로 일괄 변환한다.

IP 주소를 호스트명으로 변환하여 다른 파일로 저장하는 유틸리티 프로그램이 Apache에서는 제공하고 있다. “{Apache 설치 디렉토리}/Apache24/bin” 디렉토리에 들어있는 “logresolve” 프로그램을 사용한다.

사용법은 다음과 같습니다.

logresolve < 대상-로그-파일

위 명령어를 실행하면 변환된 로그가 표준 출력에 표시된다. 이것을 다른 파일에 저장하는 경우에는 다음과 같이 실행한다.

logresolve < 대상-로그-파일 > 변환-로그-파일

그러면 실제로 해보도록 하자. 명령 프롬프트에서 “{Apache 설치 디렉토리}/Apache24/bin"로 이동한 다음과 같이 실행한다.

logresolve < ..\logs\access.log > ..\logs\resolve.log
C:\apache\Apache24\bin>logresolve < ..\logs\access.log > ..\logs\resolve.log

C:\apache\Apache24\bin>

그러면 로그 파일이 들어있는 디렉토리에 “resolve.log"파일이 새로 생성된. 텍스트 편집기에서 내용을 확인해 본다.

DESKTOP-XXXXXXX - - [06/Dec/2019:00:48:42 +0900] "GET /admin/admin.html HTTP/1.1" 404 196 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
DESKTOP-XXXXXXX - - [06/Dec/2019:00:49:03 +0900] "GET / HTTP/1.1" 200 46 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
DESKTOP-XXXXXXX - - [06/Dec/2019:00:49:03 +0900] "GET /favicon.ico HTTP/1.1" 404 196 "http://127.0.0.1/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
DESKTOP-XXXXXXX - - [06/Dec/2019:00:49:24 +0900] "GET /phpinfo HTTP/1.1" 404 196 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
DESKTOP-XXXXXXX - - [06/Dec/2019:00:49:34 +0900] "GET /phpinfo.php HTTP/1.1" 200 72966 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
DESKTOP-XXXXXXX - - [06/Dec/2019:00:50:34 +0900] "-" 408 - "-" "-"

IP 주소를 호스트명으로 변환되어 저장되어 있다. (테스트 환경이기 때문에 127.0.0.1이DESKTOP-XXXXXXX으로 변환되고 있다.)

3.6.6 - Apache | 로그 파일 | 로그 로테이션 (rotetalogs)

로그는 별도로 지정하지 않으면 하나의 파일에 기록을 이어간다. 따로 설정을 하게 되면 로그를 일정 기간마다 별도의 파일로 전환될 수 있게 할 수 있다. 예를 들어 하루 단위로 별도의 로그 파일로 기록하도록 하면 관리도 편해진다.

로그 로테이션 (rotetalogs)

로그를 순환하는 유틸리티 프로그램을 Apache에서는 제공하고 있다. “{Apache 설치 디렉토리}/Apache24/bin” 디렉토리에 들어있는 “rotatelogs” 프로그램을 사용한다.

사용법은 다음과 같다.

rotatelogs 대상-로그-파일 지정-시간

지정 시간은 초 단위로 로그를 분할하는 시간을 지정한다. 1 일 단위라면 “60 × 60 × 24 = 86400 “으로 지정한다.

로그 로테이션은 “httpd.conf"로 설정하여 자동으로 할 수 있다. 설정하려면 “CustomLog"에 대해 다음과 같이 설정한다.

CustomLog "| rotatelogs 대상-로그-파일 지정=시간" 로그-형식명

예를 들어 “common” 로그 포맷을 사용하여 1일 단위의 로그 회전을 설정하려면 다음과 같이 작성한다.

CustomLog logs/access.log common
CustomLog "|bin/rotatelogs.exe logs/access.log 86400" common

Windows 운영체제에선 반드시 rotatelogs 다음에 .exe 를 붙여주어야 한다.

이것으로 로그가 저장될 때 지정된 시간이 경과할 때마다 다른 로그 파일을 생성하여 기록하게 된다.

그럼 실제로 해보록 하자. 앞에서의 설정을 “httpd.conf"로 설정하고 Apache를 재시작한다. 그리고 Apache에서 공개된 파일에 액세스한다.

C:\apache\Apache24\logs>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\logs 디렉터리

2019-12-07  오전 01:40    <DIR>          .
2019-12-07  오전 01:40    <DIR>          ..
2019-12-07  오전 01:40               427 access.log
2019-12-07  오전 01:40                 0 access.log.1575590400
2019-12-07  오전 01:40               532 error.log
2019-12-07  오전 01:40                 6 httpd.pid
               4개 파일                 965 바이트
               2개 디렉터리  450,662,526,976 바이트 남음

C:\apache\Apache24\logs>

위와 같이 새로 “access.log.1575590400"라는 파일이 생성되어 로그가 저장되어 있다. 뒤에 붙어있는 “.1575590400"는 1970년 1월 1일 이후의 시간을 초단위로 표시한다.

그러면 클라이언트에 설정되어있는 날짜를 2일 진행 후 다시 Apache의 파일에 액세스해 본다.

C:\apache\Apache24\logs>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\logs 디렉터리

2019-12-09  오전 01:51    <DIR>          .
2019-12-09  오전 01:51    <DIR>          ..
2019-12-07  오전 01:40               427 access.log
2019-12-07  오전 01:41               475 access.log.1575590400
2019-12-09  오전 01:51                 0 access.log.1575763200
2019-12-07  오전 01:40               532 error.log
2019-12-07  오전 01:40                 6 httpd.pid
               5개 파일               1,440 바이트
               2개 디렉터리  450,650,722,304 바이트 남음

C:\apache\Apache24\logs>

이전 생성된 로그에서 86400 초 이상 경과하여, 새 로그 파일이 생성되고 기록이 되고 있다.

로그 파일의 형식을 지정

별로 설정을 하지 않으면 로그 파일 뒤에 1970년 1월 1일 이후의 시간을 초단위로 표시된다. 이대로는 알아 보기 어렵기 때문에 로그를 구별하기 위해 붙는 부분의 포맷을 지정할 수 있다. 예를 들어, 시간(초)가 아닌 날짜를 표시하도록 하려면 다음과 같이 작성한다.

CustomLog “| ¥"D : / Apache Group / Apache2.2 / bin / rotatelogs ¥ “¥"D : / Apache Group / Apache2.2 / logs / access.log % Y- % m- % d ¥ “86400” common

CustomLog "|bin/rotatelogs.exe logs/access.log.%Y-%m-%d 86400" common

대상 로그 파일명 뒤에 마침표(.)를 입력 후 포맷을 지정한다. 이번에는 날짜를 “-“으로 구분된 형식으로 지정하였다.

그럼 실제로 해보도록 하겠다. 위에 설정을 “httpd.conf"에 설정하고 Apache를 재시작한다. 그리고 뭔가 Apache에서 공개된 파일에 액세스한다.

C:\apache\Apache24\logs>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\Apache24\logs 디렉터리

2019-12-07  오전 02:05    <DIR>          .
2019-12-07  오전 02:05    <DIR>          ..
2019-12-07  오전 02:04               122 access.log
2019-12-07  오전 02:04               122 access.log.2019-12-06
2019-12-07  오전 02:05             1,287 error.log
               3개 파일               1,531 바이트
               2개 디렉터리  450,652,733,440 바이트 남음

C:\apache\Apache24\logs>

이번에는 지정된 형식의 형식으로 날짜가 추가되었다.

참조

3.7 - Apache | 가상 호스트(VirtualHost) 설정

1대의 서버를 사용하여 여러 도메인을 사용한 Web 서버로서의 기능을 제공하는 방법에 대해 설명한다. 서버가 여러 인터페이스를 가지고 있고 IP 주소가 여러개를 할당할 수있는 경우와 하나의 IP 주소에 호스트을 보고 배분 방법이 있다.

3.7.1 - Apache | 가상 호스트(VirtualHost) 설정 | IP 기반 가상 호스트

IP 기반 가상 호스트

IP 기반은 하나의 서버에 여러 개의 LAN 카드가 장착되어 있어, 여러 IP 주소를 있는 경우에 각각의 IP 주소에 대한 가상 호스트를 지정한다.

IP 기반 가상 호스트를 할당하려면 “VirtualHost"를 사용한다.

<VirtualHost IP주소1:포트번호>
  ...
  ...
</VirtualHost>

<VirtualHost IP주소2:포트번호>
  ...
  ...
</VirtualHost>

예를 들어, “192.168.1.1"와 “192.168.1.2” 2개의 IP 주소가 할당되어 있다면 DNS에 “ww1.devkuma.com"을 “192.168.1.1"으로 등록하고, “ww2.devkuma.com"을 “192.168.1.2"을 등록한다.

하나의 Apache에서 2개의 호스트에 대한 설정을 하려면 “httpd.conf” 혹은 “http-vhosts.conf” 파일에 다음과 같이 작성한다. (관리 측면으로 본다면 “httpd.conf” 보다는 “http-vhosts.conf"에 작성하는 것이 맞을 것이다. 상세한 내용은 “이름 기반 가상 호스트“를 참조한다.)

<VirtualHost 192.168.1.1:80>
    ServerName     ww1.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww1"
    CustomLog      logs/ww1.access.log common
    ErrorLog       logs/ww1.error.log
</VirtualHost>

<VirtualHost 192.168.1.2:80>
    ServerName     ww2.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww2"
    CustomLog      logs/ww2.access.log common
    ErrorLog       logs/ww2.error.log
</VirtualHost>

IP 주소마다 필요한 설정해야 한다. 예를 들어, “ww1.devkuma.com"에 액세스하게 되면 “192.168.1.1"에 설정된 도큐먼트 루트 “${SRVROOT}/htdocs-ww1"에 있는 내용이 반환된다.

VirtualHost마다 개별 설정을 작성할 수 있으므로 필요한 설정을 하도록 한다. 위에 작성된 것처럼 “ServerName"과 “DocumentRoot” 그리고 로그 관계는 개별적으로 설정하기를 추천한다. 물론 필수는 아니기에 공통된 설정하여도 상관은 없다.

그 외에도 각 도큐먼트 루트 액세스 권한 설정이 필요하다. “httpd.conf” 파일에서 아래와 같이 이 두 도큐먼트 루트에 적절한 권한을 설정한다.

<Directory "${SRVROOT}/htdocs-ww1">
    Require all granted
</Directory>

<Directory "${SRVROOT}/htdocs-ww2">
    Require all granted
</Directory>

실습

※ IP 기반 가상 호스트의 테스트가 가능한 환경이 없어서실제로 실습 및 확인 테스트을 못하고 작성되었다. 참고하길 바란다.

3.7.2 - Apache | 가상 호스트(VirtualHost) 설정 | 이름 기반 가상 호스트

이름 기반 가상 호스트

이름 기반의 경우 IP 주소는 한개가 아니어도 된다. 이름 기반의 경우는 클라이언트의 요청에 포함된 Hosts 헤더를 보고 어떤 호스트에 액세스할 것인지를 결정한다.

먼저 “VirtualHost"를 사용하여 ServerName마다 설정하고 있다.

<VirtualHost IP주소:포트-번호>
    ServerName www1.devkuma.com
    ....
</VirtualHost>

<VirtualHost  IP주소:포트-번호>
    ServerName www2.devkuma.com
    ....
</VirtualHost>

요청(request)에 포함된 Hosts 헤더를 참조하여 “ServerName"와 일치하는 블록을 찾는다. 일치하는 블록이 발견되면 그 블록의 설정이 적용된다.

좀 더 구체적으로 설명을 하자면, “ww1.devkuma.com"과 “ww1.devkuma.com” 두 호스트를 1개 이상의 IP 주소에 할당하고, 각각에 대한 액세스에 대해 다른 동작을 하게 하려면 다음과 같이 설정한다.

<VirtualHost *:80>
    ServerName     ww1.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww1"
    CustomLog      logs/ww1.access.log common
    ErrorLog       logs/ww1.error.log
</VirtualHost>

<VirtualHost *:80>
    ServerName     ww2.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww2"
    CustomLog      logs/ww2.access.log common
    ErrorLog       logs/ww2.error.log
</VirtualHost>

※ 위의 “*:80"이라고 지정되어 있는 부분은 “192.168.1.2:80"와 같이 명시적으로 IP 주소를 지정해도 된다.

실습

그럼 실제 실습을 해보도록 하겠다. 먼저 2개의 호스트에 대한 DNS 등록한다. 여기서는 DNS 대신에 “hosts” 파일에 다음과 같이 작성한다. (※ “hosts"파일에 대해서는 “호스트 접근 설정 (hosts 파일)“를 참조한다.)

127.0.0.1 ww1.devkuma.com
127.0.0.1 ww2.devkuma.com

다음은 “httpd.conf” 설정이다. 가상 호스트에 대한 설정은 “httpd-vhosts.conf” 파일에 작성하도록 하겠다.

먼저 “httpd-vhosts.conf” 파일을 사용합니다. “httpd.conf” 파일에서 “httpd-vhosts.conf"로 검색해 보면, 다음과 같은 내용을 찾을 수 있을 것이다.

# Virtual hosts
#Include conf/extra/httpd-vhosts.conf

“Include” 앞에 있는 ‘#‘를 제거하고 “httpd-vhosts.conf"을 읽도록 설정한다.

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

다음은 “httpd-vhosts.conf” 파일을 수정한다. “(Apache 설치 디렉토리)Apache24\conf\extra"디렉토리에 있다.

다음과 같이 샘플로 작성되어 있을 것이다. (주석은 생략한다.)

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "${SRVROOT}/docs/dummy-host.example.com"
    ServerName dummy-host.example.com
    ServerAlias www.dummy-host.example.com
    ErrorLog "logs/dummy-host.example.com-error.log"
    CustomLog "logs/dummy-host.example.com-access.log" common
</VirtualHost>

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "${SRVROOT}/docs/dummy-host2.example.com"
    ServerName dummy-host2.example.com
    ErrorLog "logs/dummy-host2.example.com-error.log"
    CustomLog "logs/dummy-host2.example.com-access.log" common
</VirtualHost>

여기서는 다음과 같이 변경한다.

<VirtualHost *:80>
    ServerName     ww1.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww1"
    CustomLog      logs/ww1.access.log common
    ErrorLog       logs/ww1.error.log
</VirtualHost>

<VirtualHost *:80>
    ServerName     ww2.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww2"
    CustomLog      logs/ww2.access.log common
    ErrorLog       logs/ww2.error.log
</VirtualHost>

※ “httpd-vhosts.conf " 파일은 “Include"에 의해 “httpd.conf “파일에 로드된다. 그러므로 위의 로그 형식명을 지정하고 있는 “common"은 “httpd.conf” 파일에 정의된 “common"형식이 사용도 된다.

또한 위에서 설정한 대로 도큐먼트 루트를 각각 생성하고, 별도의 HTML 파일을 아래와 같이 각각 작성하여 넣는다.

{Apache 설치 디렉토리}/htdocs-ww1/index.html

<html>
<body>
<h1>WW1 Page</h1>
</body>
</html>

{Apache 설치 디렉토리}/htdocs-ww2/index.html

<html>
<body>
<h1>WW2 Page</h1>
</body>
</html>

“httpd.conf” 파일에서 아래와 같이 이 두 도큐먼트 루트에 적절한 권한을 설정한다.

<Directory "${SRVROOT}/htdocs-ww1">
    Require all granted
</Directory>

<Directory "${SRVROOT}/htdocs-ww2">
    Require all granted
</Directory>

이제 준비는 완료하였다. 우선 “http://ww1.devkuma.com"에 액세스해 본다.

이름 기반 가상 호스트

“ww1.devkuma.com"용의 도큐먼트 루트에 포함된 HTML 파일이 표시된다.

다음은 “http://ww2.devkuma.com/"에 액세스해 본다.

이름 기반 가상 호스트

“ww2.devkuma.com"용의 도큐먼트 루트에 포함된 HTML 파일이 표시된다.

이것으로 하나의 IP 주소와 Apache를 사용하여 여러 도메인을 사용하여 호스트에 대해 별도의 페이지를 반환하는 방법에 대해 알아보았다.

3.7.3 - Apache | 가상 호스트(VirtualHost) 설정 | 가상 호스트 별칭 설정 (ServerAlias)

가상 호스트 별칭 설정 (ServerAlias)

이름 기반 가상 호스트의 설정이 되었을 때, 등록되지 않은 호스트명으로 액세스된 경우에 어떻게 되는 보도록 하겠다.

예를 들어, DNS (또는 hosts 파일)의 다음과 같은 작성이 되어 있다고 하자.

127.0.0.1 localhost
127.0.0.1 ww1.devkuma.com
127.0.0.1 ww2.devkuma.com

이에 대해 가상 호스트가 “ww1.devkuma.com"과 “ww2.devkuma.com"만 설정이 되어 있다고 하자.

<VirtualHost *:80>
    ServerName     ww1.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww1"
    CustomLog      logs/ww1.access.log common
    ErrorLog       logs/ww1.error.log
</VirtualHost>

<VirtualHost *:80>
    ServerName     ww2.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww2"
    CustomLog      logs/ww2.access.log common
    ErrorLog       logs/ww2.error.log
</VirtualHost>

이러한 경우에 “http://localhost"에 대한 액세스가 되면, 먼저 등록되어 있는 가상 호스트 설정인 기본값으로 적용된다.

가상 호스트 별칭 설정 (ServerAlias)

여기서는 먼저 등록된 가상 호스트 “ww1.devkuma.com"가 표시되었다.

이러한 때, 가상 호스트 설정이 되어 있지 않은 호스트에 대해 기본이 아닌 호스트의 설정을 적용할 수 있다. “ServerAlias"를 사용하여 가상 호스트 설정에 별칭으로 등록한다.

ServerAlias 호스트명1 호스트명2 ...

여러 호스트명을 등록하고자하는 경우에는 공백으로 구분 이어서 작성한다.

실습

그럼 실제 실습을 해보도록 하겠다. “http://localhost/“에 대한 액세스도 “ww2.devkuma.com “설정이 적용되도록 ww2.devkuma.com"에 ServerAlias으로 “localhost"를 등록한다.

<VirtualHost *:80>
    ServerName     ww1.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww1"
    CustomLog      logs/ww1.access.log common
    ErrorLog       logs/ww1.error.log
</VirtualHost>

<VirtualHost *:80>
    ServerName     ww2.devkuma.com
    ServerAdmin    devkuma@devkuma.com
    DocumentRoot   "${SRVROOT}/htdocs-ww2"
    CustomLog      logs/ww2.access.log common
    ErrorLog       logs/ww2.error.log
    ServerAlias    localhost
</VirtualHost>

이제 준비는 완료하였다. Apache를 재시작한 후 다시 “http://localhost/“에 액세스해 본다.

가상 호스트 별칭 설정 (ServerAlias)

이번에는 기본 설정이 아닌 별칭 설정된 “ww2.devkuma.com"가 표시되었다.

3.8 - Apache | Tomcat과 연동 (mod_proxy_ajp)

Apache와 Tomcat을 연동시키는 방법에 대해 알아 보겠다. 연동에는 “mod_proxy_ajp"를 사용한다.

3.8.1 - Apache | Tomcat과 연동 (mod_proxy_ajp) | Tomcat에 간단한 웹생성

먼저 Tomcat 단독으로 동작하도록 설정한다. 간단히 Tomcat에서 “Tomcat Page"라고만 표시하는 JSP를 Apache 통해 작동시키는 것을 목표로 한다.

이번에 만들 웹 프로그램은 “{Tomcat 설치 디렉토리}/webapps"안에 hello라는 디렉토리를 만든다,

C:\apache\apache-tomcat-9.0.29\webapps>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: XXXX-XXXX

 C:\apache\apache-tomcat-9.0.29\webapps 디렉터리

2019-12-08  오전 02:38    <DIR>          .
2019-12-08  오전 02:38    <DIR>          ..
2019-12-07  오전 02:19    <DIR>          docs
2019-12-07  오전 02:19    <DIR>          examples
2019-12-08  오전 02:40    <DIR>          hello <------------------ 새로 생성한 디렉토리이다.
2019-12-07  오전 02:19    <DIR>          host-manager
2019-12-07  오전 02:19    <DIR>          manager
2019-12-07  오전 02:19    <DIR>          ROOT
               0개 파일                   0 바이트
               8개 디렉터리  450,057,445,376 바이트 남음

C:\apache\apache-tomcat-9.0.29\webapps>

생성된 디렉토리에 “{Tomcat 설치 디렉토리}/webapps/hello/WEB-INF/web.xml” 설정 파일을 생성하여, 아래와 같이 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

그러고 화면에 표시할 “{Tomcat 설치 디렉토리}/webapps/hello/index.jsp” 파일도 생성하여, 아래와 같이 작성한다.

<html>
<body>
<h1>Tomcat Page</h1>
</body>
</html>

이제 톰켓을 기동하기 위해 “{Tomcat 설치 디렉토리}/bin/startup.bat” 명령 파일을 실행시킨다. 그러면 아래와 같이 콘솔창이 표시될 것이다.

Tomcat에 간단한 웹생성

화면이 표시되는지 브라우저에서 “http://localhost:8080/hello/“에 액세스 해본다.

Tomcat에 간단한 웹생성

위와 같이 표시되었다면 준비가 완료 되었다.

3.8.2 - Apache | Tomcat과 연동 (mod_proxy_ajp) | 8080 포트를 중지하고 AJP/1.3 프로토콜 확인

Apache를 통해 액세스로 변경하기 위해 현재 8080 포트에서 실행하고 있는 Tomcat에 직접 연결을 못하게 한다.

설정을 위해 “{Tomcat 설치 디렉토리}/conf"에 있는 “server.xml"를 텍스트 편집기로 연다. 그리고 “8080” 로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

이 부분 전체를 주석 처리하도록 한다.

<!--
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
-->

이제 8080 포트에서 Tomcat에 연결하려고 하면 연결할 수 없게 되었다.

설정이 완료되면 Tomcat을 다시 시작하여 “http:// localhost:8080/hello/helloworld"브라우저에서 액세스 해본다.

8080 포트 중지

그러고"server.xml"파일에 다음과 같은 내용이 있는지 검색한다. “AJP"로 검색하면 나올 것이다.

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Apache에서 Tomcat에 연결을 “AJP/1.3"라고 프로토콜을 사용하여 8009 포트로 접속하게 될 것이다.

3.8.3 - Apache | Tomcat과 연동 (mod_proxy_ajp) | Apache 설정 (mod_proxy_ajp을 사용하여 연결)

이제 Apache 설정만 하면 된다. 연동을 하기 위해서는 “mod_proxy_ajp"을 사용하므로 먼저 ‘mod_proxy’과 ‘mod_proxy_ajp “모듈을 로드하도록 변경합니다.

“httpd.conf"파일에서 “mod_proxy_ajp"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

주석 처리가 되어 있다면 앞에 “#“를 제거합한다.

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

이로써 ‘mod_proxy’과 ‘mod_proxy_ajp “모듈이 로드되도록 변경되었다.

다음 톰켓에 대한 요청이 있을 경우 설정한다. “http://localhost/hello/“로 시작하는 URL으로 액세스가 되면 Tomcat의 파일을 호출하도록 할 것이다. 그러기 위해 먼저 섹션 컨테이너로 “Location"을 사용하여 다음과 같이 작성한다.

<Location /hello/>

</Location>

※ 섹션 컨테이너에 대해서는 “접근 허용 범위 설정 (섹션 컨테이너)“를 참조한다.

Tomcat에 액세스를 하도록 하는 설정을 <Location> 안에 작성한다. Tomcat는 AJP/1.3 프로토콜으로 8009 포트를 사용하여 연결을 하기에 다음과 같이 작성한다.

<Location /hello/>
    ProxyPass ajp://localhost:8009/hello/
</Location>

이것으로 “httpd.conf” 파일에 작성하면 완료되었다.

mod_proxy_ajp을 사용하여 연결

위와 같이 표시되면 Apache 통한 Tomcat 호출을 성공하였다.

3.9 - Apache | Apache 서버 관리 (mod_status)

Apache의 작동 상황과 설정에 대한 정보를 클라이언트 측에서 보는 등의 Apache 서버 관리에 대해 설명한다.

3.9.1 - Apache | Apache 서버 관리 (mod_status) | 작동 상태 확인 (server-status)

Apache에서는 “mod_status” 모듈에 “server-status"라는 핸들러를 제공한다. (핸들러는 있는 동작을 시키는 함수 같은 것이다. 프로그램의 모임이라고 생각하면 된다.)

“server-status” 핸들러를 호출하여 Apache의 동작 상황을 확인할 수 있다. 그럼 브라우저에서 “server-status” 핸들러를 호출하여 동작 상황을 볼 수 있도록 해보자.

mod_status 모듈 로드

먼저 “mod_status"모듈을 이용할 수 있도록 “LoadModule"에서 모듈을 로드한다. “httpd.conf” 파일에서 “mod_status"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

#LoadModule status_module modules/mod_status.so

“LoadModule” 앞부분에 “#“이 있다면 “#“을 제거한다.

LoadModule status_module modules/mod_status.so

다음은 “server-status” 핸들러를 호출하는 설정을 한다. “Include"을 사용하여 “httpd-info.conf” 파일을 로드한다. “httpd.conf” 파일에서 “httpd-info.conf"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf

“Include” 앞부분에 “#“이 있다면 “#“을 제거한다.

# Real-time info on requests and configuration
Include conf/extra/httpd-info.conf

httpd-info.conf 파일 확인

다음은 “httpd-info.conf” 파일에서 “/server-status"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

<Location /server-status>
    SetHandler server-status
    Require host .example.com
    Require ip 127
</Location>

“Location"을 사용하여 URL 경로를 “/server-status"으로 설정되었고, “/ server-status” 라고 URL 경로로 호출 할때 “server-status” 핸들러를 호출하여 실행 설정을 “SetHandler"가 지정되어 있다.

이와 같이 작성되면 브라우저에서 “http://localhost/server-status"라고 요청하게 되면 “server-status” 핸들러를 실행하고 결과를 돌려준다. 또한 서버의 작동 상황은 누구에게나 공개하는 것은 아니다. 그래서 로컬 호스트에서만 액세스를 허용한다.

실행 확인

로컬에서 “http://127.0.0.1/server-status"에 액세스하십시오.

server-status

이 처럼 URL에 접근할 수 있다면 위와 같이 Apache의 작동 상태를 모니터링 할 수 있다.

지정된 시간에 자동 업데이트

로컬 호스트에서 접속할 때 URL에 페라미터로 “?refresh=초"와 같이 넣으면, 지정한 초마다 최신 정보를 다시 받아오게 된다.

그럼 5초 단위로 자동 업데이트하도록 “http://127.0.0.1/server-status?refresh=5"라고 URL 입력한다.

server-status

위와 같이 5초 단위로 자동으로 최신의 정보를 얻을 다시 받아와 표시하는 것을 확인할 수 있다.

3.9.2 - Apache | Apache 서버 관리 (mod_status) | 확장 상태 표시 (ExtendedStatus)

“server-status” 핸들러를 실행할 때 “ExtendedStatus"에 “On"을 설정하면, 현재 처리하고 있는 URL 및 자원에 대한 정보도 함께 확인할 수 있다.

“httpd-info.conf” 파일에서 “ExtendedStatus"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

#
# ExtendedStatus controls whether Apache will generate "full" status
# information (ExtendedStatus On) or just basic information (ExtendedStatus
# Off) when the "server-status" handler is called. The default is Off.
#
#ExtendedStatus On

기본으로 Off라고 설명이 되어 있다. “ExtendedStatus On"의 “#“을 제거하여 확장 상태를 “On"으로 설정하면 상세 접보를 확인 할 수 있게 된다.

그럼 “On"으로 설정하겨 “http://localhost/server-status"에 액세스한다.

ExtendedStatus

화면의 맨 마지막보다 자세한 정보가 표시된 것을 볼 수 있다.

3.9.3 - Apache | Apache 서버 관리 (mod_status) | 설정 정보 확인 (server-info)

Apache에서는 “mod_info"모듈 “server-info"라고 핸들러가 제공된다.

“server-info” 핸들러를 호출하여 Apache 구성 정보을 확인할 수 있다. 그럼 브라우저에서 “server-info” 핸들러를 호출하여 동작 상황을 볼 수 있도록 해보자.

mod_info 모듈 로드

먼저 “mod_info"모듈을 이용할 수 있도록 “LoadModule"에서 모듈을 로드한다. “httpd.conf” 파일에서 “mod_info"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

#LoadModule info_module modules/mod_info.so

“LoadModule” 앞부분에 “#“이 있다면 “#“을 제거한다.

LoadModule info_module modules/mod_info.so

다음은 “server-info"핸들러를 호출 설정을 한다. “Include"을 사용하여 “httpd-info.conf"파일을 로드한다. “httpd.conf"파일에서 “httpd-info.conf"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf

“Include” 앞부분에 “#“이 있다면 “#“을 제거한다.

# Real-time info on requests and configuration
Include conf/extra/httpd-info.conf

httpd-info.conf 파일 확인

다음은 “httpd-info.conf” 파일에서 “/server-info"로 검색하면, 다음과 같은 내용을 찾을 수 있을 것이다.

<Location /server-info>
    SetHandler server-info
    Require host .example.com
    Require ip 127
</Location>

“Location"을 사용하여 URL 경로를 “/server-info"로 설정되었고, “/ server-info” 라고 URL 경로로 호출 하면 “server-info” 핸들러를 호출되어 실행되도록 “SetHandler” 설정이 되어 있다.

이와 같이 작성되면 브라우저에서 “http://localhost/server-info"라고 요청하게 되면 “server-info” 핸들러를 실행하고 결과를 돌려준다. 또한 서버의 작동 상황은 누구에게나 공개하는 것은 아니기에 로컬 호스트에서만 액세스를 허용된다.

실행 확인

로컬에서 브라우저로 “http://127.0.0.1/server-info"에 액세스한다.

server-info

정상적으로 액세스가 되었다면, 위와 같이 Apache의 각종 설정 정보에 대한 링크가 화면에 표시된다. 각 링크를 클릭하시면 자세한 정보가 표시된다.

server-info

server-info

4 - Tomcat 사용법

톰켓에 대한 설명

4.1 - Tomcat 사용법 | Web 폴더 접근하여 파일 목록 보기 설정

웹 화면에서 폴더에 접근하여 파일 목록을 확인하는 설정 방법에 대해 설명한다.

디폴트 설정인 경우에는 브라우저에서 URL 폴더에 직접 접근을 하게 되면 아래와 같이 404 에러가 나오면서 접근할 수 없다.

Tomcat의 DefaultServlet은 기본적으로 디렉토리 목록을 표시하지 않도록 구성됩니다. Tomcat의 {Tomcat 설치 폴더}/conf/web.xml 파일을 열어, DefaultServlet의 <servlet> 요소를 찾는다.

... 생략 ...
    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
... 생략 ...

여기서 페라미터 listings의 값을 아래와 같이 true로 변경한다.

변경전 : 목록 표시 안한다.

        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>

변경 후 : 목록 표시 한다.

        <init-param>
            <param-name>listings</param-name>
            <param-value>true</param-value>
        </init-param>

목록 표시를 하도록 변경을 하게 되면, 아래와 같이 폴더에 직접 접근을 할 수 있게 된다.

4.2 - Tomcat 사용법 | URL Encoding 설정

tomcat 문서에 의하면 URL을 디코딩은 지정하지 않으면 디폴트로 ISO-8859-1으로 지정된다. 그러기에 설정을 하지 않고 한글을 GET로 정보를 넘기게 되면 깨진다. 반면에 POST로 전달되면 HTTP body의 입력 스트림의 디폴트는 UTF-8를 디코딩되기에 문제가 없다.

이는 tomcat 설정에 엔코딩을 변경해 주면 문제는 해결된다. {tomcat 설치 폴더}/conf/server.xml에 아래 <Connector> 요소에 아래와 같이 URIEncoding을 UTF-8로 설정한다.

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" 
           URIEncoding="UTF-8" />

아파치와 연결하기 위해 mod_jk를 사용할 경우에는 mod_jk 설정부분에도 위와 동일하게 변경한다.

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>

참조

https://tomcat.apache.org/tomcat-9.0-doc/config/http.html

4.3 - Tomcat 사용법 | 특정 IP 접근 제한

Tomcat에서는 특정 IP의 접근을 허용 및 제한하는 옵션을 제공한다.

Tomcat의 설정 파일인 conf/server.xml에서 <Host></Host> 사이에 아래 내용을 추가 및 변경하고 재시작 하면된다.

특정 IP 접근 허용 allow

<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127.0.0.1, 192.168.0.1"/>

특정 IP 접근 제한 deny

<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="192.168.0.1"/> 

http://tomcat.apache.org/tomcat-9.0-doc/config/valve.html

4.4 - Tomcat 사용법 | 톰켓 기동 및 중지

Tomcat 중지

프롬프트에 아래와 같이 입력하면 Tomcat 이 중지된다.

$ ./tomcat/bin/shutdown.sh

Tomcat 시작

프롬프트에 아래와 같이 입력하면 Tomcat이 시작된다.

$./tomcat/bin/startup.sh

Tomcat 시작 확인

톰캣 시작 후 톰캣이 정상적으로 구동되었는지 확인하려면 아래와 같이 입력을 한다.

$ tail tomcat/logs/catalina.out

위 명령어 입력 시, catalina.out 파일의 내용이 화면상에 출력된다. 해당 내용의 가장 마지막 줄에 다음과 같은 문구를 확인한다.

23-Mar-2019 01:17:16.985 정보 [main] org.apache.catalina.startup.Catalina.start Server startup in 8176 ms

4.5 - Tomcat 사용법 | http에서 https로 자동 리다이렉트 설정하기

Tomcat에서 http로 접근을 하게 되었을 때 https로 변경되는 방법에 대해서 설명한다.

server.xml에 SSL설정한다.

Tomcat 의 tomcat/conf/server.xml 파일에 https 설정을 443 포트로 설정하고, 추가로 http 설정을 80 포트로 설정한다.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<server>
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

... 중간 생략...

<Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="443" />

<Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"
           keystoreFile="{keystoreFile}" keystorePass="{keystorePass}" />

<Connector port="8009" protocol="AJP/1.3" redirectPort="443" />

... 중간 생략...

</server>

web.xml에 리다이렉트 설정 추가한다.

web.xml 파일에 아래 <security-constraint> 설정을 추가한다. 그리고 Tomcat 을 재시작하고, http로 접근을 하게 되면 https로 리다이렉트 되는 것을 확인할 수 있을 것이다.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">

    ... 중간 생략...

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>HTTP</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

</web>

web.xml 파일에 <security-constraint> 태그는 여러번 나올 수 있다. Tomcat 에서 보안 목적으로 특정 HTTP Method 를 제한이나 특정 URL만 설정하는 등도 <security-constraint> 를 사용한다.

4.6 - Tomcat의 관리 및 모니터링 도구 Probe

Probe에 대해서

Probe는 Tomcat의 관리 및 모니터링 기능을 하는 도구이다. 어플리케이션 상태, 데이터 소스, 배포, 시스템, 연결 등 다양한 기능을 제공한다.

(이런 도구가 있다는 것을 필자는 이번에 처음 알게 되었고, 궁금해서 더 조사해 보기로 하였다.)

Probe에 대한 자료

Probe 자료는 잘 사용되지 않고 있어서 그런지 인터넷 검색을 하여도 잘 나오지 않았다. 겨우겨우 찾아 낸 사이트가 github 였다.

Probe 설치해 보기

여기에 나온 내용으로 Probe 설치 테스트를 할 수 있었다. 설치 방법은 아래와 같다.

  1. Probe 소스 파일을 아래와 같이 git clone 명령으로 내려 받는다.
git clone https://github.com/psi-probe/psi-probe.git

명령어를 실행하면 아래와 같다.

kimkc@kimkcui-MacBookPro probe % git clone https://github.com/psi-probe/psi-probe.git
Cloning into 'psi-probe'...
remote: Enumerating objects: 54626, done.
remote: Counting objects: 100% (1030/1030), done.
remote: Compressing objects: 100% (499/499), done.
remote: Total 54626 (delta 564), reused 927 (delta 498), pack-reused 53596
Receiving objects: 100% (54626/54626), 33.42 MiB | 10.71 MiB/s, done.
Resolving deltas: 100% (38049/38049), done.
kimkc@kimkcui-MacBookPro probe %
  1. probe 프로젝트를 아래와 같이 maven 빌드를 실행한다.
mvn package

빌드를 진행하면 아래와 표시된다.

kimkc@kimkcui-MacBookPro psi-probe % mvn package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] psi-probe                                                          [pom]
[INFO] psi-probe-core                                                     [jar]
[INFO] psi-probe-rest                                                     [jar]
[INFO] psi-probe-tomcat7                                                  [jar]
[INFO] psi-probe-tomcat85                                                 [jar]
[INFO] psi-probe-tomcat9                                                  [jar]
[INFO] psi-probe-web                                                      [war]
[INFO] 

(중간 생략)

[INFO] Reactor Summary for psi-probe 3.5.5-SNAPSHOT:
[INFO] 
[INFO] psi-probe .......................................... SUCCESS [  1.573 s]
[INFO] psi-probe-core ..................................... SUCCESS [ 20.977 s]
[INFO] psi-probe-rest ..................................... SUCCESS [  1.375 s]
[INFO] psi-probe-tomcat7 .................................. SUCCESS [  4.093 s]
[INFO] psi-probe-tomcat85 ................................. SUCCESS [  3.823 s]
[INFO] psi-probe-tomcat9 .................................. SUCCESS [  3.801 s]
[INFO] psi-probe-web ...................................... SUCCESS [  4.559 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  40.441 s
[INFO] Finished at: 2021-06-30T16:11:58+09:00
[INFO] ------------------------------------------------------------------------
kimkc@kimkcui-MacBookPro psi-probe %

위와 같이 모든 프로젝트가 “SUCCESS"라고 표시가 된다면 제대로 완료된 거다.

  1. tomcat 사이트에서 다운 받아서, 적당한 디렉토리에 파일 압축을 푼다.

여기서는 tar.gz 파일 다운 받아서 아래 명령어로 압축을 풀었다.

tar -xvf apache-tomcat-8.5.68.tar.gz
kimkc@kimkcui-MacBookPro probe % tar -xvf apache-tomcat-8.5.68.tar.gz
x apache-tomcat-8.5.68/conf/
x apache-tomcat-8.5.68/conf/catalina.policy
x apache-tomcat-8.5.68/conf/catalina.properties
x apache-tomcat-8.5.68/conf/context.xml
x apache-tomcat-8.5.68/conf/jaspic-providers.xml

압축이 모두 풀리면 파일 내용을 확인 한다.

kimkc@kimkcui-MacBookPro apache-tomcat-8.5.68 % cd /Users/kimkc/dev/probe/apache-tomcat-8.5.68 
kimkc@kimkcui-MacBookPro apache-tomcat-8.5.68 % ls
BUILDING.txt    LICENSE         README.md       RUNNING.txt     conf            logs            webapps
CONTRIBUTING.md NOTICE          RELEASE-NOTES   bin             lib             temp            work
kimkc@kimkcui-MacBookPro apache-tomcat-8.5.68 %
  1. 이제 {tomcat 디렉토리}/webapps에 probe로 빌드한 war 파일을 넣는다.

probe war 파일은 아래 디렉토리에 위치한다.

{probe 소스 코드디렉토리}/psi-probe-web/target/probe.war

war파일을 톰켓 webapps에 넣는다.

kimkc@kimkcui-MacBookPro psi-probe % cp ./psi-probe-web/target/probe.war ../apache-tomcat-8.5.68/webapps
  1. 마지작으로 톰켓 사용자 정보파일(apache-tomcat-x.x.x/conf/tomcat-users.xml)에서 role 정보를 아래와 같이 추가한다.
(생략)
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
(중간 생략)

  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-status"/>
  <user username="devkuma" password="1234" roles="manager-gui,manager-script,manager-status"/>

</tomcat-users>

이 tomcat의 probe 계정은 사용자명 “devkuma"이고 비밀번호가 “1234"이 된다.

위 정보를 넣지 않으면 probe 웹에 접근할 수 없게 된다.

  1. 이제 톰켓을 재기동한다.
kimkc@kimkcui-MacBookPro bin % ./startup.sh 
Using CATALINA_BASE:   /Users/kimkc/dev/probe/apache-tomcat-8.5.68
Using CATALINA_HOME:   /Users/kimkc/dev/probe/apache-tomcat-8.5.68
Using CATALINA_TMPDIR: /Users/kimkc/dev/probe/apache-tomcat-8.5.68/temp
Using JRE_HOME:        /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
Using CLASSPATH:       /Users/kimkc/dev/probe/apache-tomcat-8.5.68/bin/bootstrap.jar:/Users/kimkc/dev/probe/apache-tomcat-8.5.68/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
kimkc@kimkcui-MacBookPro bin %

아래 링크로 들어가봐서 화면이 열리면 제대로 설치된 것이다.

http://localhost:8080/probe/

Probe를 통해서 웹어플리케이션(.war) 파일을 배포하기

  1. 아래 위치에 이동한다.
http://10.10.100.158:8080/probe/adm/deploy.htm
  1. Select a .war file to upload *에 웹 서비스 war 파일을 선택한다.

  2. Context name (ex. /dummy)을 넣는다.

  3. “Deploy” 버튼을 클릭한다.

  4. 위에 입력한 대로 서비스 실행되는지 확인한다. Context name/dummy로 넣었다면 웹 주소는 아래와 같게 된다.

http://10.10.100.158:8080/dummy

주의: Probe로 통해서 배포를 하게 되면 Tomcat 자체가 재시작되지 않고, 웹어플케이션 war 파일만 교체해 주어서 웹 서비스가 다시 올라가게 된다. 이 과정에 서비스에 잠시 멈춤 현상이 발상하게 되기에 무중단 배포라고 볼수 없다. 어째듯, 간단히 테스트로써 배포 기능을 사용하는 것은 괜찮을 지라도 이를 이용해서 실제 서비스를 배포해서는 안된다.

5 - 그밖에

5.1 - Web | Forward와 Redirect 차이

Forward 방식

  • Forward는 Web Container 차원에서 페이지의 이동만 존재한다. 실제로 웹 브라우저는 다른 페이지로 이동했음을 알 수 없다. 그렇기 때문에 웹 브라우저에는 최초에 호출한 URL이 표시되고, 이동한 페이지의 URL 정보는 확인할 수 없다.
  • 현재 실행중인 페이지와 forward에 의해 호출될 페이지는 Request 객체와 Response 객체를 공유한다. ㅇㅇㅇㅇ Forward 방식

Servlet에서 JSP로 페이지 이동할 때 사용되는 명령문

RequestDispatcher rd = request.getRequestDispatcher("test01.jsp");
rd.forward(request, response);

Redirect 방식

  • Redirect는 Web Container로 명령이 들어오면, 웹 브라우저에게 다른 페이지로 이동하라고 명령을 내린다. 그러면 웹 브라우저는 URL을 지시된 주소로 바꾸고 해당 주소로 이동한다. 다른 웹 컨테이너에 있는 주소로 이동한다.
  • 새로운 페이지에서는 Request와 Response 객체가 새롭게 생성된다.

Redirect 방식

Servlet에서 JSP로 페이지 이동할 때 사용되는 명령문

response.sendRedirect("test02.jsp");

출처

5.2 - Pinpoint agent 설치

pinpoint-agent 설치

agent 설치

$ wget https://github.com/pinpoint-apm/pinpoint/releases/download/v2.2.0/pinpoint-agent-2.2.0.tar.gz

최신 버전은 여기를 참고하면 된다.

압축해제

$ tar xvfz pinpoint-agent-2.2.0.tar.gz

properties 설정

$ vim ./pinpoint-agent-2.2.0/profiles/release/pinpoint.config
profiler.transport.grpc.collector.ip=[서버 ip 설정]
profiler.collector.ip=[서버 ip 설정]

pinpoint-agent 실행

WAS가 jar로 되어 있는 경우

자바 실행시에 아래 옵션을 추가한다.

-javaagent:${pinpointPath}/pinpoint-bootstrap-1.8.4.jar 
-Dpinpoint.applicationName=[고유값] 
-Dpinpoint.agentId=[핀포인트내에서 보여질 이름]

옵션츨 추가한 예이다

java -jar 
-javaagent:/home/ec2-user/pinpoint/pinpoint-agent/pinpoint-bootstrap-1.8.4.jar 
-Dpinpoint.agentId=hello
-Dpinpoint.applicationName=helloWeb
-Dspring.profiles.active=real 
/home/ec2-user/hello-0.0.1-SNAPSHOT.jar 

WAS가 tomcat으로 되어 있는 경우

./tomcat/bin/catalina.sh 파일을 아래와 같은 내용을 위 부분에 추가한다.

AGENT_PATH="/usr/local/pinpoint-agent-2.2.0"
CATALINA_OPTS="$CATALINA_OPTS -javaagent:$AGENT_PATH/pinpoint-bootstrap.jar"
CATALINA_OPTS="$CATALINA_OPTS -Dpinpoint.agentId=hello" # 고유 ID
CATALINA_OPTS="$CATALINA_OPTS -Dpinpoint.applicationName=helloWeb" # 그룹 ID

내용을 추가 후에 tomcat을 재기동한다.

$ ./shutdown.sh
$ ./startup.sh

참조

5.3 - Nginx

Nginx는?

Nginx는 Igor Sysoev라는 러시아 개발자가 개발한 무료 오픈 소스 web 서버이다.

Apache의 대안으로 제안 된 web 서버 소프트웨어이다. Apache는 동시 다수 연결시의 처리에 약한 문제점이 있었다. (클라이언트 1만대일 경우 문제 발생) 그래서 높은 부하에 강한 web 서버 소프트웨어로 개발 된 것이 Nginx이다.

Web 서버는?

외부에서 들어오는 요청을 받아 Web 서버에서 정적 컨텐츠을 응답하고, 응용 프로그램 서버에 동적 콘텐츠 요청하면 응용 프로그램 서버의 처리 결과를 클라이언트에 응답한다.

이 Web 서버에 해당하는 것이 Nginx이다.

Apache와 Nginx의 차이점

Nginx와 자주 인용 나오는 것이 Apache이다. Apache는 대표적인 web 서버이다. Nginx는 원래, Apache는 일반적인 Web 서버가 지닌 동시 대량 액세스에 대한 응답이 나빠지는 문제를 해결하는 위해 태어난 것이 라든지. . .

주요 차이점

Apache의 특징

  • Web 서버로서의 기능이 풍부하고 쓰기가 좋다.
  • 다양한 만큼, 서버 비용은 높다.

Nginx의 특징

  • Web 서버와의 중개가 되어 요청에 응답을 하는 리버스 프록시 프로그램 기능이 있고, 동시 요청의 처리에 특화되어 있다.
  • non-blocking I/O를 지원하여 대량의 데이터 전송과 대량 동시 접속에 특화되어 있다.
  • 단순하기 때문에 서버 비용이 저렴하다.
  • 장점으로는 Web 서버의 존재를 숨길 수 있고, Web 서버가 여러 개가 있는 경우에는 처리를 분산 할 수 있다. 즉, 로드 밸런서와 같은 기능을 해준다. 이는 동시 다수 요청에 강한 특징을 가지게 된다.

Apache와 Nginx의 구동 방식

Apache는 멀티 프로세스의 프로세스 중심 아키텍처

  • 각 요청을 프로세스에 할당 처리를 위한 요청이 대량으로 올 때 프로세스가 동시에 시작하기 때문에 오버 헤드(부하 처리)가 매우 커진다는 단점이 있다.

Nginx는 단일 스레드 모델의 이벤트 기반 아키텍처

  • Node.js와 같이 이벤트 루프 방식 (단일 스레드에서 루프를 돌려 큐에 쌓인 이벤트를 처리해 나가는 처리 방식)
  • 이벤트 루프 방식을 채용하는 것으로, 소량의 프로세스만으로 대량의 요청을 처리 할 수 있다.
  • 그러면 C10K 문제를 해결할 수 있다

Nginx 설치

Mac에서 설치

brew 명령어를 이용하여 설치한다.

% brew install nginx

아래 명령어를 실행하고, http://localhost:8080에 접속해 본다.

% nginx

아래 명령어로 중지한다.

% nginx -s stop

설정 파일을 아래에 존재한다.

/usr/local/etc/nginx/nginx.conf

CentOS에서 설치

/etc/yum.repos.d/nginx.repo을 작성한다.

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1

yum 명령어로 설치한다.

$ sudo yum install nginx

Nginx 명령어

시작

nginx

정지

CentOS 6, Amazon Linux

nginx -s stop

CentOS 7, Amazon Linux 2

systemctl stop nginx

재시작

CentOS 6, Amazon Linux

/etc/init.d/nginx restart

CentOS 7, Amazon Linux 2

systemctl restart nginx

스타트업 등록

CentOS 7, Amazon Linux 2

systemctl enable nginx #등록
systemctl disable nginx #삭제

설정 다시로드

CentOS 6, Amazon Linux

nginx reload
service nginx reload

CentOS7, Amazon Linux 2

systemctl reload nginx

설정 파일 체크

nginx -t

설정 파일 위치

주 설정 파일

cd /etc/nginx/

각 서버 설정 파일

cd /etc/nginx/conf.d/

5.4 - robots.txt

원래 검색 엔진의 작동 방식

  • 인터넷 검색엔진 배제 표준(Robots Exclusion Protocol) 이다.
  • 크롤러라는 로봇이 인터넷을 순회하면서 사이트의 정보를 수집한다.
  • 인덱서는 크롤러가 수집 한 정보를 분석한다.
  • 분석된 데이터를 기반으로 검색 엔진당 알고리즘에 따라 검색 결과를 반환한다.

robots.txt이란?

  • robots.txt는 크롤러에게 ‘크롤링 할 페이지’ 또는 ‘크롤링하지 않으려는 페이지’를 알려주는 텍스트 파일이다.
  • 그 도메인의 최상위 디렉토리에 공개된다.
  • robots.txt은 아직 권고안이라 꼭 지킬 의무는 없다.

robots.txt 형식

  • User-agent: 검색봇 이름
  • Allow : 접근 허가 설정 (구글봇에만 적용 가능)
  • Disallow: 접근 차단 설정
  • Crawl-delay: 다음 방문까지의 디레이(초)
  • Sitemap : 사이트 맵 지정

robots.txt 사용 예제

모든 검색봇에 모든 문서에 대해 접근을 허가

User-agent: *
Allow: /

‘*’(와일드카드)는 모든 로봇을 뜻하며, ‘/‘슬래시는 모든 디렉토리를 뜻한다.

모든 검색봇에 모든 문서에 대해 접근을 차단

User-agent: *
Disallow: /

특정 디렉토리의 접근을 허가

User-agent: Googlebot
Allow: /foo/bar/

특정 디렉토리의 접근을 차단

User-agent: Googlebot
Disallow: /foo/bar/

구글봇(Googlebot)만 허용하고 나머지는 모두 차단

User-agent: Googlebot
Allow: /

User-agent: *
Disallow: /

홈페이지의 디렉토리의 일부만 검색엔진에 노출

 User-agent: * 
 Disallow: /conection/ 
 Disallow: /my_conection/ 

홈페이지의 디렉토리의 일부만 검색엔진에 노출 차단

User-agent: *
Disallow: /my_page/

사이트 부하(퍼포먼스)의 관점

크롤러 순회로 인해 사이트 부하가 증가하는 경우 robots.txt에서 중요하지 않은 대량의 콘텐츠를 크롤러 순회에서 제거하여 사이트 부하를 줄이고, 중요한 콘텐츠에 대한 순회 효율을 향상시킬 수 있다.

그러면, 중요한 콘텐츠와 중요하지 않은 콘텐츠를 구별하는 것으로, SEO와 사이트 부하 측면으로도 좋을 것이다.

여기에서 중요하지 않은 콘텐츠를 살펴보면,

  • 검색엔진에 색인하지 않아도 되는 페이지
  • 가치가 낮은 콘텐츠 페이지
  • 동일한 콘텐츠의 여러 페이지
  • 사이트에 넣은 광고의 방문 페이지
  • 제한된 사람에게만 공개하고 싶은 페이지
  • 관리 시스템 파일

등이 될것이다.

보안 관점

robots.txt에 “크롤링하고 싶은 페이지” 또는 “크롤링하지 않으려는 페이지"를 설정하게 되면 제한된 사람에게만 공개하고 싶은 콘텐츠가 보여질 수 있다.

이는 robots.txt에 “관리 시스템 파일” 또는 “제한된 사람에게만 공개하고 싶은 페이지"를 설정하면 검색 엔진 검색 결과에 나타나지 않지만 robots.txt에는 공개 되고 있으므로, robots.txt에서 직접 보여지게 된다. 즉, “관리에 관한 파일"이나 “한정된 사람에게 밖에 공개하고 싶지 않은 페이지"를 알려질 수 있다는 것이다.

robots.txt로 설정하게 되면, 검색엔진의 검색결과에 표시되는 보안위험은 완화될 수 있지만, robots.txt에서 보안에 중요한 콘텐츠를 알리게 되면 보안 위험이 발생한다.

그래서, “보안적으로 중요한 관리에 관한 파일"이나 “특정의 한정된 사람에게 밖에 공개하고 싶은 페이지"는 로그인 인증이나 IP 주소 제한 등, 확실히 액세스 제한을 마련할 필요하다.

참조