동적 프로그래밍 언어의 원숭이 패치: JavaScript 예

자바스크립트
동적 프로그래밍
동적 프로그래밍 언어의 원숭이 패치 cover image

소개

이 기사에서는 동적 및 정적 프로그래밍 언어의 개념, 둘 사이의 주요 차이점, 장점과 함정 측면에서 각 패러다임이 제공하는 내용을 살펴보겠습니다. 이 탐색에서는 동적 프로그래밍 언어, 특히 이 언어가 지원하는 필수 패턴 중 하나인 Monkey Patch에 더 중점을 둘 것입니다. 이 패턴은 JavaScript의 ​​예제를 통해 소개됩니다.

동적 프로그래밍 언어와 정적 프로그래밍 언어

용어

동적 언어 또는 정적 언어를 구성하는 것이 무엇인지 이해하려면 이 맥락에서 일반적으로 사용되는 몇 가지 주요 용어인 컴파일 시간, 런타임 및 **유형 검사*에 대한 이해를 확립해야 합니다. *.

컴파일과 런타임은 컴파일 시간부터 시작하여 컴퓨터 프로그램 수명주기의 여러 단계에 해당하는 두 가지 용어입니다.

컴파일 시간

컴파일 시간은 프로그램 수명주기의 첫 번째 단계입니다. 개발자는 주어진 프로그래밍 언어로 코드를 작성합니다. 종종 기계는 고급 언어로 작성된 코드를 이해할 수 없으므로 전용 컴파일러를 사용하여 이를 실행할 준비가 된 하위 수준 중간 형식으로 변환합니다.

런타임

런타임은 일반적으로 명령과 함께 실행에 필요한 리소스를 할당하여 프로그램을 메모리에 로드한 다음 해당 명령의 순서에 따라 프로그램을 실행하는 두 단계로 캡슐화됩니다.

다음 다이어그램은 이 프로세스를 보여줍니다.

유형 확인

유형 검사는 거의 모든 프로그래밍 언어에 내장된 기능입니다. 주어진 변수에 할당된 값이 해당 변수의 올바른 유형에 해당하는지 확인하는 기능입니다. 각 프로그래밍 언어에는 메모리에서 특정 유형의 값을 표현하는 방법이 다릅니다. 이러한 다양한 표현을 통해 값 유형과 해당 값을 할당하려는 변수 유형 간의 일치성을 확인할 수 있습니다.

이제 프로그램 수명주기와 유형 검사에 대해 높은 수준으로 이해했으므로 정적 프로그래밍 언어를 탐색할 수 있습니다.

정적 프로그래밍 언어

정적 유형 언어라고도 하는 정적 프로그래밍 언어는 컴파일 단계에서 언급한 유형 검사를 적용하는 언어입니다. 이는 사실상 변수가 선언에서 해당 유형을 유지하고 선언 유형의 값 외에는 어떤 값도 변수에 할당할 수 없음을 의미합니다. 정적 프로그래밍 언어는 유형을 처리할 때 추가적인 안전성을 제공하지만 이것이 가혹한 제한이 되는 특정 사용 사례에서는 개발 프로세스를 느리게 할 수 있습니다.

동적 프로그래밍 언어

반면 동적 프로그래밍 언어는 런타임에 유형 검사를 적용합니다. 이는 모든 변수가 프로그램의 어느 지점에서나 모든 값을 보유할 수 있음을 의미합니다. 이는 개발자에게 정적 언어에는 없는 유연성 수준을 제공하므로 유익할 수 있습니다. 동적 언어는 각 변수의 유형을 동적으로 파악하는 추가 단계를 포함하므로 정적 언어보다 실행 속도가 느린 경향이 있습니다.

원숭이 패치

정적 타이핑과 동적 타이핑은 프로그래밍 언어의 기본 특성입니다. 하나의 패러다임을 다른 패러다임과 비교하면 개발 품질과 속도를 크게 향상시킬 수 있는 다양한 패턴과 방식이 가능해집니다. 또한 디자인 결정을 내릴 때 신중하게 고려하지 않으면 많은 제한 사항과 안티 패턴이 발생할 수 있습니다.

