[angularjs] 앵귤러 서비스 vs 앵귤러 팩토리

서비스를 선언하는 데 사용되는 angular.factory ()angular.service ()를 모두 보았습니다 . 그러나 공식 문서의 어느 곳도 찾을 수 없습니다 angular.service .

두 방법의 차이점은 무엇입니까?
무엇을 사용해야합니까 (다른 일을한다고 가정)?



답변

  angular.service('myService', myServiceFunction);
  angular.factory('myFactory', myFactoryFunction);

이런 식으로 머리를 감쌀 때까지이 개념을 머리에 감쌀 수 없었습니다.

서비스 : 작성하는 기능새로운 기능 입니다 .

  myInjectedService  <----  new myServiceFunction()

팩토리 : 작성한 함수 (생성자)가 호출됩니다 .

  myInjectedFactory  <---  myFactoryFunction()

당신이하는 일은 당신에게 달려 있지만 유용한 패턴이 있습니다 …

퍼블릭 API를 공개하기 위한 서비스 함수 작성과 같은 :

function myServiceFunction() {
  this.awesomeApi = function(optional) {
    // calculate some stuff
    return awesomeListOfValues;
  }
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.awesome = myInjectedService.awesomeApi();

또는 팩토리 함수를 사용하여 공개 API를 노출하십시오.

function myFactoryFunction() {
  var aPrivateVariable = "yay";

  function hello() {
    return "hello mars " + aPrivateVariable;
  }

  // expose a public API
  return {
    hello: hello
  };
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.hello = myInjectedFactory.hello();

또는 팩토리 함수를 사용하여 생성자를 반환합니다.

function myFactoryFunction() {
    return function() {
        var a = 2;
        this.a2 = function() {
            return a*2;
        };
    };
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();

어느 것을 사용해야합니까? …

둘 다 같은 것을 달성 할 수 있습니다. 그러나 어떤 경우에는 공장 에서 더 간단한 구문으로 주사제를 만들 수있는 약간의 유연성을 제공합니다. myInjectedService는 항상 객체 여야하지만 myInjectedFactory는 객체, 함수 참조 또는 모든 값일 수 있기 때문입니다. 예를 들어 생성자를 만드는 서비스를 작성한 경우 (위의 마지막 예에서와 같이) 다음과 같이 인스턴스화해야합니다.

var myShinyNewObject = new myInjectedService.myFunction()

이것은 이것보다 덜 바람직하지 않습니다.

var myShinyNewObject = new myInjectedFactory();

(하지만 컨트롤러의 새로운 객체는 테스트하기가 까다로워 추적하기 어려운 종속성을 생성 하기 때문에 이러한 유형의 패턴을 처음 사용하는 것에주의해야합니다 . 당신은 new()wily-nilly를 사용하는 것보다 .)


한 가지 더, 그들은 모두 싱글 톤입니다 …

또한 두 경우 모두 앵귤러는 싱글 톤을 관리하는 데 도움이됩니다. 서비스 또는 기능을 어디에 또는 몇 번 주입했는지에 관계없이 동일한 객체 또는 기능에 대한 동일한 참조를 얻게됩니다. (공장에서 단순히 숫자 나 문자열과 같은 값을 반환하는 경우를 제외하고는 항상 같은 값을 얻을 수 있지만 참조는 아닙니다.)


답변

간단히 말해서 ..

// Service
service = (a, b) => {
  a.lastName = b;
  return a;
};

// Factory
factory = (a, b) => Object.assign({}, a, { lastName: b });

const fullName = { firstName: 'john' };

// Service
const lastNameService = (a, b) => {
  a.lastName = b;
  return a;
};
console.log(lastNameService(fullName, 'doe'));

// Factory
const lastNameFactory = (a, b) => 
  Object.assign({}, a, { lastName: b })
console.log(lastNameFactory(fullName, 'doe'));


답변

주요 차이점은 다음과 같습니다.

서비스

통사론: module.service( 'serviceName', function );

결과 : serviceName을 주사 가능한 인수로 선언하면에 전달 된 함수인스턴스 가 제공 됩니다 module.service.

사용법 : 주입 된 함수 참조 에 간단히 추가 하여 호출하는 데 유용한 유틸리티 함수공유하는 데 유용 할 수 있습니다 ( ). 함께 injectedArg.call( this )또는 유사 하게 실행할 수 있습니다 .

공장

통사론: module.factory( 'factoryName', function );

결과 : factoryName을 주입 가능한 인수로 선언하면에 전달 된 함수 참조를 호출하여 리턴되는 값이 제공 됩니다 module.factory.

사용법 : 인스턴스를 만들기 위해 새로 만들 수 있는 ‘클래스’ 기능 을 반환하는 데 유용 할 수 있습니다 .

다음은 services 및 factory를 사용하는 예 입니다. AngularJS Service vs Factory 에 대해 자세히 알아보십시오 .

서비스 대 팩토리에 대해 혼란스러워 하는 Stackoverflow에 대한 AngularJS 문서 및 유사한 질문을 확인할 수도 있습니다 .


답변

TL; DR

1) 당신이 사용하고있는 공장을 객체를 만든 다음 같은 개체를 반환, 그것에 속성을 추가 할 수 있습니다. 이 팩토리를 컨트롤러에 전달하면 이제 해당 컨트롤러에서 팩토리를 통해 객체의 해당 속성을 사용할 수 있습니다.

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory('myFactory', function(){
  var _artist = 'Shakira';
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});

2) Service를 사용할 때 Angular는 ‘new’키워드를 사용하여 장면 뒤에서 인스턴스화합니다. 이 때문에 ‘this’에 속성을 추가하면 서비스는 ‘this’를 반환합니다. 서비스를 컨트롤러로 전달하면 이제 ‘this’에 대한 해당 속성을 서비스를 통해 해당 컨트롤러에서 사용할 수 있습니다.

app.controller('myServiceCtrl', function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service('myService', function(){
  var _artist = 'Nelly';
  this.getArtist = function(){
    return _artist;
  }
});

비 TL; DR

1) 팩토리
팩토리는 서비스를 생성하고 구성하는 가장 보편적 인 방법입니다. TL; DR이 말한 것보다 훨씬 많지는 않습니다. 객체를 생성하고 속성을 추가 한 다음 동일한 객체를 반환하면됩니다. 그런 다음 팩토리를 컨트롤러로 전달하면 이제 해당 컨트롤러의 팩토리를 통해 객체의 해당 속성을 사용할 수 있습니다. 보다 광범위한 예는 다음과 같습니다.

app.factory('myFactory', function(){
  var service = {};
  return service;
});

이제 ‘myFactory’를 컨트롤러에 전달하면 ‘service’에 첨부 한 모든 속성을 사용할 수 있습니다.

이제 콜백 함수에 ‘비공개’변수를 추가하겠습니다. 이것들은 컨트롤러에서 직접 액세스 할 수는 없지만 결국 ‘service’에서 getter / setter 메소드를 설정하여 필요할 때 이러한 ‘private’변수를 변경할 수 있습니다.

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
   _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK';
    return _finalUrl
  }

  return service;
});

