IT정보뉴스

복잡한 코딩 필요 없는 '노코드 앱'이 떠오른다

코딩 없이 업무용 모바일앱을 만들 수 있는 마이크로소프트의 파워앱스IT 기술 고도화와 업무 심화에 따라 애널리스트, 연구원, 사무직원 등 각 직군에 특화된 애플리케이션의 수요가 늘고 있다. 이와 함께 간단한 코딩 작업만으로 직접 애플리케이션을 만들 수 있는 로우코드(low code), 또는 아예 코딩이 필요하지 않은 노코드(no code) 서비스가 대안으로 떠오르고 있다.실제로 주요 IT 기업을 중심으로 로우코드 또는 노코드 서비스를 강화하고 있다. 마이크로소프트는 전문개발자가 아닌 직원이 업무용 앱을 만들 수 있는 '파워앱스'를 서비스 중이며 구글은 지난 1월 노코드 앱 개발 플랫폼을 인수하며 경쟁력을 확보하고 있다.국내에서도 소프트파워가 '스마트메이커'라는 애플리케이션 저작 서비스를 제공 중이다. 스마트메이커는 한글로 스크립트를 작성할 수 있는 등 국내 기업 맞춤 서비스로 시장을 공략하고 있다.IT 자문기관 가트너도 지난해 2020년 10대 전략 기술 동향 중 하나로 노코드, 로우코드를 통해 추가적인 훈련을 받지 않아도 앱 개발 등 전문적인 업무를 할 수 있는 '전문성의 민주화'를 꼽았다.다만 노코드는 특성상 복잡한 업무에 도입하기 어렵고 여러 사람이 각자 애플리케이션을 제작하는 만큼 관리보수가 더욱 중요해지고 로코드와 노코드 도구 등 플랫폼에 종속될 수 있다는 점이 문제점으로 지적된다.■ 개발자 부담 줄이고 빠르고 정확한 개발 지원노코드는 사무직원 등 프로그래밍 교육을 받지 않은 사람도 원하는 애플리케이션을 직접 만들어 사용할 수 있도록 간단한 구조와 사용법이 특징이다. 사전에 마련된 템플릿을 결합해 원하는 서비스를 구현하는 식으로 이뤄져 있다.직접 만드는 만큼 빠르고 정확하게 원하는 기능을 구현할 수 있을 뿐 아니라 업무에 적용하고 분석, 평가, 개선까지 이뤄지는 주기가 짧아 애자일 개발 방식에 적합하다는 평가를 받고 있다.더불어 전문 개발자는 줄이고 시스템 구축 등 보다 중요한 업무에 집중할 수 있는 만큼 업무 효율도 높일 수 있다는 장점이 있다.현재 로우코드로 개발된 애플리케이션은 영수증 분류, 데이터 처리 등 간단한 업무에 주로 활용되며 점차 사용 범위를 넓혀가고 있다.소프트파워의 이수정 팀장은 중소 개발사 및 스타트업을 중심으로 빠르게 확장 중이라고 밝혔다. 비용 등의 문제로 프로그래머를 영입하기 어려운 중소기업도 간단한 사용법을 익힌 후 원하는 애플리케이션을 만들 수 있기 때문이다.이수정 팀장은 “많은 중소기업은 외주 개발사를 통해 애플리케이션을 만들더라도 의사소통이 제대로 이뤄지지 않아 원하는 기능이 제대로 구현되지 않거나 개발 기간이 길어지고 유지보수를 지원하지 않아 불편을 겪는 경우가 많았다”며 “하지만 노코드 도구를 활용하면 사내에서 직접 해결할 수 있어 문의가 늘고 있다”고 설명했다.업계 한 개발자는 “사내에서 요청하는 애플리케이션이 늘어나면서 개발팀만으로 이를 해결하기 버거웠다”며 “노코드 도구를 활용하면서 개발 요청이 줄면서 보다 중요한 업무에 집중할 수 있게 됐다”고 말했다.마이크로소프트 관계자는 “해외 시장을 중심으로 노코드에 대한 관심과 이용률이 늘어나고 있는 것으로 파악하고 있다”며 “파워앱스를 선보인 본사에서도 노코드 시장을 주요 사업 중 하나로 생각하는 것 같다”고 말했다.소프트파워의 스마트메이커■ 노코드관리 어렵고 보안 취약 위험노코드는 많은 장점이 있지만 아직 단점도 적지 않다.우선 개발팀 등 전문팀이 만드는 것이 아니라 실무자 각자가 만들어 사용하는 만큼 수많은 애플리케이션 관리가 어렵다. 관리자가 기업 내에서 사용 중인 애플리케이션을 모두 파악하지 못한다면 어디에 보안취약점이 있는 지 파악하지 못하는 섀도우 IT 현상이 발생할 가능성이 크다.또 사내에서 애플리케이션 정보가 제대로 공유되지 않을 경우 비슷한 기능을 가진 여러 개의 애플리케이션이 동시에 작동해 비용과 효율성을 모두 낮출 수 있다.그래서 노코드를 효율적으로 사용하기 위해선 실무자가 만든 애플리케이션 정보를 문서화고 사용 중인 모든 애플리케이션을 관리할 수 있는 플랫폼이 필요하다.노코드는 또 업무에 필요한 간단한 기능을 빠르게 구현하는 것을 목적으로 하고 있어서 복잡한 계산식이 필요하거나 새로운 기능을 만드는 것은 오히려 비효율적이다.더불어 직접 내부에 서비스를 구축하는 것이 아닌 만큼 외부 플랫폼에 종속될 수 있다는 점도 문제점으로 지적되고 있다.

