iOS 앱에서 사진을 골라 서버로 올리고 처리 결과를 받아오는 과정을 URLSession으로 구현하는 튜토리얼의 1편이다. 앨범·카메라 접근부터 업로드 태스크 구성, 순서 보장을 위한 세마포어 사용까지 이어진다. 서버 쪽 Flask API 구현은 2편으로 넘긴다.
핵심 포인트- UIImagePickerController 하나로 앨범 선택과 카메라 촬영 인터페이스를 모두 처리한다.
- 실행 전 Info.plist에 앨범·카메라 권한 설명을 넣어야 한다.
- 파일 업로드에는 URLSessionUploadTask를 쓰며 POST 또는 PUT만 지원한다.
- 이미지 바이너리는 Content-Type을 application/octet-stream으로 보내고 파일명은 커스텀 헤더로 전달한다.
- 업로드가 끝나기 전에 결과 화면으로 넘어가는 문제를 DispatchSemaphore로 막는다.
상세 정리- 배경: 모바일 앱 대부분은 서버 통신 없이는 제 기능을 못 한다. 정보를 읽고 글과 사진을 올리고 고치는 일이 모두 통신 위에서 이뤄진다.
- 예제 범위: 앱에서 사진을 서버로 보내고 처리 값인 이미지 크기를 받아 출력하는 흐름으로 네트워킹 과정을 훑는다.
- 소스 타입 확인: isSourceTypeAvailable로 photoLibrary와 camera 각각의 사용 가능 여부를 먼저 확인하고 분기한다.
- 피커 설정: delegate를 self로 두고 sourceType을 지정하며 mediaTypes에 kUTTypeImage를 넣어 이미지만 받도록 제한한다.
- 편집 옵션: 앨범 선택 경로에는 allowsEditing을 켜고 카메라 촬영 경로에는 꺼서 경로별로 다르게 뒀다.
- 표시: present로 현재 뷰 컨트롤러 위에 피커를 띄우면 앨범 또는 카메라 화면이 뜬다.
- 네트워킹 선택: Alamofire나 Moya 같은 라이브러리도 있지만 가장 기본이 되는 URLSession을 썼다. HTTP와 HTTPS로 콘텐츠를 올리고 내리는 애플 표준 API다.
- 태스크 선택: 앱에서 웹 서버로 Data 객체나 파일 데이터를 올릴 수 있는 URLSessionUploadTask를 쓴다.
- 메서드 비교: GET은 조회용이고 URL에 데이터가 노출되며 캐싱이 가능한 반면, POST는 생성용이고 본문에 데이터를 실으며 캐싱되지 않는다. 사진 업로드에는 POST가 적절하다고 판단했다.
- 요청 구성: NSMutableURLRequest에 httpMethod를 POST로 두고 Content-Type을 application/octet-stream, X-FileName을 img로 설정한다.
- 데이터 변환: UIImage를 pngData()로 바꿔 uploadTask의 from 파라미터로 넘긴다.
- 응답 처리: completionHandler에서 HTTPURLResponse의 statusCode를 분기하고, 응답 데이터를 UTF-8 문자열로 디코딩하며, error도 함께 처리한다.
- 순서 문제: 사진 전송, 서버 처리, 결과 출력이 차례로 진행돼야 하는데 비동기 완료 전에 화면이 넘어가면 의도하지 않은 결과가 나온다.
- 세마포어 사용: DispatchSemaphore를 0으로 만들고 completionHandler 끝에서 signal, 호출부에서 wait을 걸어 임계 영역을 만든다. 공유 자원 접근에 동기화를 거는 전형적인 용법이다.
- 다음 편 예고: 사진을 받아 원하는 작업을 하는 API를 만들어 서버에 올리고 결과를 받아 처리하는 부분을 이어서 다룬다.
왜 읽나외부 라이브러리 없이 URLSession만으로 이미지 업로드를 붙일 때 헤더 구성과 비동기 순서 보장 방식을 한 번에 확인할 수 있다.