-
Notifications
You must be signed in to change notification settings - Fork 6
성능 리포트
KIM DAEUN edited this page Dec 28, 2024
·
4 revisions
- 지원자 현황 대시보드
- 신규 공고 및 지원서 생성 화면
- (지원자 입장에서의) 공고 조회 화면
- ‘크루루’는 리크루팅 업무 플랫폼으로서, 지원자 및 공고 관리에 특화된 서비스입니다.
- ‘크루루’의 핵심 기능은 칸반보드 형태의 대시보드, 공고 및 지원서 생성 기능입니다. 이들은 모두 리크루팅 실무자의 업무 환경을 고려하여 데스크탑 화면을 기준으로 개발되었습니다.
- 이러한 개발 의도에 따라, 성능 측정/관리는 데스크탑 환경을 기준으로 진행합니다.
구분 | 내용 |
---|---|
Device | Macbook Air 15(M3 24GB, 2024) |
OS/Browser | macOS 14.5, Chrome 128 |
Network Throttling | Fast 4G |
CPU Throttling | 6X throttling |
구분 | 성능 지표 | 성능 예산 | 비고 |
---|---|---|---|
정량 기반 | 각 페이지에서 로드되는 JS 번들 용량 (압축 전) | ≤ 500kb |
기존 대비 50%+ 절감 |
개별 이미지 용량 | ≤ 150kb |
||
웹 폰트(Pretendard) 총 용량 | < 2mb |
기존 대비 50%+ 절감 | |
시간 기반 | LCP 시간 | < 2.5초 |
Lighthouse의 ‘Good’ 판별 기준 ㅡ |
FCP 시간 | < 1.8초 |
Lighthouse의 ‘Good’ 판별 기준 | |
CLS 점수 | < 0.1 |
Lighthouse의 ‘Good’ 판별 기준 | |
규칙 기반 | Lighthouse 성능 점수 | ≥ 95점 |
-
정량 기반 (번들, 이미지, 폰트 용량)
- 서비스 페이지가 완전히 로드되어 사용자와 상호작용이 가능하게 되기까지의 딜레이를 줄여서 사용자의 서비스 체감 속도를 높이고자 합니다.
-
시간 기반 (LCP, FCP, CLS)
- LCP(Largest Contentful Paint) : 사용자가 실제로 볼 수 있는 가장 큰 요소의 출력 타이밍을 앞당깁니다.
- FCP(First Contentful Paint) : 사용자의 초기 로딩 경험을 개선합니다.
- CLS(Cumulative Layout Shift) : 불필요한 레이아웃 변화를 최소화하여 시각적 안정성을 개선합니다.
-
규칙 기반 (Lighthouse 성능 점수)
- 위의 요소들을 종합적으로 모니터링 할 수 있는 Lighthouse 성능 점수를 모니터링 합니다.
구분 | 용량 | 비고 |
---|---|---|
JS 번들 용량 | 992.22kb |
압축시 252.98kb
|
개별 이미지 용량 | 없음 |
4kb 미만의 이미지는 base64 로 번들에 포함 |
웹 폰트 수량/용량 | 4개 / 각 파일당 약 1.2mb
|
Regular, Medium, SemiBold, Bold 사용 |
페이지 | Lighthouse | Chrome DevTools > Performance |
---|---|---|
지원자 현황 대시보드 | 78점 |
|
신규 공고 및 지원서 생성 화면 | 81점 |
|
공고 조회 화면 | 81점 |
-
리소스별 용량 절감 및 LCP 개선
- 페이지/Route별 번들링 분할 및 소스 최적화
- Chunk 분할 단위 설정 및 Code Splliting
- CSS Extract & Minify
- 웹 폰트 용량 절감, 로드 최적화
- Subset 이용
- weight 옵션 간소화
- CSS, Font 파일 각각 preload 처리
- 추후 이미지 추가시 화질 대비 용량 최적화 실행 (예: 랜딩 페이지)
- 페이지/Route별 번들링 분할 및 소스 최적화
-
리소스 로드 우선순위 변경
- 번들 파일, CSS, 웹 폰트, GA, Sentry 등 모니터링 스크립트
-
기타 렌더링 성능 개선
- 반복 렌더링 요소에 메모이제이션 적용 (공고 카드, 지원자 카드 등)
- 하나의 컴포넌트에 대한 복수/중복 애니메이션 발생 현상 수정
구분 | 성능 지표 | 성능 예산 | 개선 결과 | 비고 |
---|---|---|---|---|
정량 기반 | 각 페이지에서 로드되는 JS 번들 용량 (압축 전) | ≤ 500kb |
521kb |
Quill 에디터 제외시 |
< 500kb |
||||
개별 이미지 용량 | ≤ 150kb |
랜딩페이지 첫 커버 이미지 제외 | ||
약 150kb 내외로 조정 |
||||
웹 폰트(Pretendard) 총 용량 | < 2mb |
랜딩페이지 기준 | ||
< 300kb |
||||
시간 기반 | LCP 시간 | < 2.5초 |
< 1초 |
|
FCP 시간 | < 1.8초 |
< 1초 |
||
CLS 점수 | < 0.1 |
< 0.1 |
||
규칙 기반 | Lighthouse 성능 점수 | ≥ 95점 |
99~100 |
💡 기존에 모든 프론트엔드 코드가 하나의 파일(
main.js
)로 번들링되어 서비스되던 문제 개선
작업 사항
-
Route 단위로 React.lazy를 이용하여 Code Splitting 진행
const ErrorPage = lazy(() => import(/* webpackChunkName: "ErrorPage" */ '@pages/ErrorPage')); const SignIn = lazy(() => import(/* webpackChunkName: "SignIn" */ '@pages/SignIn')); const SignUp = lazy(() => import(/* webpackChunkName: "SignUp" */ '@pages/SignUp')); const Dashboard = lazy(() => import(/* webpackChunkName: "Dashboard" */ '@pages/Dashboard')); const RecruitmentPost = lazy(() => import(/* webpackChunkName: "RecruitmentPost" */ '@pages/RecruitmentPost')); const ConfirmApply = lazy(() => import(/* webpackChunkName: "SignConfirmApplyUp" */ '@pages/ConfirmApply')); const DashboardLayout = lazy(() => import(/* webpackChunkName: "DashboardLayout" */ '@pages/DashboardLayout')); const DashboardList = lazy(() => import(/* webpackChunkName: "DashBoardList" */ '@pages/DashBoardList')); const DashboardCreate = lazy(() => import(/* webpackChunkName: "DashboardCreate" */ '@pages/DashboardCreate'));
-
빌드 파일명에
contenthash
추가하여 Cache Busting 유도 -
Quill 에디터 등 특정 페이지에서만 사용되는 모듈/라이브러리는 별도의 Chunk로 분리 → 로드 효율 높임
작업 결과
Metric | Pre-Code Splitting | Post-Code Splitting | Sentry Optimization |
---|---|---|---|
Main JS Bundle Size | 998 KiB | 528 KiB (-470KiB) | 521 KiB (-7KiB) |
Gzipped Size | 252.98 KiB | 166.5 KiB | 164.87 KiB |
- 메인 번들 크기 47.8% 감소
💡 서비스 접속시 가장 큰 네트워크 병목을 일으킨 웹폰트 로드의 최적화 적용
작업 사항
- 웹폰트를 각 weight마다 통째로 불러오던 것을 가변 다이나믹 서브셋으로 변경
-
가변 다이나믹 서브셋이란?
- 다이나믹 서브셋 : CSS의 unicode-range 속성을 이용하여 해당 유니코드 영역의 문자가 사용될 때 폰트를 다운로드 하는 방식
- 가변 서체 : 모든 폰트의 굵기를 담고 있는 서체. 개별 폰트보다는 무거우나, 여러 개의 서로 다른 굵기 정보를 가진 폰트보다는 훨씬 가볍다는 장점이 있음
- 위의 두 가지 기술이 가진 장점을 합친 방식으로, 현재 모던 브라우저에서 모두 지원됨
-
가변 다이나믹 서브셋이란?
- 웹폰트 CDN 경로에 대한 preconnect, 웹폰트 CSS 리소스에 대한 preload 적용
- preload : 현재 페이지에서 필요한 리소스를 미리 로드
- preconnect : 브라우저가 현재 페이지에서 필요할 외부 도메인과의 연결을 미리 설정
작업 결과 (4G 네트워크 기준)
- 기존에는 웹폰트 하나를 다운로드 받는 데에 무려
5.99초
가 소요되며, 전체 약4.7MB
를 차지했습니다.
- 개선 이후에는 웹폰트 서브셋 하나당 다운로드가
0.45초
이내에 이루어지며, 전체262KB
만 차지합니다.
💡 Production 환경에 한하여, 아래와 같은 캐싱 정책을 수립하여 배포 환경에 적용했습니다.
구분 | 브라우저 캐시 | CDN 캐시 | 비고 |
---|---|---|---|
HTML | 0 | 1년 | Cache invalidation 활용 여부에 따라 CDN 캐시 기한을 조정 필요 |
CSS/JS | 1년 | 1년 | 파일명을 이용한 캐시 버스팅 활용 |
Image | 1년 | 1년 | 파일명을 이용한 캐시 버스팅 활용 |
Font | 1년 | 1년 | |
Etc (Default) | 1일 | (기본값 1일) |
AWS S3/CloudFront 환경에서의 리소스 캐싱 정책 및 적용 방안
💡 서비스 모니터링/테스트 과정에서 발견한 검색 노출 이슈를 해결하기 위한 작업을 진행했습니다.
- 검색에서 노출되어선 안 되는 경로들이 검색에 노출됨 (beta.cruru.kr)
- 본 서비스에 대해 파악 가능한 콘텐츠가 검색 노출 결과에 나타나지 않음
- 파비콘(Favicon) 미등록
- Favicon 디자인, 제작
- Open Graph용 커버 이미지(1200x630) 디자인, 제작
- 검색 노출시 우선적으로 크롤링되는
meta
태그에title
,description
등 정보 추가 - 카카오톡, 슬랙, 페이스북 등 여러 플랫폼에서 링크 공유시 노출되는 Open Graph 정보 추가
- 검색 엔진의 크롤링 로봇에 적용시킬
robots.txt
를 beta, prod 용으로 나누어 각각 추가 - 위의 모든 변동사항 적용에 필요한 webpack 설정 및 github actions workflow 수정
경로 | 페이지 | 베타(beta.cruru.kr) | 운영(cruru.kr) | 비고 |
---|---|---|---|---|
/ |
랜딩페이지 | X | O | |
/sign-in |
로그인 | X | X | |
/sign-up |
회원가입 | X | X | 로그인 필요 |
/dashboard/ |
대시보드 | X | X | 로그인 필요 |
/post/ |
공고 | X | X | 로그인 필요 |