여기서는 변수 / 함수를 ‘service’에 첨부하지 않습니다. 나중에 사용하거나 수정하기 위해 단순히 만들었습니다.

  • baseUrl은 iTunes API에 필요한 기본 URL입니다
  • _artist는 조회하고자하는 아티스트입니다.
  • _finalUrl은 iTunes를 호출 할 최종 완성 된 URL이며, makeUrl은 iTunes 친화적 인 URL을 생성하고 반환하는 기능입니다.

헬퍼 / 프라이빗 변수와 함수가 준비되었으므로 ‘service’객체에 속성을 추가해 봅시다. 우리가 ‘서비스’를 무엇이든, 우리는 ‘myFactory’를 전달하는 컨트롤러에서 직접 사용할 수 있습니다.

아티스트를 반환하거나 설정하는 setArtist 및 getArtist 메소드를 작성하려고합니다. 또한 생성 된 URL을 사용하여 iTunes API를 호출하는 메소드를 작성하려고합니다. 이 방법은 일단 데이터가 iTunes API에서 돌아 오면 이행 할 것을 약속합니다. Angular에서 약속을 사용한 경험이 많지 않은 경우 약속을 자세히 살펴 보는 것이 좋습니다.

아래 setArtist 는 아티스트를 허용하며 아티스트를 설정할 수 있습니다. getArtist 는 $ http 요청에 사용할 URL을 만들기 위해 아티스트 callItunes에서 makeUrl ()을 호출합니다. 그런 다음 promise 객체를 설정하고 최종 URL로 $ http 요청을 한 다음 $ http는 promise를 반환하므로 요청 후 .success 또는 .error를 호출 할 수 있습니다. 그런 다음 iTunes 데이터로 약속을 해결하거나 ‘오류가 발생했습니다’라는 메시지와 함께 거부합니다.

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

