import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import kotlinx.coroutines.launch import network.KisAuthService import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction import androidx.compose.runtime.* import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import model.AppConfig import network.LlamaServerManager import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction import ui.DashboardScreen import ui.SettingsScreen // 화면 상태 정의 enum class AppScreen { Settings, Dashboard } fun main() = application { // 앱 경로 기준 리소스 위치 설정 val binPath = "./src/main/resources/bin/llama-server" val modelPath = "./src/main/resources/models/gemma-2-9b-it-Q4_K_M.gguf" LaunchedEffect(Unit) { LlamaServerManager.startServer(binPath, modelPath) } Window(onCloseRequest = ::exitApplication, title = "KIS AI 자동매매") { var currentScreen by remember { mutableStateOf(AppScreen.Settings) } // 1. 초기 상태를 null로 두어 로딩 전임을 표시 var savedConfig by remember { mutableStateOf(null) } var token by remember { mutableStateOf("") } var selectedStockCode by remember { mutableStateOf(null) } // 앱 시작 시 DB에서 마지막 설정 로드 LaunchedEffect(Unit) { DatabaseFactory.init() val loaded = transaction { ConfigTable.selectAll().lastOrNull()?.let { AppConfig( appKey = it[ConfigTable.appKey], secretKey = it[ConfigTable.secretKey], accountNo = it[ConfigTable.accountNo], isSimulation = it[ConfigTable.isSimulation], modelPath = it[ConfigTable.modelPath] ) } } // 로드된 값이 있으면 업데이트, 없으면 기본 객체 생성 savedConfig = loaded ?: AppConfig() } // savedConfig가 로드될 때까지 기다림 (깜빡임 방지 및 데이터 보장) if (savedConfig == null) { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } else { when (currentScreen) { AppScreen.Settings -> { SettingsScreen( initialConfig = savedConfig!!, // !! 사용하여 null 아님을 보장 onAuthSuccess = { config, accessToken -> savedConfig = config token = accessToken currentScreen = AppScreen.Dashboard } ) } AppScreen.Dashboard -> { DashboardScreen(config = savedConfig!!, token = token) } } } } }