[swift] Swift로 파일 업로드 요청 보내기

이번 포스팅에서는 Swift를 사용하여 파일을 업로드하는 방법에 대해 알아보겠습니다.

Alamofire을 이용한 파일 업로드

Alamofire는 Swift의 인기있는 HTTP 통신 라이브러리 중 하나입니다. 다음은 Alamofire를 사용하여 파일 업로드 요청을 보내는 간단한 예제입니다.

먼저, Alamofire를 프로젝트에 추가해야 합니다. 프로젝트의 Podfile에 다음과 같이 추가하고, 터미널에서 pod install을 실행하여 라이브러리를 설치합니다.

pod 'Alamofire'

다음은 파일을 업로드하는 함수의 예제입니다.

import Alamofire

func uploadFile(url: String, fileURL: URL, parameters: [String: String]?, completion: @escaping (Result<String, Error>) -> Void) {
    AF.upload(multipartFormData: { multipartFormData in
        // 파일 데이터 추가
        multipartFormData.append(fileURL, withName: "file")
        
        // 추가적인 파라미터가 있을 경우 추가
        if let parameters = parameters {
            for (key, value) in parameters {
                multipartFormData.append(value.data(using: .utf8)!, withName: key)
            }
        }
    }, to: url).responseString { response in
        switch response.result {
        case .success:
            completion(.success("파일 업로드 성공"))
        case .failure(let error):
            completion(.failure(error))
        }
    }
}

위의 함수를 사용하면, url에 지정된 엔드포인트로 파일을 업로드할 수 있습니다. fileURL은 업로드할 파일의 로컬 경로이며, parameters는 추가적인 파라미터를 포함하는 딕셔너리입니다.

함수를 사용하는 예제는 다음과 같습니다.

let fileURL = Bundle.main.url(forResource: "example", withExtension: "jpg")!
let parameters = ["name": "example.jpg"]

uploadFile(url: "http://example.com/upload", fileURL: fileURL, parameters: parameters) { result in
    switch result {
    case .success(let message):
        print(message)
    case .failure(let error):
        print(error.localizedDescription)
    }
}

위의 예제에서는 example.jpg라는 파일을 업로드하고 있습니다. 업로드 성공 시 “파일 업로드 성공” 메시지를 출력하고, 실패 시 에러 메시지를 출력하도록 되어 있습니다.

URLSession을 이용한 파일 업로드

Alamofire를 사용하지 않고 Swift의 기본 URLSession을 이용해서도 파일 업로드를 할 수 있습니다. 다음은 URLSession을 사용하여 파일 업로드를 요청하는 예제입니다.

func uploadFile(url: String, fileURL: URL, parameters: [String: String]?, completion: @escaping (Result<String, Error>) -> Void) {
    var request = URLRequest(url: URL(string: url)!)
    request.httpMethod = "POST"
    
    // 파일 데이터
    let fileData = try! Data(contentsOf: fileURL)
    
    // HTTP Body 생성
    let boundary = "Boundary-\(UUID().uuidString)"
    let contentType = "multipart/form-data; boundary=\(boundary)"
    request.setValue(contentType, forHTTPHeaderField: "Content-Type")
    
    var body = Data()
    body.append("--\(boundary)\r\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(fileURL.lastPathComponent)\"\r\n".data(using: .utf8)!)
    body.append("Content-Type: application/octet-stream\r\n\r\n".data(using: .utf8)!)
    body.append(fileData)
    body.append("\r\n".data(using: .utf8)!)
    
    // 추가적인 파라미터
    if let parameters = parameters {
        for (key, value) in parameters {
            body.append("--\(boundary)\r\n".data(using: .utf8)!)
            body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
            body.append("\(value)\r\n".data(using: .utf8)!)
        }
    }
    body.append("--\(boundary)--\r\n".data(using: .utf8)!)
    
    // 요청에 바디 설정
    request.httpBody = body
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        if let error = error {
            completion(.failure(error))
            return
        }
        
        // 응답 처리
        if let data = data, let string = String(data: data, encoding: .utf8) {
            completion(.success(string))
        } else {
            completion(.failure(NSError(domain: "File upload error", code: 0, userInfo: nil)))
        }
    }
    
    task.resume()
}

위의 함수를 사용하는 방법은 Alamofire를 사용하는 경우와 동일합니다. 단, uploadFile 함수의 구현이 다르기 때문에, 업로드 요청 시 약간의 차이가 있을 수 있습니다.

다음은 URLSession을 사용하는 예제입니다.

let fileURL = Bundle.main.url(forResource: "example", withExtension: "jpg")!
let parameters = ["name": "example.jpg"]

uploadFile(url: "http://example.com/upload", fileURL: fileURL, parameters: parameters) { result in
    switch result {
    case .success(let message):
        print(message)
    case .failure(let error):
        print(error.localizedDescription)
    }
}

위의 예제에서도 example.jpg 파일을 업로드하고 있습니다. 업로드 성공 시 서버로부터 받은 문자열을 출력하고, 실패 시 에러 메시지를 출력하도록 되어 있습니다.

마무리

이번 포스팅에서는 Swift로 파일 업로드 요청을 보내는 방법에 대해 알아보았습니다. Alamofire를 사용하면 간편하게 파일 업로드를 구현할 수 있으며, URLSession을 사용하여 직접 업로드 요청을 보낼 수도 있습니다. 프로젝트의 요구사항에 맞게 적절한 방법을 선택하여 파일을 업로드해 보세요.