김영한의 실전 자바 - 고급 2편(HTTP서버)

2025. 1. 29. 16:51·김영한의 실전 자바 - 고급 2편
public class HttpServerV1 {
    private final int port;

    public HttpServerV1(int port) {
        this.port = port;
    }

    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        log("서버 시작 port: " + port);
        while (true) {
            Socket socket = serverSocket.accept();
            process(socket);
        }
    }

    private void process(Socket socket) throws IOException {
        try (
            socket;
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), UTF_8));
            PrintWriter writer = new PrintWriter(socket.getOutputStream(), false, UTF_8)
        ) {
            String requestString = requestToString(reader);
            if (requestString.contains("/favicon.ico")) {
                log("favicon 요청");
                return;
            }
            log("HTTP 요청 정보 출력");
            System.out.println(requestString);
            log("HTTP 응답 생성중...");
            sleep(5000); // 서버 처리 시간
            responseToClient(writer);
            log("HTTP 응답 전달 완료");
        }
    }

    private String requestToString(BufferedReader reader) throws IOException {
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.isEmpty()) {
                break;
            }
            sb.append(line).append("\n");
        }
        return sb.toString();
    }

    private void responseToClient(PrintWriter writer) {
        // 웹 브라우저에 전달하는 내용
        String body = "<h1>Hello World</h1>";
        int length = body.getBytes(UTF_8).length;
        StringBuilder sb = new StringBuilder();
        sb.append("HTTP/1.1 200 OK\r\n");
        sb.append("Content-Type: text/html\r\n");
        sb.append("Content-Length: ").append(length).append("\r\n");
        sb.append("\r\n"); // header, body 구분 라인
        sb.append(body);
        log("HTTP 응답 정보 출력");
        System.out.println(sb);
        writer.println(sb);
        writer.flush();
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

 

위 코드는 무슨 프로토콜 통신 방법인가?

  • 앞선 코드는 HTTP 프로토콜로 통신을 하는 방법으로, HTTP의 규격을 맞추고 있음.
  • 위 HTTP 메시지 구조로 맞게 코드를 구성해서 Buffer로 내보내고 있는 차이가 있음.
  • 이 방식은 HTTP 프로토콜 규격에 맞춘 클라이언트와 통신하는 방식으로 예를 들어 웹브라우저와 통신할때는 이와 같은 방식으로 통신해야 함
  • ServerSocket과 BufferedWriter를 통해서 단순 string data로만 통신한다면 이는 HTTP 통신이 아니고 TCP/IP 통신으로 예를 들어 단순 서버 클라이언트간 채팅을 주고받는다면 더욱 더 적합한 방법임.

 

앞선 코드를 톰캣+자바에서 제공해주는 서블릿 구조로 변경하면 무엇이 달라지는가?

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        out.println("Hello, World!");
    }
}
  • 앞선 코드는 서블릿을 직접 구현한 모습이라고 볼 수 있음.
  • 따라서 HTTP와 관련된 모든 내용을 직접 구성을 해야 했지만 위 코드는 그러한 기본적인 구성을 알아서 해줌
  • 또한, uri 맵핑, get, post에 대한 처리도 서블릿에서 기본적으로 모두 구현해 줌.
  • 더 이상 ServerSocker, accpet() 이런 것에 대한 관리가 필요 없고 톰캣이 커넥션과 관련된 처리를 직접 해줌.
  • 톰캣이 요청이 들어오면 그에 맞는 서블릿에 요청을 넘겨 줌.

 

WAS란?

  • Web Application Server의 줄인말로 일반적으로 단순 Web Server는 이미지나 필요한 데이터를 제공해주는 서버인 반면에 WAS는 중간에 Application이 들어감.
  • Application이 들어간다는 것은 웹 서버 역할에 추가로 프로그램 코드도 수행할 수 있다는 것을 의미
  • 이는 HTTP 요청을 처리하면서 서블릿 구현체들이 하는 작업도 동시에 한다는 의미.

'김영한의 실전 자바 - 고급 2편' 카테고리의 다른 글

김영한의 실전 자바 - 고급 2편(어노테이션)  (2) 2025.01.29
김영한의 실전 자바 - 고급 2편(리플렉션)  (1) 2025.01.29
김영한의 실전 자바 - 고급 2편(네트워크 예외)  (2) 2025.01.28
김영한의 실전 자바 - 고급 2편(네트워크 자원정리)  (1) 2025.01.28
김영한의 실전 자바 - 고급 2편(네트워크, TCP, IP, UDP, DNS)  (1) 2025.01.28
'김영한의 실전 자바 - 고급 2편' 카테고리의 다른 글
  • 김영한의 실전 자바 - 고급 2편(어노테이션)
  • 김영한의 실전 자바 - 고급 2편(리플렉션)
  • 김영한의 실전 자바 - 고급 2편(네트워크 예외)
  • 김영한의 실전 자바 - 고급 2편(네트워크 자원정리)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      cglib
      @discriminatorvalue
      프록시
      Thread
      김영한
      requset scope
      jdk 동적 프록시
      프록시 팩토리
      @discriminatorcolumn
      빈 후처리기
      Target
      reentarantlock
      typequery
      버퍼
      @args
      페치 조인
      양방향 맵핑
      자바
      log trace
      조회 성능 최적화
      hibernate5module
      락
      gesingleresult
      스레드
      WAS
      jpq
      단방향 맵핑
      고급
      JPQL
      @within
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    김영한의 실전 자바 - 고급 2편(HTTP서버)
    상단으로

    티스토리툴바