본문 바로가기
Backend/이커머스 api

order api - client (user(ChangeBalanceForm, CustomerDto), RedisClient, UserClient) (2)

by 큌 2025. 2. 10.
반응형

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)으로 변환합니다.
    1. Redis에서 데이터 가져오기:
      • redisTemplate.opsForValue().get(key)를 호출하여 Redis에서 주어진 키(key)에 해당하는 데이터를 가져옵니다.
      • opsForValue()는 Redis의 String 데이터 타입을 다루기 위한 연산을 제공합니다.
      • get(key)는 주어진 키에 해당하는 값을 가져오는 메서드입니다.
      • 가져온 데이터는 String 타입으로 반환됩니다.
    2. 데이터가 존재하는지 확인:
      • ObjectUtils.isEmpty(redisValue)를 호출하여 가져온 데이터가 존재하는지 확인합니다.
      • ObjectUtils.isEmpty()는 Spring Framework에서 제공하는 유틸리티 메서드로, 객체가 null이거나 비어있는지 확인합니다.
      • 데이터가 존재하지 않으면 (redisValue == null), null을 반환합니다.
    3. JSON 형식의 데이터를 Java 객체로 변환:
      • mapper.readValue(redisValue, classType)를 호출하여 JSON 형식의 데이터를 지정된 클래스 타입(classType)의 Java 객체로 변환합니다.
      • mapper.readValue()는 Jackson 라이브러리에서 제공하는 메서드로, JSON 데이터를 Java 객체로 역직렬화합니다.
    4. JSON 파싱 실패 시 에러 처리:
      • try-catch 블록을 사용하여 JSON 파싱 과정에서 발생할 수 있는 JsonProcessingException을 처리합니다.
      • e.printStackTrace()는 예외 정보를 콘솔에 출력합니다.
      • log.error("Parsing error", e)는 로깅 라이브러리를 사용하여 에러 로그를 기록합니다.
      • JSON 파싱에 실패하면 (JsonProcessingException 발생), null을 반환합니다.

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에 저장합니다.
    1. Java 객체를 JSON 형식의 문자열로 변환:
      • mapper.writeValueAsString(cart)를 호출하여 Java 객체(cart)를 JSON 형식의 문자열로 변환합니다.
      • mapper.writeValueAsString()는 Jackson 라이브러리에서 제공하는 메서드로, Java 객체를 JSON 데이터로 직렬화합니다.
      • redisTemplate.opsForValue().set(key, ...)를 호출하여 Redis에 데이터를 저장합니다.
      • set(key, value)는 주어진 키(key)에 해당하는 값을 저장하는 메서드입니다.
    2. JSON 변환 실패 시 예외 발생:
      • try-catch 블록을 사용하여 JSON 변환 과정에서 발생할 수 있는 JsonProcessingException을 처리합니다.
      • JSON 변환에 실패하면 (JsonProcessingException 발생), CustomException을 발생시켜 ErrorCode.CART_CHANGE_FAIL 에러를 반환합니다.

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는 데이터베이스의 엔티티와 유사하지만, 영속성을 가지지 않고 단순히 데이터를 담는 역할만 합니다.
반응형