소프트웨어 개발/Scala - Functional

cache

늘근이 2014. 12. 17. 17:42

캐시 (Cache) 사용하기

 

캐시기능은 어느정도 트래픽을 줄이고 원할하고 빠르게 웹 서비스를 제공하는데 있어 굉장히 유용한 기능(최후의 수단)입니다. 캐시기능은 컴퓨터 어디에나 존재하고 있습니다. CPU도 캐시 메모리를 이용하고 있고, DB도 내부적으로 캐시기능을 이용하고 있고, 웹 브라우저도 자체적인 캐시기능이 있습니다. 캐시는 자주 쓰는 기능이나 데이터를 가까운곳에 가져다놓고 빠르게 접근하여 꺼내쓰는 유용한 기능입니다. 어차피 자주 바뀌지않고 반복적으로 사용하는 조회기능이라면 그냥 있던 걸 쓰는게 좋지 않을까요? 다만 캐시를 너무 남발하게 되면 여러가지 문제가 발생하게 됩니다. 동기화나 분산 캐싱의 구조상의 복잡함이 급격히 늘어날수 있기 때문에, 충분히 생각을 해보고 프로그램을 설계하여야 합니다.

 

캐시를 제공하는 오픈소스 캐시 프로그램은 여러가지가 있습니다. 대부분의 라이선스가 상용화까지 가능한 형태의 라이선스이기 때문에 사용자가 할일은 자신의 환경에 적합한 캐시 프로그램만 찾으면 됩니다. EH Cache, OS Cache, JBOSS Cache, Swam Cache 등이 있으며 플레이 프레임워크에서는 대표적인 캐시 솔루션인 EH Cache는 자바의 Spring 프레임워크에도 통합되어 있으며, 플레이 프레임워크에서도 기본적으로 EH Cache를 제공하고 있습니다.

 

일단 캐시기능을 사용하려면, build.sbt 를 수정해야합니다.

 

libraryDependencies ++= Seq(

cache,

)

 

그리고 적절한 import구문도 필요합니다.

 

import play.api.cache.Cache

 

캐시 오브젝트가 가지고 있는 메서드는 사실 몇 개 없습니다. Map과 형식이 비슷하기 때문에 이해하기가 쉽습니다.

 

 

get(key: String)(implicit app: Application): Option[Any]

캐시로부터 값을 받습니다.

getAs[T](key: String)(implicit app: Application, ct: ClassTag[T]): Option[T]

T 타입으로 값을 가져옵니다.

getOrElse[A](key: String, expiration: Int = 0)(orElse: ⇒ A)(implicit app: Application, ct: ClassTag[A]): A

값이 있을경우 가져오고 그렇지 않으면 설정해준 값이 전달됩니다

remove(key: String)(implicit app: Application): Unit

캐시에서 값을 삭제합니다.

set(key: String, value: Any, expiration: Duration)(implicit app: Application): Unit

캐시를 설정합니다. Duration(100, MILLISECONDS) 와 같은 방식으로 시간을 설정합니다.

set(key: String, value: Any, expiration: Int = 0)(implicit app: Application): Unit

캐시를 설정하되, Int 초동안을 캐시를 살아있게 설정합니다.

 

한가지 명심할것은, 캐시는 세션과는 다르다는 것입니다. 세션은 접속 유저별로 다른 세션이 유지되기 때문에 로그인 정보등을 담고 있지만, 캐시는 웹사이트 자체의 정보를 들고있습니다. 세션은 또한 쓸수있는 메모리 양이 제한적이기 때문에, 되도록 캐시에는 캐시본연의 목적, 서버데이터등서 저장하는 것이 좋습니다.

 

HTTP 코드가 200번인 (Ok) 페이지들을 저장하는 로직을 이용할수있습니다.

 

def get(index: Int) = Cached.status(_ => "/resource/"+ index, 200) {

  Action {

    if (index > 0) {

      Ok(Json.obj("id" -> index))

    } else {

      NotFound

    }

  }

}

 

Cached 오브젝트에는 다음과 같은 status 메서드가 존재합니다.

 

def status(key: RequestHeader => String, status: Int, duration: Int): Cached

 

duration을 생략하면 수동으로 파괴하기 전까지는 계속 캐시가 유지됩니다. 첫번째 매개변수는 String타입은 key Int타입의 HTTP코드를 넣어주시면 됩니다. 자기자신의 타입을 받아 다시 똑같은 타입을 리턴시켜주기 때문에 체인 메서드 형식으로 includeStatus(status:Int) 를 다시한번 콜해주면 200 코드가 아닌 다른것도 저장할수 있습니다.

 

 

//그렇다면 객체나 그림등을 캐시할때는 어떻게 해야하는가?

 

'소프트웨어 개발 > Scala - Functional' 카테고리의 다른 글

Django Websocket구현하기  (0) 2015.04.27
플레이 프레임워크 IDE에 에러가 날때.  (0) 2015.04.26
coffee script  (0) 2014.12.15
scala 참조  (0) 2014.12.15
less  (0) 2014.12.12