웹프로그램을 만들다보면 그리드 시스템이 필요할떄가 있습니다. 

테이블태그를 이용한 코드 작성도 나쁘진 않지만 JQGRID를 사용해보고 개발의 편리성에 GRID라이브러리를 사용하게 되었습니다. 

JQGRID를 사용해 보았으니 최신버전은 유료라이센스로 바뀌었고 4.0대 버전을 무료로 사용할수 있었습니다. 

대체할 라이브러리를 검색을 하다 발견한 JSGRID를 사용을 해보게 되었습니다. 

JQGRID라이브러리의 예제 소스는 아래에서 다운받거나 구경할수 있습니다.

http://js-grid.com/demos/

 

Demos

 

js-grid.com

저는 JSGRID 라이브러리를 스프링에 적용하는 것을 정리합니다. 

라이브러리 로드 파일에 라이브러리경로를 넣어줍니다. 

    <link rel="stylesheet" type="text/css" href="../css/jsgrid.css" />
    <link rel="stylesheet" type="text/css" href="../css/theme.css" />
    
    <script src="../src/jsgrid.core.js"></script>    
    <script src="../src/jsgrid.load-indicator.js"></script>
    <script src="../src/jsgrid.load-strategies.js"></script>
    <script src="../src/jsgrid.sort-strategies.js"></script>
    <script src="../src/jsgrid.validation.js"></script>
    <script src="../src/jsgrid.field.js"></script>
    <script src="../src/fields/jsgrid.field.text.js"></script>
    <script src="../src/fields/jsgrid.field.number.js"></script>
    <script src="../src/fields/jsgrid.field.select.js"></script>
    <script src="../src/fields/jsgrid.field.checkbox.js"></script>
    <script src="../src/fields/jsgrid.field.control.js"></script>

각자의 경로에 맞추어 넣어주면 됩니다. 

jsgrid를 선언하는 부분은 이런식으로 나와 있습니다. 

 $("#jsGrid").jsGrid({
                height: "70%",
                width: "100%",
                filtering: true,
                editing: true,
                inserting: true,
                sorting: true,
                paging: true,
                autoload: true,
                pageSize: 15,
                pageButtonCount: 5,
                deleteConfirm: "Do you really want to delete the client?",
                controller: db,
                fields: [
                    { name: "Name", type: "text", width: 150, validate: "required" },
                    { name: "Age", type: "number", width: 50, validate: { validator: "range", param: [18,80] } },
                    { name: "Address", type: "text", width: 200, validate: { validator: "rangeLength", param: [10, 250] } },
                    { name: "Country", type: "select", items: db.countries, valueField: "Id", textField: "Name",
                        validate: { message: "Country should be specified", validator: function(value) { return value > 0; } } },
                    { name: "Married", type: "checkbox", title: "Is Married", sorting: false },
                    { type: "control" }
                ]
            });

나누어 보겠습니다. 

위부분을 인수로 받아 생성하는 코드로 변경을 합니다.

//그리드 생성.
function initGrid(grid_id,in_fields,in_paging,in_pageSize,in_pageButtonCount,in_filtering,in_inserting,in_editing,in_sorting,in_autoload
		,now_pager,now_table_custom,now_db
		,onrowClass,inonItemInserting,inonItemUpdating)
{
	jsGrid.locale("ko");
	grid_id.jsGrid({
		
		noDataContent: "데이터가 없습니다.",
		deleteConfirm: "삭제합니다 정말입니까?",
		pagerFormat: " {prev} {pages} {next}",
		pagePrevText: "&laquo;",
		pageNextText: "&raquo;",
		pageFirstText: "처음",
		pageLastText: "마지막",
		loadMessage: "잠시 기다려주십시오 .",
		invalidMessage: "입력 된 데이터가 잘못되었습니다.",
		
        height: "auto",
        width: "100%",
        filtering: in_filtering,
        editing: in_editing,
        inserting: in_inserting,
        sorting: in_sorting,
        paging: in_paging,
        pageLoading: true,
        autoload: in_autoload,
        pageSize: in_pageSize,
        pageButtonCount: in_pageButtonCount,
        controller: now_db,
        fields: in_fields,
        rowClass: onrowClass,
        onItemInserting: inonItemInserting,
        onItemUpdating: inonItemUpdating,
        onItemInserted:function(){grid_id.jsGrid("loadData");},
    });
	now_table_custom.on("click", function() {
        var $cb = $(this);
        grid_id.jsGrid("option", $cb.attr("id"), $cb.is(":checked"));
    });
    now_pager.on("change", function() {
        var page = parseInt($(this).val(), 10);
        grid_id.jsGrid("option", "pageSize", page); 
        grid_id.jsGrid("refresh");
    });
}

