공식 홈페이지에 있는 아래 주소인데요.
https://xe1.xpressengine.com/index.php?mid=download&package_id=22753684
=====================================================================
제가 조금씩 손보고 있는 기능이에요 저도 용량 걱정이 있는 편이라..
홈페이지가 구동되는 드라이브에 xe/파일에 첨부파일들이 쌓이는게 아무래도 용량 부담이 되서요.
https://bsplus.net/xe/R_XE_dataroom/14952
첨부파일을 외부로! (lua_external_file) - 리빌드 -v0.8.0
좀 더 업그레이드 시켜보았습니다.
==================================================================
그래서 다른 드라이브에 첨부파일이 쌓이게 변경을 시켰습니다.
근데 이건 홈서버 사용자들만 가능한 기능인데요
웹호스팅 사용자도 나스나 여러 외부로 보낼수 있는 방법이 있으면 너도나도 쓸수 있지 않을까? 생각합니다.
즉 홈페이지는 보여주기만 하면 되게 해주고 파일들의 중요 내용은 다른 곳에서 저장및 불러오는 거죠?
DB 백업이 그렇잖아요?
보여줄 내용들만 백업해주는거지 파일까지 백업이 아니니까요??
좋은 피드백 부탁합니다~~ 좋은 기능으로 다 같이 사용해 보면 좋겠습니다~~~
=================================================================================
끝으로... 제가 mcp 에게 이 애드온에 대해서
> 아 이 애드온에 추가 하면 좋은 기능 생각났다. 보통 웹호스팅 사용자들은 용량 걱정이 크겠지? 그럼 용량을 대체 해줄 방법이 뭐가 있을까? 나스서버나 외부 서버와 연결시켜줄 방법은 없을까?
좋은 방향이에요. 지금 애드온은 "PHP가 접근 가능한 경로"만 지원하는데, 이건 사실 로컬 드라이브나 마운트된 네트워크 드라이브(지금 쓰시는 I: 드라이브처럼)에서만 되는 방식이라 웹호스팅(공유호스팅) 환경에선 아예 못 씁니다 — 거긴 네트워크 드라이브를 마운트할 권한 자체가 없거든요.
웹호스팅 사용자용으로 실제로 통하는 방법은 이 세 가지 정도예요:
1. WebDAV — 시놀로지/큐냅 같은 NAS는 거의 다 WebDAV를 지원해요. PHP의 curl만으로 HTTP PUT/GET/DELETE 요청을 보내면 되니까 추가 확장 설치 없이 가장 가볍게 구현 가능. 저는 이게 제일 실용적이라고 봐요.
2. SFTP — NAS/원격서버에 SSH로 붙는 방식. ssh2 PHP 확장이 보통 공유호스팅엔 안 깔려있어서, 순수 PHP 라이브러리(phpseclib)를 같이 넣어야 함 → 좀 더 무거움.
3. S3 호환 오브젝트 스토리지 (Backblaze B2, 또는 NAS 자체 S3 게이트웨이) — 클라우드스럽고 확장성은 제일 좋은데, SDK 의존성이 생기고 설정도 더 복잡함.
추천: WebDAV 방식으로 새 저장 방식 하나 추가하는 게 지금 애드온의 "가볍게, 의존성 최소로" 철학과도 잘 맞을 것 같아요. 기존 "로컬 경로" 방식은 그대로 두고, 관리자 설정에 "저장 방식: 로컬 경로 / WebDAV(NAS)"를 선택하게 만들면 됩니다.
이 방향으로 만들어볼까요, 아니면 SFTP나 S3 쪽이 더 끌리세요?
✻ Baked for 27s
> 조금 다방면에서 모두가 우와~! 하고 감탄할수 있게 여러가지를 지원해보면 어떨까?
오, 좋아요! 이왕 할 거면 제대로 확장성 있게 만들어볼게요. 로컬/마운트 경로 하나만 지원하던 걸 "저장소 드라이버" 구조로 바꿔서 여러 방식을 다 지원하게 만들 수 있어요.
의존성 없이 지금 바로 만들 수 있는 것들 (PHP 내장 기능 + curl만으로):
- FTP — PHP 기본 내장 함수라 별도 설치 없음
- WebDAV — 시놀로지/큐냅 NAS 대부분 지원, curl PUT/GET/DELETE로 구현
- S3 호환 오브젝트 스토리지 — AWS S3, Backblaze B2, Cloudflare R2, MinIO, NAS의 S3 게이트웨이까지 전부 호환. AWS SDK 없이 서명(SigV4)을 직접 구현해서 가볍게 만들 수 있어요
의존성이 좀 필요한 것:
- SFTP — ssh2 PHP 확장이 서버에 없으면 phpseclib라는 순수 PHP 라이브러리를 같이 넣어야 해서 용량이 꽤 커집니다
또 하나 중요한 설계 포인트: 지금은 "다운로드 시점에 이동"인데, FTP/WebDAV/S3는 네트워크 요청이라 다운로드할 때마다 느려질 수 있어요. 그래서 원격 저장소들은 업로드 직후에 바로 이동시키고(로컬 경로만 기존처럼 다운로드 시점 이동 유지), 관리자 설정에 각 저장소별 "연결 테스트" 버튼도 넣으면 훨씬 안심되겠죠.
──────────────────────────────────────────────────────────────────────────────────────────────
[ ] SFTP 포함 여부
SFTP도 포함할까요? phpseclib 라이브러리를 번들로 들어가야 해서 용량이 꾨 커져요
1. 지금은 빼고 FTP/WebDAV/S3만 (추천)
의존성 없이 가벼게 먼저 만들고, SFTP는 나중에 필요하면 추가
> 2. 처음부터 SFTP도 같이
phpseclib 번들링해서 4가지 다 한번에 <<<< 이거를 선택해서 할지 ... 고민입니다 ㅎㅎ
3. Type something.
이렇게 진행중이긴 합니다...
좋은 피드백 많이 남겨주세용~~^^
댓글 15
제가 생각해보는건 해볼수 있지만 제가 웹 지식은 없어요 ㅠㅠ
기진곰님이나 이온디님이나 여러 개발자분들의 전문 지식이 필요합니다 ㅎㅎ 많이 피드백 남겨주세용~~
이것저것 다 하려고 하지 말고 FTP나 S3 중 하나만 해 보세요. 나머지는 AI가 흔히 하는 "오버엔지니어링"의 영역입니다. 요즘 누가 WebDAV를 써요 ㅋㅋ
난이도 상승:
1) 사진이 서버에 저장되어 있지 않으면 썸네일 생성은 어떻게?
2) 파일 삭제도 연동해 주기
https://svrforum.com/?_filter=search&vid=&mid=software&category=&search_target=title_content&search_keyword=webDAV+
여기 사이트 보니까 WebDAV 이거 이야기가 많더라구요 ㅎㅎ 그래서 많이 쓰는줄 알았습니다 ㅎㅎ
현재로서는 거의 NAS에서만 지원하는 방식이라 NAS가 있어야 하는데... 홈서버로 활용할 수 있는 NAS가 있다면 굳이 용량을 걱정해 가며 웹호스팅을 쓰지 않을 테니 수요층이 서로 안 맞죠. ㅎㅎ
기진곰님 이 애드온은 호불호가 있을꺼 같구요 혹시 자료실에 올려도 될지 모르겠습니다.
이 댓글 보신분은 어떻게 하면 좋겠는지 여쭤봅니다. 자료실에 올려도 될지 궁금합니다.
지금까지 이런 종류의 기능을 안전하게 구현한 자료는 없었습니다. 혼자 쓴다면 몰라도, 다양한 환경에서 홈페이지를 운영하는 불특정 다수에게 배포한다면 파일 날려먹기 딱 좋죠. ㅎㅎ
애드온으로 구현하는 것은 더더욱 추천하지 않습니다. 단도직입적으로 말씀드릴게요. 모듈로 만들어도 신경써야 할 것이 많은데, 애드온 "따위"로는 이런 기능의 안전성을 보장하기가 아주아주 힘들 겁니다.
1) 사진이 서버에 저장되어 있지 않으면 썸네일 생성은 어떻게?
2) 파일 삭제도 연동해 주기
ㄴ 이 2가지에 대해서 헛점이였어요 고맙습니다 기능 추가 수정하고 있습니당 ^^ ㅎㅎ
섬네일도 문제고, 접근권한 관리도 문제고 좀 많이 힘드실것같습니다.
특히 s3이나 일반 호스팅으로 빠져버리면 접근권한 관리가 쉽지 않을겁니다.
s3은 유동적으로 signed url 생성해주면 되는데, 일반 ftp환경이면 그것도 쉽지 않거든요.
에카님께서 말씀 주신걸 MCP에 적어서 줬더니
맞아요, 정확한 지적이에요. 지금까지 만든 구조를 권한 관점에서 다시 짚어보면 이렇습니다.
지금 실제로 지켜지는 부분
"다운로드" 버튼(procFileDownload)은 백엔드가 뭐든 상관없이 FileModel::isDownloadable()을 거쳐서 스트리밍하기 전에 라이믹스 권한 체크를 통과해야 해요. 이건 5개 백엔드 전부 동일하게 지켜집니다.
지금 안 지켜지는 부분
게시글 본문에 박힌 <img> 같은 정적 서빙 폴백(serve_file.php)은 권한 체크가 전혀 없어요. rel_path만 맞으면 그냥 스트리밍합니다. 다만 이건 이 애드온이 새로 만든 구멍이 아니라 — 원래 라이믹스 자체가 direct_download='Y'인 파일(본문 삽입용)은 애초에 Apache가 PHP도 안 거치고 그냥 정적으로 서빙해버려서, 파일명이 추측 불가능한 해시라는 것에만 의존하는 "보안이 아니라 난독화" 방식이었어요. 저희 애드온은 그 기존 성격을 그대로 이어받은 것뿐이고, 옮기기 전이나 후나 이 지점의 보안 수준 자체는 달라진 게 없습니다.
진짜 새로 생기는 위험 — S3 public_url / 공개 WebDAV
말씀하신 대로 이게 핵심이에요. S3의 public_url 옵션이나 익명 읽기가 열린 WebDAV를 쓰면, 파일이 라이믹스 도메인이 아니라 S3/NAS 자체 도메인에서 직접 서빙돼요. 이러면:
- 라이믹스 권한 체크가 아예 개입할 방법이 없음 (요청이 우리 서버를 거치지도 않음)
- 게시글이 삭제되거나 비공개로 바뀌어도, 이미 알고 있는 URL은 계속 살아있음 (저희 삭제 연동이 지워주는 것도 원본 삭제 시점 기준이지, 이미 유출된 URL을 무효화할 방법은 없음)
- 말씀하신 대로 S3는 그나마 서명 URL(signed URL, 시간제한+매 요청 발급)로 이 문제를 피할 수 있는데, FTP/WebDAV는 HTTP 자체가 아니거나(FTP) 서명 URL 개념이 없어서 이 완화책이 통하지 않아요. FTP/SFTP는 반대로 HTTP가 아예 아니라서 오히려 "무조건 저희 PHP를 거쳐야만 접근 가능"이라는 강제성이 있긴 한데, 그 PHP 경유 지점(serve_file.php)에 지금 권한 체크가 없다는 게 위 문단의 구멍이고요.
정리하면 손볼 수 있는 부분과 못 손보는 부분이 갈려요:
1. 고칠 수 있는 것: serve_file.php에도 isDownloadable() 같은 권한 체크를 추가해서, 최소한 "우리 PHP를 거치는" local/ftp/webdav(비공개)/sftp/S3(서명) 경로는 게시판 읽기 권한이 없는 사람에게 막을 수 있어요.
2. 구조적으로 못 고치는 것: S3 public_url이나 공개 WebDAV처럼 제3자 도메인이 직접 서빙하는 방식은 애초에 라이믹스가 개입할 지점이 없어서, 코드로 해결이 안 되고 "그 저작권 민감한 게시판 같은 곳엔 public_url/공개 WebDAV를 쓰지 말고 서명 S3나 비공개 FTP/SFTP만 쓴다"는 운영 정책으로만 막을 수 있어요.
1번(serve_file.php 권한 체크 추가)은 지금 바로 코드로 넣어드릴 수 있는데, 하시겠어요? 2번은 관리자 설정 화면에 경고 문구 정도는 추가할 수 있어요.
라고 말해주는데 어렵네요 ㅋㅋㅋ
완벽하게 만들기는 솔직히 불가능은 아닌데 난이도가 급격하게 올라가요.
애드온으로 유용한 사용자층은 웹호스팅 이용하는분들인데, 이분들에게는 배보다는 배꼽이 더 커지는 상황일거에요.
제가 더 좋은 아이디어가 떠오르지가 않네요 아는 기술이 없고 무지해서..ㅠㅠ
## v0.7.2 (2026-07-21) — 정적 서빙 폴백에 게시판 읽기 권한 체크 추가
### 배경
사용자 지적: 파일을 S3/FTP/WebDAV/SFTP처럼 라이믹스가 아니면 접근이 아예
불가능한 저장소로 옮기고 나면, 그 파일에 대한 유일한 접근 경로가
`serve_file.php`의 정적 서빙 폴백인데 여기엔 권한 체크가 전혀 없었음.
다운로드 버튼(`procFileDownload`)은 항상 `FileModel::isDownloadable()`을
거치지만, 게시글 본문에 박힌 `<img>` 태그가 트리거하는 이 폴백 경로는
비어있었음.
(원래 라이믹스 자체도 `direct_download='Y'` 파일은 Apache가 PHP도 안 거치고
정적으로 서빙해서 이 지점엔 원래부터 권한 체크가 없었음 — 해시 파일명이라는
"난독화"에만 의존하는 구조. 이 애드온이 새로 만든 구멍은 아니지만, 저작권
민감 게시판처럼 진짜 접근 제어가 필요한 경우엔 문제가 될 수 있음.)
### 해결
- `serve_file.php`에 `LefServe::isPermitted()` 추가. 매핑 테이블에서
file_srl을 알 수 있는 경우(=v0.7.0 이후 방식으로 이동된 파일)에 한해:
- `FileModel::isDownloadable()` (isvalid, download_groups 설정) 확인
- 첨부파일이 걸린 게시글(`DocumentModel::getDocument()->isAccessible()`)
또는 댓글의 읽기 권한 확인
- 권한이 없으면 스트리밍을 거부하고 코어 404 처리로 넘김
- 레거시(마이그레이션 안 된) 데이터는 file_srl을 알 수 없어 이 체크를
건너뜀 — 관리자 복구 탭의 "레거시 항목 정리"로 매핑 테이블에 올리면
이 파일들도 체크 대상이 됨
### 한계 (코드로 해결 불가능, 운영 정책으로만 대응 가능)
S3 `public_url`(공개 버킷)이나 익명 읽기가 열린 WebDAV처럼 **제3자 도메인이
직접 서빙**하는 방식은 요청이 라이믹스 서버를 아예 거치지 않으므로, 이번
수정과 무관하게 여전히 권한 체크가 불가능함. S3는 서명 URL(signed URL)로
완화 가능하지만 FTP/일반 WebDAV는 그런 개념 자체가 없어 근본적으로 막을
방법이 없음. 접근 제어가 중요한 게시판(저작권 민감 게시판 등)은
public_url/공개 WebDAV를 쓰지 말고, 서명 S3나 비공개 FTP/SFTP/WebDAV만
사용할 것 — 이건 코드가 아니라 운영 시 선택의 문제.
---
에카님 이게 지금 맞게 된건질 모르겠어요
무슨 코드인지 보려했는데, 아직 공개된 코드가 아니군요.
본문의 내용으로 미루어보아, 제 의견은 serve_file.php 제거 입니다. SFTP관련 기능도 구현하지 않았으면 좋겠어요.
- 라는 의견을 AI에게 전달해보셔요.
아하 알겠습니다
작업 지시: "첨부파일 외부로" 애드온 → 모듈 전환 (v1.0.0 신규)
배경 / 타겟
기존 애드온(lua_external_file)은 홈서버 사용자 대상 로컬/마운트 경로 이동 기능이었음
이번 작업은 타겟을 바꿔서 **웹호스팅 사용자(NAS 없음, 용량 비용 절감이 목적)**를 겨냥함
기존 애드온 코드는 참고만 하고, 모듈 구조로 완전히 새로 설계할 것 (재활용 안 함)
버전은 기존 이력과 별개로 모듈 v1.0.0으로 새출발
지원 저장소 (범위 확정)
S3 호환 오브젝트 스토리지 (AWS S3, Backblaze B2, Cloudflare R2, MinIO 등) — SigV4 직접 구현, SDK 의존성 없이
FTP — PHP 내장 함수만 사용, 의존성 없음
WebDAV, SFTP는 이번 범위에서 제외 (커뮤니티 피드백 기준: 타겟 유저층과 안 맞음 / phpseclib 번들링 부담)
모듈 구조 필수 요소
schema/*.xml — 파일↔외부경로 매핑 테이블 자동 설치 (file_srl, storage_type, remote_path, migrated_at, status 등)
module.xml에 insertTrigger로 file.insertFile / file.deleteFile 훅 등록
관리자 화면: 저장소별 설정, 연결 테스트 버튼, 매핑 목록 조회, 레거시 항목 정리(마이그레이션 안 된 데이터 처리)
업로드 직후 이동 (원격 저장소는 다운로드 시점 이동 X — 네트워크 지연 방지)
필수 해결 과제 (커뮤니티 피드백 반영, 미루면 안 됨)
썸네일 생성: 원본이 서버에 없을 때 썸네일을 언제/어디서 생성·캐싱할지 설계 필요
파일 삭제 연동: 게시글/파일 삭제 시 원격 저장소에서도 삭제되도록, 실패 시 재시도 로직 포함
serve_file.php 권한 체크: 게시글 본문 <img> 등 정적 서빙 폴백 경로에 FileModel::isDownloadable() + 게시글/댓글 읽기 권한 체크 추가 (다운로드 버튼은 이미 체크하지만 이 경로는 뚫려 있었음)
S3는 signed URL 방식 강제/권장, public_url(공개 버킷)은 관리자 설정에 경고 문구 표시 — FTP는 애초에 HTTP가 아니라 PHP를 반드시 거치므로 이 문제 자체가 없음
설계 원칙
애드온 시절의 "가볍게, 의존성 최소" 철학 유지하되, 상태 추적(매핑 테이블)과 관리자 가시성은 모듈 수준으로 끌어올릴 것
불특정 다수 배포 목적이므로 "혼자 쓸 때는 괜찮았던" 안일한 처리(레거시 데이터 미체크, 권한 누락 등)는 전부 재검토
오늘 퇴근후 재작업 하겠습니다 ㅎㅎ