리눅스 커널에 대한 신화, 거짓, 그리고 진실 - 1편
- Posted at 2008/07/26 18:38
- Filed under 리눅스
내용이 길어서 두 부분으로 나누었습니다. 현재 글은 1번째입니다.
OLS 2006 기조 강연
OLS 주최측의 배려로, 올해 폐막식 기조 강연을 담당할 기회를 얻었습니다. 다음은 강연의 슬라이드와 텍스트입니다. 음, 정확히는 이야기하고 싶었던 내용입니다. 실제로는 약간 다르게 들렸을 수도 있습니다.
이 강연을 직접 링크하고 싶다면, 이 링크를 사용하세요.
리눅스 커널에 대한 신화, 거짓, 그리고 진실 / 그렉 크로아-하트만(Greg Kroah-Hartman) / 수세 연구소 / 노벨(Novell)
안녕하세요. 데이브가 소개한 것처럼, 저는 그렉입니다. OLS 분들이 저에게 시간을 주셨으므로, 여러분에게 커널에 대해 잠시 이야기해보고자 합니다. 저는 지금부터 사람들이 언제나 말하는 커널에 대한 다양한 거짓말을 논의하고, 그것들의 정체를 폭로할 것입니다. 이어서 잘 알려지지 않은 몇몇 진실과, 무수히 반복해서 들은 몇몇 신화도 논의합니다.
제가 말하는 '신화'란 그 안에 약간의 진실이 들어 있다고 믿어지나, 실제로 검토해 보면, 허구인 것을 말합니다. 그것들을 리눅스 커널의 '도시 신화(urban myths)'라고 부르기로 합시다.
그럼 우선, 저를 정말로 화나게 하는, 매우 잘 알려진 신화를 봅시다.
내가 좋아하는 맞수, 플러그 앤 플레이는 여전히 윈도우 레벨에 이르지 못했다.
이제 저는 리눅스와 관련된 대부분의 사람이 지금까지 이와 비슷한 말을 들은 적이 있다는 것을 압니다. 리눅스는 장치 지원이 부족하다든지, 더 많은 하드웨어 지원이 급선무라든지, 모든 분야의 드라이버에서 뒤떨어져 있다든지. 몇 개월 전, OSDL(오픈 소스 개발 연구소)의 어떤 사람이 이와 비슷한 말을 해서 지역 신문에 실렸고, 정말로 화가 났습니다.
이것은 정말로 신화입니다. 따라서 사람들은 이런 말을 하기 전에 정말로 더 잘 알아야 합니다. 그래서, 도대체 누가 이런 말을 했을까요?
- 노벨 CTO, 제프 자페(Jeff Jaffe)
윽. (역주: 노벨은 강연자가 근무하는 회사)
뭐, 그는 아마 이 말을 오래 전에 했겠지요. 리눅스가 여러 가지 것을 정말로 지원하지 못하고 있었을 무렵, and when "Plug & Play" was a big deal with ISA buses and stuff:
(2006년 4월 3일)
으윽. (역주: 강연 날짜 기준으로 최근)
네, 아무래도 시간을 더 들여 이 신화를 폭로하지 않으면 안 되겠네요. 이 신화는 더 이상 사실이 아니니까요.
그럼, 최근 리눅스와 장치에 대한 사실은 어떨까요. 이렇습니다:
리눅스는 '있는 그대로', 지금까지 존재한 그 어떠한 운영체제보다 많은 장치를 지원한다.
네, 맞습니다. 우리는 누구보다도 많은 것을 지원합니다. 그리고 다른 누군가가 과거에 이룬 것보다도 많습니다. 리눅스는 그 누구보다 먼저 지원하기 시작한 것에 대한 매우 방대한 목록을 가지고 있습니다.
* USB 2.0
* 블루투스
* PCI 핫플러그 (역주: 핫플러그는 컴퓨터가 켜진 상태에서 꽂아도 인식하는 것)
* CPU 핫플러그
* 메모리 핫플러그 (물론 구식 유닉스는 옛날에 CPU와 메모리 핫플러그를 지원했지만, 데스크톱 운영체제로는)
* 무선 USB
* ExpressCard
그리고 더 있습니다. 임베디드 분야에 특히 최초 지원이 많지요.
그러나 특정 드라이버에만 머무르지 않는, 정말로 큰 부분이 있습니다. 바로 이것입니다:
리눅스는 지금까지 존재한 그 어떤 운영체제보다 다양한 프로세서(CPU)를 지원한다.
네, 우리는 지원하는 프로세서 종류와 형식의 개수에서 몇 년 전에 NetBSD를 추월했습니다. 그 어떤 '메이저' 운영체제도 리눅스의 플랫폼 지원 수준에 아득하게나마 미치지 않습니다. 리눅스는 현재 휴대전화부터 시작하여 무선 헬리콥터, 여러분의 데스크톱, 인터넷에 있는 서버, 그리고 전 세계 상위 500대 슈퍼 컴퓨터의 73%에 이르기까지 동작합니다.
그리고 기억해 둘 점은, 우리가 지원하는 다양한 드라이버 대부분은 이러한 플랫폼 모두에서 동작한다는 것입니다. 이것은 컴퓨터 역사상 그 누구도 도달하지 못한 것입니다. 리눅스가 이런 면에서 얼마나 유연하고 강력한지 놀라울 뿐입니다.
우리는 이제 역사상 가장 확장성 있고 가장 잘 지원되는 운영체제를 가지고 있습니다. 우리가 달성한 것은 매우 독특하고 다양하고 유연한 것이므로, '리눅스는 하드웨어를 지원하지 않는다'라는 신화를 말하는 사람은 그만 반복할 필요가 있습니다. 간단하게, 더 이상 진실이 아니기 때문입니다.
이제 제프 자페에 대해 공정하기 위해 한 마디 하면, 그가 저 말을 했을 때는 노벨의 CTO로 막 부임한 상태였고, 최근의 리눅스 경험도 별로 없어서, 현대 배포판이 제공하는 장치 지원의 실태를 잘 몰랐습니다.
페도라, 수세, 우분투, 그리고 기타 배포판의 최신 버전을 보세요. 설치는 완전히 식은 죽 먹기입니다(그 어떤 운영체제 설치보다 쉽습니다). 여러분은 이제 새로운 장치를 꽂을 수 있고 맞는 드라이버가 자동으로 로드되며, 어딘가에 있을 드라이버 시디를 사냥하러 다닐 필요도 없습니다. 여러분은 심지어 재부팅할 필요조차 없이 몸을 일으켜 실행하고 있습니다.
한 예로, 저는 최근에 새로 산 USB 프린터를 제 노트북에 꽂았습니다. 대화 상자가 떠서 테스트 페이지를 인쇄할 것이냐고 물었습니다. 그게 전부입니다. 다른 것은 없습니다. 이래도 '플러그 앤 플레이'가 아니라면, 저는 정말로 플러그 앤 플레이가 뭔지 모르겠습니다.
그러나 모두가 리눅스의 성공을 무시해온 것은 아닙니다. 이번 행사의 규모만 봐도 확실하죠. 많은 사람이 리눅스를 지켜보고, 필요에 맞게 사용하기를 원합니다. 그러나 그들이 커널을 깊숙이 살펴보고 어떻게 개발되었는지 알려고 한다면, 그들이 처음 느끼는 것은 계획성의 부재입니다.
리눅스 커널에는 명확한 설계가 없다.
이것은 항상 많은 사람을 미치게 합니다. 여러분은 '리눅스에는 설계도(roadmap)가 없는데, 어떻게 제가 리눅스로 새로운 제품을 만듭니까'라든지, '아무도 다른 사람을 지휘하지 않는데 어떻게 일이 제대로 됩니까'라든지, 이와 비슷한 질문을 볼 수 있습니다.
글쎄요, 우리가 성공적이라는 사실을 생각해 보면, 무언가 방법이 있을 테고, 그 방법은 옳은 것이 확실한데, 도대체 어떤 방법일까요?
전통적으로 소프트웨어 개발은 요구 사항을 결정하고, 두꺼운 설명서를 작성하며, 검토하면서 모든 사람의 동의를 받고, 그 스펙을 구현하며, 테스트하는 등의 방식으로 이루어졌습니다. 대학에서는 폭포 방식이라든지, 반복 프로세스 방식이라든지, 형식적 증명 수법이라든지 하는 소프트웨어 공학 방법론을 가르쳐 왔습니다. 그리고 익스트림 프로그래밍과 하향식 디자인 같은 새로운 방법도 있습니다.
그렇다면, 리눅스 커널에서는?
오픈 소스 개발은 알려진 관리 이론 대부분을 위배한다. -매리에타 배버 박사(Dr. Marietta Baba), 미시건 주립 대학의 사회 과학 대학 학장
배버 박사는 각종 사업이 어떻게 운영되는지를 연구합니다. 그는 오픈 소스 커뮤니티가 어떻게 운영되는지, 특히 리눅스 커널이 어떻게 개발되고 관리되는지 연구한 끝에 이런 결론을 내놓았습니다.
우리가 지금까지 없었던 무언가를 창조해냈기 때문에, 저는 이 결론이 합당하다고 생각합니다. 우리는 다른 사람과 다른 무언가를 함으로써 그것을 이루었습니다. 그렇다면, 어떤 방법입니까? 커널은 어떻게 디자인되고 만들어집니까? 리누스는 작년에 이 질문에 답했습니다. 그는 커널 디자인 과정을 설명해달라는 부탁을 받고, 여러 기업 앞에서 다음과 같이 대답했습니다.
리눅스는 진화다. 지적 설계가 아니다. -리누스 토발즈
(역주: '지적 설계'는 우주와 생명이 지적인 존재에 의해 설계되었다는 설)
이것은 정말 중요한 부분인데, 많은 사람이 이해하지 못하는 것처럼 보입니다. 사실, 저는 그들이 이해는 하지만, 좋아하지 않을 뿐이라고 생각합니다.
리눅스 커널은 방대한 디자인 문서, 기능 요구 같은 것으로 개발되지 않습니다. 그 순간의 필요에 따라 진화합니다. 커널이 처음 탄생했을 때는 하나의 프로세서 종류만 지원했습니다. 그게 필요한 전부였기 때문입니다. 나중에 두 번째 아키텍처가 추가됐고, 시간이 지남에 따라 점점 더 많아졌습니다. 그리고 우리가 새로운 아키텍처를 추가할 때마다, 개발자들은 그 아키텍처를 지원하기 위해 필요한 것이 무엇인지를 알아내어 작업했습니다. 처음부터 오늘날 지원하고 있는 다양한 프로세서 종류의 놀라운 유연성을 고려한 것이 아닙니다. 어떤 것이 필요하게 될지 몰랐으니까요.
리눅스 커널은 필요할 때만 바뀝니다. 필요한 수단을 사용해서요. 소형 프로세서에 대한 필요가 생기자 작게 변했고, 다른 사람이 커지기를 원하자 커졌습니다. 그리고 변화가 생길 때마다, 다른 사람도 이익을 얻게 하기 위해 메인 소스 코드로 합쳐졌습니다. 커널은 그러한 라이선스에 의해 출시되고 있기 때문입니다.
행사 첫날 조나단은 여러분에게 커널에서 일어나고 있는 큰 변화율을 보여주었습니다. 산더미 같은 새로운 기능이 버그 수정, 코드 정리(cleanup) 등과 함께 엄청난 비율로 추가됩니다. 이것은 커널이 탄생 이후 15년이 지난 지금도 여전히 빠른 속도로 진화하고 있다는 것을 보여줍니다. 커널은 매우 융통성 있는 모습으로 변했고, 몇 년 전의 모습조차 찾아볼 수 없습니다. 그리고 이것이야말로 리눅스가 왜 그토록 성공적이고, 왜 앞으로도 성공할 것인지에 대한 중요한 이유입니다. 왜냐하면 우리는 변화를 포용하고, 사랑하고, 환영하기 때문입니다.
그러나 많은 사람에게 한 가지 '문제'는 이러한 끊임없는 진화 상태 때문에, '전통적인' 운영체제가 제공하는 것을 리눅스 커널은 제공하지 않는다는 것입니다. 안정적인(stable) 커널 내부 API 같은 것이 그렇습니다. 여러분 모두 다음 문장을 한 번쯤 들어보셨을 것입니다:
리눅스 커널에는 안정적인 API가 필요하다. 그래야 하드웨어 제작사가 드라이버를 만들 수 있다.
API가 무엇인지 모르시는 분을 위해 설명드리자면, API는 커널이 일을 하기 위해 자신의 내부와 어떻게 대화하는지를 설명한 것입니다. 특정 작업을 하기 위해 어떤 함수가 필요한지, 어떻게 호출하는지가 기술되어 있습니다.
리눅스에는 안정적인 내부 API가 없습니다. 원하는 사람도 있겠지만, 그런 것을 가지는 것은 바보스럽습니다. 약 2년 전에, 커널 개발자들은 함께 앉아 리눅스는 왜 안정적인 커널 내부 API를 가지지 않는지 쓰고, 커널 내에 파일로 공개했습니다.
Documentation/stable_api_nonsense.txt
무언가 궁금한 점이 있다면 이 파일을 읽어주세요. 왜 리눅스는 안정적인 커널 내부 API를 가지지 않는지, 왜 앞으로도 가지지 않을지 설명하고 있습니다. 결국 진화의 문제입니다. 만일 커널의 내부 동작이 고정되면, 개발자에게 필요한 만큼 진화할 수 없게 됩니다.
이것이 어떻게 동작하는지를 보여주는 예를 소개합니다. 리눅스의 USB 코드는 적어도 세 번 다시 작성되었습니다. 우리는 원래 처리할 필요가 없었던 것들, 예를 들어 고속 장치 같은 것을 처리하기 위해 이 일을 했습니다. 그리고 초기 디자인의 문제를 배우고, 버그와 보안 문제를 고치기 위해서이기도 했습니다. 우리는 API를 변경할 때마다, 기존 API를 사용하고 있던 모든 커널 드라이버를 업데이트했습니다. 따라서 아무 것도 고장나지 않습니다. 그리고 필요 없거나 잘못 동작하는 낡은 함수를 제거했습니다. 이 덕분에, 리눅스는 현재 어떠한 운영체제보다 USB 버스 속도가 빠릅니다. 우리는 하드웨어의 한계 속도를 이끌어냅니다. 그리고 여러분은 간단한 사용자 영역(userspace) 프로그램에서 사용할 수 있습니다. 거추장스러운 커널 드라이버 작업은 필요하지 않습니다.
현재 윈도우 또한 USB 스택을 최소 3번 다시 작성했습니다. 비스타가 나왔으니 4번이 될 수도 있지만, 저는 아직 비스타를 들여다보지 않았습니다. 그러나 새로운 함수를 추가하고 예전 코드를 수정하는 작업이 이루어질 때마다, 윈도우 개발자들은 낡은 API 함수를 유지해야 합니다. 그들의 안정적인 API 철학을 위해 하위 호환성을 유지한다는 입장을 취하고 있기 때문입니다. 그들은 또한 모든 드라이버 코드에 접근할 수도 없기 때문에(역주: 윈도우 드라이버는 대부분 클로즈드 소스), 낡은 드라이버를 고칠 수가 없습니다. 그래서 현재 윈도우 코어는 API 함수 세트를 3개 가지고 있습니다. 아무 것도 제거할 수 없기 때문입니다. 즉 윈도우 개발자들은 낡은 함수를 관리해야 하고, 머리 속에 넣어둬야 합니다. 그리고 이러려면 추가적인 복잡성 때문에 작업 시간이 소요됩니다. 이것은 윈도우 개발자들의 사업 결정이니, 뭐 좋습니다. 그러나 리눅스에 대해서라면, 우리는 그런 결정을 내린 적이 없습니다. 우리의 철학은 리눅스 커널을 매우 작고, 더 안정적이고, 더 안전하게 유지할 수 있도록 돕습니다.
그리고 보안이라고 하는 것은, 문자 그대로입니다. 한 드라이버나 커널의 한 부분에서 보안 문제가 발견되면, 커널 개발자는 그것을 고치고, 더 나아가서 같은 문제를 가지고 있는 다른 모든 드라이버를 고칩니다. 그러면 해결책이 제시되었을 때 모든 드라이버를 사용하는 모든 사용자가 안전해집니다. 그러나 다른 운영체제는 운영체제 개발자들이 모든 드라이버를 관리하고 있지 않기 때문에, 개발자들이 보안 문제를 해결한다고 해도, 다른 회사가 발표한 드라이버를 수정하는 것은 그 회사에 달려있게 됩니다. 이것은 안전하지 않습니다. 이 문제는 최근 많이 발생하고 있고, 안정적인 API를 가지는 것이 일반 사용자에게 얼마나 해가 되는지를 보여줍니다. 왜냐하면 안정적인 API의 원래 목적은 개발자 자신을 돕는 것이었기 때문입니다.
제가 커널 API의 불안정성과, 커널 개발이 어떻게 이루어지는지 설명하고 나면, 종종 이런 반응이 돌아옵니다.
내가 만든 드라이버는 유명하지 않은 하드웨어 전용이므로, 메인 커널에 받아들여질 리가 없다.
이것은 전혀 사실이 아닙니다. 우리는 전 세계에 사용자가 단 2명밖에 없는 서브 아키텍처를 지원하고 있습니다. 제가 알기로 사용자가 한 명뿐인 드라이버도 있습니다. 그 드라이버를 위해 만들어진 하드웨어가 하나밖에 없었기 때문입니다. 이것은 사실일 뿐만 아니라, 우리는 어떤 하드웨어를 위한 드라이버라도 메인 코드(our tree)에 반영할 것입니다. 그것을 정말로 원하고 있기 때문입니다.
우리는 '유명도'에 관계 없이 더 많은 드라이버를 원합니다. 왜냐하면 그러면서 코드의 패턴을 보게 되고, 어떤 식으로 개선할 수 있는지 깨닫기 때문입니다. 만일 우리가 똑같은 작업을 하는 몇몇 드라이버를 보게 된다면, 우리는 공통된 코드를 모아서 공유 코드로 옮깁니다. 이렇게 하면 각각의 드라이버는 더 작아지고, 보통 더 나아집니다. 우리는 또한 똑같은 작업을 하는 모든 드라이버를 하나로 합친 적도 있습니다. 예를 들면 커널의 USB 데이터 획득 드라이버가 있습니다. 세상에는 무수한 USB 데이터 획득 장치가 있습니다. 그리고 얼마 전에 한 독일 회사가 자신들의 장치를 지원해달라고 저에게 드라이버를 보냈습니다. 그리고 저는 다른 회사의 비슷한 일을 하는 드라이버를 작업하고 있었습니다. 따라서 우리는 함께 두 드라이버를 합쳤고, 커널은 더 작아졌습니다. 그런데 한 드라이버가 몇몇 다른 회사의 장치에도 적용된다는 것을 발견했습니다. 그래서 기존 드라이버에 새로운 장치 아이디만 추가하자 아무런 추가 코드 없이도 리눅스 지원이 가능해졌습니다. 원래의 독일 회사는 자신들의 장치가 완전히 지원되니 행복합니다. 그것이 그들의 고객이 원했던 것이니까요. 그리고 다른 모든 회사는 아주 행복합니다. 그들의 장치를 지원하게 하기 위해 아무런 작업을 할 필요가 없었으니까요. 모두가 승리합니다.
후아... 번역하는 데 무지 오래 걸리네요. 매일 조금씩 해서 10시간 가까이 걸린 것 같아요. 오역이 있으면 언제든지 지적해주세요.
연설자 그렉 크로아-하트만은 현재 리눅스 커널에서 USB와 sysfs 쪽을 담당하고 있는데, 그래서 그런지 USB 이야기가 많군요.
글 내용 전체가 100% 옳은 것 같지는 않습니다. 부분 부분 과장도 섞여 있고요... 그러나 많은 것을 깨달을 수 있었습니다. 특히 '안정적인 커널 내부 API'를 왜 만들지 않는지에 대한 설명이 인상적이었습니다.
조만간 2편도 번역하여 올리겠습니다. :-)
Posted by 랜덤여신
- Tag
- FUD, Greg Kroah-Hartman, kernel, keynote, lie, linux, myth, truth, 강연, 거짓, 거짓말, 그렉 크로아-하트만, 리눅스, 신화, 연설, 진실, 커널, 키노트
- Response
- 1 Trackback , 19 Comments
Comments List
-
글 내용이 흑미롭네요.. 좋은글 번역 감사합니다..
-
좋은 글 번역해주셔서 감사합니다. ㅎ
리눅스가 CPU지원수에 있어서 넷비를 뛰어넘었군요 햐~ -
잘봤습니다. 추천!
근데 로드맵은 우리나라에서도 그냥 외래어로 로드맵이라고 쓰지않나요? ^^;-
청사진, 로드맵, 도로 지도 중 고민했는데, 청사진은 뜻이 약간 다르고 로드맵은 생각보다 유명한 단어가 아닌 것 같아서 도로 지도를 선택했습니다. 음... 바꾸는 것이 좋을까요? 생각해보겠습니다.
혹시 더 좋은 단어를 아시는 분은 알려주세요. -
아, '설계도'가 괜찮군요. 그걸로 바꾸겠습니다.
-
-
정말 좋은 번역 감사합니다. ^^
-
글 잘 읽었습니다. 정말 유익했습니다. 그리고 다음 글도 기대하고 있습니다+_+
-
재미있는 글 잘 읽었습니다. 저는 리눅스의 하드웨어 지원의 경우 사용자들이 윈도우에 비해 지원 수준이 떨어진다고 체감하는 이유는 오픈소스인 리눅스가 최신 하드웨어 지원에는 적합하지 않은 경우가 생기기 때문이라고 봅니다. 최신 하드웨어들은 시장에서 치열한 경쟁에 직면하는 까닭에 경쟁사를 견제하려면 드라이버의 소스 코드를 공개하기가 까다로운 경우가 많죠. 그러다보니 리눅스 커널에 드라이버 소스코드를 한번 제출해 버리면 가장 간단한 일이 드라이버가 공개되지 않거나 혹은 상용 바이너리만 공개되는 경우로 가지 않나 싶습니다.
결국 이렇게되면 불편함을 느낀 사용자 중에서 커널 개발 능력이 있는 몇몇 사람이 리버스 엔지니어링과 비슷한 형태로 리눅스용 오픈소스 드라이버를 만들기 시작하는데 이렇게 되면 또 문제가 동작은 하지만 몇몇 기능이 불완전하게 지원되는 경우가 자주 나오게 되고 이런 것들이 사용자들에게 리눅스는 윈도우보다 하두웨어 지원이 부실하다는 인상을 주게 되는 이유 중 하나겠죠. -
와우! 막혀있던 가슴이 뻥 뚤린 느낌입니다.
이 글로 인해 저도 몇가지 오해 했던 부분이 있었고 그것에 대해 풀게 되어 기쁩니다. 다음편도 기대하겠습니다. ^^ -
이야~ 정말 힘드셨겠어요. 덕분에 편하게 좋은 내용을 배웠습니다. 2편도 기대할게요~
-
"우리는 API를 변경할 때마다, 변경된 API를 사용하고 있던 모든 커널 드라이버를 업데이트했습니다. 따라서 아무 것도 고장나지 않습니다. 그리고 필요 없거나 잘못 동작하는 낡은 함수를 제거했습니다."
이 세상의 모든 하드웨어 드라이버가 오픈되어 있다면 이 말은 옳습니다.
그런데 안타깝게도 Nvidia나 Ati의 그래픽카드 드라이버는 공개되어 있지 않습니다. 즉 커널이 업데이트된다고 해도 그래픽 드라이버까지 같이 업데이트 되지 않는다는 것이죠. 그래서 커널이 업뎃될때마다 "아앍, 화면이 이상하게 나와요."라는 불평이 나오는 겁니다.
이 상황을 해결하려면 제조사 측에서 드라이버를 공개하거나, 아니면 상용 저장소를 따로 만들어서 동시에 업데이트 되게 하는 것이 필요하다고 생각합니다. -
좋은 글 잘 읽었습니다. 요새 리눅스 커널 관련 책을 지루하게 읽고 있었는데 더욱 즐겁게? 책을 읽을 수 있도록 큰 도움이 되는거 같네요.
-
글 잘 읽고 갑니다. 리눅스 공부하고 있는 학생입니다.
깊게 공부하면 넓고 새로운 세상을 보게 될 것 같아요.^^
좋은 글 감사합니다. -
훌륭한 글에 좋은 번역입니다. 커널이 이런 방식으로 개발되고 있는 줄 몰랐습니다. 디자인이 아닌 진화라는 말이 압권인 것 같습니다. 필요에 따라 만든다. 앞으로 제 인생에 로드맵이 될 듯 하네요. 한 명이 번역하고 여러 명이 보는 이런 것도 오픈소스 정신이겠죠. 10시간은 너무 길어요. 감사합니다.
-
멋진 글이고 읽는데 아무런 부담이 없었어요. 해석 감사해요!