[우아한테크코스 7기 FE Lv.2] 11주차 회고

유소정·2025년 4월 26일
6

지금까지 이 블로그는 꽁꽁 숨겨왔다. 하지만 한두 명에게 들키기 시작하더니, 어느새 열 명이 넘는 사람이 알게 됐다. 😂

여기에는 나의 단점도, 장점도, 생각들도 가감 없이 적혀 있다. 그래서 독자를 두지 않았었다. 누가 읽는다고 생각하면 괜히 걱정이 앞서니까. 혹시라도 아무렇지 않게 쓴 글에 나에 대한 오해가 생기면 어쩌나, 그런 생각이 드니까.

그래도 솔직하게 써야겠지. 그러려고 쓰는 글이니까!

🎯 이번주 Action Plan 회고하기

  • 좋은 자료가 있으면 공유한다. 단, 이유를 포함해서 (진행중)
  • 1) 상대방의 의견을 수용할 때 개선할 점이 있더라도, 긍정적으로 들은 부분을 먼저 피드백 해준다. (완료)
    • 그 후, 개선점을 얘기한다. (완료)
  • 2) 개념적인 부분을 설명했을 때, 예시를 함께 얘기한다. (예시를 들자면~) (완료)
  • 3) 상대를 볼 때 어떠한 이유로든 부정적인 마음이 든다면, 상대의 장점을 최소 1개 찾아본다. (완료)

1) 상대방이 의견을 이야기하면, 내가 제대로 이해했는지 먼저 확인하려고 했다. ‘아, 그러면 ~인 거구나?’ 하고 다시 정리해서 물어보고, ‘이건 ~점에서는 좋겠다’처럼 먼저 긍정적인 피드백을 전했다. 그다음에 궁금하거나 고민되는 부분이 있으면 ‘근데 이런 점에서는 문제가 있지 않을까?’ 하고 자연스럽게 이어갔다. 사소하지만, 먼저 긍정적으로 반응하는 게 상대의 의견을 존중한다는 느낌을 줄 수 있어 좋았다.

2) 개념적인 설명을 할 때는 예시를 들어서 설명하려고 노력했다. 최근 우디네 회고 스터디에서도 ‘나는 요즘 의식적으로 어떤 문제를 해결하려는지 명시하고 대화를 하려고 한다’는 얘기를 할 때, 문제에 대한 예시로 이벤트 내에서 setState가 일괄처리된다는 것을 들어 설명했다. 다만 아쉬웠던 점은, 말로만 예시를 들다 보면 설명이 한계에 부딪힐 때가 있다는 것. 조금만 복잡해져도 말로만 전달하기가 어렵다. 앞으로는 노트든 뭐든 들고 다니면서 생각을 그리거나 시각화해서 설명해보면 더 잘 전달할 수 있을 것 같다.

3) 상대의 장점을 보는 연습은 머핀에게 많이 배웠다. 내가 아는 사람 중에 가장 긍정적이고, 타인의 좋은 점을 잘 발견하는 사람이다. 머핀과 함께 있으면 나도 모르게 그 사람의 장점을 보게 된다. 저번에 어떤 사람이 혼자서 10분 넘게 계속 이야기하던 상황이 있었다. 나는 ‘이제 마이크를 넘겨야 하지 않을까’ 하는 생각만 하고 있었는데, 머핀은 그 사람의 ‘용기 내어 마이크를 잡은 모습이 멋지다’고 말했다. 나는 그 사람의 긴 발언만 신경 쓰느라 그 안에 있던 긍정적인 면은 전혀 보지 못했던 것 같다. 부정적인 마음만 쌓이면 상대가 부정적으로만 보일 수도 있는데, 머핀 덕분에 좋은 점도 함께 떠올릴 수 있었다. 앞으로도 누군가에게 그런 마음이 들면 그건 그럴 수 있는 일이고, 잘 처리하되 그 뒤에는 꼭 그 사람의 좋은 점도 다시 바라보려고 한다.

클린코드는 무조건 좋을까?

클린코드는 무조건 좋을까?
클린코드란 뭘까? 유지보수하기 좋은 코드일까? 그럼 무조건 좋을까? 언제나 좋을까?

이를 레벨 2 페이먼츠 미션에서
아래 요구사항을 만족시키기 위한 과정에서 생각하게 되었다.