최근 등록된 자바스크립트 소스

사진 설명
사진

Javascript WYSIWYG HTML editor http://naver.github.io/smarteditor2/

SmartEditor2OverviewSmartEdtitor™ 는 JavaScript로 구현된 웹 기반의 WYSIWYG 편집기입니다.WYSIWYG 모드 및 HTML 편집 모드와 TEXT 모드를 제공하고, 자유로운 폰트 크기 설정 기능, 줄 간격 설정 기능, 단어 찾기/바꾸기 기능 등 편집에 필요한 다양한 기능을 제공하므로 사용자들은 SmartEdtitor™를 사용하여 쉽고 편리하게 원하는 형태의 글을 작성할 수 있습니다.또한, SmartEdtitor™의 구조는 기능을 쉽게 추가할 수 있는 플러그인 구조로 되어 있어 정해진 규칙에 따라 플러그인을 만들기만 하면 됩니다.User Guide사용자 가이드에서는 SmartEditor2 의 특징과 기능을 소개합니다.또한, 설치 방법과 기능의 추가/삭제 방법도 알 수 있습니다.사용자 가이드Demo아래 데모페이지 에서는 SmartEditor2.0 이 제공하는 다양한 기능을 바로 체험해 볼 수 있습니다.SmartEditor2 Demo 바로가기Supported BrowsersInternet Explorer 8.x 이상Firefox 3.5 이상Chrome 4.0 이상Safari 4.0 이상LicenseSmartEditor2 is released under the LGPL v2.1.LGPL v2.1 (한국어)Third-party librariesThe following third-party libraries are used :Jindo - https://github.com/naver/jindojs-jindo: for DOM/Event Handling, OOP style codeJindo Component - https://github.com/naver/jindojs-jc: for UI Control (DragArea, LayerManager, LazyLoading)Read MoreCHANGELOGTODO List설치시 발생하는 버그 또는 질문은 "이슈" 게시판을 이용해주세요.SmartEditorBasic 0.3.X 버전이 궁금하시다면...구 SmartEditorBasic 0.3.X 버전 도움말 보기

사진

[JSP] 스마트에디터(smarteditor)의 싱글/멀티 이미지업로드하기

