메타 데이터의 끝으로 건너뛰기
메타 데이터의 시작으로 이동

이 페이지의 이전 버전을 보고 있습니다. 현재 버전 보기.

현재와 비교 페이지 이력 보기

버전 1 다음 »

X2BEE BO(BackOffice)와 API 메시지 처리 방법에 대해 설명합니다.


BO 메시지 처리 방식 가이드

BO의 메시지는 ‘다국어 번역’ 및 ‘사용자 경험 개선’을 위해 설계되었습니다. 이 구조는 ‘react-i18next’와 상태 관리 라이브러리를 활용하여 동적이고 일관된 번역과 메시지 출력을 제공합니다.

1. allLangs 설정

다국어 번역 구조를 초기 설정합니다.

export const allLangs = [
  {
    value: 'en',
    label: 'English',
    countryCode: 'GB',
    adapterLocale: 'en',
    numberFormat: { code: 'en-US', currency: 'USD' },
    systemValue: { components: { /* 영어 설정 */ } },
  },
  {
    value: 'ko',
    label: 'Korea',
    countryCode: 'KR',
    adapterLocale: 'ko',
    numberFormat: { code: 'ko', currency: 'WON' },
    systemValue: { components: { /* 한국어 설정 */ } },
  },
]

2. useTranslate Hook

다국어 번역을 관리하는 커스텀 훅입니다.

export function useTranslate(
  ns?: string | string[], // 사용할 네임스페이스(다국어 번역 키 그룹)
  options: { keyPrefix?: KeyPrefix<string> } = {} // 키 프리픽스 설정
) {
  const router = useRouter();
  // react-i18next의 번역 함수 및 언어 정보
  const { t, i18n } = useTranslation(ns, options);
  // 공통 코드 동기화 함수
  const { updateCodeList } = useUpdateCommonCodeStore();
  // 기본 언어 설정
  const fallback = allLangs.find((lang) => lang.value === fallbackLng);
  const currentLang = allLangs.find(
    (lang) => lang.value === i18n.resolvedLanguage // 현재 설정된 언어 확인
  );
  const onChangeLang = useCallback(
    async (newLang: LanguageValue) => {
      try {
        // 언어 쿠키 저장
        setCookie('data_lang_cd', newLang);
        setCookie('lang_cd', newLang);
        // 언어 변경 시 공통 코드 동기화
        updateCodeList();
        // 언어 변경 처리
        const langChangePromise = i18n.changeLanguage(newLang);
        // 해당 언어 메시지 가져오기
        const currentMessages = messages[newLang] || messages.en;
        // 언어 변경 상태에 따른 사용자 피드백
        toast.promise(langChangePromise, {
          loading: currentMessages.loading,
          success: () => currentMessages.success,
          error: currentMessages.error,
        });
        // 날짜 로케일 동기화
        if (currentLang) dayjs.locale(currentLang.adapterLocale);
        // 페이지 새로고침으로 UI 갱신
        router.refresh();
      } catch (error) {
        console.error(error);
      }
    },
    [currentLang, i18n, router, updateCodeList]
  );
  return {
    t, // 번역 함수
    i18n, // 번역 엔진 상태
    onChangeLang, // 언어 변경 핸들러
    currentLang: currentLang ?? fallback, // 현재 언어
  };
}

사용법은 다음과 같습니다.

3. 메시지 JSON 작성

src > Locals > langs 위치의 각 언어 폴더에 해당하는 메시지를 작성합니다.

{
  "adminCommon": {
    "message": {
      "successfully": {
        "saved": "저장되었습니다.",
        "deleted": "삭제되었습니다."
      }
    }
  }
}

4. 페이지 및 컴포넌트에서의 사용 예시

실 화면에서 사용하는 예시입니다.

const CM_NS = 'common';
const CM = { ns: CM_NS, keyPrefix: 'adminCommon' };
const sampleComponents = () => {
  const { t } = useTranslate([CM_NS]);
  const { dialogAlert } = useDialogContext();
  const onSave = () => {
    dialogAlert({
      text: t('message.successfully.saved', CM) // 저장되었습니다.
    });
  };
  // ...
};
export default sampleComponents;

API 메시지 처리 방식 가이드

메시지 값을 처리하기 위해 공통에서 MessageResolver 클래스를 제공합니다.

1. MessageResolver.class

getLocaleMessage 함수가 메시지 값을 가져오는 주요 함수로서 다음과 같이 작동합니다.

  • messageKey 값이 String Key인 경우, 그대로 메시지 값을 반환합니다.

  • messageKey 값이 Enum Class인 경우, RequestContextHolder 객체의 헤더 값에서 호출한 서버명을 인식하여 BO-API인 경우 두 번째 메시지 인자 값인 boMessageKey의 메시지 값을 반환합니다. 호출한 서버명이 BO-API가 아닌 경우 기존 messageKey 그대로 메시지 값을 반환합니다.

private static String getLocaleMessage(AppError appError, Object[] args, Locale locale) {
    String message = "";
    if (RequestContextUtil.isCallServerBo()) { // 호출한 서버가 BO-API인 경우
        message = getMessageKeyToMessageValue(appError.getBoMessageKey(), args, locale, false);
        if (StringUtils.isBlank(message)) {
            // BO-API 메시지 코드값이 없을 경우 기본 메시지 코드값 가져옴.
            message = getMessageKeyToMessageValue(appError.getMessageKey(), args, locale, true);
        }
    } else {
        message = getMessageKeyToMessageValue(appError.getMessageKey(), args, locale, true);
    }
    return message;
}

사용법은 다음과 같습니다.

2. ApiError Class 파일 작성

해당 enum class 파일에 code 값 및 message 키 값을 정의합니다.

public enum ApiError implements AppError {
    /* success */
    SUCCESS("0000", "common.message.success", "common.message.success", false),
    /* app error */
    EMPTY_PARAMETER("1001", "common.error.emptyParameter", "common.error.emptyParameter", false),
    INVALID_PARAMETER("1002", "common.error.invalidParameter", "common.error.invalidParameter", false),
    // unknown error
    UNKNOWN("9000", "common.error.unknown", "common.error.unknown"),
    // ValidationException error
    VALIDATION_EXCEPTION("9100", "common.error.unknown", "common.error.unknown"),
    TEST("9999", "event.aply.simple.member.limit.message", "event.aply.simple.member.limit.message.bo");
    
    private final String code;
    private final String messageKey;
    private final String boMessageKey;
}

3. message properties 파일 작성

event_ko.properties, event_en.properties 등 message properties 파일을 정리합니다. 해당 message properties 파일에 API에서 사용할 메시지 값을 정의합니다.

event.aply.simple.member.limit.message = 간편회원은 응모하실 수 없습니다.
event.aply.simple.member.limit.message2 = 간편회원은 응모하실 수 없습니다.

4. 비즈니스 로직에서 사용 예시

@GetMapping("/test")
public ResponseEntity<Response> test() throws Exception {
    // 메시지를 직접 가져오는 경우. 해당 메시지 키 값 그대로 반환함.
    String eventMsg = MessageResolver.getMessage("event.aply.simple.member.limit.message");
    // 위와 동일하지만 정의한 ApiError enum Class를 활용하는 경우
    // 호출한 서버명에 따라서 messageKey 값을 반환함.
    String msg = MessageResolver.getMessage(ApiError.TEST);
    // AppException을 발생하는 경우
    // 호출한 서버명에 따라서 messageKey 값을 반환함.
    AppException.exception(ApiError.TEST);
    Response body = Response.builder().payload("OK").message(eventMsg).build();
    return ResponseEntity.ok().body(body);
}
  • 레이블 없음