Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] 서버에 대한 모든 것 (Feat. Alamofire) #39

Closed
Suyeon9911 opened this issue May 17, 2022 · 11 comments
Closed

[iOS] 서버에 대한 모든 것 (Feat. Alamofire) #39

Suyeon9911 opened this issue May 17, 2022 · 11 comments
Assignees
Labels

Comments

@Suyeon9911
Copy link
Owner

Suyeon9911 commented May 17, 2022

네트워크

데이터를 서버에 요청하고 받기
클라이언트와 서버 관계

요청과 응답 ! -> 간단하면서도 중요한 개념
휴대폰에서 어떤 액션을 취했을 때 서버에게 원하는 데이터를 요청을 하고,
서버에서는 요청에 따른 적절한 응답을 다시 해준다 !

클라이언트 : 앱에서의 어떠한 동작을 처리하기 위해 서버에 데이터에 관련 처리를 요청함

  • 인터넷을 사용하는 거의 모든 것을 클라이언트라고 칭할 수 있음
  • 서버에서 데이터를 받아와 필요한 내용을 사용자에게 보여줌

서버 : 클라이언트의 요청에 대해 응답

  • 네트워크를 통해서 어떤 정보나 서비스를 제공
  • 클라이언트가 어떠한 것을 요청하면 데이터를 처리한 결과를 다시 클라이언트에게 보냄

프로토콜 (HTTP프로토콜) : 일련의 규칙, 정해진 형태
=> 클라와 서버는 서로 알아들을 수 있는 규칙을 만들어서 요청,응답을 수행하게 됩니다.

클라이언트의 역할은 무엇일까요??

  • 클라이언트는 서버에게 정중하게 잘 요청하는 방법을 알면 되는 것 !
  • 요청방법, API 명세서, URI

프로토콜

  • 요청과 응답을 받기 위해 정해진 약속
  • 그 중에서 우리는 http 사용.

HTTP: Hypertext Transfer Protocol

  • 클라이언트의 요청이 있을 때 해당 페이지에 대한 자료를 전송하고 곧바로 연결을 끊는 방식
  • POST GET PUT DELETE 등의 HTTP Method를 통해 데이터를 주고 받습니다.
  • 클라이언트가 서버에게 데이터를 요청할 때는 HTTP 방식으로 요청하는데 4가지 메서드에 따라서 서버는 클라이언트에게 저절한 결과를 응답해줍니다.
  • get : Read : 조회 : URL에 정보를 포함시켜 서버에 데이터 요청, 데이터를 읽어올때 사용
  • post : create : 생성 : 데이터를 body에 숨겨서 서버에 전달

REST API 사용

Representational State Transfer

  • 자원을 이름으로 구분해, 자원의 정보를 주고 받는 방식을 말합니다.
  • HTTP를 기반으로 자원에 접근하는 방식을 정해놓은 아키텍처
  • 즉, 규칙 모음이라고 생각하면 편함 !!

3가지 요소

  1. 자원 : URI를 통해 자원에 접근, URL란 자원의 위치를 나타내는 주소
  2. 행위 : HTTP Method - GET/POST/PUT/DELETE 4가지 메서드로 접근
  3. 표현(메시지) : JSON 포맷의 데이터
@Suyeon9911 Suyeon9911 added the iOS label May 17, 2022
@Suyeon9911 Suyeon9911 self-assigned this May 17, 2022
@Suyeon9911
Copy link
Owner Author

Suyeon9911 commented May 23, 2022

면접 끝나고 해야징 ~~꼭 .. 난 왤케 감자일까? ㅜ
울지마 ..................................................................................... 뿌에에ㅔ에에엥

@Suyeon9911 Suyeon9911 changed the title [iOS] Alamofire 복습 - 세미나 자료 참고 [iOS] 서버에 대한 모든 것.. - 세미나 자료 참고 Feat. Alamofire May 24, 2022
@Suyeon9911 Suyeon9911 changed the title [iOS] 서버에 대한 모든 것.. - 세미나 자료 참고 Feat. Alamofire [iOS] 서버에 대한 모든 것.. - 세미나 자료 참고 (Feat. Alamofire) May 24, 2022
@Suyeon9911
Copy link
Owner Author

