경험의 기록

https://www.data.go.kr/index.do

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

 

공공데이터포털에서

단기예보 조회서비스 ((구) 동네예보) API 를 이용하면 날씨 정보를 얻을 수 있다.

 


1. API 발급받기

https://www.data.go.kr/index.do

공공데이터포털 사이트에서 단기예보로 검색하여

 

본인이 사용하고자 하는 날씨 API를 활용신청해준다.

 

자동으로 승인되며 API키를 발급 받을 수 있다.

참고 문서를 다운받으면 콜백URL, 지역의 좌표, 자세한 사용법 등을 알 수 있다.

 

2. 라이브러리, API 세팅하기

bulid.gradle (Module)

dependencies {  
    // Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // Converter ( JSON 타입 결과를 객체로 매핑 )
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}

통신을 위해 Retrofit을 사용할 것이므로 추가해준다.

 

AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />

통신을 위해 인터넷 권한을 추가해준다.

 

또한 데이터가 http 기반이므로 http 허용하기 위해 

android:usesCleartextTraffic="true"

추가해준다.

 

API KEY 추가

원하는 위치에 자신의 API Key를 선언해주고

 

API 키는 노출하면 안되므로 깃에서 ignore 처리 해준다.

 

3. API 활용하기

참고 문서를 확인하면서 진행해보자.

 

여러가지 기능 중에 3번 단기예보조회를 사용해보자.

여기서 Call Back URl을 확인할 수 있는데

class Constants {

    companion object{
        const val BASE_URL = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/"
        const val TAG = "tst5"
    }
}

getVilageFcst 전까지의 URL을 BASE_URL로 잡아준다.

 

이제 요청 메세지 명세 부분을 확인하면서

interface WeatherApi {

    @GET("getVilageFcst?serviceKey=$API_KEY")
    suspend fun getWeather(
        @Query("dataType") dataType : String,
        @Query("numOfRows") numOfRows : Int,
        @Query("pageNo") pageNo : Int,
        @Query("base_date") baseDate : Int,
        @Query("base_time") baseTime : Int,
        @Query("nx") nx : String,
        @Query("ny") ny : String
    ) : Response<Weather>
}

API 를 작성해준다.

결과는 Response으로 Weather를 받아오게 되는데 이 Weather 모델은

 

응답 메세지 명세 부분을 확인하면서 작성해준다.

 

data class Weather(
    val response: Response
) {

    data class Response(
        val header: Header,
        val body: Body
    )

    data class Header(
        val resultCode: Int,
        val resultMsg: String
    )

    data class Body(
        val dataType: String,
        val items: Items
    )

    data class Items(
        val item: List<Item>
    )

    data class Item(
        val baseData: Int,
        val baseTime: Int,
        val category: String,
        val fcstDate : Int,
        val fcstTime : Int,
        val fcstValue : String,
        val nx : Int,
        val ny : Int
    )
}

 

쉽게 확인해보려면 밑의 메세지 예제가 있는데

서비스키 부분만 본인의 API를 넣어서 테스트해보면 결과를 확인할 수 있다.

 

http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst?serviceKey=인증키&numOfRows=10&pageNo=1&base_date=20220323&base_time=0500&nx=55&ny=127&dataType=JSON

 

JSON 타입으로 받아오려고 하므로 위 예제를 통해 확인해보면

 

 

구조를 쉽게 확인할 수 있다.

 

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    @Singleton
    fun provideRetrofit() : Retrofit =
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

    @Provides
    @Singleton
    fun provideWeatherApi(retrofit : Retrofit) : WeatherApi =
        retrofit.create(WeatherApi::class.java)

}

이제 위에서 잡아준 URI로 레트로핏의 baseurl을 정해준다.

이 프로젝트에선 코드에 Dagger-Hlit를 사용하였다.

 

@Singleton
class WeatherRepository @Inject constructor(
    private val weatherApi: WeatherApi
) {

    suspend fun getWeather(
        dataType : String, numOfRows : Int, pageNo : Int,
        baseDate : Int, baseTime : Int, nx : String, ny : String) : Response<Weather> {
        return weatherApi.getWeather(dataType,numOfRows,pageNo,baseDate,baseTime,nx,ny)
    }
}

Repository에서 날씨 API를 직접 요청하기 위한 getWeather 메소드를 정의해주고

 

@HiltViewModel
class WeatherViewModel @Inject constructor(
    private val repository: WeatherRepository
) : ViewModel() {

    private val _weatherResponse : MutableLiveData<Response<Weather>> = MutableLiveData()
    val weatherResponse get() = _weatherResponse

    fun getWeather(dataType : String, numOfRows : Int, pageNo : Int,
                   baseDate : Int, baseTime : Int, nx : String, ny : String){
        viewModelScope.launch {
            val response = repository.getWeather(dataType, numOfRows, pageNo, baseDate, baseTime, nx, ny)
            _weatherResponse.value = response
        }
    }
}

뷰모델에서 결과를 받는다.

 

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    // 뷰모델 생성
    private val viewModel by viewModels<WeatherViewModel>()

    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 데이터바인딩
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
        binding.lifecycleOwner = this

        viewModel.getWeather("JSON",14,1,
            20220322,1100,"63","89")

        viewModel.weatherResponse.observe(this){
            for(i in it.body()?.response!!.body.items.item){
                Log.d(TAG, "$i")
            }
        }
    }
}

이제 메인액티비티에서

임의의 지역의 날씨를 요청해주고 관찰하여 로그로 결과를 확인해본다.

 

지역의 좌표 정보도 참고 문서에서 확인할 수 있다.

 

이 코드에서는 임의로 전주의 좌표를 넣어 전주 날씨를 요청하도록 하였다.

 

결과를 잘 받아온 것을 확인할 수 있다.

 

 

카테고리의 의미는 참고 문서의 하단에서 확인할 수 있는데 위와 같다.

 

 

 

 

전체 코드

https://github.com/HanYeop/AndroidStudio-Practice2/tree/master/WeatherApiEx

 

GitHub - HanYeop/AndroidStudio-Practice2: (2021.05.20~) 안드로이드 학습 내용 저장소

(2021.05.20~) 안드로이드 학습 내용 저장소. Contribute to HanYeop/AndroidStudio-Practice2 development by creating an account on GitHub.

github.com

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading