-
Notifications
You must be signed in to change notification settings - Fork 47
[Han, Jay] 웹서버 1단계 구현 #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
BufferedReader를 이용, Request Header가 전체 출력되는 것 확인, Null 처리
/index.html 요청시, split 하여 정상적으로 출력된다. IOUtils parsePath method를 통해 위 요청사항을 해결
index.html 요청 시, 브라우저 출력 확인
URL 추출 메서드 이름 변경, 위치를 HttpRequestUtils로 변경
QueryString에 따른 User 객체 생성, 일치 확인
URL 이 / 이거나, /index.html일 때 index.html을 반환하도록 함. 이외 /user/create 시 객체를 생성하는 과정을 수행하도록 설정.
get -> post
header에서 content-legnth를 추출하여, 이에 해당하는 body를 읽어오는 기능 확인 body를 기반으로, User 객체 생성
302header method를 통해, 회원가입 후 브라우저에 302 status 보내서 "/"로 redirect 하도록 설정
header parse HttpRequestUtils.parseHeader를 이용. 404에 해당하는 url 요청 처리
Database 클래스를 이용하여, 회원가입 기능 구현 Database에서 로그인을 시도한 유저가 존재하는지 확인하고 성공, 실패시 로그 출력 Database에 테스트 유저가 자동적으로 추가되도록 설정
로그인 성공, 실패시 브라우저에게 전송될 header, body 설정 실패시에는 401 상태를 보내줌. 아직 로그인을 시도한 유저가 db에 존재하지 않을 때 어떻게 해야할지는 고민중
JSESSIONID를 생성하여 Set-Cookie에 저장함.
요청 헤더에서 jessionid value 추출 sessiondb에 존재하는지를 판단하여 있으면 user/list.html 보여주고 없으면 302 헤더와 함꼐 login페이지를 보여주도록 설정
db에서 user를 가져와서 list.html에 추가함.
css 자원을 요청하는 request에 대한 응답 구현
HttpResponse, SessionUtils 클래스 생성하여, 책임을 나눴다. 전자에는 요청파일을 응답하는 메서드를 할당하고, 후자에는 session 기능을 담당하게 만들었음.
redirect302, redirectWithCookie, readCss
readStaticFile, response404Header 추가함
if => switch문으로 변경 HttpRequestUtils의 extractHeader 메소드를 이용하여 헤더를 추춣하는 기능 분리
convention 수정 존재하지 않는 회원이 로그인을 시도한 경우, login_Failed.html 출력하도록 구현
1단계 배포 테스트
httpRequest 클래스 만들었고, HttpMethod enum 생성, httpRequest method 에 대한 테스트 코드 작성
HttpResponseUtils의 기능을 HttpResponse로 옮김
Response 클래스와, util 클래스의 책임과 역할을 나눔. response forward 시, 웹서버내 정적자원을 찾아서 브라우저에게 전달해주도록
[웹서버 2단계] Refactor
public static int getSizeOfUsers() { | ||
return users.size(); | ||
} | ||
|
||
public static void addUser(User user) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User 파라미터가 null인 경우에 대한 처리가 없네요
호출하는 쪽에서 null을 거르면 호출하는 곳마다 null을 체크해야하지만 해당 메소드 내부에서 안전하게 처리를 해둔다면 여러번 처리를 하지 않겠죠?
public static User findUserById(String userId) { | ||
return users.get(userId); | ||
public static User findUserById(String userId) throws NoSuchElementException{ | ||
return Optional.ofNullable(users.get(userId)).orElseThrow(NoSuchElementException::new); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 호출 하는 쪽에서 Optional로 받고 예외를 발생시킬 지 말지를 정하도록 하는 것이 좋다고 생각하는 편 입니다.
위와 같이 기능 메소드에서 예외를 발생시킬 경우 예외를 발생시키지 않아도 되는 상황에 일률적으로 발생시키는 것이 되어버리며 정상적인 진행이 되도록 하기 위해 try ~ catch 처리를 해야하기 때문입니다.
public class SessionDataBase { | ||
private static Map<String, User> sessions = Maps.newHashMap(); | ||
|
||
public static void addSession(String sessionId, User user) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위 UserDataBase와 동일한 피드백을 드리고 싶군요
} | ||
|
||
public static boolean isSessionIdExist(String sessionId) { | ||
return sessions.containsKey(sessionId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위 메소드들과 마찬가지로 예외처리를 보강해주셔야합니다.
private Map<String, String> header; | ||
private Map<String, String> parameter; | ||
|
||
public HttpRequest(BufferedReader br) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HttpRequest는 입력을 파싱하여 각각을 필드로 갖고 있는 클래스로 보이는데, BufferedReader를 생성자로 꼭 받을 필요가 있을까요?
요청 데이터가 표준입력이 아닌 파일입력 또는 그외의 방식으로 변경될 경우 HttpRequest 클래스에도 그 영향이 가지 않을까요?
여기에 대한 고민 한번 해보시고 리팩토링 권해드립니다.
저는 HttpRequest가 입력값만 받아도 크게 이상 없다고 피드백 드리겠습니다.
String requestLine; | ||
|
||
try { | ||
requestLine = br.readLine(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 라인 또한 사용자의 요청 입력 방식 변경이 영향 미칠 라인입니다.
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class HttpResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여러 리스폰스 코드(200, 302 등)에 맞춰 메소드를 만든 것으로 보입니다.
그리고 해당 메소드에 DataOutputStream 메소드가 있군요
HttpResponse는 말그대로 응답에 대한 필드만 가지고 있으면 될 것으로 보입니다. 2개의 역할을 모두 하고 있는 것으로 보여요
그리고 HttpResponse는 몇가지 정해져 있으니 각 응답코드에 맞춘 객체를 미리 생성해두고 재활용하면 어떨까요?
메소드로 풀어내는 것을 유지한다면 응답코드 대응할 때마다 메소드가 여러개 늘어나고, 이전에 만들었는지 체크하기도 힘들 것입니다.
@@ -13,6 +13,11 @@ public User(String userId, String password, String name, String email) { | |||
this.email = email; | |||
} | |||
|
|||
public User(String userId, String password) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생성자에서 예외처리가 필요해보입니다
userId, pwd 입력이 없을 경우에 대한 처리가 바깥에서 이뤄지거나 아예 없거나 한다면 User가 비정상적인 입력값에 의해서도 데이터가 계속해서 쌓일 수 있는 위험이 있습니다.
|
||
log.error("url : {}", url); | ||
|
||
switch (url) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RequestHandler 개념 도입은 좋아보이네요
RequestHandlerMapper 역할(적절한 RequestHandler를 찾아 위임하는 역할)을 하나 더 추가해보는 것은 어떨까요?
요청 url이 많아질 수록 case문은 늘어날 것이고 관리 하기가 매우 어려워 질 것 입니다.
RequestHandlerMapper가 RequestHandler List를 가지고 있고, 각 RequestHandler는 자기의 요청인지 알아차릴 url을 멤버 필드로 가지고 있으면 switch 문을 쓰지 않을 수 있을 것입니다.
spring mvc 처리 흐름 그림을 보시면 도움이 될 것 같습니다.
|
수고하셨습니다. |
구현사항
질문사항