백엔드에 회원코드 전용 필드가 없어 userId를 그대로 노출하던 열이다. 도메인 필드와
매핑도 함께 지운다 — 그리는 곳이 이 열뿐이라 남겨 두면 죽은 데이터가 된다.
행의 key로 쓰는 id(userId)는 그대로 둔다.
Co-Authored-By: Claude Opus 5
백엔드가 TB_COM_ADBK를 LEFT JOIN해 adbkList(parentNm·parentTelNo)로
보호자를 내려주기 시작했다. 한 학생에 여러 명이 붙을 수 있어 도메인 타입을
guardians 배열로 바꾸고, 목록의 보호자이름·보호자연락처 칸과 조회 팝업의
「보호자 이름 / 연락처」를 모두 줄을 나눠 그린다.
같은 개편에서 VO의 userTelno가 userTelNo로 바뀌어 있었다. 매핑이 옛 이름을
읽고 있어 휴대전화번호 칸이 늘 비어 있었다 — 새 이름으로 맞춘다.
Co-Authored-By: Claude Opus 5
백엔드를 최신화(develop 924db37 → 4d98756)하고 확인하니 막고 있던 두 가지가 모두 풀렸다.
- `GET /api/v1/mngr/user/pagination`이 4개 필드에서 18개로 늘었다 — userTelno·userEmlAddr·
userType·schNm·grade·clsNo·birth·useYn이 실린다.
- `PUT /api/v1/mngr/user/{userId}/{useYn}` 사용여부 변경 API가 생겼다.
- (덤) `GET /api/v1/mngr/user/{userId}` 단건 조회도 생겼다. 지금은 쓰지 않는다 — 목록 행이
이미 갖고 있는 값으로 팝업을 채우므로 재조회가 필요 없다.
이에 맞춰 이식했다.
- Repository: toStudentMember가 전화·이메일·학교·학년·반·생년월일·사용여부를 실제 값으로
채운다. `useYn`은 'Y'/'N' 문자열이라 boolean으로 옮기고, 값이 없으면 판단하지 않고 null이다.
보호자·학생번호·가입일은 응답에 여전히 없어 `-`로 남는다(SQL·VO 어디에도 컬럼이 없다).
- Repository: updateStudentMemberUseYn 추가. 값과 대상이 모두 경로에 실리고 본문은 쓰지 않는다.
- Server Action: 미지원 반환을 걷어내고 실제 호출로 바꿨다. 성공하면 목록을 revalidate한다.
- 팝업: 저장 성공 시 닫는 동작을 되살렸다.
backend-fetch에 `canHaveEmptyBody`를 더했다 — 이 PUT은 인터페이스에 `ApiResponseVO` 반환으로
문서화돼 있지만 구현이 `void`이고 `ApiResponseVO.success(null)`을 만들어 놓고 버려서, 본문 없는
200이 나간다. 봉투를 파싱하기 전에 빈 본문을 갈라 성공으로 받는다. 백엔드가 봉투를 돌려주도록
고쳐도 그대로 동작한다.
감사 컬럼(LAST_MDFR_*)은 보내지 않는다 — 매퍼가 쓰지만 백엔드 CrudLogInterceptor가 UPDATE마다
자동으로 채운다(확인함).
Co-Authored-By: Claude Opus 5
비활성이던 정렬 select를 되살린다. 백엔드 목록 API에는 정렬 파라미터가 없고 목록 SQL의
ORDER BY가 하드코딩돼 있어(ORDER BY rnum DESC), 두 정렬을 서로 다른 방식으로 만족시킨다.
- 가입일순: 백엔드의 고정 순서가 이미 가입일 최신순이다. rnum이
ROW_NUMBER() OVER (ORDER BY frst_reg_dt, user_nm DESC)로 매겨진 최초등록일시 순번이고
그것을 역순으로 뒤집기 때문이다. 따라서 페이지 하나만 받아오면 되고 기존 경로 그대로다.
- 이름순: 전체를 받아 서버에서 정렬하고 페이지를 잘라낸다. 받아온 한 페이지만 정렬하면
"그 페이지 안에서만 이름순"이 되어 2페이지의 '김'이 1페이지의 '이'보다 뒤에 오는, 전체 기준
정렬처럼 보이는 잘못된 결과가 나온다. 검색 조건은 백엔드에 그대로 위임하고 페이지 크기만
상한(10,000)까지 키워 한 번에 받는다. 전체를 쥐게 되므로 이 경로에서는 총건수가 확정된다.
회원 수가 상한을 넘으면 그 위로는 정렬 대상에서 빠지고 총건수도 하한값으로 표기된다 —
그 규모에서는 백엔드에 정렬 파라미터가 필요하고, 상한 인상은 임시방편일 뿐이다.
학생 회원 목록 조회를 로그인 구현이 세운 인증·통신 기반 위로 옮긴다.
- 백엔드 HTTP 클라이언트를 lib/http/backend-fetch.ts 하나로 통일한다. 목록 연동에서 임시로
두었던 lib/data/api-client.ts는 삭제하고, 거기에만 있던 세 가지를 backendFetch로 옮겼다:
쿼리스트링 조립, Authorization 헤더(accessToken), 그리고 비2xx 응답의 봉투 code 보존.
마지막 항목이 없으면 백엔드가 HTTP 401로 주는 인증 실패가 통신 오류(code -1)로 뭉개져
"세션이 끊겼다"와 "서버가 죽었다"를 호출부가 구분할 수 없다.
- 세션에 보관된 accessToken을 꺼내는 getSessionAccessToken()을 DAL에 추가한다. 화면 DTO
(AdminUser)는 토큰을 담지 않으므로 서버 전용 경로를 따로 둔다.
- 개발용 토큰 우회로(getDevApiAccessToken / EDUPAY_API_ACCESS_TOKEN)를 제거한다. 실제
로그인이 토큰을 공급하므로 존재 이유가 사라졌다.
- lib/env.ts 충돌은 hub 쪽 getApiBaseUrl()을 채택해 해소했다(같은 환경변수 키, 같은 동작).
mock 학생 회원 생성기를 제거하고 GET /api/v1/mngr/user/pagination에 연결한다.
백엔드 저장소(develop b742bb4)의 실제 구현을 읽고 계약을 확정했다.
- searchCondition은 "1"(이름)·"2"(아이디)·"3"(휴대전화)만 유효하다. 목록에 없는 값을
보내면 조건 없이 전체가 반환되므로 지원되지 않는 학교명·회원코드 검색은 제거했다.
- 유효한 페이징 파라미터는 pageIndex·recordCountPerPage 둘뿐이다(서버가 offset을 직접
계산해 나머지를 덮어쓴다).
- 응답의 totalCount는 전체 건수가 아니라 현재 페이지 행 수다(백엔드에 count 쿼리 없음).
그대로 믿으면 가득 찬 페이지 뒤 데이터에 접근할 수 없어 하한값으로 보정하고, 확정되지
않은 건수는 화면에 "N명 이상"으로 표기한다.
- 응답이 주지 않는 항목(휴대전화·이메일·학교·학년/반·보호자·가입일·사용여부)은 열을
유지한 채 '-'로 표시한다. 정렬 파라미터와 사용여부 변경 API가 없어 해당 컨트롤은
비활성으로 둔다.