Skip to content

✨ 관리자 페이지 한국어화 및 편집 기능 개선 - #33

Merged
son0307 merged 4 commits into
mainfrom
codex/admin-ui-editor-improvements
Jul 24, 2026
Merged

✨ 관리자 페이지 한국어화 및 편집 기능 개선#33
son0307 merged 4 commits into
mainfrom
codex/admin-ui-editor-improvements

Conversation

@son0307

@son0307 son0307 commented Jul 24, 2026

Copy link
Copy Markdown
Owner

변경 사항

관리자 페이지 구조 및 한국어화

  • 한 화면에 모여 있던 데이터 편집, 외부 API 동기화, 관리자 로그를 /admin/editor, /admin/sync, /admin/logs로 분리했습니다.
  • 팀·선수·경기 상세 화면의 관리자 수정 링크를 새 편집 경로로 연결했습니다.
  • 관리자 페이지의 제목, 버튼, 상태, 필드명, 이벤트 유형, 동기화 작업과 로그 설명을 한국어로 통일했습니다.
  • API와 DB에서 사용하는 원본 enum과 식별 값은 유지하고 화면에 표시되는 문구만 한국어로 변환합니다.

동기화 및 관리자 로그 사용성 개선

  • 수동 동기화 버튼의 30초 제한 시각을 localStorage에 저장해 페이지를 새로고침해도 비활성화 상태가 유지되도록 했습니다.
  • 동기화 요청의 완료와 실패를 우측 상단 토스트로 알리고, 실패 시 서버가 반환한 안전한 오류 메시지를 표시합니다.
  • 동기화 요청이 성공하거나 실패한 뒤 provider 상태와 작업별 최근 상태를 즉시 다시 조회합니다.
  • 화면 하단과 버튼 아래에 중복으로 표시되던 오류 문구를 제거하고 실패 횟수를 연속 실패 수로 정리했습니다.
  • 최근 완료 작업에 성공·실패·취소 건수를 표시하고, 결과별 카드 배경과 테두리 색상을 구분했습니다.
  • 관리자 로그의 성공·실패 카드와 badge에도 동일한 상태 색상 규칙을 적용했습니다.
  • 완료 작업 카드 사이의 간격과 관리자 페이지의 모바일 표시를 보완했습니다.

팀·선수·경기 편집 기능 보완

  • 팀과 선수 정보의 저장 성공·실패 결과를 토스트로 표시합니다.
  • 팀을 선택해 경기 목록을 조회할 때 낮은 라운드부터 표시되도록 정렬했습니다.
  • 관리자 화면의 개별 경기 동기화 기능은 제거하되 기존 백엔드 API는 유지합니다.
  • 팀 수정 화면에서 직접 변경할 필요가 없는 경기장 ID 입력란을 제거하고 기존 연결 값은 저장 시 유지합니다.
  • 팀 홈 경기장과 경기별 경기장 정보에 nullable venueNameKo를 추가하고, 사용자 화면에서는 한글 이름을 우선 표시하되 값이 없으면 기존 영문 이름을 사용합니다.
  • 외부 API 재동기화가 관리자가 입력한 경기장 한글 이름을 덮어쓰지 않도록 별도 필드로 관리합니다.
  • 경기 이벤트의 substsubstitution교체로 표시합니다.
  • 이벤트 팀을 선택하면 해당 팀의 라인업·경기 통계에 포함된 선수만 선택할 수 있도록 제한하고, 팀 변경 시 기존 선수 선택을 초기화합니다.
  • 교체 이벤트에서는 선수도움 선수 필드를 각각 교체 아웃, 교체 인으로 표시합니다.
  • 서버에서도 이벤트 팀과 선수의 소속 관계를 검증해 직접 조작된 잘못된 조합의 저장을 차단합니다.

변경 이유

기존 관리자 페이지는 데이터 편집, 외부 API 동기화와 로그가 한 화면에 집중되어 세로 길이가 길고 필요한 기능을 빠르게 찾기 어려웠습니다. 또한 영어와 한국어가 혼재하고 요청 결과가 여러 위치에 중복 표시되어 작업 성공 여부와 장애 상태를 직관적으로 확인하기 어려웠습니다.

