본문 바로가기

JavaScript

브라우저 간 API 차이, Shim으로 통합하기

안녕하세요 :)

 

개발을 하다보면 같은 기능인데 브라우저마다 API 메서드나 함수명이 다른 경우가 있습니다. 이때는 코드가 특정 브라우저에서만 작동하거나, 오류를 발생시킬 수 있기 때문에, 개발자가 골치 아픈 상황에 처하게 되죠.

출처: https://technologyadvice.com/blog/information-technology/how-to-use-an-api/

이런 문제를 해결하기 위해서는 어떻게 해야 할까요?

문제 해결을 위한 개념이 'Shim(심)'이라는 개념인데요. 오늘은 이 Shim에 대해 알아보겠습니다.

 

Shim이란?

Shim은 브라우저 간의 API 차이를 해결하기 위해 사용되는 '코드 작성 방식'입니다. 브라우저마다 다르게 구현된 함수나 메서드를 하나의 일관된 표준 API 형식으로 통합해줍니다. 이를 통해, 모든 브라우저에서 동일한 코드로 기능을 사용할 수 있죠.

출처: https://frontend.turing.edu/lessons/module-2/cross-browser-compat.html

 

Shim이라는 개념은 무슨 역할을 할까요?

1. 특정 기능이 브라우저에서 지원되지 않을 경우, 다른 대체 방식을 제공하고

2. 브라우저별 차이를 표준 방식으로 통합해줍니다.

3. 이로 인해, 개발자가 브라우저별 차이를 신경쓰지 않고 표준 API만 사용하도록 도움을 주죠.

 

예시를 살펴보겠습니다.

 

Shim 예시

이 예시는 실시간 커뮤니케이션 WebRTC API의 getUserMedia를 사용할 때의 Shim 예시입니다.

if (!navigator.mediaDevices) {
  navigator.mediaDevices = {}; // 지원하지 않으면 mediaDevices 객체 생성
}

if (!navigator.mediaDevices.getUserMedia) {
  navigator.mediaDevices.getUserMedia = function (constraints) {
    const getUserMedia =
      navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // 브라우저별 비표준 API 체크

    if (!getUserMedia) {
      return Promise.reject(new Error("getUserMedia is not supported")); // 지원하지 않으면 에러 반환
    }

    return new Promise((resolve, reject) => {
      getUserMedia.call(navigator, constraints, resolve, reject); // 비표준 API를 호출해 표준처럼 동작
    });
  };
}

// 이제 모든 브라우저에서 동일한 방식으로 사용 가능
navigator.mediaDevices.getUserMedia({ video: true })
  .then((stream) => {
    console.log("Video stream:", stream); // 성공적으로 비디오 스트림 반환
  })
  .catch((error) => {
    console.error("Error accessing media devices:", error); // 에러 처리
  });

 

하나하나 뜯어가며 예시 코드를 볼까요?

 

1. navigator.mediaDevice 지원 여부 확인

if (!navigator.mediaDevices) {
  navigator.mediaDevices = {}; // 지원하지 않으면 mediaDevices 객체 생성
}
  • navigator.mediaDevices는 최신 브라우저에서 사용 가능한 표준 객체입니다.
  • 이 코드에서 먼저 브라우저가 navigator.mediaDevices를 지원하는지 확인합니다.
  • 만약 지원하지 않는다면? mediaDevices라는 빈 객체를 생성하여 Shim에서 사용할 준비를 합니다.

2. getUserMedia 메서드 지원 여부 확인

