728x90
반응형

백엔드(Node.js) 라우터 /address 에 address.html 파일을 렌더링하게 만들고

버튼을 눌렀을 경우 팝업창을 띄우도록 만들겠다.

 

예시

 

1. 먼저 html 코드는 아래와 같다.  addr1 부분은 검색을 한 뒤 자동으로 채워줄 부분이기 때문에 readonly를 추가하였고 searchaddr()을 onclick에 추가하였으며, 상세주소는 addr2에 추가할 수 있도록 하였다.

<!--주소-->
<label class="control-label">{{__('address')}}<span class="text-danger"> *</span> </label>
  <div class="form-group m-b-20">
    <div class="d-flex justify-content-between align-items-center mb-2">
      <input id="addr1" name="addr1" type="text" class="form-control form-control-lg inverse-mode w-70 mr-2" value ="{{addr1}}" placeholder="{{__('address_1')}}" data-parsley-error-message=null readonly required >
      <input type="button" class="btn btn-primary btn-block btn-lg w-25" value="{{__('search')}}" onclick="searchAddr();">
    </div>
    <input id="addr2" name="addr2" type="text" class="form-control form-control-lg inverse-model" value ="{{addr2}}" placeholder="{{__('address_2')}}" data-parsley-error-message="{{__('required_detail')}}" required >
  </div>

 

2. searchAddr() 함수는 아래와 같다. /address 팝업창을 띄어주고 주소를 받는 콜백함수를 지정했다.

// 주소 검색 기능
function searchAddr(){
	// 호출된 페이지(jusopopup.jsp)에서 실제 주소검색URL(https://www.juso.go.kr/addrlink/addrLinkUrl.do)를 호출하게 됩니다.
    var pop = window.open("/address","pop","width=570,height=420, scrollbars=yes, resizable=yes"); 
    
	// 모바일 웹인 경우, 호출된 페이지(jusopopup.jsp)에서 실제 주소검색URL(https://www.juso.go.kr/addrlink/addrMobileLinkUrl.do)를 호출하게 됩니다.
    //var pop = window.open("/popup/jusoPopup.jsp","pop","scrollbars=yes, resizable=yes"); 
}
/** API 서비스 제공항목 확대 (2017.02) **/
function jusoCallBack(roadFullAddr,roadAddrPart1,addrDetail,roadAddrPart2,engAddr, jibunAddr, zipNo, admCd, rnMgtSn, bdMgtSn
						, detBdNmList, bdNm, bdKdcd, siNm, sggNm, emdNm, liNm, rn, udrtYn, buldMnnm, buldSlno, mtYn, lnbrMnnm, lnbrSlno, emdNo){
	// 팝업페이지에서 주소입력한 정보를 받아서, 현 페이지에 정보를 등록합니다.
	document.getElementsByName('addr1')[0].value = roadAddrPart1+roadAddrPart2;
	document.getElementsByName('addr2')[0].value = addrDetail;
}

 

3. /address 랜더링 부분 (node.js) 에선 먼저 get 메소드로 승인키를 보내고, post 메소드로 입력한 주소를 담게 하도록 구현하였다. ( address_pop.html로 랜더링 하였다. )

router.get('/address', (req, res) => {
  const juso = process.env.juso;
  res.render('address_pop', {juso});
});

router.post('/address', (req, res) => {
  const juso = process.env.juso;
  const locals = req.body;
  
  res.render('address_pop', {juso, locals});
});

 

4. addresspop.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Juso Search</title>
</head>

<script language="javascript">
//opener관련 오류가 발생하는 경우 아래 주석을 해지하고, 사용자의 도메인정보를 입력합니다. ("주소입력화면 소스"도 동일하게 적용시켜야 합니다.)
//document.domain = "abc.go.kr";

function init() {
	var url = location.href;
	var confmKey = "{{juso}}";//승인키
	// resultType항목 추가(2016.10.06)
	var resultType = "4"; // 도로명주소 검색결과 화면 출력유형, 1 : 도로명, 2 : 도로명+지번+상세보기(관련지번, 관할주민센터), 3 : 도로명+상세보기(상세건물명), 4 : 도로명+지번+상세보기(관련지번, 관할주민센터, 상세건물명)
	
	var inputYn = '{{locals.inputYn}}';

	if(inputYn != "Y") {
		document.form.confmKey.value = confmKey;
		document.form.returnUrl.value = url;
		document.form.resultType.value = resultType; // resultType항목 추가(2016.10.06)
		document.form.action="https://www.juso.go.kr/addrlink/addrLinkUrl.do"; // 인터넷망
		//document.form.action="https://www.juso.go.kr/addrlink/addrMobileLinkUrl.do"; //모바일 웹인 경우, 인터넷망
		document.form.submit();
	}
	else {
		var roadFullAddr = '{{locals.roadFullAddr}}';
		var roadAddrPart1 = '{{locals.roadAddrPart1}}';
		var addrDetail = '{{locals.addrDetail}}';
		var roadAddrPart2 = '{{locals.roadAddrPart2}}';
		var engAddr = '{{locals.engAddr}}';
		var jibunAddr = '{{locals.jibunAddr}}';
		var zipNo = '{{locals.zipNo}}';
		var admCd = '{{locals.admCd}}';
		var rnMgtSn = '{{locals.rnMgtSn}}';
		var bdMgtSn = '{{locals.bdMgtSn}}';
		/** API 서비스 제공항목 확대 (2017.02) **/
		opener.parent.jusoCallBack(
			roadFullAddr,
			roadAddrPart1,
			addrDetail,
			roadAddrPart2,
			engAddr,
			jibunAddr,
			zipNo,
			admCd,
			rnMgtSn,
			bdMgtSn
		);
		window.close();
	}
}



</script>

<body onload="init();">
	<form id="form" name="form" method="post">
		<input type="hidden" id="confmKey" name="confmKey" value=""/>
		<input type="hidden" id="returnUrl" name="returnUrl" value=""/>
		<input type="hidden" id="resultType" name="resultType" value=""/> 
		<!-- 해당시스템의 인코딩타입이 EUC-KR일경우에만 추가 START--> 
		<!-- 
		<input type="hidden" id="encodingType" name="encodingType" value="EUC-KR"/>
		 -->
		<!-- 해당시스템의 인코딩타입이 EUC-KR일경우에만 추가 END-->
	</form>
</body>
</html>

 

 

react에서는 react-daum-post라는 node모듈이 있는데, 이렇게 Jquery에서 힘들게 구현해보고 리액트의 라이브러리가 괜히 편한게 아니라는걸 깨달았다. (적어도 이 방식보단 쉽다고 느꼈다.) 참고로 JQuery에서 팝업을 띄우는 이 방식은 https가 아닌 http에서는 안전하지 않은 사이트라며 "무시하고보내기" 라는 버튼을 눌러야 실행된다. 사용자 입장에서 불안할 수도 있다고 생각하였다.

728x90
반응형
728x90
반응형

화면 구성

 

1. JQuery

ajax로 node 서버에 CNU값을 보낸다.

$.ajax({
		type: 'POST',
		url: '/company/checkCNU',
		dataType: 'json',
		data: {
			CNU : CNU
		}
	})
}

 

2. Node.js

사업자 휴폐업 조회 오픈 API를 사용했다.

JQuery에서 받아온 데이터를 가져와 직접 만든 postCRN이란 함수에 인자로 넣어서 실행해준다.

사업자 번호가 올바르면 "부가가치세 일반과세자 입니다."로 뜨기에, 올바른 사업자번호일 경우 true값을 보내도록

하였다. 이후에 res.send를 이용하여 클라이언트쪽에서 판별하기로 하였다.

// 사업자등록번호 검증
router.post('/checkCNU', async (req, res, next) => {
  const CNU = req.body.CNU;
  const CNU_CK = await postCRN(CNU);
  
  // Company Number check
  async function postCRN(crn){
    const postUrl = "https://teht.hometax.go.kr/wqAction.do?actionId=ATTABZAA001R08&screenId=UTEABAAA13&popupYn=false&realScreenId=";
    const xmlRaw = "<map id=\"ATTABZAA001R08\"><pubcUserNo/><mobYn>N</mobYn><inqrTrgtClCd>1</inqrTrgtClCd><txprDscmNo>{CRN}</txprDscmNo><dongCode>15</dongCode><psbSearch>Y</psbSearch><map id=\"userReqInfoVO\"/></map>";
      try {
        const result  = await axios.post(postUrl,xmlRaw.replace(/\{CRN\}/, crn),
          { headers: { 'Content-Type': 'text/xml' } });
        let CRNumber = await getCRNresultFromXml(result.data);
        
        if (CRNumber ==='부가가치세 일반과세자 입니다.') {
          CRNumber = true;
        } else {
          CRNumber = false;
        }
        
        return res.send({ CRNumber : CRNumber });
        
      } catch(err){
        console.error(err);
        next(err);
      }
          
  }
  
  function getCRNresultFromXml(dataString) {
    return new Promise((resolve, reject) => {
      xml2js.parseString(dataString, // API 응답의 'data' 에 지정된 xml 값 추출, 파싱
        (err, res) => {
          if (err) reject(err);
          else resolve(res.map.trtCntn[0]); // trtCntn 이라는 TAG 의 값을 get
        });
    });
  }
});

 

 

3. JQuery

 

따라서 결과값이 true일 경우, false일 경우에 각각 원하는 작업이 이루어지도록 구현했다.

// 사업자 번호 조회 및 정보 가져오기 기능
function checkCNU(companyNumber) {
	var CNU = document.getElementsByName(companyNumber)[0].value;
	$.ajax({
		type: 'POST',
		url: '/company/checkCNU',
		dataType: 'json',
		data: {
			CNU : CNU
		}
	}).done(function(data) {
		if(data.CRNumber) {
		    alert(i18nconvert('register_business_right'));
		    document.getElementsByName('hideCNU')[0].value = 'true';
		    document.getElementById('err-msg-cnu').innerHTML = i18nconvert('register_company_cer_success');
		    $("input[name='CNU']").prop('readonly', true);
		    $('.agent-select').removeClass('d-none');
		}
		else {
			alert(i18nconvert('register_business_noexist'));
			document.getElementsByName("CNA").value = null;
			document.getElementsByName("NA").value = null;
			document.getElementsByName("MN").value = null;
			document.getElementsByName("PN").value = null;
			document.getElementsByName("addr1").value = null;
			document.getElementsByName("addr2").value = null;
			document.getElementsByName('hideCNU')[0].value = null;
			document.getElementById('err-msg-cnu').innerHTML = i18nconvert('register_company_need_cer');
			$("input[name='CNU']").prop('readonly', false);
		    $('.agent-select').addClass('d-none');
		}
	});
}

 

728x90
반응형
728x90
반응형

사이트의 가장 기본이되는 회원가입 화면!!

 

Node.js 와 JQuery로 만드는 사이트 제 1단계인 로그인 만들기를 시작해보겠다.

1년동안 웹페이지를 개발한 결과 CRUD가 괜히 이 순서가 아닌거 같았다. 테이블, 계정관리, 대시보드 등 모든 것이 

등록 - 조회 - 수정 - 삭제 이순서대로 개발하면 문제가 될 것 없이 편했다.

 

1. 화면은 이런식으로 하였다. ( 본사, 지점은 무시하셔도 됩니다 )

    기타 

다른 부수적인 내용들( 특별한 기능이 없는 )을 제외한 중요 기능 위주로 설명하겠다.

728x90
반응형

+ Recent posts