๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐ŸŒˆ Chapter 9: ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด

๐Ÿ“š ๋‹จ์œ„ ํ…Œ์ŠคํŠธโ€‹

๐ŸŽˆ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋กœ ์‹ฑ๊ธ€ํ†ค ๊ณต์œ  ์บ์‹œ ๊ตฌํ˜„ํ•˜๊ธฐโ€‹

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๊ตฌํ˜„์ฒด๋‹ค. ๋‹ค๋ฅธ ๊ฐ์ฒด ์ƒ์„ฑ ํŒจํ„ด๊ณผ ๋‹ฌ๋ฆฌ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœํ•  ํ•จ์ˆ˜๋„ ์—†์„๋ฟ๋”๋Ÿฌ new ํ‚ค์›Œ๋“œ๋กœ ํ•จ์ˆ˜๋ฅผ ๋” ์ฐ์–ด๋‚ผ ์ผ๋„ ์—†๋‹ค.

ํ˜„์žฌ returnValueCache๋Š” ์ด๋ฏธ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ์บ์‹œ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๊ณต์œ  ์บ์‹œ๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ์ฃผ์ž…ํ•˜๋Š” ๊ฒŒ ๊ฐ€์žฅ ๋น ๋ฅธ ๊ธธ์ด๋‹ค.
๋‹ค์Œ์€ 8์žฅ์˜ ์˜ˆ์ œ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค.

describe('returnValueCache', () => {
'use strict';

var testObject;
var testValue;
var args;
var spyReference;

// ํ…Œ์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋„์šฐ๋ฏธ ํ•จ์ˆ˜, testFunction์— ์ŠคํŒŒ์ด๋ฅผ ์‹ฌ๊ณ 
// ๋ฐ˜ํ™˜ ๊ฐ์ฒด์˜ spyReference ํ”„๋กœํผํ‹ฐ์— ์ŠคํŒŒ์ด ์ฐธ์กฐ๊ฐ’์„ ๋‹ด์•„๋‘”๋‹ค.
function createATestObject() {
var obj = {
testFunction: function(arg) {
return testValue;
}
};
spyOn(obj, 'testFunction').and.callThrough();

// ์• ์ŠคํŒฉํŠธ๊ฐ€ ์ ์šฉ๋œ ์ดํ›„์—๋Š”
// ์ŠคํŒŒ์ด๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ํ˜„์žฌ ์ฐธ์กฐ๊ฐ’์„ ๋ณด๊ด€ํ•ด๋‘”๋‹ค.
obj.spyReference = obj.testFunction;

return obj;
}

/*** beforeEach ์ค„์ž„ ***/

describe('advice(targetInfo)', () => {
/*** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ ***/

it('์ฃผ์ž…๋œ ์บ์‹œ๋ฅผ ์ธ์Šคํ„ด์Šค ๊ฐ„์— ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค', () => {
var sharedCache = {};
var object1 = createATestObject();
var object2 = createATestObject();

Aop.around('testFunction',
new Aspects.returnValueCache(sharedCache).advice,
object1,
);

Aop.around('testFunction',
new Aspects.returnValueCache(sharedCache).advice,
object2,
);

object1.testFunction(args);

// object2์˜ testFunction ํ˜ธ์ถœ ์‹œ
// ์บ์‹œ๋œ object1์˜ testFunction ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
expect(object2.testFunction(args)).toBe(testValue);

// ๋”ฐ๋ผ์„œ object2์˜ testFunction์€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
expect(object2.spyReference.calls.count()).toBe(0);
});
});
});

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ๋ฐ›๊ฒŒ๋” 8์žฅ์˜ returnValueCache๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค.

var Aspects = Aspects || {};

