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
함수가 메시지 값을 가져오는 주요 함수로서 다음과 같이 작동합니다.
...
코드 블럭 |
---|
|
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);
} |