이제 우리 공장은 완성되었습니다. 이제 모든 컨트롤러에 ‘myFactory’를 삽입 할 수 있으며 서비스 객체 (setArtist, getArtist 및 callItunes)에 첨부 한 메소드를 호출 할 수 있습니다.

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

위의 컨트롤러에서 우리는 ‘myFactory’서비스에 주입하고 있습니다. 그런 다음 ‘myFactory’의 데이터에서 나오는 $ scope 객체의 속성을 설정합니다. 위의 유일한 까다로운 코드는 이전에 약속을 다루지 않은 경우입니다. callItunes가 약속을 반환하므로 .then () 메서드를 사용하고 iTunes 데이터로 약속이 이행 된 후에 만 ​​$ scope.data.artistData를 설정할 수 있습니다. 컨트롤러가 매우 얇다는 것을 알 수 있습니다. 모든 논리 및 영구 데이터는 컨트롤러가 아닌 서비스에 있습니다.

2) 서비스
아마도 서비스 생성을 처리 할 때 알아야 할 가장 큰 것은 ‘새로운’키워드로 인스턴스화된다는 것입니다. JavaScript 전문가에게는 이것이 코드의 특성에 대한 큰 힌트를 제공해야합니다. JavaScript에 대한 배경 지식이 제한적인 사용자 또는 ‘new’키워드의 실제 기능에 익숙하지 않은 사용자를 위해 서비스의 본질을 이해하는 데 도움이되는 JavaScript 기본 사항을 검토하겠습니다.

‘new’키워드로 함수를 호출 할 때 발생하는 변경 사항을 실제로 보려면 함수를 작성하고 ‘new’키워드로 호출 한 다음 ‘new’키워드를 볼 때 인터프리터가 수행하는 작업을 보여 드리겠습니다. 최종 결과는 동일합니다.

먼저 생성자를 만들어 봅시다.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

일반적인 JavaScript 생성자 함수입니다. 이제 ‘new’키워드를 사용하여 Person 함수를 호출 할 때마다 ‘this’는 새로 작성된 오브젝트에 바인드됩니다.

이제 Person의 프로토 타입에 메소드를 추가하여 Person ‘클래스’의 모든 인스턴스에서 사용할 수 있습니다.

Person.prototype.sayName = function(){
  alert('My name is ' + this.name);
}

이제 프로토 타입에 sayName 함수를 추가 했으므로 Person의 모든 인스턴스는 해당 인스턴스 이름을 알리기 위해 sayName 함수를 호출 할 수 있습니다.

이제 Person 생성자 함수와 프로토 타입에 sayName 함수가 있으므로 Person 인스턴스를 만든 다음 sayName 함수를 호출 해 보겠습니다.

var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'

따라서 Person 생성자를 생성하고 프로토 타입에 함수를 추가하고 Person 인스턴스를 생성 한 다음 프로토 타입에서 함수를 호출하는 코드는 다음과 같습니다.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert('My name is ' + this.name);
}
var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'

이제 JavaScript에서 ‘new’키워드를 사용할 때 실제로 어떤 일이 발생하는지 살펴 보겠습니다. 첫 번째로 주목해야 할 것은 예제에서 ‘new’를 사용한 후에는 마치 ‘tyler’에서 객체 인 것처럼 메소드 (sayName)를 호출 할 수 있다는 것입니다. 그 이유 때문입니다. 먼저, Person 생성자가 코드에서 볼 수 있는지 여부에 관계없이 Person 생성자가 객체를 반환한다는 것을 알고 있습니다. 둘째, sayName 함수는 Person 인스턴스가 아닌 프로토 타입에 있으므로 Person 함수가 반환하는 객체는 실패한 조회에서 프로토 타입에 위임되어야합니다. 더 간단한 용어로, tyler.sayName ()을 호출하면 인터프리터는“OK, 방금 만든 ‘tyler’객체를보고 sayName 함수를 찾은 다음 호출합니다. 잠깐만 요, 여기 보이지 않습니다-내가 볼 수있는 것은 이름과 나이, 프로토 타입을 확인하겠습니다. 예, 프로토 타입에있는 것 같습니다.”라고 말합니다.