Aspects.returnValueCache = function(sharedCache) {
'use strict';

// ์ฃผ์–ด์ง„ sharedCache๊ฐ€ ์žˆ๋‹ค๋ฉด ์‚ฌ์šฉํ•œ๋‹ค.
var cache = sharedCache || {};

return {
advice: function(targetInfo) {
// ํ•จ์ˆ˜์— ๋„˜๊ธด ์ธ์ž๋ฅผ ์บ์‹œ ํ‚ค๋กœ ์ด์šฉํ•œ๋‹ค.
// (๊ฐ์ฒด ์ฐธ์กฐ๊ฐ’ ๋น„๊ต๊ฐ€ ์•„๋‹Œ, ๋ฌธ์ž์—ด ๋น„๊ต๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พผ๋‹ค).
var cacheKey = JSON.stringify(targetInfo.args);

if (cache.hasOwnProperty(cacheKey)) {
return cache[cacheKey];
}

// ์žฅ์‹๋œ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์™€ ์‹คํ–‰ํ•œ ๋’ค ๊ทธ ๋ฐ˜ํ™˜๊ฐ’์„ ์บ์‹œ์— ์ €์žฅํ•œ๋‹ค.
var returnValue = Aop.next(targetInfo);
cache[cacheKey] = returnValue;
return returnValue;
}
};
};

returnValueCache๊ฐ€ ๊ณต์œ  ์บ์‹œ๋ฅผ ์ ‘์ˆ˜ํ—€์œผ๋‹ˆ restaurantApi.getRestaurantsWithinRadius์—์„œ ์• ์ŠคํŒฉํŠธ ์ ์šฉ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•œ๋‹ค.

var Conference = Conference || {};
Conference.caches = Conference.caches || {};

// restaurantApi.getRestaurantsWithinRadius ํ•จ์ˆ˜์—์„œ
// ์บ์‹œ๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด(์‹ฑ๊ธ€ํ†ค) ์ƒ์„ฑ
Conference.caches.getRestaurantsWithinRadius = {};

// getRestaurantsWithinRadius์— ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํŒจํ„ด ์ ์šฉ
Aop.around(
'restaurantApi',
function addMemoizationToGetRestaurantsWithinRadius(targetInfo) {
// ThirdParty.restaurantApi()๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์›๋ณธ API
var api = Aop.next.call(this, targetInfo);

// getRestaurantsWithinRadius ํ•จ์ˆ˜๋ฅผ ์žฅ์‹ํ•˜์—ฌ ๋ฉ”๋ชจ์ด์ œ์ด์…˜(๊ณต์œ  ์บ์‹œ๋กœ) ์ถ”๊ฐ€
Aop.around('getRestaurantsWithinRadius',
Aspects.returnValueCache(Conference.caches.restaurantsWithinRadiusCache).advice,
api,
);

// ๊ณ ์นœ API๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
return api;
},
ThirdParty,
);

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ๊ทธ์•ผ๋ง๋กœ ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ๊ตฌํ˜„์ฒด์ด์ง€๋งŒ, ๋ชจ๋“ˆ ํŒจํ„ด ๋“ฑ ํƒ€ ๊ฐ์ฒด ์ƒ์„ฑ ํŒจํ„ด์ด ์ œ๊ณตํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ฐ์ถค ๋”ฐ์œ„์˜ ๊ธฐ๋Šฅ์€ ์—†๋‹ค.

๐ŸŽˆ ๋ชจ๋“ˆ๋กœ ์‹ฑ๊ธ€ํ†ค ๊ณต์œ  ์บ์‹œ ๊ตฌํ˜„ํ•˜๊ธฐโ€‹

