[우아한 테크코스 6기] 최종 코딩 테스트 후기, 프론트엔드 풀이 방법

✨월요일에 날라온 1치 합격 메일!

월요일 오후 3시. 너무나 감사하게도 1차 합격 메일을 받았습니다!

이번 과정을 다음 7기 준비하시는 분들, 혹은 불합격 하여 다음에 또 응시하게 될 경우를 대비하여 과정을 기록하려고 합니다!

 

❗일주일간 이렇게 공부했습니다.

남은 5일 간 최종 시험과 비슷한 환경에서 많은 문제를 풀어보기 위해 노력했습니다.
1시부터 6시까지 시험이기 때문에, 이 시간에 스벅가서 각잡고 풀었답니다!
5기 문제 3주차, 최종. 4기 문제 3주차 최종 문제를 풀었구요.
결론 적으로 최종 시험의 문제 난이도는, 프리코스의 2주차 정도의 양이었고, 4주차 정도의 복잡성을 가지고 있다고 결론을 내렸습니다!
6기 1주차 미션. 야구 게임
6기 2주차 미션. 자동차 경주
6기 3주차 미션. 로또
6기 4주차 미션. 크리스마스 프로모션
5기 3주차 미션. 다리 건너기
5기 최종 미션. 점심 메뉴 추천
위의 링크를 통해 제 레포로 이동하실 수 있습니다!
참고로 4기 문제는 브라우저, html을 이용하는 문제였기에 최종 테스트에 도움이 되지 않는다 생각합니다.
 
git reset HEAD~<커밋 갯수> 명령어를 통해 커밋을 삭제하고, 다시 풀어볼 수 있습니다!

 

✨ 당일 시험은 어떻게 치뤄지나요?

시험은 오프라인으로 진행됩니다. 송파의 한국 루터회관 14층에서 시험이 실시되구요.
다과가 준비되어있습니다. 모르고 잔뜩 챙겨갔는데, 주시는거 챙겨 먹느라 하나도 못먹었네요 🤣
시험 시간은 1시부터 6시. 하지만 이번 시험에서 네트워크 이슈로 30분 지연되어 1시 30분 부터 6시 30분 까지 시험이 진행 되었습니다.
시험 공간이 매우 협소하기 때문에, 노트북만 챙기시는걸 추천드려요!

 

 

❗당일 시험 문제는 어떤 것인가요?

당일 시험 문제는 이전 5기 최종 문제에 비하면 굉장히 어려웠다 생각합니다. 이전 프리코스는 사실 ‘코딩 테스트’와는 거리가 멀었거든요. 5기 최종 미션 역시 기본기가 있는 사람인지 판단하는 테스트라고 생각했습니다. 하지만 미션에서는 추가적인 문제가 있었습니다. (’나의 풀이 방법‘ 참고해주세요!)
6기 최종 미션. 개발자 비상근무
위 링크를 통해 최종 미션 레포로 이동하실 수 있습니다!

 

시험 결과는 테스트 코드를 많이 작성하지 못했지만, 리팩터링과 추가 요구사항까지는 최대한 맞췄구요, 테스트 통과를 했습니다!

 

이후 복습하면서 출력 요구사항을 충족하지 못한 실수를 하나 발견했네요..

평일의 공휴일에만 '(휴일)' 표시를 해야하는데, 공휴일일 경우 모두 '(휴일)' 표시를 해버렸습니다..😭

 

❗나의 풀이 방법 (위 링크에서 문제 우선 풀어보세요!)

이전 미션과 이번 미션의 가장 큰 차이점이라면 다음 문제가 있었다는 것인데요.

### 미션 해결 전략

### 1. 본인이 이해하고 구현한 내용에 기반해 '다른 근무자와 순서를 바꿔야 하는 경우'를 자신만의 예시를 들어 설명하세요. (필수)

### 2. 요구사항에서 제시한 앞의 날짜부터 순서를 변경하는 방법 외에 다른 방법이 있다면 어떤 방식이 있는지, 이 방법은 기존에 제시된 방식과 비교해 어떤 차이가 있는지 설명하세요. (선택)

‘다른 근무자와 순서를 바꿔야 하는 경우’를 제외한 나머지 기능 구현은 모두 쉽게 구현했을 것이라 생각했습니다. 이 부분이 조금 막혔는데요.
다음과 같은 경우의 수를 생각했습니다.

ex -> 월(평일): 로지, 화(휴뮤):로지, 수(평일): 고니, ... 토(휴일): 고니, 일(휴일): 모디,...
변경시 -> 월(평일): 로지, 화(휴뮤):고니, 수(평일): 고니, ... 토(휴일): 로지, 일(휴일): 모디,..