JSON

  • JavaScript Object Notation의 약자
  • XML보다 가벼운 데이터 교환 포맷
  • 주고 받을 수 있는 자료형은 Int, String, Boolean, Array, Object
  • Key와 Value로 이루어져 있으며 객체는 중괄호 {}, 배열은 대괄호 [] 로 표현

@Suyeon9911 Suyeon9911 changed the title [iOS] 서버에 대한 모든 것.. - 세미나 자료 참고 (Feat. Alamofire) [iOS] 서버에 대한 모든 것 (Feat. Alamofire) May 24, 2022
@Suyeon9911
Copy link
Owner Author

HTTP 메서드

  • GET /user : 사용자를 조회하고 싶습니다.
  • GET /user?id=13 : id가 13이라는 사람을 조회하고 싶습니다.
  • PUT /user : 새로운 사용자를 수정하고 싶습니다.
  • DELETE /user?id=13 : id가 13인 사용자를 삭제하고 싶습니다.

HTTP 응답

  • 규칙에 맞게 리소스 접근을 서버에 요청하면 응답이 돌아옵니다.
  • 응답 = 상태코드 + 메시지 + 데이터 !!
  • 응답중에서는 전달 받을 데이터 말고도 신경써야할 부분이 있슴니다 ! 바로 상태코드~
  • 클라이언트가 서버에게 요청을 보냈을 때 그 요청의 결과가 어떻게 되었는지 상태 코드를 통해서 확인할 수가 있습니다.
  • 요청이 성공적인지 혹은 에러가 발생햇는지 !!

200번대 : 성공
400번대 : 클라이언트 에러
500번대 : 서버에러

200 : 요청 성공
201 : 요청 성공, 새로운 리소스가 생성, POST, PUT 이후에 응답
202 : 요청 접수, 아직 미처리

400: 클라이언트의 요청이 유효하지 않은 상태
401: 클라이언트가 권한이 없어서 작업을 진행하지 못하는 상태 , 인증필요
403: 서버가 요청을 거부할때, 사용자가 리소스에 대한 필요 권한을 가지고 있지 않을 떄
404 : 서버가 요청한 페이지를 찾지 못했을 때, 존재하지 않은 페이지를 요구
405: 클라이언트의 요청이 허용되지 않은 메서드인 경우

500: 서버에 오류가 발생하여 요청을 수행할 수 없는 경우
501: 서버에 해당요청을 수행할 수 있는 기능이 없는 경우 - 요청메서드를 인식 못함
503: 일시적으로 서버를 이용할 수 없는 경우 - 서버 오버로드, 유지관리 위한 다운

@Suyeon9911
Copy link
Owner Author

API 명세서에서 주의깊게 봐야할 것 들

  1. BaseURL
  2. HTTP Method
  3. Path
  4. Request - Header, Parameter, Body
  5. Response - StatusCode, Value

@Suyeon9911
Copy link
Owner Author

서버통신 흐름 정리

-클라이언트가 서버에게 특정 URI로 요청을 하면 JSON형태로 데이터를 받는 것

  • REST API에 기반한 데이터 요청서를 바탕으로 Request 보내기

  • 데이터 요청서 : 자원(어디에) URI, 행위(어떤것을 할 것인지) HTTP Method , 표현,메시지(어떤 데이터) JSON

  • Response로 JSON 데이터를 보내줌

  • 요청서를 보낼때에서 서버에서 필요한 데이터가 있으면 JSON을 준비해야함

  • 결과로 넘어온 응답은 JSON 형태로 되어있다. JSON을 알아들을 수 있게 해석하여 적절하게 사용해야 함

  • 또한, JSON을 준비하는 과정과 해독,해석하는 과정 필요 !!

Encode: 암호화하는 과정 - Swift 코드를 JSON 형식으로 바꾸는 과정

Decode: 해독하는 과정 : JSON을 Swift로 바꾸는 과정

인코딩을 통해 스위프트코드를 json으로 변환 -> 요청서를 가지고 서버에 요청을 보냄 -> JSON 데이터로 응답을 보내줌 -> 디코딩을 통해 JSON 데이터를 Swift로 변환

@Suyeon9911
Copy link
Owner Author

