링크 : https://d2.naver.com/helloworld/6070967
스마트폰이나 PC를 보유한 사람이라면 누구나 한 번 정도는 네이버 메인 페이지에 접속해 봤을 것입니다. 네이버 메인 페이지의 트래픽은 평소에도 많은 편이지만 사회적으로 주목을 받는 일이 있을 때는 트래픽이 엄청나게 늘어납니다.
네이버 메인 개발팀은 분산 처리 기술과 모니터링 체계를 통해 네이버 메인 페이지를 안정적으로 서비스하고 급격한 트래픽 변화에 대응하고 있습니다. 이 글에서는 네이버 메인 페이지의 트래픽 처리에 사용하는 분산 처리 기술과 모니터링 체계를 간략하게 소개하겠습니다.
네이버 메인 페이지의 트래픽 변화
다음은 2017년 11월에 포항에서 지진이 발생했을 때 네이버 메인 페이지의 트래픽 변화를 나타낸 그래프다. 변화가 별로 없는 파란색 선이 평상시의 트래픽이고, 급격하게 상승한 붉은색 선이 지진 발생 당시의 트래픽이다.
14시 30분 12초부터 트래픽이 상승하기 시작해 14시 30분 48초에서 14시 30분 57초 사이에 최고치를 기록했다. 평상시 트래픽의 6배 수준이 될 때까지 30여 초밖에 걸리지 않았다.
다음은 2018 러시아 월드컵에서 한국과 독일의 조별 예선전이 진행되고 있을 때 네이버 메인 페이지의 트래픽 변화를 나타낸 그래프다. 득점과 같은 주요 순간마다 트래픽이 급격하게 늘어났다.
네이버 메인 페이지에는 기본적으로 트래픽이 많이 들어온다. 그러면서도 많은 사람의 주목을 받는 일이 있으면 트래픽의 변동도 커진다. 이런 환경에 대처하고자 네이버 메인 개발팀은 분산 처리와 모니터링 체계 등에서 다양한 노력을 하고 있다.
네이버 메인 페이지의 분산 처리
로드 밸런서를 사용하는 일반적인 3계층(3-Tier) 분산 처리 모델은 구성 요소에 문제가 생겼을 때 문제를 해결하기에 어려움이 있다. 그래서 네이버 메인 페이지의 서비스 특성과 요구 사항에 맞는 분산 처리 모델을 구축해 적용하고 있다.
일반적인 분산 처리 모델
다음은 로드 밸런서로 구성한 일반적인 3계층(3-Tier) 분산 처리 모델을 표현한 도식이다.
클라이언트의 트래픽이 로드 밸런서를 통해 각 웹 서버로 분산된다. WAS는 동일한 데이터베이스를 참조한다.
이런 분산 처리 환경에서 각 구성 요소에 문제가 생긴다면 어떻게 처리해야 할까?
로드 밸런서에 문제가 생기면 로드 밸런서를 다중화한 다음 DNS 라운드로빈 방식 등을 적용해 문제를 처리할 수 있다.
하지만 WAS에 문제가 생기면 다음과 같은 점을 고려해야 하기 때문에 다중화로 문제를 해결하기가 쉽지 않다.
- WAS에 문제가 생겼을 때 웹 서버가 다른 WAS를 찾도록 해야 한다.
- 사용자가 로그인한 상태라면 WAS에 세션 클러스터링을 설정해야 한다.
- 세션 클러스터링 설정을 위한 추가 작업이 필요하고 관리 지점이 증가한다.
데이터베이스에서는 다음과 같은 점을 고려해야 하기 때문에 역시 다중화로 문제를 해결하기가 쉽지 않다.
- 데이터 동기화 등의 문제 때문에 데이터 스토리지 레이어는 다중화가 특히 어려운 부분에 속한다.
- 사용하는 데이터베이스가 RDB라면 다중화를 어떻게 할 것인지, 데이터를 어떻게 분산할 것인지에 관해 깊이 고민해야 한다. 예를 들어 샤딩 등을 도입했을 때 데이터가 늘어나 샤드를 추가해야 한다면 기존 데이터의 마이그레이션은 어떻게 할지 고민해야 한다.
- 사용하는 데이터베이스가 NoSQL이라면 데이터 정합성, 동기화, 장애 복구 시 다수결에 의한 데이터 오염 가능성 등을 고려해야 한다.
네이버 메인 페이지의 분산 처리 모델
서비스 특성상 네이버 메인 페이지가 실행하는 역할의 대부분이 데이터를 사용자에게 보여 주는 역할(View)이다. 데이터를 받아서 저장하는 동작이 거의 없기 때문에 분산 처리나 다중화에서 트랜잭션을 고려할 필요도 거의 없다.
이러한 서비스 특성을 고려해 도출한 요구 사항은 다음과 같다.
- 어떤 서버로 접속해도 동일한 내용을 보여 주어야 하며, 특정 상탯값(사용자의 로그인 여부 등)에 의존하지 말아야 한다.
- 무슨 일이 있더라도 사용자에게 서비스가 제공되어야 한다.
- 브라우저에 빈 페이지가 나타나지 않아야 한다.
- 네이버 메인 페이지에서 연동하는 외부 시스템은 언제든 접속이 불안해질 가능성이 있다고 가정하고 빠른 실패 전략을 실행해야 한다.
- 트래픽 증가에 탄력적으로 대처할 수 있어야 한다.
- 트래픽이 폭주할 때 서버 증설만으로도 대응할 수 있어야 한다.
- 각 컴포넌트(웹 서버, WAS)의 효율성을 극대화할 수 있어야 한다.
네이버 메인 페이지의 서비스 특성과 요구 사항을 반영한 네이버 메인 페이지의 분산 처리 모델을 간략하게 표현하면 다음과 같다(IDC 이중화와 서버, 네트워크 장비 등은 표현하지 않았음).
네이버 메인 페이지의 분산 처리 기술
네이버 메인 페이지의 분산 처리에는 다음과 같은 기술이 사용된다.
- GCDN(Global CDN)
- SSI(Server Side Includes)
- Apache 커스텀 모듈
- 마이크로서비스(부분 도입)
- 서킷 브레이커(circuit breaker)
- 서비스 디스커버리(service discovery)
GCDN
CSS와 JavaScript, 이미지와 같이 공통으로 호출되는 리소스는 한 번 업로드되면 잘 변하지 않는다. 이런 리소스를 네이버 메인 페이지의 웹 서버에서 직접 제공하면 트래픽 부하가 엄청나게 가중된다. 예를 들어 100KB 용량의 이미지를 10만 명이 조회하면 대략 10GB의 트래픽이 발생한다. 그래서 공통적으로 호출되는 리소스의 부하 분산을 위해 GCDN을 사용한다. 리소스를 GCDN으로 분산하면 네이버 메인 페이지의 트래픽을 상당히 절감할 수 있다.
또한, GCDN에서 지원하는 GSLB(Global Server LB) 기능은 접속한 IP 주소에서 가장 가까운 CDN 서버를 자동으로 선정해 연결하기 때문에 사용자가 빠른 서비스 속도를 체감할 수 있다.
SSI
SSI는 웹 서버(Apache, NGINX 등)에서 지원하는 서버사이드 스크립트 언어다. 서버에 있는 특정 파일을 읽어오거나 특정 쿠키 유무의 판별 등 간단한 기능을 실행할 수 있다. 이런 기능을 WAS에서만 실행할 수 있다고 생각하고 WAS에 요청을 보내는 경우가 많다. 하지만 SSI를 사용해 웹 서버에서 기능을 처리하면 WAS의 부담을 줄여 WAS의 성능에 여유를 줄 수 있게 되고, 웹 서버의 활용도도 높여 서버의 자원을 더 효율적으로 사용할 수 있다.
Apache 커스텀 모듈
네이버 메인 페이지는 Apache HTTP 서버로 서비스된다. 다만 Apache HTTP 서버를 그대로 사용하지 않고 APR(Apache Portable Runtime) 기반의 커스텀 모듈로 기능을 확장해 사용하고 있다.
APR(Apache Portable Runtime)
APR은 프레임워크와 비슷하게 운영체제에 독립적으로 HTTP 기반 통신을 처리할 수 있도록 하는 라이브러리다. 메모리 할당, 메모리 풀링, 파일 입출력, 멀티스레드 관련 처리 등에 필요한 기능이 포함되어 있다. Apache HTTP 서버도 APR 기반으로 작성되어 있다. APR에 관한 더 자세한 내용은 Apache Portable Runtime 프로젝트 사이트를 참고한다.
커스텀 모듈을 사용하면 SSI를 사용할 때와 마찬가지로 WAS에서 처리할 기능을 웹 서버에서 처리할 수 있어 WAS의 부담을 줄일 수 있다. 또한 SSI에서는 불가능한 고급 기능을 사용할 수 있어서 활용도가 높다. C 언어 기반이라 실행 성능도 좋다.
네이버 메인 페이지에서 사용하는 대표적인 커스텀 기능은 다음과 같다.
- 간단한 외부 시스템 연동: 단순히 API를 호출하거나 결괏값을 그대로 사용할 수 있을 때에는 WAS를 거치지 않고 커스텀 모듈을 통해 외부 시스템을 호출한다.
- WAS 연동 시 AJP(Apache JServ Protocol), 리버스 프락시(reverse proxy) 대신 커스텀 모듈 사용: 모든 WAS가 다운되더라도 웹 서버만 정상이라면 서비스를 제공할 수 있게 커스텀 모듈을 사용해 WAS와 통신한다.
- AJP나 HTTP을 사용해 WAS와 통신하면 WAS와 통신이 실패했을 때 오류로 처리된다.
- 커스텀 모듈을 사용하면 WAS와 통신이 실패했을 때 동일한 IDC에 있는 다른 WAS와 통신을 시도한다.
- 다른 WAS와 통신도 실패하면 오류로 처리하는 대신 특정한 경로에 있는 파일을 읽어서 반환한다. 반환할 파일은 정적 파일을 배포하는 Data Publisher가 특정 시간 주기에 따라 웹 서버에 생성해 놓은 파일이다.
마이크로서비스의 부분 도입
네이버 메인 페이지에서는 다른 시스템과 연관성이 적은 독립적인 기능을 별도 서비스로 분리해 구축했다.
외부 시스템과 API 연동을 담당하는 부분은 특히 Node.js로 구축했다. 네이버 메인 페이지에서는 동시에 여러 대의 외부 시스템과 API 연동을 실행해야 하는 경우가 많다. Node.js를 사용하면 병렬 처리 시 스레드 문제 등을 고려할 필요가 없고, 비동기식으로 외부 시스템 연동 시 병렬로 여러 개의 요청을 한 번에 처리할 수 있다. 그래서 이러한 기능을 구현하기에는 기존에 사용하던 Java보다는 Node.js로 구현하는 것이 더 유리하다고 판단했다. 또한 부서 내 언어적 다양성을 확보해 용도에 맞는 적절한 기술을 사용할 수 있고, 부서원의 기술 역량 향상에 도움을 주는 장점도 있다.
API 서버에는 또한 서킷 브레이커를 적용했다. WAS에는 서버의 모니터링과 관리를 위해 서비스 디스커버리를 적용했다.
서킷 브레이커
서킷 브레이커는 외부 서비스의 장애로 인한 연쇄적 장애 전파를 막기 위해 자동으로 외부 서비스와 연결을 차단 및 복구하는 역할을 한다. 서킷 브레이커를 사용하는 목적은 애플리케이션의 안정성과 장애 저항력을 높이는 데 있다. 분산 환경에서는 네트워크 일시 단절 또는 트래픽 폭증으로 인한 간헐적 시간 초과 등의 상황이 종종 발생한다. 이로 인해 다음과 같은 연쇄 장애가 발생할 가능성이 있다.
- 트래픽 폭증으로 인해 API 서버 등 외부 서비스의 응답이 느려진다.
- 외부 서비스의 응답이 타임아웃 시간을 초과하면 데이터를 받아오기 위해 외부 서비스를 다시 호출한다.
- 이전에 들어온 트래픽을 다 처리하지 못한 상태에서 재시도 트래픽이 추가로 적체되어 외부 서비스에 장애가 발생한다.
- 외부 서비스의 장애로 인하여 데이터를 수신하지 못해 네이버 메인 서비스에도 장애가 발생한다.
일시적인 경우라면 2, 3회 재시도로 정상 데이터를 수신할 수 있다. 하지만 장애 상황이라면 계속 재시도하는 것이 의미도 없을 뿐 아니라 외부 서비스의 장애 복구에 악영향을 미칠 수 있다. 이럴 때는 외부 서비스에서 데이터를 받아오는 것을 포기하고 미리 준비된 응답을 사용자에게 전달하는 것이 시스템 안정성 및 사용 편의성 측면에서 옳다고 할 수 있다.
다음 그림은 서킷 브레이커에서 서킷의 상태 변화를 나타내는 그림이다.
서킷은 다음과 같은 세 가지 상태를 가진다(회로이므로 닫힌 것이 정상, 열린 것이 비정상).
- Closed 상태: 메서드가 정상적으로 작동해 서킷이 닫힌 상태
- Open 상태: 메서드에 문제가 생겨서 서킷이 열린 상태
- Half-Open 상태: Open 상태와 Closed 상태의 중간 상태. 메서드를 주기적으로 확인해 정상이라고 판단되면 Closed 상태로 상태를 전환하고, 정상이 아니라면 Open 상태를 유지한다.
서킷이 Closed 상태에서 잘 작동하고 있다가 오류가 발생하기 시작해서 일정 횟수에 도달하면 일단 서킷을 Open 상태로 전환한다. 이때에는 메서드를 호출해도 실제로 메서드가 실행되는 대신 서킷 브레이커가 개입해 미리 지정된 응답(단순 실패를 반환할 수도 있고 특정한 값을 반환할 수도 있음)을 반환한다.
특정 주기 동안 Open 상태로 유지하고 있다가 서킷이 자체적으로 메서드가 정상으로 작동하는지 확인하는데, 이 상태가 Half-Open 상태다. Half-Open 상태에서 메서드를 몇 번 호출해서 정상 응답이 돌아온다면 서킷은 다시 Closed 상태로 전환되어 요청을 처리한다. 몇 번 호출했는데 계속 실패가 반환된다면 서킷은 Open 상태로 유지된다.
기존에는 이런 로직을 구현하기 위해 개발자가 수많은 if-else 구문을 작성해야 했다. 하지만 Netflix OSS의 서킷 브레이커 라이브러리인 Netflix OSS Hystrix가 등장한 이후 많은 개발자가 Netflix OSS Hystrix를 적극적으로 사용하고 있다. 또한 Netflix OSS를 Spring Cloud 프로젝트에서 사용할 수 있도록 래핑한 Spring Cloud Netflix를 활용하면 Spring 개발자는 자신의 애플리케이션에서 서킷 브레이커를 손쉽게 활용할 수 있다. 네이버 메인 개발팀은 Node.js에서 서킷 브레이커를 사용해야 해서 HystrixJS를 사용했다.
네이버 메인 페이지에서는 서킷 브레이커를 다음과 같이 활용한다.
- 정적 파일을 배포하는 Data Publisher를 통해 사전에 정상 응답 결괏값을 주기적으로 저장해 둔다.
- 외부 시스템에 이상이 있다고 판단되면(Open 상태) 서킷 브레이커가 개입해 바로 연결 시도를 포기하고 미리 준비해 둔 정상 응답 결괏값을 사용해 HTML 화면을 렌더링한다.
- 이후 계속 상태를 지켜보다(Half-Open 상태) 외부 시스템이 정상으로 돌아오면 서킷 브레이커가 다시 연결을 시도한다.
서비스 디스커버리
서비스 디스커버리는 동적으로 생성, 삭제되는 서버 인스턴스에 대한 IP 주소와 포트를 자동으로 찾아 설정할 수 있게 하는 기능이다.
다음은 서비스 디스커버리를 사용하지 않는 서버군의 환경을 나타낸 그림이다. 서버군 1과 서버군 2가 서로 다른 기능을 실행하는 서버군이라고 가정한다.
서버군 2에서 10.0.0.5 서버가 신규로 생성됐지만, 서버군 1에서는 10.0.0.5 서버로 연결을 맺을 수 없다. 서버군 1이 최초에 실행됐을 때에는 10.0.0.5 서버가 없었기 때문에 서버 목록에 10.0.0.5 서버가 없기 때문이다. 서버 목록을 갱신하려면 서버군 1에 있는 서버를 다시 실행해야 한다. 하지만 롤링 리스타트를 한다고 해도 서비스를 운영하는 도중에 서버를 다시 실행하는 것은 매우 위험하다.
다음은 서비스 디스커버리를 도입한 환경을 나타내는 그림이다.
서비스 디스커버리 서버는 각 서버군의 서버 목록을 관리한다. 서버는 시작할 때 자신의 정보(IP 주소, 포트)를 서비스 디스커버리 서버로 보내고, 서비스 디스커버리 서버는 이 정보를 받아 서버군의 서버 목록을 최신으로 갱신한다. 각 서버군에 있는 서버는 주기적으로 서비스 디스커버리 서버로 목록을 요청해 서버 목록을 최신으로 유지한다. 이러한 방법으로 서버는 재시작 등 외부의 개입이 없어도 자동으로 항상 최신 서버 목록을 확보할 수 있다.
예를 들어 10.0.0.5 서버가 추가되면 서버군 2의 서버 목록이 갱신되고 이 목록을 받아서 서버군 1의 서버가 자신의 서버 목록을 갱신하면 외부의 개입 없이 10.0.0.5 서버에 연결할 수 있게 된다.
서비스 디스커버리는 특히 클라우드 환경에서 빛을 발한다. 기존 온프레미스(on-premises) 환경에서는 서버를 추가, 삭제하는 일이 많지 않았다. 서버를 추가, 삭제하는 경우에도 통제된 환경에서 주로 작업하므로 갱신 문제가 크지 않다. 하지만 클라우드 환경에서는 수시로 서버가 추가, 삭제된다(특히 오토스케일링 등의 기능을 사용한다면 더욱 더). 이를 사람이 일일이 확인해 서버를 다시 실행하는 것은 불가능에 가깝다. 서비스 디스커버리는 이런 상황에서 아주 유용하게 사용할 수 있는 기술이다.
네이버 메인 페이지의 모니터링 체계
플랫폼 구축 후에는 모니터링과 유지 보수 등 끊임없는 보살핌이 필요하다. 아무런 보살핌이 없다면 시스템에 이상이 없더라도 외부 시스템의 변경 등 외부 환경의 영향으로 문제가 생길 수 있다.
시스템의 한계치를 명확히 설정하고 이를 기준으로 지속적으로 모니터링하는 일도 필요하다. 한계치를 명확히 설정하지 않으면 트래픽 급증과 같은 상황이 일어났을 때 대처를 제대로 못해 장애를 맞이할 수가 있다.
네이버 메인 개발팀은 Spring Boot Actuator로 성능 지표를 수집해 지속적으로 네이버 메인 페이지의 서비스 상태를 모니터링한다. 또한 갑작스러운 트래픽 증가 등에도 서비스가 중단되지 않도록 비상 대응 체제를 구축해 놓았다.
성능 지표 수집과 모니터링
네이버 메인 개발팀은 성능 지표를 수집해 시각화해서 보여 주는 NPOT으로 네이버 메인 페이지의 상태를 모니터링한다. NPOT은 네이버의 사내 시스템으로 Grafana 기반의 데이터 시각화 지원 시스템이다.
NPOT을 위한 성능 지표는 Spring Boot 기반의 애플리케이션인 Spring Boot Actuator의 MetricWriter를 활용해 수집한다.
수집된 성능 지표는 다음과 같은 로그 파일 형태로 저장된다. 이 로그 파일을 읽어 NPOT에 전송해 성능 지표를 시각화한다.
비상 대응 체계
네이버 메인 페이지에는 갑작스러운 트래픽 증가가 종종 나타난다. 그때마다 사람이 개입해서 조치해야 한다면 네이버 메인 페이지 개발자가 24시간 당번을 서야 할 것이다. 하지만 이는 물리적으로도 어려운 일이다. 네이버 메인 개발팀은 MEERCAT이라는 애플리케이션을 개발해서 애플리케이션이 스스로 트래픽을 예측해 갑작스러운 트래픽 증가를 방어하게 했다.
MEERCAT은 다음과 같은 두 가지 상황이 발생하면 자동으로 모든 외부 시스템과 연결을 끊고 자체 서버로만 서비스를 제공하는 방어 동작을 실행한다.
- 실시간으로 트래픽을 수집하고 그 양상을 예측한 다음 트래픽 폭증이 예측되는 경우
- 기상청의 지진 발생 신호 등 외부 신호가 수신되는 경우
방어 동작은 네이버 메인 페이지의 순간 성능 및 가용량을 향상시킴과 더불어 외부 시스템을 보호한다는 의미를 가진다. 만약 네이버 메인 페이지에 들어오는 트래픽이 아무런 제한 없이 외부 시스템으로 모두 흘러간다면 외부 시스템의 연쇄적 장애로 이어질 수도 있기 때문이다.
다음은 MEERCAT이 트래픽 이상을 감지해 처리하는 과정을 나타낸 흐름도다. 평소에는 이동평균을 이용해 트래픽을 실시간으로 모니터링한다. 만약 일정 시간 이후에 트래픽 한계치에 도달할 것으로 예측될 때는 방어 동작을 실행한다.
다음은 MEERCAT에 외부 신호가 수신됐을 때 처리 과정을 나타낸 흐름도다. 기상청의 지진 발생 신호 등 외부의 신호가 수신되면 자동으로 방어 동작을 실행한다.
다음 화면은 MEERCAT이 실제 방어 동작을 실행한 예다. 네이버 메인 페이지의 트래픽이 일정 시간 뒤에 한계치에 도달할 것으로 예측해 외부 시스템 연동을 자동으로 끊는 방어 동작(비상I모드
)을 실행했다. 밤 10시 30분경이었고 아무도 사무실에 앉아 있지 않았지만 애플리케이션이 스스로 방어 동작을 실행해 연쇄 장애를 사전에 차단할 수 있었다.
다음 그래프는 MEERCAT이 자동으로 외부 시스템과 연결을 끊을 때의 트래픽을 나타내는 그래프다.
이 그래프에서 주목해야 할 곳은 API 오류 TPS
다. MEERCAT이 자동으로 연결을 끊기 전에 오류 건수가 급증한 것이 보인다. 이대로 트래픽이 아무런 제어 없이 계속 외부 시스템으로 흘러갔다면 외부 시스템의 연쇄 장애가 일어났을 가능성이 크다. 하지만 MEERCAT이 정확히 작동해 자동으로 연결을 끊어 연쇄 장애를 막을 수 있었다. 연결 복구 이후 오류 TPS가 확연히 낮아진 것을 볼 수 있다.
마치며
네이버 메인 개발팀은 국내에서는 손꼽힐 정도로 많은 트래픽을 처리하고 있다. 그리고 외부 상황에 따라 급격하게 변화하는 트래픽을 처리해야 한다. 네이버 메인 개발팀은 무슨 일이 있더라도 사용자에게 서비스가 제공될 수 있게 분산 처리 모델을 개발하고 다양한 분산 처리 기술을 적용했다. 또한 트래픽 폭증이나 외부 재해가 일어났을 때도 서비스가 안정적으로 이루어질 수 있게 모니터링 체계와 비상 대응 체계를 갖추고 있다.
네이버 메인 페이지의 트래픽 처리 시스템과 이에 필요한 대용량 분산 처리 특화 지식, 고가용성과 동시성, 성능을 고려한 시스템 설계 지식 등은 흔히 접할 수 없는 것이다. 그 외에 네이버 메인 개발팀은 Chrome, Safari, Firefox, Internet Explorer, 삼성 브라우저, IoT 기기 등 네이버 메인 페이지가 다양한 프런트엔드 환경을 지원하면서 쌓은 경험을 가지고 있다.
네이버 메인 개발팀에 있으면 백엔드 영역에서도 Java, Node.js 등 다양한 언어를 사용한 개발을 경험할 수 있다. 또한 평범한 환경에서는 잘 발생하지 않는 특수한 문제(스레드 경합, 데이터 정합성, 고부하 상황에서 트러블슈팅)를 처리하면서 쌓은 각종 분석 경험(스레드, 힙, GC 로그 분석, strace 사용 등)을 엿볼 수 있다.
다음은 백엔드 영역에서 발생하는 다양한 문제를 분석하는 예다.
네이버 메인 개발팀은 이런 경험을 나누고 함께할 지원자를 기다리고 있다. 지원에 관한 자세한 내용은 다음의 개발자 모집 페이지를 참고한다(2019년 1월 1일까지 지원 가능).
- 포털 메인 백엔드 개발: 메인&미디어플랫폼 백엔드 S/W엔지니어 모집
- 포털 메인 앱(iOS/Android) 개발: 네이버앱 Android/iOS 개발자 모집
'WEB > 기타' 카테고리의 다른 글
MS, 엣지브라우저 크로미엄으로 재개발 공식화 (0) | 2019.01.22 |
---|---|
네이버페이 JavaScript SDK 개발기 (0) | 2019.01.22 |
GIF대신 Video로 변환해보자 (0) | 2019.01.22 |
Kakao Hangul Analyzer III (0) | 2019.01.22 |
페이스북, 자사의 이미지 압축기술 오픈소스로 공개 (0) | 2019.01.18 |