-
Notifications
You must be signed in to change notification settings - Fork 0
이경민 4주차 학습일지
Java-was 프로젝트를 진행하면서 HTTP Multi Part Request에 대해서 파싱을 하고 있었습니다. 파서를 구현한 이후 사진 추가 테스트를 진행했을때 간헐적으로 에러가 발생하는 현상이 발생했습니다.
로그를 확인해보니 Multi Part 파싱 과정에서 오류가 있는 것이라고 판단되어 분석을 시작했습니다.
다양한 시도를 해보던 중 사진의 크기가 약 1MB 이상인 경우 오류가 발생하는 것을 확인할 수 있었습니다.
이를 바탕으로 1MB 이상의 파일을 포함한 요청에 대해서 디버깅을 시작했습니다.
디바깅을 하던 중 이상한 점을 하나 발견했습니다. body를 받는과정에서 데이터가 누락되는 것이었습니다.
기존 코드는 아래와 같습니다
byte[] buffer = new byte[contentLength];
if (bufferedInputStream.read(buffer, 0, contentLength) == -1) {
throw new HttpCommonException("요청 바디가 없습니다.", StatusCode.BAD_REQUEST);
}
BufferedInputStream에 대한 JAVADOC를 읽던 도중 read1() 메서드에서 아래와 같은 주석을 발견했습니다.
/* If the requested length is at least as large as the buffer, and
if there is no mark/reset activity, do not bother to copy the
bytes into the local buffer. In this way buffered streams will
cascade harmlessly. */
요청된 길이가 최소한 버퍼만큼 크고 마크/리셋 활동이 없는 경우, 바이트를 로컬 버퍼에 복사하지 마세요. 이렇게 하면 버퍼링된 스트림이 무해하게 캐스케이드됩니다.
BufferedInputStream를 생성할 때 설정한 버퍼 사이즈보다 큰 요청에 대해서는 처리가 안된다는 주석이었습니다.
중간 버퍼를 활용하자! 라는 아이디어로 문제 해결에 도전했습니다.
기존 BufferedInputStream -> byte[] body
에서 BufferedInputStream -> byte[] buffer -> byte[] body
방식으로 중간 버퍼를 활용했습니다.
byte[] multiPartBody = new byte[contentLength];
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int offset = 0;
while (offset < contentLength) {
int size;
if ((size = bufferedInputStream.read(buffer, 0, DEFAULT_BUFFER_SIZE)) == -1) {
throw new HttpCommonException("요청 바디가 없습니다.", StatusCode.BAD_REQUEST);
}
System.arraycopy(buffer, 0, multiPartBody, offset, size);
offset += size;
}
이와 같이 수정한 이후에는 사이즈가 큰 이미지 파일을 정상적으로 파싱할 수 있었습니다 :D