[우아한테크코스] Level 1 :: 4. 자판기

레벨 1 마지막 미션..! 과 Level 1 전반에 대한 회고


🧃 자판기

마지막 미션 자판기는 여러가지로 가장 고민이 많았던 미션이었다. 지난 미션 동안은 그다지 고민하지 않았던 설계면에서도 많은 고민이 생겼고, 페어 프로그래밍을 할 때 어떻게 해야할 지에 대한 고민도 많이 했다. 또 처음 접하는 TS나 인증과 인가 구현... 등으로 시간도 오래 걸리고 꽤 힘들었던 미션이었다.

그래도 그 과정에서 새로운 생각들을 얻었으니 만족 🥰


👩‍💻 페어 프로그래밍

요번 페어 프로그래밍은 이전과는 다른 면에서 많이 배울 수 있었다.

우선 나보다 많이 알고 있는 페어 덕분에 새로 접한 것들이 많았다. scss를 처음 써보면서 그냥 css를 쓰는 것보다 편하기도 했고, 웹 폰트를 추가해보기도 했다.
안 익숙해서 어색하긴 했지만, 페어랑 안 써봤으면 나는 적용 안 했을 부분들이라 덕분에 접해볼 수 있어서 좋았다. 외에 내가 잘 모르는 부분들을 질문했을 때, 찬찬히 잘 설명해주어서 페어의 생각을 이해하기에 수월했다. 👍

가장 크게 얻은 부분은, 설계와 페어 프로그래밍에서의 나의 태도를 다시 돌아볼 수 있었다는 점이었다.

  1. 먼저 내가 그동안 너무 설계에 대한 생각이 없었던 것은 아니었는지 다시 돌아볼 수 있었다. 그간 설계에 대해서는 UI와 비즈니스 로직만 분리하는 정도만 고민했고, 구현하면서 필요성을 느꼈을 때 새로운 구조를 추가하고 변경했다. 그러나 페어는 (지금까지 내가 해왔던 것보다) 초기에 확장성을 고려한 설계를 잡아두는 편이었다. 덕분에 페어의 의견을 들으면서 혼자였으면 생각해보지 않았을 방식과 구조를 경험해볼 수 있었고, 동시에 확장성과 오버 엔지니어링 사이에서 조금 혼란스럽기도 했다. 어떤 페어를 만나냐에 따라 확실히 설계의 수준이 달라진다는 걸 제대로 느꼈다. 결과적으로는 내가 그동안 확장성에 대한 고려없이 설계하지 않았는지 고민해볼 수 있었다. 🤔

  2. 거기서 이어져서 두번째로, '페어와 의견이 다를 때 어디까지 내 의견을 주장해야하는가'에 대한 고민도 생겼다. 나는 페어가 제안한 방식을 내가 아직 경험해보지 못 했다면, 미션은 진행해야하니 내 의견을 전달하되 페어의 의견을 따르면서 경험해보는 것도 좋겠다고 생각했고, 그렇게 진행했다. 그런데 다른 크루 이야기를 듣다보니까 너무 쉽게 타협하고 넘어갔나?! 더 열심히 내 의견을 개진해야했나?! 하는 생각도 들더라. 페어가 나와 다른 의견, 다른 스타일일 때 내가 어떤 액션을 취해야할지 많이 고민해볼 수 있었다. 흑흑 협업 너무 어려워...

미션이 다 끝난 지금 돌아보면, 개인적으로는 원래 내 스타일대로 리팩터링을 하면서 구조를 만들어갔던 방식이 코드나 구조가 덜 복잡하고 깔끔했던 것 같다. 아마 혼자 작성한다면 당연히 기존의 방식을 선택할 것 같다.

하지만 협업을 할 때는 확실히 초기 설계가 중요하겠다. 설계는 곧 협업하는 사람들 간의 규칙이 되니까 협업에 있어서 확실히 용이하겠다고 새삼 생각했다.

결국 중요한 건 얼마나 어디까지 설계하느냐인 것 같다. 어떤 규모의 프로젝트에 어느 정도의 설계가 논의되어야 할지는 경험으로 알아가는 수 밖에 없는 것 같다. 내가 가진 방식과 페어의 방식 간에 적절한 타협 지점을 찾는 방법을 더 잘 고민해봐야겠다.


🚀 더 나은 설계를 향해

😂🔫 처음 만난 TypeScript, 그리고 모델링

