diff --git a/debug-login.mjs b/debug-login.mjs
new file mode 100644
index 0000000..6f613ee
--- /dev/null
+++ b/debug-login.mjs
@@ -0,0 +1,40 @@
+import { chromium } from '@playwright/test';
+
+(async () => {
+ const browser = await chromium.launch();
+ const page = await browser.newPage();
+
+ try {
+ await page.goto('http://localhost:5265/login');
+
+ // Fill and submit
+ await page.fill('input[type="text"]', 'admin');
+ await page.fill('input[type="password"]', 'admin');
+ await page.click('button[type="submit"]');
+
+ // Wait a bit for response
+ await page.waitForTimeout(3000);
+
+ // Check current page content
+ const content = await page.content();
+
+ if (content.includes('로그인 실패')) {
+ console.log('✗ Error shown: Login failed');
+ } else if (content.includes('오류 발생')) {
+ console.log('✗ Error shown: Exception');
+ } else if (content.includes('로그인 성공')) {
+ console.log('✓ Login success message shown');
+ } else {
+ console.log('✓ Form still displayed');
+ }
+
+ // Take screenshot
+ await page.screenshot({ path: './login-attempt.png', fullPage: true });
+ console.log('Screenshot saved');
+
+ } catch (e) {
+ console.error('Error:', e.message);
+ }
+
+ await browser.close();
+})();
diff --git a/final-test.mjs b/final-test.mjs
new file mode 100644
index 0000000..887bcc7
--- /dev/null
+++ b/final-test.mjs
@@ -0,0 +1,41 @@
+import { chromium } from '@playwright/test';
+
+(async () => {
+ const browser = await chromium.launch();
+ const page = await browser.newPage();
+
+ try {
+ console.log('Starting login test...');
+ await page.goto('http://localhost:5265/login');
+
+ // Check page structure
+ const html = await page.content();
+ const hasMenu = html.includes('메뉴') && html.includes('대시보드');
+ console.log(hasMenu ? '⚠ Menu visible' : '✓ Clean login page');
+
+ // Fill and submit
+ await page.fill('input[type="text"]', 'admin');
+ await page.fill('input[type="password"]', 'admin');
+ await page.click('button[type="submit"]');
+
+ console.log('Login submitted, waiting for response...');
+ await page.waitForTimeout(2000);
+
+ // Check for errors or success
+ const content = await page.content();
+ if (content.includes('로그인 실패')) {
+ console.log('✗ Login failed');
+ } else if (content.includes('오류')) {
+ console.log('✗ Error occurred');
+ } else {
+ console.log('✓ Attempting navigation to dashboard...');
+ await page.waitForNavigation({ waitUntil: 'load', timeout: 6000 });
+ console.log('✓ Navigation complete to: ' + page.url());
+ }
+
+ } catch (e) {
+ console.log('Error/Navigation timeout (expected): ' + e.message.substring(0, 50));
+ }
+
+ await browser.close();
+})();
diff --git a/login-attempt.png b/login-attempt.png
new file mode 100644
index 0000000..3edbc20
Binary files /dev/null and b/login-attempt.png differ
diff --git a/src/dotnet/QuantEngine.Web/Client/Layout/EmptyLayout.razor b/src/dotnet/QuantEngine.Web/Client/Layout/EmptyLayout.razor
new file mode 100644
index 0000000..479db95
--- /dev/null
+++ b/src/dotnet/QuantEngine.Web/Client/Layout/EmptyLayout.razor
@@ -0,0 +1,16 @@
+@inherits LayoutComponentBase
+
+@Body
+
+
diff --git a/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor b/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor
new file mode 100644
index 0000000..ef381ed
--- /dev/null
+++ b/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor
@@ -0,0 +1,343 @@
+@page "/login"
+@layout EmptyLayout
+@using Microsoft.AspNetCore.Components.Authorization
+@using QuantEngine.Web.Client.Infrastructure
+@inject HttpClient Http
+@inject NavigationManager Navigation
+@inject AuthenticationStateProvider AuthStateProvider
+
+
은퇴자산포트폴리오 우자 관리 시스템
+