AWS Rekognition을 사용해서 사업자등록증 검증하기

사업자 등록증을 처리

웹사이트에 구축한 플랫폼의 백엔드 작업중 프론트엔드 유저가 사업자등록증을 올렸을때 올바른 사업자등록번호인지를 검증하는 로직이 필요하게 되었다. 회사명 및 주소등의 정보는 필요가 없었고 단지 사업자 번호가 올바른지를 검증하면 되는 간단한 작업이었고 AWS Rekognition을 사용하여 처리한 경험을 간단히 공유하고자 한다.

참고로 Lambda 및 API Gateway는 Serverless를 통해 배포하였기 때문에 여기서는 생략하고 람다 내용만 공유한다.

우선 아키텍쳐 다이어그램을 보자

간단한 아키텍쳐 다이어그램

대략적인 워크플로우는 다음과 같다.

  1. API Gateway를 통해 제공되는 REST API를 통해 이미지를 업로드한다.
  2. Lambda에서 이미지를 AWS Rekognition에 보내 사업자 등록번호를 뽑아온다.
  3. 사업자 등록번호가 올바른 번호인지 검증한다.
  4. 검증 통과시 metadata 및 적절한 Key를 부여하여 S3에 업로드 한다.

AWS Lambda 구현

Lambda는 Javascript로 작성하였으며 다음 기능으로 구성되어 있다.

  1. 이미지를 파싱하고 원본 파일명을 저장

  2. 파싱한 Rekognition에 요청하여 Text 검출

  3. 검출된 Text중 사업자등록번호를 검출

  4. 사업자 등록번호가 검출되었을 경우 이미지에 메타데이터로 세팅하고 S3업로드

    ... 생략
    
    //버킷명은 환경변수에 세팅되어 있다.
    const bucketName = process.env.file_bucket_name;
    
    var input = JSON.parse(event.body);
    //무작위로 파일 키를 생성하기 위해 현재 시간 타임스탬프를 기준으로 키를 만든다.
    
    let key = moment().valueOf() + ""
    
    //base64로 인코딩 된 이미지를 버퍼에서 받아온다.
    const buf = Buffer.from(input.data, "base64");
    
    //등록번호는 우선 undefined
    let companyId = undefined;
    
    //AWS Rekognition
    const rekognition = new AWS.Rekognition();
    //인식을 요청하기 위한 파라메터. 받아온 이미지를 넣어준다.
    const params = {
        Image: {
            Bytes: buf
        },
    };
    
    const detectedTexts = await rekognition.detectText(params).promise();
    
    //찾아낸 텍스트들을 돌면서 사업자등록번호를 뽑는다.
    detectedTexts.TextDetections.forEach((item, index) => {
    
        const detectedText = item.DetectedText;
        //사업자등록번호인지 체크
        if (checkCorporateRegistrationNumber(detectedText)) {
            companyId = detectedText;
        }
    });
    
    //companyId가 undefined라면, 즉 아직 올바른 사업자등록번호를 못 찾았다면,
    if(!companyId){
       //...생략
       //에러 메세지 처리
    }
    //이미지 업로드
    
    //원본 파일명. 다운로드할때 필요하다.
    const filename = input.filename;
    
    //메타데이터 세팅. 원본 파일명과 사업자등록번호를 넣어준다.
    let metaData = {
        //한글 파일명등의 처리를 위해서 Base64 인코딩을 꼭 해주어야 한다. 
        "filename": Base64.encode(filename),
        "company_id":companyId
    }
    
    var data = {
        Bucket: bucketName,
        Key: key,
        Body: buf,
        Metadata: metaData
    
    };
    //S3로 업로드
    try {
        await s3.putObject(data).promise()
    } catch (e) {
        console.log(e);
        //에러 처리
    }
    .. 생략

사업자 등록번호를 검증하기 위한 로직은 “Mr.latte” 님의 블로그에서 참고하여 사용하였다.

    //https://www.mrlatte.net/code/2019/01/21/check-corporate-registration-number.html
    function checkCorporateRegistrationNumber(value) {
        var valueMap = value.replace(/-/gi, '').split('').map(function (item) {
            return parseInt(item, 10);
        });

        if (valueMap.length === 10) {
            var multiply = new Array(1, 3, 7, 1, 3, 7, 1, 3, 5);
            var checkSum = 0;

            for (var i = 0; i < multiply.length; ++i) {
                checkSum += multiply[i] * valueMap[i];
            }

            checkSum += parseInt((multiply[8] * valueMap[8]) / 10, 10);
            return Math.floor(valueMap[9]) === (10 - (checkSum % 10));
        }
        return false;
    }

아쉬운점

사업자 등록증의 상호명, 주소 등등의 내용은 가져올 수 없었다. 왜냐하면 AWS Rekognition 자체에서 한국어를 지원하지 않기 때문이다.