์œ„ ์˜ˆ์ œ์˜ ๊ณต์œ  ์บ์‹œ๋Š” ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด restaurantsWithinRadiusCache๋ฅผ Conference.caches ์ด๋ฆ„๊ณต๊ฐ„์— ์„ ์–ธํ•˜์—ฌ ๋งŒ๋“ค์—ˆ๋‹ค. ๋Œ€๊ฐœ ๊ฐœ๊ฒŒ ๋ฆฌํ„ฐ๋Ÿด ์ •๋„๋ฉด ์บ์‹œ ์šฉ๋„๋กœ ๋‚˜์˜์ง€ ์•Š์€๋ฐ, ๋” ๊ธฐ๋Šฅ์ด ๋‹ค์–‘ํ•œ ์บ์‹œ๋ฅผ ์จ์•ผ ํ•  ๋•Œ๋„ ์žˆ๋‹ค. ์ด๋ฅผํ…Œ๋ฉด ๊ฐ€์žฅ ์˜ค๋ž˜์ „์— ์บ์‹œํ•œ ๊ฐ’์„ ๊ฐ€์žฅ ์ตœ๊ทผ ์บ์‹œ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•˜๋ฉด์„œ ํ•ญ์ƒ ์ผ์ •ํ•œ ๊ฐœ์ˆ˜์˜ ๊ฐ’๋“ค๋งŒ ๋‚จ๊ธฐ๋Š”, ์ตœ์ € ์‚ฌ์šฉ๋นˆ๋„(LRU) ์บ์‹œ๊ฐ€ ์žˆ์–ด์•ผ ํ•  ๋•Œ๋„ ์žˆ๊ณ , ์ผ์ • ์‹œ๊ฐ„๊นŒ์ง€๋งŒ ์บ์‹œ๊ฐ’์„ ์ €์žฅํ•ด๋‘๋Š” ๊ฒŒ ๋” ํ•ฉ๋ฆฌ์ ์ธ ์ƒํ™ฉ๋„ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์–ด์จŒ๋“  ์บ์‹œ๊ฐ€ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์ธ ํ•œ ์ด๋Ÿฐ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ๊นŒ์ง€ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

๊ทธ๋ž˜์„œ ํ”„๋กœํผํ‹ฐ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์•„๋‹Œ API๋ฅผ ํ† ํ•ด ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๊ธฐ๋ฐ˜์˜ ์บ์‹œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” Conference.simpleCache ๋ชจ๋“ˆ์„ ์ง์ ‘ ๊ฐœ๋ฐœํ–ˆ๋‹ค.

var Conference = Conference || {};

Conference.simpleCache = function() {
'use strict';

var privateCache = {};

function getCacheKey(key) {
return JSON.stringify(key);
}

return {
// ์บ์‹œ์— ์žˆ๋Š” ํ‚ค๋ฉด true, ์•„๋‹ˆ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
hasKey: function(key) {
return privateCache.hasOwnProperty(getCacheKey(key));
},

// ์บ์‹œ์— ํ•ด๋‹น ํ‚ค๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.
setValue: function(key, value) {
privateCache[getCacheKey(key)] = value;
},

// ํ•ด๋‹น ํ‚ค๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
// (์บ์‹œ์— ํ‚ค๊ฐ’์ด ์—†์œผ๋ฉด undefined)
getValue: function(key) {
return privateCache[getCacheKey(key)];
}
};
};

simpleCache๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด returnValueCache๋ฅผ ์กฐ๊ธˆ ๊ณ ์ณ์•ผ ํ•œ๋‹ค. ๊ณต์œ  ์บ์‹œ๋ฅผ ์ฃผ์ง€ ์•Š์œผ๋ฉด ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋Œ€์‹  ์ƒˆ simpleCache๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์ดํ›„๋กœ๋Š” ์บ์‹œ ๊ฐ์ฒด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ง์ ‘ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  simpleCache API๊ฐ€ ํ‘œ์ถœํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

์ด์ „ returnValueCache์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์—์„œ simpleCache๋ฅผ ์“ฐ๊ธฐ ์œ„ํ•ด ์ˆ˜์ •ํ•  ๋ถ€๋ถ€์€ ํ•œ ์ค„ ๋ฟ์ด๋‹ค.

describe('returnValueSimpleCache', () => {
'use strict';

/*** ์„ค์ • ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋Š” ๊ทธ๋Œ€๋กœ์ด๋ฏ€๋กœ ์ค„์ž„ ***/

describe('advice(targetInfo)', () => {
/*** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ ***/

it('์ฃผ์ž…๋œ ์บ์‹œ๋ฅผ ์ธ์Šคํ„ด์Šค ๊ฐ„์— ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค', () => {
// ๋ณ€๊ฒฝ
// ๊ณต์œ  ์บ์‹œ ๊ฐ์ฒด, simpleCache๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
var sharedCache = Conference.simpleCache();
var object1 = createATestObject();
var object2 = createATestObject();

Aop.around('testFunction',
new Aspects.returnValueCache(sharedCache).advice,
object1,
);

Aop.around('testFunction',
new Aspects.returnValueCache(sharedCache).advice,
object2,
);

object1.testFunction(args);

// object2์˜ testFunction ํ˜ธ์ถœ ์‹œ
// ์บ์‹œ๋œ object1์˜ testFunction ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
expect(object2.testFunction(args)).toBe(testValue);

// ๋”ฐ๋ผ์„œ object2์˜ testFunction์€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
expect(object2.spyReference.calls.count()).toBe(0);
});
});
});