카드사 식별 번호 구분 규칙
Visa 카드와 Master 카드의 앞 번호의 규칙은 아래로 통일해서 진행한다.

💡 카드 브랜드 구분 로직 (Visa / MasterCard)
Visa: 4로 시작하는 16자리 숫자
MasterCard: 51~55로 시작하는 16자리 숫자

Before

당시에 미션 제출까지 남은 시간이 얼마 없어서 이 구현에 많은 시간을 쓸 수 없었다.
그래서 prefixes 를 하드 코딩했고 시간 내에 구현을 마무리 할 수 있었다.

하지만 아래 방식은 확장 가능한 코드는 아니다.

const CARD_NETWORKS = [
  {
    name: "visa",
    prefixes: ["40", "41", "42", "43", "44", "45", "46", "47", "48", "49"]
  },
  {
    name: "master",
    prefixes: ["51", "52", "53", "54", "55"]
  },
];

  const getCardNetwork = (number: string) => {
    return CARD_NETWORKS.find((network) => network.prefixes.includes(number));
  };

예를 들어, 요구사항이 조금이라도 바뀌어서 다음과 같이 된다면?

  • visa가 4로 시작하는 16자리 숫자가 된다면,
  • visa가 451~455로 시작하는 16자리 숫자가 된다면,
  • master의 51~55로 시작하는 16자리 숫자와 포함하는 수

지금 짠 로직은 prefixes의 범위를 수정해도 master를 찾지 못한다.
(visamaster의 문자열을 포함하는 상태이기 때문이다. 예, 51 ⊂ 451)

CARD_NETWORKS.find((network) => network.prefixes.includes(number)); // master 못 찾음!

After

다시 코드를 Refactiong 했을 땐 다음과 같이 작성했다.

시간복잡도는 O(n)에서 O(1)으로 줄었고,
visa가 451~455로 요구사항이 변경돼도 조건문에 조건만 조금 수정하면 되기에 메인 로직 자체는 문제가 없다.

type CardNetwork = 'visa' | 'master' | 'unknown';

export const getCardNetwork = (number: string): CardNetwork => {
  const prefix = parseInt(number.slice(0, 2), 10);

  if (prefix >= 40 && prefix <= 49) { // 문제없이 visa를 찾음!
    return 'visa';
  }
  if (prefix >= 51 && prefix <= 55) { // 문제없이 master를 찾음!
    return 'master';
  }
  return 'unknown';
};

그럼 항상 클린코드가 좋을까?

사실 나는 Before, After 둘 다 괜찮다고 생각했다.

Before는 확장 가능성이 높지는 않았지만, 미션 제출까지 남은 시간을 고려해 선택한 방법이었다. 요구사항에 맞게 동작한다는 점에서 충분히 의미가 있었다. 코드의 목적은 결국 동작 가능에 있기에, 동작 가능한 코드보다 클린 코드가 우선일 수는 없다고 생각했다. 클린 코드인데 동작하지 않도록 제출하면 그게 무슨 의미가 있을까.

그러면서 추가적으로 든 생각은,
클린 코드만을 지향하다 보면 성급한 기술 도입이나 과도한 추상화로 이어지기 쉬운 것 같다. 예를 들어, 무조건 재사용성을 목적으로 두고 과도하게 컴포넌트를 나누고 추상화 시킨다던가. 클린 코드라는 목적에 빠져 "왜 이렇게 해야하는가"에 대한 이유를 잊게 되는 것 같다.

그래서 항상 "시간 대비 이게 정말 필요할까?", "이 기술이 어떤 가치를 줄 수 있을까?"라는 질문을 먼저 던지는 게 좋을 것 같다.

이번주를 보내며 생기는 궁금증

  • 컴포넌트 네이밍을 지을 때 도메인을 넣게 된다. 작게 쪼개진 컴포넌트에는 또 안 넣게 된다. 예를 들어, Button.tsx. 현재 기준은 딱히 없다. 언제 도메인의 흔적을 지우면 좋을까?
  • 준은 항상 'OOP를 공동체로 바라봐야 한다'라고 말씀하신다. 컴포넌트를 만들 때 나도 이런 관점을 가지고 서로의 책임과 역할을 신경쓰며 설계하고 싶은데 아직 어렵다. 어떻게 하면 좀 더 잘할 수 있을까?

이번주에 들은 칭찬

