← 블로그로 돌아가기

Vue Composition API와 클로저 완전 정복 — 왜 파라미터 없이도 접근 가능할까?

Vue 3의 Composition API에서는 왜 setup 함수 안의 변수를 파라미터 없이 접근할 수 있는지 클로저 개념과 함께 설명합니다.

Vue 3를 공부하다 보면, setup() 함수 안에서 선언한 변수를 다른 함수에서 파라미터 없이도 사용하는 코드를 자주 보게 됩니다.

예를 들어, 이런 코드입니다:

export default {
  setup() {
    const inputData = ref({ name: '', age: '' });

    function submitForm() {
      console.log(inputData.value); // inputData를 파라미터로 넘기지 않았는데 접근 가능?
    }

    return {
      inputData,
      submitForm
    }
  }
}

이 코드를 처음 보면 의문이 들 수 있어요.

❓ “submitForm 함수 안에서 inputData를 썼는데, 파라미터로 넘긴 적도 없고 import한 것도 아닌데 어떻게 접근하지?”

그 비밀은 바로 Vue의 Composition API 구조JavaScript의 클로저(closure) 개념에 있습니다.
이 글에서는 이 개념들을 천천히, 자세히 설명해볼게요.


📌 목차

  1. Composition API란 무엇인가?
  2. setup 함수와 변수 선언의 범위
  3. JavaScript의 클로저(closure)란?
  4. 파라미터 없이도 접근 가능한 이유
  5. Composition API vs Options API: 언제 무엇을 쓸까?
  6. 마무리 정리

1. 🎨 Composition API란 무엇인가?

Composition API는 Vue 3에서 도입된 새로운 방식으로, 기존 Vue 2의 Options API 방식과 다르게 컴포넌트의 상태와 로직을 setup() 함수 안에 모아서 작성합니다.

기존에는 data(), methods, computed 등으로 구조를 역할별로 나누었다면,
Composition API는 기능 중심으로 관련된 코드끼리 묶을 수 있는 방식입니다.

📌 기존 Options API 예시

export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increase() {
      this.count++;
    }
  }
}

🔧 Composition API 예시

import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    const increase = () => {
      count.value++;
    };

    return {
      count,
      increase
    };
  }
}

Composition API에서는 ref, reactive를 사용해 상태를 만들고,
함수 안에서도 count.value처럼 .value를 통해 값에 접근합니다.


2. 🧠 setup 함수와 변수 선언의 범위

Composition API의 핵심은 setup() 함수입니다.
이 함수 안에서 선언된 변수와 함수는 모두 같은 스코프(scope) 안에 있습니다.

예를 들어 아래 코드에서는:

setup() {
  const message = ref('Hello World');

  function showMessage() {
    console.log(message.value);
  }

  return { message, showMessage };
}

showMessage()는 같은 setup() 함수 안에서 선언된 message에 접근할 수 있어요.
이건 단순히 Vue의 기능이 아니라, JavaScript의 스코프와 클로저 개념이 작동하는 거예요.


3. 💡 클로저(Closure)란?

클로저란, 함수가 선언된 위치 기준으로 바깥에 있는 변수들을 기억하고 사용할 수 있는 특성을 말합니다.

function outer() {
  const greeting = "Hello";

  function inner() {
    console.log(greeting); // greeting은 inner 함수에서 선언하지 않았는데도 접근 가능!
  }

  return inner;
}

const myFunc = outer();
myFunc(); // "Hello" 출력됨

이 개념은 Vue의 Composition API에서도 그대로 적용돼요.


4. ❓ 왜 submitForm에서 inputData를 파라미터 없이 사용할 수 있을까?

다시 돌아가서 이 코드를 보자면:

setup() {
  const inputData = ref({ name: '', age: '' });

  function submitForm() {
    console.log(inputData.value); // 왜 접근 가능할까?
  }

  return { inputData, submitForm };
}

이 코드에서 submitForm() 함수는 setup() 함수 안에서 선언되었죠.
그리고 inputData도 같은 setup() 안에서 선언되었습니다.

🧠 “submitForm 함수는 바깥 스코프(inputData가 선언된 곳)를 기억하고 있다.”
→ 즉, submitForm 함수는 클로저이고, inputData는 그 클로저가 기억하는 변수입니다.

그래서 파라미터로 넘기지 않아도, 그냥 사용할 수 있는 거예요.


📦 정리하면 이렇게 볼 수 있어요:

setup() 함수 = 하나의 방 🏠
inputData = 그 방 안에 놓인 책 📖
submitForm = 그 방 안에 있는 사람 🧑

그 사람은 굳이 책을 누가 들고 와주지 않아도
자기가 직접 방 안의 책을 꺼내볼 수 있어요!

5. 🔄 Composition API vs Options API: 언제 어떤 걸 쓰는 게 좋을까?

Composition API가 강력한 건 맞지만, 무조건 좋은 건 아닙니다.
상황에 따라 Options API가 더 나을 때도 있어요.

항목 Composition API Options API
코드 구조 로직 중심 역할 중심 (data, methods, computed)
재사용성 매우 뛰어남 (composable 가능) 낮음
가독성 복잡한 기능 분리에 유리 작고 단순한 컴포넌트에 유리
학습 난이도 약간 높음 (ref, reactive, value 등) Vue 초보자에게 친숙
TypeScript 활용 훨씬 강력 상대적으로 제한적

✅ Composition API를 쓰면 좋은 상황

  • 공통 로직을 여러 컴포넌트에서 재사용하고 싶을 때
  • 상태와 이벤트가 많은 복잡한 컴포넌트를 만들 때
  • TypeScript 기반으로 개발할 때
  • 기능 단위로 코드를 깔끔하게 정리하고 싶을 때

✅ Options API가 더 나은 상황

  • 작은 기능의 단순한 컴포넌트를 만들 때
  • Vue에 익숙하지 않은 팀원과 협업할 때
  • 빠르게 시제품(프로토타입)을 만들 때

✅ 6. 마무리 정리

Vue의 Composition API는 유연하고 강력합니다.
그리고 그 힘의 배경에는 JavaScript의 클로저가 숨어 있습니다.

setup() 함수 안에서 만든 함수는 setup() 안에 선언된 변수에 파라미터 없이 접근 가능하다.
그 이유는 바로 클로저(Closure) 덕분이다.

Vue 3에서는 Composition API와 Options API를 함께 사용할 수 있으니,
컴포넌트의 규모, 목적, 팀의 숙련도에 따라 적절히 선택하는 것이 가장 좋은 전략입니다.


📘 부록: 최종 예제 코드

import { ref } from 'vue';

export default {
  setup() {
    const inputData = ref({ name: '', age: '' });

    function submitForm() {
      console.log('사용자 입력 데이터:', inputData.value);
    }

    return {
      inputData,
      submitForm
    }
  }
}

도움이 되셨다면 댓글이나 공감 부탁드립니다 😊