✏️우테코 5기 프리코스 4주차 미션 MVC 적용기

김영우·2022년 11월 22일
0

우테코 5기 프리코스

목록 보기
11/16
post-thumbnail
  • 비즈니스 로직과 UI 로직을 분리한다.
  • 객체의 상태 접근을 제한한다.
  • 객체는 객체스럽게 사용한다.

위 조건들은 우테코 프리코스 3주차 프론트엔드 공통 피드백의 일부이다. 이전 미션과 달리 제한사항이 많이 추가된 이번 미션에서는 프로그램을 작성하는 정형화된 패턴을 사용해보는 것이 좋지 않을까 하는 생각을 했다.

이전 미션에서 다른 참가자분들이 MVC 패턴을 사용한 것을 자주 보았었다. 이전에는 그냥 다른 참가자분들이 대단하고만 생각했었지 내가 MVC 패턴을 사용할 생각은 하지 않았었다. 하지만 지난 과제 피드백 사항이었던 비즈니스 로직과 UI 로직을 분리하고, 객체스럽게 객체를 사용하는 측면에서 이 패턴이 이번 미션의 핵심이라는 느낌이 들었다. 그래서 개념적으로만 알고 있었던 내용을 이번에 한번 제대로 공부해보고 적용해보고자 했다.

이제 어떻게 이번 미션에 MVC 패턴을 적용했는지 한번 알아보자.

🧩 M, V, C 분리

MVC 패턴에 대해 공부하다 보면 사람마다 MVC에 대해 내리는 정의가 조금씩 다르다. 그래서 나만의 확고한 기준을 가지고 이를 분리해보고자 했다. 나만의 기준은 다음과 같다.

- M (모델)

  • 프로그램에서 사용되는 모든 값을 저장한다.
  • 외부에서 값을 직접 변경하지 않고, 모델 내부 메서드를 호출하는 방식으로만 값을 변경할 수 있도록 한다.
  • 외부 로직에 관한 어떤 정보도 담지 않는다.

- V (뷰)

  • 값을 저장하지 않는다.
  • 사용자에게 보여지는 모든 부분을 담당한다.
  • 외부 로직에 관한 어떤 정보도 담지 않는다.

- C (컨트롤러)

  • 값을 저장하지 않는다.
  • 프로그램을 구성하는 핵심 로직을 담당한다.
  • 값의 변경이 필요할 때 M(모델)의 메서드를 호출하여 프로그램 내 값을 변경시킨다.
  • UI에 관련된 모든 로직은 V(뷰)의 메서드를 호출하여 실행한다.

💭 다리 건너기 게임에서의 M, V, C

위에서 내가 정의한 MVC 패턴대로 각 구성 요소를 추상화해보았다.

⚙️ M (모델)

❗필요한 데이터

다리 건너기 게임에서 필요한 데이터에는 무엇이 있을까 고민해보았다.

3주차 피드백 사항에 필드의 수를 줄이라는 부분이 있어 이 부분에서 많은 고민을 했다.

일단 다리 건너기 게임에서 사용되는 모든 데이터들을 정리해보았다.

  • 다리 길이 입력값
  • 정답 다리
  • 위, 아래를 선택한 입력값
  • 사용자의 현재 위치
  • 그동안 지나온 상태를 나타내는 문자열
  • 성공, 실패 여부
  • 재시작 여부에 대한 입력값
  • 총 시도 횟수

내가 생각해낸 다리 건너기 게임을 진행하기 위해 필요한 모든 데이터들이다. 저 모든 것들을 필드에 저장하면 필드의 수가 너무 많아질 것이다. 한번 줄여보자.

일단 사용자에게 입력받는 값을 제외해도 될 것 같다. 내 생각엔 사용자의 입력보다 그에 따른 결과가 이 게임에서 더 중요하게 다뤄지는 것 같았다.

  • 정답 다리
  • 사용자의 현재 위치
  • 그동안 지나온 상태를 나타내는 문자열
  • 성공, 실패 여부
  • 총 시도 횟수

입력값만 제외했음에도 필요한 데이터가 많이 줄어들었다. 그래도 아직까진 더 줄일 필요성이 느껴진다.

생각해보니 게임 로직이 돌아가는 동안 성공, 실패 여부는 게임이 종료되었을 때만 사용되기 때문에 저장할 필요가 없을 것 같다. 또 그동안 지나온 상태는 정답값을 알면 충분히 만들어낼 수 있으므로 이 또한 저장할 필요가 없을 것 같다.

  • 정답 다리
  • 사용자의 현재 위치
  • 총 시도 횟수

내가 최종적으로 결정한 모델의 필드에 저장할 데이터들이다. 처음보다 훨씬 간소화 되었고, 이보다 더 줄이자니 게임 로직이 복잡해질 것 같아 이정도 선에서 마무리 했다.


❗값 변경을 위해 필요한 메서드

이젠 모델에서의 값 변화를 담당하는 메서드 차례이다. 다리 건너기 게임을 진행할 때 위에서 정한 필드의 값이 변화되는 경우를 생각해보았다.

