BGM용 세이라디오
열기▼       고정
전체
글목록

백업을 이용해 php에서 파일이 지워지는 사태를 막자.

목요일, 12월 05, 2013

필자는 가끔 php로 편집되는 txt파일이 "", 즉 완전히 초기화되어 백지가 되는 경험을 했다. 소중한 데이터(인기글 데이터)도 날려버렸을 뿐더러 왜 그런지 이유도 몰라서 더 당황스러웠었다.
처음엔 무료 호스팅 사이트라 가끔 이렇게 파일을 지워대는 건가 하고 역시 싼게 비지떡이구나 싶었는데, 그래도 구글에 검색해보니 필자와 같은 사례가 그리 많지 않았다. 왠지 진짜 문제가 다른 데에 숨어있는 것같았다.
그런데 파일을 열고, 읽고, 쓰고, 닫을 때 에러가 발생할 수 있다는 점을 생각해보니 이 에러에 대비하지 않아서 문제가 발생한 거라는 걸 알 수 있었다. fopen, fread, fwrite, fclose는 실패할 경우 false 값을 반환한다.(fclose는 사실 실패해도 웬만한 경우엔 상관 없지만)
그렇다면 php에서 파일이 지워지지 않게 하려면 어떻게 해야 할까? 파일을 다루는 함수가 실패했을 때 그대로 진행하면 예상치 못한 결과를 가져올 수 있고, 특히 w모드의 fwrite는 파일을 열 때 파일을 모두 지워버려 만약 쓰기가 실패하면 데이터가 php에 변수로만 존재하게 돼 매우 위험한 상태가 된다.
필자는 php에 전문적이지 않아 더 좋은 방법도 있겠지만, 필자는 다음과 같은 방법을 사용했다.



전형적인 예로 입력한 문자열을 data.txt에 축적해 편집하는 php가 있다고 하자. 그리고 fopen은 r모드, fwrite는 w모드(파일 초기화)를 사용한다고 하자.
에러 핸들링이 없을 땐 다음과 같은 구조를 가진다.(fclose는 생략했다.)
fopen->fread->처리->fopen->fwrite
여기서 프로그램 불안정을 초래하는 부분은 다음과 같다.

  • fopen 또는 fread가 실패할 경우 처리 과정에 쓰일 데이터가 없다.
  • w모드의 fwrite를 실패할 경우, 이미 파일이 초기화되어 있으므로 데이터가 사라진다.

첫째 경우에는 파일 처리 결과가 false인지를 체크해서 실패하면 다시 시도하도록 하면 해결된다. 두번째 경우는 w모드로 인한 데이터 손상이 원인이며 다음과 같은 구조적인 보완이 필요하다.

해법1-구조 보완(백업)

fopen->fread->data.txt가 공백("")일 경우, 즉 fwrite가 실패한 경우 data_temp.txt를 불러온다.(백업 데이터를 불러오는 과정)->처리->data_temp.txt에 저장(백업해놓는 과정)->성공할 경우 data.txt에 fwrite

data_temp.txt에 저장하는 작업이 성공한 후 fwrite(data.txt) 실패하는 경우는 데이터가 사라졌으므로 다시 시도해서는 해결할 수 없으며, 실패에 대비해 data_temp.txt를 백업해놓는 방식을 이용했다.

해법2-에러 감지

  • 처음에 fopen(data.txt) 실패
  • 처음에 fread(data.txt) 실패
  • data.txt가 공백이어서 fopen(data_temp.txt) 했을 때 실패
  • data.txt가 공백이어서 fread(data_temp.txt) 했을 때 실패
  • 데이터 처리후 저장할 때 fopen(data_temp.txt) 실패
  • 데이터 처리후 저장할 때 fwrite(data_temp.txt) 실패
  • data_temp.txt에 저장하는 작업이 성공한 후 fopen(data.txt) 실패

위의 에러 케이스들이 발생하면, 작업이 가벼운 편이므로 굳이 어디까지 성공했는지 확인할 필요는 없고 처음부터 다시 시작하는 것이 가장 간단한 해법이다.
첫 댓글을 써주세요!

댓글을 인용하려면 @![댓글 ID]!@와 같이 쓰시면 됩니다. "@!" 와 "!@"를 쓰시려면 "+@+!+", "+!+@+"와 같이 써주세요.

페이스북 댓글
.post-outer{ -webkit-transform:none; transform:none; display:inline; padding:0; margin:0; border-width:0; } .hentry>div{ display:none; }