| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- WebView
- 알고리즘 자바
- coroutine
- 안드로이드
- 프로그래머스 알고리즘
- Java
- Android Jetpack
- 코틀린 코루틴
- Android Interceptor
- MVP Architecture
- Android Navigation
- Android 12 대응
- 안드로이드 카카오 로그인
- Android ProgressBar
- 습관만들기
- 카카오 알고리즘
- OkHttp Interceptor
- Android
- DataBinding
- Android 12
- Android ViewPager2
- 영어공부
- 안드로이드 갤러리 접근
- Android WebView
- Kotlin FCM
- 66챌린지
- scope function
- Kotlin
- 영어독립365
- android recyclerview
- Today
- Total
목록전체 글 (150)
주맨의 개발노트
운영진으로 참여하고 있는 IT 동아리에서 운영 관련 질문에 답해 주는 도우미를 만들고 있습니다. 처음 계획은 당연히 "에이전트"였습니다. 요즘 LLM으로 뭔가를 만든다고 하면 다들 에이전트를 이야기하니까요.그런데 Anthropic의 「Building effective agents」를 읽고 나서 방향을 바꿨습니다. 이 글은 에이전트를 잘 만드는 법보다 에이전트를 언제 만들지 말아야 하는지를 먼저 이야기합니다.이 글은 원문의 앞부분(정의, 사용 시점, 프레임워크)을 읽으며 정리한 내용을 바탕으로, 원문이 말하는 원칙을 세 가지 단순함으로 묶고 제 프로젝트에 대어 본 기록입니다.출발점 — 성공한 팀들은 단순했다Anthropic은 지난 1년간 여러 산업에서 LLM 에이전트를 만드는 수십 개 팀과 협업했습니다. ..
요즘 "AI 에이전트"라는 말을 정말 자주 듣습니다. 그런데 막상 "그래서 챗봇이랑 뭐가 다른데?"라는 질문을 받으면 선뜻 답하기 어렵습니다. 둘 다 LLM을 쓰고, 둘 다 자연어로 대화하기 때문입니다.이 글은 IBM의 「AI 에이전트란 무엇인가?」 문서를 읽으며 공부한 내용을 바탕으로, 챗봇과 AI 에이전트의 차이를 도구, 메모리, 계획이라는 세 가지 기준으로 정리한 기록입니다. 그리고 그 기준을 Claude Code와 Codex로 개발해 온 제 경험에 대어 보았습니다.LLM만으로는 왜 부족할까출발점은 LLM의 한계입니다. LLM은 학습한 데이터를 기반으로 응답을 만듭니다. 학습이 끝난 시점에 지식이 멈춘다는 뜻입니다. 오늘 날씨, 회사 내부 문서, 지난번에 나눴던 대화처럼 학습 데이터에 없는 정보는 ..
[Navigation3] rememberNavBackStack()은 왜 Reflection을 사용할까?에서는 Android의 기본 rememberNavBackStack()이 Reflection 기반 NavKeySerializer를 사용하는 이유를 살펴봤습니다.핵심은 열린 다형성인 NavKey 자체가 Reflection을 강제하는 것이 아니었습니다. 기본 API가 별도의 구현체 등록 없이 간단하게 동작할 수 있도록 NavKeySerializer를 선택했고, 이 serializer가 런타임에 실제 클래스와 serializer를 탐색하기 때문에 Reflection이 발생합니다.그렇다면 앱에서 사용하는 navigation key를 sealed interface로 정의하면 Reflection을 피할 수 있을까요?..
Navigation 3에서 저장 가능한 back stack을 만들 때는 보통 rememberNavBackStack()을 사용합니다. NavigationRoot.kt Kotlin val backStack = rememberNavBackStack(Home)이 API는 Compose 계층에서 back stack을 기억할 뿐 아니라 Configuration Change와 시스템에 의한 Process Death 이후에도 navigation state를 복원할 수 있도록 돕습니다.사용하는 입장에서는 간단하지만, SavedStateConfiguration을 받지 않는 Android용 rememberNavBackStack(vararg elements: NavKey) 오버로드는 내부적으로 Reflec..
들어가며Android에서 navigation을 이야기하면 보통 "어떤 화면으로 이동할 것인가"를 먼저 떠올립니다. 상품 목록에서 상품 상세로 이동한다면 기존 Jetpack Navigation에서는 NavController에게 특정 route로 이동하라고 명령하는 코드가 자연스럽습니다.기존 Navigation KotlinnavController.navigate("productDetail/$productId")Navigation 3는 같은 장면을 조금 다르게 바라봅니다. 화면으로 이동하라는 명령을 보내기보다, 앱이 소유한 back stack에 화면을 식별하는 key를 추가합니다.Navigation 3 KotlinbackStack.add(ProductDetail(productId))겉으로는 리스트에 값을 하나..
브랜치를 바꾸려면 하던 일을 먼저 치워야 합니다. git stash로 밀어두고, 브랜치를 옮기고, 일을 끝내고, 다시 돌아와서 꺼냅니다. 익숙한 순서입니다.그런데 Android 프로젝트에서는 이 왕복이 생각보다 비쌉니다. 브랜치를 옮기면 소스가 통째로 바뀌므로 Gradle sync가 다시 돌고, 증분 빌드 상태가 무효화되면서 다음 빌드에서 상당 부분을 다시 컴파일합니다. 세 줄 고치면 끝나는 핫픽스 앞뒤로 그보다 긴 시간이 붙습니다.git worktree는 이 왕복 자체를 없애는 기능입니다. 브랜치를 바꾸는 대신 작업 디렉토리를 하나 더 두는 방식입니다. 다만 공짜는 아니고, Android에서는 치러야 할 것이 몇 가지 있습니다. 이 글에서는 worktree가 정확히 무엇을 격리하고 무엇을 격리하지 않는..
Compose를 배우면 상태 호이스팅(state hoisting)을 "왜 해야 하느냐"는 질문에 대해 대개 같은 답을 듣습니다. 재사용성이 좋아지고, 테스트가 쉬워지고, 관심사가 분리되고, 단방향 데이터 흐름(UDF)을 따르고, 단일 진실 공급원(SSOT)을 보장한다는 것입니다.전부 맞는 말이고, 상태 호이스팅을 하는 이유도 결국 여기에 있습니다. 요구사항이 바뀌어도 고쳐야 할 코드가 적고, 한 번 만든 컴포넌트를 여러 화면에서 다시 쓰고, UI를 손보는 일과 상태 로직을 손보는 일이 서로 발목 잡지 않는 — 그런 코드를 만들기 위해서입니다.다만 이 답은 "무엇이 좋아지는가"까지만 말해 줍니다. 그 효과가 어떤 원리로 생기는지, 그리고 이 원칙을 어디까지 적용해야 하는지는 한 걸음 더 들어가야 보입니다...
Compose로 화면을 설계하다 보면 한 번쯤 마주치는 고민이 있습니다. 화면 하나를 만들 때 Composable 함수를 어떻게 쪼갤 것인가 하는 문제입니다.보통 두 가지 선택지를 두고 고민하게 됩니다. 하나는 *Screen() 내부에서 *Content()를 호출하고, *Content()가 UI 렌더링을 담당하는 구조입니다. 다른 하나는 *Screen() 내부에서 곧바로 여러 Component 함수들을 조합해서 UI 렌더링까지 책임지는 구조입니다. 후자는 결국 *Content()의 역할을 *Screen()이 그대로 떠안는 셈입니다.두 경우 모두 전제는 같습니다. 개별 UI 조각(Component)은 이미 따로 분리되어 있다고 가정합니다. 그러니 여기서 다루고 싶은 것은 “Component를 어떻게 나눌 ..
Claude Code를 프로젝트에 적극적으로 활용하면서 개발 속도는 확실히 빨라졌습니다. 새 화면의 기본 구조를 만들고, 반복적인 보일러플레이트를 작성하고, 유사한 패턴을 이어가는 작업에서 특히 효과가 컸습니다.그런데 속도가 빨라진 만큼 새로운 문제가 생겼습니다. 코드 리뷰에서 MVI 패턴 위반이 발견되기 시작했습니다. CLAUDE.md에 MVI 규칙을 상세히 적어뒀는데도, Agent가 생성한 코드가 실제로 그것을 따랐는지 보장할 수 없었습니다.이 글은 그 문제를 해결하기 위해 마틴 파울러의 Harness Engineering 개념을 참고하고, Detekt 커스텀 룰을 Sensor로 도입한 경험을 정리한 기록입니다.Agent가 MVI 규칙을 어겼다제 프로젝트의 feature 모듈은 MVI 패턴을 표준으로..
사내 테스트 앱을 확인하는 과정은 생각보다 자주 개발 흐름을 끊습니다. PR이 develop에 병합됐다는 알림을 받고 실제 앱에서 확인하려면, 하던 작업을 잠시 멈추고 브랜치를 바꾸고 빌드한 뒤 앱을 설치해야 합니다.한 번이면 괜찮습니다. 하지만 하루에 여러 PR이 병합되고, 그때마다 변경사항을 확인해야 하는 상황이 반복되면 이야기가 달라집니다. 빌드 시간보다 더 크게 느껴졌던 것은 작업하던 맥락을 내려놓고 확인 모드로 전환해야 하는 비용이었습니다.그래서 develop 브랜치에 Firebase App Distribution 배포 파이프라인을 붙였습니다. 목표는 단순했습니다. PR이 병합되면 테스트 앱이 자동으로 배포되고, 팀원은 새 빌드를 받아 바로 확인할 수 있는 흐름을 만드는 것이었습니다.수동 확인 ..