[Nexacro N] 세션과 로그인
Nexacro N 애플리케이션에서 로그인 화면 구현, 세션 기반 인증 흐름, 사용자 정보 전역 저장 패턴을 설명합니다. transaction 콜백에서 인증 결과를 처리하고 application 변수로 세션 정보를 전파하는 방법을 다룹니다.
지난 글에서 대시보드를 구성하는 방법을 살펴보았다. 이번에는 모든 업무 시스템의 시작점인 로그인 화면과 세션 기반 인증 흐름을 다룬다. Nexacro N 자체는 인증 로직을 제공하지 않으므로, 서버의 세션 관리와 클라이언트의 상태 저장을 직접 설계해야 한다.
로그인 흐름 전체
Nexacro 클라이언트는 ID/PW를 Dataset에 담아 로그인 서비스로 트랜잭션을 보낸다. 서버는 자격 증명을 검증하고, 성공 시 HttpSession에 사용자 정보를 저장하고 사용자 정보 Dataset을 응답으로 내려준다. 클라이언트는 이 정보를 application 전역 변수에 보관하고 메인 화면으로 이동한다.
로그인 폼 구성
로그인 폼에는 Edit 두 개(아이디, 비밀번호)와 로그인 버튼이 있으며, 비밀번호 Edit은 type=password로 설정한다. Dataset(ds_login)에는 USER_ID, PASSWORD 컬럼을 정의한다.
// 비밀번호 Edit 설정
edt_pw.set_type("password");
edt_pw.set_maxlength(20);
// Enter 키 로그인 처리
function edt_pw_onkeyup(obj, e) {
if (e.keycode === 13) { // Enter
btn_login_onclick(null, null);
}
}
로그인 트랜잭션
입력값 검증 후 트랜잭션을 발행한다. 비밀번호는 서버에서 암호화해 비교하므로 클라이언트에서는 평문을 그대로 전송하되, TLS 통신이 전제되어야 한다.
function fn_loginCallback(sId, nErrorCode, sErrorMsg) {
if (nErrorCode < 0) {
alert("로그인에 실패했습니다: " + sErrorMsg);
edt_pw.setFocus();
return;
}
if (ds_userInfo.rowcount === 0) {
alert("아이디 또는 비밀번호가 올바르지 않습니다.");
edt_pw.setFocus();
return;
}
// 사용자 정보를 application 전역 변수에 저장
application.gv_userId = ds_userInfo.getColumn(0, "USER_ID");
application.gv_userName = ds_userInfo.getColumn(0, "USER_NM");
application.gv_roleCode = ds_userInfo.getColumn(0, "ROLE_CD");
// 메인 화면으로 이동
application.mainframe.changeForm("FrmMain::main/FrmMain.xfdl");
}
nErrorCode < 0는 네트워크 오류나 서버 500 에러다. rowcount === 0은 서버가 정상 응답했지만 인증에 실패한 경우다. 두 경우를 구분해 메시지를 다르게 보여주면 사용자가 원인을 파악하는 데 도움이 된다.
application 전역 변수 활용
application 객체에 세팅한 변수는 모든 폼에서 접근할 수 있다. 사용자 ID, 이름, 권한 코드를 여기에 저장해두면 화면마다 다시 조회할 필요가 없다.
// 어느 폼에서든 접근 가능
var userName = application.gv_userName;
var role = application.gv_roleCode;
// 권한별 버튼 노출 제어
if (role !== "ADMIN") {
btn_delete.set_visible(false);
}
application 변수는 세션과 동일한 생명주기를 가진다. 브라우저 새로고침 시 초기화되므로, 새로고침 후 로그인 상태를 복원하려면 쿠키나 서버 세션 확인 로직이 필요하다.
서버 세션 확인 (재접속 처리)
애플리케이션이 시작될 때 서버에 세션 유효성을 확인하는 패턴을 사용하면, 이미 로그인된 사용자는 로그인 화면을 건너뛰고 메인으로 바로 진입할 수 있다.
// application.xadl 또는 초기 폼 onload에서
function fn_checkSession() {
this.transaction(
"svcCheckSession",
"/api/session/check",
"",
"out:ds_sessionUser=USERINFO",
"",
"fn_checkSessionCallback"
);
}
function fn_checkSessionCallback(sId, nErrorCode, sErrorMsg) {
if (nErrorCode >= 0 && ds_sessionUser.rowcount > 0) {
// 세션 유효 → application 변수 복원 후 메인으로
application.gv_userId = ds_sessionUser.getColumn(0, "USER_ID");
application.mainframe.changeForm("FrmMain::main/FrmMain.xfdl");
} else {
// 세션 없음 → 로그인 화면 표시
application.mainframe.changeForm("FrmLogin::login/FrmLogin.xfdl");
}
}
로그아웃 처리
로그아웃 시 서버 세션을 무효화하고 application 변수를 초기화한 뒤 로그인 화면으로 이동한다.
function fn_logout() {
this.transaction(
"svcLogout",
"/api/logout",
"", "", "",
"fn_logoutCallback"
);
}
function fn_logoutCallback(sId, nErrorCode, sErrorMsg) {
// 에러 여부와 무관하게 클라이언트 정리
application.gv_userId = "";
application.gv_userName = "";
application.gv_roleCode = "";
application.mainframe.changeForm("FrmLogin::login/FrmLogin.xfdl");
}
서버 로그아웃 요청이 실패하더라도 클라이언트는 로그인 화면으로 이동시켜야 한다. 네트워크 오류로 서버 세션이 남더라도 세션 타임아웃으로 자연 소멸된다.
지난 글: 대시보드 구성
다음 글: 세션 타임아웃 처리
읽어주셔서 감사합니다. 😊