본문 바로가기

Java152

[Java] 세션(HttpSession) 구현 / 세션은 HTTP 쿠키를 기반으로 동작 클라이언트와 서버 간에 주고 받을 고유한 아이디 생성. 고유한 아이디는 쉽게 예측할 수 없어야 하며, 예측하기 쉬우면 쿠키 값을 조작해 다른 사용자처럼 속일 수 있음. 위에서 생성한 고유 아이디의 세션을 클라이언트 마다 무조건 하나를 배정받게 된다. 이를 확인하는 방법으로는, 클라이언트의 요청 헤더를 확인 후 JSESSIONID라는 Key에 대응하는 Value가 없다면 응답 헤더의 쿠키로 담아서 전달한다. if( request.getCookies().getCookies("JSESSIONID") == null) { response.addHeader("Set-Cookie", "JSESSIONID=" + UUID.randomUUID()); } 모든 클라이언트에게 전달한 세션 값을 서버측에서 관리할 수 있는 클.. 2023. 3. 21.
[Java] 다형성을 활용해 클라이언트 요청 URL에 대한 분기 처리를 제거 run() 메서드의 복잡도는 아직 상당히 높다. public void run() { log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), connection.getPort()); try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { HttpRequest request = new HttpRequest(in); String requestURL = request.getPath(); HttpResponse response = new HttpResponse(out); if( re.. 2023. 3. 20.
[Java] 응답 데이터를 처리하는 로직을 HttpResponse 클래스로 분리 및 리팩토링 응답 데이터를 처리하는 로직을 HttpResponse 클래스로 분리 아래 코드를 보면 응답 데이터 처리를 위한 많은 중복이 있다. 중복을 제거하자. private void response302LoginSuccessHeader(DataOutputStream dos) { try { dos.writeBytes("HTTP/1.1 302 Found \r\n"); dos.writeBytes("Content-Type: text/html;charset=utf-8 \r\n"); dos.writeBytes("Set-Cookie: logined=true \r\n"); dos.writeBytes("Location: /index.html \r\n" ); dos.writeBytes("\r\n"); } catch (IOExcept.. 2023. 3. 19.
[Java] 요청 데이터 처리 로직을 HttpRequest 클래스로 분리 및 리팩토링 클라이언트의 요청 데이터를 처리하는 로직을 별도의 클래스로 분리 클라이언트의 요청 데이터를 담고 있는 InputStream을 생성자로 받아 HTTP 메서드, URL, 헤더, 본문을 분리 Http Header는 Map에 저장해 관리하고, getHeader( String key ) 메서드를 통해 접근 가능 GET과 POST 메서드에 따라 전달되는 인자를 Map에 저장해 관리하고, getParameter( String key ) 메서드를 통해 접근 가능하도록 구현 public class HttpRequest { private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); private Map httpHeader = new HashM.. 2023. 3. 19.
[Java] HTTP 웹 서버 구현 / CSS 지원하기 응답을 받은 브라우저는 Content-Type를 확인한다. 서버는 클라이언트에게 요청을 받은 후 응답을 보낸다. 이때, 응답을 보내는 컨텐츠가 어떤 컨텐츠인지 알려주는 내용도 헤더에 포함 후 전송한다. 만약, 모든 응답이 text/html 이라면.. 브라우저는 CSS, JS, 이미지 등의 파일 모두 HTML로 인식하기 때문에 정상적으로 작동하지 않는다. 따라서 URI의 확장자가 css인 경우 헤더 값을 text/css로 응답을 보내도록 구현해야 한다. private void response200HeaderWithCss(DataOutputStream dos, int lengthOfBodyContent) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); dos.writeB.. 2023. 3. 17.
[Java] HTTP 웹 서버 구현 / 로그인 구현 HTTP는 무상태 프로토콜이다. HTTP는 요청을 보내고 응답을 받으면 클라이언트와 서버 간의 연결을 끊는다. 각 요청 사이에 상태를 공유할 수 없다. 웹 애플리케이션에서 대표적인 기능 중의 로그인 기능을 보면, 클라이언트가 로그인을 완료하면 매 요청마다 로그인을 다시 하지 않는다. HTTP는 클라이언트가 한 행위를 기억할 수 없는데 이는 어떻게 가능한 걸까? 쿠키로(Cookie)로 클라이언트의 행위를 기억하자. 로그인과 같이 클라이언트의 행위를 기억하기 위한 목적으로 지원하는 것이 쿠키이다. 서버에서는 로그인 요청을 받으면 로그인 성공/실패 여부에 따라 응답 헤더에 Set-Cookie로 결과 값을 저장할 수 있다. 클라이언트는 응답 헤더에 Set-Cookie가 존재할 경우 Set-Cookie의 값을 읽.. 2023. 3. 17.
[Java] HTTP 웹 서버 구현 / 302 status code 적용 302 status 적용해야하는 상황 "회원가입"을 완료하면 /index.html로 이동해야 한다. URI가 "/user/create"로 유지되는 상태로 읽어서 클라이언트에게 전달할 파일이 없다. 따라서 회원가입을 완료한 후 /index.html 페이지로 이동하면서 브라우저의 URL도 /user/create가 아니라 /index.html로 변경해야 한다. 두번의 요청과 응답 회원가입을 처리하는 /user/create 요청과 첫 화면(/index.html)을 보여주는 요청을 분리한 후 HTTP의 302 상태 코드를 활용해 해결한다. 즉, 서버측에서는 /user/create 요청을 받아 회원가입을 완료한 후 응답을 보낼 때 클라이언트에게 /index.html로 이동하도록 할 수 있다. 이때 사용하는 상태 코.. 2023. 3. 17.
[Java] HTTP 웹 서버 구현 / POST 방식으로 회원가입 POST 방식에서의 HTTP Header와 Body POST /user/create HTTP/1.1 Host: localhost:8080 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Accept: */* (공백) userId=tester1&password=test1&name=테스터 POST로 데이터를 전달할 경우 전달하는 데이터는 HTTP 본문에 담긴다. HTTP 본문은 HTTP 헤더 이후 빈 공백을 가지는 한 줄(line) 다음부터 시작한다. HTTP 본문에 전달되는 데이터는 GET 방식으로 데이터를 전달할 때의 키=value 형식과 같다. 요청 헤더에 본문 데이터에 대한 길이가 Content-Length라는 필드 이름으.. 2023. 3. 17.
[Java] HTTP 웹 서버 구현 / GET 방식으로 회원가입 GET 방식으로 회원가입 사용자가 입력한 값을 파싱(문자열을 원하는 형태로 분리하거나 조작하는 것을 의미)해 model.User 클래스에 저장한다. 사용자 아이디 비밀번호 이름 이메일 회원가입 HTTP Header GET /user/create?userId=tester1&password=test1&name=테스터 HTTP/1.1 HTTP 요청의 첫 번째 라인에서 요청 URI을 추출 요청 URI에서 접근 경로와 key=value 형식으로 전달되는 데이터를 추출해서 Model 클래스에 담는다. GET 방식의 회원가입 GET /user/create?userId=tester1&password=test1&name=테스터 HTTP/1.1 위의 코드는 GET 방식으로 회원가입을 했을 때의 요청 라인이다. 사용자가 입.. 2023. 3. 17.