Skip to Content

2장. 파일과 씨름하던 프로그래머들

만화로 보는 요약 — 먼저 읽어보세요

만화로 보는 요약 — 먼저 읽어보세요

그냥 파일에 쓰면 왜 깨지나 → 정전은 부분 쓰기를 만들고 → 동시 접근은 기록을 덮어쓰며 → DBMS가 공통 방어 코드를 떠안기 시작했다.

면접 실전 질문: ① 부분 쓰기가 위험한 이유 ② 동시 접근 충돌과 lost update ③ 초기 DBMS가 맡기 시작한 책임


배경 — 500년 뒤, 촛불이 다시 꺼지다

1장 끝에서 질문을 하나 던졌죠. 오늘날 BEGIN ... COMMIT을 위협하는 “꺼진 촛불”은 무엇일까? 답은 생각보다 시시합니다. 정전. 그리고 그 사촌들 — 프로세스 강제 종료, 커널 패닉, 디스크가 데이터를 다 쓰기 전에 전원이 뽑히는 순간.

회계사의 촛불이 꺼지면 장부가 어긋났듯, 컴퓨터의 전기가 나가면 데이터가 반쯤 쓰이다 부서집니다. 다른 점이 있다면, 회계사는 하루에 몇 건을 적었지만 컴퓨터는 초당 수천 건을 적는다는 것. 500년 전의 문제가, 이번엔 규모가 다릅니다.

스토리 — “그냥 파일에 저장하면 되잖아?”

1960~70년대, 컴퓨터는 있었지만 우리가 아는 데이터베이스는 없었습니다. 데이터를 어디에 저장했을까요? 그냥 파일입니다. 프로그램이 파일을 열고, 원하는 위치로 가서, 숫자를 씁니다. 지금 여러분이 fopen 하고 write 하는 것과 똑같아요.

문제는 여기서 시작됩니다. 계좌 잔고를 파일에 기록한다고 해볼게요.

1) 파일에서 A의 잔고를 읽는다 → 100 2) 메모리에서 100 - 30 = 70 계산 3) 파일의 그 자리에 70을 덮어쓴다

3번을 쓰는 도중에 전원이 나가면? 파일에는 70100도 아닌, 앞부분만 갱신되고 뒷부분은 옛 값이 남은 — 어느 쪽도 아닌 레코드가 남습니다. 레코드 하나가 통째로 깨지는 거죠. 회계사의 “반만 적힌 장부”가 디스크 위에서 재현됩니다. 이게 첫 번째 지옥, 부분 쓰기(partial write).

두 번째 지옥은 더 고약합니다. 프로그램이 하나가 아니거든요. 급여 정산 프로그램과 출금 프로그램이 동시에 같은 계좌 파일을 건드리면?

[출금] A 잔고 읽음 → 100 [급여] A 잔고 읽음 → 100 (아직 아무도 안 씀) [출금] 100 - 30 = 70 저장 [급여] 100 + 50 = 150 저장 ← 출금이 방금 쓴 70을 덮어씀!

30을 출금했는데 잔고는 150. 출금 기록이 증발했습니다. 두 프로그램이 서로의 존재를 몰랐기 때문이에요. 이게 두 번째 지옥, 동시 접근 충돌. 나중에 우리가 ‘격리성’이라 부르게 될 문제의 원형입니다.

그래서 사람들은 파일 위에 방어 코드를 덕지덕지 붙이기 시작했습니다. 잠금 파일 (lock file)을 만들고, 임시 파일에 먼저 쓴 뒤 이름을 바꾸고, 체크섬을 붙여 깨진 레코드를 걸러내고… 프로그램마다 제각각으로요. 짐작이 가시죠? 이 방어 코드가 바로 나중에 데이터베이스가 통째로 떠안게 될 일들입니다.

핵심 — DBMS는 “공통의 방어 코드”였다

1960년대 후반, 이 혼돈을 정리하려는 소프트웨어가 등장합니다. 아폴로 계획의 부품 관리를 위해 IBM이 만든 IMS, 그리고 네트워크 모델을 표준화한 CODASYL 계열 (네트워크 모델 자체는 찰스 바크만의 IDS에서 먼저 나왔고, CODASYL이 이를 표준으로 정리했죠). 우리가 아는 첫 세대 데이터베이스 관리 시스템(DBMS)이죠.

이들이 준 건 크게 두 가지였습니다.

  • 구조 — 데이터를 트리(계층형)나 그래프(네트워크형)로 정리하는 공통 모델. 더 이상 파일 포맷을 프로그램마다 새로 발명하지 않아도 됐어요.
  • 신뢰성의 시작 — 저장 중 사고가 나도 데이터를 지키려는 장치(로그, 복구)를 DBMS가 대신 맡기 시작합니다. 프로그램마다 붙이던 방어 코드가 한곳으로 모인 거죠.

다만 이 시절엔 부분 실패를 막는 로그동시 접근을 막는 잠금이 서로 다른 장치로 따로 존재했습니다. 로그·복구도, 심지어 “작업 단위(unit of work)“라는 운영 개념도 이미 있었어요. IMS만 해도 로그와 체크포인트로 사고에서 데이터를 되살렸으니까요. 정작 없던 건 이 조각들을 하나의 추상(BEGIN·COMMIT·ROLLBACK)으로 통합하고, “무엇이 올바른 실행인가”까지 이론으로 못박은 일반화된 트랜잭션 모델입니다.

바로 그 빈자리, “이 모든 걸 하나의 작업 단위로 묶어 보장한다”는 아이디어에 이름과 규칙이 붙는 순간이 옵니다. 다음 장의 주인공이죠. 파일과 씨름하던 개발자들의 삽질이, 드디어 transaction이라는 단어 하나로 정리됩니다.

정리

  • 1장의 “꺼진 촛불”의 정체 = 정전·크래시. 저장 도중 죽으면 데이터가 반쯤 부서진다.
  • 초기엔 데이터를 그냥 파일에 저장 → 두 가지 지옥: 부분 쓰기(원자성 부재)와 동시 접근 충돌(격리성 부재).
  • IMS·CODASYL 같은 초기 DBMS가 구조와 신뢰성(로그·복구)을 공통으로 떠안기 시작했지만, 이 조각들을 하나로 묶은 일반화·이론화된 “트랜잭션” 개념은 아직 없었다.

생각해볼 질문: 프로그램마다 제각각 붙이던 “방어 코드”를 하나로 묶으려면, 먼저 무엇을 하나의 단위로 볼지부터 정의해야 합니다. “여기서부터 여기까지가 한 묶음”을 어떻게 선을 그을 수 있을까요? (3장에서 그 선에 이름이 붙습니다.)

3장 · System R과 하나의 단어

Last updated on