์ด๋ ‡๊ฒŒ simpleCache๋ฅผ ์ž‘์„ฑํ•˜์—ฌ returnValueCache๊ฐ€ simpleCache๋ฅผ ์“ฐ๋„๋ก ๊ณ ์ณค์œผ๋‹ˆ ๋‹ค์Œ์€ restaurantApi.getRestaurantsWithinRadius ํ•จ์ˆ˜๊ฐ€ ์‚ฌ์šฉํ•  ์‹ฑ๊ธ€ํ†ค ์บ์‹œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ฐจ๋ก€๋‹ค.

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ๊ณต์œ  ์บ์‹œ๋กœ ์“ธ ๋•Œ๋Š” ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์ด ์ด๋ฏธ ์‹ฑ๊ธ€ํ†ค์ด๋‹ˆ ์บ์‹œ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด ๋ช…๋ฐฑํ–ˆ๋‹ค. ์ง€๊ธˆ์€ ๋ชจ๋“ˆ ์ž์ฒด๊ฐ€ ์บ์‹œ๋ผ ์ƒํ™ฉ์ด ๋‹ค๋ฅธ๋ฐ, ๋ชจ๋“ˆ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ฐ์ž ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

restaurantApi ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹ค๋“ค ๋‹จ์ผ simpleCache ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ”๋ผ๋ณด๊ฒŒ ํ•˜๋ ค๋ฉด ์ฆ‰์‹œ ์‹คํ–‰ ๋ชจ๋“ˆ์„ ์‘์šฉํ•ด์„œ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. RestaurantsWithinRadiusCache ๋ชจ๋“ˆ์€ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๋˜‘๊ฐ™์€ simpleCache ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‹จ์ผ ํ•จ์ˆ˜์ธ getInstance๋ฅผ ํ‘œ์ถœํ•œ๋‹ค.

describe('Conference.caches.RestaurantsWithinRadiusCache', () => {
'use strict';

describe('getInstance', () => {
it('ํ•ญ์ƒ ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค', () => {
// .getInstance๊ฐ€ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ํ™•์ธ
expect(Conference.caches.RestaurantsWithinRadiusCache.getInstance())
.toBe(Conference.caches.RestaurantsWithinRadiusCache.getInstance());
});
});
});

๋‹ค์Œ์€ RestaurantsWithinRadiusCache ๊ตฌํ˜„๋ถ€๋‹ค.

var Conference = Conference || {};
Conference.caches = Conference.caches || {};

// restaurantApi.getRestaurantsWithinRadius ํ•จ์ˆ˜์—์„œ
// ์บ์‹œ๋กœ ์‚ฌ์šฉํ•  simpleCache(์‹ฑ๊ธ€ํ†ค) ์ƒ์„ฑ
Conference.caches.RestaurantsWithinRadiusCache = (function() {
'use strict';

var instance = null;

return {
getInstance: function() {
if(!instance) {
instance = Conference.simpleCache();
}

return instance;
}
};
})();

์œ„ ์˜ˆ์ œ์—์„œ ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์„ RestaurantsWithinRadiusCache์— ํ• ๋‹นํ•˜๋ฉด์„œ ์ด ๊ฐ์ฒด๋ฅผ getInstance ํ•จ์ˆ˜๋ฅผ ํ‘œ์ถœํ•œ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋กœ ํ™•์‹คํžˆ ์ž๋ฆฌ๋งค๊น€ํ•œ๋‹ค. getInstance๋ฅผ ๋งจ ์ฒ˜์Œ ์‹คํ–‰ํ•˜๋ฉด ์ˆจ์–ด ์žˆ๋˜ instance ๋ณ€์ˆ˜๊ฐ€ simpleCache๋กœ ์ฑ„์›Œ์ง„๋‹ค. ๋‚˜์ค‘์— getInstance๋ฅผ ๋ช‡ ๋ฒˆ์ด๊ณ  ํ˜ธ์ถœํ•ด๋„ ๊ฐ™์€ instance๋ฅผ ๋‚ด์–ด์ค€๋‹ค.