특히 동적 유형 프로그래밍 언어는 변수를 단일 유형으로 제한하지 않기 때문에 더 높은 수준의 유연성을 제공하는 것으로 알려져 있습니다. 이러한 유연성에는 예측할 수 없는 동작이 발생하지 않도록 프로그램을 구현하고 디버깅할 때 개발자의 책임이 추가로 발생합니다. 원숭이 패치 패턴은 이러한 철학에서 비롯되었습니다.

Monkey Patch는 런타임 시 구성 요소의 작동을 확장/변경하는 프로세스를 나타냅니다. 문제의 구성 요소는 라이브러리, 클래스, 메서드 또는 모듈일 수 있습니다. 아이디어는 동일합니다. 코드 조각은 특정 작업을 수행하기 위해 만들어지며, Monkey 패치의 목표는 코드 자체를 변경하지 않고 해당 코드 조각의 동작을 변경하거나 확장하여 새로운 작업을 수행하는 것입니다. .

이는 우리가 다루고 있는 구성 요소의 유형에 관계없이 여전히 서로 다른 속성을 가진 동일한 객체 구조를 가지며 속성은 객체에서 새로운 동작을 달성하기 위해 재할당될 수 있는 메서드를 보유할 수 있기 때문에 동적 프로그래밍 언어에서 가능합니다. 내부 및 구현 세부 사항을 다루지 않고. 이는 조정하기가 더 어려운 타사 라이브러리 및 모듈의 경우 특히 유용합니다.

다음 예에서는 원숭이 패치 기술을 사용하여 이점을 얻을 수 있는 일반적인 사용 사례를 보여줍니다. 여기서는 구현을 위해 Javascript가 사용되었지만 다른 동적 프로그래밍 언어에도 여전히 광범위하게 적용되어야 합니다.

노드의 기본 HTTP 모듈을 사용하여 최소한의 테스트 프레임워크 구현

단위 및 통합 테스트는 Monkey 패치 사용 사례에 속할 수 있습니다. 일반적으로 통합 테스트를 위한 둘 이상의 서비스에 걸쳐 있는 테스트 사례나 단위 테스트를 위한 API 및/또는 데이터베이스 종속성이 포함됩니다. 이 두 가지 시나리오에서, 우선 테스트 목표를 달성하기 위해 우리는 테스트가 이러한 외부 리소스와 독립적이기를 원합니다. 이를 달성하는 방법은 조롱을 통해서입니다. 모킹은 테스트가 코드의 실제 논리에 집중할 수 있도록 외부 서비스의 동작을 시뮬레이션합니다. Monkey 패치는 외부 서비스의 메서드를 "스텁"이라고 부르는 자리 표시자 메서드로 대체하여 수정할 수 있으므로 여기서 도움이 될 수 있습니다. 이러한 방법은 테스트 사례에서 예상 결과를 반환하므로 단지 테스트를 위해 프로덕션 서비스에 대한 요청을 시작하는 것을 피할 수 있습니다.

다음 예는 NodeJs 기본 http 모듈에 대한 Monkey 패치의 간단한 구현입니다. http 모듈은 NodeJ에 대한 http 프로토콜 메서드를 구현하는 인터페이스입니다. 주로 베어본 http 서버를 생성하고 http 프로토콜을 사용하여 외부 서비스와 통신하는 데 사용됩니다.

아래 예에는 사용자 ID 목록을 가져오기 위해 외부 서비스를 호출하는 간단한 테스트 사례가 있습니다. 실제 서비스를 호출하는 대신 http get 메소드를 패치하여 임의의 사용자 ID 배열인 예상 결과를 반환합니다. 단지 데이터를 가져오는 것이기 때문에 이는 그다지 중요해 보이지 않을 수도 있지만, 일종의 데이터 변경과 관련된 다른 테스트 케이스를 구현하는 경우 테스트를 실행할 때 실수로 프로덕션 데이터를 변경할 수 있습니다.

이러한 방식으로 우리는 기능을 구현하고 각 기능에 대한 테스트를 작성하는 동시에 프로덕션 서비스의 안전을 보장할 수 있습니다.

