๐Ÿ“˜ SpringBoot & Docker + Reids ์—ฐ๋™


Pasted image 20250221114306.png

๋จผ์ € ๋„์ปค์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์ด์ „ ๊ธ€!

โ†’ ์—ฌ๊ธฐ๋กœ ๐Ÿ‹ docker ๋ž€


aws์˜ ์„ค๋ช…์— ์˜ํ•˜๋ฉด Docker๋ž€
  1. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹ ์†ํ•˜๊ฒŒ ๊ตฌ์ถ•, ํ…Œ์ŠคํŠธ ๋ฐ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ํ”Œ๋žซํผ์ด๋‹ค.
  2. ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์ปจํ…Œ์ด๋„ˆ ๋ผ๋Š” ํ‘œ์ค€ํ™”๋œ ์œ ๋‹›์œผ๋กœ ํŒจํ‚ค์ง•ํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค.

์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ ํ”„๋กœ์ ํŠธ์— Docker๋ฅผ ์—ฐ๋™ํ•˜์—ฌ local ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ๋‹ค.


1. Docker๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ธฐ

๊ฐ ๊ธฐ๊ธฐ์— ๋งž๋Š” docker ๋ฒ„์ „์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๋Š”๋‹ค. Pasted image 20250221114324.png

๋‹ค์šด๋กœ๋“œ ๋ฐ›์€ ํ›„ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ docker์˜ ํ˜„์žฌ ๋ฒ„์ „์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

โ€ป ํ„ฐ๋ฏธ๋„์— 'docker' ๋ฅผ ์ž…๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด ๋‹ค์–‘ํ•œ ๋ช…๋ น์–ด๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. Pasted image 20250221114327.png

์ œ๋Œ€๋กœ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์•˜๋‹ค๋ฉด docker์— ๊ธฐ๋ณธ์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ ธ์žˆ๋Š” ์ด๋ฏธ์ง€๋“ค์„ ํ™•์ธ ํ• ์ˆ˜ ์žˆ๋‹ค. ๋ฐ‘์— ์‚ฌ์ง„์€ ๋„์ปค ๋ฐ์ŠคํŠธํ†ฑ ์ด๋ผ๋Š” ์•ฑ์ด๋‹ค.

Pasted image 20250221114334.png

ํ„ฐ๋ฏธ๋„์—์„œ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Pasted image 20250221114339.png

์ด์ œ ๋„์ปค ํŒŒ์ผ ์„ ์ด์šฉํ•˜์—ฌ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•œ ํ›„, ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•ด ์ค„๊ฒƒ์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์—ฌ๋Ÿฌ ์šฉ์–ด๋“ค์ด ๋‚˜์˜ค๋Š”๋ฐ...

์šฉ์–ด๋“ค์— ๋Œ€ํ•œ ์„ค๋ช…์ด๋‹ค

Pasted image 20250221114345.png


2.  Spring ํ”„๋กœ์ ํŠธ ๋‚ด์— DockerFile ์ƒ์„ฑํ•˜๊ธฐ

Pasted image 20250221114353.png

์•„์ฃผ ๊ธฐ๋ณธ์ ์ธ Spring ํ”„๋กœ์ ํŠธ์ด๋‹ค.

Dockerfile์„ ์ƒ์„ฑํ•˜๊ธฐ์— ์•ž์„œ, .jar ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค.

gradle ์ด๋‚˜ maven ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œ ํ• ๊ฒƒ์ด๋‹ค.

์—ฌ๊ธฐ์„œ๋Š” Maven ์„ ์‚ฌ์šฉํ•œ๋‹ค.

ํ™ˆํŽ˜์ด์ง€์—์„œ ์ง์ ‘ ๋‹ค์šด๋ฐ›์•„๋„ ๋˜๊ณ , brew๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ์ž ๋‹ค์šด๋ฐ›์œผ๋ฉด ๋œ๋‹ค.

์ดํ›„์—, ํ”„๋กœ์ ํŠธ์˜ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ 'mvn install' ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Pasted image 20250221114400.png

๋นŒ๋“œ๋ฅผ ๋งˆ์น˜๋ฉด, ํ”„๋กœ์ ํŠธ ๋‚ด์— target์ด ์ƒ์„ฑ ๋จ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Pasted image 20250221114406.png

๊ทธ ํ›„, ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— 'Dockerfile' ์„ ์ƒ์„ฑํ•˜์—ฌ ์ค€๋‹ค.

Pasted image 20250221114411.png

Pasted image 20250221114423.png