jsgrid로  한페이지에 다수의 그리드를 생성 관리할수 있게 되었습니다. 

<div id="jsGrid"></div> //기본 예제 그리드 id

입력되는 값들을 기본 디폴드 값으로 분리한 선언부를 만들어 놓습니다. 

//조각 조각 입력해서 그리드 생성하기..
var sms_js_size = [];
sms_js_size["width"]="100%";
sms_js_size["height"]="auto";
var sms_basic_setting= [];
sms_basic_setting["autoload"]=true; //화면 로딩시 데이터를 불러옴.
sms_basic_setting["confirmDeleting"]=true; //삭제시 정말 지울건지 물어봄. 
sms_basic_setting["pagerContainer"] = null; //페이지 이동 위치 .. 
sms_basic_setting["pageIndex"] = 1; //시작페이지 위치.. 기본 1페이지..
sms_basic_setting["pageSize"] = 15; //화면에 나타날 기본 줄수... 15개를 기본으로한다. 
sms_basic_setting["loadIndication"] = true; // 제어기 조작 실행 중로드 표시를 표시할지 여부를 지정하는 부울 값.
sms_basic_setting["loadIndicationDelay"]= 500; //로드 표시를 표시하기 전의 지연을 ms 단위로 지정하는 정수 값
sms_basic_setting["loadShading"] = true; //표시를로드하는 동안 격자 내용 위에 오버레이 (셰이더)를 표시할지 여부를 지정하는 부울 값?
sms_basic_setting["updateOnResize"] = true;//윈도우 크기 변경 이벤트에서 격자를 새로 고칠 지 여부를 지정하는 부울 값
var sms_in_ting = [];
sms_in_ting["heading"]= true; //격자 머리글 표시 여부를 지정합니다.
sms_in_ting["filtering"]= true; // 필터 행 표시 여부를 지정
sms_in_ting["inserting"]= true; // 행 삽입 여부를 지정합니다.
sms_in_ting["editing"]= true; //편집이 허용되는지 여부를 지정합니다.
sms_in_ting["selecting"]= true; //마우스를 올리면 표 행을 강조 표시할지 여부를 지정합니다.
sms_in_ting["sorting"]= true; // 정렬 허용 여부를 지정합니다.
sms_in_ting["paging"]= true; // 페이지별로 데이터를 표시할지 여부
sms_in_ting["pageLoading"]= true; //부울 값은 페이지별로 데이터를로드할지 여부를 지정
var sms_in_row_function = [];
sms_in_row_function["rowClass"]=function (item, itemIndex)  {};
sms_in_row_function["rowClick"]=function ( args ) {};
sms_in_row_function["rowDoubleClick"]=function ( args ) {};
sms_in_row_function["invalidNotify"]=function ( args ) {};
var sms_in_callback = [];
sms_in_callback["onDataLoading"]=function ( args ) {};
sms_in_callback["onDataLoaded"]=function ( args ) {};
sms_in_callback["onError"]=function ( args ) {};
sms_in_callback["onInit"]=function ( args ) {};
sms_in_callback["onItemInserting"]=function ( args ) {};
sms_in_callback["onItemInserted"]=function ( args ) {};
sms_in_callback["onItemUpdating"]=function ( args ) {};
sms_in_callback["onItemUpdated"]=function ( args ) {};
sms_in_callback["onItemDeleting"]=function ( args ) {};
sms_in_callback["onItemDeleted"]=function ( args ) {};
sms_in_callback["onItemInvalid"]=function ( args ) {};
sms_in_callback["onOptionChanging"]=function ( args ) {};
sms_in_callback["onOptionChanged"]=function ( args ) {};
sms_in_callback["onPageChanged"]=function ( args ) {};
sms_in_callback["onRefreshing"]=function ( args ) {};
sms_in_callback["onRefreshed"]=function ( args ) {};
function get_JsSize()
{
	var return_obj = {};
	//copyArray(return_obj,sms_js_size);
	for (var key in sms_js_size )
	{
		return_obj[key]=sms_js_size[key];
	}
	return return_obj;
}
function get_JsBasic_setting()
{
	var return_obj = {};
	//copyArray(return_obj,sms_basic_setting);
	for (var key in sms_basic_setting )
	{
		return_obj[key]=sms_basic_setting[key];
	}
	return return_obj;
}
function get_JsIn_tinge()
{
	var return_obj = {};
	//copyArray(return_obj,sms_in_ting);
	for (var key in sms_in_ting )
	{
		return_obj[key]=sms_in_ting[key];
	}
	return return_obj;;
}
function get_JsIn_row_function()
{
	var return_obj = {};
	//copyArray(return_obj,sms_in_row_function);
	for (var key in sms_in_row_function )
	{
		return_obj[key]=sms_in_row_function[key];
	}
	return return_obj;;
}
function get_JsIn_callback()
{
	var return_obj = {};
	//copyArray(return_obj,sms_in_callback);
	for (var key in sms_in_callback )
	{
		return_obj[key]=sms_in_callback[key];
	}
	return return_obj;;
}

