[우아한테크코스 6기 프리코스] 1주차 회고

jkpapa·2023년 10월 25일
0

우아한테크코스

목록 보기
1/3

일주일 동안 진행했던 프리코스 과정을 회고하고 기록하려고 합니다.

코드 저장소 링크

저는 이번 한 주 동안 다음과 같은 목표를 세웠어요.

내가 설명하지 않아도 이해할 수 있는 코드, 유지보수 하기 쉬운 코드를 작성하자

프로젝트 경험이 많은 것은 아니지만 구현에만 급급해서 놓쳤던 부분이 정말 많았습니다. 이런 아쉬움들을 프리코스에서 해소하고 싶었어요.

목표를 이루려면 어떻게 해야할지 많이 고민했습니다. 지금까지 프로젝트를 진행하면서 가장 아쉬웠던 점이 설계를 꼼꼼하게 진행하지 않은 것이었어요.

개발할 때 정말 수 많은 에러들을 만나는데, 개발 단계 이전에 충분히 예상하고 대처할 수 있는 부분이라고 느낀 오류들이 정말 많았습니다. 설계를 소홀히해 새로운 오류가 생길 때 마다 조건문으로 분기 처리를 통해 해결했기에 코드가 복잡해지고 리팩토링조차 힘든 지경까지 만들어본 경험이 있어요.

다시 이런 경험을 하지 않기 위해 했던 노력을 작성해 보려고 합니다.

고민한 내용

🤔어떻게 하면 유지보수하기 쉬운 코드를 만들 수 있을까?

저는 이 부분에 대해서 과거 프로젝트와 과제를 하면서 느낀점, 예전에 유트브 영상에서 얻은 영감을 바탕으로 나름대로 정한 기준이 있습니다.

유지보수가 쉬운 코드는 변화가 일어났을 때 수정할 코드가 적여야 하며, 그리고 내가 원하는 로직을 빠르게 찾을 수 있는 코드

원하는 로직을 빨리 찾으려면?

원하는 로직을 빠르게 찾기 위해서는 좋은 모듈 설계가 바탕이 되어야 했습니다. 좋은 모듈 구조를 만들기 위해서 어떤 기능들을 같은 모듈에 배치하고 어떤 기능들을 분리해야 하는지 고민했습니다. 이 부분은 설계가 선행되어야 했어요. 저는 플로우차트를 기반으로 설계를 진행했고, 구현 할 기능들 목록을 작성했습니다.

이 기능들을 바탕으로 모듈을 설계하고 분리했습니다.

변화가 발생한다면?

만약 애플리케이션에서 기능의 변화가 있을 경우 최소한의 코드 수정으로 구현을 마쳐야 한다고 생각했습니다. 지금 구현 중인 부분에서 변화가 생길 수 있을 만한 요소를 상상하고 그 요소를 기준으로 개발을 진행했습니다.

게임에서 맞추는 숫자의 길이가 3에서 변화할 수 있다는 가정을 했고, 이를 바탕으로 구현을 시작했습니다. 만약 게임이 3자리 수가 아니라 5자리 수로 변경되었을 때, 최소한의 변화로 요구사항을 만족할 수 있도록요.

const MAX_NUM_LENGTH = 3;

상수로 진행하는 게임 숫자의 길이를 정의하고 만약 변화가 생겼을 때, 이 상수 값만 변경하면 나머지 코드들에도 반영되도록 개발을 진행했어요.

// getRandomUniqueNumber.js

import { Random } from '@woowacourse/mission-utils';
import Constant from './Constant';

const { MAX_NUM_LENGTH } = Constant;
const START = 1;
const STOP = 9;

const getRandomUniqueNumber = () => {
  const randomNumbers = [];

  while (randomNumbers.length < MAX_NUM_LENGTH) {
    const number = Random.pickNumberInRange(START, STOP);

    if (!randomNumbers.includes(number)) {
      randomNumbers.push(number);
    }
  }

  const numberString = randomNumbers.join('');

  return numberString;
};

export default getRandomUniqueNumber;

getRandomUniqueNumber는 랜덤으로 각 자리 수가 다른 숫자를 문자열로 반환하는 함수입니다. 함수 내부에서 MAX_NUM_LENGTH를 기준으로 중복이 없는 숫자를 무작위로 생성합니다.

// tryMatch.js

// ... code

const tryMatch = async (baseNumber) => {
  let isMatch = false;

  while (!isMatch) {
    const inputValue = await inputToUser(INPUT_PROMPT, isUniqueNumber);

    const { strike, ball } = compareNumberString(baseNumber, inputValue);

    const resultString = getResultString({ strike, ball });
    Console.print(resultString);

    isMatch = strike === MAX_NUM_LENGTH;
  }
};

