[우아한테크코스 2022] 프리코스 1주차 풀어보기

재오·2023년 7월 3일
6
post-thumbnail

네이버 부스트캠프 코딩테스트에서 호되게 당하고 다시 정신을 차리려고 노력을 했다. 처음 보는 시험이기도 했고, 부트캠프가 부스트캠프 하나만 있는 것도 아니고... 여러 길이 있다고 나름 자기 합리화를 하며 스스로를 위로했다. 그리고 무엇보다 부스트캠프 시험을 보면서 몸으로 새삼 느낀 점이 있어서 그것에 대한 보완을 하고자 하였다.

코드를 함수화하는 연습을 하자
이번 부스트캠프에서도 그렇고 문제 요구사항 중에서 코드를 함수화하는 문제들을 최근에 꽤 여러개 접해볼 수 있었다. 항상 프로그래머스 문제를 풀 때에도 마찬가지이고 이번 코딩 테스트에서도 나는 최종 결과만 제출할 수 있는 함수 안에 많은 코드를 때려박았(?)었다. 하지만 문제를 해결하는 능력은 코딩테스트 문제를 양치기해서 그런 것 같고... 실질적인 나의 로직을 짜고 문제를 분석하는 능력은 그대로인 것 같았다. 그래서 앞으로는 코딩테스트 문제를 풀 때에도 마찬가지로 하나의 기능만 하는 함수를 작성하여 문제를 가독성 좋게 해결하고자 한다.

클린 코드에 익숙해지자
클린 코드... 클린 코드... 말로만 많이 접했었다. 코드를 짤 줄도 모르는데 깔끔하게 짜는 코드가 중요할까... 우선 답이라도 도출할 수 있는 코드를 짜자는 것이 나의 첫번째 생각이었다. 하지만 이제는 클린코드에도 신경을 써야할 때가 된 것 같다. 변수를 설정할 때에도 의미있게 설정해야 하고, 함수는 10줄이 넘어가면 안된다는... 이런 말들을 많이 들었었는데 이제 앞으로 코드를 짤 때는 이런 것 외에도 클린 코드를 짜는 것에 대해 공부하고 적용을 할 예정이다.

작년 하반기에 우아한테크코스에 지원한 주변 지인들이 많았는데 우테코 프리코스 기간동안 정말 많은 것을 배울 수 있었다고 한다. 대략 일주일이라는 기간동안 하나의 문제를 해결하는 것인데 단순히 문제의 정답만 찾아내는 것이 아닌 얼마나 코드를 함수와 클래스를 이용하여 잘 짜는가가 관건이라고 하였다. 이번 부스트캠프 코딩테스트를 계기로 2022년도 우테코 프리코스를 통해 클린코드를 짜보는 연습을 하고자 한다.

1주차

1주차 미션은 온보딩이었다. 총 7문제로 구성되어 있었으며 기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항 을 지켜서 문제를 풀면 된다.

Problem1

기능적 요구 사항 리스트를 작성하자
prblem1에서부터는 기능적으로 요구하는 사항들을 모두 리스트화 하였다. 그 이유는 리스트화 한 목록을 갖고 함수를 제작할 것이기 때문이다. 효율적인 코드를 제작하기 위해서는 코드를 함수화하는 것이 중요하기 때문에 하나의 함수에는 반드시 하나의 기능만 할 수 있도록 하여 코드를 구성하였다. 예외처리 마찬가지로 하나의 예외처리를 할 수 있는 함수를 각각 만들어서 최종적으로 이를 포괄할 수 있는 예외 함수에 넣어주었다. 이렇게 세세한 기능까지 모두 함수화를 하면 함수의 길이는 10줄이 넘지 않는다.

function getScore(person) {
  // 코드 생략
}

function calculateScore(score) {
  // 코드 생략
}

function isError(person) {
 // 코드 생략
}

function isPageError(person) {
 // 코드 생략
}

function isPageCountError(person) {
  // 코드 생략
}

function isLeftPageError(person) {
  // 코드 생략
}

function isRightPageError(person) {
  // 코드 생략
}

function getResult(score, pobi, crong) {
  // 코드 생략
}

if else문 보다는 삼항 연산자를 사용하자
if else문을 사용하게 되면 코드가 당연하게 길어질 수밖에 없다. 하지만 삼항연산자를 사용하면 최소 2~3줄인 코드가 1줄로 줄어들 수 있기 때문에 더 간단해진다는 장점이 있다.

Problem2

상수를 적극 활용하자
변경 가능성이 있는 let 보다는 불변한 const를 우선적으로 활용하는 것이 코드 작성에 더 좋다. 또한 예외상황에서는 숫자를 그대로 적는 것 보다는 변수에 할당해서 상수처럼 사용하는 것이 의미를 보다 명확하게 전달하는 방법 중 하나이다. 상수를 선언할 때에는 스크림 스네이크 케이스 를 이용한다.

function isLengthError(string) {
  const LEAST_LENGTH = 1;
  const MAXIMUM_LENGTH = 1000
  if (string.length >= LEAST_LENGTH && string.length <= MAXIMUM_LENGTH) return "Not Error";
  else return "문자의 길이는 1 이상 1000 이하인 문자열이어야 합니다.";
}

Problem3

이중부정 ERROR는 작성하지 말자
기존에는 에러를 마지막에 판단하여 결과값을 출력하였지만 에러를 제일 먼저 확인하여 해당 에러가 발생하지 않는 경우에 결과값을 출력하는 형태로 바꾸었다. 또한 result !== Not ERROR 와 같이 이중부정을 사용하면 괜히 헷갈릴 수 있기 때문에 이는 최대한 피해서 코드를 짜는 것이 좋다.