데이터 편집 측면에서는 경기장 한글 이름을 별도로 관리할 수 없었고, 경기 이벤트에서 선택한 팀과 관계없는 선수도 지정할 수 있어 잘못된 데이터가 저장될 가능성이 있었습니다. 관리자 화면의 사용 흐름을 정리하고 화면과 서버 양쪽에서 편집 데이터의 일관성을 보장하도록 개선했습니다.

API 및 스키마 변경

  • venuefixture에 nullable venue_name_ko 컬럼이 추가됩니다.
  • 팀·경기 관리자 수정 요청 및 응답과 사용자 조회 응답에 venueNameKo가 추가됩니다.
  • 기존 venueName 필드는 유지하며 한글 이름이 없을 때 fallback으로 사용합니다.
  • 기존 관리자 동기화 REST API와 개별 경기 동기화 API는 삭제하지 않습니다.
  • 관리자 프론트엔드 경로가 /admin/* 구조로 확장됩니다.

검증

  • npm run build 통과
  • 관리자 서비스 관련 단위 테스트 통과
  • 경기 서비스 관련 단위 테스트 통과
  • git diff --cached --check 통과
  • 전체 백엔드 테스트 226개 중 225개 통과
    • contextLoads() 1개는 로컬 환경에서 Docker/Testcontainers를 사용할 수 없어 실패했습니다.

로그인된 관리자 환경의 브라우저 직접 검증은 수행하지 않았습니다.

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codex PR Review

PR 요약

요약

관리자 페이지를 편집·외부 API 동기화·로그 화면으로 분리하고 전체 UI를 한국어화했습니다. 경기장 한글 이름 관리와 이벤트 선수 선택 검증을 추가해 관리자 편집 흐름과 데이터 일관성을 개선했습니다.

주요 변경사항

  • 관리자 경로를 /admin/editor, /admin/sync, /admin/logs로 확장하고 관련 링크를 새 경로로 연결
  • 관리자 필드, 동기화 작업, 로그, 이벤트 유형 및 상태 표시를 한국어로 통일
  • 동기화 쿨다운을 localStorage에 저장하고 토스트 알림 및 최신 상태 재조회 추가
  • 동기화 작업·로그의 성공, 실패, 취소 상태별 카드와 배지 스타일 개선
  • 팀·선수 저장 결과를 토스트로 표시하고 경기 목록을 라운드 순으로 정렬
  • venueNameKo 필드를 팀·경기에 추가하고 사용자 화면에서 한글 경기장 이름 우선 표시
  • 경기장 한글 이름이 외부 API 재동기화로 덮어써지지 않도록 분리 관리
  • 이벤트 팀에 소속된 라인업·경기 통계 선수만 선택하도록 제한하고 서버 측 소속 관계 검증 추가
  • 개별 경기 동기화 UI는 제거하되 기존 백엔드 API는 유지

영향 범위

  • 관리자 UI 및 /admin/* 라우팅
  • 외부 API 동기화 상태 조회, 작업 폴링, 로그 표시
  • 팀·선수·경기 및 경기 이벤트 편집 API와 검증
  • 경기장 정보 스키마 및 사용자용 팀·경기 상세 UI
  • 관리자 페이지 반응형 스타일 및 상태 표시

검증

  • npm run build 및 관리자·경기 서비스 단위 테스트 통과
  • git diff --cached --check 통과
  • 백엔드 테스트 226개 중 225개 통과
  • contextLoads()는 로컬 Docker/Testcontainers 환경 부재로 실패
  • 로그인된 관리자 브라우저 직접 검증은 수행하지 않음

시니어 개발자 리뷰

  • [P1] frontend/src/pages/AdminPage.tsx:1168 - 저장 실패 시 서버 오류 메시지를 그대로 관리자 화면에 노출

    • 문제: runToastSavecatch에서 nextError.message를 그대로 토스트에 표시합니다. adminRequest도 HTTP 오류 응답의 errorMessage를 그대로 Error로 전달하므로, 백엔드나 외부 API가 내부 경로·SQL 정보·외부 provider 응답·스택 관련 메시지를 반환하면 관리자 UI에 그대로 노출될 수 있습니다.
    • 영향: 관리자에게 불필요한 내부 구현 정보가 노출되고, 외부 API의 원문 오류가 사용자 경험을 해치거나 민감 정보 노출로 이어질 수 있습니다. PR 설명의 “서버가 반환한 안전한 오류 메시지”가 실제로 보장되는 지점도 diff에서 확인되지 않습니다.
    • 수정 방향: 서버에서 관리자용 안전 메시지와 상세 로그를 분리하고, 프론트에서는 허용된 오류 코드/메시지만 표시하도록 제한하세요. 최소한 예상하지 못한 오류는 "저장하지 못했습니다. 잠시 후 다시 시도해주세요."로 대체하고 상세 원문은 서버 로그에만 남기는 것이 안전합니다.
  • [P2] frontend/src/pages/AdminPage.tsx:1119 - 동기화 실패에도 30초 cooldown이 적용됨

    • 문제: markSyncCooldown(cooldownKey)를 실제 동기화 요청 직전에 호출하고, 요청이 네트워크 오류나 서버 오류로 실패해도 cooldown을 제거하지 않습니다.
    • 영향: 일시적인 네트워크 장애나 서버 오류가 발생한 뒤에도 관리자가 30초 동안 재시도할 수 없습니다. 특히 수동 동기화는 실패 원인을 확인한 뒤 즉시 재시도해야 하는 운영 기능이므로 장애 대응이 느려집니다.
    • 수정 방향: 요청 자체가 서버에 접수된 경우에만 cooldown을 유지하고, 요청 전송 실패·HTTP 오류처럼 접수되지 않은 경우에는 해당 localStorage 및 메모리 cooldown을 제거하세요. 또는 cooldown의 목적이 API rate limit 방지라면 실패 유형별로 재시도 가능 시점을 구분해야 합니다.
  • [P2] frontend/src/pages/AdminPage.tsx:2740 - 상태 조회 실패를 무시해 동기화 결과가 오래된 상태로 남을 수 있음

    • 문제: reloadSyncStatusesSafelycatch가 아무 상태 변경이나 오류 표시 없이 종료됩니다. 동기화 요청 후 상태 조회가 timeout/네트워크 오류로 실패하면, 화면에는 이전 성공/실패 상태가 계속 표시됩니다.
    • 영향: 관리자가 새 동기화 결과가 반영됐다고 오해할 수 있고, 외부 provider 장애나 백엔드 응답 지연을 UI에서 확인하기 어렵습니다. PR에서 “요청 후 provider 상태를 즉시 다시 조회”하는 목적도 실패 시에는 충족되지 않습니다.
    • 수정 방향: 상태 조회 실패 여부를 별도 상태로 관리해 "최신 상태를 불러오지 못했습니다"를 표시하고 재시도 버튼을 제공하세요. 기존 상태를 유지하더라도 마지막 갱신 실패를 명시해야 합니다.

보안 리뷰

  • [Medium] frontend/src/pages/AdminPage.tsx: 약 2903행 - 동기화 실패 원문을 관리자 토스트에 직접 노출
    • 문제: syncJobCompletionMessage()가 동기화 작업의 job.errors[].message 또는 job.message를 가공 없이 토스트 메시지에 포함합니다. 또한 runToastSave()runSync()도 서버 응답의 오류 메시지를 그대로 관리자 화면에 표시합니다.
    • 공격/노출 시나리오: 외부 API 응답이나 백엔드 예외 메시지에 내부 URL, 요청 파라미터, 스택 정보, provider 응답 원문, 설정 정보 등이 포함될 경우 관리자 로그를 볼 수 있는 계정에 내부 정보가 노출될 수 있습니다. 백엔드 오류 메시지가 향후 잘못 구성되면 credential 또는 secret value가 함께 표시될 가능성도 있습니다.
    • 수정 방향: 클라이언트에서 원문을 표시하지 말고 서버가 정의한 안전한 오류 코드/메시지만 반환하도록 합니다. 동기화 작업의 상세 오류는 내부 로그에만 기록하고, UI에는 "동기화에 실패했습니다. 관리자 로그를 확인해 주세요." 같은 허용 목록 기반 메시지만 표시하세요. job.errors[].message를 토스트에 직접 사용하는 로직은 제거하는 것이 안전합니다.

중대한 보안 문제 없음
Model: gpt-5.6-luna
Diff was truncated to 90000 characters; review may be incomplete.

@son0307
son0307 merged commit 1a708df into main Jul 24, 2026
1 check passed
@son0307
son0307 deleted the codex/admin-ui-editor-improvements branch July 24, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant