쏠브북스 로그인 회원가입 리뉴얼
🎨 로그인/회원가입 페이지 UX 리뉴얼: 이탈률 감소를 위한 6가지 핵심 개선
프로젝트 목표: UI/UX 개선을 통한 회원가입 이탈률 감소 및 사용자 편의성 향상
📊 프로젝트 배경
쏠브북스 서비스의 회원가입 과정에서 높은 이탈률이 발생하고 있었습니다. 사용자 행동 분석 결과, 불편한 UI/UX 요소들이 주요 원인으로 파악되어 6가지 핵심 영역을 중심으로 전면적인 개선 작업을 진행했습니다.
🎯 6가지 핵심 개선사항
1. 🏷️ 마지막 로그인 방식 기억 기능
❌ 기존 문제점
- 재방문 시 매번 로그인 방식을 선택해야 하는 불편함
- 사용자가 선호하는 로그인 방식을 기억하지 못함
- 로그인 시간 증가로 인한 사용자 피로도 상승
▲ 개선 전: 모든 로그인 버튼이 동일하게 표시됨
✅ 개선 방안
// localStorage 기반 마지막 로그인 방식 저장
export const useLastLoginMethod = () => {
const [lastLoginMethod, setLastLoginMethod] = useState<LoginMethod | null>(
null
);
const saveLastLoginMethod = (method: LoginMethod) => {
localStorage.setItem(LAST_LOGIN_METHOD_KEY, method);
setLastLoginMethod(method);
};
return { lastLoginMethod, saveLastLoginMethod };
};
// SNS 로그인 버튼에 "최근" 태그 표시
<SSOLoginButton
src={"/assets/png/login-google.png"}
alt={"구글 로그인"}
onClick={googleLogin}
isLastUsed={lastLoginMethod === "GOOGLE"}
/>;
▲ 개선 후: 구글 로그인 버튼에 “최근” 태그 표시
🎉 기대 효과:
- ✅ 재방문 시 로그인 방식 선택 시간 단축
- ✅ 로그아웃 후에도 정보 유지로 지속적 편의성 제공
- ✅ 직관적인 “최근” 태그로 사용자 가이드
2. 📐 회원가입 폼 크기 최적화
❌ 기존 문제점
- 필요한 입력 항목에 비해 폼이 시각적으로 과도하게 넓음
- 화면 공간 낭비로 인한 산만함
- 모바일/데스크톱에서 일관성 없는 레이아웃
✅ 개선 방안
/* 기존 - 과도하게 넓은 폼 */
.signup-form {
width: 100%;
max-width: 800px; /* 너무 넓음 */
}
/* 개선 - 적절한 크기로 조정 */
.signup-form {
width: 100%;
max-width: 400px; /* 최적화된 크기 */
margin: 0 auto;
}
/* 반응형 최적화 */
@media (min-width: 640px) {
.signup-form {
max-width: 448px; /* sm:max-w-md */
}
}
@media (min-width: 1024px) {
.signup-form {
max-width: 512px; /* lg:max-w-lg */
}
}
🎉 기대 효과:
- ✅ 집중도 향상으로 폼 완성 시간 단축 기대
- ✅ 모든 디바이스에서 일관된 사용자 경험
- ✅ 시각적 밀도 개선으로 전문성 향상
3. 🎯 약관 동의 클릭 영역 확장
❌ 기존 문제점
- 작은 체크박스만 클릭 가능하여 조작이 어려움
- 특히 모바일에서 터치 타겟이 너무 작음
- 약관 텍스트 클릭 시 반응 없어 사용자 혼란
✅ 개선 방안
// 기존 - 체크박스만 클릭 가능
<input type="checkbox" id={checkboxId} />
<label htmlFor={checkboxId}>약관 텍스트</label>
// 개선 - 전체 영역 클릭 가능
<label htmlFor={checkboxId} className="cursor-pointer flex items-center gap-3 p-4 hover:bg-blue-50 transition-colors">
<input
type="checkbox"
id={checkboxId}
className="sr-only"
onChange={handleChange}
/>
{/* 커스텀 체크박스 UI */}
<div className={`w-5 h-5 rounded border-2 ${isChecked ? 'bg-blue-600 border-blue-600' : 'border-gray-300'}`}>
{isChecked && <CheckIcon />}
</div>
<span className="text-sm text-gray-700 flex-1">
약관 텍스트 전체가 클릭 가능
</span>
</label>
🎉 기대 효과:
- ✅ 클릭 성공률 향상 기대
- ✅ 모바일 사용성 대폭 개선
- ✅ 직관적인 상호작용으로 사용자 만족도 상승
4. 📁 선택 약관 접기/펼치기 기능
❌ 기존 문제점
- 모든 약관이 한 번에 노출되어 화면이 복잡함
- 필수/선택 약관의 구분이 어려움
- 긴 약관 리스트로 인한 시각적 피로도 증가
✅ 개선 방안
// 접기/펼치기 상태 관리
const [isMarketingExpanded, setIsMarketingExpanded] = useState(false);
// 스마트한 자동 펼치기 로직
const handleMarketingClick = (checked: boolean) => {
setMarketingValueAll(checked);
if (checked) {
setIsMarketingExpanded(true); // 체크 시 자동 펼치기
}
};
// UI 구현
<div className="border-b border-gray-200">
<div
className="flex items-center justify-between p-4 hover:bg-blue-50 transition-colors cursor-pointer"
onClick={() => setIsMarketingExpanded(!isMarketingExpanded)}
>
<label className="flex items-center gap-3 cursor-pointer flex-1">
{/* 마케팅 동의 체크박스 */}
</label>
{/* 화살표 아이콘 */}
<div
className={`transition-transform duration-200 ${
isMarketingExpanded ? "rotate-90" : ""
}`}
>
<ArrowRightIcon />
</div>
</div>
{/* 접기/펼치기 애니메이션 */}
<div
className={`bg-gray-50 overflow-hidden transition-all duration-300 ease-in-out ${
isMarketingExpanded ? "max-h-96 opacity-100" : "max-h-0 opacity-0"
}`}
>
{/* 세부 마케팅 약관들 (SMS, 푸시, 이메일) */}
</div>
</div>;
🎉 기대 효과:
- ✅ 화면 복잡도 대폭 감소
- ✅ 약관 동의 완료율 향상 기대
- ✅ 필요한 정보만 선택적 노출로 인지 부담 감소
5. ✅ 휴대폰 인증 완료 상태 표시
❌ 기존 문제점
- 인증 완료 후 명확한 피드백 부족
- 사용자가 인증 성공 여부를 확신하지 못함
- 불안감으로 인한 재인증 시도나 이탈 발생
✅ 개선 방안
// 조건부 렌더링으로 인증 상태 표시
<If
condition={!isMobileNumberAccess}
Component={
// 인증 진행 중 UI
<Stack direction="column" gap={16}>
<MobileNumberFormItem {...props} />
<AuthCodeFormItem {...props} />
</Stack>
}
ElseComponent={
// 인증 완료 UI
<div className="flex items-center gap-2 py-3 px-4 bg-green-50 rounded-lg border border-green-200">
<svg
className="w-5 h-5 text-green-600"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span className="text-sm font-medium text-green-800">
휴대폰 인증 완료
</span>
</div>
}
/>
▲ 개선 전: 휴대폰 인증 진행 중 상태
▲ 개선 후: 명확한 “휴대폰 인증 완료” 상태 표시
🎉 기대 효과:
- ✅ 인증 재시도율 감소 기대
- ✅ 명확한 성공 피드백으로 사용자 안심
- ✅ 다음 단계 진행에 대한 확신 제공
6. 🔄 로그인/회원가입 영역 명확한 구분
❌ 기존 문제점
- 로그인과 회원가입 영역이 시각적으로 구분되지 않음
- 사용자가 현재 어떤 과정에 있는지 혼란
- 잘못된 페이지 접근으로 인한 추가적인 네비게이션 필요
✅ 개선 방안
// 탭 기반 네비게이션으로 명확한 구분
const SigninPage = () => {
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50">
{/* 헤더 영역 - 현재 위치 명시 */}
<div className="text-center mb-8">
<h1 className="text-2xl font-bold text-gray-900 mb-2">로그인</h1>
<p className="text-gray-600">계정에 로그인하세요</p>
</div>
{/* 로그인 폼 영역 */}
<div className="bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl p-8">
{/* 로그인 컨텐츠 */}
</div>
{/* 회원가입 링크 - 명확한 구분 */}
<div className="mt-6 text-center">
<p className="text-gray-600 text-sm mb-3">아직 계정이 없으신가요?</p>
<button className="text-blue-500 hover:text-blue-700 font-semibold transition-all">
회원가입하기 →
</button>
</div>
</div>
);
};
const SignupPage = () => {
return (
<div className="min-h-screen bg-gradient-to-br from-purple-50 via-blue-50 to-indigo-50">
{/* 헤더 영역 - 가치 중심 메시지 */}
<div className="text-center mb-8">
<h1 className="text-2xl font-bold text-gray-900 mb-2">
지금 가입하고 바로{" "}
<span className="text-blue-600">무료 기출문제</span> 풀어보기
</h1>
</div>
{/* 회원가입 폼 영역 */}
<div className="bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl p-8">
{/* 회원가입 컨텐츠 */}
</div>
</div>
);
};
🎉 기대 효과:
- ✅ 사용자 혼란 대폭 감소
- ✅ 잘못된 페이지 접근률 감소
- ✅ 각 페이지별 명확한 목적 전달
📈 전체 개선 결과
🖼️ Before & After 비교
🔐 로그인 페이지
▲ 마지막 로그인 방식 기억 기능으로 재방문 편의성 향상
📝 회원가입 페이지
▲ 폼 최적화, 인증 완료 표시, 약관 접기/펼치기 등 종합적 UX 개선
📊 주요 개선사항 요약
개선 영역 | 구현 완료 | 기대 효과 |
---|---|---|
마지막 로그인 기억 | ✅ | 재방문 로그인 편의성 향상 |
폼 크기 최적화 | ✅ | 집중도 향상 및 완성도 개선 |
클릭 영역 확장 | ✅ | 터치 조작 편의성 향상 |
약관 접기/펼치기 | ✅ | 시각적 복잡도 감소 |
인증 완료 표시 | ✅ | 명확한 상태 피드백 제공 |
영역 구분 개선 | ✅ | 사용자 혼란 감소 |
💭 개선 후 기대되는 사용자 반응
- 클릭 영역 확장: 모바일에서 약관 동의 시 터치 조작이 더 쉬워질 것으로 예상
- 인증 완료 표시: 휴대폰 인증 후 명확한 피드백으로 사용자 불안감 해소 기대
- 마지막 로그인 기억: 재방문 사용자의 로그인 편의성 대폭 향상 예상
- 약관 접기/펼치기: 초기 화면 복잡도 감소로 가입 의지 향상 기대
🛠 기술적 구현 하이라이트
1. localStorage 활용한 사용자 기억 기능
// 브라우저 세션 유지와 관계없이 사용자 편의성 제공
const LAST_LOGIN_METHOD_KEY = "solve-books-last-login-method";
export const useLastLoginMethod = () => {
const [lastLoginMethod, setLastLoginMethod] = useState<LoginMethod | null>(
null
);
useEffect(() => {
const stored = localStorage.getItem(LAST_LOGIN_METHOD_KEY);
if (stored) setLastLoginMethod(stored as LoginMethod);
}, []);
const saveLastLoginMethod = (method: LoginMethod) => {
localStorage.setItem(LAST_LOGIN_METHOD_KEY, method);
setLastLoginMethod(method);
};
return { lastLoginMethod, saveLastLoginMethod };
};
2. 접근성을 고려한 커스텀 체크박스
// 스크린 리더와 키보드 네비게이션 완전 지원
<label
htmlFor={uniqueId}
className="cursor-pointer hover:bg-blue-50 transition-colors"
>
<input
type="checkbox"
id={uniqueId}
className="sr-only" // 시각적으로 숨김, 스크린 리더에서는 접근 가능
checked={isChecked}
onChange={handleChange}
/>
{/* 커스텀 UI */}
</label>
3. 반응형 애니메이션
/* 부드러운 접기/펼치기 애니메이션 */
.collapsible-content {
overflow: hidden;
transition: all 0.3s ease-in-out;
}
.expanded {
max-height: 24rem; /* max-h-96 */
opacity: 1;
}
.collapsed {
max-height: 0;
opacity: 0;
}
💡 핵심 인사이트
🎯 1. 사용자 중심 사고의 중요성
- 발견: 개발자가 생각하는 “논리적 구조”와 사용자가 느끼는 “직관적 구조”는 다름
- 적용: 기능 단위가 아닌 사용자 작업 단위로 UI 그룹화
- 결과: 인지 부담 감소로 완료율 향상
🔍 2. 미세한 상호작용의 큰 영향
- 발견: 클릭 영역 확장 같은 작은 개선이 큰 사용성 향상을 가져옴
- 적용: 터치 타겟 최소 44px, 호버 효과, 트랜지션 추가
- 결과: 모바일 사용성 대폭 개선
📊 3. 점진적 정보 공개의 효과
- 발견: 한 번에 많은 정보를 보여주면 사용자가 압도당함
- 적용: 접기/펼치기, 단계별 정보 공개
- 결과: 완료율 상승과 이탈률 감소
🎨 4. 시각적 피드백의 필수성
- 발견: 사용자는 자신의 행동에 대한 명확한 결과를 원함
- 적용: 상태별 시각적 구분, 성공/실패 피드백
- 결과: 사용자 안정감 증가, 재시도 감소
📚 참고 자료
- Apple Human Interface Guidelines - Touch Targets
- Material Design - Accessibility
- Nielsen Norman Group - Form Design
- Web Content Accessibility Guidelines 2.1
💻 기술 스택: React 18 + Next.js 15 + TypeScript + TailwindCSS + React Hook Form
📅 프로젝트 기간: 2025년 7월
🎯 핵심 성과: 6가지 UX 개선사항 구현 완료, 사용자 편의성 향상
👥 팀 구성: Frontend Developer 1명 (개인 프로젝트)