분리됨 모듈라이브러리파일을 jsgrid가 사용되는 페이지에서 로드하여 줍니다. 

페이지 부분에 들어가는 소스입니다.

<div id="jsGrid"></div>	  //그리드 위치 선언

자바스크립트 부분
$(document).ready(function(){	
     var db = {
    		loadData: function (filter) {
                return  $.ajax({
                    type: "POST",
                    headers : {
    					"Content-Type" : "application/json",
    					"X-HTTP-Method-Override" : "POST",
    					'X-CSRF-TOKEN': $("#csrf_token").val()
    				},
    				async: true,
                    url: getContextPath()+"/grid/select",
                    data: read_common_data("Appointment_Mapper.a2_list_all_select", filter),
                    error: function (request, status, error) {
                    	alert('code:' + request.status + '\n' + 'message:' + request.responseText + '\n' + 'error:' + error);
                    	}
                });
            }        
        };
    window.db = db;
    window.db.comcode = new Object();    
    window.db.comcode["mt_use"] = [         
    								{ Name: "선택", Id: "" },
						            { Name: "Y", Id: "Y" },
						            { Name: "N", Id: "N" }
						           ];

이제 그리드 등 연결해 줍니다.

now_grid=$("#jsGrid");
    now_pager= $("#pager");
    now_table_custom=$(".config-panel input[type=checkbox]");
    now_db = db;
    /* 달력 */ 
    jsGrid.fields.MySelectControlField = MySelectControlField;

필드값을 설정해줍니다.

 var fields =  [
                   { name: "idx", title:"번호", type:"number", width: 60 ,align: "center" , valueType: "number",readOnly: true},
                   { name: "mdate", title:"게시일", type: "text",  width: 100, align: "center" },
                   { name: "title", title:"제목", type: "text",  width: 300, align: "left" ,readOnly: true},
                   { name: "dname", title:"구분", type: "text",  width: 60, align: "left" ,readOnly: true},
                   { title:"답변상태",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                             	
                         	});
               		        $result_bt.append( "답변완료" );
               		     	
               		     var $result_bt1=$(" <button>")
	   					    .addClass( "btn btn-lightblue btn_icon" )
                      	.on("click", function() {                             	
                          	    
                      	});
               		     $result_bt1.append( "미답변" );
               			if(item.answer=='Y')
               			{
               				parent.append($result_bt);	
               			}
               			else
               			{
               				parent.append($result_bt1);
               			}
               		
		       		  
		       		  return parent;		     
                	   }},
                	   {title:"답변메일",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                         		email_send(item);
                         	});
               		        $result_bt.append( "보내기" );
               		            		        
               		  		if(item.memailsend=='Y')
	             			{
	             				parent.append("답장보냄");	
	             			}
	             			else
	             			{
	             				parent.append("답장안함");
	             			}
               		  		parent.append(item.memail);               		  	
							parent.append($result_bt);
		       		  return parent;		     
                	   }},                 	   
                   { type: "MySelectControlField", selectButton: true, deleteButton:false, modeSwitchButton: false, editButton: false, width: 120 },
                   { title:"공개상태",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                             	
                         	});
               		        $result_bt.append( "공개" );
               		     	
               		     var $result_bt1=$(" <button>")
	   					    .addClass( "btn btn-lightblue btn_icon" )
                      	.on("click", function() {                             	
                          	    
                      	});
               		     $result_bt1.append( "미공개" );
               			if(item.always=='Y')
               			{
               				parent.append($result_bt);	
               			}
               			else
               			{
               				parent.append($result_bt1);
               			}
               		
		       		  
		       		  return parent;		     
                	   }},
                   { title:"공개삭제",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                             	naver_send_w(item);
                         	});
               		        $result_bt.append( "공개" );
               		     	
               		     var $result_bt1=$(" <button>")
	   					    .addClass( "btn btn-lightblue btn_icon" )
                      	.on("click", function() {                             	
                          	    naver_send_d(item);
                      	});
               		     $result_bt1.append( "삭제" );
               			
		       		  parent.append($result_bt,'&nbsp;',$result_bt1);
		       		  return parent;		     
                	   }} 
               ];

