[내일배움캠프] 계산기 구현 - level.01(1)

2024. 9. 4. 21:48내일배움캠프

 정수 2개와 연산기호(=사칙연산 기호)를 입력받아 연산을 수행하는 계산기를 구현하는 과제의 진행 과정을 남겨본다. 오늘은 '단일 클래스' 계산기에 대해서 구현을 진행하였고 요구사항과 작성한 코드에 대해서는 아래의 링크를 통해 확인 할 수 있다.

 

1. 아..거슬리네

요구사항을 정리하고 구현을 진행하니 딱히 어려울 것은 없었는데, 문제는 초안을 작성하고 나서 거슬리는 부분이 있다는 것이다. (기능에는 영향이 없다고 판단하지만 현재로써는 그저 거슬려서...)

저...노란줄 너무 거슬린다..

 

물론 해당 부분은 'IntelliJ' 에서 제공하는 기능으로 심각한 오류는 아니지만 수정할 것을 권하는 경고인 것은 알고있다. 당장 사용하는데 문제는 없겠지만 어쨌든 '이보다 나은 방법이 있고 이를 수정하길 어떠냐?' 하는 말로 들리기에 위에서 처럼 거슬린다 표현하였다.

 

 경고 등장의 이유는 아래와 같다.

  • 너 'switch' 문에 사용하는 파라미터 그거 해당하는 'case' 없을 때 어떻게하게?
  • 기본적으로 처리하는 'default' 에 대한 코드도 없고...
  • 정작 수행되는 로직에 공통으로 들어가는 'result' 는 '0' 으로 초기화 했네?

그래서 해당 내용을 참고해서 아래와 같이 코드를 수정하니

그래 드디어 사라졌구나 짜식

 

노란줄(경고, 거슬리는 녀석)이 사라졌다. 기본적으로 'result' 가 '0' 으로 초기화 되어 있기에 'default(해당 케이스 없을 때 수행)' 만 추가하면 됬고, 만약 'result' 를 초기화 없이 선언만 한다면 'result' 에 '0' 을 저장하는 코드를 'default' 에 추가하면 된다. 문제가 짠 해결된 것 같지만...여기서 또 의문이 들었다."근데 'result' 에 '0' 이 저장되는 경우가 필요해?" 맞다. 이미지에 보이지 않지만 나의 경우 잘못된(지정한 연산기호가 아닌) 값이 입력되었을 때 실행 순서를 처음으로 돌아가도록 구현해 두었다. 그래서 사실 이미지에 나온 코드가 수행된다는 것은 입력된 값이 '연산 기호' 라는 소리고 당연히 어떤 케이스든 해당되기 때문에 로직이 수행될 거라 생각헀는데... 'IntelliJ' 가 보기엔 그렇지 않은 것 같다.

 

근본적으로 경고가 뜬 이유는 'operator' 변수가 무조건적으로 'switch' 의 'case' 에 해당하는 값을 가지고 있다는 판단할 수 없기 때문이라 생각한다. 이 말은 당장 내가 작성한 코드, 비교적 간단한 코드이기에 무시할 수 있겠지만 해당 코드를 확장하거나 추후에 다시 수정을 할 때 문제가 없을거란 확신을 가질 수 없었다. 그래서 위의 방법이 아닌 다른 방법으로 로직을 수정해보기로 하였다.

 

 

2. 이제는 됬겠지?

 일단 수정에 앞서 한 번더 생각한 것은 그럼 'default' 에 담을 로직이 정말 없냐는 것이었다. 사실 있었다! (미련 때문에 선뜻 수정하지 못한 코드가...)

아... 지우긴 아쉬운데;;

 

바로 'Main' 클래스에 작성한 'static' 메서드인 'checkOperator(String)' 이다. 나의 경우 전체 흐름은 대략 아래와 같은데

  1. 값 입력 -> 입력 값 확인 -> 조건에 맞지 않는다면 반복문 처음(첫 번째 값 입력)으로 돌아감
    • 만약 "exit" 를 입력 받았다면 반복문을 벗어남
  2. 입력 연산 기호에 맞는 연산 수행 후 결과 반환
  3. '1' 과 '2' 의 과정을 반복

'checkOperator(String)' 은 '1' 의 과정에서 사용되는 메서드이다. 하지만 다시 보니 'switch-default' 에 잘못된 입력 값을 알리는 메시지 출력과 함께 반복문의 처음으로 돌아가는 로직을 작성하니 해당 메서드가 "구지 필요하지 않네?" 라는 생각을 할 수 있었다. 아래는 수정한 코드이다.

수정된 연산 로직

 

'switch' 문에 'default' 구문을 추가하였고 해당 구문에는 입력받은 값과 일치하는 케이스가 없을 경우 출력되는 메시지들과 처음 과정으로 돌아가기 위한 'continue' 를 사용하였다(참고로 현재 로직은 'while' 문 안에 있다). 또한 더불어 'result' 의 초기 값을 없애 불필요한 값을 해당 변수에 저장하는 경우도 방지했다.

 

 

3. 진짜 마지막이다...

 수정된 코드를 보니 한결 편-안해졌고 다시 한 번 수정으로 인한 오류가 없는지 확인하고 실행을 해보았는데...또 거슬리는게 보였다.

좀 더 수정해보라 하는 실행창

 

그냥 쓱 보면 별 이상할게 없다. 지정한 값이 아닌 값을 입력해 예외 처리를 위해 작성한 메시지가 출력되고 다시 처음 부터 입력을 요구한다. 근데...이게 좀 말이 안된다.

 

