지난 글에서는 결과 이벤트를 받아 선택한 항목의 횟수를 올리는 데까지 연결했다. 연결과 집계를 붙이던 6월 1일에는 관리 화면도 함께 고쳤다. 집계가 돌아가는 것과, 화면만 보고 제대로 설정됐다고 알 수 있는 것은 별개였다.
이번에는 필터 저장 버튼과 0회 항목 표시를 정리한 기록이다. 처음 만든 화면에서는 저장을 눌러도 끝났는지 알기 어려웠고, 선택했지만 아직 한 번도 나오지 않은 항목은 카운터에 나타나지 않았다.
저장 버튼에 결과를 보여주기
처음 저장 코드는 선택 목록을 서버에 보내고 관리 상태를 다시 읽는 정도였다. 여기에 저장 중, 완료, 실패를 표시하도록 바꿨다. 아무것도 고르지 않았을 때도 바로 안내한다.
항목을 하나도 고르지 않음 → 필터를 하나 이상 선택해주세요
저장 요청 중 → 필터 저장 중
저장과 상태 갱신 완료 → 필터 저장 완료
요청 또는 갱신 실패 → 필터 저장 실패
요청을 보내는 동안에는 버튼을 비활성화했다. 응답이 오기 전에 같은 저장을 반복해서 누르는 것을 막기 위해서다. 성공과 실패 어느 쪽으로 끝나도 다시 누를 수 있도록 버튼 복구는 finally에 두었다.
saveFilter.disabled = true;
statusNode.textContent = '필터 저장 중';
try {
// 저장 요청, 응답 확인, 화면 상태 갱신
statusNode.textContent = '필터 저장 완료';
} catch (error) {
statusNode.textContent = '필터 저장 실패';
} finally {
saveFilter.disabled = false;
}
위 코드는 흐름만 줄인 것이다. 실제 요청에서는 response.ok도 확인했다. fetch()는 서버가 400이나 500으로 응답했다고 해서 자동으로 예외를 던지지는 않으므로, 실패 응답을 완료로 표시하지 않게 해야 했다. MDN Fetch 설명
선택했는데 0회인 항목이 없다
저장 여부를 보여준 뒤에는 카운터 목록을 맞췄다. 예를 들어 노래와 댄스를 선택했는데 노래만 한 번 나온 상태라면, 화면에 노래 1회만 보이는 것보다 댄스 0회도 같이 보여야 설정을 확인하기 쉽다.
서버 상태에는 선택한 항목을 0으로 준비하는 처리가 이미 있었다. 빠진 것은 바뀐 상태를 열려 있는 화면에 다시 전달하는 과정이었다. 필터를 바꾸고 런타임에 적용한 뒤, 전체 상태를 꺼내 INIT_STATE 메시지로 보냈다.
await state_store.update_allowed_items(next_filter.items)
state = await state_store.snapshot()
await ws_manager.broadcast(
{"type": MessageType.INIT_STATE.value, "payload": state}
)
저장 응답에도 같은 state를 넣고, 관리 화면이 그 값으로 카드를 다시 그리게 했다. 저장한 쪽의 화면과 연결된 화면이 선택 목록을 다시 맞추도록 한 것이다.
여기서 0은 ‘아직 결과가 없음’이라는 값이다. 선택된 항목 자체가 없다는 뜻과 구분해서 보여줘야 했다. 당시 구현은 현재 선택에서 빠진 항목을 상태에서도 제거했다. 나중에 다시 선택하면 그 항목은 0부터 만들어지므로, 필터를 바꿔도 모든 과거 횟수를 보존하는 방식은 아니었다.
룰렛에서 없어진 항목이 설정에 남을 때
저장된 필터와 현재 룰렛 목록도 달라질 수 있다. 이전에 고른 항목이 룰렛에서 삭제됐는데 설정에는 그대로 남아 있으면, 이제 나오지 않는 항목을 계속 기다리게 된다.
시작할 때 목록을 갱신하고, 현재 목록에 없는 필터 이름을 정리하도록 했다. 다만 목록을 가져오지 못한 경우까지 전부 지우면 안 된다.
def prune_filter_items(config, catalog_items):
if not catalog_items:
return config
allowed = set(catalog_items)
return FilterConfig(
items=tuple(item for item in config.items if item in allowed)
)
이 단계에서는 빈 목록이면 기존 필터를 유지하도록 했다. ‘정말 항목이 하나도 없음’과 ‘목록을 확인할 수 없음’을 구분할 정보가 부족했기 때문이다. 시작 시 새 목록 조회에 실패하면 저장해 둔 목록을 활용하는 흐름도 함께 넣었다.
테스트는 두 경우로 나눴다. 목록이 정상적으로 있으면 사라진 이름만 제거하고, 빈 목록이면 기존 설정을 그대로 남기는지 확인한다. 새 목록의 순서가 바뀌어도 남아 있는 선택 항목의 순서는 유지한다.
수동으로 숫자를 고칠 자리도 만들기
각 카운터 카드에는 작은 +, - 버튼을 붙였다. 화면의 숫자만 바꾸지 않고 COUNT_UPDATE 메시지로 항목 이름과 증감값을 보낸다. 다른 화면도 같은 상태 변경을 받아야 하기 때문이다.
socket.send('COUNT_UPDATE', { item: name, delta: 1 });
socket.send('COUNT_UPDATE', { item: name, delta: -1 });
숫자가 바뀐 카드는 잠깐 강조하고, 처음 목록을 그릴 때는 이름순으로 정렬했다. 항목이 많아졌을 때도 방금 바뀐 곳과 버튼 위치를 찾기 쉽게 하려는 수정이다.
저장 버튼의 반응, 선택된 0회 항목, 현재 목록과 맞지 않는 설정을 차례로 정리하니 관리 화면에서 확인할 수 있는 정보가 늘었다. 다음에는 이 숫자들을 OBS에서 가로로 보여주고, 방금 바뀐 항목을 먼저 띄우는 쪽으로 넘어간다.
'이것 저거 만들어 보기 > 뚜봇 룰렛 카운터' 카테고리의 다른 글
| 뚜봇 룰렛 개발일지 1 — 첫 집계 테스트 (0) | 2026.10.13 |
|---|