GDG 송도 2024 07-26
7월 27일 토요일 티켓값이 아까워 가기싫은 몸을 이끌고 송도 컨퍼런스에 참석했다.
가는 지하철에서는 다시 돌아갈까 생각이 들정도로 가기 싫었지만, 같은 회사 동료분들과 같이 듣게 되니 생각보다는 덜했다. 역시 움직여서 일단 가는 시작이 반인 것 같다.
시간표
1시 넘어서 도착하는 바람에 1교시는 스킵하고 주변식당에서 밥을 먹었다.
2교시 올리브영 온라인몰의 전시전략
김우경 연사님의 발표였다.
올리브영 온라인몰의 전시, 그리고 백엔드 여정 | 올리브영 테크블로그
feat. 올리브영 온라인몰 Home 신규 아키텍처 전환기
oliveyoung.tech
올리브영 전시영역 MongoDB 도입하기 | 올리브영 테크블로그
올리브영 신규아키텍처 도입
oliveyoung.tech
무형상품 서비스에 캐시 적용하기 | 올리브영 테크블로그
SpringBoot와 Cache
oliveyoung.tech
Circuitbreaker를 사용한 장애 전파 방지 | 올리브영 테크블로그
Circuitbreaker와 Resilience4j A to Z
oliveyoung.tech
1. 올리브영 온라인물 역사
연도별로
쇼핑몰 - 모바일 앱 - 공식 온라인몰 오픈 O2O 서비스 강화 -트리플 1천만 플랫폼, AI 스타트업 인수
- 멀티클라우드 체계, 개발환경 표준화
2. 이커머스 전시영역 pain point
전시영역은 눈에 띄는 곳에 상품을 진열하는 전략, 방법론으로 이해했는데,
재고, 상품 기본정보등 수십개 컴포넌트들이 존재하고 사용자도 수백만명이라
수많은 트래픽 & 많은 데이터 필요의 상황이었다.
그럼에도 빨라야한다.
구글의 연구 리서치 결과, 로딩시간이 3초가 넘어가면 53퍼가 이탈한다고 한다.
메인화면은 구매여정의 첫시작이자 트래픽이 제일 많이 몰린다.
3.온라인몰 레거시와 MSA 전환
기존 서비스는 온프레미스 환경, 모놀리식 아키텍쳐로 구성되어 있었다고 한다.
모놀리식 : 모든 기능과 모듈이 1개의 통합된 시스템으로 동작하는 것.
온프레미스 환경 : 클라우드 사용이 아닌 기업의 데이터센터 내 서버와 네트워크 구축 및 운영하는 방식.
커플링이 심했다고 한다.
커플링 : 시스템 내의 모듈간 의존성을 의미한다.
그래서 개별 모듈을 따로 테스트하는게 어려웠고 조금만 수정해도 전체 테스트가 필요했던 상황.
온프레미스 환경 특성상, 스케일 아웃을 하려면 서버 대수를 늘리는 방식일텐데, 신규로 장비 구입 및 인프라관리등이 쉽지 않다. 그래서 최대로 가용해도 실패했었다고 한다.
요약
모놀리식 아키 커플링이 강했음-> 온프레미스환경. 스케일 업,아웃어려움 - 외주개발로 인한 히스토리x,사이드이펙트
-> 평균 3.37초로 부정적 앱
그래서
2022하반기 착수 , 몽고 DB 도입, 레디스로 캐시시스템 구축 -> 신규아키텍처
-> 2024 고가용성전략
의 순서로 진행했다고 한다.
개선 방향
1. 전시 관련 도메인 MSA 분리
2. 캐싱 레이어 구축
읽기 성능을 개선하기 위해 캐시 어사이드 패턴을 도입했다고 한다.
오토 스케일링을 위해 여러 서버에서 접근하여 참조할 수 있도록 글로벌 캐시 사용결정.
그래서 elastiCache를 도입
캐시 어사이드 : 캐시데이터에 데이터가 있으면 거기서 가져오고, 없으면 documentDB(몽고DB)에서 데이터 가져옴.


3. 몽고DB 도입
전시영역의 코너는 형태가 다양해서 비규칙적형태로 데이터가 구성된다.
레거시 시스템은 RDB에서 데이터를 관리하고 있어서 공통개념추출하여 데이터 타입으로 구분 및 관리했어야 했다.

