WinForms/WPF 앱 다국어화 ── resx·새틀라이트 어셈블리·컬처 전환 실무

· · CSharp, .NET, WinForms, WPF, 다국어화, 현지화, 리소스, UI, Windows 개발, 기술 상담

“해외 거점에서도 같은 앱을 쓰고 싶다”, “공장 현장에 외국어를 쓰는 직원이 늘어서 화면을 영어로도 보여주고 싶다” ── Windows 데스크톱 앱의 다국어화는 요구사항으로는 단순해 보이지만, 막상 착수하면 “resx를 어떻게 사용해야 하는가”, “WPF는 방식이 여러 가지라 어느 것이 정답인지 모르겠다”, “실행 중에 언어를 전환할 수 있는가” 등 판단하기 어려운 지점이 계속 등장합니다.

이 글에서는 WinForms/WPF 업무 앱을 가정하고, .NET 현지화의 토대(컬처와 리소스 폴백), resx와 새틀라이트 어셈블리의 구조, 프레임워크별 현실적인 방식, 실행 중 전환, 그리고 문자열 이외(서식·레이아웃·RTL)의 쟁점까지를 실무에서 판단하기 어려운 순서대로 정리합니다.

1. 결론부터(판단표)

다국어화 방식은 프레임워크와 요구사항의 조합으로 결정됩니다.

상황 권장 방식 이유
WinForms·화면의 레이블/버튼이 중심 폼의 Localizable = true + 언어별 resx(디자이너 방식) 컨트롤의 문자열과 크기·위치를 언어별로 조정할 수 있고 Visual Studio만으로 완결된다
WinForms/WPF 공통·메시지나 공유 문구가 많음 공유 resx(Resources.resx + Resources.ja.resx 등)+ 자동 생성되는 타입 지정 클래스 문자열을 코드에서 타입 안전하게 참조할 수 있다. 화면과 로직에서 동일한 문구를 공유할 수 있다
WPF 공유 resx + x:Static 바인딩 LocBaml 방식은 .NET(Core)의 WPF에서는 사용할 수 없다1. resx 방식이라면 WinForms와 지식을 공유할 수 있다
실행 중 언어 전환이 필수 resx + 변경 통지 구조(또는 화면 재생성) 방식을 선정하기 전에 “정말로 재시작 없이 전환이 필요한가”를 요구사항으로 먼저 확인한다(6장)
번역을 외부에 위탁한다 resx 기반으로 설계하고 키와 번역문 대응표로 주고받는다 resx는 XML이므로 그대로도 주고받을 수 있지만, 문맥 정보(어느 화면의 어느 버튼인지)를 첨부하는 운영 방식이 품질을 좌우한다

결론을 먼저 적습니다.

  • CurrentCulture(서식)와 CurrentUICulture(리소스 언어)는 서로 다른 것입니다. 이 구분이 다국어화 설계 전체의 토대가 됩니다(2장).
  • 리소스의 실체는 ‘중립 언어 리소스 + 언어별 새틀라이트 어셈블리’이며, 폴백은 자동으로 이루어집니다. ja-JPja → 중립 언어 순으로 탐색되므로, 번역이 누락되어도 앱이 죽지 않고 기본 언어로 표시됩니다2.
  • WinForms는 디자이너 방식(Localizable = true)과 공유 resx 방식을 병행하는 것이 실무 해법입니다. 화면은 디자이너 방식으로, 메시지 박스나 공통 문구는 공유 resx로 몰아둡니다(4장).
  • WPF의 공식 연습(walkthrough)에 나오는 LocBaml 방식은 .NET(Core)에서는 사용할 수 없습니다1. 현재 실무에서는 resx + x:Static(또는 바인딩) 방식이 우선 후보입니다(5장).
  • 실행 중 언어 전환은 ‘다음 실행 시 반영’을 우선 후보로 삼습니다. 이미 표시된 화면의 리소스는 자동으로 교체되지 않기 때문입니다(6장).
  • 문자열 번역은 다국어화의 절반에 불과합니다. 번역 후 문자열 길이에 따른 레이아웃 대응, 날짜·숫자 서식, 폰트, 오른쪽에서 왼쪽으로 쓰는 언어(RTL) 대응이 나머지 절반입니다(7장).

