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단계] 에단(김석호) 미션 제출합니다. #422

Merged
merged 43 commits into from
Sep 13, 2023

Conversation

cookienc
Copy link

@cookienc cookienc commented Sep 8, 2023

안녕하세요 무민! 에단입니다. 4단계까지 완료해서 pr 보냅니다.
이번 단계에서 변경사항은 다음과 같습니다.

  1. Controller를 도입해서 순환참조가 없게 패키지 분리
  2. 요구사항으로 인해 HttpResponse의 값을 builder 패턴에서 setter로 변경
  3. E2E 테스트 추가
    시간 나실때 천천히 리뷰해주세요. 이번에도 잘 부탁드립니다🙇‍♂️🙇🙇‍♀️

@cookienc cookienc self-assigned this Sep 8, 2023
Copy link
Member

@parkmuhyeun parkmuhyeun left a comment

Choose a reason for hiding this comment

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

고생하셨습니다 에단~

3, 4단계 미션 잘 구현해주신거 같아요. 🙌🙌
객체 분리 후 많은 중복이 줄어들어 깔끔해졌네요.
Http11Processor test + StubSocket 만드느라 힘드셨을거 같아요ㅎㅎ (시간 되시면 단위 테스트까지?ㅋㅋㅋㅋㅋ)

아래 코멘트들 확인 부탁드립니다!


import java.io.IOException;

public abstract class RequestController implements Controller {
Copy link
Member

Choose a reason for hiding this comment

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

Controller interface에 다음과 같이 사용할 수 도 있을텐데 abstract class 사용한 이유가 궁금합니다!

public interface Controller {
    
    default void service(final HttpRequest request, final HttpResponse response) throws IOException {
        if (request.isSameRequestMethod(HttpMethod.GET)) {
            doGet(request, response);
            return;
        }

        if (request.isSameRequestMethod(HttpMethod.POST)) {
            doPost(request, response);
            return;
        }

        throw new UnsupportedOperationException("지원하지 않는 HTTP Method 입니다.");
    }

    void doPost(final HttpRequest request, final HttpResponse response);

    void doGet(final HttpRequest request, final HttpResponse response) throws IOException;
}

Copy link
Author

Choose a reason for hiding this comment

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

default 메서드는 java8에서 기존 인터페이스를 유지하면서 새로운 기능을 추가하려고 할 때 호환성을 위해서 추가된걸로 알고 있습니다. 그래서 처음 만드는 입장에서 default가 생성된 이유와 맞지 않아서 abstract class로 생성했습니다.

Comment on lines +29 to +31
response.changeStatusLine(StatusLine.from(StatusCode.OK));
response.addHeader(CONTENT_TYPE, ContentType.HTML.getValue());
response.changeBody(new HttpBody(HOME_MESSAGE));
Copy link
Member

Choose a reason for hiding this comment

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

statusLine은 정적팩토리메서드로 HttpBody는 생성자로 생성하고 있는데 혹시 기준이 있나요?

Copy link
Author

Choose a reason for hiding this comment

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

특별한 로직 같은게 있으면 정팩메를 씁니다! StatusLine에 있는 from 메서드는 Protocol이 기본으로 들어가 있어서 로직으로 봤습니다.

}
}

