Coroutines

  • [Kotlin Coroutines] Log 를 사용한 Coroutines 디버깅

    로그를 사용한 디버깅의 필요성 Kotlin Coroutines는 같은 Coroutine Builder(launch, async 등) 의 중괄호 내부의 코드들이 다른 스레드에서 실행될 수 있다. 예를 들어 아래 코드에서 "task1 : start" 는 메인 스레드에서 실행되지만, "task1 : end"는 DefaultExecutor 스레드에서 실행된다. import kotlinx.coroutines.* fun main() = runBlocking { val task1 = launch(Dispatchers.Unconfined) { log("task1 : start") delay(100) log("task1 : end") } val task2 = launch { log("task2 : start") dela..

  • [Kotlin Coroutines] IntelliJ 사용해 Coroutines 디버깅 하기

    디버깅을 하기 위한 준비 Kotlin Coroutines는 일시 중단 후에는 다른 스레드에서 실행될 수 있기 때문에 디버깅을 하기가 매우 어렵다. 이 글에서는 디버깅을 하기 어려운 예 중에 가장 간단한 예시를 제시할 것이다. 다음의 코드를 보자. import kotlinx.coroutines.* fun main() = runBlocking { launch(Dispatchers.Unconfined) { println("launch1 Working Thread : ${Thread.currentThread().name}") delay(100) println("launch1 Working Thread : ${Thread.currentThread().name}") } launch { println("launch2..

  • [Coroutine Flow] flatMapMerge 을 사용해 flow 변환 동시 처리하기

    flatMapMerge는 무슨 역할을 하는가? flatMapConcat과 flatMapLatest는 flow에서 발행된 데이터를 변환할 때 발행된 순서대로 순차적으로 변환한다. 반대로 flatMapMerge는 변환을 병렬로 수행한다. 대부분의 연산이 flatMapConcat이나 flatMapLatest를 이용한 순차 처리에 해당하지만 들어오는 데이터들을 동시에 수집한 후 수집한 값들이 가능한 빨리 방출 될 수 있도록 병렬로 처리되어야 할 때가 있다. 예를 들어 비용 처리를 위해 수십개의 지출 데이터를 취합하여 합치는 작업을 할 경우 굳이 순차적으로 처리하지 않고 병렬로 처리되는 것이 빠를 것이다. flatMapMerge는 이러한 병렬 연산을 지원하기 위해 만들어진 연산자이다. flatMapConcat과 ..

  • [Coroutine Flow] flatMapLatest 이용해 최신 데이터만 사용해 flow 변환하기

    flatMapLatest란? flatMapLatest는 flow를 최신데이터만을 이용해 새로운 flow로 변환할 수 있도록 도와주는 함수이다. flatMapLatest를 사용하면 flow에서 발행된 데이터를 변환하는 도중 새로운 데이터가 발행될 경우, 변환 로직을 취소하고 새로운 데이터를 사용해 변환을 수행한다. collectLatest의 경우 먼저 발행된 데이터를 처리하는 도중 새로운 데이터가 들어올 경우 이전 데이터 처리를 취소하고 새로운 데이터를 이용해 데이터를 처리하는데 flatMapLatest는 collectLatest와 동작이 매우 유사하다. flatMapLatest 동작 살펴보기 예를 들어 다음과 같은 flow가 있다고 해보자. 이 flow는 1과 5를 순차적으로 발행한다. val flow ..

  • [Coroutine Flow] flatMapConcat을 사용해 flow를 다른 flow로 변환하기

    Flow의 Flattening Operator flow는 데이터 파이프라인이다. 코드 상에서 데이터 파이프라인은 그 자체로 사용되는 경우는 거의 없으며 보통 다른 데이터 파이프라인들과 합쳐져 하나의 데이터 파이프라인을 완성한다. flow 또한 여러 flow가 합쳐져 하나의 flow로 만들어지기 위한 연산자를 제공하는데 데이터 파이프라인을 합치는(Flatten) 연산자여서 Flattening Operator(하나로 만드는 연산자)라 한다. 우리는 이번 글에서 가장 대표적인 Flattening Operator인 flatMapConcat에 대해 다뤄볼 것이다. flatMapConcat 은 무엇을 하는가? flatMapConcat은 여러 flow를 연결하는(concatenating) 연산자이다. 이름에서 알 수..

  • [Coroutine Flow] conflate를 이용해 최신 데이터 collect 하기

    collectLatest를 이용한 최신 데이터 collect의 한계점 그림1과 같이 데이터 발행 시간 사이의 간격보다 데이터를 처리하는 suspend fun이 수행하는 시간이 오래 걸릴 경우, 새로 들어온 데이터는 계속해서 소비되지 못한다. 즉 이런 상황에서 collectLatest를 쓸 경우 중간 데이터를 하나도 얻지 못하고 마지막 데이터만을 얻을 수 있다. 예를 들어 아래 그림2와 같이 데이터 발행에 0.1초가 걸리는데 데이터 소비에 1초가 걸릴 경우 하나도 소비가 안되고 마지막 데이터만이 소비된다. conflate을 이용해 최신 데이터 collect하기 이를 해결하는 방법은 간단하다. 한 번 시작된 데이터 소비는 끝날 때까지 하고 데이터 소비가 끝난 시점에서의 가장 최신 데이터를 다시 소비하는 것이..

Kotlin

  • [Design Pattern] 파사드 패턴이란 무엇인가? : Facade Pattern

    파사드 패턴이란? 파사드 패턴은 일련의 저수준 인터페이스들을 하나의 고수준 인터페이스로 묶어주는 패턴이다. 클라이언트 객체가 여러 저수준 인터페이스의 동작을 제어 하려면 여러 저수준 인터페이스의 메서드들을 일일히 호출해야 하는데, 파사드 패턴을 이용하면 고수준 인터페이스의 메서드 호출 만으로 한 번에 할 수 있게 된다. *파사드 패턴에서는 고수준 인터페이스를 저수준 인터페이스를 통합했다 해서 '통합 인터페이스'라고 부른다. 저수준 인터페이스를 바꾸기 위해서 다른 인터페이스를 건드리지 않고 통합 인터페이스의 코드만 건드리면 되므로 클라이언트 객체는 여러 저수준 인터페이스에 대해 의존성이 느슨해진다. 파사드 패턴을 쓰지 않았을 때의 문제점 예를 들어 우리가 커피를 만든다고 해보자. 커피를 만들기 위해서는 원..

  • [Design Pattern] 커맨드 패턴이란 무엇인가?

    커맨드 패턴 커멘드 패턴은 하나의 객체를 통해 여러 객체들에 명령(Command)을 해야 할 때 사용되는 패턴이다. 커멘드 패턴을 사용하면 요청을 캡슐화해서 커멘드 객체가 명령을 해야하는 객체들에 대한 의존성을 느슨하게 만들 수 있다. 이 말이 무슨 말일까? 커멘드 패턴을 사용하지 않으면 여러 객체들에 명령(Command)를 하기 위해서는 명령을 하는 객체(커멘드 객체)가 명령을 받는 객체들을 알아야 한다. 예를 들어 집 안의 조명을 제어하는 LightController 클래스가 있다고 해보자. LightController는 제조사가 다른 조명들(MainLight, SubLight, BedRoomLight)에 대한 제어를 한다. LightController는 조명을 제어하기 위해 각 조명을 제어하는 메서..

  • 팩토리 메소드 패턴과 추상 팩토리 패턴의 차이 알아보기 : Factory Method Pattern, Abstract Factory Pattern

    팩토리 패턴은 무엇인가? 팩토리 패턴은 한 종류의 객체를 만들기 위해서 해당 객체를 생성하는 팩토리 interface를 구현해서 만드는 것이다. 예를 들어 Item을 만드는 Factory 인터페이스가 있다고 해보자. interface Factory { fun createItem() : Item } 위 Factory를 PhoneFactory와 TabletFactory로 구현하면 해당 Factory에서는 Item을 팩토리 종류에 따라 다르게 생성한다. class PhoneFactory : Factory { override fun createItem(): Item { return .. } } class TabletFactory : Factory { override fun createItem(): Item { ..

  • [Kotlin Factory Pattern] 팩토리 패턴이란 무엇인가?

    팩토리 패턴에 대한 오해 많은 사람들이 팩토리 패턴을 객체 생성을 위한 클래스를 사용하는 것으로 알고 있다. 실제로 많은 글들을 보면 팩토리 패턴을 공장에 input을 넣으면면 결과물이 나오는 그림으로 설명해놓는 것을 볼 수 있다. 하지만 위 패턴은 팩토리 '패턴'이 아니다. 어떻게 보면 Input에 따라 결과물을 다르게 만드는 전략 패턴의 일종으로 볼 수 있다. 보통 많은 사람들이 위와 같이 팩토리 패턴을 생각하는데, 위와 같은 팩토리를 "헤드퍼스트 디자인패턴"에서는 "심플 팩토리 관용구"라고 부르기도 한다. 그렇다면 팩토리 패턴이란 무엇일까? 팩토리 패턴이란? 팩토리 패턴은 객체를 생성하기 위해 필요한 인터페이스를 만든 후, 인터페이스를 구현하는 클래스에서 어떤 객체를 만들지 결정하는 패턴이다. 즉,..

  • [Kotlin] JSONObject 사용해서 JSON 처리하기

    JSONObject란? JSONObject란 JSON 형식의 String을 처리하도록 도와주는 Java 라이브러리이다. JSONObject 사용 준비하기 JSONObject를 사용하기 위해 더미 JSON 파일이 있다고 가정해보자. { "title": "android", "version" : 1, "isValid" : false, "types": [ "class", "interface", "object" ] } 위 JSON은 Kotlin String으로는 다음과 같이 변환된다. val result = "{'title':'android', 'version' : 0, 'isValid' : false, 'types':['class',''interface','object']}" JSONObject 사용하기 JSO..

  • [Kotlin] Strategy Pattern : 전략 패턴을 사용한 유연성 증대 전략

    전략 패턴이란? 전략 패턴이란 런타임에 교체 가능한 알고리즘을 만드는데 사용되는 패턴이다. 하나의 객체가 다양하면서 변화하는 역할을 해야할 때 사용된다. 이름이 전략 패턴인 이유는, 객체의 행위를 전략(Strategy)을 통해 동적으로 바꿔주도록 해서 객체를 유연하게 만드는 패턴이기 때문이다. 전략 패턴 예시 우리가 이메일을 보낸다고 해보자. 이메일에는 시작말과 맺음말이 들어가며 사람마다 혹은 기기마다 이를 다르게 설정할 수 있어야 한다. 예를 들어 아마 한 동안 아이폰에서 메일을 보냈을 때 끝에 "Sent from IOS"라는 문구가 들어갔던 것을 기억할 것이다. 어떤 사람들은 아이폰을 사용하지 않음에도 저 문구가 멋있어 보여서 마지막에 "Send from IOS"라는 문구를 붙여서 보내기도 했다. 이..

Android

  • [Android] LruCache 사용해 이미지 캐싱하기(Bitmap Cache)

    LruCache 란? LruCache객체는 안드로이드에서 캐시를 관리하기 위해 사용하는 메모리 캐시 객체이다. LruCache 객체는 LRU(Least Recent Used) 알고리즘을 사용하는데 간단히 말해서 최근에 조회된 것을 캐시에서 삭제하는 것을 늦추기 위한 객체이다. 즉, 오랫동안 접근되지 않은 메모리가 우선적으로 삭제된다. 안드로이드에서는 이 알고리즘에 대한 구현체를 제공하는데 바로 LruCache 클래스이다. LruCache 객체 내부를 보면 다음과 같이 선언되어 있다. *java 코드이니 감안해서 보도록 하자. public class LruCache { public LruCache(int maxSize) { .. } .. } 이 LruCache는 제네릭으로 선언되어 있는데 K가 캐시에 접근..

  • [Android Error] java.lang.SecurityException: Permission denied (missing INTERNET permission?) : 문제 원인과 해결법

    문제 이유 안드로이드에서 다음과 같은 로그가 떨어지는 경우가 있다. java.lang.SecurityException: Permission denied (missing INTERNET permission?) 아래 문서를 참조하면 안드로이드는 인터넷에 접속하는 것을 일반 권한으로 설정하고 있다. https://developer.android.com/training/basics/network-ops/connecting 네트워크에 연결 | Android 개발자 | Android Developers 네트워크에 연결 애플리케이션에서 네트워크 작업을 실행하려면 매니페스트에 다음 권한을 포함해야 합니다. 참고: Internet과 ACCESS_NETWORK_STATE 권한은 모두 일반 권한입니다. 즉, 이러한 권한은 ..

  • [Android] WebView 디버깅 하는 방법 한 번에 정리하기 : Chrome 사용해 Debugging 하기

    안드로이드 웹뷰 디버깅 안드로이드 프로젝트에 웹뷰를 넣게 되면 직접 디버깅을 하기 매우 어려워진다. 로그를 직접 출력하는 것도 제한이 걸려서 어떤 곳에서 오류가 나는지 알 수 없다. 이를 위해 구글에서는 안드로이드 웹뷰를 Chrome을 사용해 디버깅 하는 방법을 제공한다. Chrome을 사용해 디버깅을 하기 위해서 몇가지 준비사항이 있다. 아래를 따라서 해보자. 디버깅 준비하기 1. 안드로이드 USB 디버깅을 활성화한다. USB를 통해 디버깅을 하기 위해서는 [설정 - 개발자 옵션 - USB 디버깅] 을 활성화 해주어야 한다. *이 글을 보는 사람은 개발자 옵션은 이미 활성화되어 있다고 가정한다. 2. Activity에서 WebView Debugging을 허용 하도록 변경 WebView.setWebCon..

  • [Android] WebView와 브릿지를 사용해 통신하는 방법 한 번에 정리하기

    개요 안드로이드를 개발하다보면 웹뷰를 쓸 일 이 생긴다. 최대한 안드로이드 컴포넌트로 뷰(View)를 개발하면 좋겠지만, 안드로이드 컴포넌트로 뷰를 개발할 경우 유연성이 떨어지게 된다. 물론 안드로이드 컴포넌트로도 유연성 있게 개발을 할 수 있지만, 이미 작성된 코드 내에서의 유연성이 생길 뿐이다. 이에 따라 유연성이 필요한 곳에서는 웹뷰를 쓰는 곳이 많다. 웹뷰를 사용하기 위해서는 Android와 Webview간 통신 방법을 알아야 한다. 이번 글에서는 브릿지를 만드는 방법에 대해 알아보고자 한다. 브릿지란? 브릿지란 안드로이드와 웹뷰의 통신을 위해 만들어지는 Javascript용 인터페이스이다. 웹뷰에서는 안드로이드의 메서드를 직접 호출하는 것이 불가능하기 때문에 '브릿지'라는 통로를 통해 호출해야 ..

  • 오류 수정 방법 : Android Gradle plugin requires java 11 to run. you are currently using java 1.8

    이번에 안드로이드 스튜디오를 Artic Fox로 올리면서 다음과 같은 오류가 생겼다. Build file '/Users/james.c/AndroidStudioProjects/MyApplication7/app/build.gradle' line: 2 An exception occurred applying plugin request [id: 'com.android.application'] > Failed to apply plugin 'com.android.internal.application'. > Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8. You can try some of the following opti..

  • R8을 이용해 안드로이드 앱을 최적화하고 코드 유출 방지하기 : minifyEnabled, shrinkResource, proguard

    안드로이드 앱의 보안은 왜 중요할까? 우리가 안드로이드 앱을 빌드하면 aab파일 혹은 apk파일로 만들어진다. 뭔가 aab나 apk하면 보안이 강할거 같다는 생각이 들지만 이 방식들은 단순히 우리가 짠 코드들을 압축한 것에 불과하다. 따라서 apk의 압축을 풀면 우리가 짠 코드의 내부가 모두 보인다. 우리가 안드로이드 앱을 빌드하면 윈도우 상에는 그림1과 같은 apk파일이 생긴다. 더블 클릭해도 열리지는 않지만 이를 안드로이드 스튜디오에서 보면 내부의 파일이 아래와 같이 모두 보이는 것을 알 수 있다. 만약 이 상태로 앱을 출시한다면 앱의 리버스 엔지니어링이 가능하다는 뜻이며, 누군가 우리의 코드를 베껴 새로운 앱을 낼 수도 있다는 이야기이다. 따라서 우리는 우리 앱의 구조를 파악하지 못하게 할 장치가 ..

Spring

  • Spring MVC Framework란 무엇인가? Spring MVC의 구조와 의의

    Spring MVC란 무엇인가? Spring MVC는 Spring에서 제공하는 웹 모듈로, Model, View, Controller 세가지 구성요소를 사용해 사용자의 다양한 HTTP Request을 처리하고 단순한 텍스트 형식의 응답부터 REST 형식의 응답은 물론 View를 표시하는 html을 return하는 응답까지 다양한 응답을 할 수 있도록 프레임웍이다. Spring MVC는 다양한 요청을 처리하고 응답하기 위해 주요 구성요소들을 만들어놓고 구성요소들을 확장할 수 있게 만들어 놓는데, 이들을 제대로 사용하기 위해서는 MVC가 어떻게 구성되어 있는지를 알아야 한다. 이번 글에서는 MVC가 어떤 구조로 이루어져 있는지, 각 구성요소들이 어떤 역할을 하는지를 알아볼 것이다. Sprint MVC의 구조..

  • [Spring] Servlet에서 Request 처리해 Response 리턴하기

    Servlet에서 Request의 파라미터를 받아오는 방법 예를 들어 다음과 같이 user에 대한 쿼리를 넣어 http 요청을 한다고 해보자. http://localhost:8080/hello?user=devcho 서블릿 상에서 위 user을 받아오기 위해서는 HttpServletRequest 인터페이스의 getParameter 메서드를 이용하면 된다. getParameter은 인풋을 String으로 받으며 결과값을 리턴하는 메서드로 user 파라미터를 받아오기 위해 다음과 같이 사용할 수 있다. @WebServlet(name = "helloServlet", urlPatterns = ["/hello"]) class HelloServlet : HttpServlet() { override fun servic..

  • [Spring] Servlet 만드는 방법 정리

    Spring에서 서블릿 만드는 방법 1. 서블릿 스캔을 위해 SpringBootApplication 위에 @ServletComponentScan Annotation을 붙인다. @ServletComponentScan // 서블릿 자동 등록 @SpringBootApplication class ServletExampleApplication fun main(args: Array) { runApplication(*args) } 2. 1에 의해 ServletExampleApplication 하위의 모든 패키지의 @WebServlet이 스캐닝 되므로 base 패키지를 추가하고 HelloServlet 클래스를 추가한다. 3. HelloServlet 클래스는 다음과 같이 작성한다. @WebServlet Annotatio..

CI/CD

  • [Gradle] 프로젝트 수준의 Gradle에서 모듈 수준의 Gradle 제어하기

    Project 수준의 build.gradle에서 모듈 수준의 build.gradle 제어하기 멀티 모듈 프로젝트를 만들다보면, 모든 모듈에 dependencies나 task들이 적용되어야 하는 경우가 있다. 이를 위해 프로젝트 수준의 build.gradle에서 모듈 수준의 build.gradle을 제어해야 할 경우가 생긴다. 이를 위해 Gradle에서는 allprojects, subprojects, project 메서드를 제공하는데 이번 글에서는 이 메서드들을 다루어볼 것이다. allprojects : 프로젝트 수준의 build.gradle 뿐만 아니라 해당 프로젝트에 포함된 모든 모듈의 build.gradle을 제어 subprojects : 해당 프로젝트에 포함된 모든 모듈의 build.gradle을 ..

  • [Gradle] Plugin이란 무엇인가? 플러그인 이해하고 Custom Plugin 만들기

    Gradle Plugin이란? Plugin이란 Gradle Task의 집합이다. Gradle Task는 어플리케이션 빌드부터 테스트까지 다양한 작업을 수행하는 작업 단위를 뜻한다. *만약 Task에 대한 이해가 부족하다면 다음글을 참조하길 바란다. Plugin을 우리가 특정 작업(어플리케이션 개발 등)을 하기 위해서 모아놓은 Task 들의 묶음이다. 예를 들어 안드로이드 어플리케이션을 개발하기 위해서는 필요한 라이브러리들을 받아온 후 해당 라이브러리들을 사용해 코틀린이나 자바 코드를 컴파일하고, 컴파일된 바이트코드의 묶음을 패키징 해 apk나 aab 파일로 만들어야 한다. 추가적으로 DB와 통신하는 부분들에 문제가 없는지, 서버와 통신하는 부분들에 문제가 없는지에 대한 테스트를 돌리기도 해야 한다. 이러..

  • [Gradle] Custom Task 만들고 Task Chaining 하기

    build.gradle의 task build.gradle의 task는 Project 객체의 메서드이다. task는 task이름과 람다식을 인자로 받으며, 이 task는 gradle [task 이름]을 통해 수행 가능해진다. build.gradle에 커스텀 task 만들기 build.gradle에는 메서드와 같이 커스텀 task를 만들 수도 있다. 커스텀 task는 다음의 문법으로 만들어진다. task 자체가 메서드이며, task의 인자로 task 이름이 넘어간다. task [task 이름] { [task에서 수행할 람다식] } Groovy는 다양한 방식으로 task를 만들 수 있다. 이는 Groovy의 특수한 문법 때문인데, String에서 ""을 생략하고도 쓸 수 있고 메서드를 수행하기 위해 [메서드명..