반응형 전체 글152 lateinit, 정말 안전한가 lateinit은 Kotlin이 주는 편리한 도구다. null 체크 없이 프로퍼티를 나중에 초기화하겠다고 선언하면, 컴파일러는 그 약속을 믿고 넘어간다. 문제는 그 약속이 깨졌을 때다. onCreate에서 초기화하기로 했던 값이 어떤 경로로든 빠지면, onResume이나 다른 시점에서 UninitializedPropertyAccessException이 터진다. 그것도 하필 프로덕션에서, 하필 재현하기 어려운 타이밍에.이 글에서는 lateinit이 왜 이런 함정을 만드는지, 그리고 nullable로 바꾸는 것이 어떤 점에서 더 안전한 선택인지 코드로 짚어본다.lateinit의 실체lateinit var는 사실 컴파일러가 null 체크를 프로퍼티 접근 시점으로 미뤄주는 문법 설탕이다. 내부적으로는 backi.. 2026. 7. 14. Compose에서 state를 어디서 읽느냐가 성능을 가른다 드래그 제스처 하나 처리하려고 만든 Composable이 프레임마다 리컴포지션을 일으키는 걸 본 적이 있을 것이다. 로직은 분명 맞는데 프로파일러를 열어보면 Composition, Layout, Drawing이 매 프레임 전부 돌고 있다. 원인은 대부분 하나다. state를 읽는 위치가 너무 이르다.이 글은 Compose 렌더링 파이프라인에서 state read의 위치가 왜 성능에 직결되는지, 그리고 이를 어떻게 뒤로 미룰 수 있는지를 다룬다.Compose가 프레임을 그리는 세 단계Compose는 화면을 그릴 때 세 단계를 거친다.Composition 단계에서는 Composable 함수를 실행해서 UI 트리를 만든다. Layout 단계에서는 각 노드를 측정하고 배치한다. Drawing 단계에서는 실제 픽.. 2026. 7. 13. NavController를 갈아엎은 이유, Navigation 3 뜯어보기 Compose로 화면 전환을 짜본 사람이라면 NavHost와 NavController 조합이 묘하게 불편했던 기억이 있을 것이다. 백스택은 내부에서만 관리되고, 인자는 "detail/{id}" 같은 문자열 라우트로 넘기다 오타 하나에 런타임 크래시가 난다. Compose는 상태를 선언적으로 다루라고 하면서 정작 네비게이션만 블랙박스로 남아있던 셈이다. Navigation 3는 이 어긋남을 정면으로 손댄 라이브러리다.문제는 백스택을 누가 쥐고 있느냐였다Navigation 2는 원래 XML 시대에 설계된 구조를 Compose 위에 얹은 것이라 태생적인 한계가 있었다. NavController가 백스택을 캡슐화해버리니 특정 화면 두 개를 건너뛰거나 순서를 바꾸는 것 같은 조작이 까다로웠고, 문자열 라우트는 컴.. 2026. 7. 10. Room은 그대로 두고 동기화만 얹는다 — SyncForge의 아웃박스 설계 오프라인 우선 앱을 만들 때 가장 어려운 부분은 로컬 저장이 아니라 "그다음"이다. 네트워크가 끊긴 동안 쌓인 변경을 어디에 보관할지, 앱이 죽어도 유실되지 않게 할지, 서버와 로컬이 동시에 수정된 레코드는 누가 이기는지. 이 세 가지를 직접 구현하다 보면 WorkManager 큐, 플래그 컬럼, 재시도 로직이 앱 DB 스키마 곳곳에 스며들어 나중에 걷어내기 힘들어진다.SyncForge는 이 문제를 꽤 명확한 원칙 하나로 푼다. 앱의 엔티티는 기존처럼 Room(또는 자체 저장소)에 두고, 동기화에 필요한 상태는 라이브러리가 소유하는 별도의 SQLDelight DB에 격리하는 것이다. 아웃박스와 충돌 기록이 앱 스키마를 오염시키지 않는다는 점이 이 라이브러리의 핵심 가치다.아웃박스 패턴을 라이브러리가 대신.. 2026. 7. 6. dependencies { } 는 왜 함수처럼 안 생겼는데 함수일까 ``` 로 시작하며, 실제로 동작하는 Kotlin 코드(람다 리시버 비교, RequestSpec DSL, DslMarker 적용)를 포함하고 있다. 2026. 7. 3. 백만 줄 스레드 코드를 코루틴으로 바꾸되, 호출부는 한 줄도 건드리지 않는 법 수십만 줄의 레거시 코드가 오래된 커스텀 스레딩 라이브러리에 의존하고 있다고 가정해보자. 그 라이브러리를 코루틴으로 교체하고 싶은데, 호출부를 전부 손대는 건 현실적으로 불가능하다.이럴 때 쓸 수 있는 전략이 있다. 라이브러리의 내부 구현만 교체하고, 기존 API는 그대로 유지하는 것이다. 핵심 파일 몇 개를 다시 쓰는 것만으로 전체 코드베이스가 코루틴 위에서 돌아가게 할 수 있다.왜 내부만 교체하는 전략인가호출부를 바꾸는 방식은 이론적으로 깔끔하지만 비용이 너무 크다. 수천 개의 호출부를 suspend 함수로 바꾸거나 launch 블록으로 감싸야 하고, 이 과정에서 버그가 조용히 끼어들 수 있다.반면 내부만 바꾸면 기존 API를 유지하면서 실행 엔진만 교체할 수 있다. 호출부는 예전 패턴 그대로 쓰고,.. 2026. 6. 30. 이전 1 2 3 4 ··· 26 다음 반응형