2. 토대 ── CurrentCulture와 CurrentUICulture의 차이

.NET의 컬처(문화권 설정)에는 역할이 다른 두 가지 속성이 있습니다3.

속성 결정하는 것
CultureInfo.CurrentCulture 날짜·숫자·통화의 서식 2026/07/07로 표시할지 7/7/2026으로 표시할지
CultureInfo.CurrentUICulture 어떤 언어의 리소스를 불러올지 버튼에 “저장”이라고 표시할지 “Save”라고 표시할지

이 둘은 독립적으로 설정할 수 있습니다. 예를 들어 “화면은 영어지만 날짜나 통화는 일본식 서식”이라는 조합(일본 국내에서 외국어를 사용하는 직원을 위한 업무 앱에서 흔한 요구사항)은 CurrentUICulture = en이면서 CurrentCulture = ja-JP로 자연스럽게 표현할 수 있습니다.

기본값은 둘 다 OS 설정에서 비롯되므로 “아무것도 하지 않으면 OS를 따른다”가 출발점입니다. 앱 전체에서 언어를 명시적으로 전환할 때는 스레드마다 설정하는 것이 아니라 기본값 자체를 교체합니다.

using System.Globalization;

// 이후 생성되는 모든 스레드의 기본 컬처를 교체한다
// (UI 스레드 생성 전 = Application.Run 이전에 실행한다)
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en"); // 리소스 언어
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("ja-JP"); // 서식

Thread.CurrentThread.CurrentUICulture에 대한 대입은 해당 스레드에만 적용됩니다. async/await나 백그라운드 처리로 스레드를 넘나드는 업무 앱에서는 DefaultThreadCurrentUICulture / DefaultThreadCurrentCulture로 기본값 자체를 바꾸는 편이 사고를 줄일 수 있습니다3.

참고로 로그·파일 출력·시스템 간 연동의 서식은 사용자 컬처를 따르지 않고 CultureInfo.InvariantCulture로 고정합니다. 날짜 서식 설계 전반은 “업무 앱의 날짜·시간대 설계“를 참조하세요.

3. 리소스 구조 ── resx·새틀라이트 어셈블리·폴백

.NET의 현지화는 ‘허브 앤 스포크(hub & spoke)’ 모델입니다. 기본 언어(중립 언어)의 리소스는 본체 어셈블리에 내장하고, 언어별 리소스는 새틀라이트 어셈블리라는 별도의 DLL로 분리합니다4.

빌드하면 언어별 resx는 다음과 같은 출력 구성이 됩니다.

MyApp.exe                     ← 본체(중립 리소스를 포함)
MyApp.dll
ja/MyApp.resources.dll        ← 일본어 새틀라이트 어셈블리
en/MyApp.resources.dll        ← 영어 새틀라이트 어셈블리

실행 시 리소스 매니저는 CurrentUICulture를 시작점으로 특정 컬처(ja-JP) → 중립 컬처(ja) → 기본(본체) 순으로 리소스를 찾습니다2. 이 자동 폴백 덕분에 번역이 하나 빠져 있어도 앱이 죽지 않고 기본 언어 문자열이 표시됩니다. 반대로 말하면 “영어 화면이어야 하는데 일부만 일본어가 섞여 있다”는 것은 번역 누락의 신호이며, 테스트 관점으로 활용할 수 있습니다(8장).

실무에서는 다음 두 가지를 기억해 둡니다.

  • 기본 언어가 어떤 컬처인지를 NeutralResourcesLanguage 속성으로 선언해 두면, 기본 컬처일 때 새틀라이트를 찾으러 가는 낭비가 없어지고 폴백의 종착점이 명확해집니다4.
  • 새틀라이트 어셈블리는 ‘본체와 함께 배포되어야 비로소 동작’하므로, 설치 프로그램이나 복사 배포 설계에 언어 폴더를 포함해야 합니다(8장).

4. WinForms 실무 ── 디자이너 방식과 공유 resx 방식

WinForms에는 두 가지 방식이 있으며, 실무에서는 이를 함께 사용합니다.

4.1 화면은 디자이너 방식(Localizable = true)

