{"id":1967,"date":"2025-03-03T16:46:06","date_gmt":"2025-03-03T07:46:06","guid":{"rendered":"https:\/\/skanto.co.kr\/?p=1967"},"modified":"2025-03-04T14:52:05","modified_gmt":"2025-03-04T05:52:05","slug":"spring-boot-caching-with-redis","status":"publish","type":"post","link":"https:\/\/skanto.co.kr\/?p=1967","title":{"rendered":"Spring Boot Caching with Redis"},"content":{"rendered":"\n<p>\uc694\uc998 Spring\uc744 \ud65c\uc6a9\ud558\ub294 \ubc29\ubc95\uc5d0 \uc775\uc219\ud574 \uc9c0\ub824\uace0 \ub178\ub825\ud558\uace0 \uc788\ub2e4. \uc0ac\uc2e4 Spring\uc740 \uac70\uc758 15\ub144\uc5ec \uc804 Spring Framework \ucd08\uae30\uc5d0 \uc7a0\uae50 \uc0ac\uc6a9\ud574\ubcf4\uace0 \uadf8 \uc774\ud6c4\ub294 \uacbd\ud5d8\uc774 \uc804\ubb34\ud55c \ud130\ub77c \uac1c\ub150 \uc815\ub3c4\ub294 \uc598\uae30\ud560 \uc218 \uc788\uc744\uc9c0\ub77c\ub3c4 \uc694\uc998 \uac1c\ubc1c\uc790\ub4e4\uacfc Spring \ud65c\uc6a9\uc5d0 \ub300\ud574 \ub9d0\uc744 \uc369\uc744 \uc218 \uc788\ub294 \ucc98\uc9c0\uac00 \ubabb\ub41c\ub2e4.<\/p>\n\n\n\n<p>\uc774 \ucc38\uc5d0 Spring\uc5d0 \ub179\uc544\uc788\ub294 \ud575\uc2ec\uc801\uc778 \uae30\uc220\ub4e4\uc744 \ud558\ub098\uc529 \uaebc\ub0b4\uc640\uc11c \uc774\ud574\ud558\uace0 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \uc774 \uae00\uc740 \uadf8 \uc2dc\ub9ac\uc988\uc758 \uccab \ubc88\uc9f8\ub85c Spring Cache\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774\ub2e4. \uc778\ud130\ub137\uc5d0\uc11c \ud754\ud788 \uc18c\uac1c\ub418\uace0 \uc788\ub294 \ub0b4\uc6a9\ub4e4 \ubcf4\ub2e4 \uc880 \ub354 \uae4a\uc219\uc774 \ub4e4\uc5b4\uac00\uc11c \uc5b4\ub5a4 \ub9e4\ucee4\ub2c8\uc998\uc5d0 \uc758\ud574 Caching\uc774 \uc801\uc6a9\ub418\uace0 \ub3d9\uc791\ud558\ub294 \uc9c0 \uc0b4\ud3b4\ubcf4\ub3c4\ub85d \ud55c\ub2e4.<\/p>\n\n\n\n<p>\uc2dc\uc791\ud558\uae30 \uc804\uc5d0, \uc774 \uae00\uc5d0\uc11c \uc124\uba85\ud558\ub294 \uc0d8\ud50c \uc5b4\ud50c\ub9ac\ucf00\uc774\uc158\uc740 \ucf54\ub4dc\ub9cc \ubd10\ub3c4 \uc27d\uac8c \uc774\ud574\ud560 \uc218 \uc788\ub3c4\ub85d \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4. \uc544\ud0a4\ud14d\ucc98\ub294 \uc77c\ubc18\uc801\uc73c\ub85c \ub9ce\uc774 \ud65c\uc6a9\ud558\ub294 Web-WAS-DB 3Tier \uae30\ubc18\uc73c\ub85c DB\ub294 PostgreSQL\uc744 \uadf8\ub9ac\uace0 Cache Store\ub85c\ub294 Redis\ub97c \uc774\uc6a9\ud588\uc73c\ub2c8 \ucc38\uace0\ud558\uae30 \ubc14\ub780\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Spring\uc5d0\uc11c Caching\uc740 Spring Framework 3.1\ubd80\ud130 \uc9c0\uc6d0\ud574 \uc624\uace0 \uc788\ub2e4. \uc774\ud6c4 Spring Framework 4.1\uc774 \ub418\uba74\uc11c \ud070 \ubcc0\ud654\uac00 \ubc1c\uc0dd\ud558\ub294\ub370 <a href=\"https:\/\/docs.spring.io\/spring-framework\/reference\/integration\/cache\/jsr-107.html\">JSR-107<\/a>\uc744 \uc9c0\uc6d0\ud568\uc73c\ub85c\uc368 Caching\uae30\ub2a5\uc774 \ud655\uc7a5\ub41c\ub2e4. \uc774\uac83\uc774 \uc694\uc998 \uac70\uc758 \ub300\ubd80\ubd84 \ud544\uc218\uc801\uc73c\ub85c \ud65c\uc6a9\ud558\ub294 Caching Annotation \uc9c0\uc6d0\uc758 \uc2dc\ucd08\uac00 \ub41c\ub2e4.<\/p>\n\n\n\n<p>\uc77c\ubc18\uc801\uc73c\ub85c Caching\uc774 \uc5b4\ub5a4 \uae30\ub2a5\uc778\uc9c0\ub294 \ub2e4\ub4e4 \uc54c\uace0 \uc788\uc73c\ub9ac\ub77c \uc0dd\uac01\ud55c\ub2e4. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*tTHfUBJf1wVii9cFfYBdhA.png\" alt=\"\"\/><\/figure>\n<\/div>\n\n\n<p>\uc704 \uadf8\ub9bc\uacfc \uac19\uc774 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c\ubd80\ud130 \ub370\uc774\ud130\ub97c \uc77d\uc5b4\uc624\uac70\ub098 Network\uc73c\ub85c \ubd80\ud130 \ub370\uc774\ud130\ub97c \uc77d\uc5b4\uc624\ub294 \uac83\uacfc \uac19\uc774 I\/O bound\uc758 \ub3d9\uc791\uc774\ub098 CPU intensive\ud55c \uc5f0\uc0b0\uc758 \uacbd\uc6b0 Application \uc131\ub2a5\uc744 \ub192\uc774\uae30 \uc704\ud574 Cache\ub97c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\ub2e4.<\/p>\n\n\n\n<p>Spring Framework\uc740 Cache Abstraction\uc774\ub77c\ub294 \ub9e4\ucee4\ub2c8\uc998\uc73c\ub85c \uc774\ub7f0 Expensive\ud55c \ub3d9\uc791\uc758 \ud69f\uc218\ub97c \uc904\uc77c \uc218 \uc788\ub3c4\ub85d Method \ucc28\uc6d0\uc5d0\uc11c Caching\uae30\ub2a5\uc744 \uc9c0\uc6d0\ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cache Abstraction<\/h2>\n\n\n\n<p>Spring Framework\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc5ec\ub7ec \uc11c\ube44\uc2a4\ub4e4 \ucc98\ub7fc Caching\ub3c4 Abstraction(\ucd94\uc0c1\ud654)\ub418\uc5b4 \uc788\ub2e4. \ub530\ub77c\uc11c \uac1c\ubc1c\uc790\uac00 Cache \ub370\uc774\ud130 \uc800\uc7a5\uc5d0 \ud544\uc694\ud55c Store\ub9cc \uc9c0\uc815\ud574\uc8fc\uba74 <em>Cache<\/em>\uc640 <em>CacheManager<\/em> \uc778\ud130\ud398\uc774\uc2a4 \uad6c\ud604\uccb4\uc778 Abstraction \ub808\ubca8\uc5d0\uc11c \ub300\ubd80\ubd84\uc758 \uae30\ub2a5\uc744 \ucc98\ub9ac\ud574 \uc90c\uc73c\ub85c \uac1c\ubc1c\uc790\uac00 \uad73\uc774 Caching\ub85c\uc9c1\uc744 \uc9c1\uc811 \uad6c\ud604\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.<\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Spring Boot\ub294 Bean \ud0c0\uc785\uc758 CacheManager \uac00 \ub4f1\ub85d\ub41c \uc0c1\ud0dc\uac00 \uc544\ub2c8\uac70\ub098 cacheResolver \uc774\ub984\uc73c\ub85c \ub41c CacheResolver\uac00 \uc815\uc758\ub418\uc9c0 \uc54a\uc740 \uc0c1\ud0dc\ub77c\uba74 \uc544\ub798\uc758 \uc21c\uc11c\ub300\ub85c Provider\ub97c \uc790\ub3d9 \ud0d0\uc9c0<\/span><\/strong>\ud55c\ub2e4.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generic<\/li>\n\n\n\n<li>JCache<\/li>\n\n\n\n<li>Hazelcast<\/li>\n\n\n\n<li>Infinispan<\/li>\n\n\n\n<li>Couchbase<\/li>\n\n\n\n<li>Redis<\/li>\n\n\n\n<li>Caffeine<\/li>\n\n\n\n<li>Cache2k<\/li>\n\n\n\n<li>Simple <em>(\uc704\uc758 Provider\ub97c \ucc3e\uc9c0 \ubabb\ud588\ub2e4\uba74 Default \uc801\uc6a9)<\/em><\/li>\n<\/ol>\n\n\n\n<p>CacheManager\uac00 \uc790\ub3d9\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub2e4\uba74 \uc774\ub97c \uc778\uc704\uc801\uc73c\ub85c \uad50\uccb4\ud560 \uc218 \uc788\ub2e4. <em>application.properties<\/em>\ud30c\uc77c\uc5d0 <em>spring.cache.type<\/em> property\ub97c \uc774\uc6a9\ud558\uc5ec \uc9c1\uc811 Provider\ub97c \uc9c0\uc815\ud558\uba74 \ud574\ub2f9 Cache Provider\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \uc608\ub97c \ub4e4\uc5b4 Cash Provider\ub97c Redis\ub85c \uc9c0\uc815\ud558\uace0\uc790 \ud55c\ub2e4\uba74 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud558\uba74 \ub41c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spring.cache.type=redis<\/code><\/pre>\n\n\n\n<p>\ub610\ud55c \uc774 \uc18d\uc131\uc744 \ud65c\uc6a9\ud558\uba74 Caching \uae30\ub2a5\uc744 \ub044\uace0 \uc2f6\uc744 \ub54c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4. \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud558\uba74 \ucf54\ub4dc\ub97c \uc77c\uc77c\uc774 \uc218\uc815\ud558\uc9c0 \uc54a\uace0\ub3c4 \uc27d\uac8c Caching\uae30\ub2a5\uc744 \uc911\uc9c0\uc2dc\ud0ac \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spring.cache.type=none<\/code><\/pre>\n\n\n\n<p>Cache Abstraction \uc740 \ud074\ub798\uc2a4\uc758 Method \ub808\ubca8\uc5d0\uc11c Caching\uc744 \uc801\uc6a9\ud55c\ub2e4\uace0 \uc55e\uc5d0\uc11c \uc124\uba85\ud588\ub2e4. \uc989, Method\uac00 \ud638\ucd9c \ub420 \ub54c\ub9c8\ub2e4 Caching\uc744 \uc704\ud574 \uba3c\uc800 \ub3d9\uc77c\ud55c \ubcc0\uc218 \uac12\uc73c\ub85c \uc774\ubbf8 \ud638\ucd9c \ub41c \uc801\uc774 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \uc774\ubbf8 \ud638\ucd9c\ub41c \uc801\uc774 \uc788\ub2e4\uba74 Method \ub97c \uc9c1\uc811 \uc2e4\ud589\ud558\uc9c0 \uc54a\uace0 Caching\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud55c\ub2e4. \uadf8\ub807\uc9c0 \uc54a\ub2e4\uba74 Method \uc2e4\ud589 \ud6c4 \uadf8 \uacb0\uacfc\ub97c \uba3c\uc800 Caching\ud558\uace0 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \uc774\ub7f0 \ubc29\ubc95\uc73c\ub85c Expensive\ud55c Method\ub294 \ud30c\ub77c\ubbf8\ud130\ub97c \uae30\ubc18\uc73c\ub85c \ucd5c\ucd08 \ud55c\ubc88\ub9cc \uc2e4\ud589\ud558\uace0 \uc774\ud6c4\ubd80\ud130\ub294 Caching\ub41c \uacb0\uacfc\ub97c \uc7ac\ud65c\uc6a9\ud558\ub3c4\ub85d \ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>Cache Abstraction \uc740 \uadf8 \uc678\uc5d0\ub3c4 \ubcf4\uc774\uc9c0 \uc54a\ub294 \ubd80\ubd84\uc5d0\uc11c Cache\uc758 \ub0b4\uc6a9\uc744 \uc5c5\ub370\uc774\ud2b8\ud558\uac70\ub098 Cache\ub97c \uc0ad\uc81c\ud558\ub294 \ub4f1 Cache\uc640 \uad00\ub828\ub41c \ub3d9\uc791\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \uc774\ub294 Application \uc2e4\ud589 \uc911\uc5d0 Cache \ub0b4\uc6a9\uc774 \ubcc0\uacbd\ub420 \uacbd\uc6b0 \ub0b4\ubd80\uc801\uc73c\ub85c Seamless\ud558\uac8c \ucc98\ub9ac\ud558\uac8c \ub41c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Auto Configuring<\/h2>\n\n\n\n<p>Spring Framework\uc740 \uc11c\ube44\uc2a4\ub294 \ub3c5\ub9bd\uc801\uc778 \ubaa8\ub4c8\ub85c \ubd84\ub9ac\ub418\uc5b4 \uc788\uc73c\uba70 \ud574\ub2f9 \ubaa8\ub4c8\uc744 Dependency\uc5d0 \ucd94\uac00\ud558\ub294 \uac83\ub9cc\uc73c\ub85c \uadf8 \uae30\ub2a5\uc744 \ubc14\ub85c \ud65c\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud558\uace0 \uc788\ub2e4. \ub530\ub77c\uc11c Spring Boot\uc5d0\uc11c Caching\uae30\ub2a5\uc744 \ud65c\uc6a9\ud558\uace0\uc790 \ud55c\ub2e4\uba74 Gradle\uc758 <em>build.gradle<\/em>\ud30c\uc77c\uc5d0 \uc544\ub798\uc640 \uac19\uc774 \ucd94\uac00(<strong>bold<\/strong>)\ud574\uc8fc\uae30\ub9cc \ud558\uba74 \uae30\ubcf8 \uc124\uc815\uc740 \ub05d\ub09c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dependencies {\n\timplementation 'org.springframework.boot:spring-boot-starter-web'\n<strong>\timplementation 'org.springframework.boot:spring-boot-starter-cache'<\/strong>\n\timplementation 'org.springframework.boot:spring-boot-starter-data-jpa'\n        ...\n}\n<\/code><\/pre>\n\n\n\n<p>Spring Boot starter\uc911 <em>spring-boot-starter-cache<\/em> \ub97c Dependency\uc5d0 \ucd94\uac00\ud558\uba74 Spring Context\uac00 Caching\uae30\ub2a5\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ub0b4\ubd80\uc801\uc73c\ub85c \ud658\uacbd\uc744 \uad6c\uc131\ud55c\ub2e4.<\/p>\n\n\n\n<p>\uc774 \uc0c1\ud0dc\uc5d0\uc11c Default \uc124\uc815\ub9cc\uc73c\ub85c Caching\uae30\ub2a5\uc744 \ud65c\uc6a9\ud560 \uc218\ub294 \uc788\ub2e4. \ub0b4\ubd80\uc801\uc73c\ub85c \uc784\uc758\uc758 Cache Store\uac00 \ucd94\uac00\ub41c \uc0c1\ud0dc\uac00 \uc544\ub2c8\ubbc0\ub85c \uc55e\uc5d0\uc11c \uc124\uba85\ud55c \ud0d0\uc9c0 \uc21c\uc11c\uc5d0\uc11c \uc81c\uc77c \ub9c8\uc9c0\ub9c9\uc5d0 \uc81c\uacf5\ub418\ub294 Simple Provider(<em>ConcurrentHashMap<\/em>)\uac00 default\ub85c \uc801\uc6a9\ub41c\ub2e4. \uc774 <span style=\"text-decoration: underline;\">Simple Provider\ub294 \uae30\ubcf8\uc801\uc778  Store\ub9cc \uc81c\uacf5\ud558\uace0 TTL\/TTI\/Eviction \uc815\ucc45 \ub4f1\uc744 \uc81c\uacf5\ud558\uc9c0 \uc54a\uc544 \uae30\ub2a5\uc774 \ub9e4\uc6b0 \uc81c\ud55c\uc801\uc774\ub2e4. \ub530\ub77c\uc11c, \uc0c1\uc6a9\ud658\uacbd\uc5d0\ub294 \uc808\ub300 \uc801\uc6a9\ud558\uc9c0 \ub9d0\uc544\uc57c \ud55c\ub2e4<\/span>.<\/p>\n\n\n\n<p>\uc774 \uae00\uc5d0\uc11c\ub294 Cache Store\ub85c Redis\ub97c \ud65c\uc6a9\ud558\uae30\ub85c \ud588\uc73c\ubbc0\ub85c \uc544\ub798\uc640 \uac19\uc774 <em>build.gradle<\/em>\ud30c\uc77c\uc5d0 Redis Dependency\ub9cc \ucd94\uac00\ud558\uba74 WAS \uc2dc\uc791 \ub2e8\uacc4\uc5d0\uc11c \uc790\ub3d9\uc73c\ub85c Redis Cache Store\ub97c \ud0d0\uc9c0\ud558\ubbc0\ub85c Cache Store\ub97c \uc9c0\uc815\ud558\ub294 \ub2e8\uacc4\uae4c\uc9c0 \uac04\ub2e8\ud558\uac8c \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dependencies {\n\timplementation 'org.springframework.boot:spring-boot-starter-web'\n<strong>\t<\/strong>implementation 'org.springframework.boot:spring-boot-starter-cache'\n        <strong>implementation 'org.springframework.boot:spring-boot-starter-data-redis'<\/strong>\n\timplementation 'org.springframework.boot:spring-boot-starter-data-jpa'\n        ...\n}<\/code><\/pre>\n\n\n\n<p>\uc774\uc81c Cache Store\ub85c Redis\ub97c \ud65c\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud588\uc73c\ub2c8 \uc544\ub798\uc640 \uac19\uc774 Spring\uc758 <em>application.properties<\/em>\ud30c\uc77c\uc5d0 Redis \uc811\uc18d\uc744 \uc704\ud55c \uae30\ubcf8\uc801\uc778 \ud658\uacbd\ubcc0\uc218\ub97c \uc9c0\uc815\ud55c\ub2e4. Redis\uad00\ub828 cache default\uc124\uc815\uc740 <em>spring.cache.data.redis.*<\/em> \uc18d\uc131\uc73c\ub85c \uc9c0\uc815\ud55c\ub2e4. \uc5ec\uae30\uc11c\ub294 Redis\uac00 <em>local<\/em>\uc5d0 \uc124\uce58\ub418\uc5b4 \uc788\uace0 <em>6379<\/em> \ud3ec\ud2b8(default)\ub85c \uc11c\ube44\uc2a4\ub418\uace0 \uc788\ub2e4\uace0 \uac00\uc815\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># redist host address(default: localhost)\nspring.data.redis.host=localhost\n\n# redis service port(default: 6379)\nspring.data.redis.port=6379\n\n# sets cache expiration(if not (m), time is milliseconds). By default the entries never expire\nspring.cache.redis.time-to-live=1m<\/code><\/pre>\n\n\n\n<p>\uc774\uc640 \uac19\uc774 \uae30\ubcf8\uc801\uc778 \ud658\uacbd\ubcc0\uc218\ub85c Redis \uc11c\ubc84\uc640 \ud3ec\ud2b8, \uadf8\ub9ac\uace0 Cache\uc758 TTL(1\ubd84)\uc744 \uc124\uc815\ud588\uc9c0\ub9cc \uc0ac\uc2e4 \uc774 \uac12\ub4e4\uc740 \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4. \uc65c\ub0d0\ud558\uba74 \uac01 Property\uc758 default \uac12\uc774 \uac01\uac01 <em>localhost<\/em>, <em>6379<\/em>, \uadf8\ub9ac\uace0 no-expire(\uc0ad\uc81c\ub418\uc9c0 \uc54a\uc74c)\uc774\uae30 \ub54c\ubb38\uc774\ub2e4.<\/p>\n\n\n\n<p>\ud658\uacbd\uc124\uc815\ub9cc\uc73c\ub85c\ub294 \ud560 \uc218 \uc5c6\ub294 \uc880 \ub354 \uc12c\uc138\ud55c \uc81c\uc5b4\ub97c \ud558\uace0 \uc2f6\uc744 \uacbd\uc6b0 \uc790\uc2e0\ub9cc\uc758 <em>RedisCacheConfiguration<\/em> \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 <em>@Bean<\/em>\uc73c\ub85c SpringContext\uc5d0 \ucd94\uac00\ud574 \uc8fc\uae30\ub9cc \ud558\uba74 Redis Provider\uac00 \uc790\ub3d9\uc73c\ub85c \uc778\uc2dd\ud55c\ub2e4. \uc774 \uacfc\uc815\uc740 \ucd94\ud6c4\uc5d0 \uc790\uc138\ud558\uac8c \uc124\uba85\ud558\uae30\ub85c \ud55c\ub2e4.<\/p>\n\n\n\n<p>\uc774\uc81c Spring Application \ud074\ub798\uc2a4\uc5d0 <strong>@EnableCaching <\/strong>Annotation\uc744 \uc9c0\uc815\ud558\uae30\ub9cc \ud558\uba74 Spring Boot\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c Caching\uae30\ub2a5\uc744 \uc790\ub3d9\uc124\uc815(auto-configuration)\ud558\ub3c4\ub85d \ud574\uc900\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enabling Caching Annotation<\/h2>\n\n\n\n<p>\uc790, \uc774\uc81c \ubcf8\uaca9\uc801\uc73c\ub85c \uc0d8\ud50c\ucf54\ub4dc\ub97c \ud65c\uc6a9\ud558\uc5ec \uc124\uba85\uc744 \uc774\uc5b4\uac00 \ubcf4\ub3c4\ub85d \ud558\uaca0\ub2e4.<\/p>\n\n\n\n<p>Cache annotation\uc778 <em>@EnableCaching<\/em> \ub9cc \uc124\uc815\ud588\ub2e4\uace0 \ud574\uc11c \uc790\ub3d9\uc801\uc73c\ub85c Caching\uae30\ub2a5\uc774 \ub3d9\uc791\ud558\ub294 \uac83\uc740 \uc544\ub2c8\ub2e4. <span style=\"text-decoration: underline;\">Caching\uae30\ub2a5\uc740 Spring\uc758 \ub2e4\ub978 \uae30\ub2a5\ub4e4\ucc98\ub7fc \uc120\uc5b8\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \uc9c0\uc815\ud574 \uc8fc\uc5b4\uc57c \ud55c\ub2e4.<\/span> <span style=\"text-decoration: underline;\">\uc989, <em>@Configuration<\/em> \uc774 \uc9c0\uc815\ub41c \ud074\ub798\uc2a4\uc5d0 \ucd94\uac00\uc801\uc73c\ub85c <span style=\"text-decoration: underline;\"><em>@EnableCaching<\/em> annotation\uc744 <\/span>\uc9c0\uc815\ud574 \uc8fc\uc5b4\uc57c\ub9cc \uc2dc\uc791\ub2e8\uacc4\uc5d0\uc11c \uc790\ub3d9\uc73c\ub85c \uc778\uc2dd\ud558\uace0 \ub3d9\uc791\ud558\uac8c \ub418\uc5b4\uc788\ub2e4.<\/span> \ubc88\uac70\ub86d\uae30\ub294 \ud558\uc9c0\ub9cc \uc774\ub294 \ud504\ub85c\uadf8\ub7a8 \ub3d9\uc791 \uc911 Caching \uae30\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc758\uc2ec\ub420 \uacbd\uc6b0 \ucf54\ub4dc \uc0c1\uc5d0\uc11c Caching\uad00\ub828 annotation\uc744 \uc77c\uc77c\uc774 \uc81c\uac70\ud558\ub294\uac83 \ubcf4\ub2e4 <em>@EnableCaching<\/em> annotation \ud558\ub098\ub9cc \uc81c\uac70\ud558\ub354\ub77c\ub3c4 Caching\uae30\ub2a5\uc744 \uc911\uc9c0\uc2dc\ud0ac \uc218 \uc788\ub294 \uc21c\uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4. (\uc55e\uc5d0\uc11c \uc124\uba85\ud55c <em>spring.cache.type=none<\/em> \ub3c4 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \ud568)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\n\n@SpringBootApplication\n<strong>@EnableCaching<\/strong>\npublic class CachingApplication {\n    \n    \/**\n     * @param args\n     *\/\n    public static void main(String&#91;] args) {\n        SpringApplication.run(CachingApplication.class, args);\n    }\n}<\/code><\/pre>\n\n\n\n<p>\uc704 \ucf54\ub4dc\uc5d0\uc11c <strong><em>@SpringBootApplication<\/em>\uc740 \ub0b4\ubd80\uc801\uc73c\ub85c <em>@Configuration<\/em>\uc744 \ub0b4\ud3ec\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0<\/strong> \uc5ec\uae30\uc5d0 <em>@EnableCaching<\/em> annotation\uc744 \ucd94\uac00\ud558\uba74 Caching\uae30\ub2a5\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc778\uc2dd\ud558\uace0 \ub3d9\uc791\ud558\uac8c \ub41c\ub2e4.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/0*zScVClCCjn6jHSSC.gif\" alt=\"\"\/><\/figure>\n<\/div>\n\n\n<p>\uc774\uc81c Spring Boot \uac1c\ubc1c\uc5d0\uc11c \uc77c\ubc18\uc801 \ud15c\ud50c\ub9bf\uc778 Controller, Repository, Model, Service \ubcc4\ub85c \uac01\uac01 \uac04\ub2e8\ud55c \uc0d8\ud50c \ucf54\ub4dc\ub97c \ucd94\uac00\ud574 \ubcf4\uae30\ub85c \ud558\uc790. \uc55e\uc5d0\uc11c\ub3c4 \uc5b8\uae09\ud588\uc9c0\ub9cc \uc774 \uae00\uc758 \uc131\uaca9\uc0c1 Spring\uc758 \uc5ec\ub7ec \uae30\ub2a5\ub4e4 \uc911 Caching \uae30\ub2a5\uc5d0 \ucd1b\uc810\uc744 \ub9de\ucd94\uc5b4 \uc124\uba85\uc744 \uc774\uc5b4\uac00\uace0\uc790 \ud55c\ub2e4. \uc0d8\ud50c Application\uc740 \ucd5c\ub300\ud55c \uac04\ub2e8\ud558\uac8c \uad6c\uc131\ud558\uba70, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 Employee \ud14c\uc774\ube14(id, name, address)\uc744 \ud558\ub098 \ub9cc\ub4e4\uace0 JPA\ub97c \uc774\uc6a9\ud558\uc5ec \ud574\ub2f9 \ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ud2b9\uc815 \ub370\uc774\ud130\ub97c \ucc3e\uc544 \ucd9c\ub825\ud558\ub294 RESTful API \ud615\ud0dc\uc774\ub2e4. \uc774 \uacfc\uc815\uc5d0\uc11c Caching\uc744 \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud558\ub294\uc9c0 \uc0b4\ud3b4\ubcf4\ub3c4\ub85d \ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Model<\/h3>\n\n\n\n<p>\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ud14c\uc774\ube14(Employee) \ub370\uc774\ud130\uc758 DTO \ud074\ub798\uc2a4(POJO)\ub85c \uc544\ub798\uc640 \uac19\ub2e4. \uc774 \ubd80\ubd84\uc740 \uac04\ub2e8\ud558\ubbc0\ub85c \uc124\uba85\uc740 \uc0dd\ub7b5\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.demo.model;\n\nimport java.io.Serializable;\n\nimport jakarta.persistence.Column;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.Id;\n\n@Entity\npublic class Employee implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    @Id\n    @Column(nullable = false)\n    private int id;\n    \n    @Column(nullable = false)\n    private String name;\n    \n    @Column(nullable = false)\n    private String address;\n    \n    \/**\n     * Default Constructor. Needed for Spring Framework when creating managed bean object\n     *\/\n    public Employee() {}\n    \n    \/**\n     * @param id\n     * @param name\n     * @param address\n     *\/\n    public Employee(int id, String name, String address) {\n        this.id = id;\n        this.name = name;\n        this.address = address;\n    }\n    \n    public int getId() {\n        return this.id;\n    }\n    \n    public void setId(int id) {\n        this.id = id;\n    }\n    \n    public String getName() {\n        return this.name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getAddress() {\n        return this.address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Repository<\/h3>\n\n\n\n<p>JpaRepository \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0c1\uc18d\ubc1b\uc544 <em>EmployeeRepository<\/em>\ub97c \uc815\uc758\ud55c\ub2e4. \uc774 \ubd80\ubd84\ub3c4 \uc124\uba85\uc744 \uc0dd\ub7b5\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.demo.repository;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\n\nimport com.example.demo.model.Employee;\n\npublic interface EmployeeRepository extends JpaRepository&lt;Employee, Integer&gt; {\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Service<\/h3>\n\n\n\n<p>Service\ub294 Controller\uac00 Client\ub85c\ubd80\ud130 \uc694\uccad\uc744 \ubc1b\uc73c\uba74(Facade) \uadf8 \uc694\uccad\uc744 \uc2e4\uc81c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub85c Employees\ub77c\ub294 \uc774\ub984\uc73c\ub85c \uc815\uc758\ud55c\ub2e4. \uc774 \ud074\ub798\uc2a4\uac00 \uc815\uc758\ud558\ub294 \uba54\uc18c\ub4dc\ub2e8\uc5d0\uc11c \uc2e4\uc81c Caching\uae30\ub2a5\uc744 \uc801\uc6a9\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.demo.service;\n\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cache.annotation.CacheEvict;\nimport org.springframework.cache.annotation.CachePut;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.stereotype.Service;\n\nimport com.example.demo.model.Employee;\nimport com.example.demo.repository.EmployeeRepository;\n\n\/**\n * Employees class represents database table named employee\n *\/\n@Service\npublic class Employees {\n\n    private final Logger log = LoggerFactory.getLogger(getClass());\n    \n    \/**\n     * repository will be auto-wired through constructor\n     *\/\n    private final EmployeeRepository repository;\n\n    \/**\n     * Constructor\n     * @param repository the instance will be injected through Spring DI\n     *\/\n    public Employees(EmployeeRepository repository) {\n        this.repository = repository;\n    }\n    \n    \/**\n     * \n     * @param employee\n     * @return\n     *\/\n    public Employee saveEmployee(Employee employee) {\n        log.info(\"Save the record\");\n        return repository.save(employee);\n    }\n\n    @Cacheable(cacheNames = \"employee\")\n    public Employee getEmployeeById(int id) throws InterruptedException {\n        TimeUnit.SECONDS.sleep(2); \/\/ thread sleep for 2 seconds\n        log.info(\"Scenario: 2 seconds consumed in finding an Employee by id: {}\", id);\n        return repository.findById(id).orElse(null);\n    }\n    \n    @CachePut(cacheNames = \"employee\", key = \"#employee.id\")\n    public Employee updateEmployee(Employee employee) {\n        log.info(\"Update the record with id: {}\", employee.getId());\n        return repository.save(employee);\n    }\n    \n    @CacheEvict(cacheNames = \"employee\", key = \"#id\")\n    public void deleteEmployee(int id) {\n        log.info(\"Delete the record id: {}\", id);\n        repository.deleteById(id);\n    }\n}<\/code><\/pre>\n\n\n\n<p>\uc774 \ud074\ub798\uc2a4\uc758 <em>getEmployeeById<\/em>, <em>updateEmployee<\/em>, <em>updateEmployee<\/em> \uba54\uc18c\uc5d0 \uac01\uac01 <em>@Cacheable<\/em>, <em>@CachePut<\/em>, <em>@CacheEvict<\/em> \uc640 \uac19\uc774 annotation\uc744 \ud65c\uc6a9\ud558\uc5ec Caching\uae30\ub2a5\uc744 \uc801\uc6a9\ud558\uc600\ub2e4. \uc608\ub97c \ub4e4\uc5b4 <em>@Cacheable<\/em>\uc774 \uc801\uc6a9\ub41c <em>getEmployeeById()<\/em> Method\uc758 \uacbd\uc6b0, \ud30c\ub77c\ubbf8\ud130\uc778 id\ub97c \uc774\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ud574\ub2f9 id\uc758 Employee\ub97c \uac80\uc0c9\ud55c \ud6c4 \uc774 \uac12\uc744 \ubc18\ud658\ud558\uba70 Cache Proxy\ub294 \uadf8 \uacb0\uacfc\ub97c Controller\ub85c \ubc18\ud658\ud558\uae30 \uc804\uc5d0 Intercept\ud558\uc5ec Redis\ub85c \uac12\uc744 Caching\ud55c\ub2e4.<\/p>\n\n\n\n<p>\uc774\ud6c4\uc5d0 \ub3d9\uc77c\ud55c id\ub97c \uac00\uc9c4 \ud30c\ub77c\ubbf8\ud130 \uac12\uc774 \ub4e4\uc5b4\uc62c \uacbd\uc6b0 Cache Proxy\ub294 <em>getEmployeeById()<\/em> Method\ub97c \ub2e4\uc2dc \uc2e4\ud589\ud558\uc9c0 \uc54a\uace0 Cache\uc5d0 \uc800\uc7a5\ub41c \uac12\uc744 \ubc14\ub85c \ubc18\ud658\ud55c\ub2e4. <em>getEmployeeById()<\/em> Method\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac80\uc0c9\uc5d0 2\ucd08(<em>TimeUnit.SECONDS.sleep(2);<\/em>)\uac00 \uc18c\uc694\ub3c4\ub85d \uc2dc\ubbac\ub808\uc774\uc158\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\ucd08 \ud638\ucd9c\uc5d0\uc11c\ub294 Caching\ub41c \uc0c1\ud0dc\uac00 \uc544\ub2c8\ubbc0\ub85c \uc751\ub2f5 \ubc1b\uc744 \ub54c\uae4c\uc9c0 2\ucd08\uac00 \uac78\ub9ac\uc9c0\ub9cc \uc774\ud6c4 \ud638\ucd9c\ubd80\ud130\ub294 \uc774\ubbf8 Caching\ub41c \uac12\uc744 \ud65c\uc6a9\ud558\ubbc0\ub85c \uc9c0\uccb4\uc5c6\uc774 \uacb0\uacfc\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>Spring\uc758 Caching Abstraction\uc740 Caching\uc744 \uc120\uc5b8\ud560 \uc218 \uc788\ub3c4\ub85d \uc544\ub798\uc640 \uac19\uc740 Java Annotation\uc744 \uc81c\uacf5\ud55c\ub2e4. \uc790\uc138\ud55c \ub0b4\uc6a9\uc740 <a href=\"https:\/\/docs.spring.io\/spring-framework\/reference\/integration\/cache\/jsr-107.html\">JCache Annotatioins<\/a>\uc5d0\uc11c \ud655\uc778\uc774 \uac00\ub2a5\ud558\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>@Cacheable<\/em>:  \uce90\uc2dc\ub97c \uc0dd\uc131\ud55c\ub2e4.<br>Method\uc758 \uacb0\uacfc \uac12\uc744 \uce90\uc2f1\ud558\uba70 \uac00\uc7a5 \uac04\ub2e8\ud55c \uc124\uc815\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uce90\uc2dc \uc774\ub984\ub9cc \uc9c0\uc815\ud558\ub294 \uac83\uc774\ub2e4. (<em>@Cacheable(&#8220;employee&#8221;)<\/em>)<\/li>\n\n\n\n<li><em>@CacheEvict<\/em>: \uce90\uc2dc\ub97c \uc81c\uac70\ud55c\ub2e4.<\/li>\n\n\n\n<li><em>@CachePut<\/em>: Method\uc758 \uc2e4\ud589\uc77c \ubc29\ud574\ud558\uc9c0 \uc54a\uc73c\uba74\uc11c \uce90\uc2dc\ub97c \uc5c5\ub370\uc774\ud2b8 \ud55c\ub2e4.<\/li>\n\n\n\n<li><em>@Caching<\/em>: \ud558\ub098\uc758 Method\uc5d0 \ubcf5\uc218 \uac1c\uc758 \uce90\uc2f1 \ub3d9\uc791\uc774 \uac00\ub2a5\ud558\ub3c4\ub85d \ud55c\ub2e4.<\/li>\n\n\n\n<li><em>@CacheConfig<\/em>: \ud074\ub798\uc2a4 \ub808\ubca8\uc5d0\uc11c Cache\uc640 \uc5f0\uad00\ub41c \uc124\uc815\uc744 \uc11c\ub85c \uacf5\uc720\ud55c\ub2e4.<br>\ud074\ub798\uc2a4 \ub808\ubca8\uc5d0\uc11c \uc9c0\uc815\ud558\uba70 Cache <em>\uc774\ub984<\/em>, Custom <em>KeyGenerator<\/em>, Custom <em>CacheManager<\/em>, Custom <em>CacheResolver<\/em>\ub97c \uc9c0\uc815\ud558\uace0 \ud074\ub798\uc2a4 \uc804\uccb4\uc5d0\uc11c \uacf5\uc720\ud560 \uc218 \uc788\ub2e4.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Default Key Generation<\/h4>\n\n\n\n<p>Cache\ub294 \uae30\ubcf8\uc801\uc73c\ub85c Key-Value \ud615\ud0dc\ub97c \uac00\uc9c0\ubbc0\ub85c Cache\uc5d0 \uc800\uc7a5\ub41c \uac12\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub3c4\ub85d Method\uc640 \ub9e4\ud551\ub418\ub294 \ud0a4\uac00 \ud544\uc694\ud558\ub2e4. Cache Abstraction\uc740 \uc544\ub798\uc758 \uc54c\uace0\ub9ac\uc998\uc5d0 \uae30\ubc18\ud558\uc5ec <em>KeyGenerator<\/em>\ub97c \uc801\uc6a9\ud55c\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud30c\ub77c\ubbf8\ud130\uac00 \uc5c6\uc744 \uacbd\uc6b0 SimpleKey.EMPTY\ub97c \ubc18\ud658<\/li>\n\n\n\n<li>\ud30c\ub77c\ubbf8\ud130\uac00 1\uac1c\uc77c \uacbd\uc6b0 \ud574\ub2f9 \ud30c\ub77c\ubbf8\ud130\uc758 \uc778\uc2a4\ud134\uc2a4\ub97c \ubc18\ud658<\/li>\n\n\n\n<li>\ud30c\ub77c\ubbf8\ud130\uac00 1\uac1c \uc774\uc0c1\uc77c \uacbd\uc6b0 \ubaa8\ub4e0 \ud30c\ub77c\ubbf8\ud130\ub97c \ud3ec\ud568\ud558\ub294 SimpleKey\ub97c \ubc18\ud658<\/li>\n<\/ul>\n\n\n\n<p>\uc774 \ubc29\ubc95\uc740 \ud30c\ub77c\ubbf8\ud130\ub4e4\uc758 \uac12\uc774 \uc77c\ubc18\uc801\uc774\uba74\uc11c <em>hashCode()<\/em>\uc640 <em>equals()<\/em> Method\ub97c \uc801\uc808\ud558\uac8c \uad6c\ud604 \ub418\uc5c8\uc744 \uacbd\uc6b0\ub294 \ub300\ubd80\ubd84\uc758 \uacbd\uc6b0 \uc798 \ub3d9\uc791\ud558\uc9c0\ub9cc \uadf8\ub807\uc9c0 \uc54a\uc740 \uacbd\uc6b0 <em>org.springframework.cache.interceptor.KeyGenerator<\/em> \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc9c1\uc811 \uad6c\ud604\ud574\uc11c \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4. KeyGenerator\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5c8\ub2e4\uba74 \uc544\ub798 \ucf54\ub4dc\uc640 \uac19\uc774 Custom KeyGenerator\ub97c @Bean\uc73c\ub85c \ub9cc\ub4e4\uace0 \uadf8 \uc774\ub984\uc744 \ub4f1\ub85d\ud574 \uc8fc\uba74 \ub41c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Cacheable(cacheNames=\"employee\", keyGenerator=\"myKeyGenerator\")<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Method Visibility and Annotations<\/h4>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Cache annotation\uc740 public visibility \ub97c \uac00\uc9c4 Method\uc5d0\ub9cc \uc9c0\uc815<\/span><\/strong>\ud560 \uc218 \uc788\ub2e4. protected, private \ub610\ub294 package visibility \ub97c \uac00\uc9c4 Method\uc5d0 Caching\uad00\ub828 annotation \uc744 \uc9c0\uc815\ud560 \uacbd\uc6b0 \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uc9c0\ub294 \uc54a\uc9c0\ub9cc Caching\uad00\ub828 \uc124\uc815 \uc815\ubcf4\uac00 \uc678\ubd80\ub85c \ub178\ucd9c\ub418\uc9c0 \uc54a\uc544 Spring Boot\uc758 Cache Proxy\uac00 \uc774\ub97c \uc778\uc2dd\ud558\uc9c0 \ubabb\ud55c\ub2e4. \ub530\ub77c\uc11c public Method \uc774\uc678\uc5d0 Caching annotation\uc744 \uc9c0\uc815\ud560 \uacbd\uc6b0 Cache\uae30\ub2a5\uc774 \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4\ub294 \uc810\uc744 \uc8fc\uc758\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p>\ub610\ud55c <span style=\"text-decoration: underline;\">Spring\uc740 Interface\uc5d0 <em>@Cache*<\/em> annotation\uc744 \uc9c0\uc815\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub77c Concrete \ud074\ub798\uc2a4 \uc989, Interface\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\uc640 Method\uc5d0 annotation \uc744 \uc9c0\uc815\ud558\ub3c4\ub85d \uac00\uc774\ub4dc<\/span>\ud558\uace0 \uc788\ub2e4. Interface\uc5d0 <em>@Cache*<\/em> annotation\uc744 \uc9c0\uc815\ud560 \uc218\ub294 \uc788\uc9c0\ub9cc \uc774 \uacbd\uc6b0 proxy\ubaa8\ub4dc\ub97c \uc124\uc815(<em>mode=&#8221;proxy&#8221;<\/em>)\ud574\uc57c\ub9cc \ub3d9\uc791\ud55c\ub2e4\ub294 \uc810\ub3c4 \uc8fc\uc758\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p>\uadf8\ub9ac\uace0 Proxy\ud2b9\uc131\uc0c1 @Cache* annotation\uc744 \uc124\uc815\ud55c \ud074\ub798\uc2a4\uc758 \uc678\ubd80\ub85c\ubd80\ud130 \ub4e4\uc5b4\uc624\ub294 method call\uc5d0 \ub300\ud574\uc11c\ub9cc \ub3d9\uc791\ud55c\ub2e4. \ub530\ub77c\uc11c, \ud074\ub798\uc2a4 \ub0b4\ubd80\uc5d0\uc11c \uc790\uccb4\uc801\uc73c\ub85c \ud638\ucd9c\ud558\ub294 \uacbd\uc6b0\ub294 \ud638\ucd9c\ubc1b\ub294 method\uac00 @Cacheable\ub85c \uc124\uc815\ub418\uc5c8\ub2e4 \ud558\ub354\ub77c\ub3c4 Caching \uae30\ub2a5\uc774 \ub3d9\uc791\ud558\uc9c0 \uc54a\ub294\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Synchronized Caching<\/h4>\n\n\n\n<p>Multi-Thread \ud658\uacbd\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \ud30c\ub77c\ubbf8\ud130 \uac12\uc73c\ub85c operation\uc774 \ub3d9\uc2dc\uc5d0 \ud638\ucd9c\ub420 \uc218 \uc788\ub2e4. <span style=\"text-decoration: underline;\">Cache Abstraction \uc740 \uae30\ubcf8\uc801\uc73c\ub85c Lock\uc744 \uc81c\uacf5\ud558\uc9c0 \uc54a\ub294\ub2e4<\/span>. \ub530\ub77c\uc11c Caching\uc758 \ubaa9\uc801\uacfc \ub9de\uc9c0\uc54a\uac8c \ub3d9\uc77c\ud55c \uac12\uc73c\ub85c \uc5ec\ub7ec \ubc88 \uc5f0\uc0b0\uc774 \uc218\ud589\ub420 \uc218\ub3c4 \uc788\ub2e4. \uc774\ub7f0 \uacbd\uc6b0\ub97c \ub300\ube44\ud574\uc11c \uc544\ub798\uc640 \uac19\uc774 <em>sync<\/em> \uc18d\uc131\uc744 \uc9c0\uc815\ud558\uba74 \uc5f0\uc0b0\uc911\uc77c \ub54c \ud558\ub098\uc758 Thread\ub9cc \uc5f0\uc0b0\uc744 \uc218\ud589\ud558\ub3c4\ub85d Cache Provider\uac00 Cache \uc9c4\uc785\uc5d0 Lock\uc744 \uac78 \uc218 \uc788\ub3c4\ub85d \uc9c0\uc6d0\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Cacheable(cacheNames=\"employee\", sync=true)<\/code><\/pre>\n\n\n\n<p>\ucc38\uace0\ub85c \uc774 \uc18d\uc131\uc740 Optional \uae30\ub2a5\uc774\ub77c\ub294 \uc810\uc744 \ucc38\uace0\ud558\uae30 \ubc14\ub780\ub2e4. \uc65c\ub0d0\ud558\uba74 \uc0ac\uc6a9 \uc911\uc778 Cache Store \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \uc774 \uae30\ub2a5\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uc744 \uc218\ub3c4 \uc788\uae30 \ub54c\ubb38\uc774\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Conditional Caching<\/h4>\n\n\n\n<p>\ud2b9\uc815 \uc870\uac74\uc5d0\uc11c\ub294 Caching \uae30\ub2a5\uc744 \uc801\uc6a9\ud558\ub294 \uac83\uc774 \ubd80\uc801\uc808 \ud558\ub2e4\uba74 <em>condition<\/em> \ud30c\ub77c\ubbf8\ud130\ub97c \ud65c\uc6a9\ud558\uba74 \ub41c\ub2e4. \uc774 \ud30c\ub77c\ubbf8\ud130\ub294 SpEL(Spring Expression Language)\ub97c \uc9c0\uc6d0\ud55c\ub2e4. EL\uc758 \uacb0\uacfc\uac00 true\uc774\uba74 Cache\uac00 \uc801\uc6a9\ub41c\ub2e4. \ubc18\ub300\ub85c Cache\uc5d0 \uac12\uc744 \uc800\uc7a5\ud558\ub294 \uac83\uc744 \ubc29\uc9c0\ud558\uace0\uc790 \ud560 \uacbd\uc6b0 <em>unless<\/em>\ub97c \ud65c\uc6a9\ud558\uba74 \ub41c\ub2e4. \ucc38\uace0\ub85c <span style=\"text-decoration: underline;\">unless\ub294 condition\uacfc \ub2ec\ub9ac Method\uac00 \uc2e4\ud589\ub41c \uc774\ud6c4\uc5d0 EL\ud3c9\uac00\uac00 \uc774\ub8e8\uc5b4 \uc9c4\ub2e4<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Cacheable(cacheNames=\"employee\", condition=#name.length() &lt; 10, unless=\"#address.length() &lt; 20\")<\/code><\/pre>\n\n\n\n<p>Spring Framework\uc740 Caching\uc5d0\uc11c SpEL\uc5d0 \ud65c\uc6a9\ud560 \uc218 \uc788\ub294 \ub0b4\uc7a5 \ud30c\ub77c\ubbf8\ud130\ub97c \uc9c0\uc6d0\ud558\uace0 \uc788\uc73c\uba70 <a href=\"https:\/\/docs.spring.io\/spring-framework\/reference\/integration\/cache\/annotations.html#cache-spel-context\">Available Caching SpEL Evaluation Context<\/a>\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Controller<\/h3>\n\n\n\n<p>\ud074\ub77c\uc774\uc5b8\ud2b8\ub85c \uc694\uccad\uc774 \uc624\uba74 \uc81c\uc77c \uba3c\uc800 \ucc98\ub9ac\ud558\ub294 Facade \uc5ed\ud560\uc744 \ud558\uba70 \uc5ec\uae30\uc11c RESTful API\uc758 \uc720\ud615\uc5d0 \ub530\ub77c \ud574\ub2f9 Service\ub85c \uc694\uccad\uc744 \ubd84\uae30\ud558\ub294 \uc5ed\ud560\uc744 \uc218\ud589\ud55c\ub2e4. \uc608\ub97c \ub4e4\uc5b4 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad URL\uc774 <em>http:\/\/localhost\/employees\/1<\/em>\uc77c \uacbd\uc6b0 <em>getEmployee()<\/em> \uba54\uc18c\ub4dc\uac00 \uc2e4\ud589\ub41c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.demo.controller;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport com.example.demo.model.Employee;\nimport com.example.demo.service.Employees;\n\n\/**\n * Controller class that handles requests mapped with '\/employees' from client\n *\/\n@RestController\n@RequestMapping(\"\/employees\")\npublic class EmployeeController {\n    private final Logger log = LoggerFactory.getLogger(getClass());\n    \n    \/**\n     * repository will be auto-wired through constructor\n     *\/\n    private final Employees employees;\n\n    \/**\n     * Constructor\n     * @param employees the instance will be injected through Spring DI\n     *\/\n    public EmployeeController(Employees employees) {\n        this.employees = employees;\n    }\n \n    @PostMapping(\"\/save\")\n    public ResponseEntity&lt;Employee> saveEmployee(@RequestBody Employee employee) {\n        return new ResponseEntity&lt;Employee>(employees.saveEmployee(employee), HttpStatus.CREATED);\n    }\n    \n    @PutMapping(\"\/update\")\n    public ResponseEntity&lt;Employee> updateEmployee(@RequestBody Employee employee) {\n        return new ResponseEntity&lt;Employee>(employees.updateEmployee(employee), HttpStatus.OK);\n    }\n    \n    @GetMapping(\"\/{id}\")\n    public ResponseEntity&lt;Employee> getEmployee(@PathVariable int id) throws InterruptedException {\n        log.info(\"Handle request for GET \/{}\", id);\n        return new ResponseEntity&lt;Employee>(employees.getEmployeeById(id), HttpStatus.OK);\n    }\n    \n    @DeleteMapping(\"\/{id}\")\n    public ResponseEntity&lt;Void> deleteEmployee(@PathVariable int id) {\n        employees.deleteEmployee(id);\n        return new ResponseEntity&lt;Void>(HttpStatus.ACCEPTED);\n    }\n}<\/code><\/pre>\n\n\n\n<p>\uc791\uc131\ub41c Spring Boot Application\uc744 \uc2e4\ud589\ud55c \ud6c4 <em>http:\/\/localhost\/employees\/1<\/em>\ub97c \uc5ec\ub7ec \ubc88 \ud638\ucd9c\ud574 \ubcf4\uba74 \uc544\ub798\uc640 \uc720\uc0ac\ud55c \uc2e4\ud589 \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2025-03-03T01:08:36.072+09:00  INFO 8312 --- &#91;Caching] &#91;nio-8090-exec-1] c.e.demo.controller.EmployeeController   : <strong>Handle request for GET \/1<\/strong>\n2025-03-03T01:08:38.230+09:00  INFO 8312 --- &#91;Caching] &#91;nio-8090-exec-1] com.example.demo.service.Employees       : <strong>Scenario: 2 seconds consumed in finding an Employee by id: 1<\/strong>\nHibernate: \n    select\n        e1_0.id,\n        e1_0.address,\n        e1_0.name \n    from\n        employee e1_0 \n    where\n        e1_0.id=?\n2025-03-03T01:08:42.439+09:00  INFO 8312 --- &#91;Caching] &#91;nio-8090-exec-2] c.e.demo.controller.EmployeeController   : <strong>Handle request for GET \/1<\/strong>\n2025-03-03T01:08:43.226+09:00  INFO 8312 --- &#91;Caching] &#91;nio-8090-exec-3] c.e.demo.controller.EmployeeController   : <strong>Handle request for GET \/1<\/strong>\n2025-03-03T01:08:43.965+09:00  INFO 8312 --- &#91;Caching] &#91;nio-8090-exec-4] c.e.demo.controller.EmployeeController   : <strong>Handle request for GET \/1<\/strong><\/code><\/pre>\n\n\n\n<p>\uc704 \ub85c\uadf8\uc5d0\uc11c \ubcf4\ub4ef\uc774 \ucd5c\ucd08 \ud638\ucd9c\uc5d0\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ud638\ucd9c \ub418\uc5c8\uc73c\uba70 \uc2dc\ubbac\ub808\uc774\uc158\uc73c\ub85c 2\ucd08\uac00 \uc9c0\uccb4\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc9c0\ub9cc \uc774\ud6c4 \uc5f0\uc18d\ub418\ub294 \ud638\ucd9c\uc5d0\uc11c\ub294 \uacb0\uacfc\uac00 \uc989\uc2dc \ubc18\ud658\ub428\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>\ucd5c\ucd08 \uc694\uccad\uc744 \uc2e4\ud589\ud55c \ud6c4\uc758 Cache\uc0c1\ud0dc\ub97c \ubcf4\uba74 \uc544\ub798\uc640 \uac19\uc774 &#8220;skanto::employee::1&#8221; \ud0a4\ub85c Cache\uac00 \uc0dd\uc131\ub418\uc5b4 \uc788\ub294 \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>root@0fae453aa5eb:\/data# redis-cli\n127.0.0.1:6379&gt; keys *\n1) \"skanto::employee::1\"<\/code><\/pre>\n\n\n\n<p>ttl\ub85c \uc124\uc815\ub41c 1\ubd84\uc774 \uc9c0\ub098\uba74 Cache\uac00 \uc0ad\uc81c\ub418\ub294 \uac83\ub3c4 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>127.0.0.1:6379&gt; keys *\n(empty array)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Extending Default Configurations<\/h2>\n\n\n\n<p>\uc9c0\uae08\uae4c\uc9c0\ub294 \ube44\uad50\uc801 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c Spring Boot\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 Caching\uae30\ub2a5\uacfc \ud65c\uc6a9\ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c\uc544 \ubcf4\uc558\ub2e4.<\/p>\n\n\n\n<p><em>application.properties<\/em>\ud30c\uc77c\uc744 \ud1b5\ud574 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc18d\uc131\ub4e4\uc774 \uc81c\ud55c\uc801\uc77c \uacbd\uc6b0 \ud504\ub85c\uadf8\ub798\ubc0d\uc73c\ub85c \uc9c1\uc811 \uae30\ub2a5\uc744 \ud655\uc7a5\uc2dc\ud0ac \uc218 \uc788\ub2e4. RedisCacheConfiguration\uc744 \uc9c1\uc811 \uc0dd\uc131\ud558\uc5ec default\ub85c \uc124\uc815\uac12 \uc774\uc678\uc758 \ub2e4\uc591\ud55c \uc18d\uc131\ub4e4\uc744 \uc124\uc815\ud560 \uc218 \uc788\uc73c\uba70 \uc774\ub807\uac8c \uc0dd\uc131\ud55c RedisCacheConfiguration\uc744 @Bean\uc73c\ub85c \ub4f1\ub85d\ud558\uba74 \uac04\ub2e8\ud558\uac8c default \uc18d\uc131\uc744 \uc624\ubc84\ub77c\uc774\ub4dc\ud560 \uc218 \uc788\ub2e4. \ub2e4\uc74c\uc740 default\ub85c \uc124\uc815\ub41c ttl\uac12(1\ubd84)\uc744 10\ucd08\ub85c \ubcc0\uacbd\ud558\uace0 key-prefix\ub97c &#8220;skanto::&#8221;\uc5d0\uc11c &#8220;key::&#8221;\ub85c \ubcc0\uacbd\ud558\ub294 \ucf54\ub4dc\ub97c \ubcf4\uc5ec\uc900\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.demo.config;\n\nimport java.time.Duration;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.cache.RedisCacheConfiguration;\n\n@Configuration\npublic class RedisConfig {\n  \n    @Bean\n    RedisCacheConfiguration configure() {\n        return RedisCacheConfiguration.defaultCacheConfig()\n                .entryTtl(Duration.ofSeconds(10))\n                .disableCachingNullValues()\n                .prefixCacheNameWith(\"key::\");\n    }\n}<\/code><\/pre>\n\n\n\n<p>Custom CacheManager\ub85c \uc124\uc815\ub41c \uac12\uc73c\ub85c \uc11c\ube44\uc2a4\ub97c \uc2e4\ud589\ud558\uba74 \uc544\ub798\uc640 \uac19\uc774 Key\uac00 &#8220;<em>key::employee::1<\/em>&#8220;\ub85c Cache\uac00 \uc0dd\uc131\ub418\uace0 10\ucd08 \ud6c4\uc5d0 \uc790\ub3d9\uc73c\ub85c Cache\uac00 \uc0ad\uc81c\ub428\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \uc880 \ub354 \uc790\uc138\ud55c \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \uc2f6\ub2e4\uba70 <a href=\"https:\/\/docs.spring.io\/spring-data\/redis\/reference\/redis\/redis-cache.html\">\uc5ec\uae30<\/a>\ub97c \ucc38\uace0\ud558\uae30 \ubc14\ub780\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>127.0.0.1:6379&gt; keys *\n1) \"key::employee::1\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\ub9c8\uce58\uba70&#8230;<\/h2>\n\n\n\n<p>Spring Framework\uc744 \ud65c\uc6a9\ud55c \uc5b4\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uaddc\ubaa8\uac00 \ucee4\uc9c8 \uacbd\uc6b0 \uc131\ub2a5\uc744 \uac1c\uc120\uc744 \uc704\ud574 \ud544\uc218\uc801\uc73c\ub85c \uace0\ubbfc\ud574\uc57c\ud560 \uae30\ub2a5 \uc911 \ud558\ub098\uc778 Spring Cach\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc558\ub2e4. \uc544\uc27d\uac8c\ub3c4 \uc778\ud130\ub137\uc5d0 \ub110\ub824 \uc788\ub294 \uc790\ub8cc\ub4e4\uc740 \ub300\ubd80\ubd84 \ucc9c\ud3b8\uc77c\ub960\uc801\uc774\uace0 \ub0b4\ubd80 \ub3d9\uc791\uc6d0\ub9ac\uc5d0 \ub300\ud55c \uc18c\uac1c\uac00 \uac70\uc758 \uc5c6\uc744 \ubfd0\ub9cc \uc544\ub2c8\ub77c \uc5b4\ub5bb\uac8c \uae30\ub2a5\uc744 Customizing \ud574\uc57c \ud560\uc9c0\uc5d0 \ub300\ud55c \uac00\uc774\ub4dc\ub97c \uc81c\uc2dc\ud558\uc9c0 \ubabb\ud558\uace0 \uc788\uc5b4 \uac1c\uc778\uc801\uc73c\ub85c \ub2f5\ub2f5\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4. \uc774 \uae00\uc744 \uc791\uc131\ud558\uac8c \ub41c \uacc4\uae30\ub3c4 \uc5ec\uae30\uc5d0 \uae30\uc778\ud55c\ub2e4\uace0 \ubcfc \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>\uc774 \uae00\uc5d0\uc11c \uc18c\uac1c\ud55c \ub0b4\uc6a9\uc740 Spring Boot\uc5d0\uc11c Caching\uae30\ub2a5\uc744 \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud558\ub294\uc9c0, Cache\ub97c \uc704\ud574 \uc801\uc6a9\ud560 \uc218 \uc788\ub294 Annotation \uc885\ub958\uc640 \ud65c\uc6a9, \uadf8\ub9ac\uace0 Default Caching\uae30\ub2a5\uc744 \ud655\uc7a5\ud574\uc11c Customizing\ud558\ub294 \ubc29\ubc95\uae4c\uc9c0 \ud3ec\ud568\ud558\uace0 \uc788\uc5b4 \ud070 \uadf8\ub9bc\uc744 \ube44\uad50\uc801 \uc27d\uac8c \uc774\ud574\ud558\uace0 \uac1c\ubc1c\uc5d0 \ud544\uc694\ud55c \uc2dc\uc791 \uac00\uc774\ub4dc\ub85c\ub294 \uc190\uc0c9\uc774 \uc5c6\uc73c\ub9ac\ub77c \uc0dd\uac01\ud55c\ub2e4. \ud558\uc9c0\ub9cc \ubaa8\ub4e0 \ub0b4\uc6a9\uc744 \ub2e4 \ub2f4\uc9c0\ub294 \ubabb\ud55c \ud130\ub77c \ubd80\uc871\ud55c \uc124\uba85\uc774\ub098 \ud2b9\ubcc4\ud788 \ud544\uc694\ud55c \ubd80\ubd84\uc740 \uc778\ud130\ub137 \ub610\ub294 \uc11c\uc801\uc744 \uc774\uc6a9\ud558\uba74 \uae38\uc744 \uc783\uc9c0 \uc54a\uace0 \uc6d0\ud558\ub294 \ub2f5\uc744 \uc27d\uac8c \ucc3e\uc744 \uc218 \uc788\uc73c\ub9ac\ub77c \uc0dd\uac01\ud55c\ub2e4. \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud558\uba74\uc11c \ucc3e\uc544\ubcf8 \uc790\ub8cc\ub4e4 \uc911\uc5d0\uc11c \uac00\uc7a5 \uba85\ub8cc\ud55c \uc124\uba85\uc744 \uc81c\uacf5\ud558\ub294 \uacf3\uc73c\ub85c\ub294 \uc5ed\uc2dc <a href=\"https:\/\/docs.spring.io\/spring-framework\/reference\/integration\/cache.html\">Spring Boot \uacf5\uc2dd \uc0ac\uc774\ud2b8<\/a>\uac00 \ucd5c\uace0\uc778\uac83 \uac19\ub2e4.<\/p>\n\n\n\n<p>\uac1c\uc778\uc801\uc73c\ub85c Spring Boot\uc758 Caching\uae30\ub2a5\uc744 \uc775\ud788\uba74\uc11c \uc9e7\uc740 \uacbd\ud5d8\uc774\uc9c0\ub9cc \uc591\uac00\uc758 \uac10\uc815\uc744 \ub290\ub07c\uac8c \ub41c\ub2e4. Spring Framework\uc740 Annotation\uc5d0 \uc758\uc874\uc801\uc778 \ubd80\ubd84\uc774 \ub9ce\uc544 \uac1c\ubc1c\uc790\ub9c8\ub2e4 \uc811\uadfc \uacbd\ub85c \ubc0f \uac1c\ubc1c \ubc29\ubc95\uc774 \ub2ec\ub77c\uc9c8 \uc218\uac00 \uc788\uace0 \uac1c\ubc1c\uacfc\uc815\uc5d0\uc11c \ud1b5\uc77c\ub41c \ud45c\uc900, \uadf8\ub9ac\uace0 \ucda9\ubd84\ud55c \uac00\uc774\ub4dc\uac00 \uc81c\uacf5\ub418\uc9c0 \uc54a\ub294\ub2e4\uba74 \uac1c\ubc1c\uc774 \uc9c4\ud589\ub418\uba74 \ub420\uc218\ub85d \uac1c\ubc1c\ubd80\ub2f4\uc774 \ucee4\uc9c0\uace0 \uc720\uc9c0\ubcf4\uc218\uc5d0 \uc5b4\ub824\uc6c0\uc774 \ubc1c\uc0dd\ud560 \uac83\uc774\ub77c\ub294 \uc6b0\ub824\uac00 \uc55e\uc120\ub2e4. \ud558\uc9c0\ub9cc, \ub300\ubd80\ubd84\uc758 \uac1c\ubc1c\uacfc\uc815\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uae30\ub2a5\ub4e4\uc744 \ucd5c\uc18c\ud55c\uc758 \ub178\ub825\uc73c\ub85c \uac1c\ubc1c\uc790\ub4e4\uc774 \ud3b8\ub9ac\ud558\uac8c \uc801\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud0c4\ud0c4\ud55c \uae30\ubc18 \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc81c\uacf5\ud558\uace0 \uc788\uc5b4 \uccb4\uacc4\uc801\uc774\uace0 \ud45c\uc900\ud654\ub41c \ubc29\ubc95\uc73c\ub85c \uc811\uadfc\ud55c\ub2e4\uba74 \uc88b\uc740 \uc810\uc218\ub97c \uc8fc\uace0 \uc2f6\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ubd80\ub85d: Install Backend Application(PostgreSQL, Redis)<\/h2>\n\n\n\n<p>Docker \ub355\ubd84\uc5d0 \ud544\uc694\ub85c \ud558\ub294 Backend Application\uc744 \ub9e4\uc6b0 \ud3b8\ub9ac\ud55c \ubc29\ubc95\uc73c\ub85c \uc124\uce58\ud558\uace0 \ud65c\uc6a9\ud574 \ubcfc \uc218 \uc788\ub2e4. \uac04\ub2e8\ud558\uc9c0\ub9cc \ucee8\ud14c\uc774\ub108 \uc124\uce58\ub97c \uc704\ud574 \ud65c\uc6a9\ud588\ub358 \ubd80\ubd84\ub4e4\uc744 \uae30\ub85d\ud574 \ub454\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">PostgreSQL \ucee8\ud14c\uc774\ub108 \uc124\uce58 \ubc0f \uc2e4\ud589<\/h3>\n\n\n\n<p>PostgreSQL\uc740 \uc544\ub798\uc758 docker \uba85\ub839\uc73c\ub85c \ucd5c\uc2e0\ubc84\uc804(13.20)\uc758 \ucee8\ud14c\uc774\ub108\ub97c \uc27d\uac8c \uc124\uce58 \ubc0f \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run --name postgres -e POSTGRES_PASSWORD=postgres -d -v postgre_db:\/var\/lib\/postgresql\/data -p 5432:5432 --restart always postgres:13.20<\/code><\/pre>\n\n\n\n<p>\ucc38\uace0\ub85c, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5f0\uacb0\uc740 5432\ud3ec\ud2b8(default)\ub97c \uc774\uc6a9\ud558\uba70 \uc0ac\uc6a9\uc790 \ubc0f \ud328\uc2a4\uc6cc\ub4dc\ub294 postgres\/postgres\uc774\ubbc0\ub85c Spring Framework\uc5d0\uc11c JPA\ub97c \uc704\ud55c \uc5f0\uacb0 \uc124\uc815\uc740 \uc544\ub798\uc640 \uac19\uc774 <em>application.properties<\/em>\uc5d0 \ucd94\uac00\ud558\uba74 \ub41c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spring.datasource.driver-class-name=org.postgresql.Driver\nspring.datasource.url=jdbc:postgresql:\/\/localhost:5432\/postgres\nspring.datasource.username=postgres\nspring.datasource.password=postgres\nspring.jpa.properties.hibernate.show_sql=true\nspring.jpa.properties.hibernate.use_sql_comments=true\nspring.jpa.properties.hibernate.format_sql=true<\/code><\/pre>\n\n\n\n<p>\uae30\ubcf8 \uc124\uc815\uc774 \ub9c8\ubb34\ub9ac \ub418\uba74 Console\ub85c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ucee8\ud14c\uc774\ub108\uc5d0 \uc811\uc18d\ud55c \ud6c4 \uc0d8\ud50c \uc5b4\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589\uc744 \uc704\ud574 employee \ud14c\uc774\ube14\uc744 \uc0dd\uc131\ud558\uace0 \uc0d8\ud50c \ub370\uc774\ud130 \ud558\ub098\ub97c \ub123\uc5b4 \ub454\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>skanto@skanto-mbp ~ % docker exec -it postgres bash\nroot@54ca6f34cbfe:\/# psql -U postgres\npsql (13.20 (Debian 13.20-1.pgdg120+1))\nType \"help\" for help.\n\npostgres=# \\dt\n          List of relations\n Schema |   Name   | Type  |  Owner   \n--------+----------+-------+----------\n public | employee | table | postgres\n public | sample   | table | postgres\n(2 rows)\n\npostgres=# \\d employee\n                      Table \"public.employee\"\n Column  |          Type          | Collation | Nullable | Default \n---------+------------------------+-----------+----------+---------\n id      | integer                |           | not null | \n name    | character varying(50)  |           |          | \n address | character varying(100) |           |          | \n\npostgres=# select * from employee;\n id |  name  | address \n----+--------+---------\n  1 | skanto | Gwangju\n(1 row)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Redis \ucee8\ud14c\uc774\ub108 \uc124\uce58 \ubc0f \uc2e4\ud589<\/h3>\n\n\n\n<p>PostgreSQL\uacfc \ub3d9\uc77c\ud558\uac8c \ucd5c\uc2e0\ubc84\uc804(7.4.2)\uc758 \ucee8\ud14c\uc774\ub108\ub97c \uc124\uce58 \ubc0f \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run --name redis -d -v redis_db:\/data -p 6379:6379 --restart always redis:7.4.2 redis-server<\/code><\/pre>\n\n\n\n<p>Spring Fremework\uc5d0\uc11c Redis Cache Store\uac00 \ud65c\uc6a9\ub420 \uc218 \uc788\ub3c4\ub85d \uc544\ub798\uc640 \uac19\uc774 Redis default \uc18d\uc131\uc744 <em>application.properties<\/em>\ud30c\uc77c\uc5d0 \uc124\uc815\uc815\ubcf4\ub97c \ucd94\uac00\ud55c\ub2e4.(\uc55e\uc5d0\uc11c \uc124\uba85\ud55c \ubd80\ubd84\uacfc \uc911\ubcf5 \ub428)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Cache type. Bye default, auto-detected according to the environment\nspring.cache.type=redis\n\n# if true allows caching null values\nspring.cache.redis.cache-null-values=false\n\n# sets cache expiration(if not (m), time is milliseconds). By default the entries never expire\nspring.cache.redis.time-to-live=1m\n\n# key prefix\nspring.cache.redis.key-prefix=skanto::\n\n# redist host address(default: localhost)\nspring.data.redis.host=localhost\n\n# redis service port(default: 6379)\nspring.data.redis.port=6379<\/code><\/pre>\n\n\n\n<p>\uc544\ub798\uc640 \uac19\uc774 Redis \ucee8\ud14c\uc774\ub108\uc5d0 \uc811\uc18d\ud574\uc11c \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>skanto@skanto-mbp ~ % docker exec -it redis bash\nroot@0fae453aa5eb:\/data# redis-cli\n127.0.0.1:6379&gt; keys *\n(empty array)\n127.0.0.1:6379&gt;<\/code><\/pre>\n\n\n\n<p>\ub05d.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc694\uc998 Spring\uc744 \ud65c\uc6a9\ud558\ub294 \ubc29\ubc95\uc5d0 \uc775\uc219\ud574 \uc9c0\ub824\uace0 \ub178\ub825\ud558\uace0 \uc788\ub2e4. \uc0ac\uc2e4 Spring\uc740 \uac70\uc758 15\ub144\uc5ec \uc804 Spring Framework \ucd08\uae30\uc5d0 \uc7a0\uae50 \uc0ac\uc6a9\ud574\ubcf4\uace0 \uadf8 \uc774\ud6c4\ub294 \uacbd\ud5d8\uc774 \uc804\ubb34\ud55c \ud130\ub77c \uac1c\ub150 \uc815\ub3c4\ub294 \uc598\uae30\ud560 \uc218 \uc788\uc744\uc9c0\ub77c\ub3c4 \uc694\uc998 \uac1c\ubc1c\uc790\ub4e4\uacfc Spring \ud65c\uc6a9\uc5d0 \ub300\ud574 \ub9d0\uc744 \uc369\uc744 \uc218 \uc788\ub294 \ucc98\uc9c0\uac00 \ubabb\ub41c\ub2e4. \uc774 \ucc38\uc5d0 Spring\uc5d0 \ub179\uc544\uc788\ub294 \ud575\uc2ec\uc801\uc778 \uae30\uc220\ub4e4\uc744 \ud558\ub098\uc529 \uaebc\ub0b4\uc640\uc11c \uc774\ud574\ud558\uace0 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \uc774 \uae00\uc740 \uadf8 \uc2dc\ub9ac\uc988\uc758 \uccab \ubc88\uc9f8\ub85c Spring Cache\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774\ub2e4. \uc778\ud130\ub137\uc5d0\uc11c \ud754\ud788 \uc18c\uac1c\ub418\uace0 \uc788\ub294 \ub0b4\uc6a9\ub4e4 \ubcf4\ub2e4 \uc880 \ub354 \uae4a\uc219\uc774 \ub4e4\uc5b4\uac00\uc11c \uc5b4\ub5a4 \ub9e4\ucee4\ub2c8\uc998\uc5d0 \uc758\ud574 Caching\uc774 \uc801\uc6a9\ub418\uace0 \ub3d9\uc791\ud558\ub294 \uc9c0 \uc0b4\ud3b4\ubcf4\ub3c4\ub85d \ud55c\ub2e4&#8230;.<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/skanto.co.kr\/?p=1967\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[14,7],"tags":[189,190,172,191,188],"class_list":["post-1967","post","type-post","status-publish","format-standard","hentry","category-sw-development","category-7","tag-boot","tag-caching","tag-postgresql","tag-redis","tag-spring"],"_links":{"self":[{"href":"https:\/\/skanto.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/1967","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/skanto.co.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/skanto.co.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/skanto.co.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/skanto.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1967"}],"version-history":[{"count":62,"href":"https:\/\/skanto.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/1967\/revisions"}],"predecessor-version":[{"id":2033,"href":"https:\/\/skanto.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/1967\/revisions\/2033"}],"wp:attachment":[{"href":"https:\/\/skanto.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/skanto.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/skanto.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}