CodeCommit

AWS는 CodeCommit을 “AWS CodeCommit은 안전한 Git 기반 리포지토리를 호스팅하는 완전관리형 소스 제어 서비스입니다.” 라고 소개하고 있습니다. 즉 GitHub의 AWS 버전입니다. CodePipeline등 AWS의 CI/CD 서비스와도 긴밀하게 연결되었고 후술할 여러 이벤트 Hook이 있어 자동화도 편리하기까지 합니다. 그래서 현재 프로젝트는 모두 CodeCommit으로 형상관리를 하고 있습니다.

서론

Devops 업무를 하다보면 CodeCommit의 여러 이벤트를 자동화하여 처리하여 효율을 높히는 방법을 고민하게 됩니다.

예를들어 PR이 생성되거나 새로운 브렌치가 생성되면 관계자에게 슬랙으로 알림을 전달하는 것 부터 보안이 철저한 회사라면 허용된 IP이외에서 레포를 다운받는걸 알람으로 받는다던지(예시입니다. 사실 이 경우는 IAM Policy를 통해 원천적으로 차단이 가능합니다.) 여러 가지 시나리오를 처리할 수 있겠지요.

CodeCommit에서는 이러한 이벤트 알람을 처리하는 방법은 크게 3가지가 있습니다.

  • CodeCommit에서 제공하는 알람을 통해 SNS호출
  • CloudWatch(EventBridge) Event Rule로 CodeCommit 이벤트를 잡아 SNS 호출
  • CloudWatch “AWS API Call via CloudTrail” 로 API 호출을 잡아 SNS호출

각 케이스에 대해서 간단히 살펴보겠습니다.

자세히 보기

AWS Config

이전 포스트에서 소개한 것 처럼 제가 관리하고 있는 AWS계정은 모든 리소스에 “Service” Tag가 붙어있어야 한다는 규칙이 AWS Config에 적용되어 모니터링 되고 있습니다. 즉, 어떤 리소스가 “Service” 태그가 붙지 않은 상태로 생성된다면 바로 슬랙으로 알림이 옵니다.

태깅이 없는 S3버킷이 생성된다면 슬랙 봇으로 이렇게 알림이 오게 됩니다.

알림이 오지 않는다?

며칠 전 Transcribe 서비스를 테스트 해 볼 일이 있어 S3 버킷을 하나 임시로 생성해서 사용하였습니다. 급하게 테스트 해볼 목적이었기 때문에 따로 태깅을 넣지 않았고 당연히 Config메세지가 슬랙으로 올 것을 기대하고 있었지만 몇 시간이 지나도 감감 무소식이었습니다. 이전에도 이런 일이 몇 차례 있었기 때문에 저는 AWS Support 티켓을 끊어서 물어보기로 했습니다. (저희 회사는 Business Plan에 가입되어 있어서 빠르게 응답을 받을 수 있습니다.)

대충 대화 내용은 이렇습니다.

  • 나: AWS Config에 태깅을 검사하는 규칙을 만들어놓고 모니터링 중인데, 태깅 없이 S3 버킷을 생성해도 알람이 울리지 않는다. 벌써 1시간 반이 지났다.
  • 상담원: AWS Conifg 인벤토리에 해당 버킷이 있는가?
  • 나: (찾아보고) 없다.
  • 상담원: 보통 몇 분 안에 인벤토리에 등록되는게 정상이다. 원인을 알아보겠다. 다른 버킷을 생성해도 그런가?
  • 나: (다른 버킷을 생성 후) 방금 생성한 버킷은 잘 등록된다.
  • 상담원: 흠… 해당 부서에 티켓을 끊어 자세히 알아보겠다.
  • 나: 부탁한다.

그렇게 채팅은 종료되었고 해당 케이스를 좀 더 조사해보겠다고 팔로우업 이메일이 왔습니다.

갑자기 알림이 울렸다.

버킷 생성후 약 4시간 반이 지났을 무렵 갑자기 알림이 똑 하고 나타났습니다. 아예 알림이 울리지 않은것도 아니라 4시간이나 딜레이 되었다는 것이 이 사건을 더욱 아리송하게 만들었습니다.

