## 42. 여러 클라이언트의 요청을 순차적으로 처리하기: Stateless 방식
- Stateless 방식으로 통신하는 방법
- 구동 원리와 Stateful 방식 대비 이점
- Stateless 방식의 문제점
ServerApp.java
ㄴ while 문 껍데기를 제거
=>
ServerApp.java
ㄴ 이제 while 문이 아니므로 quit, break 는 필요 없음
ㄴ continue 는 모두 return 으로 변경
ㄴ 클라이언트 요청을 반복해서 처리하지 않음
=> 접속 -> 요청 -> 실행 -> 응답 -> 연결 끊기
DaoBuilder.java
ㄴ DaoBuilder 의 생성자에 serverAdddress, port 를 넘겨줌
DaoBuilder.java
ㄴ Socket socket = new Socket(serverAddress, port);
ㄴ 주어진 serverAddress와 port 정보를 사용하여 서버에 소켓 연결을 수행
=> 클라이언트와 서버 간의 네트워크 연결이 이루어짐
ㄴ serverAddress와 port 정보를 사용하여 서버에 접속하는 Socket 객체를 생성
=> 이를 이용하여 서버와 통신 수행 가능
DaoBuilder.java
ㄴ 서버에 소켓 연결을 수행하고, 데이터를 송수신하기 위한 DataOutputStream과 DataInputStream을 생성
ㄴ DataOutputStream out = new DataOutputStream(socket.getOutputStream());
ㄴ 소켓에서 출력 스트림을 얻어와서 DataOutputStream으로 래핑
=> 서버로 데이터를 전송 가능
ㄴ DataInputStream in = new DataInputStream(socket.getInputStream());
ㄴ 소켓에서 입력 스트림을 얻어와서 DataInputStream으로 래핑
=> 서버로부터 데이터를 수신 가능
=> 생성된 Socket, DataOutputStream, DataInputStream 객체를 사용하여 클라이언트와 서버 간의 데이터 송수신을 처리
** 데코레이터 패턴
ㄴ 객체에 추가적인 기능을 동적으로 덧붙일 수 있는 디자인 패턴
ㄴ 기본 객체에 대한 수정 없이도 새로운 기능을 추가할 수 있도록 해주어 유연성과 확장성을 제공
ㄴ 여기서 Socket 객체는 네트워크 연결을 담당하는 기본 기능을 가지고 있음
=> 이에 대해 DataOutputStream과 DataInputStream이 데코레이터 역할을 수행하여 입출력 기능을 추가함
ㄴ 즉, Socket 객체에 대해 DataOutputStream은 데이터를 보내는 출력 기능을 덧붙이고, DataInputStream은 데이터를 받는 입력 기능을 덧붙임
=> 소켓을 통해 데이터를 보내고 받을 수 있게 됨
DaoBuilder.java
ㄴ try 문 안에 넣어줌 => 자동 close 를 위해
** try-with-resources 구문
ㄴ 자원을 사용한 후에 자동으로 닫아줘야 하는 경우를 간편하게 처리하기 위한 기능
=> 여기서는 소켓과 입출력 스트림을 자동으로 닫는 기능을 구현
DaoBuilder.java
ㄴ try 문으로 해당 부분까지 묶어주기
ㄴ 응답 객체의 상태를 확인하여 오류가 있는 경우 예외를 발생시키도록 함
=>
DaoBuilder.java
ㄴ catch 로 예외를 받아줌 (RuntimeException 이용)
ClientApp.java
ㄴ DaoBuilder 의 생성자에 ip, port 를 넘겨줌
ClientApp.java
ㄴ 이제 ClientApp 클래스에서 해당 코드들은 필요 없으므로 제거
=> DaoBuilder 클래스에서 이미 Socket과 입출력 스트림을 사용하여 요청을 보내고 응답을 받는 로직이 구현되어 있음
ClientApp.java
ㄴ DaoBuilder 클래스의 try 문에 자동 close 되도록 해두었기때문에 해당 코드 필요 없으므로 제거
** stateless 방식의 Stateful 방식 대비 이점
ㄴ 요청할 때마다 서버에 새로 연결하기 때문에 서버 과부하가 줄어듦
ㄴ 확장성, 유연성, 성능, 유지보수 용이성 등