이 사건을 간단히 정리해보자면 이렇습니다.
①4월25일 페이스북에 다큐멘터리 감독 박성미 씨가 세월호 사건과 관련해 대통령을 비판하는 글을 올립니다. (원문보기)
②이 글이 큰 공감을 얻어서 페이스북을 중심으로 공유가 되자, 정○○라는 분이 이 글을 퍼가서 청와대 사이트에 그대로 올립니다.
③청와대 자유게시판에 올라온 이 글은 크게 화제가 되면서 조회수가 50만이 넘어가면서 언론에 기사화 됩니다.
④너무 사람들의 시선이 집중되자, 청와대 자유게시판에 이 글을 올린 정○○ 님이 게시글의 삭제를 요청합니다.
⑤청와대 게시판 관리자는 본인만이 글을 삭제할 수 있다고 안내하고, 이에 따라서 정○○ 님이 직접 게시글을 삭제합니다.
⑥그러나 청와대 게시판 시스템은 글이 삭제되어도 목록에만 표시되지 않을 뿐 게시글 주소를 넣으면 본문을 볼 수 있게 되어 있었습니다. 이에 따라서 본문 링크가 여러 커뮤니티를 통해 공유되면서 청와대 사이트가 접속 폭주로 마비됩니다.
⑦청와대 사이트가 다시 정상적으로 돌아왔으나, 어째서인지 해당 글의 주소를 직접 쳐서 들어가면 에러 페이지가 표시되게 되었습니다.
그런데, ㅍㅍㅅㅅ에 레이니걸 님이 쓰신 글처럼 이 에러페이지는 어딘가 부자연스럽습니다. 왜냐면 ㅍㅍㅅㅅ의 글에도 나와 있듯이 청와대 게시판은 글이 삭제되어도 목록에만 표시되지 않을 뿐 글을 그대로 남겨두는 방식입니다. 설령 글이 DB에서 지워졌다고 해도 URL로 보내는 존재하지 않는 데이터일 경우에는 NULL 값을 리턴하고 페이지에는 아무 내용도 없는 게시판 본문 페이지의 포맷만 표시되는 방식으로 설계되어 있습니다. 그러니 다시 말해서 게시글을 DB에서 지웠다고 해도 빈 본문 페이지가 표시되어야지, 특정한 에러 페이지로 이동하는 것이 아니라는 이야기입니다.
그래서 왜 이렇게 되는지 매우 궁금해졌습니다. 그래도 나름 웹개발 경력이 있는 사람으로서 이런 궁금증은 풀어야만 하겠죠. 그래서 소스를 한번 들여다보았습니다.
이걸 보면, 오른쪽은 일반적인 게시판 본문 페이지의 소스입니다. 이건 본문의 내용이 있건 없건 동일한 구조로 되어 있습니다. 반면 왼쪽은 삭제된 해당 게시물의 소스코드 입니다. 이 게시글은 일반적인 방법으로는 볼 수 없고, 개발자 도구 등을 사용해서 스크립트에 브레이크를 걸거나 크롬에서 직접 웹소스 보기에 주소를 넣어야 확인할 수 있습니다.
다음과 같은 주소를 크롬이나 파이어폭스의 URL 입력란에 직접 넣으면 확인할 수 있습니다.
view-source:http://www1.president.go.kr/community/sympathy/free_board.php?srh%5Bview_mode%5D=detail&srh%5Bseq%5D=576100&srh%5Bdetail_no%5D=60711
그런데, 왼쪽의 해당 게시글은 제일 끝부분에 인위적으로 삽입한 스크립트가 동작하도록 되어 있습니다.
프로그래밍을 하시는 분이라면 이해하시겠지만, 프로그래밍을 모르는 분들을 위해서 간단히 설명해보죠. 이 스크립트는 아주 간단합니다. 브라우저가 웹소스를 여기까지 읽었을 경우에 ‘/util/error.php’라는 페이지로 무조건 이동을 하라는 의미입니다. 그럼 ’/util/error.php’는 어떤 페이지일까요?
그렇습니다. 바로 그 에러 페이지입니다.
그러니까, 저 게시글만 저 에러 페이지로 이동하도록 인위적으로 설정해놓은 것입니다.
그럼 왜 저 스크립트는 저 위치에 있었을까요?
스크립트 뒷부분에 나와야 할 div 엘리먼트를 닫는 태그도 날아간 상태인데, 이런 비정상적인 HTML 코드를 생성하면서까지 저 스크립트가 저기 나와야 할 이유는 무엇일까요? 그건 다음 이미지를 보시면 아주 쉽게 이해할 수 있습니다.
왜냐면 그 부분부터가 실질적으로 본문의 제목과 내용을 뿌리는 코드가 나오는 곳이었기 때문입니다.
앞서 이야기했듯이 청와대는 글을 삭제해도 어째서인지 게시글이 DB에서 삭제되거나 별도의 저장공간으로 이동하지 않고 그대로 DB에 남아서 삭제된 상태임을 나타내는 플래그만 추가되는 형태로 설계되어 있습니다.(구조를 봐서는 그렇습니다)
그래서 삭제 플러그가 붙은 데이터는 게시물 목록에 표기를 하지 않고요. 게시판에 표시된 게시글 번호는 DB에 있는 글 중에서 삭제 플러그가 붙지 않은 글을 전부 셀렉트 한 뒤에 일렬 번호를 붙여서 다시 뿌려주는 방식으로 되어 있습니다. 그래서 글을 가져올 때 게시판에 표시된 글 번호는 아무런 영향을 주지 않고, 오로지 글의 실제 ID 값만이 글을 식별하는 값으로 쓰입니다. 그런데 어째서인지 삭제 플러그가 붙은 글도 본문을 보는 쿼리스트링을 넣어주면 전부 표시되도록 설계되어 있었던 것입니다. 그 때문에 정○○ 씨는 글을 지웠지만, 본문의 URL을 링크한 커뮤니티나 SNS에서는 아무렇지도 않게 이 글을 계속 볼 수 있던 상태였던 것입니다.
이에 청와대 웹사이트 관리자는 어쩔 수 없이 해당 게시물만 본문 내용을 읽기 전에 프로그램상의 분기를 넣어서, 게시물 번호인 [seq]=576100 이 들어올 때만 ’/util/error.php’로 무조건 이동하도록 하는 코드를 찍고 HTML의 출력을 멈추게 수정을 한 것으로 보입니다. 그러니까 ’/util/error.php’는 정○○ 님의 글을 볼 수 없게 하기 위해 급조된 페이지라고 할 수 있습니다.
그럼, 이건 청와대가 진실을 은폐하고, 대통령을 비난한 글을 못 보게 하기 위한 꼼수였을까요?
저는 조금 다르게 생각을 합니다.
앞서 사건 경위에서도 설명을 했듯이 이 글은 청와대 자유게시판에 글을 퍼와서 올린 정○○ 님이 삭제를 요청했고, 직접 지우라는 권유에 스스로 지운 게시글입니다. 그런데 청와대 게시판 시스템상 글을 삭제해도 목록에만 표시되지 않을 뿐 본문 URL을 직접 치고 들어오면 본문이 보이는 상태였습니다. 그렇다면 정○○ 님이 요청한 삭제에 대한 리퀘스트가 정상적으로 반영되지 않은 것입니다. 그렇게 되면 관리자가 할 수 있는 것은 본문을 완전히 삭제하는 것이겠죠.
그런데, 청와대 웹사이트 관리자에게 DB의 삭제 권한이 있을까요? 저는 아마 없을 것이라고 생각합니다.
그렇다면 DB에서 글을 지울 수 없다면 취할 수 있는 방법은 글이 보이지 않게 숨기는 것 뿐입니다. 그런데 안타깝게도 청와대 홈페이지는 너무 설계가 거지같이 되어 있어서 게시글에 등급을 설정할 수가 없었던 것 같습니다. 특정 권한을 가진 사람에게만 열람 가능하게 하는 그런 단순한 기능조차 없었던 것입니다.
그러니 정말 바보같고 무식한 방법이지만 이 글 하나만 예외처리를 해야 했겠죠. 그 결과물이 바로 이겁니다.
하지만, 청와대 홈페이지 관리자는 이 사실을 명확하게 공지를 했어야만 합니다.
단순히 본인 스스로 삭제하셨습니다라고 공지할 것이 아니라, 왜 이 글만 특정한 에러페이지로 이동하도록 예외 처리를 했는지까지 공지해야만 불필요한 오해를 낳지 않았겠죠. 그런데 그런 간단한 일을 하지 않았습니다.
이번 청와대 자유게시판 글 삭제 문제는 우리 정부의 홈페이지 관리가 얼마나 막장인지를 보여주는 한 사례라고 할 수 있겠습니다.
아무렇지도 않게 .php가 그대로 노출되는 무신경함, 본인인증을 거치도록 되어 있는 기능들을 크롬의 개발자 콘솔로 1~2분만에 뚫을 수 있는 허술함, 게시물을 삭제해도 게시물이 그대로 보이는 황당한 처리로직… IT강국을 자처하는 대한민국의 정부 최고조직의 홈페이지라고는 믿기 힘든 수준인 것 같습니다.
ps. 밤 9시경부터 해당 게시물의 리다이렉트 스크립트가 다음과 같이 변경되었습니다.
기존 코드는 그냥 리다이렉트 하는 코드였는데, 이번에는 폼으로 notfound.php 라는 페이지로 이동시키는 소스로 바뀌었습니다. 어차피 똑같이 리다이렉트 하는 코드일 뿐인데 왜 이런 방식으로 바뀐 걸까요?
여기서 청와대 웹사이트의 해당 게시글에 대한 브라인드 처리(강제 이동 처리)는 인위적인 것임이 분명해졌습니다. 소스가 변경되었다는 점에서 그걸 확신할 수 있습니다.