옥수수와 식빵 그리고 코딩

1주차 회고 본문

2023/우테코 - 프리코스

1주차 회고

옥식 2023. 10. 26. 00:52

이 사진으로 나의 일주일을 설명할 수 있다.

물론 내 코드는 셋째의 벽돌집처럼 튼튼하진 않지만... 아니? 난 튼튼하다고 믿는다. 비록 class 개념이 부족해서 냅다 한 클래스 안에 죄다 만들어 놓긴 했지만..! 그래도 정상적으로 돌아가지 않는가? 그런 점에서 난 매우 만족한다.

내 코드 기 죽지마! 넌 내가 아는 코드 중에서 제일 멋진 코드니까..!

아무튼 본격적인 회고를 시작해 보겠습니다.

먼저 글 쓰기에 앞서 이 사람은 말이 많고.. 장황하며... 지금 상태가 약간 좋지 않아 더더욱 횡설수설 할 수 있음을 알려드리겠습니다.

 

1. 당찬 시작

비전공자 + 다룰 줄 아는 언어 python, C (사실 다룬다고 하기도 뭣하고 그냥 문법을 아는 정도가 적당하겠군요.)인 내가 여기서는 JavaScript 프론트엔드 지망생?

까짓거 뭐 다른거 있겠어? 하면서 의기양양하게 시작한건 아니구요.. 지원하기 한달 전부터 자스 특훈을 빡시게 하고 덜덜 떨면서 지원서를 제출했던 기억이 나네요..

우테코 선생님... 제 지원서를 받아주시겠어요?

그렇게 프리코스는 다가오고...

2. 차린건 쥐뿔도 없지만

에... 그렇습니다.. 전 아주 너무나 급격히 슬픔을 감출 길이 없어졌어요.

그 이유는... class와 async때문입니다. 

제가 한달동안의 자스 특훈동안 세운 목표가 "무리하게 많은 개념을 익히지 말고 한가지 개념을 확실하게 익히자" 였거든요.

그래서 class와 비동기, 동기함수 개념을 익히던 중에 프리코스를 시작한건데 안그래도 저 개념이 너무 어려워서 머리 싸매고 있던 중에 프리코스에 나와버렸으니.. 아주 곤란한 일이 아닐 수 없었습니다.

3. 못 먹어도 고

그렇다고 어쩌겠어요? 일단 킵고잉. 저는 async이 뭔지는 모르지만, 일단 대충 비동기함수라는 것만 알지만, 일단 코드는 짤 수 있잖아요? 실행이 되든 안되든 모르는 개념 붙잡고 절망하지 말고 일단 설계를 먼저 시작했습니다. 설계 다 하고 그 다음에 개념 찾아보고, 그 다음에 수정하면 되는거니까요.

 

일단 뭘 해야하는지 기능 요구사항이랑 기능 구현목록부터 정리했습니다.