일단 정답 다리는 생성이 된 이후부턴 변경이 발생하지 않는다. 따라서 정답 다리에 관한 변경 메서드는 고려하지 않아도 된다.

사용자의 현재 위치는 사용자의 게임 진행에 따라 변화하는 값이다. 사용자가 맞는 방향을 선택했다면 다음 예측을 진행하기 위해 현재 위치를 업데이트 해야한다. 또, 재시작을 했을 때 현재 위치를 초기화 해야한다.

총 시도 횟수는 재시작을 선택할 때마다 변화하는 값이다. 재시작을 선택할 때마다 이를 업데이트 해야한다.

정리해보자면 이렇게 두 가지의 메서드가 필요하게 된다.

  1. 이동시 사용자의 현재 위치 변경 메서드
  2. 재시작시 사용자의 현재 위치, 총 시도 횟수 변경 메서드

추가적으로 현재 진행 상황을 뷰에게 전달하기 위해 생각한 메서드가 있는데 이는 뷰에서 다루도록 하겠다.


⚙️ V (뷰)

❗필요한 메서드

뷰의 메서드는 대부분 컨트롤러에서 넘겨준 값을 출력해주는 식으로 사용되도록 하고자 했다. 하지만 그 외에 게임 진행 요구사항 충족을 위해 특별히 필요한 메서드가 있다. 바로 진행 상황을 보여주는 메서드이다.

처음에 이를 어떻게 처리할까 고민이 많았다. 내가 처음 생각한 방식은 다음과 같다.

  1. 모델에서 정답 다리를 현재 위치까지 잘라서 반환한다.
  2. 뷰에서 이를 받아 요구사항에 맞게 문자열을 만들어 출력한다.

나쁘지 않아 보이지만 사용자가 틀렸을 때를 구분할 수 없다는 치명적인 문제가 있었다. 이를 해결하고자 다음과 같이 방식을 변경했다.

  1. 모델의 메서드에서 정답, 오답 여부를 인자로 넘겨 받는다.
  2. 만약 오답이라면 정답 다리를 현재 위치까지 자르고, 마지막 요소의 앞부분에 'X'를 추가해 반환한다.
  3. 정답이면 그냥 정답 다리를 현재 위치까지 잘라 반환한다.
  4. 뷰에서 이를 받아 요구사항에 맞게 문자열을 만들어 출력한다.

예시를 통해 알아보자.

// 정답 다리
["U", "D", "U", "D"]

// 현재 위치
2

// 정답 여부
정답

// 반환 값
["U", "D", "U"]

// 출력 값
"[ O |   | O ]"
"[   | O |   ]"
// 정답 다리
["U", "D", "U", "D"]

// 현재 위치
3

// 정답 여부
오답

// 반환 값
["U", "D", "U", "XD"]

// 출력 값
"[ O |   | O | X ]"
"[   | O |   |   ]"

모델에서는 정답다리, 현재 위치, 정답 여부를 가지고 반환 값을 만들어 반환한다. 뷰에서는 반환 값을 받아 출력 값을 만들어 사용자에게 보여준다.


⚙️ C (컨트롤러)

❗구현할 내용

다리 건너기 게임의 전체적인 흐름을 정리해보면 다음과 같다.

  1. 다리 길이를 입력 받는다.
  2. 정답 다리를 생성한다.
  3. 위치 예측값을 입력 받는다.
  4. 정답 여부를 판별한다.
    4-1. 정답이라면 현재 위치가 마지막인지 판별한다.
    4-2. 마지막이라면 최종 결과를 출력하고, 아니면 3번을 수행한다.
    4-3. 오답이라면 재시작 여부를 입력 받아 이를 판별한다.
    4-4. 재시작을 원한다면 현재 위치를 초기화 하고 3번을 수행한다.
    4-5. 원하지 않는다면 최종 결과를 출력한다.

컨트롤러는 뷰를 통해 입력과 출력을 수행하고, 그에 따른 값 변화가 필요하다면 모델을 통해 이를 변경한다.


열심히 한 덕분인지 깃허브 리포지토리 트래픽을 보니 정말 많은 분들이 내 코드를 읽어봐주셨다.
감격 ㅠㅠㅠ😭😭😭


혹시 이 글을 읽고 전체 코드를 보고 싶다면 여기를 참고하기 바란다.

profile
불편한 일들을 개발로 풀어내고 싶은 프론트엔드 개발자입니다!

1개의 댓글

comment-user-thumbnail
2023년 11월 4일

안녕하세요 글 잘 읽었습니다. 우테코 프리코스를 하는데 MVC 패턴을 도입하려고 알아보던중에 많이 도움되었어요! 코드를 보고 궁금한게 있는데 혹시 Model 폴더는 왜 따로 만들지 않으신건지 알수 있을까요?? BridgeGame.js 에 변수들이 들어간 것 같은데 모델 역할을 하는 건가요?
MVC 패턴 어렵네요 ㅠㅠ

답글 달기