AWS의 여러 ML 관련 서비스는 영어 컨텐츠에 대해서는 어마무지한 성능을 보여주나 한국어는 아직 네이버 등과 같은 우리나라 서비스들과 비교해서 볼품없는 것 같다. AWS Transcribe, AWS Rekognition, AWS Comprehend 등 여러 서비스들의 한국어 지원이 미흡한 것이 사실이라 차차 한국어를 지원하는 서비스들이 늘어나기를 기대해본다.

WRITTEN BY
Dev Lead | Certified Professional AWS Solutions Architect/Devops Engineer

S3 Ridrection 기능을 사용하여 주소 리다이렉션 처리

S3는 AWS의 매우 강력하고 안정적인 파일 저장 서비스이다. S3의 여러 멋진 기능중의 하나는 정적 호스팅 기능인데, 동적인 컨텐츠가 아닌 정적인 컨텐츠를 호스팅 해주는 기능으로 PHP,JSP등의 동적인 웹사이트가 아닌 HTML/Javascript 기반의 웹페이지 처럼 정적인 웹사이트를 엄청나게 저렴한 비용으로 호스팅해준다.

이전 웹사이트들은 정적인 웹사이트였기 때문에 S3에서 호스팅하였고, 그에 따라 각 도메인에 대응하는 버킷이 이미 호스팅 설정이 된 상태로 존재하였다.

(참고로 Route53에서 S3호스팅 주소로 연결하기 위해서는 도메인과 버킷명이 같아야한다. 즉 example.net을 S3에서 호스팅하려면 버킷명도 example.net이어야 한다.)

그럼 S3의 정적 호스팅기능을 통해 도메인 리다이렉션을 처리해보자.

S3 버킷을 선택후 속성 탭으로 가면 정적 웹 사이트 호스팅이 있다.

S3버킷에서 리다이렉션을 처리는 두 가지 방법이 있다.

  • 웹 사이트를 호스팅하고 리다이렉션 규칙을 적용하기
  • 요청 리다이렉션 사용하기

리다이렉션 규칙 사용

웹사이트를 호스팅하고 리다이렉션 규칙을 적용하는것은 일반적으로 웹 사이트는 호스팅하고 있으나 특정 주소나 상황에 한해서 리다이렉션 규칙을 적용하기를 원할 때 사용한다.

"이 버킷을 사용하여 웹 사이트를 호스팅합니다." 를 클릭하면 리다이렉션 규칙을 사용할 수 있다.

자세히 보기

Route53으로 새 도메인을 CloudFront로 연결하기

Route53를 Alias 레코드로 CloudFront로 연결하기


CloudFront를 Route53를 사용하여 도메인 연결을 하기 위해서는 먼저 두 가지를 알아야 한다.

  • CloudFront는 고정된 IP를 사용하지 않는다 :CloudFront를 포함한 AWS의 많은 서비스들(ELB,CloudFront,RDS 등)은 고정된 IP를 사용하지 않는데 인스턴스 사이즈가 수시로 바뀌면서 IP가 매번 바뀌거나 특정 DR(Disaster Recovery) 상황에선 IP주소가 다른 주소로 바뀌기 때문이다. 예외적으로 CloudFront의 경우 SNI 지원등의 문제로 고정 IP를 부여할 수는 있으나 한달에 $600을 받는다.
  • Apex Domain은 CNAME을 사용할 수 없다. : CNAME 레코드란 한 도메인을 다른 도메인으로 포워딩 해주는 레코드 타입인데, Apex Domain(순수 도메인, 즉 www.example.com, test.example.com처럼 맨 앞에 무엇인가가 붙은게 아닌 순수한 example.com)은 CNAME을 사용할 수 없다. (표준에 관련한 문제다. 자세한 사항은 나중에 기회가 되면 포스팅하도록 하겠다.)

APEX 도메인에 CNAME을 적용하려 하면 Route53에서도 에러를 뿜어준다.

해결 방법은 몇 가지가 있다.

  • WWW.회사명.ai사용: www.회사명.ai 같이 www를 뒤에 붙여 cloudfront를 붙인다.
  • AWS의 Alias 레코드를 사용

첫번째 방법은 그닥 우아한 방법이 아니다. 도메인에 군더더기가 붙은 듯한 느낌도 들고 원래 요청사항에도 어긋난다. 조금더 우아한 방법은 바로 Alias 레코드를 사용하는 것이다.

자세히 보기

Route53 호스팅존 만들기

지난 포스팅에서는 새로 구매한 도메인을 Route53에서 호스팅하는 부분을 다루었다. 오늘은 CloudFront를 연동하는 부분을 진행해보도록 하자.

SSL 인증서 만들기