export default tryMatch;

tryMatch는 사용자에게 받은 입력이 정답일 때 까지 계속해서 반복하는 함수입니다. 함수 하단에 strike === MAX_NUM_LENGTH의 결과를 바탕으로 사용자의 입력이 정답인지 아닌지 판단할 수 있습니다.

만약 상수를 사용하지 않고 매직넘버를 사용했다면 하나의 변화 때문에 복수의 코드 수정이 불가피했을 것입니다.

🤔어떻게 하면 읽기 좋은 코드를 작성할 수 있을까

코드가 지금 어떤 목적을 가지고 무슨일을 하고 있는지 이해하기 쉬운 코드가 읽기 좋은 코드라고 생각하고 있습니다. 읽기 좋은 코드를 작성하기 위해 함수 네이밍에 신경쓰고, 최대한 선언형으로 프로그래밍하려고 노력했던 것 같아요.

다시 tryMatch 함수를 살펴보겠습니다.

// tryMatch.js

// ... code

const tryMatch = async (baseNumber) => {
  let isMatch = false;

  while (!isMatch) {
    const inputValue = await inputToUser(INPUT_PROMPT, isUniqueNumber);

    const { strike, ball } = compareNumberString(baseNumber, inputValue);

    const resultString = getResultString({ strike, ball });
    Console.print(resultString);

    isMatch = strike === MAX_NUM_LENGTH;
  }
};

export default tryMatch;

이 코드를 읽는 사람으로 하여금 다음과 같은 사고의 흐름으로 가길 바라며 작성했습니다.

tryMatch(baseNumber) >> 함수이름과 매개변수의 이름을 보면 baseNumber를 맞추는 시도를 하는 함수구나!

while(!isMatch) >> 정답을 맞출 때 까지 반복하네!

inputValue >> 사용자가 입력한 값을 이곳에 저장하네!

{ strike, ball } >> baseNumber와 inputValue를 비교한 결과구나!

resultString >> 비교한 결과를 바탕으로 만든 문자열이네!

isMatch = strike === MAX_NUM_LENGTH; >> 비교 결과가 일치하는지 판단하고 있구나

어떤가요?... 신경쓰며 작성하긴 했지만 다른 사람이 정말로 이런식으로 느꼈을지는 잘 모르겠습니다. (빨리 코드리뷰 받고 싶다!!)

좋았던 점(스스로 성장했다고 느낀 부분)

역시 구현 이전에 설계를 찐~하게 진행했던 점이라고 이야기하고 싶습니다. 하루 정도 시간을 내서 설계에만 시간을 쏟았어요.

설계를 진행해서 어떤 기능을 만들어야 할지 쉽게 뽑을 수 있었고, 이를 바탕으로 모듈 구조를 설계할 수 있었습니다. 그리고 구현할 기능을 미리 분류해 놔서 구현을 완료할 때마다 테스트하기에도 용이했습니다.

앞으로 남은 프리코스 기간 동안에 구현 전에 설계하는 습관은 유지 할 생각입니다!

아쉬운점 & 어려웠던 점

아쉬운 점은 설계의 순서에있어요. 저는 프리코스를 시작할 때, 구현할 기능 목록을 먼저 작성하고 플로우차트를 그렸습니다. 이렇게 진행하니까 미리 작성한 기능 목록에 빠진 기능들이 보였던 것입니다.

그리고 airbnb style guide를 맞추기 정말 힘들었습니다. 부랴부랴 esLint, Prettier로 컨벤션을 맞춰 놓긴했지만 esLint에 등록되어 있지 않은 컨벤션은 직접 찾아서 적용해야 했어요.

그리고 컨벤션중에 모듈을 import할 때 파일 확장자를 명시하지 말라는 내용이 있었습니다. 이 때문에 테스트 코드는 잘 동작했지만 모듈 내에서 node로 실행했을 때는 import한 모듈을 찾지 못하고 에러가 발생했습니다. 그래서 모듈 내에서 테스트 할 때 잠시 파일 확장자를 명시하고 실행하기도 했습니다.

2주차 때는 !...

우선 설계의 순서를 추상적인 설계부터 시작하여 점점 세부적인 설계로 넘어가려 합니다. 가령 1주차 프리코스를 다시 진행한다면 플로우차트 그리기 -> 구현 기능 목록 작성하기 -> 기능 설계 하기 이런 식으로 차근차근 진행하면 누락되는 내용을 최소화 할 수 있을 것 같다고 생각했습니다.

파일 확장자를 생략하고 import한 경우 node에서 자바스크립트를 실행하려면 바벨 설정을 해줘야 한다고 합니다. 다음 미션에 적용해 보고 더 빠른 테스트가 가능토록 만들어야겠습니다.

0개의 댓글