다음은 인서트나 업데이트시 체크되야할부분과 업데이트인서트 기능을 설정해줍니다.

 var onItemInserting = function(args) {
        // cancel insertion of the item with empty 'name' field
    	f_values_chack(args);
    }
    var onItemUpdating = function(args) {
    	// cancel insertion of the item with empty 'name' field
    	f_values_chack(args);
    }
    var in_filtering=true;
    var in_editing=false;
    var insert_row=false;
    initGrid(now_grid,fields,true,15,10,in_filtering,insert_row,in_editing,true,true,now_pager,now_table_custom,now_db,OnrowClass,onItemInserting,onItemUpdating);

여기서 f_values_chack함수를 만들어줍니다. 

var f_values_chack = function(args)
{
	if(args.item.mt_code === "") {
    	jQuery.each( args.grid.fields, function( key, value ) //반복
    	{
    		if(value.name==="mt_code")
    		{
    			showmessage("경고",value.title+"을(를) 입력값이 누락되었습니다. 확인해 주세요.",2000,'error');
    		}
    	});
        args.cancel = true;
        return;
    }
    if(args.item.mt_code_value === "") {
    	jQuery.each( args.grid.fields, function( key, value ) //반복
     	{
     		if(value.name==="mt_code_value")
     		{
     			showmessage("경고",value.title+"을(를) 입력값이 누락되었습니다. 확인해 주세요.",2000,'error');
     		}
     	});     	
       	args.cancel = true;
       	return;
    }
}

실행해보면 나옵니다. 

JSGRID

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

PROMENADE 프롬나드 카페 기장군 기장읍 연화1길 151 에서

새해 첫날 와이프와 노트북을 챙겨들고 기장근교 카페를 찾았다.

오늘은 대변로 쪽으로 운전을 하였는데 새해라 그런지 사람도 많고 해서 구석 구석 운전을 하였다. 

PROMENADE 건물외부사진

PROMENADE 라는 카페가 보였다. 들어가는 입구에 컨셉인지 재질을 잘못 한건지 새단장한것 치고는 녹이 슬어 있었다.

카페로 들어가니 제법 잘 꾸며져있었다. 

건물내부
건물내부
건물내부

콜드브루 2잔과 초쿄타르타를 시켜 2층으로 갔다.

콜드브루 초쿄타르타
콜드브루 초쿄타르타

커피를 마시며 와이프와 노트북으로 테트리스 및 웹 검색 유투브 등을 보며 시간을 보내다 보니 

어느듯 어두워졌다.

창밖야경

막 왔을땐 창가에 사람들이 꽉차 있어 사진을 못찍었는데 저녘에 찍으니 사진이 별루다. 낮에 오면 정말 뷰가 좋다. 

2층 내부
2층 내부
2층 내부

기장근처 대변로쪽에 좋은 카페를 발견해서 가끔오지 않을까 싶다. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

기획홍보팀에서 디지털365치과의원의 리플렛을 제작하게 되었습니다. 

어제 목요일 이번주 토요일 사용해야 된다고 해서 저희와 평소 거래해 오던 오성프로에 연락을 하니 

