처음 설정해둔 목표를 확인해보겠습니다.
commons-cli 라이브러리를 사용해 사용자가 입력한 파라미터들을 파싱할 수 있습니다. HTTP 메서드 지정, 헤더 지정, 데이터 입력이 잘 동작하는 걸 확인할 수 있습니다.
GET, POST 등의 동작하는 걸 확인할 수 있습니다. 허용되지 않는 메서드가 입력되면 오류를 반환합니다.
중복되는 key로 헤더를 가질 수 있습니다. Header는 대소문자를 구별하지 않습니다.
key1=value1&key2=value2
형태로 입력하면 application/json 타입의 Body를 만들어줄 수 있습니다.
결과적으로 입력한 값을 통해 HTTP 메세지를 만들고, 응답을 받아와 화면에 출력하는 기능을 구현할 수 있었습니다.
HTTP 메세지를 보내고 받기 위해 소켓을 사용했습니다. 기존에는 별다른 의문조차 갖지 못했는데, 이번 구현을 통해 클라이언트는 어떻게 HTTP를 사용해 요청을 보내고 응답을 받는지 기술적인 부분을 알 수 있었습니다.
인터넷을 찾아봐도 공백 라인이 왜 필요한지, 정보를 찾을 수 없었습니다. 직접 구현을 해보니, 공백 라인이 존재하지 않으면 헤더와 바디를 구분할 수 없다는 걸 깨닫게 되었습니다.
이 부분 역시 마찬가지로, body에 데이터가 있을 때, Content-Type을 추가해야 하는 이유를 찾을 수 없었습니다. 하지만, HTTP 파싱 어플리케이션은 글자 크기를 통해 Body가 끝나는 지점을 찾는다는 걸 알 수 있었습니다.
실제로 구현할 때 처음에 body 역시 readline으로 구현을 했습니다. 그러나 끝나는 지점을 알 수 없어 Socket이 닫히기 전까지 마지막 line을 받아오지 않는 이슈가 있었습니다. BufferedReader의 read 메서드로 변경을 해주면서 해당 사실을 깨달을 수 있었습니다.
여러가지 요청을 보내면서 알게된 사실인데, chunked라는 방식으로 데이터를 전송할 수 있다는 걸 알게 되었습니다.
객체지향적으로 짜려고 노력했지만, 여전히 코드가 지저분해보입니다. 크게 세 가지의 아쉬움이 있습니다.
만약 이 글을 읽으신 분들이라면, CURL을 한 번 구현해보는걸 추천합니다. 학습한 내용
블록에 적어둔 내용을만 가지고도 충분히 구현해볼만 합니다. 어려우실 것 같다면 제 블로그를 보고 따라서 작성하셔도 좋고, 해당 레포지토리를 들어와서 제 커밋기록을 따라가면서 학습하는 것도 좋을 것 같습니다.
어플리케이션을 만들면서, 그리고 글을 쓰면서 배운 내용들이 많아 어플리케이션을 만드는 과정이 일관성이 없습니다. 그래서 커밋이 지저분하지만, 누군가에겐 도움이 될거라 생각해 부끄럽지만 링크를 첨부하겠습니다.
읽어주셔서 감사합니다.