[iOS] Alamofire 사용하기

Hoojeong Kim·2022년 8월 4일
4
post-thumbnail

앱을 개발하다 보면, 서버와 통신하는 부분이 필수적이다. 이럴 때, 기본으로 제공하는 Foundation의 URLSession을 사용할 수 있다.

하지만, URLSession은 다소 번거로운 점이 있기 때문에 Alamofire를 주로 사용한다.

Alamofire?

전에 다른 포스팅을 하면서 잠깐 언급했던 적이 있다.

[iOS] M1 Mac CocoaPods 라이브러리 추가하기


Alamofire는 swift를 기반으로 한 HTTP 네트워킹 라이브러리이다. 앞에서 언급한 Foundation의 URLSession 기반으로 구현되어 있어, 이를 더 쉽게 사용할 수 있도록 한다.

Alamofire는 다음 기능들을 제공하는데, 이 외에도 다양한 기능을 제공한다.

  • Chainable request/response methods
  • JSON, Codable decoding
  • Authentication

즉, Alamofire는 HTTP 네트워킹을 하는데 있어서 자주 사용하는 코드 및 함수를 쉽게 사용할 수 있도록 한다.


여기서! 알아야 하는 게 하나 더 있다.
바로 Request Methods 이다.

Request Methods

Request Methods는 클라이언트(우리는 앱임!)가 서버에게 사용자 요청의 목적이나 종류를 알리는 수단이다.

요청 종류로는 여러가지가 있다.

서버의 여러 정보를 확인하기 위해 사용되는 메소드이다. Reponse Body가 없고, Response Code와 HEAD만 응답받는다.

HEAD /index.html

GET

서버의 데이터를 가져올 때 사용하는 메서드이다. 굉장히 자주 쓰인다. Request Body가 없어, 전달할 내용을 header에 담는다.
즉, URI에 전달할 내용이 담기기 때문에 누구나 해당 내용을 볼 수 있다.

GET /index.html

POST

서버로 데이터를 전송할 때 사용하는 메서드로, 요청 유형은 Content-Type 헤더로 나타낸다. 전달할 내용을 Request Body에 담는다.

POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom

PUT

새로운 리소스를 생성하거나, 기존 리소스를 변경할 때 사용하는 메서드이다.

PUT /new.html HTTP/1.1
Host: example.com
Content-type: text/html
Content-length: 16

<p>New File</p>

DELETE

서버에 있는 특정 리소스를 삭제하기 위해 사용하는 메서드이다.

DELETE /file.html HTTP/1.1

이밖에도 PATCH, OPTIONS등 여러 가지가 더 있지만..
개인적으로 잘 안 쓰는(?) 것 같아서 정리 안 했다.
아님 말구요..ㅠ


Request/Reponse

이제 요청 종류도 알았으니 직접 사용해보자!

let url = "https://어쩌구저쩌구"

AF.request(url,
		   method: .get,
    	   parameters: nil,
    	   encoding: URLEncoding.default,
    	   headers: ["Content-Type":"application/json", "Accept":"application/json"])
	.validate(statusCode: 200..<300)
    .responseJSON { response in
    	
	/** 서버로부터 받은 데이터 활용 */
    switch response.result {
    case .success(let data):
		/** 정상적으로 reponse를 받은 경우 */
	case .failure(let error):
    	/** 그렇지 않은 경우 */
	}
}

url : 먼저 첫 번째 파라미터로 요청할 url을 담는다.
method : 어떤 request method를 사용할 것인지를 나타낸다.
parameters : POST 메서드와 같이 request body를 사용할 때 전달할 값을 담는다.
encoding : 인코딩 방식을 정한다.
headers : 부가적인 정보를 나타낸다. 위에서는 송/수신 데이터 타입(JSON)을 나타낸다.
validate : 유효성을 검사한다. state code 값이 20x일 때가 송/수신이 원활하게 된 경우.
responseJSON : 응답 json 데이터이다.


앞에서 GET 메서드의 사용 예시를 살펴봤으니, 이번에는 POST 메서드를 사용해보자.
위에서 잠깐 설명했는데, POST 메서드를 사용할 때는 parameters를 이용하면 된다.

let url = "https://어쩌구저쩌구"
let params = ["id":"아이디", "pw":"패스워드"] as Dictionary

AF.request(url,
		   method: .post,
           parameters: params,
           encoding: JSONEncoding(options: []),
           headers: ["Content-Type":"application/json", "Accept":"application/json"])
	.responseJSON { response in

	/** 서버로부터 받은 데이터 활용 */
    switch response.result {
    case .success(let data):
		/** 정상적으로 reponse를 받은 경우 */
	case .failure(let error):
    	/** 그렇지 않은 경우 */
	}
}

위처럼 parameters에 값을 담으면, request body에 해당 값을 담아 서버로 보낸다.


File Upload

Alamofire를 사용해서 파일을 다운로드 하거나, 업로드 하는 것도 가능하다.

let url = "https://어쩌구저쩌구"

AF.upload(multipartFormData: { multipartData in
			/** 서버로 전송할 데이터 */
		 }, to: url,
    	 method: .post,
    	 headers: ["Content-Type" : "multipart/form-data"])
    .response { response in
    
    if response.error != nil {
		/** 파일 업로드 실패*/
	} else{
		/** 파일 업로드 성공*/
	}
}

이때, GET이나 POST 메서드를 사용할 때는 header의 Content-Type가 application/json 이었다.
하지만 파일을 업로드 하거나 다운로드할 때는 Content-Type을 multipart/form-data 로 작성해야 한다.


데이터는 다음과 같이 전달할 수 있다.

먼저, request body를 추가할 때는 for문을 사용해 key value 값을 추가한다.

for (key, value) in parameters {
    multipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
}

이미지를 추가할 때는 다음과 같이 나타낸다.

if let image = imageData?.pngData() {
    multipartFormData.append(image, withName: "activityImage", fileName: "\(image).png", mimeType: "image/png")
}

value : 전달할 파일
withName : key
fileName : 서버에 업로드할 파일 이름
mimeType : 파일 형식


File Download

let url = "https://어쩌구저쩌구/test.jpg"

/** 파일에 저장하기 위한 코드 */
let fileManager = FileManager.default
let appURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileName : String = URL(string: url)!.lastPathComponent /** url의 마지막 문자열로 이름 지정 */
let fileURL = appURL.appendingPathComponent(fileName)

/** 파일 경로 지정 및 다운로드 옵션 설정 (이전 파일 삭제, 디렉토리 생성) */
let destination: DownloadRequest.Destination = { _, _ in
	return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}

AF.download(url,
		    method: .get,
            parameters: nil,
            encoding: JSONEncoding.default,
            to: destination)
	.downloadProgress { progress in
		/** 다운로드 progress */
        /** progressView를 사용할 때 여기에 작성 */
	}.response{ response in
	
    if response.error != nil {
		/** 파일 다운로드 실패*/
	} else{
		/** 파일 다운로드 성공*/
	}
}

마무리

이정도만 알아도,
당신은 네트워크 통신 『master』 ...

아마두

profile
나 애기 개발자 👶🏻

1개의 댓글

comment-user-thumbnail
2023년 5월 3일

좋은정보 감사합니다 !!

답글 달기