폼의 속성에서 Localizabletrue로 설정하고 Language 속성을 대상 언어(예: 영어)로 전환한 뒤 레이블이나 버튼의 Text를 수정하면, Visual Studio가 Form1.en.resx와 같은 언어별 resx를 자동으로 생성합니다5.

이 방식의 강점은 문자열뿐 아니라 컨트롤의 크기·위치도 언어별로 저장된다는 점입니다. 일본어 “登録”이 영어 “Register”가 되면서 버튼 밖으로 삐져나오는 문제를, 디자이너 상에서 언어별로 조정할 수 있습니다. 반면 언어 수 × 폼 수만큼 resx가 늘어나고, 폼의 레이아웃을 변경할 때마다 모든 언어를 확인해야 하는 유지보수 비용도 발생합니다. 언어 수가 늘어날 가능성이 있다면, 다음 장의 레이아웃 대책(7장)에서 다루는 “조정하지 않아도 무너지지 않는” 화면 구성을 우선하시기 바랍니다.

4.2 메시지·공통 문구는 공유 resx 방식

메시지 박스의 문구, 확인 대화상자, 상태 표시줄 표시 등 코드에서 사용하는 문자열은 프로젝트 공통의 Resources.resx에 모으고, 언어별로 Resources.en.resx 등을 추가합니다. resx에서는 타입 지정 클래스가 자동으로 생성되므로, 코드에서 키를 잘못 입력할 걱정 없이 참조할 수 있습니다.

// 자동 생성된 타입 지정 클래스를 통해 참조한다.
// 반환되는 문자열은 CurrentUICulture에 따라 자동으로 전환된다
MessageBox.Show(
    Properties.Resources.ConfirmDeleteMessage,
    Properties.Resources.ConfirmTitle,
    MessageBoxButtons.YesNo);

여기서 가장 중요한 규칙은 사용자에게 보이는 문자열을 코드에 직접 작성하지 않는 것입니다. 다국어화 공수는 구조 도입이 아니라 “여기저기 흩어진 하드코딩 문자열을 회수하는 작업”에 소요됩니다. 단일 언어로 운영하는 단계에서도 resx를 경유해 두는 가치가 바로 여기에 있습니다.

5. WPF 실무 ── LocBaml이 아니라 resx를 우선 후보로

WPF의 다국어화는 정보가 뒤섞이기 쉬운 영역입니다. 공식 문서의 연습(walkthrough)에는 UICulture를 프로젝트 파일에 설정해 BAML 리소스를 생성하고 LocBaml 도구로 번역을 끼워 넣는 방식이 실려 있지만, LocBaml은 .NET Framework WPF 전용 샘플 도구이며 .NET(Core) WPF에서는 동작하지 않습니다1. 현재 새로 선택할 방식이 아니라고 생각하시기 바랍니다.

실무에서 우선 후보로 삼는 것은 WinForms와 동일한 공유 resx 방식을 XAML에서 참조하는 형태입니다.

<!-- resx의 액세스 한정자를 Public으로 설정한 뒤 x:Static으로 참조한다 -->
<Window xmlns:res="clr-namespace:MyApp.Properties"
        Title="{x:Static res:Resources.MainWindowTitle}">
    <Button Content="{x:Static res:Resources.SaveButton}" />
</Window>

이 방식의 장점은 리소스 구조(새틀라이트 어셈블리·폴백)가 WinForms와 완전히 공통이라서, 혼합 솔루션에서도 문구를 일원적으로 관리할 수 있다는 점입니다. x:Static은 시작 시 해석되는 정적 참조이므로, 실행 중 전환이 필요한 경우에는 바인딩 + 변경 통지 방식으로 확장합니다(6장).

XAML 쪽에서는 함께 루트 요소의 xml:lang을 설정해 두면, 하이픈 처리나 폰트 폴백, 숫자 표시 등 WPF의 언어 의존 기능이 올바르게 동작합니다1.

WinForms/WPF 중 무엇으로 만들지에 대한 판단 자체는 “WinForms / WPF / WinUI 구분 사용 판단표“를 참조하세요.

6. 실행 중 언어 전환 ── ‘다음 실행 시 반영’을 우선 후보로