참고] 관련포스트 [jsp] 네이버의 스마트에디터(SmartEditor) 적용하기 스마트에디터에서 사진을 업로드 해보자. 각 브라우저별로 사진 버튼 클릭시 업로드 기능에 대한 유형이 조금식 틀려진다.IE11 미만 버전에서는  싱글 멀티파트 업로드화면을 출력시키고IE11, 크롬, 사파리 등에서는 드래그앤드롭기능으로 멀티파일 업로드(드래그앤드롭) 폼을 출력시킨다.싱글업로드 화면: 멀티플업로드 화면(드래그앤드롭이용)JSP 환경에서 파일 처리를 위해 다음 라이브러리를 WebContent\WEB-INF\lib\ 폴더에 넣자.  (첨부파일 참고)commons-fileupload-1.2.2.jarcommons-io-1.4.jar WebContent/SE2/photo_uploader/popup 디렉토리 내에 있는 파일을 다음과 같이 수정해주자.※ 스마트에디터 가이드 참고 : http://jindo.dev.naver.com/smarteditor/user_guide/photo_uploader.html: 사진 퀵 업로더에서 사용하는 HTML 팝업 페이지다음 그림과 같이 form의 action속성을 제거 attach_photo.js : photo_uploader.html 파일에서 사용하는 JavaScript 파일. 사진 퀵 업로더를 설치할 때 코드를 반드시 수정해야 한다.변경함수 : callFileUploader(), html5Upload()callFileUploader() : 싱글파일 업로드 , HTML5를 지원하지 않는 브라우저에서 사용html5Upload() : 멀티플 업로드, HTML5를 지원하는 브라우저에서 사용먼저 callFileUploader() 함수에서 다음 속성을 현재 자신의 환경에 맞게 수정하자sUrl : 사진을 업로드할 서버의 경로 sCallback : 업로드 이후에 iframe이 redirect될 콜백페이지의 주소 다음으로 html5Upload() 함수에서 sUploadURL을 변경하자. 필요한 JSP파일을 다음과 같이 생성하자.file_uploader.jspfile_uploader_html5.jsp[file_uploader.jsp] <%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%>    <%@page import="java.io.FileOutputStream"%><%@page import="java.io.OutputStream"%><%@page import="java.io.InputStream"%><%@page import="java.util.UUID"%><%@page import="java.text.SimpleDateFormat"%><%@page import="java.io.File"%><%@page import="org.apache.commons.fileupload.FileItem"%><%@page import="java.util.List"%><%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%><%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%> <%String return1="";String return2="";String return3="";String name = ""; if (ServletFileUpload.isMultipartContent(request)){    ServletFileUpload uploadHandler = new ServletFileUpload(new DiskFileItemFactory());    uploadHandler.setHeaderEncoding("UTF-8");    List<FileItem> items = uploadHandler.parseRequest(request);    for (FileItem item : items) {        if(item.getFieldName().equals("callback")) {            return1 = item.getString("UTF-8");        } else if(item.getFieldName().equals("callback_func")) {            return2 = "?callback_func="+item.getString("UTF-8");        } else if(item.getFieldName().equals("Filedata")) {            if(item.getSize() > 0) {                      name = item.getName().substring(item.getName().lastIndexOf(File.separator)+1);                String filename_ext = name.substring(name.lastIndexOf(".")+1);                filename_ext = filename_ext.toLowerCase();                String[] allow_file = {"jpg","png","bmp","gif"};                int cnt = 0;                for(int i=0; i<allow_file.length; i++) {                    if(filename_ext.equals(allow_file[i])){                        cnt++;                    }                }                if(cnt == 0) {                    return3 = "&errstr="+name;                } else {                                         //파일 기본경로                    String dftFilePath = request.getSession().getServletContext().getRealPath("/");                    //파일 기본경로 _ 상세경로                    String filePath = dftFilePath + "SE2" + File.separator +"upload" + File.separator;                                         File file = null;                    file = new File(filePath);                    if(!file.exists()) {                        file.mkdirs();                    }                                         String realFileNm = "";                    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");                    String today= formatter.format(new java.util.Date());                    realFileNm = today+UUID.randomUUID().toString() + name.substring(name.lastIndexOf("."));                                         String rlFileNm = filePath + realFileNm;                    ///////////////// 서버에 파일쓰기 /////////////////                     InputStream is = item.getInputStream();                    OutputStream os=new FileOutputStream(rlFileNm);                    int numRead;                    byte b[] = new byte[(int)item.getSize()];                    while((numRead = is.read(b,0,b.length)) != -1){                        os.write(b,0,numRead);                    }                    if(is != null) {                        is.close();                    }                    os.flush();                    os.close();                    ///////////////// 서버에 파일쓰기 /////////////////                                         return3 += "&bNewLine=true";                                // img 태그의 title 옵션에 들어갈 원본파일명                    return3 += "&sFileName="+ name;                    return3 += "&sFileURL=/smarteditorSample/SE2/upload/"+realFileNm;                }            }else {                  return3 += "&errstr=error";            }        }    }}response.sendRedirect(return1+return2+return3); %>Colored by Color Scriptercs[file_uploader_html5.jsp] <%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%>    <%@page import="java.io.*"%><%@page import="java.util.UUID"%><%@page import="java.text.SimpleDateFormat"%> <%    //파일정보    String sFileInfo = "";    //파일명을 받는다 - 일반 원본파일명    String filename = request.getHeader("file-name");    //파일 확장자    String filename_ext = filename.substring(filename.lastIndexOf(".") + 1);    //확장자를소문자로 변경    filename_ext = filename_ext.toLowerCase();     //이미지 검증 배열변수    String[] allow_file = { "jpg", "png", "bmp", "gif" };     //돌리면서 확장자가 이미지인지     int cnt = 0;    for (int i = 0; i < allow_file.length; i++) {        if (filename_ext.equals(allow_file[i])) {            cnt++;        }    }     //이미지가 아님    if (cnt == 0) {        out.println("NOTALLOW_" + filename);    } else {        //이미지이므로 신규 파일로 디렉토리 설정 및 업로드           //파일 기본경로        String dftFilePath = request.getSession().getServletContext().getRealPath("/");        //파일 기본경로 _ 상세경로        String filePath = dftFilePath + "SE2" + File.separator + "multiupload" + File.separator;        File file = new File(filePath);        if (!file.exists()) {            file.mkdirs();        }        String realFileNm = "";        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");        String today = formatter.format(new java.util.Date());        realFileNm = today + UUID.randomUUID().toString() + filename.substring(filename.lastIndexOf("."));        String rlFileNm = filePath + realFileNm;        ///////////////// 서버에 파일쓰기 /////////////////         InputStream is = request.getInputStream();        OutputStream os = new FileOutputStream(rlFileNm);        int numRead;        byte b[] = new byte[Integer.parseInt(request.getHeader("file-size"))];        while ((numRead = is.read(b, 0, b.length)) != -1) {            os.write(b, 0, numRead);        }        if (is != null) {            is.close();        }        os.flush();        os.close();        ///////////////// 서버에 파일쓰기 /////////////////         // 정보 출력        sFileInfo += "&bNewLine=true";            sFileInfo += "&sFileName=" + filename;            sFileInfo += "&sFileURL=/smarteditorSample/SE2/multiupload/"+realFileNm;        out.println(sFileInfo);    }%>Colored by Color Scriptercs단일파일 업로드 테스트 : 멀티파일 업로드 테스트 : [출처] [JSP] 스마트에디터(smarteditor)의 싱글/멀티 이미지업로드하기 |작성자 자바킹

