수정과 관련된 입력 폼은 앞서 삭제에서 같이 만들었다.

삭제에서는 댓글 번호를 넣어 전달했고

수정에서는 댓글 번호와 댓글 내용을 넣어서 전달한다.

다만, 댓글 쓰기에서 같은 형태의 입력처리를 했기 때문에 충돌을 막기 위해

댓글 쓰기에서는 form1으로 폼 태그의 이름을 부여했고

댓글 수정에서는 form2으로 폼 태그의 이름을 부여했다.

즉, 게시물에 대하여 작성하는 댓글의 댓글내용(rememo)와

수정시 사용하는 댓글내용(rememo)의 컨트롤(HTML Tag) 이름이 동일해도 문제가 생기지 않는 것은

컨트롤들이 속한 폼 이름이 달라서 그런 것이다.

폼 이름이 다르면 각 폼 안의 컨트롤은 이름이 같아도 구별되어 사용된다.

댓글 내용인 rememo은 form1.rememo와 form2.rememo로 다르게 처리한다.


수정 SQL(UPDATE)문은 댓글 쓰기 처리시 같이 작성했다 (updateBoard5Reply). 


따라서 남아 있는 것이 화면 처리이고,

이 화면 처리는 자바 스크립트를 이용하여 다소 복잡하게 구현해야 한다.

사용된 자바 스크립트 함수는 3가지로

수정 버튼을 누르면 수정 폼을 화면에 보여주는 함수(fn_replyUpdate),

수정 후 저장 버튼을 누르면 서버로 전송하는 함수(fn_replyUpdateSave),

수정하나 취소 버튼을 눌러서 입력 폼을 감추는 함수(fn_replyUpdateCancel) 로 구성되어 있다.

var updateReno = updateRememo = null;
function fn_replyUpdate(reno){
    var form = document.form2;
    var reply = document.getElementById("reply"+reno);
    var replyDiv = document.getElementById("replyDiv");
    replyDiv.style.display = "";
   
    if (updateReno) {
        document.body.appendChild(replyDiv);
        var oldReno = document.getElementById("reply"+updateReno);
        oldReno.innerText = updateRememo;
    }
   
    form.reno.value=reno;
    form.rememo.value = reply.innerText;
    reply.innerText ="";
    reply.appendChild(replyDiv);
    updateReno   = reno;
    updateRememo = form.rememo.value;
    form.rememo.focus();
}

function fn_replyUpdateSave(){
    var form = document.form2;
    if (form.rememo.value=="") {
        alert("글 내용을 입력해주세요.");
        form.rememo.focus();
        return;
    }
   
    form.action="board5ReplySave";
    form.submit();   
}

function fn_replyUpdateCancel(){
    var form = document.form2;
    var replyDiv = document.getElementById("replyDiv");
    document.body.appendChild(replyDiv);
    replyDiv.style.display = "none";
   
    var oldReno = document.getElementById("reply"+updateReno);
    oldReno.innerText = updateRememo;
    updateReno = updateRememo = null;
}

BoardRead.jsp


저장 버튼 처리는 댓글 입력 여부만 확인하는 단순한 코드로 작성했다.

수정 폼을 화면에 보여주는 기능과 숨기는 기능은 제법 복잡한 처리를 해야 한다.

자바 스크립트의 document.body, document.form2, document.getElementById,.appendChild 등은 찾아보길 바라고 여기서는 간단하게 넘어간다.


수정 폼을 화면에 보여주는 함수(fn_replyUpdate)는

숨겨져 있는 댓글 입력창(id=replyDiv)을 사용자에게 보여주는 것이 핵심 기능이다.

댓글 입력창을 보여주며 입력박스(rememo)에 기존에 입력한 댓글 내용을 넣어줘야 한다.

댓글 번호를 이용해서 Ajax로 서버에서 댓글 내용을 가져올 수 있지만

여기서는 화면에 출력된 리스트에서 선택한 댓글의 내용을 가져와 넣어준다.

리스트에서 선택한 댓글의 내용을 가져오기 위해

리스트를 생성할 때 각 댓글을 DIV 테그로 생성하고, 댓글번호를 이용하여 이 DIV 테그의 ID("reply"+reno)를 부여하였다.

