Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

데이터와 빌드의 브랜치

브랜치(Branch)는 여러 사람이 운영 파이프라인을 유지하면서 각자의 변경을 분리해 개발하는 수단입니다. Foundry에서는 코드의 Git 브랜치와 데이터셋 브랜치를 빌드 시스템으로 연결합니다. 코드 변경을 시험하면서 만들어진 데이터도 별도 브랜치에 저장할 수 있습니다.

변경 작업의 순서

  1. 기본 파이프라인의 master 브랜치에서 자신의 브랜치를 만듭니다. 이 브랜치에서 운영 데이터에 영향을 주지 않고 변환을 시험합니다.
  2. 변환을 추가하거나 수정하고 커밋합니다. 커밋은 브랜치에서 수행한 변경 이력을 남깁니다.
  3. 변경을 반영할 준비가 되면 풀 리퀘스트(Pull request)를 만듭니다. 팀에 master에 반영할 변경의 검토와 검증을 요청하는 절차입니다.
  4. 조직에서 정한 검토자가 커밋을 확인합니다. 구체적인 승인 절차는 조직마다 다릅니다.

Code Repositories는 같은 파일의 같은 브랜치에서 한 명의 개발자가 작업하는 사용 방식을 전제로 설계되었습니다. 다른 사용자가 자신의 personal 브랜치에서 함께 작업하면 변경을 덮어쓸 수 있습니다. 각자 별도 브랜치를 사용합니다.

데이터셋 브랜치

데이터셋은 트랜잭션의 연속으로 버전 이력을 관리합니다. Git에 비유하면 데이터셋은 저장소, 데이터셋 브랜치는 브랜치, 트랜잭션은 커밋에 대응합니다. 데이터셋 브랜치는 해당 브랜치의 최신 트랜잭션을 가리키는 포인터입니다.

브랜치에서 트랜잭션을 확정해도 다른 브랜치의 트랜잭션과 뷰는 바뀌지 않습니다. Git 코드 브랜치와 달리 데이터셋 브랜치 자체를 병합하는 기능은 지원하지 않습니다. 코드 변경을 검토하고 병합하는 절차와 데이터 트랜잭션을 합치는 동작을 구분해야 합니다.

루트 브랜치를 제외한 각 브랜치는 부모 브랜치를 정확히 하나 가집니다. 대부분의 데이터셋에는 master라는 루트 브랜치가 있고 그 아래에 자식 브랜치를 만듭니다.

동작결과
루트 브랜치 생성부모와 트랜잭션이 없는 브랜치를 만듭니다.
자식 브랜치 생성기존 브랜치 또는 특정 트랜잭션에서 만듭니다. 처음에는 원래 위치와 같은 트랜잭션을 가리키며, 이후 부모와 자식의 포인터는 독립적으로 이동합니다.
새 트랜잭션 시작해당 브랜치의 포인터를 새 트랜잭션으로 옮깁니다.
브랜치 삭제브랜치 포인터를 삭제합니다. 브랜치가 가리키던 트랜잭션은 이 동작으로 삭제하지 않습니다.

트랜잭션과 부모 관계의 보장

한 브랜치에는 확정하거나 중단하지 않은 열린 트랜잭션이 최대 하나 존재하며, 항상 그 브랜치의 최신 트랜잭션입니다. 브랜치가 열린 트랜잭션을 가리키는 상태에서도 새 브랜치를 만들 수 있지만, 그 트랜잭션을 닫기 전에는 추가 트랜잭션을 시작할 수 없습니다.

같은 브랜치의 트랜잭션은 시작 시각과 확정 시각에 따라 순서가 정해집니다. 서로 다른 브랜치의 트랜잭션 사이에는 시간 순서를 보장하지 않습니다.

자식이 있는 중간 브랜치를 삭제하면 자식들의 부모를 삭제한 브랜치의 부모로 바꿉니다. 루트 브랜치를 삭제한 경우에는 자식이 부모 없는 브랜치가 됩니다. 이 과정에서는 조상 관계 기록만 바꾸며 트랜잭션을 재배열하지 않습니다.

빌드에서 코드와 데이터 연결

각 빌드는 지정한 빌드 브랜치에서 실행됩니다. 빌드 안의 실행 작업은 그 브랜치의 데이터만 변경합니다. 빌드 시스템은 먼저 어떤 로직을 실행할지 결정한 뒤, 입력을 읽고 출력을 쓸 데이터셋 브랜치를 결정합니다.

실행 작업 그래프 구성

Code Repositories의 브랜치에서 변환 코드를 커밋하면 해당 브랜치에 실행 작업 명세(JobSpec)가 게시됩니다. 빌드는 JobSpec과 의존 관계를 탐색해 실행할 로직을 정합니다.

빌드 브랜치에 JobSpec이 없으면 브랜치 대체 경로(Branch fallback)를 따라 찾습니다. 예를 들어 develop에서 실행하고 대체 경로가 develop --> master이면, develop에 명세가 없는 출력은 master의 JobSpec을 사용합니다.

데이터셋 아이콘이 회색이면 master에 JobSpec이 없음을 나타냅니다. 파란색이면 master에 JobSpec이 정의되어 있습니다.

입력과 출력 결정

JobSpec에서 출력으로 지정한 모든 데이터셋에는 빌드 브랜치의 트랜잭션을 엽니다. 데이터셋에 빌드 브랜치가 없으면 대체 경로의 첫 브랜치에서 생성합니다. 대체 브랜치가 없으면 루트 브랜치로 생성합니다.

입력은 가능하면 빌드 브랜치에서 읽습니다. 해당 브랜치가 없으면 대체 경로에서 처음으로 존재하는 브랜치를 읽습니다. 입력을 읽기 위해 새로운 데이터셋 브랜치를 만들지는 않습니다.

예시: feature 브랜치에서 두 단계 실행

다음은 A, B, C라는 가상 데이터셋을 사용하는 예시입니다. 처음에는 모두 master에 있고, B는 A를 읽으며 C는 B를 읽습니다.

  1. Code Repositories에서 feature 브랜치를 만듭니다.
  2. B와 C를 만드는 코드를 수정하고 커밋합니다. 저장소 검사가 두 출력의 feature 브랜치에 JobSpec을 게시합니다.
  3. feature --> master 대체 경로를 사용하는 빌드를 시작합니다. 빌드는 새 JobSpec을 읽고 B와 C의 feature 브랜치에 트랜잭션을 엽니다.
  4. 첫 실행 작업은 A에 feature가 없으므로 A의 master를 읽습니다. 결과를 B의 feature 트랜잭션에 쓰고 확정합니다.
  5. 다음 실행 작업은 B의 feature를 읽고 C의 feature에 결과를 쓴 뒤 확정합니다. 모든 실행 작업이 성공하면 빌드가 완료됩니다.

A는 변경되지 않습니다. B와 C에서도 master는 그대로 유지되고 feature에 새 데이터가 생깁니다.

빌드 브랜치의 제약

빌드의 브랜치 대체 경로는 관련 데이터셋의 조상 관계와 호환되어야 합니다. 호환되지 않으면 빌드 대상을 결정하는 단계가 성공하지 않습니다.

빌드는 지정한 빌드 브랜치 이외의 데이터셋 브랜치를 변경하지 않습니다. 새 브랜치를 만들 수 있는 대상은 출력이며, 입력 데이터셋에는 브랜치를 생성하지 않습니다.