CloudFront를 연결하기 전에, HTTPS를 지원하기 위한 인증서를 만들어야 한다. 보통은 다른 업체에 돈을 주고 인증서를 마련해야 하지만, AWS의 경우 ACM(AWS Certificate Manager)를 사용하여 무료로 인증서를 만들 수 있고, 갱신도 자동으로 해준다.

우선 ACM으로 이동한 후 리전을 바꿔줘야 한다. 왜냐하면 CloudFront는 Global Service이긴 하지만, 인증서를 가져올때는 us-east-1 리전에서 가져오기 때문에 us-east-1리전에서 만들어야 하기 때문이다. 따라서 우측 상단의 리전 선택 메뉴에서 us-east-1을 선택 하자

여러 개의 리전중 제일 위에 위치한 us-east-1을 선택

인증서 요청 버튼을 누르면 공인 인증서와 사설 인증서 중에 선택할 수 있는데, 우리는 외부 유저가 접속에 필요한 인증서를 만드려고 하기 때문에 공인 인증서를 선택한다.

  • *.회사명.ai : “www.회사명.ai” 혹은 “image.회사명.ai” 처럼 앞에 무엇이 붙는 경우를 위한 것이다.
  • 회사명.ai : APEX도메인, 도메인명 자체를 위한 것이다.

두 개의 레코드를 넣고 인증서 생성을 요청한다.

필요하다면 여러 도메인을 위한 인증서를 한번에 만들 수 도 있다. 그림에서는 .com도메인도 같이 설정하였다.

실제 인증서를 만드려면 생성하려는 인증서에 해당하는 도메인을 실제로 보유하고 있는지를 검증해야 하는데, 검증 방법은 이메일 혹은 CNAME Record를 생성하여 검증할 수 있다. 다만 Route53에서 호스팅할경우 버튼 클릭 한번으로 레코드를 생성해주기 때문에 편리하게 생성할 수 있다.

Route53에서 도메인을 호스팅하고 있다면, 이렇게 클릭 한번으로 검증 레코드를 생성할 수 있다. 아니라면 직업 생성해주어야 한다.

검증은 약 5분정도 걸렸다.

발급완료 라는 초록 글씨가 뜨면 생성이 완료되었다는 뜻이다. 이제 CloudFront와 연동해보자.

자세히 보기

CloudFront 생성 및 SSH/TLS용 인증서 연동

업무가 감지되었습니다.


아침에 출근하니 작업표시줄의 슬랙 아이콘에 빨간 뱃지가 나를 맞이해주었다. 길게 심호흡을 하고 슬랙을 실행시켜 메세지를 확인한다.

ㄷㄷㄷ

긴 글의 내용을 요약하면 다음과 같다.

  1. 회사 마케팅 정책의 일환으로 회사의 아이덴티티를 강조하기 위해 회사 웹사이트의 도메인을 “회사명.AI” 도메인으로 통일 시키기로 함(기존에는 .net , .io등 여러 TLD(최상위 도메인)을 사용하고 있었다.)

  2. 따라서 기존에 회사 홈페이지로 연결되는 모든 도메인을 “회사명.AI”로 리다이렉션 시켜야 함 (예: “회사명.com”으로 접속할 시 자동으로 “회사명.AI”로 접속)

  3. 얼마나 걸릴까요?

다행히 큰 일은 아니었기 때문에 퇴근시간은 지킬 수 있어보인다.

우선 현재 아키텍쳐를 살펴보자

현재 상황

  • 웹서버는 ALB(Application Load Balancer)뒤에 EC2가 병렬로 붙어있다.
  • 현재 Route53에서 직접 ALB로 포워딩 되어 있다.
  • CDN등의 서비스는 붙어있지 않다.

해야할 일

  • 우선 “회사명.AI” 도메인을 구입하고 도메인 관리 : AWS에 Registar에서 .AI 도메인이 등록 가능한지 확인후 Route53에서 호스팅 영역을 만든다.
  • CloudFront 붙이기 : 호스팅중인 웹서버 인프라를 AWS의 CDN 서비스인 CloudFront를 연동시킨다.
  • 웹사이트를 “회사명.AI”의 주소로 리다이렉션 : CloudFront로 “회사명.AI”로 도메인을 연결해주고, 이 과정에서 HTTPS 연결이 가능하도록 설정한다.
  • 기존 도메인의 리다이렉션 : 기존 도메인들(회사명.com, 회사명.net 등등)을 “회사명.AI”로 리다이렉션 시켜야 한다

기존의 아키텍쳐에서 새로운 아키텍쳐로

알아보니 도메인 구매는 완료되어 있었고 그럼 지체할 필요가 없으니 바로 업무 시작!
(이번 포스트에서는 EC2로 웹사이트를 직접 호스팅 하는 부분은 다루지 않겠다.)

자세히 보기