이번 미션으로 TS를 처음 만났다. 자판기 미션을 진행하면서 사용봤지만 그다지 잘 활용하지는 못한 것 같다. 방학동안 보충 공부도 제대로 못 했다. 😂
조금 늦어도 계속해서 조금씩 보충해보는 걸로..!

  • 최대한 타입부터 설계하고, 그 다음 구현해보자.
    함수부터 냅다 만든 후 타입을 찾지말고, 선언부터 작성해보자.
    '모델링(타입 설계) -> 인터페이스 -> 구현' 과정으로 작성해보기.

  • 모델링이란 어떤 사물을 코드로 표현하기 위해 고민하는 과정이다. 어떻게 묘사할 수 있을까 고민하는 과정 자체를 모델링이라 할 수 있다. 그리고 그 모델링의 과정으로 타입과 프로퍼티, 메서드를 담은 인터페이스를 정의해본다.

  • TS는 타입 구문을 가지는 JS다. 즉, JS에 추가된 구문(언어적 약속, 문법)이다. JS가 지원되는 모든 곳에서 실행할 수 있다. TS는 데이터 설명서다.

  • TS는 타입을 추론할 수 있다. TS가 내가 작성하는 코드를 보고, 타입을 추론할 수 있는지 고민해보자. 타입 추론을 유도하자.

  • 객체 지향은 뭘까? 실세계를 코드에 녹이는 것이 객체..!


🤷‍♀️ 객체 지향 설계

  • 현실의 불확실성 때문에, 소프트웨어는 변화에 기민하게 대응할 수 있어야 한다. 그런 대응이 설계를 더 나은 설계로 보고 고민한다.

  • 객체 지향 설계는 결국 지금보다 더 나은 설계를 위한 과정에서 나온 방식이다. 더 나은 설계를 찾아가는 과정에서 객체 지향 설계를 사용해본다.

    • 객체들의 소리를 잘 들어보면 객체들이 뭘 하고 싶어 하는지 말을 한다. 우리는 그걸 표현하도록 도와주어야 한다. (워드 커닝햄)
    • 객체 간의 협력 관계를 잘 고민해보자.
  • 결국 '요구사항이 추가되었을 때, 내가 잘 대응할 수 있는가?'의 관점으로 고민해야 한다. 요구사항 추가에 따라 변하는 부분과 변하지 않는 부분을 고민하자. 또 앞으로 변동될 부분을 예상하고 비교해보자.

  • 처음부터 얼마나 기민하게 대응할 수 있도록 설계해야할까?

    • YAGNI 또는 오버엔지니어링과 확장성의 경계에 대한 고민이 필요하다.
    • 어디서 변화에 잘 대응해야하고, 어디서 변화가 없을지 예상해보자.

📝 피드백 돌아보기

📌 Level 1 전반에 대한 공통 피드백

  1. 의도를 드러내는 네이밍

  2. 정답이 없는데 정답 찾지 않기, 더 나은 구조와 개선을 고민하기
    정답 같은 설계를 찾기 보다, 지금 보다 더 나은 설계를 위해서는 어떤 시도를 해볼 수 있을까로 '과정'에 집중해보기"

  3. 성공하는 일부 테스트 케이스만 작성하고 있지는 않은가?

  4. 객체의 책임 적절히 분배하기

  5. form 더 잘 활용하기
    form field tag들을 우리는 잘 사용하고 있는가?
    form 요소에 대한 이벤트 처리에 있어서 click, keyup 등을 최대한 배제하거나 위임하면서 관리할 수는 없는가?

  6. 이벤트 핸들러의 등록, 해지에 대한 고민
    변경이 잦은 컴포넌트에 대한 이벤트 핸들러를 매 렌더시마다 등록하는 대신 한 번만 위임하기
    이벤트 해지는 언제, 왜 필요할까?

  7. 내장 객체 메서드 더 잘 활용하기

  8. css에 중복이 많다면? 어떻게 재사용할 수 있을지 고민해보기

  9. 오버 엔지니어링 지양하기
    리뷰를 위한 리뷰로 그칠 가능성이 있다.


💡 의도를 드러내는 네이밍

의도를 드러내는 네이밍은 왜 필요한가?
-> (내 생각) 독자의 이해를 위한 것도 있지만, 작성자 또한 어떤 의도와 목적으로 코드를 작성하는지 다시 고민해볼 수 있게 된다.

  • 의도를 드러낸 이름을 바로 만드는 것은 어렵다. '네이밍'이라는 그 과정에 집중하는 것만으로도 의미가 있다. '어떤 과정으로 의도를 드러내는 이름을 만들 수 있을까'라는 고민을 통해, 더 나은 네이밍에 다가갈 수 있다. '과정'에 집중하기.

  • 더 나은 이름을 고민하는 단계
    1. 의도를 드러내고
    2. 구현은 숨기고
    3. 반환 타입에 대한 명확한 힌트를 제공한다.
    https://wiki.c2.com/?IntentionRevealingNames


