반응형
RedisClient
package com.zerobase.cms.order.client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zerobase.cms.order.domain.redis.Cart;
import com.zerobase.cms.order.exception.CustomException;
import com.zerobase.cms.order.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
@Service
@RequiredArgsConstructor
@Slf4j
public class RedisClient {
private final RedisTemplate<String, Object> redisTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
public <T> T get(Long key, Class<T> classType) {
return get(key.toString(), classType);
}
private <T> T get(String key, Class<T> classType) {
String redisValue = (String) redisTemplate.opsForValue().get(key);
if (ObjectUtils.isEmpty(redisValue)) {
return null;
} else {
try {
return mapper.readValue(redisValue, classType);
} catch (JsonProcessingException e) {
e.printStackTrace();
log.error("Parsing error", e);
return null;
}
}
}
public void put(Long key, Cart cart) {
put(key.toString(), cart);
}
private void put(String key, Cart cart) {
try {
redisTemplate.opsForValue().set(key, mapper.writeValueAsString(cart));
} catch (JsonProcessingException e) {
throw new CustomException(ErrorCode.CART_CHANGE_FAIL);
}
}
}
Redis 클라이언트 (RedisClient)
이 코드는 Redis 데이터베이스와 상호 작용하는 클라이언트 클래스(RedisClient)입니다. Redis는 인메모리 데이터 저장소로, 빠른 읽기/쓰기 속도를 제공하여 캐싱, 세션 관리, 실시간 데이터 처리 등 다양한 용도로 사용됩니다. 이 클라이언트는 Redis에 데이터를 저장하고 검색하는 기능을 제공합니다.
1. 클래스 구조 및 의존성
- @Service: Spring의 어노테이션으로, 해당 클래스가 Spring Bean으로 관리되어야 함을 나타냅니다. 즉, Spring 컨테이너가 이 클래스의 인스턴스를 생성하고 관리합니다.
- @RequiredArgsConstructor: Lombok 라이브러리의 어노테이션으로, final 필드나 @NonNull 어노테이션이 붙은 필드에 대한 생성자를 자동으로 생성해줍니다. 여기서는 redisTemplate을 주입받기 위한 생성자가 만들어집니다.
- @Slf4j: Lombok 라이브러리의 어노테이션으로, 로깅 기능을 간편하게 사용할 수 있도록 해줍니다. log 객체를 통해 로깅할 수 있습니다.
- RedisTemplate: Spring Data Redis에서 제공하는 클래스로, Redis 데이터베이스와 상호 작용하기 위한 핵심 클래스입니다. Redis 연결 관리, 데이터 직렬화/역직렬화, 다양한 Redis 명령 실행 등의 기능을 제공합니다.
- ObjectMapper: Jackson 라이브러리에서 제공하는 클래스로, Java 객체를 JSON 형식으로 변환 (직렬화)하거나 JSON 형식을 Java 객체로 변환 (역직렬화)하는 데 사용됩니다.
2. 메서드별 상세 설명
2.1. get(Long key, Class<T> classType)
- 기능: Redis에서 주어진 키(key)에 해당하는 데이터를 가져와서 지정된 클래스 타입(classType)으로 변환합니다.
- 이 메서드는 Long 타입의 키를 받아서 String 타입으로 변환한 후, 실제 데이터 검색을 수행하는 get(String key, Class<T> classType) 메서드를 호출합니다.
- 제네릭 타입 <T>를 사용하여 반환 타입을 유연하게 지정할 수 있습니다.
2.2. get(String key, Class<T> classType)
- 기능: Redis에서 주어진 키(key)에 해당하는 데이터를 가져와서 지정된 클래스 타입(classType)으로 변환합니다.
- Redis에서 데이터 가져오기:
- redisTemplate.opsForValue().get(key)를 호출하여 Redis에서 주어진 키(key)에 해당하는 데이터를 가져옵니다.
- opsForValue()는 Redis의 String 데이터 타입을 다루기 위한 연산을 제공합니다.
- get(key)는 주어진 키에 해당하는 값을 가져오는 메서드입니다.
- 가져온 데이터는 String 타입으로 반환됩니다.
- 데이터가 존재하는지 확인:
- ObjectUtils.isEmpty(redisValue)를 호출하여 가져온 데이터가 존재하는지 확인합니다.
- ObjectUtils.isEmpty()는 Spring Framework에서 제공하는 유틸리티 메서드로, 객체가 null이거나 비어있는지 확인합니다.
- 데이터가 존재하지 않으면 (redisValue == null), null을 반환합니다.
- JSON 형식의 데이터를 Java 객체로 변환:
- mapper.readValue(redisValue, classType)를 호출하여 JSON 형식의 데이터를 지정된 클래스 타입(classType)의 Java 객체로 변환합니다.
- mapper.readValue()는 Jackson 라이브러리에서 제공하는 메서드로, JSON 데이터를 Java 객체로 역직렬화합니다.
- JSON 파싱 실패 시 에러 처리:
- try-catch 블록을 사용하여 JSON 파싱 과정에서 발생할 수 있는 JsonProcessingException을 처리합니다.
- e.printStackTrace()는 예외 정보를 콘솔에 출력합니다.
- log.error("Parsing error", e)는 로깅 라이브러리를 사용하여 에러 로그를 기록합니다.
- JSON 파싱에 실패하면 (JsonProcessingException 발생), null을 반환합니다.
- Redis에서 데이터 가져오기:
2.3. put(Long key, Cart cart)
- 기능: 주어진 키(key)에 해당하는 데이터를 Redis에 저장합니다.}`
- 이 메서드는 Long 타입의 키를 받아서 String 타입으로 변환한 후, 실제 데이터 저장을 수행하는 put(String key, Cart cart) 메서드를 호출합니다.
2.4. put(String key, Cart cart)
- 기능: 주어진 키(key)에 해당하는 데이터를 Redis에 저장합니다.
- Java 객체를 JSON 형식의 문자열로 변환:
- mapper.writeValueAsString(cart)를 호출하여 Java 객체(cart)를 JSON 형식의 문자열로 변환합니다.
- mapper.writeValueAsString()는 Jackson 라이브러리에서 제공하는 메서드로, Java 객체를 JSON 데이터로 직렬화합니다.
- redisTemplate.opsForValue().set(key, ...)를 호출하여 Redis에 데이터를 저장합니다.
- set(key, value)는 주어진 키(key)에 해당하는 값을 저장하는 메서드입니다.
- JSON 변환 실패 시 예외 발생:
- try-catch 블록을 사용하여 JSON 변환 과정에서 발생할 수 있는 JsonProcessingException을 처리합니다.
- JSON 변환에 실패하면 (JsonProcessingException 발생), CustomException을 발생시켜 ErrorCode.CART_CHANGE_FAIL 에러를 반환합니다.
- Java 객체를 JSON 형식의 문자열로 변환:
3. 핵심 개념 및 추가 설명
- Redis (Remote Dictionary Server): Redis는 인메모리 데이터 저장소로, 빠른 읽기/쓰기 속도를 제공합니다. 다양한 데이터 타입 (String, List, Set, Hash 등)을 지원하며, 캐싱, 세션 관리, 실시간 데이터 처리 등 다양한 용도로 사용됩니다.
- Spring Data Redis: Spring Data Redis는 Spring Framework에서 Redis를 쉽게 사용할 수 있도록 지원하는 모듈입니다. RedisTemplate, StringRedisTemplate 등의 클래스를 제공하여 Redis 데이터베이스와 상호 작용할 수 있도록 해줍니다.
- JSON (JavaScript Object Notation): JSON은 데이터를 교환하기 위한 경량의 데이터 형식입니다. 사람이 읽고 쓰기 쉽고, 기계가 파싱하고 생성하기도 쉬워서 널리 사용됩니다.
- 직렬화 (Serialization): 직렬화는 Java 객체를 바이트 스트림으로 변환하는 과정입니다. 바이트 스트림은 파일에 저장하거나 네트워크를 통해 전송할 수 있습니다.
- 역직렬화 (Deserialization): 역직렬화는 바이트 스트림을 Java 객체로 변환하는 과정입니다.
- Jackson: Jackson은 Java에서 JSON 데이터를 처리하기 위한 라이브러리입니다. ObjectMapper 클래스를 사용하여 Java 객체를 JSON 형식으로 변환하거나 JSON 형식을 Java 객체로 변환할 수 있습니다.
- 로깅 (Logging): 로깅은 프로그램 실행 중에 발생하는 이벤트를 기록하는 과정입니다. 로깅은 디버깅, 성능 분석, 감사 등 다양한 목적으로 사용됩니다. SLF4J (Simple Logging Facade for Java)는 다양한 로깅 프레임워크 (Logback, Log4j 등)를 추상화하는 인터페이스입니다.
-> put 메서드를 사용하여 장바구니 데이터를 저장하고, get 메서드를 사용하여 장바구니 데이터를 가져올 수 있습니다.
UserClient
package com.zerobase.cms.order.client;
import com.zerobase.cms.order.client.user.ChangeBalanceForm;
import com.zerobase.cms.order.client.user.CustomerDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
@FeignClient(name = "user-api", url = "${feign.client.url.user-api}")
public interface UserClient {
@GetMapping("/customer/getInfo")
ResponseEntity<CustomerDto> getCustomerInfo(@RequestHeader(name = "X-AUTH-TOKEN") String token);
@PostMapping("/customer/balance")
ResponseEntity<Integer> changeBalance(@RequestHeader(name = "X-AUTH-TOKEN") String token,
@RequestBody ChangeBalanceForm form);
}
User API Feign 클라이언트 (UserClient)
이 코드는 Spring Cloud OpenFeign을 사용하여 user-api 서비스와 통신하기 위한 인터페이스(UserClient)입니다. Feign 클라이언트는 다른 서비스의 API를 마치 로컬 메서드처럼 호출할 수 있도록 해주는 기술입니다. 즉, 이 인터페이스를 통해 user-api 서비스의 /customer/getInfo 및 /customer/balance 엔드포인트를 쉽게 호출할 수 있습니다.
1. 인터페이스 구조 및 어노테이션
- package com.zerobase.cms.order.client;: 이 인터페이스가 com.zerobase.cms.order.client 패키지에 속해 있음을 나타냅니다. 패키지는 관련 있는 클래스들을 묶어 관리하는 데 사용됩니다.
- import com.zerobase.cms.order.client.user.ChangeBalanceForm;: ChangeBalanceForm 클래스를 가져옵니다. 이 클래스는 잔액 변경 요청 시 필요한 정보를 담는 폼 객체입니다.
- import com.zerobase.cms.order.client.user.CustomerDto;: CustomerDto 클래스를 가져옵니다. 이 클래스는 고객 정보를 담는 데이터 전송 객체입니다.
- import org.springframework.cloud.openfeign.FeignClient;: FeignClient 어노테이션을 가져옵니다. 이 어노테이션은 해당 인터페이스가 Feign 클라이언트임을 나타냅니다.
- import org.springframework.http.ResponseEntity;: ResponseEntity 클래스를 가져옵니다. 이 클래스는 HTTP 응답을 나타냅니다.
- import org.springframework.web.bind.annotation.GetMapping;: GetMapping 어노테이션을 가져옵니다. 이 어노테이션은 HTTP GET 요청을 처리하는 메서드를 지정합니다.
- import org.springframework.web.bind.annotation.PostMapping;: PostMapping 어노테이션을 가져옵니다. 이 어노테이션은 HTTP POST 요청을 처리하는 메서드를 지정합니다.
- import org.springframework.web.bind.annotation.RequestBody;: RequestBody 어노테이션을 가져옵니다. 이 어노테이션은 HTTP 요청 body에 담긴 데이터를 메서드 파라미터로 전달합니다.
- import org.springframework.web.bind.annotation.RequestHeader;: RequestHeader 어노테이션을 가져옵니다. 이 어노테이션은 HTTP 요청 헤더 값을 메서드 파라미터로 전달합니다.
- @FeignClient(name = "user-api", url = "${feign.client.url.user-api}"): 이 어노테이션은 해당 인터페이스가 Feign 클라이언트임을 나타냅니다.
- name = "user-api"는 Feign 클라이언트의 이름을 지정합니다. 이 이름은 Spring 컨테이너에서 Feign 클라이언트를 식별하는 데 사용됩니다.
- url = "${feign.client.url.user-api}"는 user-api 서비스의 기본 URL을 지정합니다. ${feign.client.url.user-api}는 Spring Expression Language (SpEL)을 사용하여 application.properties 또는 application.yml 파일에 정의된 속성 값을 가져옵니다.
- public interface UserClient { ... }: UserClient 인터페이스를 정의합니다. public은 이 인터페이스가 모든 패키지에서 접근 가능하다는 것을 의미합니다.
2. 인터페이스 메서드
2.1. getCustomerInfo(String token)
- 기능: user-api 서비스의 /customer/getInfo 엔드포인트를 호출하여 고객 정보를 가져옵니다.ResponseEntity<CustomerDto> getCustomerInfo(@RequestHeader(name = "X-AUTH-TOKEN") String token);`
- @GetMapping("/customer/getInfo"): 이 어노테이션은 HTTP GET 요청을 /customer/getInfo 엔드포인트로 매핑합니다. 즉, 이 메서드는 HTTP GET 요청을 통해 고객 정보를 가져오는 데 사용됩니다.
- ResponseEntity<CustomerDto>: 이 메서드는 ResponseEntity<CustomerDto> 객체를 반환합니다. ResponseEntity는 HTTP 응답을 나타내는 클래스로, 응답 코드, 헤더, body 등을 포함합니다. CustomerDto는 응답 body에 담긴 고객 정보를 나타내는 데이터 전송 객체입니다.
- @RequestHeader(name = "X-AUTH-TOKEN") String token: 이 어노테이션은 HTTP 요청 헤더 X-AUTH-TOKEN의 값을 token 파라미터에 전달합니다. X-AUTH-TOKEN은 인증 토큰으로, 사용자를 인증하고 권한을 확인하는 데 사용됩니다.
- `@GetMapping("/customer/getInfo")
2.2. changeBalance(String token, ChangeBalanceForm form)
- 기능: user-api 서비스의 /customer/balance 엔드포인트를 호출하여 고객 잔액을 변경합니다.
ResponseEntity<Integer> changeBalance(@RequestHeader(name = "X-AUTH-TOKEN") String token, @RequestBody ChangeBalanceForm form);- @PostMapping("/customer/balance"): 이 어노테이션은 HTTP POST 요청을 /customer/balance 엔드포인트로 매핑합니다. 즉, 이 메서드는 HTTP POST 요청을 통해 고객 잔액을 변경하는 데 사용됩니다.
- ResponseEntity<Integer>: 이 메서드는 ResponseEntity<Integer> 객체를 반환합니다. Integer는 응답 body에 담긴 변경된 잔액을 나타내는 정수입니다.
- @RequestHeader(name = "X-AUTH-TOKEN") String token: 이 어노테이션은 HTTP 요청 헤더 X-AUTH-TOKEN의 값을 token 파라미터에 전달합니다.
- @RequestBody ChangeBalanceForm form: 이 어노테이션은 HTTP 요청 body에 담긴 데이터를 ChangeBalanceForm 객체로 변환하여 form 파라미터에 전달합니다. ChangeBalanceForm은 잔액 변경 요청 시 필요한 정보를 담는 폼 객체입니다.
- `@PostMapping("/customer/balance")
3. 핵심 개념 및 추가 설명
- Spring Cloud OpenFeign: Spring Cloud OpenFeign은 선언적이고 간편하게 REST API 클라이언트를 생성할 수 있는 라이브러리입니다. OpenFeign을 사용하면 HTTP 클라이언트 코드를 직접 작성하지 않고도 인터페이스를 통해 REST API를 호출할 수 있습니다.
- Feign 클라이언트: Feign 클라이언트는 다른 서비스의 API를 마치 로컬 메서드처럼 호출할 수 있도록 해주는 기술입니다. Feign 클라이언트를 사용하면 HTTP 클라이언트 코드를 직접 작성하는 번거로움을 줄이고, 코드 가독성을 높일 수 있습니다.
- 선언적 (Declarative): 선언적 프로그래밍은 프로그램이 어떻게 동작해야 하는지를 명시하는 방식으로, 프로그램이 어떻게 동작하는지를 직접 제어하는 명령적 프로그래밍과는 대조됩니다. Feign 클라이언트는 인터페이스와 어노테이션을 사용하여 API 호출을 선언적으로 정의할 수 있도록 해줍니다.
- REST API (Representational State Transfer Application Programming Interface): REST API는 HTTP 프로토콜을 사용하여 서버와 클라이언트 간에 데이터를 주고받는 API입니다. REST API는 자원 (Resource)을 URI (Uniform Resource Identifier)로 식별하고, HTTP 메서드 (GET, POST, PUT, DELETE 등)를 사용하여 자원을 조작합니다.
- HTTP (Hypertext Transfer Protocol): HTTP는 웹에서 데이터를 주고받기 위한 프로토콜입니다. HTTP는 클라이언트가 서버에 요청을 보내고, 서버가 클라이언트에 응답을 보내는 방식으로 동작합니다.
- HTTP 메서드 (HTTP Method): HTTP 메서드는 서버에 요청하는 동작을 지정합니다. 주요 HTTP 메서드는 다음과 같습니다.
- GET: 서버에서 데이터를 가져옵니다.
- POST: 서버에 새로운 데이터를 생성합니다.
- PUT: 서버에 존재하는 데이터를 갱신합니다.
- DELETE: 서버에서 데이터를 삭제합니다.
- HTTP 요청 헤더 (HTTP Request Header): HTTP 요청 헤더는 클라이언트가 서버에 보내는 요청에 대한 추가 정보를 담고 있습니다. 요청 헤더는 인증 토큰, 콘텐츠 타입, 사용자 에이전트 등 다양한 정보를 포함할 수 있습니다.
- HTTP 응답 (HTTP Response): HTTP 응답은 서버가 클라이언트에 보내는 응답입니다. HTTP 응답은 응답 코드, 헤더, body 등을 포함합니다.
- HTTP 응답 코드 (HTTP Response Code): HTTP 응답 코드는 서버가 클라이언트에 보내는 응답의 상태를 나타내는 숫자입니다. 주요 응답 코드는 다음과 같습니다.
- 200 OK: 요청이 성공적으로 처리되었습니다.
- 400 Bad Request: 요청이 잘못되었습니다.
- 401 Unauthorized: 인증이 필요합니다.
- 403 Forbidden: 접근이 금지되었습니다.
- 404 Not Found: 요청한 자원을 찾을 수 없습니다.
- 500 Internal Server Error: 서버에 오류가 발생했습니다.
- ResponseEntity: org.springframework.http.ResponseEntity는 Spring Framework에서 제공하는 클래스로, HTTP 응답을 나타냅니다. ResponseEntity는 응답 코드, 헤더, body 등을 포함할 수 있습니다.
- DTO (Data Transfer Object): DTO는 서비스 간에 데이터를 주고받을 때 사용되는 객체입니다. DTO는 데이터베이스의 엔티티와 유사하지만, 영속성을 가지지 않고 단순히 데이터를 담는 역할만 합니다.
반응형