ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 에러 핸들링 작업 과정에서 마주친 리팩터링 신호
    Today I Learned 2022. 11. 26. 22:58

    게시글 작성 기능을 구현하고 나니 사용성에 문제가 있는 부분이 발견되었다.

     

     

    시간을 입력할 때 hour의 경우 1~12 사이의 숫자만을 선택할 수 있도록 했는데, 오전과 오후를 구분할 방법이 없었다. 사용자가 시작 시간과 종료 시간에 대해 오전/오후를 선택할 수 있도록 라디오 버튼을 추가하는 작업을 수행했다.

     

    // components/PostForm.jsx
    
    <div>
        <input
          id="input-game-start-time-am"
          type="radio"
          name="start-time-am-pm"
          value="am"
          onChange={handleChangeGameStartTimeAmPm}
        />
        <label htmlFor="input-game-start-time-am">
          시작 오전
        </label>
        <input
          id="input-game-start-time-pm"
          type="radio"
          name="start-time-am-pm"
          value="pm"
          onChange={handleChangeGameStartTimeAmPm}
        />
        <label htmlFor="input-game-start-time-pm">
          시작 오후
        </label>
        <SelectTime
          // props
        />
        <SelectTime
          // props
        />
    </div>

     

    여러 리스트 중 하나를 선택해야 하는 라디오 버튼 input 요소는 'name' 속성으로 자신이 어떤 라디오 버튼 요소와 그룹을 맺는지 결정한다. 버튼을 누르면 onChange 핸들러 함수에 value 속성으로 지정된 값을 포함하는 event를 전달한다.

     

    // components/PostForm.jsx
    
    const handleChangeGameEndTimeAmPm = (event) => {
        const { value } = event.target;
        changeGameEndTimeAmPm(value);
    };

     

    선택한 오전, 오후 값과 시간 값은 게시글 생성 Service 레이어에서 받도록 정의한 양식으로 바꿔 요청 데이터에 담기 위해 별도의 변환 로직이 필요했다. 예를 들어 시작 시간을 오전 10시 30분, 종료 시간을 오후 2시로 골랐다면, '10,30,14,00'의 형태로 변환해서 전달해야 했다. Store에서 API 요청을 호출하는 함수에 시간 값을 전달하기 위해 형태를 변환해주는 함수를 추가했다.

     

    사용자가 입력할 수 있는 시간의 범위를 1~12로 설정한 상태였는데, LocalTime 객체를 생성하기 위해 가능한 시간의 입력 범위는 0~23이었다. 따라서 오전 12시를 선택하거나, 오후 시간을 선택했을 때에는 시간 값을 변경해주도록 했다.

     

    // utils/timeConverter.js
    
    export function calculateHour(hour, amPm) {
      if (hour === 12 && amPm === 'am') {
        return 0;
      }
      if (hour < 12 && amPm === 'pm') {
        return hour + 12;
      }
      return hour;
    }
    
    function formatTime(hour) {
      return hour < 10
        ? `0${hour}`
        : hour.toString();
    }
    
    export default function convertTime({
      gameStartAmPm,
      gameStartHour,
      gameStartMinute,
      gameEndAmPm,
      gameEndHour,
      gameEndMinute,
    }) {
      const startHour = calculateHour(Number(gameStartHour), gameStartAmPm);
      const endHour = calculateHour(Number(gameEndHour), gameEndAmPm);
    
      return `${formatTime(startHour)},${gameStartMinute},${formatTime(endHour)},${gameEndMinute}`;
    }

     

     

    모든 동작과 예외처리 로직까지 구현을 마친 뒤, 예외처리를 잘 수행하는지 확인하기 위해 오전/오후를 선택하지 않고 게시물 등록을 시도해보았는데 예외처리를 일으키지 않고 정상적으로 게시글이 등록되는 것이 확인되었다.

     

    문제는 timeConverter의 calculateHour 함수에 있었다. 사용자가 라디오 버튼을 이용해 오전/오후를 선택하지 않으면 Store가 관리하는 오전/오후 상태값은 빈 문자열인 상태인데, 빈 문자열이 전달되더라도 위의 로직은 문제없이 hour 값을 그대로 반환하므로 시간 데이터가 정상적으로 생성되는 문제가 있었다.

     

    문제를 해결하기 위해 시간 형태를 변환하는 로직을 수행하기 전에 조건을 검사해서 오전/오후 값이 빈 문자열이라면 Error를 throw하는 동작을 시도해보았지만 잘 되지 않았고, 애초에 프론트엔드에서만 에러 핸들링을 하는 것은 회피할 수 있었기 때문에 완전한 해결책이 될 수 없었다.

     

    // PostFormStore.js 내 에러 발생 구문
    
    if (gameStartTimeAmPm === ''
      || gameEndTimeAmPm === '') {
      throw new Error({
        errorCodeAndMessages: {
          104: '오전/오후를 선택하지 않았습니다.',
        },
      });
    }
    
    // PostFormStore.js 내 에러 핸들링 구문
    try {
          // ...
    } catch (error) {
      const { errorCodeAndMessages } = error.response.data;
      this.errorCodeAndMessages = errorCodeAndMessages;
      this.publish();
      return '';
    }

     

    일단은 내키지는 않았지만 작동하는 구조를 만들기 위해, 기존의 시간 데이터를 'hh/mm/hh/mm' 방식으로 가공해 전달하던 방식을 포기하고 시작 시간의 오전/오후, 시, 분, 종료 시간의 오전/오후 시, 분을 모두 따로 전달하는 구조로 API 호출 방식을 수정하고, 모든 시간 변환 계산을 Service 레이어에서 수행하도록 POST 요청 처리 과정을 수정했다.

     

    // PostAndGameRequestDto.java의 시간 관련 요청 데이터
    
    @NotBlank(message = "시작시간 오전/오후 구분을 입력해주세요.")
    private String gameStartAmPm;
    
    @NotBlank(message = "시작 시간을 입력해주세요.")
    private String gameStartHour;
    
    @NotBlank(message = "시작 분을 입력해주세요.")
    private String gameStartMinute;
    
    @NotBlank(message = "종료시간 오전/오후 구분을 입력해주세요.")
    private String gameEndAmPm;
    
    @NotBlank(message = "종료 시간을 입력해주세요.")
    private String gameEndHour;
    
    @NotBlank(message = "종료 분을 입력해주세요.")
    private String gameEndMinute;

     

    입력하지 않은 내용이 있을 경우 에러 메세지를 전달하는 모습을 확인할 수 있다.

     

     

     

    작업 내역

    - https://github.com/hsjkdss228/smash-frontend/pull/33

    - https://github.com/hsjkdss228/smash-backend/pull/22

     

     

     

     

     

    댓글

Designed by Tistory.