파이프라인 개발 규약과 품질 관리
파이프라인 변환에도 일반적인 소프트웨어 개발의 변경 관리, 코드 재사용과 테스트 원칙이 적용됩니다. 복잡한 함수나 API를 사용해야 한다면 선택 이유와 입력 조건을 설명하고, 같은 로직을 여러 곳에 복사하기보다 공통 함수나 라이브러리로 관리합니다.
범위와 이름
프로젝트의 목적을 좁게 유지하고, 큰 변환을 작은 단계로 나누며 짧은 함수와 보조 함수를 사용합니다. 장기간 유지할 파이프라인에 일회성 업무 로직이 계속 섞이지 않도록 경계를 관리합니다.
열과 데이터셋에는 조직의 일관된 이름 규칙을 적용합니다. 예를 들어 snake_case를 규약으로 정했다면 awesome_dataset을 사용하고 같은 대상을 AwesomeDataset이나 Awesome_Dataset으로 달리 부르지 않습니다.
두세 단어로 목적을 설명하는 이름이 권장됩니다. 목록에서 이름이 잘릴 때도 구별할 수 있도록 특징적인 부분을 앞에 둘 수 있습니다. 약어, dataset1 같은 순번이나 한 글자 이름은 피합니다.
/raw/my_important_dataset과 /clean/my_important_dataset처럼 경로로 단계를 구분하는 구조는 사용할 수 있습니다. 다만 화면에서 파일 이름만 보이면 혼동될 수 있으므로 이름 자체의 구별 가능성도 고려합니다. 원천과 변환 관계는 계보에서 확인할 수 있어 모든 상태를 이름에 길게 넣을 필요는 없습니다.
프로젝트와 폴더
권한은 프로젝트 단위로 관리하는 것이 권장됩니다. 내부에서 서로 다른 접근 범위가 계속 필요하면 프로젝트를 더 나누는 방안을 검토합니다. 팀 외부 사용자도 목적과 출력을 찾을 수 있도록 의미 있는 폴더를 사용합니다. 기본적으로 문서용 /Documentation과 출력용 /Output 같은 경계를 둘 수 있으며, 프로젝트 유형별 폴더 규약과 대소문자를 일관되게 적용합니다.
개인 홈 폴더는 접근 통제가 엄격하고 공유가 어려워 공동 개발 장소로 적합하지 않습니다. 실험과 임시 작업도 프로젝트의 /scratch 같은 폴더에서 수행하는 편이 좋습니다.
데이터셋 삭제와 순환 의존성
Foundry 데이터셋은 다른 리소스의 의존 대상이므로 잘못된 데이터를 썼다는 이유로 데이터셋 자체를 삭제하지 않습니다. 잘못된 트랜잭션의 내용을 바꾸려면 새 SNAPSHOT 트랜잭션으로 현재 데이터를 대체할 수 있습니다. 리소스 삭제는 그 데이터 자산 자체를 없애려는 경우로 구분합니다.
변환 출력을 다른 변환의 입력으로 연결할 때 순환 의존성을 만들지 않습니다. 빌드 오케스트레이션은 현재 개발 브랜치의 순환을 검사하며, 발견하면 저장소 검사가 실패합니다. 코드 작성 중 모든 브랜치를 함께 검사하는 것은 아닙니다. 예를 들어 운영 브랜치에만 존재하는 온톨로지 쓰기 반영 데이터셋이 순환을 만들 수 있으며, 해당 브랜치에 병합하는 단계에서 검사가 실패할 수 있습니다.
자료형을 명시적으로 정하기
원천 프로젝트의 원시 데이터 정리 단계에서는 동기화의 스키마 추론이 맞게 보이더라도 열을 명시적으로 캐스팅합니다. 원천 자료형이 바뀌거나 비정상 값 때문에 추론 결과가 달라졌을 때 변경을 드러내는 데 도움이 됩니다.
숫자로 보이는 식별자
항공기 ID 545, 972, 314처럼 숫자로 보이는 값도 산술 연산 대상이 아니라면 문자열이 적합합니다.
123과0123을 구분해야 할 수 있습니다.- 숫자 자료형이면 화면에서
545.0,1,234또는 숫자 정렬 형식으로 표시될 수 있습니다. - 긴 식별자는 정수 자료형의 최댓값을 넘을 수 있습니다.
그 값을 더하거나 평균 내는 것이 의미 있는지 판단한 뒤 숫자형을 선택합니다.
날짜 없는 시각
사용 중인 Spark 런타임과 Foundry 입출력에서 시간 전용 자료형을 지원하지 않으면 10:59:00 같은 값을 문자열로 보존하거나, 합의한 기준 날짜에 붙인 타임스탬프로 표현할 수 있습니다.
기존 방식으로 하루 안의 초 수에 -2208988800을 더하여 Unix 초를 만들면 기준은 UTC의 1900-01-01 00:00:00입니다. 기준 날짜와 시간대의 의미를 문서화하고 실제 사건 날짜로 해석하지 않도록 해야 합니다. 문자열로 유지하면 소비자가 필요한 시점에 파싱할 수 있습니다.
Spark의 TimeType은 4.1.0에 추가되었습니다. 실제 Foundry 런타임과 데이터 입출력에서 이 자료형을 지원하는지 확인한 뒤 사용합니다.
타임스탬프와 시간대
절대 시점을 나타내는 일반적인 TimestampType 또는 TIMESTAMP_LTZ는 UTC 기준의 내부 값과 세션 시간대에 따른 해석 및 표시를 구분합니다. TimestampNTZType은 시간대 변환 없이 날짜와 시각 필드를 다루는 별도 자료형입니다. TIMESTAMP의 기본 유형 설정도 확인합니다.
원천의 시간대 없는 현지 시각을 UTC 시점으로 맞출 때는 to_utc_timestamp()에 원천 시간대를 지정할 수 있습니다. 이미 시간대가 들어 있는 문자열은 파싱 단계에서 그 시간대가 적용될 수 있으므로 다시 이동시키지 않도록 입력 의미를 먼저 구분합니다.
from_unixtime()은 Unix 초를 문자열로 표시하며 spark.sql.session.timeZone의 영향을 받습니다. 표시용 문자열을 만드는 것과 저장된 절대 시점을 바꾸는 작업은 구분합니다. 같은 시점을 서로 다른 시간대의 별도 시점인 것처럼 저장하지 않도록 기준을 통일합니다.
주석과 버전 관리
이전 코드는 Git 이력에서 찾을 수 있으므로 사용하지 않는 코드를 주석 처리한 채 커밋하지 않습니다. 작성자와 날짜도 저장소 이력에 남으므로 주석으로 중복 관리하지 않습니다. 주석은 코드가 그대로 보여 주는 동작보다 결정 이유와 제약을 설명하는 데 사용합니다. 코드 자체가 이해하기 어렵다면 먼저 함수와 구조를 단순하게 정리합니다.
팀 개발이나 장기 프로젝트에서는 운영 브랜치인 master를 보호하고 검토 및 테스트를 통과한 코드를 병합합니다. GitFlow 또는 팀에 맞는 절차를 사용할 수 있습니다.
커밋 메시지는 변경 내용을 찾을 수 있게 작성합니다. 빌드 버튼이 자동으로 만드는 시각 중심 메시지에 의존하기보다 먼저 설명을 붙여 커밋한 뒤 빌드합니다. 작업을 포기했거나 병합한 브랜치는 정리하여 현재 개발 중인 브랜치를 구분하기 쉽게 만듭니다.
저장소 업그레이드 안내가 나오면 언어 번들 및 구성 변경을 별도 PR로 적용하고 해당 브랜치에서 빌드 영향을 확인합니다. 팀원이 작성한 변환은 PR에서 함께 검토합니다. 구체적인 승인 흐름은 브랜치와 릴리스에서 설명합니다.
저장소 간 로직 공유
여러 파이프라인에서 같은 로직을 사용하면 공유 라이브러리로 관리할 수 있습니다. Python 저장소는 라이브러리를 Conda 채널에 게시하고 다른 저장소가 의존성으로 사용할 수 있습니다.
공유 로직과 공유 데이터셋은 별개의 선택입니다. 엄격한 SLA를 가진 파이프라인은 같은 계산 로직을 사용하면서 입력을 미리 필터링하거나 변환 단계를 줄이고 스케줄을 달리해야 할 수 있습니다. 이때 라이브러리만 공유하면 공통 계산의 의미를 유지하면서 실행 구성을 독립적으로 정할 수 있습니다.
공유 저장소는 1.0.0, 1.0.1, 2.0.0 같은 의미적 버전으로 릴리스를 표시할 수 있습니다. 소비 저장소는 최신 버전을 받거나 특정 버전에 고정하여 운영 반영 시점을 직접 선택합니다. 중요한 파이프라인에서는 새 버전을 검토한 뒤 명시적으로 올리는 방식이 적합합니다.
별도 스테이징 인스턴스나 장기간 유지하는 개발 브랜치 대신, 공통 로직을 라이브러리로 분리하고 소비 저장소를 승인된 주요 릴리스에 고정하는 운영도 가능합니다. 개발자는 중간 버전을 계속 게시하고 소비 저장소의 작업 브랜치에서 시험하되, 정해진 릴리스 전에 운영 브랜치로 병합하지 않습니다.
단위 테스트와 데이터 상태 검사
단위 테스트는 작고 독립적인 로직을 자동으로 확인합니다. Python 저장소는 pytest 테스트를 CI 검사에 포함할 수 있고 Java 변환도 단위 테스트를 구성할 수 있습니다. 각 테스트는 한 가지 로직을 확인하고 메모리 부담을 줄이며, 별도 외부 입력이나 다른 테스트의 실행 결과에 의존하지 않도록 구성합니다.
로직이 맞아도 입력 크기와 형태가 변하면 실행이 느려지거나 실패할 수 있습니다. 데이터셋 크기와 빌드 시간의 기본 상태 검사를 일찍 설정하면 알림을 켜지 않은 경우에도 증가 추세와 평소 소요 시간을 관찰할 수 있습니다.
기본 검사를 더 확장해야 하면 검증 전용 파생 데이터셋을 만들 수 있습니다. 변환에서 필요한 유효성 로직을 계산하여 Allowed Value 같은 간단한 검사가 판정할 수 있는 값으로 출력합니다. 입력이 갱신될 때 검증 데이터셋도 빌드하도록 스케줄을 연결합니다. 검사 배치는 Data Health와 스케줄 운영 기준에 맞춰 구성합니다.