기본 콘텐츠로 건너뛰기

AI와 함께 춤을.. 아니, 코딩을.. (5) - 에이전트 팀으로 컨텍스트 압축 해결하기

지난 포스팅에서 개발 환경을 모노레포로 통합 하여, 동일한 Claude 세션 안에서 앱과 서버들을 한꺼번에 개발할 수 있게 했다고 이야기했다. 덕분에 명세 동기화 문제나 연동 디버깅의 번거로움이 크게 줄었다. 그런데 이렇게 앱과 여러 서버를 하나의 세션에서 다루다 보면, 또 다른 효율 저하 요인이 생긴다. 바로 컨텍스트 사이즈 제약 이다. 컨텍스트 압축이라는 새로운 문제 요즘은 Max 요금제 기준으로 기본 1MB 컨텍스트를 제공해서 예전만큼 빡빡하지는 않다. 하지만 불과 두어 달 전까지만 해도 컨텍스트 크기가 지금보다 훨씬 작았다(그래도 다른 서비스보다는 컸다). 그래서 한꺼번에 많은 코드를 분석시키고 대화를 조금만 이어가면, 빈번한 컨텍스트 압축 이 발생하곤 했다. 컨텍스트 압축이 일어나면 대화의 맥락이 흐려지기 시작한다. 방금 전까지 이해하고 있던 내용을 다시 설명해야 하거나, 이미 정한 구현 방향을 잊고 다른 길로 가기도 한다. 모노레포로 프로젝트를 합친 직후에 이 문제가 두드러지게 나타났다. 해결: 에이전트 팀 구성하기 이 문제를 줄이기 위해 Claude Code가 지원하는 서브에이전트(Sub-agent) 기능 을 적극적으로 활용하기로 했다. 앱과 각 서버를 담당할 전문 에이전트를 만들고, 이들을 총괄할 팀 리더 에이전트 를 따로 두는 방식이다. 말 그대로 "에이전트 팀"을 꾸리는 셈이다. 페르소나 구성은 대략 이렇게 잡았다. 팀 리더 └─ 제품 전체 기획 / 각 개발자에게 업무 지시 앱 개발자 └─ 모바일 앱 개발에 능숙한 개발자 서버#1 개발자 └─ Node.js 개발에 뛰어난 개발자 서버#2 개발자 └─ Python 개발자 이렇게 담당 프로젝트의 특성에 맞춰 각 에이전트의 페르소나를 정의한다. 테스터 에이전트를 따로 두는 분들도 있는데, 나는 별도로 분리하지 않았다. 서브에이전트 생성은 Claude Code에서 프롬프트로 설정할 수 있고, 추가한 뒤에는 세션을 새로 ...

[iOS] iOS App Store 유럽 연합(EU) 디지털 서비스법(DSA) 규정 준수 - 거래자 제공업체 계정?

