JavaScript: 언어 기초, React Native 및 모바일 개발

저자: IT Sectr 게시일: 2026-02-10 읽는 시간: 11 분

JavaScript는 하이브리드 모바일 기술의 전체 클래스의 기초가 된 프로그래밍 언어입니다. React Native, Ionic, Apache Cordova 및 기타 많은 프레임워크는 웹 개발과 통합된 기술 스택을 사용하여 JS로 모바일 애플리케이션을 만들 수 있게 합니다. 동시에 JavaScript는 Stack Overflow 설문조사(2025)에 따르면 10년 연속으로 가장 많이 사용되는 프로그래밍 언어로 남아 있습니다. 자세한 내용은 Stack Overflow 설문조사 결과를 참조하세요.

주요 포인트

  • JavaScript — 하이브리드 모바일 개발의 기초가 된 웹의 언어
  • React Native — 네이티브 컴포넌트와 JS 브리지를 통한 네이티브 UI 렌더링
  • Ionic/Cordova — 컨테이너 내 HTML/CSS/JS를 사용한 WebView 접근 방식
  • 비동기성 — 논블로킹 I/O를 위한 event loop, Promise, async/await
  • Node.js — JS를 브라우저 너머로 확장하는 서버측 플랫폼

JavaScript란?

JavaScript(JS)는 동적 타이핑, 프로토타입 기반 상속 및 일급 객체로서의 함수를 갖는 고수준 프로그래밍 언어입니다. 1995년 Brendan Eich가 10일 만에 만들었습니다. 웹 기술(HTML, CSS, JS)의 세 가지 주요 언어 중 하나이며, JS를 브라우저 밖으로 나갈 수 있게 한 Node.js 서버 플랫폼(2009)의 기초입니다.

모바일 개발에서 JavaScript는 세 가지 패러다임으로 사용됩니다: 네이티브 컴파일(Hermes/JSC를 사용한 React Native), WebView 컨테이너(Ionic, Cordova), 서버측 JS(모바일 앱 백엔드를 위한 Node.js + Express). React Native가 지배적인 기술입니다: Statista(2025)에 따르면 크로스 플랫폼 프로젝트의 38%가 React Native를 사용하며, Flutter(46%)에 이어 두 번째입니다.

JavaScript의 주요 특징은 논블로킹 I/O를 갖춘 단일 스레드 실행 모델입니다. 이벤트 루프는 OS 스레드를 생성하지 않고 단일 스레드에서 수천 개의 비동기 작업을 처리할 수 있습니다. 이는 JS를 I/O 집약적 애플리케이션(네트워크 요청, 데이터베이스 작업)에 효율적으로 만들지만, CPU 집약적 계산에는 주의가 필요합니다.

JavaScript 표준: ES5, ES6, ES2025

ECMAScript(ES) 표준은 JavaScript 사양을 정의합니다. ES6(2015)는 let/const, 화살표 함수, 클래스, 모듈, Promise를 도입했습니다. ES2020 — Optional Chaining(?.), Nullish Coalescing(??). ES2023 — Array findLast, Hashbang Grammar. 최신 엔진 Hermes(React Native)와 V8(Node.js)은 ES2022+를 지원합니다. React Native Hermes는 Proxy와 Symbol에 일부 제한이 있지만 ES2020+를 지원합니다.

ES 버전연도주요 기능RN 지원
ES62015let/const, Promise, class, modules, arrow functions완전
ES82017async/await, Object.entries완전
ES20202020Optional Chaining, Nullish Coalescing, BigInt완전
ES20222022Top-level await, .at(), Error CauseHermes 제한적

JavaScript 구문: 타입, 함수 및 프로토타입

JavaScript 구문은 C와 유사하며 동적 타입입니다. 변수의 타입은 값에 의해 결정되며 런타임에 변경될 수 있습니다. let과 const(ES6)는 블록 스코프를 위해 var를 대체했습니다. 원시 타입: string, number, boolean, null, undefined, symbol, bigint. 나머지는 모두 객체입니다(object, array, function, date, regexp).

