Trouble shooting 관련한 글은 잘 작성하지 않았는데 이번에 알게 된 정보를 정리하면 좋을 거 같아서 정리해 보려고 한다.
nginx.conf
파일에 사이즈를 늘려보자.Expo
의 ImagePicker.launchImageLibraryAsync
를 사용한다면 ios에서 quality
값에 0.2를 주자.HEIC
포맷을 사용해서 JPEG
로 변경 시 용량이 증가한다.회사에서 이미지 업로드 구현을 하는데 용량 문제가 계속 발생하였다.
에러 메세지를 살펴보니 413 Request Entity Too Large
가 발생하는 것이었다.
바로 구글신에게 검색을 진행하였다.
Nginx 413 Request Entity Too Large 에러 해결하기, 파일 업로드 사이즈라는 글이 있어서 바로 참고를 하니 nginx
를 거쳐서 파일 업로드를 할 때 용량 제한이 있는 것이었다.
기본 사이즈는 1Mbyte인데 5Mbyte까지 허용하려고 했으니 에러가 나는 게 당연했다.
따라서 nginx.conf 파일의 용량을 늘려서 해결했다!!👏👏👏
이러면 단순하게 해결했겠지만 의문이 들었다.
도대체 이미지 사이즈가 얼마길래 파일이 안 올라갈까??
🤔
그리고 5Mbyte로 올려도 안 올라가는 이미지들이 있었다.
사진첩에서 이미지의 용량을 살펴보니 ??? 5Mbytes는 무슨 2.4Mbytes였다...😱
그래서 임시로 사이즈를 올리고 서버에서 확인해보니 대략 8Mbytes 정도였고 다른 이미지들도 작으면 1.5에서 크면 2배 정도 사이즈가 커졌다...?
이미지 올릴 때 잘못된 게 있나 싶어서 일단 코드를 계속 비교했는데 다른 게 없었다.
결국 아는 형들과 오픈 채팅 방에 질문을 올렸는데 처음에는 확실한 답을 얻을 수 없었다.
그러다가 아는 형 중 한명이 예전에 ios 앱 개발을 해본적이 있어서 코드를 같이 살펴봐주었다.
아이폰에서는 이미지를 저장할 때 이미지 포맷을 전용 포맷으로 저장한다는 것을 알려주었다.
그리고 코드를 보면서 어디가 에러인 거 같은지 알려주었다.
이를 토대로 문제를 해결한 방법을 정리하려고 한다.
먼저 이미지 가져오는 코드를 살펴보니 ImagePicker.launchImageLibraryAsync
를 사용하는 것을 알 수 있었다. 그 중 quality
값이 있길래 먼가 이것과 관련있을 거 같았다.
Note: If the selected image has been compressed before, the size of the output file may be bigger than the size of the original image.
좀 더 살펴보니 위와 같은 말이 있었다.
그리고 위에서 아는 형이 알려줬던 아이폰은 다른 이미지 포맷으로 저장한다는 것이 기억났다.
일단 테스트를 위해 quality
값을 줄여보니 사이즈가 줄어드는 것을 확인했다.
그리고 위 문서 하단에 있는 View source code for ImagePicker를 눌러서 코드를 살펴보았다.
expo/packages/expo-image-picker/ios/EXImagePicker/EXImagePicker.m의 코드를 살펴보니 const CGFloat EXDefaultImageQuality = 0.2;
라는 코드가 존재했다.
추가로 NSData *data = UIImageJPEGRepresentation(image, quality == nil ? EXDefaultImageQuality : [quality floatValue]);
라는 코드가 사용되는 거 같은데 EX에만 적용이 된 거 같고 0.2를 적용한 거 같아서 quality
에 0.2를 주니 사이즈가 폰에 저장되는 것과 같았다.
아마 아이폰의 경우 quality
의 Default 값을 0.2로 해줘야하는데 실제 코드에는 적용이 안 된 거 같다.
문제점을 알았으니 Platform.OS
를 사용해 ios
인 경우를 분기처리해서 해결했다!
이렇게 해결을 하고 끝낼 수도 있지만 위의 방법을 바로 안 것은 아니고 아래의 과정들이 있었으므로 좀 더 문제 해결 방법에 대해 서술해보려고 한다.
아래의 이슈들은 react-native-image-picker
와 관련된 이슈인데 내용이 비슷해서 살펴보니 expo
에서의 이슈와 비슷한 거 같았다.
confuse about image image local size and upload size #1272
먼저 로컬 사이즈와 업로드 된 사이즈가 다르다는 이슈가 존재했다.
위의 이슈에서는 크게 해결책이 제시되어 있지 않았지만 Images posted to server via fetch get their size inflated significantly #27099 라는 이슈가 연결되어 있었다.
이제 다음 이슈를 살펴보았다.
rn-fetch-blob
을 사용해서 해결한 사람, base64
로 변경해서 해결한 사람, 새로운 버젼에서는 해결되었다는 이야기 등 많은 내용이 있었다.
영어로 나와있어도 우리에게는 구글 번역이 있으니 겁먹지 말고 천천히 살펴보자!
여러 댓글 중 MrZhaoCn
이라는 분이 제일 근본적으로 설명을 해준 거 같아서 내용을 작성해보려고 한다.
React Native에서 jpg image를 가져올 때 RCTImageLoader를 하며 다음과 같은 코드로 작성되어 있다.
NSString *mimeType = nil; NSData *imageData = nil; if (RCTImageHasAlpha(image.CGImage)) { mimeType = @"image/png"; imageData = UIImagePNGRepresentation(image); } else { mimeType = @"image/jpeg"; imageData = UIImageJPEGRepresentation(image, 1.0); } NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:mimeType expectedContentLength:imageData.length textEncodingName:nil]; [delegate URLRequest:requestToken didReceiveResponse:response]; [delegate URLRequest:requestToken didReceiveData:imageData]; [delegate URLRequest:requestToken didCompleteWithError:nil];
아까
expo
에서 봤듯이UIImageJPEGRepresentation
가 사용됨을 알 수 있다.
UIImageJPEGRepresentation 문서에서 보면JPEG
이미지를 생성해주는 함수인 것을 알 수 있다.
좀 더 내부적인 코드나 사용법을 살펴보고 싶은데 찾지 못했다 ㅠㅠ
결국 아이폰에서 저장되는 포맷의 파일의 이미지를 JPEG
로 만들면서 용량이 커졌다는 것을 알 수 있었다!
추가로 아이폰에서 어떤 형식으로 저장되는지에 대해 검색을 진행했다.
아이폰 HEIC 파일을 JPG로 변환하는 방법 그리고 HEIC 파일을 쓰면안되는 이유라는 좋을 글이 많이 참고가 됐다.
iOS11이 되면서 사진 파일 확장자가 HEIC
포맷으로 저장이 되는 것이었다.
HEIF라고도 하고 HEIC
라고도 적었는데 HEIF는 High Efficiency Image Format이고 HEIC는 High Efficiency Image Container이다. 둘다 사용할 수 있는 단어인 거 같다.
특징은 다음과 같다.
아이폰에서 설정 -> 카메라 -> 포멧에서 설정할 수 있다.
거의 비슷한 위치에서 촬영한 이미지 파일들 정보들은 다음과 같았다.
(이미지가 너무 크다...)
1. HEIF 파일
2. JPEG 파일
용량이 2.9MB와 4MB인 것을 알 수 있다.
만약 아이폰에서 찍은 사진이 어디선가 안 보인다면 JPEG로 바꾸는 작업을 통해 해결할 수 있을 거 같다.
이번 문제를 해결하기위해 여러 곳에 질문도 했고 많은 이슈도 찾아보게 되었다.
최대한 조사한 정보를 제공하기 위해서 노력을 했는데 누군가 이런 문제를 직면했을 때 도움이 되면 좋겠다.
좀 더 수정하면 좋을 거 같은 것은 Platform.OS
에서 ios
인 경우 quality
값을 0.2를 줬는데 HEIF
포맷이 아닌 경우에도 적용이 될 수도 있어서 좀 고려해봐야겠다. 물론 해상도가 크게 나쁘지지는 않아서 큰 문제는 없지만 테스트를 좀 더 해봐야겠다.