diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt b/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt
index 3fa5d11..015324c 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt
@@ -4,10 +4,13 @@ import org.springframework.beans.factory.annotation.Value
 import org.springframework.cache.annotation.EnableCaching
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
+import org.springframework.data.redis.cache.RedisCacheConfiguration
+import org.springframework.data.redis.cache.RedisCacheManager
 import org.springframework.data.redis.connection.RedisConnectionFactory
 import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
 import org.springframework.data.redis.core.RedisTemplate
 import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
+import java.time.Duration
 
 @Configuration
 @EnableCaching
@@ -29,4 +32,21 @@ class RedisConfig(
         redisTemplate.setConnectionFactory(redisConnectionFactory())
         return redisTemplate
     }
+
+    @Bean
+    fun cacheManager(redisConnectionFactory: RedisConnectionFactory): RedisCacheManager {
+        val defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
+            .entryTtl(Duration.ofMinutes(30))
+
+        val cacheConfigMap = mutableMapOf<String, RedisCacheConfiguration>()
+        cacheConfigMap["default"] = RedisCacheConfiguration.defaultCacheConfig()
+            .entryTtl(Duration.ofMinutes(30))
+        cacheConfigMap["cache_ttl_3_days"] = RedisCacheConfiguration.defaultCacheConfig()
+            .entryTtl(Duration.ofDays(3))
+
+        return RedisCacheManager.builder(redisConnectionFactory)
+            .cacheDefaults(defaultCacheConfig)
+            .withInitialCacheConfigurations(cacheConfigMap)
+            .build()
+    }
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt
index 5b6b050..c2d80d0 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt
@@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.event.EventItem
 import kr.co.vividnext.sodalive.member.Member
 import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
 import org.springframework.beans.factory.annotation.Value
+import org.springframework.cache.annotation.Cacheable
 import org.springframework.data.domain.Pageable
 import org.springframework.stereotype.Service
 import java.time.DayOfWeek
@@ -29,21 +30,103 @@ class AudioContentMainService(
 ) {
     fun getMain(member: Member): GetAudioContentMainResponse {
         val isAdult = member.auth != null
+        val memberId = member.id!!
 
         // 2주일 이내에 콘텐츠를 올린 크리에이터 20명 조회
-        val newContentUploadCreatorList = repository.getNewContentUploadCreatorList(
+        val newContentUploadCreatorList = getNewContentUploadCreatorList(memberId = memberId, isAdult = isAdult)
+
+        val bannerList = getAudioContentMainBannerList(memberId = memberId, isAdult = isAdult)
+
+        // 구매목록 20개
+        val orderList = orderService.getAudioContentMainOrderList(
+            member = member,
+            limit = 20
+        )
+
+        // 콘텐츠 테마
+        val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult)
+
+        // 새 콘텐츠 20개 - 시간 내림차순 정렬
+        val newContentList = repository.findByTheme(
             cloudfrontHost = imageHost,
             isAdult = isAdult
         )
             .asSequence()
-            .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) }
+            .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) }
             .toList()
 
-        val bannerList = repository.getAudioContentMainBannerList(isAdult = isAdult)
+        val curationList = getAudioContentCurationList(memberId = memberId, isAdult = isAdult)
+
+        val currentDateTime = LocalDateTime.now()
+        val startDate = currentDateTime
+            .minusWeeks(1)
+            .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
+            .withHour(15)
+            .withMinute(0)
+            .withSecond(0)
+        val endDate = startDate.plusDays(7)
+
+        val contentRanking = getContentRanking(isAdult = isAdult, startDate = startDate, endDate = endDate)
+
+        return GetAudioContentMainResponse(
+            newContentUploadCreatorList = newContentUploadCreatorList,
+            bannerList = bannerList,
+            orderList = orderList,
+            themeList = themeList,
+            newContentList = newContentList,
+            curationList = curationList,
+            contentRanking = contentRanking
+        )
+    }
+
+    fun getThemeList(member: Member): List<String> {
+        return audioContentThemeRepository.getActiveThemeOfContent(isAdult = member.auth != null)
+    }
+
+    fun getNewContentByTheme(theme: String, member: Member, pageable: Pageable): List<GetAudioContentMainItem> {
+        return repository.findByTheme(
+            cloudfrontHost = imageHost,
+            theme = theme,
+            isAdult = member.auth != null,
+            offset = pageable.offset,
+            limit = pageable.pageSize.toLong()
+        )
+            .asSequence()
+            .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) }
+            .toList()
+    }
+
+    fun getNewContentFor2WeeksByTheme(theme: String, member: Member, pageable: Pageable): GetNewContentAllResponse {
+        val totalCount = repository.totalCountNewContentFor2Weeks(theme, isAdult = member.auth != null)
+        val items = repository.findByThemeFor2Weeks(
+            cloudfrontHost = imageHost,
+            theme = theme,
+            isAdult = member.auth != null,
+            offset = pageable.offset,
+            limit = pageable.pageSize.toLong()
+        )
+
+        return GetNewContentAllResponse(totalCount, items)
+    }
+
+    @Cacheable(cacheNames = ["default"], key = "'getNewContentUploadCreatorList:' + #memberId + ':' + #isAdult")
+    fun getNewContentUploadCreatorList(memberId: Long, isAdult: Boolean): List<GetNewContentUploadCreator> {
+        return repository.getNewContentUploadCreatorList(
+            cloudfrontHost = imageHost,
+            isAdult = isAdult
+        )
+            .asSequence()
+            .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) }
+            .toList()
+    }
+
+    @Cacheable(cacheNames = ["default"], key = "'getAudioContentMainBannerList:' + #memberId + ':' + #isAdult")
+    fun getAudioContentMainBannerList(memberId: Long, isAdult: Boolean) =
+        repository.getAudioContentMainBannerList(isAdult = isAdult)
             .asSequence()
             .filter {
                 if (it.type == AudioContentBannerType.CREATOR && it.creator != null) {
-                    !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creator!!.id!!)
+                    !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creator!!.id!!)
                 } else {
                     true
                 }
@@ -86,26 +169,9 @@ class AudioContentMainService(
             }
             .toList()
 
-        // 구매목록 20개
-        val orderList = orderService.getAudioContentMainOrderList(
-            member = member,
-            limit = 20
-        )
-
-        // 콘텐츠 테마
-        val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult)
-
-        // 새 콘텐츠 20개 - 시간 내림차순 정렬
-        val newContentList = repository.findByTheme(
-            cloudfrontHost = imageHost,
-            isAdult = isAdult
-        )
-            .asSequence()
-            .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) }
-            .toList()
-
-        val curationList = repository
-            .getAudioContentCurations(isAdult = isAdult)
+    @Cacheable(cacheNames = ["default"], key = "'getAudioContentCurationList:' + #memberId + ':' + #isAdult")
+    fun getAudioContentCurationList(memberId: Long, isAdult: Boolean) =
+        repository.getAudioContentCurations(isAdult = isAdult)
             .asSequence()
             .map {
                 GetAudioContentCurationResponse(
@@ -119,10 +185,7 @@ class AudioContentMainService(
                     )
                         .asSequence()
                         .filter { content ->
-                            !blockMemberRepository.isBlocked(
-                                blockedMemberId = member.id!!,
-                                memberId = content.creatorId
-                            )
+                            !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId)
                         }
                         .toList()
                 )
@@ -130,16 +193,11 @@ class AudioContentMainService(
             .filter { it.contents.isNotEmpty() }
             .toList()
 
-        val currentDateTime = LocalDateTime.now()
-        val startDate = currentDateTime
-            .minusWeeks(1)
-            .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
-            .withHour(15)
-            .withMinute(0)
-            .withSecond(0)
-        val endDate = startDate
-            .plusDays(7)
-
+    @Cacheable(
+        cacheNames = ["cache_ttl_3_days"],
+        key = "'getAudioContentCurationList:' + ':' + #isAdult + ':' + #startDate + ':' + #endDate"
+    )
+    fun getContentRanking(isAdult: Boolean, startDate: LocalDateTime, endDate: LocalDateTime): GetAudioContentRanking {
         val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일")
         val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일")
 
@@ -151,50 +209,10 @@ class AudioContentMainService(
                 isAdult = isAdult
             )
 
-        val contentRanking = GetAudioContentRanking(
+        return GetAudioContentRanking(
             startDate = startDate.format(startDateFormatter),
             endDate = endDate.minusDays(1).format(endDateFormatter),
             contentRankingItemList
         )
-
-        return GetAudioContentMainResponse(
-            newContentUploadCreatorList = newContentUploadCreatorList,
-            bannerList = bannerList,
-            orderList = orderList,
-            themeList = themeList,
-            newContentList = newContentList,
-            curationList = curationList,
-            contentRanking = contentRanking
-        )
-    }
-
-    fun getThemeList(member: Member): List<String> {
-        return audioContentThemeRepository.getActiveThemeOfContent(isAdult = member.auth != null)
-    }
-
-    fun getNewContentByTheme(theme: String, member: Member, pageable: Pageable): List<GetAudioContentMainItem> {
-        return repository.findByTheme(
-            cloudfrontHost = imageHost,
-            theme = theme,
-            isAdult = member.auth != null,
-            offset = pageable.offset,
-            limit = pageable.pageSize.toLong()
-        )
-            .asSequence()
-            .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) }
-            .toList()
-    }
-
-    fun getNewContentFor2WeeksByTheme(theme: String, member: Member, pageable: Pageable): GetNewContentAllResponse {
-        val totalCount = repository.totalCountNewContentFor2Weeks(theme, isAdult = member.auth != null)
-        val items = repository.findByThemeFor2Weeks(
-            cloudfrontHost = imageHost,
-            theme = theme,
-            isAdult = member.auth != null,
-            offset = pageable.offset,
-            limit = pageable.pageSize.toLong()
-        )
-
-        return GetNewContentAllResponse(totalCount, items)
     }
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt
index e5cba07..bf7bfc1 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt
@@ -4,6 +4,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory
 import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
 import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme
 import org.springframework.beans.factory.annotation.Value
+import org.springframework.cache.annotation.Cacheable
 import org.springframework.stereotype.Repository
 
 @Repository
@@ -27,6 +28,7 @@ class AudioContentThemeQueryRepository(
             .fetch()
     }
 
+    @Cacheable(cacheNames = ["default"], key = "'getActiveThemeOfContent:' + ':' + #isAdult")
     fun getActiveThemeOfContent(isAdult: Boolean = false): List<String> {
         var where = audioContent.isActive.isTrue
             .and(audioContentTheme.isActive.isTrue)