설정 화면에서 언어를 선택하게 하는 요구사항에서는 반영 시점을 두 가지 안 중에서 선택합니다.

  • 안 A: 다음 실행 시 반영(권장). 선택한 언어를 설정 파일에 저장하고, 실행 시 Application.Run 이전(WPF라면 Application 시작 이전)에 DefaultThreadCurrentUICulture를 설정합니다. 구현이 단순하고, 화면 재구성에 따른 문제(입력 중이던 데이터 유실, 이벤트 핸들러 중복 등록 등)가 구조적으로 발생하지 않습니다.
  • 안 B: 즉시 반영. CurrentUICulture를 변경해도 이미 표시된 화면의 문자열은 자동으로 교체되지 않습니다. WinForms의 디자이너 방식이라면 ComponentResourceManager.ApplyResources로 열려 있는 폼에 다시 적용하고, WPF라면 문자열을 바인딩 + 변경 통지로 공급하는 등, 어느 쪽이든 “모든 화면이 리소스 재적용에 대응하고 있다”는 전제가 필요한 구현이 됩니다.

업무 앱에서는 언어를 바꾸는 빈도(대개 도입 시 1회)에 비해 안 B의 구현·테스트 비용이 맞지 않는 경우가 많아, 안 A를 기본으로 하고 안 B는 요구사항상 정말로 필요한 경우에만 적용하는 것을 권장합니다. 언어 설정의 저장 위치는 사용자별 설정이므로 %LOCALAPPDATA% 하위가 적절합니다. 설정 저장 위치에 대한 판단은 “Windows 업무 앱의 구성 관리 실무“의 판단표를 참조하세요.

7. 문자열 이외의 다국어화 ── 레이아웃·서식·폰트·RTL

번역이 끝났더라도 다국어화는 아직 절반이 남아 있습니다.

  • 레이아웃의 신축. 같은 의미의 문구라도 언어에 따라 길이가 크게 달라집니다(일본어 “保存” → 독일어 “Speichern”). 좌표·크기를 고정한 레이아웃은 번역할 때마다 무너지므로, WinForms에서는 TableLayoutPanelAutoSize를 조합해 문자열 길이에 따라 늘어나는 레이아웃으로 만드는 것이 공식적으로 안내되는 방법입니다6. WPF는 레이아웃 시스템이 원래 가변적이므로 너비를 고정값으로 못박는 것만 피해도 대부분 대응할 수 있습니다. 아울러 고DPI 환경에서의 레이아웃 붕괴 대책(“WinForms 고DPI 대응 가이드”, “WPF 고DPI 대응 가이드“)과 함께 설계하면 나중에 다시 손댈 일이 없습니다.
  • 날짜·숫자·통화 서식. 화면 표시는 CurrentCulture에 맡기고, 화면 코드에서 ToString("yyyy/MM/dd")처럼 직접 고정하는 방식을 줄입니다. 반대로 파일·로그·연동 데이터는 InvariantCulture로 고정합니다(2장).
  • 폰트. 대상 언어의 문자가 폰트에 포함되어 있는지 확인합니다. 중국어(간체/번체)나 한국어를 추가하는 경우, 일본어용 폰트 지정을 그대로 두면 글자 모양이 부자연스러워질 수 있습니다(이른바 CJK 자형 문제). UI 폰트 지정을 한 곳에 모아두면 언어 추가 시 변경이 쉬워집니다.
  • 오른쪽에서 왼쪽으로 쓰는 언어(RTL). 아랍어·히브리어 대응에서는 문자열 번역에 더해 화면의 좌우 반전이 필요합니다. WinForms는 RightToLeft / RightToLeftLayout 속성으로, WPF는 FlowDirection 속성으로 제어합니다. RTL 대응은 “나중에 추가”하려고 하면 전체 화면을 재검토해야 하므로, 대상 언어에 포함될 가능성이 있다면 처음부터 요구사항에 포함시키세요.
  • 이미지·아이콘 안의 문자. 이미지에 박혀 있는 문자열은 리소스 구조로는 전환되지 않습니다. 문자가 들어간 이미지는 피하고, 이미지 + 텍스트 레이블 구성으로 해두는 것이 안전합니다.