만들어 주신다고 하였습니다. 

a3 300장 a4 300장 리플렛을 주문하였습니다. 

a4 사이즈는 가져가기 편하고 a3 사이즈는 읽기에 편해 두가지 사이즈로 준비하였습니다.

아침에 인쇄파일을 드렸는데 오후에 파일이 왔습니다. 

오후4시즘 가져다 주셨습니다.

A3 사이즈 리플렛
A4와 A3사이즈 리플렛
인쇄내용

홈페이지 제작시 있던 이미지와 내용을 토대로 만들었습니다.

혹시라도 내용이 궁금하신 분들은 저희 울산 디지털365치과 홈페이지에 오셔서 구경하세요.

 

https://digital365365.com/

 

울산치과 디지털365치과의원 치과치료 궁금해요!

울산 남구 삼산에 위치한 디지털365치과 치과치료의 궁금한점을 Q&A형태로 제공합니다.

digital365365.com

오성프로와 협업으로 무사히 제시간에 제작할수 있어 다행이었습니다.

감사합니다.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

올데이롱 TFX255S 리뷰! 

와이프가 출산후 아이를 키우며 데스크탑을 사용할 환경이 안되었습니다. 

어디에서나 놔두고 사용할수 있는 노트북이 필요해서 전에 사용하던 한성 X44노트북을 주었는데.. 

에구.. 제가 업무용겸으로 사용을 해서인지 와이프가 사용하기엔 불편했나봐요.  

저는 괜찮은데 자꾸 꺼지고 오류가 난데요. ^^ 

와이프에게 구박받는 X44

X44는 개발용 서버로 간간히 사용하고 개인노트북 XH7957T를 집에서 나 미팅시 사용할려고 구매했었는데요.

와이프에게 XH7957T를 사용하라고 하니 무거워서 싫다고 하네요.  카페에 들고가기 무겁다나.

XH7957T 카페에서 오버워치를 하는 재미.

와이프도 컴퓨터 하드웨어를 잘아는 편이어서 라이젠 이나 60만원대로 가볍고 쓸만한걸 검색하더라구요. 

저두 그쪽을 살펴보는데 무게나 화면크기나 성능이나 60만원대에선 모든게 애매하더라구요. 

그런데 검색도중.. 아.. 가성비하면 한성인데.. 한성에 가볍고 성능좋은 노트북이 있지 않을까 싶어 한성 노트북을 폭풍

검색했습니다. 

다나와에서 올데이롱 TFX255S를 보게 되었어요.  하드웨어와 무게 성능을 보고 바로 구매결정을 내렸습니다. 

가격은 생각했던 것보다 올랐지만 무게나 성능이 너무 마음에 들었거등요. 

와이프에게 링크를 보내주니 와이프도 노트북이 이쁘다며 OK하더군요. 

배송을 받으니 엄청 큰 상자가 와서 놀랐습니다. 

박스를 뜯으니 조그마한 상자가 또 보이더군요... 헐 이렇게 튼튼하게 배송하다니. ^^

좋은 컴퓨터를 만드는 사람들 한성컴퓨터.
노트북과 전원어뎁터

구성품은 노트북, 전원어뎁터 2개로 단순했어요. 

상판은 은색으로 깔끔합니다.

자판은 누르는 느낌 좋았어요. 또각또각 

노트북 화면 슬림베젤

베젤이 슬림한거 보이시나요? 윈도우를 설치하고 사운드를 테스트 할려고 유투브에서 음악을 틀었어요.

와우 슬림한 노트북이라 기대를 전혀 하지 않았는데 소리가 정말 좋았어요.

아차차 그리고 이벤트라 메모리 16기가로 무료 업그레이드 받았네요. 

메모리 16기가

이제 17인치 노트북 보다는 TFX 255S를 더 자주 사용할것 같습니다.

역시 가성비는 한성노트북인거 같아요. ^^ 

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

기획홍보팀디지털365치과에서 카탈로그 제작을 하게 되었습니다. 

수요일 아침 급히 오늘 오후에 카탈로그를 가져가야 된다고 부원장님 빨리 준비해달라고 하셔서

평소 거래를 해오던 오성프로에 연락을 하였습니다. 

금일 오후 3시 까지 제작이 되는지 물어보았습니다. 

