3회차

👉 노션에서 자세히 보기 (opens in a new tab)

3️⃣ 3회차 공지사항 (opens in a new tab)

Check In 🚪

무드미터

Join /functional-programming's Cuckoo Timer! (opens in a new tab)

민수(김)
  • 피곤한
    • 잠을 제대로 못자
  • 근심하는
    • 테오콘 연사 발표준비 근심: 청중 분들이 왜 30분이나 들어야 하지?
수림
  • 근심하는
    • 스터디 과제
종현
  • 희망 찬
    • 포괄임금제 → 한 달 20시간 이상 초과근무 → 휴가 → 안쓰면 돈으로 지급
충일
  • 의기양양한
  • 근심하는
예진
  • 근심하는
    • 내일 있을 발표 준비…1도 안함
  • 만족스러운
    • 어제 저녁 샐러드, 오늘 점심 샐러드, 오늘 저녁 닭개장 👏👏👏
민수(박)
  • 충격 받은
  • 희망 찬

이론 파트 📝

Chapter: Ch 8~ Ch 9 Page: p 167 ~ p 230

좋았던 내용, 또는 논의하고 싶었던 내용을 기반으로 공유하고 싶은 이론 파트를 정리해보아요!

지난번 피드백을 바탕으로, 이론파트에서는 좋았던 내용은 메모 느낌으로만 적고, 논의하고 싶었던 내용을 위주로 진행하도록 하겠습니다. Cuckoo time: 13분

민수(김)
  • 좋았던 내용

    계층형 설계에 대해 무지렁이..? 였던 것 같은데, 너무 읽기 편하게 설명해준 부분들이 인상 깊었다.

    이번에 예진님 실습 문제를 풀어보면서 나름의 계층형 설계..? 를 실현한 것 같아서 그 과정을 공유하고 싶다. 논의하고 싶었던 내용에 적어보겠습니다.

    함수 호출을 시각화 하는 과정에서 추상화 수준을 다르게 그림으로 표현하는 게 이해에 많은 도움이 되었다.

      계층형 설계는 코드를 추상화 계층으로 구성합니다.
      각 계층을 볼 때 다른 계층의 구체적인 내용은 몰라도 됩니다.

    라는 표현이 와닿았다.

    함수 이름을 통해서도 어느 계층에 위치해야 하는 함수인지를 알려줄 수 있다는 것도 좋았다.

    실제로 이번에 예진님 실습 문제를 풀다가, 비즈니스 규칙이 필요가 없는 최하위 계층의 함수인데 도메인 관련된 네이밍이 붙은 걸 보고 네이밍을 바꾼 경험이 있었다.

  • 논의하고 싶었던 내용

    사실 논의하고 싶었던 내용이라기 보다는, 제가 작성한 예진님 실습 문제를 리뷰 받고 싶은 내용이긴 합니다 키키

    제가 작성한 코드를 그대로 들고 와봤습니다.

    // 기존의 메소드를 wrapping 하는 것에 의미가 있을까? 를 실현해봤습니다.
    // 이번 파트를 읽고 나니, 비슷한 추상화로 함수를 호출해야 한다는 것에서 패턴 1을 적용한걸까?
    // 라는 생각이 들었습니다. 배열의 메소드를 직접 호출하는 건 가장 낮은 계층을 쓰는 것이니
    // 가독성이 낮아지는 걸까? 라는 측면에서 적용해봤습니다.
    const hasIncludes = (url: string, value: string): 'YES' | 'NO' =>
      url.includes(value) ? 'YES' : 'NO'
     
    export const splitHashPart = (
      text: string,
    ): { nonHash: string; hash: string } => {
      const indexOfHash = text.indexOf('#')
     
      if (indexOfHash >= 0) {
        return {
          nonHash: text.slice(0, indexOfHash),
          hash: text.slice(indexOfHash),
        }
      }
     
      return {
        nonHash: text,
        hash: '',
      }
    }
     
    export const replaceKeyValue = (
      url: string,
      key: string,
      newValue: string | number,
    ) => {
      const regExp = new RegExp(`${key}=([^&]*)`, 'g')
      if (url.match(regExp)) {
        return url.replace(regExp, `${key}=${newValue}`)
      }
     
      return url
    }
     
    /**
     * 출제자: 예진님 (yejineee)
      * URL의 쿼리스트링 관련 유틸 함수를 계산 을 최대한 이용하여 만들기
      *
      * - 해쉬가 있다면, 유지해야 함
      * - 기존 쿼리가 있다면, 유지해야 함
      * - 기존 쿼리와 추가하려는 쿼리의 key가 동일하다면, 기존 쿼리가 대체됨
      */
     
    export const addQuery = (
      originURL: string,
      key: string,
      value: string | number,
    ) => {
      const { nonHash, hash } = splitHashPart(originURL)
     
      let returnUrl = nonHash
      let connector = '?'
     
      if (hasIncludes(originURL, '?') === 'YES') {
        connector = '&'
      }
     
      returnUrl += `${connector}${key}=${value}`
     
      if (hasIncludes(originURL, `?${key}`) === 'YES') {
        returnUrl = replaceKeyValue(nonHash, key, value)
      }
     
      return returnUrl + hash
    }

    가장 논의하고 싶던 내용이 hasIncludes 라는 함수인 것 같습니다.

    wrapping 만 하는 함수를 만드는 것이 과연 가독성 향상에 도움을 주는 것일까? 라는 생각에 return 값을 boolean이 아니라 “YES” 와 “NO”로 변환해봤습니다.

    또한, splitHashPart 를 만들면서, 원래는 변수명에 url이라는 변수가 들어가 있었는데, 가장 low한 계층의 함수가 url이라는 비즈니스 규칙이 강제가 되어야 할까 라는 생각에 변수명을 바꾼 경험이 재밌는 경험이었습니다.

  • 실습 문제 아이디어 스토밍

    실습으로 가기는 어렵겠지만, 브라우저 익스텐션으로, 특정 hoc으로 감싼 컴포넌트를 계층형으로 다이어그램을 보여주는 익스텐션 만들어보고 싶다. 재밌겠다

    함수 하나로 짜여져 있는 긴 로직을 계층화 패턴을 활용해서 개선해보는 작업을 해보자!