위와 같이 ‘로지’가 곂쳐 다음 근무자인 ‘고니’로 변경할 경우, ‘고니’가 한 번 더 곂치는 상황이 발생하면서 문제가 생기게 됩니다.
저는 Queue를 이용하여 문제를 풀었습니다.

  1. Queue에 근무자가 있고, 이전 날의 근무자와 다르면 할당한다.
  2. 1을 충족하지 못하고, 이전 날의 근무자와 오늘 근무자가 같으면 이번 근무자를 Queue에 넣고 다음 근무자를 할당한다.
  3. 1을 충족하지 못하고, 이전날의 근무자와 오늘 근무자가 다르면 이번 근무자를 할당한다.
...
#workerCalendarAll(DAY_CALENDAR) {
	// 평일 Q와 주말 Q
    const DAY_WORKER_DUP = [];
    const END_WORKER_DUP = [];

	// 달력 순회
    DAY_CALENDAR.forEach((string, number) => {
      if (!number) return;
	  // 평일인 경우
      this.#workerCalendarDay(string, number, DAY_WORKER_DUP);
	  // 주말인 경우
      this.#workerCalendarEnd(string, number, END_WORKER_DUP);
    });
  }

	// 평일인 경우
  #workerCalendarDay(string, number, DAY_WORKER_DUP) {
    const MONTH = this.#calendar.getMonth();
    if (!this.isWeekEnd(string, number, MONTH)) {
	// Queue에 근무자가 있고, 이전 날의 근무자와 다르면 할당한다.
      if (this.#isQueueDayWorker(DAY_WORKER_DUP, number)) {
        this.#workerCalendar[number] = DAY_WORKER_DUP.shift();
        return;
      }
	// 이전 날의 근무자와 오늘 근무자가 같으면 이번 근무자를 Queue에 넣고 다음 근무자를 할당한다.
      // 이전날의 근무자와 오늘 근무자가 다르면 이번 근무자를 할당한다.
	  if (this.#workerCalendar[number - 1] === this.#dayWorkers[this.#dayOrder]) {
        DAY_WORKER_DUP.push(this.#dayWorkers[this.#dayOrder]);
        this.#dayOrder = this.upDayOrder(this.#dayOrder);
      }
      this.#workerCalendar[number] = this.#dayWorkers[this.#dayOrder];
      this.#dayOrder = this.upDayOrder(this.#dayOrder);
    }
  }

  #isQueueDayWorker(DAY_WORKER_DUP, number) {
    return DAY_WORKER_DUP[0] && this.#workerCalendar[number - 1] !== DAY_WORKER_DUP[0];
  }

	// 주말인 경우
  #workerCalendarEnd(string, number, END_WORKER_DUP) {
    if (this.isWeekEnd(string, number, this.#calendar.getMonth())) {
	  // Queue에 근무자가 있고, 이전 날의 근무자와 다르면 할당한다.
      if (this.#isQueueEndWorker(END_WORKER_DUP, number)) {
        this.#workerCalendar[number] = END_WORKER_DUP.shift();
        return;
      }
	// 이전 날의 근무자와 오늘 근무자가 같으면 이번 근무자를 Queue에 넣고 다음 근무자를 할당한다.
      // 이전날의 근무자와 오늘 근무자가 다르면 이번 근무자를 할당한다.
      if (this.#workerCalendar[number - 1] === this.#endWorkers[this.#endOrder]) {
        END_WORKER_DUP.push(this.#endWorkers[this.#endOrder]);
        this.#endOrder = this.upEndOrder(this.#endOrder);
      }
      this.#workerCalendar[number] = this.#endWorkers[this.#endOrder];
      this.#endOrder = this.upEndOrder(this.#endOrder);
    }
  }

  #isQueueEndWorker(END_WORKER_DUP, number) {
    return END_WORKER_DUP[0] && this.#workerCalendar[number - 1] !== END_WORKER_DUP[0];
	}

이 외에 여러 방법이 있겠지만, 저는 이 방법이 제일 깔끔하게 풀렸습니다.
총 문제를 풀고, 테스트를 통과하는데는 대략 3시간 20분 정도가 걸렸으나, 위 중복 로직의 길이가 어마어마하게 길어서 위 코드와 같이 리팩토링 하는데만 1시간 넘게소요되었어요..!
더 다듬을 수 있었는데, 저는 나머지 시간을 다른 부분 리팩터링과 테스트 코드 작성에 시간을 보냈답니다!

 
저의 우테코 6기 도전기는 이렇게 막을 내리네요..! 2주간 기도하면서 합격 소식을 기다리도록 하겠습니다.🙏