Dockerfile ์ƒ์„ฑ์‹œ ์‚ฌ์šฉ๋˜๋Š” ๋ช…๋ น์–ด๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Pasted image 20250221114428.png

๋‚˜๋Š” ๊ธฐ๋ณธ์ ์ธ ์˜ต์…˜๋งŒ ๋„ฃ์–ด์„œ test ํ•˜์˜€๋‹ค.

FROM ํƒœ๊ทธ์— ๋‚˜์˜ java(jdk)๋ฒ„์ „์„ ํ™•์ธํ•˜์—ฌ baseimage๋ฅผ ์ง€์ •ํ•˜๊ณ  ( dockerRpository์—์„œ ๋‹ค์–‘ํ•œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฐพ์•„๋ณด์„ธ์š”)

ADD ํƒœ๊ทธ์— maven์„ ํ†ตํ•ด ์ƒ์„ฑ๋œ .jarํŒŒ์ผ๊ณผ ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค

์ด์™ธ์— ํƒœ๊ทธ๋Š” ์ž์œ ๋กญ๊ฒŒ ์ž‘์„ฑํ•ด ์ค„ ์ˆ˜ ์žˆ๋‹ค.


3. dockerfile ์„ ์‹คํ–‰ํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

ํ”„๋กฌํ”„ํŠธ์—

docker build -t ${"๋„์ปคํŒŒ์ผ ๋ช…"} ${"๋””๋ ‰ํ† ๋ฆฌ"} 

ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Pasted image 20250221114434.png

Pasted image 20250221114439.png

ํ•ด๋‹น ๋‹จ๊ณ„๋ฅผ ๋งˆ์น˜๋ฉด ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


4. ๋งˆ์ง€๋ง‰์œผ๋กœ, ์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€์„ RUN ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด  ์ปจํ…Œ์ด๋„ˆ๋กœ ์‹คํ–‰ํ•˜๊ธฐ!!

ํ”„๋กฌํ”„ํŠธ์—

docker run -p ${์‚ฌ์šฉํ•  ํฌํŠธ๋ฒˆํ˜ธ} ${์ด๋ฏธ์ง€ ๋ช…}

์„ ์‚ฌ์šฉํ•œ๋‹ค.

๋ณธ์ธ์€ 8000๋ฒˆ ํฌํŠธ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ 8080ํฌํŠธ์ธ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ์— ์ ‘๊ทผํ•  ๊ฒƒ์ด๋‹ค.

Pasted image 20250221114443.png

์งœ์ž”!   ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. Pasted image 20250221114501.png Pasted image 20250221114448.png


+ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ Redis ์—ฐ๋™ํ•˜๊ธฐ!(์‹ค์Šต)

Step 1. Docker๋ฅผ ์ด์šฉํ•˜์—ฌ Redis๋ฅผ ๋ฐ›์•„๋ณด์ž!

docker๋Š” ๋‹ค์šด๋ฐ›์•„์ ธ ์žˆ๋Š”๊ฑธ๋กœ ์•Œ๊ณ .. 

'docker pull redis:latest' ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์‹ ๋ฒ„์ „์˜ redis๋ฅผ ๋ฐ›์•„์˜จ๋‹ค.

Pasted image 20250221114522.png

๊ทธ ๋‹ค์Œ,

docker network create redis-network --driver bridge

๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ๋ฅผ ์ƒ์„ฑํ•ด ์ค€๋‹ค.

โ€ป docker network : ์ปจํ…Œ์ด๋„ˆ๊ฐ„์˜ ํ†ต์‹  ๋ฐ ๋ฐ์ดํ„ฐ ๊ณต์œ ๋ฅผ ์œ„ํ•œ ๊ฐ€์ƒ ๋„คํŠธ์›Œํฌ

Pasted image 20250221114527.png

์ด์ œ, 'sudo vim redis.conf' ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ redis.conf ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜์—ฌ ์„ค์ •์„ ์žก์•„์ค€๋‹ค.

Pasted image 20250221114531.png

docker run \
        -d \
        --name redis \
        -p 6379:6379 \
        --network redis-network \
        -v ~/${๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ํŒŒ์ผ ๊ฒฝ๋กœ} /redis.conf:/etc/redis/redis.conf \
        -v redis_data:/data \
redis:latest redis-server /etc/redis/redis.conf

Pasted image 20250221114535.png

ํฌํŠธ๋ฒˆํ˜ธ์™€, ๋ฐฉ๊ธˆ ์„ค์ •ํ•œ ๋„คํŠธ์›Œํฌ, ๋ฐ์ดํ„ฐ ์ €์žฅ ๊ฒฝ๋กœ๋ฅผ ์žก์•„์ค€๋‹ค.