앱에 대한 고객 리뷰를 보기 위해서 App Store Connect 에 접속을 하니, 불안감을 조성하는 붉은색 알림이 하나 표시되고 있었습니다. 디지털 서비스법에 따라 정보를 제공 하라는 메시지입니다. 일단, 무슨 법에 따라서 변경 하라는 메시지는 법을 잘모르는 입장에서는 괜히 부담이 많이 갑니다. 용어도 잘 모르겠고, 이것으로 인하여 나에게 미치는 영향도 잘 모르겠는 경우가 많아서 입니다. 그렇다고 무시하면 앱 배포가 중단될 수 있다는 협박성(?) 내용이 항상 뒤 따르기 때문에 잘 모르더라도 해야만 합니다. 그래서 규정 준수를 위하여 링크를 타고 들어가면 아래와 같은 절차를 만나게 됩니다. 디지털 서비스법은 유럽 연합(EU)에서 정한 법인 것은 알겠고, "거래자 제공업체 계정", "비거래자 제공업체 계정" 둘 중에 하나를 고르면 되는 것으로 보입니다. 심리적으로는 왠지 모르게 "거래자 제공업체 계정"에 해당할 것 같은데, 거래자가 뭔지 모르겠으니, "거래자 자격이 있는지 더 알아보기"를 클릭해서 해당 설명이 있는 페이지로 이동합니다. (불친절한) 애플 가이드 페이지가 보여지고, 거래자에 대한 설명은 아래와 같이 되어 있고, EU에서 제공하는 홈페이지 링크가 하나 걸려 있습니다. DSA에서는 거래자를 “개인 또는 공공 소유 여부와 무관하게 자신의 명의로 또는 자신을 대신하여 행동하는 사람 또는 모든 자연인,  그리고 무역, 비즈니스(Business), 기술 또는 직업과 관련된 목적을 위해 행동하는 모든 사람” 으로 정의합니다. 귀하가 거래자에 해당되는지 여부는 법률 고문과 상담하십시오.( # ) 위 문장을 제가 이해하기에는 앱스토어에 앱을 배포하는 모든 사람/회사는 거래자에 해당할 것 같습니다. 그럼 나는 "거래자 제공업체 계정"을 선택하면 될 것 같은데, 그럼 "비거래자 제공업체 계정" 선택이 필요 없지 않은가라는 의문이 들었습니다. 아니면 애플에서 ...

수경재배 상추 파종 3일차 - 싹이 돋았습니다

12포트 중 8포트 발아 성공 사무실 수경 재배기에 뿌려 놓은 상추 씨앗이 주말 동안 싹을 틔웠습니다. 오래된 씨앗이라서 싹이 날지 걱정했는데, 12 포트 중에서 8포트가 싹이 났습니다. 남은 포트와 뿌리 노출 문제 4포트가 아직 소식이 없는데, 조금 더 지켜보고 다시 파종 해야 겠습니다. 씨앗이 흙에 묻히는 구조가 아니라서 뿌리가 LED 빛에 노출되는 구조인데, 문제 없는지 모르겠네요. 뿌리에는 빛이 안가는게 좋을 것 같은데...

가정용 수경재배기 구매 후기 - 사무실에서 상추 키우기 시작

식집사가 되기로 결심한 이유 식집사라는 말이 요즘 유행하는 것 같습니다. 저는 식집사까지는 아니고, 화분에 뭔가를 키우는 걸 좋아합니다. 다만, 애써 뭔가를 사서 하거나 하지는 않고, 생기면 물주고 최대한 안죽이고 키운다 정도였습니다. 집에서 키우는 호야, 벤자민고무나무 같으면 누나가 주고.. 형이 주고.. 해서 한식구가 되었고, 죽이지 않고 10 수년째 키우고 있는 중입니다. 단지, 분갈이도 안해주고, 물만 주고, 가끔 다이소 같은데서 파는 비료 조금 넣어주는 정말 죽지 않고 버티게만 하고 있다는 표현이 맞을 것 같습니다. 그리고, 상추, 고추 같은걸 화분에 키워서 먹는걸 좋아합니다. 키우는 기간도 짧고 뭔가 결과물도 있고.. ^^; 그런데, 집이 아파트이다 보니 햇볕도 부족하고 키울 공간도 부족해서 부족함을 느끼다가, 2~3년 전에 사무실 근처에 텃밭을 조금 빌려서 상추를 기른 적이 있는데, 저랑은 좀 맞지 않더군요.. 너무 열심히 가꿔야 한다라는 제약이 있더군요. 하루 이틀만 게을리하면 잡초가 상추보다 더 많이 나고.. 땅은 정말 조금인데 수확물은 감당할 수 없고.. 해서 이후로는 상추 같은건 그냥 사먹는 걸로 하고... 농사(?)는 안하는 걸로 했습니다. 요근래 뭔가를 다시 키우고 싶다는 생각이 들었습니다. 좀 열심히.. 그래서 저도 식집사가 되어 보기로 했습니다. 돈도 좀 쓰고.. ㅡ.ㅡ;; 알리익스프레스 12포트 수경재배기 선택 그 첫번째 시도로 사무실에 농장을 만들어 보기로 했습니다. 바로 가정용 수경 재배기라는 것을 구매해 보았습니다. G마켓, 알리 같은데 보면 많은 종류의 수경재배기를 판매하고 있습니다. 작은 것 부터 큰 것 까지 종류가 참 많더군요.. 가격도 싼것 부터 비싼것 까지 다양하게 있더군요.. 전 알리에서 $43정도 하는 12포트짜리 수경 재배기를 구매하였습니다. 이걸 선택한 이유는 사무실 책상에 놓고 키우기에 크기도 적당하고, 자체 조명도 있어서 햇볕 걱정도 하지 않아도 되고, 보기도 나름 나쁘지 않고, 처음 시도부...

[Flutter] Deep Link 구현 가이드 - go_router, app_links를 활용한 iOS/Android 딥링크 적용기

 개발하고 있는 앱에서 다른 사용자를 앱으로 초대하는 기능을 추가하게 되어 앱에 deep link 기능을 앱에 구현하게 되었습니다. 구현에 필요한 자료는 이미 더 잘 정리되어 있는 많은 자료들이 있으니 그것들을 참고하면 될 것 같아서 여기에서는 특별히 설명하지 않습니다. 다만 내 앱에 해당 기능을 넣기 위해서 자료를 찾고 구현하는 과정에서 헷갈렸던 것들과 구현중 문제가 있었던 부분에 대해서 프로젝트를 정리하는 차원에서 메모를 남기기로 해서 글을 쓰고 있습니다. 참고:  - https://itnext.io/deep-linking-in-flutter-boost-user-experience-in-apps-29dd25842757  - https://docs.flutter.dev/ui/navigation/deep-linking 용어 deep link는 보통 웹에서 인덱스 페이지가 아닌 상세 페이지에 대한 다이렉트 링크를 생성하는 것을 말합니다. 예를 들어서 어떤 웹페이지를 사용하기 위해서는 홈 화면에서 로그인을 하고 몇 단계를 거쳐서 특정 페이지로 들어가야하는데, 이 기능에 대한 지름길을 만드는걸 deep link로 이해하면 되겠습니다. 그리고 deep link 구현관련하여 모바일에서는 OS에 따라서 custom scheme(url scheme), universal link, app link 등의 용어가 튀어 나오는데, 표준 URI 형식을 이용하여 앱을 실행시키기 위한 방법을 말한다고 이해하면 간단하겠다. 기술에 대한 상세로 들어가면 약간의 차이가 있으나 큰 틀에서 차이는 없기 때문에 deep link를 구현하기 위해서 app을 실행(lunch)하기 위한 기술이라고 보면 됩니다. 그리고, 검색하다가 보면 dynamic link라는 용어가 나오는데, firebase에서 제공하던 서비스인데 현재는 서비스 종료되었으니 무시하면 됩니다. Navigator / Router flutter로 deep link를 구현할 때 현재 앱이 Navigator를 이용...

[Flutter] textScaleFactor로 접근성 글자 크기 설정 제어하기 - 레이아웃 깨짐 방지

노안이 있는 사람이나 시각 장애가 있는 사람들은 모바일 환경의 기본 글자 크기에 불편함을 느끼는 사용자들을 위해서 iOS와 안드로이드에서는 접근성 설정을 통해서 글자 크기를 크게 또는 작게 설정할 수 있도록 지원하고 있습니다. 그리고, 앱 개발시에도 이를 고려하여 개발하라고 가이드하고 있습니다. 그렇지만 앱 개발 단계에서 이런 부분이 몰라서, 귀찮아서 또는 디자인과 같은 현실적 한계로 인하여 가이드를 무시하고 개발되는 경우가 종종 발생하게 됩니다. 이렇게 접근성 설정을 무시하고 앱을 개발하면 앱 접근성 설정을 이용하는 사용자 환경에서 화면이 깨지거나, 사용상의 문제를 발생시키는 경우가 발생합니다. 또는 앱 심사 과정에서 거부되기도 합니다. 그런데 이런 문제가 인식된 시점에 디자인 변경이 어렵거나, 변경해야 하는 범위가 커서 접근성 설정을 무시하고 기본 글자크기로 나오도록 하여 문제를 회피하여 해결해야하는 방법을 알아보겠습니다. 아래 방법은 flutter에서 문자의 비율을 시스템에서 설정하는 값이 아닌 개발자가 기본 비율로 강제하도록 하여 접근성 설정이 무시되도록 하는 방법입니다. Widget build(BuildContext context) { // 사용자가 OS에서 제공하는 접근성 설정을 변경할 경우, 앱의 폰트 크기가 변경되는 것을 방지한다. // 폰트 크기가 크게 변경되면 다이얼로그의 레이아웃이 깨져서 다음 단계로 진행하지 못하는 경우가 발생함. final mediaQueryData = MediaQuery.of(context); final newMediaQueryData = mediaQueryData.copyWith(textScaleFactor: 1.0); return MediaQuery( data: newMediaQueryData, child: Container() ) } 내용이 잘못되었거나, 더 좋은 방법이 있으면 댓글 남겨주시기 바랍니다.

[Flutter] 모바일 앱 재시작 및 종료 구현 방법 - iOS/Android 네이티브 코드 활용

모바일 앱을 개발하다 보면 앱을 재실행 시키거나 코드에 의한 종료를 해야하는 경우가 발생합니다. 예를 들어서 앱의 전반에 걸쳐서 영향을 끼치는 설정을 초기화하고 새로 로딩해야 하는 경우가 있습니다. 이런 경우에는 해당 설정값만 다시 로딩하는 방법도 있겠지만, 이 값이 여러곳에 영향을 끼친다던가 초기화 해야하는 값들이 많다던가 하면 머리가 아파지고, 앱을 재시작 시켜서 자연스럽게 설정값을 읽어들지게 하는게 자연스러울 수 있습니다. 그런데, iOS와 안드로이드 모바일 환경에서는 코드에 의해서 앱을 재실행 시키거나, 종료 시키는 것에 대해서는 권장하지 않으며, iOS의 경우에는 이런 기능이 들어가면 앱 스토어 심사 단계에서 거부될 수 있습니다. 그래도 좋은 사용자 경험을 위해서 앱의 종료나 재시작이 꼭 필요한 경우에는 구현을 하는게 좋습니다. 앱 재시작 설정 초기화 후 앱을 재로딩이 필요한 경우라면 앱이 자동으로 재시작 되는 것이 앱이 종료되는 것 보다는 더 좋은 사용자 경험을 제공합니다. 그런데 iOS에서는 앱을 재시작 시킬 수 있는 방법을 찾지 못해서 안드로이드에서 재실행 시키는 방법만 정리하도록 하겠습니다. flutter 에서 제공하는 기능만으로 앱을 재시작 시키는 방법은 아직 찾지 못했고, 메소드 채널을 이용하여 네이티브 코드로 구현하셔야 합니다. PackageManager packageManager = getPackageManager(); Intent intent = packageManager.getLaunchIntentForPackage(getPackageName()); ComponentName componentName = intent.getComponent(); Intent mainIntent = Intent.makeRestartActivityTask(componentName); startActivity(mainIntent); System.exit(0); 참고 : https://ideaj...

Xcode 15 - ipa is not a valid bundle.

 Xcode 15.0.1(15A507) 업데이트 후 ipa 파일을 생성해서 XCode의 Device 메뉴를 통해서 ipa 설치시 아래와 같은 오류가 발생합니다. Error installing  'xxxxxx.ipa', ERROR: Error Domain=com.apple.dt.CoreDeviceError Code=3002 "Failed to install the app on the device." UserInfo={NSLocalizedDescription=Failed to install the app on the device., NSURL=file:///xxxxxx.ipa, NSUnderlyingError=0x600005c85c80 {Error Domain=com.apple.dt.CoreDeviceError Code=3000 "The item at xxxxxx.ipa is not a valid bundle." UserInfo={NSURL=file://xxxxxx.ipa, NSLocalizedDescription=The item at xxxxxx.ipa is not a valid bundle., NSLocalizedFailureReason=Failed to read the bundle.}}} Domain: com.apple.dt.DVTCoreDevice Code: -1 User Info: {     DVTErrorCreationDateKey = "2023-11-20 06:30:34 +0000"; } -- System Information macOS Version 14.1 (Build 23B74) Xcode 15.0.1 (22266) (Build 15A507) Timestamp: 2023-11-20T15:30:34+09:00 ipa 파일이 유효하지 않은 번들이라는 오류 입니다.  인증서, 프로비저닝 등은 Xcode에서 자동 생성하는 것을 사용하였고, 단말은 테스트 단말로 등록되어 있는 단말임에도 ...