여러 파일로 나뉜 Structurizr 워크스페이스, 이제 Archyl로 가져올 수 있습니다

어떤 Structurizr 워크스페이스는 workspace.dsl에 거의 아무것도 두지 않습니다. 헤더 하나, model 블록 하나, 그리고 시스템마다 한 줄씩 늘어선 !include 줄이 전부이고, 실제 모델은 그 줄들이 가리키는 파일에 흩어져 있습니다.

이번 주까지 Archyl은 이런 워크스페이스를 가져올 수 없었습니다. Structurizr Cloud 종료에 관한 8월 4일 글에서도 한 줄로 밝혔습니다. 여러 파일로 된 워크스페이스는 먼저 하나로 합쳐야 한다고요. 그 때문에 시스템마다 파일을 따로 두는 워크스페이스는 가져올 수 없었습니다. Structurizr Cloud는 2주 뒤인 9월 30일에 종료됩니다.

이제 워크스페이스를 .zip으로 업로드할 수 있고, Archyl은 모든 !include를 그 안의 파일을 기준으로 해석합니다.

단일 파일로는 애초에 안 되는 이유

다음과 같이 구성된 워크스페이스가 있다고 합시다.

workspace.dsl
model/
  people.dsl
  relationships.dsl
systems/
  ledger.dsl
  notifications.dsl
  payments.dsl

루트 파일은 조각들을 이어 붙이기만 합니다.

workspace "Payments Platform" "Card payments and settlement" {
    model {
        !include model/people.dsl
        !include systems
        !include model/relationships.dsl
    }
}

이 루트 파일만 업로드하거나 붙여 넣으면, 임포터에는 경로를 해석할 기준이 없습니다. 가진 것만 파싱하고, include를 하나하나 건너뛴 뒤 이렇게 알려 줍니다.

line 3: directive '!include' is not supported and was skipped
line 4: directive '!include' is not supported and was skipped
line 5: directive '!include' is not supported and was skipped

경고 내용은 정확하지만, 결과도 그게 전부입니다. 여섯 파일의 내용은 하나도 들어 있지 않습니다. 그 자체로 완결된 단일 .dsl 파일은 이전과 똑같이 가져옵니다. zip은 그 밖의 모든 경우를 위한 것입니다.

리포지토리가 아니라 워크스페이스 디렉터리를 zip으로 묶으세요

워크스페이스가 !include를 쓴다면, 나뉜 파일들은 어딘가에 파일로 존재합니다. Structurizr의 include 문서는 파일 include를 이렇게 설명합니다: "a single local file, specified by a relative path" — 상대 경로로 지정된 단일 로컬 파일. 그러니 중요한 사본은 클라우드가 아니라 디스크나 Git에 있습니다. workspace.dsl이 있는 디렉터리를 찾아 그 디렉터리를 zip으로 묶으세요.

디렉터리 안에서:

zip -r workspace.zip workspace.dsl model systems

워크스페이스가 리포지토리에 있다면, 커밋에서 바로:

git archive --format=zip -o workspace.zip HEAD:docs/architecture

이 구분이 중요한 이유는 아카이브 항목 수가 500개로 제한되고, 이 개수를 무엇이든 걸러 내기 전에 검사하기 때문입니다. .git 폴더까지 포함해 리포지토리 전체를 묶으면 .dsl 파일을 하나도 읽기 전에 한도를 넘을 수 있습니다. 아카이브 최상위에 감싸는 폴더가 하나 있는 것은 괜찮습니다. include는 include를 하는 파일을 기준으로 한 상대 경로로 해석되기 때문입니다.

업로드하면 일어나는 일

가져오기 모달의 Structurizr DSL 탭 버튼은 이제 .dsl 또는 .zip 업로드로 표시됩니다. 아카이브를 선택하면 코드 에디터 대신 이름과 크기를 보여 주는 카드가 나타납니다. 검증을 클릭하면 카드에 파일 수와 선택된 루트 파일이 추가됩니다.

기존 프로젝트로 가져올 때도, 새 프로젝트를 만들 때도 똑같이 동작합니다. 새 프로젝트는 워크스페이스 헤더에서 이름을 가져오므로, workspace "Payments Platform" { ... }는 프로젝트를 만들 수 있지만 이름 없는 workspace { ... }는 만들 수 없습니다.

