되돌릴 수 없는 변경 · 승인한 두 건은 아무 두 건이 아니다 · 이론
승인한 두 건은 아무 두 건이 아니다
한 줄 요약
변경 승인은 몇 건을 바꿔도 된다는 허가가 아닙니다. 어느 고객의 어느 행을, 어떤 상태에서 어떤 상태로 바꿀지에 대한 합의입니다.
왜 이게 필요했나
축제 운영자가 비 때문에 일부 간식 주문을 취소해 달라고 했습니다. 아침에 대기 주문 두 건을 조회하고 승인받았습니다. 점심에 실행하려고 보니 한 주문은 다른 담당자가 수량을 바꿨고, 같은 고객의 새 대기 주문도 들어왔습니다. 아침에 사용한 WHERE 조건을 다시 실행하면 승인 때 없던 주문까지 취소할 수 있습니다. SELECT가 맞았다는 사실과 나중의 UPDATE가 승인 범위를 지킨다는 사실은 같지 않습니다.
앞 수업에서는 넓은 요청을 좁히고, 백업과 중단 기준을 준비했습니다. 이제 시간이라는 변수를 추가합니다. 사람이 승인 문서를 읽는 동안 데이터베이스는 계속 움직입니다. 읽기부터 적용까지 테이블 전체를 잠그면 그 사이의 다른 업무가 멈춥니다. 그래서 승인 시점의 관측을 작은 명시적 데이터로 남기고, 실행할 때 그 관측이 여전히 유효한지 비교합니다. 비교가 실패하면 멈추고 새 승인을 받아야지, 현재 값으로 조용히 계획을 바꾸면 안 됩니다.
어떻게 동작하나
이번 실습의 승인 대상은 id·revision·qty 세 값입니다. 고객 구분 tenant는 별도 인자로 전달합니다. 예를 들어 blue 고객의 주문 1이 revision=3, qty=7일 때 승인을 받았다면, 적용 조건에는 이 값들과 pending 상태가 모두 들어갑니다. ID만 있으면 다른 담당자가 바꾼 값을 덮을 수 있고, 버전만 있으면 다른 고객의 행을 바꿀 수 있습니다. 값 하나를 검사하는 장치가 아니라 승인한 사실 전체를 보존하는 계약입니다.
승인 때: 고객 blue / 주문 1 / 버전 3 / 수량 7 / pending적용 때: 고객 blue / 주문 1 / 버전 4 / 수량 7 / pending판단: 수량이 같아도 버전이 바뀌었으므로 재확인버전은 마지막 숫자가 아니라 변경 이력을 구분하는 표식입니다. 수량이 7에서 8로 바뀌었다가 다시 7이 됐을 수 있습니다. 값을 비교하는 것만으로는 이 왕복을 구별하지 못합니다. 이번 계약에서는 모든 정상 업무 변경이 revision을 증가시킨다는 전제를 둡니다. 다른 프로그램이 그 규칙 없이 테이블을 고치면 보호 범위가 달라지므로, 운영에서는 쓰기 경로와 권한도 함께 관리해야 합니다. 이 실습의 토큰 하나가 모든 쓰기 프로그램을 통제해 주지는 않습니다.
승인 집합은 ID로 정렬한 사본으로 만듭니다. 같은 두 대상을 반대 순서로 받았다고 다른 변경으로 보지 않으려는 것입니다. 반대로 같은 ID가 두 번 들어오면 한 행을 두 번 다루려는 모호함이 생기므로 거부합니다. 빈 목록도 성공처럼 처리하지 않습니다. 개수가 0인 실행을 받아 주면 입력을 잃어버린 버그가 아무 일 없이 끝난 정상 작업으로 기록될 수 있습니다. 이번 학습에서는 1개부터 16개까지의 작은 배치를 사용합니다.
숫자 검증도 단순한 방어 코드가 아닙니다. Python에서 True는 int의 하위 타입이라 느슨한 검사에는 주문 ID 1처럼 들어갈 수 있습니다. 승인 자료에서 논리값이 번호로 바뀌는 것은 데이터 해석 오류입니다. id·revision·qty에 정확한 정수 범위를 정하고 bool을 거부합니다. 반환한 계획을 다른 코드가 수정해도 원래 입력이 함께 바뀌지 않도록 각 대상도 새 dict로 복사합니다.
현장에서 만나는 모습
고객이 가장 많이 묻는 것은 SQL 문법보다 영향 범위입니다. 왜 이 두 주문만 바꾸는지, 다른 고객은 왜 영향이 없는지, 승인 후 달라진 건이 있으면 누가 다시 판단하는지를 설명할 수 있어야 합니다. 따라서 변경 도구의 입력은 담당자에게 보여 준 계획과 연결되어야 합니다. 기술자가 읽은 CSV와 실제 실행한 목록이 서로 다르면 승인 절차가 있어도 안전하지 않습니다.
실제 FDE 업무는 고객의 문제를 이해하고 데이터와 애플리케이션으로 해결하며 배포까지 책임지는 일과 연결됩니다. 아래 Palantir 공개 공고도 고객과의 협업, 아키텍처와 데이터 중심 구현을 요구합니다. 그러나 이 공고가 특정 PostgreSQL 기법이나 이번 예제의 스키마를 요구한다는 뜻은 아닙니다. 여기서는 그 역할에 필요한 변경 범위 설명과 구현 검증을 작은 가상 사례로 연습합니다. 실제 고객 데이터나 개인 정보는 사용하지 않습니다.
계획을 남기는 것과 권한을 받는 것도 구분합니다. tenant 문자열을 함수에 넣었다고 호출자가 그 고객을 변경할 권한을 얻는 것은 아닙니다. 이 함수는 권한 있는 담당자가 호출한다는 전제 아래 동시 변경 충돌을 검사합니다. 운영 API에서는 로그인, 고객 범위 권한, 승인 주체, 감사 보존 정책을 별도로 강제해야 합니다. 테스트용 DB 계정을 실제 서비스 운영 계정의 예시로 사용하지 않습니다.
다음 확인에서 할 것
이어지는 퀴즈에서 같은 건수·다른 ID, 같은 값·다른 버전, 중복 ID와 빈 승인을 구분합니다. 뒤의 종합 실습에서는 preview로 관측한 계획을 실제 두 PostgreSQL 연결 사이에서 오래되게 만든 뒤, 적용이 거부되는지 확인합니다. 실패한 대상만 몰래 새 값으로 바꾸지 않고 변경 전제를 다시 확인하는 연습입니다.
참고: [Palantir FDSE 공고](https://jobs.lever.co/palantir/dab396d4-2f14-4796-aac0-0d82883dccf0), [PostgreSQL UPDATE](https://www.postgresql.org/docs/16/sql-update.html). 공고는 2026-09-13 확인했으며 채용 보장이나 시험 출제 범위를 뜻하지 않습니다.