Github : https://github.com/junghun9102/AndroidTemplate

Branch : library/retrofit

 

junghun9102/AndroidTemplate

Contribute to junghun9102/AndroidTemplate development by creating an account on GitHub.

github.com

 

 


Commit ea187676

 

기본 사용법

1. Service

2. OkHttpClient

3. Retrofit을 이용한 Service 구현체

 

1번과 3번만 구현하면 API통신이 가능하다.

2번은 선택적이지만 보통 구현한다.

 

GoogleNews RSS를 사용해 Retrofit 기본 사용법을 정리하려고 한다.

https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko 

 

 

 

 

 


https://square.github.io/retrofit/

 

Retrofit

A type-safe HTTP client for Android and Java

square.github.io

dependencies

    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
    implementation 'com.squareup.retrofit2:converter-simplexml:2.1.0'
//    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

 

 

 

1. Service 

HTTP Method(GET/POST/PUT/DELETE)로 API 요청을 위한 interface

 

interface GoogleNewsService {

    @GET("/rss")
    fun getNews(
        @Query("hl") hl: String,
        @Query("gl") gl: String,
        @Query("ceid") ceid: String
    ): Call<RespNewsRss>

}

 

추가적인 사용 방법들은 아래 포스팅에 잘 설명되어 있다.

 

https://medium.com/@ggikko/retrofit-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0-%EC%93%B0%EA%B8%B0-a6ce90cf7768

 

Retrofit 홈페이지 한글로 긁어보기 RESTFUL SERVICE VERY EASY!!

원래 Volley를 쓰다가 부분적으로 적용해서 사용해 보려했는데 하다보니 홈페이지에 있는 글을 다 읽고 말았다. 그래서 영어로 읽으면 시간이 오래걸려서 한글로 작성해보려한다.. 허접하게 번역

medium.com

 

 

 

 

2. OkHttpClient

API 요청과 응답에 관한 설정을 할 수 있다.

object GoogleNewsServiceFactory

    private const val HTTP_TIMEOUT_READ = 10L
    private const val HTTP_TIMEOUT_CONNECT = 5L

    private fun makeOkHttpClient(httpLoggingInterceptor: HttpLoggingInterceptor, appendHeaderInterceptor: Interceptor) = OkHttpClient.Builder()
        .connectTimeout(HTTP_TIMEOUT_CONNECT, TimeUnit.MILLISECONDS)
        .readTimeout(HTTP_TIMEOUT_READ, TimeUnit.MILLISECONDS)
        .addInterceptor(httpLoggingInterceptor)
        .addInterceptor(appendHeaderInterceptor)
        .build()

    private fun makeLoggingInterceptor(debug: Boolean): HttpLoggingInterceptor {
        return HttpLoggingInterceptor().apply {
            level = if (debug) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
        }
    }

    private fun makeAppendHeaderInterceptor() = Interceptor { chain ->
            val newRequest = chain.request().newBuilder()
//            newRequest.addHeader("Version", "v1.0")
            chain.proceed(newRequest.build())
    }

 

connectTimeout / readTimeout / writeTimeout / callTimeout

타임아웃을 설정 가능

 

HttpLoggingInterceptor

요청과 응답 로그를 볼 수 있다.

 

 

makeAppendHeaderInterceptor

1번의 Service에서도 각각의 요청마다 Header를 붙일 수 있다.

하지만 디폴트 헤더 데이터가 필요한 경우 interceptor를 만들어 요청마다 같은 헤더를 추가할 수 있다.

 

 

 

 

3. Retrofit을 이용한 Service 구현체

실제 사용하기 위한 구현체 생성