CocoaPods ; iOS에서 사용되는 의존성 관리 도구 중 하나

  • '의존성 관리 도구'란 앱 개발을 위해 외부 라이브러리를 사용할 때 프로젝트와 해당 라이브러리의 상관관계를 용이하게 관리해주는 도구 !
  • 의존성관리 도구를 사용하면 라이브러리 버전이 올라갈때마다 명령어 한줄로 간단하게 해결,
  • 버전 업데이트, 협업하는 사람들과 버전 맞추기 편리 !!
  • 코코아팟, Carthage, SPM
  • 코코아팟 : 내프로젝트에 사요할 프로젝트를 연결해주고 명령어 한 번으로 해당 프로젝트의 버전을 최신으로 유지시켜준다 . 자바의 Mavle, Gradle, 노드 JS의 npm과 같은 역할 ~

Carthage : 빌드 시 라이브러리를 프로잭트와 통합하지 않고 관리

빠른 빌드 속도, 동적라이브러리

@Suyeon9911
Copy link
Owner Author

서버통신 순서 !

  1. API 명세 확인하기

  2. 포스트맨 테스트하기
    --- 서버 파트원과 필요한 데이터 논의 , api 테스트 과정

  3. 사전준비 1) http 통신을 위한 plist 설정

  4. 사전준비 2) APIConstants

  5. 사전준비 3) NetworkResult

  6. 데이터 모델 생성

  7. Service 코드 작성

  8. Service 코드 호출

@Suyeon9911
Copy link
Owner Author

2단계 사전 준비

  1. plist 설정
  • App Transport Security Settings 추가
  • Allow Arbitrary Loads 추가
  • YES로 변경

애플 측에서는 앱 자체의 보안성을 위해서 ATS 라는 정책을 통해 기본적으로 https 통신을 하도록 유도하고 있습니다. 그래서 http 서버와 통신을 하려고 하면 에러가 발생합니다.

  1. APIConstants : 어디에 있는 자원을 찾을 것인지 URI를 관리하기 쉽게 API주소를 모아놓은 파일 만들기
  • BaseURL, 그리고 + LoginURL 등등 ..
  1. NetworkResult : 서버통신 결과를 처리하기 위한 파일 만들기
  • 에서 T는 타입 파라미터로 지금 당장 타입을 정하지 않겠다는 의미 !!
  • 해당 자리에는 Int, String, Bool 등 다양한 타입이 들어갈 수 있습니다 !

@Suyeon9911
Copy link
Owner Author

Suyeon9911 commented May 24, 2022

3단계 서버통신

  1. 넘겨받은 JSON을 Swift 객체 형태로 잘 사용할 수 있도록 DataModel을 만들고
  2. 실제로 서버에 Request하는 코드와
  3. 서버에서 넘겨받은 Response를 받아보는 코드를 작성 !

작성한 서버통신 코드를 뷰컨에서 호출

  1. DataModel
  • 기본적으로 네트워크 통신 결과로 넘어오는 JSON 데이터를 앱이 이해할 수 있는 형태인 Swift로 바꿔야함 : decode 과정
struct LoginResponse:  Codable {
    let status: Int
    let success: Bool?
    let message: String
    let data: LoginData?
}

struct LoginData: Codable {
    let name: String
    let email: String
}


### 데이터 모델을 encode하거나 decode 하려면 프로토콜 채택이 필요합니다. 바로 , Encodable, Decodable 프로토콜 !
### Codable이라는 프로토콜을 사용해서 한꺼번에 ! 인코더블 과 디코더블의 묶음 !
- `public typealias Codable= Decodable & Encodable`

데이터 부분은 왜 옵셔널일까 ??

  • 로그인이 성공했을때는 data가 넘어오는데 실패했을 때는 data가 안넘어오기 때문 !

준비 완료
api 주소모음 구조체, 서버통신 결과처리 열거형, 서버통신 결과로 받는 응답 바디를 디코딩할 데이터보델 !!

@Suyeon9911
Copy link
Owner Author

Request. Response

  • 통신코드를 작성할 파일 만들기 !
  • Service 파일 만들기
  1. import Alamofire
  2. Service 클래스를 만들어주고 싱글톤 객체를 선언한다 : 앱 어디에서든지 접근할 수 있도록

