LogoSEO Jing
  • All Posts
  • SEO Jing
  • okayJing
  • KD Team
  • CLAB Coreteam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

자바스크립트 퀴즈북 리마인드 Day 10: 함수는 값이고 경계다

2026년 7월 5일·5분 읽기
오늘의 질문: “함수를 인자로 넘기는 코드가 항상 더 함수형이고 안전할까?”

먼저 보는 코드

js
function withLoading(run) {
  setLoading(true);

  return run().finally(() => {
    setLoading(false);
  });
}

withLoading(() => fetchUser(userId));

겉으로는 단순한 고차 함수입니다. 그런데 리뷰할 때는 한 가지를 더 봐야 합니다.

run은 값을 계산하는 함수일까, 아니면 네트워크와 UI 상태를 건드리는 부수 효과 묶음일까?

함수는 자바스크립트에서 값입니다. 변수에 담고, 인자로 넘기고, 반환할 수 있습니다. 그래서 함수는 추상화를 만들기 쉽지만, 동시에 부수 효과를 예쁘게 숨기기도 쉽습니다.

함수 설계 경계

틀리기 쉬운 직감: 함수로 감싸면 설계가 좋아진다

함수로 감싸는 것 자체는 설계가 아닙니다. 좋은 함수는 호출자가 무엇을 넣고 무엇을 받는지, 그리고 어디에서 부수 효과가 생기는지 설명할 수 있어야 합니다.

js
function getDisplayName(user) {
  console.log("render user", user.id);
  localStorage.setItem("last-user", user.id);
  return `${user.name} (${user.role})`;
}

이 함수는 이름만 보면 문자열을 만드는 순수 계산처럼 보입니다. 하지만 로그와 storage write가 섞여 있습니다. 테스트에서는 문자열만 검증하고 넘어가도, 실제 앱에서는 렌더마다 storage가 갱신되는 문제가 생길 수 있습니다.

리뷰에서는 먼저 이렇게 나눕니다.

js
function formatDisplayName(user) {
  return `${user.name} (${user.role})`;
}

function recordUserView(user) {
  console.log("render user", user.id);
  localStorage.setItem("last-user", user.id);
}

순수 계산과 부수 효과를 분리하면 함수의 역할이 작아지고, 테스트도 명확해집니다.

고차 함수는 관계를 드러낼 때 유용하다

고차 함수는 함수를 받거나 함수를 돌려주는 함수입니다. 중요한 점은 “멋진 문법”이 아니라 반복되는 관계를 드러내는 데 있습니다.

js
const byStatus = (status) => (item) => item.status === status;

const visibleTodos = todos.filter(byStatus("visible"));
const archivedTodos = todos.filter(byStatus("archived"));

여기서는 status 조건을 만드는 반복 규칙이 드러납니다. 반대로 모든 코드를 콜백으로 감싸서 흐름을 끊는다면 오히려 읽기 어려워집니다.

js
run(() => validate(() => submit(() => notify())));

이런 코드는 “단계가 있다”는 사실은 보이지만, 각 단계의 입력과 실패 처리가 흐려집니다. 고차 함수는 흐름을 감추는 장식이 아니라, 반복되는 호출 규칙을 이름 붙이는 도구로 쓰는 편이 안전합니다.

async 함수는 값을 바로 돌려주지 않는다

async function은 항상 Promise를 반환합니다.

js
async function loadUser(id) {
  return fetch(`/api/users/${id}`).then((r) => r.json());
}

const user = loadUser("1");

여기서 user는 실제 사용자 객체가 아니라 Promise입니다. 간단하지만 리뷰에서 자주 보이는 버그입니다. 특히 상태 업데이트와 섞이면 문제가 커집니다.

js
function renderProfile(id) {
  const user = loadUser(id);
  return `<h1>${user.name}</h1>`;
}

이 코드는 타입스크립트를 쓰면 잡히기 쉽지만, 자바스크립트 코드나 느슨한 경계에서는 그대로 들어올 수 있습니다. 리뷰 질문은 “이 함수가 동기 값을 반환하는가, 비동기 작업의 약속을 반환하는가?”입니다.

순수 함수와 부수 효과 shell

프론트엔드 코드에서는 완전히 순수한 앱을 만들 수 없습니다. fetch, DOM, storage, analytics, timer가 필요합니다. 다만 부수 효과를 어디에 둘지는 선택할 수 있습니다.

위치좋은 신호위험 신호
순수 계산 함수입력만으로 결과가 결정됨내부에서 storage, DOM, log를 만짐
이벤트 핸들러부수 효과 시작점이 명확함계산 로직까지 길게 섞임
API wrapper네트워크/파싱/에러 모양이 드러남호출자가 모르는 retry/cache가 숨음
고차 함수반복되는 호출 규칙에 이름을 붙임callback nesting으로 흐름이 흐려짐
async 함수Promise 반환과 실패 처리가 명확함동기 값처럼 호출하거나 에러를 삼킴

핵심은 “부수 효과를 없애자”가 아닙니다. 부수 효과가 시작되는 위치를 코드에서 알아볼 수 있게 하자입니다.

프론트엔드 코드 리뷰 체크리스트

함수 이름이 반환값과 부수 효과를 솔직하게 드러내는가? 값 계산 함수 안에 fetch, DOM, storage, analytics, timer가 섞이지 않았는가? 고차 함수가 반복 규칙을 줄였는가, 아니면 호출 흐름만 숨겼는가? async 함수 반환값을 동기 값처럼 사용하지 않았는가? Promise 실패 경로가 호출자에게 전달되는가, 내부에서 조용히 삼켜지는가? 테스트가 순수 계산만 보는지, 부수 효과 shell까지 필요한 만큼 검증하는지 분리되어 있는가?

함수는 작은 문법 조각이 아니라 아키텍처의 경계입니다. 값을 계산하는 core와 세상을 바꾸는 shell을 나눌수록 리뷰할 때 “무엇이 바뀌고 무엇이 계산되는지”가 선명해집니다.

Day 10 복습 퀴즈

Quiz1 / 4
Q.다음 함수에서 가장 먼저 의심할 점은 무엇일까요?
js
"function getTitle(post) {\n  localStorage.setItem('last-post', post.id);\n  return post.title.trim();\n

Post Q&A

오케이징에게 물어보기

자바스크립트 퀴즈북 리마인드 Day 10: 함수는 값이고 경계다 전체를 기준으로 질문과 피드백을 받아요.답을 본 뒤에는 이 내용을 댓글로 달아서 서징에게도 물어볼 수 있어요. 작성자가 직접 볼 수 있어요!

0/500

포스트 목록

/study/javascript-quizbook
파일 10개, 폴더 0개
자바스크립트 퀴즈북 리마인드 Day 1: 숫자는 왜 가끔 믿을 수 없을까자바스크립트 퀴즈북 리마인드 Day 2: 같은 값인지 묻는 네 가지 방법자바스크립트 퀴즈북 리마인드 Day 3: + 연산자와 ToPrimitive 흐름자바스크립트 퀴즈북 리마인드 Day 4: 프로퍼티 descriptor와 freeze의 경계자바스크립트 퀴즈북 리마인드 Day 5: 참조, 복사, Map/Set의 메모리 감각자바스크립트 퀴즈북 리마인드 Day 6: 스코프 체인과 호이스팅자바스크립트 퀴즈북 리마인드 Day 7: 클로저 버그와 오래된 값자바스크립트 퀴즈북 리마인드 Day 8: 이벤트 루프와 Promise 타이밍자바스크립트 퀴즈북 리마인드 Day 9: this는 호출한 쪽이 정한다자바스크립트 퀴즈북 리마인드 Day 10: 함수는 값이고 경계다

같은 섹션의 대표 이미지

10 posts · latest first
입력, 순수 계산, 출력, 부수 효과 경계를 나누어 함수 설계를 보여주는 다이어그램
Study26. 07. 06.

자바스크립트 퀴즈북 리마인드 Day 10: 함수는 값이고 경계다.

고차 함수, 순수 함수, 부수 효과, async 함수의 Promise 반환을 코드 리뷰에서 어떻게 읽을지 정리합니다.

26. 07. 06.SEOJing
메서드 호출, 분리된 함수, 이벤트 콜백, bind와 arrow function의 this 차이를 보여주는 다이어그램
Study26. 07. 05.