결국 알림이 오긴 왔습니다.

며칠 후 답변이 오다.

바쁜 일정에 잊고 지낸 며칠이 지난 후, 장문의 답장이 아래처럼 도착했습니다.내용 하나하나가 중요하기에 전문을 인용하겠습니다.

자세히 보기

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

AWS PRO시험을 보았다.

AWS 솔루션즈 아키텍트 프로페셔널 시험을 보고 합격하였다.
AWS 솔루션즈 아키텍트 프로페셔널(이하 SA PRO) 시험은 AWS의 여러 자격증 시험중 AWS의 클라우드 이키텍쳐를 설계하는 부분을 담당하는 시험이다.

다양한 시험이 존재한다.

SA PRO 시험은 PRO의 아래 단계인 Associate 시험보다 상당히 어렵고 요구하는 지식 역시 매우 방대하다. 어려운 시험인 만큼 공부하는 동안 많은 지식을 습득할 수 있었다.

시험 후기

  • 시험 장소
    문정역의 SRTC에서 보았다. 깔끔한 시험장이 인상적이었다. 신분증과 내 명의의 신용카드를 ID로 제시하면 간단한 확인과 함께 시험에 관한 전반적인 안내사항을 알려준다. 주의할것은 시험실에 입실하기 전 주머니 체크를 하는데 목걸이와 반지등의 악세사리도 반입 불가이다. 단 결혼반지는 가능하다고 하여 번거롭게 결혼반지를 뺄 필요는 없었다. 참고로 시험 대기실에선 전자기기 사용 금지기 때문에 태블릿 등으로 마지막 점검을 하려 한다면 주의하자. 또한 코로나때문에 발열이나 기침이 있을땐 시험을 볼 수 없다.

  • 시험 환경
    연필 두개와 여러장의 A4용지가 주어졌다. A4용지는 여러 용도로 쓰였는데 주로 리뷰가 필요한 문제 번호 적어두기와 Migration 시간 계산하기에 사용하였다. (무엇인진 밑에 팁에 서술)

  • 시험 시간 및 문제들
    180분동안 75문제를 풀어야 하는데, 한 문제당 2.4분 정도가 주어진다. 사실 시간 자체는 그렇게 모자란 편은 아니었지만 문제는 집중력이었다. 쉴세없이 3시간(아래 언급할 추가시간을 합치면 3시간 30분)동안 집중하는건 너무너우 어려웠다. 75문제를 다 풀었을때 검토할 시간도 있었지만 검토 자체를 때려치고 싶을 정도로 지쳐있었다. 시험을 준비할때 아래 언급할 연습문제 등에 꼭 시간체크를 해서 한번에 쉬지않고 180분동안 75문제를 푸는 경험을 해보는 것이 꼭 필요할 듯 싶다. 필자는 문제와 보기를 읽고 한번에 답이 나오지 않는 문제는 과감히 리뷰할 문제로 적어두고 스킵하여 마지막 문제까지 푼 다음 천천히 시간을 가지고 못푼 문제를 풀었다.

합격 팁

필자는 한번에 시험을 합격하였고 합격을 위한 지극히 개인적인 팁을 공유하고자 한다. 참고로 필자는 영어로 시험을 보았는데, 시험 자체는 한국어도 지원을 하긴 한다. 다만 번역 자체가 그다지 매끄럽지 못하고 시험 유형도 영어에 비해서 최신 기술들을 반영하지 않아 필자는 영어가 더 편했다. 물론 덤프 등으로 외워서 합격을 노린다면 최신 유형의 문제가 빨리 빨리 반영되는 것이 더 불리할 수 있지만 개인적인 목표는 실력을 키우는것이었기 때문에 크게 문제는 없었다.

  1. Assoicate 시험을 먼저 보자
    예전에는 PRO시험을 보기 위해서는 Associate 시험에 합격해야 했으나 이제는 PRO 시험을 보기위한 다른 요구조건은 폐지되었다. 다만 필자는 PRO 시험을 준비한다면 Assoicate 시험에 우선 합격하는 것을 강력하게 추천한다.
자세히 보기

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로 웹사이트를 직접 호스팅 하는 부분은 다루지 않겠다.)

자세히 보기