Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

서버측 페이지가 2번 로딩되는 문제

개발을 하다보면 항상 머리아프게 고생시킨 문제는 어이없는 무제인 경우가 많다. 이번에도 역시 그랬다. 이 문제 때문에 하루 업무를 다 날렸다. 오전 11시부터 저녁 8시까지 이것만 붙들고 있었으니 머리가 아플만도 했다.

이건 트러블슈팅(?)쪽이나 마찬가지기 때문에 제목을 저렇게 달기는 했지만 서버측 페이지가 2번 로딩된다는 것을 알아내는 데도 한 5시간 걸린듯 하다. 왜냐하면 2번 로딩된다는 생각은 상상도 못했기 때문에.... 팀장님이 한번 그얘기를 하고 나서 아니라도 대답한 후에 한참있다가 혼자 종이에 적다보니 2번 로딩이 된다면 모든게 이치에 맞았다. 왜 2번되는지만 모를 뿐..... 일단 소스를 좀 보자.


' deleteComentProc.asp
sql =       " SELECT * FROM tbl_fob_comment "
sql = sql & " WHERE commentid='" & commentId & "' AND cmt_password='" & cmtCheckPass & "' "

rs.open sql,con, 3, 1, adCmdText

if rs.EOF = false then
    sql = " DELETE FROM tbl_fob_comment WHERE commentid='" & commentId & "' "
    con.Execute(sql), , adCmdText + adExecuteNoRecords

    sql =       " UPDATE tbl_fob_article SET atc_commentcount = atc_commentcount - 1 "
    sql = sql & " WHERE articleid='" & articleid & "'"
    con.Execute(sql), , adCmdText + adExecuteNoRecords

    resultMessage = "삭제 되었습니다."
else
    resultMessage = "비밀번호가 틀렸습니다."
end if

코드는 ASP코드이지만 서버단 언어는 상관없다.(원인이 이쪽이 아니니까... 이것만 몇시간을 봤는지...) 혹 ASP를 모르시는 분을 위해 설명을 드리자면(필요없는 코드는 빼고 메인로직만 썼다.)

게시판에서 코멘트를 단 것을 삭제하는 부분이다. POST로 코멘트의 id값(commentId)와 비밀번호(cmtCheckPass)를 받고 그걸로 쿼리를 해서 결과값이 있으면 if문에 들어가서 코멘트를 지우고 게시판의 코멘트 갯수를 하나 줄여주고 결과값이 없으면 else로 빠져서 비밀번호가 틀렸다고 뿌려주는 간단한 코드이다. ㅡ..ㅡ

근데 코멘트 삭제를 하면 화면엔 비밀번호가 틀렸다고 찍히면서 실제로 코멘트는 삭제가 되었다. 물론 비밀번호를 틀리게 입력하면 비밀번호 틀렸다고 정상적으로 나온다. if문 안에 출력도 해보고 별의별짓을 다 해봤지만 if문 안에 들어간건 아무것도 화면에 출력되지 않고 오직 쿼리만 실행되었다. 진짜 미치는줄 알았다.

"코드는 거짓말을 안해"가 내 개발 신조였는데 거짓말하는줄 알았다. 제길슨......

그러다 위에 말했듯이 이 페이지가 Delay없이 2번 로딩이 되면 모든 것이 이치에 맞다는 것을 깨달았다.(5시간만에.. ㅠ..ㅠ) 첫번째 로딩에서 비밀번호가 맞으니까 if문에 들어가고 코멘트를 지우고 2번째 로딩되면서 이미 지웠으니까 rs에 아무것도 안나오고 else에 빠지고 비밀번호가 없다고 출력하는 것이다. ㅡ..ㅡ

이 소스 아래쪽에선 resultMessage를 자바스크립트를 이용해서 alert했기 때문에 서버사이드에서 2번 로딩되는 현상이 클라이언트 사이드인 자바스크립트는 그냥 무시해 버린 것이다.



이 환장하던 문제의 발단은 일단 나였다.(당연하겠지... 내가 짰으니.. ㅡ..ㅡ) 전에는 안그랬었는데 개발자가 본격적으로 되면서 웹표준과 크로스브라우징에 상당히 민감하게 되었다. 우리팀은 아직 그런 부분에 대한 마인드가 전혀 없기 때문에 이 혼자하는 프로젝트에서 그걸 적용해보려던게(잘 모르면서) 화근이 되었다.


<!-- // view.asp -->
<script type="text/javascript">
    ...................
    function goDeleteCommentSubmit()
    {
        $("formFobComment").action = "fob_CommentDel.asp?boardid=<%=boardid %>";

        $("formFobComment").submit();
    }
    ...................
</script>

<form id="formFobComment" method="post" action="">
    ...........
    <input type="hidden" id="commentId"       name="commentId"       value="" />
    ...........
    <input type="password" id="cmtCheckPass"  name="cmtCheckPass" />
    ...........
    <input type="submit"   id="cmtPassSubmit" name="cmtPasSubmit" value="확인" onclick="goDeleteCommentSubmit();" />
</form>

이번에도 역시 필요한 코드만 써 넣었다. 이렇게 핵심부분만 놓아놓고 보니 이해가 되는가? 이제 이쯤 되면 눈치까야된다.. ㅠ..ㅠ

웹표준의 기본은 태그를 용도에 맞게 쓰는 거라고 생각한다. 그래서 그걸 따르고자 submit을 썼다. 근데 우리팀에선 이렇게 안한다. 보통은 그냥 <button>만 사용하고 난 우리소스에선 submit버튼은 본적두 없다. 당연히 button을 쓰기 때문에 자바스크립트 function에서 Validation을 해 준 다음에 폼.submit()을 사용한다.

기존소스를 왔다갔다 하면서 작성하다 보니 이게 섞여 버린거다. 혹시라도 설명이 부족할까봐(난 친절하다. ㅡ..ㅡ) 자세히 설명하면 type=submit은 클릭(또는 Enter)하는 순간 submit이 발생하고 javascript에서 form.submit()을 했으니 또 submit이 발생한 것이다. 연속으로 두번 submit이 발생하고 서버측인 deleteComentProc.asp페이지가 2번 로딩된것이다. 아~~주 자연스럽게 2번이 되기 때문에 감쪽같아서 디버깅도 무지 더럽다.(지금 생각하면 if문안에 Response.End로 멈춰버렸으면 될것 같지만.. ㅡ..ㅡ)

view.asp에 form이 또 있어서 폼이 2개 있어서 그런가 해서 한 7시간정도 고민했을때 폼까지는 지워봤지만 이건 생각도 못했다. 과장님이 3시간 대리님이 3시간 같이 붙들고 있었지만 개발쪽에서 막구른 우리형한테 물어보고(이때쯤 submit버튼을 의심하고 있긴 했었는데 더이상 만져보기도싫은 상태였다.) 1분만에 해결했다. ㅡ..ㅡ 역시 개발을 막 굴러야대... 경험이 짱이야....

이날의 교훈.... 웹표준은 어렵다... 경험이 짱이다.. 일단 막 구르고 보자...
2007/12/13 01:23 2007/12/13 01:23