private static User getValidateUser(final HttpRequest request) {
Copy link
Member

Choose a reason for hiding this comment

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

메서드 추출하면서 아래 부분들에 static이 붙은거 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

지우겠습니다ㅜㅜ @parkmuhyeun 혹시 이거 자동으로 없애는 팁있나요?

Copy link
Member

@parkmuhyeun parkmuhyeun Sep 13, 2023

Choose a reason for hiding this comment

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

이거 찾아봤는데 딱히 없는거 같아요 ㅠㅠ 저도 자주 실수하는 부분..

Comment on lines 41 to 59
if (request.isRequestUriEndsWith(HTML.getFileExtension())) {
createHttpResponseByContentTypeAndPath(response, HTML, filePath);
return;
}

if (request.isRequestUriEndsWith(JS.getFileExtension())) {
createHttpResponseByContentTypeAndPath(response, JS, filePath);
return;
}

if (request.isRequestUriEndsWith(CSS.getFileExtension())) {
createHttpResponseByContentTypeAndPath(response, CSS, filePath);
return;
}

if (request.isRequestUriEndsWith(ICO.getFileExtension())) {
createHttpResponseByContentTypeAndPath(response, ICO, filePath);
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

ContentType Enum 만드셨으니 충분히 중복제거 할 수 있을 거 같아요!

return requestLine.containsRequestUri("?");
}

public boolean isRequestUriEndsWith(final String uri) {
Copy link
Member

Choose a reason for hiding this comment

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

isEndsWithRequestUri가 좀 더 자연스러운거 같아요!


public class SessionManager implements LoginManager {

private static final Map<String, Session> SESSIONS = new HashMap<>();
private static final Map<String, Session> SESSIONS = new ConcurrentHashMap<>();
Copy link
Member

Choose a reason for hiding this comment

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

혹시 ConcurrentHashMap에 대해 더 자세히 알고 싶으시다면
https://parkmuhyeun.github.io/woowacourse/2023-09-09-Concurrent-Hashmap/

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

Copy link
Author

Choose a reason for hiding this comment

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

댓글 남겼습니닼ㅋㅋㅋㅋ

private final HttpRequestParser httpRequestParser;

public Http11Processor(final Socket connection) {
public Http11Processor(final Socket connection, final RequestHandler requestHandler) {
Copy link
Member

Choose a reason for hiding this comment

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

여러 생성자가 생성되고 있는데 혹시 Http11Processor의 생성자가 언제 호출 되시는지 아시나요?

Copy link
Author

Choose a reason for hiding this comment

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

클라이언트가 요청 들어올때 생성되나요? 잘 모르겠어요

Copy link
Member

Choose a reason for hiding this comment

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

Connector에서 서버소켓이 수락한 후 process 메서드가 실행되면 그때 processor가 생성되더라구요.

그럼 요청이 들어올 때마다 현재 생성자들을 다시 생성해줄 필요가 있을까?라고 생각이 들어서 위와같이 남겼어요!

Copy link
Author

Choose a reason for hiding this comment

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

저는 상관없다고 생각해요. 왜냐하면 세션같은 건 static으로 떠있어서 공유되기 때문에 상관없을 것 같고, 객체 생성비용만 생길것같은데, 오히려 싱글톤으로 구현하면 예상하지 못한 오류가 날수도 있을것 같아요

Copy link
Member

Choose a reason for hiding this comment

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

상태가 없는 HttpRequestParser 같은 경우 요청이 들어올 때 마다 새로 생성하는 것보다 한번만 만들면 더 좋지 않을까요

class Register {

@Test
void register으로_POST_요청하면_해당_페이지로_이동한다() throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

해당_페이지 보다 index_html로 이동한다가 좀 더 이해하기 좋을 거 같아요

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다!

}

@Test
void register으로_GET_요청하면_register_html로_리다이렉트_된다() throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

테스트 내용이 뭔가 잘못된거 같아요. 한번 파라미터들 확인해주세요!!

Copy link
Author

Choose a reason for hiding this comment

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

일단 제가 테스트 코드 이름을 잘못적은것 같네요. register으로_GET_요청하면_register_html로_이동한다가 맞긴한데 어떤 점이 문제가 될까요?

Copy link
Member

Choose a reason for hiding this comment

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

현재 requestURI가 login이 아니라 register가 되어야 되는거 아닌가요

Copy link
Author

@cookienc cookienc Sep 13, 2023

Choose a reason for hiding this comment

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

아아 맞네요! 왜 저는 이게 안보였을까요.. 매의 눈이시네요

@@ -8,41 +17,58 @@
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.EnumMap;

public class StubSocket extends Socket {
Copy link
Member

Choose a reason for hiding this comment

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

👍🏻👍🏻

@parkmuhyeun parkmuhyeun self-requested a review September 9, 2023 21:05
Copy link
Member

@parkmuhyeun parkmuhyeun left a comment

Choose a reason for hiding this comment

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

코드 스멜 제거까지 Good!

몇가지 궁금한 점 코멘트 남겼으니 확인해보시고 다시 리뷰 요청 부탁드립니다!

@sonarcloud
Copy link

sonarcloud bot commented Sep 13, 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 0 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

@cookienc
Copy link
Author

안녕하세요 무민~
꼼꼼한 리뷰 감사합니다. 덕분에 이번 미션에서 많이 배웠습니다!
리뷰 내용 반영했습니다 :)

Copy link
Member

@parkmuhyeun parkmuhyeun left a comment

Choose a reason for hiding this comment

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

여기서 마무리 해도 충분할 것 같아서 이만 머지하겠습니다!
톰캣 미션하는 동안 고생 많으셨어요~ 저도 많이 배워갑니다.

남은 미션들도 화이팅 🙌

private final HttpRequestParser httpRequestParser;

public Http11Processor(final Socket connection) {
public Http11Processor(final Socket connection, final RequestHandler requestHandler) {
Copy link
Member

Choose a reason for hiding this comment

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

상태가 없는 HttpRequestParser 같은 경우 요청이 들어올 때 마다 새로 생성하는 것보다 한번만 만들면 더 좋지 않을까요

@parkmuhyeun parkmuhyeun merged commit c5efff1 into woowacourse:cookienc Sep 13, 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