-
Notifications
You must be signed in to change notification settings - Fork 0
3주차 수요일 그룹 1
지찬우 edited this page Jul 10, 2024
·
1 revision
-
기본적으로 리팩토링을 진행하여 이번주 미션에 대해 진행한것은 별로 없습니다.
-
세션에 대한 로직은 아래와 같은 구조를 가지고 있습니다.
-
SessionManager : 세션을 통합적으로 관리하는 객체입니다. 세션 id 생성, 세션 생성 및 저장, id 반환, 세션 생성시간, 마지막 접근 시간 업데이트 등의 책임을 집니다.
-
SessionStorage : 세션 객체를 관리합니다. 저장 및 삭제를 책임집니다.
-
Session : 세션에 대한 정보를 담당합니다. 세션 id, 생성 시간, 업데이트 시간 등을 조회할 수 있고, 세션 객체 안에 사용자의 attribute를 삽입, 삭제 할 수 있습니다. 또한 invalidation 을 책임집니다.
-
쿠키 관련 부분은 response header에서 key값으로 multi value를 받을 수 있게 설정했기 때문에, response.addCookie 메서드를 이용하여 값을 관리할 것 입니다.
핸들러 인터페이스는 아래와 같이 default 로 선언하여 기본적으로는 MethodNotAllowed 를 throw 할 수 있도록 구현했습니다.
package codesquad.was.http.handler;
import codesquad.was.http.exception.HttpMethodNotAllowedException;
import codesquad.was.http.exception.HttpNotFoundException;
import codesquad.was.http.message.request.HttpRequest;
import codesquad.was.http.message.response.HttpResponse;
public interface RequestHandler {
default void handle(HttpRequest req, HttpResponse res){
switch(req.getMethod()){
case GET->getHandle(req,res);
case POST ->postHandle(req,res);
case PUT ->putHandle(req,res);
case PATCH -> patchHandle(req,res);
case DELETE -> deleteHandle(req,res);
case OPTIONS -> optionsHandle(req,res);
case TRACE -> traceHandle(req,res);
case HEAD -> headHandle(req,res);
case CONNECT -> connectHandle(req,res);
}
}
default void getHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void postHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void putHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void patchHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void deleteHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void optionsHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void traceHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void headHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void connectHandle(HttpRequest req, HttpResponse res){
throw new HttpMethodNotAllowedException("This method is not allowed");
}
}
마지막으로 테스트코드를 용이하도록 DI & IOC 구조를 채택해서 테스트 커버리지를 약 80% 까지 올렸습니다.
package codesquad.was.http.handler;
import codesquad.was.http.exception.HttpMethodNotAllowedException;
import codesquad.was.http.exception.HttpNotFoundException;
import codesquad.was.http.message.request.HttpRequest;
import codesquad.was.http.message.response.HttpResponse;
public interface RequestHandler {
default void handle(HttpRequest req, HttpResponse res) {
switch (req.getMethod()) {
case *GET *->getHandle(req, res);
case *POST * ->postHandle(req, res);
case *PUT * ->putHandle(req, res);
case *PATCH * ->patchHandle(req, res);
case *DELETE * ->deleteHandle(req, res);
case *OPTIONS * ->optionsHandle(req, res);
case *TRACE * ->traceHandle(req, res);
case *HEAD * ->headHandle(req, res);
case *CONNECT * ->connectHandle(req, res);
}
}
default void getHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void postHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void putHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void patchHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void deleteHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void optionsHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void traceHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void headHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
default void connectHandle(HttpRequest req, HttpResponse res) {
throw new HttpMethodNotAllowedException("This method is not allowed");
}
}
리팩토링할 대상을 찾을 목적으로 그룹 리뷰에 참여 했습니다.
- 쿠키를 객체로 관리하기
- 한곳에서 예외처리
- 다양한 content-type을 지원하기 위해 reader 추상화 or byte[] 읽기
- 멀티스레드에서 안전하게 동작하는 싱글톤 만들기
- request processor를 디폴트 메서드를 포함한 인터페이스를 만들어두면 유연한 설계 가능
- 정적 리소스 핸들러를 먼저 고려하는게 좋은지 마지막에 고려하는게 좋은지는 매핑된 url 수 vs static 핸들러 수에 따라 달라질 수 있다. 스프링은 정적 리소스 핸들러를 마지막에 고려하는데 아마 스프링은 정적 리소스를 서빙하기 위해서 사용되기 보다 앞단에 web server를 두고 사용하는 경우가 많기 때문일듯
- 테스트 커버리지 살펴보기
- 목소리 조금 더 크게 해주세요~
- 간단한 템플릿 엔진을 만들어서 동적인 html을 만들었습니다. 밖으로 빼서 라이브러리로 만들어보면 재밌을 것 같아요.
- 템플릿 엔진을 사용하는 과정에서 문자열
reaplce()
가 반복해서 호출되고 있어 비효율적인 부분이 있을 것 같아요. - 구조가 스프링과 유사해보이는 것 같아요.
- http 요청 메시지를 읽어들이는 부분에서 실제 HTTP 메시지의 줄바꿈 형식과 달라지는 경향이 있습니다.
- 목소리 조금 더 크게 해주세요~
- 간단한 템플릿 엔진을 만들어서 동적인 html을 만들었습니다. 밖으로 빼서 라이브러리로 만들어보면 재맸을 것 같아요.
- 템플릿 엔진을 사용하는 과정에서 문자열
reaplce()
가 반복해서 호출되고 있어 비효율적인 부분이 있을 것 같아요. - 구조가 스프링과 유사해보이는 것 같아요.
- http 요청 메시지를 읽어들이는 부분에서
- static 남발로 인한 test 부족때문에 이를 고쳐야 할 것 같습니다
- encoder, decoder를 앞에 만들어서 filter를 쓰면 좀 더 깔끔해 이를 고치면 좋겠습니다.
- exception을 좀 더 세분화하여 진행하고 handler를 method 별로 바꾸면 더 좋은 코드가 될 거 같습니다.
- 핸들에서 한 번 캐치할 수 있게 예외 처리할 부분 지점들이 많아지다 보니까 매번 Response를 생성하기 힘들어 한 번 해두면 편할 것 같음
- 핸들러 할 때 Exception 넘겨주면 그대로
StatusCode
를 꺼내옴 - 예외 던질 때
throw HttpStatusException
할 때 상황에 맞는StatusCode
를 주입 - 어떻게 핸들링할지 고민