UI 설계 전반에 대한 판단은 “Windows 앱의 UX 설계 판단표“도 함께 참조하세요.

8. 운영 ── 번역 주고받기·누락 검출·배포

마지막으로, 구조가 갖춰진 이후의 운영 측면입니다.

  • 번역을 주고받을 때는 문맥을 첨부한다. resx의 키와 원문만 전달하면 “OK”, “열기”처럼 짧은 문구의 번역 품질이 안정되지 않습니다. 키·원문·번역문에 “표시되는 화면과 용도”를 첨부한 대응표(스프레드시트 등)로 주고받고, 받은 뒤 resx에 반영하는 운영 방식이 현실적입니다.
  • 번역 누락은 폴백으로 찾아낸다. 리소스 폴백에 의해 번역 누락은 “해당 언어 화면에 기본 언어가 섞여 나오는” 형태로 드러납니다2. 언어별 resx의 키 목록을 중립 resx와 대조하는 간단한 검사(스크립트나 테스트 코드)를 CI에 넣어두면 릴리스 전에 기계적으로 검출할 수 있습니다.
  • 배포에 새틀라이트 어셈블리를 포함한다. ja/, en/ 등의 언어 폴더를 통째로 배포하지 않으면 해당 언어만 폴백되어 “번역은 했는데 반영되지 않는” 상태가 됩니다. 수작업 복사 과정에서 언어 폴더가 누락되는 것은 흔히 일어나는 사고이므로, 설치 프로그램(MSI/MSIX 등)에 디렉터리 구조째로 포함시킵니다. ClickOnce 배포에서는 기본적으로 모든 언어의 새틀라이트 어셈블리가 배포에 포함됩니다7. 배포 방식 전반에 대한 판단은 “Windows 앱 배포 방법 선택 가이드“를 참조하세요.

정리

데스크톱 앱의 다국어화는 resx와 새틀라이트 어셈블리라는 검증된 구조 위에서 이루어지며, 구조 자체는 어렵지 않습니다. 실무의 성패를 가르는 것은 CurrentCultureCurrentUICulture를 구분한 설계, 사용자에게 보이는 문자열을 직접 작성하지 않는 규율, 번역 후 문자열 길이를 견디는 레이아웃, 그리고 “즉시 전환이 정말로 필요한가”라는 요구사항 판별입니다. WPF에서는 오래된 LocBaml 방식의 정보에 이끌리지 말고 resx 기반으로 구성하는 것이 현재의 실무 해법입니다.

기존 앱의 다국어화 방식 선정과 영향 범위 산정, 해외 거점 전개를 위한 화면·장표·연동 데이터의 다국어 대응은 코드베이스의 현재 상태를 보면서 판단해야 하는 경우가 많으므로, 고민되신다면 상담해 주세요.

관련 글

관련 상담 분야

합동회사 코무라 소프트에서는 WinForms/WPF 앱의 다국어 대응 설계·구현, 기존 앱을 나중에 다국어화할 때의 방식 선정과 영향 범위 정리에 관한 기술 상담을 다루고 있습니다.

