레거시 스킨 API

예전 채팅방이 쓰는 레거시 스킨(basic)의 room.skin API — jQuery DOM, 메뉴바, 팝업, 닉네임 메뉴 — 목록과 기본 스킨으로 옮기는 대응표예요.

마지막 수정 2026년 10월 17일

이 페이지

레거시 스킨(basic, 관리 페이지에는 "레거시 스킨 (구버전)"으로 보임)은 예전 채팅방이 쓰는 스킨이에요. 새 채팅방은 기본 스킨(basic-v2)으로 만들어지며, 새 기능은 기본 스킨에만 더해져요. 이 문서는 아직 레거시 스킨을 쓰는 채팅방을 위한 room.skin 목록이에요. 기본 스킨의 API는 스킨 UI API를 보세요.

페이지 스크립트의 U.chat(), 이벤트, room.action, 채널(room.plugin), 서버 API는 두 스킨에서 같아요. 다른 것은 room.skin뿐이에요.

어느 스킨인지 확인

room.skin의 멤버는 스킨이 화면을 만든 뒤에 생기므로 after.create 안에서 확인해요.

U.chat('my-room').on('after.create', function (room) {
	if (room.skin.menubar) {
		// 레거시 스킨
	} else if (room.skin.menu) {
		// 기본 스킨
	}
});

userMenu는 두 스킨에 모두 있으므로 구별에 쓰지 마세요. 스킨은 관리 페이지 스킨 메뉴나 <u-chat skin="basic-v2"> 속성으로 바꿀 수 있어요. 회원 연동처럼 스킨과 상관없는 기능은 바꿔도 그대로 동작해요.

원칙

  • 레거시 스킨은 채팅방 iframe 안의 DOM을 jQuery(1.12)로 직접 다뤄요. 스킨 HTML 구조와 클래스 이름은 정해진 계약이 아니며, 고친 화면은 스킨이 바뀌면 깨질 수 있어요.
  • 등록은 모두 after.create 안에서 해요. 그 전에는 room.skin.arguments와 room.skin.messages만 있어요.
  • 유챗 로고와 정보 표시를 가리거나 지우지 마세요.

room.skin 목록

이름 설명
room.skin.arguments 스킨 설정값(관리 페이지 스킨 설정 + skin_arguments 속성 + 전역 Uchat_argument). 스킨이 색 기본값을 채워 넣어요
room.skin.messages 스킨 화면 문구(현재 언어)
room.skin.window 채팅방 iframe의 window. jQuery는 room.skin.window.$
room.skin.document 채팅방 iframe의 document
room.skin.dom 주요 영역의 jQuery 객체. 아래 dom
room.skin.menubar 입력창 아래 메뉴바. 아래 menubar
room.skin.popup 팝업(알림·확인·입력·선택). 아래 popup
room.skin.userMenu 닉네임을 누르면 나오는 메뉴. 아래 userMenu
room.skin.scrollDown(force) 대화를 맨 아래로 내려요. force가 참이 아니면 사용자가 위로 올려 둔 동안에는 내리지 않아요

dom

모두 채팅방 iframe 안 요소의 jQuery 객체예요.

키 영역
wrap 채팅방 전체(.wrap)
top 위쪽 제목 영역(.top)
middle 대화와 사용자 목록 영역(.middle)
content 대화 스크롤 영역(.contentWrap)
content_target 대화 줄이 붙는 요소(.content)
userList 사용자 목록 스크롤 영역(.userListWrap)
contour 사용자 목록과 대화 사이 구분선(.contour)
bottom 아래 입력 영역(.bottom)
inputContent 입력창(.inputContent)
menubar 메뉴바(.menuBar)
latest_chat 위로 스크롤했을 때 보이는 최근 대화 알림(.latest_chat)
setting, settingBG 설정 창과 그 배경(.settingContent, .settingBackground)
U.chat('my-room').on('after.create', function (room) {
	var $ = room.skin.window.$;
	var banner = $('<div/>').text('오늘 8시에 이벤트가 있습니다!').css({ padding: '6px', background: '#fff4cc' });
	room.skin.dom.middle.before(banner);
	$(room.skin.window).resize(); // 높이가 바뀌었으면 스킨이 다시 배치하게
});