싱글톤 ?

  • 어플리케이션이 시작될 때 어떤 클래스가 최초 한 번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴
  • 어떤 경우에 사용? 지정한 클래스의 인스턴스가 1개 밖에 존재하지 않는 것을 보장하고 싶을 때, 단일 인스턴스로 제한하여 어느지점에서나 객체를 변경시키고 싶을 때 , 한 인스턴스에 여러곳에서 접근이 가능하도록 하고 싶을때 !
  • 객체가 불필요하게 여러개 만들어질 필요가 없는 환경설정, 네트워크 연결처리, 데이터 관리와 같은 경우에 많이 사용
  1. 로그인 통신을 할 때 사용할 함수를 정의 - 필요한 값을 파라미터로 받자 .
  • func login(name: String, email: String, password: String, completion: @escaping (NetworkResult<Any>) -> Void)
  • escaping 클로저는 클로저가 함수의 인자로 전달됐을 때 함수의 실행이 종료된 후 실행되는 클로저
  • completion클로저를 탈출클로저로 정의
  1. URI, Request header, Request Body 준비
  • 함수 내부에 let url = APIConstants.loginURL : 통신할 API 주소
  • let header: HTTPHeaders = ["Content-Type": "application/json"] : 요청 헤더
let body: Parameters = [
    "name": name,
    "email": email,
    "password": password
]

: 요청 바디 !!

  1. 요청서 만들기 : Alamofire에서 제공하는 여러가지 메서드가 있는데요, 그 중에서 encoding이라는 파이미터가 들어간 함수로 request를 만들 거에욤 !
  • JSONEndcoding.defalut : 우리가 만든 데이터를 JSON으로 인코딩하겠다 ! 이런의미
  • 통신할 api 주소, http method, 요청 방식, 인코딩 방식, 요청헤더
let dataRequest = AF.request(url, method: .post, parameters: body, encoding: JSONEncoding.defalut, headers: header)
  1. 만든 요청서의 responseData메서드를 호출 : 데이터 통신 시작 !
  • 데이터 통신의 결과가 response 인자에 담기게 됩니다.
dataRequest.responseData { response in 
    switch response.result {
    case .success: 
        guard let statusCode = response.response?.statusCode else { return }
        guard let value = response.value else { return }
        let networkResult = self.judgeStatus(by: statusCode, value)
        completion(networkResult)
   case .failure: 
        completion(.networkFail)
    }
}
  • 성공이면 데이터 처리
  • 실패면 networkfil 값을 담아서 뷰컨에 넘겨줌 !!

성공인 경우로 가보자

  • 먼저, 통신 결과의 statuscode와 value값을 가져옵니다.

  • 그리고 가져온 값들을 만들어 놓은 judgeStatus() 메서드를 이용해 정제된 networkResult를 받아서 그 값을 completion 파라미터에 넣습니다 .

  • judgeStatus()

private func judgeStatus(by statusCode: Int, _ data: Data) -> NetworkResult<Any> {
    switch statusCode {
    case 200: return isVaildData(data: data)
    case 400: return .pathErr
    case 500: return .serverErr
    default: return .networkFail
   }
}

: 서버통신 자체는 성공일지라도 응답 실패로 우리가 원하는 데이터를 받지 못한 상태일 때를 분기처리하기 위한 메서드

  • isVailData(data: data)
private func isVaildData(data: Data) -> NetworkResult<Any> {
    let decoder = JSONDecoder()
    guard let decodedData = try? decoder.decode(LoginResponse.self, from: data)
    else { return .pathErr }
   
   return .success(decodedData.data as Any)
}

: 통신이 성공하고 원하는 데이터가 올바르게 들어왔을 때 데이터 처리를 위한 함수 .

  • 서버에서 준 JSON 데이터를 Codable을 채택하여 해독이 가능한 LoginResponse 모델 구조체로 데이털르 변환해서 넣고, 그 데이터가 올바르게 변환이 되었다면, 그 데이터를 NeworkResult.success 파라미터로 전달합니다.
  1. 작성한 서비스 코드를 뷰 컨트롤러에서 호출
  • 텍스트 필드에 잇는 값을 guard let을 사용해 안전하게 꺼내오기
  • 파라미터로 보내서 요청
  • 서버로 request를 보내서 성공적으로 response가 돌아왔다면, 인자에 원하는 데이터가 담겨있을 것.
  • LoginResponse 타입으로 된 객체가 담겨있을 것이당 !
  • 타입캐스팅과 옵셔널 바인딜릉 통해서 안전하게 data를 꺼내자 !

@Suyeon9911
Copy link
Owner Author

수고했어잉 ~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant