키워드
재사용성, 깔끔한 UI, 네이밍 룰
아래는 회원가입에 필요한 페이지를 figma로 작업한 사진 입니다.
회원가입 페이지
회원 가입에 필요한 페이지로 이메일과 비밀번호를 input으로 받고 있습니다.
html
<div class="user-main-window">
<div class="user-logo">
<img src="../image/logo.png" alt="logo">
</div>
<div class="user-input-field">
<div class="user-input-field-inner-group">
<label for="input-email">이메일</label>
<input type="email" name="email" id="input-email" />
<span class="user-input-field-inner-info">잘못된 형식입니다</span>
</div>
<div class="user-input-field-inner-group">
<label for="input-pwd">비밀번호</label>
<input type="password" name="pwd" id="input-pwd" />
<span class="user-input-field-inner-info hidden"></span>
</div>
<div class="user-input-field-inner-group">
<label for="input-pwd2">비밀번호 확인</label>
<input type="password" name="pwd2" id="input-pwd2" />
<span class="user-input-field-inner-info hidden">비밀번호가 일치하지 않습니다.</span>
</div>
</div>
<div class="user-btn-group">
<button class="user-btn-group-inner">회원가입</button>
</div>
</div>
css
.user-main-window {
max-width: var(--user-main-window-max-width);
margin : auto;
padding : var(--user-main-window-padding);
display : flex;
flex-direction: column;
border : var(--default-border);
border-radius: var(--default-border-radius);
}
.user-logo {
text-align: center;
}
.user-logo > img{
max-width: var(--user-logo-width);
}
.user-input-field {
display: flex;
flex-direction: column;
}
.user-input-field-inner-group {
display: flex;
flex-direction: column;
}
.user-input-field-inner-group:not(:last-child) {
margin-bottom: var(--user-input-field-margin-bottom);
}
.user-input-field-inner-group > *:not(:last-child) {
margin-bottom: var(--user-input-field-inner-margin-bottom);
}
.user-input-field-inner-group > label {
font-size: var(--user-input-field-label-font-size);
}
.user-input-field-inner-info {
font-size: var(--default-font-size-small);
color: var(--red-color);
}
.user-btn-group {
margin-top: var(--user-btn-group-margin-top);
}
button.user-btn-group-inner {
width : 100%;
}
.user-signup-a {
padding: var(--default-padding);
text-align: right;
font-size: var(--default-font-size-small);
color: var(--red-color);
}
HTMLElement의 class 이름을 작성하는데 부모 element를 prefix를 가지는 convention을 가지고 구현하였습니다. 또한 스네이크 케이스에서 MDN에서 _ 대신 - 를 장려하여 -를 사용하여 네이밍을 했습니다.
해당 HTML과 CSS를 확인했으니 JavaScript로 노드를 만들어서 구현하였습니다.
scripts/user/signView.js
function SignView() {
this.body = this.getElement('body');
this.userMainWindow = this.createElement('div', 'user-main-window');
this.userLogo = this.createElement('div', 'user-logo');
this.userLogoImg = this.createElement('img');
this.userLogoImg.setAttribute('src', '../image/logo.png');
this.userLogoImg.setAttribute('alt', 'logo');
this.userLogo.appendChild(this.userLogoImg);
this.userInputField = this.createElement('div', 'user-input-field');
this.userInputFieldGroup = [];
this.userBtnGroup = this.createElement('div', 'user-btn-group');
this.userBtnGroupInner = this.createElement('button', 'user-btn-group-inner');
this.userBtnGroupInner.setAttribute('data-testid', 'test-btn');
this.userBtnGroupInner.setAttribute('disabled', '');
this.userBtnGroup.appendChild(this.userBtnGroupInner);
this.appendChildList(this.userMainWindow, [
this.userLogo,
this.userInputField,
this.userBtnGroup,
]);
this.body.appendChild(this.userMainWindow);
}
SignView.prototype.createElement = function (tag, ...classNameList) {
const element = document.createElement(tag);
classNameList = null ?? classNameList;
classNameList.forEach((className) => {
element.classList.add(className);
});
return element;
};
SignView.prototype.getElement = function (selector) {
const element = document.querySelector(selector);
return element;
};
SignView.prototype.appendChildList = function (parent, childList) {
childList = null ?? childList;
childList.forEach((child) => {
parent.appendChild(child);
});
};
위의 HTML를 JavaScript에서 DOM을 조작하며 만들었습니다.
element의 네이밍은 스네이크 케이스로 되어있는 class를 카멜 케이스로 바꾸었습니다.
Document.createElement() 함수와 class이름을 설정하는 코드는 빈번히 사용하여 SignView 함수 객체의 prototype에 createElement()를 추가하였습니다.
userMainWindow라는 container를 먼저 완성 후 body element의 자식노드에 추가하여 repaint, rerendering이 한번만 일어나게 하여 성능을 올렸습니다.
SignUpView가 아닌 SignView로 네이밍을 한 이유는 로그인 페이지에서 해당 컴포넌트를 재사용하기 위해서 입니다.