요소를 더해 높이가 바뀌면 $(room.skin.window).resize()를 불러 스킨이 대화 영역 크기를 다시 계산하게 해요. 사용자 입력은 .text()로 넣고 .html()에 넣지 마세요.

입력창 아래 메뉴바에 버튼을 더해요.

U.chat('my-room').on('after.create', function (room) {
	room.skin.menubar.add({
		id: 'hello',
		title: '인사 보내기',
		html: '<div>인사</div>',
		condition: function (room, item) {
			return room.my.auth >= 1; // false면 보이지 않음
		},
		onClick: function (room, item) {
			room.action.send('안녕하세요!');
		},
	});
});
키 설명
id 필수. 겹치면 등록되지 않아요. 버튼에 menubar-아이디 클래스가 붙어요
title 마우스를 올렸을 때 설명
html 버튼 내용(HTML 문자열). 없으면 빈 <div>
icon 배경 이미지 주소
condition(room, item) 정확히 false를 돌려주면 그리지 않아요
onClick(room, item) 눌렀을 때. item.event가 클릭 이벤트예요
beforeLoad(room, item), afterLoad(room, item) 그리기 전후. beforeLoad가 false면 그리지 않아요
beforeUnload(), afterUnload() 지우기 전후

item은 add에 넘긴 객체 자신이며, 그려진 버튼의 jQuery 객체가 item.layout에 들어가요.

함수 설명
add(item) 등록해요. 성공하면 true, 아이디가 없거나 겹치면 false
refresh() 등록된 버튼을 condition에 따라 그려요
remove(id) 등록을 지워요
hide(), show(), toggle() 메뉴바 전체를 숨기기·보이기·바꾸기
list 등록된 항목 배열
  • add만으로는 화면에 나오지 않아요. 스킨이 입장할 때마다 refresh()를 부르므로 after.create에서 등록하면 입장할 때 보여요. 입장한 뒤에 등록했다면 room.skin.menubar.refresh()를 직접 부르세요.
  • condition은 refresh() 때만 다시 계산해요. 이미 그려진 버튼의 condition이 false가 되면 등록이 지워지고, 나중에 다시 참이 되어도 돌아오지 않아요. 권한에 따라 버튼을 숨겼다 보였다 해야 하면 condition 대신 afterLoad에서 받은 item.layout을 toggle()하세요.
  • remove(id)는 아이디가 숫자가 아니면 그려진 버튼을 화면에서 지우지 못해요. 버튼을 지울 때는 item.layout.remove()도 함께 부르세요.
  • 기본 버튼의 아이디는 scroll, bold, picture, call_admin 등이에요.

채팅방 안에 팝업을 띄워요. 팝업은 한 번에 하나만 보이고, 나머지는 순서대로 기다려요. 모든 함수가 팝업 번호를 돌려주며, close(번호)로 닫을 수 있어요. 결과는 Promise가 아니라 콜백으로 받아요.

var popup = room.skin.popup;

popup.confirm('가위바위보', '도전을 받을까요?', function (ok) {
	// 확인 true, 취소 false, 바깥을 눌러 닫으면 null
});

popup.prompt('닉네임', '새 닉네임을 적어 주세요.', '기본값', function (value) {
	// 입력한 글자, 취소하면 null
});

popup.select('선택', '하나를 고르세요.', { r: '바위', p: '보', s: '가위' }, function (key) {
	// 고른 키(문자열), 취소하면 null
});

var id = popup.alert('알림', '10초 뒤에 닫힙니다.');
setTimeout(function () { popup.close(id); }, 10000);
함수 콜백이 받는 값
alert(title, html, onOpen, onClose) onOpen(layer, pb, pu)은 열릴 때 불리고, 닫힐 때는 onClose()가 불려요. html은 HTML로 들어가므로 사용자 값은 이스케이프하세요
confirm(title, subtitle, fn) true, false, 바깥을 누르면 null
prompt(title, subtitle, value, fn) 입력한 글자, 취소하면 null
password(title, subtitle, value, fn) prompt와 같고 입력이 가려져요
select(title, subtitle, list, fn) list(객체 또는 배열)의 키, 취소하면 null
add(html, type, fn(layer, pb, pu), after) 직접 만든 팝업. layer는 { close(), centering() }, pb는 배경, pu는 팝업 본체(jQuery). after()는 닫힐 때
close([번호]) 그 팝업을 닫거나 대기열에서 빼요. 번호를 빼면 지금 보이는 팝업을 닫아요
closeByType(type) add에 준 type이 같은 팝업을 모두 닫아요
  • 입력 팝업에서 Enter를 누르면 확인과 같아요.
  • 브라우저 창이 포커스를 잃으면 지금 보이는 팝업이 바깥을 누른 것처럼 닫혀요(confirm·prompt·select는 null). 다른 창을 열고 돌아오는 흐름에서는 결과가 null일 수 있다고 보고 짜세요.

