함수형 사고는 왜 필요한가?Develop약 10분 소요developmentfunctionalfunctional-programmingreact 발표 모드로 보기Why Functional Thinking?Introduction to Functional Thinking (Programming) for React Developers함수형 사고는 왜 필요한가?: 리액트 개발자를 위한 함수형 사고(프로그래밍) 입문2026/03/30 구효민.I Heard about "Functional Programming"나는 함수형 컴포넌트를 써 봤어요!map, filter, reduce?Monad? (함수형 프로그래밍을 들어본 적이 있다면)Program as a Function프로그램은 무엇일까요?Imperative Programming의 관점: 무언가를 처리하는 과정을 기술한 문장(statements)의 순열Functional Programming의 관점: 무언가를 입력하면 무엇을 출력하는 함수프로그램을 하나의 합성 함수로 정의한다면, 우리가 생각하는 문제 정의/해결책과 프로그램 코드의 멘탈 모델이 일치될 수 있음 프로그램 (복잡한 문제를 처리하는 함수) ㄴ 내부 모듈 (복잡한 문제를 쪼갠 하위 문제를 처리하는 함수) ㄴ 내부 함수 (하위 문제를 또 쪼갠...) ㄴ 라이브러리 코드 (내부는 복잡하지만 입력과 출력이 명확하여 이 문제에서 깊게 들여다 볼 필요가 없는 함수) 결국 UI는 다양한 상태를 잘 보여주는(transform) 하는 것선언형 UI 패턴(React, Vue, Jetpack Compose 등)결국 정확한 좌표나 크기보다 컨텐츠들이 어떤 방식으로 표기되는 의도가 중요한 것이 아닌가?Side-effects: Reality Is Not Always Ideal수학의 세계에서는 모든 함수들이 순수 함수 (닫힌 함수)이지만 현실 세계에서는 그렇지 않음I/O interrupt, 하드웨어 오류, 네트워크... 등등컴퓨터 세계에서 쌓아진 모든 레이어들이 완벽하게 동작하지 않을 가능성컴퓨터 구조에 따라 컴퓨터 내부의 상태를 직접 변경하는 것이 효율적일 가능성결국 컴퓨터는 state machinePurity: We Need More Safe Areas순수 함수는 외부 환경에 영향을 받지 않는 함수현실의 특성 상 프로그램의 모든 부분이 순수하기는 매우 어렵지만, 순수 함수의 영역이 넓어질수록 프로그램의 예측 가능성은 증가함순수 함수로 작성하면...프로그램을 실행하지 않아도 결과를 알 수 있다 (??)전제: 입력과 출력에 대한 제약을 정확하게 정의하기정적 분석(타입 시스템 등)의 도움을 많이 받을 수 있다내가 기존 함수를 사용할 때 두려워 할 필요가 없다FP in React: We Are Already Using ItReact는 왜 함수형 컴포넌트로 전환했는가?Composable: UI 컴포넌트를 합성 함수로 보기useMemo의 전제: 순수 함수여야 함!useEffect와 Strict mode왜 useEffect의 이름이 useEffect인가? 왜 개발 환경에서 두번 실행되는가?useReducer: 불변성, 순수성HOC(Higher-order components)Why React Best Practices Feel Functional함수형 프로그래밍의 극의: 언제 어디서 실행하든 입력이 같으면 출력은 같다리액트의 모든 BP는 이를 보장하면서, 좋은 composition을 통해 나의 컴포넌트(함수)가 원하는 입력과 출력만 갖도록 하는 것Badconst NoCompose = (props: SomeLargeProps) => ( <article> <section id="a-sec"> <p>{props.a.wow}</p> {/* ... */} </section> <section id="b-sec"> <p>{props.b.what}</p> {/* ... */} </section> </article> ); Goodconst ASection = (props: ASectionProps) => ( <section id="a-sec">{/* ... */}</section> ); const BSection = (props: BSectionProps) => ( <section id="b-sec">{/* ... */}</section> ); const GoodCompose = (props: SomeLargeProps) => ( <article> <ASection {...props.a} /> <BSection {...props.b} /> </article> ); EventuallyBefore: no_compose(a, b) -> viewAfter: compose(a_sec(a), b_sec(b)) -> view직관적으로 봐도 내부 섹션이 바뀌었을 때, Before는 no_compose 내부 로직을 전부 수정해야 함 -> 섹션간 경계 침범 위험 -> 스파게티반면 함수 합성을 사용하면 내부 섹션이 바뀌어도 compose 함수는 남고, 다른 섹션의 함수 내부는 절대 변경되지 않음이 보장함수의 순수성을 유지하면, 작은 단위로 쪼개고 조합하는 것이 쉬워짐좋은 React 코드는 결국state를 덜 저장하고props를 더 명확하게 나누고effect를 바깥으로 밀어내고render를 더 순수하게 만드는 방향으로 감즉 React Best Practice는 프레임워크의 취향이 아니라, 함수형 사고를 따를 때 자연스럽게 나오는 결과물Requirements Become Test Cases and Constraints요구사항은 보통 긴 문장으로 시작하지만, 결국 코드로 옮길 때는 아래 두 가지로 수렴함Test Cases이 입력이 들어오면 이 출력이 나와야 한다Constraints어떤 상황에서도 반드시 지켜야 하는 규칙이 있다장바구니 UI를 만든다면...Test Case상품이 0개면 empty view가 보여야 한다상품이 3개면 total count는 3이어야 한다할인 코드가 적용되면 total price가 다시 계산되어야 한다Constrainttotal price는 item들의 합과 항상 일치해야 한다음수 가격은 보여주면 안 된다서버 응답이 늦어도 UI는 깨지면 안 된다함수형 사고는 이런 요구사항을“어떤 함수가 어떤 입력을 받아 어떤 출력을 내야 하는가”"각각의 요소들을 어떤 함수로 쪼개고, 어떤 파이프라인으로 합성해야 하는가"“어떤 제약이 항상 유지되어야 하는가”로 바꾸어 생각하게 만듦Pipelines for Changing Requirements복잡한 요구사항은 보통 한 번에 해결되지 않음서버 응답 형식이 바뀜디자이너가 UI 조건을 바꿈새로운 예외 케이스가 추가됨정렬/필터/가공 규칙이 계속 늘어남이때 거대한 함수 하나보다, 작은 변환 파이프라인이 더 강함raw_data -> validate -> normalize -> derive_view_model -> render 파이프라인으로 나누면어디서 무엇을 처리하는지 명확해짐test case를 단계별로 검증할 수 있음constraint를 어느 단계에서 지켜야 하는지 드러남요구사항이 바뀌어도 전체를 뜯지 않고 일부 단계만 수정 가능React에서도 비슷함API 응답을 그대로 렌더하지 않기중간에 view model, hooks를 만들기render 함수는 최대한 “보여주기”에 집중하기effect는 마지막 동기화 단계로 밀어내기Functional Thinking Is the Real Goal오늘 이야기한 핵심은 FP 문법 자체가 아님Monad를 몰라도 됨Functor를 몰라도 됨Haskell을 쓰지 않아도 됨더 중요한 것은 이런 사고 방식프로그램을 함수로 보기side-effect를 경계로 밀어내기가능한 많은 safe area 만들기요구사항을 test case와 constraint로 다루기변화를 파이프라인으로 받기React는 이 사고를 연습하기에 꽤 좋은 환경임UI를 함수처럼 다루고composition을 장려하고purity를 요구하고effect를 분리하게 만들기 때문결국 중요한 것은 FP가 아니라 Functional Thinking이다더 예측 가능하게더 조합 가능하게더 덜 무섭게 코드를 바꾸기 위해EOD
좋은 개발자란 무엇인가?약 10분 소요[Yourssu Web FE 세미나] 개발자로써의 삶을 선택한 당신, 어떤 마음으로, 그리고 철학으로 개발하고 있나요?Developdevelopmentphilosophymastery