ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 사이드 프로젝트 수행기 (2)
    사이드 프로젝트 2022. 6. 12. 18:06

    이번에 진행했던 부분은

     

    어드민 서버에서 지정된 조건의 유저들에게 

    푸시 서버로 API 를 호출하면

    푸시 서버에서 해당 API를 받아서 단말기로 푸시를 보내는 기능을 구현하였다.

    (소스레벨에서는 어드민 모듈과 푸시 모듈로 구성)

     

    푸시 보내는 어드민 화면은 다음과 같다. 

     

     

     

    푸시 서버는 별도로 구현하였고,

    여기서는 위 화면의 '푸시 종류' 중에서 여러 종류 중 '이벤트 전체 알림' 인 경우에 대해 진행하였다.

     

     

    푸시 서버에서 이벤트 푸시 보내는 경우 내용 소스이다.

    // 해당 이벤트 존재하는지 체크
    Event event = eventService.findById(requestDTO.getEventId());
    
    List<User> allEventUsers = userService.findAllForEvent();
    int successCnt = 0;
    int failCnt = 0;
    Exception exception = null;
    for (User user : allEventUsers) {
        
        try {
            if (user.getProfile().isPushEvent() && user.getProfile().getUserOs() != null && user.getProfile().getUserOs().equals(UserOS.AOS)) {
                boolean isResult = firebaseCloudMessageService.sendPushMessage(user.getPushToken(),
                        requestDTO.getTitle(), requestDTO.getPushContent(),
                        PushType.EVENT_ALL_USER, requestDTO.getEventId());
    
                if (isResult) {
                    successCnt += 1;
                }
                else {
                    failCnt += 1;
                }
    
                Thread.sleep(300);
            }
    
        } catch (IOException e) {
            failCnt += 1;
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            failCnt += 1;
            throw new RuntimeException(e);
        } catch (Exception e) {
            failCnt += 1;
            throw new RuntimeException(e);
        }
    
    }
    pushHistoryService.updatePushHistory(requestDTO.getPushHistoryId(),
            successCnt, failCnt);
    
    if (failCnt > 0) {
        throw new RuntimeException(exception);
    }

     

    처음에 대충 이런식으로 개발 진행했었는데,

    동작은 하긴 했지만 보다보니 문제가 좀 보이던게 

     

    } catch (IOException e) {
        failCnt += 1;
        throw new RuntimeException(e);
    } catch (InterruptedException e) {
        failCnt += 1;
        throw new RuntimeException(e);
    } catch (Exception e) {
        failCnt += 1;
        throw new RuntimeException(e);
    }

     

    이 부분에 관한 내용이었다.

    에러가 발생하게 되면  이 부분에서 문제가 발생하게 될 것인데,

    boolean isResult = firebaseCloudMessageService.sendPushMessage(user.getPushToken(),
            requestDTO.getTitle(), requestDTO.getPushContent(),
            PushType.EVENT_ALL_USER, requestDTO.getEventId());

    위처럼 처리를 하게 되면 

    문제 발생시  throw new RuntimeException(e); 로 처리하게 되어 

     failCnt += 1; 연산은 필요가 없어지게 되어 매번 해당 블락에서

    불필요하게 pushHistoryService.updatePushHistory() 로 호출하게 되는 문제가 생길 수가 있다.

     

    그래서, 생각해낸 방법은 

    } catch (IOException e) {
        failCnt += 1;
        exception = e;
    } catch (InterruptedException e) {
        failCnt += 1;
        exception = e;
    } catch (Exception e) {
        failCnt += 1;
        exception = e;
    }

    처럼 Exception exception = null; 로  초기화해주고, 

    에러가 발생한 곳에서 실패 카운트를 + 1 해주고, 

    어떤 에러인지 파악하기 위한 부분은 exception = e; 로 받아서 

     

    해당 로직이 끝난 뒤,

    pushHistoryService.updatePushHistory(requestDTO.getPushHistoryId(),
                    successCnt, failCnt);
    
    if (failCnt > 0) {
        throw new RuntimeException(exception);
    }

    해당 푸시 히스토리 값의 성공과 실패 카운트를 업데이트 해준뒤,

    실패 카운트가 있는 경우 결과에서 알려주도록 처리하도록 하였다.

     

     

    * 아직은 유저가 많은 경우에 푸시를 보내는 부분에 대한 처리가 없는 상태인데,

    향후에는 스프링에서 제공하는 비동기 메시지 방법이나 카프카 같은걸 사용해서 처리가 필요할 것 같다.

     

    '사이드 프로젝트' 카테고리의 다른 글

    사이드 프로젝트 수행기 (3)  (1) 2022.06.22
    사이드 프로젝트 수행기 (1)  (0) 2022.05.29
Designed by Tistory.