์ธ์Šคํ„ด์Šค ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ๋‚˜์ค‘์œผ๋กœ ๋ฏธ๋ฃฐ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋˜ ๋‹ค๋ฅธ ๋งค๋ ฅ์ด๋‹ค. ์ธ์Šคํ„ด์Šค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„/๋น„์šฉ์ด ๋งŽ์ด ๋“ฃ๋‹ค๋ฉด ์ค‘์š”ํ•œ ์žฅ์ ์ด๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ์œ ๋…ํ•  ์ ์€ returnValueCache ์• ์ŠคํŒฉํŠธ๋ฅผ restaurantApi.getRestaurantsWithinRadius ํ•จ์ˆ˜์— ์ ์šฉํ•  ๋ถ€๋ถ„ ์—ญ์‹œ ์ƒˆ๋กœ์šด RestaurantsWithinRadiusCache ์‹ฑ๊ธ€ํ†ค์„ ์“ฐ๊ฒŒ๋” ๊ณ ์ณ์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์ด๋‹ค.

// getRestaurantsWithinRadius์— ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํŒจํ„ด ์ ์šฉ

Aop.around(
'restaurantApi',
function addMemoizationToGetRestaurantsWithinRadius(targetInfo) {

// ThirdParty.restaurantApo()๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์›๋ณธ API
var api = Aop.next.call(this, targetInfo);

// ์‹ฑ๊ธ€ํ†ค ์บ์‹œ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
var cache = Conference.caches.RestaurantsWithinRadiusCache.getInstance();

// getRestaurantsWithinRadius ํ•จ์ˆ˜๋ฅผ ์žฅ์‹ํ•˜์—ฌ
// ๋ฉ”๋ชจ์ด์ œ์ด์…˜(๊ณต์œ  ์บ์‹œ๋กœ) ์ถ”๊ฐ€
Aop.around('getRestaurantsWithinRadius',
Aspects.returnValueCache(cache).advice, api);

// ๊ณ ์นœ API๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
return api;
},
ThirdParty,
);

๐Ÿ“š ์ •๋ฆฌํ•˜๊ธฐโ€‹

์‹ฑ๊ธ€ํ†ค์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋„๋ฆฌ ์“ฐ์ด๋Š” ํŒจํ„ด์ด๋‹ค. ์ „์—ญ ์ด๋ฆ„๊ณต๊ฐ„์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•จ์ˆ˜๋‚˜ ๋ณ€์ˆ˜๋กœ ์˜ค์—ผ์‹œํ‚ค์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ์ด๋ฆ„๊ณต๊ฐ„์„ ์ƒ์„ฑํ•  ๋•Œ ์œ ์šฉํ•œ๋‹ค. ๋˜ํ•œ, ์บ์‹œ์ฒ˜๋Ÿผ ๋ชจ๋“ˆ๋ผ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์šฉ๋„๋กœ ์ตœ์ ์ด๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ๋กœ ์›€์ง์ด๋ฏ€๋กœ ๋‹ค๋ฅธ ์–ธ์–ด๋ณด๋‹ค ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๊ณผ ์ฆ‰์‹œ ์‹คํ–‰ ๋ชจ๋“ˆ ๊ฐ™์€ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ๋‹ค. ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด์— ๋™์‹œ์— ์ ‘๊ทผํ•  ๋•Œ ์•ผ๊ธฐ๋˜๋Š” ๋ฌด์ œ๋Š” ๊ณ ๋ฏผํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ๊ตฌํ˜„์— ๋”ฐ๋ฅธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ผ์ด ๊ด€๊ฑด์ด๋‹ค.