
ํ์ : PM(1) / Design(1) / Frontend(2) / Backend(3)
๊ธฐ๊ฐ : 2024.03 ~ 2025.03
๋งํฌ : https://github.com/M-ung/MoodBuddy_Server
์๋น์ค ๋ด์ฉ : ์ฌ์ฉ์๊ฐ ์์ฑํ ์ผ๊ธฐ๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ์ ๋ถ์ํ๋ ์น ์๋น์ค
์ํต : GitHub, Slack, Notion, Discord
์ผ๊ธฐ ๋ชฉ๋ก ์กฐํ ์๋๋ฅผ ๋์ด๊ธฐ ์ํด์ Redis ์บ์๋ฅผ ์ ์ฉํ๋ค. ํ์ง๋ง ๋จ์ํ ์๋ต ์กฐํ๋ฅผ ๋์ด๊ธฐ ์ํด Redis๋ฅผ ์ ์ฉํ์ฌ, ์คํ๋ ค ๊ด๋ฆฌ ์ธก๋ฉด์์ ๋ถ๋ด์ ๋๊ผ๋ค.
๋ํ, ์ฌ์ฉ์ id์ ํ์ด์ง ๋ฒํธ ์กฐํฉ์ผ๋ก ์บ์ ํค๋ฅผ ์์ฑํ๋ค ๋ณด๋, ์ฌ์ฉ์ ์์ ํ์ด์ง ์์ ๋น๋กํด ์บ์ ํค๊ฐ ๊ธ๊ฒฉํ ์ฆ๊ฐํ๊ฒ ๋์๋ค. ์ด ์ญ์... ๋ฉ๋ชจ๋ฆฌ ์์์ ์ง์์ ์ผ๋ก ์๋นํ๋ ์์ธ์ด ๋์๋ค.
๊ฒฐ๊ตญ ์ฌ์ฉ์๊ฐ ๋๋์ผ๋ก ๋ชฐ๋ฆด ๊ฐ๋ฅ์ฑ์ด ๋ฎ์ ๊ธฐ๋ฅ์ Redis๋ฅผ ์ฐ๊ฒฐํ๋ฉด์ ์คํ๋ ค ๊ฐ๋ฐ ๋ฐ ์ด์ ๋น์ฉ์ ๋์ด๋ ์์ธ์ด ๋์๋ค.
์๋ k6 ๊ฒฐ๊ณผ๋ Redis ์บ์๋ฅผ ์ ์ฉํ์ ๋์ ๊ฒฐ๊ณผ์ด๋ค.
๐ ์ผ๊ธฐ ๋ชฉ๋ก ์กฐํ ํ
์คํธ ๊ฒฐ๊ณผ (Redis Cache ์ ์ฉ)

์๋์ ๊ฐ์ด ์ผ๊ธฐ ๋ชฉ๋ก ์กฐํ์๋ง ํ์ํ ํ ์ด๋ธ์ ๋ฐ๋ก ๋ง๋ค์๋ค.
Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
name = "diary_query",
uniqueConstraints = @UniqueConstraint(columnNames = {"userId", "date"}),
indexes = {
@Index(name = "idx_id_user_Id_mood_buddy_status", columnList = "diary_id, user_id, mood_buddy_status"),
@Index(name = "idx_user_Id_mood_buddy_status_date", columnList = "user_id, mood_buddy_status, date")
}
)
public class DiaryQuery {
@Id
@Column(name = "diary_id")
private Long diaryId;
@Column(name = "title", nullable = false)
private String title;
@Column(name = "date", nullable = false)
private LocalDate date;
@Column(name = "content", nullable = false, columnDefinition = "text")
private String content;
@Column(name = "user_id", nullable = false, columnDefinition = "bigint")
private Long userId;
@Column(name = "thumbnail", columnDefinition = "text")
private String thumbnail;
@Enumerated(EnumType.STRING)
@Column(name = "emotion")
private DiaryEmotion emotion;
@Enumerated(EnumType.STRING)
@Column(name = "subject")
private DiarySubject subject;
@Enumerated(EnumType.STRING)
@Column(name = "mood_buddy_status")
private MoodBuddyStatus moodBuddyStatus;
}
๊ทธ๋ฆฌ๊ณ yml ์ค์ ์ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํ์ฌ, Spring Cache๋ก ๋ณ๊ฒฝํ๋ค.
spring:
threads:
virtual:
enabled: true
cache:
type: simple
๐ ๋ถํ ์ฆ๊ฐ ๋จ๊ณ
๐ ํ ์คํธ ์์ฒญ
๐ ํ ์คํธ ํต๊ณผ ๊ธฐ์ค
๐ ์ผ๊ธฐ ๋ชฉ๋ก ์กฐํ ํ
์คํธ ๊ฒฐ๊ณผ (Spring Cache ์ ์ฉ)

