๐ก ๋์์ธ ํจํด ์ค์ ํ๋์ธ MVP ํจํด์ ๋ํ์ฌ ํ์ตํ์์ต๋๋ค !
MVP
- MVP๋ Model, View, Presenter๋ฅผ ํฉ์น ์ฉ์ด์ด๋ฉฐ, MVC์์ C์ ํด๋นํ๋ Controller๊ฐ Presenter๋ก ๊ต์ฒด๋ ํจํด์ ๋๋ค.
- ์๋ํ๋ ๋จ์ ํ ์คํธ๋ฅผ ์ฉ์ดํ๊ฒ ํ๊ณ , Presenter ๋ก์ง์์ ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํ๋๋ก ์ค๊ณ ๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค ์ํคํ ์ฒ ํจํด์ ๋๋ค.
MVC์์ ์ฐจ์ด
- MVC์์๋ Controller๋ฅผ ํตํด์ ์ง์ ์ ์ผ๋ก View์ ์ ๊ทผํ๊ธฐ ๋๋ฌธ์, Controller์ ์ฐ๊ฒฐ ๋ Model๊ณผ View๋ ์๋ก ์ด๋์ ๋์ ๊ฒฐํฉ๋๊ฐ ์๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
- ํ์ง๋ง MVP๋ ์ค์ง Presenter์ ์ธํฐํ์ด์ค๋ฅผ ํตํด ๋ฉ์์ง ์ ๋ฌํ๊ธฐ ๋๋ฌธ์ ๋ถ๋ฆฌ๋ ์ฑ
์(Separation of Concerns)๋ฅผ ์ป์ ์ ์์ต๋๋ค.
- ๋น์ฆ๋์ค ๋ก์ง(Model)๊ณผ ์ฌ์ฉ์ ์ธํฐํ์ด์ค(View)๋ฅผ ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌํ๋ฏ๋ก ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ํฅ์ ๋ฉ๋๋ค.
MVP ํน์ง
์ฅ์
- ์ฝ๋๊ฐ ๊น๋ํด์ง๊ณ , ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ๋ฐ ๋ณ๊ฒฝ์ ํ ๋๋ง๋ค ๊ด๋ จ๋ ๋ถ๋ถ๋ง ์ฝ๋๋ฅผ ์์ ํ๊ธฐ ๋๋ฌธ์ ํ์ฅ์ฑ์ด ๊ฐ์ ๋ฉ๋๋ค.
- UI, Model ๊ฐ๊ฐ ํํธ๋ฅผ ๋๋ ์ ํด์ผ ํ ์ผ์ด ๋ช ํํด์ง๋ฉฐ ์์กด์ฑ์ด ์ ๊ฑฐ๋๊ณ ๊ฒฐํฉ๋๊ฐ ๋ฎ์์ง๊ฒ ๋ฉ๋๋ค.
- ์ธํฐํ์ด์ค๋ฅผ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ๋จ์ ํ ์คํธ๊ฐ ์ฉ์ดํ๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
๋จ์
- ํ์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ณต์กํด์ง์๋ก View์ Presenter ์ฌ์ด์ ์์กด์ฑ์ด ๊ฐํด์ง๋ ๋ฌธ์ ๊ฐ ์์ ์ ์์ต๋๋ค.
- 1:1 ๊ด๊ณ๋ฅผ ์ ์งํด์ผ ํ๊ธฐ ๋๋ฌธ์ Presenter๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ด๋ View๊ฐ ๋์ด๋ ๋๋ง๋ค Presenter๋ ๊ฐ์ด ๋์ด๋ ํด๋์ค๊ฐ ๋ง์์ง๊ณ ๋น๋ํด์ง๋๋ค.
Model
- ์ ํ๋ฆฌ์ผ์ด์ ์์์ ๋ฐ์ดํฐ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค, ์์, ๋ณ์๋ฅผ ๋ปํฉ๋๋ค.
- ๋ทฐ์์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ฑฐ๋ ์์ ํ๋ฉด Presenter๋ฅผ ํตํด ๋ชจ๋ธ์ ์์ฑํ๊ฑฐ๋ ๊ฐฑ์ ํฉ๋๋ค.
// ์ฃผ์ฌ์๋ฅผ ๋์ง๋ ํ์๋ฅผ ๊ด๋ฆฌํ๋ DiceModel์ ์์ฑํ์์ต๋๋ค.
class DiceModel {
// ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ง๋ ์์ง๋ง, ์๋์ ๊ฐ์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.
val color = Color.Red
fun rollDice(): Int { // ๋ด๋ถ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค
return (1..6).random()
}
}
View
- ์ฌ์ฉ์ ์ธํฐํ์ด์ค ์์๋ก ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์๊ฐ ๋ณผ ์ ์๋ ํ๋ฉด์ ๋ปํฉ๋๋ค.
- ๋ชจ๋ธ์ด ๊ฐ์ง๊ณ ์๋ ์ ๋ณด๋ฅผ ๋ฐ๋ก ์ ์ฅํ์ง ์์์ผ ํ๋ฉฐ ๋จ์ํ ํ๋ฉด์ ํ์ํ๋ ์ ๋ณด๋ง์ ๊ฐ์ง๊ณ ์์ด์ผ ํฉ๋๋ค.
class MainActivity : AppCompatActivity(), DiceContract.View {
private lateinit var presenter: DiceContract.Presenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Model๊ณผ Presenter ์ด๊ธฐํ
val model = DiceModel()
presenter = DicePresenter(this, model)
val rollButton = findViewById<Button>(R.id.rollButton)
rollButton.setOnClickListener {
presenter.onRollDice()
}
}
override fun showResult(result: Int) {
val resultTextView = findViewById<TextView>(R.id.resultTextView)
resultTextView.text = "์ฃผ์ฌ์ ๊ฒฐ๊ณผ: $result"
}
override fun showError(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
Presenter
- Model๊ณผ View ์ฌ์ด์ ๋งค๊ฐ์ฒด ์ญํ ์ ํฉ๋๋ค.
- MVC์ Controller์ ์ ์ฌํ์ง๋ง, View์ ์ง์ ์ฐ๊ฒฐ๋๋ ๋์ ์ธํฐํ์ด์ค๋ฅผ ํตํด ์ํธ์์ฉํ๋ค๋ ํฐ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
- ์ด๋ฅผ ํตํด MVC๊ฐ ๊ฐ์ง ํ ์คํธ ๋ฌธ์ ์ ํจ๊ป ๋ชจ๋ํ, ์ ์ฐ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
- View์๊ฒ ํ์ํ ๋ด์ฉ(Data)๋ง ์ ๋ฌํ๋ฉฐ ์ด๋ป๊ฒ ๋ณด์ฌ์ค ์ง๋ View๊ฐ ๋ด๋นํฉ๋๋ค.
class DicePresenter(
private val view: DiceContract.View,
private val model: DiceModel
) : DiceContract.Presenter {
override fun onRollDice() {
try {
val result = model.rollDice()
view.showResult(result)
} catch (e: Exception) {
view.showError("์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.")
}
}
}
MVP Logic
- MVP ํจํด์ ์๋์ ๊ฐ์ ๋ก์ง์ผ๋ก ๋์ํฉ๋๋ค.
- View์์ ์ฌ์ฉ์ ์ด๋ฒคํธ๋ฅผ ์์ ํฉ๋๋ค.
- View → Presenter๋ก ์ด๋ฒคํธ๋ฅผ ํธ์ถํฉ๋๋ค.
- Presenter → Model๋ก ๋ฐ์ดํฐ๋ฅผ ์์ฒญํฉ๋๋ค.
- Model → Presenter๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํฉ๋๋ค. (์์ , ์ญ์ , ์ถ๊ฐ ๋ ์ ๋ณด)
- Presenter → View๋ก ์ ๋ฌ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ๋ฐ์ดํธ ํฉ๋๋ค.
- View์์ ํ๋ฉด์ ์ ๋ฐ์ดํธ ํฉ๋๋ค.
Contract Interface
- Contract Interface๋ View์ Presenter ๊ฐ์ ์ด๋ฒคํธ๋ค์ ์ ์ธํฉ๋๋ค.
interface DiceContract {
//Contract.View interface
interface View {
fun showResult(result: Int)
fun showError(message: String)
}
//Contract.Prsenter interface
interface Presenter {
fun onRollDice()
}
}
Contract.View interface
- Presenter์์ View๋ฅผ ์
๋ฐ์ดํธํ๊ธฐ ์ํ ์ด๋ฒคํธ๋ค์ ์ ์ธํฉ๋๋ค.
- ์ด๋ 5๋ฒ์งธ ๋ก์ง ์์ ์ด ๋ฉ๋๋ค.
Contract.Prsenter interface
- View์์ ํธ์ถํ Presenter ์ด๋ฒคํธ๋ค์ ์ ์ธํฉ๋๋ค.
- ์ด๋ 2๋ฒ์งธ ๋ก์ง ์์ ์ด ๋ฉ๋๋ค.
์ฐธ๊ณ
https://velog.io/@kyeun95/๋์์ธ-ํจํด-MVP-ํจํด์ด๋