2017년 11월 22일 수요일

국세청 사이트에서 사업자 번호로 사업자 상태 조회하는 API 개발

0. 회사 ERP에 거래업체를 등록할 때마다 매번 국세청 사이트에 접속해서 사업자 번호로 사업자 상태를 조회해서 같이 입력을 해줘야 함

1. 국세청 사이트는 IE 전용이라 날 귀찮게 함.

2. 참고 또 참고 했지만, 역시 결국 귀찮음.

3. 에라이 개발해보자!!

4. 일단 있는거 있음 날로 먹기로 결심

5. 절라 구글링 해도 안나오거나, 뭔 놈의 유료로 파는 것만 발견.

6. 국세청 사이트의 해당 서비스를 분석

7. 결국은 서블릿 호출 + XML 전문통신

8. 간단하게 하기 위해서 ASP로 개발. (Java도 마찬가지 임.. 귀찮아서 개발 안함.)

9. 이하 소스

10. 퍼갈땐 출처 좀 밝혀 주길..(혹시 알어... 출세할지.. 불펌하면.. 혼내줄꺼임!)

11. git 에도 추가 (https://github.com/jaymz9634/retcompanystatus)

--------------------------------------------------------------------
2020-03-03 내용 추가:

국세청에서 과도한 접근에 대한 금지를 해놨음.

자체 테스트 해봤을때 한번에 30건 정도 조회하고 1분 쉬었다가 요청하면 문제없이 처리 됨을 확인.

내 경우에는 java로 구현해서 thread.sleep 으로 30건 마다 1분씩 쉬게해서 처리 완료.

<%
Session.CodePage = 949
Response.Charset = "euc-kr" '결과가 한글이기에 안 깨지게...'
'On Error Resume Next'

txprDscmNo = Request("txprDscmNo")

xmldata = xmldata & "<map id='ATTABZAA001R08'><pubcUserNo/><mobYn>N</mobYn><inqrTrgtClCd>1</inqrTrgtClCd><txprDscmNo>"&txprDscmNo&"</txprDscmNo><dongCode>05</dongCode><psbSearch>Y</psbSearch><map id='userReqInfoVO'/></map>"

set api = createobject("msxml2.serverXmlhttp")
api.open "POST", "https://teht.hometax.go.kr/wqAction.do?actionId=ATTABZAA001R08&screenId=UTEABAAA13&popupYn=false&realScreenId=", false 
api.setRequestHeader "content-type","text/xml; charset=utf-8"
api.send xmldata

if api.status = 200 Then
    Response.ContentType="text/xml"
    Response.Write(api.ResponseText)
else
    Response.Write("[statusCode : "&api.status&"]" & "<br/>")
    Response.Write("<hr/>")
    Response.Write(xmldata & "<br/>")
    Response.Write("<hr/>")
    Response.Write(api.responseText & "<br/>")'
End if

If Err.number <> 0 Then     '오류 발생 시 이 부분 실행
    Response.Write "<b3>" & Err.Source & "<hr noshade></h3>"
    Response.Write "오류 번호 : " & Err.number & "<br>"
    Response.Write "내용 : " & Err.Description & "<br>"
End If

Set api = nothing
%>

2017년 11월 10일 금요일

[악보채보]트리니티 - 무화과 나뭇잎이 마르고(라이브 워십2 버전)

언제나 귀찮은게 싫은 본인에게 교회 속회 인도자에게서 연락 옴..

A : 저희가, 추수 감사절 찬양대회 나가는데..

듣는 시작부터 귀차니즘 몰려옴... 이미 안하기로 결심

나 : 얘가 넷이고, 바빠서 어쩌구 저쩌구.

A : 집사님 없으면 안되효~~~ 풀 밴드로 하기로 했어효~~~

난 한적도 없고, 왜 지들 맘대로 선곡해서 날 거기에 맞추나 ㅡㅡ^

나 : 네... 하여간 생각은 해봅니다만, 안사람 한데 물어봐야 해요.

A : 네.. 꼭 해주시리라 믿쑵니다~~!~!

나 : 네, 다시연락드릴께요~ (안 한다라고~~!!!!)

끊고, 마눌님과 입맞추기 위해 물어봄..

속회 찬양대회 한다는데... 난 한다고 하지도 않았는데~~~ ㅡㅡ~~~~~ 주저리 주저리

마눌님 : 응, 그래 해보자~~

헉!! 이게 아닌데...

의 결과로 나온 악보...

트리니티라는 CCM 밴드의 라이브 버전을 한단다... 아무리 검색을 해도 안나와서리..

급한대로 딴 기타 악보...

너무 귀찮다~~




악보 다운!!

퍼가드라도... 출처는 좀 밝히자!!! 혹시 알어? 요딴걸로 잘먹고 살지!

끗!

2021-01-29 : 구글드라이브로 링크 수정
---------------------------------------------------------------------------
2022-08-30 : 뒤늦게 생각난 그 결과물..



2017년 11월 7일 화요일

Apache Solr에서 두개의 분류로 Group 하기

참고 : https://stackoverflow.com/questions/15758829/solr-how-can-i-group-on-two-different-fields

Apache Solr 4.3 에서는 group 기능이 있긴 하지만, 하나의 컬럼만 그룹이 가능하다.

이래저래 검색해서 pivot을 사용하면 된다는 걸 발견

전송 매개변수는 다음과 같다.

"fl":"분류1,분류2", -- 출력 컬럼
"indent":"true",
"q":"검색조건",
"group.field":"분류2",  -- 분류1 아님!!
"group":"true", --- group 사용
"wt":"json",
"facet.pivot":"분류1,분류2",
"fq":"필터조건",
"rows":"999" -- 반환 결과수 (분류2의 결과를 다 출력해야 해서 일부러 999 줌)


위에서 group.filed와 group을 제거하고 매개변수를 보내면 분류들만 출력되는 결과가 나옴.
이것도 나름 응용할 곳이 있을 듯 하다.

2017년 10월 18일 수요일

DB에서 구분자가 들어간 파라메터를 한줄로 출력

업무를 하다 보니...

DB 프로시저 등에 파라메터를 여러개 전달해서

구분자로 분해해서 쿼리의 IN 문장에 쓰고 싶은 경우가 많은데..

정작 찾아보니... 없다!!

split 구현한것들은 내가 원하는 형태가 안 나오길래.. 직접 구현..

목표는 '5040:5050:5060:' --->'5040','5050','5060' 요 딴식이다!!

이하 mssql 스칼라 함수!!

(
P.S. 기껏 만들어 놨더니.. 생각대로 안됨... 내가 상상한 사용법으로 안됨..

https://stackoverflow.com/questions/2944511/sql-server-in-clause-with-a-declared-variable

위의 링크대로 해야 함..
)


  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO
  5. -- =============================================
  6. -- Author:     
  7. -- Create date: <2017-10-18>
  8. -- Description: <특정구분자로 결합된 문자 집합을 IN에 사용할 수 있는 형식으로 변경 반환 '5040:5050:5060:' --->'5040','5050','5060' >
  9. -- 구분자 마지막까지 붙일것!!!
  10. -- SELECT dbo.UFN_CONVERT_PARAMS('5040:5050:5060:',':')
  11. -- =============================================
  12. ALTER FUNCTION dbo.UFN_CONVERT_PARAMS(
  13.     @PARAMS VARCHAR(5000),
  14.     @TOKKEN VARCHAR(10)
  15. )
  16. RETURNS VARCHAR(5000)
  17. AS
  18. BEGIN
  19.     DECLARE @RTN    VARCHAR(5000)
  20.     DECLARE @TMP_CNT    INT
  21.     DECLARE @loop INT
  22.     SET @TMP_CNT = LEN(@PARAMS)-LEN(REPLACE(@PARAMS,@TOKKEN,''))    -- 슬래시 갯수 추출
  23.     SET @loop = 0
  24.    
  25.     DECLARE @SPLIT_SP   VARCHAR(500)    --분리한 값 저장
  26.     DECLARE @SPLIT_REMAINS  VARCHAR(500)
  27.     DECLARE @SPLIT_TMP_CD   VARCHAR(5)
  28.     SET @SPLIT_SP = ''
  29.     SET @SPLIT_TMP_CD = ''
  30.     SET @SPLIT_REMAINS = @PARAMS
  31.     WHILE(@loop < @TMP_CNT)
  32.     BEGIN
  33.         SET @SPLIT_TMP_CD = LEFT(@SPLIT_REMAINS,CHARINDEX(@TOKKEN,@SPLIT_REMAINS)-1)
  34.         SET @SPLIT_SP = @SPLIT_SP + '''' + @SPLIT_TMP_CD + '''' + ','
  35.         SET @SPLIT_REMAINS = REPLACE(@SPLIT_REMAINS,LEFT(@SPLIT_REMAINS,CHARINDEX(@TOKKEN,@SPLIT_REMAINS)),'')
  36.         SET @loop = @loop + 1      
  37.     END
  38.     RETURN LEFT(@SPLIT_SP, LEN(@SPLIT_SP) - CHARINDEX(',', reverse(@SPLIT_SP)))
  39. END
  40. GO

2017년 10월 16일 월요일

[Google Cloud 번역-0]앱 엔진 환경 선택


내맘대로 번역

앱 엔진 환경 선택

당신은 유연한 환경이나 표준 환경을 사용하여 앱 엔진에서 당신의 응용 프로그램들을 구동시킬수 있다. 또한 당신의 응용 프로그램에 두개의 환경을 사용하도록 선택할 수도 있고 서비스에 각 환경의 개별적인 이점을 얻을 수 있게 허용할 수도 있다.

앱 엔진 환경을 선택하라

microservice 아키텍처를 사용하여 응용 프로그램을 구성하면, 특히 두 환경을 모두 사용하기로 결정한 경우 App Engine에 가장 잘 부합된다. 응용 프로그램과 해당 서비스에 더 적합한 환경을 결정할 때 고려해야 할 몇 가지 요소가 있다. 다음 섹션으로 응용 프로그램의 요구 사항을 가장 잘 충족시키는 환경을 파악하고 이해하시오.

유연한 환경을 선택했다면

앱 엔진 유연한 환경을 사용한다는 것은 응용 프로그램 인스턴스가 구글 연산 엔진 가상 머신 (VM)의 Docker 컨테이너 내에서 실행된다는 것을 뜻한다.
일반적으로, 유연한 환경에 적합한 응용 프로그램들은 일정한 트래픽을 수신하거나, 정기적인 트래픽 변동이 생기거나, 점차적으로 매개변수들이 조정되는 것들이다.
유연한 환경은 다음과 같은 특징이 있는 응용 프로그램들에 최적화 되어 있다:
  • 지원되는 프로그래밍 언어의 모든 버전으로 소스 코드를 작성함: 
    PythonJavaNode.jsGoRubyPHP, 또는 .NET
  • 사용자 정의 런타임이 포함되었거나 다른 프로그래밍 언어로 작성된 소스코드가 포함된 Docker 컨테이너에서 구동.
  • imagemagick, ffmpeg, libgit2, Ehsms apt-get을 통한 그 밖의 운영체제를 포함하는, 다른 소프트웨어에 의존.
  • 네이티브 코드가 포함된 프레임웍을 사용하거나 의존.
  • 연산 엔진 네트웍에 있는 당신의 클라우드 플랫폰 프로젝트 리소스나 서비스에 접근.

표준 환경을 선택했다면

앱 엔진 표준 환경 사용은 당신의 응용 프로그램 인스턴스가 하나의 샌드박스 내에서 구동되고, 다음에 나열된 지원 언어의 런타임 환경을 사용한다는 것을 뜻한다.

일반적으로, 표준 환경에서 실행되는 응용 프로그램을 빌드하는 것이 더 제한적이고 복잡하지만, 응용 프로그램의 빠른 크기 조정 시간을 가질 수 있다.

표준 환경은 다음과 같은 특징이 있는 응용 프로그램에 최적화 되어 있다:
  • 지원되는 프로그래밍 언어의 특정 버전으로 소스 코드가 작성함:
    • Python 2.7
    • Java 7, Java 8
    • PHP 5.5
    • Go 1.6
  • 무료 또는 저렴한 비용으로 운영되며, 필요한 곳과 필요할 때만 비용을 지불한다. 예를 들어, 당신의 응용 프로그램이 트래픽이 없다면, 0 인스턴스로 조정 할 수 있다.
  • 즉각적인 크기 조정이 요청되는 급작스럽고 극단적으로 트래픽이 치솟음을 겪음.
고수준 기능 비교
다음 표는 두개의 환경에 대한 차이점에 대한 요약이다:
기능유연 환경표준 환경
인스턴스 시동 시간 수분 수초
최대 요청 시간만료 60 분 60 초
백그라운드 스레드 가능 제한적인 가능
백그라운드 프로세스가능 불가능
SSH 디버깅 가능 불가능
크기 조정 수동, 자동 수동, 기본으로 자동
로컬 디스크에 기록 가능, 임시적 (각 VM 시동시 디스크 초기화됨) 불가능
런타임 수정가능(Dockerfile 통해서) 불가능
자동 내부 보안 패치 가능(컨테이너 이미지 런타임 제외) 가능
네트워크 접근 가능 앱 엔진 서비스(아웃 바운드 소켓 포함)를 통해서만, 결제가 가능한 Python, Go 및 PHP 애플리케이션에만 사용할 수 있음.
써드-파티 바이너리 설치 지원가능 불가능
지역 North America, Asia Pacific, 또는 Europe North America, Asia Pacific, 또는 Europe
가격 vCPU, 메모리, 그리고 영구 디스크들의 사용에 기반함 instance 시간에 기반함
환경의 심도있는 비교는, 언어의 안내서를 참고하라: PythonJavaGo, 또는 PHP.

유연 환경을 연산 엔진과 비교

유연한 환경은 연산 엔진 VM에서 인스턴스 내의 서비스로 구동되지만, 유연한 환경은 다음 같은 점에서 연산 엔진과 차이가 있다:
  • 유연한 환경에서 사용되는 VM 인스턴스는 매주 재시작된다. 재시작 중에는, 구글의 관리 서비스는 필요한 운영 체제 및 보안 업데이트를 적용한다.
  • 항상 연산 엔진 VM 인스턴스에 root로 접속한다. 기본으로, 유연한 환경내의 VM 인스턴스에 대한 SSH 접근은 비활성화이다. 당신이 선택한다면, 앱의 VM 인스턴스에 root 접근을 활성화 할 수 있다.
  • 유연한 환경에서 사용되는 VM 인스턴스의 지리적 영역은 Cloud Platform 프로젝트의 App Engine application에 지정하는 위치에 따라 결정된다. Google의 관리 서비스는 최적의 성능을 위해 VM 인스턴스가 함께 배치되도록 한다.

표준 환경에서 유연 환경으로 이전

당신에게 표준 환경에서의 응용 프로그램이 있다면, 몇개의 서비스를 유연 환경으로 옮기고 싶어할 수 있다. 지침으로,  PythonJavaGo, 그리고 PHP의 권장 사항을 참고하라.
특정 서비스의 이전은, PythonJavaGo, 그리고 PHP에 대한 지침서를 참고하라.

2017년 8월 29일 화요일

히든싱어 다시보고픈 무대

나중에 또 보려고 퍼 옴...



원킬 - 비정 (김경호)





시즌1 이수영편 - Grace





시즌2 휘성편 - 결혼까지 생각했어





시즌2 故김광석편 - 서른 즈음에





시즌2 조현민 - 소주 한잔 (임창정)





시즌2 임성현 - For Your Soul (조성모)





시즌3 이선희편 - 그중에 그대를 만나





시즌3 임재용 - 애상 (이재훈)





시즌3 윤종신편 - 본능적으로 





시즌3 김영관 - 어떻게 사랑이 그래요 (이승환)





시즌4 김진호편 - 살다가





시즌4 민경훈편 - 남자를 몰라





시즌4 김수진 - 비몽 (신지)





시즌4 이은아 - 친구라도 될 걸 그랬어 (거미)






시즌4 정재훈 - 그대에게 (신해철)

2017년 8월 25일 금요일

2017년 G4



토미 옹의 독무대!!

필 콜린 정말 애쓴다..

왜 하필 저기에 껴서.. 취급도 못 받냐.. ㅎㅎㅎ

2017년 8월 9일 수요일

윈도우즈10에서 예약작업으로 시스템 종료 만들던 중 오류..

"하나 이상의 작업 인수가 잘못되었습니다"

라고 에러가 나오며 진행을 할 수 없을때...

"사용자 또는 그룹 선택" 대화상자에서 '고급' 클릭
새로운 대화상자에서 '지금 찾기' 클릭
검색 결과에서 "SYSTEM" 선택, 확인 클릭, 다시 확인 클릭, 확인





자꾸 반복해서 찾게 되서 아얘 적어 놓음..

2017년 7월 14일 금요일

LG G3 히든메뉴 진입

다이얼에서

*#546368#*460# 

하면 히든메뉴 진입...

매번 헤매느니 한번 적자..

2017년 7월 4일 화요일

Java로 SQL Agent Log에서 잡다한 거 빼고 보기

0. 일단.. SQL Server Profiler 한 바퀴 돌려주고

1. xml로 저장해서 java로 parsing 한다.

2. 내 맘대로 짠거임.. 알아서 변용하도록

3. 남자답게!! 출처는 밝히자!!


package com.lifebook.util;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class parseSqlLog {
 private static Connection conn = null;
 private static PreparedStatement psmt = null;
 private static ResultSet rs = null;
 private static String conUrl = "니꺼 jdbc 접속 문자열!";
 private static String[] chkFilterList = {
  "SQL:BatchCompleted",
  "Trace Stop",
  "RPC:Completed",
  "select @@microsoftversion",
  "select convert(sysname, serverproperty(N'servername'))",
  "SET TEXTSIZE 1024",
  "SELECT ISNULL(SUSER_SNAME(), SUSER_NAME())",
  "SELECT N'Testing Connection...'",
  "SET NO_BROWSETABLE ON",
  "SET NO_BROWSETABLE OFF",
  "set fmtonly off",
  "select serverproperty(N'instancename')",
  "ServerProperty('",
  "SERVERPROPERTY",
  "@@microsoftversion",
  "#err_log_tmp er",
  "SERVERPROPERTY(N'",
  "SET LOCK_TIMEOUT",
  "EXEC master.dbo.xp_readerrorlog",
  "CAST(serverproperty(N'Servername') AS sysname)",
  "DECLARE @edition sysname; SET @edition = cast(SERVERPROPERTY(N'EDITION') as sysname)",
  "select value_in_use from sys.configurations where configuration_id",
  "select is_srvrolemember('sysadmin') * 1 +is_srvrolemember('serveradmin') * 2 +is_srvrolemember('setupadmin') * 4 +is_srvrolemember('securityadmin') * 8 +is_srvrolemember('processadmin') * 16 +is_srvrolemember('dbcreator') * 32 +is_srvrolemember('diskadmin') * 64+ is_srvrolemember('bulkadmin') * 128",
  "select SERVERPROPERTY(N'servername')",
  "EXECUTE msdb.dbo.sp_sqlagent_log_jobhistory @job_id = 0xC8FAC217480CAB478E3BB07AB02962E9",
  "BEGIN TRAN UPDATE msdb.dbo.sysjobsteps SET last_run_outcome"
 };

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  try {
   File fXmlFile = new File("E:\\workspace\\parseSqlLog\\src\\com\\lifebook\\util\\20170703.xml");
   DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
   DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
   Document doc = dBuilder.parse(fXmlFile);
   doc.getDocumentElement().normalize();
   System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
   System.out.println("----------------------------");
   NodeList nList = doc.getElementsByTagName("Events");
   double rowCnt = 0d;
   for (int temp = 0; temp &lt; nList.getLength(); temp++) {
    System.out.println("item:::" + nList.item(temp).getChildNodes().getLength());
    Node nNode = nList.item(temp);
    NodeList cList = nNode.getChildNodes();
    for(int cCnt = 0 ; cCnt &lt; cList.getLength() ; cCnt ++){
     Node cNode = cList.item(cCnt);
     if (cNode.getNodeType() == Node.ELEMENT_NODE) {
      Element eElement = (Element) cNode;
      if(chkString(eElement.getAttribute("name").toString())){
       //System.out.println("name : " + eElement.getAttribute("name"));
       NodeList colsList = cNode.getChildNodes();
       for(int colCnt = 0 ; colCnt &lt; colsList.getLength() ; colCnt ++){
        Node colNode = colsList.item(colCnt);
        //System.out.println(colNode.getNodeName());
        if (colNode.getNodeType() == Node.ELEMENT_NODE) {
         Element colEle = (Element) colNode;
         //System.out.println("cols name : " + colEle.getAttribute("name"));
         if(colEle.getAttribute("name").toString().equals("TextData")){
          if(chkString(colEle.getTextContent())){
           rowCnt ++;
           //System.out.println(rowCnt + "::::::" + colEle.getTextContent());
           //System.out.println(colEle.getTextContent().toLowerCase().indexOf("select"));
           chkDbCmd(colEle.getTextContent());
           if(colEle.getTextContent().toLowerCase().indexOf("select")&gt;=0){
            //System.out.println(rowCnt + "::::::" + colEle.getTextContent());
            //chkDbCmd(colEle.getTextContent());    
           }
          }          
         }
        }
       }
      }
     }
    }
   }
  } catch (ParserConfigurationException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SAXException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 
 public static boolean chkString(String chkStr){
  boolean rtnBool = true;
  for(int chkCnt = 0 ; chkCnt &lt; chkFilterList.length ; chkCnt++){
   //System.out.println(chkStr);
   //System.out.println(chkFilterList[chkCnt]);
   //System.out.println(chkStr.indexOf(chkFilterList[chkCnt]));
   if(chkStr.indexOf(chkFilterList[chkCnt]) &gt;= 0){
    rtnBool = false;
    break;
   }
  }
  return rtnBool;
 }
 
 public static void chkDbCmd(String sql){//얘는 SQL 실행시 오류 발생하는지 알아볼라고 만든거임..
 try {
   Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
   conn = DriverManager.getConnection(conUrl);
   psmt = conn.prepareStatement(sql);
   rs = psmt.executeQuery();
   
   rs.close();
   psmt.close();
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   System.out.println(sql);
   e.printStackTrace();
  } finally {
   if (conn != null) {
    try {
     conn.close();
    } catch (Exception e) {
    }
   }
   
   if (psmt != null) {
    try {
     psmt.close();
    } catch (Exception e) {
    }
   }
   
   if (rs != null) {
    try {
     rs.close();
    } catch (Exception e) {
    }
   }
  }
 }
}

BE Band (비밴드) - 2024년 03월 02일 잠실새내 락앤롤욱스 공연

나의 10~20대를 보낸 잠실에서의 공연.. 오랜만에 가보니.. 여기가.. 마눌님과 자주 가던 영화관이었는데... 여긴 뭐가 있었는데... 란 추억도 떠올리며 기분좋게 감.​ 공연장은 좀 협소한 편이었고, 인천의 쥐똥나무 보다는 약간 크고... 인천 ...