문제점 :
- 공통 컬럼에 데이터를 보관해야 하여 컬럼을 명확한 목적으로 사용하지 못함 (문서 혹은 주석에 의존)
- 컨텐츠 구성 변경 시 많은 공수 및 확인 절차 필요
- json 데이터로 변환 시 다량의 가공작업 필요
MongoDB 장점
1. 스키마 없음. 테이블-컬럼 구조가 아닌 컬렉션안에 json형태로 데이터 보관. 그래서 구조변경이 유용하다.
2. R/W가 매우 빠름. Btree 구조라서. 시간 복잡도 O(log n)을 유지함.
그중 주목한건 스키마-less 구조로 인한 유연성.
MongoDB에서는 각각의 데이터를 객체 형태로 관리할 수 있기 때문에 해당 오브젝트별로 명확한 데이터관리가 가능능.
이로써, 데이터 관리의 이점을 살리며 불필요한 가공과정까지 제거하며 효율을 극대화.

버저닝
MongoDB의 장점인 유동적인 데이터관리를 더욱 극대화하기 위해, 데이터를 버전화하여 관리


-올리브영에 전시되는 상품이나 컨텐츠는 시간에 따라 지속해서 변하기 때문에 매번 조건에 따른 컨텐츠를 불러와야 합니다.
이에 데이터를 버전화하여 현재 활성화된 데이터를 별도의 가공이나 복잡한 탐색 없이 확인하고,
변화될 데이터를 미리 준비하거나 필요 시 롤백하여 더욱 안정적인 데이터 관리를 가능하게 하였습니다.
4. 캐싱 데이터 세분화
전시영역은 정적영역과 개인화영역 2가지로 나뉘어 있었는데, 정적영역도 하단 스크롤을 내리는 유저가 18%밖에 없어서 영역별로 분리하여 불필요 데이터로 인한 비용을 감소.
요약
MSA 전환 -> 캐시어사이드(레디스 사용. 높은 TPS low 레이턴시집중) -> 캐시 스템피드문제( 캐시미스시 RDB
부하 방지를 위해 NOSQL로 전시데이터 사전가공 보관) -> 버저닝 전략.
4. 고가용성
서킷 브레이커를 도입하여 특정 시스템의 지연을 전체 장애로 이어지지 않게 했다.
Redis -> MongoDB -> oracle의 3중 방벽을 세웠다.
'어떠한 환경에서도 Home 은 노출되어야 한다’
CircuitBreaker는 문제가 발생한 지점을 감지하고 실패하는 요청을 계속하지 않도록 방지하며,
이를 통해 시스템의 장애 확산을 막고 장애 복구를 도와주며 유저는 불필요하게 대기하지 않게 됩니다.
아래 그림과 같이 Service A 가 Service B를 호출할 때
Service B가 반복적으로 실패한다면 CircuitBreaker를 Open 하여 Service B 에 대한 흐름을 차단하는 게 CircuitBreaker의 역할입니다.