수림
  • 좋았던 부분
    • 계층형 설계 패턴
      • 어떤 기준으로 코드를 리팩터링 하면 좋을지에 대한 구체적인 패턴들을 제시해주어서 좋았다.
      • 왜 코드 스멜이 나는지?
        • 한 함수에서 서로 다른 추상화 단계를 사용하기 때문
      • 지난 스터디와 이어지는 내용, 함수의 재사용은 “중복 코드”를 찾기 위해 함수를 빼내는 것이 아닌 구현을 명확하게 하기 위해 일반적인 함수를 빼내는 것
  • 논의하고 싶은 부분
class Test {
constructor() {
  this.#car = new Car()
  this.#race = new Race()
}
 
getCars() {
  this.#car.getCar()
}
 
getRace() {
  this.#race.getRace()
}
}
  • 계층형 설계 감각을 위한 입력과 출력에서 여기에서 이야기하는 입력과 출력은 무엇인지? (p.170)
    • 입력
      • 함수 본문
      • 계층 구조
      • 함수 시그니처
    • 출력
      • 조직화
      • 구현
      • 변경
충일
  • 좋았던 내용
    • 계층형 설계

      • 먼저 코드의 가독성을 크게 향상시키는 효과
      • 함수나 클래스의 계층 구조를 통해 코드의 논리적인 흐름을 쉽게 이해할 수 있다.
      • 코드의 다양한 계층에서 상황에 따른 최적의 해결책을 선택할 수 있게 해주기 때문에 유연성 또한 향상된다.
      • 중복을 줄이고 코드 재사용성을 높이는데도 도움이 돼요.
        • 비슷한 기능을 하는 함수가 여러 개 있을 경우, 그들을 한 곳에 모아 상위 계층으로 만들어, 코드의 재사용성을 높이고 중복을 줄일 수 있습니다.

      책에서 계층형 설계에는 몇 가지 중요한 패턴이 있는데요,

      1. 직접 구현, 이 패턴은 가장 낮은 수준에서 세부 구현을 처리하는 것을 의미
      2. 추상화 벽, 이 패턴은 특정 계층이 자신의 하위 계층에 대해 알 필요가 없도록 추상화를 통해 그 사이에 벽을 세우는 것입니다. 이로 인해 코드 간의 결합도를 줄일 수 있고, 각 계층을 독립적으로 테스트하거나 수정할 수 있게 됩니다. → 팀 간 책임 명확
      3. 작은 인터페이스, 이는 각 계층이 제공하는 인터페이스를 최소화함으로써, 계층 간의 상호작용을 단순화하는 것을 목표로 합니다.
      4. 편리한 계층 패턴은 가장 일반적인 작업을 수행하는 편리한 인터페이스를 제공함으로써 사용자에게 편의성을 제공하는 것입니다. 이런 패턴들을 사용함으로써 코드의 가독성, 유연성, 재사용성을 향상시키고, 유지보수를 쉽게 할 수 있어요. 책에서 계층형 설계는 정말 유용하다고 말하고 있는걸 느꼈어요
    • 197p 197p

  • 논의하고 싶은 부분
    • 테스트코드 225p
      • 코드를 그래프로 그리면 테스트의 중요성을 더 잘 알 수 있나?
      • 더 잘알수있다 → 호출 그래프 구조를 통해 규칙을 얻을 수 있고 규칙을 통해 테스트 우선순위를 설정할 수 있다.
