diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt
index 9d121eb..2b6c768 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt
@@ -18,8 +18,8 @@ import javax.persistence.OneToMany
 import javax.persistence.OneToOne
 import javax.persistence.Table
 
-enum class AudioContentType {
-    INDIVIDUAL, BUNDLE
+enum class PurchaseOption {
+    BOTH, BUY_ONLY, RENT_ONLY
 }
 
 enum class SortType {
@@ -37,7 +37,7 @@ data class AudioContent(
     val limited: Int? = null,
     var remaining: Int? = null,
     @Enumerated(value = EnumType.STRING)
-    val type: AudioContentType = AudioContentType.INDIVIDUAL,
+    val purchaseOption: PurchaseOption = PurchaseOption.BOTH,
     val isGeneratePreview: Boolean = true,
     var isOnlyRental: Boolean = false,
     var isAdult: Boolean = false,
@@ -63,7 +63,4 @@ data class AudioContent(
 
     @OneToMany(mappedBy = "audioContent", cascade = [CascadeType.ALL])
     val audioContentHashTags: MutableList<AudioContentHashTag> = mutableListOf()
-
-    @OneToMany(mappedBy = "child", cascade = [CascadeType.ALL])
-    var children: MutableList<BundleAudioContent> = mutableListOf()
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt
index e417a61..acc85e7 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt
@@ -3,7 +3,6 @@ package kr.co.vividnext.sodalive.content
 import com.querydsl.core.types.dsl.Expressions
 import com.querydsl.jpa.impl.JPAQueryFactory
 import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
-import kr.co.vividnext.sodalive.content.QBundleAudioContent.bundleAudioContent
 import kr.co.vividnext.sodalive.content.category.QCategoryContent.categoryContent
 import kr.co.vividnext.sodalive.content.comment.QAudioContentComment.audioContentComment
 import kr.co.vividnext.sodalive.content.like.QAudioContentLike.audioContentLike
@@ -32,7 +31,6 @@ interface AudioContentRepository : JpaRepository<AudioContent, Long>, AudioConte
 interface AudioContentQueryRepository {
     fun findByIdAndActive(contentId: Long): AudioContent?
     fun findByIdAndCreatorId(contentId: Long, creatorId: Long): AudioContent?
-    fun findBundleByContentId(contentId: Long): List<AudioContent>
     fun findByCreatorId(
         creatorId: Long,
         coverImageHost: String,
@@ -147,18 +145,6 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
             .fetchOne()
     }
 
-    // 해당 컨텐츠가 속한 묶음(번들) 상품 리스트 검색
-    override fun findBundleByContentId(contentId: Long): List<AudioContent> {
-        return queryFactory
-            .select(bundleAudioContent.parent)
-            .from(bundleAudioContent)
-            .where(
-                bundleAudioContent.child.id.eq(contentId)
-                    .and(bundleAudioContent.child.isActive.isTrue)
-            )
-            .fetch()
-    }
-
     override fun findByCreatorId(
         creatorId: Long,
         coverImageHost: String,
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt
index a8d1519..4610561 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt
@@ -160,25 +160,28 @@ class AudioContentService(
         }
 
         // contentFile 체크
-        if (contentFile == null && request.type == AudioContentType.INDIVIDUAL) {
+        if (contentFile == null) {
             throw SodaException("콘텐츠를 선택해 주세요.")
         }
 
-        if (request.type == AudioContentType.BUNDLE && request.childIds == null) {
-            throw SodaException("묶음상품의 하위상품을 선택해 주세요.")
-        }
-
         // 테마 체크
         val theme = themeQueryRepository.findThemeByIdAndActive(id = request.themeId)
             ?: throw SodaException("잘못된 테마입니다. 다시 선택해 주세요.")
 
         if (request.price in 1..4) throw SodaException("콘텐츠의 최소금액은 5캔 입니다.")
 
+        val isOnlyRental = if (request.limited != null && request.limited > 0) {
+            false
+        } else if (request.purchaseOption == PurchaseOption.RENT_ONLY) {
+            true
+        } else {
+            request.isOnlyRental
+        }
+
         // DB에 값 추가
         val audioContent = AudioContent(
             title = request.title,
             detail = request.detail,
-            type = request.type,
             price = if (request.price > 0) {
                 request.price
             } else {
@@ -188,18 +191,13 @@ class AudioContentService(
             limited = request.limited,
             remaining = request.limited,
             isAdult = request.isAdult,
-            isGeneratePreview = if (request.type == AudioContentType.INDIVIDUAL) {
-                request.isGeneratePreview
-            } else {
-                false
-            },
-            isOnlyRental = if (request.limited != null && request.limited > 0) false else request.isOnlyRental,
+            purchaseOption = request.purchaseOption,
+            isGeneratePreview = request.isGeneratePreview,
+            isOnlyRental = isOnlyRental,
             isCommentAvailable = request.isCommentAvailable
         )
         audioContent.theme = theme
         audioContent.member = member
-        audioContent.isActive = request.type == AudioContentType.BUNDLE
-
         repository.save(audioContent)
 
         // 태그 분리, #추가, 등록
@@ -246,48 +244,34 @@ class AudioContentService(
 
         audioContent.coverImage = coverImagePath
 
-        if (contentFile != null && request.type == AudioContentType.INDIVIDUAL) {
-            // 콘텐츠 파일명 생성
-            val contentFileName = generateFileName(prefix = "${audioContent.id}-content")
+        // 콘텐츠 파일명 생성
+        val contentFileName = generateFileName(prefix = "${audioContent.id}-content")
 
-            // 콘텐츠 파일 업로드
-            metadata = ObjectMetadata()
-            metadata.contentLength = contentFile.size
-            metadata.addUserMetadata(
-                "generate_preview",
-                if (request.price > 0) {
-                    request.isGeneratePreview.toString()
-                } else {
-                    "false"
-                }
-            )
-
-            if (request.previewStartTime != null && request.previewEndTime != null) {
-                metadata.addUserMetadata("preview_start_time", request.previewStartTime)
-                metadata.addUserMetadata("preview_end_time", request.previewEndTime)
+        // 콘텐츠 파일 업로드
+        metadata = ObjectMetadata()
+        metadata.contentLength = contentFile.size
+        metadata.addUserMetadata(
+            "generate_preview",
+            if (request.price > 0) {
+                request.isGeneratePreview.toString()
+            } else {
+                "false"
             }
+        )
 
-            val contentPath = s3Uploader.upload(
-                inputStream = contentFile.inputStream,
-                bucket = audioContentBucket,
-                filePath = "input/${audioContent.id}/$contentFileName",
-                metadata = metadata
-            )
-
-            audioContent.content = contentPath
+        if (request.previewStartTime != null && request.previewEndTime != null) {
+            metadata.addUserMetadata("preview_start_time", request.previewStartTime)
+            metadata.addUserMetadata("preview_end_time", request.previewEndTime)
         }
 
-        if (request.childIds != null && request.type == AudioContentType.BUNDLE) {
-            for (childId in request.childIds) {
-                val childContent = repository.findByIdAndActive(childId)
-                    ?: continue
+        val contentPath = s3Uploader.upload(
+            inputStream = contentFile.inputStream,
+            bucket = audioContentBucket,
+            filePath = "input/${audioContent.id}/$contentFileName",
+            metadata = metadata
+        )
 
-                val bundleAudioContent = BundleAudioContent()
-                bundleAudioContent.parent = audioContent
-                bundleAudioContent.child = childContent
-                audioContent.children.add(bundleAudioContent)
-            }
-        }
+        audioContent.content = contentPath
 
         return CreateAudioContentResponse(contentId = audioContent.id!!)
     }
@@ -438,9 +422,6 @@ class AudioContentService(
     }
 
     fun getDetail(id: Long, member: Member, timezone: String): GetAudioContentDetailResponse {
-        // 묶음 콘텐츠 조회
-        val bundleAudioContentList = repository.findBundleByContentId(contentId = id)
-
         // 오디오 콘텐츠 조회 (content_id, 제목, 내용, 테마, 태그, 19여부, 이미지, 콘텐츠 PATH)
         val audioContent = repository.findByIdOrNull(id)
             ?: throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.")
@@ -455,23 +436,16 @@ class AudioContentService(
             memberId = member.id!!
         )
 
-        // 구매 여부 확인
-        val isExistsBundleAudioContent = bundleAudioContentList
-            .map { orderRepository.isExistOrdered(memberId = member.id!!, contentId = it.id!!) }
-            .contains(true)
-
         val (isExistsAudioContent, orderType) = orderRepository.isExistOrderedAndOrderType(
             memberId = member.id!!,
             contentId = audioContent.id!!
         )
 
-        val existOrdered = isExistsBundleAudioContent || isExistsAudioContent
-
         // 차단된 사용자 체크
         val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = creatorId)
-        if (isBlocked && !existOrdered) throw SodaException("${creator.nickname}님의 요청으로 콘텐츠 접근이 제한됩니다.")
+        if (isBlocked && !isExistsAudioContent) throw SodaException("${creator.nickname}님의 요청으로 콘텐츠 접근이 제한됩니다.")
 
-        val orderSequence = if (existOrdered) {
+        val orderSequence = if (isExistsAudioContent) {
             limitedEditionOrderRepository.getOrderSequence(
                 contentId = audioContent.id!!,
                 memberId = member.id!!
@@ -481,7 +455,7 @@ class AudioContentService(
         }
 
         if (
-            !existOrdered &&
+            !isExistsAudioContent &&
             !audioContent.isActive &&
             audioContent.releaseDate != null &&
             audioContent.releaseDate!! < LocalDateTime.now()
@@ -536,7 +510,6 @@ class AudioContentService(
             audioContentCloudFront.generateSignedURL(
                 resourcePath = if (
                     isExistsAudioContent ||
-                    isExistsBundleAudioContent ||
                     audioContent.member!!.id!! == member.id!! ||
                     audioContent.price <= 0
                 ) {
@@ -604,6 +577,18 @@ class AudioContentService(
             false
         }
 
+        val isOnlyRental = if (audioContent.purchaseOption == PurchaseOption.RENT_ONLY) {
+            true
+        } else {
+            audioContent.isOnlyRental
+        }
+
+        val purchaseOption = if (audioContent.isOnlyRental) {
+            PurchaseOption.RENT_ONLY
+        } else {
+            audioContent.purchaseOption
+        }
+
         return GetAudioContentDetailResponse(
             contentId = audioContent.id!!,
             title = audioContent.title,
@@ -621,8 +606,9 @@ class AudioContentService(
             isActivePreview = audioContent.isGeneratePreview,
             isAdult = audioContent.isAdult,
             isMosaic = audioContent.isAdult && member.auth == null,
-            isOnlyRental = audioContent.isOnlyRental,
-            existOrdered = existOrdered,
+            isOnlyRental = isOnlyRental,
+            existOrdered = isExistsAudioContent,
+            purchaseOption = purchaseOption,
             orderType = orderType,
             remainingTime = remainingTime,
             creatorOtherContentList = creatorOtherContentList,
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/BundleAudioContent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/BundleAudioContent.kt
deleted file mode 100644
index 375e819..0000000
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/BundleAudioContent.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package kr.co.vividnext.sodalive.content
-
-import kr.co.vividnext.sodalive.common.BaseEntity
-import javax.persistence.Entity
-import javax.persistence.FetchType
-import javax.persistence.JoinColumn
-import javax.persistence.ManyToOne
-import javax.persistence.Table
-
-@Entity
-@Table(name = "bundle_content")
-data class BundleAudioContent(
-    var isActive: Boolean = true
-) : BaseEntity() {
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "parent_content_id", nullable = false)
-    var parent: AudioContent? = null
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "child_content_id", nullable = false)
-    var child: AudioContent? = null
-}
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/CreateAudioContentRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/CreateAudioContentRequest.kt
index 7a155c1..3c4e6bf 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/CreateAudioContentRequest.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/CreateAudioContentRequest.kt
@@ -5,6 +5,7 @@ data class CreateAudioContentRequest(
     val detail: String,
     val tags: String,
     val price: Int,
+    val purchaseOption: PurchaseOption = PurchaseOption.BOTH,
     val limited: Int? = null,
     val timezone: String = "Asia/Seoul",
     val releaseDate: String? = null,
@@ -13,8 +14,6 @@ data class CreateAudioContentRequest(
     val isGeneratePreview: Boolean = false,
     val isOnlyRental: Boolean = false,
     val isCommentAvailable: Boolean = false,
-    val type: AudioContentType = AudioContentType.INDIVIDUAL,
-    val childIds: List<Long>? = null,
     val previewStartTime: String? = null,
     val previewEndTime: String? = null
 )
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/GetAudioContentDetailResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/GetAudioContentDetailResponse.kt
index baf2cbc..d7346ef 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/GetAudioContentDetailResponse.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/GetAudioContentDetailResponse.kt
@@ -23,6 +23,7 @@ data class GetAudioContentDetailResponse(
     val isMosaic: Boolean,
     val isOnlyRental: Boolean,
     val existOrdered: Boolean,
+    val purchaseOption: PurchaseOption,
     val orderType: OrderType?,
     val remainingTime: String?,
     val creatorOtherContentList: List<OtherContentResponse>,
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt
index 4826816..630b22a 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt
@@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.can.use.CanUsage
 import kr.co.vividnext.sodalive.common.SodaException
 import kr.co.vividnext.sodalive.content.AudioContent
 import kr.co.vividnext.sodalive.content.AudioContentRepository
+import kr.co.vividnext.sodalive.content.PurchaseOption
 import kr.co.vividnext.sodalive.content.comment.AudioContentCommentRepository
 import kr.co.vividnext.sodalive.content.like.AudioContentLikeRepository
 import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
@@ -31,7 +32,7 @@ class OrderService(
     fun order(contentId: Long, orderType: OrderType, container: String, member: Member) {
         val content = audioContentRepository.findByIdAndActive(contentId)
             ?: throw SodaException("잘못된 콘텐츠 입니다\n다시 시도해 주세요.")
-        validateOrder(memberId = member.id!!, content = content)
+        validateOrder(memberId = member.id!!, content = content, orderType = orderType)
 
         val order = if (content.limited != null && content.remaining != null) {
             if (content.remaining!! <= 0) throw SodaException("해당 콘텐츠가 매진되었습니다.")
@@ -75,11 +76,17 @@ class OrderService(
         return order
     }
 
-    private fun validateOrder(memberId: Long, content: AudioContent) {
+    private fun validateOrder(memberId: Long, content: AudioContent, orderType: OrderType) {
         if (memberId == content.member!!.id!!) throw SodaException("자신이 올린 콘텐츠는 구매할 수 없습니다.")
-        if (repository.isExistOrdered(memberId = memberId, contentId = content.id!!)) {
-            throw SodaException("이미 구매한 콘텐츠 입니다.")
-        }
+
+        val existOrdered = repository.isExistOrdered(memberId = memberId, contentId = content.id!!)
+        if (existOrdered) throw SodaException("이미 구매한 콘텐츠 입니다.")
+
+        val isOnlyRental = content.purchaseOption == PurchaseOption.RENT_ONLY || content.isOnlyRental
+        if (isOnlyRental && orderType == OrderType.KEEP) throw SodaException("대여만 가능한 콘텐츠 입니다.")
+
+        val isOnlyBuy = content.purchaseOption == PurchaseOption.BUY_ONLY && orderType == OrderType.RENTAL
+        if (isOnlyBuy) throw SodaException("소장만 가능한 콘텐츠 입니다.\n앱 업데이트 후 구매해 주세요.")
     }
 
     fun getAudioContentOrderList(