자바스크립트 퀴즈북 리마인드 Day 9: this는 호출한 쪽이.

this 바인딩을 정의 위치가 아니라 호출 형태, 메서드 분리, arrow function, bind 기준으로 읽는 방법을 코드 리뷰 관점에서 정리합니다.

26. 07. 05.SEOJing
콜 스택이 비워진 뒤 마이크로태스크 큐가 먼저 실행되고 다음 태스크로 넘어가는 이벤트 루프 다이어그램
Study26. 07. 04.

자바스크립트 퀴즈북 리마인드 Day 8: 이벤트 루프와.

콜 스택, 태스크 큐, 마이크로태스크 큐를 기준으로 Promise와 setTimeout 실행 순서를 코드 리뷰 관점에서 정리합니다.

26. 07. 04.SEOJing
클로저가 생성 위치의 바인딩을 기억해 나중 실행에서 오래된 값을 읽을 수 있음을 보여주는 다이어그램
Study26. 06. 29.

자바스크립트 퀴즈북 리마인드 Day 7: 클로저 버그와 오래된.

클로저가 값 복사가 아니라 렉시컬 환경 참조라는 점을 stale closure, 루프 콜백, React 이벤트 리뷰 관점에서 정리합니다.

26. 06. 29.SEOJing
스코프 체인과 호이스팅 관계를 단순화한 다이어그램
Study26. 06. 28.

자바스크립트 퀴즈북 리마인드 Day 6: 스코프 체인과 호이스팅.

스코프 체인, 클로저, var/let/const 호이스팅 차이를 콜백·상태 버그 리뷰 관점에서 짧게 정리합니다.

26. 06. 28.SEOJing
JavaScript 객체 참조와 Map, Set, WeakMap의 참조 구조를 비교한 다이어그램
Study26. 06. 27.

자바스크립트 퀴즈북 리마인드 Day 5: 참조, 복사,.

객체 참조와 얕은 복사, Object와 Map/Set의 차이, WeakMap/WeakSet이 필요한 메모리 상황을 프론트엔드 코드 리뷰 관점에서 정리합니다.

26. 06. 27.SEOJing
JavaScript 프로퍼티 descriptor가 data descriptor와 accessor descriptor로 갈라지는 구조 다이어그램
Study26. 06. 26.

자바스크립트 퀴즈북 리마인드 Day 4: 프로퍼티.

객체 프로퍼티를 key/value가 아니라 descriptor로 읽는 법, getter/setter와 defineProperty, preventExtensions/seal/freeze의 경계를 코드 리뷰 관점에서 정리합니다.

26. 06. 26.SEOJing
객체가 ToPrimitive를 거쳐 + 연산자의 문자열 연결 또는 숫자 덧셈으로 갈라지는 흐름 다이어그램
Study26. 06. 25.

자바스크립트 퀴즈북 리마인드 Day 3: + 연산자와.

객체가 원시값으로 바뀌는 ToPrimitive 흐름, + 연산자의 문자열 연결과 숫자 덧셈 분기, Symbol.toPrimitive가 코드 리뷰에서 왜 중요한지 정리합니다.

26. 06. 25.SEOJing
==, ===, Object.is, SameValueZero의 차이를 정리한 JavaScript equality 다이어그램
Study26. 06. 24.

자바스크립트 퀴즈북 리마인드 Day 2: 같은 값인지 묻는 네.

==, ===, Object.is, SameValueZero가 각각 어떤 비교 알고리즘을 쓰는지 정리하고, includes와 indexOf, Map/Set 키 비교에서 생기는 프론트엔드 리뷰 포인트를 잡습니다.

26. 06. 24.SEOJing
JavaScript Number, safe integer, NaN, -0, BigInt를 한 장으로 정리한 다이어그램
Study26. 06. 23.

자바스크립트 퀴즈북 리마인드 Day 1: 숫자는 왜 가끔 믿을.

자바스크립트의 Number가 왜 정수처럼 보여도 부동소수점 모델 위에서 움직이는지, NaN과 -0, safe integer, BigInt를 프론트엔드 코드 리뷰 관점에서 다시 정리합니다.

26. 06. 23.SEOJing