if (!navigator.mediaDevices.getUserMedia) {
  navigator.mediaDevices.getUserMedia = function (constraints) {
    const getUserMedia =
      navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // 브라우저별 비표준 API 확인
  • 표준 메서드인 getUserMedia가 브라우저에 존재하지 않으면, 이를 대신할 비표준 API를 확인합니다.
  • 크롬에서는 webitGetUserMedia, 파이어폭스에서는 mozGetUserMedia라는 이름으로 구현되어 있는데요.
  • 브라우저별 비표준 API를 이렇게 확인하고, getUserMedia로 할당합니다.
  • 만약 두 API 모두 없는 경우, 아래 코드에서 에러를 반환하게 됩니다.

3. 비표준 API가 없을 때

    if (!getUserMedia) {
      return Promise.reject(new Error("getUserMedia is not supported")); // 지원하지 않으면 에러 반환
    }
  • 브라우저가 getUserMedia를 지원하지 않는다면, Promise를 거부(reject)하면서 "getUserMedia is not supported"라는 에러 메시지를 반환하게 됩니다.
  • 이렇게 하면 브라우저에서 이 기능이 완전히 비활성화된 경우도 적절히 처리할 수 있죠.

4. 비표준 API를 표준 방식으로 호출

    return new Promise((resolve, reject) => {
      getUserMedia.call(navigator, constraints, resolve, reject); // 비표준 API 호출
    });
  };
}
  • 브라우저가 제공하는 비표준 API(getUserMedia)를 호출하여 표준 방식으로 동작하도록 처리합니다.
  • getUserMedia.call을 통해 constraints, 성공 시 resolve, 실패 시, reject를 전달합니다.
  • constraints는 비디오나 오디오 스트림을 요청할 때 카메라 해상도, 프레임 속도, 오디오 설정 등 미디어 입력 장치의 요구 사항을 지정하는 조건 객체입니다.
  • 아무튼, 이렇게 Promise로 반환하여, 최신 브라우저의 표준 API 방식과 동일하게 사용할 수 있게 만듭니다.

5. 통합된 표준 API 사용

navigator.mediaDevices.getUserMedia({ video: true })
  .then((stream) => {
    console.log("Video stream:", stream); // 성공적으로 비디오 스트림 반환
  })
  .catch((error) => {
    console.error("Error accessing media devices:", error); // 에러 처리
  });
  • 이제 Shim 덕분에 navigator.mediaDevices.getUserMedia라는 표준 형식으로 호출이 가능해졌습니다.
  • 브라우저 간의 차이를 걱정할 필요 없이 동일한 방식으로 사용이 가능해진 것이죠.
  • 호출 성공 시, 비디오 스트림이 반환되고, stream객체는 카메라에서 가져온 미디어 데이터를 포함합니다.
  • 또한, 실패 시, 에러가 출력되게 됩니다.

 

Shim을 사용하면?

Shim을 사용하면 브라우저 간 차이를 해결하고, 아래와 같은 장점을 얻을 수 있습니다.

  1. 모든 브라우저에서 동일한 API를 사용할 수 있습니다.
  2. 브라우저별 조건을 처리하는 코드를 한 곳에 모아 관리할 수 있습니다.
  3. 표준화된 방식으로 코드 작성이 가능합니다.

예를 들어, 위의 getUserMedia 코드를 Shim 방식으로 작성하면, 브라우저마다 다른 방식의 API를 호출할 필요없이 항상 navigator.mediaDevices.getUserMedia만 호출하면 되는 것이죠.

 

Shim이라는게, 코드를 작성하는 방식이고, 직접 작성하거나, WebRTC에서 사용하는 adapter.js처럼 이미 만들어진 라이브러리를 가져다 사용할 수도 있습니다.

 

끝내는 말

오늘은 코드 표준화 방식인 Shim에 대해 글을 작성해봤습니다. Shim을 조금 긴 한 마디로 정리하면, '브라우저마다 다른 기능이나 메서드 구현 방식을 하나의 표준 인터페이스로 통일하여, 개발자가 환경 차이를 신경쓰지 않고 코드를 작성할 수 있게 해주는 방식'입니다.

 

Shim을 활용하면 복잡한 브라우저 호환성을 조금은 해결할 수 있기 때문에, 알고 있으면 나중에 유용하게 쓰지 않을까요?

읽어주셔서 감사합니다 :)

'JavaScript' 카테고리의 다른 글

WebPack 설치 및 설정하기  (4) 2024.12.13
WebPack이란 무엇인가? 기본 파헤치기  (6) 2024.12.11
함수 스코프와 블록 스코프  (3) 2024.11.12
console.log? console.error? 무슨 차이일까?  (1) 2024.11.10
npm은 뭘까?  (1) 2024.11.09