userMenu

닉네임을 누르면 나오는 메뉴에 항목을 더해요. 메뉴는 누를 때마다 새로 만들어지므로 condition이 매번 다시 계산돼요.

room.skin.userMenu.add({
	id: 'profile',
	text: '프로필 보기',
	condition: function (room, data) {
		return data.target !== room.my.nick; // 내 닉네임에는 숨김
	},
	onClick: function (room, data) {
		var user = room.user.get(data.target);
		if (user && user.id) window.open('/profile/' + encodeURIComponent(user.id));
	},
});
키 설명
id 필수. 겹치면 등록되지 않아요(false)
text 항목 글자
condition(room, data) 정확히 false를 돌려주면 숨겨요. data.target은 누른 닉네임 문자열이에요
onClick(room, data) 눌렀을 때. data는 { event, id, target, messageUid }
함수 설명
add(item) 항목 하나를 더해요
group(left, right) 두 항목을 한 줄에 나란히 둬요
hr([{ condition }]) 구분선. 아이디는 늘 hr이라 remove('hr')는 구분선을 모두 지워요
remove(id) 그 아이디의 항목을 모두 지워요(기본 항목 포함)
list 등록된 항목 배열

기본 항목의 아이디는 info, whisper, call, ignore, un_ignore, report, invite, individual, mute, unmute, ban, ip, op, deop, freeze, unfreeze, clearlog, removeChat, logout 등이에요. 기본 항목을 숨기려면 remove(id)를 부르세요. 메뉴를 숨겨도 권한 검사는 서버가 해요.

레거시 전용 이벤트

before.user.list, after.user.list(data는 { list })는 레거시 스킨이 사용자 목록을 열어 전체 목록을 받을 때 와요. 기본 스킨은 사용자 목록을 나눠 받으므로 이 이벤트가 오지 않아요. 나머지 이벤트는 이벤트와 같아요.

기본 스킨으로 옮기기

하는 일 레거시 스킨 기본 스킨
버튼 더하기 menubar.add({ id, title, html, condition(room, item), onClick(room, item) }) menu.add({ id, label, title, condition(ctx), onSelect(ctx) })
버튼 다시 계산 menubar.refresh() menu.resolver.refresh()
닉네임 메뉴 userMenu.add({ id, text, onClick(room, data) }), data.target은 닉네임 userMenu.add({ id, label, onSelect(ctx) }), ctx.target은 사용자 객체
기본 항목 숨기기 userMenu.remove('ignore') userMenu.resolver.add(...)로 skin.ignore 걸러 내기
팝업 popup.confirm(t, s, fn) 등 콜백 dialog.confirm(t, s) 등 Promise
화면에 영역 넣기 dom.middle.before(...) 등 DOM 직접 mount.messageList({ position: 'before', mount(host) }) 등
대화 위에 겹치기 dom.content.append(...) + CSS mount.overlay({ layer, scope, mount(host) })
닉네임·메시지 꾸미기 window.$로 <style> 넣기 nickname.resolver, message.resolver
맨 아래로 scrollDown(force) scrollToBottom(force)

기본 스킨에서는 스킨 DOM, jQuery, <style> 넣기를 지원하지 않아요. 옮긴 뒤의 사용법은 스킨 UI 확장하기부터 보세요.

봐도 잘 이해가 되지 않나요? 문의 게시판에 질문을 남겨 주세요.

상호 UCHAT · 대표 김경욱 · 사업자등록번호 141-05-32832
사업장소재지 경기도 파주시 와석순환로 61 · 통신판매업신고번호 2013-경기파주-4485호
대표번호 010-8677-8633 · 이메일 support@uchat.io

ⓒ 2013–2026 UCHAT. All rights reserved.