📌 기술과 문제 상황에 대한 접근 태도

💡 routing을 통해 구현한 SPA

  1. Hash
  2. History API를 사용하고, webpack devserver, 웹 서버를 설정하기. 404 Error 뜨면 index.html 내려주기
    • 대부분 SPA의 방식
  3. path가 아닌 parameter로 사용하기
    • 왜 파라미터를 사용할까? 파라미터로 페이지를 보여주는 경우도 있고, path로 보여주는 경우도 있다.
  • ✨ 구현 과정에서 마주한 문제에 대한 해결은 위와 같이 다양한 방법으로 가능하다. 중요한 것은 문제가 '왜' 발생했는지에 대한 이해다. 그 근본적인 이유를 이해해야 한다.

  • 기술을 사용하는 맥락을 고민해야한다. 어떤 기술을 사용했을 때 사용자 경험은 어떻게 달라지는지, SPA는 왜 등장했는지, 언제 SPA가 좋고 언제 SSR이 좋은지 고민해보자.

💡 인증과 인가

token을 어디에 저장하고 어떻게 관리할까? 각 방식의 장단점 고민해보기.

  1. 로컬 스토리지
  2. 세션 스토리지
  3. 쿠키
  4. 사용자 도메인

💡 1단계 PR

  • 웹 폰트와 로컬 폰트 알아보기
  • 웹 폰트
    사용자가 웹 페이지를 요청했을 때, CSS에 기술된 폰트가 클라이언트에 없는 경우, 폰트를 서버에서 클라이언트로 전송한다.
    1. 서버 폰트 로딩: 서버에 직접 폰트를 업로드 해두고 css에서 선언해주는 방법
    2. CDN(Content Delevery Network): 구글 CDN 서버를 통해 폰트를 제공받는 방법.
  • 로컬 폰트
    사용자 컴퓨터에 설치된 폰트 찾기
    @font-face {
      src: local("Font Name")
    }
  • 외에 웹 폰트 사용 시, 폰트 용량, 로딩 시간이나 브라우저 렌더링에 의해 폰트가 적용되지 않았을 때 생기는 상황들이 문제가 될 수 있다는 점을 간단히 살펴봤습니다.

@font-face :: MDN
CSS3 Web Font :: poiemaweb
웹 폰트 사용과 최적화의 최근 동향 :: NAVER D2
웹폰트 사용하기 (웹폰트 101) :: NTS WIT 블로그

  • 유사한 형태의 if문 반복되는 경우, switch 문으로 바꿀 방법 고민해보기.
    -> switch value로 true를 넣어서 사용하는 것은 일반적이지 않다. target.value나 name이나 id, class 같은 값을 switch value로 사용할 수 있다.

  • 네이밍..! 변수명, 인터페이스명 구체적으로..! + 일관성 있게

  • 하나의 함수가 너무 많은 역할을 하지 않는지 확인하고 역할 분리

  • toLocaleString() 관련 버그 생기지 않도록 관리 영역 고민해보기

  • URL의 path와 parameters 사이에 '/'가 들어가지 않도록


💡 2단계 PR

  • 다른 페이지는 모두 view가 manager를 통해 필요한 로직에 접근하고, 토큰을 다뤄야하는 로직에 접근해야하는 페이지는 manager 없이 필요한 로직에 바로 접근한다. view에서 필요한 로직에 접근하는 방식이 다른데, 일관성이 떨어져 보이지는 않는가?
    -> (리뷰어님의 의견) 토큰을 핸들링하는 부분만 manager가 없다. manager의 유무가 페이지의 역할에 따라 나눈 것으로 보여 일관성이 떨어져 보이지는 않는다.

  • requestAnimationFrame 사용해보기

  • auth 관련 로직은 서비스에서 중요한 역할을 담당하기 때문에, 보통 util이 아닌 다른 디렉토리로 구분한다.

  • E2E 테스트 명세 - 고객의 입장의 어떤 기능을 테스트하는지 고민하여 구체적으로 명시하기.


🧐 Level 1 돌아보기

Level 1의 목표