object GoogleNewsServiceFactory

    fun makeNewsService(debug: Boolean, baseUrl: String): GoogleNewsService {
        val okHttpClient = makeOkHttpClient(
            makeLoggingInterceptor(debug),
            makeAppendHeaderInterceptor()
        )
        return makeNewsService(
            baseUrl,
            okHttpClient
        )
    }

    private fun makeNewsService(baseUrl: String, okHttpClient: OkHttpClient): GoogleNewsService {
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(SimpleXmlConverterFactory.create())
            .build()

        return retrofit.create(GoogleNewsService::class.java)

 

baseUrl(baseUrl)

기본 URL을 설정

 

client(okHttpClient)

2번에서 만들었던 okHttpClient 설정

 

addConverterFactory(SimpleXmlConverterFactory.create())

응답 데이터를 파싱해 객체로 받기 위한 설정

 

 

 

 

XML

 

dependecies

implementation 'com.squareup.retrofit2:converter-simplexml:2.1.0'

 

Retrofit Builder 

addConverterFactory(SimpleXmlConverterFactory.create())

 

<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
  <channel>
  <generator>NFE/5.0</generator>
  <title>주요 뉴스 - Google 뉴스</title>
  <link>https://news.google.com/?hl=ko&gl=KR&ceid=KR:ko</link>
  <language>ko</language>
  <webMaster>news-webmaster@google.com</webMaster>
  <copyright>2020 Google Inc.</copyright>
  <lastBuildDate>Fri, 29 May 2020 03:09:37 GMT</lastBuildDate>
  <description>Google 뉴스</description>
  <item>
    <title>[속보] 코로나19 확진 58명 늘어…신규 확진자 전원 수도권 - 한겨레</title>
    <link>https://news.google.com/__i/rss/rd/articles/CBMiNWh0dHA6Ly93d3cuaGFuaS5jby5rci9hcnRpL3NvY2lldHkvaGVhbHRoLzk0NzA1Ny5odG1s0gEA?oc=5</link>
    <guid isPermaLink="false">52782408608000</guid>
    <pubDate>Fri, 29 May 2020 01:23:03 GMT</pubDate>
    <description><ol><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiNWh0dHA6Ly93d3cuaGFuaS5jby5rci9hcnRpL3NvY2lldHkvaGVhbHRoLzk0NzA1Ny5odG1s0gEA?oc=5" target="_blank">[속보] 코로나19 확진 58명 늘어…신규 확진자 전원 수도권</a>&nbsp;&nbsp;<font color="#6f6f6f">한겨레</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9UEFEOE1UVXBoMmfSAQA?oc=5" target="_blank">쿠팡발 감염 확산에 수도권 '비상'…모자·신발서 코로나 나와</a>&nbsp;&nbsp;<font color="#6f6f6f">뉴스TVCHOSUN</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiMWh0dHBzOi8vd3d3Lnl0bi5jby5rci9fbG4vMDEwM18yMDIwMDUyOTEwNTI0NDc0NDbSAUNodHRwczovL20ueXRuLmNvLmtyL25ld3Nfdmlldy5hbXAucGhwP3BhcmFtPTAxMDNfMjAyMDA1MjkxMDUyNDQ3NDQ2?oc=5" target="_blank">신규 발생 58명...지역 발생 55명 모두 수도권에 집중</a>&nbsp;&nbsp;<font color="#6f6f6f">YTN</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiJ2h0dHBzOi8vbmV3cy5qb2lucy5jb20vYXJ0aWNsZS8yMzc4ODg4MNIBK2h0dHBzOi8vbW5ld3Muam9pbnMuY29tL2FtcGFydGljbGUvMjM3ODg4ODA?oc=5" target="_blank">코로나 신규환자 58명, 지역감염 55명···모두 수도권서 터졌다 - 중앙일보</a>&nbsp;&nbsp;<font color="#6f6f6f">중앙일보 모바일</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9cnVjU2VzMVB0R2_SAQA?oc=5" target="_blank">수도권 덮친 '쿠팡 물류센터 집단감염'…"2주가 고비" / JTBC 뉴스룸</a>&nbsp;&nbsp;<font color="#6f6f6f">JTBC News</font></li><li><strong><a href="https://news.google.com/stories/CAAqOQgKIjNDQklTSURvSmMzUnZjbmt0TXpZd1NoTUtFUWlBMHR6bGxZQU1FVmdIQWUwRXpZRzRLQUFQAQ?oc=5" target="_blank">Google 뉴스에서 전체 콘텐츠 보기</a></strong></li></ol></description>
    <source url="http://www.hani.co.kr">한겨레</source>
  </item>

 

@Root(name = "rss", strict = false)
data class RespNewsRss(
    @field:Element(name = "channel") var channel: RespNewsRssChannel? = null
)

@Root(name = "channel", strict = false)
class RespNewsRssChannel(
    @field:ElementList(entry = "item", inline = true) var newsList: List<RespNews>? = null
)

@Element(name = "item")
data class RespNews(
    @field:Element(name = "title") var title: String? = null,
    @field:Element(name = "link") var link: String? = null,
    @field:Element(name = "guid") var guid: String? = null,
    @field:Element(name = "pubDate") var pubDate: String? = null,
    @field:Element(name = "description") var description: String? = null,
    @field:Element(name = "source") var source: String? = null
)

 

 

Json

 

depenencies

implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

 

Retrofit Builder

.addConverterFactory(GsonConverterFactory.create())

 

{
  "rss" : {
    "channel" : {
    	"items" : [{
          "title" : "인천시 “쿠팡물류센터 확진자 딸 등 2명 추가 확진” - 한겨레",
          "link" : "https://news.google.com/__i/rss/rd/articles/CBMiM2h0dHA6Ly93d3cuaGFuaS5jby5rci9hcnRpL2FyZWEvY2FwaXRhbC85NDcyMjIuaHRtbNIBAA?oc=5",
          "guid" : "52782408608000",
          "pubDate" : "Sun, 31 May 2020 05:56:12 GMT",
          "description" : "<ol><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiM2h0dHA6Ly93d3cuaGFuaS5jby5rci9hcnRpL2FyZWEvY2FwaXRhbC85NDcyMjIuaHRtbNIBAA?oc=5" target="_blank">인천시 “쿠팡물류센터 확진자 딸 등 2명 추가 확진”</a>&nbsp;&nbsp;<font color="#6f6f6f">한겨레</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiOGh0dHBzOi8vd3d3Lmhhbmtvb2tpbGJvLmNvbS9OZXdzL1JlYWQvMjAyMDA1MzAxNjc3MDQ3MzMy0gEA?oc=5" target="_blank">이태원 클럽→쿠팡 물류센터→여의도 학원 전파?</a>&nbsp;&nbsp;<font color="#6f6f6f">한국일보</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiNWh0dHA6Ly93d3cuaGFuaS5jby5rci9hcnRpL3NvY2lldHkvaGVhbHRoLzk0NzE4OS5odG1s0gEA?oc=5" target="_blank">부천 쿠팡물류센터 관련 코로나19 확진자 최소 109명</a>&nbsp;&nbsp;<font color="#6f6f6f">한겨레</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiJ2h0dHBzOi8vbmV3cy5qb2lucy5jb20vYXJ0aWNsZS8yMzc4OTYxONIBK2h0dHBzOi8vbW5ld3Muam9pbnMuY29tL2FtcGFydGljbGUvMjM3ODk2MTg?oc=5" target="_blank">쿠팡 물류센터 총 108명 확진…"이태원클럽 학원강사발 추정" - 중앙일보</a>&nbsp;&nbsp;<font color="#6f6f6f">중앙일보 모바일</font></li><li><a href="https://news.google.com/__i/rss/rd/articles/CBMiK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9R1RwQ3ZuQ2I2U1nSAQA?oc=5" target="_blank">코로나19 신규 확진 39명…수도권 이어 지역서도 산발 감염</a>&nbsp;&nbsp;<font color="#6f6f6f">뉴스TVCHOSUN</font></li><li><strong><a href="https://news.google.com/stories/CAAqOQgKIjNDQklTSURvSmMzUnZjbmt0TXpZd1NoTUtFUWlBMHR6bGxZQU1FV1BYSElmd2VCR2RLQUFQAQ?oc=5" target="_blank">Google 뉴스에서 전체 콘텐츠 보기</a></strong></li></ol>",
          "soruce" : "한겨레"
        }]
    }
  }
}

 

data class RespNewsRss(
    @field:SerializedName("channel") var channel: RespNewsRssChannel? = null
)

class RespNewsRssChannel(
    @field:SerializedName("items") var newsList: List<RespNews>? = null
)

data class RespNews(
    @field:SerializedName("title") var title: String? = null,
    @field:SerializedName("link") var link: String? = null,
    @field:SerializedName("guid") var guid: String? = null,
    @field:SerializedName("pubDate") var pubDate: String? = null,
    @field:SerializedName("description") var description: String? = null,
    @field:SerializedName("source") var source: String? = null
)

 

 

 

 

실제 사용

MainActivity

    private val newsService = GoogleNewsServiceFactory.makeNewsService(BuildConfig.DEBUG, "https://news.google.com")

    private fun initViews() {
        btn_main.setOnClickListener {
            newsService.getNews("ko", "KR", "KR:ko")
                .enqueue(object : Callback<RespNewsRss> {
                    override fun onResponse(
                        call: Call<RespNewsRss>,
                        response: Response<RespNewsRss>
                    ) {
                        tv_main.text = response.body()?.channel?.newsList?.toString()
                    }

                    override fun onFailure(call: Call<RespNewsRss>, t: Throwable) {
                        Toast.makeText(this@MainActivity, t.message, Toast.LENGTH_SHORT).show()
                    }
                })
        }
    }

 

 

 

 


Commit ad3ddc26

 

 

+Rx

1. Service

2. OkHttpClient

3. Retrofit을 이용한 Service 구현체

 

 

dependecies 추가

implementation "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0"

 

 

1. Service

interface GoogleNewsService {

    @GET("/rss")
    fun getNews(
        @Query("hl") hl: String,
        @Query("gl") gl: String,
        @Query("ceid") ceid: String
    ): Single<RespNewsRss>

}

리턴 타입만 바꼈다.

 

 

2. 동일함

 

 

3. Retrofit을 이용한 Service 구현체

    private fun makeNewsService(baseUrl: String, okHttpClient: OkHttpClient): GoogleNewsService {
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(SimpleXmlConverterFactory.create())
            .build()

        return retrofit.create(GoogleNewsService::class.java)
    }

 

addCallAdapterFactory(RxJava2CallAdapterFactory.create())

기존의 리턴받던 Call에서 Rx객체로 변경하기 위한 한줄이 추가되었다.

 

 

실제사용

    private val newsService = GoogleNewsServiceFactory.makeNewsService(BuildConfig.DEBUG, "https://news.google.com")
    private val compositeDisposable = CompositeDisposable()

    private fun initViews() {
        btn_main.setOnClickListener {
            newsService.getNews("ko", "KR", "KR:ko")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { resp ->
                    val newsList = resp.channel?.newsList
                    tv_main.text = newsList.toString()
                }.let {
                    compositeDisposable.add(it)
                }
        }
    }

 

 

 

 

'창고' 카테고리의 다른 글

custom_dialog (+custom_toast)  (0) 2020.05.02
Activity간의 화면 전환  (0) 2020.03.11
internal_storage  (0) 2020.02.26
permission  (0) 2020.02.26
DP(Device Independence Pixel)?  (0) 2019.06.09

 

관련 키워드

Thread, UiThread, MainThread, Jank, ANR, Asynchronous, Synchronous, Blocking, Non-Blocking, Concurrency, Parallelism, Handler, Looper, MessageQueue, AsyncTask

 

 


왜 비동기가 필요한가?

 

안드로이드에서는 UI를 그리는 메인스레드가 매우 중요하다.

 

애플리케이션이 실행되고 메인액티비티가 메모리에 로드되면

메인스레드를 포함한 프로세스가 생성된다.

 

안드로이드는 초당 60프레임을 지원하고 한 프레임은 16ms안에 그려져야 한다.

16ms 안에 화면을 그리는 작업이 완료되지 않으면 쟁크가 발생한다.

(쟁크; jank : 프레임 누락으로 인해 끊겨보이는 현상)

5초 이상의 긴 작업을 메인스레드에서 실행한다면 ANR이 발생한다.

(ANR; Application Not Responding)

 

결국 안드로이드에서 UI스레드가 원활하게 돌아가기 위해서는 비동기가 필수로 사용된다.

 

 

 

 

 


그럼 비동기는 무엇인가?

 

동기(Synchronous)

작업을 수행하고 그 작업이 완료될 때까지 다른 작업을 하지못하고 기다리는 방식

 

예를 들어 편의점에서 혼자 일을 한다면 카운터 일 물건 정리나 청소 등의 일을 하는 동안 전혀할 수 없다.

즉, 메인스레드가 UI를 그려야만 하는데 무거운 작업(시간이 오래걸리는)을 한다면 그 동안 UI를 그릴 수 없어 화면이 멈춰있을 것이다.

 

 

비동기(Asynchronous)

어떤 작업을 수행하지만 완료와 상관없이 계속해서 작업을 할 수 있는것

 

편의점이 바빠 한 명의 직원을 더 고용했다. 한명은 계속해서 카운터 일을 보고 물건 정리나 청소 등의 일은 다른 직원에게 시키면 카운터가 비는 일이 없다.

메인 스레드는 계속해서 UI를 그리고, 무거운 작업은 추가적인 스레드에게 시키면 된다.

 

 

 

 

사실 위에서 설명한 동기는 Sync-Bloking이고, 비동기는 Async-NonBlocking이다.

Sync-NonBlocking, Async-Blocking은 거의 사용되지 않기 때문에 우선은 위에 설명만 알아도 된다.

하지만 더 자세히 알고 싶다면 아래 포스팅 참조

 

Sync, Async, Blocking, NonBlocking 추천 포스팅

https://homoefficio.github.io/2017/02/19/Blocking-NonBlocking-Synchronous-Asynchronous/

 

Blocking-NonBlocking-Synchronous-Asynchronous

꽤 자주 접하는 용어다. 특히나 요즘들어 더 자주 접하게 되는데, 얼추 알고는 있고 알고 있는게 틀린 것도 아니지만, 막상 명확하게 구분해서 설명하라면 또 만만치가 않은.. 그래서 찾아보면 ��

homoefficio.github.io

 

 

 

 

 


그럼 어떻게 구현하지?

 

무거운 작업을 새로운 스레드에서 한다고 치자.

작업이 끝나고 그 결과를 가지고 UI에 보여주고 싶다.

UI관련 작업은 메인스레드에서만 해야하는데 어떻게 보여줄까?

 

이때 Handler가 필요로 하다.

 

Handler는 스레드의 작업을 관리하고 스레드간에 작업을 전달하기 위한 용도로 존재한다.

 

굉장히 오랜시간동안 Handler가 UI를 변경하기 위한 용도라고만 생각해왔다.

작업스레드에서 UI를 처리하기 위해 주로사용하다 보니 그런 고정관념이 생겼던 것 같다.

 

 

새로운 스레드에서 작업을 마치면 결과를 가지고 변경할 UI 작업을

Handler를 통해 메인스레드에 전달하면 된다.

 

 

 

 

 


Handler 예시

 

    private val handler = MainHandler(this)

    companion object {
        const val HANDLE_WORK_UPDATE_PROGRESS = 1
        const val HANDLE_WORK_DONE = 2

        class MainHandler(
            activity : MainActivity
        ) : Handler() {
            private val activity = WeakReference<MainActivity>(activity)
            override fun handleMessage(msg: Message) {
                when(msg.what) {
                    HANDLE_WORK_UPDATE_PROGRESS -> activity.get()?.updateProgress(msg.obj as Int)
                    HANDLE_WORK_DONE -> activity.get()?.showDoneMessage()
                }

            }
        }
    }

    private fun processAndUpdateUI() {
        Thread {
            for(i in 0..10) {
                Thread.sleep(1000L)

                handler.obtainMessage().apply {
                    what = HANDLE_WORK_UPDATE_PROGRESS
                    val progress = i*10
                    obj = progress
                }.let {
                    handler.sendMessage(it)
                }
            }
            handler.sendEmptyMessage(HANDLE_WORK_DONE)
        }.start()
    }

    fun showDoneMessage() {
        tv_main_state.text = "completed"
    }

    fun updateProgress(progress: Int) {
        tv_main_state.text = "progress $progress"
    }

 

processAndUpdateUI()에서 10초동안 작업이 진행하며

매 1초마다 진행정도를 전달하는 UI작업 (HANDLE_WORK_UPDATE_PROGRESS)

10초가 모두 지나고 완료를 표시하는 UI작업 (HANDLE_WORK_DONE)

두가지를 Handler를 통해 처리하는 간단한 예시이다.

 

Handler에 메세지 외에도 Runnable을 던질 수도 있다.

 

AsyncTask, runOnUiThread 역시 내부적으로는 Handler를 이용하고 있다.

 

 

 

 

 


Handler의 동작 원리

 

 

위에 그림에서 Handler, MessageQueue, Looper역할을 알아야 한다.

 

 

1. Handler를 통해 스레드의 외부 혹은 내부에서 작업을 받는다.

2. 처리해야할 작업을 MessageQueue에 enqueue한다.

3. Looper는 처리해야할 작업이 있는지 계속해서 확인하고 Handler에게 처리를 맡긴다.

4. Handler는 해당 작업에 맞는 처리를 한다.

 

 

메인스레드에서 위와 같이 동작한다고 보면된다.

 

우리가 새로 만드는 작업 스레드는 여기서 Looper가 없기 때문에 직접 만들고 loop해줘야 한다.

그렇기 때문에 Looper를 포함한 HandlerThread를 지원한다. 

 

 

추천 포스팅

https://academy.realm.io/kr/posts/android-thread-looper-handler/

 

안드로이드 백그라운드 잘 다루기 Thread, Looper, Handler

안드로이드 백그라운드 잘 다루기 Thread, Looper, Handler

academy.realm.io

 

 

 

 


실제 비동기 사용

 

위에 Handler 예시를 LiveData를 사용해서 바꿔보았다.

 

    private val stateText = MutableLiveData<String>()

    private fun observe() {
        stateText.observe(this, Observer {
            tv_main_state.text = it
        })
    }

    private fun initViews() {
        btn_main_update_ui.setOnClickListener { processAndUpdateUI() }
        stateText.value = "start progress"
    }

    private fun processAndUpdateUI() {
        Thread {
            for(i in 0..10) {
                Thread.sleep(1000L)
                stateText.postValue("progress ${i*10}%")
            }
            stateText.postValue("done")
        }.start()
    }

 

LiveData를 공부없이 써서 맞게 쓴것인지 모르겠지만..

대략 반으로 코드 라인이 줄었다.

 

실제 회사에서 Handler를 UI 변경을 위해 사용하는 일은 드물 것이라 생각한다.

비동기를 더 쉽게하기 위한 정말 많은 기술과 조합이 있기 때문이다.

 

대표적으로 사용하는 비동기 기술로 Coroutine과 Rx가 있다.

 

 

 

 

 

'Android > Common' 카테고리의 다른 글

수명주기; Lifecycle  (0) 2020.06.22
안드로이드 개발자 로드맵  (2) 2020.05.07
안드로이드 프로젝트 루틴  (0) 2020.02.20

 

 

안드로이드 개발자로서 잘하는 개발자가 되기 위해선 무엇이 필요할까?

체워도 체워도 언제나 고민이다.

 

우연히 찾게된 안드로이드 개발자 로드맵 PPT이다.

네이버 테크 콘서트에서 발표한 내용을 담은 PPT였다.

더 검색해보니 영상도 찾을 수 있었다.

 

영상을 보면서 나오는 내용들 대부분은 접하거나 공부한 내용이다.

하지만 부족한 부분도 있고 공부했다 해도 완벽하게 설명할 수 있는가 하면 아니다.

 

안드로이드 개발자로서 튼튼한 기본기를 가지고

이를 바탕으로 더 많은 것을 할 수 있는 개발자가 되기를 바란다.

 

발표한 내용을 바탕으로 포스팅을 정리해보려 한다.

 

 

PPT

https://www.slideshare.net/NaverEngineering/techcon-2019-mobile-android3

 

[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵

NAVER WEBTOON | Son App Tech | 안중환 안드로이드개발자로드맵

www.slideshare.net

 

영상

https://tv.naver.com/v/9329737/list/486582

 

TECH CONCERT: MOBILE 2019 - 안드로이드 개발자 로드맵

NAVER Engineering | 내용 네이버 안드로이드 개발자 3년차가 되는 과정에서 졸업생은 무엇을 준비하고, 어떤 걸 공부해야 하는지 키워드와 노하우를 공유합니다.

tv.naver.com

 

 


기본기

 

CS(Computer Science)

DB + OS + Network + Algorithm + Data Structures

 

개발자라면 너무 당연히 접해본 것들이다.

대학교에서 공부했고 취업을 하기 위해 공부했고

실무를 하면서도 계속 부족하다고 느끼는 기본 중의 기본이다.

 

 

T자형 인재

DB + OS + Network + Algorithm + Data Structures + Git

Framework + Programming Language

 

Git을 사용하지 않는 회사는 거의 없다라고 생각한다.

Git까지 공부하고 나면 어떤 언어로 어떤 것을 개발할지 확장해 공부한다.

 

 

 

 


키워드

 

안드로이드 개발자로 정했다.

그렇다면 관련 키워드는 어디에서 나올까?

 

GoogleIO : 매년 구글의 기술을 설명하는 컨퍼런스

Android Dev Summit : 개발에 관해 집중적으로 발표하는 컨퍼런스

 

위의 컨퍼런스들을 통해 새로운 키워드들이 등장한다.

뒤늦게 대세가 된 후 접하기 보단 더 빠르게 기술에 대해 인지할 수 있다.

 

 

Android Developers Youtube : 컨퍼런스 발표 동영상이 올라와 있다.

https://www.youtube.com/user/androiddevelopers/videos

 

Android Developers

Welcome to the official Android Developers YouTube channel. Get the latest Android news, best practices, live videos, demonstrations, tutorials, and more. Su...

www.youtube.com

 

위의 컨퍼런스 외에 한국에서 진행하는 컨퍼런스들도 있다.

드로이드 나이츠, 코틀린 나이트, GoogleIO in Seoul, if kakao, Naver Deview

 

항상 관심을 가지고 참석해보도록 하자.

 

 

 

 

그 외에 사이트로

 

Android Weekly : 메일을 통해 안드로이드 뉴스를 전달해준다.

https://androidweekly.net/

 

Android Weekly - Free weekly Android & Kotlin development newsletter

Android Weekly is a free newsletter that helps you to stay cutting-edge with your Android Development.

androidweekly.net

 

 

 

 


안드로이드

 

개발을 하다보면 구글링이 필수가 된다.

 

하지만 구글링으로 나오지 않을 수도 있고 잘못된 정보를 다루고 있을 수 도 있다.

그렇기 때문에 공식 문서부터 찾아보는 방법을 권한다.

 

 

새로운 API를 접할 때

1. Android Developer 검색

2. Android Developer Medium, Blog 검색

3. CodePath Android Cliffnotes 검색

4. 구글링

 

 

Android Developer : 최신 정보는 영어로 먼저 나오기 때문에 영어로 보길 권장한다.

 - Android Studio / User Guide

 - Jetpack

 - Kotlin

 - Docs / Guides, References, Samples

https://developer.android.com/

 

Android 개발자  |  Android Developers

Android 앱 개발자를 위한 공식 사이트입니다. Android SDK 도구 및 API 문서를 제공합니다.

developer.android.com

 

Android Developer Medium

https://medium.com/androiddevelopers

 

Android Developers – Medium

The official Android Developers publication on Medium.

medium.com

 

Android Developer Blog

https://android-developers.googleblog.com/

 

Android Developers Blog

 

android-developers.googleblog.com

 

Google Codelabs : 코드베이스로 익혀나가고 싶다면...

https://codelabs.developers.google.com/

 

Google Codelabs

Google Developers Codelabs provide a guided, tutorial, hands-on coding experience. Most codelabs will step you through the process of building a small application, or adding a new feature to an existing application. They cover a wide range of topics such a

codelabs.developers.google.com

 

CodePath Android Cliffnotes : 사용법, 꿀팁, 관련 오픈소스

https://guides.codepath.com/android

 

Home | CodePath Android Cliffnotes

CodePath Android Cliffnotes Welcome to the open-source CodePath Android Cliffnotes! Our goal is to become the central crowdsourced resource for complete and up-to-date practical Android developer guides for any topic. Just take me to the notes! We have And

guides.codepath.com

 

 

기본적인 내용

4대 컴포넌트 : Activities, Services, BroadcaseReceivers, ContentProviders

Jetpack : Fragment, ConstraintLayout, ViewPager, RecyclerView...

Inflater

View

 

Inflate, View

 - XML -> Inflate -> 화면을 객체 형태로 만듬

 - 비용이 있는 동작

 - Layout Inspector로 만든 화면 보기 

 - 화면은 모두 View로 되어있다.

 - 화면은 View의 트리구조형태이며 전위 순회하며 깊이우선탐색하여 처리해나아간다.

 - 렌더링 : measure > layout > draw

 - Fragment 역시 View : 즉 Fragment보다 View를 재활용 단위로 가져가는 것이 좋다.

   View를 사용하면 xml에 넣거나 동적생성하여 재활성이 좋아진다.

 

 

 

 


비동기

  안드로이드의 꽃!   

 

 

비동기관련 기술들

 - Thread

 - Executor

 - CompletableFuture(java8, sdk>=24)

 - AsyncTask

 - Loader

 - WorkManager

 - Rx

 - Coroutine

 

AndroidDeveloper의 비동기 관련 내용

https://developer.android.com/

 

Docs - Core topics - Activities - Processes and app lifecycle

 - foreground process

 - visible process

 - service process

 - cached process

Docs - Core topics - Background tasks - Sending operations to multiple threads - Communicate with the UI thread

 - UI Thread 의 정의와 통신하는 방법

 - Handler, Looper, MessageQueue

Docs - Besr Practice - Processes and Threads Overview

 - Thread 기본 사용법

 

 

Callback에 대한 이해

 - Runnable 왜 있을까?

 - subroutines, lamda, expressions, blocks, function pointers...

 

concurrency vs parallelism

 

synchronous vs asynchronous

 

blocking vs non-blocking

 

Java Concurrent

 

#synchronized #volatile #atomic #semaphore #ReentrantLock #LockFree #FalseSharing #ForkJoinPoll #Executor #BlockingQueue #CountDownLatch #Future ...

 

 

Thread, MessageQueue, Handler, Looper에 대한 이해

#Consumer-Producer Patter #MainThread #UiThread #MessageQueue #Handler #MainLooper #Looper #HandlerThread

https://academy.realm.io/kr/posts/android-thread-looper-handler/

 

안드로이드 백그라운드 잘 다루기 Thread, Looper, Handler

안드로이드 백그라운드 잘 다루기 Thread, Looper, Handler

academy.realm.io

 

 

위에 내용을 이해하고 Rx, Coroutine을 사용하자

 

 

 

정확한 타이밍에 실행이 보장되길 원한다면

  : Foreground Service

특정 조건을 걸고 실행이 보장되길 원한다면

  : JobScheduler, JobDispatcher, AlarmManager, BroadcastReceivers

 

 

WorkManager in Jetpack

 - 기존의 파편화된 백그라운드 처리를 하나로 모아서 실행 

 

 

 

 


성능 최적화

 

초당 60프레임 : 프레임당 16ms

한 프레임에 16ms보다 더 오래 걸리는 경우 프레임 드랍이 발생

 

프레임 드랍이 발생한다면

 - MainThread -> WorkerThread

 - UI 업데이트가 순차적으로 진행될 수 있도록 조절

 - CPU -> GPU

 - GPU에 안그려도 되는 부분을 알려준다

 

#ViewHierarchy #DoubleLayoutTaxation #Async #Overdraw #AnimationProperty #Cache #Clipping #ObjectPool #HardwareAcceleration #VSYNC

 

 

발표에서 보여주고자 하는 동영상이 어디있는지 모르겠지만

같은 내용을 다루는 듯 하다.

https://www.youtube.com/watch?time_continue=8&v=qk5F6Bxqhr4&feature=emb_title

 

 

 


안드로이드 프레임워크

 

우리가 사용하는 부분은 Application Framework까지이다.

 

NDK 개발시에는 필수로 더 로우레벨까지 공부해야 한다.

 

 

Android Open Source Project

 - Cofigure / RUNTIME : 컴파일러 관련 내용

#.class #.dex #Dalvik #ART #D8 #R8 #AOT #JIT

 - Develop / GRAPHICS : 화면 렌더링 관련 내용

#SurfaceView #TextureView #BufferQueue, #SurfaceFlinger, #Surface, #Canvas, #SurfaceHolder 

 - Develop / ARCHITECTURE : IPC 관련 내용

#HAL #Context #Parcel # BinderIPC #SystemServices #MediaServer #SystemServer

https://source.android.com/ 

 

Android 오픈소스 프로젝트  |  Android Open Source Project

Android는 세계를 하나로 묶어줍니다. 오픈소스 Android 운영체제를 사용하여 강력한 기기를 만드세요.

source.android.com

 

 


언어

 

Kotlin이 인기가 많다.

Kotlin을 하려면 Java도 알아야 한다.

함수형 프로그래밍을 사용하기에는 Java보다는 Kotlin을 사용하는 것이 났다.

 

 

프로그래밍 패러다임

 - 기능에 따라 프로그래밍 언어를 분류하는 방법. 언어는 여러 패러다임으로 분류 할 수 있다.

 - 프로그래밍 관점을 갖게 해 주고, 결정하는 역할

 - 서로 다른 프로그래밍 언어는 서로 다른 프로그래밍 패러다임을 지원

 - 새로운 것을 가능하게도 하지만 어떤 기법을 금지 함

 

#StructuredProgramming #Object-OrientedProgramming #FunctionalProgramming #ReactiveProgramming
#FunctionalReactiveProgramming #Modular Programming

 

 

 

Kotlin과 Java는 객체지향프로그래밍, 함수형 프로그래밍패러다임을 가지고 있다. 

 

 

객체지향프로그래밍

 

#OOP #클래스 #객체 #메시지 #추상화 #캡슐화 #상속 #구성 #다형성 #S.O.L.I.D

 

 

디자인 패턴

 

SourceMaking

https://sourcemaking.com/

 

Design Patterns and Refactoring

Design Patterns and Refactoring articles and guides. Design Patterns video tutorials for newbies. Simple descriptions and full source code examples in Java, C++, C#, PHP and Delphi.

sourcemaking.com

 

 

 

함수형프로그래밍

 - 클래스가 아닌 함수가 재활용 단위

 - 함수는 1급 객체

 

#람다 #클로저 #순수함수 #고차함수 #lazy #커링 #재귀 #메모이제이션 #모나드

 

 

 


Best Practice

 

클린 아키텍처

클린 코드

리팩토링

 

굉장히 유명한 책들이다.

하지만 많은 학습이 전제되지 않은 상태에서는 의미가 없을 수 있다.

 

그러니 우선 이것만 해보자!

 - 함수는 한가지 일만 한다.

 - SRP : 클래스는 하나의 책임만 가진다.

 - 상속 대신 구성

 

 

드로이드 나이츠에서 발표한 Clean Arhcitecture

(몇년전 발표. 첫 드로이드 나이츠로 기억하고 있다.)

https://academy.realm.io/kr/posts/clean-architecture-in-android/

 

안드로이드에 Clean Architecture 적용하기

안드로이드 앱을 만들면서 두 번의 대규모 업데이트를 배경으로 코드가 계속 바뀌었고, 이런 변화하는 코드에 잘 대응할 수 있는 Clean Architecture에 대해 고민한 경험에 대해 공유하고자 합니다.

academy.realm.io

 


TODO

키워드 수집

기록해라 : 블로그, Git과 같은 것들로 기록해라

 

테스트

 - 유닛테스트를 작성해보자

 - 좋은 구조로 가는 지름길이 되기도 한다.

 - CI

 

#TDD #BDD #Junit #Dummy #Stub #Spy #Fake #Mock #Mockito #PowerMock #Robolectric #CI #Jenkins #TestCoverage #Jacoco

 

 

 

위에 내용들을  완벽 하게 익혀다고 생각한다면

다양한 기술들을 공부해 스펙트럼을 넓혀보자!

 

 

 

 

 

'Android > Common' 카테고리의 다른 글

수명주기; Lifecycle  (0) 2020.06.22
비동기  (0) 2020.05.14
안드로이드 프로젝트 루틴  (0) 2020.02.20

+ Recent posts