주요 변경 사항
이제 사용량 산정에 결제 주기에 포함된 모든 시간이 반영되어 Usage & Limits 페이지의 크레딧 총액이 주기의 첫 1초부터 정확히 포함됩니다. 조직 기능에는 지난주에 빠져 있던 후속 프로세스가 추가되었습니다. 추가된 사용자에게 알림이 전송되고, 결제를 담당하는 소유자에게도 공유되며, 역할 선택 시 각 역할의 권한이 명확히 표시됩니다. 아울러 Dashboard 전반에서 관리자 기준이 아닌 사용자 관점에 맞게 메시지를 전면 수정했습니다.
새로운 기능
결제 주기의 모든 시간 반영
결제 주기는 가입한 초 단위 시점부터 시작됩니다. 반면 사용량은 고정된 버킷 단위로 측정됩니다. 이 두 시점은 거의 일치하지 않으므로, 경계 부분에서 두 기준을 매핑하는 연산이 정확해야 합니다.
이제 정확히 처리됩니다. 결제 주기는 사용 가능한 가장 세밀한 해상도의 온전한 버킷으로 나뉘며, 누락되거나 중복 집계되는 일은 없습니다. 사용량을 조회하는 세 곳 모두 단일 구현을 공유하도록 통합한 것이 근본적인 해결책입니다. 동일한 연산 로직이 세 곳에 분산되어 있으면 그중 하나에서 오류가 발생하기 마련입니다.
변경 후 달라진 점: Usage & Limits의 수치가 지난주보다 약간 높게 표시됩니다. 트래픽은 그대로이지만 집계 방식이 더 완전해졌기 때문입니다. 이 변경으로 인해 플랜 한도를 초과하는 일은 없습니다. 동일한 연산이 할당량 제한에도 적용되므로 양방향 모두에서 중요했던 수정입니다.
조직 참여 알림 자동화
지난주에 출시된 조직 기능을 통해 동료를 추가하고 역할을 부여하며 회사가 비용을 지불하는 키를 사용하도록 설정할 수 있었습니다. 다만 동료에게 해당 사실을 자동으로 알리는 방법이 없어 양식 아래 안내에 따라 직접 전달해야 했습니다.
이제 두 가지 이메일이 발송됩니다. 추가된 사용자에게는 조직 이름, 초대한 사람, 역할의 권한, 예상치 못한 경우 탈퇴할 수 있는 링크가 담긴 이메일이 전달됩니다. 소유자에게는 누군가 참여할 때마다 알림이 전송됩니다. 조직의 키는 소유자의 플랜으로 청구되며, 크레딧을 사용하는 구성원이 늘어나는 것은 단순 편의가 아니라 비용과 직결되기 때문입니다. 작업을 수행한 사용자 본인에게는 메일이 가지 않습니다. 직접 수행한 작업에 대한 영수증성 알림은 불필요하기 때문입니다.
소유자 알림은 직접 추가된 경우와 초대 링크를 통해 첫 로그인 시 직접 참여한 경우 모두에서 발송됩니다. 후자의 경우 초대한 작업자 없이 본인이 직접 들어오게 됩니다.
역할별 권한 안내도 추가되었습니다. 선택 항목 아래의 설명이 변경에 맞춰 바뀌며, Role 열의 툴팁에는 소유자를 포함한 세 가지 역할에 대한 설명이 제공됩니다. "Member"와 "Admin"의 차이를 모른 채 기본값으로 관리자 권한을 부여하는 문제를 방지하기 위함입니다.
동료 추가 단계 간소화
이메일 주소를 입력하고 Add를 누르기만 하면 됩니다. 이미 FourA를 사용 중인 사용자는 즉시 참여합니다. 아직 사용자가 아니라면 초대 메일이 발송되며 로그인하는 즉시 참여 처리됩니다. 동일한 버튼, 동일한 확인 절차, 동일한 방식으로 동작하며, 입력한 이메일에 따라 분기하는 대신 두 가지 결과를 한 문장으로 명확히 안내합니다.
해당 두 번째 대화상자는 제거되었으며, 특정 주소에 이미 계정이 있는지 알려주던 응답 역시 사라졌습니다. 임의의 이메일이 등록되어 있는지 여부는 FourA가 답할 질문이 아닙니다.
Dashboard 로그 출력 정리
"Failed to fetch organizations"는 내부 엔지니어링용 메시지입니다. 그러나 이 메시지가 사용자 화면에 노출되고 있었습니다.
이러한 문구 35개를 "조직 목록을 불러오지 못했습니다. 잠시 후 다시 시도해 주세요."와 같이 사용자가 조치할 수 있는 명확한 문장으로 변경했습니다. 사람이 읽는 모든 텍스트에 축약형을 적용했습니다. "Invalid member id" 및 유사한 오류들은 이제 변수명을 그대로 노출하는 대신 무엇이 잘못되었는지를 안내합니다. 내부용 콘솔 출력 라인은 실제로 FourA 엔지니어를 위한 것이므로 그대로 유지됩니다. 코드를 통해 API를 호출할 때 반환되는 스키마 유효성 검사 응답이나 Dashboard가 분기 처리에 사용하는 머신 리더블 코드도 기존과 동일하게 유지됩니다.
이메일 템플릿도 동일하게 수정되었습니다. 모르는 사람에게 "어떤 조직"에 참여하라는 식의 초대 메일은 스팸함으로 직행하기 마련이므로, 설정한 구체적인 명칭(계정, 키, 조직, 초대자 이름)이 다시 표시되도록 복원했습니다. 고객이 직접 입력한 자유 형식 텍스트는 전송되는 모든 이메일에서 기존처럼 제외됩니다.
내부 기술적 세부사항
Browser 인스턴스가 렌더링 세션마다 파일 핸들을 하나씩 누수하고 있었으며, 이는 당사 코드의 문제가 아니었습니다. 업스트림 종속성이 두 개의 로그 핸들 중 하나를 닫은 후 조기 반환(early return)하면서 두 번째 핸들 정리를 건너뛰고 있었는데, 호출자가 자체 프로필 디렉터리를 전달할 때만 이 문제가 발생했습니다. FourA는 매 실행마다 디렉터리를 전달하므로, 누수가 확정적이고 영구적으로 발생하고 있었습니다.
이번 패치는 종속성을 포크하는 대신 해당 단일 메서드를 래핑하는 방식을 취했습니다. 원본 로직을 먼저 실행한 뒤 핸들이 여전히 열려 있는 경우에만 개입하므로, 향후 업스트림에서 해당 라인을 반환문 위로 이동하더라도 당사의 패치는 자동으로 아무런 동작도 하지 않게(no-op) 됩니다. 테스트 코드는 패치가 적용되기 전에 누수를 재현하여, 단순히 상태가 정상이라고 단언하는 대신 정확히 어떤 문제를 방어하고 있는지를 명시합니다.
실질적인 효과: 장시간 실행되는 Browser 인스턴스가 세션 누적에 따라 성능이 저하되는 대신 처리 용량을 온전히 유지합니다. 이러한 세션이 네트워크 상에서 어떻게 전송되는지 직접 제어하고 싶다면, 이번 릴리스와 함께 제공된 브라우저 프로필 기능을 사용할 수 있습니다.
위의 두 가지 수정 사항은 모두 동일한 원인에서 출발했습니다. 중요한 검증이 아닌 엉뚱한 검사를 통과했던 것입니다. 주기마다 한 시간씩 누락되는 와중에도 테스트 스위트는 통과 상태(green)를 유지했고, 프로세스는 필수 리소스를 모두 소진했음에도 정상 작동 중이라고 보고했습니다. 테스트를 통과시키는 것은 간단합니다. 더 본질적인 질문은 모니터링 도구가 실패 상태(red)로 전환되기 위해 어떤 지표를 감지해야 하는지, 그리고 과연 그 지표를 실제로 감지할 수 있는지 여부입니다.