-
Notifications
You must be signed in to change notification settings - Fork 0
2주차 금요일 그룹 3
7월 5일 랜덤 그룹 리뷰
FilterChain 기법으로 doRun, doFilter 를 사용해서 순서대로 filter 를 적용시킨 점이 인상 깊었습니다. preHandle, postHandle 로 Filter 의 기능을 구현한 점이 좋았습니다.
preHandle (request) -> doFilter(request, response) -> postHandle(request, response)
LoggingFilter, AcceptHeaderFilter 필터 적용이 좋았습니다.
Runnable implements 는 멀티스레딩을 실제로 돌리는 곳에서만 하면 좋을 것 같습니다. Acceptor 와 processor 가 병렬적인 스레딩으로 존재함.
톰캣의 endpoint 에 대한 공부를 많이 하신 게 인상깊었습니다.
Function 인터페이스에 대해서 알게되었습니다. Function<Request, Response> handler 를 이용해서 사용하신게 인상깊었습니다.
다형성을 이용하게되면 오버라이드를 해야하기 때문에 1클래스에 1메서드만 핸들할 수 있기 때문에 이 부분을 해결하기 위해서 여러 url 을 한 클래스에 2개이상 매핑하기 위해서 펑션 핸들러를 등록할 수 있도록 한 게 매우 인상깊었습니다.
HttpStatusException 을 사용하신 부분이 인상깊었습니다.
유저를 저장할 때 동시성 테스트를 작성하신 부분이 인상깊었습니다.
byte 값이 200 몇이 바이트가 오버플로우 나서 - 되는데 String 변환이 안 된다!
New URI 를 통해서 url을 분리하는 방식도 있다는 것을 배웠습니다.
파일을 가져오는 방법이 여러개있다는 점을 알았습니다.
jar 내부의 압축 파일을 인풋 스트림으로만 받아야 읽을 수 있다?
스트림으로 받아도 상대경로 문제가 있다.
- 이미지 파일을 String으로 읽었을 때, 지원하지 않은 바이트를 인코딩하게 되면 해당 데이터가 깨지는 문제가 발생하기 때문에 이를 고려해서 response를 만들어야 한다.
- 함수형으로 처리할 로직을 매핑하는 구현에 대해서 알 수 있었습니다.
- UrI 클래스를 통해서 path와 query를 파싱할 수 있다는 것을 알 수 있었습니다.
- 자바에서 우아한 종료를 하기 위한 훅을 제공한다는 사실을 알 수 있었습니다. 톰켓에서 Graceful shutdown을 구현할 때, 이러한 기술을 사용했을 것이라고 추측하게 되었습니다.
- 세민님이 라우팅을 함수형으로 구현한 방식이 인상적이었습니다. 어노테이션으로 구현하는 방식도 좋지만 함수형으로 구현하게 된다면 리플렉션을 사용하지 않아도 충분히 유연한 코드를 만들 수 있을 것 같아서 적용하면 좋겠다는 생각이 들었습니다.
- 현재 코드에서는 메인 스레드가 다른 스레드를 생성하고 종료가 되고 있습니다. 리뷰 과정에서 메인 스레드가 종료되지만 왜 프로세스가 종료되지 않고 실행되는가?에 대한 피드백을 받게 되었습니다. 일단 종료가 되지 않고 실행되는 것을 보면 처음 실행되는 메인 스레드 역시 jvm 프로세스에 종속된 스레드이기 때문에 영향이 가지 않는 것인가? 하는 생각을 하게 되었습니다. 추측은 가지만 정확한 사실을 모르기 때문에 한번 찾아봐야겠다는 생각이 들었습니다.
피드백 받은 내용
-
현재 HttpMethod, path를 통해 handler를 매핑해주는
RouteEntry
클래스를 Builder를 통해 만들고 있는데 조금만 개선해서 메서드 체이닝형태로 만들면 가독성이 더 좋아질 것 같다고 해주셨습니다!new RouteEntry.Builder().route(HttpMethod.GET, "/registration") .handler((httpRequest) -> ObjectContainer.getStaticResourceMappingUsecase().register()) .build()
인상 깊었던 코드
- 동근님이 FilterChain으로 필터를 구현한 것이 인상적이었습니다. 요청이 들어왔을 때 Filter의 순서대로
preHandle()
하고, 요청을 반환할 때prehandle()
의 역순으로postHandle()
을 실행하는 로직이었습니다. -
File
의isDirectory()
메소드를 활용해 요청 경로가 디렉토리일 때 Default page(index.html) 이 있는지 확인해서 반환해주도록 한 부분이 인상적이었습니다.
추가로 생각해 볼 점
-
classLoader
에getResource()
와getResourceAsInputStream()
메서드의 차이를 잘이해하지 못하고 적용했는데 jar 빌드 후 환경에서 예상과 다른 결과가 나와서 의문이 들었습니다. 동근님의 의견으로는 jar를 만들면 File을 직접적으로 읽을수 없는 이슈가 생긴다고 했는데, 이 부분에 대해 더 알아보려고 합니다. - while 무한루프를 가지는 메소드에 대한 테스트를
Thread
를 만들어서 수행하도록 하였습니다. 신기한 방법이라고 생각했으나 요청 처리 시간을 측정할 수 없는 경우 문제가 생길 수 있지 않을까 생각이 들었습니다.
[구현 내용]
- JVM의
Runtime.addShutdownHook()
을 사용하여 gracefully stop을 구현하였습니다. - Exception 처리 시 중복 코드를 줄이기 위해 catch로 각 Exception 타입을 잡아 처리하는 대신 Exception으로 잡고 if문으로 처리하도록 구현하였습니다.
- Content-Length, Content-Type, Date 헤더 필드 로직을 구현하였는데, 이 말고도 다른 헤더를 처리하는 로직을 생각해보니 헤더 로직이 분산될 수 밖에 없다고 생각하여 HTTP 요청 처리 전반에 걸쳐 Response를 만들어나갈 수 있도록 setter를 열어두었습니다. 또, 딱 한 번씩만 설정할 수 있도록 이미 값이 존재하는 경우는 예외 발생 처리를 추가하였습니다.
- URI 기반 API 처리와 정적 파일 반환 요청 분기를 나누어 처리했습니다.
- URI 기반 API 실행은 메서드별 실행할 수 있는 함수를 가진 RequestHandler 인터페이스를 두고, RequestHandlerResolver를 통해 해당 URI에 맞는 RequestHandler를 찾아와 각 메서드에 맞게 HTTP 메서드별 메서드를 실행시키는 방식으로 구현하였습니다.
[배운 점]
- 동근 님이
FilterChain
을 통해 여러 로직들을 순서대로 처리할 수 있는 방식으로 구현하셨습니다. 절차대로 처리하거나, 중간에 특정 로직을 끼워넣어야 하는 경우와 같이 유연한 실행 구조를 만드려면 필터 구조를 사용하면 좋겠다는 생각이 들었습니다.- 필터 우선순위를 위해
Comparable
을 구현하셨는데,Comparable
이 가진 "순서"의 의미를 더 넓게 생각할 수 있어 좋았습니다.
- 필터 우선순위를 위해
- 세민 님이 URI 기반 API 처리를 위해 method, uri, Function<>을 하나로 가지는
RouteEntry
를 정의하셨는데, 함수형 프로그래밍이 이런 데 장점이 있구나 배웠습니다.- byte[]를 String으로 변환하고 String을 byte[]로 변환할 때, 인코딩 때문에 깨진 문자열이 그 바이트대로 변환되는 것이 아니라 "깨진 문자열"의 바이트 대로 변환되어 인코딩 문제가 있을 수 있다고 말씀해주셔서 다른 인코더로 인코딩, 디코딩 시 이런 문제가 발생할 수 있구나를 알 수 있었습니다.
- Exception 내부에 HttpStatus 필드를 두어 각 Exception 발생 시 어떤 status를 반환해야 하는가를 분기 처리 대신 해당 Exception이 발생한 곳에서 설정할 수 있는 로직을 구현하셨는데, 정말 좋은 아이디어라는 생각이 들었습니다!
- 은기 님이 jar 파일로 실행하더라도 파일을 제대로 불러올 수 있도록
class.getResourceAsStream()
을 사용하셨는데, class 타입에도 메서드가 있다는 걸 처음 알았습니다. 아직 자바에 대해 모르는 게 많다는 생각이 들었습니다! - 영민 님이 스레드를 만들어 웹서버 실행 코드도 테스트할 수 있도록 하셨는데, 이런 방식은 생각해본 적이 없어 정말 새로웠습니다!
[후기]
- 다들 어떤 레퍼런스를 가지고, 어떤 걸 구현하고 싶냐에 따라 구조가 많이 달랐습니다. 이번 프로젝트로 WAS의 다양한 구현 방식, 혹은 구조를 배울 수 있을 것 같아 좋았습니다!!
- 질문이 정말 많았고, 활기 차게 진행해서 좋았습니다!!
- 수, 금마다 제 코드에 대해 이야기해보며 제 코드를 더 정리해서 바라볼 수 있게 되어 좋았습니다!
- 필터를 구현하여 체이닝을 통해 요청을 핸들링하기 전, 후로 원하는 로직을 실행하는 것이 인상 깊었습니다.
현재는 요구사항이 많지 않아 로그 출력, header 검사 등의 역할을 수행하지만 이후 인증, 인가 등과 같이 요청 전에
처리해야할 로직을 넣을 수 있을 것 같아 확장이 편리할 것 같다고 생각했습니다. - 요청에 대한 처리를 클래스가 아닌 Function 클래스를 사용하여 메소드 별로 분리하여 확장성을 챙긴 것이 인상 깊었습니다.
자바의 람다를 공부할 때 배웠던 것 같은데 함수형 프로그래밍에 익숙하지 않아서 Function 클래스에 대해서 더 알아봐야겠습니다. - server 클래스에 시작하는 함수 뿐만아니라 stop과 같은 종료함수도 추가하여 테스트시에 서버를 중지 시킬 수도 있다는 것을 알았습니다.
- jar 파일로 빌드시에 파일을 읽는 경로가 달라져 기존에 사용했던 getResource 메서드가 제대로 동작하지 않았는데 이유에 대해 자세히 알아봐야겠습니다.