diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index adfe0180..bcf2571a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -282,5 +282,8 @@
             android:name="com.facebook.FacebookActivity"
             android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" />
         
+
+        
+        
     
 
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailActivity.kt
new file mode 100644
index 00000000..935d0d6f
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailActivity.kt
@@ -0,0 +1,207 @@
+package kr.co.vividnext.sodalive.chat.character.detail
+
+import android.content.Intent
+import android.graphics.Rect
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.viewModels
+import androidx.core.net.toUri
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import coil.load
+import kr.co.vividnext.sodalive.R
+import kr.co.vividnext.sodalive.base.BaseActivity
+import kr.co.vividnext.sodalive.databinding.ActivityCharacterDetailBinding
+import kr.co.vividnext.sodalive.extensions.dpToPx
+
+class CharacterDetailActivity : BaseActivity(
+    ActivityCharacterDetailBinding::inflate
+) {
+    private val viewModel: CharacterDetailViewModel by viewModels()
+
+    private val adapter by lazy {
+        OtherCharacterAdapter(
+            onItemClick = { item ->
+                startActivity(
+                    Intent(this, CharacterDetailActivity::class.java).apply {
+                        putExtra(EXTRA_CHARACTER_ID, item.characterId)
+                    }
+                )
+            }
+        )
+    }
+
+    private var isWorldviewExpanded = false
+    private var isPersonalityExpanded = false
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        // 더미 데이터 로드 (추후 Intent/Repository 연동)
+        val characterId = intent.getLongExtra(EXTRA_CHARACTER_ID, 0)
+
+//        if (characterId <= 0) {
+//            showToast("잘못된 접근 입니다.")
+//            finish()
+//        }
+
+        viewModel.loadMock(characterId)
+        bindObservers()
+    }
+
+    override fun setupView() {
+        // 뒤로 가기
+        binding.detailToolbar.tvBack.setOnClickListener { finish() }
+
+        // 다른 캐릭터 리스트: 가로 스크롤
+        val recyclerView = binding.rvOtherCharacters
+        recyclerView.layoutManager = LinearLayoutManager(
+            this,
+            LinearLayoutManager.HORIZONTAL,
+            false
+        )
+
+        recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
+            override fun getItemOffsets(
+                outRect: Rect,
+                view: View,
+                parent: RecyclerView,
+                state: RecyclerView.State
+            ) {
+                super.getItemOffsets(outRect, view, parent, state)
+
+                when (parent.getChildAdapterPosition(view)) {
+                    0 -> {
+                        outRect.left = 0
+                        outRect.right = 8f.dpToPx().toInt()
+                    }
+
+                    adapter.itemCount - 1 -> {
+                        outRect.left = 8f.dpToPx().toInt()
+                        outRect.right = 0
+                    }
+
+                    else -> {
+                        outRect.left = 8f.dpToPx().toInt()
+                        outRect.right = 8f.dpToPx().toInt()
+                    }
+                }
+            }
+        })
+
+        recyclerView.adapter = adapter
+
+        // 세계관 전체보기 토글 클릭 리스너
+        binding.llWorldviewExpand.setOnClickListener {
+            toggleWorldviewExpand()
+        }
+        // 성격 전체보기 토글 클릭 리스너
+        binding.llPersonalityExpand.setOnClickListener {
+            togglePersonalityExpand()
+        }
+    }
+
+    private fun bindObservers() {
+        viewModel.uiState.observe(this) { state ->
+            val detail = state.detail ?: return@observe
+
+            // 배경 이미지
+            binding.ivCharacterBackground.load(detail.imageUrl) { crossfade(true) }
+
+            // 기본 정보
+            binding.detailToolbar.tvBack.text = detail.name
+            binding.tvCharacterName.text = detail.name
+            binding.tvCharacterStatus.text = when (detail.characterType) {
+                CharacterType.CLONE -> "Clone"
+                CharacterType.CHARACTER -> "Character"
+            }
+            // 캐릭터 타입에 따른 배경 설정
+            binding.tvCharacterStatus.setBackgroundResource(
+                when (detail.characterType) {
+                    CharacterType.CLONE -> R.drawable.bg_character_status_clone
+                    CharacterType.CHARACTER -> R.drawable.bg_character_status_character
+                }
+            )
+            binding.tvCharacterDescription.text = detail.description
+            binding.tvCharacterTags.text = detail.tags
+
+            // 세계관 내용과 버튼 가시성 초기화
+            val worldviewText = detail.backgrounds?.description.orEmpty()
+            binding.tvWorldviewContent.text = worldviewText
+            applyWorldviewCollapsedLayout()
+            binding.tvWorldviewContent.post {
+                val needExpand = binding.tvWorldviewContent.lineCount > 3
+                binding.llWorldviewExpand.visibility = if (needExpand) View.VISIBLE else View.GONE
+            }
+
+            // 성격 내용과 버튼 가시성 초기화
+            val personalityText = detail.personalities?.description.orEmpty()
+            binding.tvPersonalityContent.text = personalityText
+            applyPersonalityCollapsedLayout()
+            binding.tvPersonalityContent.post {
+                val needExpand = binding.tvPersonalityContent.lineCount > 3
+                binding.llPersonalityExpand.visibility = if (needExpand) View.VISIBLE else View.GONE
+            }
+
+            // 원작 섹션 표시/숨김
+            if (detail.originalTitle.isNullOrBlank() || detail.originalLink.isNullOrBlank()) {
+                binding.llOriginalSection.visibility = View.GONE
+            } else {
+                binding.llOriginalSection.visibility = View.VISIBLE
+                binding.tvOriginalContent.text = detail.originalTitle
+                binding.tvOriginalLink.setOnClickListener {
+                    runCatching {
+                        startActivity(Intent(Intent.ACTION_VIEW, detail.originalLink.toUri()))
+                    }
+                }
+            }
+
+            // 다른 캐릭터 리스트
+            adapter.submitList(detail.others)
+        }
+    }
+
+    private fun toggleWorldviewExpand() {
+        isWorldviewExpanded = !isWorldviewExpanded
+        if (isWorldviewExpanded) {
+            // 확장 상태
+            binding.tvWorldviewContent.maxLines = Integer.MAX_VALUE
+            binding.tvWorldviewContent.ellipsize = null
+            binding.tvWorldviewExpand.text = "간략히"
+            binding.ivWorldviewExpand.setImageResource(R.drawable.ic_chevron_up)
+        } else {
+            // 접힘 상태 (3줄)
+            applyWorldviewCollapsedLayout()
+            binding.tvWorldviewExpand.text = "전체보기"
+            binding.ivWorldviewExpand.setImageResource(R.drawable.ic_chevron_down)
+        }
+    }
+
+    private fun applyWorldviewCollapsedLayout() {
+        binding.tvWorldviewContent.maxLines = 3
+        binding.tvWorldviewContent.ellipsize = TextUtils.TruncateAt.END
+    }
+
+    private fun togglePersonalityExpand() {
+        isPersonalityExpanded = !isPersonalityExpanded
+        if (isPersonalityExpanded) {
+            binding.tvPersonalityContent.maxLines = Integer.MAX_VALUE
+            binding.tvPersonalityContent.ellipsize = null
+            binding.tvPersonalityExpand.text = "간략히"
+            binding.ivPersonalityExpand.setImageResource(R.drawable.ic_chevron_up)
+        } else {
+            applyPersonalityCollapsedLayout()
+            binding.tvPersonalityExpand.text = "전체보기"
+            binding.ivPersonalityExpand.setImageResource(R.drawable.ic_chevron_down)
+        }
+    }
+
+    private fun applyPersonalityCollapsedLayout() {
+        binding.tvPersonalityContent.maxLines = 3
+        binding.tvPersonalityContent.ellipsize = TextUtils.TruncateAt.END
+    }
+
+    companion object {
+        const val EXTRA_CHARACTER_ID = "extra_character_id"
+    }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailResponse.kt
new file mode 100644
index 00000000..6c146602
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailResponse.kt
@@ -0,0 +1,48 @@
+package kr.co.vividnext.sodalive.chat.character.detail
+
+import androidx.annotation.Keep
+import com.google.gson.annotations.SerializedName
+
+@Keep
+data class CharacterDetailResponse(
+    @SerializedName("characterId") val characterId: Long,
+    @SerializedName("name") val name: String,
+    @SerializedName("description") val description: String,
+    @SerializedName("mbti") val mbti: String?,
+    @SerializedName("imageUrl") val imageUrl: String,
+    @SerializedName("personalities") val personalities: CharacterPersonalityResponse?,
+    @SerializedName("backgrounds") val backgrounds: CharacterBackgroundResponse?,
+    @SerializedName("tags") val tags: String,
+    @SerializedName("originalTitle") val originalTitle: String?,
+    @SerializedName("originalLink") val originalLink: String?,
+    @SerializedName("characterType") val characterType: CharacterType,
+    @SerializedName("others") val others: List
+)
+
+@Keep
+enum class CharacterType {
+    @SerializedName("CLONE")
+    CLONE,
+    @SerializedName("CHARACTER")
+    CHARACTER
+}
+
+@Keep
+data class OtherCharacter(
+    @SerializedName("characterId") val characterId: Long,
+    @SerializedName("name") val name: String,
+    @SerializedName("imageUrl") val imageUrl: String,
+    @SerializedName("tags") val tags: String
+)
+
+@Keep
+data class CharacterPersonalityResponse(
+    @SerializedName("trait") val trait: String,
+    @SerializedName("description") val description: String
+)
+
+@Keep
+data class CharacterBackgroundResponse(
+    @SerializedName("topic") val topic: String,
+    @SerializedName("description") val description: String
+)
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailViewModel.kt
new file mode 100644
index 00000000..c2b3ed7e
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/CharacterDetailViewModel.kt
@@ -0,0 +1,73 @@
+package kr.co.vividnext.sodalive.chat.character.detail
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import kr.co.vividnext.sodalive.base.BaseViewModel
+
+/**
+ * 캐릭터 상세 화면에서 사용하는 ViewModel.
+ * - 캐릭터 명과 상태
+ * - 캐릭터 소개
+ * - 태그 문자열 (예: "#태그1 #태그2")
+ * - 세계관 내용 (3줄 이상일 경우 전체보기 토글)
+ * - 원작 섹션 (빈 값이면 UI에서 숨김)
+ * - 다른 캐릭터 목록 (이미지, 캐릭터 명, 태그)
+ */
+class CharacterDetailViewModel : BaseViewModel() {
+    // UiState를 CharacterDetailResponse 구조에 맞게 변경
+    data class UiState(
+        val detail: CharacterDetailResponse? = null
+    )
+
+    private val _uiState = MutableLiveData(UiState())
+    val uiState: LiveData get() = _uiState
+
+    fun loadMock(characterId: Long) {
+        // TODO: Repository 연동 예정. 현재는 더미 데이터로 표시
+        val demoWorldview = CharacterBackgroundResponse(
+            topic = "세계관",
+            description = "특별한 꽃을 길러낼 수 있는 능력을 가진 리엘라.\n그녀는 호손 공작의 상속자가 되고 말아버리는데...\n\n뜻하지 않은 만남과 비밀이 펼쳐진다."
+        )
+        val demoPersonality = CharacterPersonalityResponse(
+            trait = "밝음, 고집",
+            description = "밝고 쾌활하지만 고집이 있으며, 친구를 소중히 여기고 어려움 앞에서도 물러서지 않습니다.\n상황에 따라 유연하게 대처하지만 신념은 확고합니다.\n\n상황에 따라 유연하게 대처하지만 신념은 확고합니다.\n\n\n상황에 따라 유연하게 대처하지만 신념은 확고합니다."
+        )
+        val others = listOf(
+            OtherCharacter(
+                characterId = 1,
+                name = "엘리시아",
+                imageUrl = "https://picsum.photos/seed/char1/300/300",
+                tags = "#마법 #학생 #쾌활"
+            ),
+            OtherCharacter(
+                characterId = 2,
+                name = "루카",
+                imageUrl = "https://picsum.photos/seed/char2/300/300",
+                tags = "#기사 #충직 #과묵"
+            ),
+            OtherCharacter(
+                characterId = 3,
+                name = "세라",
+                imageUrl = "https://picsum.photos/seed/char3/300/300",
+                tags = "#암살자 #쿨 #시크"
+            )
+        )
+
+        val response = CharacterDetailResponse(
+            characterId = characterId,
+            name = "리엘라",
+            description = "꽃을 키우는 공작가의 상속자",
+            mbti = "ENFP",
+            imageUrl = "https://picsum.photos/seed/bg1/1000/1000",
+            personalities = demoPersonality,
+            backgrounds = demoWorldview,
+            tags = "#커버곡 #라이브 #연애 #썸 #채팅 #라방",
+            originalTitle = "네이버 시리즈 독 안에 든 선생님",
+            originalLink = "https://series.naver.com/",
+            characterType = CharacterType.CLONE,
+            others = others
+        )
+
+        _uiState.value = UiState(detail = response)
+    }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/OtherCharacterAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/OtherCharacterAdapter.kt
new file mode 100644
index 00000000..28d3ee92
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/OtherCharacterAdapter.kt
@@ -0,0 +1,58 @@
+package kr.co.vividnext.sodalive.chat.character.detail
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import coil.load
+import coil.transform.RoundedCornersTransformation
+import kr.co.vividnext.sodalive.R
+import kr.co.vividnext.sodalive.databinding.ItemOtherCharacterBinding
+import kr.co.vividnext.sodalive.extensions.dpToPx
+
+class OtherCharacterAdapter(
+    private var items: List = emptyList(),
+    private val onItemClick: ((OtherCharacter) -> Unit)? = null
+) : RecyclerView.Adapter() {
+
+    @SuppressLint("NotifyDataSetChanged")
+    fun submitList(newItems: List) {
+        items = newItems
+        notifyDataSetChanged()
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OtherCharacterViewHolder {
+        return OtherCharacterViewHolder(
+            ItemOtherCharacterBinding.inflate(
+                LayoutInflater.from(parent.context),
+                parent,
+                false
+            )
+        )
+    }
+
+    override fun onBindViewHolder(holder: OtherCharacterViewHolder, position: Int) {
+        holder.bind(items[position])
+    }
+
+    override fun getItemCount(): Int = items.size
+
+    inner class OtherCharacterViewHolder(
+        private val binding: ItemOtherCharacterBinding
+    ) : RecyclerView.ViewHolder(binding.root) {
+        fun bind(item: OtherCharacter) {
+            binding.tvName.text = item.name
+            binding.tvTags.text = item.tags
+            binding.ivThumb.load(item.imageUrl) {
+                crossfade(true)
+                placeholder(R.drawable.ic_place_holder)
+                transformations(RoundedCornersTransformation(16f.dpToPx()))
+            }
+
+
+            binding.root.setOnClickListener {
+                onItemClick?.invoke(item)
+            }
+        }
+    }
+}
diff --git a/app/src/main/res/drawable/bg_character_status_character.xml b/app/src/main/res/drawable/bg_character_status_character.xml
new file mode 100644
index 00000000..a05ed00a
--- /dev/null
+++ b/app/src/main/res/drawable/bg_character_status_character.xml
@@ -0,0 +1,6 @@
+
+
+    
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_character_status_clone.xml b/app/src/main/res/drawable/bg_character_status_clone.xml
new file mode 100644
index 00000000..1f9810c1
--- /dev/null
+++ b/app/src/main/res/drawable/bg_character_status_clone.xml
@@ -0,0 +1,6 @@
+
+
+    
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_character_status_creator.xml b/app/src/main/res/drawable/bg_character_status_creator.xml
new file mode 100644
index 00000000..05a12731
--- /dev/null
+++ b/app/src/main/res/drawable/bg_character_status_creator.xml
@@ -0,0 +1,6 @@
+
+
+    
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_round_corner_16_solid_3bb9f1.xml b/app/src/main/res/drawable/bg_round_corner_16_solid_3bb9f1.xml
new file mode 100644
index 00000000..2a2bb323
--- /dev/null
+++ b/app/src/main/res/drawable/bg_round_corner_16_solid_3bb9f1.xml
@@ -0,0 +1,6 @@
+
+
+    
+    
+
diff --git a/app/src/main/res/drawable/bg_round_corner_16_stroke_37474f.xml b/app/src/main/res/drawable/bg_round_corner_16_stroke_37474f.xml
new file mode 100644
index 00000000..f086e3d0
--- /dev/null
+++ b/app/src/main/res/drawable/bg_round_corner_16_stroke_37474f.xml
@@ -0,0 +1,9 @@
+
+
+    
+    
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_round_corner_16_stroke_3bb9f1.xml b/app/src/main/res/drawable/bg_round_corner_16_stroke_3bb9f1.xml
new file mode 100644
index 00000000..8f31048c
--- /dev/null
+++ b/app/src/main/res/drawable/bg_round_corner_16_stroke_3bb9f1.xml
@@ -0,0 +1,9 @@
+
+
+    
+    
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_chevron_down.xml b/app/src/main/res/drawable/ic_chevron_down.xml
new file mode 100644
index 00000000..54f20bb0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chevron_down.xml
@@ -0,0 +1,14 @@
+
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_chevron_up.xml b/app/src/main/res/drawable/ic_chevron_up.xml
new file mode 100644
index 00000000..0a798045
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chevron_up.xml
@@ -0,0 +1,14 @@
+
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_character_detail.xml b/app/src/main/res/layout/activity_character_detail.xml
new file mode 100644
index 00000000..840d2fa9
--- /dev/null
+++ b/app/src/main/res/layout/activity_character_detail.xml
@@ -0,0 +1,389 @@
+
+
+
+    
+    
+
+    
+    
+
+        
+
+            
+            
+
+                
+                
+
+                
+                
+
+                
+                
+
+                    
+                    
+
+                        
+
+                        
+                    
+
+                    
+                    
+
+                    
+                    
+                
+            
+
+            
+            
+
+                
+                
+
+                
+                
+
+                
+                
+
+                    
+
+                    
+                
+            
+
+            
+            
+
+                
+                
+
+                
+                
+
+                
+                
+
+                    
+
+                    
+                
+            
+
+            
+            
+
+                
+                
+
+                
+                
+
+                
+                
+            
+
+            
+            
+
+                
+                
+
+                
+                
+
+                
+                
+            
+
+            
+            
+
+                
+                
+
+                    
+                
+
+                
+                
+            
+        
+    
+
+    
+    
+
diff --git a/app/src/main/res/layout/item_other_character.xml b/app/src/main/res/layout/item_other_character.xml
new file mode 100644
index 00000000..3e3ff8f8
--- /dev/null
+++ b/app/src/main/res/layout/item_other_character.xml
@@ -0,0 +1,38 @@
+
+
+
+    
+
+    
+
+    
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index c5748ebb..f3b6a0ce 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -133,4 +133,6 @@
     #7849BC
     #607D8B
     #B0BEC5
+    #7C7C80
+    #37474F