스토리 홈

인터뷰

피드

뉴스

개발에 관심있다면 꼭 읽어야하는 글
조회수 1438

반복적인 모니터링 프로세스 구축

IT 서비스에 장애가 발생 할 경우 모니터링 프로세스는 장애를 찾는 것으로 끝나지 않습니다. 장애를 발견하는 것은 모니터링 프로세스의 시작 점이며 최종적으로 모니터링을 통해 장애의 근본 원인을 찾아낼 수 있어야 합니다. 그리고 찾아낸 원인들은 예측과 추론에서 확인까지 이르는 하나의 프로세스로 정착되어 다시금 모니터링 과정에 포함되어져야 합니다. 이렇게 서비스를 운영하는 과정에서 근본적인 장애를 찾기 위해 모니터링을 어떻게 이해해야 하는지 알아보겠습니다. 우리가 모니터링 해야 하는 지표어플리케이션 지표(WORK METRICS)- 처리량 지표(THROUGHPUT)- 성공 지표(SUCCESS)- 에러 지표(ERROR)- 성능 지표(PERFORMANCE)시스템 지표(RESOURCE METRICS)- 가동률(UTILIZATION)- 포화상태(SATURATION)- 에러 지표(ERROR)- 이용률(AVAILABILITY)이벤트(EVENTS)- 코드 변경(CODE CHANGES)- 경고 알림(ALERTS)- 규모 변경(SCALING EVENT)- 기타(ETC)IT 서비스를 운영하는 과정에서 발생하는 문제의 근본원인을 추적하기 위한 모니터링 데이터는 크게 3가지로 나눌 수 있습니다. 어플리케이션 지표(Work metrics)서비스의 흐름(트렌젝션)을 측정하여 시스템의 최상위 레벨의 이슈를 보여줍니다. 시스템 지표(Resource metrics)이용률, 상태, 에러 또는 시스템 의존적인 리소스의 이용률을 수량화합니다.이벤트(Events)코드변경, 내부 경고, 확장 이벤트와 같이 드물게 발생하는 불연속적이 이슈를 보여줍니다.일반적으로 IT 모니터링의 핵심 이슈는 어플리케이션 지표를 통해 확인할 수 있습니다. 하지만 다른 지표들 또한 어플리케이션의 지표에서 나타난 문제의 원인을 찾기 위한 중요한 요소이기 때문에 같이 모니터링 해야 합니다. 시스템 지표를 통한 모니터링인프라스트럭쳐는 대부분 시스템의 자원으로 구성됩니다. 최상위 수준에서 유용한 작업을 하는 각각의 시스템들은 다른 시스템들과 연동하기도 하는데요. 예를 들어, 여러분의 아파치 서버가 MySQL 데이터베이스를 자원으로 사용하여 요청을 처리하는 작업을 지원할 수 있습니다. 연관된 작업을 따라 들어가보면 MySQL은 제한된 커넥션 풀을 관리하기 위한 리소스를 가지고 있고 MySQL이 실행되는 서버의 물리적인 리소스 레벨에서는 CPU, Memory, Disk 같은 지표를 보게 됩니다.어플리케이션이 서비스를 제공하는 데 있어서 각각의 리소스가 그 작업을 지원한다면 우리는 장애가 발생한 경우에, 필요한 원인을 얻는 좋은 방법을 시스템을 통해서도 찾아볼수 있습니다. 이런 프로세스를 만들어 간다면 시스템에서 발생한 경고를 통해 장애의 원인을 체계적인 조사하는데 도움이 될 것입니다. 1. 최상위 어플리케이션 지표에서 시작하기첫번째 해야 하는 질문은 "발생한 장애를 설명할 수 있는가?" 이다. 처음부터 문제를 명확하게 정의하지 못하면 이슈를 분석하기 위해 파고들어가야 하는 시스템 패스를 잃어버릴 확률이 높다.다음으로 문제가 있을 것으로 보여지는 최상위 시스템의 작업 지표를 검사해라. 이 지표들은 종종 문제의 원인을 알아내거나 또는 적어도 추적해야 하는 방향을 알려 줄 것이다. 예를 들어 성공적으로 진행된 작업의 성공율이 한계치 이하로 떨어졌다면 에러 지표를 찾아보고 반환된 에러의 형러의 타입을 살펴봄으로써 문제의 방향을 찾아나갈 것이다. 반면에, 대기시간이 길고 외부 시스템에 의해서 요청된 작업처리량이 매우 높다면 시스템 과부하로 인한 문제일 확률이 높다. 다만 와탭의 어플리케이션 분석 서비스를 사용한다면 약간 방법을 달리해도 된다. 와탭의 성능 분포도(어플리케이션 히트맵)와탭의 어플리케이션 성능 분포도를 통해 문제가 발생한 트랜잭션을 드래그하여 선택하게 되면 실제 어플리케이션에서 발생하는 스탭들을 추적하여 문제 해결에 바로 도달할 수도 있다. 하지만 더 복잡한 형태의 장애라면 시스템의 리소스 정보를 찾아봐야 합니다.  2. 리소스 찾아보기최상위 work metrics를 조사하여 문제의 원인을 알수 없다면, 다음으로 시스템이 사용하는 리소스(물리적인 요소 뿐만 아니라 시스템의 리소스 역할을 하는 소프트웨어 또는 외부 서비스)들을 조사합니다. 해당 리소스가 높다면 리소스를 사용하는 하위 Application 지표를 찾아보는 방식으로 찾아나갑니다. 와탭의 데시보드(CPU, MEMORY)3. 변경 내용 찾아보기다음으로 지표에 연관된 경고와 다른 이벤트들을 살펴봅니다. 문제가 발생하기 직전 코드가 릴리즈 되었거나, 내부 경고가 발생하고나 다른 이벤트가 등록되었다면 문제와 연관된 부분을 찾아봐야 합니다. 4. 수정하기 (잊지 말기)문제의 원인을 찾았다면 문제의 원인이 되는 상태를 수정해보고 증상이 사라지는 것을 확인합니다. 증상이 더이상 나오지 않는다면 향후 유사한 문제를 피하기 위해 시스템을 어떻게 변경할지 고민해야 합니다.  서비스가 중단된 상황이 오면 1분이 중요합니다. 문제를 찾는 속도를 높이기 위해 눈앞에서 벌어진 상황에 대한 높은 집중력을 유지하면서 대쉬보드를 상황에 맞춰 재 조정합니다. 최상위 어플리케이션 데쉬보드와 각각의 서브시스템들을 위한 대시보드를 하나씩 설정합니다. 시스템 대시보드는 시스템 지표의 하위 시스템의 키 메트릭스와 함께 어플리케이션 메트릭을 확인 할 수 있어야 합니다. 이벤트 데이터도 이용가능한 상황이라면 연관 분석 차트에서 관련된 이벤트가 올라가 있어야 합니다. 와탭의 알림 서비스정리하기   서비스에 장애는 무조건 발생하지만 우리는 모니터링을 통해 빠르게 해결 할 수 있습니다. 이를 위해 표준화된 모니터링 프로세스를 만들고 대시보드로 연관관계를 만들어 놓는다면 문제를 빠르게 추적 조사할 수 있습니다. 가능하면 모든 지표는 어플리케이션 지표에서 부터 찾을 수 있도록 대시보드를 구성합니다.인프라스트럭처를 통해서도 문제를 분석할 수 있습니다. 시스템에 대해 대시보드를 설정하고 주요 지표들을 올려놓아야 합니다. 문제의 원인을 조사하는 것은 증세가 나타나는 최상위 시스템에서 부터 시작합니다. 문제가 되는 리소스가 발견되면 문제를 발견하고 수정할 때가지 리소스에서 발견되는 패턴을 조사하고 적용시키는작업을 반복해야 합니다. #와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1177

