본문 바로가기

BackEnd

naver smartEditor2.8 with javascript(multiple upload, setEditMode)

전직장에서 고객이 원하는 제품을 맞춰서 생산해주는 형태의 (SI) 일을 주로했다.

고객의 다양한 요구를 수용함에따라 네이버 ,다음, 라인, 페이스북, 트위터등.. 정말 많은 오픈소스들을

가져와서 사용했다. 처음엔 새로운 기술을 가져다 쓴다는것이 힘들었지만, 어느순간부터 오픈소스를 신뢰하기 시작하니

모듈이나 API를 쉽게 가져다 쓰기 시작했고 오픈소스 맹신자가 되버린 나를 발견할수 있었다.

회사는 당연하게도 빠른 결과만을원했고 나역시도 결과지향적인 개발자가 되어가고 있었다. 

소프트웨어 공학에서 소프트웨어는 프로그램 및 관련문서로 정의되고 있다. 여느 오픈소스건 API 가이드북이 존재했고

네이버역시 존재했지만, 신입 개발자 입장으로서 네이버의 가이드북은 불친절하게 다가왔다.

다중업로드는 결과지향적으로 기능구현하기에 급급했고, 에디터모드는 자바스크립트를 조금더 알게된 상태에서 해결한 문제이다.

다중업로드를 자바스크립트에서 가능하게 수정한것은 내가 삽질한 결과물이고, 어디에도 포스팅되있지않지만

(JSP는 티스토리 포스팅글이 있습니다.)

효율성이나 ,성능 ,자바스크립트가 가진 특성등을 놓고본다면 결코 좋은 코드는 아니며 당시 나로서 이게 최선이였다는 생각이다.

어쩌면, 나처럼 “자바스크립트는 제이쿼리나 대충 다룰줄 알면 되는거 아닌가?”라는  오해로 시작해서

Node.js 혹은 FullStack(Mean stack) 개발자로 개발일을 시작한 자알못(자바스크립트를 잘 알지 못함) 분들에게는 필요할수도 있겠구나

라는 생각이 들어서 포스팅을 하게되었다.

사설이 길었다.

-블로그를 보시는분들에 대다수가 구글링으로 들어와서 필요한정보만보고 cmd+w (또는 ctrl+w)  하는경우가 대부분일꺼라 생각 합니다.

 저역시도 끊임없이 배우는입장이고 여전히 자바스크립트를 잘 알지 못합니다. 비하목적은 없으니 오해 마시길~

자바스크립트 기반 서버에서 네이버 스마트 에디터 다중업로드 구현

스마트에디터를 오픈소스로 붙일경우 jindo 컴포넌트와 sample 파일등으로 스마트에디터의 구조를 파악하게 되는데

업로드 커스터마이징을 특별히 하지않는다면

sample\photo_uploader 에 있는 attach_photo.js 를 수정하여 파일업로드를 구현하는 경우가 많을 것이다.

기존소스

  function html5Upload() {    
        var tempFile,
            sUploadURL;

        sUploadURL= 'file_uploader_html5.php';  //upload URL

        //파일을 하나씩 보내고, 결과를 받음.
        for(var j=0, k=0; j < nImageInfoCnt; j++) {
            tempFile = htImageInfo['img'+j];
            try{
                if(!!tempFile){
                    //Ajax통신하는 부분. 파일과 업로더할 url을 전달한다.
                    callAjaxForHTML5(tempFile,sUploadURL);
                    k += 1;
                }
            }catch(e){}
            tempFile = null;
        }
    }
    function callAjaxForHTML5 (tempFile, sUploadURL){
        var oAjax = jindo.$Ajax(sUploadURL, {
            type: 'xhr',
            method : "post",
            onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
                var sResString = res._response.responseText;
                if (res.readyState() == 4) {
                    if(sResString.indexOf("NOTALLOW_") > -1){
                        var sFileName = sResString.replace("NOTALLOW_", "");
                        alert("이미지 파일(jpg,gif,png,bmp)만 업로드 하실 수 있습니다. ("+sFileName+")");
                    }else{
                        //성공 시에  responseText를 가지고 array로 만드는 부분.
                        makeArrayFromString(res._response.responseText);
                    }
                }
            },
            timeout : 3,
            onerror :  jindo.$Fn(onAjaxError, this).bind()
        });
        oAjax.header("contentType","multipart/form-data");
        oAjax.header("file-name",encodeURIComponent(tempFile.name));
        oAjax.header("file-size",tempFile.size);
        oAjax.header("file-Type",tempFile.type);
        oAjax.request(tempFile);
    }

다음과 같은 코드가 구현되있는것을 볼수있다. 진도 컴포넌트는 함수 호출시 $를 사용하기때문에 jQuery 와 충돌 가능성이 있다

그래서 구글링을 하다보면 진도 컴포넌트와 제이쿼리를 같이 사용해야 한다면 제이쿼리를 $ 가 아닌 jQuery 로 호출해서 사용할것을

권고하는 포스팅을 찾아볼수 있을것이다.

php 파일을 불러와서 업로드 하는방식을 취하고 있는데 노드서버 기반으로는 불가능 하다. 그래서 callAjaxForHTML5 함수를 수정했다.

비동기 통신을 직접 구현해서 폼을 생성하고 , 이미지를 업로드하는 방식인데 컨텐츠 타입을 contentType 으로 정의하면 에러가 발생된다.

여기에 대한 문제점은 http://dev.naver.com/projects/smarteditor/issue/55985 참고하기 바란다.