검수시 나왔던 수정사항이 및 인쇄용으로 수정하여 디자이너선생님이 오성프로에 보냈습니다.

잠시 시간을 보낸뒤 3시즘 연락을 하니 제작이 완료 되었다고 연락이 왔습니다.

칫솔세트와 삼송빵집에서 빵을 사들고 카탈로그를 찾으로 갔습니다.

전무님이 직접 카탈로그 제작과정을 챙겨 주셨더군요.

전무님께 치솟세트와 삼송빵집에서 구매한 빵을 드리며 고마움을 표현했습니다.

그리고 저희 치과에서 이번에 네이비게이션 임플란트 이벤트를 한다는 소식도 전했습니다.

주변에 임플란트 하실분들 계시면 소개 부탁드리면서요.

제작된 카탈로그는 생각했던것보다 색감이 좋았고 종이 재질도 마음에 들었습니다.

카탈로그 표지
카탈로그 표지

 

인쇄 된 소개페이지

홈페이지 제작시 있던 이미지와 내용을 토대로 만들었습니다.

혹시라도 내용이 궁금하신 분들은 저희 울산 디지털365치과 홈페이지에 오셔서 구경하세요.

https://digital365365.com/

 

울산치과 디지털365치과의원 치과치료 궁금해요!

울산 남구 삼산에 위치한 디지털365치과 치과치료의 궁금한점을 Q&A형태로 제공합니다.

digital365365.com

오성프로와 협업으로 무사히 제시간에 제작할수 있어 다행이었습니다. 

곧 리플렛 제작기도 올리겠습니다.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

한우떡갈비
밑반찬
주인의 그림
가게분위기

주말 가족끼리 경주여행을 갔습니다.
점심으로 고색창연에 들렀습니다.
10여년동안 옆에 카페가 생기고 주변 가게가 생기고 카페주인이 바뀌어도 항상 똑같습니다.
오랜만에 먹었는데 맛있습니다.
사장님이 요즘 장사가 예전같지 않다고 하더군요.
경주 황리단길이 떠서 그런거 같은데 그래도 여전히 손님이 많더군요.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

웹페이지에 상담신청이 왔을시 E-MAIL로 받게 했었다. 알람설정을 했지만 스마트폰을 잘보지 않아

문자로 보게 하는게 좋겠다고 하여 카페24에서 서비스 중이 SMS호스팅을 이용하기로 했다.

https://www.cafe24.com/

 

카페24

No.1 글로벌 전자상거래 플랫폼 '카페24'

www.cafe24.com

SMS서비스 및 비용

적당한 상품을 고르고 신청을 합니다. 

상품메뉴

메뉴가 있는데 발신번호 관리에서 번호를 인증해줍니다.

디지털365치과의원 번호로 인증함

디지털365치과의원 대표전화번호로 인증을 받았습니다.

restTemplate 이용해서 보내봅니다. 소스입니다.

	
    	String url = "https://sslsms.cafe24.com/sms_sender.php";
		String secret_key = "시크릿키";
		Util_Message smsp = Util_Message.getInstance(); //메세지 찍어보는거 
		CommonData result = new CommonData();
		smsp.print_String("/sms_send"); //위치sms_send 
		smsp.print_CommonData(dto); //db에서 읽어온 문자 메시지 내용 		
		RestTemplate restTemplate = new RestTemplate(); 
		HttpHeaders headers = new HttpHeaders();
	    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
	    LinkedMultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
	    map.add("user_id", "유저ID");	    
	    map.add("secure", secret_key); //시크릿키
	    map.add("msg", dto.get("content")); //SMS내용
	    map.add("sphone1", "052"); //인증된 발신번호
	    map.add("sphone2", "710");
	    map.add("sphone3", "5020");
	    map.add("rphone", dto.get("to_phone")); //수신 휴대번호
	    map.add("title", "디지털365치과의원"); //타이틀 ..
	    map.add("rdate", ""); //예약일자
	    map.add("rtime", "");  //예약시간
	    map.add("mode", "1");
	    //map.add("testflag", "Y");	 //테스트시..
	    HttpEntity<LinkedMultiValueMap<String, String>> request2 = new HttpEntity<LinkedMultiValueMap<String, String>>(map, headers);
        
	    String response2 = restTemplate.postForObject( url, request2, String.class );
	    smsp.print_String(response2);

