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

[톰캣 구현하기 - 1, 2단계] 케로(김지현) 미션 제출합니다. #363

Merged
merged 23 commits into from
Sep 10, 2023

Conversation

jyeost
Copy link

@jyeost jyeost commented Sep 4, 2023

안녕하세여 바론 ㅎㅅㅎ
케로입니더 ㅎㅎ 리뷰를 열심히 해달라고 부탁했지만....
2단계 구현을 전부 다하지는 못한 점 미리 사과드리옵니다....

시간 관계상 2단계의 2번째까지 구현 완료하였으며
테스트 코드도 작성하지 못했습니다.... ヽ(;▽;)ノ

최대한 보기 좋게 작성하려 노력했는데
로직이 복잡하다 보니.... (변명)(눈물)
이해가 안되는 점이 있다면 바아로 디엠 부탁드립니다...

Copy link

@somsom13 somsom13 left a comment

Choose a reason for hiding this comment

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

안녕하세요 케로~!~!!! 바론입니다 🙇‍♀️

전체적인 구조가 너무 깔끔해서 코드 리뷰 하면서 많이 배웠습니다 ㅎ.ㅎ
그래서 걱정하신 것과는 다르게 로직를 이해하기 어렵지 않았어용 ( •̀ .̫ •́ )✧

케로가 말씀해주신 것 처럼 아직 구현이 안 된 부분들을 마저 구현해주시면 좋을 것 같아요!

간단한 코멘트와 질문들만 남겼습니당 ㅎ.ㅎ
고생하셨어요~!~~!! 👏 👍 ❤️‍🔥

