G7 소셜 TOTP 인증 로그인 - Glitter Social Login TOTP
Gnuboard7용 OAuth 소셜 로그인 5종에 필수 TOTP 2차 인증을 결합하여 회원가입부터 로그인·계정 연결·복구까지 안전하게 관리하는 독립 보안 플러그인
TOTP란 무엇인가?
TOTP, Time-based One-Time Password는 일정한 시간마다 새로운 인증번호를 생성하는 시간 기반 일회용 비밀번호입니다.
일반적으로 스마트폰의 인증 앱에서 6자리 숫자를 생성하며,
대부분의 서비스에서는 30초마다 새로운 인증번호로 변경됩니다.
인증번호의 자릿수와 갱신 주기는 서비스 설정에 따라 달라질 수 있습니다.
Google Authenticator, Microsoft Authenticator, 2FAS, Aegis Authenticator 등
대표적인 TOTP 인증 앱에서 사용하는 국제 표준 기술(RFC 6238)입니다.
소셜 로그인에 TOTP가 왜 필요한가요?
일반적인 소셜 로그인은 네이버·카카오·구글 등의 계정 인증에 성공하면 로그인이 완료됩니다.
반면 Glitter Social Login TOTP는 소셜 계정 인증에 성공하더라도 추가로 TOTP 인증번호를 입력해야 최종 로그인이 완료됩니다.
소셜 계정 인증 → TOTP 인증 → 로그인 완료
따라서 소셜 계정이 탈취되더라도 별도로 등록한 TOTP 인증 수단이 없다면 최종 로그인을 완료하기 어렵습니다.
별도의 인증 앱이 필요한가요?
네. 최초 사용 시 스마트폰 등에 TOTP 인증 앱을 설치하고 사이트에서 제공하는 등록 정보를 인증 앱에 추가해야 합니다.
이후 로그인할 때마다 인증 앱에 표시되는 6자리 일회용 인증번호를 입력하면 됩니다.
특정 인증 앱만 사용해야 하는 것은 아니며, 표준 TOTP를 지원하는 다양한 인증 앱을 사용할 수 있습니다.
TOTP 인증번호는 앱에서 자체적으로 생성하므로 일반적으로 SMS 수신이나 인터넷 연결 없이도 확인할 수 있습니다.
단, TOTP는 피싱에 완전히 안전한 방식은 아니며, 인증번호를 타인에게 알려주거나 의심스러운 사이트에 입력하지 않도록 주의해야 합니다.
Glitter Social Login TOTP · v1.0.8 · Glitter.kr · MIT
저장소: https://github.com/glitter-node/glitter-social_login_totp
릴리스 태그: https://github.com/glitter-node/glitter-social_login_totp/tree/v1.0.8
검증 상태: 수동 브라우저 인증 테스트 통과 — 운영자가 실제 브라우저에서 인증 관련 테스트를 수동·육안으로 모두 통과했다고 확인했습니다. 별도 Gnuboard7 테스트 환경에서
vendor/를 제외한 번들 기반 실제 설치 및 PHP 의존성 로딩도 통과했습니다. 자동화된 전체 회귀 테스트와 보안 침투 테스트를 완료했다는 의미는 아닙니다.
소개
Glitter Social Login TOTP는 Gnuboard7에 다섯 가지 OAuth Provider를 통합하고, 소셜 로그인만으로 인증을 완료하지 않고 시간 기반 일회용 비밀번호(TOTP) 확인을 필수로 요구하는 독립 플러그인입니다.
일반적인 소셜 로그인 버튼 제공을 넘어 신규 소셜 회원가입의 TOTP 등록, 기존 소셜 회원의 TOTP 인증, 명시적인 소셜 계정 연결·해제, 복구와 관리자 전환 정책을 하나의 인증 흐름으로 구성합니다.
기존 Glitter Social Login과 별개의 플러그인으로 개발되었으며, 플러그인 식별자와 설정·라우트·세션·캐시·로그·데이터베이스 테이블을 분리합니다. 기존 플러그인을 수정하거나 해당 플러그인의 데이터 테이블에 의존하지 않습니다.
기존 Glitter Social Login과의 차이
Glitter Social Login은 OAuth 기반 로그인 편의성과 기존 회원 계정 연동을 중심으로 설계된 플러그인입니다.
반면 Glitter Social Login TOTP는 OAuth 인증 이후 TOTP 추가 인증을 필수로 요구하고, 이메일 일치에 따른 기존 회원 자동 연결을 허용하지 않는 보안 중심의 독립 플러그인입니다.
두 플러그인은 동일한 5개 OAuth Provider를 지원하지만 인증 완료 조건과 계정 연결 정책이 다릅니다.
| 구분 | Glitter Social Login | Glitter Social Login TOTP |
|---|---|---|
| OAuth Provider | 5종 | 5종 |
| 로그인 추가 인증 | 코어 인증 정책과 연계 | 독립 TOTP 필수 |
| 신규 가입 TOTP 등록 | 필수 아님 | 필수 |
| 기존 회원 이메일 자동 연결 | Provider별 조건부 허용 | 허용하지 않음 |
| 소셜 계정 연결·해제 | 지원 | 지원 |
| TOTP 복구·관리자 전환 | 제공하지 않음 | 전용 정책 제공 |
Glitter Social Login TOTP는 기존 플러그인의 설정을 변경하여 TOTP를 활성화하는 방식이 아니라, 별도의 인증 정책과 데이터 구조를 가진 독립 플러그인입니다.
v1.0.8에서 달라진 점
외부 QR 생성 서비스 없이 TOTP 등록
신규 소셜 회원가입의 TOTP 등록 단계에서 Bacon QR Code 3.1.1 기반의 로컬 QR 코드 생성을 지원합니다. QR 코드 이미지를 외부 생성 서비스에 전송하지 않고 서버에서 생성하도록 구성했으며, QR 표시가 어려운 환경에서는 수동 등록키 입력을 대체 경로로 제공합니다.
- QR 렌더링 실패 시 예외 메시지 전체 대신 예외 클래스와 고정 오류 코드만 기록하도록 개선했습니다.
- 수동 등록키 복사 버튼에서 의도하지 않은 폼 제출과 이벤트 중복 등록을 방지했습니다.
- Gnuboard7 공식 플러그인 자산 등록 방식으로 JavaScript를 로딩하고, 빌드된
dist/자산을 배포합니다. - QR 생성에 필요한 PHP 의존성을
vendor-bundle.zip에 포함했습니다.
OAuth 및 TOTP 설정 안정성
- 플러그인에서 사용하는 Socialite/Guzzle HTTP 연결 제한 시간 10초, 요청 제한 시간 15초를 설정했습니다.
- TOTP 전환 정책의 기본 설정을 동기화하고, 해당 설정을 백엔드 전용으로 유지했습니다.
- 로그인·가입 단계에서 소셜 인증 및 TOTP 입력 UI가 일반 폼보다 먼저 표시되도록 레이아웃 배치를 개선했습니다.
QR 이미지 표시 및 인증 앱을 이용한 등록을 포함한 브라우저 인증 테스트는 운영자가 수동·육안으로 통과했다고 확인했습니다.
주요 기능
- OAuth Provider 5종: Naver, Kakao, Google, Facebook, GitHub
- 신규 가입 TOTP 등록 필수: TOTP 검증이 끝나기 전에는 신규 소셜 회원가입을 완료하지 않음
- 기존 로그인 TOTP 인증 필수: 추가 인증 성공 이후에만 최종 로그인 토큰 발급
- 독립적인 TOTP 정책: Gnuboard7 코어의
security.two_factor_auth설정과 무관하게 적용 - 명시적인 계정 연결: 이메일 일치만으로 기존 회원 계정에 자동 연결하지 않음
- 소셜 계정 관리: 인증된 회원의 명시적 연결·해제 흐름 제공
- TOTP 복구: 이메일만으로 끝나지 않는 본인확인, 관리자 승인 및 일회성 복구 권한 사용
- 관리자 전환 제어: 대상 명부, 기간, 마감 시각, 바인딩, 권한 및 긴급 중지 정책
- 한국어·영어 UI: 로그인, 가입, 프로필 및 관리자 관련 번역 리소스
- 로컬 QR 등록: TOTP 등록 QR 코드 생성과 수동 등록키 복사·대체 등록 경로
지원 OAuth Provider
| Provider | OAuth 로그인·가입 흐름 | 필수 TOTP | 명시적 연결·해제 |
|---|---|---|---|
| Naver | 지원 | 적용 | 지원 |
| Kakao | 지원 | 적용 | 지원 |
| 지원 | 적용 | 지원 | |
| 지원 | 적용 | 지원 | |
| GitHub | 지원 | 적용 | 지원 |
소셜 계정의 식별 기준은 이메일이 아닌 (provider, provider_user_id) 조합입니다. 동일한 이메일 주소를 사용하더라도 서로 다른 Provider identity는 자동으로 같은 회원 계정에 연결되지 않습니다.
로그인과 신규 회원가입
기존 소셜 회원 로그인
- 사용자가 Provider를 선택하고 OAuth 인증을 진행합니다.
- OAuth state와 브라우저 바인딩을 검증합니다.
(provider, provider_user_id)에 연결된 기존 회원을 확인합니다.- 회원 상태와 추가 인증 조건을 확인한 후 TOTP 인증을 요구합니다.
- TOTP 검증에 성공한 경우에만 최종 인증 교환을 통해 로그인 토큰을 발급합니다.
OAuth 인증 성공 자체가 최종 로그인 성공을 의미하지 않습니다.
기존 소셜 회원의 로그인은 OAuth 인증과 TOTP 인증이 모두 완료되어야 성립합니다.
OAuth 인증만 성공한 상태에서는 최종 로그인 토큰을 발급하지 않는 정책입니다.
신규 소셜 회원가입
- OAuth 인증으로 Provider identity를 확인합니다.
- 연결된 회원이 없다면 신규 가입 흐름을 진행합니다.
- 가입에 필요한 회원 정보와 동의 사항을 확인합니다.
- 인증 앱에 TOTP를 등록하고 발급된 코드를 검증합니다.
- 검증 완료 후 회원·소셜 계정·TOTP 정보를 트랜잭션으로 생성합니다.
신규 회원가입에서는 TOTP 등록과 최초 인증번호 검증이 회원 생성의 필수 선행 조건입니다.
따라서 TOTP 등록을 완료하지 않은 상태에서는 소셜 회원가입을 완료하지 않습니다.
Provider 이메일은 신규 가입에 필요한 입력 조건으로 사용할 수 있지만, 기존 회원을 이메일만으로 자동 검색·연결하는 근거로 사용하지 않습니다.
이메일 자동 연결 금지 정책
Glitter Social Login TOTP에서는 Provider가 검증된 이메일을 반환하더라도 해당 이메일과 일치하는 기존 Gnuboard7 회원을 자동으로 연결하지 않습니다.
기존 회원의 소셜 계정 추가 연결은 인증된 회원이 직접 시작한 명시적 연결 절차를 통해서만 수행합니다. 동일한 Provider identity가 다른 회원에게 이미 연결된 경우에는 중복 연결을 허용하지 않습니다.
이는 기존 Glitter Social Login의 Provider별 조건부 이메일 자동 매칭 정책과 구별되는 중요한 보안 정책입니다.
TOTP 인증 정책
TOTP는 인증 앱에서 생성되는 시간 기반 일회용 코드를 이용합니다.
플러그인은 TOTP 등록과 검증을 자체적으로 관리하며
Gnuboard7의 전역 2FA 활성화 여부에 의존하지 않습니다.
현재 구현의 주요 보호 조건은 다음과 같습니다.
| 항목 | 정책 |
|---|---|
| 인증 코드 재사용 | 이미 사용한 카운터 이하의 코드 거부 |
| TOTP 인증 실패 제한 | 5회 |
| 인증 실패에 따른 잠금 시간 | 15분 |
| TOTP 등록·인증 대기 유효시간 | 300초 |
| TOTP 비밀키 | Laravel 암호화 경로 사용 |
| 최종 로그인 토큰 | TOTP 검증 및 challenge 조건 확인 후 발급 |
인증 실패 제한과 임시 잠금은 TOTP 인증 시도에 대한 보호 정책입니다.
인증 코드 재사용 방지는 이미 사용한 시간 카운터를 기준으로 적용합니다.
TOTP는 계정 보안을 강화하지만 피싱에 완전히 저항하는 인증 수단은 아닙니다.
OAuth + Passkey(WebAuthn) 지원은 현재 포함되지 않으며
추후 확장 검토 대상으로 남겨 두었습니다.
로그인 완료와 일회용 Exchange
OAuth callback 이후 최종 bearer token을 URL query로 직접 전달하지 않습니다. 대신 짧은 수명의 일회용 exchange code를 사용합니다.
- 유효시간: 60초
- 원본 코드 대신 SHA-256 hash 저장
- OAuth를 시작한 브라우저의 session 및 암호화된 HttpOnly cookie와 결합
- 미사용·미만료 코드만 조건부 1회 소비
- 추가 인증 검증 시각 및 challenge hash를 확인한 뒤 최종 토큰 발급
OAuth state 검증과 최종 exchange 검증은 서로 다른 보안 경계로 적용됩니다.
TOTP 복구와 관리자 전환
TOTP 인증 수단을 사용할 수 없는 상황을 위한 복구 경로는 단순한 이메일 소유 확인만으로 완료되지 않습니다. 별도의 본인확인, 관리자 승인 및 1회용 복구 grant를 활용합니다.
관리자 전환 기능은 허용 대상 명부, 유효 기간과 마감 시각, 브라우저·계정 바인딩, 권한 검사 및 긴급 중지 기능을 포함합니다.
전환 관리 권한 식별자는 다음과 같습니다.
glitter-social_login_totp.totp_transition.manage
이 권한은 플러그인에서 등록한 관리자 권한으로, 코어의 일반 TOTP 설정과는 별개입니다.
관리자 설정과 소셜 계정 관리
관리자는 사용할 OAuth Provider를 활성화하고 각 Provider의 Client ID 또는 App ID, Client Secret 또는 App Secret 등 필요한 Credential을 설정할 수 있습니다. Provider 개발자 콘솔에서 OAuth 애플리케이션을 생성하고 callback URL을 등록하는 작업은 별도로 필요합니다.
기본 callback 경로 형식:
/api/plugins/glitter-social_login_totp/{provider}/callback
회원은 인증된 상태에서 소셜 계정의 연결 상태를 확인하고 명시적인 연결 또는 연결 해제 절차를 이용할 수 있습니다. 실제 사용 가능 범위와 화면 표시는 사이트 설정 및 활성 Provider에 따라 달라질 수 있습니다.
보안 및 운영 설계
- Socialite 기반 OAuth state 검증
- OAuth 시작 브라우저와 callback 간 바인딩
- 1회용·단기 유효 exchange code
- Provider identity의 DB unique 제약
- 이메일 일치만으로 기존 회원 자동 연결 금지
- TOTP 재사용 방지, 실패 횟수 제한 및 임시 잠금
- TOTP 비밀키 암호화 저장
- 복구·전환 grant와 권한 검사
- 로그인·등록·관리자 흐름의 서비스별 보호 경계
- 플러그인 전용 로그 채널 및 민감정보 로그 노출 방지 설계
- 기존 Glitter Social Login과 독립된 DB·설정·라우트 구조
보안 장치가 존재한다는 사실이 모든 공격이나 외부 OAuth 환경에 대한 완전한 안전성을 보장하지는 않습니다.
UI 및 다국어
한국어와 영어 번역 리소스를 제공하며, 로그인·가입·프로필·관리자 관련 플러그인 UI에서 동일한 glitter-social_login_totp 번역 namespace를 사용합니다.
Gnuboard7의 플러그인 레이아웃 확장 방식에 따라 UI를 구성합니다. 임의로 변경된 모든 외부 템플릿에서 동일하게 표시된다고 보장하지는 않습니다.
Database 및 의존성
플러그인은 별도의 소셜 계정, TOTP, 인증 교환, 복구 및 전환 관련 데이터 구조를 사용합니다. 검증 환경에서 플러그인 테이블 11개와 migration 기록 8개가 확인되었습니다. 실제 생성 항목은 설치 버전과 마이그레이션 상태에 따라 확인해야 합니다.
주요 OAuth 의존성은 Laravel Socialite와 SocialiteProviders 계열이며, 배포용 의존성 번들 파일을 함께 제공합니다.
vendor-bundle.jsonvendor-bundle.zip
배포용 ZIP 및 TAR.GZ에서는 .git/, node_modules/, vendor/를 제외하고, vendor-bundle.zip, vendor-bundle.json, dist/를 포함합니다. 공식 플러그인 설치·업데이트 lifecycle에서 --vendor-mode=bundled를 사용하여 의존성을 구성합니다.
설치 검증: vendor/를 제외한 배포 구성을 별도 Gnuboard7 환경에서 설치해 플러그인 1.0.8 설치 완료, 권한 3개 등록, vendor/autoload.php 및 Bacon QR Code 패키지 구성과 BaconQrCode\Writer 클래스 오토로드를 확인했습니다. 설치·의존성 검증 결과이며, 모든 서버 환경에서 동일한 동작을 보증하지는 않습니다.
설치 및 배포
Plugin ID: glitter-social_login_totp
Version: 1.0.8
Vendor: Glitter.kr
License: MIT
설치 환경의 구체적인 Gnuboard7 및 PHP 최소 버전은 배포 패키지의 plugin.json과 composer.json을 기준으로 확인해야 합니다.
1. GitHub 저장소에서 설치
Gnuboard7 관리자 화면의 플러그인 관리 기능에서 GitHub 저장소를 이용합니다.
https://github.com/glitter-node/glitter-social_login_totp
2. 배포 압축 파일로 설치
배포 압축 파일명:
glitter-social_login_totp-v1.0.8.zipglitter-social_login_totp-v1.0.8.tar.gz
배포 패키지는 glitter-social_login_totp/를 최상위 폴더로 사용하며,
의존성 설치를 위한 vendor-bundle.zip을 포함하는 구성입니다.
GitHub Release에서 압축 파일을 제공하는 경우 해당 자산을 내려받아 설치할 수 있습니다.
릴리스 태그와 배포 압축 파일의 게시 여부는 별개입니다.
설치·업데이트는 migration, 의존성, 서비스 프로바이더, 라우트 및 설정 반영이 필요한 Gnuboard7 공식 플러그인 lifecycle을 이용하는 것이 적절합니다. 활성 설치본을 직접 덮어쓰는 방식은 권장하지 않습니다.
설치 후 설정
- 플러그인을 설치하고 활성화합니다.
- 사용할 OAuth Provider를 활성화합니다.
- 각 Provider의 개발자 콘솔에서 OAuth 애플리케이션과 Credential을 준비합니다.
- 사이트의 callback URL을 해당 Provider에 등록합니다.
- 로그인·가입·TOTP 등록 및 관리자 설정을 실제 브라우저에서 점검합니다.
버전별 주요 변경 사항
| 버전 | 주요 변경 사항 |
|---|---|
| 1.0.8 | 로컬 TOTP QR 등록, 수동 등록키 복사, 공식 JS 자산 등록, QR 오류 로그 최소화, TOTP 전환 기본값 동기화, OAuth HTTP 타임아웃 |
| 1.0.5 | Gnuboard7 코어 자동 탐색 규약에 맞춘 서비스 프로바이더 namespace 수정 및 런타임 등록 복구 |
| 1.0.4 | 이메일 기반 기존 회원 자동 연결 제거, 누락 번역 추가, Secure cookie 판정 수정, 로그 채널 설정 및 Composer lock 정합성 보완 |
| 1.0.3 | TOTP 전환 관리 권한 식별자 정합성 수정 및 회귀 검사 추가 |
| 1.0.2 | Provider 정렬 및 프로필 계정 제어 UI의 번역 참조 수정 |
| 1.0.1 | 설정·관리자·로그인·가입·프로필 UI 번역 namespace 수정 |
| 1.0.0 | 독립 플러그인 생성, OAuth 5종 지원, 신규 가입·기존 로그인 필수 TOTP, 코어 2FA와 정책 분리 |
v1.0.8 검증 현황
확인된 항목
- PHP·JavaScript 문법 및 JSON 설정 유효성, 자산 빌드, 의존성 번들 무결성에 대한 정적 검사
- 격리된 PHP 환경에서 QR 생성 및 수동 등록키 대체 경로에 대한 검사
- 별도 Gnuboard7 환경에서
vendor/를 제외한 배포 구성으로plugin:install --vendor-mode=bundled --force설치 성공 - 설치본
vendor/autoload.php, Bacon QR Code 패키지,BaconQrCode\Writer클래스 로딩 확인 - 설치 결과: 플러그인 버전 1.0.8, 관리자 권한 3개 등록
운영자 확인: 브라우저 인증 테스트 통과
- 실제 브라우저에서 진행한 인증 관련 수동·육안 테스트 전체 통과(운영자 보고)
- 이는 운영자가 직접 확인한 실사용 검증 결과이며, 자동화된 E2E 테스트 결과와는 구분합니다.
별도 자동화 검증 현황
- 격리된 환경에서의 PHPUnit 전체 실행은 완료된 것으로 확인되지 않았습니다.
- 전체 자동화 회귀 테스트 및 보안 침투 테스트 통과 여부는 별도로 확인되지 않았습니다.
따라서 v1.0.8은 번들 기반 설치·의존성 로딩과 수동 브라우저 인증 테스트를 통과한 릴리스입니다. 다만 모든 환경에서의 무결점 동작이나 자동화된 전체 회귀 검증을 보증하는 것은 아닙니다.
알아두어야 할 점
- OAuth 인증만으로 로그인 완료가 되지 않으며 TOTP가 필수입니다.
- 같은 이메일이라는 이유로 기존 회원 계정과 자동 연결하지 않습니다.
- 코어의
security.two_factor_auth설정이 비활성화되어 있어도 플러그인 TOTP 정책은 유지됩니다. - OAuth Provider의 애플리케이션 등록 및 Credential 발급은 사이트 운영자가 수행해야 합니다.
- TOTP 복구와 관리자 전환은 별도 본인확인 및 권한 정책을 따릅니다.
- OAuth + Passkey(WebAuthn)는 현재 지원하지 않습니다.
- 외부 Provider의 정책과 사이트의 템플릿·세션·쿠키 환경에 따라 실제 동작이 달라질 수 있습니다.
- v1.0.8은 별도 환경에서 번들 기반 설치·의존성 로딩을 통과했으며, 운영자가 브라우저 인증 테스트 전체의 수동·육안 통과를 확인했습니다. 자동화된 전체 회귀 테스트 통과를 의미하지는 않습니다.
요약
Glitter Social Login TOTP 1.0.8는 Gnuboard7의 다섯 가지 OAuth Provider에 필수 TOTP 인증을 결합한 독립 플러그인입니다. 이메일만으로 기존 계정을 자동 연결하지 않으며, 신규 가입과 기존 로그인 모두에서 TOTP를 인증 완료의 필수 조건으로 적용합니다.
v1.0.8에서는 로컬 QR 코드 등록과 배포 자산·보안 로그·OAuth 연결 안정성을 개선했으며, vendor/ 없는 번들 기반 설치를 검증했습니다. 실제 브라우저 인증 테스트 역시 운영자가 수동·육안으로 모두 통과했다고 확인했습니다.
GitHub: https://github.com/glitter-node/glitter-social_login_totp
Tag: v1.0.8
Vendor: Glitter.kr
License: MIT
이 개발자의 다른 프로젝트
그누보드7 예약 모듈 - glitter-reservation
코어 수정 없이 붙여 사용하는 그누보드7 예약 모듈로, 신청·인증·조회·취소·관리까지 예약 흐름 전체를 모듈 단위로 제공합니다.
그누보드7 상담예약 템플릿 - Glitter Academy Core
GnuBoard7 Template 엔진 기반으로 상담예약 사이트 구성을 위한 초기 템플릿 예제로 설계되었습니다.
그누보드7 커뮤니티 템플릿 - SIRsoft Community
쇼핑몰(이커머스 의존)을 제거하고 커뮤니티 기능에 집중한 경량 사용자 템플릿, ID : sirsoft-comm
최신 댓글
전체 보기 →👍
TOTP 보안 좋아요.
고객이 원하는 것만 수정 개발 해주는거죠
회원가입하고, 하단 부분은 전혀 손 안대고 아미나 원본이 나옵니다.
좋은 말씀 감사합니다. (●'◡'●) 다만 저는 이미 현업에서는 내려온 상태라 교육이나 멤버십까지 운영할 계획은 없습니다. 지금처럼 개인적으로 관심 있는 것들을 만들어 보고, 정리한 내용이나 결과물을 필요하신 분들과 공유하는 정도가 제게는 소일거리입니다. G7을 처음 접하시는 분들이 조금이라도 쉽게 시작할 수 있도록, 제가 아는 범위에서 계속 자료를 남겨두는 것. 그 정도가 제가 생각하는 방향입니다. :)
TOTP 보안 좋아요.