테스트를 해보니 문자가 잘 받아집니다. 

문자메세지

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

네이버 플레이스 상위 노출은 모두에게 필요한 일일것입니다.

인터넷에 노출된 공개된 비법과 팁을 정리해봅니다.

디지털365치과의원 1페이지에 진입

페이지 진입한 결과를 캡쳐하여 올립니다. 울산치과 네이버로 검색해보시길 바랍니다. 

1. 홈페이지, 네이버블로그, 인스타그램, 페이스북 등을 준비합니다.

 지역업체 등록전에 먼저 준비하시기 바랍니다.

2. 지역업체 등록으로 업체를 등록합니다. 

지역업체 등록

상세 내용은 적지 않겠습니다. 정확한 정보를 입력합니다.

3.네이버 예약페이지를 열어줍니다.

4. 블로그는 2-3일 한번씩 꾸준히 글을 올려줍니다. 매일매일 올리는 것도 좋지만 결국 양질의 컨텐츠가 필요합니다. 

5. 파워링크 등록을 합니다. 

  고가의 키워드는 적당히 비중을 두어 등록합니다. 

6. 양질의 컨텐츠를 작성하며 , 고객의 네이버 예약의 활용 및 리뷰 등이 차곡 차곡 쌓이면 플레이스에서 순위가

  상승합니다. 

이상 인터넷에 공개된 플레이스 상위 노출에 대한 진심있는 자료들이라 판단되는 것들을 정리해 보았습니다.

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

SPRING으로 홈페이지를 개발했습니다. 

SPRING MVC구조로 큰어려움 없이 개발을 했는데 검색엔진에 최적화를 하다보니 META태그를 주소마다

변경해야 됨을 알았습니다. 

저는 메타데이터를 이렇게 관리 하고 있었습니다. 그래서 모든페이지가 동일한 메타값으로 관리되고 있었죠. 

<%@include file="../include/digital_meta.jsp"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
	<meta name="title" content="${meta_info.m_title}">
	<meta name="keywords" content="${meta_info.m_keywords}">
	<meta name="description" content="${meta_info.m_description}">
	<meta name="author" content="${meta_info.m_author}">
	
	 <!-- Facebook Open Graph -->
	<meta property="og:locale" content="ko_KR">
	<meta property="og:site_name" content="${meta_info.m_author}">
	<meta property="og:title" content="${meta_info.m_title}" />
	<meta property="og:type" content="${meta_info.m_type}">
	<meta property="og:url" content="${meta_info.m_og_url}">	
	<meta property="og:image" content="${meta_info.m_og_image}">
	<meta property="og:description" content="${meta_info.m_description}" />
	<meta property="fb:admins" content="digital365365"/>
	
	 <!-- Twitter Cards -->
	<meta name="twitter:card" content="${meta_info.m_card}">
	<meta name="twitter:title" content="${meta_info.m_title}">
	<meta name="twitter:description" content="${meta_info.m_description}">
	<meta name="twitter:image" content="${meta_info.m_og_image}">
	<meta name="twitter:domain" content="${meta_info.m_og_url}">
		
	<!-- Google+ / Schema.org -->
	<meta itemprop="name" content="${meta_info.m_title}"/>
	<meta itemprop="headline" content="${meta_info.m_title}"/>
	<meta itemprop="description" content="${meta_info.m_description}"/>
	<meta itemprop="author" content="${meta_info.m_author}"/>
	
	<!-- application/ld+json관련 --> 
	<script type="application/ld+json" class="aioseop-schema">
	{
	"@context":"https://schema.org"
	,"@graph":[{
				"@type":"Organization"
				,"@id":"https://digital365365.com/intro/drintro/"
				,"url":"https://digital365365.com/intro/drintro"
				,"name":"${meta_info.m_author}"
				,"sameAs":[]}
				,{
				  "@type":"WebSite"
				  ,"@id":"https://digital365365.com/"
				  ,"url":"https://digital365365.com/"
				  ,"name":"${meta_info.m_author}"
				  ,"publisher":{
								"@id":"https://digital365365.com/intro/drintro/"}}
				,{
				  "@type":"WebPage"
				  ,"@id":"${Full_URL}"
				  ,"url":"${Full_URL}"
				  ,"inLanguage":"ko-KR"
				  ,"name":"${meta_info.m_author}"
				  ,"isPartOf":{
								"@id":"https://digital365365.com/"}
				  ,"datePublished":"2019-11-25T02:25:36+00:00"
				  ,"dateModified":"2019-11-26T12:43:59+00:00"
				  ,"description":"${meta_info.m_description}"
				  }
				]}