@@ -96,6 +99,7 @@ class OutputStream_학습_테스트 {
* try-with-resources를 사용한다.
* java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다.
*/
outputStream.close();
Copy link

Choose a reason for hiding this comment

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

케로쨩 저도 처음에 이렇게 학습 테스트 작성했었는데 위에 적힌 todo를 보니까 try-with-resource 를 활용하라고 되어있더라구요 (•_•)

케로도 못 보고 지나친 것 같아서 코멘트 남겨봅니당 ㅎ.ㅎ 이건 이번 미션 관련 코멘트가 아니라서 그냥 스킵하셔도 돼요~!

Copy link
Author

Choose a reason for hiding this comment

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

기차나서 이악물고 모른척 했는데(?)
덕분에 수정했습니다 ◡̈♥

Comment on lines 6 to 9
public interface Controller {

Response handle(Request request);
}
Copy link

Choose a reason for hiding this comment

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

Controller 인터페이스 짱이네용 👍 👍 깔꼼 그자체

Comment on lines 32 to 34
if(!requestBody.containsKey(QUERY_ACCOUNT_KEY) || !requestBody.containsKey(QUERY_PASSWORD_KEY)){
return new PathResponse("/401", HttpURLConnection.HTTP_UNAUTHORIZED, "Unauthorized");
}
Copy link

Choose a reason for hiding this comment

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

로그인에 필요한 입력값이 모두 들어오지 않아서 예외 페이지를 반환하는 상황인 것 같아요!

혹시 401 Unauthorized 상태코드를 선택하신 이유가 있을까요 ?.?

Copy link
Author

Choose a reason for hiding this comment

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

로그인 실패 상황을 어떻게 표현할까 하다가 이렇게 작성했습니다..
지금은 커스텀 예외를 던지도록 변경하였습니다


@Override
public Response handle(Request request) {
return new StringResponse("Hello world!", HttpURLConnection.HTTP_OK, "OK");
Copy link

Choose a reason for hiding this comment

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

HttpURLConnection 처음봐서 찾아봤는데 내부에 상수로 HTTP 상태코드값을 가지고 있네요!!! 😮 😮

그런데 아쉽게 "OK" 같은 상태코드에 대한 설명은 따로 관리하지 않는 것 같아서 상태코드 숫자와 의미를 함께 관리하는 다른 방법을 생각해볼 수도 있을 것 같아요! (저는 상태코드값이랑 이름이 아직도 헷갈리더라구요 ㅎㅎ)

이건 제 개인적인 의견이라 케로가 선호하시는 방법으로 3단계 리팩터링 때 고민해보시면 좋을 것 같습니당~!

Copy link
Author

Choose a reason for hiding this comment

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

구현할때는 시간이 없어서 이렇게 막구현 했습니다 ㅠㅠ
리팩터링 하면서 Enum 클래스로 따로 관리하니 확실히 보기 깔끔하더라구영!!
감사합니다 바론 ㅎㅅㅎ

return new PathResponse("/index", HttpURLConnection.HTTP_MOVED_TEMP, "Temporary Redirect");
}

return new PathResponse("/401", HttpURLConnection.HTTP_UNAUTHORIZED, "Unauthorized");
Copy link

Choose a reason for hiding this comment

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

이 Response는 401.html 정적 파일을 읽어와서 반환하는 것 같은데
위에서 GET /login 에 대해서는 StaticResponse를 사용하고 여기에서는 PathResponse를 사용하신 이유가 따로 있는지 궁금해요!!

Copy link
Author

Choose a reason for hiding this comment

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

pathResponse를 만드는게 더 쉬웠나... 그래서 그랬던 것 같아요...
다만 코드 변동이 많아서 지금은 없는 객체입니다 ㅜㅜ

현재는 ResponseEntity 객체를 하나두고 여러가지 팩토리 메서드로 분리하여 관리하도록 하였습니다 !!

Comment on lines 39 to 41
RequestMessage header = RequestMessage.from(bufferedReader);

return getRequest(method, pathFromStartLine, header.getRequestBody());
Copy link

Choose a reason for hiding this comment

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

header라는 이름의 RequestMessage에서 body가 추출되는게 사알짝 헷갈리게 느껴지는 것 같아요 ╯︿╰

header와 body가 명확하게 이해될 수 있도록 할 수 있는 다른 방법은 없을지 고민해보면 좋을 것 같아요~!!

Copy link
Author

Choose a reason for hiding this comment

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

reader라는 객체를 만들어서 startLine headers body를 각각 읽어올 수 있도록 수정했습니다 !

Comment on lines 3 to 8
public class PathResponse implements Response{
private static final String FILE_TYPE_FIXTURE = "html";
private static final String FILE_EXTENSION_DELIMITER = ".";


private final String path;
Copy link

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.

짜잔~!! 클래스를 업애버렸습니다 ㅎㅅㅎ

private final int statusCode;
private final String statusValue;

public StaticResponse(final String fileType, final String path, int statusCode, String statusValue) {
Copy link

Choose a reason for hiding this comment

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

파라미터에 final 키워드를 통일해서 붙이면 좋을 것 같아요!.! 😊

다른 클래스 내의 변수, 파라미터도 final 키워드를 통일하면 좋을 것 같습니당

Copy link
Author

Choose a reason for hiding this comment

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

이제서야 인텔리제이 설정을 추가하였습니다... !!!
감사합니다 ㅜㅜ 흑흑

Comment on lines +20 to +25
static {
urlMapper.put("/", new HelloWorldController());
urlMapper.put("/login", new LoginController());
urlMapper.put("/register", new RegisterController());
}

Copy link

Choose a reason for hiding this comment

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

정말 어마어마하네요 케로쨩... o( ̄▽ ̄)d
맛있게 배워갑니다

Copy link
Author

Choose a reason for hiding this comment

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

굳굳 따봉따봉>ㅡ<

Comment on lines 18 to 21
if(request.isFile()){
return doProcess(staticController, request);
}
return doProcess(dynamicController, request);
Copy link

Choose a reason for hiding this comment

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

정적 파일 요청과 동적 요청을 분리하는 부분이군요!!!!
이렇게 두 종류의 요청을 처리하는 controller를 분리하면 어떤 장점이 있나용?.?

그나저나 정말 어마어마합니다 케로쨩...

Copy link
Author

@jyeost jyeost Sep 5, 2023

Choose a reason for hiding this comment

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

스프링에서 톰캣이 서블렛을 띄워줄때 정적 파일 요청이라면 어뎁터 핸들러를 매핑하지 않는다고 알고 있어서 비슷하게 처리 하고 싶어서 고민하다가 나온 결과입니다... ヽ(;▽;)ノ
이렇게 작성해주니 예외처리를 한 곳에서 하기 편하던데용?!?!

Choose a reason for hiding this comment

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

오홍 그렇군요~~!!!! 확실이 굳이 정적 파일을 위해 매핑할 필요가 없어질 것 같아요 👍 따봉 드립니다

…, 해당 세션 매니저에 Jsessionid에 일치하는 회원정보가 있다면 index로 redirect하도록 구현
@sonarcloud
Copy link

sonarcloud bot commented Sep 10, 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 5 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

Copy link

@somsom13 somsom13 left a comment

Choose a reason for hiding this comment

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

케로..... 짧은 시간 내에 어마어마한 수정과 기능 구현을 해오셨네요 😲

원래도 좋았던 구조가 더 좋아진 것 같아서 따봉들 잔뜩과 아아주 간단한 코멘트 하나를 남겨두었습니다 ㅎ.ㅎ

너무 고생하셨어요~!~!! 👍 ❤️‍🔥

Comment on lines +26 to +31
if (request.isPost()) {
return login(request);
}
if (request.isGet() && request.hasQueryString()) {
return loginInConsole(request);
}

Choose a reason for hiding this comment

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

미션에 주어진 두 가지 로그인 방법이 다 되는군여 따따봉 👍 👍

Comment on lines +42 to +47
final User user = InMemoryUserRepository.findByAccount(account)
.orElseThrow(MemberNotFoundException::new);
if (user.checkPassword(password)) {
log.info("user : {}", user);
}
return ResponseEntity.fromViewPath(request.httpVersion(), request.getPath(), ResponseStatus.OK);

Choose a reason for hiding this comment

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

요롷게 되면 account가 없는 회원에 대해서는 처리가 잘 되지만, account는 맞는데 비밀번호가 틀린 회원도 로그인이 되었다고 처리되어 버릴 것 같아요! 😿

앗 밑의 login 메서드는 이 상황도 처리가 되어있네용 ㅎ.ㅎ 확인해씁니다~~~

Copy link
Author

Choose a reason for hiding this comment

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

사실 쿼리 파라미터로 로그인 하는 경우는 없을 것 같아서 수정하지 않았습니다 ㅎㅎ

Comment on lines +17 to +23
private static final Map<String, FileType> map = new HashMap<>();

static {
for (FileType fileType : FileType.values()) {
map.put(fileType.extension, fileType);
}
}

Choose a reason for hiding this comment

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

댑악 👍 😮 😲

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.

클래스 분리 좋와용 ㅎㅅㅎ

Comment on lines +16 to +18
for (final String oneCookie : requestCookie.split("; ")) {
if (!oneCookie.contains("=")) {
continue;

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.

근데 상수로 추출할때 어떤 필드명을 써야 이해하기 쉬울까요...
전 사실 이 쪽이 보기 더 편하답니다... ( ノω-、)

Comment on lines +23 to +31
final ArrayList<String> lines = new ArrayList<>();
while (true) {
final String line = reader.readLine();
if ("".equals(line)) {
break;
}
lines.add(line);
}
return lines;

Choose a reason for hiding this comment

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

BufferedReader에 담긴 모든 라인들을 다 읽어오는 거라면 lines() 메서드를 활용해보는 것은 어떨까용~??~?? (그런 상황이 아니라면 지금 흐름이 좋은 것 같습니다 ㅎ.ㅎ)

Copy link
Author

Choose a reason for hiding this comment

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

마지막 requestBody라인을 제외하고 모두 읽어오는 메서드 입니다 ..!
근데 body도 한꺼번에 읽어와서 처리할 수 있나 해봐야겠어용 ㅎㅅㅎ

Choose a reason for hiding this comment

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

Content-LengthContent-Type 이 따로 객체 분리가 된 이유가 있을까요 ?.?

Copy link
Author

Choose a reason for hiding this comment

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

각각 header에서 한 라인을 담당하고 있기 때문에 분리해주는 것이 header를 만들기 편할 것 같다고 생각했습니다

Comment on lines +27 to +29
return headers.stream()
.collect(Collectors.joining(" " + System.lineSeparator()));
}

Choose a reason for hiding this comment

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

👍

@@ -23,7 +23,7 @@ void process() {
processor.process(socket);

// then
var expected = String.join("\r\n",
var expected = String.join(System.lineSeparator(),
Copy link

@somsom13 somsom13 Sep 10, 2023

Choose a reason for hiding this comment

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

HTTP는 라인 구분자로 \r\n 을 쓴다고 알고있어요! 이 상황에서 System.lineSeparator() 를 쓰게된다면 운영체제에 따라 구분자가 달라질 수도 있지 않을까요?.?

((근데 지금보니까 제가 지난번 리뷰에서는 System.lineSeparator() 짱이라고 리뷰 남겼었네요.. 와리가리해서 죄송합니다 케로쨩... 😓 😓 ))

Copy link
Author

Choose a reason for hiding this comment

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

헉.... 아뇨
저갓은 핑프에게 좋은 정보를 알려주셔서 감사합니다...
찾아보니까 맞네용...ㅜㅜ
바로 수정하겠습니다.

@somsom13 somsom13 merged commit 1064589 into woowacourse:jyeost Sep 10, 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