아래는 JavaScript에서 ‘new’키워드가 실제로하는 일에 대해 어떻게 생각할 수 있는지에 대한 코드입니다. 기본적으로 위 단락의 코드 예입니다. 나는 ‘인터프리터 뷰’또는 인터프리터가 코드 내부의 코드를 보는 방식을 넣었습니다.

var Person = function(name, age){
  //The line below this creates an obj object that will delegate to the person's prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets 'this' to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

이제 ‘new’키워드가 JavaScript에서 실제로하는 일에 대한 지식이 있으면 Angular에서 서비스를 작성하는 것이 이해하기 쉬워야합니다.

서비스를 만들 때 이해해야 할 가장 큰 것은 서비스가 ‘new’키워드로 인스턴스화된다는 것입니다. 위의 예제와 그 지식을 결합하여 이제 속성과 메소드를 ‘this’에 직접 첨부하여 서비스 자체에서 반환한다는 것을 인식해야합니다. 이것을 실제로 살펴 봅시다.

우리가 팩토리 예제로 원래했던 것과는 달리, 우리는 객체를 생성 할 필요가 없습니다. 이전에 여러 번 언급했듯이 인터프리터가 해당 객체를 생성하고 위임 할 수 있도록 ‘new’키워드를 사용했기 때문입니다. 그것은 프로토 타입이고, 우리가 작업을하지 않아도 우리를 위해 그것을 돌려줍니다.

먼저, ‘비공개’및 도우미 기능을 만들어 봅시다. 우리가 공장과 똑같은 일을했기 때문에 이것은 매우 친숙하게 보일 것입니다. 팩토리 예제에서 각 라인이 무엇을하는지 설명하지 않겠습니다. 혼란 스러우면 팩토리 예제를 다시 읽으십시오.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

이제 컨트롤러에서 사용할 수있는 모든 메소드를 ‘this’에 첨부하겠습니다.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

이제 팩토리 에서처럼 setArtist, getArtist 및 callItunes는 myService를 전달하는 컨트롤러에서 사용할 수 있습니다. 다음은 myService 컨트롤러입니다 (공장 컨트롤러와 거의 동일).

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

앞에서 언급했듯이 ‘새로운’기능을 실제로 이해하면 서비스는 Angular의 공장과 거의 동일합니다.


답변

실마리는 이름에있다

서비스와 공장은 서로 비슷합니다. 둘 다 다른 객체에 주입 할 수있는 단일 객체를 생성하므로 종종 상호 교환 적으로 사용됩니다.

그것들은 다른 디자인 패턴을 구현하기 위해 의미 적으로 사용되도록 고안되었습니다.

서비스는 서비스 패턴을 구현하기위한 것입니다

서비스 패턴은 애플리케이션이 논리적으로 일관된 기능 단위로 분리되는 패턴입니다. 예를 들어 API 접근 자 또는 일련의 비즈니스 논리가 있습니다.

Angular 모델은 일반적으로 서버에서 가져온 JSON 객체이므로 비즈니스 로직을 넣을 곳이 필요하기 때문에 Angular에서 특히 중요합니다.

예를 들어 Github 서비스는 다음과 같습니다. Github과 대화하는 방법을 알고 있습니다. URL과 메소드에 대해 알고 있습니다. 컨트롤러에 삽입하면 약속을 생성하고 반환합니다.

(function() {
  var base = "https://api.github.com";

  angular.module('github', [])
    .service('githubService', function( $http ) {
      this.getEvents: function() {
        var url = [
          base,
          '/events',
          '?callback=JSON_CALLBACK'
        ].join('');
        return $http.jsonp(url);
      }
    });
  )();

공장은 공장 패턴을 구현

한편, 공장은 공장 패턴을 구현하기위한 것이다. 팩토리 함수를 사용하여 객체를 생성하는 팩토리 패턴입니다. 일반적으로 모델을 빌드하는 데 사용할 수 있습니다. 다음은 Author 생성자를 반환하는 팩토리입니다.

angular.module('user', [])
  .factory('User', function($resource) {
    var url = 'http://simple-api.herokuapp.com/api/v1/authors/:id'
    return $resource(url);
  })

우리는 이것을 다음과 같이 사용할 것입니다 :

angular.module('app', ['user'])
  .controller('authorController', function($scope, User) {
    $scope.user = new User();
  })

팩토리는 싱글 톤도 반환합니다.

공장은 생성자를 반환 할 수 있습니다

팩토리는 단순히 객체를 반환하기 때문에 위에서 본 것처럼 생성자 함수를 포함하여 원하는 모든 유형의 객체를 반환 할 수 있습니다.

공장은 개체를 반환합니다. 새로운 서비스

또 다른 기술적 차이점은 서비스와 공장 구성 방식에 있습니다. 객체를 생성하기 위해 서비스 기능이 새로워집니다. 팩토리 함수가 호출되어 객체를 반환합니다.

  • 서비스는 새로운 생성자입니다.
  • 팩토리는 단순히 호출되어 객체를 반환합니다.

즉, 서비스에서 생성자 컨텍스트에서 생성중인 객체를 가리키는 “this”에 추가합니다.

이를 설명하기 위해 다음은 서비스와 팩토리를 사용하여 만든 동일한 간단한 객체입니다.

angular.module('app', [])
  .service('helloService', function() {
    this.sayHello = function() {
      return "Hello!";
    }
  })
  .factory('helloFactory', function() {
    return {
      sayHello: function() {
        return "Hello!";
      }
    }
  });


답변

여기에있는 모든 대답은 서비스 및 공장 주변에있는 것으로 보이며 그것이 요청 된 이후 유효합니다. 그러나 거기를 포함한 여러 다른 사람들이 있다는 사실을 숙지하는 것도 중요합니다 provider(), value()하고 constant().

기억해야 할 열쇠는 각각이 서로의 특별한 경우라는 것입니다. 각각의 특수한 사례는 적은 코드로 동일한 작업을 수행 할 수 있도록합니다. 각각에는 추가 제한이 있습니다.

어느 것을 사용할지 결정하려면 적은 코드로 원하는 것을 할 수있는 것을 볼 수 있습니다. 다음은 이미지가 얼마나 유사한 지 보여주는 이미지입니다.

여기에 이미지 설명을 입력하십시오

단계별 사용법 및 각 사용시기에 대한 빠른 참조를 위해이 이미지를 가져온 블로그 게시물을 방문 할 수 있습니다.

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/


답변

app.factory ( ‘fn’, fn) vs. app.service ( ‘fn’, fn)

구성

팩토리를 사용하면 Angular는 함수를 호출하여 결과를 얻습니다. 캐시되고 주입 된 결과입니다.

 //factory
 var obj = fn();
 return obj;

서비스를 통해 Angular는 new를 호출하여 생성자 함수를 호출 합니다. 생성 된 함수는 캐시되어 주입됩니다.

  //service
  var obj = new fn();
  return obj;

이행

반환 값 컨트롤러, 실행 블록, 지시문 등에 주입되는 것이기 때문에 일반적으로 팩토리는 오브젝트 리터럴을 리턴합니다.

  app.factory('fn', function(){
         var foo = 0;
         var bar = 0;
         function setFoo(val) {
               foo = val;
         }
         function setBar (val){
               bar = val;
         }
         return {
                setFoo: setFoo,
                serBar: setBar
         }
  });

서비스 기능은 일반적으로 아무것도 반환하지 않습니다. 대신, 초기화 및 노출 기능을 수행합니다. 함수는 ‘new’를 사용하여 생성되었으므로 ‘this’를 참조 할 수도 있습니다.

app.service('fn', function () {
         var foo = 0;
         var bar = 0;
         this.setFoo = function (val) {
               foo = val;
         }
         this.setBar = function (val){
               bar = val;
         }
});

결론

팩토리 나 서비스를 사용하는 경우에는 둘 다 매우 유사합니다. 그것들은 컨트롤러, 지시어, 실행 블록 등에 주입되며 클라이언트 코드에서 거의 같은 방식으로 사용됩니다. 또한 둘 다 싱글 톤이므로 서비스 / 공장이 주입되는 모든 장소에서 동일한 인스턴스가 공유됩니다.

그렇다면 어느 것을 선호해야합니까? 어느 쪽이든-그들은 너무 유사하여 차이점이 사소합니다. 둘 중 하나를 선택하는 경우 구성 방법을 알고 있어야 제대로 구현할 수 있습니다.