| ์งํ | Redis Cache ์ ์ฉ | Spring Cache ์ ์ฉ | ๊ฐ์ ์จ |
|---|---|---|---|
์ด ์์ฒญ ์ (http_reqs) | 474,188 | 473,652 | 0.11% ๊ฐ์ |
์๋ต ์๊ฐ ํ๊ท (http_req_duration avg) | 12.33ms | 13.2ms | 7.04% ์ฆ๊ฐ |
์๋ต ์๊ฐ 90ํผ์ผํธ (p(90)) | 23.89ms | 27.01ms | 13.04% ์ฆ๊ฐ |
์๋ต ์๊ฐ 95ํผ์ผํธ (p(95)) | 33.22ms | 38.22ms | 15.05% ์ฆ๊ฐ |
๋๊ธฐ ์๊ฐ ํ๊ท (http_req_waiting avg) | 12.26ms | 13.13ms | 7.1% ์ฆ๊ฐ |
์ต๋ ์๋ต ์๊ฐ (http_req_duration max) | 979.22ms | 2.08s | 112.4% ์ฆ๊ฐ |
์ด๋ฒ ํ
์คํธ๋ ํ์ค๋ณด๋ค ํจ์ฌ ๋์ ๋ถํ์ธ 1000๋ช
์ ๋์ ์ฌ์ฉ์(VUs)๋ฅผ ๊ฐ์ ํ ํ๊ฒฝ์์ ์งํ๋์๋ค.
์ด๋ฌํ ์กฐ๊ฑด์ ์ค์๋น์ค์์ ์์ฃผ ๋ฐ์ํ์ง ์์ง๋ง, ์ต์
์ ์ํฉ์ ๊ฐ์ ํ ์ฑ๋ฅ ์์ ์ฑ ํ๊ฐ๋ก๋ ์๋ฏธ๊ฐ ์๋ค.
Spring Cache๋ Redis Cache์ ๋นํด ํ๊ท ์๋ต ์๊ฐ๊ณผ ์ต๋ ์๋ต ์๊ฐ์์ ๋ค์ ๋๋ฆฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์์ง๋ง, ๊ทน๋จ์ ์ธ ๋ถํ ํ๊ฒฝ์์ ๋ํ๋ ์ฐจ์ด์ด๋ฉฐ, ์ค์ ์ด์ ์ํฉ์์๋ ๊ทธ ์ฐจ์ด๊ฐ ์ฒด๊ฐ๋ ์์ค์ ์๋๋ผ๊ณ ์๊ฐํ๋ค.
๐ Spring Cache ์ ์ฉ์ผ๋ก ์ป์ ์ด์
๊ฒฐ๊ณผ์ ์ผ๋ก ์๋๋ ์ฝ๊ฐ ๋ฎ์์ก์ง๋ง, ์ด์ ๋น์ฉ์ ์ค์๋ค๋ ์ ์์ ์ถฉ๋ถํ ์ข์ ์ ํ์ด๋ผ๊ณ ์๊ฐํ๋ค.