토스 개발자 컨퍼런스 SLASH24 NoLimit
KeyNote
(feat. 토스 CTO 이형석)
- NoLimit : 풀지 못할 문제는 없다!
- 토스 앱 누적 가입자수 : 2600만 / MAU : 1900만
- 토스가 문제 해결을 하기 위해 노력한 개발 문화
- 문제의 어려움을 최선의 선택을 할 수 있도록 도와주는 문화
- 문제점에 대해 누구든지 다양한 의견을 낼 수 있는 문화
- 문제 해결을 위한 최선의 선택을 함께 할 수 있는 문화
- 끊임없이 기술을 학습하는 문화
- 문제 해결을 위해 다양한 기술을 학습하고 검토하고 적용하는 문화
- “최복동”: 최고의 복지는 동료다!
- 각자가 옆에 있는 동료에게 최고의 복지가 되기 위한 노력하는 문화
- 문제의 어려움을 최선의 선택을 할 수 있도록 도와주는 문화
국내원장 프로젝트 MSA 전환 (feat. 토스증권 양승영)
- 거대한 C언어 기반 모놀리식 코어뱅킹 시스템을 Kotlin 기반 MSA 구조 전환
- 전환 과정 제약 사항
- API 스펙을 유지
- DB 스키마도 유지
- 주요 비즈니스 로직 또한 유지
- 전환 과정 문제점
- 기존 시스템의 변경: 기존 코어뱅킹 시스템에 변경 사항 반영 필요
- 테스트 코드 작성 부담: 거대한 코어뱅킹 시스템의 모든 기능에 대한 테스트 코드 작성 부담
- 한번의 통합 테스트를 위해 필요한 많은 선행 작업들
- 전환 과정 제약 사항
- 아키텍처 전환을 위해
수정 > 배포 > 테스트 > 검증
사이클 무한 반복.. 테스트 > 검증
구간을 자동화 계획!!
Read Verifier
- 조회
Read
API 검증 자동화 모듈 - API 호출을 비동기로 리플레이하면서 서비스 전환 검증
레거시 API
와차세대 API
를 비동기적으로 각각 호출하여 각 응답 결과값 비교Read
API 검증 결과는 주기적으로 리포팅하여 어드민 기능 지원을 통해 검증 결과 확인
Write Verifier
- 쓰기
Write
API 검증 자동화 모듈Read
보다 더 많은 고민
Write
요청에 대해레거시 API
처리되기 전,Gateway
에서차세대 API
로 Intercept 하여 1차 처리차세대 API
처리 결과를Redis
저장차세대 API
에서 수행한CUD
쿼리는 조회 쿼리로 변경하여 저장- P6Spy : 애플리케이션에서 실행되는 쿼리 수집 도구
- ANTLR : 수집된
CUD
쿼리를 분석해 조회 쿼리 변환 도구
- 이후 다시
레거시 API
로 처리하고,Verifier
모듈로 검증 요청레거시 API
의 결과와차세대 API
의 결과를 비교
- 실시간 리포팅으로 개발자가 눈으로 확인하는 것보다 더 빠르고 정확하게 검증
성과
- 레거시 시스템에서 발생하는 데이터를 기반으로 안정성 보장하며 전환 집중
- 총 182개의 API 를 효과적으로 검증
- 테스트 시간 효과적으로 절약
긴 생애 주기의 프로젝트 관리 (feat. 토스뱅크 박종수)
대출 상품 같은 생명 주기가 긴 서비스를 개발하고 관리한다면?
- 대출 상품을 가입하는 경우, 짧게는 1년 길게는 10년 이상 데이터 관리 필요
- 10년 동안 변경될 기준금리에 맞게 실제 금리 반영 필요
미래에 실행될 로직을 ‘지금’ 테스트해볼 수 있는 방법은?
- 독립된 테스트 환경에서 시간을 바꿔가며 테스트 시뮬레이션 실행
- 실시간 거래, 배치 거래 데이터를 표준화
- k8s 활용한 독립적인 시뮬레이션 환경 구축
- 1일 1회 DB 복제 & 시뮬레이션 DB 자동 생성
Redis
활용하여 시뮬레이션테스트기준시간
관리- 시뮬레이션 거래 과정을 DB 값을 조회하여 검증
CPU 사용률 50% 이상시, Hyperthread
사용 자제 필요하다는 이슈 발생 !!
Hyperthread
- 인텔(Intel)에서 개발한 기술로, 하나의 물리적 CPU 코어가 동시에 두 개의 스레드를 처리
- 하나의 물리적 코어를 두 개의 논리적 코어로 분리하여 작업
- 두 개의 논리적 코어는 물리적 코어의 자원 공유
- 하나의 스레드가 대기 상태일 떄 다른 스레드가 실행되어 CPU 자원 활용 극대화 가능
- 하지만, 무분별한
Hyperthread
사용은 다른 코어 CPU 악영향 발생
Hyperthread Observability
- Elasticsearch 기반의 성능 측정 계획
- Linux-KI : CPU 의 double busy 라는
Hyperthread
매트릭 정보 수집 - perf : 리눅스 CPU Instruction 성능 측정 도구
토스뱅크 코어뱅킹 MSA 전환 배경
- 기존 토스뱅크의 코어뱅킹 모놀리식 시스템의 단점을 해결하기 위해 MSA 전환 계획
- 코어뱅킹 + 오라클DB <> 채널계 + MySQL 구조
- 코어뱅킹 시스템의 오라클 의존성을 줄이기 위해 MySQL DB 전환 계획
- 오라클 장점 : 신뢰성과 안정성, 대용량 데이터 볼륨 처리 확장성, 뛰어난 성능, 오랜 운영 노하우
- 오라클 단점 : SFOP 문제, 비용 문제, 제한적인 Scale-out 문제
- 오라클DB 보안책
Redis 분산락
,SAGA 패턴
등 Application Layer 에서 트랜잭션 관리 보장- MySQL Replication 전략 등 높은 수준의 데이터 처리 확장성, 빠른 Scale-out 전략 보장
- MySQL MVCC 기술 사용으로 효율적 데이터 동시성 제어 보장
- MySQL 또한 오라클 못지않은 오랜 운영 노하우 보유
코어뱅킹 신규 서비스 MSA 개발
- 새로운 신규 서비스는 MSA 와 MySQL 기반으로 개발 진행 👉 점진적인 MSA 전환
- 트랜잭션이 중요한 내부 서비스는 동기식 트랜잭션 처리, 외부 트랜잭션 처리는 비동기 트랜잭션 처리
- API 동시성 제어를 위해서는 분산락을 사용하고, DB 데이터 동시성 처리를 위해선 비관적 락 사용
- 여러가지 거래 가능 검증을 위해 코루틴을 활용한 비동기적 처리 방식으로 지연 감소
24/365
서비스 지원을 위해 전일자 스냅샷을 통해서 거래 대사 처리- 전일자 데이터 스냅샷 저장 > 거래 내역 기준 역산하여 잔액 원장 등 데이터 처리
- 하둡을 사용하여 전일자 데이터 저장&조회를 통한 대사 처리
신규 서비스 테스트 자동화
- 비중 : 개발 20% / 테스트 80% 👉 개발 80% / 테스트 20%
- 테스트 자동화를 위한 과정
Local
: 단위테스트 코드 작성 👉 프로그램 정합성 검증Dev
: E2E 서버 테스트 👉 업무 정합성 검증E2E 서버 > 타켓 서버 API
테스트 자동화 도구 개발을 통해 실시간 E2E 테스트 검증
Live
: 이상거래탐지 서비스 개발 👉 데이터 완결성 검증- 하둡 저장 데이터 기준 이상거래탐지 배치 프로그램 개발을 통해 실시간 데이터 검증
Push 서버 개발 배경
- 실시간 데이터 정보 조회 제공을 위해 다양한 도메인 정보를 3초마다
Polling
시스템으로 요청 & 수집- 이슈 발생 : 급증한 트래픽으로
Polling
시스템의 DB 부하 발생
- 이슈 발생 : 급증한 트래픽으로
- 실시간 Event 트랜잭션 완료 시 각 도메인 정보를 조회하고, 클라이언트에게 전달할 수 있는 Push Server 개발 필요
Push 서버 구성
WebSocket
vs SSE
구분 | SSE |
WebSocket |
---|---|---|
Protocal | HTTP | WebSocket |
Direction | 서버사이드 단방향 | 양방향 |
Auto Reconnect | Yes | No |
Cookie | Yes | No |
Response Type | Text | text or byte |
Usage | 불필요한 Polling 제거개인화 데이터를 이용한 이벤트 푸쉬 가능 |
양방향 통신 필요 시 사용 송/수신량 데이터량 높은 서비스에 유리 |
SSE
ServerSendEvents
- HTTP 의
Content-Type : text/event-stream
을 통해 데이터 파이프라인을 구축하여 서버에서 클라이언트로 데이터를 보낼 수 있는 구조 SSE
서버는 메시지 브로커로부터 데이터를 수신하여 클라이언트로 데이터 전달Broadcasting
,Unicasting
방식 모두 지원 가능
SSE
사용 사례
Broadcasting
방식 활용- 이벤트성 단일 채팅방 서비스 구축
Unicasting
방식 활용- 개인화된 데이터 정보 조회 서비스 구축
- 개인 보유자산 실시간 정보 PUSH 처리
FCM
안드로이드 PUSH 알림 대체- 비회원에게는 FCM 으로 푸쉬 알림 / 회원에게는 SSE 서버로 푸쉬 알림
Redis Pub/Sub
를 이용하여 회원 여부 판단하는 세션 기능 개발
- 개인화된 데이터 정보 조회 서비스 구축
Message Broker 선택 전략
- Kafka
- Redis Pub/Sub
- NATS : Go-Lang 기반 Pub/Sub 메시징 분산 처리 지원 오픈 소스 메시징 시스템
기존 테스트 자동화 문제점
- 표준화 되지 않는 다양한 컨텐츠의 테스트 자동화 도구 👉 통합된 테스트 자동화 플랫폼 제공
- 표준화 되지 않는 자동화 코드의 공유 👉 통합 테스트 자동화 플랫폼 활용한 공유
- 테스트 결과 가공의 어려움 👉 테스트 결과의 이력 관리 및 커스텀 리포트 자동 생성
Playwright 활용한 테스트 자동화 플랫폼
Playwright
- Microsoft 에서 개발한 E2E 자동화 테스트 도구
- VSCode 개발자 도구 연동하여 개발 가능
- 테스트 파일 실행 제어
- 테스트 파일 실행 리포트 자동 생성
Test Automation Platform 구성
Test Automation Platform 문제
- 테스트 종류마다 다른 리소스 크기로 컴퓨팅 리소스 문제 발생
- 👉 테스트 러너의 동시 실행 가능한 Playwright 실행 수 제어
- 👉 메시지 큐를 사용하여 편린한 테스트 러너 인스턴스 Scale-out 구조 설계
- 👉 테스트 결과를 청크 단위 처리
Test Automation Platform 테스트 결과 조회
- 서비스 웹뷰 <> 스크래핑 웹뷰 분리하여 스크래핑 웹뷰는 보이지 않도록 한 상태에서 스크래핑 처리 진행
- 웹뷰에 서버를 기동하는 방법으로 문제 해결
- Nest.js 를 통해서 웹뷰에 서버를 올리고, API 통신 처리
- FE 에서는 Nest.js 서버로 요청을 하고, 복잡한 비즈니스 로직은 Nest 서버에서 처리
- Nest.js 인메모리 활용한 동시성 데코레이터로 동시성 제어 처리
- 모니터링을 위한 APM Sentry 도입
- 웹뷰에서 Nest.js 서버를 기동을 위해 PolyPill 를 활용
ebpf 를 활용한 CPU 사용률 분석
- 커널에서 블랙박스 형태로 모니터링의 어려움이 있었는데, ebpf 를 통해 커널까지 모니터링
- numa 아키텍처 : CPU 와 메모리 간의 간격을 줄이기 위한 아키텍처
- CPU 와 메모리의 간격을 줄이기 위해 remote access 를 사용
Redis latency 이상현상 파악
- 20~50 ms 지연이 발생하여 문제 파악 시작
- TCP 덤프를 통해서 네트워크 영역부터 분석
- 네트워크 장비와 애플리케이션 사이의 지연 발생 확인
- perf trace 를 사용해서 매트릭 정보 수집하였지만 로그 수집이기 때문에 정확한 정보 수집 불가 > ebpf 로 분석 시작
- pixie : ebpf 모니터링 도구
- 알고 있는 지식 기준으로 해볼 수 있는 모든 방식을 시도해보고, 안되면 기초 지식부터 하나씩 올라가본다!
- Observability 를 적극 활용하여 근본적인 원인을 찾을 수 있다!
분산환경이 만들어진 이유
- 모놀리식 시스템 레거시 시스템 개선 필요
- 기존 코어뱅킹 시스템을 MSA 구조로 분리 욕심
- 하지만, 거대한 코어뱅킹을 분리는 무리
- 그래서, 신규 서비스는 바로 MSA 구조로 설계
- 환전은 레거시 원화 시스템 & 신규 외화 시스템 2가지 모두 활용하는 신규 MSA 서비스
- 분리된 시스템 간 트랜잭션 처리를 위한 분산 트랜잭션 구현 필요
분산 트랜잭션 처리: 2PC vs SAGA 패턴
2PC Two-Phase Commit
Coordinator
코디네이터에서 트랜잭션을 관리하고,Prepare Phase
&Commit Phase
2단계로 구성- 각 시스템에서 트랜잭션 처리 요청하여 성공인 경우, 커밋 처리 / 실패인 경우, 롤백 처리
SAGA 패턴
2PC
보다 높은 가용성/확장성 제공2PC
보다 롤백 트랜잭션을 직접 관리해야한다는 단점
SAGA 패턴의 환전 서비스 구현
- 환전 서비스가 SAGA 패턴의 오케스트레이터가 되어서 원화/외화 트랜잭션을 관리
- 다음 트랜잭션 실패하는 경우, 실패 보상 트랜잭션을 이전 서비스로 요청 처리
- 트랜잭션 처리 순서도 중요 (원화 출금 > 외화 입금 순서 필수!)
네트워크 통신 방식: HTTP vs Messaging
- HTTP : 동기 vs 메시징 : 비동기
- SAGA 패턴의 구현은 무조건 메시징이 아니라 정확한 동기 처리를 위해선 HTTP 방식으로 선택 가능
- 하지만, 보상 트랜잭션은 비동기 처리를 해도 되기 때문에 비동기 방식으로 선택 가능
에러 핸들링
- 타임아웃과 같은 요청 실패에 대해서는 결과 확인 요청을 통해 성공 처리
- 타임아웃이 발생하였을 경우, 요청 서버로 결과 확인 요청
- 요청 서버 결과 확인 요청에 대한 결과 따른 예외 처리 진행
- 결과 확인 요청마저 실패한다면, 지연 메시징 처리를 활용하여 요청 서버로의 요청을
Backoff
재시도 처리 - 환전 서버가 장애 발생하였을 떄는, 오케스트레이션의 트랜잭션 이력 기준 Batch 재처리
- 보상 트랜잭션 비동기 처리 중 실패하는 경우 Dead Letter 처리를 통해서 해결
Eventually Consistency: Consumer Dead Letter(CDL)
- 메시지를 수신하는 도중 에러가 발생하는 경우,
Consumer Dead Letter
메시지를 발행하여 재시도 처리 Dead Letter
서버 별도 구성하여DL
메시지를 다시 발행 처리
Transaction Messaging: Produssor Dead Letter(PDL)
- 메시지를 발행하는 도중 에러가 발생한다면,
Produssor Dead Letter
메시지를 발행하여 재시로 처리 Dead Letter
서버에서DL
메시지를 다시 발행 처리
Monitoring
- 각 원화/외화 서비스의 DB 를
ETL
로 별도 DB로 데이터를 저장 - 배치를 통해 별도 DB 의 이상 트랜잭션을 감지하고 알림
결론
- 금융권 차세대 프로젝트는 대규모 프로젝트를 기술 부채를 해결하기 위한 프로젝트
- 보통은 워터폴 방법론으로 차세대 프로젝트를 진행하기 때문에 큰 리스크를 가지게 된다.
Strangler Fig Pattern
- 기존 시스템을 점진적으로 새로운 시스템으로 대체하는 전략
- 모놀리식 시스템의 기능을 하나씩 마이크로 서비스로 전환
- 낮은 응집도와 높은 결합도의 모놀리식 서비스를 UseCase 단위로 독립적으로 분리
- 좋은 소프트웨어는 코드보다 철저한 설계로부터 나온다!!
- 효과적인 도메인 문서화로 지속적인 관리 효과를 발현
- 글보다는 시각적인 문서화가 더욱 더 이해하기 쉽다!!
- 다양한 시각과 의견으로 최선의 선택을 하고, 최적의 비즈니스 로직 유지 가능하다!!
- 부수효과를 막기 위해 기존 기능과 동일한 출력을 만들어내야 한다.
- 분할정복 리팩토링을 통해서 기능 뎁스/리프 별로 리팩토링하고, 흡수하고, 반복한다
- 리팩토링 코드를 검증하기 위해서 레커시/리팩토링 코드를 동시 병렬 실행하여 비교군을 만든다
- 검증 실패하는 경우, 다시 분석 > 설계 > 구현 단계를 반복한다
- 콘웨이 법칙
- 시스템은 조직을 닮는다. - 콘웨이
마이데이터
- 마이데이터 : 여러 금융기관에서 개인의 신용 정보 조회/제공 서비스
마이데이터 서비스 장애 대응
- 제공 기관의 요청을 조절하여 제공 기관의 부하 제어 필요
Resilience4j
서킷-브레이커 적용하여 제공 기관으로 가는 트래픽 제어- 하지만 멀티 인스턴스 구성 환경에서는, 각 인스턴스의 서킷-브레이커 상태를 알 수 없기 때문에 장애 발생 가능
트래픽 제어 Coordinator 서버
- 별도의 트래픽 제어 코디네이터 서버를 구성
- 장애포인트를 일원화, 유연하고 확장 가능한 별도 코디네이터 시스템을 구현
- 코디네이터에서 외부 업체별 서킷-브레이커 상태를 저장하고, 각 서비스 인스턴스는 코디네이터로 서킷-브레이커 상태를 조회
- 각 서비스 인스턴스는 로컬 캐시로 서킷-브레이커 상태를 저장하여, 제공 기관에 요청을 제어
토스 시스템 부하 개선
- 제공 기관의 응답이 느려 바로 성공 응답이 아니더라도, 유저 이탈 이후 다시 진입하더라도 결과를 다시 확인할 수 있도록 비동기 처리
- 하지만, 인프라 리소스에 대한 부하 발생
- 이를 해결하기 위해 Websocket & Polling 활용
- APP 에서 Websocket 를 통해 마이데이터 서비스와 연결하고, API 요청에 대한 응답은 바로 처리한다
- 그러면, 공용 네트워크 리소스에 대한 부하 해결
유동적인 대용량 데이터 처리 개선
- 유저의 패턴을 분석해서 유저 인입이 적은 날에는 배치 처리량을 늘려 서버 부하를 일자별로 분산한다
- 코루틴 채널을 통해서 배치 프로그램을 성능 개선
결론
- 엔지니어는 공학으로 문제를 해결하는 역할을 수행한다