개발 메모장

[Java] 공공데이터 - 공휴일 API 사용하기 본문

Java

[Java] 공공데이터 - 공휴일 API 사용하기

yyyyMMdd 2023. 12. 6. 15:15
728x90

#. 웹에서 15일, 30일을 선택하여 데이터를 처리하는 로직을 만들어야 했었습니다.

 

#. 15일과 30일이 주말 또는 공휴일인 경우 그 전의 평일을 웹에 보여줘야 했습니다.

 

#. 주말의 경우엔 일반적으로 처리가 가능하나 공휴일은 그렇지 않기에 정부에서 제공하는 공휴일 API를 사용하기로 했습니다.

 


  • Step 1. 현재 년과 월, 15일 및 30일에 대한 변수 생성

- ModelAndView를 이용해 JSP로 데이터를 리턴해 웹에 뿌려줄 것입니다.

- Java에서 기본적으로 제공하는 라이브러리인 Util > Calendar 메서드를 이용해 년, 월을 가져옵니다.

public ModelAndView availableDay(Map<String, Obejct> param, ModelMap modelMap) {
    Calendar cal = Calendar.getInstance();
    int year = cal.get(Calendar.YEAR);
    int month = cal.get(Calendar.MONTH)+1;
    
    int halfDay = 15;
    int endDay = 30;
    
    return new ModelAndView("JSP 경로");
}

 


  • Step 2. 날짜 체크하는 메서드 생성 및 로직 구성

- 생성한 변수를 파라미터로 넘겨 처리하는 메서드 생성 및 로직을 구성할 것입니다.

- 로직에는 공휴일 및 주말을 체크해야 하는 내용이 필요하며  getDayCheck 메서드에서 처리할 예정입니다.

- 위 로직에서 추가한 로직부터 작성합니다.

public ModelAndView availableDay(Map<String, Obejct> param, ModelMap modelMap) {
    Calendar cal = Calendar.getInstance();
    int year = cal.get(Calendar.YEAR);
    int month = cal.get(Calendar.MONTH)+1;
    
    int halfDay = 15;
    int endDay = 30;
    
    halfDay = getDayCheck(year, mmonth, halfDay);
    endDay = getDayCheck(year, mmonth, endDay);
    
    modelMap.put("halfDay", String.format("04d-%02d-%02d", year, month, halfDay));
    modelMap.put("endDay", String.format("04d-%02d-%02d", year, month, endDay));
    
    return new ModelAndView("JSP 경로");
}

- 전달받은 파라미터로 Calendar 메서드에 날짜를 세팅해 줍니다.

public static int getDayCheck(int year, int month, int day) throws IOException {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month, day);
    
    List<Integer> holidays = getHolidays(year, month);
    
    // 체크 로직은 아래에서 추가 예정
    
    return cal.get(Calendar.DAY_OF_MONTH);
}

 


  • Step 3. 주말 및 공휴일에 대한 유효성 검사를 한 번에 하기 위해 공휴일 체크 메서드 생성

- 공휴일의 경우 해당 년, 월 파라미터를 입력 시 그에 대한 공휴일의 날짜를 리턴해옵니다.

- getHolidays라는 메서드를 생성해 로직을 구성합니다.

- API 사용을 위한 준비사항

    1. 공공데이터포털 회원가입

    2. 사용하려는 API의 KEY 발급

    3. API 사용방법 인지(공휴일 API는 리턴 값이 XML 형식으로 오기 때문에 편한 사용을 위해 json 파싱처리함)

- API 사용방법은 아래 참조에 기재한 사이트를 확인 바랍니다.

public static List<Integer> getHolidays(int year, int month) throws IOException {
    String apiUrl = "공휴일API의 url" // 웹사이트 내 참고문서 확인
    String apiKey = "API 이용을 위한 일반 인증키"
    
    // 요청 URI 작성(예를 위해 작성한 것이므로 참고문서 확인 후 넣기)
    String requestUrl = "키=" + apiKey
    			+ "년=" + String.format("%04d", year)
                        + "월=" + String.foramt("%02d", month);
                        
    // API 통신을 위한 세팅
    URL url = new URL(apiUrl + requestUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Content-type", "application/json");
    BufferedReader rd;
    
    if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) {
    	// 정상처리 시
    	rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
    } else {
    	// 에러발생 시
    	rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
    }
    
    // 받은 데이터 담기
    StringBuilder sb = new StringBuilder();
    String line;
    while((line = rd.readLine()) != null) {
    	sb.append(line);
    }
    rd.close();
    conn.disconnect();
    
    // 받은 데이터가 XML형식이므로 json 형태로 파싱
    List<Integer> result = new ArrayList<Integer>();
    JSONObject json = XML.toJSONObject(sb.toString());
    String jsonStr = json.toString();
    // 사용할 데이터 찾아 변수에 담기
    json = (JSONObject) json.get("depth 1");
    json = (JSONObject) json.get("depth 2");
    
    if(!(json.get("depth 3") instanceof JSONObject)) {
    	// 에러 처리
	}
    json = (JSONObject) json.get("depth 3");
    Object item = json.get("depth 4");
    
    // list에 담기(여러 개 일 때 처리방법)
    if(item instanceof JSONArray) {
    	JSONArray items = (JSONArray) item;
        for(int i = 0; i < items.length(); i++) {
        	json = (JSONObject) items.get(i);
            // 키에 대한 값은 yyyyMMdd로 가져오므로 
            // 날짜가 필요한 상황에선 100으로 나눈 나머지가 날짜가 될 것
            result.add(json.getInt("날짜키") % 100);   
        }
    // list에 담기(한 개 일 때 처리방법)
    } else if(item instanceof JSONObject) {
    	json = (JSONObject) item;
        result.add(json.getInt("날짜키") % 100);
    }
    return result;  
}

 


 

  • Step 4. 날짜를 토, 일요일, 공휴일인지 체크

- 15, 30이라는 값이 holidays에 포함되는지 확인하기 위한 로직을 추가합니다.

- Step 2에서 만든 메서드의 나머지 부분을 채울 것입니다.

public static int getDayCheck(int year, int month, int day) throws IOException {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month, day);
    
    List<Integer> holidays = getHolidays(year, month);
    
    while(cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ||
    	  cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
          holidays.contains(cal.get(Calendar.DAY_OF_MONTH))) {
	    // while문에 걸릴 시 토, 일, 공휴일이기 때문에 날짜를 전날 만듦
	    cal.add(Calendar.DATE, -1);
    }
    return cal.get(Calendar.DAY_OF_MONTH);
}

 


 

#. 위와 같이 처리해 주면 토요일, 일요일, 공휴일을 제외한 이전 평일의 날짜를 가져올 수 있게 됩니다.

 

#. 이를 원하는데로 가공하여 사용하면 될 것입니다.

 

#. 참고로 2월의 경우엔 날짜가 다르므로 이에 대한 처리는 Step 1. 에서 추가 처리해 주면 될 듯합니다.

if(month == Calendar.FEBUARY) {
	if(윤달 체크) {
    	endDay = 28;
    } else {
    	endDay = 29;
    }
}

 

#. 자주 사용해야 하는 경우 API 통신을 계속 해야므로 이보다는 몇 년치 데이터를 DB에 저장하여 호출해 사용하는 것이 좋습니다.

 

#. 게다가 가끔 공공데이터에서 오류를 뱉는 경우도 있기 때문에 DB 저장이 더 낫다고 볼 수 있습니다.

 

 

 

 

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!

참조 : https://www.data.go.kr/data/15012690/openapi.do

===========================================================

 

728x90