Skip to content
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

[톰캣 구현하기 - 3, 4단계] 다즐(최우창) 미션 제출합니다. #470

Merged
merged 7 commits into from
Sep 12, 2023

Conversation

woo-chang
Copy link
Member

안녕하세요 에코!
미션과 프로젝트를 병행하다 보니 생각보다 미션 제출이 늦어지게 되었네요 🥲

코드의 큰 변화는 없고 1, 2단계 구현 내용을 바탕으로 패키지 구조 변경과 동시성 문제만 해결한 것 같아요 :)
이번에도 에코의 커멘트를 통해 많이 고민해보고 배워가도록 하겠습니다 🙇🏻‍♂️

@woo-chang woo-chang self-assigned this Sep 11, 2023
Copy link

@echo724 echo724 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다즐 지난번 미션 코드도 너무 깔끔해서 감동이였는데 이번에는 한 층 더 깔끔한 느낌이더라구요.. Spring은 이런 느낌으로 굴러가려나 싶은 코드였던 것 같습니다! 자바 코드를 정말 다양하게 잘 쓰시네요! 멋지고,, 배워갑니다..

아래는 실제로 코드를 돌렸을때 모든 요청에 대해 발생하는 에러인데요, 아무래도 bufferReader.readLine에서 발생하는 예외로 보입니다. 혹시 이 예외도 처리해주실 수 있을까요?

23:46:52.257 [pool-1-thread-86] ERROR org.apache.coyote.http11.Http11Processor - Socket closed
java.net.SocketException: Socket closed
...

private static final List<Servlet> servlets = new ArrayList<>();

static {
servlets.add(new DispatcherServlet());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 이게 디스패쳐 서블릿이군요..! 다즐 코드 보면서 한 번 배워보겠습니다 ㅎㅎ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추상적인 구현이라 에코가 학습해서 저에게도 공유해주세요 :0

}

public Connector(final int port, final int acceptCount) {
public Connector(final int port, final int acceptCount, final int maxThreads) {
this.executorService = new ThreadPoolExecutor(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 이 부분 설명해주실 수 있나요? 저는 그냥 ExecutorService.newFixedThreadPool을 이용한 것 같은데 차이가 뭔지, 사용한 이유가 따로 있는지 궁금합니다..!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스크린샷 2023-09-12 오후 1 38 38

newFixedThreadPool을 사용하더라도 내부적으로는 동일한 코드를 통해 생성하는 것을 확인할 수 있습니다!

ThreadPoolExecutor의 각각의 인자는 아래와 같습니다.

  • corePoolSize : 스레드가 유휴상태에 있더라도 유지해야하는 최소 스레드의 개수
  • maximumPoolSize : 스레드 풀이 최대로 가질 수 있는 스레드 수
  • keepAliveTime : 유휴 상태의 스레드가 스레드 풀에서 남아있을 수 있는 시간
  • unit : 시간 단위
  • workQueue : 실행할 작업이 담기는 큐

newFixedThreadPool과 다르게 설정한 부분은 workQueue입니다. 작업 큐의 크기를 설정하지 않으면 정수 최대값이 설정되게 되는데 해당 수를 조절하여 100개까지만 가능하도록 스레드풀 설정을 하였습니다 :)

@@ -67,12 +80,13 @@ private void process(final Socket connection) {
return;
}
var processor = new Http11Processor(connection);
new Thread(processor).start();
executorService.submit(processor);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future를 반환받을 필요가 없는 경우인데도 submit을 사용하신 이유가 있을까요?!저는 submit은 Future를 반환하는 경우, execute는 반환값이 없는 경우에 사용하는 걸로 알고 있었거든요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

명확한 근거없이 사용했었는데 그런 차이가 있었네요 👍👍

현재는 연산의 결과가 필요하지 않은 상황이기에 submit보다는 execute가 적절한 경우라고 생각이 드네요 ! 배워갈 수 있었습니다. 감사합니다 ㅎㅎ


public class GetFileMappingInfo extends MappingInfo {

private static final String FILE_PATTER = "/[^.]*\\.[^.]*$";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PATTERN 오타 났습니다!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에코 매의 눈이네요 🦅

}

public void renderPage(final HttpResponse httpResponse, final HttpStatus httpStatus, final String page)
public static void renderPage(final HttpResponse request, final HttpStatus response, final String page)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpResponse가 request로, HttpStatus가 response로 되어있네요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

새벽에 졸린채 작성한 코드라 HTTP prefix만 보고 무지성을 바꿨던 기억이 있네요 😅 감사합니다

final String cookie = httpCookie.getCookie(JSESSIONID);
if (cookie == null || SessionManager.findSession(cookie) == null) {
viewResolver.renderPage(httpResponse, HttpStatus.OK, LOGIN_PAGE);
ViewResolver.renderPage(response, HttpStatus.OK, LOGIN_PAGE);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 부분을 좀 고민하긴 했는데, 만약 유저가 로그인 된 상태에서 login.html로 직접 접근하는 경우는 어떻게 처리해야할까요? /login으로 들어올 경우는 이렇게 쿠키 확인을 해주지만, login.html로 직접 들어가는 경우는 따로 확인을 해줘야하지 않을까 싶기도 해요..!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설명해주신 접근은 전혀 생각지도 못했네요 ! 에코의 리뷰를 보고 저도 고민해볼 수 있었어요 ㅎㅎ

말씀하신대로 login.html 페이지에 접속했을 때 쿠키를 확인하고 쿠키가 존재한다면 리다이렉트하는 방법도 좋은 것 같아요 👍

저는 조금 다른 관점으로도 생각해본 것 같아요. 클라이언트가 파일을 요청하는 경우는 진짜 해당 정적 파일이 필요한 상황일 수도 있겠다는 생각이 들었어요. 로그인을 위해 페이지를 보여주는 것이 아닌 해당 페이지의 리소스가 필요한 상황? (마땅한 예시는 떠오르지가 않네요)에서 해당 요청을 통해 login.html 파일을 받아갈 수도 있을 것 같았어요. 이때 쿠기가 존재해서 리다이렉트가 되버리면 클라이언트가 예상했던 html 파일 응답을 받지 못할 것 같아요.

사실 이러한 고민이 발생하는 이유는 서버에서 JSON 형식의 응답만 제공하는 것이 아닌 정적 파일까지 제공하고 있기에, 다시 말해서 서버 사이드 렌더링이 발생하고 있기에 발생하는 문제라 생각이 들어요 🤓

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다즐의 의견 잘 들었습니다~! 저도 또하나 생각난 방법은 아예 html의 경우에는 정적 파일 경로로 접근할 수 없도록 하는것도 방법일 것 같네요. 사실 유저 입장에서는 .html로 접근한다는게 자연스럽지 않아서이기 때문인데요, 따라서 .html로 들어오는 접근의 경우 아예 막고 /login 경로로 들어왔을때에만 html 컨텐트를 응답으로 주는 것도 좋을 것 같아요!


@Override
public void service(final HttpRequest request, final HttpResponse response) throws Exception {
final HandlerMethod handlerMethod = handlerMapping.getHandlerMethod(request);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

캬 깔끔한 mapping이네요.. 리플렉션 내일 수업 배운다고 하는데 배우고 나면 다즐처럼 코드 짤 수 있겠죠? ㅎㅎ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저처럼 짜면 큰일 날 수도 있어요 🥲

@woo-chang
Copy link
Member Author

woo-chang commented Sep 12, 2023

23:46:52.257 [pool-1-thread-86] ERROR org.apache.coyote.http11.Http11Processor - Socket closed
java.net.SocketException: Socket closed
...

적어주신 해당 에러가 저의 로컬에서는 발생하지 않는데, 어떤 환경과 상황에서 발생하는지 알려주실 수 있나요 ?

@sonarcloud
Copy link

sonarcloud bot commented Sep 12, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 16 Code Smells

0.0% 0.0% Coverage
0.0% 0.0% Duplication

warning The version of Java (11.0.20.1) you have used to run this analysis is deprecated and we will stop accepting it soon. Please update to at least Java 17.
Read more here

@echo724
Copy link

echo724 commented Sep 12, 2023

엇 어제 저도 밤에 하다보니깐 환경을 헷갈렸던 것 같네요! 지금 다시 돌려보니 에러가 뜨지 않습니다! 다즐 수고 많으셨고 mvc 미션도 화이팅입니다~~~!!

@echo724 echo724 merged commit bad7596 into woowacourse:woo-chang Sep 12, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants