구글시트 함수

거래처 목록을 구글시트로 관리한다면, 사업자번호 옆 칸에 =CHOM(A2, "상태")처럼 쓰면 국세청 상태·세금계산서 가능 여부 등을 채울 수 있습니다. 촘촘 API 키(무료, 월 1,000건)가 필요합니다.

설정 (처음 한 번)

  1. 마이페이지 > API에서 키를 발급합니다.
  2. 구글시트에서 확장 프로그램 > Apps Script를 엽니다.
  3. 아래 코드를 모두 복사해 붙여 넣고 저장합니다.
  4. 시트를 새로고침하면 위쪽에 촘촘 메뉴가 생깁니다. 촘촘 > API 키 넣기에 발급한 키를 넣습니다. 처음 실행할 때 구글이 권한(외부 서비스 연결)을 물으면 허용합니다.
/**
 * 촘촘(chom.kr) 구글시트 함수
 *   =CHOM(사업자번호, "항목")   예) =CHOM(A2, "상태")   =CHOM(A2:A100, "세금계산서")
 * 항목: 상호, 상태, 과세유형, 폐업일, 세금계산서, 대표자, 주소, 업종, 직원수, 설립일
 * 처음 한 번: 메뉴 [촘촘 > API 키 넣기]에서 마이페이지의 API 키를 넣는다.
 * 같은 번호는 6시간 동안 다시 묻지 않는다(무료 월 1,000건 한도를 아끼기 위해).
 */
const CHOM_API = "https://chom.kr/v1/biz/";

function onOpen() {
  SpreadsheetApp.getUi().createMenu("촘촘").addItem("API 키 넣기", "chomSetKey").addToUi();
}

function chomSetKey() {
  const ui = SpreadsheetApp.getUi();
  const r = ui.prompt("촘촘 API 키", "chom.kr 마이페이지 > API 탭에서 발급한 키를 붙여 넣으세요.", ui.ButtonSet.OK_CANCEL);
  if (r.getSelectedButton() === ui.Button.OK) {
    PropertiesService.getUserProperties().setProperty("CHOM_KEY", r.getResponseText().trim());
    ui.alert("저장했어요. 이제 =CHOM(사업자번호, \"상태\")를 쓸 수 있어요.");
  }
}

/**
 * 촘촘에서 사업자 정보를 가져옵니다.
 * @param {string|Array} bizno 사업자등록번호(하이픈 있어도 됨) 또는 범위
 * @param {string} field 상호·상태·과세유형·폐업일·세금계산서·대표자·주소·업종·직원수·설립일
 * @customfunction
 */
function CHOM(bizno, field) {
  if (Array.isArray(bizno)) return bizno.map((row) => row.map((v) => CHOM(v, field)));
  const no = String(bizno || "").replace(/\D/g, "");
  if (!no) return "";
  if (no.length !== 10) return "번호 확인";
  const d = chomFetch(no);
  if (typeof d === "string") return d;
  const s = d.status || {}, tax = s.taxType || "";
  switch (String(field || "상태").trim()) {
    case "상호": return d.name || "";
    case "상태": return s.nts || "조회 기록 없음";
    case "과세유형": return tax;
    case "폐업일": return s.closedOn || "";
    case "세금계산서": return chomInvoice(s.nts, tax);
    case "대표자": return d.ceo || (d.type === "개인" ? "(개인사업자 비공개)" : "");
    case "주소": return d.address || (d.type === "개인" ? "(개인사업자 비공개)" : "");
    case "업종": return (d.industry && d.industry.name) || "";
    case "직원수": return d.employees == null ? "" : d.employees;
    case "설립일": return d.founded || d.opened || "";
    default: return "항목 확인";
  }
}

function chomFetch(no) {
  const cache = CacheService.getUserCache();
  const hit = cache.get("chom:" + no);
  if (hit) return JSON.parse(hit);
  const key = PropertiesService.getUserProperties().getProperty("CHOM_KEY");
  if (!key) return "API 키 필요(메뉴 촘촘)";
  const r = UrlFetchApp.fetch(CHOM_API + no, { headers: { Authorization: "Bearer " + key }, muteHttpExceptions: true });
  const code = r.getResponseCode();
  if (code === 404) return "없는 번호";
  if (code === 401) return "API 키 확인";
  if (code === 429) return "한도 초과(잠시 뒤)";
  if (code !== 200) return "조회 실패";
  const d = JSON.parse(r.getContentText()).data;
  cache.put("chom:" + no, JSON.stringify(d), 21600);
  return d;
}

// 국세청 상태·과세유형으로 세금계산서를 받을 수 있는지(촘촘 상세 화면과 같은 기준)
function chomInvoice(stt, tax) {
  if (stt === "폐업자") return "불가(폐업)";
  if (stt === "휴업자") return "불가(휴업)";
  if (tax.indexOf("사업자단위과세") >= 0) return "불가(본점 번호로 발급)";
  if (tax.indexOf("간이과세자(세금계산서 발급사업자)") >= 0) return "가능";
  if (tax.indexOf("간이과세자") >= 0) return "불가(간이과세자)";
  if (tax.indexOf("일반과세자") >= 0) return "가능";
  if (tax.indexOf("면세사업자") >= 0) return "계산서(면세)";
  if (tax.indexOf("고유번호") >= 0 || tax.indexOf("비영리") >= 0) return "불가(고유번호)";
  return "";
}

쓰는 법

=CHOM(A2, "상태")계속사업자·휴업자·폐업자
=CHOM(A2, "세금계산서")가능 · 불가(간이과세자) · 계산서(면세) 등
=CHOM(A2, "상호")상호. 그 밖에 과세유형·폐업일·대표자·주소·업종·직원수·설립일
=CHOM(A2:A100, "상태")범위를 넣으면 한 번에 채웁니다.

알아 둘 점

  • 상태는 촘촘이 국세청에 조회해 둔 값(보통 주 1회 갱신)입니다. 거래 직전에는 촘촘 기업 상세의 '지금 다시 확인'이나 홈택스로 다시 확인하세요.
  • 같은 번호는 6시간 동안 다시 묻지 않아 한도를 아낍니다. 한 번 호출이 API 1건으로 셉니다.
  • 개인사업자의 대표자·주소는 나오지 않습니다.
  • 키는 이 시트를 쓰는 본인 계정에만 저장됩니다(Apps Script 사용자 속성). 시트를 공유해도 키는 함께 넘어가지 않습니다.