나의 강점이나 장점을 아는 것도 중요하다고 생각해서
누가 칭찬해주면 일단 적으려고 한다!

같은 칭찬이 여러 번 쌓이면 정말 내 것이고 강점이 아닐까?

  • 얘기하면서 중간중간 정리한다
    • 최근에 ‘얘기하면서 정리를 잘한다’는 말을 들었다. 이야기를 쭉 이어가는 게 아니라, 중간에 잠깐 멈춰서 ‘그러니까 지금까지 얘기한 걸 정리하면’ 하고 다시 한번 흐름을 잡아주는 시간을 갖는다는 점에서였다. 이건 레벨 인터뷰 이후로 꼭 채우고 싶었던 부분이라 그렇게 들으니 잘하고 있는 것 같아 뿌듯했다. 앞으로도 계속 의식적으로 이렇게 대화하고 싶다.
  • ‘왜?’를 계속 던지며 코드를 짠다
    • 미션을 할 때 그냥 코드를 작성하기보다는 ‘왜 이렇게 해야 하지?’ 하고 계속 스스로 질문하며 한다고 한다. 예를 들어, 이벤트로 트리거되는 함수 안에서 setState를 3번 쓰면 리렌더링이 1번 될까, 3번 될까?
      이런 게 문득 궁금해지는 순간이 많다. 코치님이 항상 ‘의도를 가지고 코드를 작성하라’고 했던 것도 있어서,
      기계적으로 코드만 치고 싶지는 않다. 다만 문제는, 이런 고민이 너무 깊어지다 보면 한번 파기 시작한 생각에서 쉽게 못 빠져나올 때가 있다는 것. 지금은 미션을 진행해야 하는데 머릿속이 아까 그 의문에 계속 붙잡혀서 흐름이 끊기곤 한다. 그래서 앞으로는 이런 고민이 들면 일단 시트에 적어두고 나중에 해결하거나, ‘이 고민은 10분까지만’ 하고 시간을 정해서 빠져나오는 연습을 해야겠다.
  • 차분하게, 천천히 말한다
    • ‘말을 차분하게 한다’는 이야기를 들었다. 요즘에는 일부러 더 차분히, 천천히 말하려고 한다.
      특히 기술적인 얘기를 할 때는 일상 대화 속도로 말하면 듣는 사람이 따라가기 어렵다는 걸 느꼈다. 내가 말을 조금 천천히 하면, 상대도 그만큼 이해할 시간을 가질 수 있다. 이 점을 계속 의식하면서 말하려고 노력 중이다.
  • 고치고 싶은 점이 있으면 메타인지를 통해 원인을 잘 파악하고 Action Plan을 잘 세운다. 그리고 세우는 것에서 멈추지 않고 꼭 실행을 하고 다시 회고한다

🍵 마무리...

이번 주는 정신이 없어서 마음이 복잡했다.

레벨 2가 되면서 새로운 데일리조 사람들과 첫 회식도 하고, 리액트 스터디를 시작했고, 영어 레벨 테스트도 봤다. 첫 미션도 진행 중이다. 신경 쓸 것이 이만저만이 아니다.

새로운 일들이 쉴 틈 없이 이어진 한 주였다. 다음 주에는 영어 스터디까지 시작된다.

하하하... 처음은 언제나 쉽지 않다.

🎯 다음주 Action Plan 은?

  • 좋은 자료가 있으면 공유한다. 단, 이유를 포함해서
  • 미션을 진행하기 전에, 이 미션을 주신 출제자의 의도를 생각해본다.
    • 왜 이 미션을 주셨지? 이 미션에서 얻어갈 수 있는 건 뭐지?
  • 미션을 진행할 때, 요구사항을 읽고 (코드 레벨에 들어가기 전에) 책임과 역할을 나눠본다.
profile
기술을 위한 기술이 되지 않도록!

2개의 댓글

comment-user-thumbnail
2025년 5월 1일

안녕하세용~
투두 메이트로 하나씩 투두 리스트를 지우는 것부터 블로그 글까지.... 👍
본인의 성장에 진심이신 분이구나 느꼈어요.

회고 내용에서 공감되는 부분도 많았고, 반대로 개념적인 설명을 하실 때 저는 "와~ 이해가 잘 되도록 설명 잘 하신다." 라고 생각했어요 ㅋㅋㅋㅋㅋ

1개의 답글