테이블을 내 마음대로! 컬럼 추가와 삭제, 테이블 분리

Overview이전까지는 단일 테이블에서 INDEX를 적용하는 효과적인 방법들을 살펴봤습니다. 아직 못 본 개발자를 위해 친절히 링크도 준비했습니다. 이 글을 보기 전에 아래의 글들을 먼저 보는 것이 좋습니다.단일 TABLE을 SELECT하자!: 올바른 SELECT문 작성하기순서대로 척척, ORDER BY: ORDER BY 조건 처리 알아보기원하는 대로 뭉치는 GROUP BY: GROUP BY 조건 처리 알아보기이번 글에서는 테이블에서 컬럼을 추가 또는 삭제하고, 테이블을 분리하는 방법까지 알아보겠습니다.Let’s do it먼저 아래의 컬럼을 추가해봅시다.ALTER TABLE test.TB_MBR_BAS ADD COLUMN AREA_NM    VARCHAR(10)    COMMENT '지역 명'; 그리고 테스트 자료를 넣습니다.UPDATE test.TB_MBR_BAS SET     AREA_NM =         CASE FLOOR(RAND()*15)             WHEN 0    THEN '서울특별시'             WHEN 1    THEN '부산광역시'             WHEN 2    THEN '인천광역시'             WHEN 3    THEN '대전광역시'             WHEN 4    THEN '대구광역시'             WHEN 5    THEN '광주광역시'             WHEN 6    THEN '울산광역시'             WHEN 7    THEN '경기도'             WHEN 8    THEN '강원도'             WHEN 9    THEN '충청남도'             WHEN 10    THEN '충청북도'             WHEN 11    THEN '전라남도'             WHEN 12    THEN '전라북도'             WHEN 13    THEN '경상남도'             WHEN 14    THEN '경상북도'             WHEN 15    THEN '제주도'         END WHERE AREA_NM IS NULL ; 자료를 확인하면 아래와 같이 나옵니다.SELECT     * FROM test.TB_MBR_BAS ; AREA_NM 컬럼을 추가해 지역이 나오도록 했습니다. AREA_NM을 보면 중복되는 지역명이 있습니다. 이럴 때 보통 AREA_NM을 별도의 테이블을 만들어 ID OR 코드를 부여해 처리합니다. 위의 UPDATE 문을 참조하여 ID를 만들면 아래와 같이 만들 수 있습니다.0    : ‘서울특별시’1    : ‘부산광역시’2    : ‘인천광역시’3    : ‘대전광역시’4    : ‘대구광역시’5    : ‘광주광역시’6    : ‘울산광역시’7    : ‘경기도’8    : ‘강원도’9    : ‘충청남도’10    : ‘충청북도’11    : ‘전라남도’12    : ‘전라북도’13    : ‘경상남도’14    : ‘경상북도’15    : ‘제주도’먼저 AREA_NM과 ID를 다룰 테이블을 만들겠습니다.CREATE TABLE test.TB_AREA_BAS  (     AREA_ID        TINYINT UNSIGNED NOT NULL    COMMENT '지역 아이디 '     ,AREA_NM     VARCHAR(10)             NOT NULL    COMMENT '지역 명'     ,PRIMARY KEY (AREA_ID)  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='TB 지역 기본' ; 테이블을 만들었으면 자료를 넣어줍니다. INSERT INTO test.TB_AREA_BAS  (     AREA_ID      ,AREA_NM  ) VALUES (0,'서울특별시')  ,(1,'부산광역시')  ,(2,'인천광역시')  ,(3,'대전광역시')  ,(4,'대구광역시')  ,(5,'광주광역시')  ,(6,'울산광역시')  ,(7,'경기도')  ,(8,'강원도')  ,(9,'충청남도')  ,(10,'충청북도')  ,(11,'전라남도')  ,(12,'전라북도')  ,(13,'경상남도')  ,(14,'경상북도')  ,(15,'제주도')  ; 자료를 확인하면 아래와 같이 나옵니다.SELECT     * FROM test.TB_AREA_BAS ; 테이블을 만들었다면 test.TB_MBR_BAS 테이블에 AREA_ID 를 추가하여 자료를 넣은 후 AREA_NM 컬럼을 삭제하면 됩니다.이제 AREA_ID를 추가합니다.ALTER TABLE test.TB_MBR_BAS ADD COLUMN AREA_ID TINYINT UNSIGNED NOT NULL COMMENT '지역 아이디'; AREA_NM을 참조하여 AREA_ID를 넣습니다.UPDATE test.TB_MBR_BAS SET     AREA_ID =         CASE AREA_NM             WHEN '서울특별시'    THEN 0             WHEN '부산광역시'    THEN 1             WHEN '인천광역시'    THEN 2             WHEN '대전광역시'    THEN 3             WHEN '대구광역시'    THEN 4             WHEN '광주광역시'    THEN 5             WHEN '울산광역시'    THEN 6             WHEN '경기도'    THEN 7             WHEN '강원도'    THEN 8             WHEN '충청남도'    THEN 9             WHEN '충청북도'    THEN 10             WHEN '전라남도'    THEN 11             WHEN '전라북도'    THEN 12             WHEN '경상남도'    THEN 13             WHEN '경상북도'    THEN 14             WHEN '제주도'    THEN 15         END ; 자료를 확인하면 아래와 같이 나오는데요.SELECT     * FROM test.TB_MBR_BAS ; 최종적으로 AREA_NM 컬럼을 삭제합시다.ALTER TABLE test.TB_MBR_BAS DROP COLUMN AREA_NM; 삭제했다면 자료를 확인해봅시다.SELECT     * FROM test.TB_MBR_BAS ; 이제 두 개의 테이블을 연결해서 조회해보겠습니다. JOIN을 사용하면 되고, Quey 문은 아래와 같습니다.SELECT     T101.MBR_ID      ,T101.MBR_INDFY_NO      ,T101.MBR_NM      ,T101.AGE      ,T101.AREA_ID      ,T102.AREA_NM FROM test.TB_MBR_BAS T101      INNER JOIN test.TB_AREA_BAS T102          ON T102.AREA_ID = T101.AREA_ID  ; 정리하며위에서 보여드린 예시는 두 가지 다른 점이 있습니다. 첫째는 TABLE 뒤에 T101, T101 과 같은 얼라이스를 준 것, 둘째는 INNER JOIN 문장이 들어간 것입니다.만약 테이블이 2개 이상이라면 사용할 테이블 컬럼을 써야 하는데 테이블명을 그대로 쓴다면 너무 길어집니다. 그래서 얼라이스로 테이블을 간단하게 표시하는 것이죠.INNER JOIN은 JOIN 중 가장 기본이 되는 문장입니다. 플랜을 보면 T101 즉 test.TB_MBR_BAS를 차례대로 전부 읽는데, 그때마다 T102인 test.TB_AREA_BAS 를 AREA_ID 를 기준으로 값을 읽습니다. T101에 해당하는 내용과 T102에 해당하는 내용을 보여주는 것이죠. 저는 Database를 쓰는 이유가 바로 JOIN 때문이라고 생각하는데요. 여러분의 생각은 어떤가요. 조금 헷갈린다면 다음에는 JOIN에 대해서 알아보도록 하겠습니다. (자연스러운 결말..!)글한석종 부장 | R&D 데이터팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유
조회수 936

DevOps 문화 안에서의 APM의 역할 [2] (DevOps+JENNIFER)

전편에서는 개발 프로세스 내에서 모니터링 단계의 문제점과 이를 해결하기 위한 방법으로 APM의 역할이 DevOps 진영에서는 매우 중요한 이슈가 되고 있다고 정리했었다. 또한 모니터링 프로세스의 세부 단계와 모니터링 기준 값 설정에 대한 내용을 다뤘는데, 이를 기반으로 제니퍼를 활용하여 모니터링하는 방법에 대해 알아보려고 한다.장애 발견 및 알림제니퍼에서 이벤트 발생 조건은 컴파일 에러나 응답 시간 초과, OOM과 같은 애플리케이션 에러 유형이나 액티브서비스 개수, 응답 시간, CPU 사용률, 힙 메모리 사용률 등 서비스나 시스템의 상태 값으로 설정될 수 있다. 그리고 이벤트 설정시 외부연동 활성화 기능을 사용할 수 있으며, SMTP(Simple Mail Transfer Protocol) 모듈을 기본으로 제공한다. 또한 고객이 직접 이벤트 모듈을 구현할 수 있도록 인터페이스와 유틸리티를 제공한다. 참고로 제니퍼를 사용하는 고객사 중에서 자체적으로 구축한 관제 시스템에 제니퍼 이벤트를 연동하여, 별도의 WAS 경고 시스템을 만든 사례도 있다.   서비스 부하량 제어 (운영)제니퍼는 PLC(Peak Load Control)라는 서비스 부하량을 제어할 수 있는 기능을 제공한다. 트랜잭션 유입 차단의 기준이 되는 최소/최대 액티브서비스 개수를 설정하고, 해당 임계치 값 초과시 사용자에게 가이드해줄 수 있는 메시지나  리다이렉트 페이지를 설정할 수 있다.   만약에 대상 애플리케이션(서버 또는 WAS)이 처리 중인 액티브서비스 개수가 설정한 임계치 값을 초과하면 들어오는 사용자 요청은 거절되며 액티브서비스 이퀄라이저 차트의 요청 효과가 반사되고, 색상 또한 붉은색 계통으로 변하게 된다.사용자의 요청(Request)이 거절되면 PLC 관리 화면에서 설정한 메시지가 보이거나 아래와 같은 화면으로 리다이렉트 되며, 모니터링 대상 애플리케이션의 액티브서비스가 임계치보다 낮아지면 원래의 화면으로 돌아올 수 있다.  장애 원인 분석 (개발)개별 트랜잭션에 대한 프로파일 데이터를 분석하기 위해서는 대상이 되는 패키지나 클래스를 알아야 하는데, 적용 범위에 따라 프로파일 데이터 크기가 매우 커질 수 있으므로 실제로 운영되는 서비스에는 큰 부담이 될 수 있다. 하지만 제니퍼의 자동 프로파일링과 스택트레이스 기능은 설정한 응답시간을 초과한 트랜잭션에만 적용되기 때문에 실제 운영 단계에서 사용하기에 적합하다. 프로파일이란 트랜잭션의 시작점이 되는 메소드의 호출 구조를 상세하게 분석하는 기능을 말하며, 스택트레이스는 앞에서 설정한 기준 값을 초과하는 순간에 호출된 메소드 구조에 대한 로그를 남기는 것을 말한다. 만약에 설정한 응답시간을 초과하여 의심이 될만한 트랜잭션을 분포도 차트에서 찾았다면, 트랜잭션 분석 화면을 통해 문제 시점의 스택트레이스 정보를 참고하거나 응답이 지연되는 프로파일 데이터를 구간 별로 검색하여 콜-트리를 통해 문제가 되는 메소드 위치를 정확히 알아낼 수 있다.소스코드가 배포되었다면 트랜잭션 분포도 차트에서 배포 시점에 세로 축이 하나 그려진다. 해당 축을 선택하면 새로 추가되거나 수정된 리소스 목록을 조회할 수 있으며, 리소스의 배포 전/후의 내용을 분석하는 코드리뷰 기능은 개발 환경에서 반영된 소스코드를 분석해야하는 번거로움을 덜어준다.배포 이후에 액티브서비스가 빠르게 처리되지 못하고, 트랜잭션 분포도 차트가 기존의 패턴과 다르게 형성이 된다면 새로 반영된 소스코드에 문제가 있을 가능성이 매우 높다.결론인류 사회에서 자신이 속해 있는 환경과 전혀 다른 이질적인 문화나 새로운 생활 양식을 접할 때 받는 충격과 공포를 문화 충격(Culture Shock)라고 하는데, 이는 IT 분야에서도 크게 다르지 않다. 사실 DevOps는 몇년 전부터 계속 주목받고 있으며, 많은 소프트웨어 개발 조직에서 시도하고 있는 개발 방법론이다. 하지만 새로운 문화에 대한 거부감으로 인해 제대로 적용되지 못하고 있는 것이 현실이다.DevOps가 추구하는 가치인 존중과 신뢰를 바탕으로 개발과 운영의 원활한 의사소통과 협업 관계 형성은 말처럼 쉽지 않다. 어떻게 보면 이상적일 수 밖에 없는 추상적인 개념이지만 본문에서 다뤘듯이 APM을 상호 간의 의사소통 도구로써 잘 활용한다면 이상이 아닌 보다 현실에 가까워질 수 있다고 필자는 확신한다. APM은 소프트웨어 제품과 서비스를 빠른 시간에 개발 및 배포하는 것을 목표로 하는 DevOps를 개발 문화로 성공적으로 정착시키는데 가장 중요한 역할을 하는 도구라고 생각한다.
조회수 4129

서버 비용을 70%나 줄인 온디맨드 리사이징 이야기

비트윈의 서버에는 사용자들이 올리는 수많은 사진이 저장되어 있습니다. 2016년 3월 기준으로 커플들이 데이트에서 찍은 사진, 각자의 프로필 사진, 채팅을 나누며 올린 재미있는 짤방까지 약 11억 장의 사진이 저장되어 있습니다. 비트윈에서는 이러한 사용자들의 소중한 추억을 잘 보관하고, 사용자들의 요청을 빠르고 비용 효율적으로 처리하기 위해서 많은 노력을 기울이고 있습니다. 이번 포스팅에서는 비트윈 개발팀이 사용자들의 사진 처리를 보다 효율적으로 하기 위해서 어떠한 노력을 하였는지 공유하고자 합니다.기존의 아키텍쳐¶비트윈 사용자가 채팅창이나 모멘츠 탭에서 사진을 업로드 할 경우, 해당 사진은 업로더 서버라고 불리는 전 세계 각지에 퍼져 있는 사진 업로드 전용 서버 중 가장 가까운 서버를 자동으로 찾아서 업로드 됩니다. 업로더 서버는 사진을 해당 AWS Region의 S3 bucket에 적재하고, 미리 지정된 크기의 썸네일을 자동으로 생성하여 역시 S3에 저장합니다. 그리고 Tokyo Region에 있는 비트윈 메인 서버에 이 결과를 토큰 형태로 전송하여 DB에 그 정보를 저장하도록 합니다. 이러한 과정을 통해서 일반 HTTP request보다 훨씬 큰 용량을 가지고 있는 사용자의 사진이 최대한 적은 지연시간을 가지고 업로드되도록 합니다.사용자가 올린 사진은 원본이 S3에 저장됨과 동시에 미리 정해진 사이즈로 썸네일을 생성해서 저장된다.하나의 사진이 대략 5장에서 6장의 서로 다른 크기의 썸네일로 리사이징이 되는데, 이는 클라이언트의 디스플레이 크기에 따라서 최적화된 이미지를 내려주기 위함이었습니다. 예를 들어서 아주 작은 썸네일이면 충분한 채팅 프로필 표시 화면을 그리기 위해서 사용자가 올린 3백만 픽셀이나 되는 원본 사진을 받아서 클라이언트가 리사이징 하는 것은 지연 시간뿐 아니라 과도한 데이터 사용이라는 측면에서 효율적이지 않기 때문에 작게 리사이징 해놓은 사진을 내려주는 것이 더 바람직합니다.비트윈 사용자들의 넘치는 사랑(?)에 비트윈은 출시 후 5년 동안 약 11억 장, 썸네일을 모두 합치면 66억 장의 사진을 저장하게 되었습니다. 이 사진은 전부 AWS S3에 저장되어 있으며, 썸네일을 합친 총 용량은 2016년 3월 기준 무려 738TB였습니다. 이에 따라 사진을 저장하기 위한 S3 비용이 전체 인프라 운영 비용에서 상당 부분을 차지하게 되었습니다.기존 아키텍쳐의 비효율성¶비트윈 팀은 어느 날 위와 같은 기존의 사진 전송 아키텍쳐에 의문을 가지게 되었습니다. 비트윈 서비스가 다른 서비스와 가장 다른 특징 중의 하나는 커플 간의 데이터는 그 둘 사이에서만 공유된다는 점입니다. 일반적인 웹사이트 같은 경우, 하나의 게시물 혹은 이미지가 수천 수 만명의 유저에게 전달되지만 비트윈에서는 그렇지 않습니다. 즉, 개별 사진의 Fan-out이 작다는 점을 특징으로 가지고 있습니다.그리고 클라이언트에서 LRU를 기반으로 한 파일 캐쉬를 사용하고 있는데, 이를 통해서 위에서 말씀드린 채팅창 프로필 사진 같은 경우 클라이언트에서 캐쉬될 가능성이 매우 커지게 됩니다. 그리고 CDN으로 사용하고 있는 AWS의 CloudFront에서도 약 30~40%의 추가적인 Cache hit을 얻을 수 있었습니다. 즉, 이미 Fan-out이 낮은 리소스가 높은 Cache hit rate를 가지는 사용패턴을 가지고 있는 셈이 됩니다.더군다나 사용자의 디바이스 사이즈에 따라서 미리 리사이징 해놓은 썸네일 중 일부는 아예 사용하지 않는 사용패턴이 나타나기도 합니다. 아이패드와 같은 큰 디스플레이를 가진 클라이언트를 쓰는 사용자와 아이폰4를 사용하는 사용자가 필요로 하는 썸네일의 크기는 다를 수밖에 없기 때문입니다.아래의 그래프는 S3 접근 로그를 분석해서 파악한 특정 기간 내에 같은 해상도를 가지는 썸네일을 클라이언트가 한 번 이상 재요청 하는 비율을 나타내는 그래프입니다. 하루 내에 같은 해상도의 사진을 요청하는 경우는 10% 가 되지 않으며, 한 달 안에도 33% 정도에 불과한 것을 알 수 있습니다.특정 기간 내에 S3에 저장된 썸네일이 다시 요청되는 비율결국 비트윈 팀은 미리 여러 해상도의 썸네일을 준비해서 저장해 놓은 아키텍쳐보다는 사용자가 요청할 때 그 요청에 알맞게 리사이징된 썸네일을 새로 생성해서 내려주는 게 훨씬 비용 효율적이라는 결론에 도달하게 됩니다.새로운 아키텍쳐¶Skia¶하지만 이러한 온디맨드-리사이징 아키텍쳐로의 변환에 가장 큰 걸림돌이 있었습니다. 바로 사진의 리사이징에 오랜 시간이 걸린다는 점이었습니다. 비록 아키텍쳐 변화를 통해서 저희가 얻을 수 있는 비용 이득이 크더라도, 비트윈 사용자 경험에 느린 사진 리사이징이 방해가 되어서는 안 되었습니다.이때 저희가 찾은 것이 바로 Skia 라이브러리였습니다. Skia 라이브러리는 Google에 의해서 만들어진 2D 그래픽 라이브러리로써, 크롬이나 안드로이드, 모질라 파이어폭스 등에 사용되고 있었습니다. 그리고 이 라이브러리는 CPU 아키텍쳐에 따라서 인스트럭션 레벨로 매우 잘 최적화가 되어 있었습니다. 저희가 기존에 쓰고 있던 ImageMagicK에 비해서 거의 4배 속도로 이미지 리사이징을 처리할 수 있었으며, 총 CPU 사용량도 더 적었습니다. 저희는 이 라이브러리를 Python으로 wrapping한 PySkia라는 라이브러리를 내부적으로 만들어서 사진 리사이징에 사용하기로 하였습니다.WebP¶저희는 여기서 한발 더 나아가 보기로 했습니다. 단순히 리사이징만 Skia로 대체하는 것이 아니라, 원본 사진의 저장도 더 효율적으로 할 방법을 찾게 되었습니다. 그 결과 자연스럽게 떠오른 것이 비트윈 스티커 시스템에서 사용되었던 WebP 방식이었습니다. WebP 역시 구글이 만든 이미지 인코딩 방식으로써, 비슷한 화질을 가지는 JPEG에 비해서 약 26% 정도의 용량이 절약된다는 점에서 장점이 있습니다.온디멘드-리사이징¶위에서 언급한 대로 Skia 리사이징과 WebP 원본 저장을 합하여 아래와 같이 필요한 해상도의 사진을 그때그때 리사이징 하는 온디멘드-리사이징 아키텍쳐로 옮겨가게 되었습니다.사용자가 올린 사진은 원본이 WebP로 변환되어 S3에 저장된다. 클라이언트의 요청이 있을 때는 그때그때 요청한 사이즈로 리사이징한 썸네일을 생성해서 내려준다.리사이저 서버가 사용자의 요청을 받아서 원하는 해상도의 사진을 리사이징해서 내려주기까지 채 100ms가 걸리지 않는데, 이 정도면 사용자의 경험에 영향을 주지 않는다고 판단하였습니다. 리사이저 서버는 업로더 서버와 함께 세계 각지의 AWS Region에 배포되어 있으며, 이는 사용자가 요청한 사진을 최대한 빨리 받아가기 위함입니다.기존 사진 마이그레이션¶위와 같은 아키텍쳐 전환을 통해서 새롭게 업로드 되는 사진들은 원본만 WebP로 변환되어 저장한 후 요청이 들어올 때만 온디멘드 리사이징이 되지만, 그동안 비트윈 사용자들이 축적해 놓은 11억 장의 사진은 여전히 여러 사이즈의 썸네일로 미리 리사이징이 되어 있는 비효율적인 상태였습니다. 저희는 이 사진들도 마이그레이션하는 작업에 착수했습니다.11억 장이나 되는 원본 사진들을 전부 WebP로 변환하고, 나머지 50억 장의 미리 생성된 썸네일 사진을 지우는 작업은 결코 간단한 작업이 아니었습니다. 저희는 이 작업을 AWS의 Spot Instance와 SQS를 통해서 비용 효율적으로 진행할 수 있었습니다.Auto Scaling with Spot instance¶마이그레이션 작업은 크게 다섯 단계로 이루어져 있습니다.커플 단위로 작업을 쪼개서 SQS에 쌓아놓습니다.Worker가 SQS로부터 단위 작업을 받아와서, 해당 커플에 존재하는 모든 사진을 WebP로 변환하고 S3에 올립니다.S3로의 업로드가 확인되면, 그 변경 사항을 DB에 적습니다.기존 썸네일 사진들을 삭제합니다.기존 썸네일이 삭제되었다는 사실을 DB에 적습니다.작업을 하는 도중에 얼마든지 Worker가 중단되거나 같은 커플에 대한 작업이 두 번 중복되어서 이루어질 위험이 있습니다. 이를 위해서 마이그레이션 작업을 멱등적으로 구성하여서 사용자의 사진이 손실되는 등의 사고가 발생하지 않도록 하였습니다. 중간마다 DB에 접근해서 변경된 내용을 기록해야 하는 작업의 특성상, 작업의 병목 구간은 비트윈 DB였습니다. 그리고 사진 인코딩을 바꾸는 작업의 특징상 많은 CPU 자원이 소모될 것으로 생각하였습니다.DB에 부담이 가지 않는 범위내에서 많은 CPU 자원을 끌어와서 작업을 진행해야 할 필요성이 생긴 것입니다. 이 조건을 만족하게 하기 위해서 SQS를 바라보는 Worker들로 Auto-scaling group을 만들었습니다. 그리고 이 Auto-scaling group은 c3.2xlarge와 c3.4xlarge spot instance로 구성되어 있으며, DB의 CPU 사용량을 메트릭으로 하여 Scaling이 되도록 하였습니다. 작업은 주로 DB의 부하가 적은 새벽 시간에 집중적으로 이루어졌으며, 이 인코딩 작업은 대략 4일 정도가 소모되었습니다. 작업 과정에서 Tokyo Region에 있던 c4.2xlarge와 c3.4xlarge spot instance를 최대 140대를 사용했고, 총 사용 시간은 6,767시간이었습니다. 사용한 instance의 계산 능력을 ECU로 환산하면 총 303,933 ECU · hour를 작업에 사용하였습니다. 마이그레이션에 사용된 EC2 비용을 바탕으로 계산해 보면, 백만 장의 WebP 인코딩을 위해서 사용한 비용이 $1.8 밖에 되지 않았다는 것을 알 수 있습니다.작업 과정에서 AWS 서비스에 의외의 병목 구간이 있다는 것을 알게 되었는데, S3 단일 버킷에 1분당 1천만 개 이상의 object에 대한 삭제 요청이 들어오면 Throttling이 걸린다는 사실과 SQS의 in-flight message의 개수가 12만 개를 넘을 수 없다는 것입니다.결과¶위의 아키텍쳐 변화와 마이그레이션 작업 후 저희의 S3 비용은 70%가 넘게 감소했으며 전체 인프라 비용의 상당 부분이 감소하였습니다. 온디멘드 리사이징으로의 아키텍쳐 변화는 Storage 비용과 Computation 비용 사이의 교환이라고 볼 수 있는데, 아래 그래프에서 볼 수 있듯이 확연한 비용 절감을 달성할 수 있었습니다.총 마이그레이션 비용¶항목사용량비용 ($)EC2 spot instance6,767 hrs1,959.11SQS188,204,10489.59S3 Put/Get Requests2,492,466,8605,608.34총비용7,657.04마이그레이션 결과¶항목Before MigrationAfter Migration감소량 (%)S3 # of objects6.65 B1.17 B82.40S3 storage738 TB184 TB75.06비용 감소¶사진 저장과 리사이징에 관련된 비용이 68% 감소하였음못다 한 이야기¶이번 포스팅에서는 최근에 있었던 비트윈 사진 아키텍쳐의 변화에 대해서 알아보았습니다. 주로 사용자의 경험을 방해하지 않는 조건에서 비용을 아끼는 부분에 중점을 두고 저희 비트윈의 아키텍쳐 변화에 대해서 설명해 드렸습니다. 하지만 이 글에서 미처 언급하지 못한 변화나 개선 사항들에 대해서는 다루지 못했습니다. Tokyo Region에서 멀리 떨어져 있는 사용자를 위해서 전 세계 여러 Region에 사진 저장/전송 서버를 배포하는 일이나, 사진을 로딩할 때 낮은 해상도로부터 차례대로 로딩되도록 하는 Progressive JPEG의 적용, 사진을 아직 받아오지 못했을 때 Placeholder 역할을 할 수 있는 사진의 대표색을 찾아내는 방법 등이 그것입니다. 이에 관해서는 후에 자세히 다뤄보도록 하겠습니다.정리¶비트윈 개발팀에서는 많은 인프라 비용을 소모하는 기존 썸네일 저장 방식을 개선하여 70%에 가까운 비용 절감 효과를 보았습니다. 기존의 썸네일을 미리 생성해놓는 방식으로부터 클라이언트가 요청할 때 해당 크기의 썸네일을 리사이징해서 내려주는 방식으로 변경하였고, WebP와 Skia등의 새로운 기술을 적용하였습니다. 이를 통해서 사용자 경험에는 거의 영향을 주지 않은 상태로 비용 절감 효과를 볼 수 있었습니다.저희는 언제나 타다 및 비트윈 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자를 모시고 있습니다. 언제든 부담없이 [email protected]로 이메일을 주시기 바랍니다!

기업문화 엿볼 때, 더팀스

로그인

/