diff --git a/build.gradle b/build.gradle index aa4f5b60..f5ff8bba 100644 --- a/build.gradle +++ b/build.gradle @@ -104,6 +104,9 @@ dependencies { // Apache Commons Codec implementation"commons-codec:commons-codec:1.19.0" + + // Redis (Spring starter) + implementation 'org.springframework.boot:spring-boot-starter-data-redis' } dependencyManagement { diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/controller/ApiV1AuthController.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/controller/ApiV1AuthController.java index a7c675d9..68ff3ef0 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/controller/ApiV1AuthController.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/controller/ApiV1AuthController.java @@ -69,7 +69,6 @@ public ResponseEntity> logout( * @param sessionId 쿠키에 포함된 현재 로그인한 사용자의 sessionId. * @param response Servlet 기반 웹에서 server -> client로 http 응답을 보내기 위한 객체, 자동 주입. */ - @PostMapping("/refresh") @Operation(summary = "사용자 액세스 토큰 재발급 (서버 저장 RefreshToken 사용)") public ResponseEntity> refreshToken( @@ -77,7 +76,6 @@ public ResponseEntity> refreshToken( String sessionId, HttpServletResponse response ) { - if (sessionId == null) { return ResponseEntity .status(HttpStatus.UNAUTHORIZED) @@ -91,7 +89,11 @@ public ResponseEntity> refreshToken( } catch (AuthenticationException e) { return ResponseEntity .status(HttpStatus.UNAUTHORIZED) - .body(new RsData<>("401", e.getMessage(), null)); + .body(new RsData<>( + "401", + e.getMessage(), + null + )); } String refreshToken = refreshTokenEntity.getRefreshToken(); @@ -126,7 +128,6 @@ public ResponseEntity> refreshToken( * 확장프로그램의 액세스 토큰 발급을 위한 백그라운드 풀링에 대응하는 API * @param state 확장프로그램 로그인 시 전달한 state 값. */ - @GetMapping("/result") @Operation(summary = "확장프로그램 백그라운드 풀링 대응 API") public ResponseEntity> pullingResult( diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/dto/AuthResultData.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/dto/AuthResultData.java index dbdace4a..07694675 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/dto/AuthResultData.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/dto/AuthResultData.java @@ -1,19 +1,15 @@ package org.tuna.zoopzoop.backend.domain.auth.dto; -public class AuthResultData { - private final String accessToken; - private final String sessionId; - - public AuthResultData(String accessToken, String sessionId) { - this.accessToken = accessToken; - this.sessionId = sessionId; - } - - public String getAccessToken() { - return accessToken; - } - - public String getSessionId() { - return sessionId; - } +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AuthResultData implements Serializable { + private String accessToken; + private String sessionId; } \ No newline at end of file diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/entity/AuthResult.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/entity/AuthResult.java index e29721ac..043f04a1 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/entity/AuthResult.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/entity/AuthResult.java @@ -1,23 +1,26 @@ package org.tuna.zoopzoop.backend.domain.auth.entity; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.tuna.zoopzoop.backend.domain.auth.dto.AuthResultData; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; + +import java.time.Duration; @Component +@RequiredArgsConstructor public class AuthResult { - private final Map results = new ConcurrentHashMap<>(); + private final RedisTemplate redisTemplate; + private static final String PREFIX = "auth:result:"; public void put(String state, String accessToken, String sessionId) { - results.put(state, new AuthResultData(accessToken, sessionId)); + AuthResultData data = new AuthResultData(accessToken, sessionId); + redisTemplate.opsForValue().set(PREFIX + state, data, Duration.ofMinutes(1)); // TTL 1분, 프론트단에선 백그라운드 풀링 형식으로 계속 작동할 것이므로. } public AuthResultData get(String state) { - return results.remove(state); - } - - public void consume(String state) { - results.remove(state); + AuthResultData data = redisTemplate.opsForValue().get(PREFIX + state); + if (data != null) redisTemplate.delete("auth:" + state); + return data; } } \ No newline at end of file diff --git a/src/main/java/org/tuna/zoopzoop/backend/global/config/redis/RedisConfig.java b/src/main/java/org/tuna/zoopzoop/backend/global/config/redis/RedisConfig.java new file mode 100644 index 00000000..437b3935 --- /dev/null +++ b/src/main/java/org/tuna/zoopzoop/backend/global/config/redis/RedisConfig.java @@ -0,0 +1,28 @@ +package org.tuna.zoopzoop.backend.global.config.redis; + +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.tuna.zoopzoop.backend.domain.auth.dto.AuthResultData; + +@Configuration +@EnableCaching +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + // Key Serializer + template.setKeySerializer(new StringRedisSerializer()); + // Value Serializer (JSON 직렬화) + template.setValueSerializer(new Jackson2JsonRedisSerializer<>(AuthResultData.class)); + + return template; + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1acbd1a7..c13af761 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -35,6 +35,17 @@ spring: options: model: meta-llama/llama-4-scout-17b-16e-instruct temperature: 0 + data: #RedisTemplate 등을 사용하기 위한 직접 연결용 + redis: + host: localhost + port: 6379 + timeout: 6000 + cache: #Spring Cache를 사용하기 위한 Redis + type: redis + redis: + time-to-live: 300000 + cache-null-values: false + key-prefix: springdoc: default-produces-media-type: application/json;charset=UTF-8 @@ -48,7 +59,6 @@ logging: server: port: 8080 - app: seed: enabled: true \ No newline at end of file