# Memcached 사용 가이드

## 고도몰 멤캐시 소개

#### 라이브러리

* 고도몰 멤캐시 기능은 Symfony Cache v3.4 라이브러리를 바탕으로 구현되었습니다.
* [Symfony Cache v3.4 구현 코드 바로가기](https://github.com/symfony/symfony/tree/3.4/src/Symfony/Component/Cache)

#### Eviction 정책

* 고도몰 멤캐시 Eviction 정책은 LRU (Least Recently Used) 방식입니다.
* [Symfony 공식 구현에서의 Memcached 설정 예시](https://github.com/symfony/symfony/blob/0a9296a8b23360475c282cd98b1fd36e3937d259/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php#L22-L31)

## 코딩 가이드

### Using namespaces

* 고도몰에서 제공하는 캐시 함수는 SimpleCache 클래스 내부에 구현되어 있습니다.
* 캐시 함수를 사용하는 곳에서 SimpleCache namespaces 를 불러와주세요.

```php
use Framework\SimpleCache\SimpleCache;
```

### 고도몰 캐시 함수

* 고도몰에서 제공하는 캐시 함수의 종류는 총 5개입니다.
  * set()
  * has()
  * get()
  * getSet()
  * delete()

#### set

```php
/**
 * Save cache item
 *
 * @param string $key
 * @param mixed $value
 * @param int $ttl 1 or more, up to 300 (seconds)
 *
 * @return bool stating if caching succeeded or not
 */
```

* 캐시 내부에 데이터를 저장하는 함수입니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$cacheValue = "(CACHE_VALUE)";
$ttl = 300;

$setResult = SimpleCache::init(SimpleCache::MEMCACHED)->set($cacheKey, $cacheValue, $ttl);
```

* 위와 같이 set 함수를 이용할 수 있습니다.
* ttl 값은 300을 초과할 수 없습니다.

#### has

```php
/**
 * Confirms if the cache contains specified cache item.
 *
 * @param string $key
 *
 * @return bool True if item exists in the cache, false otherwise
 */
```

* 캐시 내 조회하고자 하는 key에 대한 데이터가 있는지 확인하는 함수입니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$hasKey = SimpleCache::init(SimpleCache::MEMCACHED)->has($cacheKey);
```

* 위와 같이 has 함수를 이용할 수 있습니다.

#### get

```php
/**
 * Fetches cache item.
 *
 * @param string $key
 *
 * @return mixed The corresponding values found in the cache, returning null if no value is present in the cache.
 */
```

* 캐시 내 저장된 데이터의 value를 반환하는 함수입니다. \
  조회하고자 하는 키값이 존재하지 않을 경우 null을 반환합니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$cacheData = SimpleCache::init(SimpleCache::MEMCACHED)->get($cacheKey);
```

* 위와 같이 get 함수를 이용할 수 있습니다.

#### getSet

```php
/**
 * Finding the corresponding value in the cache, 
 * setting the value if it is not present in the cache, and returning the value stored in the cache.
 *
 * @param string $key
 * @param callable $callback
 * @param int $ttl 1 or more, up to 300 (seconds)
 *
 * @return mixed The corresponding values found in the cache, returning values from the cache. 
 *               If no value is present in the cache, it returns the result of the lambda function provided as the second parameter.
 */
```

* 캐시 내 조회하고자 하는 키값의 데이터가 있을 경우, 캐시 데이터를 반환하고 캐시 내 조회하고자 하는 키값의 데이터가 없을 경우, 2번째 파라미터의 람다 함수 내 로직 실행 결과를 캐시에 set 한 다음 저장된 데이터를 반환합니다.
* `$callback` 이 `null` 일 경우에는 캐시에 저장되는 값이 없으며, `null` 로 return 됩니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$ttl = 300;
$cacheData = SimpleCache::init(SimpleCache::MEMCACHED)->getSet(
    $cacheKey,
    function () {
        $cacheValue = "(CACHE_VALUE)";
        return $cacheValue;
    },
    $ttl
);
```

* 위와 같이 getSet 함수를 이용할 수 있습니다.
* ttl 값은 300을 초과할 수 없습니다.

#### delete

```php
/**
 * Removes cache item.
 *
 * @param string $key
 *
 * @return mixed True if the items were successfully removed, false otherwise
 */
```

* 캐시 내 저장된 데이터를 삭제하는 함수입니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$cacheData = SimpleCache::init(SimpleCache::MEMCACHED)->delete($cacheKey);
```

* 위와 같이 delete 함수를 이용할 수 있습니다.

### 개발 시 유의사항

* 캐싱 처리가 필요한 위치에서 직접 가이드에 제공된 함수를 호출하여 사용해주세요.

  ```php
  /**
   * 캐시 내 goods_benefit_config 키에 할당된 값이 있는지 확인합니다.
   * set()을 하지 않았거나 ttl(만료 시간)이 지나 캐시가 삭제된 경우에는 has() 값이 false 로 반환됩니다.
   */
  $cacheKey = "(CACHE_KEY)";
  if (SimpleCache::init(SimpleCache::MEMCACHED)->has($cacheKey)) {
      /**
       * goods_benefit_config 키에 할당된 값이 있으면
       * 캐시에서 값을 가져와 $goodsBenefitConfig 에 할당합니다.
       */
      $goodsBenefitConfig = SimpleCache::init(SimpleCache::MEMCACHED)->get($cacheKey);

  } else {
      /**
       * goods_benefit_config 키에 할당된 값이 없으면
       * 저장을 원하는 데이터를 가져와 다시 캐시에 set()을 합니다.
       * 
       * set()을 통해 goods_benefit_config 키에는 $goodsBenefitConfig 값이 300초 동안 저장됩니다.
       */
      $goodsBenefit = \App::load('\\Component\\Goods\\GoodsBenefit');
      $goodsBenefitConfig = $goodsBenefit->getConfig();
      $ttl = 300;
      SimpleCache::init(SimpleCache::MEMCACHED)->set($cacheKey, $goodsBenefitConfig, 300);
  }

  /**
   * getSet 함수를 활용한 캐시 개발 가이드입니다.
   * 1번째 파라미터의 $cacheKey에 대한 데이터가 캐시에 있을 경우,
   * 2번째 람다 함수 내 로직이 수행되지 않고 캐시 내 저장된 데이터가 반환됩니다.
   *
   * 1번째 파라미터의 $cacheKey에 대한 데이터가 캐시에 없을 경우,
   * 2번째 람다 함수 내 로직이 수행된 결과가 캐시 내 set 되며, set 된 결과가 반환됩니다.
   */
  $cacheKey = "(CACHE_KEY)";
  $ttl = 300;
  $goodsBenefitConfig = SimpleCache::init(SimpleCache::MEMCACHED)->getSet(
      $cacheKey,
      function () {
          $goodsBenefit = \App::load('\\Component\\Goods\\GoodsBenefit');
          $goodsBenefitConfig = $goodsBenefit->getConfig();
          return $goodsBenefitConfig;
      },
      $ttl
  );
  ```

{% hint style="danger" %} <mark style="color:red;">**캐싱 처리를 위한 클래스를 생성하여 기존 클래스를 상속받는 방법은 성능 저하와 클래스 간의 복잡성을 증가시킬 수 있습니다.**</mark> \ <mark style="color:red;">**가급적 가이드 내에 소개된 방식에 맞춰 활용하시는 것을 권장합니다.**</mark>
{% endhint %}
