Releases

  • 1.2.0

    다운로드는 끊기지 않는 방식 하나로

    • 폴더나 여러 항목을 받을 때 더 이상 방식을 고르지 않습니다. Cloudflare가 연결을 끊거나 멈춰도 알아서 이어받는 방식으로 바로 받습니다.
      • Chrome·Edge: 고른 폴더에 폴더 구조 그대로 저장합니다.
      • Firefox: 이어받는 ZIP으로 받습니다. 다 받을 때까지 페이지를 열어 두세요.
      • Safari·iOS: 이어받는 방식을 지원하지 않아 일반 ZIP으로 받습니다.
    • 공유 페이지에는 전체 다운로드 버튼 하나만 남겼습니다. 'ZIP 다운로드' 버튼과 ZIP 안내 창은 없앴고, 목록의 하위 폴더 다운로드도 같은 방식으로 받습니다.
    • 앱에서 폴더를 받을 때 뜨던 'ZIP / 폴더로 저장' 선택 창도 없앴습니다.

    공유 링크

    • 링크 설정에서 만료 기간을 바꿀 수 있습니다. 그대로 두거나, 지금부터 1일·7일·30일·90일·무제한, 또는 날짜를 지정할 수 있습니다.
    • 공유 링크 기록에서 IP 주소를 끝까지 보여 줍니다. 긴 IPv6 주소는 콜론 뒤에서 줄을 바꿉니다.
    • 휴대폰으로 연 공유 페이지 상단에 사이트 이름이 보입니다.

    실수 방지

    • 삭제 확인 창이 실제 동작을 알려 줍니다. 공유 폴더에 휴지통(#recycle)이 있으면 휴지통으로 옮긴다고 안내하고, 없을 때만 되돌릴 수 없다고 알립니다.
    • 삭제처럼 위험한 확인 창은 처음에 취소가 선택돼 있어서, Enter를 눌러도 지워지지 않습니다.
    • 옮기거나 복사할 때 같은 이름이 있으면 기본 선택이 '덮어쓰기'에서 둘 다 유지로 바뀌었습니다.

    휴대폰과 보기 편의

    • 휴대폰에서 여러 항목을 선택하면 아래 막대의 버튼이 3열로 줄을 바꿔 모두 보입니다. 선택하는 동안에는 앱 설치 안내를 숨깁니다.
    • 터치 화면에서 체크박스와 작은 버튼을 키웠고, 조회 수 같은 링크와 정렬 버튼은 누르는 영역을 넓혔습니다.
    • 다크 모드의 파란·빨간 버튼, 검색창 안내 글씨, 배지 글씨를 더 잘 읽히게 했습니다.
    • 링크와 검색 지우기 버튼에 키보드 포커스 표시를 넣었고, 🔒 이모지를 다른 아이콘과 같은 선 아이콘으로 바꿨습니다.
    • 확인 창의 문장이 단어 중간에서 끊기지 않습니다.

    업데이트

    compose.yaml은 바뀌지 않았습니다. docker compose pull && docker compose up -d 하세요.

    이미지: git.2ex.dev/hanyul/webdav:latest

    Downloads 2
  • 1.1.2

    내 공유 링크 창

    • 창을 넓혔습니다(너비 520px → 860px, 목록 높이 420px → 560px).
    • 공유한 경로를 ...로 자르지 않고 줄을 바꿔 끝까지 보여 줍니다.
    • 만료·생성 시각을 2026. 11. 07. 12:01 까지, 2026. 10. 31. 12:01 생성처럼 띄어 쓰고, 항목 사이의 ·를 없앴습니다. 줄마다 날짜 위치가 맞습니다.
    • 날짜, 조회·다운로드 수, 배지가 중간에 끊기지 않습니다.
    • 좁은 화면(640px 이하)에서는 버튼이 아래 줄로 내려가 경로와 날짜가 전체 폭을 씁니다.

    업데이트

    compose.yaml의 포트가 Web Station 포털에 맞춰 127.0.0.1:30005로 바뀌었습니다. compose.yaml을 바꾼 뒤 docker compose pull && docker compose up -d 하세요.

    이미지: git.2ex.dev/hanyul/webdav:latest

    Downloads 2
  • 1.1.1

    코드 정리

    기능과 화면은 그대로이고, 내부 코드만 정리했습니다.

    • 웹 화면의 여러 파일에 복사돼 있던 공통 함수(크기·날짜 표시, 아이콘, 텍스트 디코딩 등)를 public/util.js 하나로 모았습니다.
    • 새 폴더·이름 바꾸기 입력 창, 파일과 ZIP의 이어받기(Range) 처리, ZIP 파일 읽기를 각각 하나로 합쳤습니다.
    • 더 이상 필요 없는 코드를 지웠습니다: Node 26에서는 쓰이지 않는 CRC32 대체 구현, 1.1.0에서 이미 끝난 ZIP CRC 캐시 이전 코드, 화면에서 쓰지 않는 응답 필드, 겹치는 검사.

    업데이트

    compose.yaml은 바뀌지 않았습니다. docker compose pull && docker compose up -d 하세요.

    이미지: git.2ex.dev/hanyul/webdav:latest

    Downloads 2
  • 1.1.0

    데이터 보호

    • 공유 폴더 자체(맨 위 단계의 폴더)는 웹·WebDAV 어디서든 지우기, 옮기기, 이름 바꾸기를 할 수 없습니다. 맨 위 단계에는 파일이나 폴더를 만들 수 없습니다. 화면에서도 해당 버튼이 꺼집니다.
    • 덮어쓴 기존 파일은 #recycle로 옮겨 둡니다. 중간에 실패하면 원래 파일을 되돌립니다.
    • 공유 폴더 사이 이동은 파일마다 복사한 뒤 원본을 지웁니다. 숨김 파일과 링크도 함께 옮기고, 그 안을 가리키던 공유 링크 경로가 따라갑니다.
    • 복사할 때 링크는 따라가지 않고 링크 그대로 복사합니다.

    새 기능

    • 복사·이동 작업에 취소 버튼이 생겼습니다. 이미 옮긴 항목은 그대로 둡니다.
    • 격자 보기: 시놀로지가 만들어 둔 썸네일을 보여 주고, 작은 이미지는 원본을 씁니다. 고른 보기는 기억합니다.
    • 공유 링크
      • 다운로드 횟수 제한
      • 일시 중지(설정 버튼)
      • 폴더 링크에서 방문자 업로드 허용: 이름이 겹치면 이름 (1)로 저장, 올린 파일 기록 탭

    보안

    • IP별 제한에 더해 계정별 로그인 실패 제한(MAX_ACCOUNT_FAILURES, 기본 30)을 둡니다. WebDAV 로그인과 OTP 실패도 횟수에 넣습니다.
    • 패스키는 PIN이나 생체 인증을 요구합니다(PASSKEY_REQUIRE_UV, 기본 true). 사용 횟수를 확인하고, 등록되지 않은 계정에도 가짜 키 정보를 돌려줘서 계정 유무를 알 수 없게 합니다.
    • 로그인 세션을 해시로 state/app.db에 저장해서 재시작해도 로그인이 유지됩니다. 업데이트 직후에는 한 번 다시 로그인해야 합니다.
    • 활동 로그(state/activity.log)에 로그인, 공유, 업로드, 이동·복사, WebDAV 쓰기를 남깁니다.
    • 보내는 파일에 Content-Security-Policy: sandbox(PDF 제외), 컨테이너는 읽기 전용(read_only, tmpfs /tmp, pids_limit)으로 바꿨습니다.
    • 공유 링크 방문자는 미디어 재생과 ZIP 받기를 동시에 몇 개까지만 할 수 있습니다. 공유 폴더 밖을 가리키는 링크는 목록에서 숨깁니다.
    • Cloudflare IP 목록을 CLOUDFLARE_IPS로 바꿀 수 있습니다.

    정리

    • 웹 화면 코드를 기능별 모듈로 나눴고, 정적 파일은 ETag로 캐시합니다.
    • ZIP 이어받기 계획을 다시 쓰고, CRC 캐시는 SQLite로 옮겼습니다.
    • 단위 테스트(npm run test:unit)를 추가했습니다.

    업데이트

    compose.yaml이 바뀌었습니다(읽기 전용 설정). 새 compose.yaml을 받은 뒤 docker compose pull && docker compose up -d 하세요.

    이미지: git.2ex.dev/hanyul/webdav:latest

    Downloads 2
  • 1.0.4

    공유 페이지 다운로드 버튼 정리

    • 폴더를 열면 파란 전체 다운로드와 그 옆에 회색 ZIP 다운로드가 나옵니다.
    • 전체 다운로드는 끊기거나 멈춰도 알아서 이어받습니다.
      • Chrome·Edge: 고른 폴더에 폴더 구조 그대로 저장 (기존 '폴더째 받기')
      • Firefox 등 (새로 추가): 페이지가 ZIP을 직접 받아 브라우저 다운로드로 넘깁니다. 연결이 끊기거나 30초 멈추면 끊긴 지점부터 다시 이어서, 브라우저에는 한 번도 끊기지 않은 다운로드로 보입니다. 다 받을 때까지 페이지를 열어 둬야 합니다.
    • ZIP 다운로드는 브라우저가 직접 받는 ZIP으로, 누르면 끊길 수 있다는 안내가 먼저 나옵니다.
    • 로그인 화면에서 폴더를 받을 때도 Firefox는 자동 이어받는 ZIP을 씁니다.
    • Safari는 이 방식을 지원하지 않아 기존 ZIP 다운로드를 그대로 씁니다.

    이미지: git.2ex.dev/hanyul/webdav:1.0.4

    Downloads 2
  • 1.0.3

    만료된 공유 링크를 기록까지 바로 지우도록 바꾼 patch 릴리스입니다. 설정 변경은 필요 없습니다.

    변경

    • 만료되면 바로 삭제: 공유 링크가 만료되면 링크와 조회·다운로드 기록(state/share-logs/<token>.jsonl)을 함께 삭제합니다. 이전에는 만료 뒤 7일 동안 "만료됨"으로 목록에 남았습니다.
    • 정리 주기: 1분마다 정리합니다(이전 1시간). 공유 목록을 열 때도 먼저 정리해서, 만료된 링크는 목록에 보이지 않습니다.
    • 화면 정리: 공유 목록의 "만료됨" 표시와 관련 스타일을 없앴습니다.

    검증

    • E2E 테스트 35건 통과.
    • 만료된 링크가 목록에서 사라지고, 기록 조회가 404를 돌려주는지 확인하는 검사를 추가했습니다.
    • 배포 시점에 운영 서버에는 만료된 링크가 없었습니다(전체 5개).

    이미지

    git.2ex.dev/hanyul/webdav:1.0.3 / latest: sha256:edf92de7f5e46e20bc96847c93d9e6cae0d2d85e4101d44ef84a25a15bcb9135

    릴리스 소스: 84db4d5622e4eaa513fa9eb7232897285a23bca7

    1.0.2 이후 전체 변경 비교

    Downloads 2
  • 1.0.2

    공유 페이지의 ZIP 다운로드에 끊김 경고를 추가한 patch 릴리스입니다. 설정 변경은 필요 없습니다.

    변경

    • ZIP 경고 창: 공유 페이지에서 "전체 다운로드 (ZIP)"를 누르면 먼저 경고 창을 띄웁니다. ZIP은 한 파일로 오래 받아서 Cloudflare 경유 중 끊기거나 멈출 수 있고, 그때는 브라우저 다운로드 목록에서 "다시 시작"을 눌러야 한다는 내용입니다.
    • 폴더째 받기로 전환: Chrome·Edge에서는 경고 창에서 끊겨도 알아서 이어받는 "폴더째 받기"로 바로 바꿀 수 있고, 이 버튼이 기본 선택입니다. 폴더 저장을 지원하지 않는 브라우저(Firefox·Safari 등)에서는 취소와 "ZIP으로 받기"만 보입니다.
    • 본 앱 다운로드 창: 같은 경고를 넣고, 폴더 저장 설명을 현재 동작("끊기거나 멈춰도 알아서 이어받음")에 맞췄습니다.

    배경

    1.0.1로 94GB를 다시 받아 본 결과입니다.

    방식 끊김 직접 "다시 시작"
    폴더째 받기 4번 0번 (모두 자동 복구)
    Chrome 기본 ZIP 다운로드 5번 5번 (Chrome이 스스로 재시도하지 않음)

    두 방식 모두 파일은 정상이었습니다(크기 일치, ZIP CRC 전부 정상).

    검증

    브라우저 테스트로 Chromium과 폴더 API가 없는 브라우저를 각각 확인했습니다.

    • 경고 문구와 버튼 구성
    • 취소하면 다운로드하지 않음
    • "ZIP으로 받기"는 다운로드 시작, "폴더째 받기"는 폴더 저장 완료

    이미지

    git.2ex.dev/hanyul/webdav:1.0.2 / latest: sha256:b03ff043063d533928d8015b541459da8036f4fa5943f59a9dafd8df677d4322

    릴리스 소스: 1eb9203309e07223da1210775556d51505775da0

    1.0.1 이후 전체 변경 비교

    Downloads 2
  • 1.0.1

    대용량 다운로드가 Cloudflare 경유 중 끊길 때 자동으로 복구하도록 고친 patch 릴리스입니다. 설정 변경은 필요 없습니다.

    배경

    94GB 공유 폴더를 실제로 받아 보며 끊김을 기록했습니다. 한 연결이 1~6분마다 끊겼고, 원인은 모두 Cloudflare 경로였습니다.

    • 끊김 증상: TCP 리셋, Cloudflare의 HTTP/2 스트림 리셋(INTERNAL_ERROR), TLS 레코드 손상(bad record mac).
    • 가장 나쁜 경우: 서버 쪽 요청만 끊고 받는 쪽 연결은 데이터 없이 열어 둡니다. 브라우저 다운로드가 0B/s로 멈춰 직접 "다시 시작"을 눌러야 합니다.
    • 같은 회선에서도 연결마다 Cloudflare 데이터센터가 바뀝니다(HKG·NRT·LAX·PDX·SEA). 속도도 1~60MB/s로 크게 다릅니다.
    • NAS 안에서는 끊김이 없었습니다: Node에 직접, DSM nginx(HTTP/2)를 거쳐 각각 450초씩 받았습니다.

    변경

    • 공유 페이지: Chrome·Edge에서는 "폴더째 받기"가 기본 버튼입니다. 끊기거나 멈추면 알아서 이어받습니다. ZIP은 보조 버튼입니다.
    • 폴더째 받기: 30초 동안 데이터가 없으면 멈춘 연결로 보고 다시 연결합니다(이전 60초). 진행 없이 연속 10회까지 재시도합니다(이전 6회).
    • 로그: 중간에 끊긴 응답을 보낸 양과 함께 기록합니다. (1.0.0 이후 반영)

    검증

    • ZIP 실다운로드: 94GB를 받는 동안 10번 끊겼고, 매번 끊긴 지점부터 이어받아 완료했습니다. 53개 파일 CRC 전부 정상.
    • 브라우저 테스트: 한 파일에서 9번 끊어도 이어서 완료했습니다. 응답 없이 멈춘 요청은 31초 만에 다시 연결했습니다.

    이미지

    git.2ex.dev/hanyul/webdav:1.0.1 / latest: sha256:a19e3ab8ca377886948381fb36a61b5f7f2f0fb57c6d665bf525f267e744f30d

    릴리스 소스: 60f3e7238a4e5aeda57b65bfce1fd5b64a732e1b

    1.0.0 이후 전체 변경 비교

    Downloads 2
  • 1.0.0

    Synology NAS용 브라우저·WebDAV 파일 서버의 첫 정식 릴리스입니다. DSM 계정과 패스키로 로그인하고, 브라우저와 Windows 탐색기(WebDAV)에서 같은 공유 폴더를 다룹니다.

    주요 기능

    • 로그인: DSM 계정(2단계 인증 포함)과 DSM에 등록한 패스키, 허용 사용자 제한, IP별 로그인 차단.
    • 파일 관리: 탐색, 여러 개 선택(Shift·Ctrl+A), 끌어서 이동, 이름 변경·복사·삭제, 원격 검색.
    • 업로드: 청크 업로드와 이어 올리기. Cloudflare 100MB 요청 제한 안에서 큰 파일도 올라갑니다.
    • 다운로드
      • 파일·폴더 ZIP 다운로드. 압축 결과가 항상 같아서 끊겨도 이어받을 수 있습니다.
      • Chrome·Edge에서 "폴더째 받기": 파일 3개를 동시에 받고, 끊기면 파일 단위로 자동 이어받습니다.
    • 미리보기
      • 영상: 브라우저가 못 여는 코덱(HEVC 4:4:4, 10비트 H.264, Xvid, MPEG-TS 등)은 ffmpeg로 변환해 재생합니다.
      • 자막: 같은 이름의 자막 파일과 내장 자막을 표시하고, 크기·배경·싱크를 설정할 수 있습니다. 음성 트랙도 고를 수 있습니다.
      • 그 밖에 이미지, 음악, PDF, 텍스트를 미리 봅니다. 확장자를 모르는 파일도 텍스트로 열어 봅니다.
    • 텍스트 편집: 원격 텍스트 파일을 바로 고쳐 저장합니다. 소유자와 권한은 유지하고, 그사이 다른 곳에서 바뀌었으면 알려 줍니다.
    • 공유 링크: 만료일, 비밀번호, 조회·다운로드 기록, 디스코드 같은 메신저에서 보이는 링크 미리보기(OG 태그).
    • WebDAV: URL 루트에서 Windows 탐색기 네트워크 위치로 연결됩니다.
    • 모바일: 홈 화면에 추가(PWA) 안내.

    이번 릴리스 직전 수정

    • 재시작 뒤 ZIP 이어받기: 이어받을 지점 앞 파일들의 CRC를 백그라운드에서 계산하고, 결과를 state/zip-crc.json에 저장합니다. 88GB 지점에서 이어받아도 0.4초 안에 응답합니다. 이전에는 앞부분을 다 읽느라 Cloudflare 제한에 걸려 실패했습니다.
    • 폴더째 받기 재시도: 진행이 있으면 재시도 횟수를 초기화하고, 60초 동안 데이터가 없는 연결은 다시 연결합니다.
    • 로그: 중간에 끊긴 응답도 보낸 양과 함께 기록합니다.
    • 앱 설치 안내: 한 줄로 표시합니다.

    이미지

    태그 digest
    git.2ex.dev/hanyul/webdav:1.0.0 / latest sha256:25959eadf54d333bc63edd0c9be16f27c8aa732213ffd699214a570bd42b0487

    linux/amd64, Node.js 26 (Alpine), ffmpeg 포함. compose.yaml은 이제 이 이미지를 받아 실행합니다. 업데이트는 docker compose pull && docker compose up -d로 합니다. 특정 버전에 고정하려면 .env에 IMAGE_TAG=1.0.0을 적습니다.

    검증

    • E2E 테스트 35건 통과: WebDAV, 업로드, 인증·패스키, ZIP 이어받기(CRC 캐시가 없는 상태 포함), 공유 링크, 영상 변환, 심볼릭 링크 차단, 클라이언트 IP 판별.
    • 브라우저 테스트: 폴더째 받기에서 연결을 9번 끊어도 끝까지 받는지, 앱 설치 안내가 320·360·412px 화면에서 한 줄로 나오는지 확인.
    • 운영 NAS에서 이 이미지로 전환해 정상 동작(healthy)과 실서비스 응답을 확인했습니다.

    릴리스 소스: a889e70404172f7978ca6d3670fe40ab34226922

    Downloads 2