맺음말이 참 기억에 남았다.
"어떤기술을 사용하는지는 크게 중요하지 않다.
고객경험을 위한 꺾이지 않는 개선 의지가 있고,
그것을 진행하고 있는 것이 종요합니다"
- 레거시는 회사가 살아남았다는 증거다.
- 단위테스트, 일관된 코딩 컨벤션, 코드리뷰등 품질향상을 위한 끊임없는 노력.
- 안정적인 시스템 구축에 대한 해답은 단순히 기술에 있지 않다.
회사에서도 현 시스템과 서버의 상황을 파악하고, 그에 맞는 개선을 어떻게 할지 고민해보는 자세가 필요하겠다는 생각이 들었다.
3교시 테스트 자동화 사례 공유
테스트코드의 개념
독립성,자동화,명확성,재현성, 범위, 유지보수
장점
- 품질보증
의도대로 동작, 버그 조기 발견 - 비용절감
자동화테스트는 장기적으로 시간과 비용 절약 가능
반복적인 테스트를 빠르게 수행 가능. (룰만 제대로 정해지면.) - 유지보수 용이성
- 문서화 역할
예상 동작을 명확히 보여주는 살아있는 문서역할 - 설계개선
TDD로 모듈화 및 유지보수쉬운 코드 작성가능
코드 결합도 및 응집도 높이기 기여 - 회귀 테스트
수정시에도 기존 기능의 정상동작 여부 - 개발자 신뢰도 향상.
제품에 대한 자신감 및 생산성 향상. - CI/CD 지원
자동화된 테스트는 CI/CD 파이프라인 핵심 요소. - 예외 처리 개선
다양한 시나리오 테스트. 예상치못한 상황 대비 강화
테스트코드 단점
- 개발시간 증가
초기 개발시 추가적인 시간과 노력 요구
(의도와 목적에 따라 과감히 포기하는것도 방법) - 유지보수 부담
코드 변경시 테스트 코드 업데이트 필요. - 잘못된 안정감
모든 시나리오 커버가 안되면 안심하게 되서 버그, 엣지 케이스 누락 가능 - 복잡성 증가
테스트 시나리오가 매우 복잡한 경우. - 리소스 소비
테스트실행시 컴퓨팅 리소스, CI/CD 파이프라인 속도 저하 - 오버엔지니어링 위험
테스트에 과도한 집중으로 필요이상 복잡한 테스트코드
불필요 작업 및 코드 가독성 저하 초래. - 테스트환경 구축
특정 시나리오 테스트를 위한 환경 구축 - 잘못된 테스트
너무 구체적이면 코드 유연성 저하 및 작은 변경에도 테스트 실패 - 학습 곡선
효과적인 테스트 코드 작성 스킬습득 및 일관성 유지는 상당한 시간과 노력 필요
범위별 테스트 코드 유형
- 단위테스트 -개별함수, 메서드 동작
- 기능테스트- 특정 기능 flow 테스트
- 통합테스트 - 애플리케이션 서버와 DB간 데이터 저장 및 조회과정이 정상적으로 동작하는지
- E2E테스트 - 전체 프로세스 검증
목적별 테스트 코드 유형
- 성능 테스트 - 리소스 데드락 등
- 보안테스트 - ex sql 인젝션
- 사용성 테스트 - 데이터독을 사용할 수도 있음 히트로
- 회귀 테스트 - 새 변경 사항이 기존 기능에 부정적영향을 미치진 않았는지 검증. 이전에 통과한 테스트를 재실행
테스트 자동화의 필요성
- 복잡한 테스트 범위
- 정밀한 수동 테스트 케이스
- 유닛테스트 환경 고도화중임
의사결정 배경
전문 QA인력 활용, 자동화코드개발 역량보유, 개발 리소스 전략적 배분
내부 admin 서비스 활용
비동기처리
슬랙으로 실시간 알림
결과 보고
자동생성하는 상세 보고서

서버리스 펑션 사용이유는 비용 절감을 위해서
- api test : Jest 유닛 테스트와 기술 스택 통일.
- gui test : playwright 병렬 테스트 실행 지원, 테스트 수행 시간 대폭 단축
서버리스 펑션 환경의 playwright 구현과제
playwright가 서버리스 function 환경에서는 지원이 부족한 환경이라 어려움을 겪으셨다고 한다.
- 브라우저 모듈 부재 -> 환경 맞춤 이미지 구성
- 테스트 코드 작성 최적화 -> 테스트 클래스 구현
- 리포트 생성 기능 개발 -> 리포팅 모듈 구현
람다 펑션에서는 병렬처리가 안되는게 흠. 로컬환경에서는 됨.
팁
시나리오, 케이스 작성 사례
부정적인 케이스
작성 팁
1.비즈니스에 집중 : 인풋 아웃풋 집중하기 보단.
이메일 형식이 올바르지 않을때 특정 에러 리튼과 같이 기능 정의 및 문제해결 관점에서
케이스 네임 정의
2.네거티브 케이스 집중 : 타임존과 같은 경계값 테스트
3. 다양한 관점 : 기대하는 순서와 반대로 기능동작, 시간관점, 다국어관점등
실제 사용자 관점에서 해볼법한 시나리오 고민