노드서버에 싱글스레드(이벤트기반 루프) 방식때문인지 , 진도 컴포넌트 때문인지 원인은 불명확하지만 타임 스케쥴링을

하지않으면 다중 업로드 사진이 모두 같은 사진으로 나오는 문제가 발생되었다.

이부분에 대해선 잉여력과 x신력이 충만해지면 찾아볼 예정이다. (..그런데 내가 네이버 오픈소스를 뜯어볼 기회가 있을까 싶다..)

sleep 함수를 추가 구현해서 해결완료

수정후


    function html5Upload() {
        /* 로딩중 이미지 출력 */
        document.getElementById('loading').style.display = 'block';

        var tempFile ;
        var sUploadURL= '/content_img_upload';  //upload URL

        setTimeout(function htmlStarted (){
            //파일을 하나씩 보내고, 결과를 받음.
            for(var j=0; j < nImageInfoCnt; j++) {
                tempFile = htImageInfo['img'+j];
                try{
                    if(!!tempFile){
                        //Ajax통신하는 부분. 파일과 업로더할 url을 전달한다.
                        //console.log(j);
                        //시간지연을 하지않을경우 비동기식이라 2번재사진부터 이미지출력이제대로안됨.
                        sleep(1000); //1초
                        callAjaxForHTML5(tempFile,sUploadURL);
                    }

                }catch(e){}
                tempFile = null;
            }
        },2000);
    }


    function sleep(num){    //[1/1000초]
        var now = new Date();
        var stop = now.getTime() + num;
        while(true){
            now = new Date();
            if(now.getTime() > stop)return;
        }
    }

    function callAjaxForHTML5 (tempFile, sUploadURL){
        var request = new XMLHttpRequest();
        // POST to httpbin which returns the POST data as JSON
        request.open('POST', sUploadURL, /* async = */ false);

        var formData = new FormData();
        //formData.append('key1', 'value1');
        //formData.append('key2', 'value2');
        formData.append("content-type","multipart/form-data"); // contentType 으로 정의하면 에러발생.
        formData.append("file-name",encodeURIComponent(tempFile.name));
        formData.append("file-size",tempFile.size);
        formData.append("file-Type",tempFile.type);
        formData.append('file',tempFile);
        request.send(formData);
        var sResString =  request.response ;

        if(sResString.indexOf("NOTALLOW_") > -1){
            var sFileName = sResString.replace("NOTALLOW_", "");
            alert("이미지 파일(jpg,gif,png,bmp)만 업로드 하실 수 있습니다. ("+sFileName+")");
        }else{
            makeArrayFromString(sResString);
        }

    }//html5 upload

꼭 네이버 스마트 에디터를 이용한 다중업로더를 구현해야 한다면 임시방편으로 써먹을만 한것같다.. 지금도 자알못 이지만

이소스를 구현할땐 심각한 자알못(자알못:자바스크립트를 잘알지 못함)

스마트 에디터 에디트 모드 제어 하기

이 이슈는 친한 동생의 질문으로 찾아보게 되었다. 스마트 에디터 오른쪽 하단부에는 에디터 모드를 선택하는 3가지의 탭이 존재한다

HTML , TEXT ,WYSNG 동생은 이상태값을 디비에 저장하는것과 글수정시 불러와서 상태를 셋 하는 기능을 구현하고 싶다 했다.

처음엔 단순한 방식으로 탭을 disable 시켜서 css 로 페이크 탭을 붙여넣으라는 식으로 조언했지만 그게 힘들게되어서

궁금하기도하고.. 결국 진도 컴포넌트와 스마트 에디터 게시판을 검색하기 시작했다.

oEditors.getById["ir1"].getEditingMode(); 초기 스마트 에디터를 oEditors 배열에 담는데 여기서 프로퍼티를 뽑아오면된다.

이렇게 하면 현재 상태가 text 탭을 클릭하였는지 HTML 을 클릭하였는지 문자열로 값을 가져올수 있다.

그리고 초기값 설정은 에디터 로드시에 SE_EditingAreaManager 에서 sDefaultEditingMode : 'TEXT' 이런식으로 정의해주면된다.


var oEditors = [];

nhn.husky.EZCreator.createInIFrame({
   oAppRef: oEditors,
   elPlaceHolder: "notice_cont",
   sSkinURI: "../smarteditor/SmartEditor2Skin.html",   
   htParams : {
      bUseToolbar : true,            // 툴바 사용 여부 (true:사용/ false:사용하지 않음)
      bUseVerticalResizer : true,      // 입력창 크기 조절바 사용 여부 (true:사용/ false:사용하지 않음)
      bUseModeChanger : true,         // 모드 탭(Editor | HTML | TEXT) 사용 여부 (true:사용/ false:사용하지 않음)
      //aAdditionalFontList : aAdditionalFontSet,      // 추가 글꼴 목록
      fOnBeforeUnload : function(){
          clearHTML("");
         //alert("완료!");
      },
      SE_EditingAreaManager : { 
        sDefaultEditingMode : 'TEXT'
                              // - Editor 모드 : WYSIWYG - HTML 모드 : HTMLSrc - TEXT 모드 : TEXT 
            } 
         }
   }, //boolean



   fOnAppLoad : function(){
      //예제 코드
      //oEditors.getById["ir1"].exec("PASTE_HTML", ["로딩이 완료된 후에 본문에 삽입되는 text입니다."]);
   },
   fCreator: "createSEditor2"
});

 

부디 나같은 시행착오를 겪지 않길 바란다.

그리고 내가 작성한 포스팅이 도움이 되었다면 이글도 꼭 읽어보길 바란다.

http://www.bloter.net/archives/253447