function problem3(number) {
  const result = clapCount(number);
  const error = isError(number);
  if (error === "Not Error") return result;
}

Problem4

String.fromCharCode()을 활용한다.
기존 코딩테스트 문제를 풀 때에는 알파벳이라고 해봤자 26개가 담긴 배열을 생성하면 되는 문제여서 배열을 미리 생성했었다. 하지만 Array.from() 메서드를 이용하면 동적으로 배열을 생성할 수 있다. 배열의 길이와 배열 값, 배열의 인덱스를 받아온다. String.fromCharCode() 은 숫자를 문자로 변환하는 역할을 한다.

const upperAlphabet = Array.from({ length: 26 }, (value, index) =>
    String.fromCharCode(index + 65)
  );

Problem5

fill()을 활용한다.
fill() 메서드를 이용하면 배열의 초기값을 지정할 수 있다. new Array(배열의 길이) 로 배열을 하나 생성 후에 fill 메서드를 이용하여 인자로 값을 넣어주면 해당 값으로 배열이 초기화 된 상태가 된다.

const BILL_UNIT_LIST = [50000, 10000, 5000, 1000, 500, 100, 50, 10, 1];
const BILL_LENGTH = BILL_UNIT_LIST.length;
let billUnitCount = new Array(BILL_LENGTH).fill(0);

Problem6

new Set을 활용한다.
Set을 활용한다면 중복되는 값을 제거할 수 있다. 수학의 개념으로 이해한다면 집합과 같다. 반복문을 통해 중복되는 값을 제거할 수는 있지만 시간복잡도에서 조금 우위를 갖고 코드를 간결하게 작성하고 싶다면 Set을 사용하는 것을 적극 추천한다. 하지만 Set은 일반 배열과는 다르게 접근해야 한다. 대괄호 표기법을 사용하거나 점 표기법을 사용했던 것과는 다르게 Set에서는 값을 추가할 때에는 add를, 제거할 때에는 delete를 사용한다.

  let result = [];
  const userNumber = forms.length;
  let email_set = new Set();

Problem7

사실 이 문제는 문제 자체를 이해하지 못했다... 왜 결과값이 저렇게 나오는걸까...저 고민만 1시간동안 했다. 여기서 문제를 얼마나 빨리 이해하느냐도 상당히 중요한 문제인 것 같았다. 최종 코딩테스트까지 간다면 5시간동안 이것보다 더 어려운 문제를 풀어야 하는데 이해하는 데에만 1시간 이상을 투자한다면 상당히 난감하다.

객체 사용을 지향한다.
위와 같이 문자열과 문자열에 해당되는 값을 비교할 때에는 객체가 훨씬 유용하다. 배열을 두개로 만들어버리는 순간 후에 두개의 배열을 비교하는 관정에서 시간초과가 발생할 확률이 훨씬 높아지기 때문이다. 객체를 사용하게 되면 해당 문자열이 등장할 때 값을 바로바로 변환해줄 수 있어 훨씬 코드도 간결해지고 나중에 원하는 결과값을 도출해낼 때에도 보다 짧은 코드로 해결이 가능해진다.

let usersObj = {};
if(friendPlace !== -1 && friends[j][1 - friendPlace] !== user) {
	usersObj[friends[j][1 - friendPlace]] += 10;
}
let sorted = Object.entries(usersObj).sort((a, b) => b[1] - a[1]); // 배열을 정렬하고
let result = [];

// value 값이 큰 순서대로 배열에 넣는 작업... 배열을 이용하면 10줄 이상 나오는 코드이다
for (let element of sorted) {
	if (element[1] !== 0) result.push(element[0]);
}

1주차 회고

실제로 우아한테크코스 과정을 참여한 것이 아닌 작년의 기출문제를 지금 풀어보는 것이어서 긴장감이 덜하였다. 무엇보다 블로그나 깃허브에 이미 답안이 작성되어있는 코드도 많기 때문에 내가 막히는 부분이 있으면 찾아볼 수도 있다. 하지만 개인적인 실력 향상을 위해서 그러한 해답은 과감하게 버리고 스스로 작성할 수 있는 힘을 길러야하는 것 같다.

평상시 코딩테스트 문제를 풀고나면 맞으면 두번다시 보지도 않았다. 하지만 우테코 프리코스 문제는 내가 작성한 코드에 대해서 복기해보는 과정이 너무 의미있었던 것 같다. 실제 문제 난이도는 프로그래머스 lv1정도이지만 최대한 클린코드를 작성하기 위한 리팩토링 과정에 많은 힘을 쏟게 되었고 그 과정에서 스스로 많이 성장함을 느낄 수 있었다. 있는 힘껏 클린 코드를 이용하여 문제를 풀었다면 마지막 과정으로는 작년에 제출하신 다른 분들의 코드를 참고하여 그분들이 작성한 코드에서 배울 점에 대해 찾고자 하였다. 긴 시간이 필요했지만 의미있는 시간이었다.

2주차부터는 1주차 온보딩처럼 1일에 1문제가 아닌 정말 많은 기능을 담고있는 하나의 문제에 대해서 7일동안 풀어야 한다고 들었다. 더 좋은 코드를 짜기 위해서 노력할 것이고 기대가 되는 일주일의 시작이다.

profile
블로그 이전했습니다

3개의 댓글

comment-user-thumbnail
2023년 7월 4일

잘 보구갑니다! 응원해요😊

1개의 답글
comment-user-thumbnail
2023년 7월 22일

화이팅입니다 🔥

답글 달기