diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 40997222..9bd82503 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -191,6 +191,7 @@
                 
             
         
+        
 
         >
 
+    // 신규 캐릭터 전체보기
+    @GET("/api/chat/character/recent")
+    fun getRecentCharacters(
+        @Header("Authorization") authHeader: String,
+        @Query("page") page: Int,
+        @Query("size") size: Int
+    ): Single>
+
     @POST("/api/chat/character/image/purchase")
     fun purchaseCharacterImage(
         @Header("Authorization") authHeader: String,
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt
index 833aa987..6b9a8d3d 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt
@@ -22,6 +22,7 @@ import kr.co.vividnext.sodalive.base.SodaDialog
 import kr.co.vividnext.sodalive.chat.character.curation.CurationSectionAdapter
 import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity
 import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity.Companion.EXTRA_CHARACTER_ID
+import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersAllActivity
 import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacterAdapter
 import kr.co.vividnext.sodalive.common.LoadingDialog
 import kr.co.vividnext.sodalive.common.SharedPreferenceManager
@@ -289,6 +290,14 @@ class CharacterTabFragment : BaseFragment(
         recyclerView.adapter = newCharacterAdapter
 
         binding.tvNewCharacterAll.setOnClickListener {
+            ensureLoginAndAuth {
+                startActivity(
+                    Intent(
+                        requireContext(),
+                        NewCharactersAllActivity::class.java
+                    )
+                )
+            }
         }
 
         // 신규 캐릭터 LiveData 구독
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllActivity.kt
new file mode 100644
index 00000000..c2941645
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllActivity.kt
@@ -0,0 +1,92 @@
+package kr.co.vividnext.sodalive.chat.character.newcharacters
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import kr.co.vividnext.sodalive.base.BaseActivity
+import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity
+import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity.Companion.EXTRA_CHARACTER_ID
+import kr.co.vividnext.sodalive.common.GridSpacingItemDecoration
+import kr.co.vividnext.sodalive.common.LoadingDialog
+import kr.co.vividnext.sodalive.databinding.ActivityNewCharactersAllBinding
+import kr.co.vividnext.sodalive.extensions.dpToPx
+import org.koin.android.ext.android.inject
+
+class NewCharactersAllActivity : BaseActivity(
+    ActivityNewCharactersAllBinding::inflate
+) {
+    private val viewModel: NewCharactersAllViewModel by inject()
+
+    private lateinit var adapter: NewCharactersAllAdapter
+    private lateinit var loadingDialog: LoadingDialog
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setupView()
+        bindData()
+        viewModel.loadMore()
+    }
+
+    override fun setupView() {
+        loadingDialog = LoadingDialog(this, layoutInflater)
+        binding.toolbar.tvBack.text = "신규 캐릭터 전체보기"
+        binding.toolbar.tvBack.setOnClickListener { finish() }
+
+        val spanCount = 3
+        val spacingPx = 8f.dpToPx().toInt()
+
+        adapter = NewCharactersAllAdapter { characterId ->
+            startActivity(
+                Intent(this, CharacterDetailActivity::class.java).apply {
+                    putExtra(EXTRA_CHARACTER_ID, characterId)
+                }
+            )
+        }
+
+        binding.rvCharacters.layoutManager = GridLayoutManager(this, spanCount)
+        binding.rvCharacters.addItemDecoration(
+            GridSpacingItemDecoration(
+                spanCount,
+                spacingPx,
+                false
+            )
+        )
+        binding.rvCharacters.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
+                super.onScrolled(recyclerView, dx, dy)
+                val lastVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager)
+                    .findLastVisibleItemPosition()
+                val totalItemCount = recyclerView.adapter?.itemCount ?: 0
+                if (
+                    !recyclerView.canScrollVertically(1) &&
+                    lastVisibleItemPosition >= totalItemCount - 1
+                ) {
+                    viewModel.loadMore()
+                }
+            }
+        })
+        binding.rvCharacters.adapter = adapter
+    }
+
+    private fun bindData() {
+        viewModel.isLoading.observe(this) { isLoading ->
+            if (isLoading) loadingDialog.show(screenWidth) else loadingDialog.dismiss()
+        }
+
+        viewModel.totalCount.observe(this) { count ->
+            binding.tvTotalCount.text = "$count"
+        }
+
+        viewModel.items.observe(this) { list ->
+            adapter.addItems(list.drop(adapter.itemCount))
+            binding.rvCharacters.visibility = if (list.isEmpty()) View.GONE else View.VISIBLE
+        }
+
+        viewModel.toastLiveData.observe(this) { message ->
+            message?.let { showToast(it) }
+        }
+    }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllAdapter.kt
new file mode 100644
index 00000000..a7a2d568
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllAdapter.kt
@@ -0,0 +1,55 @@
+package kr.co.vividnext.sodalive.chat.character.newcharacters
+
+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.chat.character.Character
+import kr.co.vividnext.sodalive.databinding.ItemNewCharacterAllBinding
+import kr.co.vividnext.sodalive.extensions.dpToPx
+
+class NewCharactersAllAdapter(
+    private val onClick: (Long) -> Unit
+) : RecyclerView.Adapter() {
+
+    private val items = mutableListOf()
+
+    inner class VH(val binding: ItemNewCharacterAllBinding) : RecyclerView.ViewHolder(binding.root) {
+        fun bind(item: Character) {
+            binding.tvCharacterName.text = item.name
+            binding.tvCharacterDescription.text = item.description
+            binding.ivCharacter.load(item.imageUrl) {
+                crossfade(true)
+                placeholder(R.drawable.ic_logo_service_center)
+                transformations(RoundedCornersTransformation(16f.dpToPx()))
+            }
+            binding.root.setOnClickListener { onClick(item.characterId) }
+        }
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
+        val binding = ItemNewCharacterAllBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+        return VH(binding)
+    }
+
+    override fun getItemCount(): Int = items.size
+
+    override fun onBindViewHolder(holder: VH, position: Int) {
+        holder.bind(items[position])
+    }
+
+    fun addItems(newItems: List) {
+        val start = items.size
+        items.addAll(newItems)
+        notifyItemRangeInserted(start, newItems.size)
+    }
+
+    @SuppressLint("NotifyDataSetChanged")
+    fun clear() {
+        items.clear()
+        notifyDataSetChanged()
+    }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllViewModel.kt
new file mode 100644
index 00000000..eb699a9f
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersAllViewModel.kt
@@ -0,0 +1,68 @@
+package kr.co.vividnext.sodalive.chat.character.newcharacters
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.orhanobut.logger.Logger
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+import io.reactivex.rxjava3.schedulers.Schedulers
+import kr.co.vividnext.sodalive.base.BaseViewModel
+import kr.co.vividnext.sodalive.chat.character.Character
+import kr.co.vividnext.sodalive.common.SharedPreferenceManager
+
+class NewCharactersAllViewModel(
+    private val repository: NewCharactersRepository
+) : BaseViewModel() {
+
+    private val _toastLiveData = MutableLiveData()
+    val toastLiveData: LiveData get() = _toastLiveData
+
+    private val _isLoading = MutableLiveData(false)
+    val isLoading: LiveData get() = _isLoading
+
+    private val _totalCount = MutableLiveData(0)
+    val totalCount: LiveData get() = _totalCount
+
+    private val _items = MutableLiveData>(emptyList())
+    val items: LiveData> get() = _items
+
+    private var page = 0
+    private val size = 20
+    private var isLast = false
+
+    fun loadMore() {
+        if (_isLoading.value == true || isLast) return
+        _isLoading.value = true
+
+        compositeDisposable.add(
+            repository.getRecentCharacters(
+                token = "Bearer ${SharedPreferenceManager.token}",
+                page = page,
+                size = size
+            )
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({ response ->
+                    val data = response.data
+                    if (response.success && data != null) {
+                        val current = _items.value ?: emptyList()
+                        val next = current + data.content
+                        _items.value = next
+                        _totalCount.value = data.totalCount
+                        if (data.content.isNotEmpty()) {
+                            page += 1
+                        } else {
+                            isLast = true
+                        }
+                    } else {
+                        _toastLiveData.value = response.message
+                            ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
+                    }
+                    _isLoading.value = false
+                }, { e ->
+                    _isLoading.value = false
+                    e.message?.let { Logger.e(it) }
+                    _toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
+                })
+        )
+    }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersRepository.kt
new file mode 100644
index 00000000..801b36eb
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/NewCharactersRepository.kt
@@ -0,0 +1,21 @@
+package kr.co.vividnext.sodalive.chat.character.newcharacters
+
+import io.reactivex.rxjava3.core.Single
+import kr.co.vividnext.sodalive.chat.character.CharacterApi
+import kr.co.vividnext.sodalive.common.ApiResponse
+
+class NewCharactersRepository(
+    private val api: CharacterApi
+) {
+    fun getRecentCharacters(
+        token: String,
+        page: Int,
+        size: Int
+    ): Single> {
+        return api.getRecentCharacters(
+            authHeader = token,
+            page = page,
+            size = size
+        )
+    }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/RecentCharactersResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/RecentCharactersResponse.kt
new file mode 100644
index 00000000..93ae6ebb
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/newcharacters/RecentCharactersResponse.kt
@@ -0,0 +1,11 @@
+package kr.co.vividnext.sodalive.chat.character.newcharacters
+
+import androidx.annotation.Keep
+import com.google.gson.annotations.SerializedName
+import kr.co.vividnext.sodalive.chat.character.Character
+
+@Keep
+data class RecentCharactersResponse(
+    @SerializedName("totalCount") val totalCount: Long,
+    @SerializedName("content") val content: List
+)
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
index 39c917c0..cd42f689 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
@@ -67,6 +67,8 @@ import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
 import kr.co.vividnext.sodalive.chat.character.CharacterApi
 import kr.co.vividnext.sodalive.chat.character.CharacterTabRepository
 import kr.co.vividnext.sodalive.chat.character.CharacterTabViewModel
+import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersAllViewModel
+import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersRepository
 import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentApi
 import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentRepository
 import kr.co.vividnext.sodalive.chat.character.detail.detail.CharacterDetailRepository
@@ -364,6 +366,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
         viewModel { TalkTabViewModel(get()) }
         viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListViewModel(get()) }
         viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentReplyViewModel(get()) }
+        viewModel { NewCharactersAllViewModel(get()) }
     }
 
     private val repositoryModule = module {
@@ -413,6 +416,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
         factory { CharacterGalleryRepository(get()) }
         factory { TalkTabRepository(get()) }
         factory { CharacterCommentRepository(get()) }
+        factory { NewCharactersRepository(get()) }
     }
 
 