참고 자료

  1. Microsoft Learn, WPF Globalization and Localization Overview. 프로젝트 파일의 UICulture 설정을 통한 새틀라이트 어셈블리 생성, 루트 요소의 xml:lang 역할, 그리고 LocBaml이 .NET Framework WPF 전용 샘플 도구이며 .NET WPF에서는 동작하지 않는다는 점에 대해 다룹니다.  2 3 4

  2. Microsoft Learn, Retrieve resources in .NET apps. 리소스 폴백 프로세스(특정 컬처 → 중립 컬처 → 메인 어셈블리의 기본 리소스 순으로 탐색되는 과정)에 대해 다룹니다.  2 3

  3. Microsoft Learn, CultureInfo.CurrentUICulture Property. CurrentUICulture가 리소스 매니저의 컬처별 리소스 탐색에 사용된다는 점, 기본값이 OS의 사용자 인터페이스 언어에서 비롯된다는 점, DefaultThreadCurrentUICulture를 통한 전체 스레드 기본값 설정에 대해 다룹니다.  2

  4. Microsoft Learn, Resources in .NET apps. resx 리소스의 생성·패키징, 메인 어셈블리와 새틀라이트 어셈블리를 이용한 허브 앤 스포크 모델, NeutralResourcesLanguage 속성에 대해 다룹니다.  2

  5. Microsoft Learn, Walkthrough: Localizing a Hybrid Application. Windows 폼 디자이너에서 Localizable 속성을 true로 설정하고 Language 속성을 전환해 언어별 resx(예: Form1.es-ES.resx)를 생성하는 절차, InitializeComponent 호출 전에 CurrentUICulture를 설정하는 예시에 대해 다룹니다. 

  6. Microsoft Learn, How to: Design a Windows Forms Layout that Responds Well to Localization. TableLayoutPanel을 사용해 현지화에 따른 Text 속성의 문자열 길이 변화에 컨트롤 크기가 따라가는 레이아웃을 만드는 방법에 대해 다룹니다. 

  7. Microsoft Learn, Localize ClickOnce applications. 모든 새틀라이트 어셈블리를 하나의 배포에 포함시키는 방식이 Visual Studio의 기본값이라는 점, 실행 시 OS의 컬처에 따라 새틀라이트 어셈블리가 사용된다는 점에 대해 다룹니다. 

같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.

이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.

이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.

자주 묻는 질문

이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.

일본어로만 만든 기존 앱을 나중에 다국어화할 수 있나요?
가능합니다만, 작업의 대부분은 '리소스 구조 도입'이 아니라 '코드에 직접 작성된 문자열을 찾아내고 치환하는 작업'입니다. 화면의 문자열뿐 아니라 메시지 박스, 로그, 예외 메시지, 장표, DB에 저장된 표시용 문자열까지 전수 조사가 필요하며, 작업 규모는 화면 수보다 문자열이 얼마나 흩어져 있는가로 결정됩니다. 신규 개발 단계에서부터 사용자에게 보이는 문자열만이라도 resx를 경유하도록 해두면 향후 다국어화 비용이 크게 줄어듭니다.
번역은 기계 번역으로 끝내도 괜찮나요?
사내 도구나 임시 대응이라면 기계 번역으로 시작하는 것도 현실적입니다. 다만 업무 앱은 버튼이나 메뉴의 짧은 단어(예: '등록', '취소')가 많아 문맥이 없으면 기계 번역의 오역률이 높아지는 영역입니다. 최소한 실제로 해당 언어를 사용하는 사람이 화면을 직접 확인하는 리뷰를 한 차례는 거치는 것을 권장합니다. 또한 번역 품질 이전에 '번역 후 길어진 문자열로 레이아웃이 무너지지 않는' 것을 TableLayoutPanel과 AutoSize로 먼저 보장해두는 편이 더 중요합니다.
로그나 오류 메시지도 번역해야 하나요?
사용자 화면에 표시되는 메시지는 번역하고, 로그 파일이나 이벤트 로그에 기록하는 내용은 번역하지 않는(언어를 고정하는) 것이 실무의 정석입니다. 로그는 사용자가 아니라 개발자·운영자가 읽는 것이며, 다국어로 된 로그는 조사 시 검색성을 해칩니다. 서식(날짜·숫자)도 로그는 CultureInfo.InvariantCulture로 고정하세요. CurrentCulture와 CurrentUICulture를 분리해서 다루는 설계로 해두면 이러한 구분이 자연스럽게 실현됩니다.
OS의 표시 언어와는 별도로 앱만 언어를 전환할 수 있게 해야 하나요?
해외 거점 전개나 국내에서 외국어를 쓰는 직원이 사용하는 업무 앱이라면, 앱 내부에 언어 설정을 두는 가치가 큽니다. 기본값은 OS의 표시 언어를 따르고(CurrentUICulture의 기본값), 설정 화면에서 명시적으로 선택한 경우에만 이를 덮어쓰는 2단계 구성이 무난합니다. 전환 반영은 '다음 실행 시'로 명세하는 것이 가장 안전하며, 구현도 운영 설명도 단순해집니다.

저자 프로필

기사 저자의 프로필 페이지입니다.

Go Komura

합동회사 코무라소프트 대표

Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.

블로그 목록으로 돌아가기