중간고사와 프리코스 1주차가 마무리되고, 10월 22일 오후 3시부터 프리코스 2주차가 시작되었다. 사실 화요일부터 바로 2주차 프리코스를 시작하지는 않았고, 프리코스 커뮤니티(디스코드)에서 다른분들의 PR을 보며 리뷰를 하고, 또 내가 1주차 미션 PR 링크를 올려서 리뷰를 받았다.
1. 1주차 피드백
정말 감사하게도 네 분께서 코드 리뷰를 해주셨다. 리뷰 중 기억해두면 좋을 내용들을 요약해보자면
- 변경될 일이 없는 상수값(기본 구분자)는 클래스의 정적 속성이나 상수 변수로 분리하고, 커스텀 구분자만 별도로 관리할 것이 명확
- 추출된 숫자 배열은 메서드 내부의 let으로 둬서 더 명확하게 표현하는 것이 좋을 듯
- calculateSum 메서드는 sum만 구현하고 다른 로직은 코드 분리하기
- 3번과 비슷한 맥락으로, validateNumber는 숫자 유효성만 확인하고, splitAndExtractNumbers는 단순히 분리된 숫자를 배열로 만들고, 다른 로직은 코드 분리하기
- 조건을 변수로 네이밍을 해서 조건절에 변수를 사용하기
- 출력 방법을 분리했으니 입력 방법도 분리하기
- str.trim().length === 0; → !!!str.trim()으로도 표현 가능( !!는 Boolean()과 동일, !!!는 !!의 부정)
단일 책임 원칙에 따라 하나의 메서드가 하나의 기능만 동작하도록 구현하는 부분이 조금은 미흡하지 않았나 하는 생각이 든다. 또한 조건을 변수로 네이밍하는 것도 괜찮은 방법인 것 같다는 생각이 들었다.
위 피드백들을 복기하며, 프리코스 2주차를 시작했다.
2. 기능 요구사항
초간단 자동차 경주 게임을 구현한다.
- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
- 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
- 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
- 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
- 사용자가 잘못된 값을 입력할 경우 "[ERROR]"로 시작하는 메시지와 함께 Error를 발생시킨 후 애플리케이션은 종료되어야 한다.
3. 설계
1주차 미션 때에는 모든 로직을 App.js에 담았었다. (사실 파일들을 분리해도 되는건지에 대한 확신이 들지를 않아서 그랬는데, 1주차 종료 후 다른 분들의 코드를 보니 역할에 맞게 코드를 분리해놓았었다)
이번에는 구조를 설계하고 폴더와 파일들을 그 구조에 맞게 분리를 해서 코드의 가독성을 늘릴 계획이다.
이번 미션에서는 어떤 구조를 적용할까 고민을 해봤는데, MVC 패턴을 적용하면 어떨까하는 생각이 들었다.
보통 프론트엔드 프로젝트를 진행할 때에는 MVC 패턴이 아닌 MVVM 패턴으로 구현하는데, 이번 미션은 실시간 UI 업데이트가 필요하지 않으므로 ViewModel이 필요가 아닌 것 같아 MVC 패턴을 사용하는 것이 더 좋을 것 같았다.
https://blog.naver.com/designerkhs/223522670304
(MVC 패턴과 MVVM 패턴 관련해서 위 링크의 글을 참고했다)
MVC 패턴을 사용해서 폴더 구조를 설계해보았다.
📦src
┣ 📂controller
┃ ┗ 📜gameController.js
┣ 📂models
┃ ┣ 📜car.js
┃ ┗ 📜racingGame.js
┣ 📂utils
┃ ┣ 📜constants.js
┃ ┣ 📜random.js
┃ ┗ 📜validator.js
┣ 📂views
┃ ┣ 📜inputView.js
┃ ┗ 📜outputView.js
┣ 📜App.js
┗ 📜index.js
각 파일마다 무슨 역할을 하는지 README.md에 작성했다.
📋 구현할 기능 목록
### 🗂 Model
car.js (자동차 데이터 관리)
- [x] 자동차 상태 객체 생성
- [x] 자동차 상태 업데이트
racingGame.js (게임 상태 관리)
- [x] 게임 상태 객체 생성
- [x] 게임 상태 업데이트
- [x] 우승자(들) 찾기
- [x] 게임 종료 상태 확인
### 👀 View
inputView.js (사용자 입력 처리)
- [x] 자동차 이름 입력 받기
- [x] 입력받은 자동차 이름을 쉼표(,) 기준으로 구분
- [x] 시도 횟수 입력 받기
outputView.js (게임 상태 출력)
- [x] 현재 라운드 상태 출력
- [x] 최종 우승자 출력
- [x] 에러 메시지 출력
### 🎮 Controller
gameController.js (게임 로직 제어)
- [x] 자동차 이름 입력받기 (InputView 활용)
- [x] 시도 횟수 입력 받기 (InputView 활용)
- [x] 참가자 정보 검증하기 (Validator 활용)
- [x] 레이싱 게임 객체 생성하기 (RacingGame 활용)
- [x] 자동차들의 이동 처리하기 (RacingGame 활용)
- [x] 라운드 진행 상태 보여주기 (OutputView 활용)
- [x] 우승자 찾기 (RacingGame 활용)
- [x] 우승자 발표하기 (OutputView 활용)
### 🛠 Utils
validator.js (입력값 검증)
🏷️ 자동차 이름 검증
- [x] 최소 1대 이상의 자동차가 있는지 확인
- [x] 이름이 빈 문자열이나 공백인지 확인
- [x] 이름이 5자 이하인지 확인
- [x] 중복된 이름이 있는지 확인
🔢 시도 횟수 검증
- [x] 빈 값이나 공백이 입력되었는지 확인
- [x] 숫자가 아닌 값이 입력되었는지 확인
- [x] 음수가 입력되었는지 확인
- [x] 0이 입력되었는지 확인
- [x] 소수가 입력되었는지 확인
- [x] 입력된 값이 오버플로우를 발생시키는지 확인
random.js (난수 생성)
- [x] 난수 생성
- MissionUtils.Random.pickNumberInRange 사용
constants.js (상수 정의)
- [x] 에러 메시지 상수
- [x] 입력 메시지 상수
- [x] 출력 메시지 상수
- [x] 자동차 이름 검증을 위한 테스트 케이스 상수
- [x] 시도 횟수 검증을 위한 테스트 케이스 상수
### 🎯 Application
App.js (애플리케이션 진입점)
- [x] 게임의 시작점으로서 GameController 초기화 및 실행
4. 구현
4-1. Model
먼저 model을 생성했다.
class Car {
name;
position;
constructor(name) {
this.name = name;
this.position = 0;
}
move(number) {
if (number >= 4) {
this.position += 1;
}
}
getPosition() {
return this.position;
}
getName() {
return this.name;
}
}
export default Car;
먼저 car.js에서 Car 클래스를 생성했는데, name, position 필드와 생성자를 만들었고, move 메서드와 getter 함수를 생성했다. 코드를 작성하면서 학교에서 자바 프로그래밍을 배웠을 때의 기억이 떠올랐다. 자바스크립트에서 이렇게 객체 지향적인 코드를 작성해도 될까? 하는 의문이 살짝 들었었지만, 실시간 UI 업데이트가 없이 MVC 모델로 구현하기로 한 만큼 이렇게 구현해도 괜찮다는 생각이 들어 계속 진행했다.
4-2. View
view는 inputView.js와 outputView.js로 구성되어 있었는데, outputView.js에는 포매팅하는 메서드와 출력 메서드를 구현했다.
import { Console } from '@woowacourse/mission-utils';
import { OUTPUT_MESSAGES } from '../utils/constants.js';
const OutputView = {
printGameStart() {
Console.print(OUTPUT_MESSAGES.GAME_START);
},
formatCarStatus(car) {
const position = '-'.repeat(car.getPosition());
return `${car.getName()} : ${position}`;
},
printRoundStatus(cars) {
cars.forEach((car) => {
Console.print(this.formatCarStatus(car));
});
Console.print('');
},
(...)
4-3. Validator
Validator에는 검증하는 메서드들이 있다. 밑의 코드에서 확인할 수 있다시피 특정한 기능에 대한 validate 메서드가 있고, 이 기능들을 한번에 실행시켜주는 통합 메서드(validateCarNames)를 만들었다. 이 메서드는 Controller에서 실행된다.
import OutputView from '../views/outputView.js';
import { ERROR_MESSAGES } from './constants.js';
const Validator = {
validateCarCount(carNames) {
if (!carNames || carNames.length === 0) {
OutputView.throwError(ERROR_MESSAGES.NO_CARS);
}
},
validateEmptyNames(carNames) {
const hasEmptyName = carNames.some((name) => name.trim().length === 0);
if (hasEmptyName) {
OutputView.throwError(ERROR_MESSAGES.EMPTY_NAME);
}
},
validateNameLength(carNames) {
const hasLongName = carNames.some((name) => name.length > 5);
if (hasLongName) {
OutputView.throwError(ERROR_MESSAGES.NAME_TOO_LONG);
}
},
validateDuplicateNames(carNames) {
const uniqueNames = new Set(carNames);
if (uniqueNames.size !== carNames.length) {
OutputView.throwError(ERROR_MESSAGES.DUPLICATE_NAME);
}
},
validateCarNames(carNames) {
this.validateCarCount(carNames);
this.validateEmptyNames(carNames);
this.validateNameLength(carNames);
this.validateDuplicateNames(carNames);
},
(...)
4-4. Controller
Controller는 지금까지 View, Model, Validator에서 만든 메서드들을 가져와서 start 메서드에 적용을 해주었다. 이 start 메서드는 App.js의 run에서 실행된다.
import RacingGame from '../models/racingGame.js';
import Validator from '../utils/validator.js';
import InputView from '../views/inputView.js';
import OutputView from '../views/outputView.js';
class GameController {
carNames;
gameRounds;
racingGame;
async start() {
await this.readCarNames();
this.validateCarNames();
await this.readGameRounds();
this.validateGameRounds();
this.createRacingGame();
OutputView.printGameStart();
while (!this.racingGame.isGameFinished()) {
this.playOneRound();
}
this.announceWinners();
}
async readCarNames() {
this.carNames = await InputView.readCarNames();
}
validateCarNames() {
Validator.validateCarNames(this.carNames);
}
async readGameRounds() {
this.gameRounds = await InputView.readGameRounds();
}
validateGameRounds() {
Validator.validateGameRounds(this.gameRounds);
}
createRacingGame() {
this.racingGame = new RacingGame(this.carNames, this.gameRounds);
}
playOneRound() {
this.racingGame.playOneRound();
this.printRoundStatus();
}
printRoundStatus() {
const cars = this.racingGame.getCars();
OutputView.printRoundStatus(cars);
}
(...)
5. 테스트 진행
ApplicationTest.js에서 코드를 수정해서 검증하고 싶은 부분에 대한 테스트를 진행했다.
## 🧪 테스트 목록
### 자동차 이름 검증 테스트
- [x] 자동차 이름이 빈 문자열인 경우 에러를 발생 (["pobi", ""])
- [x] 자동차 이름이 공백인 경우 에러를 발생 (["pobi", " "])
- [x] 자동차 이름이 5자를 초과하는 경우 에러 발생 (["pobi", "abcdef"])
- [x] 중복된 자동차 이름이 있는 경우 에러 발생 (["pobi", "jason", "pobi"])
### 시도 횟수 검증 테스트
- [x] 시도 횟수가 빈 값이나 공백이 입력된 경우 에러 발생 (" ")
- [x] 시도 횟수가 숫자가 아닌 값이 입력된 경우 에러 발생 ("abc")
- [x] 시도 횟수가 음수가 입력된 경우 에러 발생 ("-1")
- [x] 시도 횟수가 0이 입력된 경우 에러 발생 ("0")
- [x] 시도 횟수가 소수가 입력된 경우 에러 발생("1.5")
- [x] 시도 횟수가 오버플로우를 발생시키는 값이 입력된 경우 에러 발생 ("Number.MAX_SAFE_INTEGER + 1")
constants.js에서 테스트 케이스 상수들을 입력했다.
export const CAR_NAME_TEST_CASES = {
EMPTY_NAME: {
input: ['pobi', ''],
errorMessage: `${OUTPUT_MESSAGES.ERROR_PREFIX} ${ERROR_MESSAGES.EMPTY_NAME}`,
},
EMPTY_NAME_WITH_SPACE: {
input: ['pobi', ' '],
errorMessage: `${OUTPUT_MESSAGES.ERROR_PREFIX} ${ERROR_MESSAGES.EMPTY_NAME}`,
},
NAME_TOO_LONG: {
input: ['pobi', 'abcdef'],
errorMessage: `${OUTPUT_MESSAGES.ERROR_PREFIX} ${ERROR_MESSAGES.NAME_TOO_LONG}`,
},
DUPLICATE_NAME: {
input: ['pobi', 'jason', 'pobi'],
errorMessage: `${OUTPUT_MESSAGES.ERROR_PREFIX} ${ERROR_MESSAGES.DUPLICATE_NAME}`,
},
VALID_NAMES: {
input: ['pobi', 'woni', 'jun'],
expected: ['pobi', 'woni', 'jun'],
},
};
(...)
그리고 ApplicationTest.js에서 위 상수들과 test.each를 활용해 테스트 케이스 상수들의 루프를 돌면서 테스트를 진행하였고, 다행히도 테스트들은 무사히 통과되었다.
6. 리팩토링
다음과 같은 리팩토링이 진행되었다.
## ♻️ 리팩토링 목록
- outputView.js에서 printRoundStatus 메서드를 단일 책임 원칙에 따라 두 개의 메서드로 분리
- validator.js에서 기존에 하드코딩되었던 에러 메시지들을 constants.js의 ERROR_MESSAGES로 대체
- inputView.js에서 기존에 하드코딩되었던 입력 메시지들을 constants.js의 INPUT_MESSAGES로 대체
- outputView.js에서 기존에 하드코딩되었던 입력 메시지들을 constants.js의 OUTPUT_MESSAGES로 대체
- constants.js에서 테스트 케이스 상수 CAR_NAME_TEST_CASES, GAME_ROUNDS_TEXT_CASES의 이름들을 ERROR_MESSAGES 값들과 일치 시켜서 혼란을 방지
- constants.js에서 실제 구현 가능한 테스트 케이스만 남도록 NO_CARS 상수 삭제
- constants.js에서 불필요한 상수 제거 및 TEST_DESCRIPTIONS를 test.each 사용에 적합하게 사용
- ApplicationTest.js에서 테스트 설명을 상수들을 활용
- ApplicationTest.js에서자동차 이름 검증과 시도 횟수 검증을 test.each를 활용해서 코드 가독성 향상
대부분이 constants.js에 작성되있는 상수들을 활용하여 하드코딩되었던 메시지들을 대체한 내용이다. 다른 분들의 1주차 코드를 확인했을 때상수를 특정 파일에 저장해놓고 불러오는 방식이 마음에 들었었고, 이번 2주차 때 활용하기로 했다. 이 때 상수명이 명확해야 가독성이 좋으므로 그 부분에 유의했다.
export const ERROR_MESSAGES = {
EMPTY_NAME: '자동차 이름은 빈 문자열이나 공백일 수 없습니다.',
NAME_TOO_LONG: '자동차 이름은 5자 이하만 가능합니다.',
DUPLICATE_NAME: '자동차 이름은 중복될 수 없습니다.',
EMPTY_ROUNDS: '시도 횟수는 빈 값이나 공백일 수 없습니다.',
NOT_A_NUMBER: '시도 횟수는 숫자여야 합니다.',
NEGATIVE_NUMBER: '시도 횟수는 음수일 수 없습니다.',
ZERO_ROUNDS: '시도 횟수는 0일 수 없습니다.',
NOT_INTEGER: '시도 횟수는 정수여야 합니다.',
OVERFLOW: `시도 횟수는 ${Number.MAX_SAFE_INTEGER}보다 작거나 같아야 합니다.`,
};
export const INPUT_MESSAGES = {
CAR_NAMES: '경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\\n',
GAME_ROUNDS: '시도할 횟수는 몇 회인가요?\\n',
};
(...)
7. 배운 점
7-1. some()의 활용
validateEmptyNames(carNames) {
const hasEmptyName = carNames.some((name) => name.trim().length === 0);
if (hasEmptyName) {
OutputView.throwError(ERROR_MESSAGES.EMPTY_NAME);
}
},
검증 메서드를 생성할 때 some()을 많이 사용했다.
some()은 배열의 요소 중 하나라도 주어진 조건을 만족하면 true를 반환하고, 모든 요소가 조건을 만족하지 않으면 false를 반환하는 배열 메서드이다.
7-2. MVC 패턴
지금까지 웹 프론트엔드 개발을 하면서 MVC 패턴을 활용할 기회가 없었다. MVC 패턴에 대해 들어본 적은 있지만 확실히 이해를 하지는 못했었는데, 이번 기회를 통해서 MVC 패턴에 대해서(Controller는 무슨 역할을 하는 지 등…) 알 수 있었다.
7-3. Jest 사용법
2주차 프리코스 때 Jest를 사용해보았다. describe와 test를 사용하여 테스트를 구조화하고, expect와 toThrow 등의 matcher를 활용하여 다양한 테스트 케이스를 작성하는 방법을 배웠다. 나중에 개발을 진행할 때 Jest를 활용하면 미처 잡아내지 못한 에러에 대한 대응을 할 수 있기 때문에 이 유용한 도구의 사용법을 더 익혀놓아야겠다는 다짐을 했다.
7-4. getter 메서드
이번 프리코스를 진행하면서 getter 메서드를 사용했는데, Car 클래스에서 직접적으로 position이나 name 속성에 접근하지 않고, getPosition()과 getName() 메서드를 통해 접근하도록 구현했다. 이러한 캡슐화를 통해 객체의 내부 상태를 보호하고, 객체의 상태를 안전하게 관리할 수 있다는 점을 알게 되었고, 다음에 클래스 기반으로 또 구현을 할 일이 생기면 getter 메서드를 활용해야겠다는 생각을 했다.
8. 후기
아래 질문에 대한 회고를 진행하라는 조건이 있었기에, 각 질문에 대해 깊게 생각해보고 답변을 작성하였다.
8-1. 지원서에 작성한 목표를 얼마나 달성하고 있다고 생각하는지에 대한 질문
지원서 목표에 작성 했던 목표를 크게 2가지로 나눈다면 바로 ‘메타인지에 대한 의식’과 ‘프리코스를 해치우지 말자’입니다. 프리코스 1,2주차를 진행하며 개발을 진행하기 전에 먼저 구현할 기능들이 무엇인지 생각하고 설계를 진행했습니다. README.md에 작성된 기능 옆에 체크박스를 놓고 해당 기능이 구현될 때마다 체크박스를 채웠습니다. 기능들을 하나씩 구현하면서 제가 목표했던 바에 몇 퍼센트 정도 다가갔는지 확인할 수 있었습니다. 또 학습적인 측면에서 Javascript에 대해 제가 얼마나 부족했었는지 알게 되는 계기가 되었습니다. class 내에서 메서드를 생성하려면 명시적으로 function을 작성하면 안된다는 기초적인 사실도 모르고 있었고, 알고 있었다고 생각했던 reduce나 some의 사용법 또한 헷갈려했습니다. 돌이켜보면 react나 새로운 라이브러리(프레임워크)를 사용해보는 것에 빠진 나머지 기초적인 Javascript 지식들에 대한 복기가 부족했던 것 같습니다. 프리코스를 통해 배운 점들을 글로 작성하고 있습니다. 프리코스가 끝나고 스스로를 되돌아봤을 때 정말 많이 배워갔다라는 소감을 남기고 싶습니다.
1주차 프리코스를 진행할 때에는 중간고사 기간과 겹쳐서 프리코스에 몰입하기 어려운 환경이었습니다. 저 스스로 시험 공부와 프리코스에 투자하는 시간을 1대1로 분산하기로 다짐했었고, 다행히 이 다짐을 지킬 수 있었습니다. 미션을 마무리하는데에만 집중하지 않고 지금 제대로 된 방향으로 나아가고 있나 시간을 가지고 생각을 해보았습니다. 사실 가장 어려웠던 점은 마음 속의 조급함을 다스리는 일이었습니다. 시험 공부를 하고 있을 때에는 프리코스가, 프리코스를 하고 있을 때에는 시험 공부가 떠올랐습니다. 이런 생각들은 막상 일에 몰입하고 있을 때에는 가라앉는다는 것을 알고 있기에 몰입을 함으로써 생각들이 저를 방해하지 않게 만들었습니다.
중간고사가 끝난 2주차 프리코스부터는 프리코스에 시간 투자를 많이 할 수 있었습니다. 먼저 디스코드의 프리코스 커뮤니티를 통하여 다른 분들의 코드를 리뷰하고, 제 코드의 리뷰를 받을 수 있었습니다. 리뷰를 하며, 또 피드백을 받으며 많은 점을 배워갈 수 있었습니다. 프리코스를 진행하는데 서로의 코드를 리뷰하는 것은 꼭 필요한 과정은 아니지만, 저의 코드를 실력이 우수하신 다른 분들께 검증받을 수 있는 기회는 흔치 않다고 생각했기에 즐겁게 진행할 수 있었습니다.
2주차 프리코스까지는 ‘프리코스를 해치우지 말자’라는 목표를 잘 지키고 있습니다. 현재 프리코스는 제 일상의 많은 부분을 차지하고 있으며 이 면적은 프리코스가 끝날 때까지 줄어들지 않을 것입니다. 남은 프리코스도 몰입하며 더욱 성장하겠습니다.
8-2. 지원서에 작성한 목표를 변경해야 한다고 생각하는지에 대한 질문
목표를 변경하고 싶다기보다는 목표를 추가하고 싶습니다. 제가 추가하고 싶은 목표는 바로 ‘자바스크립트 문법을 자연스럽게 틀리지 않고 입력하기’입니다. 프리코스를 진행하며 이론적으로 제가 알고 있는 내용들을 코드로 적용시키는 일이 쉬운 일이 아님을 느끼고 있습니다. AI를 활용하거나 검색을 통하여 문법을 확인하는 행동이 나쁜 것은 아니지만, 제가 구현하고자 하는 바를 머릿 속에서 생각한 그대로 바로 코드로 작성할 수 있다면 효율성이 많이 상승할 것입니다. 남은 프리코스를 진행하며 많은 코드를 작성하게 될 텐데, 코드를 작성하며 자바스크립트 문법을 손에 익히겠습니다.
8-3. 프리코스를 진행하면서 눈에 띄는 변화나 깨달은 점이 있는지에 대한 질문
일단 프리코스를 진행하면서 가장 크게 바뀐 것은 커밋 방식입니다. 프리코스 진행 전까지는 커밋을 본문 없이 제목만 작성했었습니다. 기능별로 커밋을 하지도 않았고 PR을 하기 전이나 컴퓨터를 덮기 전에 부랴부랴 커밋을 진행했었습니다. 하지만 이번에 AngularJS commit convention의 사용법을 익히고 적용하기 시작하면서, 저의 커밋은 구체적으로 작성되었으며 가독성도 향상될 수 있었습니다. 이번에 배운 커밋 컨벤션을 프리코스에서 계속 사용할 것이며, 또한 다른 프로젝트 개발을 진행할 때에도 이 커밋 컨벤션을 사용하려 합니다.
또한 단일 책임 원칙을 배우고, 이 원칙에 따라 메서드를 분할했습니다. 이렇게 개발을 진행하니 코드가 이해하기가 편하고 메서드를 다른 곳에서 활용하기도 편했습니다. 사실 다른 프로젝트도 같이 진행하고 있어서 제가 작성했던 코드를 다시 확인을 할 일이 있었는데, 제가 얼마나 코드를 잘 못 짜고 있었는지 보자마자 깨달았습니다. 원칙을 지키며 코딩을 해야함을 느끼며, 해당 코드들을 리팩토링해야겠다는 다짐을 하게 되었습니다.
2주차까지 프리코스를 진행하며 계속 와닿은 점은 바로 일관성이 있게, 가독성이 있는 코딩을 해야한다는 점이었습니다. 다른 사람이 코드를 읽었을 때 이 코드가 무슨 의미를 지니고 있는지 확인할 수 있어야하며, 다른 곳에 있는 코드들도 같은 방식으로 입력이 되어 보는 사람들로 하여금 헷갈리지 않게 만들어야합니다. 기존에 코딩을 하던 습관들이 남아있어 아직은 일관성 있게 코딩을 하지 못하고 서투릅니다. 남은 2주 동안 계속 깔끔하게 코딩을 하려고 훈련을 해가며 클린한 코딩을 체화해 나가고 싶습니다.
'우아한테크코스(프리코스)' 카테고리의 다른 글
전혀 예상치 못했던, 우아한테크코스 7기 최종 코딩테스트 후기 (3) | 2024.12.18 |
---|---|
우아한테크코스 7기 프리코스 최종 회고 (웹 프론트엔드) (7) | 2024.11.16 |
우아한테크코스 7기 프리코스 1주차 회고 (웹 프론트엔드) (0) | 2024.10.20 |