💡 목표 :: 프로그래밍 기본 역량 쌓기

  • HTML/CSS
    주어진 디자인을 웹 표준을 준수하는 UI로 옮길 수 있다.
  • JavaScript
    프레임워크 없이 JS만으로 작은 웹 어플리케이션들을 만들어보면서 언어의 주요 문법들을 깊이 있게 학습하며, 이를 바탕으로 클린 코드에 대해 고민하는 연습을 한다. 런타임 환경으로서 브라우저의 기본 동작 원리를 함께 학습한다.
  • 테스트
    E2E 테스트와 유닛 테스트 코드를 작성하면서 개발하고 리팩토링하며 테스트 코드의 필요성을 경험해본다.
  • TypeScript
    TypeScript의 기본 문법을 익히며 TypeScript의 필요성을 이해한다.
    이를 객체지향적으로 활용하는 방법을 고민한다.
  • 목표를 달성했나 돌아보면, 관련 내용들을 모두 한 번쯤은 훑어보고, 경험하고, 고민했다. 꽤 열심히 살았군.
    쫓아가느라 가랑이 찢어질 것 같았다... 남은 기간도 열심히 쫓아가자~ 😇

  • 두 달 전과 비교하면 JS에 대해 많이 알게 되었다. 핵심 개념을 한 번씩 찍먹 정도는 했다. 앞으로도 열심히 보충해야지. TS도 더 챙겨줄게...

  • 스스로가 만족할 수준의 코드 퀄리티를 지키진 못 했다. 시간만 많으면 무한정 고민하겠지만, 일정을 따라가다보니 어쩔 수 없었다. 언제까지고 붙잡을 순 없으니 모든 프로젝트에서 당연한 일이긴 하다. 그럼에도 주어진 시간 속에서 조금 더 좋은 코드 퀄리티를 챙길 수 있도록,,, 앞으론 더더욱 신경써야겠다.

  • 테코톡 이후로 당장 내일 Level 2 시작하는 오늘까지, 휴식과 운동은 제대로 챙기지 못했다. 생활 패턴은 아직도 엉망이다. 마찬가지로 중간부터 학습 키워드 정리도 제대로 챙기지 못한 점이 아쉽다.
    -> 일찍 자고 일찍 일어나기!
    -> 학습 내용 짧게 짧게 자주 정리하기!


스터디 돌아보기

  • 독서모임은 이 정도면 성공이었던 것 같다.
    마지막에 미션이 바빠지면서 인증률이 떨어진 것과, 인증을 레포지토리로 옮기면서 일일 인증의 접근성이 떨어지다 보니 잦은 소통이 없었던 건 아쉽다. 그럼에도 나를 포함한 멤버들이 독서로 공부하는 경험, 혹은 공부할 동기를 스터디에서 얻어간 것 같아서 큰 목적은 달성했다고 생각한다. 마지막에 스터디 회고를 통해 보완하면 좋을 점도 나눴으니, 다음 모임은 더 잘 굴러갈 것 같다. 나는 책을 읽으면서 공부하는 걸 좋아해서, 이 독서 모임이 공부 자체에 대한 동기가 많이 되었다. 직접 진행은 안 할거지만, Level 2에 여력이 있으면 계속 참여하고 싶다.

  • 객체 소리 찾기 스터디를 최근에 시작했다.
    다른 크루들은 같은 요구사항에 어떻게 구현했는지, 어떤 생각을 했는지 볼 수 있어서 좋다. 코드 리뷰 규칙을 만든 것도 서로 대화를 많이 나눌 수 있다는 점에서 잘한 부분인 것 같다. 방학 동안 마냥 쉬지 않고 코딩한 것도 좋았다.
    하지만 이 스터디를 통해 객체가 뭔지 알게 되었냐고 묻는다면 아직 잘 모르겠다고 대답할 수 밖에 없을 듯..? 멤버들이랑 계속 논의해봐야겠다.


🎈 나의 다짐과 잡담

  • 지난 주에 서울에 올라왔다. 서울에서 이렇게 몇 개월 지내는 건 처음이다. 조금 있으면 부산 가야할 것 같고, 사실 가고 싶다. ^-^ 대학도 집에서 30분 거리 다녔는데... 왕복 2시간씩 매일 통학하려니 벌써 짜릿하다. 서울에선 왕복 2시간이면 괜찮은 거라던데 ㅎ,,, 특별히 서울이 더 좋은지는 모르겠다. 오히려 부산에 있을 때보다 스타벅스가 멀어져서 아쉽다. 😭
    아직 별로 실감 안 난다. 가끔 찐한 서울 말 들리면 여기 서울이었지 싶은 정도. 어쨌건 집 떠나 서울에 온 건 나한테는 큰 변화다. 적당히 서울 구경도 하고 잘 지내봐야지.

  • 이제 오프라인 시작이다. 온라인과는 또 다른 상황들이 있을 것 같다.
    그래도 무던히 지내고, 부단히 노력하면 다 괜찮을 거라고 생각한다.

  • 이사 아닌 이사와 연속된 회식으로 피로가 누적되었다. 근데 방학은 끝나버려서 눈물날 것 같다. 내일의 나를 위해 오늘이라도 일찍 자야겠다.


좋은 웹페이지 즐겨찾기