서버에서 아카이브는 네 단계를 거칩니다.

  1. 루트를 고릅니다. 아카이브에 workspace.dsl이 있으면 그것을, 없으면 가장 얕은 위치의 .dsl 파일을 씁니다. 여러 파일 중에서 골라야 하는데 workspace.dsl이라는 이름의 파일이 없으면, 사용한 파일을 경고로 알려 줍니다.
  2. 파싱 전에 include를 텍스트로 펼칩니다. include된 파일의 내용이 !include 줄을 대체합니다. Structurizr가 하는 것과 같은 인라인 처리입니다. 경로는 include를 하는 파일 기준의 상대 경로이므로, systems/index.dsl이 shared/platform.dsl을 include하면 systems/shared/platform.dsl을 찾습니다.
  3. 디렉터리 include를 해석합니다. !include systems는 systems/ 바로 아래에 있는 모든 .dsl 파일을 이름순으로 가져옵니다. 하위 디렉터리는 탐색하지 않습니다.
  4. 경계에서 멈춥니다. 직접이든 다른 파일을 거쳐서든 결국 자기 자신을 include하게 되는 파일은, 그 순환을 끊고 보고합니다. 중첩은 10단계에서 멈춥니다.

펼쳐진 워크스페이스는 그다음 단일 파일과 똑같은 Structurizr 임포터를 거칩니다. 충실도도 같고, 건너뛴 항목에 대한 경고 목록도 같습니다.

없는 파일이나 아카이브 밖을 가리키는 경로처럼 해석할 수 없는 include도 경고가 됩니다. 워크스페이스의 나머지는 그대로 가져옵니다.

원격 include는 의도적으로 거부합니다

Structurizr는 !include가 HTTPS URL을 가리키는 것도 허용합니다. Archyl은 이를 따라가지 않습니다. 이를 해석하면 업로드된 어떤 파일이든 우리 서버가 그 파일이 고른 주소로 요청을 보내게 만들 수 있고, 이는 누가 업로드하든 server-side request forgery의 통로가 됩니다. 해당 줄은 경고와 함께 건너뜁니다.

!include: remote target "https://example.com/shared/identity.dsl" is not supported and was skipped

필요한 모델 요소가 원격 파일에 들어 있다면, 그 파일을 내려받아 아카이브에 넣고 해당 줄을 상대 경로로 바꾸세요.

제한

제한 값 초과 시
아카이브 크기 10 MiB 업로드 거부
아카이브 항목 수 500 업로드 거부
펼친 후 전체 크기 50 MiB 업로드 거부
개별 파일 5 MiB 경고와 함께 파일 건너뜀
include 중첩 10단계 더 깊은 include는 경고와 함께 건너뜀

절대 경로나 .. 세그먼트로 아카이브 밖으로 빠져나가려는 경로의 항목은 경고와 함께 건너뜁니다. 텍스트 파일만 남깁니다: .dsl, .md, .json, .yaml, .yml, .txt. 이미지와 그 밖의 파일은 DSL 임포터에 쓸모가 없으므로 경고 없이 버립니다.

아직 안 되는 것

Git 동기화는 include를 해석하지 않습니다. 리포지토리 동기화는 Structurizr 워크스페이스가 아니라 archyl.yaml을 읽습니다. 그래서 Archyl이 여러 파일로 된 DSL을 리포지토리에서 바로 가져오는 경로는 아직 없습니다. DSL이 Git에 있다면, 당분간은 위의 git archive 명령이 그 워크플로입니다.

그 밖에 Structurizr 충실도에서 달라진 점은 없습니다. 레이아웃, 스타일, deployment view는 이전에도 가져오지 않았고 zip에서도 가져오지 않습니다. workspace.json 경로도 여전히 없습니다. Archyl은 DSL 텍스트를 읽습니다. Structurizr에서 가장 중요하게 여기는 것이 손으로 다듬은 레이아웃이라면, 종료 관련 글에서 소개한 선택지 중 Structurizr 자체 도구를 계속 쓰는 쪽이 여전히 더 잘 맞습니다.

9월 30일 전에

  1. 소스 파일을 확보하세요. !include로 나뉜 워크스페이스는 파일로 작성된 것이니 그 파일을 찾으세요. 브라우저에서 조정한 레이아웃이나 그곳에서 작성한 문서처럼 클라우드 사본에만 있는 것이 있다면, 8월 4일 글에서 꺼내는 방법을 다룹니다.
  2. workspace.dsl이 있는 디렉터리를 zip으로 묶으세요. 그 디렉터리를 감싼 리포지토리가 아닙니다.
  3. 업로드하고 검증하세요. Import Project 또는 기존 프로젝트 안의 가져오기 모달을 열고, Structurizr DSL을 선택한 뒤 zip을 업로드하고 검증을 클릭하세요. 가져오기 전에 선택된 루트 파일을 확인하고 모든 경고를 읽으세요.
  4. 디렉터리를 리포지토리에 커밋하세요. 아직 리포지토리에 없다면 그렇게 해 두어야 다음 사람이 여러분의 노트북에서 그걸 찾지 않아도 됩니다.

임포터의 전체 동작은 새 프로젝트의 이름 규칙까지 포함해 Architecture as Code 문서에 있습니다. Archyl이 가져올 수 있는 다른 형식은 Structurizr, LikeC4, IcePanel 프로젝트 가져오기를 참고하세요.