</script>
<link rel="canonical" href="${meta_info.url}">
			
	<link rel="icon" href="${pageContext.request.contextPath}/resources/digital365/images/favicon.ico">
	
	<title>${meta_info.m_title}</title>	

그럼 주소값 별로 메타태그 값을 변경하기로 했습니다. 

인터셉터 를 만들고 preHandle 에 넣었습니다.

String CPath = request.getContextPath().toString();
CommonData dto = new CommonData();
dto.put("m_menu", originalURL);
CommonData result_list = first_service.selectone(dto,"Meta_Mapper.meta_info_select");
HttpSession session = request.getSession();
session.setAttribute("meta_info", result_list);

주소를 얻어오고 그주소값에 맞는 메타태그값을 가져옵니다. 

그리고 섹션에 담아가서 값을 넣어주게 되죠.

네이버에서 site:digital365365.com 를 검색해보면 각페이지마다 타이틀이 달라져 나오는걸 볼수 있습니다.

네이버 site:digital365365.com 검색내용

그리고 네이버 웹마스터 도구 에서 리포트를 보면

네이버 SEO 전체 결과

사이트 구조는 사이트 최적화에서 a태그로 이동을 권장하는데 스크립트를 최소한으로 사용해서 이동하게 했지만 이런결과는 어쩔수 없는것으로.

검색 로봇 수집결과

검색 로봇이 메타태그를 수집 기능 잘 되고 있습니다. 

콘텐츠 관리 페이지입니다.

게시판의 경우 동일 제목이라 53페이지가 동일함을 알수 있습니다.

그리고 dadentalclinic.com 으로 먼저 홈페이지를 열었었는데 가비아에서 반응형 템플릿을 구매하여 운영했었기때문에

53프로의 제목이 동일하다고 나오고 있습니다. 삭제요청도하고 구글역시 삭제 하고 있습니다만 이부분은 시간이 걸릴것 같습니다.

 

네이버 아래쪽 모바일사용성

기기가 모바일일때 동일주소 다른페이지를 보여지게끔 하였는데 최적화된 반응형 웹사이트라고 잘나옴.@@

운영하면서 점점 수정하고 잘 검색될수 있도록 하겠습니다. 

https://digital365365.com/

 

울산치과 디지털365치과의원 치과치료 궁금해요!

울산 남구 삼산에 위치한 디지털365치과 치과치료의 궁금한점을 Q&A형태로 제공합니다.

digital365365.com

 

운영중인 사이트입니다.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

입냄새 제거?

치과에서 근무를 하다보니 구강관련 정보를 많이 듣는편이에요.

입냄새의 원인은 너무 다양하기 때문에 가까운 치과를 방문 하는것이 좋아요.

입냄새 예방법은 치과에서 관리받는방법이 제일 확실하지만 바쁘다면 해볼만한 방법을 소개할게요.

1.양치질을 꼼꼼히 해요. 치약보다는 칫솔이 중요해요.

칫솔 고르는게 고민이라면 이걸 추천해요.

스카이덴트칫솔

2. 양치후 입안 행굼을 7-8번 정도로 많이 해야해요.

3. 혀클리너 사용 꼭 하기

다이소에서 파는 싸구려를 써도 괜찮으나 제가 써본것 중에선 이제품이 괜찮았어요.

혀클리너

혀클리너는 다이소 제품을 사용하다 행사로 2500원에 판매하길래 구매했어요. 시중가는 8000원 인가봐요.

4.구강유산균이 섭취하기.

오라덴티 
그린브레스

입안 유산균인데요. 양치만으로 구강상태가 나아지지 않는 분들에게 도움이 돼요.

입안 유해균으로 인해 나는 입냄새일경우인데요. 세균이 원인이에요.

이상 입냄새 제거에 대해 정리해보았어요.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,