playwright 도입시 도움을 얻었던 래퍼런스도 공유해 주셨다.
테스트의 전반적인 개념과
자동화를 위해 서버리스펑션, 메세지큐를 도입한 내용이었다.
관련 개념이 부족해서 그렇구나 정도로만 받아들인게 아쉬웠다. 메세지큐와 서버리스펑션에 대해 공부가 필요하다.
4교시 100명의 개발자분들을 도와 100개 넘는 오픈소스PR을 함께 만들고 세상을 바꾼 이야기
김인제 연사님의 강연이었다.
강의는 연사님의 오픈소스PR 기여에 발담그게 된 스토리,
예시,
오픈소스 PR 방법,
마무리글 및 앞으로 진행하실 일에 대해 얘기해주셨다.
전반적으로 예시를 보여주시면서 설명해주셨는데, 아무래도 영어로 전부 되어있다보니 저런게 있구나 정도 밖에 인식하지 못했다.
오픈소스에 기여하는 것 자체는 정말 좋은 문화라고 생각하고 있고,
오픈소스 모각코나 멘토링, 컨퍼런스도 예정되어 있다고 해서 관련 정보를 찾아보는게 필요해 보였다.

5교시 왜 내가 만든 쿼리는 항상 느릴까?
강성욱
특정 케이스를 예제로 설명
공통 튜닝케이스 얘기.
엣지 케이스마다 솔루션이 달라서 그대로 현업에 적용하면 위험함.
목차
- 문제를 바르게 인식하기
- 인덱스 기초 이해
- 다양한 사례를 통한 튜닝 전략
효율적인 인덱스 전략
좋은 튜닝이란?
전제조건
1. 비즈니스 이해
2. 무엇이 문제인지 정의하는 것. 진짜 느린쿼리가 맞는지? ex : top slow 쿼리 튜닝
3. 사고방식을 DB처럼 생각해야함. Optimizer 관점에서 생각. 사람이 생각하는 방식이 아닌.
문제 바르게 인식하기
엔드포인트의 장애(ex: DB는 대부분 시스템에서 엔트포인트를 맡는다.)
는 전체 장애로 확산된다.
사전 예방 방법?
개발 프로세스강화?
모니터링 강화?
이중화?
쿼리가 느린 것 판단 방법
응답속도?
실행계획 분석?
느리다고 하니까?
느낌으로?
문제 해결시에는 먼제의 정의부터 명확히 해야한다
DB성능을 이야기할때는 순수 DB관점에서 파악해야 한다.