์ด๋ ‡๊ฒŒ ์„ค์ •์„ ๋งˆ์ณค์œผ๋ฉด redis ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Pasted image 20250221114539.png

์ตœ์ข…์ ์œผ๋กœ ์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€๋กœ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

Pasted image 20250221114543.png

docker run --name myredis \
        -p 6379:6379 \
        --network redis-network \
        -v /Users/lts/Desktop/docker/redis:/data \
        -d redis:latest redis-server \
        --appendonly yes

Pasted image 20250221114600.png

์ปจํ…Œ์ด๋„ˆ๊นŒ์ง€ ์ƒ์„ฑ์™„๋ฃŒ!

docker exec -it myredis redis-cli --raw

๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰

Pasted image 20250221114605.png

ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ณด๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ ‘์†๋จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


Step 2. Redis์™€ Spring Boot ์—ฐ๋™ํ•˜๊ธฐ

โ€ป ํ•ด๋‹น ํ”„๋กœ์ ํŠธ๋Š” Maven ์„ ์‚ฌ์šฉํ•œ ํ”„๋กœ์ ํŠธ์ด๋‹ค.

๋จผ์ € application.properties ์— redis ํฌํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ์ค€๋‹ค

spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379

Pasted image 20250221114610.png

๊ทธ ๋‹ค์Œ config ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜์—ฌ์ค€๋‹ค.

Pasted image 20250221114616.png

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }

    @Bean
    public StringRedisTemplate stringRedisTemplate() {
        final StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        stringRedisTemplate.setValueSerializer(new StringRedisSerializer());
        stringRedisTemplate.setConnectionFactory(redisConnectionFactory());
        return stringRedisTemplate;
    }
}

Model๊ณผ Repository ๋„ ์ž‘์„ฑํ•ด์ค€๋‹ค.

Pasted image 20250221114621.png

import lombok.AllArgsConstructor;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

import java.time.LocalDateTime;

@Getter
@RedisHash(value = "resultHistory", timeToLive = 3600) // Redis Repository ์‚ฌ์šฉ์„ ์œ„ํ•œ
@AllArgsConstructor
@NoArgsConstructor
public class ResultHistory {

    @Id
    private String id;
    @Indexed // ํ•„๋“œ ๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ • (findByAccessToken)
    private String ip;
    private String originalText;
    private String translatedText;
    @Indexed
    private LocalDateTime createDateTime;

    @Builder
    public ResultHistory(String ip, String originalText, String translatedText, LocalDateTime createDateTime) {
        this.ip = ip;
        this.originalText = originalText;
        this.translatedText = translatedText;
        this.createDateTime = createDateTime;
    }
}

Pasted image 20250221114628.png

import com.teamTS.funfun.model.ResultHistory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface ResultRedisRepository extends JpaRepository<ResultHistory, String> {
    Optional<List<ResultHistory>> findByIpOrderByCreateDateTimeAsc(String ip);
}

controller ์— ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๊ฐ’์„ ํ™•์ธํ•ด๋ณด์ž!

Pasted image 20250221114633.png

    @GetMapping("/hello")
    public String HelloWorld(Model model) {
    
        redisConnectionTest();
        
        List<TestModel> tm = testRepository.getTestData();
        model.addAttribute("data", tm.get(0).getTitle());
        return "home/homeView";
    }

    void redisConnectionTest() {
        final String key = "a";
        final String data = "1";

        final ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        valueOperations.set(key, data);

        final String s = valueOperations.get(key);
    }

}

๊ทธ๋Ÿฐ๋ฐ...

Pasted image 20250221114638.png

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.

๋Œ€์ถฉ ๋นˆ ์ƒ์„ฑ์ด ์ค‘๋ณต์œผ๋กœ ๋ฐœ์ƒํ•˜์—ฌ ์ƒ๊ธด ์˜ค๋ฅ˜์ธ๋“ฏ ํ•˜๋‹ค..

์›์ธ์€ ๊ธฐ์กด MapperRepository์™€ Redis์šฉ JpaRepository์—์„œ

@Repository

ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถฉ๋Œํ•œ๋“ฏ ํ•˜๋‹ค. ์ด๋Ÿด๋•Œ๋Š”

application.properties ์— 

spring.main.allow-bean-definition-overriding=true

ํ•œ ์ค„์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ค€๋‹ค.

Pasted image 20250221114644.png

์„ฑ๊ณต์ ์ธ ์‹คํ–‰.

Pasted image 20250221114648.png

 ์ดํ›„ ' keys * ' ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.