오늘은 정답자가 적은 문제 중에 하나로 골라 풀어보았다. 한글로된 문제를 읽었을 때는 살짝 헷갈리는 문제였는데, 입출력 예시와 비교하면서 문제를 제대로 이해하게 됐다. 문제에서는 특정 인덱스부터 시작하는 문자열을 접미사라고 하는데 그냥 모든 인덱스에서 마지막 글자까지 자른 것이 접미사이다. 풀이 먼저 반복문을 사용해 리턴할 배열에 원소를 넣어주기 전에 리턴할 배열의 길이를 정해야 한다. 생각해보면 주어진 문자열의 길이만큼의 숫자가 리턴할 배열의 길이가 된다. 이제 반복문을 사용해 가장 긴 문자열부터 가장 짧은 문자열까지 배열을 채워준다. 그 다음 문제의 요구사항은 해당 배열이 정렬되어 있는 것인데 사전 순으로 정렬이 되어야한다. 보통 사전은 가나다순. 즉, 오름차순이기에 sort() 메소드를 사용했다. ..
지금까지 코루틴을 공부하면서 보면 이 녀석은 특정 시점에 내 맘대로 멈추고 다시 실행시키는데 이런 동작은 참 신기하다. 그래서 이번 글에서는 코틀린 컴파일러가 내부적으로 어떻게 동작하는지 살펴보겠다. 코틀린 컴파일 과정 사실 이렇게 제목을 달아야할까 싶을 정도로 간단히 적을 내용이다. 자바를 알고 있는 개발자라면 자바가 어떻게 컴파일되는지 알고 있을텐데 코틀린도 유사하다. .kt 확장자를 가진 파일을 코틀린 컴파일러가 .class 확장자인 바이트코드로 변환한다. 이게 끝이다. 바이트코드를 Decompile하면? 대체 뭐가 나올까? .java 파일로 decompile된 코드가 보인다. Android Studio에서 해당 과정을 진행할 수 있는데 Tools - Kotlin - Show Kotlin Bytec..
이번 글은 저번 글 문맥이 살짝 섞여있는데, 간단히 말해 저번 글에서는 코루틴을 메인 스레드에서만 실행했다. 그래서 이번 글에서는 코루틴을 다른 스레드에서 실행해보려고 한다. 다른 스레드에서 코루틴 실행하기 바로 예제를 통해 알아보자. fun main() = runBlocking { println("main starts") joinAll( async { threadSwitchingCoroutine(1, 500) }, async { threadSwitchingCoroutine(2, 300) } ) println("main ends") } suspend fun threadSwitchingCoroutine(number: Int, delay: Long) { println("Coroutine $number sta..
코루틴 개념에 관한 글을 보면 다들 코루틴은 경량 스레드(light-weight threads)라고 소개하고 있다. 그런데 사실 코루틴을 처음 공부하는 사람이라면 이 문장은 잘 와닿지 않는다. 그냥 그렇구나.. 하고 넘어가긴 했지만 제대로 이해한 적은 없다. 개념적으로도 그렇지만 실제로 코루틴이 스레드보다 가벼운지도 궁금했다. 그래서 이번 글에서는 코루틴이 실제로 스레드보다 가볍다는 사실을 코드와 실행 결과로 기록해보려 한다. 코루틴 100만개 실행하기 fun main() = runBlocking { repeat(1_000_000) { launch { delay(5000) println(".") } } } 이 코드를 실행하면 정말 "."이 백만개 찍힌다. 그럼 이제 같은 코드를 스레드로 실행시켜보자. 스..
오늘 문제는 리스트를 자르는 부분이 필요해서 한 번 풀어보게 되었다. 문제 문제를 읽어보면 주의해야할 점이 하나 있었다. 바로 인덱스에 관련한 것인데 입출력 예시에서 보면 n값이 3일 때, num_list의 2번 인덱스에서부터 자르는 모습을 볼 수 있었다. 풀이 풀이 코드는 한 줄로 적었기 때문에 읽을 때 무리가 없을 것이라 생각한다. 주어진 배열을 리스트로 변경한 뒤, 주어진 인덱스에 맞춰 자르고 다시 배열로 형변환을 해주었다. 실행 결과
이번 문제는 제목에 충실한 문제다. 문제를 먼저 살펴보자. 문제 연산자에 대한 진리표를 보면 아랫 화살표는 OR 연산으로 보이고, 윗 화살표는 AND 연산으로 보인다. 풀이 결국 문제에서 주어진 네 개의 변수값을 원하는 식에 대입해주면 되는데 먼저 x1, x2의 결과가 true일 때 x3, x4의 연산값이 의미가 있고 false인 경우, 무조건 false로 리턴되어야 한다. 실행 결과
이번에는 안드로이드 UrlQuerySanitizer를 Url Query를 파싱하는데 사용하지 않을 때 생긴 문제를 다루고자 한다. 문제 발생 배경 최근 새 프로젝트를 진행 중, API 응답이 json, xml, csv와 같은 형식이 아닌 URL의 GET method 사용 시 붙어있는 Query 형식으로 body 값을 주는 녀석이 있었다. 물론 반복문을 사용해서 일일히 파싱할 수도 있었지만, Retrofit에서 json, xml 형식을 곧장 객체로 변환해주는 기능을 맛 본 이상 그 전으로 돌아가긴 싫었다. 그래서 찾다 보니 우회할 방법으로써 찾은 녀석이 UrlQuerySanitizer였다. 알고 보니 API level 1부터 유구한 역사를 가진 친구였지만 처음 들어봤다.(^^) UrlQuerySanitiz..
이번에는 저번 글과 이어지는 부분이 있는데 시스템 파일로 저장된 크래시 로그 저장하는 방법에 대해 소개해보려 한다. 필요해진 배경 며칠동안 앱을 실행시켜두고 안전성 테스트를 하던 도중이었다. 그런데 갑자기 주말이 지나서 보니 앱이 죽어있던 것이 아닌가.. 분명 어떤 이유에서인지 비정상 종료가 되었을 것인데 그 원인을 보고 싶어 검색해보게 되었는데, 안드로이드에서 크래시 로그를 파일로 저장하는 폴더가 있다고 해서 그 내부를 살펴보게 되었다. 목표물 안드로이드 시스템 내부에 tombstones 라는 폴더가 존재하는데 진짜 언어 그대로 죽은 이유를 적어둔 백트레이스를 가진 폴더이다. 내부를 확인해보니 "tombstone 0"과 같은 형식으로 tombstone에 숫자를 더한 형식의 이름을 가진 파일들이 있었고,..
오늘은 ADB(Android Debug Bridge)로 스크린샷을 찍고 저장하는 방법에 대해 공유해보겠다. 필요해진 배경 이 기능이 필요했던 이유를 설명하자면 Android TV 같은 녀석들은 Android Studio가 설치된 컴퓨터와 USB 연결을 통해 실행할 수 없는 경우가 있다. 그렇게 되면 같은 Wifi 망에 접속해 원격 ADB로 실행해야 했다. 또한 Android TV 같은 경우 일반 스마트폰처럼 전원버튼과 음량버튼으로 스크린샷을 찍을 수 없기 때문에 이 글의 주제인 ADB로 스크린샷 저장하는 방법을 찾아보게 되었다. 방법 일단 ADB로 디바이스가 연결되어있다는 전제 하에 글을 작성해보도록 하겠다. adb shell screencap -p /sdcard/screenshot.png 위 명령어를 ..