You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Redis를 적용한 API 응답 시간은 기준 내에 들기 때문에 문제가 될 것은 없다.
그러나 추가적으로 성능을 개선할 수 있는 방법이 있어. Thread Pool을 조정하여 성능 개선을 시도했다.
Spring Boot는 기본적으로 Thread Pool의 Thread Max를 200개로 설정한다.
Thread가 너무 많으면 잦은 Cpu Context Switch로 인해 성능 저하가 발생할 수 있다.
Local PC는 vCPU 16개를 가지고 있어. 이를 기준으로 Goetz의 Thread Pool 공식에 따라 측정을 했다.
현재 서버가 명확하게 Cpu , I/O Bound 중 어디에 해당하는지 감이 잡히지 않아 둘 다 테스트를 했다.
Thread가 생성되는 시간을 제거하기 위하여, Thread Max와 Min 을 동일하게 설정했다.
1. Cpu Bound - Number of cores + 1
Thread 17개로 설정하여 테스트를 진행했다.
`Thread 17 부하테스트 결과 Table
Thread 17
avg
max
p95
1차
65.02ms
844.1ms
121.26ms
2차
63.91ms
278.01ms
122.24ms
3차
67.63ms
515.77ms
211.49ms
4차
51.02ms
168.24ms
85.42ms
5차
67.71ms
461.84ms
183.78ms
평균
63.06ms
453.59ms
144.84ms
2. I/O Bound - Number of cores * (1 + Wait time / Service time)
임의적으로 Thread 32개로 설정하여 테스트를 진행했다.
Wait time과 Service time 측정에 시간을 사용하기 보다는, 먼저 서버가 I/O Bound임을 가정하였다.
만약 서버가 I/O Bound인 경우, Cpu Bound 보다 많은 Thread를 설정했을 때 성능이 더 높을 것으로 예상한다.
Thread 32 부하테스트 결과 Table
Thread 32
avg
max
p95
1차
76.74ms
1.14s
193.47ms
2차
62.67ms
455.74ms
113.69ms
3차
56.24ms
428.98ms
87.66ms
4차
54.2ms
270.9ms
82ms
5차
131.95ms
1.23s
780.15ms
평균
76.36ms
705.12ms
251.39ms
결과
Thread
avg
max
p95
17
63.06ms
453.59ms
144.84ms
32
76.36ms
705.12ms
251.39ms
Thread 17로 설정했을 때가 모든 값에서 좋은 성능을 보인다.
서버는 Cpu Bound 작업을 위주로 하고 있으며, Thread Pool 조정을 통해 추가 성능을 개선 하였다.
평균 응답 속도는 102.16ms 에서 63.06ms로 38.27% 최적화
최대 응답 속도 또한 1.26s 에서 453.59ms로 64.00% 최적화
2. AI 서버 비동기 Callback 통신으로 컨텐츠 생성 시간 최적화
문제
일기 작성시, 웹툰(1분 30초), BGM(40초), 위로 메시지(2초) 생성을 위해 오랜 시간(약 2분 12초)이 소요됨
클라이언트는 일기 작성 후, 컨텐츠 생성이 완료되는 동안 웹 페이지를 벗어날 수 없음
원인 분석
WAS (Spring)는 AI 서버에게 컨텐츠 생성을 요청하고, 생성 결과를 끝까지 기다린 뒤에 클라이언트에게 응답함
해결 과정
컨텐츠(웹툰/BGM) 생성시 WebClient를 이용한 비동기 요청을 적용
위로 메시지는 응답 시간(약 2초)이 빠르다고 판단하여, 동기 요청 적용 및 즉시 클라이언트에게 응답
AI 서버는 컨텐츠(웹툰/BGM) 생성 완료시, WAS(Spring) 에게 HTTP의 POST 메서드로 컨텐츠 생성 완료 요청(callback)을 보냄
WAS는 결과를 DB에 저장
결과
일기 작성시 약 2분 12초(132초)의 대기 시간을 위로 코멘트 생성 시간 대기(2초)만으로 98.48% 최적화
콘텐츠를 생성하는 동안 클라이언트는 페이지간 이동이 자유롭게 가능하여 사용자 경험 개선
추가 개선점
일기 작성 후, 실제 2초를 기다려 보니 체감이 상당히 길었음.
위로 메시지 또한 비동기 요청 및 Callback 방식으로 전환이 필요.
개발 편의성 개선
1. 인증 객체의 getId() 값을 Controller에 자동 전달
문제
18번의 반복적인 getId() 메서드 발생
해결 과정
@AuthenticationPrincipal 에노테이션을 활용한, 커스텀 에노테이션 생성 및 SpEL 활용
결과
18개의 반복적인 코드 제거
2. Commit 메시지에 Jira Issue 번호 작성 자동화
문제
Commit Message 컨벤션에 의해 Message의 1번 줄 가장 오른쪽에 Jira Issue 번호 작성 필요
해결 과정
.git/hooks/commit-msg 파일에 Shell 스크립트 작성
Branch 이름에 있는 Jira Issue 번호를 가져와 Commit시 Message에 번호 작성 자동화
결과
Jira Issue 번호를 신경쓰지 않고 편하게 Commit 가능
Shell Script
#!/bin/sh## Get the current branch name
BRANCH_NAME=$(git symbolic-ref --short HEAD)# Extract project ID from branch name (e.g., 'todak4' from 'feature/todak4/auth')
PROJECT_ID=$(echo $BRANCH_NAME| sed -n 's/.*\/\([^/]*\)\/.*/\1/p')# Convert PROJECT_ID to uppercase
PROJECT_ID=$(echo "$PROJECT_ID"| tr '[:lower:]''[:upper:]')# Read the commit message from the file
commit_msg_file=$1
commit_source=$2
sha1=$3# Function to insert project ID at the end of the first lineinsert_project_id() {
# Read the first line
first_line=$(head -n 1 "$commit_msg_file")# Read the rest of the lines
rest_of_msg=$(tail -n +2 "$commit_msg_file")# Append project ID to the first line
modified_first_line="$first_line$PROJECT_ID"# Write the modified first line and the rest of the message back to the fileecho"$modified_first_line">"$commit_msg_file"if [ -n"$rest_of_msg" ];thenecho"$rest_of_msg">>"$commit_msg_file"fi
}
# Check if the commit message already contains the project IDif [ -n"$PROJECT_ID" ] &&! grep -qiF "$PROJECT_ID""$commit_msg_file";then
insert_project_id
fi
고려한 점
1. JPA Projection 과 Covering Index를 활용하여 DB 조회시 비용 감소
한 달간의 일기 작성 현황 정보를 API로 제공하기 위하여 아래와 같이 조치를 취함
Diary Table에 1.Member Id, 2.CreatedTime에 대한 DB Index 생성
위의 2가지 조건으로 Select 할 때, Diary Table의 Id와 Diary_Created_Time만을 Select 하는 Interface Projection 활용
2. JPA Cascade Delete 설정시 연관된 객체 수 만큼 쿼리가 발생하여, DB Cascade Delete 설정
공개 일기 삭제시, 연관된 일기 반응(Reaction)을 삭제하는 DB Cascade Delete 설정
공개 일기와 일기 반응은 양방향 연결 관계이기에, 공개 일기에 JPA Cascade Delete를 설정한 후 삭제를 하면 일기 반응 개수
만큼 Delete 쿼리가 발생하는 문제가 생겨 DB Cascade로 변경
그러나 10만개, 100만개의 일기 반응 Cascade Delete가 발생하면 DB에 부담이 가기에, 추후에 Batch와 Soft Delete를 활용하여 삭제 구현 예정
3. 동료와 Junit 기반으로 237개의 테스트 코드를 작성하여 Instruction Test Coverage 70% 기록
Google 에서 제안한 일반적인 Test Coverage를 기준으로 목표치 60% 이상 설정