기능 요구 사항

  • 게임 시작 문구 출력
  • 출제자 : 컴퓨터, 전부 다른 숫자 3개 출제
  • 사용자 : 유저, 서로 다른 숫자 3개 입력 단, 형식에 맞지 않는 값을 입력한 경우 throw를 통해 예외 발생 후 애플리케이션 종료 예외 1. 숫자 3개 아님. 예외 2. 숫자 아님 (문자, Null, 입력없음, 등..) 예외 3. 같은 숫자 있음. 예외 4. 1~9 이외의 값.
  • 컴퓨터는 입력받은 수와 출제한 수를 비교하고 힌트를 출력한다. 같은 수 다른 자리 - 볼 같은 수 같은 자리 - 스크라이크 같은 수 전혀 없음 - 낫싱
  • 정답을 맞히면 승리
  • 재시작 / 종료를 여부를 입력받는다. 1입력시 재시작 2입력시 종료 (단, process.exit()사용 금지

기능 구현 목록

  • makeRandomNum() 랜덤 숫자 3자리 생성. @woowacourse/mission-utils의 Random API를 사용하여 구현하였다.
  • checkUserInput(userInput) 사용자로부터 입력받은 값의 유효성을 확인한다. 유효하지 않은 형식일 경우 throw를 통해 Error를 발생시킨다.
  • scoreInArry(comsAnswer, userInput) 컴퓨터가 생성한 랜덤숫자와 사용자가 입력한 값을 비교하여 결과를 배열에 저장한다.
  • scoreInString(comsAnswer, userInput) scoreInArry()에서 받은 결과를 문자열로 바꾼 뒤 출력한다.
  • checkAnswer(answer, result) 정답 여부를 확인. 정답을 맞혔다면 재시작/종료 여부를 묻는 함수로 넘기고, 정답이 아니라면 처음부터 입력을 받는다.
  • startGame(answer) 랜덤값 생성을 제외한 전체 게임 코드가 담긴 함수. 정답이 아닌 경우 랜덤값은 변하지 않고 사용자의 입력값만 변해야 하기 때문에 랜덤값을 뺀 함수를 만들었다.
  • play() 프로그램을 샐행하는 앱.

물론 처음부터 이렇게 깔끔하게 정리한건 아니고.. 이건 제출용으로 깔끔하게 정리한거긴 합니다. ㅎㅎ

 

시작할 때는

  1. 랜덤한 수 생성 
  2. 내가 숫자 입력하게 하는 함수
  3. 내가 입력한 숫자가 유효한지 확인(1~9인지, 3자리인지, 모두 다른지, 모두 숫자인지)
  4. 내 수랑 정답이랑 비교해서 볼, 스트라이크, 낫싱
  5. 종료후 다시할건지 말건지

1-1랜덤 수 생성 : Random.pickNumberInRange()를 활용

2-1사용자 값 입출력 ; Console.readLineAsync, Console.print를 활용

 

이렇게 적어두고 시작했습니다.

4. 그렇게 하나씩

검색, 검색, 검색만이 살길이다. 구글은 내친구요, 내친구는 구글이다. 모르는 개념은 외국 우두부 선생님들의 강의를 듣고(절반은 못 알아듣고) 어찌어찌 하나하나 굴리다보니 점점 길이 뚫리는 것이 느껴졌습니다.

 

조금만 더..!

문제를 풀면서 마주했던 몇가지 어려움과 해결방법을 기록해 보겠습미다.

메서드 공부

- 함수 문법에 대한 기본 지식 부족

makeRandomNum() { // 이 부분이 ;가 필요하다고 오류가 나는데 이유를 모르겠다.
  let answer = ''; // 여기 랜덤 돌린거 넣을거임.
  while(randomNum.size < 3) {
    let pick = MissionUtils.Random.pickNumberInRange(1, 9); // 라이브러리 써서 범위 내에서 수 뽑기.
    if(!answer.includes(pick)){
      answer += pick;
    }
  }
  return answer;
}

-> 이런 형식은 object 내에서만 가능함. (class와 같은)object외에서 선언할 경우 앞에 function을 붙여줘야 함.

 

- Number() 메서드와 parseInt()메서드 차이 이해

Number()은 1n과 같이 문자가 섞여있으면 NaN을 뱉고, parseInt()는 섞여있어도 숫자1을 뱉어줌. 

 

- forEach(element, index, array) 메서드 이해

각 매개변수는 순서대로  배열에서 처리중인 현재 요쇼, 현재 요소의 인덱스,  현재 forEach를 호출한 배열을 의미. 최종 코드에서 사용하진 않았습니다만 굉장히 유용한 메서드라 느꼈습니다. 그리고 어렵다..! 알 듯 말 듯!

 

입력값 정답 비교

노볼 & 노스 → 낫싱 ⭐️

노볼 & 예스 → 스트라이크 개수 표기⭐️ -> 게임 종료

예스볼 & 노스트 → 볼개수 표기

예스볼 & 예스스트 → 볼, 스트라이크 개수 표기(이때만 두개 표기)

5. 아직 멀었다

하지만 저는 아직 async라는 큰 산을 넘지 못했죠..

이거 발음도 어떻게 하는건지 방금 검색해서 알았습니다. 그동안 아신크? 에이에스와이? 무슨 엔씨?이러다가 에이싱크라고 부른다고 하네요~! 멋진 이름 놔두고 이상하게 불러서 미안하다!

그래서 알아온  ⭐️async 함수 쓰는법!!!!!!!!!!!

async function 함수명() {
	await 비동기_처리_메서드_명();
}

 

 

그렇다면? 이제 끝이냐? 그렇지 않습니다. 저도 끝인줄 알았는데요. 제가 생각을 덜 했더라구요.

 

일단 현재 함수는

  1. 랜덤한 수의 세자리 수 정답 생성
  2. 사용자 값 입력받기
    1. 유효성확인
    2. 정답비교
    3. 정답확인 → 정답 아니면 2번으로, 정답이면 3번으로
  3. 재시작 여부 확인 → 1 입력시 1번으로, 2 입력시 종료.

이렇게 돌고 있는데 반복을 어떻게 할것인가! 여기서 또 골머리를 앓았습니다. 

문제를 해결하고 지금 생각해보니 함수들을 반복문 돌려도 되는건데 저 때는 머리가 안 돌아가서 한참을 낑낑 거리다가 2번 소항목을 전부 함수 하나로 묶어서 2-3에서 조건이 맞지 않으면 다시 2번 전체 함수로 돌아오는! 그런 반복을 만들었습니다.

getaguitar(answer) {
    const userInput = Console.readLineAsync('userInput: ');
    if(this.checkUserInput(userInput)) {
      let strike = this.scoreInString(answer, userInput);
      this.checkAnswer(strike);
    }

그리고 결과는 오류났습니다.

 

이유는 잘 모릅니다!

하지만 짧게나마 눈치껏 알아본 것에 따르면 async를 쓰려면 await이 같이 있어야 하는데 async play()안에 들어가는 getaguitar()메서드에는 await이 없다!

->그럼 붙이면 되나? ->오류남

지금 생각해보니 비동기함수로 만들어야 await을 붙일 수 있어서 그런 듯 합니다. 아니라면.. 알려주세요!

 

그럼 어떡하지?

getaguitar()앞에도 async 붙이면? ..? 됐습니다!

 

이 부분의 최종 구현

메인함수

async play() {
    
    let answer = this.makeRandomNum();
    Console.print('random number : ' + answer);
    
    await this.getaguitar(answer);

  }

반복함수를 뭉쳐놓은 겟어기타

async getaguitar(answer) {
    const userInput = await Console.readLineAsync('userInput: ');
    if(this.checkUserInput(userInput)) {
      let strike = this.scoreInString(answer, userInput);
      this.checkAnswer(answer, strike);
    }
  }

정답이면 그만두고 정답이 아니면 겟어기타를 다시 호출하는 함수

checkAnswer(answer, result) { //scoreInString결과값을 매개변수로 받아야 함. (템플릿 문자열 써서 문자열)
    if(result === "3스트라이크") {
     return Console.print("3개의 숫자를 모두 맞히셨습니다! 게임 종료") ;
     //+ this.startNewgame()
    }
    else { 
      //Console.print("재입력받이야...");
      this.getaguitar(answer);
    }
  }

아. 함수이름이 저런거는 머리쓰는데 함수이름까지 고민하는게 너무 힘들어거 그냥.. 더이상 만들 함수도 없겠다 쟤 하나쯤은 아무 이름으로 지어도 될 것 같아 냅다 저런이름이 되었습니다.

 

이렇게 최종 함수까지 끝내고 덩실덩실 끝인가 싶었지만!

6. 뒷정리는 중요한 법

클린코드 정리를 위해 꼬박 하루동안 코드를 정리했습니다.

코드 정리 만만하게 봤는데 정말 쉽지 않더라구요. 그리고 제가 얼마나 지저분하게 코드를 짜왔는지 오우.. 느꼈습니다.

마지막 최종의 제출까지 끝내고 나니 그동안의 긴장이 풀려 몸살이 찾아오더라군요.

 

그래서 뜨끈하게 해물잔뜩 넣은 순두부찌개 먹고 쉬는 시간을 약간 가졌습니다.

이야기가 산으로 가는 기분인데 여기서 줄여야겠네요.

 

아직도 깃은 여전히 어렵고, 다음주 미션도 고난과 역경을 딛고 제출하겠지만 하나 확실한건 프리코스를 시작하고 나서 정말인지 배움의 속도가 빨라졌다는 것입니다.

 

오늘도 힘차게 도전한 나 제법 멋짐. 그리고 이 글을 읽은 여러분도 저만큼 멋짐. 굿

 

요즘 날씨가 제법 쌀쌀한데 다들 감기 걸리지 마시고 건강 조심하세요!

 

 

 

'2023 > 우테코 - 프리코스' 카테고리의 다른 글

지원 완료  (1) 2023.10.18
Comments