변경내역

Semantic Versioning을 따릅니다 — MAJOR.MINOR.PATCH.

업데이트로 무엇이 달라졌는지 쉽게 보려면 패치노트를 보세요. 이 페이지는 더 자세한 기록입니다.

최신 버전 안내와 설치파일은 운영팀(hanalabs@hanapf.kr 또는 안내받은 카카오톡 채널)으로 문의해 주세요.


[0.4.5] — 2026-11-02

0.4.3 후속 묶음입니다. 하나로 자체 라벨 인쇄를 없애고 송장 출력을 택배사(로젠) 출력으로 일원화했고(#335), 주문 화면 택배사 선택기의 기본값(로젠택배)을 없앴습니다(#337). 카페24에서 송장이 빠진 주문의 보낸 기록 정리(#338)와 [마켓 동기화]의 무변경 회차 재조회 생략(#330 · #343 · #347)을 담았습니다. 이어서 주문 [엑셀 저장] 칸 고르기(#419), 주문 표 Shift+클릭 범위 체크(#422), 매출 일별 추이 축 날짜(#420), [송장번호 불러오기]의 다른 PC ESM 묶음 판정(#421), 자동 로그인 창 안내 띠(#423), 주문 화면 버튼 정리(#428)를 더했습니다. DB 마이그레이션은 없습니다.

⚠️ 업데이트 뒤 주문 화면 택배사 선택기가 비어 있으면(택배사 선택) [택배 자동접수]·[접수 후 작업 ▾]·[택배 접수용 엑셀]·[더보기 ▾]가 꺼져 있습니다 — 아래 줄 [발주확인] 오른쪽에서 쓰는 택배사를 한 번 골라야 합니다.

Added

  • 설정 → 마켓 계정 [셀러센터 로그인] 칸 — 로그인 방식 선택 + [취소] 버튼 (노션 [0.4.5] 설정 → 마켓 계정 [셀러센터 로그인] 칸, 사용자 요청 2026-10-26) — 방식이 둘 이상인 마켓에만 드롭다운을 둡니다(셀러센터로그인방식옵션 — 칸은 마켓을 모르고 옵션만 봅니다). 스마트스토어: 판매자 아이디 / 네이버 아이디(새 Domain 정책 스마트스토어로그인방식들, 판매처 슬롯 DPAPI 키 자격증명키.스마트스토어_셀러센터로그인방식 = SELLER/NAVER, 없으면 판매자 아이디). ESM: 종전 읽기 전용 글자 “로그인 방식: … (바꾸려면 [재인증])”를 드롭다운으로 바꿔 이 칸에서도 고칩니다([재인증] 폼과 같은 키 ESM_로그인방식, 방식이 바뀌면 세션 쿠키·판매자ID 기억을 지워 다음 수집이 새 탭으로 다시 로그인). 쿠팡·11번가·카페24는 폼이 하나라 드롭다운이 없습니다. [취소]([지우기]·[취소]·[저장] 순)는 입력값을 버리고(아이디는 저장된 값, 비밀번호 칸 비움, 방식은 저장된 값) 칸을 접습니다 — 저장소는 건드리지 않습니다. 셀러센터 창 자동 로그인(셀러센터창): 스마트스토어 판매처의 방식이 네이버 아이디면 판매자센터 로그인 화면(accounts.commerce.naver.com)에서 [네이버 아이디로 로그인] 버튼만 누르고(네이버아이디전환템플릿, 값은 넣지 않음 — 결과 naver-login-redirect), 네이버 로그인(nid.naver.com, #id·#pw·#log.login)에서 아이디·비밀번호를 넣습니다(네이버아이디자동입력템플릿). 판매자 아이디 방식과 다른 마켓은 종전 그대로입니다(자동입력마켓·자동로그인판정·자동입력스크립트에 선택 인자 네이버아이디방식, 기본 false). 보안문자·새 기기 확인·2단계 인증은 종전처럼 추가 인증 안내로 셀러가 직접 마칩니다. I셀러센터로그인저장소.스마트스토어로그인방식Async(읽기 실패 = 판매자 아이디). 🔴 실계정 미확인: 네이버 아이디 경로([네이버 아이디로 로그인] 버튼 글자·nid.naver.com 폼 선택자)는 공개 화면 구조 기준이고 이 PC에 네이버 아이디 스마트스토어 계정이 없어 자동 입력까지는 확인하지 못했습니다. 로그에는 결과 코드만 남고 아이디·비밀번호는 남지 않습니다. 리뷰 반영: [네이버 아이디로 로그인] 버튼만 누른 결과(naver-login-redirect·naver-login-button-not-found)는 비밀번호를 내지 않았으므로 자동 로그인 2회 정지 횟수에서 되돌리고(셀러센터창.비밀번호미제출결과, 한 창에서 버튼은 최대 3번), 자동 로그인 시도 지문에 로그인 방식을 넣어(자동로그인시도기록.지문(아이디, 비밀번호, 방식) — 셀러센터 창의 스마트스토어·ESM 자동 로그인 모두) 방식만 고쳐 저장해도 2회 정지가 풀립니다. ESM 방식 저장은 세션·기억을 먼저 지우고 방식을 저장해(종전 반대 순서는 삭제가 실패하면 재시도 때 삭제를 건너뛰었다) 실패 뒤 다시 저장해도 삭제가 빠지지 않습니다. 아이디·비밀번호 저장 뒤 방식 저장만 실패하면 “아이디·비밀번호는 저장했지만 로그인 방식을 저장하지 못했습니다”로 칸을 열어 두고(버튼 색·저장 상태는 저장됨으로), 저장된 방식을 읽지 못하면 칸에 “기본값으로 보여요”를 알립니다.
  • 카페24 보낸 기록 자동 정리 (#338) — 하나로가 보냈다는 기록(송장번호전송일시)은 있는데 [마켓 동기화]에서 카페24 주문이 송장번호 없이 발주확인·배송준비중으로 오면 그 기록만 지워 [선택 주문 송장 등록]으로 다시 보낼 수 있게 합니다. 규칙은 Domain 송장전송기록판정.미반영정리대상인가(① 기록 있음 ② 마켓 송장 없음 ③ 마켓·하나로 상태 모두 발주확인/배송준비중, CS상태 정상 ④ 기록이 수집 시작보다 10분 이상 앞섬 — 경합 방지) 단일 출처, EF·InMemory가 같은 함수(Persistence/송장전송기록정리)로 적용합니다. 하나로 송장·택배사·불일치 기록은 그대로, 새 컬럼·마이그레이션 없음. 정리 건수는 수집 결과 기타변경건수(화면 재조회)에 들어가고 로그에는 판매처 번호·건수만 남깁니다. 끄기 스위치 HANARO_CAFE24_UNSENT_RESET_DISABLED. 🔴 카페24에서 송장을 지웠을 때 배송준비중으로 돌아가는지는 실계정 미확인(안 돌아가면 규칙이 걸리지 않을 뿐 — 종전 동작)(사용자 승인 2026-10-15).
  • 주문 [엑셀 저장] — 저장할 칸 고르기 (#419 · 노션 [0.4.5?] 주문 [엑셀 저장]에 주문자 전화·받는 분 전화·주소·배송메모·옵션명 — 2026-10-28 셀러 문의: 셀로 엑셀처럼 한 파일로, 스스로 매출 관리용)
    • [엑셀 저장]을 누르면 버튼 위 Flyout에 “저장할 칸” 체크 목록(2열) + [전체 선택]·[취소]·[저장]. 체크한 칸만 정해진 순서로 저장한다(사용자 확정 2026-10-28). 체크한 주문만 저장하는 규칙·저장 진행 창은 그대로.
    • 칸 목록·순서·처음 고른 칸·전화주소 칸은 주문엑셀칸 단일 출처 — 종전 15칸(주문표열.엑셀헤더들) + 옵션명(상품명 뒤 — 고르면 상품명 칸에 옵션을 붙이지 않음)·받는분 휴대폰·배송지 주소·배송메모(받는분 뒤)·주문자 전화번호(주문자명 뒤). 처음엔 15칸 체크(종전과 같은 파일). 전화는 전화번호표기.하이픈넣기.
    • 마지막 선택은 %APPDATA%\Hanaro\order-excel-columns.json(주문엑셀칸설정서비스 — 칸 이름만, 원자 저장, 손상·모르는 이름뿐이면 처음 고른 칸, 빈 선택은 기억 안 함). 기억 실패는 저장을 막지 않는다.
    • 전화·주소 칸을 고르면 목록 아래 “전화번호·주소가 파일에 들어가요 — 보관에 주의해 주세요.” 칸을 모두 끄고 [저장]하면 저장 창을 열지 않고 “저장할 칸을 하나 이상 골라 주세요.”
    • IExcelExportService.ExportOrdersAsync에 고른 칸 인자 추가, 주문엑셀행에 상품명만·옵션명·받는분휴대폰·배송지주소·배송메모·주문자전화번호(뒤에 붙임 — [행 전체 복사]의 칸들() 15칸은 그대로), 송장행Vm.주문자전화(화면 미표시). 🔴 전화·주소는 셀러가 고른 파일에만 — 로그·Sentry·상태 문구 금지.
    • 묶음 색(사용자 결정 2026-10-28 — 셀로 엑셀처럼): 같은 묶음(엑셀묶음키들 — 판매처 안에서 ① 같은 송장번호·택배사 또는 ② 같은 상자(쿠팡은 묶음배송번호, 그 밖은 화면 “묶음 N”과 같은 키 표시묶음키) 중 하나만 같아도 한 묶음(합집합). 발송 뒤 ESM 묶음은 주문번호가 제각각이라 화면 키만으로는 줄마다 색이 달랐고(실기), 번호가 대표에만 들어간 상자는 송장 키만으로는 갈렸다(리뷰)) 줄을 그 묶음의 첫 줄 아래로 모으고(그 밖의 순서는 화면 그대로) 묶음마다 바탕색 4가지를 돌려 줄 전체를 칠한다. 혼자인 주문도 칠한다. 규칙은 주문엑셀묶음 단일 출처, 키는 주문엑셀행.묶음(칸이 아님 — [행 전체 복사]와 무관).
    • 개인정보처리방침(1.0) 문구 보완(사용자 결정 2026-10-28 — 시행 중 문서를 바로 고침, 수집 항목 변화 없음): 1항 판매처 목록에 11번가, 6항에 “엑셀 저장 등으로 직접 저장한 파일은 앱을 삭제해도 남으니 이용자가 직접 삭제”.
    • 추가구성(스마트스토어 추가상품 등)은 하나로가 받아 두지 않는 정보라 이번엔 넣지 않았다(사용자 결정).
    • 리뷰 반영: [저장] 없이 닫으면([취소]·바깥 누름) 열 때의 선택으로 되돌림, 고른 칸이 없으면 [저장]해도 목록을 열어 둠(안내만), 늦게 끝난 복원이 셀러가 바꾼 체크를 덮지 않음, DI 주입 가드 시험. 목록 맨 위 “체크한 주문 N건을 저장해요.”, 체크한 주문이 없거나 칸이 없으면 목록 안 경고 + [저장]해도 목록을 열어 둠(실기 — 상태 줄 안내를 놓쳤다), 체크한 주문 없이 연 목록은 닫혀도 고른 칸을 되돌리지 않음(안내대로 표를 누르면 닫히므로), 칸을 다시 고르면 경고를 지움. 결제금액은 숫자 칸(표시 #,##0)으로 — 합계를 낼 수 있게(사용자 결정 2026-10-28, 주문엑셀행.결제금액숫자). [행 전체 복사]는 종전 글자 그대로.
  • 주문 표 — 체크박스 Shift+클릭으로 여러 주문 한 번에 체크 (#422 · 노션 [0.4.5] 주문 탭 — Shift+클릭 — 2026-10-29 사용자 요청: 주문을 하나하나 체크하기 힘듦)
    • 탐색기·Gmail과 같은 방식(사용자 확정): 체크박스를 클릭한 행이 기준, Shift를 누른 채 다른 행 체크박스를 클릭하면 기준~그 행 사이(양 끝 포함) 전부를 클릭한 행의 새 상태로 맞춘다(켜면 모두 켜고 끄면 모두 끔). 기준은 마지막으로 클릭한 행.
    • 범위는 지금 표시 목록 순서(필터·정렬 반영) — 걸러져 안 보이는 주문은 건드리지 않는다. 목록을 새로 불러오거나 필터를 바꿔 기준 행이 없으면 그 행만 바뀐다. 체크박스가 아닌 칸 클릭·머리글 전체 선택·키보드 이동은 그대로.
    • 송장관리ViewModel.범위체크(머리글·선택 안내는 끝에서 한 번 맞춤), View는 행 체크박스(order-check)의 Click 직전 입력(포인터·키)의 수정키로 Shift를 가린다. 기준은 행 VM으로 들고(가상화로 컨테이너가 재활용된다) 쓸 때 지금 목록에서 위치를 찾는다.

Changed

  • 주문 화면 택배사 선택기 기본값 제거 (#337 · #343) — 셀러마다 쓰는 택배사가 달라 처음(저장된 선택 없음·옛 courier-prefs.json·손상)에는 미선택(택배사 선택)이고, 고르기 전에는 [택배 자동접수]·[접수 후 작업 ▾]·[택배 접수용 엑셀]·더보기 ▾가 꺼지며 버튼 줄 아래에 “먼저 택배사를 골라 주세요.”가 뜹니다(명령 입구도 같은 가드). 저장된 선택은 그대로 복원하고 미선택은 저장하지 않습니다. [선택 주문 송장 등록]·[엑셀 저장]·[발주확인]은 선택기와 무관합니다(사용자 지시 2026-10-15).
  • [마켓 동기화]·자동 수집 — 바뀐 것이 없으면 목록을 다시 읽지 않습니다 (#330 · #343 · #347) — 주문수집결과.화면갱신필요(저장·상태갱신·숨김·기타변경 건수) 단일 판정으로 무변경 회차의 목록 재조회(수동)·변경 알림(자동)을 건너뜁니다. 수집 전에 목록 읽기가 실패해 있었으면(조회실패로끝남) 바뀐 게 없어도 다시 읽습니다(재조회생략가능(…, 수집전목록실패) — 자동 수집은 시작 때 _자동수집전목록실패에 기록). 임시 판매처 이름을 가게명으로 실제로 바꿨을 때만 기타변경건수에 셉니다(Try판매처이름업데이트Async → Task<bool>, Contracts 시그니처 불변). 한계: Upsert가 값이 같아도 저장 건수를 세므로 쿠팡·카페24처럼 92일 창을 다시 받는 판매처에서는 거의 생략되지 않습니다. 판매처 간 병렬(C)·카페24 단일 스캔(E)은 claudedocs/design/동기화-단축-2차_보류항목_2026-10-15.md에 착수 조건을 남기고 보류, 쿠팡 일괄 전송(F)은 미구현.
  • 주문 화면 버튼 정리 (#428 · 노션 [0.4.5] 주문 화면 버튼 정리 — 사용자 지시 2026-10-30) — [택배 접수용 엑셀]을 버튼 줄에서 [더보기 ▾] 첫 항목으로 옮겼습니다(명령·활성 조건·툴팁 그대로). [택배 자동접수]는 ghost → primary입니다. HANARO_LOGEN_REPRINT_DISABLED는 이제 다시 출력 항목만 숨기고 [더보기 ▾] 버튼은 남습니다.

Fixed

  • 자동 수집이 실패·취소되면 상태 줄의 [다시 시도]가 사라지던 문제 (#347) — 직전 목록 조회가 실패한 상태에서 자동 수집이 실패하면 조회실패꼬리로 실패 안내를 유지하고, 취소면 조회실패문구로 되돌립니다. 잠금 해제 뒤 미뤄 둔 조회가 곧 목록을 읽으면 꼬리를 남기지 않습니다(그 조회 결과가 정합니다). 실패 판정은 조회실패로끝남(string?)(EndsWith)으로 통일해, 더 새 조회에 밀린 읽기가 남긴 “결과 + 실패 꼬리”도 실패로 봅니다. 한계: 기간 시작·끝이 뒤바뀐 상태면 미룬 조회가 안내만 덧붙여 [다시 시도]가 사라집니다(종전 완료 경로와 같음).
  • 자동 수집이 바뀐 것 없이 끝나면 위쪽 “마켓 연결 확인 필요” 안내가 내려가지 않던 문제 (develop → 0.4.5 머지 리뷰) — 0.4.5가 자동 수집의 데이터변경있음을 “DB가 바뀌었는가”로 좁히면서(바뀐 것 없는 회차는 목록 재조회 생략) 0.4.2의 “실패 없는 수집이면 배너 내림” 조건이 변경 0건 성공 회차에 걸리지 않았습니다. 0.4.3의 수집 로그인 실패 배너와 합쳐지면 연결을 고친 뒤에도 자동 수집으로는 배너가 남을 수 있었습니다. 주문수집상태변경·I주문수집상태서비스.완료에 수집실행됨(bool?)을 더해 자동 수집 경로가 싣고, MainWindowViewModel의 배너 내리기 조건이 그것을 봅니다(null이면 종전처럼 데이터변경있음 — 수동 동기화·과거 주문 받기는 그 값이 이미 “수집 실행됨”). 목록 재조회 생략 동작은 그대로입니다.
  • 매출 탭 일별 매출 추이 — 축 날짜 잘림 (#420 · 노션 [0.4.5] 매출 탭 일별 매출 추이 — 2026-10-27 사용자 캡처: “9/28”이 “9/2”처럼 잘리고 “10/1”이 옆 칸과 붙음)
    • 원인: 축 라벨 폭 28px 고정(2026-10-21, 30칸이 1440 창에 들어가게)에 월이 붙는 4~5글자 라벨이 넘쳤다. 표기도 “10/1”과 “02”(앞 0)가 섞였다.
    • 두 줄로(사용자 결정 2026-10-28): 윗줄 일 숫자만·앞 0 없이(일별매출Vm.축라벨), 아랫줄 꼬리표(축꼬리표) — 첫 칸·매달 1일 “10월”, 1월 1일 “27년”(해가 바뀜), 그 밖은 빈 줄(같은 줄 높이 — 막대 바닥 정렬 시험). 꼬리표는 본문 글꼴(고정폭 글꼴의 한글이 28px를 넘지 않게). 툴팁에 연도(“2026년 10월 21일 (수) · …”). 라벨 폭·칸 폭은 그대로라 가로 스크롤 조건은 바뀌지 않는다.
  • [송장번호 불러오기] — 다른 PC에서 접수한 ESM 묶음의 나머지 주문이 “로젠에 없음”으로 보임 (#421 · 노션 [0.4.5] [송장번호 불러오기] — 2026-10-27 실기: G마켓 묶음 5건 중 1건만 “변화 없음”, 4건 “로젠에 없음”)
    • 원인: 다른 PC가 묶음을 대표 주문번호 하나로 접수해 로젠에는 그 줄만 있고, 이 PC에는 접수 기록·묶음 구성이 없어 나머지 주문을 자기 주문번호로 찾다 못 찾았다(배송은 정상).
    • 새 판정 번호확인결과.같은상자접수됨(번호확인대조.같은상자줄 — 판정 단일 출처라 등록 직전 재확인·주기 확인도 같은 규칙): 로젠에 없는 주문이라도 하나로의 지금 번호가 같은 받는 사람의 다른 주문번호 출력완료 줄(그 주문의 최신 줄 — 다시 출력돼 옛 번호가 된 줄은 아님, 확인된 접수일자가 있으면 그 날짜)과 같으면 이 판정. 저장 대상이 아니라 번호를 덮어쓰지 않는다. 결과 문구 끝에 “같은 상자로 접수됨 N건(묶음의 다른 주문번호로 로젠에 접수돼 있어요 — 송장번호는 그대로)”.
    • 재확인·주기 확인은 저장 대상(채움·번호 바뀜)만 다뤄 동작이 바뀌지 않는다. [선택 주문 송장 다시 출력(새 번호)…]은 이 판정을 “로젠에 없음”으로 본다(대표 상자를 다른 주문번호로 다시 출력하지 않게).
  • 자동 로그인 창 — 앞으로 뜰 때 왜 떴는지 안내 · ESM 탭 전환 뒤 입력 결과 기록 (#423 · 노션 [0.4.5] ESM 자동 로그인 — 2026-10-29 실기: 앱 시작 직후 ESM 로그인 창이 안내 없이 떠 이유를 몰랐음)
    • 원인: 앱 시작 연결 확인의 ESM 자동 로그인이 15초 안에 끝나지 않으면 창을 앞으로 띄우는데, 사유(“자동 로그인에 시간이 걸리고 있어요 — 직접 로그인을 완료해 주세요.”)가 창 아래 상태 줄에만 작게 보였다.
    • 창을 앞으로 띄울 때(모든 사유) 주소창 아래에 노란 안내 띠: 첫 줄 “하나로가 ○○ 자동 작업 중에 이 창을 띄웠어요 (판매처: ○○) — 직접 확인이 필요해요.”(체인단계대기.승격안내띠제목, 판매처 이름은 MarketLoginConfig.판매처표시이름 — 자동 로그인 경로만 채움, 화면 표시 전용), 둘째 줄은 상태 줄과 같은 사유 문구(승격안내문구). 띠 높이는 문구 길이에 맞추고, 창을 다시 숨기면 띠도 감춘다. 로그인 뒤 셀러가 직접 작업하는 창(사유 “수동작업”)은 종전 “직접 로그인을 완료해 주세요”(거짓) 대신 “로그인됐어요 — 화면에서 작업을 마친 뒤 [닫기]를 눌러 주세요.”(리뷰).
    • ESM 로그인 방식 탭을 눌러야 하는 판매처는 자동 입력 스크립트가 tab-switching을 돌려준 뒤 실제 입력·클릭 결과(window.__hanaroEsmFill, 시작할 때 비움)를 0.1초 간격으로 최대 4초 다시 읽어 “탭 전환 뒤 자동 입력 결과” 로그·진단에 남긴다(결과 코드만 — 아이디·비밀번호 없음). 화면이 로그인 페이지를 벗어나면 멈춘다. 창 동작(앞으로 띄우는 시점·결과)과 비밀번호 제출 판정은 바꾸지 않는다.
    • 같은 날 다시 띄웠을 때는 두 판매처 모두 창 없이 로그인됐고, ESM 로그인 화면의 탭·입력칸·버튼 선택자도 그대로였다 — 그때 멈춘 원인은 아직 모른다(다음에 멈추면 이 로그로 본다).

Removed

  • 하나로 자체 라벨 인쇄(택배사 출력 사용) (#335 · #343) — 택배사 연동(로젠 [이 PC에서 출력]·[선택 주문 송장 다시 출력(새 번호)…])으로 송장을 뽑으므로 하나로가 직접 그리던 100×150mm 라벨 인쇄를 없앴습니다(사용자 결정 2026-10-15).
    • 화면: [더보기 ▾] → [선택 주문 라벨 인쇄…], 행 우클릭 [이 박스 라벨 인쇄…]·[체크한 주문 라벨 인쇄…], 라벨 미리보기 창, 송장 칸 “🏷 인쇄됨” 배지, 대시보드 “라벨 미인쇄” 칩(과 그 딥링크 필터), 설정 → 일반 [테스트 출력]을 뺐습니다.
    • [더보기 ▾]에는 [선택 주문 송장 다시 출력(새 번호)…]만 남고, HANARO_LOGEN_REPRINT_DISABLED로 그 항목이 숨으면 [더보기 ▾] 버튼째 숨깁니다(빈 메뉴 방지).
    • 설정 → 일반의 “라벨 인쇄” 카드는 “프린터” 카드로 이름을 바꿔 남깁니다 — 여기서 고른 프린터를 로젠 인쇄 창 프린터 자동 선택과 [이 PC에서 출력] 전 출력 환경 점검이 씁니다(print-settings.json 그대로).
    • 저장소 메서드 Mark라벨인쇄됨Async·Select라벨인쇄여부들Async(Contracts·EF·InMemory)와 처리큐판정.라벨미인쇄여부·처리큐필터.라벨미인쇄를 지웠습니다.
    • 🔴 DB 컬럼 shipments.label_printed_at(송장.라벨인쇄일시)과 송장번호를 바꿀 때 그 값을 비우는 코드는 남깁니다(옛 버전으로 되돌린 셀러가 그대로 쓰도록 — 마이그레이션 추가 없음).
    • ⚠️ 0.4.3으로 되돌리면 대시보드 “라벨 미인쇄” 칩 수가 늘어 보입니다 — 0.4.5는 라벨 인쇄 기록을 남기지 않으므로, 0.4.5에서 송장번호를 붙였고 아직 발송 전·마켓 등록 전인 주문은 로젠으로 이미 뽑았어도 0.4.3이 “라벨 미인쇄”로 셉니다(0.4.3 처리큐판정.라벨미인쇄여부 기준).
    • 셀러 문서 라벨-인쇄.md를 지우고 프린터 고르기·드라이버 여백 안내를 발송처리 → 출력할 프린터 고르기로 옮겼습니다. 앱 안 FAQ의 라벨 인쇄 항목 4개(invoice-018~020·029 “인쇄했는지 표시가 남나요?”)를 지웠습니다(0.4.2 정리 151건 → 147건). 프린터 항목(invoice-021·022, trouble-023)의 문서 링크는 지운 라벨-인쇄.html 대신 발송처리.html#printer를 가리킵니다.

내부 (화면 변화 없음)

  • 판매처 병렬 수집이 판매처마다 센 기타변경건수를 합치는지 시험 2개를 더했습니다(#424 — 합산 줄을 빼면 두 시험 모두 실패함을 확인).
  • 카페24 보낸 기록 정리의 EF 묶음 저장 실패 → 건별 재저장 경로 회귀 테스트, 택배사 미선택 상태로 [선택 주문 송장 등록]이 끝까지 도는 테스트, 자동 수집 재조회 판정 테스트를 더했습니다(#343 · #347). OrderListPerf 시드의 라벨 인쇄 30%를 뺐습니다(난수 소비는 유지). 🔴 카페24 N21·N22(배송대기·보류)의 송장번호 노출은 실계정 미확인.

[0.4.4] — 2026-10-27

Fixed

  • 스마트스토어 [선택 주문 송장 등록]·[발주확인]을 31건 이상 한 번에 하면 전부 실패하던 문제 (노션 [0.4.4] 스마트스토어 31건 이상 발주확인 실패 — 2026-10-27 사업2팀 현장: 31건 등록이 모두 “발주확인 실패: 네이버 커머스API 오류(400): Size.placeOrderHeimdallRequest.productOrderNoList”, 로그 발주확인중.. (31건)) — StoreFarmApiAdapter.발주확인Async가 대상 상품주문번호 전부를 한 요청에 실었고, 네이버가 목록 개수 검사(30건 초과)로 요청 전체를 거절했습니다. 이제 발주확인과 발송 처리 모두 한 요청에 StoreFarmApiAdapter.한요청최대건수(30, 단일 출처)씩 나눠 보냅니다. 발주확인은 묶음마다 결과를 주문별로 남기고(응답 누락 재조회도 묶음별) 성공한 주문의 원본 상태를 발주확인으로 표시해, 뒤 묶음 호출이 실패해도 [발주확인] 버튼 경로가 앞 묶음 성공을 가려냅니다(호출 실패 예외는 종전처럼 던짐 — 송장 등록 경로는 종전대로 그 회차 대상 전체를 같은 사유로 실패 처리하고, 이미 발주확인된 앞 묶음은 다음 등록 때 “이미 발주확인”으로 성공 처리됩니다). 발송 처리는 같은 주문번호(한 상자)의 상품주문을 한 요청에 두고(한 주문이 30건을 넘을 때만 자름 — 묶음나누기) 묶음마다 결과를 남기며, 한 묶음이 거절되거나 예외로 끝나도(사용자 취소 제외) 그 묶음 주문에만 사유를 싣고 다른 묶음은 그대로 보냅니다(종전 단일 요청에는 없던 부분 성공을 처리기가 버리지 않게). 발송 처리의 네이버 상한은 확인하지 못했지만 같은 주문 묶음이 바로 이어 가므로 같은 상한을 씁니다(종전 처리기 묶음 100건은 그대로 — 어댑터 안에서 나눔). 현장 우회(이 버전 전): 한 번에 30건 이하로 나눠 등록.
  • 로젠 [택배 자동접수] 중 로젠이 안내 창(비밀번호 변경 안내 등)을 띄우면 창이 숨은 채 3분 동안 멈추던 문제 (노션 [0.4.4] 로젠 자동접수 — 로그인 뒤 안내 창이 뜨면 창을 보여 주기)
    • 현장(2026-10-27): 로그인 직후 메뉴 클릭이 3분 멈췄다가 시간 초과로 창이 뜬 뒤에야 셀러가 안내 창을 닫았고, 닫자 3초 만에 접수가 이어졌다. 로젠 JS 대화상자가 떠 있는 동안 페이지 스크립트가 멈춰 클릭 대기(횟수로 세는 10초 상한)도 끝나지 않았다.
    • 숨긴 로젠 창에 alert·confirm·prompt가 뜨면 곧바로 창을 보이고 “로젠이 안내 창을 띄웠어요 — … 닫으면 이어서 자동으로 진행해요”로 안내한다(하나로가 대신 누르지 않는다). 조용히 실행(주기 확인·등록 직전 재확인)은 2분을 기다리지 않고 바로 포기한다. 보관 중 대화상자 닫기·이어 쓰기 beforeunload 수락은 그대로(로젠창보관판정.대화상자판정 단일 출처).
    • 대화상자 처리는 창 보관 끄기 스위치(HANARO_LOGEN_WINDOW_KEEP_DISABLED)와 무관하게 로젠 창 전부에 건다.
    • 🔴 실제 안내 창으로는 미확인 — 로그의 3분 멈춤(클릭 시도가 끝나지 않음)으로 JS 대화상자로 판단했다. HTML 안내 창이면 종전처럼 메뉴 클릭 10초 실패로 창이 뜬다.
    • 문구와 무관한 멈춤 감시(사용자 요청 — 창마다 규칙을 정하지 않게): 로젠 로그인 제출 뒤 10초가 지나도 로그인 화면에 머물러 있으면(로젠로그인멈춤한도 — 로그인 뒤 화면으로 넘어갔으면 계정 대조가 느려도 보이지 않는다, 리뷰 R1), 작업 화면에서 스크립트 한 번이 15초 안에 돌아오지 않으면(로젠스크립트멈춤한도, 사유 화면응답없음 — “로젠 창은 닫지 마세요”) 창을 보인다. 끄기 스위치 HANARO_LOGEN_STALL_WATCH_DISABLED. 스크립트를 부르지 않는 타이머라 대화상자로 화면이 막혀도 동작한다. 아래 문구 감지는 안내 문구를 고르는 데만 쓴다.
    • 로젠 로그인 화면(/, 제출 뒤 /#n)을 비밀번호 오류 감지 대상(MarketLoginConfig.Is로그인페이지URL)에 넣었다 — 종전에는 목록에 없어 “NoSuchUser”(일치하는 사용자 계정이 없습니다) 창을 감지하지 못하고 3분을 숨어 기다렸다(2026-10-27 실기 → 수정 뒤 즉시 창·비밀번호 확인 문구 확인). 잠김 창(“로그인 실패 횟수가 10회를 초과…”)은 잠금 해제 안내(로그인잠김 — 로젠 화면에서만, 리뷰 Y2), 문구를 모르는 로젠 공통 모달은 일반 안내(로그인안내, 자격증명 실패로 단정하지 않음)로 가른다(체인단계대기.로그인오류승격사유). 잠김 감지는 실기 로그로 확인(제출 3.5초 뒤 창).
  • 로젠 자동 로그인 2회 정지 (같은 카드 — 틀린 비밀번호로 작업·배경 확인이 반복돼 로젠 계정이 잠긴 실기 2026-10-27)
    • 같은 로그인 정보로 비밀번호를 제출하고 비밀번호 오류·잠김을 감지했거나 로그인 화면을 벗어나지 못한 일(로젠자동로그인정지.실패로셈 — 취소·로그인 뒤 화면 도달은 세지 않음, 리뷰 Y1)이 2번이면 그 뒤 로젠 작업(셀러 명령·배경 확인)은 창을 열지 않고 로그인 실패로 끝낸다(로젠자동로그인정지, ESM과 같은 자동로그인시도기록 규칙, 메모리 전용). 로그인 성공·정보 변경(지문)·설정 → 택배사 저장/변경/삭제(설정ViewModel.로젠보관창닫기수행)로 풀린다. 이어 쓴 보관 창은 로그인을 다시 하지 않아 세지 않는다. 끄기 스위치 HANARO_LOGEN_LOGIN_STOP_DISABLED. 정지·잠김 때도 화면 결과 문구는 아직 “비밀번호를 확인해 주세요”로 같다(리뷰 Y4 후속 — 잠김 문구는 로젠 창에 보인다). 한 창 안의 재제출·설정 [저장하고 로그인]의 제출은 세지 않는다(리뷰 G3).

[0.4.3] — 2026-10-26

0.4.1 후속 묶음입니다. 카페24 송장 후속(배송완료 교체 차단·배송준비중 올리기 품목 지정·권한 부족 [재인증] 안내), 시작 업데이트 게이트 창 지연 표시, 업데이트 E2E용 상태 폴더 override, 셀러 문서 정비(그림 WebP·해요체·문제해결 정정)에 더해, 스마트스토어 상품번호 링크, 주문 엑셀 15칸, 셀러센터 로그인 저장 표시·계정 전환, 수집 로그인 실패 배너, 로젠 [이 PC에서 출력] 대기 단축, 주문 수집 판매처 병렬을 담았습니다. DB 마이그레이션은 없습니다.

Changed

  • 카페24 배송준비중 올리기에 품목 지정 (#328 · #341) — 송장 등록 전 상품준비중(N10) → 배송준비중(N20) 올리기 PUT /api/v2/admin/orders/{order_id}가 본문 request.order_item_code[]에 이번에 보내는 품목(로컬 상태 발주확인)의 품주코드만 담습니다(Cafe24Adapter.올리기본문·지정할품주코드 — 빈 값 제외·공백 정리·중복 제거, 비면 종전 주문 전체 본문). 근거는 카페24 공식 문서(2026-09-01판)의 필드 존재뿐이고 지정 시 그 품목만 올라가는지는 문서에 서술이 없어 실계정 미확인입니다. 품목 지정이 400·422로 거절되면(품목지정거절인가) 주문 전체 본문으로 한 번 더 보냅니다. 401·403·404·429·5xx·시간 초과는 다시 보내지 않고 종전처럼 품목 상태를 다시 읽어 판정합니다(#341에서 4xx 전체 → 400·422로 좁힘 — 쓰기를 몰래 다시 보내지 않는 규칙과 맞춤). 로그에는 판매처·HTTP 상태·품목 지정 여부만 남고 품주코드·주문번호는 남기지 않습니다.
  • 시작 업데이트 게이트 창 지연 표시 (#329) — 게이트 창을 만들되 바로 보이지 않고, “확인 중” 단계가 400ms(시작업데이트표시판정.표시지연) 안에 끝나면 보이지 않은 채 닫습니다. 발견됨·내려받는 중·적용 중은 즉시 표시합니다(진행 상태 화면 표시 규칙 유지). 창을 보였던 경우에만 Background 우선순위로 한 틱 넘긴 뒤 호스트를 시작합니다. 부트스트랩 순서·ShutdownMode 복원·치명 실패 경로·적용 경로 600ms·X → [나중에]는 그대로입니다. 확인이 400ms를 넘는 PC는 “확인 중” 창이 400ms 늦게 뜹니다.
  • 셀러 문서 (#327 · #341) — docs/images/screens 화면 그림 58장 PNG(6.67 MiB) → WebP(3.28 MiB, 품질 85). scripts/DocsScreenshot이 .webp로 저장하고(SkiaSharp 재인코딩) --convert로 기존 PNG를 재촬영 없이 변환합니다. 문서 <details> 안 본문을 해요체로 통일했고, 문제해결·시작하기의 사실과 다른 문장(포터블 zip의 .NET Runtime 별도 설치, 설치 파일 이름 Hanaro-stable-Setup.exe, 로그 파일 이름 hanaro-20260509.log·보관 14개, 비상 실행 파일 Hanaro.UI.exe, 로그 레벨은 HANARO_Serilog__MinimumLevel__Default 환경변수 — 실행은 미검증)을 바로잡았습니다. 시작 단계(업데이트 확인) 로그는 로그 레벨 설정과 무관하다는 한 줄을 더했습니다(#341).
  • 스마트스토어 커머스API 판매처의 스토어 경로명 자동 확보 (2026-10-23 실기 — 커머스API 판매처는 주문 응답에 productUrl이 없어 #386 만으로는 링크가 생기지 않았다) — StoreFarmApiAdapter가 I스토어경로명제공(Contracts 선택 인터페이스)으로 GET v1/seller/channels의 url(실계정: 루트 배열·channelType STOREFARM·https://smartstore.naver.com/{경로명})에서 경로명을 읽고(경로명추출 — STOREFARM 채널이 정확히 하나면 그것, 없으면 스마트스토어 형식인 채널이 하나일 때만, 둘 이상이면 null — 주문 응답에 채널 구분값이 없어 한 키 계정에 스토어가 여럿이면 어느 스토어인지 가릴 수 없으므로 틀린 링크를 만들지 않고 “스토어 주소” 칸에 맡긴다(2026-10-23 사용자 지적), 실패는 null·마지막에러 미기록), 주문수집실행기가 경로명이 빈 스마트스토어 판매처에서 주문을 받기 전에 한 번 불러(Try스토어경로명어댑터확보Async — 형식 재검사, 모름·형식 밖·예외면 종전 productUrl 폴백, 취소만 전파) 저장한다. 실계정 확인: 채널 주소의 경로명 + 커머스API productId로 만든 상품 페이지가 실제 상품으로 열림(2026-10-23).
  • 스마트스토어 “스토어 주소” 입력 칸 (자동 확보가 안 될 때의 수동 경로) — 설정 → 마켓 계정 → 스마트스토어 [재인증]에 “스토어 주소 (선택)” 칸. 붙여 넣은 값(스토어 첫 화면·상품 주소·경로명만 모두 허용, 스토어URL파싱.스토어주소해석 — 수집과 같은 경로명 형식)에서 경로명만 Update판매처스토어경로명Async로 저장하고, 형식 밖이면 키 저장 전에 막는다(스마트스토어스토어주소형식안내). 비워 두면 건드리지 않고, 저장된 값은 재인증 폼에 주소로 보인다. 경로명 저장 실패는 키 저장을 되돌리지 않고 안내만 덧붙인다. 커머스API 셀러도 이 칸으로 상품번호 링크를 쓴다.
  • 스마트스토어 상품번호 링크 (사용자 요청 2026-10-22) — 주문 표 [상품번호]가 스마트스토어 주문에서도 smartstore.naver.com/{스토어 경로명}/products/{상품번호}로 열립니다. 스토어 경로명은 수집이 판매자센터(GraphQL) 세션 어댑터의 주문 응답 productUrl에서 한 번 확보해 비어 있는 판매처 행(market_channels.store_path)에만 저장합니다(주문수집실행기.Try스토어경로명확보Async — 형식 밖·저장 실패는 수집을 막지 않고 그 회차엔 다시 시도하지 않음, 로그에 경로명·URL 없음). 🔴 그 세션 어댑터는 β.lite-25부터 MarketAdapterFactory가 만들지 않아 운영에서 이 productUrl 경로는 돌지 않습니다 — 실제 자동 확보는 위 “자동 확보” 항목의 커머스API 채널 주소 하나입니다(합본 리뷰 2026-10-23). 경로명이 없으면 종전처럼 글자만입니다.
  • 스토어 경로명 저장은 비어 있을 때만 · 가리지 못한 판매처는 6시간 보류 (합본 리뷰 2026-10-23) — 수집의 자동 확보는 IMarketChannelRepository.Update판매처스토어경로명_비어있을때만Async(기본 구현 + EF·InMemory 재정의, 패리티 테스트)로 저장해 수집 중 셀러가 설정 “스토어 주소” 칸에 적은 값을 덮지 않습니다(다른 값이 있으면 false·메모리 판매처도 그대로). 종전 Update판매처스토어경로명Async(무조건 덮어쓰기)는 설정·블로그 전용으로 남습니다. 채널 목록이 경로명을 가려 주지 못한 판매처(STOREFARM 채널 둘 이상·조회 실패·형식 밖)는 스토어경로명확보보류(Application 싱글턴, 프로세스 메모리)에 6시간 보류해 회차마다 v1/seller/channels를 다시 부르지 않습니다 — 셀러가 칸에 적으면 행이 채워져 더 묻지 않고, 앱을 다시 켜면 한 번 다시 묻습니다. 주소는 상품페이지주소규칙이 만들 때와 열기 직전 두 번 검사합니다(https·호스트 정확 일치·/{경로명}/products/{숫자 1~20자리}·쿼리·조각·% 없음, 경로명은 영문·숫자·.·_·- 1~60자). 켜기 스위치 스마트스토어링크사용. 커머스API 경로가 저장하는 productId가 채널 상품번호인 것은 2026-10-23 실계정에서 확인(상품 페이지가 열림 — 위 “자동 확보” 항목).
  • 주문 [엑셀 저장]·[행 전체 복사] = 화면 표 열 (#384 · 노션 [0.4.3] 엑셀 저장이 화면 표와 다름) — 10열 → 15열(마켓·주문일자·주문번호·상품주문번호·상품번호·상품명·관리코드·수량·받는분·송장번호·택배사·발송기한·상태·주문자명·결제금액). 헤더 단일 출처 = 주문표열.엑셀헤더들(열키들 − 체크·배송조회 + 송장번호 뒤 택배사), 값 순서 = 주문엑셀행.칸들(), 행 복사도 같은 칸(종전 9칸·발송기한 없음). “수령자” → “받는분”, 주문일자는 yyyy-MM-dd HH:mm, 택배사 = 화면 글자(택배사표시 — 방문수령 “(방문수령)”), 수량은 숫자 셀, 결제금액은 종전 “N0” 문자열. 0.4.2의 “주문자명은 엑셀·복사 제외” 결정은 사용자가 뒤집음(2026-10-22). 열 위치가 바뀌어 저장 파일을 열 번호로 읽던 셀러 쪽 수식·매크로는 다시 맞춰야 한다.
  • 주문 수집 판매처 병렬 — 마켓 종류가 다른 판매처는 함께, 같은 종류는 차례로 (#396 · #397 · 노션 [0.4.3·0.4.5] 마켓 동기화 시간 단축 2차) — 2026-10-22 사업2팀 3 PC 로그(수집 16회): 수집 전체 8~62초가 판매처 직렬 합이었고(스마트스토어 0.5~0.9초·카페24 1.4~1.9초·ESM 0~4초·쿠팡 10.9~17.7초·11번가 14.6~39초 — 11번가 발송 전은 정확히 12.00초/32.00초로 호출 간격 0.5초에 묶인 값, 저장 ≤150ms), 병목은 마켓 호출 간격(쿠팡 공지 한도·11번가 보수값 — 둘 다 바꾸지 않음)이었습니다. #396은 실행기가 판매처 루프 전체에서 공유하던 지역 상태를 판매처별 결과(판매처수집결과 + 합치기 — 원래 판매처 순서, 안내줄 판매처 간 중복 제거)와 수집진행집계(전역 저장 누계·25건 중간 보고·진행률)로 나눈 동작 동일 리팩터링이고(리팩터링 전에 쓴 골든 특성 시험 주문수집_직렬동일성Tests가 수정 없이 통과), #397이 그 위에서 판매처를 줄로 나눠 줄끼리 동시에 받습니다 — 줄 키는 IMarketAdapterFactory.수집병렬줄키(Infrastructure가 Create와 같은 어댑터종류판정으로 구현, 같은 종류 = 한 줄: ESM 여럿·쿠팡 여럿·카페24는 몰이 달라도 한 줄, 판정이 던지면 전부 한 줄 + 경고). 실행기의 저장 쓰기는 모두 저장구간Async(SemaphoreSlim 1)로 한 번에 하나씩, 진행률은 남은 몫이 가장 큰 줄 기준 + 뒤로 가지 않음(줄 하나면 종전 값), 문구는 도는 판매처 중 원래 순서가 가장 앞선 것(형식 불변). 취소는 모든 줄이 끝날 때까지 기다린 뒤 전파하고(모든 줄이 정상 종료한 뒤의 취소는 직렬처럼 결과 반환), 판매처 실패 격리·고아 숨김·완전 수집·워터마크 판정은 그대로입니다. 저장 잠금을 기다리는 중 사용자가 취소하면 그 묶음(200건 이하)은 저장하지 않고 다음 수집이 다시 받습니다. 끄기 스위치 HANARO_SYNC_PARALLEL_DISABLED(완전 직렬, 주문수집병렬설정 단일 출처). 기대: 전체 ≈ 가장 느린 줄(11번가가 있으면 11번가, 없으면 쿠팡). 🔴 현장 실측 전. 설계·0.4.5 머지 체크리스트 claudedocs/design/판매처병렬수집_2026-10-23.md.
  • 로젠 [이 PC에서 출력] 고정 대기 단축 (#394 · 노션 [0.4.3] 택배 자동접수 속도 단축) — 같은 로그에서 이PC출력 2건 36.6초 중 출력 단계 25.7초, 그 안의 외부 대기(인쇄 창이 뜰 때까지)는 약 4초였고 나머지는 클릭 체인의 고정 대기였습니다. 로젠 작업 체인에서만(로젠체인대기 단일 출처, 판정은 로젠창보관판정.대상인가) 단계 뒤 대기를 1초 → 0.3초(다음 단계가 일반 클릭·hideproc일 때만 — trusted·delay 앞은 1초), 출력 뒤 체인(출력후단계들)의 마지막 단계 뒤 대기 생략, 출력 창 첫 대기 delay:3000 → delay:3000|trim=1000(체인단계대기.지연인자분리). 인쇄 직후 delay 2000·1500, 체인 첫머리 1.5초, sendkeys·ibsheet 뒤 1초, 출력 버튼 체인 끝 1초(출력 직후 재조회·지역 확인 창 감시 약 6초 유지), 서버전송 결과 폴링은 그대로입니다. 체인 시작 로그에 대기단축=켜짐/꺼짐. 끄기 스위치 HANARO_LOGEN_WAIT_TRIM_DISABLED(종전 값 전부 복귀). 기대 이PC출력 1회 약 5.1초. 🔴 프린터 PC 실기 전.
  • 셀러센터 자동 로그인 저장 여부를 [셀러센터 로그인] 버튼 색으로 표시 (#393 · 노션 [0.4.3] 사업2팀 피드백 — “셀러센터 로그인 정보가 저장돼 있는지 화면에서 안 보인다”) — 설정 → 마켓 계정 카드의 [셀러센터 로그인] 버튼이 저장 상태를 띤다: 자동 로그인 저장됨(아이디·비밀번호 둘 다 — 셀러센터 창 자동 입력 판정과 같은 기준, Button.ghost.success 송학) / 없음(기본 ghost) / 확인 못 함(복호화 실패·DB 오류, Button.ghost.warn Saffron). 평소에는 테두리만 반투명(*.Line.Faint.Brush 알파 0.5, 면·글자는 그대로), 마우스를 올리면 진한 의미색 테두리. 색만으로는 모르므로 ToolTip과 접근성 이름(버튼접근성이름)에 상태 글자. 불러오기 전과 ESM 카드는 기본 색(ESM은 카드 상태 배지가 같은 두 키로 판정). 새로고침이 카드를 먼저 그린 뒤 카드 순서대로 상태를 읽고(셀러센터로그인Vm.상태불러오기Async), 칸의 [저장]이 성공하면 칸을 접는다(실패는 열어 둔 채 문구, 비밀번호를 비운 채 [저장]해도 저장된 비밀번호는 그대로 — 종전과 같음). 카드 상태 배지는 로컬 색을 지우고 pill 클래스로 색을 나눕니다(등록됨 송학·미설정 Saffron·미확인·신규 중립 — 라벨 상수 등록마켓계정Vm.등록됨라벨 등). 제목 줄은 Grid(*,Auto,Auto)+말줄임(…)·전체 이름 툴팁으로 긴 계정 이름이 오른쪽 버튼을 덮지 않게. 대시보드 칸으로 하나로 안 셀러센터 창을 열 때(스마트스토어·쿠팡·카페24 — 셀러센터창.자동입력지원채널 단일 출처, 설정 칸을 만드는 조건도 이것) 안내 문구가 저장 여부에 따라 나뉩니다(대시보드ViewModel.셀러센터열림안내, 외부 브라우저·ESM은 종전 그대로 — ESM은 창을 열기 직전 await를 넣지 않음). 저장소에 I셀러센터로그인저장소.저장상태Async(키마다 읽어 “없음”과 “읽지 못함”을 가름)를 더했고 상태Async는 이를 감싸 의미가 그대로입니다(스마트스토어 계정 대조 fail-closed 유지). 셀러센터 세션이 지금 살아 있는지는 확인하지 않습니다(범위 밖). docs/마켓-추가하기.md의 상태 라벨 설명을 코드 라벨(등록됨/미설정/미확인)에 맞췄습니다.

Changed

  • 마켓 추가·재인증 폼 — 마켓별 확인 버튼을 없애고 [저장] 한 번이 연결을 확인 (노션 [0.4.3] 마켓 추가 — 마켓별 확인 버튼과 [저장]의 역할 겹침 정리, 사업2팀 실기 2026-10-22: ESM [로그인 확인]을 누르고 “저장된 줄 알았다”) — ESM [로그인 확인]·11번가 [연결 확인]·스마트스토어 [연결 테스트] 버튼을 설정 인라인 카드(설정View.axaml)와 마켓계정Dialog.axaml 두 곳에서 모두 뺐습니다. [저장]은 종전처럼(β.lite-9.8) 확인이 안 된 상태면 연결을 확인하고(쿠팡·11번가 = 검증 서비스, 스마트스토어 = 커머스API 연결 테스트, ESM = 실제 로그인 + 목록 1건 — 2단계 인증·보안문자면 창이 앞으로 뜸), 통과하면 저장, 실패하면 저장하지 않고 “연결을 확인하지 못해 저장하지 않았습니다. {사유}” 한 줄만 보입니다(종전 “검증 실패: …” + 아래 사유 줄 두 벌 → 한 줄, 확인 중 문구 “연결 확인 중…”). 이 PC의 공인 IP(스마트스토어 커머스API센터·11번가 셀러오피스에 API 호출 IP로 등록할 값)는 [연결 테스트] 없이 마켓을 고르면 바로 조회해 모든 마켓 폼의 마켓 선택 아래에 보입니다(On마켓유형Changed → 공인IP갱신Async, 실패하면 줄이 빠짐 — 사용자 요청 2026-10-26: 판매자센터마다 등록해야 하므로 스마트스토어만이 아니라 공통). 문구는 마켓 중립(“마켓 판매자센터의 API 호출 IP에 이 값을 등록하세요”, 스마트스토어·11번가가 확인에 성공하면 “마켓에 등록된 IP로 연결됐습니다”). 카페24 [카페24 연결하기]는 OAuth 창에서 토큰을 받아야 해 그대로입니다. 확인이 [저장] 안으로 들어와 길어진 만큼(ESM은 2단계 인증 창까지) 확인 중에는 폼 입력·마켓 선택이 잠기고(저장중), 취소는 진행 중인 확인을 끊어 확인이 끝나도 저장하지 않습니다(마켓계정DialogViewModel.저장중단 — “저장을 취소했습니다.”, 새 판매처 행도 만들지 않음; 리뷰 🔴). 실패 사유 한 줄은 줄바꿈되고, 사유가 이미 “연결을 확인하지 …”로 시작하면 머리말을 겹치지 않습니다. 명령(검증Command·스마트스토어연결테스트Command)은 남아 저장 흐름·테스트가 씁니다. ESM 안내 문구의 “[재인증] → [로그인 확인] → [저장]”은 모두 “[재인증] → [저장]”으로(ESM연결오류·EsmAdapter.Orders·ESM셀러센터로그인서비스), 셀러 문서(docs/마켓-추가하기.md·문제해결.md)와 문서 그림 캡션(scripts/DocsScreenshot/촬영목록.cs — 스마트스토어·ESM·11번가 그림은 릴리즈 때 다시 찍어야 함)도 맞췼습니다. 🔴 실기 확인 예정.

Fixed

  • 카페24 토큰 갱신 직후 수집을 취소하면 새 토큰이 저장되지 않아 연결이 끊길 수 있던 문제 (#397 · 데이터 안전 감사) — 카페24토큰갱신조정자.갱신Async가 갱신 HTTP 성공 뒤 토큰 저장에 수집 취소 토큰을 넘겨, 그 사이 취소되면 새 refresh 토큰을 저장하지 못했습니다(카페24 refresh 토큰은 한 번 쓰면 옛 토큰이 무효). 이제 갱신이 성공한 뒤의 저장은 취소와 무관하게 끝까지 합니다. 같은 패턴은 다른 마켓에 없습니다(커머스API는 메모리 캐시, 쿠팡은 서명 방식, ESM 쿠키는 다시 로그인하면 되는 값).
  • 진단 로그에 다른 프로그램의 창 제목이 남던 문제 (#394) — 로젠 작업의 [포커스]·창 정보 로그가 앞으로 온 창의 제목을 그대로 적어, 사업2팀 PC 로그에 카카오톡 대화방 이름이 남았습니다. 이제 창제목가림이 하나로 자신(pid)·ozcviewer·OZWebLauncher 창만 제목을 80자까지 남기고 나머지(msedgewebview2 포함)는 <가림 N자>로 적습니다(hwnd·class·proc는 유지). 이미 쌓인 로그·Sentry 기록은 지워지지 않습니다.
  • 수집에서 마켓 로그인이 실패해도 상단 “마켓 연결 확인 필요” 배너·알림센터가 조용하던 문제 (#398 · 노션 [0.4.3] ESM 비밀번호가 바뀌어 수집 로그인이 실패해도 안내가 안 뜸 — 2026-10-22 사업2팀 실기: 하나로가 ESM에 로그인된 채 ESM PLUS에서 비밀번호를 바꿨는데 안내가 없었다) — 배너·알림센터·대시보드 연결 경고는 앱시작자동연동서비스의 결과(앱 시작 점검·설정 재점검)로만 만들어졌고, 0.4.2의 “실패 없는 수집이면 배너 내리기”(전체연결확인됨)의 반대 방향이 없었습니다. 그래서 세션이 끊긴 뒤 옛 비밀번호로 재로그인이 실패하거나(같은 정보로 2회 실패 → 자동 로그인 정지) 커머스API 키가 거절돼도 사유가 수집 결과 문구(실패메시지들)에만 남아 대시보드 머리글 “받지 못한 마켓이 있어요”와 동기화 띠에만 보였습니다. 이제 주문수집결과.연결실패들(Contracts 판매처연결실패 — 판매처 번호·이름·어댑터 마지막 오류)에 로그인하지 못한 판매처를 구조로 싣고(주문수집실행기, 문구는 종전대로), 수집 완료(주문수집상태.연결실패들 — 자동·수동 동기화·과거 주문 받기 모두)에서 MainWindowViewModel.On수집상태변경이 I앱시작자동연동서비스.연결실패보고로 그 판매처를 결과에 실패로 반영합니다(있던 행은 교체, 없던 판매처는 추가, 같은 사유면 이벤트 없음). 사유 → 빨강·노랑 매핑은 앱 시작 점검과 같은 실패결과(ESM 연결 오류·커머스API 거부, 그 밖의 셀러 안내용 예외는 그 문구로 노랑, 원시 예외는 공통 문구)입니다. 알림센터 항목 문구를 마켓 공통으로(“마켓 연결 확인 필요 N건 — … [재인증] … “ + 판매처별 안내, 마켓연결알림문구), 설정 카드의 ESM 로그인 정보 칸에서 비밀번호를 저장하면 바로 연결을 다시 점검해(셀러센터로그인Vm 저장후 콜백 → 연결재점검) 배너가 다음 수집까지 남지 않게 했습니다. EsmAdapter의 세션 판정(쿠키가 살아 있으면 비밀번호를 쓰지 않음, 5분 확인 캐시)은 바꾸지 않았습니다 — ESM이 비밀번호 변경 때 기존 세션을 끊지 않으면 세션이 만료될 때까지는 수집이 그대로 되고 안내도 없습니다(그 구간은 정상). 스마트스토어 한정이던 주석·로그 문구(“앱시작 커머스API 점검” → “앱시작 마켓 연결 점검”)도 정리했습니다. 실기(2026-10-25, 이 PC): 수집 로그인 실패(ESM 2단계 인증 필요·카페24 토큰 거절) 뒤 노란 배너 2건과 알림센터 항목이 올라오고, 설정 칸 저장 뒤 재점검이 바로 도는 것을 확인했습니다. ESM 비밀번호 오류를 빨간 배너로: 같은 실기에서 틀린 비밀번호를 저장해도 배너가 끝까지 노랑(“추가 인증 필요”)이었습니다 — ESM PLUS 로그인 화면은 주소 이동 없이 “로그인에 실패했습니다. 아이디(ID)와 비밀번호를 확인하고 다시 로그인해 주세요.”를 띄우는데, 자격증명 실패 감지가 (가) NavigationCompleted에서만 돌아 다시 볼 기회가 없었고 (나) 구문 목록(‘비밀번호를 확인해’)과 오류 요소 선택자가 그 문구·요소를 놓쳤습니다. 이제 감지 스크립트에 ESM 실 문구(‘비밀번호를 확인하’)를 더하고, 오류 요소를 못 찾으면 보이는 본문에서 비밀번호를 가리키는 강한 문구(‘비밀번호를 확인하고 다시 로그인’ 등 — ‘로그인에 실패했습니다’ 같은 앞부분만의 문구는 서버 오류·잠금 안내와 겹쳐 넣지 않음)만 보는 폴백을 두었으며(MarketLoginConfig.DetectCredentialErrorScript), 자동 입력이 비밀번호를 제출한 뒤(filled-and-clicked·tab-switching) 1초 간격 최대 8회 같은 감지를 다시 돕니다(WebView2LoginWindow.자격증명실패감시Async — URL·체류 시간 가드 동일, 로그인 페이지를 벗어나면 중단, 조용한 실행의 15초 대기 안). 감지되면 조용한 수집은 자격증명 실패(빨강 “ESM 로그인에 실패했습니다. 아이디·비밀번호를 확인해 …”)로 끝나고 두 번 실패 멈춤 문구도 비밀번호 확인 안내가 됩니다. 창을 띄운 경로(앱 시작 점검·설정 재점검·[마켓 동기화])에서 오류 문구를 감지한 뒤 셀러가 창을 닫으면 종전 “취소”(노랑 “창이 닫혀 …”)가 아니라 자격증명 실패로 봅니다(WebView2LoginHost.SelectResult — 추가 인증도 함께 감지됐으면 종전처럼 취소). 실기(2026-10-25): 틀린 비밀번호 저장 뒤 시작 점검 창을 닫자 빨간 배너, 이어진 조용한 자동 수집은 4초 만에 문구를 감지해 자격증명 실패로 끝났고 배너에 반영됐습니다(감지 시그니처 비밀번호를 확인하|text text--red). 맞는 비밀번호로 되돌린 뒤 재점검은 2단계 인증 화면(시간 초과 승격)으로 넘어가 감지가 오탐하지 않았습니다.
  • 셀러센터 창 — 같은 마켓의 다른 판매처를 열면 앞 계정 화면이 열리던 문제 (#395 · 2026-10-22 실기, 쿠팡 2계정 — 1번으로 연 뒤 2번 칸을 누르면 1번 계정 윙이 그대로 열림) — 셀러센터 창은 창·WebView2 프로필을 하나만 두고 모든 판매처가 함께 써서, 판매처가 바뀌어도 쿠키를 그대로 썼습니다. 이제 셀러센터창.열기가 마켓별로 마지막에 연 계정 키(쿠팡·스마트스토어 = 판매처 일련번호, 카페24 = 몰 ID — 같은 몰의 다른 쇼핑몰은 관리자 로그인이 한 벌이라 전환하지 않음, 프로세스 메모리만)와 비교해(셀러센터계정전환판정) 다르면 빈 화면(about:blank, 상한 5초)으로 옮긴 뒤 그 마켓 쿠키를 지우고(WebView2호스팅공통.도메인쿠키삭제Async — 쿠팡 coupang.com, 스마트스토어 naver.com 전체, 카페24 cafe24.com; 접미 비교라 로젠 ilogen.com·ESM esmplus.com은 건드리지 않음) 목적지로 갑니다 — 마켓이 로그인 화면으로 보내면 기존 자동 입력이 그 판매처 정보로 로그인합니다. 기록이 없을 때(앱을 다시 켠 뒤 첫 열기)는 같은 마켓 판매처(카페24는 몰)가 2개 이상이거나 수를 모르면 지우고, 1개면 종전처럼 로그인을 유지합니다 — 대시보드 칸과 주문 화면 [⚠ 마켓 불일치] → 셀러센터 열기 두 경로 모두 같은 함수(셀러센터계정전환판정.같은마켓판매처수 — 비 ESM·같은 채널, 카페24는 몰 아이디 소문자 중복 제거)로 수를 세어 넘깁니다(주문 화면은 마켓 칩용 판매처 목록 캐시, 없으면 그 자리에서 읽고 못 읽으면 모름). 판매자센터가 다른 계정으로 로그인돼 있다고 확인된 경우(판매자센터세션상태.계정다름 → 마켓송장교체오류.셀러센터계정다름 → 마켓송장번호교체결과.셀러센터계정다름)만 열기(…, 강제전환: true)로 기록이 같거나 판매처가 1개여도 지웁니다(끄기 스위치가 우선). 빈 화면 이동이 5초 안에 끝나지 않거나, 빈 화면 이동·쿠키 삭제 중 예외가 나거나, 쿠키를 지우지 못하면 모두 같은 실패로 처리합니다 — 목적지로 가지 않고(fail-closed, 앞 화면이 남아 있을 수 있음) 그 마켓 기록을 지우고 실패 표시(다음 열기는 판매처 수와 무관하게 다시 지움)를 남기며, 창 위쪽 “계정을 바꾸지 못했어요 — 창을 닫고 다시 열어 주세요.”, 창 제목 “계정 전환 실패 · {화면 이름}”(전환 중에는 “계정 전환 중 · {화면 이름}” — 새 판매처 이름이 앞 계정 화면과 함께 보이지 않게). 기록 전이(성공 → 기록 = 요청 키·실패 표시 해제 / 실패 → 기록 제거·실패 표시 / 그사이 다른 칸 클릭 → 변경 없음)는 순수 함수 셀러센터계정전환판정.전환결과반영이 단일 출처입니다. 로그인 화면 처리기는 about: 주소를 건너뜁니다(자동 입력 성공 오기록·안내 덮어쓰기 방지). 대시보드 안내는 창이 쿠키를 지우기 전에 뜨므로 미래형 “앞 계정 로그인을 지우고 ○○ 계정으로 다시 로그인해요(저장된 정보가 있으면 자동 입력). 창 위쪽 안내를 확인해 주세요.”(저장 정보 있음/없음/읽지 못함 — 없음·읽지 못함은 “다시 로그인해야 해요 — 로그인 화면이 나오면 직접…”)로 나뉘고, 같은 마켓 판매처가 2개 이상이면 “화면 위 계정(업체명·스토어 이름)이 ○○인지 확인해 주세요”를 붙입니다(I셀러센터창열기.열기에 선택 인자 같은마켓판매처수·강제전환, 기본 구현 질의 계정전환예정). ESM은 종전 흐름 그대로입니다. 비상 끄기 스위치 HANARO_SELLERCENTER_ACCOUNT_SWITCH_DISABLED. 로그에는 마켓·판매처 번호·지운 쿠키 개수·예외 형식만 남깁니다. 실기(2026-10-23): 쿠팡 2계정에서 1번 → 2번 전환이 정상이었고 2단계 인증(OTP)은 뜨지 않았습니다. 🔴 실기 미확인: 스마트스토어 판매처 전환, 카페24에서 쿠키 삭제가 실제로 필요한지. 알려진 한계: 같은 프로필의 숨은 판매자센터 세션(스마트스토어판매자센터세션)이 요청하는 중이거나 앱 시작 자동 로그인이 같은 프로필에서 동시에 도는 중에 naver.com 쿠키를 지울 때의 영향은 확인하지 못했습니다(둘 사이 잠금 없음). 화면의 판매자ID를 읽어 대조하지 않으므로 셀러가 창 안에서 직접 다른 계정으로 로그인한 경우와 스마트스토어 한 네이버 아이디 다중 스토어(쿠키 교체로 스토어를 고를 수 없음)는 막지 못합니다(안내 문구로만 완화). 네이버 아이디로 로그인하는 스마트스토어 셀러는 자동 입력 대상이 아니라 전환할 때마다 직접 로그인해야 하고, 같은 프로필의 스마트스토어판매자센터세션은 전환 뒤 다음 요청에서 로그인 필요로 끝납니다(계정 대조가 있어 틀린 계정으로 쓰지 않음).
  • 카페24 — 조회 기간 앞에 주문된 건이 그 뒤에 입금·발송·취소돼도 하나로 상태가 옛 값으로 남던 문제 (#402 · #403, 노션 [0.4.3] 카페24 주문 상태가 하나로에 반영되지 않음 — 2026-10-22 사업2팀 PC 로그: 카페24 수집 5회 모두 성공·토큰 갱신 성공·오류 0인데 “배송 중” 주문 상태가 바뀌지 않음) — 카페24 수집은 date_type=order_date(주문일) 창 + 상태 코드 필터로만 물어, 조회 기간(앱 시작 92일 · [마켓 동기화]는 주문 화면의 조회 기간, 기본 최근 29일) 앞에 주문된 건의 상태 변화(입금전 N00 → 배송중 N30 등)를 다시 묻지 않았습니다. 기간을 어떻게 잡아도 “기간 앞 주문의 변화”는 날짜 조회로 잡을 수 없으므로(#402의 날짜 기준 7개 대조는 변화가 기간보다 전이거나 완료 날짜만 기간 안이면 놓쳤고 결과가 없어도 최소 14회를 불렀습니다 — #403에서 걷어냄), 하나로가 가진 아직 끝나지 않은 주문을 주문번호로 직접 다시 묻습니다(새 선언 I미완료주문재확인 — 지금은 카페24만). 수집기(주문수집실행기)가 수집 뒤 그 판매처의 저장 주문 중 어댑터가 선언한 상태·주문일 범위(Cafe24Adapter.미완료재확인.cs — 신규주문·발주확인·배송준비중·배송중은 180일, 배송완료는 45일: N40은 끝없이 쌓여 길게 잡으면 매 수집 호출이 불어남)에 든 것을 읽어(저장소 선택 능력 I재확인주문조회 — EF·InMemory가 판매처를 DB에서 걸러 (번호, 순번, 상태, 일자)만 투영, 숨김·비활성 판매처·주문일 없는 주문 제외; 없으면 종전 Select주문Async; 이번 수집분 제외; 주문일·번호 순으로 최대 1,000건 — 넘으면 판매처별 메모리 커서(재확인대상고르기)로 다음 수집에 이어서 돌아가며 읽고 “저장된 주문 N건 중 M건만 …” 안내), 어댑터가 order_id를 100개씩 묶어(수령자재조회청크, 호출 수 = 대상 ÷ 100 — 사업2팀 로그 기준 배송중 44건이면 1회) embed=items만 붙여 품주별 지금 상태를 읽고(수령자·주문자 개인정보 없음, 상태 해석은 수집과 같은 ParseOrdersResponse), 상태가 바뀐 주문만 Update주문상태들Async로 덮습니다(알수없음은 덮지 않음, 응답에 없는 주문·대상이 아닌 같은 주문의 다른 품주는 그대로, 신규 생성 없음). 실패는 셋으로 가릅니다 — 인증 실패(토큰 없음·갱신 실패 Cafe24인증오류, 401·403)는 첫 묶음에서 바로 던져 남은 묶음을 묻지 않고(수집 결과 “카페24 — 저장된 주문의 상태를 다시 확인하지 못했습니다”), 그 밖(422·네트워크)은 그 묶음만 포기하고 계속하되 하나라도 포기했으면 I수집경고보고(카페24 어댑터가 새로 구현)로 셀러에게 한 줄(“저장된 주문 최대 N건의 지금 상태를 다시 읽지 못해 …”), 모든 묶음이 실패하면 던집니다. 주문번호 조회·수령자 재조회·재확인은 같은 묶음 조회(주문번호묶음조회Async — limit 명시, 실패 HttpRequestException에 HTTP 상태 코드)를 쓰고, 종전에 번호를 전부 한 요청에 싣던 주문조회By주문번호순번Async도 100개씩 끊습니다. 스마트스토어 I신규주문재확인(신규주문만·신규가 아니게 된 것만)은 그대로입니다. 로그 카페24 저장 주문 재확인 — 판매처=… 대상 N건 · 묶음 N개(실패 N개) · 받음 N건과 저장된 주문 상태 재확인 — 카페24 대상 N건 · 받음 N건 · 상태 바뀜 N건 · 갱신 N건으로 적용을 봅니다(새 줄 2개에는 주문번호·개인정보 없음 — 저장소의 종전 상태 변경 로그는 바뀐 건마다 주문번호를 남기므로 재확인으로 한 회차에 늘 수 있습니다). 🔴 실계정 미확인: order_id 100개 묶음이 받아들여지는지(수령자 재조회와 같은 보수값), 취소된 주문이 주문번호 조회에 나오는지. 알려진 한계·후속: ① 주문일이 180일(배송완료는 45일)보다 오래된 미완료 주문은 다시 묻지 않습니다. 이어 읽기 커서는 프로세스 메모리라 앱을 다시 켜면 처음부터입니다. ② 재확인으로 클레임 상태가 된 주문은 수집 Upsert가 세는 “송장 발급 뒤 클레임” ⚠ 집계(송장후클레임전환)에 들어가지 않습니다 — 11번가·스마트스토어 대조와 같은 공백, 후속.
  • 마켓 계정 카드 한 장의 키를 읽지 못하면 그 카드부터 뒤 카드가 목록에서 빠지던 문제 (노션 [0.4.3] 셀러센터 로그인 정보 저장 여부 — 설계 중 발견) — 설정ViewModel.마켓계정새로고침Async가 카드별 자격증명 상태 판정·ESM 로그인 방식 읽기에서 예외(DPAPI 복호화 실패 등)가 나면 바깥 catch로 빠져 그 카드부터 뒤 카드가 목록에 들어가지 않고 OnAccountsChanged도 건너뛰었습니다(첫 카드면 목록 전체가 빔). 이제 카드마다 감싸 실패한 카드만 “미확인”으로 두고 나머지는 그대로 그립니다(취소는 삼키지 않음).
  • 카페24 배송완료·구매확정 주문의 송장 교체를 막습니다 (#328) — [⚠ 마켓 불일치] → [우리 번호로 전송]이 배송완료(N40)·구매확정(N50) 주문에도 배송 수정 PUT을 보낼 수 있었습니다(사용자 결정 2026-10-13 “배송완료 주문은 교체 대상 아님”을 코드가 강제하지 않음). 이제 Cafe24Adapter.교체전검사가 호출 없이 “배송완료된 카페24 주문은 송장번호 교체 대상이 아니라 보내지 않았습니다…”로 끝냅니다. 배송중(N30)은 실계정 확인 경로라 그대로입니다.
  • 카페24 배송준비중 올리기가 권한 부족이면 [재인증]을 안내합니다 (#345) — 올리기 PUT(1차 또는 400·422 뒤 주문 전체 2차)의 마지막 응답이 403 insufficient_scope(옛 권한 토큰)면 셀러 문구 끝 조치를 “카페24 관리자에서 배송준비중으로 바꾼 뒤…” 대신 권한추가재인증안내(“…설정 → 마켓 계정 → [재인증]으로 다시 연결해 주세요.”)로 바꿉니다. 상태 다시 읽기까지 실패한 문구에도 같은 조치를 씁니다. 판정은 쇼핑몰 목록과 같은 권한부족안내이고, 본문 해석을 검증실패사유(string? body)로 떼어 두 곳이 같은 규칙을 씁니다. 403이라도 insufficient_scope가 아니면(다른 message·빈 본문·JSON 아님) 종전 문구이며, 1차 403이면 다시 보내지 않습니다(PUT 1회). 새 로그 줄은 없습니다.
  • 문서 그림 캡션 표의 손으로 넣은 줄이 촬영 스크립트 실행 때 지워지던 문제 (#341) — 촬영목록.직접캡처()(카페24 개발자센터 2장 + 표에 없던 11번가 2장)를 표에 보존하고, 그림 파일이 없으면 경고합니다.

내부 (화면 변화 없음)

  • HANARO_E2E_STATE_FOLDER (#329) — 업데이트 E2E용 상태 폴더 override(시험상태폴더 단일 출처). 비어 있지 않은 절대 경로일 때만 적용하고 경로는 로그·Sentry에 남기지 않습니다. 덮는 대상은 게이트 적용 시도 기록(update-gate-attempt.json)·셸 아이콘 갱신 표식(shell-icon-refreshed.txt)·앱 로그(logs\hanaro-.log) 3종뿐이며 DB·courier-prefs·notices·설치 표식·테마·WebView2는 덮지 않습니다. 실제 Velopack E2E로는 미확인입니다.
  • 카페24 “관리자에서 송장을 지웠는데 하나로는 이미 등록” 정리 설계안(claudedocs/design/카페24-지운-송장-정리_설계안_2026-10-15.md, #328) — 결정 대기, 코드 변경 없음.

[0.4.2] — 2026-10-21

0.4.1 후속 묶음입니다. 주문 표 키보드 이동(화면 밖 행까지)과 승인함 “이미 답변됨” 표시를 더했고, 쿠팡 송장 교체([⚠ 마켓 불일치] → [우리 번호로 전송], #298) 리뷰 후속으로 안내 문구와 화면 상태를 실제 동작에 맞췄습니다. 주문 화면의 작업 중 조회 보류 범위를 넓히고, 지원봇 외부 전송을 “개인정보 치환 → 길이 자르기” 순서로 바로잡았으며, 개발기 실행은 설치 통계에 등록하지 않습니다. [주문 직접 등록]에 주문별 보내는 분 칸을 더했습니다. 2026-10-20 회의 피드백(①~⑧)을 반영했습니다 — 상품번호 링크 G마켓·옥션·카페24, 직접 등록 주문 복사, 송장 미등록 줄 색, [택배 자동접수] 진행 칸·단계 로그, 쿠팡 수집 세부 진행·소요 로그, 우편번호 “(선택)”. 접수 속도는 바꾸지 않았고(측정 로그만), 쿠팡 수집은 실측 뒤 단축했습니다(아래 “쿠팡 수집 단축”). DB 마이그레이션은 증분 1개(V042_DirectOrderSender — 주문에 보내는 분 이름·전화 열 추가, 기존 행은 비어 있음 = 설정 → 택배사 따름)입니다.

⚠️ 셀로(Sello) 등 다른 프로그램과 하나로를 같은 주문에 함께 쓰면 송장번호가 어긋날 수 있습니다 — 한 주문의 송장 등록은 한쪽에서만 하세요.

Added

  • 주문 표 키보드 이동 (#323) — 방향키 ↑↓·PageUp/PageDown·Ctrl+Home/End·행 경계 Tab/Shift+Tab으로 가상화된 화면 밖 행까지 이동하고 스크롤이 따라갑니다(Views/주문표키보드이동 순수 판정 + 송장관리View Tunnel 핸들러). Ctrl 없는 Home/End·행 안의 칸 이동·맨 위 행 Shift+Tab은 기본 동작에 맡깁니다. 헤드리스 테스트만 — 실제 화면 체감·스크린리더 포커스 표시는 미확인.
  • 승인함 “이미 답변됨” 표시 (#323 · #342) — 이전 회차 답변이 이미 마켓에 나간 대기 초안에 이미 답변됨 배지(pill.warn, Saffron.Soft 토큰)와 상세 배너를 달고 [승인하고 등록]·[수정 승인]을 막습니다(승인함ViewModel.승인가능). 정리는 기존 [거절]로(새 경로 없음). 0.4.1 문의 단위 중복 방어(#297)의 화면 후속이며 실제 이중 등록 차단은 종전대로 초안승인유스케이스가 합니다. 이미답변됨표시Async·이전회차로드Async는 “문의응대·문의” 고정이 아니라 카드의 직원·대상 종류로 조회합니다(#342 — 문의응대는 종전과 같은 값). 배지·배너 문구는 승인함표시규칙 상수를 x:Static으로 씁니다.
  • 셀러가 넣는 전화번호를 하이픈 표기로 저장 — Domain 전화번호표기.하이픈넣기 단일 출처(02 9·10자리, 0XX 10·11자리, 050X·0303 11·12자리, 15/16/18XX 8자리; 02로 시작하는 다른 길이·ASCII 숫자·하이픈·공백·괄호·점 외 글자·다른 길이는 그대로). 직접 등록 입력 정리(직접주문입력검증.정리 — 받는 분·주문자·보내는 분 전화), [수령자 정보 편집]에서 고친 받는 분 전화(마켓 주문 포함 — 마켓 주문 전화는 이미 하이픈 표기, 2026-10-20 운영 DB 전건 확인), 설정 → 택배사 보내는 사람 전화에 쓴다. 마켓이 보낸 값에는 쓰지 않는다. 송장 뒤 잠금 비교(잠긴칸바뀜)와 주문자 전화 따라감 판정은 전화번호표기.같은번호(숫자 비교)라 0.4.2 전 하이픈 없이 저장된 주문도 거부되지 않는다. 입력 칸에는 거꾸로 전화번호표기.입력칸표시로 하이픈을 뗀 숫자만 보인다(설정 → 택배사 칸, 직접 등록 창 세 칸·수정으로 열 때·보내는 분 안내 글씨, [수령자 정보 편집] 받는 분 전화 — 마켓 주문 포함, 사용자 결정 2026-10-20). 내선·+82처럼 다른 글자가 섞인 값은 그대로. 손대지 않은 칸은 [수령자 정보 편집]이 보내지 않으므로(바뀐 칸만) 마켓 주문 전화가 숫자로 덮이지 않는다. 안내 글씨는 하이픈 없이(01012345678).
  • “택배사 기본값” 문구 — 보내는 사람을 비웠을 때의 안내를 “로젠 기본값”에서 “택배사(에 등록된) 기본값”으로(설정 → 택배사 안내·저장 문구, 직접 등록 창 안내 글씨 — 설정을 읽었는데 칸이 비면 “비우면 택배사 기본값”, 못 읽으면 종전 “비우면 설정 → 택배사의 보내는 사람”). 로젠 외 택배사를 붙일 때를 대비.
  • 직접 등록 주문자 전화를 비우면 받는 분 전화 — 주문자명과 같은 규칙입니다. 저장 때 받는 분 전화로 채우고(직접주문행.채우기, 송장 뒤 수정 허용칸적용), 수정 창은 받는 분 전화와 숫자가 같으면 빈 칸으로 보이며(직접주문송장후수정.주문자전화미입력 — 하이픈 무시), [수령자 정보 편집]으로 받는 분 전화를 바꾸면 그런 주문자 전화도 따라 바뀝니다(EF·InMemory). 기존 주문의 빈 주문자 전화는 다음 수정·저장 때부터 채워집니다. AI 직원 성과 판정(동일주문자전화-7일)은 (판매처, 구매자키)로 맞추는데 직접 등록 판매처에는 AI 답변이 없어 직접 등록 주문은 전부터 귀속되지 않으므로 영향이 없습니다.
  • 직접 등록 주문의 보내는 분(이름·전화) — [주문 직접 등록] 창 주문자 칸 아래에 선택 칸 2개를 두고 주문.보내는분명·보내는분전화(orders.sender_name 128자·sender_phone 32자, NULL 허용·백필·인덱스 없음)에 품목 줄마다 같은 값으로 저장합니다. 비우면 null = 설정 → 택배사의 보내는 사람을 따릅니다(설정 값을 복사하지 않아 설정을 바꾸면 따라감). 전화는 받는 분과 같은 형식 검사(숫자 9~12자리), 값은 오류 문구·로그에 싣지 않습니다.
    • 로젠 접수 엑셀 H·I열(Build택배사발송행들 — [택배 자동접수]·[택배 접수용 엑셀] 공통): 직접 등록 상자는 칸마다 주문 값 → 없으면 설정 값(로젠보내는사람.이름구하기·전화구하기 단일 출처). 다른 마켓 상자는 종전과 같습니다(주문 값을 보지 않음).
    • 라벨(Build라벨모델들): 직접 등록 상자의 보내는 분 이름 = 주문 값 → 설정 이름 → 빈칸, 전화는 주문에 넣은 값만(설정 전화로 채우지 않음 — 사용자 결정). 설정은 이름을 넣지 않은 직접 등록 주문이 있을 때만 읽고, 못 읽어도 주문에 넣은 값은 인쇄합니다. 다른 마켓 라벨은 종전처럼 판매처 이름·전화 빈칸.
    • 송장번호가 붙은 뒤에는 잠긴 칸입니다(직접주문송장후수정.잠긴칸바뀜 — 공백 차이는 같은 값, 바뀌면 입력 전체 거부). 창의 워터마크에 설정 → 택배사 값을 보여 줍니다(표시만, 못 읽으면 기본 문구).
    • 마켓 수집(Upsert)은 이 열을 쓰지 않습니다(주문원본에 필드 없음, 기존 행 갱신이 필드별 대입) — EF·InMemory 패리티 테스트로 고정.
  • 주문 표 상품번호·주문자명 칸 + 상품 판매 페이지 링크 (#353, 바이앤드셀 10/19 피드백) — 16열(상품번호 = 상품주문번호 뒤, 주문자명 = 상태 뒤). 값은 이미 전 마켓에서 수집·저장 중이라 화면만 추가했고 [엑셀 저장]·행 복사 형식은 그대로입니다. 상품번호 링크는 쿠팡(www.coupang.com/vp/products/{번호} — 2026-10-20 사용자 실주문 확인)·11번가이고, 주소는 상품페이지주소규칙(https·정확한 호스트·숫자 1~20자리)으로 만들 때와 열기 직전 두 번 검사해 셸열기로 엽니다(같은 주소 1.5초 안 재클릭 무시, 로그에 번호·주소 없음). 열 너비 저장은 열 이름 키 v2로 바꾸고 옛 14개 배열은 열 이름으로 옮겨 기존 너비를 지킵니다(읽기만으로는 파일을 쓰지 않음).
  • 상품번호 링크 G마켓·옥션·카페24 확장 (10/20 회의 피드백 ②) — 상품페이지주소규칙에 입력 레코드 상품페이지주소입력(사이트 코드·판매사이트·상품번호·직접등록·판매처아이디·쇼핑몰번호)과 마켓별 형식표. ESM은 주문.판매사이트로 G마켓 item.gmarket.co.kr/Item?goodscode={goodsNo}(숫자) / 옥션 itempage3.auction.co.kr/DetailView.aspx?itemno={goodsNo}(영문·숫자), 카페24는 {몰ID}.cafe24.com/product/detail.html?product_no={product_no}(몰 ID = 판매처.아이디, 카페24앱설정.몰아이디형식인가 통과 라벨 하나, 1번 쇼핑몰만). 허용 검사는 https·기본 포트·UserInfo/조각/% 없음·호스트 정확 일치·경로 규칙·쿼리 “키=값 한 쌍”(&·;·두 번째 = 거절). 스위치 ESM링크사용·카페24링크사용(internal static)은 2026-10-20 운영 DB 사본의 실주문 번호로 G마켓·옥션·카페24 상품 페이지가 열리고 페이지 제목이 저장된 상품명과 같음을 확인한 뒤 켰습니다(_workspace/02b_product_link_evidence.md). 판매처 아이디는 카페24 행에서만 행 VM에 싣고 로그·툴팁에 쓰지 않습니다. 스마트스토어는 스토어 경로명(market_channels.store_path)이 비어 있어 미제공(예정). 미확인: 독자 도메인만 쓰는 카페24 몰에서 기본 도메인이 열리는지, 2번 이상 쇼핑몰(링크 없음).
  • 직접 등록 주문 [이 주문 복사해 새로 등록…] (10/20 회의 피드백 ④) — 직접 등록 행 우클릭 메뉴. I직접주문서비스.불러오기Async → 복사번호제안Async(Domain 직접주문번호.복사번호: 끝 숫자 +1·자리 유지(001→002, 999→1000), 숫자 없으면 -2·-3…, 50자 초과·금지 조각(-복사본/-분할/-부분수량취소)이면 null; DB에 있는 번호는 I직접주문Repository.Select있는번호들Async(후보 50개 정확 일치, Insert 중복 검사와 같은 범위·비교 — EF·InMemory 패리티)로 건너뜀) → 직접주문DialogViewModel.Initialize복사(복사 모드: 받는 분·보내는 분·상품 줄·금액·배송메모·주문자 채움, 주문일 오늘(지금 시계), 발송기한 비움, 수정모드·송장잠김 해제) → 저장은 기존 등록Async(번호 중복이면 창 안 안내). 송장·접수 기록·상태는 입력 레코드에 칸이 없어 구조상 복사되지 않습니다(테스트가 원본 배송중·송장 있음 / 복사본 신규주문·송장 없음을 DB로 단언). 데이터 안전 감사 🔴 0(스키마 변경 없음).
  • 주문 표 송장 미등록 줄 색 (10/20 회의 피드백 ⑧) — Domain 처리큐판정.송장미등록(상태, 송장번호)(기존 송장미등록여부가 위임, 대시보드와 같은 식) + 행 VM 계산 속성 송장행Vm.송장미등록표시(방문수령 행만 제외 — 대시보드 숫자·딥링크 필터는 방문수령을 그대로 세므로 N건으로 들어오면 칠해진 줄이 N보다 적을 수 있음) + Classes.invoice-missing + 토큰 Hanaro.Row.InvoiceMissing(Dark #262012 / Light #f8efd9, hover 스타일이 이김). 가상화 행 재활용에 상태를 두지 않는 계산 속성. Light/Dark PNG 캡처는 하지 않았습니다.
  • [택배 자동접수] 진행 칸·경과 시간 + 단계별 소요 로그 (10/20 회의 피드백 ⑦) — 표시 전용 택배접수진행단계(로그인·접수목록확인·엑셀첨부·서버전송·접수확인·출력·끝)와 택배접수진행표(이PC출력 5칸·접수만 4칸)를 UI에 두고(접수 기록 확정·되돌림 판정용 택배접수단계와 분리), 택배접수요청.단계알림(init IProgress)으로 로젠자동화가 보고(예외 삼킴). VM partial 송장관리ViewModel.택배진행이 칸 VM·1초 DispatcherTimer(UI 스레드에서만, 이번 실행에 묶인 IProgress라 늦은 보고 무시)를 갖고 택배자동접수가 try/finally로 항상 끕니다. Information 로그(단계명·ms·건수만): 로젠 자동접수 단계 소요(창 준비·접수일자·전목록·첨부·서버전송 버튼/대기·접수확인·출력·출력후목록, 못 간 단계 -1, 예외·취소에도), 택배사 작업 창 소요(작업 모드), 보관 창 이어 쓰기 재개·상태읽기 ms. 고정 대기 8곳(_workspace/01_architect_plan.md ⑦(c))은 모두 그대로 — 서버전송 결과 폴링을 1초 → 0.5초로 줄였다가 리뷰(🟡-1)로 되돌렸습니다: 그 루프는 읽기 전용이 아니라 확인 창이 떠 있으면 회차마다 확인창닫기Async가 버튼을 실제로 누르므로, 간격을 줄이면 늦게 닫히는 창(partial-send 포함)을 두 번 누를 수 있습니다. 실기로 창이 닫히는 시간을 잰 뒤 바꿉니다. 이번 릴리즈에서 접수 속도 자체는 바뀌지 않았고 측정 로그만 들어갔습니다. 다른 로젠 명령([받은 파일로 송장 출력]·[송장번호 불러오기])은 진행 칸 없음.
  • 쿠팡 수집 세부 진행·소요 로그 (10/20 회의 피드백 ⑤) — CoupangAdapter가 I조회진행보고를 구현(CoupangAdapter.조회진행 partial): 묶음 = 조회 창 × 상태(클레임 스냅샷 묶음도 같은 카테고리 칸 앞부분), 쪽마다 보고, 비율 = (앞선 묶음 + 지금 묶음 − 1 + 0.5) / 전체 묶음. 마켓조회진행에 init 속성 대상·쪽(묶음 번호·수는 10/21 상태 줄 개편 때 화면에서 빼고 속성도 지움 — 비율 계산에만 씀). 주문수집실행기.기간조회문구가 “쿠팡 하나상회 · 발송 전 주문 받는 중 · 4쪽째”(대상이 있을 때만, 총 쪽 수는 nextToken 방식이라 모르므로 표시하지 않음). 진행률은 판매처 몫을 넘지 않고 비감소(테스트). Information 로그: 쿠팡 조회 소요·쿠팡 클레임 스냅샷 소요·쿠팡 호출 한도(429) 재시도 {회차}회 대기 {ms}ms(종전 없음)·수집 카테고리 소요(vendorId·주문번호 없음). 쿠팡 어댑터 로거 주입(MarketAdapterFactory 1줄) — 문의 답변 경로 로거 금지 가드는 “수집 소요·호출 한도 파일에만” 가드로 바꿈. 단축은 같은 날 실측 뒤 아래 “쿠팡 수집 단축”으로 넣었습니다.
  • 쿠팡 수집 단축 (10/20 회의 피드백 ⑤ 후속, 같은 날 실측) — 운영 DB 사본(쿠팡 판매처 2곳만 활성, 92일)에서 실제 수집 실행기를 돌려 요청마다 잰 결과: 판매처당 51회 호출(클레임 목록 36 + 발송 전 9 + 배송 중 6+쪽)에 14~26초, 호출 1건 지연 중간값 150ms·배송완료 목록 쪽당 1초 안팎·즉시취소 목록 0.6초, 호출 간격 250ms(초당 4회)에 묶여 호출 수 × 간격이 바닥이었습니다. 쿠팡 개발자센터 공지(“초당 5회 이상 호출하는 vendorId 차단”, 기준 변경 가능)라 간격은 그대로 두고 셋을 바꿨습니다.
    • 창 겹쳐 받기(CoupangAdapter.병렬조회 partial 순서대로병렬Async, 동시요청수 3) — ordersheets 기간 창(31일)끼리, 클레임 스냅샷의 반품 창·교환 창끼리 최대 3개 겹쳐 띄우되 한 창 안의 상태(ACCEPT → INSTRUCT → …, 반품 RU → UC → PR → CC → 즉시취소)는 종전처럼 차례로 받습니다 — 리뷰 C 🔴-1: 같은 창의 상태를 겹치면 앞 상태 2쪽보다 뒤 상태 1쪽이 먼저 나가 그 사이 넘어간 주문·출고중지요청이 두 목록 모두에서 빠질 수 있었습니다(창은 주문일·접수일 구간이라 창 사이로는 옮기지 않음). 결과는 입력 순서대로 흘립니다. 호출 간격 조절기는 호출 시작만 띄우므로 겹치는 것은 응답 대기뿐이고(테스트: 시계를 멈추면 n번째 호출이 (n−1)×250ms 뒤에 예약됨), 중복 거르기(본것)·클레임 후보 선택·경고 건수는 순차 조회와 같습니다(테스트: 겹침 결과 = 순차 결과, 앞 상태 마지막 쪽 뒤에 다음 상태). 창 하나가 실패하면 나머지를 취소하고 그 예외를 던져 카테고리 실패(fail-closed)가 그대로입니다. 429를 받으면 그 vendorId의 다음 차례를 재시도 대기만큼 미뤄(쿠팡호출간격.뒤로미루기) 겹쳐 띄운 다른 요청도 쉽니다. HttpClient 시간 초과는 Canceled 작업이지만 사용자 취소(시작 토큰)가 아니면 오류로 기억해 같은 회차에서 다시 받지 않습니다. 진행 보고는 어댑터에서 잠금으로 직렬화하고, 사전 조회가 받는 중인 스냅샷도 판매처 차례가 기다리는 동안 묶음 진행이 보입니다.
    • 클레임 목록 사전 조회 — Contracts I수집사전준비(어댑터) + IMarketAdapterFactory.수집사전준비지원(기본 false, 쿠팡만 true). 주문수집실행기가 판매처 루프 전에 지원 판매처 어댑터를 만들어 사전준비시작(클레임 스냅샷 작업 시작)하고, 차례가 오면 같은 인스턴스로 로그인·조회(어댑터준비Async), 차례가 오지 않은 어댑터는 await using 묶음이 정리합니다. 판매처(vendorId)마다 한도가 따로라 두 판매처의 목록이 겹쳐 받아집니다. 스냅샷 캐시는 결과 대신 작업(Task)(_클레임스냅샷작업)이라 사전 조회와 차례 조회가 같은 작업을 기다리고(두 번 받지 않음, 실패도 같은 오류를 다시 던짐), 취소로 끝난 작업만 버립니다. 미리 만들기·시작에 실패하면 그 판매처는 종전 경로(CreateWith로그인Async)로 갑니다. 비쿠팡 판매처는 종전 그대로.
    • 반품 창 30 → 31일(반품요청창일수) — 실계정 2곳에서 간격 31은 200·32는 400을 확인(종전 30은 추정). 92일이면 반품 창 4 → 3, 요청 5회 감소.
    • 실측(새 코드, 같은 사본·92일): 상태까지 겹친 1차 코드로 쿠팡 전체 40.4초 → 18.8·16.7초, 창끼리만 겹치는 최종 코드로 19.3초·17.1초(2회). 판매처별로는 164건 판매처 26초 → 7.1·5.4초, 3건 판매처 14.4초 → 12.0·11.7초(46회 호출 × 250ms 바닥). 429 0회, 저장 결과 동일(167건). 수동 [마켓 동기화]는 화면 기간을 쓰므로 수치가 다릅니다.
    • 하지 않은 것: status 없이 반품 목록 한 번에 받기(실계정 400 “OrderId can’t be null, if doesn’t pass the parameter status” — 문서도 orderId 필수), 간격 200ms(공지의 차단 기준 “초당 5회”), 판매처 전체 병렬(SQLite 단일 쓰기·진행률 의미 — 별도 카드), 조회 기간 축소(완전 수집·sweep 판정이 깨짐). 🔴 공지는 한도 기준이 “시스템·vendorId에 따라 사전고지 없이 바뀔 수 있다”고 하므로 현장에서 쿠팡 호출 한도(429) 재시도 로그가 늘면 동시요청수를 1로 되돌릴 수 있게 상수로 두었습니다(환경변수 스위치는 없음).
  • 수집 상태 줄 — 어느 판매처에서 무엇을 받는지와 몇 % (2026-10-21 사용자 지시 — “취소 주문 …”만 보이고 어느 마켓·몇 %인지 안 보임) — 주문 화면 상태 줄과 전역 스트립의 진행 문구를 {퍼센트} · {마켓 판매처이름} · {지금 받는 것} 받는 중[ · N쪽째][ · 날짜까지] (판매처 i/n)로 바꿨습니다. 예: “37% · 쿠팡 하나상회 · 배송 중·완료 주문 받는 중 (판매처 2/6)”. 송장관리ViewModel.수집진행문구가 %를 맨 앞에 붙이고(종전 끝 괄호 — 문구 길이가 달라 숫자 자리가 흔들렸음) [과거 주문 받기] 문구(과거주문문구.진행)도 같은 자리로 맞췄습니다.
    • 표시 이름은 주문수집실행기.마켓표시이름 — 마켓 이름 + 셀러가 붙인 판매처 이름, 임시 이름(판매처이름정책.Is임시이름 — “쿠팡”·”쿠팡 2”)이면 마켓 이름만, 이름이 마켓 이름으로 시작하면(“쿠팡 본점”) 그대로. 주문수집진행상황.판매처이름도 이 값이라 과거 주문 문구에도 같이 보입니다. 판매처 순서 꼬리는 둘 이상일 때만.
    • 카테고리 시작 문구가 “{마켓} — 발송 전 조회…”에서 “{표시 이름} · 발송 전 주문 받는 중”으로(카테고리들 표에 대상 열 추가 — 발송 전 주문·배송 중·완료 주문·취소 주문·반품 주문·교환 주문). 판매처 공용 스캔(11번가·ESM — 첫 카테고리에서 전부 받음)이 대상 없이 기간조회를 보고하면 카테고리 이름이 거짓이라 “주문 받는 중 · 날짜까지”로 보입니다. 쿠팡 세부 문구의 “2/3”(묶음 번호)은 뺐습니다 — 진행률이 묶음마다 나아가 숫자가 겹쳤고, 쪽째만 남겼습니다. 상태 대조 문구는 “주문 상태 확인 중”.
    • 진행률을 판매처별 지난 소요 시간에 비례해 나눕니다 — 종전에는 판매처 × 카테고리 칸을 같은 크기로 세어 스마트스토어(0.1초)와 쿠팡(12초)이 같은 1/6이라 한 판매처에서 오래 멈췄다가 다음에서 훌쩍 뛰었습니다(10/21 실측 6곳 40.9초). 새 판매처수집소요기록(Application, 메모리 싱글턴)이 평소 수집(자동·수동)의 판매처별 소요를 남기고, 다음 평소 수집의 진행률계산이 판매처 몫을 그 누적 가중치로 나눕니다(기록 없는 판매처는 아는 것의 평균, 하한 0.5초, 비감소·100% 고정은 테스트). 앱을 켠 뒤 첫 수집과 과거 주문 받기는 종전처럼 같은 크기(소급은 기록하지도 쓰지도 않음), 취소로 중간에 빠진 판매처는 기록하지 않습니다. 호출 수를 미리 아는 마켓이 없어(쿠팡도 쪽 수는 모름, ESM은 로그인 대기) 시간 기반이 가장 정직한 근사입니다. 표시 전용 — 결과·저장·sweep·완전 수집 판정을 바꾸지 않습니다. 알려진 한계(리뷰 🟢-5): 자동 수집(92일)과 수동 마켓 동기화가 같은 기록을 덮어쓰고, 셀러가 직접 처리한 로그인(보안문자 등) 시간도 들어가며, 쿠팡 사전 조회가 앞 판매처와 겹쳐 받은 시간은 빠진다 — 그 회차에서 한 판매처 몫이 크거나 작게 잡혀도 다음 회차가 다시 덮습니다.
    • 판매처 루프 시작 때 “{표시 이름} · 연결 중 (판매처 i/n)”을 먼저 보고합니다(리뷰 🟡-1 — 종전에는 ESM 로그인 대기 동안 앞 판매처 문구가 남았음). 실패 문구(“… 주문을 받는 중 문제가 생겼습니다”)도 화면에는 표시 이름·순서 꼬리를 쓰고, 결과 문구·로그는 종전처럼 마켓 이름만입니다(🟡-2).
  • “마켓 연결 확인 필요” 배너가 동기화 성공 뒤에도 남던 문제 (2026-10-21 실기 — ESM 로그인 창을 닫아 시작 점검 실패 1건 → 설정에서 비밀번호를 고쳐 동기화 3회 성공 → 배너 그대로) — 원인 둘. ① UIServiceCollectionExtensions의 설정ViewModel 생성에 연결점검:(I앱시작자동연동서비스) 인자가 빠져 “계정 저장·삭제 뒤 연결 재점검”(2026-10-02 수정)이 운영에서 한 번도 돌지 않았다 — 인자를 넣고 InMemory저장소부트스트랩Tests가 DI로 만든 설정ViewModel.연결재점검가능을 단언(인자 목록이 길어 빠져도 컴파일이 통과하므로). ② 배너는 앱 시작 점검 결과만 봤다 — I앱시작자동연동서비스.전체연결확인됨()을 더해 자동·수동 동기화가 실패 없이 끝나면(MainWindowViewModel.On수집상태변경 완료 전이 + 데이터변경있음 — 수동 취소·중복 실행 스킵은 완료로 끝나지만 판매처를 받지 않아 제외 — + 일부실패·실패 아님, 과거 주문 받기 제외) 실패였던 판매처를 실패 종류와 무관하게 “자동 연동 완료”로 바꾸고 결과변경됨을 올려 상단 배너와 대시보드 경고가 함께 내려간다(바뀐 것이 없으면 이벤트 없음). 결과 대입은 잠금 안(설정 재점검이 배경에서 대입하는 것과 겹치지 않게). 로그인 창에서 직접 로그인한 경우도 다음 동기화 성공으로 사라진다. 일부 실패 수집은 어느 판매처가 연결됐는지 가를 수 없어 건드리지 않는다. 🔴 실기 확인 항목: ①로 재점검이 처음 실제로 돌게 되면서 어느 마켓 계정이든 저장·삭제·되살리기·카페24 쇼핑몰 추가 뒤 스마트스토어·ESM 전체를 다시 점검한다 — ESM 세션이 만료돼 있으면 그때 로그인 창이 뜰 수 있고, 시작 점검이 아직 도는 중이면 “연결 확인이 이미 진행 중입니다”가 잠시 보인 뒤 덮인다.
  • 직접 등록 우편번호 “(선택)” 표기 (10/20 회의 피드백 ①) — 칸 이름·워터마크·안내 문구만. 검증(비우면 통과, 넣으면 숫자 5자리)은 그대로.
  • [택배 자동접수] 중복 클릭 가드 테스트 (10/20 회의 피드백 ⑥) — 코드 변경 없음. 실행 중 재클릭은 명령이 받지 않음(AllowConcurrentExecutions=false, 로젠 접수 1회) · 다른 로젠 작업 중이면 “이미 진행 중” 안내(택배사작업잠금)를 송장관리Vm_택배접수중복클릭Tests로 고정.
  • 전체 리디자인 — 안 B 먹빛 크롬 + 대시보드 매출 추세 띠 S3 (#359, 10/20 회의 피드백 ⑧ “한지·주황 톤 탈피”) — 토큰 단일 출처는 _workspace/design/variants/variants.py(gitignored)이고 Styles/Tokens.axaml은 gen.py apply B로 생성한다(직접 편집 금지). 디자인 언어: 베이지 제거, 반경 6/8/12, 알약·칩 한 겹(보더 0), ghost 버튼 Elevated 면, 사이드바 전용 토큰(Fg.OnSidebar.*·Bg.SidebarActive 등 신설 8개 — Row.InvoiceMissing은 기존 토큰 값 변경), 메뉴 글리프 → 선 아이콘(Styles/Icons.axaml + 글리프아이콘Converter), 올빼미 마크 펼침에도 표시. 대시보드 매출 띠(매출띠계산 순수 함수 + 대시보드ViewModel 파생 속성): 주간 = 어제까지 7일 vs 그 전 7일(오늘 제외) → 머리 문장 “지난주보다 N% 늘었어요/줄었어요/지난주와 비슷해요”, 월간 = 이번 달 1일~어제 vs 지난달 1일~같은 날짜(짧은 달은 말일 클램프 — 의도) → 알약 “▲ N%”·”▼ N%”·보합 “─ +N%/−N%/0%”(실제 반올림 값), ±2% 보합, 999% 상한, 지난 기간 0이면 비교 불가, 최근 28일 면 채움 꺾은선(View가 실제 폭을 알려 점을 다시 계산 — Viewbox 늘림 없음). 대비 검산(리뷰 재계산): OnSidebar.Primary/Bg.Sidebar 15.7(Light)·17.0(Dark), OnSidebar.Tertiary 6.1·7.7, SidebarActive 7.8·7.5, Fg.Tertiary/Canvas 5.6·7.2, 알약 Text/Soft 5.4~7.0, Line.Strong/Surface 3.5·4.0 — 리뷰 🔴-1([새 소식] 배지 글자가 사이드바 단축키 회색 규칙에 덮여 Light 2.33:1)은 선택자를 의미색 pill 제외로 좁혀 고치고 렌더 테스트로 고정. 🔴 Light 사이드바 위에 Fg.Primary를 쓰면 1.02:1 — 사이드바 안 글자는 반드시 OnSidebar 토큰. DocsScreenshot·OrderListPerf의 App 미러에도 Icons.axaml 포함, 데모 전용 HANARO_DEMO_SALES_TREND=down(스크립트만 읽음). 사용자 육안 확인 “괜찮다”(로컬 앱·운영 DB). 미해결 🟢: 꺾은선 끝점(오늘 진행 중)이 오전에 아래로 꺾여 보이는 착시(사용자 결정 2026-10-21 — 오늘 점은 실시간으로 보이게 그대로 둠), 발송 보류(Saffron) 버튼 평소 테두리 구분(실기 확인 항목). 2026-10-21 사용자 피드백 “오른쪽 공간이 남는다”: [매출 자세히 (F3) →] 링크를 차트 줄 오른쪽 열에서 머리 줄 KPI 묶음 끝(매출자세히링크, 구분선 뒤)으로 옮겨 꺾은선이 띠 안쪽 폭 전체를 쓴다(좁은 폭에서는 KPI 묶음과 함께 문장 아래로). 렌더 테스트로 고정(그림 폭 = 머리 줄 폭, 마지막 점 = 오른쪽 끝). 같은 피드백의 본래 대상은 매출 화면(F3) “일별 매출 추이” — 날짜 칸이 고정 폭(MinWidth 28 · 막대 18px)으로 왼쪽부터 쌓여 30일 조회에서 카드의 1/3만 썼다 → ItemsControl 패널을 한 줄 UniformGrid로 바꿔 날짜 수만큼 카드 폭을 고르게 나누고, 막대는 칸 가운데 절반(최대 40px, Border.sales-daily-bar). 날짜 칸 최소폭(28 + 여백 8) × 날짜 수가 뷰포트보다 넓으면(92일 조회 등) 종전처럼 가로 스크롤(ScrollContentPresenter가 내용을 뷰포트 폭 이상으로 배치하는 성질 이용). 렌더 테스트 매출관리_일별추이렌더Tests(12일 = 카드 폭 전체·칸 폭 균등·막대 ≤ 36 / 92일 = 스크롤·칸 ≥ 28). 개발 PC 실기: 21일 조회에서 막대가 카드 끝까지.
  • 로젠 오류 사유 표시·전부 오류 시 서버전송 생략 (PR #372, invercelina, release/0.4.2 → #373 develop) — ① 로젠 목록 조회(getTransData) 오류 목록(transErrList) 행의 remarks를 rmk(400자)로 읽어 택배접수행.오류사유에 싣고, 오류 목록에서 찾은 대상의 알림 문구를 고정 안내 대신 그 행의 로젠 문구로(택배사받지않은주문.오류목록사유만들기, 80자). ② 로젠페이지절차.전송전검증읽기Async: 엑셀 첨부 뒤·서버전송 버튼 전에 화면 검증 결과(excelData)를 읽어 올린 줄이 전부 오류면 버튼을 누르지 않고 창 없이 끝냄(창없이끝난안내 = 문구_전부오류, 단계 첨부함 → 접수 안 됨 확실, 엑셀 오류 줄과 맞은 주문만 “오류” 기록·나머지 되돌림). 종전에는 로젠이 모르는 안내 창을 띄워 120초 뒤 send-timeout으로 창이 뜨고 기록이 “확인 안 됨”이었다. ③ 검증 응답은 서버 왕복이라 첨부 직후 0줄 — 실릴 때까지 10회 × 500ms 되읽음. 오류 문구는 화면 전용(로그·Sentry·DB 금지).
  • 로젠 “전부 오류” 알림·판정 후속 (PR #372(invercelina) 리뷰 🟡 2건, 같은 PR) — ① 송장관리ViewModel.전부오류요약: “모두 로젠 검증 오류라 보내지 않았습니다”는 실제로 보낸 것이 없을 때만(서버전송 전 종료 접수안됨확실 또는 빠진 대상 전부가 엑셀 오류 줄) — 종전에는 건수만 봐서 대상 1건이 서버전송 뒤 로젠 오류 목록 행(주소 정제 실패 등, 실제로는 서버로 감)이어도 그 문구가 떴다 → 그런 경우 종전 “N건 중 0건을 접수” 문구. ② 로젠부분전송.줄다실림: 전부 오류·검증끝남 판정을 로젠이 읽었다는 건수(#readCnt = 엑셀건수)만큼 줄이 다 실린 뒤에만(응답이 나눠 실릴 때 앞 묶음만 보고 버튼을 안 누르는 일 방지 — 추정 방어, 읽은 건수를 모르면 종전대로 줄 수만). 테스트 3건.
  • 매출 화면(F3) 시각 폴리시 (디자인 하네스, 2026-10-21 사용자 “매출 부분도 좀 더 시각적으로”) — 지시서·적용·리뷰는 _workspace/design/sales-2026-10-21/(gitignored). Styles/Hanaro.axaml “F3 매출 화면 시각 폴리시” 블록: 총매출 카드 Border.card.sales-hero(Songhak.Soft 배경·테두리 한 겹, 라벨 Songhak.Text, 숫자 Type.Numeric 32/Emphasis), 나머지 카드 sales-kpi(숫자 22/26 — 대시보드 매출 띠 KPI와 같은 값, 단위 Caption) + 차감 카드 .deduct(숫자 Fg.Secondary, 보조 줄 kpi-sub Vermillion.Text SemiBold), 막대 Border.sales-daily-bar(인라인 Background·CornerRadius 제거 → 스타일: 모서리 3,3,0,0·MinHeight 2·.zero(바인딩 매출없음) Line.Strong 회색 스텁·호버 Songhak.Bright, 날짜 라벨 label sales-axis·호버 Fg.Primary, MaxWidth 36), 표(거터 12, 머리글 선 Line.Default, 행 Margin 0,6, 매출액 열 amount SemiBold, 건수·수량 count Fg.Secondary). 토큰 신설 없음(리터럴 22/26·3,3,0,0은 variants.py 경유 토큰화 후속). 대비(리뷰 재계산, Light/Dark): Songhak.Text/Soft 5.35/6.83, Fg.Tertiary/Soft 5.12/4.92, Line.Strong/Surface 3.51/4.02, Vermillion.Text/Surface 6.75/7.66 — 모두 기준 이상. VM(폴리시 범위 밖, 같은 PR): 매출관리ViewModel.일별축채우기 — 집계는 주문 있는 날만 돌려줘 빈 날이 축에서 빠진 채 “매일 이어진” 차트로 읽혔다(리뷰 5-1) → 조회 기간의 모든 날을 0원 행으로 채움(같은 날 합산, 기간 밖 날짜는 축을 넓혀 보존, 미래 날짜는 오늘까지로 자름, 결과 전체가 비면 축도 비워 카드 숨김 유지). 축 라벨 일별매출Vm.축라벨 = 일 숫자(“22”), 첫 칸과 1일은 “9/22”·”10/1”(“09-22” 폭으로는 30칸이 1440 창에 안 들어가 스크롤이 생겼음 — 실기), 툴팁 툴팁 = “10월 21일 (수) · 36,000원 · 2건”, 칸 Background=Transparent로 칸 전체에서 호버·툴팁. 엑셀 일별 시트는 종전대로 주문 있는 날만(원본 결과 사용). 긴 기간(“올해” 294칸)은 가로 스크롤 — 라벨 솎기·주 단위 묶기는 후속(지시서 §5-7). 실기: 개발 PC Light 1440 실데이터 캡처(총매출 카드·30칸·0원 스텁·”10/1”).
    • 접힌 레일 아이콘(2026-10-21 사용자 피드백 “메뉴 접기했을 때 아이콘이 잘 안 보임”, develop 실기) — 접힘에도 펼침 규칙(15px · 투명도 0.85 · OnSidebar.Secondary 상속)이 그대로라 먹색 레일 위에서 흐렸다. Button.nav PathIcon 기본(15 · 0.85)을 Hanaro.axaml로 올리고(요소 지역 값 제거 — 지역 값은 스타일을 이김) MainWindow 접힘 규칙에서 18px · 불투명 · OnSidebar.Primary(활성 SidebarActive), 접힘 Button.nav Padding 5 → 3으로 아이콘 가운데 = 레일 가운데(28). 사이드바접힘렌더Tests가 크기·투명도·색·가운데를 렌더로 단언.
  • 카페24 대시보드 카드 → 쇼핑몰 관리자 + [셀러센터 로그인] (2026-10-21 사용자 질문 “카페24 카드를 누르면 왜 사이트가 아니라 주문 칸으로 가나”) — 셀러센터주소의 카페24 3칸이 확인됨: false(2026-10-02 “실계정 확인 전”)라 늘 주문 화면으로 대체됐고, 구형 경로(/admin/php/shop1/s_new/order_list.php 등)는 로그인 없이도 403이었다. /admin/은 alert(“관리자 전용 로그인 페이지로 이동합니다”) 뒤 eclogin.cafe24.com/Shop/로 간다(Playwright, 로그인 없이 확인). 다섯 칸 모두 몰 관리자 구형 화면 https://{mall}.cafe24.com/admin/php/{shop}/…(2026-10-21 실계정 — 로그인한 셀러센터 창에서 관리자 메뉴를 눌러 UI 자동화로 이동 주소를 기록): 신규 s_new/order_list.php(전체 주문 조회 — 입금전 관리 주소는 못 받음) · 발주확인 s_new/product_prepare_list_ord_num.php(상품 준비중 관리 = 카페24 N10) · 배송중 s/shipped_end_list.php(배송 중 관리) · 완료 s_new/shipped_complete_list_ord_num.php(배송 완료 조회) · 이슈 = 전체 주문 조회(취소 s/order_cancel.php·교환 s/order_change.php로 갈라짐). {shop} = 판매처 쇼핑몰 번호(MarketStatusVm.쇼핑몰번호, 찾기 4번째 인자 — 🔴 shop1 만 실계정 확인, 2번 이상은 경로 규칙 추정). 🔴 로그인이 없으면 이 주소는 403이고 로그인 화면으로 보내지 않는다 — 셀러센터창.카페24복귀판정(순수 함수)이 403 을 보면 원래 주소를 적어 두고 /admin/으로 가고, 관리자 홈(/disp/admin/…)에 닿으면 돌아온다(창당 1회, 두 번째 403 은 안내만). /admin/의 알림 “관리자 전용 로그인 페이지로 이동합니다”는 CDP(Page.javascriptDialogOpening + handleJavaScriptDialog)로 자동 수락 — 이 창은 WebView2 기본 대화상자라 ScriptDialogOpening이 오지 않는다(로젠 창 실측과 같음). 범위는 카페24알림자동수락: 몰 호스트(*.cafe24.com, eclogin 제외)의 alert 중 그 문구일 때만(eclogin 로그인 실패·비밀번호 변경 알림, confirm·prompt, 다른 마켓은 그대로 보임). 셀러센터 창 자동입력마켓에 eclogin.cafe24.com → 카페24, 전용 자동 입력 스크립트(form#frm_user · input#mall_id[name=loginId] · input#userpasswd[name=loginPasswd] · 폼 안 <button type=button>로그인</button>). 실계정 확인(2026-10-21, 앱 실기): 403 → 알림 자동 닫힘 → 자동 입력 “로그인 버튼 클릭 성공” → (카페24 “소식 받기” 동의 화면은 셀러가 고름 — 하나로는 누르지 않는다) → 관리자 홈 → 전체 주문 조회 복귀, 로그인된 상태에서 다섯 칸 각각 그 화면 제목 확인. 미확인: 추가 인증·부운영자 로그인 탭. 설정 → 마켓 계정 카페24 카드에 셀러센터 로그인 노출. 자동 입력 2회 실패 정지·2단계 인증 직접 처리 규칙은 종전과 같다. 셀러센터 창 이동 로그(호스트+경로)는 주소 확정 뒤 제거했다(몰 ID가 Sentry breadcrumb 에 섞이지 않게).
  • 주문 표 여러 열 클릭 정렬 (#353) — 헤더 클릭마다 정렬 안 함 → ▲ → ▼ → 정렬 안 함, 여러 열은 켠 순서대로 누적(▲1·▼2는 2개 이상일 때만), 기본(조회 쿼리 주문일자 최신순)은 흐린 ▼, 기본이 아니면 마켓 탭 줄에 “정렬: … [정렬 해제 ✕]” 칩(주문표정렬 순수 클래스, 안정 정렬, 상품번호는 숫자 순). 정렬은 실행 중에만 유지합니다(앱을 켠 직후 새 주문이 묻히지 않게 — 사용자 결정). 행 더블클릭 가드는 행 안 버튼의 시각 트리 상위까지 봅니다(행안의버튼인가).
  • 도움말 검색 (#354) — 셀러 PC의 도움말은 외부 AI 없이 내장 FAQ에서 찾는 LocalAISupportBot이라 “AI 도우미” → “도움말 검색”, 결과 머리는 로컬 “검색 결과”·Anthropic 모드(HANARO_AI_PROVIDER+키가 있을 때만)만 “AI 답변”, 버튼 [찾기]. 로컬 모드는 맞는 FAQ를 순위 목록(최대 5)으로 보여 주고 자세히 보기를 붙입니다. 검색은 FAQ검색어분석(조사·어미 떼기, 흔한 말 제외, 셀러 표현 동의어, 질문·키워드 > 답 가중치, 흔한 말 감쇠, 띄어쓰기 무시, 1위 20% 미만 컷)으로 바꿨고 FAQ 시드를 143 → 151건으로 지금 화면에 맞게 정리했습니다(141건 문서 링크). pages.yml이 시드의 문서 링크·앵커 존재를 검사합니다(.github/scripts/check_faq_doc_links.py). Anthropic 모드 외부 전송 내용·개인정보 처리 순서는 그대로입니다.

Changed

  • 주문 화면 작업 중 조회 보류 확대 (#323) — 기간·상태 변경 조회를 미루는 작업중조회보류가 동기화·송장 등록 외에 로젠 택배 자동접수·과거 주문 받기 중에도 미루고, 끝나면 그때 조건으로 한 번 읽습니다(종전에는 즉시 조회로 표 행을 새로 만들어 행별 결과·진행 문구가 사라질 수 있었음).
  • [우리 번호로 전송] 확인창 중립화 (#326) — 양쪽 번호가 있고 정규화하면 같은 번호(예: 하이픈 차이)면 “다시 확인만 하고 마켓 번호를 바꾸지 않는다”는 중립 문구를 띄웁니다(송장관리ViewModel.교체확인문구). 하나로에 송장번호가 없으면 확인창 없이 “보낼 번호가 없습니다”로 끝냅니다.
  • 로젠 송장번호 바뀜 안내 4곳에 [우리 번호로 전송] 경로를 더했습니다 (#326) — [송장번호 불러오기]·상단 배너·[송장 다시 출력] 확인창·등록 직전 재확인이 “하나로는 다시 보내지 않으니 셀러센터에서 고쳐 주세요”만 말했습니다. 이제 셀러센터와 함께 쿠팡·카페24·스마트스토어는 다음 [마켓 동기화] 뒤 [⚠ 마켓 불일치] → [우리 번호로 전송]도 안내합니다(송장번호바뀜안내.고치는경로 단일 출처).
  • 도움말 패널 질문 길이 (#325 · #342) — 검색창 상한이 500자 → 2,000자(지원봇입력정리.입력최대길이, 치환 상한 8,000 안쪽)로 늘었습니다. 봇에 보내는 질문은 종전처럼 500자 이하이고 월 호출 상한도 그대로입니다. 잘림 안내는 “질문이 길어 앞 500자만 보냈어요” → “질문이 길어요. 앞부분(최대 500자)만 답변에 써요.”(가린 글자가 원문보다 짧을 수 있어 원문 기준 글자 수를 단정하지 않음).
  • 설정 → 일반의 알림 사운드·볼륨 칸 제거 (#355) — 재생 코드·음원·저장 경로가 없는 칸이었습니다(src·scripts·tests grep 0건). 카드 제목 “수집·알림” → “주문 수집”. 저장된 값이 없어 사용자 파일은 건드리지 않습니다.
  • 예정 택배사 안내 정정 (#355) — “[택배 접수용 엑셀]로 직접 접수해 주세요” → “○○ 사이트에서 직접 접수해 주세요. [택배 접수용 엑셀]은 로젠 양식이에요.”(엑셀은 택배사와 무관하게 로젠 업로드 양식 9열). 엑셀 버튼 툴팁·저장 확인 창 끝 문장에도 로젠 양식을 적었고 버튼 활성 조건은 그대로입니다.
  • 주문 화면 마켓 탭·상태 버튼에 화면 읽기용 이름 (#351).
  • 셀러 문서 정정 (#354·#355) — 도움말 단축키는 Ctrl+/만(Shift+/는 β.lite-27에서 제거됨), 로그 보관은 14개, 포터블 zip은 자체 포함이라 .NET 8 별도 설치가 필요 없음(v0.4.1 Portable.zip 실물 확인), “AI 도우미” → “도움말 검색”(FAQ·문제해결·지원정책. 이용약관·개인정보처리방침의 표현은 개정 절차로 따로).

Fixed

  • 직접 등록 주문의 보내는 사람에 “직접 등록”이 들어가던 문제 — 보내는 사람에 마켓 계정 이름 쓰기가 켜져 있으면 로젠 접수 엑셀 보내는 사람에 판매처 이름을 넣는데, 직접 등록 판매처 이름은 화면 표시용 고정값(직접등록사이트.판매처이름)이고 마켓 계정 목록에 나오지 않아 셀러가 바꿀 수 없었습니다(셀러 문의 2026-10-19 — 실제 송장에 인쇄됨). 직접 등록 상자는 설정과 무관하게 설정한 보내는 사람 이름을 씁니다(로젠보내는사람.이름구하기의 직접등록 인자, 비면 택배사 기본값). [선택 주문 라벨 인쇄…]도 보내는 분이 늘 판매처 이름이라 같은 문제였습니다 — 직접 등록 상자만 설정한 보내는 사람 이름(비었으면 빈칸, 못 읽으면 빈칸 + 완료 문구 안내, Build라벨모델들). 다른 마켓 주문은 접수 엑셀·라벨 모두 종전과 같습니다. 주문에 보내는 분을 넣었으면 그 값이 먼저입니다(Added “직접 등록 보내는 분” 참조).
  • 등록 직전 재확인에서 마켓이 주문을 찾지 못하면 “확인 못 함”으로 알립니다 (#326) — 종전에는 조회 응답에 없는 주문(카페24 다른 쇼핑몰·쿠팡 조회 창 밖 등)을 아무 표시 없이 보냈습니다. 전송은 종전처럼 하고, 조회 실패와 구분되는 문구(“…에서 이 주문을 찾지 못해 현재 송장번호를 확인하지 못했습니다”)를 남깁니다(MarketGroupProcessor.마켓송장번호사전확인Async 사유별 반환). 마켓에 번호가 없는(주문은 찾음) 경우는 종전대로 “확인 못 함”이 아닙니다.
  • [우리 번호로 전송] 지원 여부 확인이 일시 오류로 실패하면 “미지원”으로 단정하지 않습니다 (#326) — I마켓송장번호교체.지원여부Async가 bool?(확인 실패 = null)를 돌려주고, 화면은 “교체 지원 여부를 확인하지 못했습니다(일시 오류) — 잠시 뒤 다시 시도하거나…”로 끝냅니다(차단도 풀지 않음). 송장번호 직접입력 창은 확인 실패를 지원하지 않는 쪽 문구로 다룹니다.
  • 쿠팡 같은 배송 상자의 다른 상품 행의 ⚠ 불일치 표시도 함께 정리합니다 (#326) — 쿠팡 송장 수정은 상자 단위로 보이나 실계정 미확인이라, 하나로는 클릭한 행만 ⚠ 불일치를 걷었습니다. 이제 같은 상자 · 같은 우리 번호 · 같은 옛 마켓 번호(정규화 비교)이고 취소·반품·교환 상태가 아닌 다른 상품 행은 불일치 표시만 정리하고 전송 기록(송장번호전송일시)은 남기지 않습니다(I배송상자주문조회 재사용, 결과 함께해소된주문일련번호 = 실제로 기록을 지운 주문만). 마켓 반영은 다음 [마켓 동기화]가 확인합니다(형제 번호가 그대로면 ⚠가 다시 섭니다). 상자를 읽지 못하거나 일부를 정리하지 못하면 그 건수와 “다음 [마켓 동기화] 때 맞춰집니다”를 덧붙입니다.
  • 보류 조회가 성공해도 낡은 “주문 목록을 불러오지 못했습니다” 안내가 되살아나던 경합 (#323) — 보류 조회 성공 시 직전 작업 문구 끝의 낡은 조회 실패 안내를 떼어 냅니다(송장관리ViewModel.낡은조회실패꼬리제거). 원인은 코드로 추정(재현 기록 없음).
  • 지원봇 외부 전송은 개인정보 치환 뒤에 자릅니다 (#325 · #342) — AnthropicAISupportBot이 질문·문맥(현재 화면·마지막 에러)을 자른 뒤 치환해, 500자·300자 경계에 걸린 전화번호가 010-1234-5 같은 조각으로 패턴을 비껴 나갈 수 있었습니다. 이제 PIIMask 치환 → 길이 상한 자르기 순서입니다(치환 입력은 PIIMask.스크럽최대길이 8,000으로 캡). #325만으로는 화면(도움말PanelViewModel)이 질문을 먼저 500자로 잘라 질문 칸에는 효과가 없었고, #342에서 화면이 원문(앞뒤 공백만 정리)을 봇에 넘기고 잘림은 따로 판정하게 고쳤습니다(VM → 실제 봇(가짜 HTTP) 경계 전화번호 테스트 추가). FAQ 검색(로컬)은 종전처럼 길이만 맞춘 원문으로 합니다.
  • 상품명·옵션 수정 뒤 상품명 칸이 간헐적으로 왼쪽 정렬되던 문제 (#353, 바이앤드셀 10/19 피드백) — Avalonia 11.2.2 TextBlock이 측정 무효 순간에 레이아웃을 Left로 만드는 동작이 원인으로 추정(Headless에서 재현). 표 셀 전용 주문표글자로 늘 지정 정렬을 쓰고 송장행Vm.상품반영으로 변경 알림을 1회로 줄였습니다. 셀러 PC에서의 최종 확인은 배포 뒤입니다.
  • 마켓 탭 선택이 바뀔 때 뒤 탭이 1px 밀리던 것 (#350).

내부 (화면 변화 없음)

  • 설치 통계에서 개발기 실행 제외 (#324 · #342) — 설치등록설정.개발기인가: 디버거가 붙었거나 실행 버전이 0.0.0-dev(로컬 빌드, Domain 앱버전.개발버전 단일 상수)면 설치 등록을 하지 않습니다. 전송 필드는 설치 번호·앱 버전 그대로(개인정보처리방침 표 변경 없음). 한계: 릴리즈 빌드를 개발 PC에 설치하면 구분되지 않고, 신규 등록분부터만 유효합니다. scripts/admin/list-installs.ps1 헤더·런북 §6-E의 조회 전제(“service_role 키 필요”)를 정정하고, 재설치는 같은 MachineGuid 해시라 중복 집계되지 않음(= 순증 기기 수)·”(알 수 없음)” 버전 의미를 적었습니다.
  • 쿠팡 쓰기 요청(문의 답변 등록·송장업데이트)이 재시도 0(시도당 15초)임을 테스트로 고정하고(쿠팡HTTP정책Tests), “답변 등록이 재시도 2회·최악 55초”라고 적힌 낡은 주석 2곳(초안승인잠금·실행표식회수서비스)을 바로잡았습니다(#326). 동작 변화는 없습니다.

[0.4.1] — 2026-10-15

11번가 마켓(셀러오피스 공식 오픈API — 주문 수집·발주확인·송장 등록)과 주문 화면 [발주확인] 버튼을 추가했습니다. 마켓에 등록된 송장번호 교체(쿠팡·카페24·스마트스토어), 카페24 상품준비중 주문 송장 등록, 주문 화면 택배사 선택기·상태 필터 세분화를 추가했고 0.4.0 점검에서 나온 대시보드·송장 재출력·문의 중복 답변 문제를 고쳤습니다. 카페24 한 몰의 여러 쇼핑몰 등록과 카페24 요청 권한 확대(2개 → 7개)도 들어갔습니다. DB 마이그레이션은 증분 1개(Beta53_MarketShopNo — 판매처·주문에 쇼핑몰 번호 열 추가, 기존 행은 비어 있음 = 1번)입니다. 11번가는 사이트 시드 11ST만 추가하고 스키마 변경이 없습니다.

⚠️ 카페24 셀러 할 일: 0.4.1부터 카페24에 요청하는 권한이 7개로 늘었습니다. 기존 연결은 주문 수집·송장 등록을 그대로 하지만, 새 권한이 필요한 기능([쇼핑몰 추가]의 쇼핑몰 목록 등)은 [재인증]으로 한 번 다시 연결해야 씁니다. 본인 개발자센터 앱으로 연결한 셀러는 그 앱에 7개 권한을 먼저 등록해야 합니다.

Added

  • 11번가 마켓 추가 — 주문 수집 · [발주확인] · [선택 주문 송장 등록] · [택배 자동접수] 직전 배송지 재조회 (β.lite-55, #313 · 문서 #314, 신동환). 셀러오피스 공식 오픈API(Infrastructure/Marketplaces/ElevenStreet/) — 헤더 openapikey(판매처 슬롯 DPAPI, 로그 마스킹), EUC-KR XML 파서.
    • 수집: 결제완료(신규주문)·배송준비중(발주확인)·배송완료 정식 행 + 배송중·판매완료(구매확정) 상태 대조 + 취소요청·취소완료 클레임 스냅샷(목록 7일·취소 29일 창, 평소 92일). 배송중 목록의 송장번호를 마켓 송장으로 반영(하나로에 있는 주문만). 배송완료 목록은 결제금액이 없어 할인 전 주문금액(ordAmt)으로 대신. 진행 중 클레임·배송 단계 역행은 대조허용이 막고, 취소 거부·철회 뒤 발송은 Domain 클레임상태판정.하향차단 규칙. 모든 행 터미널관측제외(목록에서 사라진 주문을 숨기거나 바꾸지 않음).
    • 발주확인: 직전 재조회로 추가상품·배송번호 확보, (배송번호, 상품번호)당 1회. 송장 등록: 배송번호(dlvNo)당 1회 + 결과 분배, 5대 택배사 코드 — 같은 배송번호 주문은 11번가에서 함께 발송처리되며 확인창에 안내.
    • 🔴 발주확인·발송처리도 GET이라 HttpClient 정책을 경로 허용 목록으로 갈라 조회 7종만 재시도, 쓰기는 재시도 0 + ConnectionClose, 호출 시작 뒤 예외·타임아웃은 “결과 확인 필요”.
    • IP 미등록: HTTP 500 + <AuthMessage>를 네트워크 오류와 갈라 키·IP 안내(공인 IP는 셀러 문구에만, 로그·Sentry 금지). [마켓 추가]·온보딩·설정에 11번가, 같은 API 키 중복 차단. 사이트 시드 11ST(코드 기준 멱등) — DB 마이그레이션 없음.
    • 실계정 확인(2026-10-14~15, 셀러 1곳): 수집·취소 목록·결제금액 / [발주확인] → 배송지 재조회 → 로젠 자동접수 → 송장 등록 → 배송중 / IP 허용 해제·복구 안내 / 구매확정 반영 / 셀러오피스 직접 발송 송장 반영 / 발주확인 전 구매자 취소 → 취소. 미확인: ordPrdStat 상태코드표 전체, 부분 취소 후 수량 변화, 호출 제한. 후속: 부분 취소 주문의 남은 수량 발주확인(지금은 취소 기록이 있으면 막음), 주문번호가 다르고 배송번호가 같은 묶음의 로젠 한 상자 접수.
  • 주문 화면 [발주확인] 버튼 (β.lite-53, #305) — 체크한 신규 주문을 송장번호 없이 각 마켓에 발주확인합니다(확인창 승인 후, 하단 액션 바 [엑셀 저장] 다음의 ghost 버튼, 대상만 행·제외는 사유별 건수). 대상 판정은 Application 발주확인대상판정 단일 출처(송장 등록의 발주확인 게이트도 같은 판정 + 송장 있음). 카페24(하나로 신규주문 = 입금 전)·직접 등록·발송 보류·복사/분할·취소·반품·교환·클레임 확인 필요는 제외, ESM은 택배사와 무관하게 주문확인. 마켓이 받은 주문만 신규주문 → 발주확인으로 저장(I발주확인상태반영, SQL 조건부 전이). 호출 시작 뒤 예외는 “결과 확인 필요”로 두고 DB는 그대로. 쿠팡은 상자(판매처 + 배송번호) 단위라 같은 상자의 신규 주문을 함께 보이고 함께 처리(발주확인대상판정.상자포함판정 — 진행 중 클레임·발송 보류가 있으면 상자 전체 제외). 🔴 쿠팡은 2xx면 응답 본문의 상자별 결과를 보지 않고 전건 성공으로 저장(사용자 결정) — 송장 없는 단독 발주확인·쿠팡 부분 실패 응답은 실계정 미검증.
  • 마켓 등록 송장번호 교체 — [⚠ 마켓 불일치] → [우리 번호로 전송] (쿠팡 #298 · 카페24 #300 · 스마트스토어 #301·#302). 확인 창을 거친 뒤 마켓의 번호를 하나로 번호로 바꾸고, 마켓이 성공을 명시하고 다시 읽었을 때 우리 번호가 보일 때만 불일치 기록을 해제합니다. 지원하지 않는 마켓(ESM 등)은 종전대로 마켓 셀러센터에서 직접 고칩니다.
    • 쿠팡: 이미 등록된 송장의 수정 API로 전송. 응답 본문의 항목별 실패(succeed=false·resultCode·responseCode)를 감지합니다(업로드는 모르는 모양이면 종전대로 성공, 교체는 실패 처리). [선택 주문 송장 등록] 직전에 마켓의 현재 번호를 재조회해 다르면 보내지 않고 ⚠ 불일치로 남깁니다(조회 실패는 보내되 “확인 못 함” 표시).
    • 카페24: 배송코드별 수정 1회, 교체 전 검사(주문·배송코드 없음, 입금 전, 택배사 코드, 같은 배송의 다른 번호)에 걸리면 보내지 않고 사유 표시. 성공은 재조회로 우리 번호가 보일 때만(번호가 그대로면 오류, 재조회 실패면 “확인 못 함”). 등록 직전 재조회도 합니다(고유 주문 100건당 조회 1회 추가). 끄기 스위치 HANARO_CAFE24_INVOICE_REPLACE_DISABLED.
    • 스마트스토어: 커머스API에 송장 수정이 없어 셀러센터 로그인 세션(숨은 WebView2, 셀러센터 창과 프로필 공유)에서 판매자센터 송장수정을 1회 호출합니다(쓰기 재시도 0, 3초 이상 간격). 판매자센터 로그인 계정이 [셀러센터 로그인]에 저장된 아이디와 다르거나 읽지 못하면 보내지 않습니다. 성공은 커머스API 재조회(2/4/8초, 최대 3회, 확인에 10초 남짓)로 우리 번호가 보일 때만, 모르면 “결과 확인 필요”. 로그인·2단계 인증이 필요하면 창을 띄우지 않고 [셀러센터 열기] 안내만 합니다(저장된 계정으로 자동 로그인). 등록 직전 재확인은 하지 않습니다. 끄기 스위치 HANARO_STOREFARM_INVOICE_REPLACE_DISABLED.
    • 🔴 확인 범위(2026-10-13, 신동환 사원 주문·운영 DB): 스마트스토어·카페24는 배송중 주문 1건으로 등록 → 불일치 감지 → [우리 번호로 전송] → 재조회로 확인까지 확인했습니다 (스마트스토어는 [마켓 번호로 맞춤]까지). 카페24 PUT은 tracking_no 수정과 배송중 주문을 받아 주었고 재조회로 우리 번호가 보였습니다. 쿠팡은 사원이 실계정에서 시험해 동작을 확인했습니다(세부 응답 기록은 이 문서에 없음). 배송완료 주문은 교체 대상이 아닙니다(사용자 결정).
  • 카페24 상품준비중(N10, 하나로에서는 발주확인) 주문 송장 등록 (#303) — 카페24는 배송준비중(N20)에서만 송장 등록을 받아 N10은 거절(422)됐습니다. 이제 등록 직전 로컬 상태가 발주확인인 주문은 주문번호당 1회 배송준비중으로 올린 뒤 등록합니다. 올리기 실패 시 품목 상태를 다시 읽어 이미 배송준비중이면 등록, 아니면 사유와 함께 등록하지 않습니다. 입금 전 주문은 등록하지 않습니다. 끄기 스위치 HANARO_CAFE24_AUTO_PREPARE_DISABLED. 🔴 카페24에는 상태를 되돌리는 API가 없어 올린 주문은 되돌려지지 않고, 주문 전체 품목이 함께 올라갑니다(품목 지정 방법 미확인). 2026-10-13 실계정 1건에서 올리기·등록 확인(N10 → 올리기 HTTP 200 → 등록 성공). 배송완료 주문은 대상이 아닙니다.
  • 주문 화면 택배사 선택기와 [접수 후 작업 ▾] (#286) — 하단 맨 앞에 택배사 선택기(로젠택배만 동작, 나머지는 “(예정)”, 마지막 선택은 courier-prefs.json에 기억). 선택 택배사의 능력에 따라 [택배 자동접수]·[접수 후 작업 ▾]가 켜집니다. [송장번호 불러오기]·[받은 파일로 송장 출력…]·[출력 요청 파일 다시 만들기…]는 [더보기 ▾]에서 [접수 후 작업 ▾]로 이동했습니다.
  • 주문 화면 [? 사용 순서] 버튼 (#288) — 도구막대 맨 오른쪽, 누르면 발송처리.html을 엽니다(툴팁에 ① 체크 → ② 택배 자동접수 → ③ 송장 등록).
  • 로젠 접수 “보내는 사람에 마켓 계정 이름 쓰기” (#293) — 설정 → 택배사의 체크박스(기본 꺼짐). 켜면 접수 엑셀 보내는 사람 이름에 판매처의 마켓 계정 이름을 씁니다(비면 설정한 이름). 실제 송장 인쇄는 미확인.
  • 카페24 한 몰 여러 쇼핑몰(shop_no) — 설정 → 마켓 계정의 카페24 카드 [쇼핑몰 추가] (β.lite-53) — 판매처 1개 = (몰 ID, 쇼핑몰 번호). 같은 몰의 판매처들은 연결(토큰) 1벌을 함께 쓰고 다시 로그인하지 않습니다. 입력 줄을 열면 쇼핑몰 목록(GET /api/v2/admin/shops, mall.read_store)을 받아 고르게 하고(이미 추가된 번호 제외), 옛 권한 토큰(403 insufficient_scope)·실패면 번호 직접 입력으로 대체합니다. 목록은 고르기만 돕고 판매처는 셀러가 [추가]를 누른 것만 만듭니다. 추가 전에 그 번호로 주문 조회 1건(로그인 확인)을 하고, 최근 2개월 주문이 0건이면 경고만 합니다(추가는 함). 모든 카페24 조회·쓰기에 shop_no를 명시하고, 판매처와 다른 쇼핑몰 번호의 주문은 쓰기·재조회에서 보내지 않습니다. 같은 몰의 다른 쇼핑몰이 남아 있으면 판매처를 삭제해도 연결 정보는 지우지 않습니다. 🔴 실계정 미확인: /shops 응답 모양(공식 문서 기준으로 보수적 파싱), shop_no 생략 시 1번만 오는지, 없는 번호의 응답, 목록 응답의 주문별 shop_no 유무.
  • 카페24 요청 권한 2개 → 7개 — mall.read_order·mall.write_order·mall.read_shipping·mall.read_store·mall.read_community·mall.write_community·mall.read_product(단일 출처 카페24앱설정.기본Scopes, Supabase cafe24-app 기본값·개인정보처리방침 4절과 대조 테스트). 회원·프로모션·알림·매출통계·접속통계·디자인은 요청하지 않습니다. 지금 새 권한을 쓰는 곳은 쇼핑몰 목록(상점 읽기)뿐이고 배송·게시판·상품 권한을 쓰는 기능은 준비 중입니다. 옛 권한 토큰으로 새 권한 호출 시 403 insufficient_scope는 “카페24 권한이 새로 늘었어요. 설정 → 마켓 계정 → [재인증]으로 다시 연결해 주세요”로 안내합니다(로그인 확인 실패 문구에도 같은 분류). 주문 수집·송장은 옛 권한으로 그대로 동작합니다.
  • 스마트스토어 한 아이디 여러 스토어 등록 + 쿠팡 업체 중복 차단 (#306) — 스마트스토어는 같은 판매자 아이디의 다른 스토어를 [계속]/[취소] 확인 뒤 등록할 수 있습니다(같은 애플리케이션 ID는 종전대로 차단). 같은 아이디의 활성 스토어가 둘 이상이면 스마트스토어 [우리 번호로 전송]은 막습니다(판매자센터 세션이 스토어를 구분하지 못함). 쿠팡은 업체 코드나 접근 키가 다른 활성 쿠팡 계정과 같으면 저장을 막습니다. 한 아이디에 스토어 2개인 네이버 계정과 쿠팡 실계정으로는 확인하지 못했습니다.
  • 대시보드 마켓별 진행 현황 칸별 집계 기준 툴팁 (#295, 문서 #292) — 마켓(스마트스토어·쿠팡·카페24·ESM·기타) × 칸별로 원본 상태·한 건의 단위·최근 30일 기준을 안내합니다. 집계·클릭 동작은 그대로입니다. docs/대시보드와-알림.md에 쿠팡 집계 기준 추가.

Changed

  • 주문 화면 상태 필터를 10개 칩으로 세분화 (#299) — 신규 주문 / 발주확인 / 배송 준비중 / 배송 중 / 배송 완료 / 구매확정 / 취소 / 반품 / 교환 / 알 수 없음. 모든 주문 상태가 정확히 한 칩에 속하고, 취소·반품·교환 칩은 툴팁에 포함 상태를 보입니다. 대시보드 딥링크는 칸 상태 집합이 칩 여러 개의 합이면 그 칩들을 함께 체크합니다(발주확인 칸 → 발주확인 + 배송 준비중).
  • 선택 택배사와 다른 택배사 송장이 붙은 행은 [택배 자동접수]에서 제외 (#286) — 확인 창 맨 앞 경고와 접수 후 상태 줄에 건수를 표시합니다(택배사 비어 있음·”(미지정)”·같은 택배사는 종전대로).
  • [송장번호 입력/수정] 창 안내 (#302) — 교체 가능한 마켓이면 “저장 뒤 주문을 다시 받으면 ⚠ 마켓 불일치가 뜨고 [우리 번호로 전송]으로 바꿀 수 있다”로, 아니면 종전 문구(교체 지원은 마켓 이름이 아닌 I마켓송장번호교체.지원여부Async로 판정).
  • 송장 다시 출력 메뉴 이름·안내 (#290) — 선택 주문 송장 다시 출력(새 번호).... 로젠 전산송장 재발행은 새 번호를 채번하는 로젠 사양이라 동작은 그대로이고 메뉴 툴팁·확인 창·문서에 명시했습니다.
  • ⚠ 문의 단위 중복 답변 방어 (#297) — 같은 문의의 다른 회차 초안이 이미 답변됐으면 보내지 않고(이미답변됨, 상태는 바꾸지 않음), 초안 저장소는 행 전체 덮어쓰기 대신 조건부 갱신으로 바꿨습니다. 행동 변화: 실행실패 문의는 사유와 무관하게 회차 2 자동 초안을 더 받지 않으며, 마감초과 실행실패는 큐에서 영구히 빠집니다(셀러가 [다시 시도]하거나 마켓에서 직접 답). 미제공: 카페24 등록 직전 reply_status 재확인(공식 문서 필드 실재 미확인). 승인함 “이미 답변됨” 배지와 수정 전 레거시 회차 쌍 정리는 0.4.2 후속에서 추가 — 이전 회차 답변이 이미 나간 대기 초안에 배지를 달고 [승인]을 막으며 [거절]로 정리합니다.
  • 지원봇 전송 마스킹·입력 상한 (#296) — 질문·화면·에러 문맥을 개인정보 마스킹한 뒤 보내고, 잔존 패턴이 있으면 전송하지 않습니다. 입력 상한 질문 500자·화면 50자·에러 300자. 프롬프트의 문의처를 셀러용(hanalabs@hanapf.kr / 카카오톡)으로 바꿨습니다. 주문번호·송장번호 같은 긴 숫자와 문맥 없는 이름은 마스킹 설계상 그대로 나갑니다.

Fixed

  • 확인 창 끝 문장이 잘리던 문제 (#302) — AvaloniaDialogService 확인 창이 높이 200px 고정이라 긴 안내와 “[확인]을 누르면 지금 ○○에 보냅니다”가 잘렸습니다(쿠팡·카페24 포함, 코드·레이아웃 계산 기준 확인). 문구 길이에 맞춰 늘고(상한 560) 스크롤하며 버튼은 아래 고정입니다. 안내 창(180px)도 같습니다. 짧은 문구 창은 오히려 작아집니다. 스마트스토어 교체의 로그인 필요 오판(로그인 화면으로 이동해 요청이 끊긴 것을 “화면 준비 실패”로 읽던 것)도 고쳐 [셀러센터 열기] 안내로 갑니다.
  • ESM 발송지연(1031) 주문이 알수없음으로 저장돼 대시보드에서 빠지던 문제 (#289) — 상태표에 코드 1031·”발송지연”을 발주확인으로 추가했습니다(2026-10-12 실응답 확인, 재수집 후 알수없음 0건).
  • 스마트스토어에서 발주확인한 주문이 신규로 남던 문제 방어 (#294, 진단 로그 #291) — 이 판매처에 신규로 저장된 주문(최대 600건, 조회 31일)을 번호로 다시 읽어 신규가 아니게 된 것만 반영합니다. 원인은 확정하지 못했고(증분 변경 피드에 발주확인이 안 나온다는 가설), 실제 스마트스토어에서 반영되는지는 확인하지 못했습니다. 수집 회차마다 (상품주문상태/발주확인여부) 조합별 건수를 로그에 남겨 원인 확인에 씁니다.
  • 쿠팡 [우리 번호로 전송]이 불일치 기록만 지우고 “이미 등록”을 남겨 다음 등록이 호출 0회로 끝나던 문제 (#298) — 위 Added의 쿠팡 교체로 대체되었습니다.
  • 도움말 FAQ가 운영에서 0건이던 결함 (#296) — IFAQService DI 등록을 팩토리로 고쳤습니다(회귀 테스트 항목수 ≥100). 시드 143건이 처음 노출되어 문구 검토와 도움말 패널 실기 확인은 하지 않았습니다.
  • AI 직원 배치 서비스가 종료 중에 돌고 있던 배치의 세마포어를 폐기하던 문제 (0.4.1 위생 묶음, 5383986) — 직원배치HostedService.Dispose가 single-flight 세마포어를 더 이상 폐기하지 않아 끝나는 배치의 Release()가 ObjectDisposedException을 내지 않습니다(회귀 테스트). 같은 묶음: HTTP 재시도 대기 주석(총 55초) 정정, DbSet 15종 단언, 주문 표 키보드·헤더 테스트 3건, OrderListPerf 시드 경로 가드(\\?\·UNC 거부).

[0.4.0] — 2026-10-08

G마켓·옥션(ESM) 주문 수집과 로젠 송장 자동 등록을 추가했습니다. 택배 자동접수를 접수와 출력으로 나눠 프린터가 없는 PC도 접수할 수 있게 했고, 대시보드를 주문 흐름 보드로 다시 짰습니다. 쿠팡 과거 주문 받기를 마켓별 기간·상한 해제로 고쳤고, 하나로를 관리자 권한으로 실행하는 설정을 추가했습니다. 이 버전은 DB 마이그레이션 2건(orders.sales_site 컬럼 추가, courier_receipts 테이블 추가)을 포함합니다 — 기존 주문 값은 보존됩니다(v0.3.8 경로 업그레이드 테스트).

Added

  • ESM(G마켓·옥션) 주문 수집 — 공식 API 승인 전이라 ESM PLUS 화면 내부 호출(주문 목록 + 주문 상세)을 WebView2 로그인 세션 쿠키로 부릅니다. 판매처 1개 = ESM 계정 1개, 로그인 방식은 ESM PLUS 마스터 / G마켓 판매자 / 옥션 판매자(마켓 추가의 로그인 방식 탭). 마스터면 두 사이트 주문을 함께 받고 주문 목록 마켓 칸에 G·A(사이트 미상 ES)로 구분합니다. 앱 시작·[마켓 추가] [로그인 확인]·자동 로그인(2회 실패 시 정지, [재인증] → [로그인 확인] → [저장]으로 해제), 보안문자·2단계 인증 감지. 주기 자동 수집·접수 직전 배송지 재조회는 ESM 로그인 창을 띄우지 않고 “[주문 동기화]를 눌러” 안내로 끝냅니다. 호출 간격·상세 조회 건수 상한을 두어 계정 제재 위험을 줄였습니다. 마켓 추가하기 · FAQ · 문제 해결
    • 주문 상태: 신규주문(1020)·발주확인(1030)·배송중·배송완료·구매확정(송금완료 포함)·취소(G마켓 2070 취소완료·옥션 6060 환불완료)를 구분하고, 환불승인일이 있으면 취소요청으로 봅니다. 취소 처리일만 있는 주문, 환불승인일 없는 미수령·반품·교환 표시, G마켓 발송 전 주문의 CN 표시는 클레임 확인 필요, 알 수 없는 상태는 알수없음(상태 확인 필요)으로 두고 [택배 자동접수] 확인 창에서 기본 체크를 풀어 둡니다. 옥션의 CN 표시는 진행 중 주문에도 붙어 판단에 쓰지 않습니다. 결제 전 취소는 받지 않고 건수만 알립니다.
    • 받은 건수가 ESM이 알려 준 건수보다 적으면 경고, ESM 판매자 정보가 지난번과 전혀 다르면(다른 계정 로그인이 섞였을 수 있음) 저장하지 않고 멈춥니다.
  • ESM 송장 자동 등록(로젠만) — [선택 주문 송장 등록]이 ESM 주문을 처리합니다. 신규주문은 ESM [주문확인]을 먼저 하고(확인 창에 ESM PLUS 주의사항을 함께 표시) 발송처리합니다. 보내기 직전에 목록을 다시 읽어 발송처리 이후·취소·환불·클레임 확인 필요·상태 모름이면 보내지 않고 사유를 남깁니다. 쓰기는 재시도하지 않고 묶음 50건 상한·2초 간격을 둡니다. 결과를 건별로 가를 수 없으면 묶음 전체를 “ESM 처리 결과를 확인하지 못했습니다”로 둡니다(처리됐을 수 있음). 로젠 외 택배사 ESM 주문은 제외(자동 등록 미지원)로 두고 처리기로 보내지 않습니다. 송장 수정·취소 통보는 지원하지 않습니다(ESM PLUS에서 직접). 옥션 주문은 목록 행의 판매자 고객번호(sellerCustNo)가 빈 값이어도 그대로 보냅니다(ESM PLUS 화면도 옥션에는 빈 값을 보내 성공 — 2026-10-08 화면 캡처 근거). G마켓은 종전대로 값이 있어야 하고, 필드가 아예 없으면 사이트와 무관하게 보내지 않습니다. 🔴 하나로의 실제 옥션 발송처리는 단위 테스트까지만 확인했습니다.
  • ESM 수집을 통합 목록 + 단계별 목록으로(β.lite-51) — 통합 목록(/api/order-integration/orders)은 주문 존재·상태·클레임·주문일·판매자 대조의 단일 출처로 두고, 주소·전화·옵션·송장은 ESM PLUS 화면의 단계별 목록(신규주문·발송관리·배송현황 1040/1050·구매결정 [전체] 탭, pageSize 500)에서 (siteOrderNo, orderNo) 키로 얹습니다. 배송완료·구매결정은 판매처별 6시간에 한 번([과거 주문 받기]는 매번). 주문 상세는 단계 목록에서 못 찾은 발송 전·주소 없는 주문만 회차당 20건으로 줄였고, 접수 직전 배송지 재조회도 신규주문·발송관리 목록으로 합니다(목록에 없으면 “ESM PLUS에서 확인” 안내). 단계 목록이 세션 만료·형식 변경이어도 통합 목록이 정상이면 그 단계만 포기하고 경고합니다(로그인 유지).
    • 송장번호 수집: 배송중·배송완료·구매결정 행에서만, 통합 상태도 발송 이후일 때. 기존 마켓 송장 반영 경로 그대로(하나로 송장이 있으면 덮지 않고 다를 때만 ⚠). 택배사 역매핑 ESM택배사코드.하나로택배사이름(10003 → 로젠택배), 모르는 택배사 코드·가려진(*) 번호는 받지 않고 경고. 발송관리(1030) 행의 번호는 쓰지 않습니다.
    • 방문수령(10035): 주문에 마켓배송방법="방문수령"(새 컬럼 orders.market_delivery_method, 마이그레이션 Beta51_OrderMarketDeliveryMethod)을 저장하고 송장번호가 없을 때 택배사 칸 “(미지정)” 자리에 “(방문수령)”으로 표시합니다(표시 전용).
    • 🔴 실기(2026-10-08 테스트 DB, ESM 56건 재수집): 단계 4종 실패 0·호출 5~6회, 송장 36건 연결(로젠), 방문수령 9건 표시, 상세 호출 0. 배송완료(1050) 응답은 0건이라 미관측(다르면 그 단계만 포기·경고). 정산 끝난 옛 구매확정 주문은 이름·주소가 가려져 주소가 비고 송장만 들어옵니다.
  • 택배 자동접수: 접수와 출력 분리 — [로젠 자동 접수]를 [택배 자동접수 ▾](로젠택배만 활성, 다른 택배사는 “(예정)” 비활성)로 바꿨습니다. 접수 확인 창에서 고릅니다.
    • [이 PC에서 출력]: 첨부·서버전송 뒤 로젠 목록을 직접 조회해 서버전송 전에 없던 행(이번 접수분)만 대조·체크하고, 체크된 집합이 의도와 같을 때만 출력합니다 (종전에는 그 접수일자의 미출력 전부를 출력할 수 있었습니다). 결과 엑셀(없으면 목록 조회)로 송장번호를 반영합니다.
    • [접수만 (출력은 다른 PC에서)]: 접수 확인까지만 하고 출력 요청 파일 하나로_송장출력요청_*.xlsx(접수일자·주문번호·가린 이름·택배사, 전화·주소 없음)를 저장합니다. 저장 폴더는 설정 → 택배사(기본 바탕화면). 목록에 송장번호가 붙기 전까지 ⏳ 출력 대기.
    • [더보기 ▾]: [받은 파일로 송장 출력…](로젠 미출력 중 파일과 맞는 최신 접수만, 이 PC 주문 자료는 건드리지 않음) · [송장번호 불러오기](체크한 주문, 로젠 최신 번호로 채움·덮어씀) · [출력 요청 파일 다시 만들기…]. 대조 규칙은 주문번호 + 받는 사람 이름 + 접수일자(원송장번호로 옛 행을 뺀 최신 행).
    • 출력 환경 점검: 실제 프린터 없음(PDF·XPS·OneNote·팩스 같은 가상 프린터 제외)·지정 프린터 없음·프린터 오프라인·OZ 뷰어(로컬 포트 36479/36509/36480/36510) 없음이면 [이 PC에서 출력]을 회색으로 막고 사유를 보여 줍니다(처음 선택은 [접수만]). 확인하지 못한 항목이 있으면 [이 PC에서 출력]을 골랐을 때만 경고합니다.
    • 로젠이 “정상 N건만 서버로 전송됩니다”로 알린 오류 줄은 접수 기록을 오류로 남기고, 접수 직후 알림 창(주문번호·받는 분·로젠 오류 문구)과 목록의 ⚠ 접수 오류로 알립니다.
    • [선택 주문 송장 등록] 직전 로젠 최신 번호 재확인, 시작 2분 뒤·3시간마다 번호 주기 확인(창 없이), 바뀌면 상단 “송장번호가 바뀐 주문 N건” 배너.
    • 접수 기록 테이블 courier_receipts(박스 = 판매처 + 주문번호 + 택배사, 이름·주소·전화 없음)가 출력 대기 표시·중복 접수 경고·번호 지켜보기의 근거입니다.
    • 🔴 로젠 화면 스크립트 사본과 IBSheet8 문서가 근거이고 실제 로젠 화면 실행은 일부만 확인했습니다(2026-10-07 접수 → 서버전송 → 새 행 대조 → 출력 버튼 클릭까지). 프린터 PC에서 출력 이후와 [받은 파일로 송장 출력…]은 실기 확인 전입니다. 스크립트는 기대와 다른 모양을 만나면 출력하지 않고 멈춥니다.
  • “하나로를 관리자 권한으로 실행” — 설정 → 일반 → 실행 권한(기본 켜짐). 로젠 인쇄 창(오즈 뷰어)이 관리자 권한이면 일반 권한 하나로의 [확인] 자동 클릭이 Windows 규칙으로 막히던 PC를 위한 것입니다. 켜면 하나로를 켤 때마다 UAC를 거쳐 관리자 권한으로 다시 켭니다(다음 실행부터 적용). UAC [아니요]·실패면 일반 권한으로 계속하고 상단에 안내합니다. 표준 사용자 PC는 다른 계정으로 실행되어 자료가 안 보이므로 올리지 않고 경고만 보입니다. 관리자 하나로가 여는 파일·링크·탐색기는 일반 권한으로 내려서 엽니다. 문제 해결
  • 마켓 계정 이름 바꾸기 — 설정 → 마켓 계정 카드의 이름 바꾸기. 바꾼 이름은 주문 수집이 덮어쓰지 않고(비교 후 교체로 동시 변경 보호) 대시보드·주문 화면 목록이 갱신되며 송장 라벨의 보내는 분 이름에도 쓰입니다.
  • 대시보드 ESM 카드 칸 → ESM PLUS 화면 — 신규(new-order)·발주확인(send-processing)·배송중·완료(shipping-status)를 하나로 안의 셀러센터 창으로 열고, 먼저 설정에 저장된 이 판매처의 로그인 방식·ID·PW로 로그인합니다(셀러가 누른 경로만, 같은 ESM 로그인이 진행 중이면 두 번째를 시작하지 않음). 이슈 칸은 ESM에서 한 화면으로 모이지 않아 하나로 주문 화면으로 갑니다. 완료 칸은 ESM 화면이 배송완료만 보여 안내에 적습니다. ESM 판매처가 둘 이상이면 공유 프로필 때문에 창의 계정이 바뀔 수 있어 계정 확인 경고를 유지하고, 창 안에서 ESM 로그인 화면을 만나면 경고합니다. 🔴 주소는 2026-10-08 실제 로그인으로 확인했으나, 세션이 남았을 때 로그인 없이 열리는지·옥션/일반 판매자 계정에서 같은 주소인지·대시보드 숫자와 ESM 화면 숫자의 일치는 미확인입니다.
  • ESM 묶음 배송(β.lite-50) — 같은 판매처·판매사이트(G마켓/옥션 따로)·받는 분 이름·우편번호·주소(이름·주소는 공백·대소문자 무시, 우편번호는 숫자만)인 ESM 주문을 주문번호가 달라도 한 상자(운송장 1장)로 접수합니다. 묶음 키는 Domain ESM묶음키(접수키 = 송장번호·전화 제외) 단일 출처, 대표 = 상자 안 가장 작은 주문번호(상자배정). 끄기 설정·체크 연동은 없고, [택배 자동접수]·[택배 접수용 엑셀]이 체크한 행끼리 묶습니다. 묶지 않는 주문은 직접 등록·출고 차단(취소·반품·교환)·클레임 확인 필요(발송 전)·이름/주소 없음·발송 이후입니다. 주문 목록에 묶음 N 배지(같은 분의 아직 안 보낸 주문이 2건 이상일 때), 라벨은 이미 붙은 송장번호 단위(번호가 다르면 각각 1장), [송장번호 입력/수정]은 “같은 받는 분 주문 N건 전부 / 이 주문만”을 고릅니다. 구성원은 새 테이블 courier_receipt_members(마이그레이션 Beta50_CourierReceiptMembers)에 둡니다.
    • 다시 접수: 일부만 먼저 접수했다가 나머지를 발견하면 전부 체크해 다시 접수하며, 확인 창은 “이미 접수한 기록”·”이미 송장번호가 있는 주문”에 더해 “출력 요청 파일로 아직 출력하지 않은 이전 접수”·”같은 운송장으로 나갔던 주문 N건이 이번 접수에서 빠집니다”를 알립니다. 옛 접수 기록은 로젠이 이번 접수를 받은 것이 확인된 뒤에만 바뀝니다(오류·미대조면 옛 상자 그대로, 저장 실패면 송장번호를 채우지 않고 안내).
    • [송장번호 불러오기]·등록 직전 재확인·[출력 요청 파일 다시 만들기…]는 새로 묶지 않고 접수 기록으로 고정된 상자만 따릅니다.
    • 🔴 실기: 2026-10-08 테스트 DB에서 같은 분 G마켓 3건 → 로젠 1줄·운송장 1장·송장번호 셋 동일·구성 저장, G마켓+옥션 혼합은 2줄(사이트별 1장), 같은 번호로 G마켓 3건 ESM 발송처리 성공을 확인했습니다. 묶은 운송장의 출력 단계는 다른 출력 단계와 같이 실기 확인 전입니다.
  • 송장 재출력 — [더보기 ▾] → [선택 주문 송장 다시 출력…]. 체크한 주문 중 송장번호가 있는 로젠택배 주문(한 번에 10건까지)을 로젠 출력완료 탭에서 다시 출력합니다. 로젠이 새 송장번호를 채번하고 옛 번호는 원송장번호로 남으며, 새 번호는 출력 뒤 로젠 목록을 다시 읽어 [송장번호 불러오기]와 같은 경로로 반영합니다. 확인 창은 한 번(새 번호 생김·옛 송장 폐기·마켓 등록분은 셀러센터에서 수정). 출력 직전 목록 재조회로 번호가 그대로인 행만, 출력횟수 3 이상·발송됨·횟수 모름·아직 출력 전 제외, 출력 환경 점검, 로젠 작업 배타. 재출력 중이거나 새 번호를 확인 못 한 주문이 [선택 주문 송장 등록] 대상이면 확인 창에 경고합니다. 새 번호를 저장한 묶음의 접수일자는 새 행 날짜로 맞춥니다. 프린터 PC의 [받은 파일로 송장 출력…]에서는 재출력하지 않습니다. 🔴 프린터 PC 실기 전: 재출력 출력 창 이후 단계, 새 행의 접수일자, 출력완료 목록 노출은 스크립트 사본만으로 확정하지 못했고, 안 맞으면 출력하지 않고 멈추거나 새 번호를 저장하지 않습니다. 끄기 스위치 HANARO_LOGEN_REPRINT_DISABLED.
  • 접수 확인 창 배지 칸 확대 — 배지 열 76→136px·창 폭 880(최소 760), 긴 문구는 말줄임 + 전체 문구 툴팁. 주문 표 송장번호 칸의 출력 대기·접수 오류·인쇄됨에도 말줄임. 제보된 “표 깨짐”이 이 수정으로 해결됐는지는 확정하지 못했고(캡처 미수령, 확인 창 쪽 잘림만 측정과 일치), 125%·150% 배율은 미확인입니다.
  • 로젠 작업 창 유지 — 로젠 작업이 정상으로 끝나면 창을 닫지 않고 숨긴 채 보관해(로젠창보관소) 하나로가 켜져 있는 동안 다음 로젠 작업이 이어 씁니다. 이어 쓸 때 main.html로 다시 이동하고 beforeunload 대화상자는 자동 처리하며, 매 작업 전 로그인 상태(토큰 만료 24시간·”인증 토큰이 존재하지 않습니다” 모달·로그인 화면)와 empId·로그인 정보 지문을 확인해 다르면 닫고 새로 로그인합니다. 업무상 실패·멈춤·취소·예외·조용히 포기·계정 확인 멈춤이면 보관하지 않고 닫고, 설정에서 로젠 로그인 정보를 저장·변경·삭제하면 보관 창을 닫습니다. 보관 중에는 페이지를 중단(TrySuspend)해 메모리를 줄입니다. 🔴 실기 확인: 읽기 전용 [송장번호 불러오기] 연속 실행(로그인 1회 뒤 이어 쓰기 3회), 그리고 2026-10-08 [송장번호 불러오기]로 만든 보관 창을 이어 쓴 [택배 자동접수 → 접수만] 1건 정상 종료(로젠 창이 화면에 뜨지 않음을 육안 확인). 이어 쓴 창으로 하는 출력([이 PC에서 출력]·프린터 PC 출력·[받은 파일로 송장 출력…])은 현장 미확인입니다. 한계: 보관 창이 살아 있는 동안 WebView2 프로세스 6개가 남아 메모리를 더 씁니다(중단해도 개인 메모리 약 320~380 MB). 같은 프로필을 쓰는 다른 마켓 세션이 남는 경로는 확인하지 못했습니다. 끄기 스위치 HANARO_LOGEN_WINDOW_KEEP_DISABLED·..._KEEP_WRITES_DISABLED·..._SUSPEND_DISABLED.

Changed

  • 대시보드: 주문 흐름 보드 — 흐름 띠 4칸(① 신규 → ② 발주확인 → ③ 배송 중 → ④ 배송 완료)과 “흐름 밖” 칩(취소 요청·반품 요청·교환 재배송 대기), 단계 아래 할 일 칩 (송장번호 미등록·발송 지연·라벨 미인쇄 → ②, 배송 이상 → ③). 칸·칩을 누르면 주문 화면이 같은 건수로 열립니다. ④는 최근 30일 배송완료·구매확정만 세어(종전 “완료” 칸은 취소·반품완료·교환완료가 섞였음) 마켓별 표(최근 30일)의 “완료”와 다를 수 있습니다. 헤더 시각은 DB 재집계 시각이 아니라 실제 마켓 수집 시각 + 받는 중/받지 못한 마켓/추가 인증 상태입니다. “발송기한 임박·초과”는 코드 판정과 같은 “발송 지연”으로 이름을 맞췄습니다.
    • 매출은 전체 폭 카드(오늘·어제·이번 달 누적 — 매출 화면과 같은 계산 + 최근 7일 막대 + “매출 자세히 (F3)”). 마켓 카드는 표로(맨 아래 “최근 30일 합계”, 이슈 ≥1만 빨강).
    • 없어진 것: 전일 대비 %, 운영에서 한 번도 채워진 적 없던 “이번 주 발송량” 차트, 핵심 지표 카드 4개, 처리할 일 목록 카드. 주문 탭의 파란 “대시보드:” 배너는 마켓 탭 줄 끝의 필터 칩(“배송 중 58건 ✕”)으로 대체.
    • 본문 폭 640 미만이면 띠가 2×2로 접힙니다. 1분 갱신은 바뀐 항목만 반영해 칩 깜빡임을 없앴습니다. 어두운 테마의 주황 글자색을 밝게 조정(Soft 배경 위 4.87:1).
  • 쿠팡 과거 주문 받기 — 창에서 마켓마다 기간을 따로 고릅니다(주문 화면과 같은 기간 버튼, 기본은 주문 화면 기간). 쿠팡 소급 수집의 92일 상한을 풀어 31일 창으로 나눠 전부 조회합니다(평소 수집·자동 수집은 종전대로 92일). 다른 수집이 돌고 있으면 거절하지 않고 끝나기를 기다렸다가 자동 시작합니다(상단 줄에 안내와 [취소]). 다 받으면 표 기간을 받은 기간으로 맞추고 [마켓 동기화]를 최근 30일 창으로 1회 이어 돌립니다. 안내문을 8줄에서 3줄로 줄였고 쿠팡·스마트스토어 예상 시간 문구를 뺐습니다. 🔴 쿠팡이 약 90일보다 오래된 주문을 실제로 돌려주는지는 키 없는 환경이라 실측하지 못했습니다. 매출관리
  • 주문 화면 마켓 탭 — 연결된(활성) 판매처 기준으로 항상 만듭니다(주문이 없어도 (0)). 탭 숫자는 묶음이 아니라 목록에 보이는 행 수 하나입니다(쿠팡 (24) — 탭을 누르면 보이는 행 수·대시보드 건수와 같은 기준). 상태 문구(“조회 완료 — 1묶음 (2건)”)·접수 확인 요약은 묶음 수와 건수를 함께 씁니다. 기본 기간의 끝일이 앱을 켠 날에 고정되던 문제도 조회·동기화·과거 주문 창에서 오늘로 따라가게 고쳤습니다.
  • 택배 자동접수·엑셀 저장은 체크한 주문만 — “체크 없으면 표시된 전체” 규칙을 걷어 냈습니다. 체크 0건이면 확인 창·저장 창을 열지 않고 “택배 접수할 주문을 먼저 체크해 주세요.”(자동접수는 로젠을 부르지 않음). 전체를 보내려면 머리글의 전체 선택을 씁니다. 하단 선택 안내문과 버튼 툴팁도 맞췄습니다.
  • 로젠은 설정에 저장된 화주 ID/PW로만 로그인합니다 — 없으면 안내만 하고, 창에서 직접 로그인하는 길은 없앴습니다.
  • 받는 분 주소가 없는 주문(모든 마켓)은 접수 확인 창에서 주소 없음으로 체크가 풀리고 체크해도 접수하지 않으며, 택배 접수용 엑셀·라벨 인쇄에서도 뺍니다(뺀 묶음 수를 알림).
  • 로젠 로그인 계정 확인 — 로젠 로그인 직후 화면의 로그인 계정(empId)을 저장된 화주 ID와 대조합니다(공백·대소문자 무시). 다르면 로젠 로그인 정보를 지우고 한 번 다시 로그인하며, 그래도 다르거나 읽지 못하면 작업을 시작하지 않고 창을 보이지 않은 채 끝낸 뒤 “로젠에 로그인된 계정이 하나로에 저장된 화주 ID와 다르거나 확인하지 못해 멈췄습니다…”로 안내합니다(접수 기록은 되돌림). 끄기 스위치 HANARO_LOGEN_ACCOUNT_CHECK_DISABLED. 🔴 empId = 화주 ID라는 가정은 최상위 계정으로만 확인했고, 하위 ID 계정은 미확인입니다.
  • 마켓 계정 등록 때 계정 이름을 필수로 입력 — 이름 칸이 “계정 이름 (필수)”로 바뀌었고, 비어 있거나 규칙에 어긋나면 인증 창·검증을 시작하기 전에 막습니다(자동 이름 “스마트스토어 2” 생성 제거). [재인증] 화면은 이름 칸을 숨기고 수정은 설정의 [이름 바꾸기]만 씁니다. 이미 있는 ESM 판매처의 자동 기본 이름은 그대로 둡니다.
  • ESM 표시 이름 — 마켓 추가·처음 설정 화면과 설정의 ESM 카드에서 “ESM (G마켓·옥션)”으로 표시합니다(내부 값·저장 키는 “ESM” 그대로). ESM 안내 문구를 로젠 송장 자동 등록 기준으로 정정했습니다.
  • 숫자 글꼴·정렬(대시보드 매출 띠·F3 매출 화면) — 숫자 표시를 번들 Pretendard로 통일(PC마다 다른 대체 글꼴 때문에 “원”·”건” 위치가 흔들리던 것), 매출 띠 헤드라인 세로 가운데 정렬, F3 표 금액·건수를 이름 첫 줄과 같은 높이로.
  • 셀러 문서 — 마켓 추가하기(ESM·계정 이름 정하기)·FAQ·문제 해결(ESM 로그인·상태·송장, 관리자 권한 실행)·발송처리·매출관리(과거 주문 받기)·대시보드와 알림·시작하기·개인정보처리방침(판매처 목록에 ESM)과 화면 이미지(대시보드·설정 일반)를 갱신했습니다.

Fixed

  • 대시보드 “라벨 미인쇄”에 하나로가 마켓에 송장을 등록한 주문이 남던 문제 — 쿠팡은 등록 뒤에도 택배 수거 전까지 마켓 상태가 배송준비중에 머물러 다음 동기화까지 세어졌습니다. 송장번호 전송 일시가 있는 주문은 제외합니다(등록 뒤 번호가 바뀐 주문도 제외 유지). 쿠팡 Wing에서 직접 등록해 수집된 주문은 여전히 셉니다.
  • 대시보드 칩으로 들어간 주문 필터가 다음 진입에도 남던 문제 — 주문 화면 VM이 페이지 캐시로 살아 있어 필터가 이어졌고 칩 건수가 0이 돼 사라져도 목록이 “라벨 미인쇄 0건”으로 비었습니다. 다른 화면에서 주문 화면으로 다시 들어올 때 딥링크 필터를 이어받지 않습니다(칩을 눌러 온 이동은 그 뒤에 필터를 다시 걺).

내부 (화면 변화 없음)

  • 마이그레이션 Beta46_OrderSalesSite(orders.sales_site nullable 추가 + ESM 판매 사이트 시드), Beta46_CourierReceipts(courier_receipts CreateTable + 유일 인덱스). 업그레이드 경로 테스트(v0.3.8 경로·순서 뒤바뀜 경로) 추가. 🔴 develop에 머지된 뒤에는 이 마이그레이션들을 다시 만들지 않습니다.
  • EsmAdapter(수집·EsmAdapter.Send.cs 송장 전송), ESM주문상태표·ESM택배사코드 단일 출처, 로젠출력판정.출력가능 단일 허가 지점, 로젠작업잠금(셀러 로젠 작업 배타), 로젠번호재확인HostedService, 출력환경점검/오즈뷰어찾기. 판매처 이름 규칙 판매처이름정책(Domain 단일 출처), 저장소 “현재값일 때만 갱신”(EF·InMemory 쌍).
  • 시작 순서에 관리자 권한 재실행(관리자권한실행.시작, Velopack 훅 뒤·단일 실행 잠금 앞)과 UAC 전면 표시, 단일 실행 잠금의 접근 거부 처리, 셸열기 단일 경로를 추가했습니다.
  • 환경변수: HANARO_RUN_AS_ADMIN_DISABLED, HANARO_LOGEN_RECHECK_DISABLED, HANARO_LOGEN_ACCOUNT_CHECK_DISABLED(TestAppBuilder가 켬).
  • 로젠 목록 직접 조회가 변환차수를 ALL로 보내도록 고쳤습니다(''이면 로젠이 접수가 있어도 세 목록을 비워 줌 — 이 버전의 신규 흐름이 쓰던 조회).

[0.3.8] — 2026-10-06

주문·매출 화면의 표 위아래 버튼·필터 영역을 한 줄 도구막대로 줄여 같은 창에서 보이는 주문 수를 늘렸습니다. 팝업 계열(펼침 창·메뉴·콤보박스 목록·툴팁·달력)의 색을 하나로 테마 토큰으로 통일했습니다. 기능·동작 변화는 없습니다.

Changed

  • 주문 화면 배치(시안 A “위는 찾기, 아래는 작업”) — 제목·설명 줄을 없애고(창 상단 띠에 이미 “주문”이 있음), 맨 위 한 줄에 [마켓 동기화][▾] · [주문 직접 등록] · 기간 버튼 · 상태 · 검색(남은 폭)을 두었습니다. 마켓 chip은 밑줄 탭으로 바꾸고 같은 줄 오른쪽에 마지막 수집 시각을 붙였습니다. 하단은 “주문 받기 / 보내기 / 마켓에 알리기” 묶음 상자와 이름표를 떼고 한 줄로 — [엑셀 저장] | [로젠 자동 접수] [택배 접수용 엑셀] [더보기 ▾] | [선택 주문 송장 등록]. 순서 정보는 세로 구분선이 남깁니다. 모든 버튼의 Command·활성 조건·툴팁·우클릭 메뉴·조건부 줄(상태 문구, 처리할 일 배너, 교환 띠)은 그대로입니다. 1440×900 예시 데이터에서 표에 온전히 보이는 주문이 4건 반 → 8건 반. 주문 화면 구성
  • 기간 버튼 — 날짜범위 선택기(단축 버튼 + 시작일·종료일 칸)를 버튼의 펼침 창 안으로 넣었습니다. 버튼 글자는 날짜만 (09-30 ~ 10-06, 하루면 10-06, 해가 다르면 2025-12-20 ~ 2026-01-05). 단축 버튼 이름은 펼친 창의 강조 단추가 보여 주므로 버튼에 또 쓰지 않습니다. 기간을 바꾸면 즉시 재조회되는 동작은 그대로입니다. 펼친 창은 바깥을 누르면 닫힙니다(단축 버튼을 눌러도 자동으로 닫히지 않음). 펼친 창의 폭 상한을 넓혀 가로 스크롤이 생기지 않게 했습니다.
  • 하단 선택 안내 — 고정 안내문 대신 지금 상태를 보여 줍니다. 체크가 있으면 “선택 N건 — 엑셀·택배 접수·라벨 인쇄·송장 등록 모두 체크한 주문만”, 없으면 “체크 없음 — 엑셀·택배 접수는 표시된 전체 M건, 송장 등록·라벨 인쇄는 체크한 주문만”. 종전 안내문은 툴팁으로.
  • 매출 화면 — 같은 한 줄 도구막대(기간 버튼 · 기준: 주문일 · 상태 문구/[다시 시도] · [엑셀 내보내기]). 요약 카드·차트·표는 그대로.
  • 팝업 톤앤톤 — Flyout·MenuFlyout/ContextMenu·ComboBox 드롭다운·ToolTip·CalendarDatePicker 달력의 배경·테두리·항목 hover/선택 색을 Hanaro 테마 토큰(Light/Dark)으로 재정의했습니다. 종전에는 기본 테마의 회색 상자였습니다.
  • 셀러 문서 — 발송처리·라벨 인쇄·베타 시작가이드·매출관리·대시보드와 알림의 화면 설명과 화면 이미지를 새 배치로 갱신했습니다.

내부 (화면 변화 없음)

  • 기간 단축 버튼의 정의·판정을 한 곳으로 모아 날짜범위 선택기와 주문·매출 화면이 같은 규칙을 씁니다.
  • 마켓 chip 전용 고정색 변환기를 제거했습니다(토큰 경유로 대체).

[0.3.7] — 2026-10-05

쿠팡 취소·반품·교환을 받아 오고, 취소·반품·교환 상태 주문은 모든 마켓에서 송장 전송을 막았습니다. 수거가 끝난 교환 주문은 교환 재배송 송장을 하나로에서 마켓에 등록하고, 반품 상품 수거 완료(쿠팡 입고확인)도 하나로에서 알릴 수 있습니다. 마켓 밖에서 받은 주문을 직접 등록할 수 있게 했고, 주문 화면 버튼을 일 순서대로 정리했습니다. 주문이 많을 때 주문 화면과 [마켓 동기화]가 느리던 문제를 고치고, 구매자가 바꾼 배송지를 따라가도록 했습니다.

⚠️ 쿠팡을 쓰시는 분은 쿠팡 OPEN API 사용 범위에 “반품 / 교환”이 있는지 확인해 주세요.

  • 없으면 [마켓 동기화] 결과에 “쿠팡 Open API 키가 취소·반품·교환 조회를 거부해 받지 못했습니다”가 뜨고, 쿠팡 취소·반품·교환이 반영되지 않으며 완료된 주문 자동 정리도 쉬어 갑니다. 신규 주문·배송 중 주문은 그대로 받습니다. 절차: 마켓 추가하기 — 쿠팡
  • 업데이트 뒤 첫 동기화에서 최근 약 3개월(92일) 안의 쿠팡 취소·반품이 한꺼번에 반영되어 매출이 줄어 보일 수 있습니다.

Added

  • 쿠팡 취소·반품·교환 수집 — [마켓 동기화] 때 쿠팡 취소·반품·교환 목록을 함께 받아, 하나로에 이미 있는 쿠팡 주문의 상태를 취소요청·반품요청·교환요청 등으로 바꿉니다. 하나로에 없는 주문은 새로 만들지 않습니다. 일부 수량만 취소·반품된 주문은 상태를 바꾸지 않고 안내만 띄웁니다. 취소·반품 상태는 매출에서 빠지고, 대시보드 “이슈”에 쿠팡 건도 셉니다. 한 번 받은 취소·반품·교환 상태는 쿠팡 목록을 못 받은 회차에 일반 상태로 되돌리지 않습니다.
  • 취소·반품·교환 주문 송장 전송 차단(스마트스토어·쿠팡·카페24) — 송장 등록 확인 창에 제외로 표시하고 마켓에 보내지 않으며, 결과에 “보내지 않음”으로 따로 셉니다. [로젠 자동 접수] 확인 창에서는 기본으로 체크가 풀리고(다시 체크 가능), [택배 접수용 엑셀]·라벨 인쇄는 섞여 있으면 먼저 확인 창을 띄웁니다. 마켓에서 이미 재배송 처리된 교환 주문(교환재배송)은 “이미 다시 보냈는지 확인하세요”라고 따로 경고합니다. 카페24 교환의 원 주문 줄은 “원 주문 줄은 보내지 마세요”라고 알립니다. 발송처리
  • 교환 재배송 송장 마켓 등록(스마트스토어·쿠팡·카페24) — 반품 상품 수거가 끝나 새 교환 상품을 보낼 차례인 주문은 새 상태 교환재배송대기가 됩니다(상태 필터 “교환”·대시보드 “이슈”에 포함, 매출 포함). 이 주문은 [로젠 자동 접수]에서 기본으로 체크되고 배지에 교환 재배송이 보이며, 출력·접수 경고가 뜨지 않습니다. [선택 주문 송장 등록]은 이 주문을 마켓의 교환 재배송 절차로 보내고, 확인 창에 교환 재배송과 보낼 송장번호를 보여 줍니다. 보내기 직전에 마켓 상태를 다시 확인해 조건이 맞지 않으면 보내지 않고(교환 재배송 — 미전송), 처음 보낸 송장번호와 같은 번호는 막습니다. 성공하면 교환 재배송 송장 등록됨으로 표시하고, 다음 [마켓 동기화] 전에 다시 누르면 이미 등록 — 마켓 미전송으로 보내지 않습니다. 이미 등록한 주문을 다시 접수·출력·엑셀로 내보내면 “이미 마켓에 교환 재배송 송장을 등록한 주문입니다”라고 경고합니다.
    • 스마트스토어: 수거 완료 뒤 등록. 교환이 보류 중이면 등록하지 않고 “보류를 풀어 주세요”라고 안내합니다.
    • 쿠팡: 입고확인 뒤 등록(입고확인 후 최대 10분 뒤부터 가능). 회수가 필요 없는 교환은 Wing에서 처리합니다.
    • 카페24: 원 주문 줄이 아니라 별도 ‘교환 상품’ 줄로 등록합니다. 실계정 확인 중이며, 카페24가 거부하면 사유를 [상태] 열에 보여 줍니다.
    • 업데이트 전에 이미 수거가 끝난 스마트스토어 교환은 교환수거중으로 남을 수 있습니다 — [과거 주문 받기]로 그 기간을 다시 받으면 바뀝니다. 교환 재배송 송장 등록
  • 수거 완료 처리 — 교환수거중 주문을 체크하면 표 아래에 “교환 주문 N건 — 반품 상품을 받으셨나요?” 띠와 [수거 완료 처리]가 나타납니다(쿠팡이 섞이면 “쿠팡은 입고확인으로 처리돼요”). 확인 창을 거쳐 셀러가 누를 때만 마켓에 알리며, [마켓 동기화]·송장 등록 중에 저절로 호출하지 않습니다. 처리 직전에 마켓 상태를 다시 확인해 이미 처리·철회·보류된 교환은 처리하지 않고 이유를 보여 줍니다. 처리한 판매처는 바로 다시 받아 와 상태를 반영합니다. 되돌릴 수 없습니다. 교환 수거 완료 처리
  • 주문 직접 등록 — 견적서·전화·카카오톡·오프라인으로 받은 주문을 [주문 직접 등록] 창에서 넣습니다(한 번에 한 주문, 상품 여러 줄). 목록에 초록 H 배지·”직접 등록” 칩으로 보이고, 매출에도 “직접 등록”으로 잡힙니다. 주문번호는 견적서·발주 번호를 그대로 넣거나, 비우면 H261005-001처럼 자동으로 매깁니다. [로젠 자동 접수]·[택배 접수용 엑셀]·라벨 인쇄는 마켓 주문과 같고(배송지 재조회 없음), 송장번호가 붙으면 자동으로 배송중이 됩니다. [선택 주문 송장 등록]·발주확인·교환 수거 완료 등 마켓 절차에서는 제외됩니다. 행 오른쪽 클릭 메뉴로 직접 등록 주문 수정…·상태 변경·직접 등록 주문 삭제…(되살릴 수 없음)를 합니다. 송장번호가 붙은 뒤에는 금액·발송기한·주문자만 고칠 수 있고 지울 수 없습니다. 로젠 결과 엑셀을 짝지을 때 판매처가 다른데 주문번호가 같은 주문이 섞이면 자동으로 채우지 않고 미매칭: 주문번호 겹침 N건으로 알립니다(마켓끼리 겹친 경우도 같습니다). 주소 검색·엑셀로 여러 주문 가져오기·삭제 복원·배송 완료 자동 반영은 아직 없습니다(예정). 직접 받은 주문 등록
  • [새 소식] — 사이드바 아래 메뉴에서 패치노트·공지를 앱 안에서 봅니다. 설치한 버전 이하의 업데이트 소식만 보이고, 셀러가 직접 할 일이 있는 소식은 시작 후 한 번 창으로 띄웁니다. 대시보드와 알림
  • 엑셀 저장 창 — 주문 엑셀·택배 접수용 엑셀·매출 리포트·로젠 결과 엑셀을 저장하면 완료 뒤 [파일 열기]·[폴더 열기]를 누를 수 있습니다. 로젠 결과 엑셀로 송장번호를 한 건도 못 채웠으면 “송장번호 자동 반영 실패 — 파일을 직접 확인하세요.”를 띄웁니다.
  • 왼쪽 메뉴 접기 — [메뉴 접기]로 사이드바를 아이콘만 남겨 본문을 넓힙니다. 상태는 다음 실행에도 유지됩니다.
  • 주문 표 열 추가·너비 조절 — 주문일자·관리코드(판매자 상품·옵션 관리코드)·수량 열(정렬 가능)과 관리코드 검색. 열 경계를 끌어 너비를 바꾸고 더블클릭으로 초기화하며, 표가 넓으면 가로로 스크롤합니다.
  • 대시보드 바로가기·셀러센터 자동 로그인 — 대시보드 숫자를 누르면 스마트스토어·쿠팡은 셀러센터의 해당 화면을 하나로 안 창으로 엽니다(쿠팡 이슈·카페24는 하나로 주문 화면). 설정 → 마켓 계정의 [셀러센터 로그인]에 저장한 아이디·비밀번호로 자동 입력하며, 2단계 인증은 셀러가 직접 합니다. 성공 없이 두 번 실패하면 계정 잠금을 막기 위해 멈춥니다.

Changed

  • 주문 화면 버튼 3묶음 — 일 순서대로 위쪽 주문 받기([마켓 동기화]·[주문 직접 등록]), 아래쪽 보내기([로젠 자동 접수]· [택배 접수용 엑셀]·[더보기 ▾])와 마켓에 알리기([선택 주문 송장 등록])로 묶었습니다. 색이 채워진 버튼은 [선택 주문 송장 등록] 하나입니다. [엑셀 저장]은 어느 묶음에도 속하지 않는 보조 도구로 아래에 둡니다.
  • [과거 주문 받기] 위치 — [마켓 동기화] 옆 ▾ 메뉴 안(과거 주문 받기…)으로 옮겼습니다(활성 조건은 같음). 한 번 더 눌러야 합니다.
  • [선택 주문 라벨 인쇄] 위치 — 하단 “보내기” 묶음의 [더보기 ▾] 메뉴 안(선택 주문 라벨 인쇄…, 다시 인쇄용)으로 옮겼습니다. 한 번 더 눌러야 합니다. 주문을 체크해 두고 행을 오른쪽 클릭하면 체크한 주문 라벨 인쇄…로도 찍을 수 있습니다. 이 박스 라벨 인쇄…는 그대로입니다.
  • 주문·매출 화면 — 기간을 바꾸면 바로 조회 — 기간 단축 버튼·시작일·종료일을 바꾸는 즉시 목록(매출 화면은 집계)을 다시 불러옵니다. 같은 날 안에서 시각만 바뀌는 경우는 다시 읽지 않고, 단축 버튼처럼 시작·종료가 연달아 바뀌면 마지막 조건의 결과만 남습니다 (먼저 시작해 늦게 끝난 옛 기간 결과가 새 기간 결과를 덮지 않습니다 — 매출 화면에는 이 보호가 없었어서 새로 넣었습니다). 주문 화면에서 마켓 동기화·송장 등록·수거 완료 처리가 도는 중에 기간·상태를 바꾸면 그 작업이 끝난 뒤 마지막 조건으로 한 번만 조회합니다 (송장 등록·수거 완료 처리 뒤에는 체크해 둔 주문이 체크된 채 남고, 마켓 동기화 뒤에는 종전처럼 체크가 풀립니다). 송장 등록·수거 완료 처리의 결과 안내(성공·실패 건수)는 “조회 완료”로 덮지 않습니다 — 다만 송장 등록 뒤 다시 불러오면 표 [상태] 열의 주문별 결과(“등록 실패: …” 등)는 지워지므로 안내 끝에 그 사실을 한 줄 덧붙입니다. 마켓 동기화는 종전처럼 끝나면 목록을 다시 읽어 상태 줄이 “조회 완료”로 바뀝니다(동기화 결과는 위쪽 표시줄에 잠시 남습니다. 다시 읽기가 실패했을 때만 동기화 결과 아래에 조회 실패 안내가 붙습니다).
  • [목록 새로고침] 버튼 제거 — 화면과 저장된 주문이 어긋난 경우(주문을 찾을 수 없음, 송장번호 반영 실패, 목록 갱신 중 오류, 직접 등록 주문이 그사이 지워짐, 교환 수거 완료 처리의 “대상 아님”)에는 목록을 저절로 한 번 다시 읽은 뒤 그 사실을 알립니다 (그 다시 읽기가 실패하면 조회 실패 안내가 남습니다 — 교환 수거 완료 처리·직접 등록 주문 저장/삭제·송장번호 입력·마켓 동기화·과거 주문 받기처럼 작업 결과가 있는 경우는 결과 아래에 실패 안내를 붙입니다). 다시 읽은 뒤에도 셀러가 체크해 둔 주문은 체크된 채 남습니다(사라진 주문은 빠짐 — “목록 갱신 중 오류”만은 체크를 되살리다 난 오류라 체크를 풀고 다시 골라 달라고 알립니다). 목록 조회 자체가 실패했을 때만 상태 줄에 [다시 시도]가 나타나고, 자동으로 되풀이하지 않습니다. 화면 문구·FAQ의 “[목록 새로고침] 후 다시 시도” 안내도 이에 맞춰 고쳤습니다.
  • 매출 화면 [매출 보기] 버튼 제거 — 첫 진입·다른 화면의 주문 받기·송장 전송 뒤 집계는 원래 자동이었고, 기간 변경도 이제 바로 집계하므로 버튼이 하던 일이 없어졌습니다. 매출을 불러오지 못했을 때만 안내 줄 옆에 [다시 시도]가 나타나며 자동으로 되풀이하지 않습니다. 엑셀 내보내기의 기간 표기는 종전대로 마지막으로 집계에 성공한 기간입니다(새 기간 집계가 실패·진행 중이면 옛 기간으로 찍힙니다).
  • 날짜 선택기 “시작일 ~ 종료일” — 두 칸에 라벨을 붙이고 화면 용어를 “끝일” → “종료일”로 바꿨습니다. 종료일보다 늦은 시작일을 고르면 종료일이 같은 날로(반대도 마찬가지) 따라옵니다. 주문·매출 화면 공통입니다.
  • [마켓 동기화] 시간 단축 — 받아 온 주문을 200건씩 묶어 저장해 저장 시간을 크게 줄였습니다(합성 데이터 실측 3,000건 첫 수집 약 4.1초 → 0.7초, 마켓 응답 시간 제외). 배송조회는 [마켓 동기화]가 기다리지 않고 끝난 뒤 따로 돌며, 끝나면 화면이 새 값을 읽습니다 — 동기화 직후 잠깐은 배송 상태가 이전 값입니다. 진행 건수는 묶음 단위로 올라가고, 동기화가 중간에 끊기면 마지막 묶음(최대 200건)은 다음 동기화가 채웁니다.
  • 쿠팡 쓰기 요청 자동 재시도 제거 — 송장 업로드·발주확인·문의 답변·송장 취소 통보·교환 재배송 송장·입고확인을 일시 오류(5xx·시간 초과)에 자동으로 다시 보내지 않습니다. 같은 송장이 두 번 등록되는 것을 막기 위해서이며, 실패로 끝나면 셀러가 다시 누르면 됩니다.
  • 주문 화면 첫 진입이 빨라졌습니다 — 보이는 행만 그리도록 바꿨습니다. 탭을 떠났다 돌아와도 보던 위치가 유지됩니다. 세로 스크롤바 막대 크기가 조금 달라질 수 있습니다.
  • [과거 주문 받기]가 백그라운드로 진행됩니다 — 위쪽 줄에 마켓·날짜·진행률과 [취소]를 표시하고, 받을 마켓을 고를 수 있습니다. 취소해도 이미 저장된 주문은 남습니다. 받는 동안 [마켓 동기화]·[과거 주문 받기]·송장 등록과 주문 행 수정은 잠깁니다. 스마트스토어 요청 한도 거절을 줄이도록 요청 간격 조절을 고쳤습니다(전체 시간이 줄어든다는 뜻은 아닙니다).
  • 글자 크기·대비 — 기본 글자를 한 단계(1px) 키우고 연한 회색 글자를 더 진하게 했습니다(Light/Dark 모두).
  • 구매자 배송지 변경 반영 — [마켓 동기화]가 마켓의 바뀐 수령자 정보를 반영합니다. 셀러가 하나로에서 고친 주소는 덮지 않고 “⚠ 마켓 주소와 다름”으로 표시하고, 이번 업데이트 전에 받은 주문은 기준을 알 수 없어 “⚠ 주소 확인”으로 표시합니다. [로젠 자동 접수]·[택배 접수용 엑셀] 직전에 마켓 주소를 다시 조회해 달라진 점을 확인 창으로 알리고, 송장 발급 뒤 주소가 바뀌면 해당 주문에 경고를 띄웁니다.
  • 주문 상태 “발송 전”을 발주확인으로 바꾸고 상태를 여러 개 고를 수 있게 했습니다. 대시보드 “대기”도 “발주확인”으로 바꿨습니다.
  • 송장 입력 창의 주문 정보를 선택·복사할 수 있고, 송장번호 붙여넣기 때 숫자만 남깁니다.
  • 쿠팡 상품주문번호 칸에 옵션 ID 대신 묶음배송번호를 표시합니다(마켓 전송에 쓰는 값은 그대로).
  • 쿠팡 [마켓 동기화]가 취소·반품·교환 목록 조회로 판매처당 약 8초 이상 늘었습니다(위 저장 시간 단축과 별개 — 조회 요청 수가 늘어난 몫).

Fixed

  • [로젠 자동 접수]로 송장은 출력됐는데 하나로 송장번호가 “미지정”으로 남던 문제 — 로젠 용지 선택 창이 늦게 뜨면 한 번만 확인하고 멈췄습니다. 이제 느린 단계(서버전송 확인·용지 선택·인쇄·출력 완료·엑셀저장)를 단계별로 충분히 기다리고 경과 시간을 보여 줍니다. 결과 엑셀 없이 로젠 창을 닫으면 송장번호가 반영되지 않았다고 알려 줍니다. 문제해결
  • 기간 칸 글자가 잘리고 달력 버튼이 안 보이던 문제 — 칸 폭이 고정(118px)이라 날짜가 2026-09-2까지만 보였고, 달력 아이콘을 투명하게 숨겨 버튼이 폭만 차지했습니다. 고정 폭을 없애고(최소 150px) 아이콘을 다시 보이게 했습니다 — 주문 직접 등록 창의 주문일·발송기한 칸에도 아이콘이 보입니다.
  • 주문 상세 창이 떠 있는 동안 주문 목록 스크롤 위치가 튀던 문제.
  • 스마트스토어 키를 저장한 뒤에도 “연결 확인 필요” 배너가 남던 문제, 커머스API 연결에 성공했는데 IP 등록 안내가 함께 뜨던 문제.
  • 상단 배너의 긴 문구가 잘리던 문제.

[0.3.6] — 2026-10-02

스마트스토어를 네이버 공식 커머스API로 연결하도록 바꿨습니다. 주문을 받아 오는 기간을 모든 마켓 약 3개월(92일)로 맞추고, 쿠팡·카페24에서 요청이 몰릴 때 주문 받기가 실패하지 않도록 고쳤습니다.

⚠️ 스마트스토어를 쓰시는 분은 업데이트 후 커머스API 키를 한 번 등록해 주셔야 주문 받기·송장 등록이 다시 동작합니다.

  • 커머스API센터에서 애플리케이션을 만들고, 발급된 애플리케이션 ID·시크릿을 하나로에 넣는 방식입니다. 절차는 마켓 추가하기 — 스마트스토어에 있습니다.
  • 이미 쓰시던 스마트스토어 계정은 지우거나 새로 추가하지 마세요. 설정 → 마켓 계정에서 기존 카드의 [재인증]을 눌러 키를 넣어야 합니다. 새로 추가하면 같은 주문이 두 번 들어옵니다.
  • 키를 넣기 전에는 앱을 켤 때 “커머스API 키가 등록되지 않았습니다” 안내가 뜨고 스마트스토어 주문 받기가 멈춥니다. 이미 받아 둔 주문·송장·매출은 그대로 남아 있습니다.

Changed

  • 스마트스토어 연결이 네이버 로그인에서 커머스API 키로 바뀌었습니다 — 네이버 아이디·비밀번호로 로그인 창을 띄워 연결하던 방식을 더 이상 쓰지 않습니다. 셀러가 직접 만든 커머스API 애플리케이션의 키로 연결합니다.
    • 키를 넣는 화면에서 [연결 테스트]를 누르면, 커머스API센터에 등록해야 하는 이 PC의 인터넷 주소(IP)를 알려 드립니다.
    • 인터넷 주소가 바뀌면(공유기 재시작, 다른 장소에서 노트북 사용 등) 주문 받기가 멈추고 새 주소를 알려 드립니다. 커머스API센터에 그 주소를 추가하면 다시 동작합니다.
    • 같은 애플리케이션을 다른 스마트스토어 계정에 이미 넣어 두었다면 저장이 막히고, 어느 계정에 들어 있는지 알려 드립니다.
    • 판매자센터에서 먼저 발주확인한 주문도 발주확인된 것으로 보고 송장 등록을 이어 갑니다. 취소·반품 등이 진행 중인 주문은 그 사유를 알려 드립니다.
    • 처음 연결 화면(온보딩)의 스마트스토어 안내도 공식 연결 기준으로 바뀌었습니다.
  • 스마트스토어는 두 번째 [마켓 동기화]부터 훨씬 빨라집니다 — 지난번 이후 바뀐 주문만 받기 때문입니다. 키를 넣고 처음 받을 때는 최근 3개월을 하루씩 확인해 1분 가까이 걸리고, 그 뒤로는 보통 몇 초면 끝납니다.
  • 주문을 받아 오는 기간을 모든 마켓 약 3개월(92일)로 맞췄습니다.
    • 앱을 켤 때 하는 자동 동기화가 종전 6개월(180일)에서 3개월로 바뀌었습니다.
    • 쿠팡은 종전에 최근 31일까지만 받았습니다. 이제 3개월치를 받습니다.
    • 카페24는 3~6개월 전 주문의 상태(반품·구매확정 등)가 더 이상 자동으로 갱신되지 않습니다. 주문 자체는 그대로 남아 있습니다.

Added

  • [과거 주문 받기] — 주문 화면(F2)에서 고른 기간을 처음부터 다시 받습니다. 하나로를 새로 깔았거나 마켓을 새로 연결해 그 전 매출이 비어 있을 때 씁니다. 한 번에 최대 2년(730일)까지 받을 수 있습니다. 매출관리 — 과거 주문 받기
    • 스마트스토어는 고른 시작일부터 오늘까지 하루씩 확인해서, 1년이면 3분 정도 걸립니다. 시작 전에 예상 시간을 알려 드립니다.
    • 이미 받아 둔 주문은 지우지 않고 갱신만 합니다.

Fixed

  • 쿠팡 주문 받기가 “호출 한도” 오류로 실패하던 문제 — 쿠팡에 요청을 연달아 보내다 한도에 걸리면 그 상태의 주문을 받지 못했습니다. 이제 요청 간격을 띄우고, 한도에 걸리면 잠시 기다렸다 다시 시도합니다.
  • 카페24도 “호출 한도”에 걸려 실패하지 않도록 했습니다 — 한 번에 받는 주문 수를 늘려 요청 횟수를 줄이고, 한도에 걸리면 잠시 기다렸다 다시 시도합니다.
  • 카페24와 같은 아이디를 쓰는 다른 마켓 계정을 지우면 카페24 연결이 끊길 수 있던 문제 — 예를 들어 스마트스토어 계정 아이디와 카페24 몰 ID가 같으면, 카페24 연결 정보가 스마트스토어 계정 쪽에 저장될 수 있었습니다. 이제 카페24 계정에 저장합니다(이미 저장된 연결은 그대로 이어서 씁니다).

[0.3.5] — 2026-10-02

업데이트할 때 보이는 화면과 업데이트 뒤 아이콘을 다듬었습니다.

Fixed

  • 업데이트 뒤에도 바로가기·작업 표시줄 아이콘이 예전 것으로 보이던 문제 — 창 제목줄 아이콘은 새것인데 바탕화면·시작 메뉴 바로가기와 작업 표시줄에는 옛 아이콘이 남았습니다. Windows가 저장해 둔 옛 아이콘을 계속 쓰기 때문입니다. 이제 새 버전을 처음 켜고 몇 초 뒤 하나로가 Windows에 아이콘을 다시 읽으라고 한 번 요청합니다(이때 바탕화면 아이콘이 잠깐 깜빡일 수 있습니다). 그래도 옛 아이콘이면 문제해결의 순서대로 해 주세요.
  • 업데이트 내려받기가 중간(예: 50%)에서 멈춘 것처럼 보이던 문제 — 하나로가 실제로 내려받거나 받은 파일을 확인하는 중에도 숫자가 한동안 그대로라, 멈춘 줄 알고 앱을 끄게 될 수 있었습니다.
    • “하나로 업데이트” 창에 경과 시간(예: “경과 1분 12초”)과 깜빡이는 점이 보여, 숫자가 그대로여도 진행 중인 것을 알 수 있습니다.
    • 숫자가 8초 넘게 그대로면 “숫자가 멈춰 보여도 계속 기다리는 중입니다 — 앱을 끄거나 다시 켜지 마세요”라고 안내합니다.
    • 100%가 된 뒤에는 “새 버전을 다 받았습니다 — 받은 파일을 확인하고 있습니다”로 바뀝니다.
    • 내려받기가 처음부터 다시 시작되면 숫자가 줄어든 이유를 “처음부터 다시 내려받고 있습니다”로 알려 줍니다 (종전에는 직전 숫자에 멈춰 있었습니다).
    • 상단 업데이트 알림에도 100%가 된 뒤의 “다 받았습니다 — 받은 파일을 확인하고 있습니다”와 “처음부터 다시 내려받고 있습니다” 문구가 같게 나오고, 진행 중에는 아이콘이 깜빡입니다(경과 시간과 8초 안내는 시작 창에만 있습니다).
    • 숫자가 멈춘 채 기다려 주는 시간을 30초에서 90초로 늘렸습니다 — 정상 진행 중인데 시작 창이 먼저 닫히고 뒤로 넘어가는 일을 줄입니다.
  • 업데이트를 적용하고 다시 켜진 직후 “하나로 업데이트” 창이 또 떠 새 버전을 확인하던 문제 — 방금 새 버전으로 바뀐 참이라 확인할 것이 없는데도 창이 한 번 더 떴습니다. 이제 업데이트 직후 다시 켜질 때는 이 창 없이 바로 메인 화면이 뜹니다. 새 버전 확인은 몇 초 뒤 상단 알림 쪽에서 평소처럼 합니다.

[0.3.4] — 2026-10-01

0.3.3을 쓰는 분은 이 버전부터 앱을 켤 때 “하나로 업데이트” 창에서 바로 적용됩니다.

Changed

  • 앱 아이콘 색을 앱 화면과 맞췄습니다 — 0.3.3의 올빼미 아이콘은 검은 바탕에 파랑·노랑이라 밝은 제목줄에서 검은 네모가 튀어 보였습니다. 바탕을 앱과 같은 한지색으로 바꾸고, 올빼미 색을 하나로 로고의 주홍 계열로 맞췄습니다.

[0.3.3] — 2026-10-01

앱을 켤 때 새 버전을 먼저 적용하는 시작 화면, 새 앱 아이콘, 로젠 자동 접수·대시보드 결함 수정, AI 직원 답변이 두 번 올라가는 것을 막는 수정을 모았습니다.

Added

  • 하나로에 아이콘이 생겼습니다 — 지금까지는 기본 아이콘으로 떠 작업 표시줄에서 찾기 어려웠습니다. 이제 실행 파일, 창 제목줄, 작업 표시줄, 마켓 로그인 창, 설치 프로그램에 같은 올빼미 아이콘이 보입니다.
  • 앱을 켤 때 새 버전을 먼저 적용합니다 — 시작하면 작은 “하나로 업데이트” 창이 떠 새 버전을 확인하고, 있으면 메인 화면을 띄우기 전에 내려받아(진행률 % 표시) 적용한 뒤 다시 시작합니다. 종전에는 앱을 쓰는 중에 뒤에서 내려받아, [지금 다시 시작]을 누르거나 앱을 다시 켜기 전까지는 옛 버전으로 쓰셨습니다.
    • [나중에]를 누르면 지금 버전으로 바로 시작합니다. 내려받기는 끊기지 않고 뒤에서 이어지며, 상단 알림에 같은 진행률로 이어서 표시됩니다(처음부터 다시 받지 않습니다). 창의 X 버튼도 [나중에]와 같습니다.
    • 인터넷이 없거나 서버가 느리면 기다리지 않고 바로 시작합니다(확인은 최대 5초, 내려받기가 30초 넘게 멈추면 뒤로 넘깁니다).
    • 적용이 실패해 옛 버전으로 다시 켜진 경우, 같은 버전을 하루 안에 다시 자동 적용하지 않고 상단 알림으로 넘깁니다 — 켤 때마다 적용을 되풀이하지 않게 합니다.
    • 0.3.3을 설치한 뒤 다음 업데이트(0.3.4)부터 동작합니다. 0.3.3으로 올라갈 때는 종전처럼 상단 알림으로 받아 [지금 다시 시작]을 누르거나 앱을 다시 켜면 적용됩니다.
    • 시작하기 — 자동업데이트

Fixed

  • 로젠 인쇄 창의 [확인]이 자동으로 눌리지 않으면 송장번호를 손으로 넣어야 하던 문제 — [로젠 자동 접수] 중 운송장 인쇄 창의 [확인]을 하나로가 누르지 못하는 PC(예: 인쇄 프로그램이 관리자 권한으로 뜨는 경우)에서는, 셀러가 창을 찾아 누르는 사이 자동 진행이 끊겨 결과 엑셀 저장·송장번호 자동 입력까지 가지 못했습니다. 이제 인쇄 창을 앞으로 띄우고 “인쇄 창의 [확인]을 직접 눌러 주세요”라고 안내한 뒤, 누르실 때까지(최대 5분) 기다렸다가 송장번호 자동 입력까지 이어갑니다. 문제해결
    • 자동으로 누를 수 없는 경우를 바로 알아채고 곧장 안내로 넘어갑니다(몇 초씩 헛시도하지 않습니다).
  • 대시보드의 AI 직원 추세선이 그려지지 않던 문제 — 자리만 잡히고 선이 비어 있었습니다. 또 데이터가 연결되지 않아 늘 비어 있던 KPI 카드 4장(신규 주문·발송 대기·배송 중·취소·반품)의 작은 추세선 자리를 없앴습니다.

  • AI 직원(유료): 답변을 올리는 도중 앱이 꺼지면 같은 답변이 두 번 올라갈 수 있던 문제 — 마켓에 답변을 보내는 중에 앱이 꺼지거나 등록이 중간에 취소되면, 하나로는 보냈는지 모른 채 다시 보낼 수 있었습니다. 이제 보내기 직전에 기록을 남겨, 결과를 모르는 답변은 자동으로 다시 보내지 않습니다. 약 11분 뒤 승인함의 실패 목록에 “결과 확인 필요”로 표시되며, 마켓 판매자 센터에서 확인한 뒤 둘 중 하나를 눌러 주세요.
    • [이미 올라가 있음 — 완료 처리]: 마켓에는 아무것도 보내지 않고 완료로 바꿉니다(하나로가 직접 확인한 것이 아니라는 표시가 남습니다).
    • [다시 시도]: 답변이 없는 것을 확인한 경우에만 누르세요. 한 번 더 확인을 받은 뒤 보냅니다.
    • ⚠️ 업데이트 직후 “결과 확인 필요”가 몇 건 뜰 수 있습니다. 업데이트 전부터 승인됐지만 등록 결과가 남지 않은 답변이 여기에 들어오며, 실제로는 보내지 않은 건도 섞여 있습니다. 마켓에서 확인한 뒤 처리해 주세요.
    • ⚠️ 이 버전 이후 옛 버전으로 되돌려 설치하면 “결과 확인 필요” 답변이 자동으로 다시 보내질 수 있습니다. 되돌리기 전에 먼저 처리해 주세요.

내부 (화면 변화 없음)

  • AI 직원(유료) [초안 만들기]가 과거 문의를 찾는 범위의 기준점이 앱을 켤 때마다 바뀌던 것을, 처음 고용이 확인된 시각으로 고정했습니다. 종전보다 찾는 범위가 줄지는 않습니다.
  • AI 직원(유료) 백그라운드 작업이 멈추는 순간 깨우기 요청이 겹치면 오류가 날 수 있던 경합을 막았습니다. 무료 이용자 화면에는 영향이 없습니다.
  • 셀러 문서에 앱 화면 스크린샷을 추가하고, 문서 사이트 배포가 실패하던 원인을 바로잡았습니다.

[0.3.2] — 2026-09-29

0.3.1 이후 셀러가 겪던 결함을 모았습니다. 첫 실행 때 데이터베이스가 깨질 수 있던 문제 수정이 들어 있어 받으시는 것을 권합니다.

Fixed

  • 🔴 첫 실행 때 앱이 두 개 동시에 떠 데이터베이스가 깨지던 문제 — 하나로를 처음 켤 때 실행이 두 번 겹치면 두 프로세스가 같은 빈 데이터베이스를 동시에 만들면서 주문 테이블이 중간 상태로 남았습니다. 그 뒤로는 앱을 다시 켤 때마다 같은 자리에서 실패해 스스로 복구되지 않았고, 스마트스토어·쿠팡·카페24 계정 등록이 모두 실패했습니다. 이제 한 사용자 계정에서 하나로는 하나만 실행되고, 이미 켜져 있으면 그 창을 앞으로 가져옵니다.
    • 이미 이 문제를 겪어 계정 등록이 실패하는 분은 이 업데이트만으로는 복구되지 않습니다. 예방 수정입니다. 운영팀에 문의해 주세요.
    • 실행 잠금을 만들 수 없는 환경에서는 잠금 없이 그대로 실행됩니다 — 드문 동시 실행을 막으려다 앱이 아예 안 켜지는 쪽이 더 나쁘기 때문입니다.
  • 비밀번호 칸에 ?를 입력할 수 없던 문제 — 도움말 패널 단축키(Shift+/)가 입력란에서도 키를 가져가, ?를 치면 도움말이 열리고 글자는 들어가지 않았습니다. 스마트스토어 비밀번호·로젠 비밀번호·전역 검색창 등 모든 입력란이 영향을 받았습니다. Shift+/ 단축키를 없앴습니다. Ctrl+/와 상단 도움말 버튼은 그대로입니다.
  • 계정 등록이 실패해도 원인을 알 수 없던 문제 — “계정 등록에 실패했습니다”만 뜨고 실제 사유가 화면에도 로그에도 남지 않았습니다. 이제 가장 안쪽 오류 메시지를 함께 보여 주고 기록에도 남깁니다.
  • 카페24 [연결하기]의 저장 실패가 “OAuth 인증 중 오류”로 보이던 문제 — 카페24 설정 문제로 오해할 수 있었습니다. 이제 “계정 등록에 실패했습니다”로 정확히 구분해 보여 주고, 그 경우 카페24 인증을 시작하지 않습니다.
  • 화면의 버전 표기가 실제 설치본과 달랐던 문제 — 설치본이 0.3.x인데도 화면에는 Hanaro 0.1.0-alpha · 2026.05.09가 떠 있었습니다. 자동 업데이트가 실제로 적용됐는지 확인할 단서가 틀린 값이었습니다. 이제 실행 중인 버전을 읽어 표시하고, 근거 없는 날짜는 뺐습니다.
  • 주문 화면에 처음 들어오면 어떤 날짜 칩도 선택되지 않던 문제 — 기본 기간이 31일이라 “최근 30일” 칩과 한 칸 어긋나 있었습니다. 이제 “최근 30일”이 선택된 채로 뜨고, 대시보드 마켓 카드도 같은 기간을 봅니다.
  • 설정 ▸ 택배사 탭이 스크롤되지 않아 [저장] 버튼이 창 밖으로 밀릴 수 있던 문제 — 창이 낮을 때 로그인 폼까지 펼치면 새 카드의 버튼이 보이지 않았습니다.
  • 작업 확인창의 행 글자가 위로 붙던 문제 — 체크박스가 들어가며 행이 높아진 뒤 글자가 칸 위쪽에 그려졌습니다.

Added

  • 로젠 접수 보내는 사람 설정 — 설정 ▸ 택배사에 “로젠 접수 보내는 사람” 카드가 생겼습니다(보내는 사람 · 전화번호). 종전에는 로젠 화주 계정의 기본 보내는 사람으로만 접수됐습니다. [로젠 자동 접수]와 수동 [택배 접수용 엑셀] 둘 다 적용됩니다.
    • 둘 다 비우고 저장하면 저장값이 지워져 로젠 기본 보내는 사람으로 돌아갑니다.
    • 보내는 사람만 바꿀 때 로그인 창이 뜨지 않습니다(로그인 저장과 분리).
    • 전화번호는 개인정보라 설정 파일에 평문으로 두지 않고 로젠 아이디·비밀번호와 같은 암호화 저장소(DPAPI)에 보관합니다.
  • 작업 확인창에서 체크를 풀어 주문을 뺄 수 있습니다 — [로젠 자동 접수]·[선택 주문 송장 등록] 확인창에서 뺄 주문을 발견하면, 창을 닫고 주문 화면 체크를 고쳐 다시 열어야 했습니다. 이제 그 자리에서 체크를 풀면 체크된 것만 실행됩니다. 창에서 푼 체크는 이번 실행에만 쓰이고 주문 화면 체크는 바뀌지 않습니다.
  • 날짜 칩을 누르면 선택한 칩이 표시됩니다 — 어느 기간을 보고 있는지 화면에서 알 수 있습니다.
  • 사이드 메뉴에 현재 보고 있는 항목이 표시됩니다.
  • 마켓 재인증에서 비밀번호를 비워 두면 저장된 값을 씁니다 — 매번 다시 입력하지 않아도 됩니다. 저장된 값은 같은 아이디일 때만 사용합니다.

Changed

  • 설정 화면 정리 — 탭을 합치고, 쓰이지 않던 인쇄 보정값을 없애고, 택배사 탭의 버튼 겹침을 고쳤습니다. 일반 탭은 섹션 카드 2단으로 펼쳐지고, 마켓 계정 탭은 세로로 스크롤됩니다.
  • 마켓 재인증 시 그 계정 마켓의 입력 폼만 보입니다 — 종전에는 모든 마켓 폼이 함께 떴습니다.
  • 압축 모드 단축키(Ctrl+\)를 없앴습니다 — 상단 [압축] 버튼과 설정 토글로 켜고 끕니다.

내부 (화면 변화 없음)

  • AI 직원(유료) 준비 작업이 포함돼 있으나 무료 이용자 화면에는 나타나지 않습니다 — 문의 조회·수집·답변 등록 배선, 승인함 후속, 중복 전송 차단.
  • CI·테스트 정비 — 테스트가 멈추면 어느 테스트인지 남기는 타임박스, 병렬 실행 설정 가드, 주문 화면 상태 필터의 조회 경로 정리.

[0.3.1] — 2026-09-20

0.3.0 사용 중 드러난 문제를 고칩니다. 아래 수정은 0.3.1을 받으셔야 적용됩니다.

Fixed

  • 자동 업데이트 화면이 “내려받는 중 N%”에서 멈추던 문제 — 진행률이 뒤늦게 도착해 “준비됨” 표시를 덮어쓰는 경우가 있었습니다. 그러면 [지금 다시 시작] 버튼이 보이지 않아, 다 받아 놓고도 적용할 수 없었습니다.
  • 받지 못한 업데이트를 “준비됨”으로 알리던 문제 — 내려받기가 실패해도 화면에는 준비됐다고 나왔습니다. 이제 실패하면 실패로 알리고, 지금 버전을 그대로 쓰실 수 있으며 다음 확인 때 자동으로 다시 받습니다.
  • 마켓 응답이 깨졌을 때 “0건”으로 조용히 넘어가던 문제 — 스마트스토어·카페24 응답이 주문 목록 형태가 아닌데도 주문 0건을 받은 것처럼 처리해, 그 구간 주문이 빠진 채 수집이 정상 완료된 것처럼 보일 수 있었습니다. 이제 수집 실패로 드러내고 다음 동기화에서 다시 받습니다.

Security

  • 오류 기록에 주문 응답 본문이 섞이던 것을 차단 — 마켓 연동이 실패하면 오류 진단을 위해 응답 내용 일부를 기록해 왔는데, 여기에 받는 분 성함·주소가 섞일 수 있었습니다. 이제 서버가 준 오류 코드와 메시지, 응답 길이만 남깁니다. 오류 보고에 실리는 내용도 같은 기준으로 한 번 더 걸러집니다.

[0.3.0] — 2026-09-18 · 무료 Core 공개 출시

첫 공개 릴리스입니다. 비공개 베타(0.1.0-beta · 0.2.0-beta)에서 검증한 기능이 모두 포함됩니다.

Changed

  • 하나로 Core 무료화 — 요금제(Lite/Pro/Business)와 14일 체험을 없앴습니다. 주문 수집·송장 발행·전송·배송 추적·매출 집계를 기간 제한·결제 없이 사용합니다. 설정의 “라이선스” 탭은 “계정” 탭으로 바뀌고 라이선스 코드 입력이 사라졌습니다.
  • 지원 정책 시행 — 담당자 1:1 상담은 AI 직원 고용 이용자에게 제공합니다. 무료 이용자는 앱 안 AI 도우미(Ctrl+/)·사용설명서·커뮤니티로 지원합니다. 지원 정책
  • 체험 만료·라이선스 만료로 주문 수집과 송장 기능이 잠기던 동작을 제거했습니다.
  • 주문 화면의 [마켓에서 새 주문 받기]가 [마켓 동기화]로 바뀌었고, 순번 컬럼은 상품주문번호로 바뀌었습니다.
  • 주문 목록의 마켓 칸이 마켓 이름 대신 마켓 색 원 안의 약자(스마트스토어 N · 쿠팡 C · 카페24 24)로 바뀌었습니다. 약자에 마우스를 올리면 마켓 이름이 보입니다.
  • 🔴 카페24 연동 방식 변경 — 기존 연동 셀러는 재연결이 필요합니다 (δ.agency-1.0-A). 이제 개발자센터 가입도, Client ID/Secret 발급도 필요 없습니다. 하나로 공용 앱을 쓰므로 셀러는 몰 ID만 입력하고 [카페24 연결하기] → 카페24에서 [허용]을 누르면 끝입니다. 가이드
    • 이전 방식으로 연동해 두신 분은 한 번 다시 연결해 주세요. 기존 연결은 셀러 개인 앱으로 발급된 것이라 새 방식에서는 갱신되지 않고, 주문 수집이 “다시 연결해 주세요” 안내와 함께 멈춥니다. 설정 → 마켓 계정에서 몰 ID로 다시 연결하면 복구됩니다.
    • 계정을 삭제하고 다시 등록하지 마세요. 같은 몰을 새로 등록하면 주문 이력이 두 계정으로 나뉩니다. 기존 계정의 [재인증] → [카페24 연결하기]로 다시 연결하면 됩니다.
    • 기존 주문·송장 데이터는 그대로 유지됩니다. 지워지는 것은 없습니다.
    • 이미 입력해 두신 Client ID/Secret은 더 이상 쓰이지 않습니다. 다시 입력하실 필요 없습니다.
  • 카페24: 셀러 본인 앱(Client ID/Secret)으로도 연결할 수 있습니다 (δ.agency-1.7). 새로 카페24를 연결할 때는 카페24 개발자센터에서 만든 앱의 Client ID와 Client Secret을 입력합니다. 하나로 화면에 표시된 Redirect URI를 앱에 그대로 등록해 주세요. 가이드
    • 기존 연결은 그대로 동작합니다. 다시 연결할 필요가 없습니다. 다시 연결할 때도 Client ID/Secret을 비운 채 [카페24 연결하기]를 누르면 위 하나로 공용 앱 방식이 유지됩니다.
    • 공용 앱 연결을 본인 앱으로 바꾸려면 [재인증]에서 Client ID/Secret을 입력해 한 번 다시 연결하면 됩니다. 한 번 바꾸면 공용 앱 방식으로는 되돌릴 수 없습니다.
    • 연결 직후 주문 조회를 한 번 확인하고, 카페24 앱의 API 버전이 맞지 않으면 그 사유를 화면에 한국어로 알려 줍니다.

Added

  • 마켓 동기화 진행 표시 — 수동·자동 수집 모두 진행률과 완료 문구를 같은 자리에 보여 주고, 자동 수집은 어느 화면에 있든 표시됩니다.
  • 송장번호 직접 입력/수정 — 주문 행을 우클릭해 [송장번호 입력/수정…]에서 송장번호와 택배사를 직접 넣습니다. 자동 접수가 실패했을 때의 비상구이자 잘못 들어간 번호를 고치는 수단입니다. 가이드
  • 마켓 송장번호 불일치 감지 — 마켓에 등록된 송장번호와 앱의 송장번호가 다르면 배지로 알리고 전송을 막습니다. 배지를 눌러 앱 안에서 바로 해결합니다.
  • 도움말 FAQ 143건 + “해결됐나요?” 피드백 — AI 도우미 답변에 피드백 버튼이 붙고, 답변은 FAQ 근거에 고정됩니다.
  • 알림센터·토스트 알림, 배송 이상 큐(“처리할 일”에 배송 지연·이상 건 표시), 주기 수집(간격 설정 + 마지막 수집 시각), 삭제 되돌리기.
  • 주문 목록 — 헤더 전체선택 체크박스, “신규 주문” 상태 필터, 받는분·송장번호 검색, Enter로 검색.
  • Pretendard 글꼴을 앱에 번들해 어느 PC에서나 같은 화면을 그립니다. 본문 글자 크기·굵기 바닥을 올렸습니다.
  • 릴리스 채널 분리(stable / beta) — 설치할 때 쓴 Setup 파일의 채널을 따라갑니다. 시작하기

Fixed

  • 테마를 한 번 바꾼 뒤 앱이 다음 실행부터 뜨지 않던 문제, 자동업데이트가 조용히 꺼지던 문제, 처음 사용 안내가 한 번도 뜨지 않던 문제.
  • 배송조회가 로젠에서만 되던 문제 — CJ대한통운·한진·롯데·우체국 전부 동작합니다.
  • 마켓 동기화 때 같은 주문 2건이 계속 갱신되던 문제.
  • 스마트스토어 롯데 택배사 코드 오류.
  • 카페24 주문을 발송처리할 때 발주확인 동의 창이 뜨고 “발주확인에 동의해야 발송처리할 수 있습니다”라고 잘못 안내하던 문제 — 카페24는 발주확인 단계가 없어 이제 묻지 않습니다. 입금 전 주문은 전과 같이 발송처리되지 않습니다.
  • 로젠 접수 중 하나로 창이 뒤로 밀리거나 뷰어 창이 남던 문제, 접수 인쇄가 설정한 프린터로 나가지 않던 문제.
  • 대시보드 마켓 카드가 셀을 넘치던 문제, 매출 화면 건수 표기, 인쇄 설정 라벨 잘림.

Notes

  • 이번 빌드는 코드서명 전이라 설치 시 SmartScreen 경고가 뜹니다. 추가 정보 → 실행. 10월 서명 빌드(0.3.1)부터 사라집니다. 시작하기
  • 카페24 연동이 새 방식으로 포함됩니다. 이미 연결해 쓰시던 분은 위 “카페24 연동 방식 변경”대로 [재인증]으로 한 번만 다시 연결해 주세요(계정 삭제 금지). 정산·수수료 집계는 다음 업데이트에 포함됩니다.
  • AI 직원(첫 직원은 구매자 문의 응대)은 2026년 12월에 월정액으로 열립니다. 고용하지 않아도 Core는 계속 무료입니다.

[0.1.0-beta · 0.2.0-beta] — 2026-08-13 · 2026-08-24 (비공개 베타)

Added

  • 매출관리 화면 (β.lite-10) — 기간별·마켓별·상품별 매출 집계 + 엑셀(.xlsx) 리포트 내보내기. 가이드
  • 송장 라벨 인쇄 (β.lite-11) — 감열 프린터(XPrinter XP-DT108B 등)로 100×150mm 택배 라벨 인쇄. 미리보기·일괄 인쇄·”인쇄됨” 배지. 가이드
  • 대시보드 개편 (β.lite-14) — 오늘 매출 스트립(전일 대비 증감), “처리할 일” 큐(송장 미등록·발송 지연·라벨 미인쇄), 마켓별 진행 현황 일감순 정렬. 가이드
  • 처리할 일 바로가기 (β.lite-14.1) — 큐 항목 클릭 시 주문 화면에서 해당 건만 필터 표시.
  • 사용설명서 사이트 (docs/) — 셀러용 GitHub Pages.
  • Onboarding 마법사 4단계 (Wave β.2-E).
  • 운영 게이트: Velopack 자동업데이트, Sentry 에러 추적 (Wave β.1-C). 코드서명은 파이프라인만 준비된 상태(인증서 발급 진행 중) — 현재 설치파일은 서명되지 않아 SmartScreen 경고가 나올 수 있습니다 (시작하기 참조).

Changed

  • 화면 문구 명확화 (β.lite-12) — 혼동을 주던 안내 문구 정비 + 용어 통일 + 오류 리포트의 개인정보 자동 제거 강화.
  • 디자인 정비 (β.lite-13) — 색 대비 접근성(WCAG AA) 교정 + 화면 간 색·글꼴 일관성 통일.
  • 단위테스트 확장 + CI 커버리지 게이트 강제 (평균 라인·브랜치 ~49%).
  • 한국어 도메인 식별자 일관성 정리.

Fixed

  • 스마트스토어 송장번호 전송 실패 수정 (β.lite-14.2) — 마켓 전송 규격 불일치로 전량 실패하던 문제 해소.
  • 송장번호 충돌 다이얼로그 — “다음 충돌에도 같은 선택 적용” 옵션.
  • 그리드 클립보드 붙여넣기 행 단위 처리.

[β.1.0] — 2026-04-XX (Wave β.1)

Added

  • 마켓 어댑터 — 스마트스토어, 쿠팡, 카페24.
  • 택배사 추적 — 5대 택배사 (로젠, CJ대한통운, 한진, 롯데, 우체국).
  • 화면: 대시보드 / 주문(주문수집·송장관리 통합) / 배송조회 / 설정.
  • DPAPI 암호화 마켓 자격증명 저장.
  • CI/CD 파이프라인 (GitHub Actions) — 빌드 경고 0 + 테스트 + 커버리지 게이트 (0%제외 평균 라인·브랜치 30% + 프로젝트별 floor 라인 20%·브랜치 15%).

Architecture

  • Clean Architecture: Domain → Contracts → Application → Infrastructure → UI.
  • .NET 8 + Avalonia 11 + EF Core 8 + CommunityToolkit MVVM.
  • 한국어 도메인 식별자 — 클래스·메서드·열거형 이름에 한글 사용(예: 주문, 송장, 자격증명검증서비스). 네임스페이스는 영어(Hanaro.Domain / Hanaro.Application 등).

[α.0.1] — 2026-03-XX (Wave α 프로토타입)

Added

  • 도메인 모델 초안 (Aggregate / Entity / Value Object).
  • spec-panel 평가 8/10 (Reliability ✓, Security ✓, Maintainability ✓).
  • 기술 스택 결정: .NET 8 / Avalonia 11 / EF Core / SQLite.

형식 안내

각 릴리스는 다음 항목으로 구성됩니다:

항목 의미
Added 새 기능
Changed 기존 기능 변경
Deprecated 제거 예정 기능
Removed 삭제된 기능
Fixed 버그 수정
Security 보안 패치

문의

  • 설치파일 · 릴리스 노트 · 다음 버전 계획 — 운영팀(hanalabs@hanapf.kr 또는 안내받은 카카오톡 채널)