Terraform/OpenTofu 기초 · 데이터 소스와 자원의 차이 · 이론
만드는 블록과 읽는 블록
한 줄 요약
resource 는 대상을 소유하고 data 는 대상을 읽기만 한다. 이 한 글자 차이가 상태 모양·계획 시점·파괴 범위를 모두 가른다.
왜 이 구분이 필요했나
초기 설정 언어에는 resource 만 있었다. 그런데 현실의 인프라는 한 팀이 전부 만들지 않는다. 네트워크는 인프라 팀이 이미 만들어 두었고, 인증서는 보안 팀이 발급하고, 계정 번호는 회사가 하나뿐이다. 이런 것들을 쓰려면 값이 필요한데, 값을 얻자고 resource 로 적으면 도구는 그것을 자기 소유로 오해한다. 소유했다고 믿는 순간 destroy 는 남의 네트워크를 지우려 들고, 드리프트 감지는 남의 팀이 바꾼 것을 되돌리려 든다.
그래서 "읽기만 하는 블록" 이 따로 생겼다. data 블록은 대상을 만들지도 바꾸지도 지우지도 않는다. 상태에 항목이 생기기는 하지만 그것은 소유 증서가 아니라 마지막으로 읽은 값의 사본이다. 그래서 destroy 를 돌려도 원본은 남고, 계획에는 create 나 destroy 가 아니라 read 만 나온다.
어떻게 동작하나
상태 파일을 열면 항목마다 mode 가 있다. 값은 managed 아니면 data 두 가지다. tofu state list 가 주소를 찍을 때 data. 접두어를 붙이느냐 마느냐도 여기서 갈린다.
tofu state list# data.local_file.seed ← mode = "data"# local_file.copy ← mode = "managed"읽기가 언제 일어나는지가 두 번째 갈림길이다. 기본은 계획 단계다. 인자가 모두 알려진 값이면 도구는 계획을 세우면서 읽고, 읽은 값을 계획에 그대로 박아 넣는다. 그래서 리뷰어는 계획만 보고도 무엇이 들어갈지 안다.
읽기가 적용 시점으로 밀리는 경우는 두 가지다. 인자가 아직 만들어지지 않은 리소스의 속성에 의존할 때, 그리고 데이터 소스에 depends_on 이 붙어 있을 때다. 후자는 원본이 이미 디스크에 있어도 밀린다 — 의존이 끝나야 읽겠다는 선언이기 때문이다. 이때 계획에는 이렇게 나온다.
# data.local_file.back will be read during apply + content = (known after apply)값이 알 수 없음이 되면 그 값을 쓰는 하류 리소스의 속성도 전부 알 수 없음이 된다. 계획 리뷰의 값어치가 그만큼 떨어지므로, 데이터 소스에 depends_on 을 붙일 때는 정말 필요한지 한 번 더 따져야 한다.
세 번째 갈림길은 다시 읽는다는 점이다. managed 리소스는 상태에 적힌 값과 실물을 견줘 드리프트를 잡지만, 데이터 소스는 견줄 것이 없다. 매 계획마다 새로 읽고 그 값을 하류에 흘려보낸다. 원본이 바뀌면 "상태가 어긋났다" 가 아니라 "입력이 바뀌었다" 로 잡히고, 그 값이 재생성을 부르는 속성이면 하류가 통째로 교체된다.
읽을 수 없을 때의 실패도 시점이 다르다. 파일이 없으면 적용까지 가지 못하고 계획이 그 자리에서 멈춘다.
Error: Read local file data source error+Original Error: open ./absent.txt: no such file or directory이름이 헷갈리는 형제가 하나 있다. terraform_data 는 data 블록이 아니라 내장 프로바이더가 제공하는 managed 리소스다. 상태의 mode 는 managed 이고, 값을 바꾸면 계획에 update 나 replace 가 나오며, destroy 하면 사라진다. 이름 때문에 데이터 소스로 읽는 사람이 많은데, 이 블록의 쓰임새는 값을 읽는 것이 아니라 "바뀌면 무언가를 다시 하게 만드는 표식" 을 상태에 남기는 것이다.
현장에서 만나는 모습
가장 흔한 사고는 남이 만든 것을 resource 로 적는 것이다. 이미 있는 대상을 resource 로 선언하면 도구는 그것을 새로 만들려 하고, 이름이 겹치면 적용이 실패하고, 이름이 안 겹치면 똑같은 것이 하나 더 생긴다. 후자가 더 나쁘다 — 아무도 실패를 보지 못한 채 중복이 쌓인다. 읽기만 하면 되는 것은 data 로 적고, 이미 있는 것을 정말 소유해야 한다면 import 로 편입한다.
두 번째로 흔한 것은 계획이 알 수 없음으로 도배되는 일이다. 리뷰 문화가 자리 잡은 팀일수록 "계획에 값이 다 보여야 승인한다" 는 규칙을 두는데, 데이터 소스 하나에 depends_on 을 붙인 탓에 승인할 수 없는 계획이 나온다. 이럴 때는 의존을 데이터 소스가 아니라 그 값을 쓰는 리소스 쪽으로 옮기는 편이 낫다.
세 번째는 반대 방향이다. 원본이 조용히 바뀌어 하류가 교체되는 경우다. 설정 파일은 한 글자도 안 바뀌었는데 계획에 교체가 뜬다. 원인을 코드에서 찾으면 영원히 못 찾는다. 데이터 소스가 읽는 원본이 무엇인지, 그것을 누가 바꿀 수 있는지를 먼저 본다.
다음 실습에서 할 것
파드의 OpenTofu 와 local·random·null 프로바이더로 여덟 단계를 돕니다. 파일 하나를 data 로 읽어 복사하고, 상태에서 mode 로 두 항목을 가르고, destroy 뒤에 원본이 남는 것을 확인합니다. 이어서 이름이 적용 시점에 정해지는 파일을 읽어 계획이 어떻게 달라지는지, 이미 있는 파일에 depends_on 을 붙이면 무엇이 밀리는지, 원본이 없을 때 계획이 어디서 멈추는지를 봅니다. 마지막 두 단계에서는 terraform_data 의 mode 를 데이터 소스와 나란히 놓고 비교하고, 원본을 바꿔 하류가 교체되는 것까지 확인합니다.