HTTP(Hyper Text Transfer Protocol)는 Hyper Text 즉 HTML을 전송하기 위한 프로토콜, TCP 와 UDP를 사용하여 통신하며 80번 포트를 사용하는 통신프로토콜(통신규약)이다.
❗️HTTP의 특징
1. 요청 행(Request-Line)
Request-Line은 요청 방식(Method), URL정보, HTTP버전을 포함한다.
아래 그림에서는 Request URL, Request Method를 나타내고 있다.
2. 요청 헤더(Request Header)
헤더 정보는 요청하는 클라이언트 PC, 브라우저 정보, 사용자언어 환경, 쿠키 등 다양한
클라이언트 환경에 대한 정보를 가지고 있다.
3. 공백(CRLF)
줄 바꿈 명령.
4. 메시지 본문(Body)
Body, 클라이언트가 입력한 데이터를 저장하는 영역.
데이터 형식은 요청 헤더에 지정된 타입을 따른다.
1. 응답 행(State-Line)
응답 상태정보 표시 라인, HTTP버전 정보와 세 자리 값(200)과 같은 상태코드 값을 통해
응답 결과 및 상태정보를 나타낸다.
2. 응답 헤더 정보
헤더 정보, 각종 서버 및 웹사이트 관련 환경정보를 제공한다.
3. 메시지 본문(Body)
HTTP본문영역, 주로 서버에서 사용자에게 전달되는 HTML 소스 및 포함된 데이터를 저장하는 영역이다.
HTTP Method는 송수신 방법을 뜻하며, GET, POST, PUT, DELETE, PATCH 등이 있다.
웹 페이지에서는 대부분 통신에 GET 메서드를 사용하며, 폼 등을 사용해서 데이터를 전송할 땐
POST 메서드를 사용한다.
즉, 클라이언트가 웹 서버에게 사용자의 요청의 목적/종류를 알리는 수단이다.
- GET(검색)
웹 서버에 페이지를 요청한다. 요청할 때 필요한 데이터는 URL에 덧붙여 보낸다.
- POST(생성)
서버의 데이터를 갱신하거나 보내는 데이터 양이 많을 때 등 사용한다.
요청할 때 필요한 데이터는 메시지 본문에 담아서 보낸다.
- PUT(변경)
대상 자원을 나타내는 데이터를 대체한다.
- DELETE(삭제)
웹 자원을 제거할 때 사용한다. 하지만 DELETE의 경우 서버에서 클라이언트의 요청을 무시 가능하기 때문에 실제로 삭제되지 않았지만, 클라이언트는 파일이 삭제 되었다고 생각할 수 있다.
- PATCH(일부 변경)
자원의 일부를 수정할 때 사용한다.
서버가 요청을 클라이언트에서 성공적으로 수신했으며 서버 끝에서 처리 중이라는 정보를 나타낸다.
서버가 요청을 받고 성공적으로 처리되었음을 나타낸다.
300번대 상태 코드는 대부분 클라이언트가 이전 주소로 데이터를 요청하여 서버에서 새 URL로 리다이렉트를 유도하는 경우이다.
400번대 상태 코드는 클라이언트의 코드가 잘못된 경우이다. 유효하지 않은 자원을 요청했거나 요청이나 권한이 잘못된 경우 발생한다.
500번대 상태 코드는 서버 쪽에서 오류가 난 경우이다.
안드로이드에서 서버와 클라이언트 간의 Http 통신을 도와주는 라이브러리입니다.
클라이언트에서 서버로 어떠한 요청을 보내면 서버는 그 요청에 대한 응답을 클라이언트로 보내주어야 하는데,
이 일련의 과정을 도와주는 역할을 하는 것이 Retrofit 입니다.
초기 안드로이드에서는 서버와의 통신을 위해 HttpClient를 사용했다. 그러나 HttpClien는 Android 5.1 이후로 deprecated 된 후, OKHttp와 그 상위 구현체인 Retrofit을 서버 통신을 위한 라이브러리로 사용된다.
1) Retrofit의 장점
2) Retrofit의 구성 요소
Retrofit2를 이용하여 자신의 Github 정보를 불러오는 예제를 정리했습니다.
1-1) build.gradle (Module: app)
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
1-2) AndroidManifest.xml에 인터넷 사용 권한추가
<uses-permission android:name="android.permission.INTERNET" />
data class UserInfo(
@SerializedName("login")
val userId: String,
val followers: Int,
val following: Int
)
위에 주소로 접속하게 되면 아래와 같이 많은 유저 정보가 나오는데
그 중 유저 아이디, 팔로워 수, 팔로잉 수에 대한 정보만을 담는 DTO Class를 생성합니다.
변수의 이름을 JSON의 키 값과 이름을 맞춰 매핑하거나
@SerializedName을 통해 매핑시킬 수 있습니다.
interface Service {
@GET("users/alsrbs12304")
fun getUserInfo(): Call<UserInfo>
}
API Interface를 생성 후 어노테이션을 이용해 HTTP Method를 설정해 준다.
해당 유저의 정보를 검색하기 때문에 HTTP Method 중 GET메서드를 사용한다.
object RetrofitBuilder {
var service : Service
init {
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
service = retrofit.create(Service::class.java)
}
}
Retrofit Builder 를 object로 만들어 싱글톤으로 생성.
.baseUrl() 에는 서버의 주소를 넣는데 항상 주소 끝에는 '/'로 끝나야 한다.
.addConverterFactory()는 데이터를 파싱 할 converter를 추가하는 메서드이다.
JSON 같은 데이터는 자바나 코틀린에서 바로 사용할 수 있는 데이터 형식이 아니기 때문에 이를 변환해주기 위해 converter를 사용해야 한다.
여기서는 JSON을 변환해줄 GSON 변환기를 등록한 것이다.
이렇게 만들어진 Retrofit 객체를 이용해 Interface를 구현한다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
RetrofitBuilder.service.getUserInfo().enqueue(object : Callback<UserInfo> {
override fun onResponse(call: Call<UserInfo>, response: Response<UserInfo>) {
val userInfo = response.body()
Log.d("response", "${userInfo?.userId} ${userInfo?.followers} ${userInfo?.following}")
}
override fun onFailure(call: Call<UserInfo>, t: Throwable) {
Log.d("error", t.message.toString())
}
})
}
}
enqueue로 비동기 통신을 실행한다. 통신종료 후 이벤트 처리를 위해 Callback 등록
onResponse -> 성공
하지만 onResponse가 무조건 성공을 뜻하는 것은 아니기 때문에 isSuccesful()로 확인이 필요하지만 생략했다.
onFailure -> 실패를 뜻함.
onResponse로 성공하면 응답에 대한 Body를 userInfo에 담아 로그로 확인한다.