일급 객체로서의 함수

JavaScript는 고차 함수를 가진 언어입니다. 함수는 변수에 할당되고, 인수로 전달되고, 다른 함수에서 반환될 수 있습니다. 화살표 함수(=>)는 자체 this가 없으며 — 외부 컨텍스트에서 this를 상속합니다. 클로저는 생성된 스코프의 변수를 기억하는 함수입니다.

javascript
// JavaScript의 데이터 타입과 함수
// 원시 타입
const name = 'React Native';
let version = 0.71;
var isActive = true; // 구식 var

// 객체와 배열
const app = {
  platform: 'iOS',
  version: 15,
  getInfo() {
    return `${this.platform} ${this.version}`;
  }
};

const items = ['Dart', 'Kotlin', 'Swift'];

// 고차 함수
function filterByVersion(apps, minVersion) {
  return apps.filter(app => app.version >= minVersion);
}

// 클로저
function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

// 객체 복사를 위한 스프레드 연산자
const newApp = { ...app, version: 16 };

스프레드 연산자 ...는 객체의 얕은 복사본을 만듭니다. 구조 분해(const { platform, version } = app)는 필드를 변수로 추출합니다. filterByVersion의 화살표 함수는 function 표현식보다 짧고 자체 this를 만들지 않습니다 — this가 컴포넌트 클래스를 참조하는 React Native 컴포넌트에서 중요합니다.

프로토타입 기반 상속

JavaScript는 Java나 C#처럼 클래스 기반이 아닌 프로토타입 기반 상속을 사용합니다. 클래스(ES6)는 프로토타입 위의 문법적 설탕입니다. 모든 객체는 다른 객체에 대한 내부 [[Prototype]] 참조를 가집니다. 객체에 없는 속성에 접근할 때 JS는 프로토타입 체인에서 찾습니다. 클래스 구문(extends, super)은 코드를 더 읽기 쉽게 하지만 내부는 프로토타입으로 유지됩니다.

javascript
// JavaScript의 클래스 — 문법적 설탕
class PlatformService {
  // 비공개 필드(ES2022)
  #apiKey;

  constructor(name, apiKey) {
    this.name = name;
    this.#apiKey = apiKey;
  }

  // 정적 메서드
  static getPlatforms() {
    return ['iOS', 'Android'];
  }

  // 게터
  get info() {
    return `${this.name} SDK`;
  }

  // 비동기 메서드
  async initialize() {
    return await this.#validateKey();
  }

  #validateKey() {
    return this.#apiKey.length > 10;
  }
}

// 상속
class AndroidService extends PlatformService {
  constructor(apiKey) {
    super('Android', apiKey);
  }
}

비공개 필드 #apiKey(ES2022)는 _언더스코어 규칙으로는 불가능했던 진정한 캡슐화를 제공합니다. 정적 메서드 getPlatforms는 인스턴스가 아닌 클래스에 속합니다. 게터 info는 접근 시 계산됩니다. async/await는 비동기 코드를 선형으로 만듭니다. React Native Hermes는 버전 0.71부터 비공개 필드를 지원합니다.

JavaScript의 비동기성: Event Loop 및 Promise

JavaScript의 비동기성은 이벤트 루프를 기반으로 합니다 — 호출 스택과 작업 큐를 확인하는 무한 루프입니다. 호출 스택은 동기 코드를 처리하고, 마이크로태스크 큐는 Promise.then/catch/finally를 처리하며, 매크로태스크 큐는 setTimeout, setInterval, I/O를 처리합니다. 이벤트 루프는 먼저 마이크로태스크에서, 그 다음 매크로태스크에서 작업을 가져옵니다. 호출 스택 차단(무한 루프)은 전체 UI를 중지시킵니다.

Promise는 미래 값을 나타내는 객체입니다. 프로미스는 pending(대기 중), fulfilled(이행됨), rejected(거부됨) 상태가 될 수 있습니다. .then().catch().finally() 체인은 비동기 결과를 처리합니다. async/await(ES8)는 문법적 설탕입니다: async 함수는 Promise를 반환하고, await는 스레드를 차단하지 않고 프로미스가 해결될 때까지 실행을 일시 중지합니다.

javascript
// React Native의 비동기 데이터 로딩
import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;

    async function fetchUser() {
      try {
        const response = await fetch(
          `https://api.example.com/users/${userId}`
        );

        if (!response.ok) {
          throw new Error('Network error');
        }

        const data = await response.json();

        if (!cancelled) {
          setUser(data);
          setLoading(false);
        }
      } catch (error) {
        if (!cancelled) {
          console.error('가져오기 실패:', error);
          setLoading(false);
        }
      }
    }

    fetchUser();

    return () => { cancelled = true; };
  }, [userId]);

  if (loading) return <ActivityIndicator />;

  return (
    <View>
      <Text>{user?.name ?? 'Unknown'}</Text>
    </View>
  );
}

useEffect 훅과 async fetchUser 함수는 컴포넌트 마운트 시 HTTP 요청을 수행합니다. cancelled 플래그는 마운트 해제 후 setState를 방지합니다 — 일반적인 React Native 문제입니다. Optional Chaining user?.name과 Nullish Coalescing ??는 오류 없이 undefined를 처리합니다. ActivityIndicator는 로딩 중에 표시됩니다 — 모든 JS 개발자에게 익숙한 비동기 패턴입니다.

React Native: 모바일 플랫폼의 JavaScript

React Native는 JavaScript로 네이티브 모바일 애플리케이션을 만들기 위한 Meta(Facebook)의 프레임워크입니다. WebView 접근 방식과 달리 React Native는 실제 네이티브 컴포넌트(iOS의 경우 UIView, Android의 경우 ViewGroup)를 렌더링합니다. JS 코드는 별도 스레드(Hermes 또는 JSC)에서 실행되며 Bridge(이전 아키텍처) 또는 JSI(새로운 Fabric 아키텍처)를 통해 네이티브 UI 스레드와 통신합니다.

React Native 아키텍처

React Native는 JS 스레드(코드), 네이티브 스레드(UI) 및 상호 작용을 위한 Bridge/JSI로 구성됩니다. 이전 아키텍처(Bridge)에서는 JSON 메시지가 직렬화되어 비동기적으로 전송됩니다 — 이는 빠른 애니메이션 중 지연을 만듭니다. 새로운 Fabric 아키텍처(React Native 0.68+)는 JSI(JavaScript Interface)를 사용합니다 — 직렬화 없이 C++ 객체와 직접 JS 상호 작용.

javascript
// 네이티브 API를 사용한 React Native 컴포넌트
import React, { useState, useEffect } from 'react';
import {
  View, Text, TouchableOpacity, Platform,
  PermissionsAndroid, Alert
} from 'react-native';
import Geolocation from '@react-native-community/geolocation';

function LocationTracker() {
  const [location, setLocation] = useState(null);

  useEffect(() => {
    requestLocationPermission();
  }, []);

  async function requestLocationPermission() {
    if (Platform.OS === 'android') {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
      );
      if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
        Alert.alert('Permission denied');
        return;
      }
    }
    getCurrentPosition();
  }

  function getCurrentPosition() {
    Geolocation.getCurrentPosition(
      pos => setLocation({
        lat: pos.coords.latitude,
        lng: pos.coords.longitude
      }),
      error => Alert.alert('Error', error.message),
      { enableHighAccuracy: true, timeout: 15000 }
    );
  }

  return (
    <View>
      <Text>Lat: {location?.lat ?? 'N/A'}</Text>
      <Text>Lng: {location?.lng ?? 'N/A'}</Text>
      <TouchableOpacity onPress={getCurrentPosition}>
        <Text>Update Location</Text>
      </TouchableOpacity>
    </View>
  );
}

LocationTracker 컴포넌트는 네이티브 위치 정보 API 작업을 보여줍니다. Platform.OS는 Android와 iOS를 구분합니다. PermissionsAndroid.request는 네이티브 Android 권한 대화상자입니다. Geolocation.getCurrentPosition — @react-native-community/geolocation의 모듈로, npm을 통해 설치합니다. React Native는 카메라, 블루투스, 가속도계 및 기타 센서용 JS 인터페이스를 제공합니다.

Ionic 및 Cordova: WebView 컨테이너

Ionic은 HTML/CSS/JS를 렌더링하기 위해 WebView를 사용하는 하이브리드 모바일 애플리케이션용 프레임워크입니다. React Native와 달리 Ionic은 네이티브 컴포넌트를 만들지 않습니다 — 애플리케이션은 iOS(WKWebView) 및 Android(Android WebView)의 웹 컨테이너(WebView) 내에서 실행됩니다. 이는 웹 코드의 100% 재사용을 제공하지만 복잡한 애니메이션의 성능을 제한합니다.

Apache Cordova는 Ionic의 기반으로, JavaScript 플러그인을 통해 네이티브 API에 대한 액세스를 제공합니다. 카메라, GPS, 연락처, 파일 시스템 — 모든 것이 cordova-plugin-*을 통해 사용 가능합니다. Ionic 7+는 Capacitor를 사용합니다 — Cordova의 후속 제품으로, 더 나은 성능, ESM 지원 및 Swift와 Kotlin을 통한 iOS/Android SDK 직접 액세스를 제공합니다.

특성React NativeIonic(Capacitor)Cordova
UI 렌더링네이티브 컴포넌트WebView(WKWebView)WebView
언어JS/TSJS/TS + HTML/CSSJS/TS + HTML/CSS
네이티브 APIBridge/JSI + 모듈Capacitor PluginsCordova Plugins
성능높음(60FPS)중간(WebView에 따라 다름)중간
APK 크기~25-40MB~10-15MB~8-12MB
코드 재사용~60% 코드~95% 코드(웹 버전 포함)~95%

JavaScript 개발자 도구

모바일 애플리케이션을 위한 JS 개발자 도구에는 Node.js, npm/yarn, Expo, React Native CLI 및 Metro 번들러가 포함됩니다. Node.js는 브라우저 외부의 JS 런타임으로, 생태계의 기초입니다. npm(Node Package Manager)은 200만 개 이상의 라이브러리를 가진 패키지 관리자입니다. npx는 설치 없이 npm 패키지를 실행하는 유틸리티입니다.

도구 생태계

Expo는 React Native 위의 계층으로 개발을 단순화합니다: 시작하는 데 Xcode/Android Studio가 필요하지 않으며, 사전 설치된 라이브러리로 Managed Workflow를 제공합니다. Expo Application Services(EAS) — 클라우드에서 빌드 및 게시. Metro는 JS 코드와 종속성을 하나의 파일로 모으는 React Native 번들러입니다. Hermes는 AOT 컴파일로 모바일 장치에 최적화된 Meta의 JS 엔진입니다.

javascript
// package.json — React Native 프로젝트 구성
{
  "name": "MyMobileApp",
  "version": "1.0.0",
  "scripts": {
    "start": "npx react-native start",
    "android": "npx react-native run-android",
    "ios": "npx react-native run-ios",
    "test": "jest",
    "lint": "eslint . --ext .ts,.tsx"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-native": "^0.73.0",
    "@react-navigation/native": "^6.1.0",
    "@react-native-community/geolocation": "^3.2.0"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "eslint": "^8.56.0",
    "metro-react-native-babel-preset": "^0.77.0"
  }
}

