3.4.2 실습 환경 세팅 및 소스코드 분석
실습으로 진행할 HTTP 웹 서버는 로컬 개발 환경을 세팅한 https://github.com/slipp/web-application-server 저장소의 master 브랜치에서 시작하면 된다. webserver.WebServer를 실행한 후 브라우저에서 http://localhost:8080 으로 접근했을 때 "Hello World" 메시지가 출력되면 실습할 수 있는 준비가 끝났다.
실습으로 진행할 HTTP 웹 서버의 핵심이 되는 코드는 webserver 패키지의 WebServer와 RequestHandler 클래스이다. WebServer 클래스는 웹 서버를 시작하고, 사용자의 요청이 있을 때까지 대기 상태에 있다가 사용자의 요청이 있을 경우 요청을 RequestHandler 클래스에 위임하는 역할을 한다.
- WebServer.java
package webserver;
import java.net.ServerSocket;
import java.net.Socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class WebServer {
private static final Logger log = LoggerFactory.getLogger(WebServer.class);
private static final int DEFAULT_PORT = 8080;
public static void main(String args[]) throws Exception {
int port = 0;
if (args == null || args.length == 0) {
port = DEFAULT_PORT;
} else {
port = Integer.parseInt(args[0]);
}
// 서버소켓을 생성한다. 웹서버는 기본적으로 8080번 포트를 사용한다.
try (ServerSocket listenSocket = new ServerSocket(port)) {
log.info("Web Application Server started {} port.", port);
// 클라이언트가 연결될때까지 대기한다.
Socket connection;
while ((connection = listenSocket.accept()) != null) {
RequestHandler requestHandler = new RequestHandler(connection);
requestHandler.start();
}
}
}
}
사용자 요청이 발생할 때까지 대기 상태에 있도록 지원하는 역할은 자바에 포함되어 있는 ServerSocket 클래스가 담당한다. WebServer 클래스는 ServerSocket에 사용자 요청이 발생하는 순간 클라이언트와 연결을 담당하는 Socket을 RequestHandler 에 전달하면서 새로운 스레드를 실행하는 방식으로 멀티스레드 프로그래밍을 지원하고 있다.
RequestHandler 클래스는 Thread를 상속하고 있으며, 사용자의 요청에 대한 처리와 응답에 대한 처리를 담당하는 가장 중심이 되는 클래스다.
- RequestHandler.java
package webserver;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RequestHandler extends Thread {
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);
private Socket connection;
public RequestHandler(Socket connectionSocket) {
this.connection = connectionSocket;
}
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
DataOutputStream dos = new DataOutputStream(out);
byte[] body = "Hello World".getBytes();
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n");
dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void responseBody(DataOutputStream dos, byte[] body) {
try {
dos.write(body, 0, body.length);
dos.flush();
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
앞으로 진행할 모든 실습은 RequestHandler 클래스의 run() 메서드에서 구현할 수 있다. 단, run() 메서드의 복잡도가 증가하는 경우 새로운 클래스, 메서드로 분리하는 방식으로 리팩토링을 하면서 실습을 진행하면 된다. run() 메서드에서 InputStream은 클라이언트(웹 브라우저)에서 서버로 요청을 보낼 때 전달되는 데이터, OutputStream은 서버에서 클라이언트에 응답을 보낼 때 전달되는 데이터를 담당하는 스트림이다. 스트림을 이해할 때 웹 서버 입장에서 입력되는 데이터( InputStream)와 출력되는 데이터(OutputStream)를 이해하면 좀 더 쉽게 이해할 수 있다.
프로그래밍을 할 때 좋은 습관 중의 하나는 프로그래밍 실행 중 발생하는 로그 메시지를 주의 깊게 살펴보는 것이다. 로그 메시지는 프로그래밍이 정상적으로 실행되고 있는지의 여부를 판단할 수 있는 정보를 제공해 준다. 이번 실습을 하면서도 로그로 출력되는 메시지를 눈여겨 본다. 로그 메시지를 통해 새로운 지식을 학습할 수 있는 기회도 된다. 로그 메시지를 적절하게 출력하도록 구현하는 것 또한 연습이 필요한 부분이다. 이 실습을 진행하면서 로그 메시지를 출력하는 연습도 같이 할 수 있다.
참고링크1 : https://kadosholy.tistory.com/121
[Java] 자바 - Thread란? 스레드 개념 및 사용방법
자바 - Thread란? 스레드 개념 및 사용방법 자바에서 여러가지 일을 동시에 처리하기 위해 사용되는 스레드(Thread)에 대해서 알아보도록 하겠습니다. 목차 프로세스와 스레드 (Process vs Thread) 스레드
kadosholy.tistory.com
void run( ) : 스레드의 실행코드가 작성되는 메소드로 사용자는 run() 메소드를 오버라이드 하여 사용해야 합니다.
void start( ) : 스레드가 시작되도록 요청하는 메소드로 JVM은 해당 스레드의 run() 메소드를 호출합니다.
참고링크2 : https://hianna.tistory.com/602
[Java] 줄바꿈 하기 (\n, \r, \r\n 의 차이)
Java에서 문자열의 줄바꿈을 표현할 때 주로 아래와 같은 escape 문자를 사용합니다. \n \r \r\n 그렇다면 위 3가지 escape 문자의 차이점은 무엇일까요? 세가지 표현 모두 줄바꿈을 나타내지만, 시스템
hianna.tistory.com
세가지 표현 모두 줄바꿈을 나타내지만, 시스템에 따라서 사용하는 개행문자가 다릅니다.
\n - unix
\r - mac
\r\n - windows
참고도서 : https://roadbook.co.kr/169
[신간안내] 자바 웹 프로그래밍 Next Step
● 저자: 박재성 ● 페이지: 480 ● 판형: 사륙배변형(172*225) ● 도수: 1도 ● 정가: 30,000원 ● 발행일: 2016년 9월 19일 ● ISBN: 978-89-97924-24-0 93000 [강컴] [교보] [반디] [알라딘] [예스24] [인터파크] [샘
roadbook.co.kr