1. function-al의 시작
type safe 함수형 프로그래밍 유틸리티 라이브러리, function-al을 만들기 시작한 지 벌써 한 달이 넘었다.
처음부터 뭔가 거창한 목표가 있었던 건 아니다. 그저 출퇴근길이 너무 지루해서, 지하철에서 읽기 시작한 Functional-Light JavaScript 책이 시작이었다.
사실 함수형 프로그래밍에 대해서는 거의 무지한 상태였다. 그런데 책에서 소개하는 다양한 use case들을 보면서, 완전히 새로운 세상을 만난 느낌이었다. FP가 설명하는 개념들이 생각보다 너무 자연스럽고 합리적이었고, 무엇보다 코드가 엄청 깔끔해지는게 신기하고 인상적이었다.
책을 읽다 보니 “이거 그냥 읽고 끝내면 금방 다 잊어버리겠는데?”라는 생각이 들었다. FP를 잘 쓰는 개발자가 되고 싶었다.
그렇게 시작된 function-al은 일종의 ‘체화 프로젝트’가 됐다. 책에서 새로운 함수나 개념이 나올 때마다 직접 구현해보고, 그때그때 function-al에 하나씩 추가하면서 라이브러리를 확장해나갔다.
단순히 동작만 하는 것보다는, TypeScript의 타입 시스템을 최대한 활용해서 타입 안전성까지 함께 챙기는 방향으로 구현했다. (이 과정에서 TypeScript가 엄청 늘었다!)
단순히 공부하려고 시작한 라이브러리지만, 하나하나 함수가 쌓여가다 보니 실전에서도 꽤 쓸만 한 도구가 점차 되가고 있다.
2. 함수형 프로그래밍은 코드 품질을 올리는 무기다
우테코 미션에 녹여내기: 반복되는 UI 로직을 추상화해볼까
function-al을 만들면서 가장 뿌듯했던 순간 중 하나는, 이 함수들이 실제 코드에서 제법 유용하게 쓰이기 시작했을 때였다.
우테코 미션에서 카테고리와 정렬 기준을 선택할 수 있는 필터 UI를 만들고 있었는데, <select> 태그 안에 <option>을 반복해서 렌더링해야 했다. 이런 건 누구나 한 번쯤 만들어봤을 법한 UI인데, 코드가 은근히 지저분해지기 쉽다.
처음에는 아래처럼 작성했다:
// (before)
${Object.entries(CATEGORY)
.map(
([key, label]) =>
`<option value="${key}" ${
key === selectedCategory && "selected"
}>${label}</option>`
)
.join("")}
딱히 틀린 코드는 아니지만, 비슷한 구조가 정렬 필터에도 또 한 번 반복되고, 나중에 필터 개수가 늘어나기라도 하면 이 코드를 계속 복붙하게 될 것 같았다. 그래서 이 부분을 function-al에서 만든 partial 함수로 리팩토링해보기로 했다.
partial 함수는 어떤 함수의 일부 인자만 고정한 새로운 함수를 만드는 간단한 유틸이다. FP에서는 이걸 ‘부분 적용(Partial Application)’이라고 부른다.
그래서 <option> 하나를 렌더링하는 함수 renderOption을 만들고, 거기에 selectedKey만 먼저 고정해두면, 나머지 [key, label]만 map으로 넘기면 되는 구조가 된다.
const renderOption = (selectedKey, [key, label]) =>
`<option value="${key}" ${key === selectedKey ? "selected" : ""}>${label}</option>`;
const renderOptions = (entries, selectedKey) =>
entries.map(partial(renderOption, selectedKey)).join("");
이렇게 바꾸고 나면, 핵심 로직이 더 명확해진다. “선택된 값을 기준으로, 옵션들을 렌더링한다”는 구조가 함수 레벨에서 드러난다.
결국 전체 코드 구조도 더 유연하게 정리됐다:
${renderSelect({
name: "category",
id: "category-filter",
action: "set-category-filter",
entries: Object.entries(CATEGORY_META),
selectedKey: selectedCategory,
})}
카테고리든 정렬이든, 어떤 필터든 상관없이 공통 로직은 renderSelect로 묶이고, 반복되는 옵션 생성도 partial로 정리된 구조다.
[2단계 - 자주 가는 음식점] 빌리(정환희) 미션 제출합니다. by hwanheejung · Pull Request #236 · woowacourse
안녕하세요 카일! 😊 이번 미션도 잘 부탁드립니다!! 학습 목표 이번 미션을 통해 다음과 같은 학습 경험들을 쌓는 것을 목표로 합니다. UI와 도메인 영역을 분리할 수 있는 설계를 고민해보고,
github.com
이렇게 직접 써보면서 가장 좋았던 점은, 라이브러리를 실제 코드에 적용해보는 것이 최고의 테스트 환경이라는 사실이었다. 내가 만든 함수가 진짜 쓰기 편한지, 어떤 부분이 아쉬운지, 그리고 테스트 코드로는 잡히지 않던 예외 케이스들이 실전에서 더 잘 드러난다는 걸 경험했다.
또 사용하다 보면 자연스럽게 “이런 함수도 하나 있으면 좋겠다”는 아이디어가 계속 떠오른다.
그리고 또 하나 인상 깊었던 건, 단순히 코드 몇 줄을 줄이는 수준이 아니라, 함수를 조립하고 흐름을 명확히 만드는 사고방식 자체가 바뀌고 있다는 점이었다. 이전에는 copy-paste가 당연했던 구조도, 지금은 “이 부분은 함수로 추출할 수 있을까?”, “이 인자를 고정해두면 조합이 더 자연스러울까?” 같은 시선으로 보게 된다.
3. 함께 써보고, 함께 키워보기: function-al 컨트리뷰션 스터디
이쯤 되니, 이걸 나만 쓰기보다는 우테코 크루들도 FP의 매력을 함께 느껴보면 좋겠다는 생각이 들었다. 코드가 비교도 안되게 깔끔해지는 도파민, 함수를 바라보는 시각의 변화, 여러 함수를 조립하는 쾌감… 이건 직접 써봐야 느낄 수 있는 즐거움인 것 같다.
게다가 오픈소스기 때문에, 함께 쓰고, 함께 개선하고, 함께 성장해보는 것도 엄청 재밌을 거라고 생각했다.
그렇게 해서, 작은 오픈소스를 함께 발전시켜보는 컨트리뷰션 스터디를 만들게 되었다.
혼자만의 작은 실험이, 함께 성장하고 함께 만들어가는 공동의 목표로 바뀌자 마음가짐도 달라졌다. 이번엔 정말 체계적으로, 제대로 키워보고 싶어졌다.
스터디의 공통된 목표는 두 가지다:
- ✨ function-al만의 색깔과 차별점을 만들어가기
- 🌱 함수형 프로그래밍을 함께 학습하고 인사이트를 나누기
회의에서는 스터디의 활동 방식과 각자 맡을 역할도 정리했다.
이렇게 역할을 나누고 실제로 손을 대기 시작하니, 진짜 오픈소스 생태계를 경험하는 프로젝트로서 무게감이 생겼다. 물론 아직 시작 단계고, 배워야 할 것도 많겠지만 그래서 더 기대된다.
앞으로 어떤 모습으로 성장할지,
어떤 새로운 함수들이 더해질지,
어떤 인사이트들이 공유될지—
벌써부터 많이 기대된다.
(스터디 이름은 woowaf이다..ㅎ 우아한 function-al이란 뜻. npm i @woowaf/function-al이 될 예정 크크)
https://www.npmjs.com/package/@zoeykr/function-al
@zoeykr/function-al
A type-safe utility library for functional programming. Latest version: 0.0.3, last published: 4 days ago. Start using @zoeykr/function-al in your project by running `npm i @zoeykr/function-al`. There are no other projects in the npm registry using @zoeykr
www.npmjs.com
https://github.com/hwanheejung/function-al
GitHub - hwanheejung/function-al: a type-safe utility library for functional programming.
a type-safe utility library for functional programming. - hwanheejung/function-al
github.com
스타 한번씩 누르고 가세요 😁
'CS > Functional Programming' 카테고리의 다른 글
[FP] 아무도 모르는 side effect는 괜찮을까? (2) | 2025.02.26 |
---|---|
[FP] Type Safe Pipe 함수 만들기 (0) | 2025.02.19 |
[FP] Type Safe Curry함수 만들기 (1) | 2025.02.01 |