DBA관점에서는 DB의 응답속도만 본다.
다행히 DB는 쿼리만 봐도 어느정도 성능 예측이 된다.
데이터 적재, 이미쌓여진 데이터 있음, 스키마 사전정의, 사용자패턴(인덱스설계)
DBMS의 물리적 특성알고 있어서
ORM으로 하는데 쿼리를 알아야 하는 이유?
객체를 통해 간접적으로 데이터베이스 데이터를 제어한다.
-> 아직까지는 ORM이 모든것을 커버할 수는 없다.
잘 읽는 방법 순서
1.from
2.where
3.on
4.select
그외..
분석방법
- 테이블의 정보 수집
- 생성된 인덱스,
- where절, on절에 사용된 키가 인덱스에 있는지
- select에 사용된 컬럼이 인덱스에 있는지 -> 커버링 인덱스
- 제약조건확인
- 컬럼 속성 확인
- 조회하는 컬럼길이가 얼마인지 데이터 확인
인덱스의 기초 이해
클러스터 인덱스
- 인덱스값 기반 테이블 데이터행 전체를 정렬해서 저장.
- 키값으로 정렬된 넓은 범위 검색에 유리하다.
- 테이블당 1개 인덱스 생성가능.
- 운영중에는 함부로 인덱스 생성 x. 락이 발생할 수도 있어서
- 인덱스가 잠기면 테이블이 잠김(키락) 모든 데이터가 잠김.
넌 클러스터 인덱스
- 테이블당 여러개 생성 가능
- 인덱스 추가와 삭제는 쉽게 볼게 아니고 넌, 클러스터 순서가 중요함
- 인덱스는 선정되는 칼럼크기는 되도록 작을 수록 좋다. 인덱스는 btree -> logn. 깊이가 중요하다. 그래서 인덱스 깊이에 성능이 영향 받는다.
사례
컬럼순서는 중요하지 않다.
1. 쿼리 파서는 SQL 문장을 잘게 쪼개서 트리형태로 구조를 생성한다.
문법, 쿼리문장 구조적 문제, 객체의 존재여부와 접근권한 확인
쿼리오류나 권한이 없으면 이단계에서 걸러진다.
최적의 경로 찾기.
2. 옵티마이저는 쿼리를 가장 저렴하고 빠르게 처리할 수 있는 방법 을 결정함.
sQL 파싱 정보를 찾아서 읽을테이블,인덱스 선택
3. 쿼리 플랜 생성
대부분 옵티마이저가 선택하고, 옵션과 힌트로 사용자가 더 나은 선택하도록 유도
4. 쿼리플랜 실행
스토리지 엔진은 레코드 반환.
SQL엔진이 조인,정렬등 작업진행
실행엔진이 결과를 사용자에게 반환한다.
쿼리실행시 진행되는 단계를 알려주시면서 컬럼순서가 중요하지 않다는 내용을 강조하셨는데,
이해가 부족해서 다 파악하지는 못했다 ㅠ
다양한 사례를 통한 튜닝 전략
- 반드시 필요한 칼럼만 조회한다.
- Lookup 최소화
- 인덱스에 없는 컬럼데이터 조회를 위해 실제 데이터
- lookup은 랜덤 엑세스 방식으로 실제 I/O 비용이 너무 많이 발생함. 대부분의 슬로우 쿼리이슈
- 복합인덱스는 컬럼순서가 중요하다.
- 선행 컬럼에 따라 성능차이가 크다
- 복합 인덱스여도 트리 높이가 동일하면 검색속도가 동일하다.
- 형변환 주의(컬럼 가공)
- 데이터타입 불일치로 암시적 형변환 발생하면 인덱스를 사용할 수 없다.
- 부정조건 보다 긍정조건으로 최대한 변경.
- 부정조건은 조건외 나머지 모두를 뜻해서 전체를 다 읽어야함.
- NOT IN, !=은 outer join으로 변경해서 Null검색으로 치환하자
- 조인 조건에 인덱스가 있어야 효과가 있다.
- 데이터 존재 유무 판단하는 다양한 방법
- EXISTS를 사용권장. 1행이라도 검색되면 TRUE 반환하고 종료
- 데이터 합칠때
- UNION ALL을 UNION보다 권장. SORT작업이 생략되기 때문.
- 불필요한 정렬, 그룹화는 성능저하의 요소
- 정렬할때 최대한 인덱스 활용 유도
- 조인은 양날의 검이다
- 최대한 최소한 데이터만 조인에 사용되도록 작성
- 사용자 함수는 정말 주의해서 사용하기(웬만하면 사용금지)
- 결과 row수만큼 함수가 호출됨
- 최대한 결과행을 작게 만들고 함수 사용을 권장한다.
- 수행횟수 줄이기 or 함수 내부 최적화하기.
- 서브쿼리는 정말 느릴까?
- select에 사용되는 스칼라 서브쿼리는 성능에 문제.row수만큼 호출되므로.
- from 인라인 서브쿼리는 쿼리속도 향상에 많은 도움.
인덱스 선정 전략
- lookup 최소화
- 적은 범위에는 클러스터인덱스
중간 커버인덱스 레인지스캔
넓은 -> 클러스터
DB튜닝은 지속적으로 이루어져야 한다.
DB의 끝은 모델링이다.
전체적으로, 제너럴한 DB 관련 내용이라고 하셨지만 배경지식이 너무나도 필요했던 세션이었다.
특히, 클러스터 인덱스와 넌클러스터 인덱스 생성시, 순서에 따라 DB가 죽을 수도 있다는 내용은 생각지도 못한 내용이었다.
튜닝 전략 정도는 쿼리 작성시에 해볼 수 있겠다는 정도의 생각..?
항상 느끼는 거지만, 송도는 너무 멀다..ㅠ
그럼에도 방문하는 사람들이 정말 많았고, 그만큼 성장하려고 하는 사람들이 넘쳐나는구나 하는 동기를 느낄 수 있었던 하루였다.
물론, 당장 들은 내용들을 바로 적용하기란 불가능할 것이다. 회사마다 상황이 전부 다르니까.
하지만 올리브영 세션에서 들었듯이, 개선의 의지를 가지고 조금씩 해보려고 하는 자세가 더 중요하겠다는 생각이 든다.
(알람 개선이나 단위 테스트 도입부터라던가..)