Domain layer ย |ย Android Developers
<ํด๋น ๋ด์ฉ์ ์ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์์ต๋๋ค>
Domain Layer๋ UI Layer์ Data Layer ์ฌ์ด์ ์กด์ฌํ๋ฉฐ, ์ ํ์ ์์
๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง or ๋ทฐ๋ชจ๋ธ์์ ์ฌ์ฌ์ฉ๋๋ ๊ฐ๋จํ ๋น์ฆ๋์ค ๋ก์ง ๋ฑ์ ์บก์ํ ๋ด๋น
๋ชจ๋ ์ฑ์์ ๋ฐ๋์ ํ์ํ ๊ฒ์ ์๋๋ฏ๋ก, ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๋ฉด ๋๋ค.
๐ย ๋ด๊ฐ ๋ชฐ๋ผ์ ์ค๋นํ IT ์ฌ์
[์บก์ํ] : ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ(OOP)์ ๊ฐ๋ ์ค ํ๋๋ก, ๋ฐ์ดํฐ์ ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฉ์๋๋ฅผ ํ๋์ ๋จ์๋ก ๋ฌถ๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๋ ์ธ๋ถ์์ ์ง์ ์ ์ผ๋ก ๋ฐ์ดํฐ์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ํ๊ณ , ์ค์ง ์ ์๋ ๋ฉ์๋๋ฅผ ํตํด์๋ง ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ค.
โก๏ธย ๊ฐ๊ฐ์ UseCase์์ ํ๋์ ๊ธฐ๋ฅ๋ง ๋ด๋นํด์ผํ๊ณ , ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ฅผ ํฌํจํด์๋ ์๋๋ค.
๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ UI Layer์ Data Layer์์ ์ฒ๋ฆฌํด์ผ ํ๋ค.
์์)
FormatDateUseCase
LogOutUserUseCase
GetLatestNewsWithAuthorsUseCase
ย
MakeLoginRequestUseCase
์ผ๋ฐ์ ์ธ ์ฑ ์ํคํ ์ฒ์์ UseCase๋ UI Layer์ ViewModel๊ณผ Data Layer์ Repository ์ฌ์ด์ ์กด์ฌ
โก๏ธย UseCase๋ Repository ํด๋์ค์ ์ข ์๋์ด ์์ผ๋ฉฐ, Repository์ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ์ฝ๋ฃจํด์ ์ฌ์ฉํ์ฌ UI Layer์ ํต์
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository
) { /* ... */ }
์์์
GetLatestNewsWithAuthorsUseCase
๋NewsRepository
์AuthorsRepository
๋ฅผ ๊ฒฐํฉํ์ฌ ์ฌ์ฉํ๊ณ ์๋ค.
UseCase๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ก์ง์ ํฌํจํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ UseCase์ ์ํด์ ์ฌ์ฉ๋ ์ ์๋ค.
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository,
private val formatDateUseCase: FormatDateUseCase
) { /* ... */ }
์์ ์ฝ๋์์ GetLatestNewsWithAuthorsUseCase
์์ FormatDateUseCase
๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๐ฉ๐ปโ๐ป Kotlin์์ย operator
ย ์ ํจ๊ปย invoke()
ย ํจ์๋ฅผ ์ ์ํ์ฌ UseCase ํด๋์ค ์ธ์คํด์ค๋ฅผ ํจ์์ฒ๋ผ ํธ์ถํ๊ฒ ๋ง๋ค ์ ์๋ค.
class FormatDateUseCase(userRepository: UserRepository) {
private val formatter = SimpleDateFormat(
userRepository.getPreferredDateFormat(),
userRepository.getPreferredLocale()
)
operator fun invoke(date: Date): String {
return formatter.format(date)
}
}
FormatDateUseCase
์ยinvoke()
ย ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํด๋์ค ์ธ์คํด์ค๋ฅผ ํจ์์ธ ๊ฒ์ฒ๋ผ ํธ์ถํ ์ ์๋ค.invoke()
ย ๋ฉ์๋๋ ํน์ ํ ์๊ทธ๋์ฒ์ ์ ํ๋์ง ์๋๋ค. ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์์ ์๊ด์์ด ์ทจํ๊ณ ๋ชจ๋ ์ ํ์ ๋ฐํํ ์ ์๋ค.
class MyViewModel(formatDateUseCase: FormatDateUseCase) : ViewModel() {
init {
val today = Calendar.getInstance()
val todaysDate = formatDateUseCase(today)
/* ... */
}
}
FormatDateUseCase
์MyViewModel
์์ ์์ ๊ฐ์ด ํธ์ถ ํ ์ ์๋ค.
< invoke()
๋ฉ์๋์ operator
์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ฐ์ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์. >
โก๏ธย UI Layer์ ํด๋์ค์์ Service
์์ ๋๋ย Application
ย ํด๋์ค ์์ฒด์์ UseCase๋ฅผ ํธ์ถ
UseCase๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ฅผ ํฌํจ โย
โก๏ธย UseCase ํด๋์ค์ ์ ์ธ์คํด์ค๋ฅผ ์ข ์ ํญ๋ชฉ์ผ๋ก ์ ๋ฌํ ๋๋ง๋ค ๊ทธ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
Domain Layer์ ์ํ๋ UseCaseํด๋์ค๋ ๋ฉ์ธ ์ค๋ ๋์์ ์์ ํ๊ฒ ํธ์ถ๋ ์ ์์ด์ผ ํ๋ค.
์ผ๋ฐ์ ์ผ๋ก ์๋๋ก์ด๋ ์ฑ์์๋ ๋ฉ์ธ ์ค๋ ๋์์๋ UI ์ ๋ฐ์ดํธ๋ฅผ ์ํ ํ๊ณ , ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋ธ๋กํนํ๋ ์์ ์ด ๋ฐ์ํ๋ฉด ์ฑ์ ๋ฐ์์ฑ์ด ์ ํ๋ ์ ์๋ค.
โก๏ธ UseCase ํด๋์ค ๋ด์์๋ ๊ธด ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ๋ธ๋กํน ์์ ์ด ๋ฐ์ํ ๊ฒฝ์ฐ, ํด๋น ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ์ฒ๋ฆฌํ์ฌ ๋ฉ์ธ ์ค๋ ๋์ ๋ธ๋กํน์ ๋ฐฉ์งํด์ผ ํ๋ค.
class MyUseCase(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend operator fun invoke(...) = withContext(defaultDispatcher) {
// Long-running blocking operations happen on a background thread.
}
}
Kotlin์ ์ฝ๋ฃจํด(Coroutine)์ ์ฌ์ฉํ์ฌ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๊ณ ์๋ค.
๐ก MyUseCase ํด๋์ค์ invoke ๋ฉ์๋๋ฅผ ํธ์ถํ ๋์๋ ํด๋น ์์ ์ด ๋ฉ์ธ ์ค๋ ๋์์ ํธ์ถ๋๋๋ผ๋ ์ค์ ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ์ํ๋๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ๋ฉ์ธ ์ค๋ ๋์ ๋ธ๋กํน์ ๋ฐฉ์งํ๊ณ ์ฑ์ ๋ฐ์์ฑ์ ์ ์งํ ์ ์๋ค.
๊ธด ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ์์ ์ด ๋ฐ๋์ UseCase ํด๋์ค ๋ด์์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ ๊ฒ์ ์๋๋ฉฐ, ํด๋น ์์ ์ด ๋ค๋ฅธ ๋ ์ด์ด์์ ๋ ์ ํฉํ ์๋ ์๋ค. ์๋ฅผ ๋ค์ด, Data Layer์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋ณต์กํ ๊ณ์ฐ์ ์ํํ๋ ๊ฒ์ด ๋ ์ ํฉํ ๊ฒฝ์ฐ๋ ์๋ค.
UI Layer์ ์๋ ๋ฐ๋ณต ๊ฐ๋ฅํ ๋น์ฆ๋์ค ๋ก์ง์ UseCase ํด๋์ค์์ ์บก์ํ ๋์ด์ผ ํ๋ค.
๊ทธ ๋ก์ง์ด ์ฌ์ฉ๋ ๋ชจ๋ ๊ณณ์ ๋ณ๊ฒฝ์ฌํญ์ ๋ ์ฝ๊ฒ ์ ์ฉํ ์ ์๊ณ ๋ก์ง์ ๋ ๋ฆฝ์ ์ผ๋ก ํ ์คํธํ ์๋ ์๋ค.
import java.text.SimpleDateFormat
import java.util.*
class FormatDateUseCase {
// ๋ฉ์ธ ์ค๋ ๋์์ ์์ ํ๊ฒ ํธ์ถํ ์ ์๋๋ก suspend ํจ์๋ก ์ ์ธ
suspend operator fun invoke(date: Date): String {
// ๋ ์ง ํฌ๋งท ํ์
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
// ์ฃผ์ด์ง ๋ ์ง๋ฅผ ํฌ๋งท์ ๋ง์ถฐ์ ๋ณํํ์ฌ ๋ฐํ
return dateFormat.format(date)
}
}
// ์ฌ์ฉ ์์
fun main() {
// ํ์ฌ ๋ ์ง๋ฅผ ๊ฐ์ ธ์ด
val currentDate = Date()
// FormatDateUseCase๋ฅผ ์ด๊ธฐํ
val formatDateUseCase = FormatDateUseCase()
// UseCase๋ฅผ ํธ์ถํ์ฌ ๋ ์ง ํฌ๋งทํ
์ํ
val formattedDate = formatDateUseCase(currentDate)
// ๊ฒฐ๊ณผ ์ถ๋ ฅ
println("Formatted date: $formattedDate")
}
ํฅํ์ ๋ ์ง ํ์๊ณผ ๊ด๋ จ๋ ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ด ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ์ฝ๋๋ฅผ ์ค์์์ ํ ๊ณณ์ผ๋ก ๋ชจ์ ๊ด๋ฆฌํ ์ ์๋ค.
News์ฑ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ณด์.
๋ด์ค์ ์์ฑ์ ๋ฐ์ดํฐ ์์
์ ๊ฐ๊ฐ ์ฒ๋ฆฌํ๋ย NewsRepository
ย ์ย AuthorsRepository
ย ๊ฐ ์์ ์ ์๋ค.
NewsRepository
์์ ๋
ธ์ถ๋๋ย Article
ย ํด๋์ค์๋ ์์ฑ์ ์ด๋ฆ๋ง ํฌํจ๋๋ค.
โย ํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ์์ฑ์์ ๋ํ ์์ธํ ์ ๋ณด๋ฅผ ์ป๊ณ ์ถ๋ค๋ฉด?
์ด๋ฌํ ์ ๋ณด๋ AuthorsRepository
์์ ์ป์ ์ ์๊ฒ ์ฃ .
์ด๋ ๊ฒ ํ๋์ ๋ก์ง ์์ ์ฌ๋ฌ๊ฐ์ง repository๊ฐ ํฌํจ๋์ด ์๋ ๊ฒฝ์ฐ์๋GetLatestNewsWithAuthorsUseCase
ย ๋ฅผ ๋ง๋ค์ด์ ViewModel์์ ๋ก์ง์ ์ถ์ํํ๊ณ ๊ฐ๋
์ฑ์ ๋์ผ ์ ์๋ค. ๋ํ ๋ก์ง์ ๋ณด๋ค ์ฝ๊ฒ ๊ฐ๋ณ์ ์ผ๋ก ํ
์คํธํ๊ณ ์ฑ์ ๋ค๋ฅธ ๋ถ๋ถ์์ ์ฌ์ฌ์ฉํ ์๋ ์๋ค.
๐ตย ์ฅ์ : Domain Layer ๋ก์ง ์ํ ๋ฐฉ์ง
Domain Layer์ ๋ก์ง์ UI Layer๊ฐ ์ฐํํ์ฌ ์ ๊ทผํ๋ ๊ฒ์ ๋ง๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ์์ ์ Domain Layer์ ๋ก์ง์ผ๋ก ํฌํจ ๋ ์ ์๋ ์์ญ์ด๋ค. ์ด๋ฌํ ๋ก์ง์๋ ์ฌ์ฉ์ ์ธ์ฆ, ๊ถํ ๋ถ์ฌ, ๋ฐ์ดํฐ ๊ฒ์ฆ ๋ฐ ๋ถ์ ๋ก๊น ๊ณผ ๊ฐ์ ๋ณด์ ๋ฐ ๋ก๊น ๊ธฐ๋ฅ์ด ํฌํจ๋ ์ ์๋ค.
ํ์ง๋ง UI Layer๊ฐ Domain Layer๋ฅผ ์ฐํํ์ฌ Data Layer์ ์ง์ ์ก์ธ์ค ํ๋ค๋ฉด, ์ด๋ฌํ ๋ณด์ ๋ฐ ๋ก๊น ๋ก์ง์ด ์ฐํ๋ ์ ์๋ค.
โก๏ธ UI Layer๊ฐ ์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ก์ธ์คํ๋ค๋ฉด, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง์ด Domain Layer๋ฅผ ๊ฑฐ์น์ง ์๊ณ ๋ฐ๋ก ์คํ๋ ์ ์๋ค.
๋ฐ๋ผ์ ์ฌ์ฉ์ ์ธ์ฆ์ด๋ ๊ถํ ๋ถ์ฌ์ ๊ฐ์ ์ค์ํ ๋ณด์ ๊ธฐ๋ฅ์ด ๋ฌด์๋ ์ ์๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, UI Layer๋ Domain Layer์ ๋ก์ง์ ์ฐํํ์ฌ ์ง์ ๋ฐ์ดํฐ ๋ ์ด์ด์ ์ ๊ทผํ๋ ๊ฒ์ ๋ง์์ผ ํ๋ค. UI Layer๋ Domain Layer๋ฅผ ํตํด ๋ฐ์ดํฐ ๋ ์ด์ด์ ์ก์ธ์คํด์ผ ํ๋ฉฐ, ๋๋ฉ์ธ ๋ ์ด์ด์ ๋ณด์ ๋ฐ ๋ก๊น ๋ก์ง์ด ํญ์ ์คํ๋๋๋ก ๋ณด์ฅํด์ผ ํ๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ์์คํ ์ ๋ณด์์ฑ๊ณผ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
๐ดย ๋จ์ : ๋ณต์ก์ฑ ์ฆ๊ฐ
๋จ์ํ Data Layer์ ๋ํ ํธ์ถ์ด ์์ ๋๋ UseCase๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค๋ ์ ์ ๋ณต์ก์ฑ์ ์ฆ๊ฐ์ํฌ ์ ์๋ค.
๐ก ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๊ณ , Data Layer์ ๋ํ ์ ๊ทผ์ ์ ํํ ์ง ์ฌ๋ถ๋ ๊ฐ๋ณ ์ฝ๋๋ฒ ์ด์ค์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์์ต๋๋ค.
์๊ฒฉํ ๊ท์น์ด๋ ์ ์ฐํ ์ ๊ทผ ๋ฐฉ์ ์ค ์ด๋ค ๊ฒ์ ์ ํธํ๋์ง์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ค.
๊ฐ๋ฐ์๋ ๊ฐ๋ณ ํ๋ก์ ํธ์ ์๊ตฌ ์ฌํญ๊ณผ ์ ํธ๋์ ๋ฐ๋ผ ์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ ์ ์ ํ ์กฐ์ ํ๋ ๋ฅ๋ ฅ์ด ํ์ํ๋ค.