사용자가 무엇인가 잘못 입력했다면 어떤 부분을 잘못 입력했는지 명확히 알려 같은 실수를 통해 사용자가 서비스로 불쾌감을 느끼면 안된다는 것이 내 생각인데, 위의 실행창 이미지를 보면

  • 첫 번째 입력에 대한 경우 중간의 연산기호 오입력으로 예외처리가 잘 된 것 같다.
  • 두 번째 입력에 대한 결과를 확인해보면 분명 입력 순서는 '피연산자 > 연산기호 > 피연산자' 순서인데 사용자가 '피연산자 > 피연산자 > 연산기호' 로 착각해 값을 오입력하니 먼저 입력한 '연산기호' 에 대한 오입력을 짚어주거나 '연산기호' 와 '피연산자' 오입력 모두 짚어주어야 할 것 같은데... '피연산자' 오입력만을 사용자에게 알려준다.

이렇게 되면 사용자는 피연산자 입력만 신경쓰고 연산기호는 신경안써 비슷한 상황을 또 겪고 연산 값을 처음부터 다시 입력하며 "아C 왜 한 번에 안알려주는거야?" 하며 불쾌감을 느낄 수도 있기에 바꿀 필요성을 느꼈다.

 

그러면 어떻게 코드를 수정해야 할까? 우선 기존 수행 로직의 순서를 변경할 필요가 있다. 이미 한 번 바뀐 로직을 확인해 보면

  1. 피연산자1 입력 > 피연산자 체크
  2. 연산 기호 입력
  3. 피연산자2 입력 > 피연산자 체크
  4. 연산 수행 + 연산 기호 체크

인데, '입력 값을 일단 모두 받은 다음에 한 번에 예외를 처리하면 어떨까?' 라는 생각을 하였다.

입력 값의 유효성을 한 번에 검사하는 메서드 추가

 

그래서 추가한 것이 'validInputCheck()' 이다(덤으로 'checkNum()' 메서드도 사망...). 입력 받은 세 값을 파라미터로 받으며 boolean 값을 반환한다. 기본적(모든 값이 유효할 경우)으로 true 를 반환하며 세 값들 중 하나라도 유효하지 않은 값이 있다면 false 를 반환한다. 결과 값 반환 전 입력 값의 유효하지 않다면 해당 값의 입력에 오류가 있음을 알리고 반환 값이 false 라면 처음부터 값을 다시 입력할 것을 요구하는 메시지(+실행창 구분선)를 출력한다.

 

이렇게 메서드를 작성하니 결과적으로 입력 받은 값 중 오류가 있는 입력에 해당하는 모든 오류 메시지를 출력해줄 수 있게 되었다. 한 번에 유효성을 검사하는 메서드를 추가했으니 해당 메서드가 수행될 위치도 수정하였다.

유효성 검사 시점 변경

 

기존에는 입력 값을 받을 때마다 유효성을 검사했지만, 이제는 모든 값을 입력 받은 후에 모든 입력 값을 파라미터로 받은

'validInputCheck' 메서드를 사용해 한 번에 유효성 검사를 진행, 해당 메서드는 모두 유효하면 true, 하나라도 유효하지 않은 값이 있으면 false 를 반환하므로 false 반환시 'continue' 를 통해 반복문 처음으로 돌아가도록 하였다. 

 

이후에는 오입력 상황을 가정해 실행창에 값을 입력후 의도대로 결과가 출력 되는지 확인했다.

예외 상황 가정 입력 결과

 

 

4. 돌고 돌아...또 너네?

 이렇게 로직 순서를 맞추니 '1' 에서 다룬 그 놈의 스위치가 다시 처음 모습마냥 다가왔다...스위치를 먼저 신경쓸게 아니었나보다. 해당 스위치를 왜 바꾸고 싶어하는지는 '1' 에서 다루었으니 바로 수정한 내용을 적는다. "애초에 스위치 케이스마다 연산 로직을 직접 다룰 필요가 있을까? 결과 값을 저장하는 것 때문에 고민이 이었으니 케이스별로 다른 메서드를 호출하고 해당 메서드가 결과를 출력하게 끔 하면 되지 않나?" 라는 생각이 빠르게 들었고 바로 수정하였다.

switch 문 수정
연산별 연산 수행 메서드 추가

 

switch 문은 연산자를 확인하고 연산자에 해당하는 연산을 수행하고 결과를 출력할 메서드를 호출하게 된다. 호출된 메서드는 연산을 진행하고 결과를 출력하게 되는데, 4개의 연산 메서드 모두 같은 형식의 결과 메시지를 출력하기에 결과 메시지를 출력하는 'printResult' 를 생성해 결과(result) 값을 파라미터로 받아 결과 메시지를 출력하도록 하였다. 이렇게하니 '1' 에서 다루었던 거슬리는 불편함은 해결되었다. 아까 예외에 대한 결과는 확인했으니 정상 입력에 대한 결과를 확인하는 것으로 마무리 해보도록 하겠다.

정상 입력 결과

 

사칙연산 결과도 정상적으로 출력되고 '0' 을 피연산자로 입력했을 때도 연산을 통해 정상적인 결과가 출력되며 "exit" 입력시 반복문을 빠져나와 실행을 (정상)종료하게 된다.

 

 

5. 마무리

하...인터페이스 쓰고 싶다;;