즉, document.getElementById("reply"+reno)로 사용자가 수정하고자 하는 댓글의 내용을 가져와

입력창의 입력박스에 넣어주는 것이다 (form.rememo.value = reply.innerText;).

댓글 수정 상태에서 취소나 저장을 하지 않고 다른 글을 수정하려고 할 때,

현재 입력하던 내용을 취소하기 위해, 현재 입력하는 댓글 번호를 저장해서 가지고 있어야 한다.

updateReno는 현재 입력하는 댓글 번호로

현재 입력하던 내용을 취소하고 이전 내용을 화면에 출력하는 데 이용한다 (oldReno.innerText = updateRememo).

입력 창을 감추는 함수(fn_replyUpdateCancel)는

수정하던 댓글 내용(updateReno)를 취소하고 입력창(replyDiv)을 화면에서 보이지 않게 처리한다 (display="none”).

그리고 부모를 document.body로 바꾸어 준다.

현재 있는 위치에는 기존 댓글의 내용이 출력되어야 하기 때문에 다른 곳으로 옮겨 주는 것이다.


수정 후 저장 버튼을 누르면 입력한 내용을 서버로 전송(submit)하고,

서버에서는 내용을 데이터베이스에 저장한 후

다시 게시판 글 읽기로 돌아가("redirect:/board5Read?brdno=") 수정된 댓글이 보이게 된다.


이상의 내용에서 자바 스트립트가 조금 복잡해 보일 수 있는데

기본 개념은 입력창을 적절한 위치에 보여주고 숨기는 것이니 잘 익혀두길 바라고

여기서는 자바 스트립트로만 구성했지만

실제로는 JQuery를 이용하는 것이 조금 더 깔끔하고 쉬울 수 있다.

직접 JQuery로 변환해 보는 것도 좋을 것이고 차후에 변환할 예정이다.


'Java > 게시판 5: 댓글' 카테고리의 다른 글

1. 댓글 시작하기  (1) 2016.05.15
2. 댓글 쓰기  (2) 2016.05.15
3. 댓글 리스트 / 삭제  (0) 2016.05.15

PMD는 정적인 소스코드 분석 도구로

자세한 설치와 사용법은 한국인터넷진흥원에서 제공하는

"공개SW를 활용한 소프트웨어 개발보안 검증가이드"의 "4장 PMD 사용방법"을 따라 한 후 다음 내용을 읽기 바란다.


게시판 예제를 대상으로 PMD를 실행하면 다음과 같은 결과를 얻게 된다.

화면 하단의 "Violations Overview"에서 오류를 두번 클릭하면 해당 오류 코드로 이동한다.

게시판에서 AvoidCatchingGenericException오류가 발견되었다.

이 오류는 일반적인 예외처리(Exception)을 하지 말라는 것으로

TransactionException 등과 같이 구체적으로 작성하면 된다.


예외 처리에 대한 자세한 설명은 검색해 보거나 이 블로그를 참고하기 바라고

위 결과와 관련하여 한가지를 더 처리한다.

board4.xml의 게시판 글쓰기 처리를 하는 SQL인 insertBoard4에서 사용하는 필드명을 틀리게 작성한다.

여기에서는 BRDTITLE1으로 지정했다.

    <insert id="insertBoard4" parameterType="gu.board4.boardVO" >
           <selectKey resultType="String" keyProperty="brdno" order="BEFORE">
            SELECT IFNULL(MAX(BRDNO),0)+1 FROM TBL_BOARD
        </selectKey>
   
        INSERT INTO TBL_BOARD(BRDNO, BRDTITLE1, BRDWRITER, BRDMEMO, BRDDATE, BRDHIT, BRDDELETEFLAG)
        VALUES (#{brdno}, #{brdtitle}, #{brdwriter}, #{brdmemo}, NOW(), 0, 'N' )
    </insert>

board4.xml

웹 브라우저에서 게시글을 작성한후 저장하면(http://localhost:8080/board/board4Save) 다음과 같은 오류가 발생한다.

그림에 나타난 것과 같이 사용된 SQL문과 경로 정보등이 사용자에게 노출되어 보안에 문제를 야기하게 된다.

따라서 PMD에서는 잡히지 않았지만 예외 처리를 바꿔야 한다.


흔히 사용되지만 다음과 같은 코드는 사용하지 않는 것이 좋다.

try {
    프로그램 코드
} catch(Exception e) {
    e.printStackTrace();
}

printStackTrace대신에 System.out.println(e), throw e 등도 사용하지 않는 것이 좋다.

예제에 사용하지 않았지만

이러한 오류를 오류 메시지를 통한 정보노출이라고 하여 PMD에서는 AvoidPrintStackTrace로 설정하여 오류로 출력해 준다.


즉, 앞서 PMD에서 지적된 Avoid catching generic exceptions과 같이 정리하면

다음과 같이 구체적인 예외 처리를 하고 메세지는 직접 출력하는 것이 좋다.

try {
    프로그램 코드
} catch (BadSqlGrammarException ex) {
    System.out.println("잘못된 SQL 문 사용"+ ex.toString());
}

SQL문을 틀리게 작성했기 때문에 BadSqlGrammarException으로 구체적으로 명시하고

오류메세지를 직접 출력한다.

board4Svc.java의 insertBoard 함수에서 위와 같이 수정하고 실행하면

로그에는 오류가 출력되지만 웹 사이트에서는 오류 없이 리스트로 넘어간다.

(사용자에게 글 저장이 안된다는 연락을 받을 수 있다.)


정리하면 다음과 같이 사용하는 것이 좋다.

BadSqlGrammarException는 일부러 발생시킨 오류이기 때문에 TransactionException으로 처리한다.

아니면 try 문을 사용하지 않고 처리해도 된다.

public void insertBoard(BoardVO param, List<FileVO> filelist, String[] fileno)  throws Exception {
       
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = txManager.getTransaction(def);
       
        try {
            ~~ 생략 ~~
            txManager.commit(status);
        } catch (TransactionException ex) {
            txManager.rollback(status);
            System.out.println("데이터 저장 오류: " + ex.toString());
        }           
    }

Board41Svc.java

오류로 잡히지 않았지만 모든 메소드에  throws Exception(위 코드의 굵은 글자) 가 사용되고 있다.

Java 관련 코드에서 일반적으로 사용하는 것이지만 제거하는 것이 좋다.

앞서 언급된 일반적인 예외처리는 지양하는 것이 좋고, 

예외 처리를 Exception으로 던지고 마는 것이 아니라

try문으로 보다 구체적으로 처리하는 것이 추천되기 때문이다.

따라서 Board41Ctr.java와 Board41Svc.java의 throws Exception를 모두 제거하는 것이 좋다.

ex.toString()도 가급적 사용하지 않는 것이 좋지만

개발시 정확한 오류 메시지를 확인하기 위해 사용하였다.


언급한 예외 처리는 Eclipse에서 기본적으로 생성해 주는 것으로 무심코 넘기는 경우가 많은 데,

최근 공공기관, 대기업 등에서 보안에 대한 관심이 높아지면서

상용 도구를 이용하여 이상의 내용보다 더 많은 내용을 점검하고 있다.

따라서 공개 S/W를 이용하여 이러한 사항들을 미리 처리하는 것이 좋을 것이다.


마지막으로

이러한 조치를 다한 후에 web.xml에서 에러 페이지 처리를 해줘야 한다.

설정 방법은 검색해 보거나 다음 블로그를 참고하면 된다.

http://artrix.tistory.com/383

http://hyeonstorage.tistory.com/98


이러한 조치를 통해 다음 그림과 같이 사용자에게 불필요한 정보가 노출되지 않도록 해야 된다.

다음과 같이 web.xml에서 Exception 오류에 대한 오류 웹 페이지 지정을 처리를 해주면 되고

404, 500등의 오류도 처리해 주는 것이 좋다.

    <!-- error 페이지 -->
    <error-page>
        <exception-type>java.lang.Exception</exception-type>
        <location>/WEB-INF/jsp/common/error.jsp</location>
    </error-page>

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/jsp/common/error404.jsp</location>
    </error-page>

board\src\main\webapp\WEB-INF\web.xml

이상의 내용은 사이트 품질과도 관련되지만

정보 노출의 의미에서는 웹 사이트 보안과도 관련이 있는 내용으로 잘 숙지해서 처리해야 한다.


'Java > 게시판 기타: 품질 등' 카테고리의 다른 글

1. 프로그램 작성 외의 것들  (1) 2016.04.24
2. CheckStyle I - 설치  (0) 2016.04.23
3. CheckStyle II  (0) 2016.04.23
4. FindBugs  (0) 2016.04.23

자세한 사용법은 검색해서 찾아보길 바라고

“개발자가 디자인(CSS)을 알아야 하는 이유”와 관련하여 간단한 사항을 정리한다.

개발자들은 웹 브라우저에서 F12키를 눌러 자바스크립트 디버깅을 많이 쓰고

DOM 탐색기에 대해서는 무심코 넘어가는 경우가 많다.

앞서 언급한 바와 같이 디자인(CSS)는 개발하기 쉽게 해주는 한 방법이 되고

웹 개발에서는 동적으로 HTML 생성을 많이 한다.

제대로 생성되는지, 안 될 경우 쉽게 이유를 파악하고 처리하는 방법을 제공하는 것이 DOM 탐색기이다.


먼저 calendar5.html을 다운받아 실행한다.


이 상태에서 F12키를 누른다.

왼쪽에 보이는 HTML 트리가 DOM 탐색기이고

오른쪽에 보이는 것이 해당 DOM (HTML 태그)에 적용된 스타일(CSS)이 나오게 된다.

HTML은 트리 구조의 계층형으로 구성되는데

태그 옆의 삼각형(▷)을 눌러서 하위(자식) 태그를 볼 수 있다.

다음 그림은 DOM 탐색기에서 1(<div>1</div>)을 선택해서 웹 브라우저에서 1이 선택된 것을 볼 수 있다.

그림 상단의 풍선도움말에 나오듯 옵션이 그렇게 선택되어 있는 상태이다.

왼쪽 옆의 “요소선택”을 하면 웹 브라우저에서 마우스로 선택한 태그가 위 그림처럼 DOM 탐색기에 나타난다.

즉 앞서의 옵션은 DOM 탐색기에서 선택하면 웹브라우저에서 해당하는 태그가

요소 선택은 웹 브라우저에서 태그를 선택하면 DOM 탐색기가 선택되는 방식이다.

다음 그림처럼 요소 선택은 웹 브라우저에서 해당 태그를 선택하고

마우스 오른쪽 버튼을 눌러서 나타나는 컨텍스트 메뉴에서도 실행할 수 있다.


이제 이글의 본론을 이야기 한다.

다음 그림과 같이 태그를 선택하면 DOM 탐색기 오른쪽에 스타일 표시 창에 현재 사용중인 CSS 스타일(Class)이나 직접 입력한 인라인 스타일이 나타난다.

여기서 개발자가 값을 입력해 결과를 바로 확인할 수 있고

잘 모르는 CSS 속성이나 값에 대한 도움을 받을 수 있다.


테스트로 달력의 숫자 정렬을 중앙에서 오른쪽으로 바꾸어 보았다.

CSS 클래스가 calendar 하위에 있는 div (#calendar > div)에 일률적으로 부여되었기 때문에 하나만 수정해도 전체에 적용이 된다.

text-align의 값을 right로 바꾸어 주면 화면에 적용되는 것을 바로 알 수 있다.

이렇게 테스트해 보고 코드를 수정해 주면 된다.


이외에도 그림과 같이 숨겨진 값(hidden 태그)을 확인할 때도 유용하게 사용할 수 있다.


개인적인 경험으로

자바스크립트나 JSP에서 동적으로 HTML을 생성했는데

디자인이 틀어지거나 원하는 데로 되지 않는 경우 이 방법으로 쉽게 원인을 찾고 해결할 수 있었다.

익혀두면 웹 개발에서는 많은 도움이 되니 좀 더 자세한 내용을 찾아보길 바란다.




+ Recent posts