세 개의 컨텍스트를 하루에 욱여넣은 날
목차
오늘은 유달리 정신이 분산된 날이었다. Java 레거시 백엔드, Flutter 앱, Python 스크립트, 그리고 자동화 파이프라인까지. 커밋 다섯 개짜리 하루지만 실제로는 세 개의 완전히 다른 우주를 오갔다. 같은 날 egovframework 패키지 경로를 쳐다보다가 pubspec.yaml을 열고, 거기서 또 asc_new_version.py를 건드리는 게 뭔가 이상하게 느껴지면서도 익숙하다. 팀장이 되면 이런 날이 많다. 문맥 전환 비용은 고스란히 내 뇌가 낸다.
1.0.7+18, 또 재제출
제일 먼저 끝내야 했던 건 앱스토어 재제출이었다. 전면광고 트리거 이슈로 이미 몇 번 갔다 온 버전이다. 1.0.7+18이라는 빌드 번호가 그 흔적을 말해준다. 같은 버전 번호 안에서 +18까지 올라간 거면, 심사 과정에서 얼마나 많이 튕겨 나왔는지 대략 짐작이 간다.
이번에 추가한 트리거는 측정 세션 종료 시점이다. lib/audio/monitor_service.dart와 lib/ui/measure_screen.dart를 건드렸다. 오디오 측정이 끝나는 순간 전면광고를 노출하는 흐름인데, 논리 자체는 단순하다. 세션이 완료됐다 → 사용자가 결과를 보기 직전이다 → 거기가 광고 적당한 자리다. 사용자 경험 관점에서도 그나마 덜 방해가 되는 타이밍이다.
문제는 스토어 심사였다. cas_settings103.json을 새로 추가한 것도 그 맥락이다. CAS 설정 파일 자체를 버전별로 관리하고 있다는 뜻인데, 심사 때마다 광고 SDK 설정이 달라지면서 파일이 늘어나는 구조다. noiseproof107 설정은 store/asc_new_version.py에 추가했다. 자동화 스크립트에 노이즈 필터 관련 CFG를 얹은 거다. 이름이 noiseproof107인 걸 보면 107번째 변형이 아니라 특정 버전에 대응하는 설정이겠지만, 이 이름 하나가 그동안 심사 과정에서 얼마나 많은 설정을 갈아치웠는지를 간접적으로 보여준다.
CLAUDE.md에 제출 기록을 남겼다. preflight 위치문구 예외 반영도 같이 적었다. 이걸 문서에 남기는 이유는 분명하다 - 다음 번에 또 같은 삽질을 하지 않기 위해서. 앱스토어 심사는 같은 규칙이 어떤 날은 통과되고 어떤 날은 막힌다. preflight에서 위치 관련 문구가 걸렸다가 예외 처리된 기록을 남겨두지 않으면, 다음 릴리즈 때 또 처음부터 파악해야 한다. 이런 문서화가 귀찮아 보여도 결국 팀 전체의 시간을 아끼는 일이다.
whatsnew.md도 업데이트했다. 스토어 제출용 변경 이력이다. 사용자 보는 릴리즈 노트를 쓰는 건 언제나 약간 어색하다. 개발자 언어와 사용자 언어 사이 어딘가에서 줄을 타야 하는데, 전면광고 트리거를 추가했다는 사실을 어떻게 자연스럽게 풀어내느냐가 항상 고민이다. "앱 안정성 개선"이라고 쓰면 거짓말이고, 그렇다고 "광고 노출 시점 추가"라고 쓰면 너무 노골적이다.
welfareDelayDays, 하드코딩을 걷어내다
오후에는 완전히 다른 세계로 전환했다. eGovFramework 기반의 Java 프로젝트다. 복지몰 탈퇴 처리 로직에서, 유예일수를 코드에 박아두었던 걸 설정값으로 빼는 작업이었다.
이런 작업은 대개 배경이 있다. 어느 날 운영팀에서 연락이 온다. "탈퇴 신청하면 며칠 유예하는 거죠?" 개발자가 코드 열어서 확인한다. "30일입니다." 운영팀: "그거 바꿔주세요." 그러면 개발자가 배포를 다시 해야 한다. 그 사이클을 끊는 게 이번 작업이다. welfareDelayDays라는 이름을 파라미터로 만들고, 관리자 화면에서 설정 가능하게 했다.
건드린 파일은 세 곳이다. web 패키지 안의 내부 클래스, utl 패키지 안의 유틸리티 클래스, 그리고 auth-config.jsp. 컨트롤러에서 값을 받아 서비스로 전달하고, JSP에서는 관리자가 입력할 수 있는 필드를 노출하는 흐름이다. eGov 프레임워크 특성상 레이어가 명확하게 나뉘어 있어서 작업 자체가 복잡하진 않다. 다만 기존 코드에서 하드코딩된 값을 찾아서 설정 경로로 바꿔주는 작업이 생각보다 세심하게 손이 많이 간다.
가장 신경 쓴 부분은 기본값 처리다. 기존에 30일이었다면, 관리자가 설정을 안 했을 때 여전히 30일이 되어야 한다. 그냥 null 체크 없이 넘기면 NullPointerException이 나든, 아니면 0일로 처리돼서 탈퇴가 즉시 처리될 수 있다. 후자는 실제로 사용자 데이터가 날아갈 수 있는 버그다. 그래서 유틸리티 클래스에서 방어 처리를 잡아뒀다.
auth-config.jsp를 수정하는 건 항상 약간 조심스럽다. JSP는 컴파일 시점에 오류를 못 잡는 경우가 있고, 브라우저에서 직접 열어봐야 확인이 된다. 특히 JSTL 표현식 안에서 EL이 꼬이면 화면에 아무것도 안 나오거나 리터럴 문자열이 그대로 나온다. 이번엔 간단한 변경이었지만, 그래도 로컬에서 한 번 직접 띄워서 확인했다.
결과적으로는 깔끔하게 마무리됐다. 이런 설정 가능화 작업은 당장의 기능보다 운영 편의성을 위한 거라, 체감 임팩트가 큰 편은 아니다. 하지만 앞으로 유예일수를 바꿔야 할 때 개발자를 거치지 않아도 된다는 게 실용적인 가치다. 인프라 코드는 이런 식으로 조금씩 유연해져야 한다.
자동화가 콘텐츠를 세 개 뽑아냈다
저녁 즈음엔 psy 프로젝트 쪽에서 자동 생성 커밋이 하나 들어왔다. chore(psy): daily auto-generated tests (2026-08-29). 일일 자동 생성 테스트 콘텐츠다.
오늘 생성된 건 세 개다.
abandoned-lighthouse-horror- 버려진 등대 공포 계열bunsik-style- 분식 스타일fading-friendship-type- 희미해지는 우정 유형
커버 이미지는 .webp 포맷으로, JSON 데이터와 함께 레포에 들어갔다. public/covers/ 아래 이미지, src/content/tests/ 아래 JSON. 자동화 파이프라인이 잘 돌아가고 있다는 증거다.
커밋 자체에 손을 댄 건 없다. 파이프라인이 알아서 생성하고 커밋하고 푸시한 거다. 그런데 이게 자동으로 돌아간다고 해서 신경을 안 써도 되는 건 아니다. 오늘 생성된 세 개가 내용면에서 적절한지, 커버 이미지가 제대로 나왔는지, JSON 구조가 깨지진 않았는지는 별도로 확인해야 한다. 자동화의 함정이 여기 있다. 파이프라인이 에러 없이 돌아갔다는 게 콘텐츠가 올바르다는 뜻은 아니다.
세 개의 테스트 주제가 묘하게 섞여 있다. 공포 분위기, 일상 음식 문화, 관계의 쇠퇴. 알고리즘이 무작위로 뽑았을 텐데 의외로 다양성이 있다. bunsik-style은 아마 "당신은 어떤 분식을 좋아하는가" 같은 가벼운 유형 테스트겠고, fading-friendship-type은 결별이나 멀어지는 관계에 대한 심리 테스트일 거다. abandoned-lighthouse-horror는 공포 서바이벌 시나리오 기반의 유형 분류일 가능성이 높다. 실제 JSON 내용을 지금 열어보진 않았지만, 파이프라인이 이 주제들을 어떻게 풀어냈는지는 내일 한 번 훑어볼 생각이다.
오늘 하루를 뒤에서 보면
커밋 다섯 개지만 실질적으로 사용한 언어와 프레임워크는 Java, Dart, Python, JSP에 JSON까지 뒤섞였다. 이게 총괄 팀장의 하루다. 모든 프로젝트의 모든 문맥을 머릿속에 동시에 유지해야 한다.
앱 재제출 쪽이 제일 신경 쓰였다. 1.0.7+18까지 올라온 빌드 번호를 보면서 이번엔 통과가 됐으면 좋겠다는 생각이 자꾸 들었다. 심사 결과는 내가 통제할 수 없는 영역이라 더 찝찝하다. 설정 파일도 바꿨고, 트리거 시점도 수정했고, 문서도 남겼다. 할 수 있는 건 다 했다. 결과는 기다려봐야 안다.
복지몰 유예일수 작업은 조용히 잘 끝났다. 이런 작업이 겉으론 별로 티가 안 나지만, 운영 측에서 나중에 감사하다고 하는 경우가 많다. 직접 배포 없이 설정값 하나만 바꾸면 되는 구조가 된다는 게 중요하다.
psy 자동화는 오늘도 잘 돌았다. 이건 믿고 맡겨두는 중이다. 가끔씩 결과물을 확인하는 게 내 역할이다.
세 개의 컨텍스트를 하루에 다 소화하고 나면 피곤하다. 특히 오전에 앱 재제출 관련 설정 파일 씨름하다가, 오후에 갑자기 egovframework.내부 패키지 패키지 경로로 넘어올 때의 전환 비용이 꽤 크다. 에디터 탭을 닫고 새 프로젝트를 여는 물리적 행위보다, 머릿속 컨텍스트를 비우고 다시 채우는 데 시간이 더 걸린다.
내일은 심사 결과가 나오면 그쪽을 먼저 봐야 할 것 같다. 또 튕겨 나왔다면 다시 이유를 분석해야 하고, 통과됐다면 그다음 버전 계획으로 넘어갈 수 있다. 어느 쪽이든 아침부터 앱스토어 콘솔 열어두게 될 거다.
댓글 0
첫 댓글 달아줘.