Releases

  • 5.17.2

    5.17.2 주요 변경사항

    게시(ops)

    • ops/publish-images.ps1이 backend를 릴리스마다 새로 빌드합니다. backend는 빌드 때 박힌 APP_VERSION을 health version과 운영 관리 버전·릴리스의 현재 버전에 쓰는데, 5.17.1처럼 빌드 입력이 같아 digest를 재사용하면 배포한 릴리스보다 낮은 버전(5.17.0)을 보고해 새 버전 안내가 계속 떴습니다. 이제 latest의 OCI version label이 게시 버전과 다르면 backend만 다시 빌드하고 다른 서비스는 그대로 재사용합니다. 모의 게시 검증에 이 시나리오를 더했습니다.

    앱 코드·schema·Compose·환경 키 변경은 없고 backend 이미지는 APP_VERSION만 달라지는 patch 5.17.2로 게시합니다.

    이미지 게시 범위

    • 새로 빌드(5.17.2·latest): backend. 빌드 입력은 같지만 latest의 version label이 5.17.0이라 이번 규칙으로 다시 빌드했고 APP_VERSION=5.17.2를 확인했습니다.
    • digest 재사용: web(5.17.1 digest), crawler(5.17.0 digest), nginx(5.10.0 digest), byedpi(5.15.0 digest). 기존 digest에 5.17.2·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.17.2 태그가 있으므로 IMAGE_TAG=5.17.2로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • schema·Compose 변경 없음: 반영 SQL이 없고 compose.yml·환경 파일 변경이 없습니다.
    • 5.17.1에서 올라오면 backend(와 같은 이미지를 쓰는 log-reader)만 교체되고, 운영 관리의 현재 버전이 5.17.2로 보이며 새 버전 안내가 사라집니다. 앞으로는 매 릴리스마다 backend가 교체됩니다.
    • 배포 전 레지스트리에 다섯 서비스의 latest가 모두 있는지 확인합니다.
    • rollback: 5.17.1 이미지가 다섯 서비스 모두 레지스트리에 있어 IMAGE_TAG=5.17.1로 되돌릴 수 있습니다.

    5.17.1 대비 전체 변경

    검증

    • 릴리스 commit e47e04ee: run-operations.ps1 -DeploymentOnly 통과(게시 모의 실행의 backend-version 시나리오 포함). 앱 코드는 5.17.0과 같아 5.17.0의 run-unit.ps1 -Workspace all·run-integration.ps1 통과 결과가 그대로 유효합니다.
    • NOT RUN: 그 밖의 runner(앱 코드 변경 없음).

    게시 확인

    • 릴리스 소스: e47e04ee (annotated Git 태그 5.17.2 대상, 앱 코드는 5.17.0과 같음).
    • backend 5.17.2·latest(새 빌드, APP_VERSION=5.17.2): sha256:15b6d6998c60618ef73b49886bc7dec241a70d2fb7b1137c1da96a6e9b926cec
    • web 5.17.2·latest(5.17.1 digest 재사용): sha256:2ecdd6c0e8ce61f6e10d7f306191cbdfc075af53a25ce5abed32b7ebdd493e98
    • crawler 5.17.2·latest(5.17.0 digest 재사용): sha256:1123e8eaf5fbb1596e840d353cebdccee7b827c3d1e27e3cdb8b17917b9e225e
    • nginx 5.17.2·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.17.2·latest(5.15.0 digest 재사용): sha256:bc1a69ccfe5f0fc8185b43bd3ca4802a7f1f0bfd1487a141b7f052958d26dcc4
    • ops/publish-images.ps1 -Version 5.17.2 -Publish가 첫 실행에서 완료됐고(Registry tags verified for 5.17.2.) docker manifest inspect로 다섯 latest·5.17.2를 다시 확인했습니다.
    Downloads 2
  • 5.17.1

    5.17.1 주요 변경사항

    화면(web)

    • 5.17.0에서 흰 바탕으로 만든 앱 아이콘 192·512를 의도대로 favicon과 같은 투명 바탕으로 되돌렸습니다. maskable 아이콘은 규격상 불투명 바탕이 필요해 흰 바탕과 안전 영역 여백을 유지합니다.

    web 정적 파일만 바뀐 patch 5.17.1로 게시합니다. schema·Compose·환경 키·앱 코드 변경은 없습니다.

    이미지 게시 범위

    • 새로 빌드(5.17.1·latest): web(아이콘 파일 변경).
    • digest 재사용: backend·crawler(5.17.0 digest), nginx(5.10.0 digest), byedpi(5.15.0 digest). 기존 digest에 5.17.1·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.17.1 태그가 있으므로 IMAGE_TAG=5.17.1로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • schema·Compose 변경 없음: 반영 SQL이 없고 compose.yml·환경 파일 변경이 없습니다.
    • 5.16.0에서 올라오면 5.17.0의 주의사항(backend·web 함께 배포, crawler 교체 시 E-Hentai 관리자 재개)이 그대로 적용됩니다. 5.17.0에서 올라오면 web만 바뀝니다.
    • 배포 전 레지스트리에 다섯 서비스의 latest가 모두 있는지 확인합니다.
    • rollback: 5.17.0 이미지가 다섯 서비스 모두 레지스트리에 있어 IMAGE_TAG=5.17.0으로 되돌릴 수 있습니다.

    5.17.0 대비 전체 변경

    검증

    • 앱 코드는 5.17.0과 같아 5.17.0의 run-unit.ps1 -Workspace all·run-integration.ps1 통과 결과가 그대로 유효합니다. 개발 web 재빌드 뒤 아이콘 응답(RGBA, 투명 모서리)을 확인했습니다.
    • NOT RUN: 그 밖의 runner(이미지 파일만 변경), 실기기 홈 화면 아이콘 확인.

    게시 확인

    • 릴리스 소스: 3620689f (annotated Git 태그 5.17.1 대상, 앱 코드는 5.17.0과 같음).
    • web 5.17.1·latest(새 빌드): sha256:2ecdd6c0e8ce61f6e10d7f306191cbdfc075af53a25ce5abed32b7ebdd493e98
    • backend 5.17.1·latest(5.17.0 digest 재사용): sha256:4f4bc99ae0a8aae403724909720767ce0c125137d4fdd94760a2281f6f9bfd00
    • crawler 5.17.1·latest(5.17.0 digest 재사용): sha256:1123e8eaf5fbb1596e840d353cebdccee7b827c3d1e27e3cdb8b17917b9e225e
    • nginx 5.17.1·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.17.1·latest(5.15.0 digest 재사용): sha256:bc1a69ccfe5f0fc8185b43bd3ca4802a7f1f0bfd1487a141b7f052958d26dcc4
    • ops/publish-images.ps1 -Version 5.17.1 -Publish가 첫 실행에서 완료됐고(Registry tags verified for 5.17.1.) docker manifest inspect로 다섯 latest·5.17.1을 다시 확인했습니다.
    Downloads 2
  • 5.17.0

    5.17.0 주요 변경사항

    버전 확인과 새 릴리스 안내(backend·web)

    • 관리자 GET /api/health/release가 실행 중인 backend 이미지 버전과 이 저장소의 Forgejo 최신 release를 비교해 current·latest(버전·release 페이지 링크·게시 시각)·updateAvailable·checkedAt·error를 반환합니다. 결과는 backend process에 성공 1시간·실패 5분 동안 두고 ?refresh=true로 바로 다시 확인하며, Forgejo 호출 실패는 마지막 성공 결과를 남긴 채 error 문구로 알립니다. 개발 빌드(local)는 새 버전 여부를 판단하지 않습니다.
    • 운영 관리 관찰 그룹에 버전·릴리스 패널을 더했습니다. 접힌 제목에 새 버전 x.y.z·x.y.z 최신·확인 실패를 요약하고, 펼치면 현재 버전·최신 릴리스·마지막 확인 시각과 릴리스 페이지 열기(새 탭)·다시 확인을 둡니다.
    • 새 릴리스가 있으면 관리자 화면 오른쪽 아래(모바일은 하단 바)에 PWA 안내·알림 유도창과 같은 틀의 새 버전 안내가 뜹니다. 릴리스 보기는 release 페이지를 새 탭에 열고, 닫기는 그 버전을 이 브라우저에 기억해 더 새 릴리스가 나올 때만 다시 보입니다. 하단 안내 바는 PWA 안내 → 새 버전 안내 → 알림 유도창 순으로 하나만 보입니다.

    화면(web·shared)

    • 앱 아이콘(192·512·maskable)을 favicon과 같은 선화 캐릭터로 바꿨습니다(흰 바탕, maskable은 안전 영역 여백). 내비게이션 로고도 같은 아이콘을 씁니다.
    • 설정의 읽기 방향을 페이지 읽기 방향으로 바꾸고, 갤러리 보기의 그리드 외 항목을 **리스트(베타)·컴팩트(베타)·매거진(베타)**로 표시합니다.
    • 5.16.0에서 일반화한 선택 면 이동(SegmentedIndicator)이 선택 직후 ResizeObserver 초기 알림에 transition을 잃어 홈 연속·페이지 전환의 물방울 이동이 보이지 않던 결함을 고쳤습니다.
    • 홈 연속·페이지 전환 때 목록과 작품 개수를 비우지 않고 첫 page만 조용히 다시 받습니다. 같은 카드가 그대로 남아 skeleton·개수 깜빡임이 없고, 페이지 모드 2쪽 이후에서 연속으로 바꿀 때만 비웁니다.
    • 뷰어 조작 UI 자동 숨김 기본값을 끔으로 바꿨습니다. 저장된 설정이 있는 사용자는 그대로이고 새 사용자·guest만 새 기본값을 받습니다.

    그 밖

    • compose 호환 검증 기준 commit을 5.16.0으로 갱신했습니다.

    새 관리자 API·운영 패널·안내 바가 더해지고 schema·Compose·환경 키 변경은 없으므로 minor 5.17.0으로 게시합니다.

    이미지 게시 범위

    • 새로 빌드(5.17.0·latest): backend·crawler·web. backend는 GET /api/health/release, web은 버전·릴리스 패널·새 버전 안내·아이콘·설정 이름이 바뀌었고, crawler는 소스 변경 없이 빌드 입력 fingerprint(저장소 문서·설정 포함)가 달라져 다시 빌드했습니다.
    • digest 재사용: nginx(5.10.0 digest), byedpi(5.15.0 digest). 빌드 입력이 같아 기존 digest에 5.17.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.17.0 태그가 있으므로 IMAGE_TAG=5.17.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • schema·Compose 변경 없음: 반영 SQL이 없고 compose.yml·환경 파일 변경이 없습니다.
    • backend와 web은 함께 배포합니다(web의 버전 패널·안내 바가 새 GET /api/health/release를 호출). crawler는 shared만 바뀐 재빌드이며 교체 시 실행 중인 수집 job은 checkpoint에서 멈추고 Hitomi는 자동, E-Hentai는 관리자 재개가 필요합니다.
    • 버전 확인은 backend가 git.2ex.dev로 나가는 HTTPS를 쓰며, 막혀 있으면 확인 실패로만 보이고 운영에는 영향이 없습니다.
    • 배포 전 레지스트리에 다섯 서비스의 latest가 모두 있는지 확인합니다(5.16.0 게시 뒤 crawler:latest가 사라진 사례).
    • rollback: 5.16.0 이미지가 다섯 서비스 모두 레지스트리에 있어 IMAGE_TAG=5.16.0으로 되돌릴 수 있습니다.

    5.16.0 대비 전체 변경

    검증

    • 각 변경 커밋에서 run-unit.ps1 -Workspace all과 run-integration.ps1이 통과했고 검증 기록은 커밋 메시지에 있습니다. 뷰어 header dialog 통합 검증은 자동 숨김 기본값 변경에 맞춰 관리자 설정으로 자동 숨김을 켠 뒤 확인하도록 고쳤습니다.
    • 릴리스 commit 6f3951a5(앱 코드는 f2988e79와 같음): run-unit.ps1 -Workspace all(backend 88·crawler 155·web 72 suites, 3,647 tests), run-integration.ps1(API·crawler runtime·브라우저 단계 포함) 통과. 개발 stack backend·web 재빌드 뒤 /api/health/release guest 401·live 200 확인.
    • NOT RUN: run-schema.ps1·run-compose-compat.ps1·run-operations.ps1(schema·Compose·ops·Nginx 변경 없음), Hitomi·E-Hentai network runner, 실브라우저에서 새 버전 안내 바·아이콘 시각 확인.

    게시 확인

    • 릴리스 소스: 6f3951a5 (annotated Git 태그 5.17.0 대상, 앱 코드는 f2988e79와 같음).
    • backend 5.17.0·latest(새 빌드): sha256:4f4bc99ae0a8aae403724909720767ce0c125137d4fdd94760a2281f6f9bfd00
    • crawler 5.17.0·latest(새 빌드): sha256:1123e8eaf5fbb1596e840d353cebdccee7b827c3d1e27e3cdb8b17917b9e225e
    • web 5.17.0·latest(새 빌드): sha256:f113fa92d1af7b7d22233d491d54141f5857c97ef93c8556832c4a5f86222fad
    • nginx 5.17.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.17.0·latest(5.15.0 digest 재사용): sha256:bc1a69ccfe5f0fc8185b43bd3ca4802a7f1f0bfd1487a141b7f052958d26dcc4
    • ops/publish-images.ps1 -Version 5.17.0 -Publish가 첫 실행에서 완료됐고 다섯 서비스의 5.17.0·latest 일치를 확인했습니다(Registry tags verified for 5.17.0.). 게시 뒤 docker manifest inspect로 다섯 latest가 모두 있는지 다시 확인했습니다.
    Downloads 2
  • 5.16.0

    5.16.0 주요 변경사항

    Turnstile 선택 설정(backend·web·ops)

    • TURNSTILE_SITE_KEY·TURNSTILE_SECRET_KEY를 모두 비우면 backend가 시작 경고만 남기고 로봇 검증을 끕니다(가입·로그인 options는 token 없이 통과, guest viewer grant는 최초 검증 없이 trust). 한쪽 키만 채우면 설정 실수로 보고 시작하지 않으며, 공개 host에 Cloudflare test key를 쓰는 것은 그대로 거절합니다. 쓰지 않던 TURNSTILE_DISABLED 분기를 제거했습니다.
    • ops/publish-images.ps1은 빈 site key를 경고로 허용하고 placeholder·test key만 거절합니다. .env.example·README·운영 가이드·설계·API 계약 문서가 선택 설정 기준으로 바뀌었습니다. 운영 .env.production은 키가 있어 동작 변화가 없습니다.

    화면(web)

    • 홈 보기 방식(연속·페이지)에만 있던 "선택 면이 칸 사이를 옮겨 가는" 효과를 SegmentedIndicator로 일반화해 단일 선택 묶음 전체(북마크 종류, 읽기 상태·읽기 기록 상태 필터, 고급 검색 AND·OR·태그 분류·게시일 범위, 설정 radio group, 수집 모드, 중복 상태 필터, 뷰어 보기 모드)에 적용했습니다. 다중 선택 묶음(카테고리·로그 필터)은 제외했습니다.
    • 뷰어 자동 숨김이 본문 scroll 방향을 봅니다. wheel·터치·키 입력 직후 위로 24px 이상 올리면 숨긴 조작 막대가 다시 보이고, 아래로 48px 이상 이어서 내리면 바로 숨깁니다. 이미지 로드 보정 같은 programmatic scroll에는 반응하지 않습니다.

    태그 번역(shared)

    • 2026-10-21 운영 미번역 내보내기 67개를 사용자 결정으로 모두 처리했습니다. character 49·parody 1은 운영 갤러리 제목으로 대상을 특정한 공식·통용 표기(원신 리사·모나, LoL 루시안·모르가나, 포켓몬 벨·란·라이치, 스트리트 파이터 영문명 교차 마이크 바이슨·발로그, 니케 츠바이, 트릭컬 가비아·마요, 마도정병의 슬레이브 등) 또는 통용 음역이고, tag namespace의 작가·서클 인명 17개는 원문 유지 목록에 넣었습니다. 근거는 apps/web/src/lib/__fixtures__/missing-tag-translations-2026-10-21.json이 보존합니다.

    수집(crawler)

    • E-Hentai 수집이 byedpi sidecar 재시작·배포로 SOCKS 연결이 거절돼 멈추면 원문(Socks5 proxy rejected connection - HostUnreachable) 대신 DPI 우회 proxy 단절 사정과 관리자 재개 안내를 적고 원문을 괄호에 남깁니다. 일반 네트워크 코드는 뜻(코드)을 붙입니다.

    그 밖

    • compose 호환 검증 기준 commit을 5.15.0으로 갱신하고, 5.15.0 반영 SQL 절 이름과 현재 계획을 운영 배포 완료 상태로 정리했습니다.

    Turnstile 선택 설정과 화면·번역 기능이 더해지고 schema·Compose·환경 키 추가는 없으므로 minor 5.16.0으로 게시합니다.

    이미지 게시 범위

    • 새로 빌드(5.16.0·latest): backend·crawler·web. shared(translations/)가 바뀌어 세 앱의 빌드 입력이 달라졌고, backend는 Turnstile 선택 설정, crawler는 E-Hentai 실패 문구, web은 선택 면 이동·뷰어 scroll 복귀·Turnstile 문서가 바뀌었습니다.
    • digest 재사용: nginx(5.10.0 digest), byedpi(5.15.0 digest). 빌드 입력이 같아 기존 digest에 5.16.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.16.0 태그가 있으므로 IMAGE_TAG=5.16.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • schema·Compose 변경 없음: 반영 SQL이 없고 compose.yml·Dockerfile 변경이 없습니다. .env.example은 Turnstile 주석만 바뀌었고 운영 환경 파일은 바꾸지 않습니다.
    • backend와 web은 함께 배포합니다(Turnstile 켜고 끄는 상태는 두 이미지가 같아야 함. 운영은 둘 다 켜진 상태 유지). crawler 교체 시 실행 중인 수집 job은 checkpoint에서 멈추고 관리자 재개가 필요합니다. 배포 스크립트가 byedpi를 먼저 교체하므로 실행 중인 E-Hentai job은 proxy 단절 문구(이번 릴리스부터 한국어 안내)로 멈출 수 있습니다.
    • rollback: 5.15.0 이미지가 다섯 서비스 모두 레지스트리에 있고 schema 변경이 없어 IMAGE_TAG=5.15.0으로 되돌릴 수 있습니다.

    5.15.0 대비 전체 변경

    검증

    • 각 변경 커밋에서 run-unit.ps1(backend·web·all)과 Turnstile 키를 비운 일회성 backend 기동 확인이 통과했고 검증 기록은 커밋 메시지에 있습니다. 미번역 태그 67개는 운영 DB 읽기 전용 조회로 갤러리 제목을 확인해 대상을 특정했습니다.
    • 릴리스 commit c95fd519(앱 코드는 31dd94f0과 같음): run-unit.ps1 -Workspace all(backend 87·crawler 72·web 154 suites), run-integration.ps1, run-operations.ps1 -DeploymentOnly 통과, update-base-images.ps1 기반 이미지 digest drift 없음.
    • NOT RUN: run-schema.ps1·run-compose-compat.ps1(schema·Compose 변경 없음), Hitomi·E-Hentai network runner, run-translation-coverage.ps1(개발 DB에 해당 태그 없음), 실브라우저에서 선택 면 이동·scroll 복귀 시각 확인.

    게시 확인

    • 릴리스 소스: c95fd519 (annotated Git 태그 5.16.0 대상, 앱 코드는 31dd94f0과 같음).
    • backend 5.16.0·latest(새 빌드): sha256:ffbd6e0b77e96e7007730db9e3e37694d52e6098eb5bb41b8e74e7a73a2b096b
    • crawler 5.16.0·latest(새 빌드): sha256:4086f6744ca4461d0d3863c1626979bac7e8aae748274c95f3a51fd88a698add
    • web 5.16.0·latest(새 빌드): sha256:4c790c7d8ce27ad1cbba2fee50177a38034e0204e77fc32892be22a01238534d
    • nginx 5.16.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.16.0·latest(5.15.0 digest 재사용): sha256:bc1a69ccfe5f0fc8185b43bd3ca4802a7f1f0bfd1487a141b7f052958d26dcc4
    • ops/publish-images.ps1 -Version 5.16.0 -Publish가 첫 실행에서 완료됐고 다섯 서비스의 5.16.0·latest 일치를 확인했습니다(Registry tags verified for 5.16.0.).
    Downloads 2
  • 5.15.0

    5.15.0 주요 변경사항

    화면·사용 흐름(web·backend)

    • 홈 목록을 유동 2열 이상 grid로 바꾸고 카드에 작가·카테고리·쪽수 메타 줄, 읽는 중 표지의 p.N/M 배지, namespace 색 태그 칩(5줄 scroll)과 +N 표시를 두었습니다. 북마크 갤러리·모아보기도 같은 grid를 씁니다.
    • 북마크 화면에 전체 북마크 파일 내보내기·불러오기(형식 검사, page 단위 내보내기, 묶음 불러오기, guest 병합)를 추가했습니다.
    • 고급 검색의 태그 선택 방식을 AND·OR 버튼으로 표시하고 쪽수·게시일 범위를 넓은 패널에서 나란히 배치했습니다. 홈 툴바 보기 방식은 segmented로 묶였고 연속·페이지 선택 면이 옮겨 가는 움직임을 갖습니다.
    • 뷰어의 핀치·더블탭 줌을 초점 기준으로 바꾸고 팬을 경계 안에 묶었으며, 터치 탭은 좌·우 넘김과 가운데 조작 막대 토글로 나뉩니다. 진행률 막대는 transform으로 움직입니다.
    • 상세 modal 정보 순서를 작가·쪽수·읽던 위치 중심으로 재배치했고, 북마크 별은 누르는 즉시 바뀌며 실패하면 되돌립니다. 개인 차단 태그 삭제에 되돌리기와 목록 검색, 패스키 삭제에 확인 dialog를 추가했습니다.
    • 한국어 폰트 스택·타입 단계·모션 토큰·maskable 아이콘·상태 표시줄 색을 공용 레시피로 정리하고 본문 건너뛰기 링크, 설정 radio group의 키보드 이동 등 접근성을 보강했습니다.
    • Hitomi 전체 크롤링에서도 수집 기록 무시 토글을 쓸 수 있고 범위 상한이 없어졌습니다. 갤러리 상세의 중복 검사 아이콘을 검색·대조 의미의 아이콘으로 바꿨습니다.

    개발 서버 로그인(backend·web·Compose)

    • DEV_LOGIN_ENABLED=true인 개발 서버에서만 로그인 창에 사용자·운영자 즉시 로그인 버튼과 전용 endpoint가 생깁니다. 기본값 false이며 AUTH_COOKIE_SECURE=true면 무시됩니다. compose.yml이 backend에 이 키를 전달하고 .env.example에 키가 추가됐습니다. 운영 .env.production에는 넣지 않거나 false로 둡니다.

    schema·내부 정리(backend·crawler·shared·sql)

    • fresh schema에서 reading_status enum을 unread·reading·completed로 좁히고 reading_progress.status 단독 index, tags의 쓰지 않는 description·"galleryCount" 컬럼을 없앴으며 image_thumbnails.storage_path를 collation "C"로 고정했습니다. backend schema verifier가 두 경로 컬럼의 collation과 key 범위 index 사용을 단언합니다.
    • backend·crawler의 graceful shutdown, entity enum·상태 값, 설정·crawler 상태 응답 타입, 작가 namespace 판정과 검색 조건 상한을 shared 한 곳으로 통일했고, backend가 raw SQL로만 쓰던 entity 등록·crawler 전용 entity 사본·orphan audit 호환 분기를 제거했습니다. 중복 검사 매칭은 min-cost max-flow로 같은 결과를 내며 duplicate_groups 포함 관계 CHECK 식을 backend·fresh schema와 맞췄습니다.
    • MinIO bucket은 backend·crawler 모두 시작 시 확인하고 없으면 만들며(앱별 계정이면 backend는 생성 불가), ops/production-audit.sh는 운영 디렉터리 기준으로 실행 위치를 안내합니다. .dockerignore의 쓸모없는 항목과 비활성 Forgejo workflow 파일을 지웠습니다.

    문서·검증 자산

    • README를 소개·실제 화면 캡처·4줄 빠른 시작 중심으로 다시 썼고, 캡처는 합성 데이터로 재현하는 tests/compose/readme-capture.yml이 만듭니다. docs/완료_이력.md를 없애고 검증 기록은 커밋 메시지, 릴리스 결과는 Forgejo 릴리스, 남은 운영 조치는 문서 색인 현재 계획이 맡습니다. 설계·운영 문서 전반을 코드와 대조해 바로잡았습니다.
    • passkey runner는 실행 중인 개발 stack의 Compose project 이름을 읽고, 통합 runner는 api-test 조기 종료 시 로그를 출력합니다.

    새 기능·새 환경 키가 더해지고 기존 데이터는 유지되므로 minor 5.15.0으로 게시합니다. schema 변경은 기존 설치에 수동 SQL(아래)로 반영합니다.

    이미지 게시 범위

    • 새로 빌드(5.15.0·latest): backend·crawler·web. shared(gallery-policy.ts·설정·crawler 상태 타입·중복 비교·schema verifier)가 바뀌어 세 앱의 빌드 입력이 달라졌고, backend는 개발 로그인·북마크 내보내기·상세 응답 필드·graceful shutdown, crawler는 Hitomi 전체 크롤링 토글·entity 통일·bucket 확인, web은 UI/UX 개편 전반이 바뀌었습니다.
    • byedpi: 소스는 5.4.0 이후 변경이 없으나 추적 입력 fingerprint가 latest 이미지의 기록과 달라 다시 빌드·게시했습니다(동일 Dockerfile·alpine:3.24 digest).
    • digest 재사용: nginx(5.10.0 digest). 빌드 입력이 같아 기존 digest에 5.15.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.15.0 태그가 있으므로 IMAGE_TAG=5.15.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • Compose·환경 키: compose.yml이 backend에 DEV_LOGIN_ENABLED(기본 false)를 전달합니다. 운영 .env.production에는 키를 두지 않거나 false로 둡니다. 그 밖의 Compose·Dockerfile 변경은 없습니다.
    • 기존 설치 schema 반영(필수): 새 backend를 배포한 뒤 다음 릴리스 반영 SQL 16단계를 실행합니다. 13단계(reading_status enum 축소·index 삭제)는 새 backend 배포 뒤에만 실행하고 실행 뒤에는 5.14.0 backend로 되돌리지 않습니다. 4~6단계(tags 컬럼 삭제, 썸네일 경로 collation)는 배포 순서와 무관합니다.
    • backend와 web은 함께 배포합니다(상세 modal·북마크·고급 검색 응답 필드가 함께 바뀜). crawler 교체 시 실행 중인 수집 job은 checkpoint에서 멈추고 새 crawler가 재개합니다(E-Hentai job은 운영 화면에서 수동 재개).
    • migrations·typeorm_metadata·crawl_attempts 테이블 삭제는 선택 정리이며 5.13.0 이하로 되돌릴 가능성이 없을 때만 실행합니다.
    • rollback: 5.14.0 이미지는 다섯 서비스 모두 레지스트리에 있어 반영 SQL 1~3단계 실행 전까지는 IMAGE_TAG=5.14.0으로 되돌릴 수 있습니다. 실행 뒤에는 되돌리지 않습니다.

    5.14.0 대비 전체 변경

    검증

    • 각 작업 브랜치(UI/UX 4개 라운드·정리·문서·DB 후속)에서 run-unit.ps1 -Workspace all, run-integration.ps1, run-schema.ps1과 변경 영역의 격리 검증(이미지 검색·운영 UI·북마크 UI·passkey·README 캡처)이 통과했고, 모든 브랜치는 gpt-6.1-sol 읽기 전용 리뷰(P1·P2 지적은 수정 후 재검)를 거쳤습니다. 검증 기록은 각 커밋 메시지에 있습니다.
    • 병합 main d51a4b94(릴리스 commit 1ba8a132와 앱 코드 동일): run-schema.ps1, run-unit.ps1 -Workspace all, run-integration.ps1, run-operations.ps1 -DeploymentOnly, run-compose-compat.ps1(세 조합, -OldRef 7b6e1e1c) 통과, update-base-images.ps1 기반 이미지 digest drift 없음. 운영 DB 읽기 전용 점검으로 tags 미사용 컬럼이 모두 NULL/0, reading_progress에 dropped·on_hold 없음, images.storagePath가 이미 collation "C"임을 확인했습니다.
    • NOT RUN: Hitomi·E-Hentai network runner(네트워크 경로 변경 없음), 실브라우저 수동 확인, 운영 규모의 storedBytes 집계·이미지 검색 p95 실측.

    게시 확인

    • 릴리스 소스: 1ba8a132 (annotated Git 태그 5.15.0 대상, 앱 코드는 d51a4b94와 같음).
    • backend 5.15.0·latest(새 빌드): sha256:21c0fed8f7ec8cb41d84ed1eeb72aa57631b979503372e65f2da3ac2110e10f8
    • crawler 5.15.0·latest(새 빌드): sha256:079b3055a55013dd5f4deeed642bbf0261deb575390fcda8939001fd3773b6f5
    • web 5.15.0·latest(새 빌드): sha256:e54d84c7814e6e9316ea4e57549686d36cd244da97f3b25a7d8643613a5815b3
    • nginx 5.15.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.15.0·latest(새 빌드): sha256:bc1a69ccfe5f0fc8185b43bd3ca4802a7f1f0bfd1487a141b7f052958d26dcc4
    • ops/publish-images.ps1 -Version 5.15.0 -Publish 첫 실행이 backend·crawler·web 푸시 중 레지스트리 TLS 오류(bad record MAC)로 멈춰(byedpi 5.15.0만 게시됨) 빌드된 이미지를 docker push로 다시 올리고 nginx는 imagetools create로 태그를 붙인 뒤 -PromoteOnly -ServiceNames byedpi,nginx,backend,crawler,web으로 latest를 승격했습니다. 다섯 서비스의 5.15.0·latest 일치를 확인했습니다(Registry tags verified for 5.15.0.).
    Downloads 2
  • 5.14.0

    5.14.0 주요 변경사항

    migration 제거(backend·crawler·운영 스크립트)

    • TypeORM migration 28개와 migrationsRun 설정, upgrade runner·검증기를 제거했습니다. sql/init-db.sql이 유일한 schema 기준이며, 새 설치는 이 파일만으로 현재 운영과 같은 schema를 받습니다(제거 전 fresh catalog가 28개 migration 적용 결과와 동일함을 확인).
    • schema 검증(run-schema.ps1)이 entity 컬럼 타입·NULL·enum·FK·기본값, SQL 소유 index 28개의 정의, shared 생성 SQL의 독립 적용 결과까지 init-db.sql과 대조합니다.
    • ops/deploy-production.sh는 crawler를 미리 멈추거나 migration을 기다리지 않습니다. crawler는 자기 단계에서 교체될 때 checkpoint에 멈춘 뒤 새 이미지로 재개합니다. ops/production-audit.sh·ops/compat-state-audit.sql에서 migration 항목을 제거했습니다.

    중복 관리 작품 용량 수정(backend·web)

    • GET /api/duplicates/review-groups가 작품마다 storedBytes(원장의 ready 원본 크기 합, 없으면 0)를 추가로 내려주고, 운영 화면 중복 관리가 이 값을 표시합니다. 이전에는 Hitomi 작품에 채워지지 않는 galleries.fileSize(bigint 문자열 "0")를 그대로 표시해 모두 0 B로 보였습니다. reclaimableBytes 의미는 그대로입니다.

    기본 블랙리스트·태그 번역(shared)

    • 기본 전역 블랙리스트 태그 seed를 운영 내보내기 기준 152개로 갱신했습니다(추가 artist:borikori·artist:campbell gichou·artist:gfrp·artist:taejaho·artist:tsutsumi akari·forniphilia, 제거 tomgirl). 새 설치에만 적용되며 기존 DB의 규칙은 바뀌지 않습니다.
    • 누락 태그 50개에 공식 한국어 명칭 기준 번역을 추가했고, 작가 태그 taikou는 원문 유지, 공식 출처가 없는 63개는 보류 목록으로 고정했습니다.

    기존 설치의 schema는 이미 같아 필수 수동 전환이 없고 새 API 필드·번역이 추가되므로 minor 5.14.0으로 게시합니다. compose.yml·.env.example·Dockerfile은 5.13.0과 같습니다.

    이미지 게시 범위

    • 새로 빌드(5.14.0·latest): backend·crawler·web. shared(blacklist.ts·translations/·server/duplicate-scan-store.ts·schema-verifier.ts)가 바뀌어 세 앱의 빌드 입력이 달라졌고, backend는 migration 삭제·database.config.ts·중복 검토 서비스, crawler는 schema 검증·entity 기본값, web은 중복 관리 화면·태그 번역이 바뀌었습니다.
    • digest 재사용: nginx(5.10.0 digest), byedpi(5.4.0 digest). 빌드 입력이 같아 기존 digest에 5.14.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.14.0 태그가 있으므로 IMAGE_TAG=5.14.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • backend 기동 시 migration을 실행하지 않습니다. 기존 DB의 migrations·typeorm_metadata 테이블은 남아 있어도 무해하며, 삭제는 기존 설치 schema 반영의 선택 SQL로 할 수 있습니다. 삭제하면 5.13.0 이하로 되돌릴 때 migration이 다시 실행되므로 되돌리기 전에는 지우지 않습니다.
    • 새 ops/deploy-production.sh는 crawler를 미리 정지하지 않습니다. 실행 중인 수집 job은 crawler 교체 시 checkpoint에서 멈추고 새 crawler가 재개합니다. 운영 화면에서 job 상태를 확인합니다.
    • backend와 web은 함께 배포합니다. 옛 web과 새 backend 조합은 storedBytes를 무시하고 0 B를 유지하며, 새 web과 옛 backend 조합은 용량을 정보 없음으로 표시합니다.
    • compose.yml·.env.example은 5.13.0과 같아 이미지와 ops/·sql/ 파일만 바뀝니다.
    • rollback: 5.13.0 이미지는 다섯 서비스 모두 레지스트리에 있어 IMAGE_TAG=5.13.0으로 되돌릴 수 있습니다(migrations 테이블을 지우지 않았다면 schema 변경 없음).

    5.13.0 대비 전체 변경

    검증

    • 각 브랜치(migration 제거·블랙리스트·번역·중복 용량)에서 run-unit.ps1 -Workspace all, run-integration.ps1, run-schema.ps1이 통과했고, migration 삭제 직전 a3c20428에서 fresh init-db.sql catalog가 28개 migration 적용 결과와 동일함을 run-schema.ps1로 확인했습니다. 블랙리스트 격리 compose 검증, schema 검증 변이 4종 탐지 확인, 배포 스크립트 mock 검증이 통과했습니다. 네 브랜치는 gpt-6.1-sol 읽기 전용 리뷰(승인, P2 지적은 수정 후 재검)를 거쳤습니다.
    • 병합 main 38de95b5: 개발 backend·web 재빌드, run-translation-coverage.ps1(미번역 103개 모두 보류 판정), 저장소 Markdown 23개 링크·anchor 검사 0오류, git diff --check. 릴리스 commit에서 update-base-images.ps1(기반 이미지 digest 최신).
    • NOT RUN: run-compose-compat.ps1(compose.yml·Dockerfile 변경 없음), 이미지 검색·운영 UI 격리 검증(중복 관리 화면 시각 확인), crawler·network runner, 실브라우저 확인, 운영 규모의 storedBytes 집계 실측.

    게시 확인

    • 릴리스 소스: 6ffd65f9 (annotated Git 태그 5.14.0 대상, 앱 코드는 38de95b5와 같음).
    • backend 5.14.0·latest(새 빌드): sha256:4809c97fbda729ff89690f8fbda1fa9149e6126f2e48865b76d9731cd7cc7525
    • crawler 5.14.0·latest(새 빌드): sha256:d69cee16dfd4c6a73449b5835a32cae4d8707375587980f59cf91495d441eaf3
    • web 5.14.0·latest(새 빌드): sha256:1f0fc9a49898b4c977084333feb9a05e77cd64832993899e7658db1847f2d382
    • nginx 5.14.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.14.0·latest(5.4.0 digest 재사용): sha256:04cf2838499d67a033a3c3101913563bf983e551fee27b891dab0d2f75a4233a
    • ops/publish-images.ps1 -Version 5.14.0 -Publish가 첫 실행에서 완료됐고 다섯 서비스의 5.14.0·latest 일치를 확인했습니다(Registry tags verified for 5.14.0.).
    Downloads 2
  • 5.13.0

    5.13.0 주요 변경사항

    고급 검색 2라운드(web·backend)

    • POST /api/galleries/search에 하나라도 일치 태그 anyTags(최대 20), 쪽수 범위 minPages/maxPages(1~100000), 게시일 범위 uploadedAfter/uploadedBefore(YYYY-MM-DD, UTC 일 경계, 게시일 없는 작품 제외)를 추가했습니다. query 가중치 5, 캐시 키에 포함되며 GET 목록에는 적용되지 않습니다. 홈 검색창 pill과 고급 검색 패널에 같은 조건이 표시·편집됩니다.
    • 저장한 검색: saved_searches 테이블과 GET/PUT/DELETE /api/saved-searches(로그인 전용, 이름 60자·사용자당 50개·조건 JSON 8 KiB 상한)를 추가했고 계정 내보내기에 포함됩니다. guest는 브라우저에만 저장하며 로그인 뒤 병합 안내를 받습니다.
    • guest 최근 태그, 제외 태그를 개인 차단 규칙으로 승격(꺼 둔 규칙은 다시 켬, 409 처리), 긴 제외 칩 말줄임, 게시일 편집기·pill의 터치 높이 등 보정을 포함합니다.

    문서 정리

    • 저장소 Markdown 23개를 현재 코드·설정과 대조해 어긋난 설명(중복 검사 trigger 이름, creator-feed 가중치, UUID v4 규칙, checkpoint 409 조건, galleryinfo timeout, probe 수 402→401 등)을 정정하고, 변경 이력·측정 수치·구현 세부·이전 버전 전환 안내·보류 항목을 제거했습니다(약 614KB→510KB). docs/완료_이력.md는 최신 게시·마지막 운영 배포·현재 릴리스 주기의 검증 기준선만 유지합니다. 현재 미완료 계획은 없습니다.

    새 API·화면 기능과 데이터 보존 migration이 있어 minor 5.13.0으로 게시합니다. compose.yml·.env.example은 5.12.0과 같고 sql/init-db.sql에 saved_searches가 추가됐습니다.

    이미지 게시 범위

    • 새로 빌드(5.13.0·latest): backend·web. backend는 galleries 검색 DTO·query, saved-searches 모듈, 계정 내보내기, migration이, web은 홈 검색창·고급 검색 패널·저장한 검색·개인 차단 승격 컴포넌트·hook이 바뀌었습니다. 빌드 입력(Dockerfile·shared·lockfile) 자체는 같습니다.
    • digest 재사용: crawler(5.12.0 digest), nginx(5.10.0 digest), byedpi(5.4.0 digest). 빌드 입력이 같아 기존 digest에 5.13.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.13.0 태그가 있으므로 IMAGE_TAG=5.13.0으로 고정할 수 있습니다.
    • 참고: 같은 backend·web digest가 게시 과정의 착오로 잠시 5.12.1 태그로 올라갔다가 삭제됐습니다(Git 태그·레지스트리 태그 모두 제거). 내용은 5.13.0과 동일합니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • backend 기동 시 migration CreateSavedSearches가 saved_searches 테이블을 만듭니다(forward-only, 기존 데이터 변경 없음). 새 설치는 5.13.0 태그의 sql/init-db.sql을 받습니다.
    • backend와 web은 함께 배포합니다. 새 web은 anyTags·범위 조건과 /api/saved-searches를 호출하므로 옛 backend와 섞이면 해당 조건이 400, 저장한 검색이 404를 받습니다.
    • backend 교체 전 crawler를 정지하는 배포 절차 때문에 실행 중인 E-Hentai 수집 job은 운영 화면에서 수동 재개가 필요합니다.
    • compose.yml·.env.example은 5.12.0과 같아 운영이 5.10.0 이상 Compose라면 이미지만 바뀝니다.
    • rollback: 5.12.0 이미지는 다섯 서비스 모두 레지스트리에 있어 IMAGE_TAG=5.12.0으로 되돌릴 수 있습니다. saved_searches 테이블은 남지만 5.12.0은 이를 읽지 않습니다. 더 이전 버전은 web 5.6.05.11.0·crawler 5.9.05.11.0·backend 5.10.0 이하 태그가 없어 digest로만 지정할 수 있습니다.

    5.12.0 대비 전체 변경

    검증

    • 앱 코드(b6c87bfa, 릴리스 commit과 동일): 개발 stack 재빌드(backend·web), run-unit.ps1 -Workspace all, run-integration.ps1, 이미지 검색·운영 UI 격리 검증, 북마크 UI 격리 검증, 문서 검증이 통과했습니다. run-schema.ps1·run-passkey.ps1은 1차 병합 2ff9fe56, run-search-benchmark.ps1은 브랜치 311c61f8(p95 ≤ 11.6ms, index 추가 없음)에서 통과했습니다. backend·web 브랜치는 각각 gpt-6.1-sol 읽기 전용 리뷰 2라운드를 거쳤습니다.
    • 문서(8fb29a60): 문서 브랜치 네 개를 gpt-6.1-sol 읽기 전용 리뷰로 코드 대조(승인 3, P2 1건 복원 후 판정)했고, 저장소 전체 Markdown 23개 링크·anchor 검사 533건 0오류, git diff --check, 개발·운영 Compose config --quiet, update-base-images.ps1(기반 이미지 digest 최신)이 통과했습니다.
    • NOT RUN: main의 run-search-benchmark.ps1, run-compose-compat.ps1(compose.yml·Dockerfile 변경 없음), crawler·network runner(crawler 변경 없음), 실브라우저 확인, 운영 배포.

    게시 확인

    • 릴리스 소스: 29d639a8 (annotated Git 태그 5.13.0 대상, 앱 코드는 b6c87bfa와 같음).
    • backend 5.13.0·latest(새 빌드): sha256:6d9b3f8115d6cae09399a04eb7932a6a248b01f77f3816ba4e75b03d4bac20db
      • linux/amd64 manifest: sha256:28d25e05feb6adc6296d7a3a2065798394639620ecab0aee6215fc54e0e82f0d
    • web 5.13.0·latest(새 빌드): sha256:7234e4cfcdc633f99b1cc1de55a1e96a70e7c54873ef70a6577c7c38cd5a68a4
      • linux/amd64 manifest: sha256:94c009e46ab3901bc83da2cc292eff8fcd1c36272b3dd5de6fba3ce3b240e255
    • crawler 5.13.0·latest(5.12.0 digest 재사용): sha256:f5ce5f079ff563e6939330f9562afd50081e47eac253fa6cc867b377cdbfef09
    • nginx 5.13.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.13.0·latest(5.4.0 digest 재사용): sha256:04cf2838499d67a033a3c3101913563bf983e551fee27b891dab0d2f75a4233a
    • ops/publish-images.ps1 -Version 5.13.0 -Publish가 첫 실행에서 완료됐고 다섯 서비스의 5.13.0·latest 일치를 확인했습니다(Registry tags verified for 5.13.0.).
    Downloads 2
  • 5.12.0

    5.12.0 주요 변경사항

    고급 검색 패널(web)

    • "태그를 누를 때마다 포함 → 제외 → 해제 순서로 바뀌고 바로 적용됩니다." 안내 문구를 없애고, 태그 행의 접근성 이름에 다음 동작(누르면 포함·누르면 제외·누르면 해제)을 표기합니다.
    • 기본 태그 목록이 로그인 사용자의 선호 태그(대시보드 선호 태그와 같은 집계, 선호 배지와 읽은 횟수)를 먼저 보이고 그 뒤에 인기 태그를 이어 붙여 최대 50개를 보입니다. guest와 인증 복원 전에는 인기 태그만 보입니다. 선호 태그 조회가 실패해도 인기 태그는 그대로 보이고, 검색 중(두 글자 이상) 조회가 실패하면 기본 목록 대신 오류만 보입니다.
    • 카테고리 행(공개 category)을 더해 category:"code" 조건을 포함 → 제외 → 해제로 순환합니다. 기존 tags·excludeTags·URL 형식을 그대로 씁니다.
    • 분류 칩(전체·여성·남성·작가·그룹·캐릭터·패러디·언어·일반)으로 태그 검색·인기 목록을 분류별로 좁힙니다(패널 안 임시 상태, URL·저장값에 넣지 않음).
    • 모두 해제(태그 조건만 지움)·링크 복사(현재 조건 URL) 버튼과 포함할 태그 (N/20) 상한 표시를 더했고 상한에 닿은 목록으로 추가하는 행은 비활성화합니다.
    • ui-segmented-item 선택·제외 경계를 inset-ring 의미 토큰으로 바꿔 키보드 포커스 ring과 겹치지 않게 했습니다(다른 화면의 segmented 컨트롤도 같은 레시피를 씁니다).

    API(backend)

    • GET /api/reading-progress/preferred-tags?limit=(로그인 전용, query 가중치 1, limit 1~50·기본 20)을 추가했습니다. 응답은 { tags: [{ namespace, name, count }] }이며 대시보드 preferredTags와 같은 집계(전체 기간, 일반 tag 분류 제외, 개인 차단 적용)를 하나의 helper로 공유합니다. 같은 횟수의 태그는 namespace·name 오름차순으로 정렬하며, 이 정렬은 대시보드 선호 태그에도 적용됩니다.
    • GET /api/tags/search·GET /api/tags/popular가 선택 인자 namespace(^[a-z_]+$, 1~50자)를 받아 해당 분류만 돌려줍니다. groupBy=name과 함께 쓰면 400입니다.
    • /api/tags/popular가 DTO를 바인딩해 알 수 없는 query 인자는 400으로 거절합니다(web은 limit만 보냅니다).

    5.11.0 대비 새 API·새 화면 기능이 더해져 minor 5.12.0으로 게시합니다. 필수 환경 키·DB migration·compose.yml·.env.example·sql/init-db.sql 변경은 없습니다.

    이미지 게시 범위

    • 새로 빌드(5.12.0·latest): backend·web·crawler. backend는 reading-progress·tags 모듈, web은 고급 검색 패널 컴포넌트·hook·globals.css가 바뀌었습니다. crawler는 5.11.0 이후 소스 변경이 없지만 레지스트리에 비교할 이전 crawler 버전 태그(5.11.0)가 남아 있지 않아 지문을 재사용하지 못하고 새로 빌드했습니다. shared·lockfile·Dockerfile은 바뀌지 않았습니다.
    • digest 재사용: nginx(5.10.0 digest), byedpi(5.4.0 digest). 빌드 입력이 같아 기존 digest에 5.12.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.12.0 태그가 있으므로 IMAGE_TAG=5.12.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • backend와 web은 함께 배포합니다. 새 web은 preferred-tags·namespace 인자를 호출하므로 옛 backend와 섞이면 선호 태그 구역이 비고 분류 칩이 400을 받습니다(인기 태그·검색 자체는 동작).
    • backend 교체 전 crawler를 정지하는 배포 절차 때문에 실행 중인 E-Hentai 수집 job은 운영 화면에서 수동 재개가 필요합니다.
    • compose.yml·.env.example·sql/init-db.sql은 5.11.0과 같습니다. 운영이 이미 5.10.0 이상 Compose라면 이미지만 바뀝니다.
    • rollback: DB 변경이 없어 이전 이미지로 되돌릴 수 있지만, 레지스트리에 web·crawler의 5.11.0 버전 태그가 남아 있지 않습니다(backend·nginx·byedpi 5.11.0만 존재). web·crawler를 되돌리려면 이전 digest를 직접 지정해야 하며, 패키지 정리 규칙의 keep pattern(^(latest|\d+\.\d+(\.\d+)?)$) 점검이 필요합니다.

    5.11.0 대비 전체 변경

    검증

    • 병합 main c40d5f33(앱 코드는 릴리스 commit과 같음)에서 개발 stack 재빌드(backend·web, 9개 컨테이너 healthy, /api/health/ready 200), run-unit.ps1 -Workspace all(backend 82 suites·635 tests, crawler 71·923, web 141·1,755, lint·typecheck 포함), run-integration.ps1 전체, 이미지 검색·운영 UI 격리 검증(1440·768·390·320px), 북마크 UI 격리 검증(1440·768·390·450·320px), 문서 검증(개발·운영 Compose config, git diff --check, Markdown 링크·anchor 23개 파일 0건)이 통과했습니다.
    • 0e0dd28c(앱 코드 동일)에서 run-compose-compat.ps1(5.11.0 7e9f1e7e 대비 세 조합)과 update-base-images.ps1(기반 이미지 digest 모두 최신)이 통과했습니다.
    • backend·web 두 브랜치는 각각 gpt-6.1-sol 읽기 전용 리뷰를 거쳤습니다. web 1라운드의 P2 3건(검색 실패 시 기본 목록 노출, 선호 태그 재조회 실패 시 stale 행 유지, 제외 상태 CSS의 포커스 ring 충돌)은 수정 뒤 2라운드 리뷰에서 승인됐습니다.
    • NOT RUN: run-passkey.ps1·run-schema.ps1·run-search-benchmark.ps1, crawler·network runner(crawler 코드 변경 없음), 실브라우저 확인(다크 모드 제외 상태 포커스 표시, 320px 카테고리 행 실측), 운영 배포.

    게시 확인

    • 릴리스 소스: 67e88de1 (annotated Git 태그 5.12.0 대상, 앱 코드는 c40d5f33과 같음).
    • backend 5.12.0·latest(새 빌드): sha256:1dda399c6d66a8e2309118eca2af82b9c1a014b484add4677c88bc160907db3a
      • linux/amd64 manifest: sha256:bb349e02a07873ff9b3087b24b813665152604018aa73086aa02540e7911660b
    • web 5.12.0·latest(새 빌드): sha256:d4d0f26b224c16de64783e384d85ecbc2367c6fa0bbd04c005f0cd7b54c7254e
      • linux/amd64 manifest: sha256:9aa6607cf9ff20a57260df91b7d157b4e580fff022877670231d79e0623cddc1
    • crawler 5.12.0·latest(새 빌드, 소스 변경 없음): sha256:f5ce5f079ff563e6939330f9562afd50081e47eac253fa6cc867b377cdbfef09
      • linux/amd64 manifest: sha256:c9d8ed6a2e09918fa149356f33167573ba9f2215c000c6e8ba44e3e124889049
    • nginx 5.12.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.12.0·latest(5.4.0 digest 재사용): sha256:04cf2838499d67a033a3c3101913563bf983e551fee27b891dab0d2f75a4233a
    • ops/publish-images.ps1 -Version 5.12.0 -Publish가 첫 실행에서 완료됐고 다섯 서비스의 5.12.0·latest 일치를 확인했습니다(Registry tags verified for 5.12.0.).
    • 게시 시점 레지스트리에는 web 5.6.05.11.0, crawler 5.9.05.11.0, backend 5.10.0 이하 버전 태그가 남아 있지 않았습니다(패키지 정리 규칙 확인 필요).
    Downloads 2
  • 5.11.0

    5.11.0 주요 변경사항

    인증 · 세션

    • 세션 토큰의 auth_time claim이 필수가 되었습니다. auth_time이 없거나 유효하지 않은 토큰(5.4.0 이전에 발급된 토큰)은 첫 요청에서 세션 만료로 거절되고 해당 session이 삭제되므로, 그 사용자는 배포 뒤 한 번 다시 로그인해야 합니다. 정상 auth_time 토큰은 영향이 없습니다.
    • session metadata가 Redis eviction으로 비어 있어도 인증은 유지됩니다. 세션 목록에서는 현재 session의 createdAt을 토큰의 auth_time으로 보여주고, metadata가 없는 다른 session은 createdAt·lastUsedAt을 null로 돌려줍니다. 옛 session의 createdAt을 touch·renewal 때 다시 채우던 보정은 제거했습니다.

    web · 화면 수정

    • 운영 관리 이미지 색인 패널 상단의 "기존 이미지 등록 · 지문 생성 누적" 문장을 두 줄로 고정해, 누적 수가 길어져도 버튼 줄과 통계 칸이 밀리지 않습니다(390px에서 재현되던 20px 밀림).
    • 중복 검토 그룹의 판정 라벨은 저장된 detection 값으로만 정합니다. 값이 없거나 알 수 없는 그룹은 검사 방식 미기록으로 표시하고 더는 파일 목록 일치로 추정하지 않습니다.
    • 홈 마지막 검색 조건 저장값의 옛 useAdvancedSearch 읽기 변환을 제거했습니다. 저장값은 version과 관계없이 검색어·태그·정렬을 함께 읽습니다.

    테스트

    • 이미지 검색·운영 UI 격리 검증에 운영 패널 숫자가 바뀌어도(999→1,000→12,345, 진행률 0→100%) heading·버튼 줄·통계 칸 좌표가 유지되는지 1440·768·390·320px에서 검사하는 시나리오를 더했습니다.
    • 요청 제한(request budget) integration 검증이 고정 시각으로 창 경계를 검사해 호스트 부하에 따른 flake를 없앴습니다. 운영 코드는 Redis 시각을 그대로 씁니다.
    • session integration 검사가 auth_time 필수·metadata 없는 session 계약과 renewal 뒤 createdAt 미복원을 고정합니다.

    5.10.0 대비 새 기능은 없지만 5.4.0 이전 토큰의 지원을 끝내는 호환 범위 변경이 섞여 있어 minor 5.11.0으로 게시합니다(5.9.0·5.10.0의 호출처 없는 API 제거를 minor로 본 전례를 따릅니다). 필수 환경 키·DB migration·compose.yml 변경은 없습니다.

    이미지 게시 범위

    • 새로 빌드(5.11.0·latest): backend·web. backend는 auth 모듈·request budget service, web은 운영 패널·중복 검토·홈 검색 저장값 코드가 바뀌었습니다. shared·lockfile·Dockerfile은 바뀌지 않았습니다.
    • digest 재사용: crawler·nginx(5.10.0 digest), byedpi(5.4.0 digest). 빌드 입력이 같아 기존 digest에 5.11.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.11.0 태그가 있으므로 IMAGE_TAG=5.11.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • backend 배포 뒤 auth_time이 없는 5.4.0 이전 발급 토큰 사용자는 한 번 다시 로그인해야 합니다. 인증 장애가 아니라 의도된 세션 만료입니다.
    • backend 교체 전 crawler를 정지하는 배포 절차 때문에 실행 중인 E-Hentai 수집 job은 운영 화면에서 수동 재개가 필요합니다.
    • compose.yml·.env.example·sql/init-db.sql은 5.10.0과 같습니다. 운영이 이미 5.10.0 Compose라면 이미지만 바뀝니다.
    • rollback: 5.10.0 이미지로 되돌릴 수 있습니다(DB 변경 없음).

    5.10.0 대비 전체 변경

    검증

    • 병합 main 5cbbab47(앱 코드는 릴리스 commit과 같음)에서 개발 stack 재빌드(backend·web·log-reader, 9개 컨테이너 healthy, /api/health/ready 200), run-unit.ps1 -Workspace all(backend 80 suites·614 tests, crawler 71·923, web 140·1,738, lint·typecheck 포함), run-integration.ps1 전체, run-passkey.ps1, 이미지 검색·운영 UI 격리 검증(1440·768·390·320px, 숫자 변동 시나리오 포함), 북마크 UI 격리 검증(1440·768·390·450·320px), 문서 검증(개발·운영 Compose config, git diff --check, Markdown 링크·anchor 23개 파일 0건)이 통과했습니다.
    • 릴리스 commit에서 run-compose-compat.ps1(5.10.0 d8ad4758 대비 세 조합)이 통과했습니다(new-image-old-compose·new-image-new-compose·old-image-new-compose).
    • 세 브랜치(budget-flake·auth-compat·web-compat)는 각각 gpt-6.1-sol 읽기 전용 리뷰를 거쳤고, 리뷰 P2 2건(운영 가이드의 옛 토큰 재로그인 안내, detection 누락 그룹의 라벨)은 수정 뒤 코디네이터 판정으로 병합했습니다.
    • NOT RUN: run-crawler-recovery.ps1(crawler 코드 변경 없음)과 그 밖의 전용 runner, 실제 Hitomi·E-Hentai 통신 runner, 실브라우저 확인(320px에서 다섯 자리 페이지 번호의 진행 label 줄바꿈 후보), 운영 배포.

    게시 확인

    • 릴리스 소스: 7e9f1e7e (annotated Git 태그 5.11.0 대상, 앱 코드는 5cbbab47과 같음).
    • backend 5.11.0·latest(새 빌드): sha256:4909f241bb8dcf3841558362d7e71e937e77b70b96c5f7ba7fe949679a0cbd87
      • linux/amd64 manifest: sha256:a38aa8f2e232bc39d08c40e872bb0c803a4b0d8c957b289a30abcad3219aee78
    • web 5.11.0·latest(새 빌드): sha256:ba76de419b39c4580a4f1f09031d6aa88132c9c9c9c06e263a945dac4d6856e7
      • linux/amd64 manifest: sha256:bb93e0db02e0b16de4a78f6c0554a3877b8da99df85474cf72a94a56573d094f
    • crawler 5.11.0·latest(5.10.0 digest 재사용): sha256:f6db86d6da3cc66b88f199df24de3ec815ba1fe1989db245ddeffdc0c6ba08e2
    • nginx 5.11.0·latest(5.10.0 digest 재사용): sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
    • byedpi 5.11.0·latest(5.4.0 digest 재사용): sha256:04cf2838499d67a033a3c3101913563bf983e551fee27b891dab0d2f75a4233a
    • ops/publish-images.ps1 -Version 5.11.0 -Publish가 첫 실행에서 완료됐고 다섯 서비스의 5.11.0·latest 일치를 확인했습니다(Registry tags verified for 5.11.0.).
    Downloads 2
  • 5.10.0

    5.10.0 주요 변경사항

    북마크 · 모아보기

    • 작가·그룹 작품 탭이 모아보기로 바뀌어 북마크한 작가·그룹의 작품과 단일 갤러리 북마크를 한 목록으로 합쳐 보여줍니다(guest는 로컬 북마크 최대 500개, 로그인은 서버 북마크를 함께 조회).
    • 모아보기에 작품 탭과 같은 제목·작가 검색창과 전체/안 읽음/읽는 중/완독 필터가 생겼습니다. 검색은 서버에서 NFKC 정규화 뒤 단어 AND로 처리하고, 조건을 바꾸면 첫 page부터 다시 조회합니다. 로그인 사용자의 읽기 상태가 바뀌면(읽기 시작·완독·기록 삭제, 다른 탭 포함) 필터 결과와 개수가 갱신됩니다.

    web · 화면 수정

    • 홈 검색창의 포함 태그 pill에 + 접두가 보입니다(제외는 −).
    • 태그를 눌러 검색했을 때(또는 검색창 제안으로 넣었을 때) 고급 검색 목록의 해당 행에 + 포함·− 제외 표시가 뜨지 않던 문제를 고쳤습니다.
    • 홈 상세 modal에서 태그를 눌러 검색하면 modal 닫기의 history.back이 검색 이동을 취소해 Firefox에서 NS_BINDING_ABORTED가 나던 문제를 고쳤습니다. 닫기는 popstate까지 한 번만 처리하고 검색은 그 뒤 한 번 실행합니다.
    • 운영 관리의 이미지 색인·썸네일 생성 패널에서 버튼 아래 빈 줄을 없앴습니다.
    • 목록 카드 요약에 원본 게시 시각(uploadDate)이 포함되어 상세 modal 첫 render에 다른 행과 함께 표시됩니다.

    정리

    • 호출처 없는 코드·API·설정을 정리했습니다: backend TypeORM CLI·debug script와 미사용 devDependency, 로컬 실행 script, 소비처 없는 응답 필드(dashboard·통계·health·home-state 등), GET /api/duplicates/jobs/:id, 중복 검토의 legacy detection 필터, GC 실행 기록의 옛 deleted·includeDeleted 변환, 전역 태그 차단 단건 POST /api/blacklist/tag(일괄 POST /api/blacklist/tags로 통합, 응답 201), 카드 요약 tags[].usageCount, GC 결과 orphaned, crawler unified-status 축소.
    • crawler 운영 이미지의 dist에서 spec·fixture·test-support를 제외했습니다.
    • 항상 false이던 SYNCHRONIZE 키를 backend 설정과 compose.yml에서 지웠습니다(운영 조치 없음: 옛 이미지는 키가 없으면 false, 새 이미지는 키를 읽지 않습니다).
    • 의도한 동작 변경 두 가지: 괄호가 있는 작가·그룹 태그를 한 태그로 검색·차단하고, storage를 쓸 수 없을 때 설정 저장은 예외 없이 현재 화면 값만 유지합니다.
    • 테스트: runner 공용 helper(tests/lib/compose.ps1), web 테스트 파일을 typecheck에 포함, 중복 fixture·spec 정리.

    새 기능(모아보기 검색·필터·북마크 합치기)과 web이 더 쓰지 않는 관리자 API 제거가 섞여 minor 5.10.0으로 게시합니다. 필수 환경 키·DB migration 변경은 없습니다. compose.yml에서 backend SYNCHRONIZE 키가 빠졌지만 운영 조치는 없습니다.

    이미지 게시 범위

    • 새로 빌드(5.10.0·latest): backend·crawler·web·nginx. backend·crawler·web은 앱·shared 코드와 lockfile(devDependency 제거)이, nginx는 Dockerfile 정리로 빌드 입력 지문이 바뀌었습니다.
    • digest 재사용: byedpi(5.4.0 digest). 빌드 입력이 같아 기존 digest에 5.10.0·latest 태그만 붙였습니다.
    • 다섯 이미지 모두 5.10.0 태그가 있으므로 IMAGE_TAG=5.10.0으로 고정할 수 있습니다.

    NAS 업데이트와 주의사항

    운영은 운영 반영을 따릅니다.

    • backend·web을 함께 교체해야 합니다. 옛 web과 새 backend가 섞이면 전역 태그 차단(POST /api/blacklist/tag)이 404가 나고, 새 web과 옛 backend가 섞이면 모아보기 검색·필터가 무시됩니다.
    • backend 교체 전 crawler를 정지하는 배포 절차 때문에 실행 중인 E-Hentai 수집 job은 운영 화면에서 수동 재개가 필요합니다.
    • compose.yml을 5.10.0 태그 버전으로 받습니다(SYNCHRONIZE 키 제거만 바뀌었습니다).
    • 운영이 아직 5.8.1이면 5.9.0의 주의사항(Compose 변경, migration 1건, Web Analytics 수동 snippet 전환)이 그대로 적용됩니다.
    • rollback: 5.9.3 이미지로 되돌릴 수 있습니다(DB 변경 없음).

    5.9.3 대비 전체 변경

    검증

    • 병합 main 733ce1ee에서 개발 stack 재빌드(backend·crawler·web·log-reader, 9개 컨테이너 healthy), run-integration.ps1 전체, run-crawler-recovery.ps1 전체, 이미지 검색·운영 UI 격리 검증(1440·768·390·320px), 북마크 UI 격리 검증(1440·768·390·450·320px, 모아보기 검색·필터 포함), 문서 검증이 통과했습니다. 테스트 파일만 고친 fd20e486에서 run-unit.ps1 -Workspace all(backend 80 suites·614 tests, crawler 71·923, web 139·1,739, lint·typecheck 포함)이 통과했습니다.
    • pill + 변경(0f07cecf)은 run-unit.ps1 -Workspace web과 이미지 검색·운영 UI 격리 검증(접두 기호·같은 폭 단언 추가)으로 검증했습니다.
    • 전용 검증은 브랜치 commit에서 통과했습니다: run-schema.ps1·run-operations.ps1 -DeploymentOnly·run-compose-compat.ps1(5.9.3 2ddb1529 대비 세 조합)·run-upgrade.ps1 -BuildNew(deploy-script)·검색·중복 benchmark·near-miss fixture는 03eaeeb4, 모아보기 SQL EXPLAIN ANALYZE(10만 작품 fixture, 후보 수 비례 2~90ms)는 6912001d.
    • 각 브랜치는 gpt-6.1-sol 읽기 전용 리뷰를 거쳤습니다(ui-bugs·bookmarks-feed는 수정 뒤 2라운드 승인). pill 변경은 독립 리뷰 없이 병합했습니다.
    • NOT RUN: 위 전용 runner의 main 재실행, run-crawler-recovery.ps1 -EHentaiOnly, run-passkey.ps1, 실제 Hitomi·E-Hentai 통신 runner, run-upgrade.ps1 watchtower 모드, 실브라우저(Firefox NS_BINDING_ABORTED 재현, 두 탭 읽기 신호), 운영 규모 feed 실행 계획, 운영 배포.

    게시 확인

    • 릴리스 소스: d8ad4758a927028d732badef2e5ebb686ff383d5 (annotated Git 태그 5.10.0 대상).
    • backend 5.10.0·latest: sha256:42e2378f1f3b5c1ac276be83b6c8c9d099d9be6e75aca6f56dbbc3cef6e63cf2
      • linux/amd64 manifest: sha256:72a09087218406dd608ffe856378034c1df6b49085b7bcd841ef181bdbef2ca2
      • OCI version 5.10.0·revision d8ad4758a927028d732badef2e5ebb686ff383d5
    • crawler 5.10.0·latest: sha256:f6db86d6da3cc66b88f199df24de3ec815ba1fe1989db245ddeffdc0c6ba08e2
      • linux/amd64 manifest: sha256:822a2893e030760db7331581a7f4af159023ed1889f623aec94163dfe2c57754
    • web 5.10.0·latest: sha256:4244f95ab4b99d4fd192a7dc6ddff709753fe9a79a58ea7963e3d7b72de4a24f
      • linux/amd64 manifest: sha256:b2560f42720759a64c32913f3aecd0bd778469db7e5bf6889776524636c1dd64
    • nginx 5.10.0·latest: sha256:552b18eddb10c22b7dbfaee60a6e1bacd20f8b004892c8209f3b48f508c3a780
      • linux/amd64 manifest: sha256:1daf8285e6aedac87ca3b22e41c20678414e1e92d7d994fa4bd62f30a3c009cb
    • byedpi 5.10.0·latest(5.4.0 digest 재사용): sha256:04cf2838499d67a033a3c3101913563bf983e551fee27b891dab0d2f75a4233a
    • ops/publish-images.ps1 -Version 5.10.0 -Publish는 첫 실행에서 네 버전 태그 push가 error from registry: unknown으로 실패했고(latest는 그대로 5.9.3) 같은 명령 재실행으로 완료했습니다. 다섯 서비스의 5.10.0·latest 일치를 확인했습니다(Registry tags verified for 5.10.0.).
    Downloads 2