트랙
/
Roc
Roc
/
연습 문제
/
오류 처리
오류 처리

오류 처리

보통

지침

다양한 종류의 오류 처리와 리소스 관리를 구현해요.

프로그래밍에서 중요한 점 중 하나는 오류가 발생하더라도 오류를 처리하고 리소스를 닫는 방법이에요.

이 연습 문제에서는 다양한 오류를 처리해야 해요. 오류 처리는 프로그래밍 언어마다 차이가 크기 때문에, 정확히 무엇이 필요한지 확인하려면 해당 트랙의 테스트를 참고해야 해요.

구현

아주 작은 웹 서버를 만들고 있는데, 이 서버는 그보다 더 작은 사용자 데이터베이스에 질의해요. 간단해 보이지만 실제로는 여러 가지가 (그리고 자주) 잘못될 수 있어요:

  • 연결이 안전하지 않을 수 있어요: URL은 "https://"로 시작해야 해요
  • 도메인 이름이 유효하지 않을 수 있어요: 이 연습 문제에서는 "example.com"이어야 해요
  • 페이지를 찾지 못할 수 있어요: "https://example.com/", "https://example.com/users/", "https://example.com/users/<user_id>"만 허용돼요
  • user_id가 양의 정수가 아닐 수 있어요
  • 데이터베이스에 이 user_id를 가진 사용자가 없을 수 있어요

문제가 생겼을 때는 최종 사용자가 문제를 해결할 수 있도록 친절하고 유용한 오류 메시지를 보여주는 게 중요해요. 그러려면 오류가 감지된 지점에서 오류 메시지가 만들어지는 지점까지 코드가 정보가 담긴 오류를 전달하도록 해야 해요.

다행히도 Roc에서는 Err 태그 안에 페이로드(즉, 데이터)를 담을 수 있어요. 오류 메시지를 그대로 담고 싶은 유혹이 들기도 해요(예: Err("User #42 was not found")). 단순한 경우에는 이렇게 해도 괜찮을 수 있지만, 몇 가지 한계가 있어요:

  • 오류를 감지하는 함수 안에서 충분히 유용한 오류 메시지를 만들 만큼의 맥락을 갖지 못할 수 있어요.
    • 예를 들어 Str.to_u64 함수는 날짜, 초, 사용자 ID 등 온갖 정수를 파싱하는 데 쓸 수 있어요. 오류 메시지가 그냥 Could not convert string "0.5" to a positive integer라고만 알려준다면, 사용자는 문제를 해결할 만큼의 맥락을 갖지 못할 수 있어요.
  • 많은 경우 오류 처리 코드가 어떤 오류는 다른 오류와 다르게 처리해야 할 수 있어요. 그런데 오류가 문자열 페이로드만 담고 있다면, 오류 처리 코드는 어떤 문제가 발생했는지 알기 위해 그 문자열을 파싱해야 해요. 이는 비효율적이고, 오류 메시지가 조금이라도 바뀌면 쉽게 깨질 수 있어요.
  • 웹사이트가 여러 언어를 지원한다면, 오류 메시지를 사용자의 언어로 번역해야 해요. 오류 페이로드가 영어 문자열이 아니라 기계가 다루기 쉬운 데이터라면 훨씬 하기 쉬울 거예요.

그래서 이 연습 문제에서는 오류가 의미 있는 태그와 그에 맞는 유용한 페이로드를 함께 담아요. 예를 들어 사용자를 찾지 못하면, 오류는 Err(UserNotFound(42))처럼 생겼어요.

자, 시작해볼까요! 해야 할 일은 다음과 같아요:

  1. get_user를 구현해서 users "데이터베이스"(사실 그냥 Dict예요)에서 요청한 사용자를 반환해요. 사용자를 찾지 못한 경우에는 Err(KeyNotFound) 대신 Err(UserNotFound(user_id))를 반환하는지 꼭 확인해요.
  2. parse_user_id를 구현해서 URL의 경로(예: "/users/123")를 양의 정수 사용자 ID(123)로 변환해요. 오류가 나면 Err(InvalidUserId(user_id_str))를 반환해요.
  3. getPage를 구현해요:
    • URL이 "https://example.com/"이면 Ok("Home page")를 반환해요
    • URL이 "https://example.com/users/"이면 Ok("Users page")를 반환해요
    • URL이 "https://example.com/users/<user_id>"이면 사용자 ID를 파싱하고, 그 ID를 가진 사용자를 불러온 뒤 Ok("<user name>'s page")를 반환해요
    • URL 접두사가 "https://"가 아니면 Err(InsecureConnection(url))를 반환해요
    • URL 도메인 이름이 "example.com"이 아니면 Err(InvalidDomain(url))를 반환해요
    • 경로가 /, /users/, /users/<user id> 중 어느 것도 아니면 Err(PageNotFound(path))를 반환해요
    • 사용자 ID가 양의 정수가 아니면 Err(InvalidUserId(user_id_str))를 반환해요
    • 사용자가 존재하지 않으면 Err(UserNotFound(user_id))를 반환해요
  4. error_essage를 구현해서 앞의 오류들을 번역된 오류 메시지로 변환해요. 이 함수는 적어도 영어는 처리해야 하지만, 다른 언어도 처리해보면 좋아요. 영어 오류 메시지는 다음과 같아요:
  • "Insecure connection (non HTTPS): http://example.com/users/789"
  • "Invalid domain name: https://google.com/wrong"
  • "Page not found: /oops"
  • "User ID is not a positive integer: abc"
  • "User #42 was not found"

참고: 사용자가 HTTPS 대신 HTTP를 사용할 때 오류 메시지를 보여주는 대신, 웹 서버가 사용자의 브라우저를 HTTPS로 리디렉션할 수도 있어요. 그러면 사용자는 오류를 눈치채지도 못할 거예요. Roc에서는 오류가 기계 친화적이라, 이런 걸 구현하기가 아주 쉬워요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Roc Exercism

오류 처리 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Roc 트랙을 연습 문제 126개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.