-
Notifications
You must be signed in to change notification settings - Fork 0
2. Data
data layer는 데이터를 가져오는 역할을 합니다.
안드로이드에선 보통 Room이나 Retrofit 라이브러리를 사용하여 데이터를 로컬, 서버에서 가져옵니다.
저는 이 프로젝트에서 domain layer에 의존성을 가진 후 domain에 정의된 데이터 타입을 참조하여 override합니다.
접미어로 어떤 의미의 클래스인지를 구분하였습니다.
이 모듈의 Convention은 아래와 같습니다.
- Item
공공Api에서 주는 데이터의 단위입니다.
보통 list로 구성되어있으며 domain의 Info를 상속 받은 dataclass입니다.
- ResponseData
공공 Api의 응답 데이터입니다.
위의 Item 뿐 아니라 메시지, 페이지 번호, 총 페이지 수 등 여러 필요한 데이터도 포함되어 있습니다.
domain layer의 ApiBody를 상속받는 클래스입니다.
- Service
Retrofit의 메소드를 정의하는 Interface입니다.
추후에 이야기 할 CallAdapter를 등록해 놓아서 domain layer에 직접 정의해 놓은 ApiResponse를 바로 반환합니다.
- Source
데이터 제공을 담당합니다. Interface로 작성하였으며, 이를 상속 받는 Impl클래스로 이루어져 있습니다.
- RepositoryImpl
domain layer의 Repository 클래스를 상속 받는 클래스 입니다.
설계만 들어가있는 Interface인 Repository를 위의 Source를 사용하여 구현하는 클래스 입니다.
Hilt의 @Inject로 Source의 인스턴스를 주입받습니다.
이와 같이 구성한 패키지는 아래와 같습니다.

api에서 제공하는 데이터와 실제 프로젝트에서 사용하는 데이터는 다를 수 있습니다.
그래서 보통 이 중간 단계에 데이터 변환기를 놓는 프로젝트도 존재하는데요,
저는 크게 데이터가 변경 되는게 없었습니다.
다만 추가로 어떤 데이터가 사용될 지 모르기에 api에서 제공하는 모든 데이터를 담아 놓는 Item클래스에
domain layer에 있는 실제 사용할 데이터 타입 Info를 상속시키고,
getter를 정의하여 조금씩 가공하였습니다.
그 다음 앱 내부에서는 Info 타입으로만 사용한다면 api 데이터 타입의 변경에 대한 직접적인 의존을 줄일 수 있습니다.
아래는 이의 예시입니다.

data class BusInfoItem(
@SerializedName("nodeid")
val _stationId: String = "",
@SerializedName("nodenm")
val _stationName: String = "",
@SerializedName("routeid")
val _id: String = "",
@SerializedName("routeno")
val _number: String = "",
@SerializedName("routetp")
val _lineType: String = "",
@SerializedName("arrprevstationcnt")
val _remainStation: Int = -1,
@SerializedName("arrtime")
val _remainTimeSec: Int = -1,
@SerializedName("vehicletp")
val _busType: String = "",
@SerializedName("endnodenm")
val _endStation: String = "",
@SerializedName("startnodenm")
val _startStation: String = "",
) : BusInfo {
override val id
get() = _id
override val number
get() = _number
override val lineType
get() = _lineType
override val endStation
get() = _endStation
override val startStation
get() = _startStation
override val remainStation
get() = _remainStation
override val remainTimeSec
get() = _remainTimeSec
override val busType
get() = _busType
}그 다음은 ResponseData 예시입니다.
공공 api에서는 데이터를 구분하지 않고 한데 모아서 주게 됩니다.
{
"response":{
"header":{
"resultCode":"00",
"resultMsg":"NORMAL SERVICE."
},
"body":{
"items":{
"item":[
{
"arrprevstationcnt":17,
"arrtime":1196,
"nodeid":"GGB213000227",
"nodenm":"소하2동행정복지센터.광명동굴길입구",
"routeid":"GGB213000017",
"routeno":2,
"routetp":"일반버스",
"vehicletp":"저상버스"
},
{
"arrprevstationcnt":8,
"arrtime":938,
"nodeid":"GGB213000227",
"nodenm":"소하2동행정복지센터.광명동굴길입구",
"routeid":"GGB208000008",
"routeno":3,
"routetp":"일반버스",
"vehicletp":"저상버스"
},
{
"arrprevstationcnt":4,
"arrtime":348,
"nodeid":"GGB213000227",
"nodenm":"소하2동행정복지센터.광명동굴길입구",
"routeid":"GGB213000005",
"routeno":17,
"routetp":"일반버스",
"vehicletp":"일반차량"
},
{
"arrprevstationcnt":10,
"arrtime":940,
"nodeid":"GGB213000227",
"nodenm":"소하2동행정복지센터.광명동굴길입구",
"routeid":"GGB213000005",
"routeno":17,
"routetp":"일반버스",
"vehicletp":"일반차량"
}
]
},
"numOfRows":100,
"pageNo":1,
"totalCount":12
}
}
}
Body에 Header라는 데이터까지 가지고 있는 아이러니한 상황 입니다.