제품 공개 공유(공개 HTTPS 링크)
.md / .html / .xlsx 제품을 로그인이 필요 없는 짧은 링크로 게시하세요. Slack/이메일은 링크만 보내고 파일은 보내지 않습니다. TTL / 비밀번호 / 다운로드 수 / HTML 온라인 미리보기를 지원합니다.
워크플로에서 보고서(.md / .html / .xlsx / .pdf)를 생성하고 이를 다른 사람에게 보내려는 경우 가장 직접적인 방법은 Slack/mail 모듈에서 파일 첨부를 업로드하도록 하는 것입니다. 그러나 대용량 파일은 속도가 느리며 메시징 플랫폼에는 일반적으로 단일 파일 크기와 첨부 파일 수에 제한이 있습니다.
제품 공개 공유 는 또 다른 길입니다: 개별 아티팩트를 로그인이 필요 없는 HTTPS 단축 링크로 발행하여, 메시지에는 링크만 보내고 열면 바로 볼 수 있습니다 — 파일 자체는 서버에 남아 트래픽을 절약하고 브라우저 직접 미리보기도 지원합니다(.md는 온라인으로 HTML로 렌더링할 수 있음). 한 번에 여러 파일을 공유할 때는 아티팩트 디렉터리 전체를 링크 하나로 발행할 수도 있으며, 아래 「디렉터리 수준 공개 링크」를 참고하십시오.
언제 사용하나
- 보고서/대시보드는 Slack/Feishu/이메일로 보내야 하며 모든 사람이 각각 3MB xlsx를 저장하는 것을 원하지 않습니다.
- 외부 협력자(플랫폼 계정 없음)에게 앱스토어 데이터 스냅숏을 보여줘야 할 때
- 고객에게 .md 요약을 임시로 공유하고, 상대가 휴대폰 브라우저로 HTML을 바로 보게 하고 싶을 때
- 링크에 만료 시간 / 다운로드 횟수 상한 / 비밀번호 보호를 설정하고 싶을 때
사용법 — UI에서 생성
- 실행이 끝난 execution을 열고 "아티팩트" 탭으로 전환하면 각 아티팩트 옆에 🔗 공유 버튼이 보입니다
- 🔗 공유를 클릭하면 공유 대화 상자가 열립니다
- 필요에 따라 설정:
- 접근 범위: 공개(기본) / 비밀번호 접근 / 팀 내 / 지정 구성원. 자세한 내용은 아래 "접근 범위와 접근 신청" 참고
- 유효기간: 만료 없음(기본) / 1시간 / 24시간 / 7일 / 30일. 지난번 선택을 기억합니다
- 다운로드 횟수 상한: 0 = 무제한, >0 = 소진되면 링크 자동 무효화
- 접근 비밀번호(비밀번호 접근 모드): 링크를 열 때 브라우저에 비밀번호 입력창이 뜹니다
- 온라인 HTML 렌더링(.md 전용): 선택하면 링크를 열었을 때 정리된 HTML이 바로 표시되며 .md 원본 파일 다운로드가 아닙니다
- 「링크 생성」을 클릭 → https://braidrun.com/p/a/hN2kQ9... 형태의 URL을 얻고, 「복사」를 클릭하여 아무 곳에나 붙여넣습니다
사용법 — 워크플로 안에서 자동 게시(권장)
워크플로가 실행된 후 제품은 자동으로 공개 링크로 전환되고 링크는 자동으로 Slack에 푸시됩니다. 전체 프로세스에서 공유하기 위해 수동으로 클릭할 필요가 없습니다.
워크플로 엔진은 실행 ID, 단기 액세스 토큰 및 플랫폼 액세스 주소를 각 코드 단계에 자동으로 삽입합니다. 내장된 아티팩트 게시 모듈은 이러한 런타임 매개변수를 읽으므로 "아티팩트를 공유할 단계"(from_step)만 알려주면 됩니다. 액세스 토큰은 유효 기간이 짧으며 작동 후 수동 유지 관리가 필요하지 않습니다.
대표적인 3단계 구성
- 아티팩트를 생성하는 단계는 평소대로 작성하며 특별한 표시가 필요 없습니다 — 예:
- step: build_report agent: reporter input: | 生成今天的业务报表,写入 /tmp/.../daily.md。 # 这一步完成后,引擎自动注册一个产物(execution 的 artifacts 列表里会出现) - 내장 artifact publish 모듈을 연결하고 이전 단계 이름 `from_step: build_report`를 전달합니다. 모듈은 execution의 아티팩트 목록을 자동 조회해 해당 단계가 생성한 파일을 찾아 공개 링크를 만듭니다:
- step: share_report sub_workflow: name: dingyue-module-artifact-publish inputs: from_step: "build_report" # ← 唯一必需字段:引用上一步的步骤名 ttl_minutes: "0" # 永不过期;如需限时可改成分钟数 render_markdown_as_html: "true" # .md 直接在线 HTML 预览 # base_url / api_token 不用填 —— 引擎自动注入运行时访问令牌 outputs: share_url: public_url # 下游可以用 {{var:share_url}} 引用 depends_on: [build_report] - 이어서 내장 Slack 전송 모듈을 연결하고 public_url을 전달합니다 → Slack은 "텍스트 메시지 + 링크" 한 건만 받고 파일은 업로드되지 않습니다:
- step: notify sub_workflow: name: dingyue-module-slack-deliver inputs: slack_webhook_url: "{{var:slack_webhook_url}}" message_text: "📊 今日报表已生成" public_url: "{{var:share_url}}" # ← 复用 share_report 的输出 depends_on: [share_report]
아티팩트가 여러 개라면
build_report 단계가 여러 파일을 생성했다면(예: daily.md와 metrics.json을 동시에 작성) artifact_name으로 필터링합니다:
- step: share_report
sub_workflow:
name: dingyue-module-artifact-publish
inputs:
from_step: "build_report"
artifact_name: "daily.md" # ← 精确挑选
ttl_minutes: "0"
outputs:
share_url: public_urlartifact_name이 없으면 모듈은 첫 번째로 일치하는 아티팩트를 사용하고, 사용되지 않은 것이 몇 개 있는지 로그에 남깁니다.
디렉터리 수준 공개 링크: URL 하나로 아티팩트 디렉터리 전체 공유
단일 파일 링크는 한 번에 아티팩트 하나만 공유할 수 있습니다. 한 번의 실행이 여러 파일(리포트 + 데이터 + 이미지, 심지어 완전한 다중 페이지 정적 웹사이트)을 산출했다면, 아티팩트 디렉터리 전체를 링크 하나로 발행할 수 있습니다:
- UI 진입점: 실행 상세의 「아티팩트」 Tab에서 「모든 아티팩트 공유」를 클릭하면 이번 실행의 모든 아티팩트를 아우르는 디렉터리 링크가 생성됩니다. 설정 항목(접근 범위 / 유효기간 / 다운로드 쿼터 / 비밀번호 / 온라인 렌더링)은 단일 파일과 동일하며, 표시명을 커스터마이즈할 수도 있습니다
- API로 특정 스텝의 산출물만 공유할 수도 있습니다. 실행 전체를 공유하려면:
POST /api/executions/{id}/directory-public-link; 단일 스텝만 공유하려면:POST /api/executions/{id}/steps/{stepName}/directory-public-link - 링크는 https://braidrun.com/p/d/hN2kQ9.../ 형태이며, 접근자는 계정이 필요 없습니다(공개 모드에서).
접근자에게 보이는 것
- 기본은 파일 목록 페이지입니다: 파일명, 크기, 유형, 그리고 링크의 유효기간과 다운로드 쿼터
- 디렉터리 루트에 index.html이 있으면 바로 정적 사이트로 열립니다 — 워크플로가 생성한 다중 페이지 HTML 리포트를 사이트 전체로 공유할 수 있습니다. URL에 ?listing=1을 추가하면 파일 목록 뷰로 강제로 돌아갑니다
- 온라인 렌더링을 선택하면 디렉터리 내 .md 파일이 편집이 완료된 HTML로 표시됩니다
- 디렉터리 내 파일은 항상 플랫폼이 올바른 Content-Type으로 전달하며(오브젝트 스토리지 302 직링크를 거치지 않음), HTML / CSS / JS가 브라우저에서 정상적으로 렌더링됨을 보장합니다
- 다운로드 쿼터는 디렉터리 전체에 누적되며, 소진되면 링크가 자동으로 무효화됩니다
접근 범위와 접근 신청
단일 파일 링크와 디렉터리 링크는 같은 접근 범위 세트를 공유합니다:
| 모드 | 누가 열 수 있는가 |
|---|---|
PUBLIC 대중 | 링크를 받은 누구나 |
PASSWORD 비밀번호 접근 | 링크를 받고 비밀번호를 아는 사람. 브라우저 팝업으로 입력하고, 스크립트 클라이언트는 Authorization: Basic 또는 X-Artifact-Password 헤더를 사용 |
TEAM 팀 내에서 | Braidrun 계정 로그인이 필요하며, 지정 팀에 속해야 함 |
USERS 지정회원 | 로그인이 필요하며, 구성원 명단에 있어야 함. 명단은 선택한 팀의 구성원 중에서만 고를 수 있음 |
팀 내 / 지정 구성원 모드에서 링크는 "로그인이 필요한 딥링크"가 됩니다: 로그인하지 않고 접근하면 로그인으로 안내되고, 로그인했으나 명단에 없으면 "접근 권한 없음" 페이지를 보게 됩니다.
접근 신청 프로세스(팀 내 / 지정 구성원 모드에서 선택적으로 활성화 가능):
- 링크 생성 시 「로그인 사용자가 접근 권한이 없을 때 신청 제출 허용」을 선택합니다
- 접근 권한이 없는 사람이 링크를 열면 "접근 권한 없음" 페이지에서 신청 폼을 작성하고 설명을 첨부할 수 있습니다. 중복 제출하면 원래 신청이 갱신됩니다
- 공유자 또는 링크 관리자가 「계정 → 공유 관리」에서 승인 / 거부합니다. 승인 전에 상대가 이미 선택한 팀에 속했는지 확인해야 합니다
- 승인 후 상대는 접근 가능 명단에 추가되어, 원래 링크로 바로 열 수 있습니다
디렉터리 링크 관리
- 「계정 → 공유 관리」에서 단일 파일과 디렉터리 링크를 함께 관리합니다: 접근 범위 변경, 유효기간 변경, 취소, 그리고 접근 횟수와 접근 로그(시간, 계정 신분, IP, User-Agent) 확인
- 해당 관리 API(목록 / 수정 / 취소)는 다음과 같습니다:
GET /api/directory-public-links·PATCH /api/directory-public-links/{token}·DELETE /api/directory-public-links/{token} - 생성자는 기본적으로 링크 관리자이며, 추가 관리자를 지정하여 접근 신청과 취소를 함께 처리할 수 있습니다
지원되는 공유 방법
| 배포 | 지원 여부 | 설명 |
|---|---|---|
| 단일 노드 + 로컬 디스크 | ✅ | 플랫폼은 파일 내용을 직접 반환합니다. |
| 다중 노드 + 로컬 디스크 | ⚠️ 권장하지 않음 | 요청은 파일이 없는 노드에 도달할 수 있습니다 → 410 Gone. 객체 스토리지를 활성화하는 것이 좋습니다. |
| 원하는 수의 노드 + 객체 스토리지 | ✅ Recommended | 302 임시 서명 다운로드 링크(TTL 10분, 방문할 때마다 새 서명), 플랫폼은 파일 트래픽을 전달하지 않습니다. |
위 표는 단일 파일 링크에 대한 것입니다. 디렉터리 링크는 항상 플랫폼이 파일 스트림을 전달하므로 어떤 배포 형태에서도 사용할 수 있습니다.
보안과 컴플라이언스
- 토큰은 열거 불가 —— 24바이트 SecureRandom → base62 ≈ 143비트 엔트로피, 무차별 스캔은 불가능합니다
- 크롤러 인덱싱 방지 —— 응답 헤더 X-Robots-Tag: noindex, nofollow + Referrer-Policy: no-referrer로 Google/Bing이 링크를 인덱싱하지 않습니다
- 속도 제한 —— 게이트웨이 레이어: 동일한 IP에 대해 초당 10회, 버스트 20회; 서비스 계층: 토큰의 maxDownloads를 기반으로 한 엄격한 제한
- 비밀번호 보호(선택) —— Argon2id 해시. 브라우저 접근 시 팝업으로 입력하고, 스크립트 클라이언트는 Authorization: Basic 또는 X-Artifact-Password 헤더를 사용합니다. 비밀번호는 URL 쿼리 파라미터에 두지 않아 접근 로그에 남는 것을 방지합니다
- 감사 로그 —— 생성/접근/취소 때마다 클라이언트 IP + User-Agent + 타임스탬프를 포함한 audit_log가 한 건 기록됩니다
- GDPR 호환 —— 계정 삭제 시 모든 링크가 자동 연쇄 정리됩니다. 데이터 내보내기 시 artifact_public_links.jsonl이 ZIP에 포함됩니다
- 즉시 취소 —— 공유 관리 페이지에서 "취소"를 누르면 즉시 적용되며, 취소된 링크 접근은 410 Gone을 반환합니다(404가 아니며 "존재하지 않음"과의 혼동을 피하기 위함)
공유된 링크 관리
"계정 → 공유 관리"(또는 직접 GET /api/public-links)에서 생성한 모든 링크, 접근 횟수, 취소 여부를 볼 수 있습니다. 취소 버튼을 누르면 링크는 즉시 무효화됩니다.
FAQ
Q: 링크를 열면 왜 410 Gone이 표시되나요?
- 링크가 만료됨(유효 기간 종료)
- 링크가 생성자 또는 관리자에 의해 취소됨
- 다운로드 횟수가 상한에 도달함(쿼터를 다 쓰면 자동으로 무효화됨)
- 비밀번호를 잘못 입력함(비밀번호를 입력한 적이 없으면 410 대신 먼저 브라우저 비밀번호 팝업을 보게 됨)
Q: 링크를 만료되지 않게 할 수 있나요?
가능합니다. 다만 UI에서 2차 확인이 표시됩니다 — 영구 링크는 수동으로 취소하지 않는 한 링크를 가진 누구나 영원히 접근할 수 있다는 뜻이므로 신중하세요. 관리자는 BRAIDRUN_PUBLIC_LINK_REJECT_PERMANENT=true로 영구 링크를 전역 비활성화할 수 있습니다.
Q: 링크가 검색 엔진에 인덱싱되나요?
아니요. 응답 헤더에서 noindex, nofollow를 강제하고 nginx 계층에서도 한 번 더 추가합니다. 다만 링크를 공개 웹페이지에 붙이면 외부 크롤러를 통해 URL이 발견될 수 있으니 — GitHub README나 블로그 글에 링크를 공개하는 일은 절대 피하세요.
Q: 어느 정도 크기의 파일이 적당한가요?
객체 스토리지 모드: 이론적으로 무제한입니다. 실제로는 사용자의 브라우저 시간 초과로 인해 제한됩니다(일반적으로 수십 MB는 문제가 되지 않습니다). 로컬 디스크 모드: 플랫폼 파일 읽기 속도로 제한되므로 100MB를 초과하지 않는 것이 좋습니다.
Q: 아티팩트가 속한 execution을 삭제하면 기존 링크는 계속 쓸 수 있나요?
아니요. execution을 삭제하면 해당 execution을 가리키는 모든 링크가 연쇄 취소되며 이후 접근은 410 Gone이 됩니다.
Q: 이 기능은 기본적으로 켜져 있나요?
관리자가 환경 변수 BRAIDRUN_PUBLIC_BASE_URL로 명시적으로 활성화해야 합니다. 비활성 상태에서는 UI에 공유 버튼이 보이지 않습니다. 운영 문서 PRODUCTION_GUIDE §2.4를 참고하세요.