package.json 파일은 모든 JS 프로젝트의 기초입니다. start, android, ios 스크립트는 Metro 번들러와 빌드를 시작합니다. 종속성은 dependencies(런타임)와 devDependencies(테스트, 린터)로 나뉩니다. React Navigation은 표준 라우터입니다. Jest는 테스트 프레임워크입니다. ESLint는 코드 스타일과 잠재적 오류를 검사하는 정적 분석기입니다.

자주 묻는 질문

JavaScript란?

JavaScript(JS)는 동적 타이핑, 프로토타입 기반 상속 및 단일 스레드 이벤트 루프 모델을 가진 프로그래밍 언어입니다. 1995년에 만들어졌습니다. 모바일 개발에서는 React Native(네이티브 컴포넌트 + JS 로직)와 Ionic(WebView 컨테이너)을 통해 사용됩니다. Stack Overflow 데이터에 따르면 10년 연속 가장 많이 사용되는 언어입니다.

React Native에서 JavaScript는 어떻게 작동하나요?

React Native는 JS를 별도 스레드(Hermes 또는 JSC)에서 실행합니다. JS 스레드는 로직과 상태를 관리하고, 네이티브 스레드는 UI 컴포넌트를 렌더링합니다. 데이터 교환은 Bridge(이전 아키텍처, JSON 직렬화) 또는 JSI(새로운 Fabric 아키텍처, 직접 C++ 액세스)를 통해 이루어집니다. Hermes는 AOT 컴파일로 시작 시간을 50% 줄이는 Meta의 JS 엔진입니다.

JavaScript와 TypeScript의 차이점은?

JavaScript는 동적 타입 — 타입이 런타임에 확인됩니다. TypeScript는 컴파일 시간 확인, 인터페이스, 제네릭 및 열거형을 갖춘 정적 타이핑을 추가합니다. 모든 JS 코드는 유효한 TypeScript입니다. TS는 tsc 또는 Babel을 통해 순수 JS로 컴파일(트랜스파일)됩니다. React Native에서 TS는 새로운 프로젝트의 약 65%에서 사용됩니다.

어떤 모바일 프레임워크가 JavaScript를 사용하나요?

주요: React Native(Meta) — Bridge/Fabric을 갖춘 네이티브 렌더링 플랫폼. Ionic(Capacitor) — 플러그인을 통해 네이티브 API에 액세스할 수 있는 WebView 컨테이너. Apache Cordova — Ionic의 전신, 역시 WebView. NativeScript — WebView 없이 네이티브 API에 직접 액세스. Expo — 네이티브 빌드 설정 없이 빠른 프로토타이핑을 위한 React Native 위의 계층.

JavaScript의 비동기성이란?

JS 비동기성은 이벤트 루프를 기반으로 합니다: 호출 스택(동기 코드) → 마이크로태스크 큐(Promise.then) → 매크로태스크 큐(setTimeout, I/O). Promise는 비동기 작업을 위한 객체입니다. async/await는 Promise 위의 문법적 설탕입니다. 단일 스레드 모델은 UI를 차단하지 않지만, CPU 집약적 작업에는 Web Workers 또는 별도 스레드가 필요합니다(React Native에서는 InteractionManager).

요약

  • JavaScript — React Native 및 Ionic을 통한 하이브리드 모바일 개발을 위한 범용 언어
  • React Native는 별도 스레드의 JS 로직으로 Bridge/JSI를 통해 네이티브 컴포넌트를 렌더링
  • Event Loop — 논블로킹 I/O를 위한 Promise와 async/await를 갖춘 단일 스레드 비동기 모델
  • Hermes — AOT 컴파일을 갖춘 Meta의 JS 엔진, React Native에서 사용
  • Ionic/Capacitor — 95% 웹 코드 재사용을 제공하는 WebView 접근 방식
  • npm — JS용 200만 개 이상의 라이브러리를 가진 가장 큰 패키지 관리자
  • Expo — 네이티브 빌드 구성 없이 가속화된 개발을 위한 React Native 위의 계층

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기