[TIL] 21.03.05.(Fri)

Ryan (Geonhee) Son·2021년 3월 6일
0
post-thumbnail

수행 내용

  • 페어 프로그래밍 통해 묵찌빠 게임 프로젝트 Step 2 구현 완료 및 PR
  • 학습 경로 마인드맵 통해 정리
  • TWL 작성

학습 내용

에러 처리 (throw do-try-catch 문)

에러가 발생할 수 있는 메서드에서 에러를 던지고(throw) 에러를 받는 메서드에서 어떻게 처리할지 (do-try-catch)를 정의하는 문법이다. 아래 예시를 통해 알아보자.

// Code 1-1. 에러를 던지는 메서드 (에러 발생이 예상되는 메서드)
private func getUserInput() throws -> Int {
    guard let userInput: String = readLine(), let resultInteger: Int = Int(userInput) else {
        throw GameError.invalidInput
    }
    if !(resultInteger >= 0 && resultInteger <= 3) {
        throw GameError.outOfRange
    }
    return resultInteger
}

이 메서드는 묵찌빠 게임에서 사용자의 입력을 받아 옵셔널 바인딩을 통해 옵셔널을 안전하게 처리하고, 사용자의 입력이 유효한 범위에 있는지를 판별하는 메서드이다. 별도의 메서드를 구성하여 분리할 수 있지만, 에러 처리가 어떤 방식으로 이루어지는지 한 눈에 알 수 있으므로 구성에 따른 장단이 있다.
먼저 에러를 던지는 메서드는 메서드 선언부에서 반환값 화살표 앞에 throws 키워드를 추가한다. 다음으로 에러가 발생할 구문 (위의 예시에서는 옵셔널 처리가 되지 않은 경우 (nil 또는 정수형 입력이 아닌 경우, invalidInput), 입력값이 입력 범위를 벗어난 경우 (정수형이지만 0 ~ 3 이 아닌 경우, outOfRange))에서 에러 객체를 던지고(throw) 있다. 그럼 이제 이 에러를 받는 메서드를 보자.

// Code 1-2. 에러를 받아 처리하는 메서드 (do-try-catch)
func play() {
    repeat {
        printMenu()
        do {
            var userInput: Int = 0
            userInput = try getUserInput()
            if userInput == 0 {
                exitGame()
            }
            choicePlayerHands(userInput)
            decideWinnerByMode()
        } catch {
            handleError()
        }
    } while true
}

위 메서드는 묵찌빠 게임 실행의 전반을 담당하는 play() 메서드로, getUserInput() 메서드에서 던진 에러를 처리하는 메서드이다. do-try-catch 구문은 간단히 말하면 아래와 같이 구성되어 있다.

일련의 행동을 하고(do) 행동 사이에 에러가 발생할 수 있는 메서드의 실행을 시도해보는데 (try) 실제로 에러가 발생하면 이것을 잡아서 (catch) 어떻게 처리한다.

실제로 위 메서드도 동일한 논리 흐름으로 구성되어 있다. userInput 지역변수를 초기화하고 사용자 입력이 0인 경우 exitGame() 메서드를 호출하되, 그 간 getUserInput() 메서드 실행을 시도해보고, 만약 여기서 에러가 발생하면 이를 잡아서 handleError() 메서드를 호출하라는 형식으로 작성되어 있다. 코드 리뷰 중 한 가지 의견은 do-try-catch문은 코드가 깊어지기에 선호하지 않는 개발자도 있다는 것이었다.

학습 트리 정리


현재까지 학습한 내용을 트리 형식으로 정리하고 미흡한 부분은 분홍색 음영으로 표시하였다.

문제점 / 고민한 점

에러 처리

프로젝트 수행 중 유효하지 않은 입력 (0 ~ 3 범위를 벗어나는 정수 및 기타 입력)을 처리하기 위해 -1과 같은 의미 없는 정수값을 반환하는 메서드를 작성하였었다 (반환하는 값을 Int로 지정하였다, func getUserInput() -> Int). 아무리 GameError라는 열거 타입을 통해 invalidInput이라는 에러를 선언하였다고 하더라도 -1이라는 에러 처리용 정수를 불러오기 위해 메서드가 GameError.invalidInput.rawValue라는 값을 반환하는 것이 가독성에 영향이 있을 수 있다고 생각했다. 그래서 이번 프로젝트에서는 throw, do-try-catch 문을 사용해 에러를 처리했다.

해결 방법

  • throw do-try-catch문을 통해 에러를 처리하였다. 다음 스텝은 에러를 에러 객체로 반환하기 위해 취할 수 있는 방법을 고민해보는 것이다. checkInvalidInput(of userInput:) -> Error와 같이 에러 타입을 반환하는 메서드를 만들거나 Swift의 Result에 대해 알아보는 방법이 있을 것이라고 예상하고 있다.
profile
합리적인 해법 찾기를 좋아합니다.

0개의 댓글