diff --git a/app/src/main/res/layout/activity_new_characters_all.xml b/app/src/main/res/layout/activity_new_characters_all.xml
new file mode 100644
index 00000000..ca6851b5
--- /dev/null
+++ b/app/src/main/res/layout/activity_new_characters_all.xml
@@ -0,0 +1,61 @@
+
+
+
+    
+
+    
+
+        
+
+        
+
+        
+    
+
+    
+
+
diff --git a/app/src/main/res/layout/fragment_character_tab.xml b/app/src/main/res/layout/fragment_character_tab.xml
index d7c3e073..219a144f 100644
--- a/app/src/main/res/layout/fragment_character_tab.xml
+++ b/app/src/main/res/layout/fragment_character_tab.xml
@@ -160,8 +160,7 @@
                     android:fontFamily="@font/pretendard_regular"
                     android:text="전체보기"
                     android:textColor="#90A4AE"
-                    android:textSize="14sp"
-                    android:visibility="gone" />
+                    android:textSize="14sp" />
 
             
 
diff --git a/app/src/main/res/layout/item_new_character_all.xml b/app/src/main/res/layout/item_new_character_all.xml
new file mode 100644
index 00000000..057f641b
--- /dev/null
+++ b/app/src/main/res/layout/item_new_character_all.xml
@@ -0,0 +1,52 @@
+
+
+
+    
+
+    
+
+    
+
+