예진
  • 좋았던 내용
    • 책에서 설계에 대해 얘기할 때에는 ‘같은 용어를 사용하는 것이 중요하다’라고 하였다. 함수형 코딩 책을 읽으면서, 이 책에 있는 언어로(계산, 액션 등등) 팀원들과 같이 얘기하면 더 소통하기 편하고, 좋은 코드에 대한 논의가 잘 이뤄질 것 같다는 생각이 들었다. 지금 이 책에서 소개하는 개념들을 팀원들에게 간단히 전해봐도 좋겠다는 생각이 들었다.
    • ‘어떤 부분에 더 많은 테스트를 붙일지’를 고민하였는데, 책에서도 어떤 계층에 있는 부분을 테스트하는게 더 좋은지를 말해주어서 좋았다. 계층에서 가장 아래에 있는 부분이 제일 수정하기 어렵고, 더 많은 영향 범위를 끼치므로, 더 잘 구현해야 한다는 것을 느끼게 되었다.
  • 논의하고 싶은 내용
    • p.218에 있는 add_item_to_cart 함수에서 어떤 점을 개선하고 싶고, 어떻게 개선할 수 있을지에 대해 얘기하고 싶습니다

      add item func

      const cartItem = makeCartItem({ name, price })
       
      function addItemToCart(cartItem, cart){
        return addItem(cart, item)
      }
       
      const cartAdded = addItemToCart(cartItem, cart)
    • p.198에서 ‘일반적인 함수가 많을수록 재사용하기 좋다’라고 하였고, p.210에서는 ‘오지 않을 수도 있는 미래를 위해 불필요한 코드를 작성하는 것은 좋지 못하다’고 하였다. 어디까지 추상화 벽을 세우는 것이 이 둘 다를 충족시키는 것일까?

민수(박)
  • 좋았던 내용
    • 구체화 단계, 혹은 계층 관점에서의 추상화에 대한 예시를 보고 이해할 수 있어서 좋았다. (p. 198)
      • 하나의 책임으로 추출되는 경우 보통 복잡성을 감추기 위해서도 함수를 추출해왔는데, 같은 계층으로는 복잡성을 감추기 위해서는 함수를 추출하지 말라해서 충격이었다.
    • 계층으로 추상화를 잘 해놓으니까 자료구조를 변경할 때도 수정되어야 할 함수가 쉽게 특정지어지고 그만큼 사이드이팩트를 예측하기 쉬워지는 것 같아 그 부분이 좋았다. (p. 209)
  • 논의하고 싶은 내용
    • 다들 추상화를 할 때 이번 장에서 배운 구체화 단계, 혹은 계층 관점으로도 고려해서 추상화를 하시는지 궁금합니다.

실습 💻

실습 풀이 및 리뷰간 논의하고 싶었던 내용 (2 회차 실습 간)

민수(김)

우선, 다들 많이 바쁘신지 실습 풀이가 잘 안 되는 것 같아서 맘이 아픕니다 ㅠㅠ

강제성이 있는 건 절대 아니지만, 알고리즘 공부랑은 다른 느낌의 재미가 있습니다..! 시간 나실 때 꼭 한 번씩 풀어보시길!

테스트 코드를 작성하면서, 순수함수와 도메인 분리에 대해서 생각해보게 된 계기가 있습니다.

export const splitHash = (url: string): { splittedUrl: string; hash: string } => {
  const [splittedUrl, hash] = text.split('#')
 
  return {
    splittedUrl,
    hash: hash ? `#${hash}` : '',
  }
}

제가 만들고 싶었던 초기 모습입니다.

작성할 때는 몰랐는데, 테스트코드를 작성하면서 도메인과 분리된 곳에서 사용을 하다보니, 내가 왜 url이라는 네이밍을 굳이 붙였지, 라는 생각에 도메인 관심사를 분리했습니다.

export const splitHash = (text: string): { nonHash: string; hash: string } => {
  const [nonHash, hash] = text.split('#')
 
  return {
    nonHash,
    hash: hash ? `#${hash}` : '',
  }
}

실습 문제 아이디어 스토밍

  • 수림
    • 현생에 바빠서 책읽기에 조금 힘들었다
  • 종현
    • 다른 사람이 써놓은 걸 보는 것도 재밌다.
    • 떠오를 때도 있지만, 떠올리기는 어렵다.
    • 자유도를 주는 방식도 괜찮겠다.
      • 수림: 실습 파트도 참여할 수 있나요?
      • 종현: 이론 파트를 조금 더 선호하는 것 같지만, 실습도 자유를 주면 좋겠다.

문제집 만들기

💡

이번 주는 스킵

아이디어가 있고, 풀어볼만한 문제가 나왔을 때 진행하는 것으로 결정

Check out 🚪

[3주차] 쏙쏙쑥쑥 스터디 만족도 조사 (opens in a new tab)

3 회차 CA notion에서 보기 (opens in a new tab)