사진

[JSP] naver SmartEditor2 이미지 첨부 기능 (수정 보완)

https://zero-gravity.tistory.com/171정말 불친절한 네이버가이드 때문에 이걸 하느라고 얼마나 고생했는지 모른다. 전부 php로 되어 있어서 이걸 jsp로 바꾸고 해야 하는데, 다른 사람들이 블로그에 올려놓은 것들을 보니 저마다 조각조각이라 어찌할 방도가 없었다. 결국 회사 선배의 도움으로 해결..   혹시라도 나같이 jsp 스마트에디터 이미지 첨부를 미친듯이 구글링하고 있을 불쌍한 중생들을 위해 아래 파일과 간단한 방법을 올린다. se2.zip   먼저 첨부한 파일을 다운로드 받아서 폴더째 서버에 복사 붙여넣기 한다.   그리고 cos.jar파일을 lib에 추가해준다. 이 글 참조 → http://zero-gravity.tistory.com/168    (MultipartRequest와 DefaultFileRenamePolicy를 사용하기 때문..)   나머지는 다른 환경에서 작동하도록 첨부한 파일들에서 몇몇 설정만 변경해주면 된다.se2 > photo_uploader > popup > file_uploader.jsppath를 각자의 "서버 안에 있는 폴더"로 경로를 변경해준다.에를 들어, 프로젝트의 WebContent 안에 있는 uploadFolder를 경로로 설정하고 싶다면,아래와 같이 변경해줘야 한다. 각자 경로에 맞춰서.(무슨 말인지 알 거다.)String path = "D:/folder/workspace/projectName/WebContent/uploadFolder";path는 스마트에디터로 이미지를 첨부했을 시에 업로드 될 경로다.참고: 만약 path를 request.getSession().getServletContext().getRealPath("/") + File.separator + "저장될 폴더" 이런 식으로 써주면 폴더를 새로고침 하지 않아도 이미지를 즉각적으로 확인할 수 있다. 이 때 이미지가 저장되는 곳은 metadata쪽이다.   그리고나서,,?1234567891011121314151617181920212223242526272829303132333435363738<!-- Smart Editor --><script type="text/javascript" src="<%=request.getContextPath()%>/se2폴더를 붙여넣기 한 곳의 경로/se2/js/HuskyEZCreator.js" charset="utf-8"></script><script type="text/javascript" src="<%=request.getContextPath()%>/se2폴더를 붙여넣기 한 곳의 경로/se2/photo_uploader/plugin/hp_SE2M_AttachQuickPhoto.js" charset="utf-8"></script>  <!-- Smart Editor --><script type="text/javascript"> var oEditors = [];nhn.husky.EZCreator.createInIFrame({    oAppRef: oEditors,    elPlaceHolder: "textAreaContent",    sSkinURI: "<%=request.getContextPath()%>/se2폴더를 붙여넣기 한 곳의 경로/se2/SmartEditor2Skin.html",    fCreator: "createSEditor2"}); //‘저장’ 버튼을 누르는 등 저장을 위한 액션을 했을 때 submitContents가 호출된다고 가정한다.function submitContents(elClickedObj) {    // 에디터의 내용이 textarea에 적용된다.    oEditors.getById["textAreaContent"].exec("UPDATE_CONTENTS_FIELD", [ ]);     // 에디터의 내용에 대한 값 검증은 이곳에서    // document.getElementById("textAreaContent").value를 이용해서 처리한다.      try {        elClickedObj.form.submit();    } catch(e) {         }} // textArea에 이미지 첨부function pasteHTML(filepath){    var sHTML = '<img src="<%=request.getContextPath()%>/path에서 설정했던 경로/'+filepath+'">';    oEditors.getById["textAreaContent"].exec("PASTE_HTML", [sHTML]);} </script>   스마트에디터를 사용할 jsp페이지에 위와 같이 자바스크립트를 삽입한다.   textarea 태그의 id 값을 자바스크립트에 넣었던 id와 같게 해주는 것도 잊지 말자.?1<textarea style="width: 100%" rows="10" name="content" id="textAreaContent" cols="80"></textarea>   다음은 설정을 모두 끝내고 스마트에디터를 실행했을 시의 화면이다.우측 상단에 있는 "사진"을 클릭.사진 첨부하기 창이 뜰 것이다.이미지를 첨부하고 확인.그럼 이렇게 이미지가 X박스 표시되어 나온다.정상적이다. 왜냐하면 이클립스에서 새로고침을 하지 않았기 때문이다.실제로 본 서버에 올리면 잘 돌아간다.그럼 이미지가 올라갔는지 어떻게 확인하나?일단 이클립스에서 이미지가 올라간 폴더에 새로고침을 해주고(이때 올렸던 이미지가 추가됐다면 성공한 거다),스마트에디터의 HTML로 가서 내용을 복사한다.스마트에디터를 다시 실행하고, HTML로 가서 복사한 내용을 붙여넣기한다.Editor로 돌아오면 짠~!   글쓰기를 완료하지 않아도 이미지 파일 자체는 서버에 업로드 된다.   글쓰기를 완료할 경우, DB에는 이미지 파일 자체가 올라가는 게 아니라 아까 HTML영역에서 복사했던 그 내용이 올라간다.   이런 데에 시간을 허비하는 건 너무 아깝지 않은가.   어짜피 오픈소스 갖다 쓰는 건데,, 그냥 대충 어떻게 돌아가겠구나 정도만 알면 된다고 본다.   이게 뭐라고.. 혼자만 알려고 꼭꼭 숨기는 사람들 보면 참....   물론 고생 더럽게 해서 알려주기 아깝겠지만, 그런 사람은 더럽게 이기적인 사람이라고 생각한다. ㅡ.ㅡ..;   인류가 이렇게 발전할 수 있었던 데에는 지식의 전달과 축적이 있었기에 가능했던 것 아닌가.    공유하는 세상이 아름다운 세상이다. 크~