// import the http module
let http = require("http");

// patch the get method of the http module
http.get = async function(url) {
  return {
    data: ["1234", "1235", "1236", "1236"]
  };
}

// example test suite, call new patched get method for testing
test('get array of user ids from users api', async () => {
  const res = await http.get("https://users.api.com/ids");
  const userIds = res.data;
  expect(userIds).toBeDefined();
  expect(userIds.length).toBe(4);
  expect(userIds[0]).toBe("1234");
});

위의 코드는 간단합니다. http 모듈을 가져오고, ID 배열을 반환하는 새 메서드로 http.get 메서드를 다시 할당합니다. 이제 테스트 케이스 내에서 새로운 패치된 메서드를 호출하고 새로운 예상 결과를 얻습니다.

~/SphericalTartWorker$ npm test

> nodejs@1.0.0 test
> jest

PASS  ./index.test.js
  ✓ get array of user ids from users api (25 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.977 s, estimated 2 s
Ran all test suites.

일반적인 함정 및 제한 사항

Monkey 패치에는 자체 결함과 한계가 있다는 것은 놀라운 일이 아닙니다. 노드 모듈 시스템의 모듈과 관련하여 http와 같은 전역 모듈을 패치하는 것은 부작용이 있는 작업으로 간주됩니다. 이는 http가 코드베이스 내부의 어느 지점에서나 액세스 가능하고 다른 엔터티가 http에 종속될 수 있기 때문입니다. 이러한 엔터티는 http 모듈이 일반적인 동작으로 작동할 것으로 기대합니다. http 메서드 중 하나를 변경하면 코드베이스 내의 다른 모든 http 종속성을 효과적으로 중단할 수 있습니다.

동적으로 유형이 지정된 언어 내에서 작업하고 있기 때문에 상황이 즉시 실패하지 않고 디버깅 작업을 매우 복잡하게 만드는 예측할 수 없는 동작으로 기본 설정될 수 있습니다. 다른 사용 사례에서는 동일한 속성에 동일한 구성 요소의 두 가지 다른 패치가 있을 수 있습니다. 이 경우 어떤 패치가 다른 패치보다 우선할지 예측할 수 없으므로 훨씬 더 예측할 수 없는 코드가 생성됩니다.

Monkey 패치는 프로그래밍 언어에 따라 동작이 약간 다를 수 있다는 점을 언급하는 것도 중요합니다. 그것은 모두 언어 디자인과 구현 선택에 달려 있습니다. 예를 들어 Python에서 패치된 메서드를 사용하는 모든 인스턴스가 패치의 영향을 받는 것은 아닙니다. 인스턴스가 패치된 메서드를 명시적으로 호출하면 새 업데이트된 버전을 가져옵니다. 반대로 패치된 메서드를 가리키는 속성만 있고 이를 명시적으로 호출하지 않는 다른 인스턴스는 원래 버전을 가져옵니다. 이는 Python이 클래스의 바인딩이 작동합니다.

결론

이 기사에서 우리는 정적 프로그래밍 언어와 동적 프로그래밍 언어 간의 높은 수준의 차이점을 살펴보았고, 동적 프로그래밍 언어가 이러한 언어가 제공하는 고유한 유연성을 활용하는 새로운 패러다임과 패턴을 통해 어떻게 이점을 얻을 수 있는지 살펴보았습니다. 우리가 선보인 예는 소스에서 코드를 변경하지 않고 코드 동작을 확장하는 데 사용되는 기술인 Monkey 패치와 관련이 있습니다. 우리는 이 기술의 사용이 잠재적인 단점과 함께 유익할 수 있는 사례를 보았습니다. 소프트웨어 개발은 ​​모두 절충에 관한 것이며 문제에 대한 올바른 솔루션을 사용하려면 개발자의 정교한 고려와 아키텍처 원칙 및 기본 사항에 대한 충분한 이해가 필요합니다.


Career Services background pattern

취업 서비스

Contact Section background image

계속 연락하자

Code Labs Academy © 2024 판권 소유.