/**
 *  Repository 단에서
 *  UserRequestDTO의 형식을 검증하여 service단으로 넘김
 *
 *
 *  Fragment
 *                      UserRequest / UserResponse
 *  ViewModel
 *                      UserRequestDTO / UserRequestDTO
 *  Repository
 *                      (LoginRequestDTO , RegisterRequestDTO, ... ) / ( LoginResponseDTO, RegisterRequest, ...)
 *  Service
 *  **/

 

 

코드의 통일성을 위해서 앱 아키텍처에 따른 각 계층구조에서 사용할 모델을 정리해 보았다.

 

Fragment에서는 각각의 요청 (로그인 / 회원가입 / 아이디 찾기 / 비밀번호 찾기)에 대해 각각의 DTO 를 사용하여

다음과 같이 ViewModel에 UserRequest 클래스로 요청한다.

            loginViewModel.request(
                UserRequest.Login(
                    LoginRequestDTO(
                        email =    binding.username.text.toString(),
                        password = binding.password.text.toString()
                    )
                )
            )
            
            
            
            
    /** 
    /* 현재 코드는 각 상황별로 직접 UserRequest(UserRequestDTO())로 요청하도록 되어있지만 
    /* 서버에 요청하는 코드를 UserRequestDTO 형식을 받는 함수로 따로 만들어
    /* 해당 함수에서 UserRequestDTO의 형식을 구분하여 UserResponse에 담아 viewModel에 요청하는 역할을 수행하도록 하여
    /* 요청하는 부분에서는 단순히 해당 코드를 각각의 DTO에 담아서 요청할 수 있도록 만든다면 가독성측면과 직관성을 보완 할 수 있을 것 같다.
    **/

 

형식을 통해 ViewModel에게 데이터를 요청하고

 

class LoginActivity{

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loginViewModel.response.observe(this, ::responseObserver )
    }



	private fun responseObserver(response : UserResponse){
        if( loading.isShowing )
            loading.dismissWithAnimation()
            
        when(response){
            is UserResponse.Login ->{
                val dto = response.dto
                if(dto.success){
                	//로그인 성공 시 결과값 표시
                }
            }
            is UserResponse.FindIdPw ->{
                val dto = response.dto
                if(dto.success) {
                    //아이디&비밀번호 찾기 성공 시 결과값 표시
                }

            }
            is UserResponse.Register ->{
                val dto = response.dto
                if(dto.success) {
                    //회원가입 성공 시 결과값 표시
                }
            }
        }
    }
}

ViewModel에서는 reqeust함수로 들어오는 UserRequest의 타입에 따른 요청을 

repository에 UserRequestDTO 형식을 사용하여 전송한다.

 

UserRequestDTO형식을 사용하기 때문에 dto =  requestType.dto로 미리 정의하여

_resposne.value = repository.해당함수(dto)와 같이 코드를 통일성있고 간결하게  작성할 수 있었다.

class LoginViewModel : ViewModel() {
    val _response = MutableLiveData<UserResponse>()
    val response : LiveData<UserResponse> = _response
    val request : (UserRequest) -> Unit

    init {
        request = { requestType ->
            val dto = requestType.dto
            viewModelScope.launch {
                when(requestType){
                    //로그인
                    is UserRequest.Login -> {
                        if ((isUserNameValid(requestType.dto.email) && isPasswordValid(requestType.dto.password))) {
                            _response.value = repository.login(dto)
                        }
                    }
                    //회원가입
                    is UserRequest.Register -> {
                        _response.value =  repository.register(dto)
                    }
                    //아이디찾기
                    is UserRequest.FindPW -> {
                        _response.value = repository.findID(dto)
                    };
                    //비밀번호찾기
                    is UserRequest.FindID -> {
                        _response.value = repository.findPW(dto)
                    };
                }
            }

        }
    }
}

sealed class UserRequest() {
    abstract val dto: UserRequestDTO
    data class Login(override val dto : LoginRequestDTO) : UserRequest()
    data class FindPW(override val dto : FindPwRequestDTO) : UserRequest()
    data class FindID(override val dto : FindIdRequestDTO) : UserRequest()
    data class Register(override val dto : RegisterRequestDTO) : UserRequest()
}

sealed class UserResponse{
    abstract val dto : UserResponseDTO
    data class Login(override val dto : LoginResponseDTO) : UserResponse()
    data class FindIdPw(override val dto : FindResponseDTO) : UserResponse()
    data class Register(override val dto : SuccessResponse) : UserResponse()
}

 

다음은 UI 처리 부분이다. Activity는 onCreate에서 response LiveData를 observing하게 한다.

해당 observer에서는 response의 타입을 기준으로 UI에 반영하는 부분만 처리하면 된다.

fun UserRepository() : UserRepository = UserRepositoryImpl()

interface UserRepository {
    suspend fun login(dto : UserRequestDTO) : UserResponse
    suspend fun register(dto : UserRequestDTO) : UserResponse
    suspend fun findID(dto : UserRequestDTO) : UserResponse
    suspend fun findPW(dto : UserRequestDTO) : UserResponse
}

private class UserRepositoryImpl: UserRepository {
    @Inject
    private lateinit var backend : UserService
    
    
    override suspend fun login(dto: UserRequestDTO): UserResponse {
        return withContext(Dispatchers.IO){
				//처리코드
			}
            UserResponse.Login(responseDTO)
        }
    }
    override suspend fun register(dto: UserRequestDTO): UserResponse {
        return withContext(Dispatchers.IO) {
            //처리코드
            UserResponse.Register(responseDTO)
        }
    }
    override suspend fun findID(dto: UserRequestDTO): UserResponse {
        return withContext(Dispatchers.IO){
            //처리코드
	        UserResponse.FindIdPw(responseDTO)
        }
    }
    override suspend fun findPW(dto: UserRequestDTO): UserResponse {
        return withContext(Dispatchers.IO){
            //처리코드
            UserResponse.FindIdPw(responseDTO)
        }
    }

 

+ Recent posts