시작하기 앞서...
이번에 우아한 테크코스 6기 웹 프론트엔드에 지원하게 되어
지난주에 무사히 1주 차 미션을 수행하고 2주 차가 되었다.
git 프로젝트 관리
지난번처럼 프로젝트 fork를 해서 나의 깃허브 저장소에 프로젝트를 가져오고 git clone을 하여
내 로컬에서 코드를 작성할 수 있게 한다.
이에 대한 자세한 내용은 1주 차 후기 게시물에 있다.
이번에는 task2/racingcar 라는 브랜치를 만들어 작업을 했다.
eslint & prettier 설정
과제 요구 사항
메일로 온 공통 피드백에
linter와 Code Formatter의 기능을 활용한다
라는 내용이 있어, eslint 와 prettier를 사용하기로 했다.
그런데 git readme 에 있는 요구사항에는
package.json을 변경할 수 없고 외부 라이브러리(jQuery, Lodash 등)를 사용하지 않는다. 순수 Vanilla JS로만 구현한다.
이런 내용이 있었다.
그런데 다시 공통 피드백을 보니
git을 통해 관리할 자원에 대해서도 고려한다
이런 말이 있어
eslint와 prettier을 사용하되, package.json 파일은 깃에 안 올라가도록 해야겠다.
eslint & prettier 설정하기
eslint와 prettier을 설정하는 방법은 우테코 디스코드에 함께-나누기 카테고리에 올려주신 글을 참고하였다.
(정보 공유 감사합니다!!👍 일부러 블러처리함)
git readme 요구 사항에 들여 쓰기를 3이 넘지 않도록 구현하라는 것이 있어
.eslintrc.json 에 다음 규칙을 추가하였다.
"rules": {
// 들여쓰기 깊이 제한
"max-depth": ["error", 2]
}
.gitigrnore에 eslint와 prettier 설정 파일을 추가해 깃에 안 올라가도록 하였다.
그런데.. package.json package-lock.json 파일도 .gitignore 에 있는데 git status 에 반영이 된다..ㅠㅠ
구글링 해보니
무시하려는 파일이 이미 github repository에 올라가 있으면, 이후에 gitignore에 추가해도 반영이 되지 않는다.
라고 한다..
그래서 그냥 git add 를 할 때, 해당 파일을 빼고 올려야겠다..
+) 우테코 디스코드 글을 보다가
함께-나누기 카테고리에 package.json 커밋 제외 시키기라는 글을 보았다!!
(정보 공유 감사합니다!!)
그래서 블로그에 있는 글을 참고해서 git status 를 했을 때,
package.json package-lock.json 파일을 커밋에서 제외된 것을 확인할 수 있었다.
프로젝트 기능 문서 작성
이번에도 먼저 구현할 기능 목록 문서를 작성했다.
다 작성했으므로, git 에 올려준다.
그리고 이번 요구사항에 커밋 메시지 컨벤션 가이드를 참고하여 작성하라고 했다.
그래서 이를 참고해서 작성해 보기로 했다.
<type>(<scope>): <subject>
<빈줄>
<body>
<빈줄>
<footer>
작성 후에 깃에 올리고
결과를 보니 아래 사진처럼 올라갔다.
type은 docs로,
subject는 구현 기능 목록 문서 추가
body는 새로운 README.md 파일을 생성하여 구현할 기능 목록을 문서화함
이렇게 작성하였다.
아직 이슈가 없어 footer는 작성하지 않았다.
미션 구현하기
게임 초기 세팅
생성자 초기화
구현 기능 목록 문서에 작성한 생성자 초기화 부분을 먼저 만들었다.
constructor(name, forward) {
this.name = name;
this.forward = forward;
}
문서에 있는 기능을 만들었으니깐 커밋을 하여 깃에 올렸다.
경주할 자동차 입력받기
다음으로 경주할 자동차 입력받기이다.
지난번과 같은 방법으로 입력을 받았고
async getCarName() {
const name = await MissionUtils.Console.readLineAsync();
return name;
}
출력을 하니, 이렇게 콤마로 구분된 문자열이었다.
내가 문서에는 배열로 적었는데 잘 못 적었다.. 그래서 수정을 했다.
그리고 제대로 입력은 받아지는데 eslint 오류가 발생하는데 메서드에 this 를 사용하지 않아서 그렇다고 한다.
그런데 이건 나중에 수정해야지,,
경주할 자동차를 입력받았으니 깃에 올려줬다!!
입력받은 자동차 이름 생성자에 저장
경주할 자동차 이름을 문자열로 입력받았으면 이제 이걸 생성자를 사용하여 각각 정보를 담은 배열로 만들어준다.
처음엔 코드를 아래처럼 for문을 사용하였는데
const nameList = name.split(",");
for (let i = 0; i < nameList.length; i += 1) {
cars[i] = new App(nameList[i], "");
}
메일에 온 피드백에 자바스크립트에서 제공하는 API 를 활용하라고 했기 때문에,
자바스크립트에 내장된 map을 사용하여 코드를 수정하였다.
saveCarConstructor(name) {
const nameList = name.split(",");
const cars = nameList.map((carName) => new App(carName, ""));
return cars;
}
saveCarConstructor 함수에서 리턴 받은 cars 를 출력하면 정상적으로 값이 들어간 것을 볼 수 있다.
기능을 구현했으므로 깃에 올려준다.
시도할 횟수 입력받기
이번엔 게임을 시도할 횟수를 입력받는다.
async getNumberOfTry() {
const tryNum = await MissionUtils.Console.readLineAsync();
return tryNum;
}
출력하면 시도할 횟수가 제대로 입력이 된다.
기능이 구현되었으므로 깃에 커밋한다.
시도할 횟수 값 유효성 검사
그런데 테스트를 돌리면 예외 케이스로 undefined 를 받는 경우가 있어, 이를 예외 처리를 해줘야 한다.
그리고 횟수만큼 시도하려면 숫자(number)가 편하기 때문에
Number()를 사용해서 문자열로 입력받은 수를 number 타입으로 변경해 주고 유효성 검사를 실시해야겠다.
숫자나 숫자로 된 문자열이 아닐 경우 Number() 를 하면 NaN이 나오기 때문에 NaN 일 경우 에러 처리를 해주고,
그렇지 않으면 정상적으로 입력받은 횟수를 반환시켜 줬다.
isValidNumberOfTry(tryNum) {
if (Number.isNaN(tryNum)) {
MissionUtils.Console.print("[ERROR] 숫자가 잘못된 형식입니다.");
throw new Error("[ERROR]");
} else {
MissionUtils.Console.print(tryNum);
MissionUtils.Console.print("");
return tryNum;
}
}
그러고 테스트를 실행시키면 정상적으로 작동이 되는 것을 확인할 수 있다.
역시나 깃에 커밋한다.
여기까지 게임을 실행하기 전까지 입력받아야 할 값들을 모두 받았다.
게임 실행
전진 조건 입력받기
이제 랜덤 수를 입력받아, 해당 값에 따라 전진 여부를 결정해야 한다.
랜덤수를 입력받는 함수는 위에서 구한 시도할 횟수만큼 실행해야 한다.
(그런데 이렇게 for문 사용하기 싫다,, 다른 방법 없을까..)
for (let i = 0; i < tryNum; i += 1) {
this.carMoveForward(cars);
}
carMoveForward 함수에서 랜덤 수를 입력받고 4 이상이면 전진해야 된다.
해당 코드는 forEach를 사용해서 구현했다.
carMoveForward(cars) {
cars.forEach((car) => {
const randomNum = MissionUtils.Random.pickNumberInRange(0, 9);
if (randomNum >= 4) {
// 전진
MissionUtils.Console.print(`${car.carName}전진`);
} else {
// 전진 X
MissionUtils.Console.print(`${car.carName}전진X`);
}
});
}
전진 조건 값을 입력받았으니 깃에 올려준다.
전진 결과
전진 결과를 출력해야 한다.
4보다 클 경우 forward 에 - 를 추가해 주고
car.forward = car.forward !== "" ? `${car.forward}-` : "-";
자동차 이름과 전진 결과를 출력한다.
MissionUtils.Console.print(`${car.carName} : ${car.forward}`);
코드를 작성하고 테스트를 실행하면 정상적으로 출력이 되고 테스트가 통과되었다.
해당 기능도 구현했기 때문에 깃에 올려준다.
게임 결과
최종 우승자 출력
전진된 개수를 보고 가장 많이 전진된 자동차가 최종우승이다.
그래서 forward 값이 제일 큰 것을 가진 것을 가져오고, 해당 값을 가진 것만 filter 하여 출력했고 결과도 잘 나왔다.
getWinner(cars) {
const maxLength = Math.max(...cars.map((car) => car.forward.length));
const longestForwardCars = cars.filter(
(car) => car.forward.length === maxLength,
);
const longestCarNames = longestForwardCars
.map((car) => car.carName)
.join(", ");
MissionUtils.Console.print(`최종 우승자 : ${longestCarNames}`);
}
그래서 코드를 깃에 올렸다.
리팩토링 하기
코드를 보면 상당히 지저분하다..
그래서 시작, 게임, 결과를 나뉘어 따로 파일을 만들었다.
Init.js
해당 파일에서는 자동차 이름을 입력받고, 시도할 횟수를 입력받는 부분을 가져왔다.
경주할 자동차 이름 입력받기 & 예외 처리
경주할 자동차 이름을 입력받고 생성자를 통해 데이터를 저장했었는데
이번 코드에서는 생성자 constructor 를 없애고 그냥 배열에 객체를 넣는 걸로 바꿨다.
왜냐하면 내가 생성자를 잘 모르는 것도 있지만 굳이 써야 할까 생각이 들어서 그냥 배열에 객체를 담는 형식으로 코드를 수정했다...ㅎ
createCarArray(carNameList) {
return carNameList.map((item) => ({ name: item, forward: "" }));
}
그전 코드에서 내가 자동차 이름들을 입력받을 때, 예외 처리를 하지 않았다.
그래서 새롭게 예외 처리를 하는 코드를 추가했다.
각 이름이 5글자 이상이거나 쉼표(,) 사이에 글자가 없어 길이가 0 인 경우 false 를 반환시켜 에러를 처리하였다.
isValidCarNames(carNameList) {
return carNameList.every((name) => name.length <= 5 && name.length > 0);
}
그리고 쉼표(,) 사이에 사용자가 공백을 입력할 수 있는데 이 경우 나는 예외를 처리하지 않고
관대(?)하게 공백 문자를 없애주는 trim을 사용하여 공백을 없애주었다.
const carNameList = name.split(",").map((item) => item.trim());
시도할 횟수 입력받기 & 예외 처리
처음 코드에서 시도할 횟수는 숫자가 아닌 문자열을 입력했을 때 예외 처리를 발생시켰는데,
추가적으로 시도할 횟수가 음수일 가능성이 있다고 판단이 들어 해당 부분도 판별하여 예외 처리하도록 수정했다.
isValidNumberOfTries(tryNum) {
return !Number.isNaN(tryNum) && tryNum > 0;
}
해당 부분이 완료되었기 때문에 깃에 올려주었다.
Race.js
여기서는 전진 조건인 랜덤 값을 입력받아 전진 결과를 출력하는 부분이다.
이전 코드와 크게 달라진 점이 없고 함수를 좀 분리해 주었다.
Result.js
해당 파일은 forward의 길이가 가장 큰 자동차인 우승한 자동차를 출력하는 부분이다.
여기도 이전 코드와 큰 변화가 없다.
테스트 코드 작성 하기
이번 미션에서 추가된 요구사항으로 다음과 같은 내용이 있었다.
Jest를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.
한 번도 테스트 코드를 작성해 본 적이 없었는데 새로운 경험이다..!
게임 초기 세팅 값 예외 테스트
게임 초기 세팅 값인 자동차 이름과 시도 횟수가 제대로 예외 처리되는지 확인하는 코드를 만들었다.
그냥 기존에 있는 테스트 코드 일부를 복붙하고 이것저것 값을 넣어보면서 코드를 완성했다.
이 부분에 대해서는 나중에 공부해 봐야겠다.
자동차 이름이 5자 이상인 경우
먼저 자동차 이름이 5자 이상일 때 예외를 처리하는 테스트 코드를 만들었다.
const carNames = ["jihyun,woo,hi", 2];
코드를 실행했더니 예외가 정상적으로 처리되었다.
쉼표 사이 자동차 이름이 없을 경우
쉼표로 구분한 자동차 이름이 없어 자동차 이름의 길이가 0 이하일 경우 예외 처리를 했기 때문에 이에 대한 테스트 코드도 작성하였다.
const carNames = ["hi,woo,,"];
코드를 실행했더니 예외가 정상적으로 처리되었다.
시도 횟수를 숫자가 아닌 다른 값 입력했을 경우
시도 횟수가 숫자가 아닌 그냥 문자열로 입력했을 때에 대한 테스트 코드를 작성했다.
const carNames = ["hi,woo,jh", "둘"];
이것도 예외가 정상적으로 처리되었다.
게임 초기 세팅 값 예외 처리 코드를 완성했으므로 깃에 올려주었다.
최종 우승자 출력 테스트
이번에는 forward 값에 따라 최종 우승자가 제대로 출력이 되는지 확인하는 테스트 코드를 작성했다.
우승자가 1명일 경우, 2명 이상일 경우 두 가지 나뉘어 테스트 코드를 작성했다.
const RaceResult = new Result();
RaceResult.start([
{ name: "jh", forward: "--" },
{ name: "woo", forward: "--" },
{ name: "hi", forward: "---" },
]);
expect(logSpy).toHaveBeenCalledWith("최종 우승자 : hi");
const RaceResult = new Result();
RaceResult.start([
{ name: "jh", forward: "-" },
{ name: "woo", forward: "--" },
{ name: "hi", forward: "--" },
]);
expect(logSpy).toHaveBeenCalledWith("최종 우승자 : woo, hi");
두 개의 테스트 모두 정상적으로 성공이 되었다.
해당 테스트 코드를 구현했으므로 깃에 올려준다.
랜덤 값에 따른 전진 결과 테스트
다음 테스트는 랜덤값이 4 이상 일 때, 전진이 되는지 확인하는 테스트 코드를 작성했다.
describe("랜덤 값에 따른 전진 결과 테스트", () => {
test("랜덤 값이 4 이상이면 전진", async () => {
mockRandoms([3, 1, 6, 4, 1, 5]);
const logSpy = getLogSpy();
const RaceResult = new Race();
await RaceResult.start(
[
{ name: "jh", forward: "" },
{ name: "woo", forward: "" },
{ name: "hi", forward: "" },
],
"2",
);
expect(logSpy).toHaveBeenCalledWith("최종 우승자 : hi");
});
});
해당 테스트를 실행하면 전진 결과와 최종 우승자가 제대로 찍히는 것을 확인할 수 있다.
이것도 깃에 올려주었다.
게임 시도 횟수 값 예외 테스트
구현 기능 목록을 수정하다가 예외 테스트를 하지 않은 것이 하나 생각났다.
바로 Init.js 파일을 보면, 횟수 값이 음수일 경우 에러 처리를 하였는데 이에 대한 테스트 예외 코드를 작성하지 않았다.
isValidNumberOfTries(tryNum) {
return !Number.isNaN(tryNum) && tryNum > 0;
}
그래서 게임 초기 세팅 값 예외 테스트에 있는 시도 횟수를 숫자가 아닌 값을 입력했을 경우도 같이 가져와서
게임 시도 횟수 값 예외 테스트도 추가하였다.
const carNames = ["둘"];
const carNames = [-4];
이러한 상황도 정상적으로 예외 처리가 되었다.
해당 테스트가 구현됐기 때문에 깃에 올려주었다.
미션 제출 하기
아마 미션 구현이 완성된 거 같아 pull request를 하고 미션을 제출하였다.
제출 후 예제 테스트도 성공하였다
이번주 미션도 끝..!!
후기
무사히 미션이 제출되었고, 이번에는 코드 리뷰도 남겨보았다.
다른 사람들의 코드를 보면서 알아가는 게 많았고, 다음 미션에는 어떻게 작성해야 될 지 도움이 되었다.
[ 2주차 미션 깃허브 주소٩( ᐛ )و ]
'💜 후기 및 활동 > 우아한 테크코스 프리코스' 카테고리의 다른 글
[우아한 테크코스/프리코스] 웹 프론트엔드 6기 4주차 회고록 (0) | 2023.11.21 |
---|---|
[우아한 테크코스/프리코스] 웹 프론트엔드 6기 3주차 회고록 (0) | 2023.11.10 |
[우아한 테크코스/프리코스] 웹 프론트엔드 6기 1주차 회고록 (0) | 2023.10.26 |
FE 개발자가 되고 싶은 짱잼이
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!